Skip to main content

Module stream

Module stream 

Source
Expand description

CORD-01 Private Streams — the Concord v2 envelope.

Every durable plane event is the same three-layer shape: a kind-1059 wrap signed by the plane’s derived group key (fixed author, random ephemeral p tag — NIP-59 reversed), containing a seal signed by the author’s real key, containing the unsigned rumor that carries the functional kind.

Two seal forms, fixed per plane (CORD-02 §5), declared by the seal’s kind:

  • 20013 encrypted (Chat, Guestbook, rekey planes): the rumor is NIP-44-encrypted again inside the already-encrypted wrap, so no layer can ever be lifted out as a standalone public event.
  • 20014 plaintext (Control Plane ONLY): the seal’s content is the rumor’s serialized JSON string byte-verbatim, which is what lets a compaction re-wrap a signed edition into a new epoch with the signature intact. A re-wrap MUST carry those exact bytes forward, never re-serialize.

Ephemeral actions (typing, voice presence) ride the identical structure at kind 21059 — relays MUST NOT store it.

NIP-44 hard-caps plaintext at 65,535 bytes and libraries are lenient, so the cap is enforced HERE at every nesting layer — a lenient publisher mints events a strict reader cannot decrypt.

Structs§

OpenedStream
A fully verified, opened stream event.

Enums§

SealForm
Which seal form a plane uses (CORD-02 §5) — a fixed property of the plane, never a per-message choice.
StreamError
Errors from building or opening a v2 stream event.

Constants§

KIND_SEAL_ENCRYPTED
Encrypted seal (Chat / Guestbook / rekey planes).
KIND_SEAL_PLAINTEXT
Plaintext seal (Control Plane only).
KIND_WRAP
Durable stream wrap.
KIND_WRAP_EPHEMERAL
Ephemeral stream wrap — identical structure, relays MUST NOT store it.
NIP44_MAX_PLAINTEXT
NIP-44 v2 plaintext hard cap, enforced at every nesting layer.

Functions§

build_rumor_ms
Build an unsigned rumor carrying a full epoch-ms timestamp: created_at takes the seconds, an ["ms", <0..999>] tag the remainder.
build_rumor_secs
Build an unsigned rumor with a plain seconds timestamp and NO ms tag — the Control Plane shape (editions fold by version, not time).
build_seal
Local-keys convenience: build + sign the seal in one step. Wire-identical to the split path (seal_content + caller-side signing), which bunker accounts use instead.
channel_binding_tags
The standard chat binding tags for a rumor: ["channel", id] + ["epoch", n].
check_channel_binding
Enforce the Chat-plane binding (CORD-03 §3): the rumor MUST commit ["channel", id] + ["epoch", n], strict-equal to the coordinate whose key decrypted the wrap; a mismatch (or duplicate/absent tag) is a splice — drop.
open_wrap
Open and fully verify a stream wrap against the plane’s group key.
resolve_ms_strict
Resolve a rumor’s true millisecond time — STRICT per CORD-02 §5: an absent ms tag is offset 0; ANY present ms tag that isn’t a lone integer in 0..=999 makes the event malformed (BadMs — drop it, never clamp), or the excess would smuggle arbitrary “future” past the coalesce clock checks.
rewrap_seal
Re-wrap an already-verified PLAINTEXT seal into another stream (a compaction carrying a signed edition into a new epoch). The seal event is carried whole — its content string holds the rumor bytes verbatim, so the rumor id and the author’s signature survive.
seal_content
The seal’s content for a rumor: NIP-44 ciphertext under the stream’s conversation key (encrypted form) or the rumor’s serialized JSON string verbatim (plaintext form). Split from signing so the caller can sign with local keys OR a NIP-46 bunker — the seal is (seal_form.kind(), content, created_at = rumor.created_at) signed by the author’s real key.
split_ms
Split a full epoch-ms send time into (created_at seconds, ms remainder).
wrap_seal
Wrap a signed seal into the outer stream event: content = NIP-44 under the stream conversation key, signed by the group key, one random ephemeral p tag (NIP-59 reversed). Returns the wrap and the ephemeral p keypair — a client MAY retain the latter to best-effort NIP-09-scrub the wrap later.
wrap_seal_with_tags
wrap_seal plus caller-supplied extra_tags on the outer wrap. The chat plane uses this to mirror a message’s NIP-40 expiration (Self-Destruct Timer) onto the wrap so relays drop the stored event on schedule; every other plane wraps with none.