57 lines
2.1 KiB
Markdown
57 lines
2.1 KiB
Markdown
# 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)`
|
||
|