From 98aa2b0ec7e320df2a59cd337f71a58aa6cebc9651f7c4961bf754ed69b2890a Mon Sep 17 00:00:00 2001 From: Tyler King Date: Sat, 28 Feb 2026 09:12:59 -0500 Subject: [PATCH] feat(attestation): add SAT-SPEC-0002 protobuf definitions Add protobuf message definitions for the four-layer attestation architecture defined in SAT-SPEC-0002. Package: substrate.attestation.v2 Files: - common.proto: QmReceipt (hash-chained Ed25519-signed receipts) - platform.proto: PlatformClaim, TpmQuoteBinding (L1 hardware identity) - software.proto: SoftwareClaim, BuildProvenance (L2 image provenance) - governance.proto: GovernanceClaim, AccordReference, DelegationReference (L3) - session.proto: SessionClaim, ActorContext, PostureEvidence, PostureLevel (L4) - sat.proto: SatBundle (composite, optional claim fields for has_*() codegen) Also adds buf.yaml for lint/breaking-change checks. Co-Authored-By: Claude Opus 4.6 --- attestation/v2/README.md | 35 +++++++++++++++++++++++ attestation/v2/common.proto | 20 +++++++++++++ attestation/v2/governance.proto | 44 +++++++++++++++++++++++++++++ attestation/v2/platform.proto | 31 ++++++++++++++++++++ attestation/v2/sat.proto | 26 +++++++++++++++++ attestation/v2/session.proto | 50 +++++++++++++++++++++++++++++++++ attestation/v2/software.proto | 29 +++++++++++++++++++ buf.yaml | 9 ++++++ 8 files changed, 244 insertions(+) create mode 100644 attestation/v2/README.md create mode 100644 attestation/v2/common.proto create mode 100644 attestation/v2/governance.proto create mode 100644 attestation/v2/platform.proto create mode 100644 attestation/v2/sat.proto create mode 100644 attestation/v2/session.proto create mode 100644 attestation/v2/software.proto create mode 100644 buf.yaml diff --git a/attestation/v2/README.md b/attestation/v2/README.md new file mode 100644 index 0000000..a60852b --- /dev/null +++ b/attestation/v2/README.md @@ -0,0 +1,35 @@ +# attestation/v2 — SAT-SPEC-0002 Protobuf Definitions + +Protobuf message definitions for the Substrate Attestation Token v2 (SAT-SPEC-0002), +the four-layer attestation architecture for Substrate nodes. + +## Package + +`substrate.attestation.v2` + +## Files + +| File | Layer | Messages | +|------|-------|----------| +| `sat.proto` | — | `SatBundle` (top-level composite) | +| `platform.proto` | L1 Platform | `PlatformClaim`, `TpmQuoteBinding` | +| `software.proto` | L2 Software | `SoftwareClaim`, `BuildProvenance` | +| `governance.proto` | L3 Governance | `GovernanceClaim`, `AccordReference`, `DelegationReference` | +| `session.proto` | L4 Session | `SessionClaim`, `ActorContext`, `PostureEvidence`, `PostureLevel` (enum) | +| `common.proto` | — | `QmReceipt` | + +## Layer Architecture + +``` +L4 Session ← actor identity + posture evaluation +L3 Governance ← accords, delegations, ceremonies +L2 Software ← image provenance + QM build receipt +L1 Platform ← TPM measurements + hardware identity +``` + +Each layer's claim hash binds to the layers below it (hash chaining). +The composite `sat_hash` in `SatBundle` covers all present layers. + +## Spec + +Canonical specification: `substrate/docs/specs/SAT-SPEC-0002.md` diff --git a/attestation/v2/common.proto b/attestation/v2/common.proto new file mode 100644 index 0000000..3b838aa --- /dev/null +++ b/attestation/v2/common.proto @@ -0,0 +1,20 @@ +syntax = "proto3"; + +package substrate.attestation.v2; + +// ─── QM Receipt ───────────────────────────────────────────────────── +// +// The Quartermaster receipt is the fundamental trust primitive for +// non-hardware claims. Every QM receipt is hash-chained, self-contained, +// and verifiable with the QM's Ed25519 public key. + +message QmReceipt { + string receipt_id = 1; // Unique identifier (UUIDv7) + bytes claim_hash = 2; // SHA-256 hash of the notarized claim + repeated bytes referenced_hashes = 3; // Previous layer claim hashes (binding chain) + string issuer = 4; // QM instance identity (SPIFFE ID) + string timestamp = 5; // ISO 8601, QM clock (authoritative) + uint64 chain_position = 6; // Position in the QM's hash chain (monotonic) + optional string previous_receipt = 7; // Receipt ID of previous chain entry + bytes signature = 8; // Ed25519 signature +} diff --git a/attestation/v2/governance.proto b/attestation/v2/governance.proto new file mode 100644 index 0000000..dda0cd5 --- /dev/null +++ b/attestation/v2/governance.proto @@ -0,0 +1,44 @@ +syntax = "proto3"; + +package substrate.attestation.v2; + +// ─── Layer 3: Governance Claim ────────────────────────────────────── +// +// Governance state binding: active accords, delegations, and ceremony +// state. Hash-chained via governance_epoch for tamper detection. + +message GovernanceClaim { + uint32 layer = 1; // MUST be 3 + bytes governance_state_hash = 2; + repeated AccordReference active_accords = 3; + repeated DelegationReference active_delegations = 4; + uint32 pending_ceremonies = 5; + uint64 governance_epoch = 6; + bytes previous_governance_hash = 7; + bytes platform_claim_hash = 8; + bytes software_claim_hash = 9; + bytes claim_hash = 10; +} + +message AccordReference { + string accord_id = 1; + bytes accord_hash = 2; + string forge_repo = 3; + string forge_commit = 4; + repeated string parties = 5; + string scope = 6; // Summary + string activated_at = 7; // ISO 8601 + optional string expires_at = 8; + string qm_receipt = 9; +} + +message DelegationReference { + string delegation_id = 1; + string delegator = 2; + string delegate = 3; + repeated string scope = 4; + string delegator_accord = 5; + optional string ceremony_id = 6; + string qm_receipt = 7; + string expires_at = 8; // ISO 8601 +} diff --git a/attestation/v2/platform.proto b/attestation/v2/platform.proto new file mode 100644 index 0000000..39a31ae --- /dev/null +++ b/attestation/v2/platform.proto @@ -0,0 +1,31 @@ +syntax = "proto3"; + +package substrate.attestation.v2; + +// ─── Layer 1: Platform Claim ──────────────────────────────────────── +// +// Hardware-rooted identity and integrity measurements. Anchored to TPM +// Endorsement Key (EK) and backed by TPM Quote over PCR digest. + +message PlatformClaim { + uint32 sat_version = 1; // MUST be 2 + uint32 layer = 2; // MUST be 1 + string machine_id = 3; // H(TPM EK public key) + bytes tpm_ek_public = 4; + bytes tpm_ak_cert = 5; + bytes pcr_digest = 6; + string pcr_bank = 7; // "sha256" or "sha384" + repeated uint32 pcr_selection = 8; + optional bytes ima_log_hash = 9; + bool uefi_secureboot = 10; + uint64 boot_timestamp = 11; // TPM monotonic counter + bytes nonce = 12; + bytes claim_hash = 13; // Computed, not serialized for hashing + TpmQuoteBinding tpm_binding = 14; +} + +message TpmQuoteBinding { + bytes quoted = 1; + bytes signature = 2; + string signature_algorithm = 3; // "ECDSA-P256" +} diff --git a/attestation/v2/sat.proto b/attestation/v2/sat.proto new file mode 100644 index 0000000..a3d000d --- /dev/null +++ b/attestation/v2/sat.proto @@ -0,0 +1,26 @@ +syntax = "proto3"; + +package substrate.attestation.v2; + +import "attestation/v2/platform.proto"; +import "attestation/v2/software.proto"; +import "attestation/v2/governance.proto"; +import "attestation/v2/session.proto"; + +// ─── Top-level SAT Bundle ─────────────────────────────────────────── +// +// Composite attestation bundle containing all four layers. +// Layers are optional — a minimal bundle may contain only L1 + L4. +// The explicit `optional` keyword generates has_*() accessors in +// codegen (Rust/prost, Python/protobuf) to distinguish absent layers +// from present-but-empty layers. + +message SatBundle { + uint32 sat_version = 1; // MUST be 2 + optional PlatformClaim platform_claim = 2; + optional SoftwareClaim software_claim = 3; + optional GovernanceClaim governance_claim = 4; + optional SessionClaim session_claim = 5; + bytes sat_hash = 6; // H(L1 || L2 || L3 || L4) + string qm_receipt_id = 7; // Top-level QM receipt +} diff --git a/attestation/v2/session.proto b/attestation/v2/session.proto new file mode 100644 index 0000000..cd47770 --- /dev/null +++ b/attestation/v2/session.proto @@ -0,0 +1,50 @@ +syntax = "proto3"; + +package substrate.attestation.v2; + +// ─── Layer 4: Session Claim ───────────────────────────────────────── +// +// Per-session attestation binding actor identity to platform, software, +// and governance state. Posture is verifier-computed, not self-asserted. + +message SessionClaim { + uint32 layer = 1; // MUST be 4 + string session_id = 2; // UUIDv7 + ActorContext actor = 3; + PostureEvidence posture_evidence = 4; + PostureLevel posture_level = 5; + string timestamp = 6; // ISO 8601 + bytes nonce = 7; + bytes platform_claim_hash = 8; + bytes software_claim_hash = 9; + bytes governance_claim_hash = 10; + bytes claim_hash = 11; +} + +message ActorContext { + string actor_id = 1; // OIDC sub or SPIFFE ID + string actor_type = 2; // "human" | "agent" | "system" | "node" + string auth_method = 3; // "oidc" | "oidc+entra" | "spiffe" | "service_account" + optional string delegated_by = 4; + optional string delegation_id = 5; +} + +message PostureEvidence { + bool platform_attested = 1; + string platform_method = 2; + bool software_verified = 3; + string software_method = 4; + bool governance_bound = 5; + string governance_method = 6; + bool identity_verified = 7; + string identity_method = 8; +} + +enum PostureLevel { + POSTURE_LEVEL_UNSPECIFIED = 0; + POSTURE_LEVEL_NONE = 1; + POSTURE_LEVEL_LOCAL = 2; + POSTURE_LEVEL_VERIFIED = 3; + POSTURE_LEVEL_GOVERNED = 4; + POSTURE_LEVEL_ATTESTED = 5; +} diff --git a/attestation/v2/software.proto b/attestation/v2/software.proto new file mode 100644 index 0000000..ddebd61 --- /dev/null +++ b/attestation/v2/software.proto @@ -0,0 +1,29 @@ +syntax = "proto3"; + +package substrate.attestation.v2; + +// ─── Layer 2: Software Claim ──────────────────────────────────────── +// +// Software provenance and capability declaration. Binds the running +// image to its build pipeline via QM-notarized build receipts. + +message SoftwareClaim { + uint32 layer = 1; // MUST be 2 + string image_id = 2; + bytes image_hash = 3; + bytes capability_manifest = 4; // H(manifest JSON) + repeated string capabilities = 5; // Informational + BuildProvenance build_provenance = 6; + string qm_build_receipt = 7; + bytes platform_claim_hash = 8; // L1 binding + bytes claim_hash = 9; +} + +message BuildProvenance { + string source_repo = 1; + string source_commit = 2; + string builder_identity = 3; // SPIFFE ID or OIDC sub + string build_timestamp = 4; // ISO 8601 + bool build_reproducible = 5; + uint32 builder_count = 6; +} diff --git a/buf.yaml b/buf.yaml new file mode 100644 index 0000000..13e52ac --- /dev/null +++ b/buf.yaml @@ -0,0 +1,9 @@ +version: v2 +modules: + - path: . +lint: + use: + - STANDARD +breaking: + use: + - FILE