Skip to content

docs(bridge): allowedAppOrigins admits origin patterns - #48

Merged
xgreenx merged 9 commits into
docs/ceremony-browser-architecturefrom
specs/bridge-wildcard-app-origins
Sep 23, 2026
Merged

xgreenx merged 9 commits into
docs/ceremony-browser-architecturefrom
specs/bridge-wildcard-app-origins

Conversation

@xgreenx

@xgreenx xgreenx commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

The bridge contract says every allowedAppOrigins member is a canonical application origin. #46 gave the browser side origin patterns and #28 moved member validation out of the Callback into the popup package. This carries both through the bridge, CCDP and Distribution chapters.

Changes

  • allowedAppOrigins admits a pattern member, spelled *.handles.link with no scheme, and *. The popup transport owns the spelling and the matching rule; this chapter cites it rather than restating it.
  • REQ-BRIDGE-02 admission covers the pattern case, and the response still echoes the exact requesting origin, never a pattern and never *.
  • The bridge narrows no member on width. How wide an allowlist is belongs to whoever writes it. It admits the origins its members admit on the browser side, neither more nor fewer; only ccdpOrigin becomes a policy source and only it is held to the alphabet a source expression can carry.
  • Coordinated upgrades resolve the versioning contradiction: widening a member type without adding an input binds deployment order instead of an input-contract version. ccdp-distribution.md owns the rule; oauth-bridge.md cites it.
  • Rejection targets pattern spellings. An exact member still authenticates a peer observed at exactly that origin, and TEST-CCDP-04 pins that positive case.
  • Validation moved. Sentences assigning member validation to the Callback now say where it happens; feat(ceremony): implement browser identity ceremonies #28 deleted that check.
  • The ccdp.md invariant on browser-observed exact origins keeps its claim and names what a pattern costs, at the depth the merged matcher allows.

Merge order

This branch sits on #13, whose tree still carries the pre-#46 popup-transport.md — the one that bans patterns — while oauth-bridge.md here delegates the pattern rule to it. #47 must land on #22 first, or this chapter is unsatisfiable against the popup chapter in its own tree.

Verified

Spec linter over the whole suite: 31 errors, 100 warnings, byte-identical finding set to the baseline.

The bridge implements this: libid-org/libID-bridge-rs#20, merged, released as v0.4.0. A differential run over 3,192,340 admission pairs found the bridge and the browser side admit the same origins, with zero in either direction.

Not verified

Nothing here is executable. No deployment carries a pattern yet.

An operator serving one application per subdomain cannot enumerate them, so
an allowlist member may now be a pattern; the popup transport owns its
grammar and match, and no layer restates them.

The union stays literal, so a pattern never absorbs the CCDP origin, and the
peer is still bound to the exact observed origin. What widens is the type of
an existing Callback input: an older Callback accepts a pattern and matches
no peer, so a deployment waits for a Callback that understands one.

Assisted-by: Claude Opus 5
Signed-off-by: Green Baneling <XgreenX9999@gmail.com>
A URL parser reports a suffix with a port, a trailing dot or an empty label
canonical, so well-formedness needs byte checks the parser does not do, and
the spec now names them rather than leaving each layer to infer them.

A star that is not a well-formed pattern is a typo, not an exact origin, and
admitting it only postpones the failure to a ceremony that never becomes ready.

Canonicality is tested ahead of membership of either kind, because the literal
branch otherwise lets a peer claim a member's own spelling and bind it.

Assisted-by: Claude Opus 5
Signed-off-by: Green Baneling <XgreenX9999@gmail.com>
A URL parser reports 127.0.0.1 canonical and every byte check passes it, so
the grammar admitted https://*.127.0.0.1 although an address has no labels to
delegate and the loopback exception covers exact hosts only.

The CCDP origin reaches the Callback's frame-src, so a pattern in that input
would reach a Content-Security-Policy, and the conformance list now says so.

Rejecting an Origin that spells a pattern is the rule that a member spelling is
never an observed origin, not an exception to literal membership.

Assisted-by: Claude Opus 5
Signed-off-by: Green Baneling <XgreenX9999@gmail.com>
The merged popup package spells a member `*.handles.link`, admits every depth
below the suffix, and accepts a one-label suffix, so the grammar described here
named a list the client rejects outright.

The bridge refuses `*` and a one-label suffix at startup: refusal narrows
admission, so the two sides cannot disagree, and an operator reads an error
rather than a ceremony that never becomes ready. Member validation now happens
in the popup endpoint, not the Callback.

Assisted-by: Claude Opus 5
Signed-off-by: Green Baneling <XgreenX9999@gmail.com>
A bridge refuses an origin carrying a byte its own policy composition
cannot name, so it admits fewer origins than the browser side under the
same member. Only the reverse would let the two disagree.

Assisted-by: Claude Opus 5
Signed-off-by: Green Baneling <XgreenX9999@gmail.com>
@xgreenx
xgreenx requested a review from Wondertan September 23, 2026 15:51

@Wondertan Wondertan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Three corrections requested below. Exact-origin handoff and literal CCDP membership otherwise align with the implementation. Whole-suite lint introduces no new findings relative to the base.

Comment thread specs/oauth-bridge.md Outdated
Comment thread specs/ccdp-distribution.md Outdated
Comment thread specs/ccdp.md Outdated
The pattern prose restated the transport's grammar and matching rule, then
explained each rule it stated. A restated normative statement can drift from
the one that owns it, and an explanation is not a requirement.

The rules are unchanged: the member kinds, the two startup refusals, the
subset relation and its direction, the literal union, the exact echoed origin,
the deployment ordering, and where member validation happens. The cut examples
and the rejected spellings live in the TEST entries.

Assisted-by: Claude Opus 5
Signed-off-by: Green Baneling <XgreenX9999@gmail.com>
An allowlist as wide as `*` is the responsibility of whoever configures it, so
the bridge-only startup refusals come out.

The two versioning rules disagreed; the artifact contract now owns one
coordinated-upgrade exception and the bridge cites it.

TEST-CCDP-04 rejected any member's own spelling, which also rejects an exact
member's ordinary case; it is a pattern member's spelling.

Restored: the bound on the MAY, canonicality ahead of membership of any kind,
and Callback's exact-authentication.

Assisted-by: Claude Opus 5
Signed-off-by: Green Baneling <XgreenX9999@gmail.com>
The byte filter it applies to every origin it reads is a member refusal,
so a blanket claim that it adds none contradicts the paragraph below.

Assisted-by: Claude Opus 5
Signed-off-by: Green Baneling <XgreenX9999@gmail.com>

@xgreenx xgreenx left a comment •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All three addressed.

  • Both bridge-only refusals removed. * is a member kind the bridge publishes.
  • Versioning: ccdp-distribution.md owns the rule and states the coordinated-upgrade exception. oauth-bridge.md cites it.
  • Rejection vector: pattern member's spelling. TEST-CCDP-04 also pins the positive case — an exact member authenticates a peer observed at exactly that origin.

The bridge now admits what the browser admits, neither more nor fewer. The byte filter it applied to every origin is scoped to ccdpOrigin, which names_a_policy_host already holds to the policy alphabet.

@xgreenx
xgreenx requested a review from Wondertan September 23, 2026 16:21
The subset language covered a byte filter the bridge no longer applies
to application origins. Only the CCDP origin becomes a policy source.

Assisted-by: Claude Opus 5
Signed-off-by: Green Baneling <XgreenX9999@gmail.com>
@xgreenx xgreenx self-assigned this Sep 23, 2026
@Wondertan

Copy link
Copy Markdown
Member

Re-reviewed at d03104a. All three findings are resolved:

  • Bridge accepts * and valid suffix patterns.
  • Coordinated upgrades explicitly resolve the versioning contradiction.
  • Exact-origin entries remain valid; rejection targets pattern spellings.

No new blocking findings; spec lint results are unchanged.

Remaining cleanup: the PR description still claims Bridge-only restrictions and says libid-server-rs PR20 is unmerged—it has merged. PR47’s transport rules still need incorporating before merge.

@xgreenx

xgreenx commented Sep 23, 2026

Copy link
Copy Markdown
Contributor Author

Description corrected: the bridge-only restrictions are gone from it, and libid-org/libID-bridge-rs#20 is recorded as merged and released as v0.4.0.

On the transport rules: #47 carries them and is open against #22. This branch stays unmergeable until it lands, as the Merge order section says.

@xgreenx
xgreenx merged commit 2b9afbf into docs/ceremony-browser-architecture Sep 23, 2026
6 of 8 checks passed
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.

2 participants