Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
0179f10
docs(popup): package documentation
Wondertan Sep 3, 2026
ac1f684
feat(popup): implement the MessagePort connection
Wondertan Sep 2, 2026
68a9722
feat(popup): qualify the connection in real browsers
Wondertan Sep 2, 2026
afb544f
docs(popup): record implementation coverage and keeper timing
Wondertan Sep 2, 2026
4dab745
fix(popup): harden record checks, send failure, and window guards
Wondertan Sep 3, 2026
caf9f47
feat(popup): admit a set of popup origins and rebind across origins
Wondertan Sep 3, 2026
f8717f7
feat(popup): add navigateAway and the popup-side wildcard allowlist
Wondertan Sep 3, 2026
05a7eeb
fix(popup): settle the focused review findings
Wondertan Sep 3, 2026
bf38fc0
test(popup): keep the accept helper's derived promise handled
Wondertan Sep 3, 2026
c397165
fix(popup): satisfy noVoidTypeReturn in the inbound router
Wondertan Sep 3, 2026
e620905
chore(popup): add the browser install script the CI job runs
Wondertan Sep 3, 2026
ae35c50
docs(popup): state ordering across a transition and test it
Wondertan Sep 3, 2026
fb6f317
feat(popup): open the popup as a separate window
Wondertan Sep 4, 2026
47018e7
feat(popup): reach isolation through a same-origin fallback automatic…
Wondertan Sep 5, 2026
776e14c
feat(popup): structured fragments and captured-fragment fallback
Wondertan Sep 5, 2026
60cdebf
feat(popup): isolation fallback over a non-transferable carrier
Wondertan Sep 6, 2026
3a3e1f6
fix(popup): hop into isolation before constructing a fallback carrier
Wondertan Sep 7, 2026
2d2fe15
feat(popup): select the continuity worker registration by exact scope
Wondertan Sep 7, 2026
631027f
test(popup): await the observed handshake instead of a fixed tick
Wondertan Sep 7, 2026
7291be8
test(popup): let tick outlast a stalled poll phase
Wondertan Sep 7, 2026
06e1c0b
feat(popup): find the continuity registration automatically, with an …
Wondertan Sep 7, 2026
3b96378
fix(popup): align continuity guarantees and support loopback HTTP
Wondertan Sep 11, 2026
b8dec84
feat(popup): expose authenticated peer origins
Wondertan Sep 13, 2026
e0d2a23
feat(popup): place new windows side by side
Wondertan Sep 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,8 @@ ts/apps/demo/public/

# Harness runtime output
harness/.env

# @libid/popup e2e bundles and Playwright output
ts/packages/popup/e2e/dist/
ts/packages/*/test-results/
ts/packages/*/playwright-report/
64 changes: 64 additions & 0 deletions ts/packages/popup/METRICS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Popup metrics and diagnostics

`@libid/popup` measures its own window, connection, carrier, continuity, and
control work. It never exports telemetry itself. A caller may supply
`onDiagnostic` to receive sanitized local events under its own observability
policy.

```ts
interface PopupDiagnostic {
readonly code: string
readonly timestamp: number
readonly durationMs?: number
readonly count?: number
}
```

`code` is a stable package-owned identifier. The public type stays `string`
because the catalog is open: each carrier adds its own codes, and a closed
union would break exhaustive consumers on every addition. Renaming or removing
a catalogued code is a breaking change. `timestamp` uses
`performance.timeOrigin + performance.now()`. Optional finite, nonnegative
`durationMs` and integer `count` fields are present only where their meaning is
fixed by the code. The callback receives no arbitrary details map, raw
exception, URL, origin, connection ID, message discriminator, or transported
value.

## Measurements

| Area | Measurements |
|---|---|
| Popup window | `window-opened`, `window-blocked`, `window-bound` |
| Connection | `handshake-rejected`, `opener-timeout`, `carrier-message-port`, `carrier-restored`, `carrier-fallback`, `fallback-unavailable`, `fallback-failed`, `popup-unavailable`, `send-unavailable`, `connection-closed` and `connection-failed` with `durationMs` since construction |
| Message delivery | `decode-rejected`; MessagePort adds no encoding or clock, so no size or latency measurement exists |
| Continuity | `keep-acknowledged` with `durationMs`, `keep-failed`, `claim-empty`, `claim-failed`, `continuity-unsupported`, `isolation-fallback`, `isolation-unavailable` |
| Control | `control-direct`, `control-connected`, `control-rejected`; never remote success |
| WebRTC | signaling-path class, offer publication, answer pickup, candidate class, selected-pair class, ICE checks, DTLS, data-channel open, and terminal failure |

`fallback-unavailable` is emitted exactly once only when opener-based
connection has failed and no fallback constructor exists. Merely omitting the
constructor or successfully selecting MessagePort emits no fallback failure.
A supplied constructor which rejects retains its own stable failure code;
connection records it only if that fallback path is selected.

## Privacy and failure handling

Diagnostics never contain:

- popup or application origins, URLs, connection IDs, SDP, ICE addresses,
cookies, or signaling records;
- caller message types, fields, payloads, proof material, credentials, or byte
contents; or
- raw exceptions, stacks, caller-selected labels, or unbounded strings.

Candidate and selected-pair measurements use only package-defined classes.
Message sizes use bounded numeric buckets rather than contents. Any caller
export maps package codes to its own cardinality-controlled schema.

An operation that can reject reports failure through that rejection and the
optional callback. A caught asynchronous failure with no remaining caller
operation emits one sanitized `console.error` containing only the package
subsystem and stable code, then invokes `onDiagnostic` when present. Failure of
the callback or console path is inert. The package starts no reporting request,
writes no durable diagnostic record, retries nothing, and synthesizes no caller
result.
Loading
Loading