Skip to content

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.

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.

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

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

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.