Skip to content

Message/token lifetime and fungibility #33

Description

@Mearman

Parent: #28

Independently design-verified (2026-09-14) against the real spec and TypeScript source, matching sections A-C's own dedicated passes -- no longer just conversational reasoning. Confirmed the core finding, corrected two real overclaims, and found genuine gaps the original framing glossed over.

Message/content lifetime -- verified, ready to implement

token-claims' expires/not-before gate authorisation only, checked in verifyTokenChain (ts/packages/core/src/domain/tokens.ts:190-196) against the verifier's own local Clock. Neither room.send/room.read nor room-notice-claims carry any TTL field. core/data's retention is explicitly deployment policy (spec/data-domain.cddl:11-21), not protocol.

Design (both extension points already exist, no schema renegotiation needed -- token-claims' tail at tokens.cddl:95, room-notice-claims' tail at room.cddl:236):

? "valid-until": uint,   ; Unix ms; bounds the authorised CONTENT/ACTION's lifetime, distinct from `expires` (authorisation-to-present-the-token). Absent = unbounded.

Verifier obligation: reject when now > valid-until, independent of expires/revocation; for notices, checked at read time. Real integration point for tokens: verifyTokenChain in tokens.ts, right after its existing expires check. room-notice-claims has no verifier function at all today (no room.ts/verifyRoomNotice exists in ts/packages/core/src/domain) -- the notice-side check is net-new domain logic, not an addition. Also inherited (not introduced) by this: mesh-session.ts::applyManageRequest does no verification and no re-check loop -- "expired mid-flight" is already undefined behaviour for expires today, and valid-until won't get continuous enforcement for free either.

Fungibility -- two of three mechanisms have no current use case; correctly deferred

Exhaustive search of spec/*.cddl found no single-use/redemption/use-count language anywhere except delegations-remaining (a depth bound, not a use-count bound). The obvious candidate (room.invite as a coupon) doesn't fit on inspection: its token is bearer-bound at mint time and room.join mints fresh per request -- membership isn't "spent," it's the authorisation itself. Single-use and limited-fungibility should not be built without a real use case -- speculative machinery, against this project's own no-premature-abstraction principle. Conditional fungibility isn't a deliverable -- it's just the existing extension-tail-plus-verifier-obligation pattern, already shipped.

Redemption/double-spend detection -- does NOT hold as originally stated; real gap, own design pass needed (see sub-issue)

The original "reuse the existing revocation-announce/gossip mechanism" claim doesn't survive checking the real code:

  • revocation-claims (management.cddl:45-50) is a closed CDDL map, no extension tail -- can't carry a "redeemed" fact without its own schema change.
  • Revocation is issuer-only by design; a redemption fact is naturally attested by whoever received it, often not the issuer -- doesn't fit the trust model as-is.
  • Propagation is not flood-gossip today: sendRevocationAnnounce (mesh-session.ts:586-599) sends over one direct connection only; nothing re-broadcasts; relay-hub.ts:163 drops these frames; web-console/src/webrtc-negotiation.ts:36 already documents "no revocation-gossip ingestion yet" as a known limitation.

Real current behaviour: a second presentation of an already-redeemed grant to a peer that hasn't seen the redemption announcement verifies as valid, full stop -- not "best-effort detected eventually," since there's no flood propagation to make it best-effort. Genuinely decentralisation-limited (no true double-spend-proofness without consensus) remains correctly stated and unchanged.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions