Skip to content

fix(addon): isolate frame bridge authority - #14

Open
K4zoku wants to merge 22 commits into
mainfrom
fix/cross-port
Open

K4zoku wants to merge 22 commits into
mainfrom
fix/cross-port

Conversation

@K4zoku

@K4zoku K4zoku commented Sep 14, 2026

Copy link
Copy Markdown
Collaborator

What does this PR do?

Reworks the addon bridge topology from one isolated bridge multiplexing multiple frames to one isolated bridge per exact frame/document as the correctness and security baseline.

This closes the cross-origin bootstrap and lifetime confusion window created when a shared bridge had to hand capabilities across frame boundaries. Browser-owned endpoint identity is now bound to tabId, frameId, documentId, origin, and the exact runtime Port. Session ownership, persistence scope, picker state, and Permissions Policy evaluation follow that exact document lifetime.

The PR also:

  • retires replaced document endpoints and cleans their sessions, policy state, pending delegation queries, and picker state
  • revalidates persistence authority across async grant and device-open operations
  • derives canonical opaque persistence scopes as opaque|<topOrigin>|<sourceOrigin>
  • treats literal opaque origin null as non-persistable
  • evaluates iframe allow="hid" allowlists for the exact child origin/document
  • propagates ancestor container-policy denial through exact document ancestry
  • resyncs settings after persistence-scope changes while preventing stale async loads from overwriting the new scope
  • updates event and session routing for exact frame ownership

There is no storage schema version change. IndexedDB remains version 2, STORAGE_SCHEMA_VERSION remains 1, and the existing settings key structure is unchanged. The only new persisted scope form is the canonical opaque key above.

Related issue(s)

N/A

Type of change

  • Bug fix
  • New feature
  • Refactor
  • Performance / Benchmark
  • Packaging / CI
  • Documentation
  • Tests
  • Other (please describe)

Testing

Added and extended addon coverage for:

  • exact frame/document endpoint replacement
  • stale pending opens across document replacement
  • opaque iframe persistence partitioning and top navigation
  • iframe HID allowlist semantics
  • nested Permissions Policy delegation and ancestor denial
  • settings scope-transition races
  • session cleanup on persistence-scope changes
  • picker cleanup on proactive endpoint retirement

Rust (daemon, NM host, mock)

  • cargo build --release passes, if the change touches Rust code
  • npm run lint:rs (cargo clippy) passes with no new warnings
  • npm run test:rs passes
  • Tested against a real HID device if the change touches enumeration,
    report descriptor parsing, or the data plane

Addon (JS)

  • npm run lint:js and npm run lint (web-ext) pass
  • npm run test:browser passes (no hardware needed)
  • npm run test:e2e passes if the change touches the data plane or
    worker-spawn paths (see E2E setup note below)
  • npm run test:benchmark if the change affects throughput or latency
  • Manually tested the changed area in the browser

E2E needs the debug binaries and one-time Linux setup
(sudo make install-e2e-udev-rule); see
docs/DEVELOPMENT.md. Running both e2e
projects concurrently requires --workers=1.

Checklist

  • I've read CONTRIBUTING.md
  • My commit messages follow Conventional Commits style
  • I've updated relevant docs (README, DEVELOPMENT.md, ARCHITECTURE.md,
    BENCHMARK.md) if needed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant