Specification §17
Limits of the current design and implementation, not open questions about the invariants. The key words MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY are to be interpreted as described in RFC 2119.
FrogNet Specification — Draft 0.9, revision 2026-08-29. Cite a conformance claim against this revision, not against a section number alone.
These are limits of the current design and implementation. They are not open questions about whether the invariants in §2 hold. None is hidden behind a fallback: each fails visibly, says what it is, and is written down here, which is the only honest way to ship something unfinished.
An implementation claiming conformance MUST reproduce these limits or state explicitly which it has removed and how, since several of them are consequences of the invariants rather than defects to be repaired.
Mechanism. There is no watch, no subscription, and no callback on a value moving. A program that needs to know when a value changed reads it again.
Consequence. Observation latency is bounded by the reader's poll interval, chosen by the reader. Polling is inexpensive on this fabric because an unchanged read collapses to a SAME frame (§11), but inexpensive is not free and is not the same as being told.
Status. Open, and a consequence of §2e rather than an oversight. The conceptual memwatch in §1.4 is named there precisely so that no reader goes looking for the call — verified absent: the tree contains no watch, no subscribe, and no notification path for a value.
Mechanism. Every write in a connected pond is ordered at the elected database host (§2b).
Consequence. Writes are bounded by the throughput of one point and do not scale horizontally. The coherence property and the scaling limit are the same fact stated twice, so this limit cannot be removed without removing the guarantee that makes the model work. Contention on a single key is whatever the backing database does about contention on a key; a thousand writers fighting over one value is a design problem no substrate repairs.
Reads are not bounded the same way, and not by replication. Nothing is replicated (§2a). Reads relieve the store by three mechanisms, each of which preserves the single copy:
| Mechanism | Where | What keeps it honest |
|---|---|---|
| Receive-side collapse | Any node answering | N callers asking the same question in the same instant cost one origin execution among them (§11.12) |
| Proven-current RAM materialization | Database host only | Served only where a generation counter proves RAM equals disk on this request; fails closed (§9.4a) |
| Local read cache | Every node, its own forwards only | Scoped invalidation plus a short TTL; bounded-stale within the freshness window, which the store evaluates on the clock that stamped the row (§9.4) |
None of these is a second authoritative copy, and an implementation MUST NOT describe them as replication.
Status. Structural. Not a defect.
Mechanism. The per-tunnel address allocator bounds the number of addresses available within one pond.
Consequence. A ceiling of roughly fifty-eight nodes in a single-pond broker, and as few as sixteen where one broker carries a second pond. Larger deployments span multiple ponds joined by the broker (§7) rather than growing one pond — and an implementation MUST NOT assume the single-pond figure holds on a shared broker.
The arithmetic. Every tunnel the broker builds needs a carrier block: a point-to-point link at each end, joining two nodes through the broker's namespace. Blocks are allocated from a reserved /16, but the current algorithm uses only a band of it, in fixed groups:
reserved transit range /16 = 65,536 addresses
current algorithm 54 blocks x 31 tunnels = 1,674 tunnels
full mesh needs n(n-1)/2 tunnels
n(n-1)/2 <= 1,674 -> n = 58
Two effects make the practical figure worse. Bands are spaced so each pond's begins four steps after the last, so a broker running a second pond leaves the first with four blocks instead of fifty-four — 124 tunnels, sixteen nodes. Nothing about the first pond changed; the room it was free to grow into now belongs to another. And each tunnel consumes eight addresses where it uses four: carrier blocks are allocated as pairs of four-address subnets, two addresses of each being subnet bookkeeping that a WireGuard link has no use for, having neither broadcast nor address resolution. Half the space goes to a convention that does not apply.
A larger range is not the fix, and an implementation MUST NOT treat it as one. Tunnels in a full mesh grow as the square of the nodes, so addresses buy nodes back at a square root:
stop wasting half of each block 2x tunnels -> 1.4x nodes use the whole reserved range 5x tunnels -> 2.2x nodes hand transit ALL of 10/8 256x tunnels -> 16x nodes
The last line settles it: 256 times the space — every address the mesh itself lives in, which is impossible — buys sixteen times the nodes. The size of the address space is not the defect. Allocating anything at all per tunnel is the defect. While the scarce resource is spent per tunnel and tunnels are quadratic, the ceiling stays low however much of the resource exists.
Status. The replacement in development moves allocation from per tunnel to per node: one carrier address per node rather than one per peer it talks to. WireGuard has carried many peers on one interface since it existed, routing among them by key rather than by interface.
internet_tunnels_v3/.Mechanism. Last write wins against the key, with a freshness window the store evaluates against the row's own update time (§9.4), plus process-owned tuples reaped at their writer's exit. That is the whole of it.
Consequence. Handable authority, versioning, leases, transactions, optimistic updates and single-writer regions are not provided. An application needing one today has to build it — which is exactly the class of code this model exists to stop people writing.
Status. Open; named as direction, not as commitment.
Mechanism. The thresholds at which the codec selects between full, differential and identity replies are set by judgement rather than derived from measurement.
Consequence. There exist payload shapes for which a different threshold would send fewer bytes. No correctness property depends on the choice; only efficiency does.
Mechanism. The codec classifies a body by inspecting it, never by its declared content type (§10.7). Five content modes are registered — json, xml, html, text, raw — plus one media mode registered separately for the SotF codex.
Consequence. Misclassification to raw forfeits compression for that class: a raw body learns no template and every send of it crosses FULL (§11.7). It does not produce a wrong answer — a raw body is transmitted whole and correctly — so the failure is a cost, not a fault. An empty or undecodable body classifies raw by construction.
Mechanism. Outbound, audio takes precedence over video on the shared wire: a voice packet never waits behind a keyframe. Inbound, frames are handled in arrival order.
Consequence. The rule that holds in one direction does not hold in the other. It is one rule applied in one more place.
Status. Open. Bounded, with an obvious oracle; a good first contribution.
Mechanism. The media relay reports backpressure in aggregate.
Consequence. Reduced since the aggregate report stopped moving the rate: the rate now derives from what participants publish about themselves, and a viewer reports its own condition directly. What survives is that the relay still cannot attribute a discard.
Status. Partially closed, 11 August 2026. Per-sender attribution is information the relay already holds and does not use.
Mechanism. The media relay forwards one stream and bounds the call rate to the slowest participant.
Consequence. A fast participant is held to a slow one for as long as both are in the call. This stands until the relay can send a client something other than what arrived.
What the simulator does not model, stated as of the closed feedback loop rather than as of first release. A conforming test suite MUST NOT claim anything in the first column.
| Not modelled | Because |
|---|---|
| Concurrency | Merges are serialized. A race that requires two merges in flight cannot be produced. |
| Packet loss and jitter | The wire delivers. Per-edge latency is modelled and is calibrated from measurement (§17.11.1); loss and jitter are not. |
An earlier statement of this section said that no simulated result had been confirmed by a real deployment. That is no longer accurate and MUST NOT be repeated. A closed feedback loop exists in both directions:
| Direction | Mechanism | Status |
|---|---|---|
| Hardware blesses the model | A run on the box records committed route tables by kernel readback and writes them as a versioned baseline stamped source: "hardware". The offline gate re-runs the real planner and committer and asserts the output still matches. | 20 of 20 topologies recorded source: hardware; the offline engine reproduces every one |
| Hardware calibrates the model | Measured per-edge RTT medians by bearer kind are ingested and override the model's guessed values at run time, before the timing tier runs. | In use; guesses replaced by measurement |
| Hardware faults become tests | Each captured real fault is written as a failure scenario with its honest expectation and replayed offline thereafter. | In use |
Provenance MUST be recorded per baseline, because it decides severity: a mismatch against a hardware baseline is a regression — the offline code no longer reproduces blessed kernel truth — while a mismatch against an offline baseline is drift since the last blessing and may be intended.
What correspondence covers, precisely. Committed route tables and reachability are gated against hardware truth. Discovery convergence cycle counts are recorded but not gated, because timing varies; an implementation MUST NOT treat a simulated cycle count as a predicted one. As everywhere in this specification, convergence here means discovery reaching a stable derived topology and nothing else (§2c, §6.7). Nothing here establishes that a simulated throughput or bandwidth figure predicts a deployed one; those remain separate measurements of separate workloads (§14).
Specification §2, §9.8, §11, §14, §16. Build manual: Croakus §54. Contributions: Discussions.