docs(peer): describe the new discovery, hint, framing and unpack bounds

Bring ARCHITECTURE.md in line with the security fixes on this branch:
unicast-only mDNS candidates and the per-source-IP candidate budget,
source-IP binding of change hints, the split 64 KiB request / 8 MiB
response frame caps, and the `-ol-` plus link-audit rule for ordinary
`.eti` extraction.

Claude-Session: https://claude.ai/code/session_017C3Nbgwpdm3YNwZhhFLHwg
This commit is contained in:
2026-09-02 22:39:40 +02:00
parent 55fa4941bc
commit 1ae752f2a5
+25 -6
View File
@@ -57,8 +57,12 @@ When a peer is discovered:
1. Parse `peer_id`, address, and `proto_ver` into a candidate `PeerEndpoint`.
Discovery is not authentication and does not add the peer to `PeerGameDB` or
emit UI membership events. The mDNS ingress queue and active candidate
negotiations are each capped at 64.
emit UI membership events. Advertised addresses must be unicast with a
nonzero port; multicast, broadcast, and unspecified targets are dropped
before any handshake packet is sent. The mDNS ingress queue and active
candidate negotiations are each capped at 64, and one source IP may hold at
most 8 active-or-cooling candidates so a single host cannot fill every slot
by rotating claimed peer IDs and ports.
2. Reserve a candidate negotiation lease before queueing or awaiting work, then
establish a TLS-pinned connection to that exact endpoint. Missing or non-v8
records are rejected, and neither an ephemeral QUIC source port nor a payload
@@ -85,15 +89,20 @@ When a peer is discovered:
and both domain revisions. A session or revision mismatch schedules a full
pinned pull, so idle liveness heals dropped change hints.
- Local library or Call-to-Play changes send cheap revision hints. Hints are
untrusted and lossy: unknown claims are ignored, and a known claim can only
coalesce a pull from the claimed peer's already authenticated endpoint.
untrusted and lossy: unknown claims are ignored, a hint is honoured only when
it arrives from the IP address at which the claimed peer was authenticated,
and a known claim can only coalesce a pull from the claimed peer's already
authenticated endpoint. Requesters are anonymous, so this source binding is
what stops a third host from choosing which peers this node pulls.
- The state-sync scheduler caps its ingress and tracked peers at 64, coalesces
work for five seconds, and runs at most eight pinned pulls and eight hint
sends concurrently. Child work is drained lexically on shutdown.
- The server admits at most 64 unauthenticated handshakes, 64 established
connection scopes, and 32 control streams per connection. Each control stream
accepts one frame followed by request EOF and sends at most one response; the
frame cap is 8 MiB and control I/O has ten-second deadlines.
accepts one frame followed by request EOF and sends at most one response.
Inbound request frames are capped at 64 KiB (the QUIC receive window per
server stream matches it), response frames at 8 MiB, and control I/O has
ten-second deadlines.
### Call to Play replication
@@ -315,6 +324,16 @@ Most scans become O(number of game dirs), with full recursion only when needed.
`local/`, and install transaction metadata are preserved, so a cancelled
update of an installed game settles as local-only.
### Ordinary install extraction
- `install`/`update` extract every direct regular root `.eti` archive with the
external `unrar` unpacker into the staging directory. The archives were
BLAKE3-verified against the catalog when downloaded.
- `unrar` runs with `-ol-`, so symbolic-link entries are skipped, and the
staging tree is walked without following links before promotion. Any symlink
(or reparse point on Windows) aborts the transaction and rolls staging back,
so a link can never redirect later launch-time rewrites or uninstall.
### Streamed install integrity
- Low-disk streamed installs request archive-derived file bytes from one peer