Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Open Issues

This chapter catalogues known cross-implementation hazards in v0.1 of the specification. Each entry describes the issue, the concrete risk it presents, and the direction of the eventual resolution. Some of these will be addressed in a future minor version; some will require a major version. Where this chapter makes commitments to future versions, those commitments are non-normative.

The chapter exists for two reasons. First, hiding known hazards from implementers is a worse outcome than acknowledging them up front. Second, an open public list of known issues is how the specification gets corrected — it invites the discussion that produces v0.2 and v1.0.

Most entries describe true cross-implementation hazards. A small number describe decisions whose original justification was the reference implementation’s internal needs and which deserve re-evaluation now that the spec has a public audience of would-be implementers in non-Rust languages. Entries of that kind are flagged as such.

If you discover a hazard not listed here, please open an issue against the specification repository.

OI-1. Wire format has no version tag

The postcard encoding of an operation does not carry an explicit format-version field. Schema evolution within a minor version is constrained to additions only, but a binary mismatch between two implementations using different incompatible schema versions will fail at decode time without a graceful error.

Risk. A future schema migration that is not strictly additive — for example, removing or repurposing a field — will silently corrupt logs read by an implementation expecting the old shape.

Direction. The next major version is expected to introduce a leading version byte (or a varint) on every op envelope, allowing recipients to dispatch on schema version explicitly.

Workaround in v0.1. Implementations SHOULD include the specification version they implement in their bearer token metadata or in a discovery endpoint, so peers can refuse to sync with mismatched versions before the wire format issue manifests. The X-Likewise-Mesh-Rules-Hash header (see Sync) provides a partial signal.

OI-2. Causal frontier cursor is opaque

The since cursor passed to GET /ops is the base64url encoding of a postcard CausalFrontier value. This is opaque from the client’s perspective beyond the empty-frontier special case, and there is no negotiation about its format.

Risk. An implementation that changes the underlying CausalFrontier representation in a non-additive way will break clients that hold persisted cursors from an earlier version.

Direction. Future versions are expected to specify a versioned cursor envelope or to standardize the CausalFrontier shape explicitly so changes are detectable.

Workaround in v0.1. Implementations MUST treat cursors as write-once-then-echo: a client sends back exactly what the server returned in X-Likewise-Next-Frontier. Implementations SHOULD discard cached cursors on protocol-version upgrades.

OI-3. Sanitized ops carry no signature, by design

A sanitized op has its signature cleared to None and is distinguished from corruption by a sanitization marker (see Wire Format).

Risk. A receiver that does not implement marker checking will either reject all sanitized ops as corrupted (denying service to legitimate filtered traffic) or accept all unsigned ops as sanitized (admitting forged traffic). The marker check is the only thing distinguishing the two cases.

Status. This is a design decision, not a defect. The specification’s contract is that sanitization is intentional and the marker is verifiable against the sender’s delegation chain.

Direction. A future revision MAY introduce a hash-chain mechanism that lets a receiver verify a sanitized op’s provenance to its pre-sanitization form, addressing the “delegated trust” concern at the cost of additional bytes on the wire. v0.1 does not include this.

OI-4. Mesh-rules drift has no negotiation

Two peers with different X-Likewise-Mesh-Rules-Hash values pause sync (per Sync). There is no automatic protocol for resolving the divergence.

Risk. A long-running mesh whose rules document has incrementally drifted on one node (typically because the operator updated it) will lock that node out of sync until the divergence is resolved manually.

Direction. A future revision is expected to define a mesh-rules-negotiation pre-handshake: peers exchange rule documents and either adopt the newer common version or explicitly refuse to interoperate. The exact mechanism is open.

Workaround in v0.1. Operators MUST manage rules versioning out of band (e.g., by deploying rule updates to all nodes in lockstep). Implementations SHOULD log mesh-rules-hash mismatches loudly enough to catch operator errors early.

OI-5. HLC skew tolerance is implicit

The protocol does not specify a maximum allowable wall-clock skew between a node and the operations it accepts (per Clocks). A node whose clock is far in the future can effectively rewrite the order of the mesh’s history by emitting future-dated timestamps; receiving nodes will adopt the larger wall_ms on receive.

Risk. A compromised or malfunctioning node can dominate the HLC ordering for the rest of the mesh, distorting the meaning of “before” and “after” for as long as it does so.

Direction. A future revision is expected to specify a negotiated skew bound as part of the mesh-rules document: operations whose wall_ms exceeds the recipient’s local time by more than the bound are rejected.

Workaround in v0.1. Implementations SHOULD warn on operations whose timestamp is more than one hour ahead of the local wall clock. They MAY refuse to accept such ops as a local policy choice, but doing so is not specified by v0.1 and may cause sync to lag.

OI-6. UCAN v0.10 is the wire format

v0.1 implementations carry UCAN v0.10 (JWT-shaped) tokens. The UCAN working group has moved to v1.0 (DAG-CBOR + Varsig + CIDv1 envelopes). v0.10 is no longer the upstream’s preferred format.

Risk. Tooling and ecosystem support for v0.10 will atrophy over time. New external libraries will target v1.0 and inter-protocol interop (with other UCAN-using systems) will be harder.

Direction. The next major version is expected to migrate to UCAN v1.0. The migration is non-trivial: token canonical form, signature shape, and the proof-chain reference encoding all change. The migration MAY be staged (v0.10 and v1.0 co-existing during transition) or atomic; the working group will decide.

Workaround in v0.1. Implementations are stuck on v0.10. They SHOULD isolate the UCAN implementation behind a narrow interface so the migration is a contained change.

OI-7. No bulk-transfer mode for first sync

Catching up a long-disconnected node from genesis requires paginated GET /ops calls (per Sync). For a mesh with millions of ops this can be slow.

Risk. Onboarding a new node, or recovering a node that has been offline for an extended period, takes longer than it needs to.

Direction. A future minor version is expected to add a bulk-transfer mode (likely a streaming response with a specific Accept header on GET /ops) that ships a snapshot plus a delta from a known checkpoint.

Workaround in v0.1. Implementations MAY ship the underlying storage offline (USB drive, file copy) for first-time onboarding, then resume incremental sync. This is operator choice, not a protocol mechanism.

OI-8. No server-initiated push hints

The sync protocol is pull-based. A node learns of new operations only when it polls. There is no server-initiated push of “you have new operations to fetch.”

Risk. Propagation latency is bounded below by the polling cadence, which is in tension with battery and bandwidth considerations on mobile nodes.

Direction. A future minor version is expected to add an optional WebSocket or webhook endpoint a server can use to hint a peer that fresh operations are available. Hints are advisory; the actual op exchange remains pull-based for authoritative correctness.

Workaround in v0.1. Implementations choose polling cadences that balance latency and resource use (typical defaults: 30 seconds on stable connections, 5 minutes on metered).

OI-9. No confidential sync

A peer can probe a node for the existence of operations it is not authorized to receive by sending crafted since cursors and observing the response shape. The capability filter prevents the operations themselves from being returned, but it does not prevent a peer from learning that the unreachable operations exist.

Risk. An attacker with read access to part of the log can infer the existence and approximate timing of operations they are not authorized to see.

Direction. A future revision is expected to adopt a confidential-sync mechanism (likely modeled on Willow Protocol’s private-set-intersection-style approach), where peers cannot probe for unauthorized operations at all. This is a significant protocol redesign and is unlikely to land before a major version bump.

Workaround in v0.1. Implementations SHOULD NOT distinguish “unauthorized op” from “no op” in their response shape (return the filtered op set without any “filtered N” indicator). Implementations MUST NOT return per-op “you are not authorized” errors, which would themselves leak the existence of the filtered ops.

OI-10. Predicate vocabulary is not yet standardized externally

The set of claim predicates is centralized in this specification but is not yet structured for external extension. An application wishing to add a new predicate (for a new domain — health data, financial data, professional context) must either propose it for inclusion in the specification or hijack a generic predicate.

Risk. Without an external-extension mechanism, the predicate vocabulary either grows to encompass every imaginable domain (unwieldy) or fragments across non-standard predicate strings (non-interoperable).

Direction. A future minor version is expected to introduce namespaced predicate prefixes (e.g., org.cortex.location_at versus com.example.medical.diagnosed_with) and a registry mechanism for third-party namespaces.

Workaround in v0.1. Stay within the existing vocabulary where possible. For application-specific extensions, use the custom-metadata field on evidence and let consumers interpret it; do not author claims with non-vocabulary predicates.

OI-11. Wire encoding choice was implementation-led

Decision under review based on the spec’s publishing situation. This entry is a re-evaluation of an originally- defensible default, not a known defect.

The canonical wire encoding (postcard) was chosen because the reference implementation is in Rust (see Wire Format §1). Postcard is compact and deterministic by construction, which satisfies the protocol’s bit-exact-output requirement, and the encoding is fully specified in the wire-format chapter without reference to the postcard library. From inside the reference implementation the choice is invisible.

From outside, postcard has near-zero tier-1 implementation support outside Rust. There is no schema language, no validator, and no widely-deployed cross-language tooling. The wire-format chapter specifies enough that a determined implementer in Go, Swift, or TypeScript can produce byte-identical output, but the work is materially larger than it would be against a more universally-supported encoding.

Risk. Implementer friction. The single biggest external signal that a protocol specification is legitimate is the appearance of a second, independent implementation. Anything that raises the cost of that work — including the choice of a wire codec with limited cross-language support — slows the appearance of that signal.

Direction. A future major version is expected to migrate the canonical encoding to one of:

  • CBOR (RFC 8949) with the deterministic encoding profile (§4.2). CBOR is an IETF-track standard, has tier-1 libraries in every language, and aligns with UCAN v1.0’s DAG-CBOR envelope (see OI-6) — consolidating the protocol to one binary codec.
  • Borsh. Smaller and simpler than CBOR, deterministic by default, used in the NEAR / Solana ecosystem so it has non-Rust implementations, but less universal than CBOR.

Both candidates preserve the bit-exact deterministic property the protocol requires. The wire-format chapter is already careful about encoding mechanics (option discriminant, varint conventions, field ordering) that mostly carry over with vocabulary changes. Signing canonicalization is independent of the underlying codec.

Workaround in v0.1. Postcard remains the canonical encoding for v0.1 conformance. Implementations targeting v0.1 SHOULD isolate the serialization layer behind a narrow interface so a future migration is a contained change. Implementers considering an exploratory port to a different codec can use the wire-format chapter as a structural guide; the encoding rules specified there are codec-agnostic in spirit even though the canonical codec named in v0.1 is postcard.

How to propose changes

Each open issue here is a candidate for revision. To propose a direction, open an issue on the specification repository (see Contributing) and reference the OI number above. Substantive changes are expected to land in v0.2 (additive minor) or v1.0 (backwards-incompatible major) depending on scope.