# Sentinel v1 Contract Matrix Purpose: Define what must be recorded, by whom, when, and what the verifier must enforce. Legend: - Emitter: system responsible for writing the event - Trigger: when the event must be emitted - Hard rule: verifier MUST fail if violated - Soft rule: verifier MAY warn/fail in strict mode --- ## 0) Bundle & Schema Contracts (Seal Bundle) | Contract ID | Invariant | Evidence Artifact(s) | Verifier Enforcement | Failure Codes | | --- | --- | --- | --- | --- | | `B-1` | Bundle MUST contain `seal.json`, `integrity.json`, `verifier_manifest.json`, plus the paths referenced by `seal.json.files.*`. | `seal.json` | File presence checks in `vaultmesh-orgine-mobile/tools/vm_verify_sentinel_bundle.py:557`. | `E_MISSING_REQUIRED_FILE`, `E_SCHEMA_INVALID` | | `B-2` | Bundle MUST be offline-verifiable (no network assumptions). | Entire bundle | Verifier MUST rely only on bundle bytes; no network calls are permitted by design. | `E_MISSING_REQUIRED_FILE`, `E_SCHEMA_INVALID` (derived from missing/incomplete artifacts) | ### `seal.json` (vm-sentinel-seal-v1) | Contract ID | Invariant | Evidence Artifact(s) | Verifier Enforcement | Failure Codes | | --- | --- | --- | --- | --- | | `S-1` | `seal.json.format` MUST equal `vm-sentinel-seal-v1`. | `seal.json` | Format allowlist check in `vaultmesh-orgine-mobile/tools/vm_verify_sentinel_bundle.py:594`. | `E_SCHEMA_INVALID` | | `S-2` | `seal.json.hash_algo` MUST be `blake3` or `sha256`. | `seal.json` | `hash_algo` validation in `vaultmesh-orgine-mobile/tools/vm_verify_sentinel_bundle.py:604`. | `E_SCHEMA_INVALID` | | `S-3` | Seal MUST declare a sequence range (`since_seq`, `until_seq`). | `seal.json.range` | Schema validation in `vaultmesh-orgine-mobile/tools/vm_verify_sentinel_bundle.py:582`. | `E_SCHEMA_INVALID` | | `S-4` | Seal MUST declare `root.start` and `root.end`. | `seal.json.root` | Schema validation in `vaultmesh-orgine-mobile/tools/vm_verify_sentinel_bundle.py:582`. | `E_SCHEMA_INVALID` | | `S-5` | Seal MUST point to receipts/roots/integrity/verifier_manifest files (and they must exist in the bundle). | `seal.json.files.*` | Path resolution + existence checks in `vaultmesh-orgine-mobile/tools/vm_verify_sentinel_bundle.py:640`. | `E_MISSING_REQUIRED_FILE`, `E_SCHEMA_INVALID` | ### `integrity.json` (vm-sentinel-integrity-v1) | Contract ID | Invariant | Evidence Artifact(s) | Verifier Enforcement | Failure Codes | | --- | --- | --- | --- | --- | | `I-1` | `integrity.json.format` MUST equal `vm-sentinel-integrity-v1`. | `integrity.json` | Format allowlist check in `vaultmesh-orgine-mobile/tools/vm_verify_sentinel_bundle.py:689`. | `E_SCHEMA_INVALID` | | `I-2` | `integrity.json.hash_algo` MUST match `seal.json.hash_algo`. | `integrity.json`, `seal.json` | Cross-check in `vaultmesh-orgine-mobile/tools/vm_verify_sentinel_bundle.py:697`. | `E_SCHEMA_INVALID` | | `I-3` | Each listed file MUST have `path` + `digest`, and the digest MUST match. | `integrity.json.files[]` | Digest recomputation + compare in `vaultmesh-orgine-mobile/tools/vm_verify_sentinel_bundle.py:766`. | `E_MANIFEST_HASH_MISMATCH`, `E_SCHEMA_INVALID`, `E_MISSING_REQUIRED_FILE` | | `I-4` | If `size_bytes` is present, it MUST match file size. | `integrity.json.files[].size_bytes` | Size check in `vaultmesh-orgine-mobile/tools/vm_verify_sentinel_bundle.py:822`. | `E_SCHEMA_INVALID` | ### `verifier_manifest.json` (vm-sentinel-verifier-manifest-v1) | Contract ID | Invariant | Evidence Artifact(s) | Verifier Enforcement | Failure Codes | | --- | --- | --- | --- | --- | | `V-1` | `verifier_manifest.json.format` MUST equal `vm-sentinel-verifier-manifest-v1`. | `verifier_manifest.json` | Format allowlist check in `vaultmesh-orgine-mobile/tools/vm_verify_sentinel_bundle.py:874`. | `E_SCHEMA_INVALID` | | `V-2` | MUST declare `sentinel_version`, `schema_version`, `canonicalization_version`. | `verifier_manifest.json` | Schema validation in `vaultmesh-orgine-mobile/tools/vm_verify_sentinel_bundle.py:866`. | `E_SCHEMA_INVALID` | | `V-3` | If `hash_algo` is present, it MUST match `seal.json.hash_algo`. | `verifier_manifest.json`, `seal.json` | Cross-check in `vaultmesh-orgine-mobile/tools/vm_verify_sentinel_bundle.py:898`. | `E_SCHEMA_INVALID` | | `V-4` | `verifier` object MAY include `name/version/sha256`; if present, include it in reports. | `verifier_manifest.json` | Report inclusion in `vaultmesh-orgine-mobile/tools/vm_verify_sentinel_bundle.py:912`. | N/A | ## A) Action Lifecycle Events (Intent → Decision → Outcome) | Event Type | Emitter | Trigger | Required Fields (minimum) | Hard Verification Rules | | --- | --- | --- | --- | --- | | `action_intent` | Actor system (Cloudflare ops / guardian / CLI / RTOS host) | Before any attempt to execute an operation | `seq`, `ts`, `event_type`, `actor`, `op`, `op_digest`, `trace_id`, `cap_hash`, `prev_event_hash`, `event_hash` | No execution without prior intent: Every `action_executed` must reference a prior `action_intent` with same `trace_id`. | | `policy_decision` (recommended v1; can be embedded in intent `payload` to keep schema lean) | Policy engine (Layer0/classifier) | After intent, before allow/deny | `seq`, `ts`, `actor`, `trace_id`, `op_digest`, `result` (`allow`/`deny`), `payload.reason_code`, `payload.classification`, `prev_event_hash` | Policy recording: if system claims policy enforcement, then every allow/deny must have a recorded decision (either as this event or as a signed payload embedded in intent). | | `action_executed` | Actor system | Immediately after side-effect completes | `seq`, `ts`, `actor`, `trace_id`, `op_digest`, `result` (`ok`/`error`), `root_before`, `root_after`, `prev_event_hash`, `event_hash` | Must have matching prior `action_intent`. Must not exist if corresponding denial exists for same `trace_id` (no split reality). | | `shadow_receipt` | Sentinel core (or Actor if core is embedded) | On any denial (capability fail, policy deny, budget deny, degraded mode) | `seq`, `ts`, `actor`, `trace_id`, `op_digest`, `result` (`deny`), `payload.reason_code`, `payload.side_effects="none"`, `prev_event_hash`, `event_hash` | No silent denial: if an intent does not lead to `action_executed`, there must be a `shadow_receipt` unless explicitly marked “write-impossible” (rare). Shadow receipts must assert `side_effects="none"`. | Notes: - If you want to avoid a separate `policy_decision` event, put the decision in `action_intent.payload.policy` and require it to be present when `result != "unknown"`. --- ## B) Trust / Authority Events (Capabilities) | Event Type | Emitter | Trigger | Required Fields | Hard Verification Rules | | --- | --- | --- | --- | --- | | `cap_grant` | Authority issuer (operator tool / provisioning process) | When a capability is created/issued | `seq`, `ts`, `actor` (issuer), `payload.capability_json`, `cap_hash`, `prev_event_hash` | Capability used later must hash to a previously granted token OR be in a pinned trust root (bootstrap). | | `cap_revoke` | Authority issuer | When revoking capability | `seq`, `ts`, `actor`, `payload.revoked_cap_hash`, `payload.reason_code`, `prev_event_hash` | Revocation is authoritative: any subsequent event with `cap_hash` matching a revoked one MUST be denied (`shadow_receipt` with reason revoked). | | `cap_use` (optional; can be derived) | Sentinel core | Whenever a capability is presented | `seq`, `ts`, `actor`, `cap_hash`, `trace_id`, `prev_event_hash` | If enabled, must correlate to `action_intent/trace_id`. Not required if you already store `cap_hash` on intent/outcome. | --- ## C) Root & Sealing Events (Time Compression / Witness Bundles) | Event Type | Emitter | Trigger | Required Fields | Hard Verification Rules | | --- | --- | --- | --- | --- | | `root_published` | Sentinel core | After appending N events or T time window | `seq`, `ts`, `payload.root_hex`, `payload.coverage_seq`, `prev_event_hash` | Root must match recomputation over all events up to `coverage_seq`. Root determinism required. | | `seal_created` | Sentinel core | On schedule OR on tamper/corruption OR on manual request | `seq`, `ts`, `payload.seal_id`, `payload.range_since`, `payload.range_until`, `payload.end_root`, `payload.canonicalization_version`, `prev_event_hash` | Seal must be verifiable offline: receipts + roots + integrity manifest present. Seal completeness is a hard requirement. | --- ## D) Integrity / Tamper / Degradation Events (Hostile Reality) | Event Type | Emitter | Trigger | Required Fields | Hard Verification Rules | | --- | --- | --- | --- | --- | | `tamper_signal` | Hardware/host sensor adapter → recorded by Sentinel | Unexpected power cycle, clock jump, enclosure open, seizure sensor | `seq`, `ts`, `payload.kind`, `payload.sensor_digest`, `payload.severity`, `prev_event_hash` | Presence of tamper signals must tighten policy: subsequent high-risk ops should be denied or require stronger caps (enforced in policy rules; verifier can check if policy recorded). | | `corruption_detected` | Storage layer / Sentinel core | On detection of checksum/page/parse failure | `seq`, `ts`, `payload.affected_ranges`, `payload.last_good_seq`, `payload.last_good_root`, `prev_event_hash` | No silent data loss: corruption must be recorded. Recommended: must trigger immediate `seal_created` if possible (strict mode can enforce). | | `boot_event` | Sentinel core | On startup | `seq`, `ts`, `payload.version`, `payload.schema_version`, `payload.hash_algo`, `prev_event_hash` | Boot events should be monotonic across sessions; verifier can warn if missing across long ranges. | --- ## E) Minimal Verifier Rules (Derived from Matrix) Hard fails (always): 1. Schema invalid for any required file/event → `E_SCHEMA_INVALID` 2. `seq` non-monotonic / duplicate / missing in covered range → `E_SEQ_NON_MONOTONIC` 3. `prev_event_hash` chain discontinuity → `E_CHAIN_DISCONTINUITY` 4. Root mismatch for declared coverage → `E_ROOT_MISMATCH` 5. Seal missing required artifacts (receipts + roots + integrity + verifier manifest) → `E_MISSING_REQUIRED_FILE`, `E_SCHEMA_INVALID` 6. Revoked capability used without denial → `E_REVOKED_CAPABILITY_USED` Strict-mode fails (recommended): 7. Missing `shadow_receipt` where intent didn’t execute 8. Corruption without subsequent seal (when seal could be created) 9. Policy enforcement claim without recorded policy decision --- ## F) Boundary Rules (encoded) - Actor Replaceability: actor systems can change; evidence format cannot. - Policy Recording: decisions go into receipts. - Tamper Evidence: tamper events must exist for power/clock anomalies. - Export Redundancy: portable artifacts exist independent of runtime. - Verifier Independence: no network/secrets required. - Version Compatibility: verifier supports N-2. --- ## G) Failure Code Map (v1) Source of truth: `vaultmesh-orgine-mobile/tools/sentinel_failure_codes.py` - `E_SCHEMA_INVALID`: Any required schema/format/cross-field validation fails. - `E_MISSING_REQUIRED_FILE`: A required file is missing from the bundle (or referenced but absent). - `E_MANIFEST_HASH_MISMATCH`: A file’s computed digest does not match `integrity.json`. - `E_OVERSIZE_INPUT`: Input exceeds configured maximum bytes. - `E_EVENT_HASH_MISMATCH`: `event_hash` does not match recomputation from canonical bytes. - `E_CHAIN_DISCONTINUITY`: `prev_event_hash` chain breaks (tamper/reorder/rollback evidence). - `E_SEQ_NON_MONOTONIC`: Duplicate, missing, or non-monotonic `seq` values. - `E_RANGE_MISMATCH`: Seal declares a range that does not match included events. - `E_CANON_VERSION_UNSUPPORTED`: Declared `canonicalization_version` is unknown/unsupported. - `E_ROOT_MISMATCH`: Recomputed Merkle end root does not match declared/observed root. - `E_REVOKED_CAPABILITY_USED`: A revoked capability is used after revoke without denial semantics. Warnings (non-fatal unless strict-mode elevates): - `W_FILE_NOT_IN_MANIFEST`: A file exists in the bundle but is not listed in `integrity.json` (or recommended `seal.json` coverage is missing). - `W_RANGE_ROOT_PARTIAL`: Verifier cannot fully verify roots/chain due to missing prior context (eg. `since_seq > 0` without continuation state).