Goal
Attribute every message in a multi-user session to its sender without per-message crypto, so identity is available to all participants at chat volume. cklib is the reference client and the public face — this contract is inherited by every public client project.
Principle — verify once, attribute cheap
The JWT signature is verified exactly once, at connection open; the connection is bound to that identity. Every later message is attributed by a lookup, never a re-verification. Signature crypto is once-per-connection; per-message cost is O(1).
Flow
- Connect — the edge (Envoy) verifies the JWT signature once and binds the identity to the connection (header on the WS upgrade / NATS CONNECT); NATS binds it to the connection.
- Client publishes
{verb, kernel_urn, payload} — no identity field (already shipped, ck-client.js).
- Ingress attaches — the relay reads the connection
s bound identity (O(1)) and passes it as the 4th element of ckp.dispatch(verb, urn, payload, identity)`. Identity is never a client parameter — the client cannot forge what it does not control.
cklib`s part (this repo)
- Never assert identity — send path stays
{verb, kernel_urn, payload} (done).
- Surface
msg.by — every delivered message/event carries the server-attributed sender (URN/handle), read O(1) from a header; exposed as msg.by. How a session shows who-said-what without the client asserting or verifying.
- Handle-intern participant URNs — for the ephemeral lane, resolve sender → an interned integer handle (the existing dictionary table) so attribution is ~4 bytes at volume.
Throughput — two lanes
Sealing (DB + HMAC) is the volume cost, not the JWT. Split by intent:
- Governed lane (decisions, edges, transitions): server-sealed, proof-chained,
created_by stamped.
- Ephemeral lane (chat lines, typing, presence): connection-attributed
by, delivered fast, not sealed per message.
The sealed-vs-ephemeral classification sets the throughput ceiling.
Implications (agreed)
- Trust boundary: NATS must be reachable only through the verifying edge, else a client bypasses verification. Deployment invariant.
- Revocation: verify-once means a revoked token stays live until the connection drops — long-lived connections need a max-lifetime (reconnect = re-verify).
Cross-repo
- Substrate reads the ingress-attached identity — styk-tv/pgCK (companion, filed).
- Edge/bundle attaches identity at connect + locks NATS to the edge — sporaxis-com/oci-germination (companion, filed).
Goal
Attribute every message in a multi-user session to its sender without per-message crypto, so identity is available to all participants at chat volume. cklib is the reference client and the public face — this contract is inherited by every public client project.
Principle — verify once, attribute cheap
The JWT signature is verified exactly once, at connection open; the connection is bound to that identity. Every later message is attributed by a lookup, never a re-verification. Signature crypto is once-per-connection; per-message cost is O(1).
Flow
{verb, kernel_urn, payload}— no identity field (already shipped,ck-client.js).s bound identity (O(1)) and passes it as the 4th element ofckp.dispatch(verb, urn, payload, identity)`. Identity is never a client parameter — the client cannot forge what it does not control.cklib`s part (this repo)
{verb, kernel_urn, payload}(done).msg.by— every delivered message/event carries the server-attributed sender (URN/handle), read O(1) from a header; exposed asmsg.by. How a session shows who-said-what without the client asserting or verifying.Throughput — two lanes
Sealing (DB + HMAC) is the volume cost, not the JWT. Split by intent:
created_bystamped.by, delivered fast, not sealed per message.The sealed-vs-ephemeral classification sets the throughput ceiling.
Implications (agreed)
Cross-repo