Errors, limits and timers
Every bound below is normative. Each links to the mechanism it constrains, because a constant without its mechanism is not implementable.
1. Fail-closed inventory
Section titled “1. Fail-closed inventory”The single most important table in this specification: every boundary where SSP/1 chooses safety over availability.
| Condition | Behaviour | Defined in |
|---|---|---|
| Invalid event signature | Drop and surface — never hold, so a forger cannot stall the impersonated node’s stream | semantics |
Unknown sender kid |
Drop and surface | data model |
| Unknown critical COSE header or content type | Reject | registry |
| Clock skew beyond bound | Reject, never clamp | data model |
| Out-of-scope event | Drop and log, never raise | semantics |
| No matching policy row | Deny | scope |
| Incomparable maximal policy rows | Deny and log, never guess open | scope |
| Purge requested | Error, never downgrade to soft delete | scope |
Identity conflict on existing site_id |
Hard fail, never overwrite | identity |
| Pairing signature failure | Abort, no downgrade | identity |
| Software key custody outside a dev build | Fail closed | identity |
Unknown ssp_version |
Refuse the exchange | messages |
| Malformed sync body | Reject | messages |
Unsolicited push without mutual supports_realtime |
Reject | messages |
| NaN or infinity in canonical CBOR | Refuse to serialize | data model |
The one deliberate exception is eviction, which fails open and keeps the row. The asymmetry is the justification: failing open wastes local storage, failing closed destroys data.
2. Normative bounds
Section titled “2. Normative bounds”| Bound | Value | Rationale |
|---|---|---|
| Clock skew tolerance | 300 000 ms | Bounds a hostile clock’s ability to win every future comparison |
| Vouch validity | 86 400 s | Long enough to seat a node across a brief outage; short enough to bound replay |
| Vouch future-dating tolerance | 300 s | Accommodates ordinary clock drift between honest nodes |
| Vouch quorum k | 2 where the mesh has 3+ nodes, else 1 | A quorum is meaningless below three participants |
| SAS strength | ~39.9 bits | log₂(10¹²); see SAS |
| Fingerprint display | First 4 bytes of site_id |
Display aid only, never an authentication input |
3. Implementation-chosen limits
Section titled “3. Implementation-chosen limits”These MUST be documented but are not fixed by the protocol, because the right value depends on deployment rather than on correctness.
| Limit | Constraint |
|---|---|
| Events per sync response | Finite; MUST be enforced by the sender |
| Materialization batch size | Finite |
| Backfill rows per cycle | Finite |
| Sync cycle interval | The retry unit; there is no separate backoff protocol. MUST keep running in realtime mode |
| Realtime push cadence | Implementation- or policy-chosen; a fixed cadence trades latency for timing-channel flatness |
| Mailbox retention | Finite and stated |
| Mailbox quota | Optional; MUST reject rather than silently drop |
4. Error handling posture
Section titled “4. Error handling posture”SSP/1 distinguishes three responses, and conflating them is the common implementation error:
- Reject — refuse this item, surface it, continue processing others.
- Hold — refuse this group for now, do not advance the watermark past it, retry next cycle. For conditions that may resolve.
- Drop — discard permanently, advance the watermark. For conditions that will not resolve, and for anything a hostile peer could otherwise use to stall the apply loop.
An implementation MUST NOT raise an exception that halts the apply loop on peer-supplied input. A single malformed event from one peer must not stop replication with every other peer.