feat: add bounded compatible session browser (#8)
quality-gate / quality (push) Successful in 57s
quality-gate / quality (push) Successful in 57s
Closes #8
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
# ADR 0006: bounded compatible session browser
|
||||
|
||||
- Status: Accepted
|
||||
- Date: 2026-07-16
|
||||
- Tracking: #8
|
||||
|
||||
## Decision
|
||||
|
||||
The public list endpoint requires game, environment, and exact gameplay protocol.
|
||||
Region is optional, page size is 1–100, and callers may exclude sessions whose
|
||||
advisory current-player count has reached the advertised maximum. Lists contain
|
||||
public sessions only and only while both lease and authenticated host presence are
|
||||
fresh. Unlisted sessions never appear in a list; they may be retrieved directly by
|
||||
their 128-bit unguessable listing ID only when the caller also supplies the exact
|
||||
game, environment, and protocol scope.
|
||||
|
||||
Results use ascending opaque listing ID as a deterministic keyset. A cursor carries
|
||||
the last ID plus every compatibility/filter field, a five-minute expiry, and an
|
||||
HMAC-SHA256 signature under a per-process key. Tampering, expiry, or reuse with a
|
||||
different tenant/protocol/region/full filter returns `InvalidRequest`. Restart
|
||||
rotates the key, matching the loss of ephemeral listings.
|
||||
|
||||
Pagination is a bounded live view, not a database snapshot. A record that remains
|
||||
eligible and whose ID is greater than the cursor is returned exactly once. Records
|
||||
removed or made stale disappear immediately. A record created after a page whose ID
|
||||
sorts before that page's cursor is outside that traversal; callers refresh from the
|
||||
first page to discover new sessions. This avoids skips or duplicates among stable
|
||||
eligible records without retaining per-browser snapshot state.
|
||||
|
||||
The store reads at most page size plus one record. The service serializes against
|
||||
the 256 KiB response ceiling and shortens a page before returning it when metadata
|
||||
makes the requested count too large. A continuation cursor is emitted whenever an
|
||||
extra or byte-trimmed record remains. All cursor, page, metadata, property, scalar,
|
||||
and collection sizes are bounded before untrusted allocation can grow without a
|
||||
ceiling.
|
||||
|
||||
Browser DTOs are fresh copies containing only opaque listing ID, exact compatibility,
|
||||
region, visibility/trust presentation, advisory capacity, build/display labels, and
|
||||
policy-validated string metadata. They contain no observed endpoint, lease,
|
||||
capability, ticket, credential fingerprint, derivation salt, principal subject, or
|
||||
store key. Metadata is display text: JSON encoding escapes markup, but game UI must
|
||||
still render values as text and must never execute markup, interpret endpoints, or
|
||||
use metadata for authorization.
|
||||
|
||||
## Consequences
|
||||
|
||||
- Cross-game, cross-environment, incompatible, stale, revoked, expired, unlisted,
|
||||
and optionally full sessions are removed before response construction.
|
||||
- Direct unlisted lookup is suitable for an out-of-band invite carrying the opaque
|
||||
ID; human join codes remain future work and require their own bounded abuse model.
|
||||
- Host capacity remains advisory. The host makes the final admission decision.
|
||||
@@ -8,6 +8,7 @@ decision requires a superseding ADR and corresponding contract/test updates.
|
||||
- [ADR 0003: state, privacy, availability, and safety budgets](0003-state-privacy-availability-and-budgets.md)
|
||||
- [ADR 0004: atomic ephemeral state and single-active availability](0004-atomic-ephemeral-state.md)
|
||||
- [ADR 0005: authenticated session lease and presence lifecycle](0005-session-lease-lifecycle.md)
|
||||
- [ADR 0006: bounded compatible session browser](0006-compatible-session-browser.md)
|
||||
- [Threat model](../security/threat-model.md)
|
||||
- [Security promise and test matrix](../security/control-matrix.md)
|
||||
- [Versioned HTTP and UDP contracts](../contracts/README.md)
|
||||
|
||||
Reference in New Issue
Block a user