Files
git.stella-ops.org/docs/contracts/execution-evidence-v1.md
2026-02-19 22:07:11 +02:00

173 lines
6.8 KiB
Markdown

# Execution Evidence Predicate Contract
**Predicate Type:** `stella.ops/executionEvidence@v1`
**Status:** Active
**Sprint:** SPRINT_20260219_013
Provides a cryptographically verifiable, deterministic attestation that a specific artifact was observed executing in a real environment. Converts "it executed" from an implicit signal into a signed DSSE predicate suitable for policy gates and audit packs.
## Overview
- **Auditability:** Offline-verifiable proof that an artifact ran in a given environment.
- **Determinism:** Same trace input blob produces byte-identical predicates (address-canonicalized, sorted).
- **Privacy-safe:** Coarse trace summary (syscall families, hot symbols, counts) — no raw syscall logs.
- **Offline-first:** No external service dependencies; uses local signing keys.
## Schema
```json
{
"predicateType": "stella.ops/executionEvidence@v1",
"subject": [{"name": "artifact", "digest": {"sha256": "<canonical_id>"}}],
"predicate": {
"artifact_id": "sha256:<image_or_binary_digest>",
"environment_id": "<env_identifier>",
"trace_source": "ebpf|etw|dyld",
"observation_window": {
"start": "2026-02-19T12:00:00Z",
"end": "2026-02-19T12:00:10Z",
"duration_ms": 10000
},
"trace_summary": {
"syscall_families_observed": ["network", "filesystem", "process"],
"hot_symbols": ["main", "handleRequest", "db.Query"],
"hot_symbol_count": 42,
"unique_call_paths": 17,
"address_canonicalized": true
},
"trace_digest": "sha256:<hash_of_canonical_trace_blob>",
"determinism": {
"replay_seed": "<if applicable>",
"inputs_digest": "sha256:<hash_of_frozen_inputs>",
"expected_output_digest": "sha256:<if deterministic replay enabled>"
},
"timestamp": "2026-02-19T12:00:10Z"
}
}
```
## Field Definitions
### Root Fields
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `predicateType` | string | yes | Always `stella.ops/executionEvidence@v1` |
| `subject` | array | yes | Single-element array with artifact canonical ID |
### Predicate Fields
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `artifact_id` | string | yes | `sha256:<digest>` of the container image or binary |
| `environment_id` | string | yes | Identifier of the environment where execution was observed |
| `trace_source` | string | yes | Instrumentation source: `ebpf`, `etw`, or `dyld` |
| `observation_window` | object | yes | Time window of the trace capture |
| `trace_summary` | object | yes | Coarse summary of observed behavior |
| `trace_digest` | string | yes | `sha256:<hex>` digest of the canonical trace blob |
| `determinism` | object | yes | Replay and determinism metadata |
| `timestamp` | ISO 8601 | yes | When the predicate was generated |
### Observation Window
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `start` | ISO 8601 | yes | Trace capture start time |
| `end` | ISO 8601 | yes | Trace capture end time |
| `duration_ms` | long | yes | Window duration in milliseconds |
### Trace Summary
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `syscall_families_observed` | string[] | yes | Coarse syscall families: `network`, `filesystem`, `process` |
| `hot_symbols` | string[] | yes | Top-K symbols by hit count (capped by `MaxHotSymbols`) |
| `hot_symbol_count` | int | yes | Total number of distinct hot symbols before top-K |
| `unique_call_paths` | int | yes | Number of unique call paths observed |
| `address_canonicalized` | bool | yes | Whether ASLR noise was stripped |
### Determinism Metadata
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `replay_seed` | string | no | Seed for deterministic replay (if applicable) |
| `inputs_digest` | string | yes | `sha256:<hex>` of frozen input set |
| `expected_output_digest` | string | no | Expected output digest (if deterministic replay enabled) |
## Privacy Canonicalization Rules
The following transformations are applied to raw trace data before predicate generation:
| Data | Canonicalization | Rationale |
|------|-----------------|-----------|
| Memory addresses (loader base) | Stripped to zero-based offset | Removes ASLR noise |
| Socket addresses | Port stripped, IP retained as family indicator | Privacy — port numbers leak service topology |
| Process names | Retained (coarse family classification only) | Needed for `process` syscall family |
| Raw syscall sequences | Collapsed to family set (`network`, `filesystem`, `process`) | Privacy-safe, deterministic |
| Symbol names | Retained (hot symbols are public API surface) | Required for trace utility |
| File paths | Not included in predicate | Privacy — paths leak deployment layout |
## Digest Computation
### Trace Digest
1. Sort canonical trace events by `(SymbolId, HitCount)` ascending.
2. Serialize to deterministic JSON (sorted keys, no whitespace).
3. Compute `SHA256` over the UTF-8 bytes.
4. Encode as lowercase hex with `sha256:` prefix.
### Predicate Digest
1. Serialize the complete predicate to deterministic JSON.
2. Compute `SHA256` over the UTF-8 bytes.
3. Encode as lowercase hex (no prefix).
## DSSE Signing
Predicates are wrapped in a DSSE envelope and signed using the environment's configured crypto profile. Supported profiles: EdDSA, ECDSA, RSA, GOST R 34.10, SM2, eIDAS QSealC, PQC (ML-DSA).
```json
{
"payloadType": "application/vnd.in-toto+json",
"payload": "<base64(predicate_json)>",
"signatures": [
{
"keyid": "<key_identifier>",
"sig": "<base64(signature)>"
}
]
}
```
## Rate Limiting
One predicate per `(artifact_id, environment_id)` per configurable window (default: 60 minutes). Duplicate submissions within the window return a rate-limited result without generating a new predicate.
## Configuration
Section: `Signals:ExecutionEvidence`
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `Enabled` | bool | `true` | Whether the pipeline is active |
| `RateLimitWindowMinutes` | int | `60` | Rate limit window per artifact/environment pair |
| `MaxHotSymbols` | int | `50` | Maximum hot symbols in trace summary |
| `MinEventsThreshold` | int | `5` | Minimum events required to produce a predicate |
## API Endpoints
| Method | Path | Description |
|--------|------|-------------|
| `POST` | `/signals/execution-evidence` | Submit runtime trace for evidence generation |
| `GET` | `/signals/execution-evidence/{artifactId}/{environmentId}` | Query latest evidence for an artifact/environment pair |
## Related Documents
- `docs/contracts/witness-v1.md` — Runtime witness predicate (complementary)
- `docs/contracts/beacon-attestation-v1.md` — Beacon attestation predicate (lightweight complement)
- `docs/modules/policy/gates/execution-evidence-gate.md` — Policy gate consuming this predicate
---
*Last updated: 2026-02-19.*