Outcome
Replace the best-effort page-message/runtime-callback flow with a one-shot protocol binding every decision to the exact transaction, tab, frame, document, wallet adapter, and review window. Requests must survive MV3 worker suspension, reject replay or cross-window decisions, and settle within a defined deadline.
Audit evidence and problem
src/intercept/mainWorldEntry.ts generates a page-visible ID, posts XDR through window.postMessage(..., '*'), and has no page-side timeout.
src/intercept/bridgeEntry.ts trusts and forwards that page-provided ID; it does not generate the authoritative ID claimed by README.
src/background/background.ts keeps resolver functions only in an in-memory Map; DEFAULT_TIMEOUT_MS is unused.
- Popup creation results are not retained. There is no
chrome.windows.onRemoved handler, so closing a popup can hang the dApp request.
DECISION_MADE resolves solely by request ID and ignores sender tab/frame/window. Duplicate IDs overwrite map entries.
- Transaction data and decision identity are placed in popup query parameters and treated as authoritative by
src/popup/App.tsx.
docs/threat-model.md records forgery, MV3 state loss, stale popup, request flooding, and missing sender binding as open threats.
Non-negotiable invariants
- A decision is bound to one transaction digest, tab, frame, document, adapter, and review window.
- Page-controlled identifiers are never authoritative capabilities.
- The first valid terminal transition wins; replay is a no-op.
- Unrelated or stale senders cannot resolve a request.
- Worker restart cannot release a cancelled request or lose a completed decision.
- Popup close, creation failure, bridge loss, and timeout settle deterministically.
- The released XDR is byte-for-byte identical to the reviewed XDR.
- Pending state, windows, timers, and tombstones are bounded and pruned.
Required scope
A. Versioned protocol
Define runtime-validated, versioned messages. Separate page correlation IDs from extension-generated request IDs and bind immutable transaction digests, network, adapter, tab/frame/document identity, timestamps, and state.
B. Durable state machine
Implement received → validating → assessing → awaiting_review → proceed | cancel | expired | failed. Persist recoverable metadata before opening UI and add a bridge resume/status handshake because callback functions cannot survive suspension.
C. Trusted review capability
Pass only an opaque capability in the review URL. Load display state from the worker, retain windowId, validate sender context, and reject copied, expired, mismatched, or consumed capabilities.
D. Failure and concurrency semantics
Install deadlines at page, bridge, assessment, and review layers. Handle popup/tab closure, navigation, worker restart, extension update, storage failure, duplicate messages, and popup creation failure. Add per-frame and global admission limits.
E. Compatibility
Define safe behavior for stale content scripts after extension updates and browsers lacking documentId. Compatibility fallbacks must be explicit and testable.
Deliverables
- Protocol/state-machine ADR and threat-model update.
- Runtime message schemas and transaction digest binding.
- Durable pending repository, replay tombstones, and resume handshake.
- Sender/window-bound popup state API.
- Timeout, close, restart, update, and admission-control handlers.
- Developer inspection/cleanup tooling and adversarial browser tests.
Acceptance criteria
Required verification
Unit and property-based state-machine tests; actual Chrome sender integration tests; multi-tab/frame Playwright tests; forced worker termination; popup/navigation/update failure injection; adversarial same-page messaging; load tests; security review. A mocked happy-path resolver test is insufficient.
Out of scope
Oracle accuracy, expanded Stellar semantics, new wallets, and protection against a compromised browser/wallet.
Dependencies and sequencing
Foundational; land before the oracle, semantic review, protection-status, and retained-record contracts stabilize.
Complexity
Extreme
Impact
Critical — forged, lost, mismatched, or hanging decisions compromise a financial signing workflow.
Suggested labels
epic architecture security reliability browser-extension state-machine production
Outcome
Replace the best-effort page-message/runtime-callback flow with a one-shot protocol binding every decision to the exact transaction, tab, frame, document, wallet adapter, and review window. Requests must survive MV3 worker suspension, reject replay or cross-window decisions, and settle within a defined deadline.
Audit evidence and problem
src/intercept/mainWorldEntry.tsgenerates a page-visible ID, posts XDR throughwindow.postMessage(..., '*'), and has no page-side timeout.src/intercept/bridgeEntry.tstrusts and forwards that page-provided ID; it does not generate the authoritative ID claimed by README.src/background/background.tskeeps resolver functions only in an in-memoryMap;DEFAULT_TIMEOUT_MSis unused.chrome.windows.onRemovedhandler, so closing a popup can hang the dApp request.DECISION_MADEresolves solely by request ID and ignores sender tab/frame/window. Duplicate IDs overwrite map entries.src/popup/App.tsx.docs/threat-model.mdrecords forgery, MV3 state loss, stale popup, request flooding, and missing sender binding as open threats.Non-negotiable invariants
Required scope
A. Versioned protocol
Define runtime-validated, versioned messages. Separate page correlation IDs from extension-generated request IDs and bind immutable transaction digests, network, adapter, tab/frame/document identity, timestamps, and state.
B. Durable state machine
Implement
received → validating → assessing → awaiting_review → proceed | cancel | expired | failed. Persist recoverable metadata before opening UI and add a bridge resume/status handshake because callback functions cannot survive suspension.C. Trusted review capability
Pass only an opaque capability in the review URL. Load display state from the worker, retain
windowId, validate sender context, and reject copied, expired, mismatched, or consumed capabilities.D. Failure and concurrency semantics
Install deadlines at page, bridge, assessment, and review layers. Handle popup/tab closure, navigation, worker restart, extension update, storage failure, duplicate messages, and popup creation failure. Add per-frame and global admission limits.
E. Compatibility
Define safe behavior for stale content scripts after extension updates and browsers lacking
documentId. Compatibility fallbacks must be explicit and testable.Deliverables
Acceptance criteria
Required verification
Unit and property-based state-machine tests; actual Chrome sender integration tests; multi-tab/frame Playwright tests; forced worker termination; popup/navigation/update failure injection; adversarial same-page messaging; load tests; security review. A mocked happy-path resolver test is insufficient.
Out of scope
Oracle accuracy, expanded Stellar semantics, new wallets, and protection against a compromised browser/wallet.
Dependencies and sequencing
Foundational; land before the oracle, semantic review, protection-status, and retained-record contracts stabilize.
Complexity
Extreme
Impact
Critical — forged, lost, mismatched, or hanging decisions compromise a financial signing workflow.
Suggested labels
epicarchitecturesecurityreliabilitybrowser-extensionstate-machineproduction