/** * outbox-log — read-only diagnostic inspection of `@ng-org/web`'s offline write * outbox, at session bootstrap (polyfill-era, low-level-data-path trace). * * ── What this surfaces ────────────────────────────────────────────────────── * `@ng-org/web` (the real injected SDK) queues writes made while offline/ * disconnected in an "outbox", persisted client-side in `sessionStorage` by the * WASM verifier (see `sdk/rust/src/local_broker.rs` `JsStorageConfig:: * get_js_storage_config` in the `nextgraph-rs` core repo — read-only reference, * NOT vendored here). A non-empty outbox at session start is an ANOMALY worth * surfacing unconditionally: it means writes from a previous (disconnected) * session are still queued and haven't reached the broker yet. * * ── sessionStorage key shapes (verified in the core repo, not guessed) ────── * The outbox is keyed per LOCAL PEER id (`peer_id`, the persistent local peer's * pubkey — NOT the ng-eventually shim's `account`/`identity` concept), via two * key families written by `session_write`/read by `session_read`: * - `ng_peer_last_seq@` — the peer's last reserved seq number. * - `ng_outboxes@@start` — the seq number the outbox starts at. * - `ng_outboxes@@<00000-idx>` — one queued (base64url + BARE-encoded) * event per zero-padded index, contiguous from 0 until the first miss (the * exact shape `outbox_read_function` walks — see `local_broker.rs`). * We don't know `peerId` ahead of time (it's internal to the injected SDK), so * we DISCOVER it by scanning `sessionStorage` for `@start` markers instead of * requiring it to be passed in — this also means the probe works unchanged * however many peers/wallets the browser session has touched. * * ── Read-only, defensive, best-effort ──────────────────────────────────────── * This NEVER writes or deletes a key (unlike the real `outbox_read_function`, * which drains on read) — it only counts. The queued event bytes are opaque * (BARE-encoded Rust structs, base64url'd); decoding them to report concrete * write TARGETS (topics/docs) would mean duplicating the WASM verifier's wire * format in this polyfill, which is explicitly out of scope (SDK internals live * in the `@ng-eventually/client`-independent core repo, per this repo's * doctrine) — so only the pending COUNT is reported, never fabricated targets. * `sessionStorage` access itself can throw (sandboxed iframe, disabled storage — * see the exact error string handled in the core repo's `main.ts` * `convert_error`), so the whole probe is wrapped in one try/catch: unavailable * → skip silently, never throw into the caller. * * Polyfill-era; removed at the real multi-store migration alongside the rest of * this low-level trace instrumentation. */ import { accessLogPrefix, logStage } from "./access-log"; /** Matches an outbox "start" marker key, capturing the peer id. */ const OUTBOX_START_KEY = /^ng_outboxes@(.+)@start$/; /** Safety bound on the per-peer index walk, so a corrupted/mocked storage * (e.g. a `@start` marker with no matching index gaps) can't spin forever. * Real outboxes are queued-while-offline writes — nowhere near this size. */ const MAX_SCAN_PER_PEER = 10_000; /** * Inspect the outbox NOW and log its state — count only, never targets (see * module doc). Non-empty → `console.warn`, ALWAYS printed (anomaly, not gated * by the access-log flag). Empty → a normal {@link logStage} line, gated by the * access-log flag like the rest of the low-level trace. Read-only: never * mutates `sessionStorage`. Never throws. */ export function inspectOutbox(): void { try { const storage = (globalThis as any)?.sessionStorage; if (!storage) return; const peers = new Set(); const length: number = storage.length ?? 0; for (let i = 0; i < length; i++) { const key = storage.key?.(i); if (!key) continue; const m = OUTBOX_START_KEY.exec(key); const peerId = m?.[1]; if (peerId) peers.add(peerId); } let total = 0; for (const peer of peers) { let idx = 0; while (idx < MAX_SCAN_PER_PEER) { const idxKey = "ng_outboxes@" + peer + "@" + String(idx).padStart(5, "0"); if (storage.getItem(idxKey) === null) break; total++; idx++; } } if (total > 0) { // Anomaly: ALWAYS visible, regardless of the access-log flag. console.warn(accessLogPrefix() + " OUTBOX " + total + " pending write(s)"); } else { logStage("OUTBOX empty"); } } catch { // sessionStorage unavailable / access denied — skip silently. Diagnostic // only, never a hard dependency of the read/write path. } }