Initialize repository snapshot
This commit is contained in:
137
spec/SENTINEL_V1_CONTRACT_MATRIX.md
Normal file
137
spec/SENTINEL_V1_CONTRACT_MATRIX.md
Normal file
@@ -0,0 +1,137 @@
|
||||
# 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).
|
||||
Reference in New Issue
Block a user