7. Frame Types
All frames are JSON objects with a type field (string).
Implementations MUST silently ignore frames with unrecognised type values to allow forward
compatibility.
7.1 Frame Type Registry
The table is rendered from the normative machine-readable frame registry; its own shape is validated by frame-registry.schema.json.
| Type | Layer | Gated | Status | Schema | Fields |
|---|---|---|---|---|---|
| client-hello | 2 | No | core | handshake.schema.json | First authenticated handshake offer. |
| server-hello | 2 | No | core | handshake.schema.json | Server offer, negotiated extensions, transcript proof and key confirmation. |
| client-finish | 2 | No | core | handshake.schema.json | Transcript hash, client proof and key confirmation. |
| cmb | 3/4 | SVAF | core | cmb-frame.schema.json | Signed CAT7 record assertion. |
| cmb-encrypted | 2/3 | After decrypt | core | encrypted-cmb-frame.schema.json | Directional ChaCha20-Poly1305 envelope with session, sequence, routing metadata and sealed record bytes. |
| cmb-fetch | 3 | No | core | cmb-fetch.schema.json | Request a record by exact content address. |
| cmb-fetch-result | 3 | No | core | cmb-fetch-result.schema.json | Self-verifying result for an exact content-address request. |
| role-grant | 3 | Authority | core | authority-frame.schema.json | Signed, anchor-rooted lifecycle role grant. |
| role-revoke | 3 | Authority | core | authority-frame.schema.json | Signed revocation of a lifecycle role grant. |
| peer-info | 2 | No | core | control-frame.schema.json | Authenticated-room peer and wake-channel gossip. |
| wake-channel | 2 | No | core | control-frame.schema.json | Platform wake-channel registration. |
| error | 2 | No | core | control-frame.schema.json | Protocol error code, message and optional bounded detail. |
| ping | 2 | No | core | control-frame.schema.json | Peer keepalive request. |
| pong | 2 | No | core | control-frame.schema.json | Peer keepalive response. |
| relay-auth | 1 | Relay auth | transport | relay-frame.schema.json | Authenticate a node to a relay. |
| relay-peers | 1 | No | transport | relay-frame.schema.json | Relay peer directory. |
| relay-ping | 1 | No | transport | relay-frame.schema.json | Relay keepalive request. |
| relay-pong | 1 | No | transport | relay-frame.schema.json | Relay keepalive response. |
| relay-reauth | 1 | No | transport | relay-frame.schema.json | Request a fresh relay-auth frame. |
| relay-peer-joined | 1 | No | transport | relay-frame.schema.json | Relay presence notification. |
| relay-peer-left | 1 | No | transport | relay-frame.schema.json | Relay departure notification. |
| relay-error | 1 | No | transport | relay-frame.schema.json | Relay-level error. |
| state-sync | deprecated | No | legacy | — | Reserved legacy type. MUST NOT emit; ignore on receipt. |
| message | legacy | No | legacy | — | Legacy unsigned application message. |
| mood | legacy | No | legacy | — | Legacy mood fast path; Core Secure carries mood inside CAT7. |
| xmesh-insight | legacy | No | legacy | — | Legacy runtime projection. |
All cognitive content — observations, decisions, feedback, directives — MUST be sent
as cmb frames. Only cmb frames
enter SVAF evaluation, produce anchor weights, and modulate CfC state.
The registry distinguishes Core Secure wire types from retained legacy and runtime-extension
types. A Core Secure participant MUST complete the three-frame authenticated handshake before it
accepts cmb or cmb-encrypted.
It MUST NOT silently downgrade to the legacy one-frame handshake
or to an unsigned application frame.
The relay-* types are transport-scope (Section 4.4):
they are exchanged between a node and a relay, never between peers, and never reach the application
layer. The relay forwards peer frames as opaque payloads (Section 4.4.4) and does not originate any
of the peer-scope types above.
Deprecated — state-sync. The
state-sync frame carried a node’s hidden-state vectors
(h₁, h₂). Per the hidden-state locality invariant
(Section 2.7),
hidden state MUST NOT cross the wire. Implementations MUST NOT emit state-sync
and SHOULD ignore it on receipt. It is retained in this registry only to reserve the type and document the
deprecation; all peer influence flows through cmb frames evaluated by SVAF.
7.2 Error Frame
When a node encounters a protocol-level error, it SHOULD send an error frame
before closing the connection (if applicable). Error frames are informational — the receiving
node MUST NOT treat them as commands.
| Code | Name | Action | Description |
|---|---|---|---|
| 1001 | VERSION_MISMATCH | Close | Peer version is incompatible |
| 1002 | DIMENSION_MISMATCH | Reject frame | Vector dimension mismatch (legacy state-sync; deprecated — see §2.7) |
| 1003 | FRAME_TOO_LARGE | Close | Frame exceeds MAX_FRAME_SIZE |
| 1004 | HANDSHAKE_TIMEOUT | Close | No handshake within deadline |
| 1005 | DUPLICATE_NODE | Close | nodeId already connected |
| 2001 | SVAF_REJECTED | None | Memory-share rejected by SVAF (informational) |
| 1006 | AUTHENTICATION_FAILED | Close | Transcript signature or key confirmation failed |
| 1007 | ROOM_MISMATCH | Close | Authenticated room does not match the local room |
| 1008 | REPLAY_DETECTED | Close | Encrypted-frame counter repeated or moved backwards |
Codes 1xxx are connection-level (close connection). Codes 2xxx are evaluation-level (informational). Error frames MUST NOT contain sensitive information.
7.3 Type Naming and Extensions
Frame types are identified by their type string value.
Core types (this specification) MUST NOT be redefined by extensions.
Extension types MUST use <extension>-<name> format.
Vendor types MUST use x-<vendor>-<name> format
and MUST be silently ignored by non-supporting nodes.
Q&A
Why MUST nodes silently ignore unknown frame types?
Without this rule, you can never add new features to the protocol. If a node crashes or rejects unknown frame types, then deploying a new extension (like mesh rooms) requires upgrading every node on the mesh simultaneously — impossible in a peer-to-peer system. Silent ignore means old nodes and new nodes coexist: a node running a new extension sends its frames, and nodes that don’t support the extension simply ignore them. No crash, no error, the mesh keeps working. When a node adds support later, it handles the frame. No coordinated upgrade needed. This is the same principle used by HTTP (unknown headers ignored), TCP (unknown options skipped), and HTML (unknown tags ignored). Every successful protocol is evolvable because of this rule.
What happens if a relay receives an unknown frame type?
The relay forwards it. The relay is a dumb transport pipe — it wraps the payload in a { from, fromName, payload } envelope and sends it to the target or broadcasts it. It never inspects the payload type. This means extension frames (room, vendor, future types) flow through the relay without any relay changes. The intelligence is at the endpoints, not the transport.
Can an extension frame break an existing node?
No, if the node follows Section 7. The frame handler switches on msg.type. Unknown types fall through with no match and no action. The node’s cognitive state, memory, and coupling are unaffected. This is a hard requirement — implementations that reject or error on unknown types are non-conformant.