# VaultMesh EventEnvelope (v0) – Canonical Spec This document defines the stable, audit-friendly contract for `EventEnvelope` as used by the Command Center: - HTTP API: `POST /api/events`, `GET /api/events` - SSE stream: `GET /events` (event name = `kind`) - Durable log: `$VAULTMESH_LOG_DIR/events.jsonl` (one envelope per line) ## Envelope Shape `EventEnvelope` is a single JSON object with the following fields: Required: - `format`: string, must be `"vm-event-envelope-v0"` - `schema`: object, must be `{ "envelope": 0, "payload": 0 }` - `id`: UUID string (server-assigned) - `ts`: RFC3339 UTC timestamp with **seconds precision** (server-assigned), e.g. `"2025-12-17T23:07:10Z"` - `kind`: string (e.g. `"note"`, `"incident"`, `"ack"`, `"tag"`, `"resolve"`) - `author`: string (e.g. `"operator"`, `"system"`, `"vm-copilot"`) - `payload`: JSON value (kind-specific; usually an object) Optional: - `node_id`: UUID string (omit if global event) Compatibility: - Incoming requests/log lines may use `body` instead of `payload`; Command Center treats `body` as an alias for `payload`. ## Timestamp Rules - Canonical timestamps are **UTC `Z`**, **seconds precision only**. - If a timestamp contains fractional seconds, Command Center truncates to seconds during canonicalization. ## Canonical JSON Ordering To keep bytes stable forever (for hashing, Merkle roots, and diffability), Command Center canonicalizes envelopes before persistence and broadcast: - Top-level field order is fixed by the envelope struct definition. - `payload` is recursively normalized by sorting **object keys** lexicographically. - Arrays preserve order (arrays are never sorted). - Optional fields are omitted when absent (no `field: null` unless semantically meaningful). ## Canonical Bytes + Newline The canonical byte representation of an event is: - UTF-8 bytes of the canonical JSON serialization of the envelope - followed by a single LF newline byte (`0x0A`) `events.jsonl` is the concatenation of these canonical envelope line bytes in file order. ## Hashing (v0) When hashing a canonical event line (leaf hashing), use: - `SHA-256(canonical_event_line_bytes)`