new two advisories and sprints work on them

This commit is contained in:
master
2026-01-16 18:39:36 +02:00
parent 9daf619954
commit c3a6269d55
72 changed files with 15540 additions and 18 deletions

View File

@@ -52,7 +52,7 @@ WebSocket /api/v1/doctor/stream
## Available Checks
The Doctor system includes 48+ diagnostic checks across 7 plugins:
The Doctor system includes 60+ diagnostic checks across 9 plugins:
| Plugin | Category | Checks | Description |
|--------|----------|--------|-------------|
@@ -60,10 +60,32 @@ The Doctor system includes 48+ diagnostic checks across 7 plugins:
| `stellaops.doctor.database` | Database | 8 | Connectivity, migrations, schema, connection pool |
| `stellaops.doctor.servicegraph` | ServiceGraph | 6 | Gateway, routing, service health |
| `stellaops.doctor.security` | Security | 9 | OIDC, LDAP, TLS, Vault |
| `stellaops.doctor.attestation` | Security | 4 | Rekor connectivity, Cosign keys, clock skew, offline bundle |
| `stellaops.doctor.verification` | Security | 5 | Artifact pull, signatures, SBOM, VEX, policy engine |
| `stellaops.doctor.scm.*` | Integration.SCM | 8 | GitHub, GitLab connectivity/auth/permissions |
| `stellaops.doctor.registry.*` | Integration.Registry | 6 | Harbor, ECR connectivity/auth/pull |
| `stellaops.doctor.observability` | Observability | 4 | OTLP, logs, metrics |
### Setup Wizard Essential Checks
The following checks are mandatory for the setup wizard to validate a new installation:
1. **DB connectivity + schema version** (`stellaops.doctor.database`)
- `check.db.connection` - Database is reachable
- `check.db.schema.version` - Schema version matches expected
2. **Attestation store availability** (`stellaops.doctor.attestation`)
- `check.attestation.rekor.connectivity` - Rekor transparency log reachable
- `check.attestation.cosign.keymaterial` - Signing keys available (file/KMS/keyless)
- `check.attestation.clock.skew` - System clock synchronized (<5s skew)
3. **Artifact verification pipeline** (`stellaops.doctor.verification`)
- `check.verification.artifact.pull` - Test artifact accessible by digest
- `check.verification.signature` - DSSE signatures verifiable
- `check.verification.sbom.validation` - SBOM (CycloneDX/SPDX) valid
- `check.verification.vex.validation` - VEX document valid
- `check.verification.policy.engine` - Policy evaluation passes
### Check ID Convention
```
@@ -75,6 +97,8 @@ Examples:
- `check.database.migrations.pending`
- `check.services.gateway.routing`
- `check.integration.scm.github.auth`
- `check.attestation.rekor.connectivity`
- `check.verification.sbom.validation`
## CLI Reference

View File

@@ -866,6 +866,119 @@ curl https://rekor.sigstore.dev/api/v1/log/publicKey > fixtures/rekor-pubkey.pem
---
## 9A. PERIODIC VERIFICATION (Background Job)
**Sprint Reference**: `SPRINT_20260117_001_ATTESTOR_periodic_rekor_verification`
### 9A.1 Overview
The Periodic Verification system provides continuous validation of previously logged Rekor entries. This addresses the gap where entries are logged but never re-verified, enabling detection of:
- Signature tampering or key compromise
- Merkle tree rollbacks (split-view attacks)
- Time skew violations indicating replay attempts
- Root consistency drift between stored and remote state
### 9A.2 Architecture
```
┌─────────────────────────────────────────────────────────────────────┐
│ Periodic Verification Job │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ RekorVerification │───►│ IRekorVerification │ │
│ │ Job (Scheduler) │ │ Service │ │
│ └─────────┬───────────┘ └──────────┬──────────┘ │
│ │ │ │
│ │ batch query │ verify │
│ ▼ ▼ │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ IRekorEntry │ │ RekorVerification │ │
│ │ Repository │ │ Metrics │ │
│ └─────────────────────┘ └──────────┬──────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ IRekorVerification │ │
│ │ StatusProvider │ │
│ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
```
### 9A.3 Configuration
```yaml
attestor:
rekor:
verification:
enabled: true
intervalMinutes: 60 # Run every hour
batchSize: 100 # Entries per batch
sampleRate: 0.1 # 10% sampling for large deployments
maxTimeSkewSeconds: 300 # 5 minute tolerance
alertOnRootInconsistency: true
```
### 9A.4 Verification Checks
| Check | Description | Failure Severity |
|-------|-------------|------------------|
| Signature | Verify entry signature against stored public key | Critical |
| Inclusion Proof | RFC 6962 Merkle inclusion proof verification | Critical |
| Time Skew | Validate integrated_time within tolerance | Warning |
| Root Consistency | Compare stored tree root with remote | Critical |
### 9A.5 Metrics (OpenTelemetry)
```
# Meter: StellaOps.Attestor.RekorVerification
attestor.rekor.verification.runs # Counter
attestor.rekor.verification.entries.verified # Counter
attestor.rekor.verification.entries.failed # Counter
attestor.rekor.verification.entries.skipped # Counter
attestor.rekor.verification.time_skew_violations # Counter
attestor.rekor.verification.signature_failures # Counter
attestor.rekor.verification.inclusion_proof_failures # Counter
attestor.rekor.verification.root_consistency_checks # Counter
attestor.rekor.verification.entry_duration # Histogram
attestor.rekor.verification.batch_duration # Histogram
```
### 9A.6 Health Check Integration
The `RekorVerificationHealthCheck` integrates with the Doctor diagnostic system:
```
Check ID: check.attestation.rekor.verification.job
Status Levels:
- Healthy: Last run within expected window, failure rate < 1%
- Degraded: Failure rate 1-5%, or last run overdue
- Unhealthy: Failure rate > 5%, root inconsistency detected, or job not running
```
### 9A.7 Alerting
| Condition | Alert Level | Action |
|-----------|-------------|--------|
| Root inconsistency | P1 Critical | Immediate investigation required |
| Signature failure rate > 5% | P2 High | Review key material |
| Job not running > 3x interval | P3 Medium | Check scheduler |
| Time skew violations > 10% | P3 Medium | Check NTP sync |
### 9A.8 Offline Verification
When network access to Rekor is unavailable, the system falls back to stored inclusion proofs:
1. Read stored `inclusion_proof` from database
2. Verify Merkle path locally against stored root
3. Log verification as "offline" mode
4. Schedule online re-verification when connectivity returns
---
## 10. MIGRATION GUIDE
### 10.1 Database Migrations

View File

@@ -589,7 +589,120 @@ Pre-computed test cases with known results:
---
## 15. References
## 15. Delta-Sig Predicate Attestation
**Sprint Reference**: `SPRINT_20260117_003_BINDEX_delta_sig_predicate`
Delta-sig predicates provide a supply chain attestation format for binary patches, enabling policy-gated releases based on function-level change scope.
### 15.1 Predicate Structure
```jsonc
{
"_type": "https://in-toto.io/Statement/v1",
"predicateType": "https://stellaops.io/delta-sig/v1",
"subject": [
{
"name": "libexample-1.1.so",
"digest": {
"sha256": "abc123..."
}
}
],
"predicate": {
"before": {
"name": "libexample-1.0.so",
"digest": { "sha256": "def456..." }
},
"after": {
"name": "libexample-1.1.so",
"digest": { "sha256": "abc123..." }
},
"diff": [
{
"function": "process_input",
"changeType": "modified",
"beforeHash": "sha256:old...",
"afterHash": "sha256:new...",
"bytesDelta": 48,
"semanticSimilarity": 0.87
},
{
"function": "new_handler",
"changeType": "added",
"afterHash": "sha256:new...",
"bytesDelta": 256
}
],
"summary": {
"functionsAdded": 1,
"functionsRemoved": 0,
"functionsModified": 1,
"totalBytesChanged": 304
},
"timestamp": "2026-01-16T12:00:00Z"
}
}
```
### 15.2 Policy Gate Integration
The `DeltaScopePolicyGate` enforces limits on patch scope:
```yaml
policy:
deltaSig:
maxAddedFunctions: 10
maxRemovedFunctions: 5
maxModifiedFunctions: 20
maxBytesChanged: 50000
minSemanticSimilarity: 0.5
requireSemanticAnalysis: false
```
### 15.3 Attestor Integration
Delta-sig predicates integrate with the Attestor module:
1. **Generate** - Create predicate from before/after binary analysis
2. **Sign** - Create DSSE envelope with cosign/fulcio signature
3. **Submit** - Log to Rekor transparency log
4. **Verify** - Validate signature and inclusion proof
### 15.4 CLI Commands
```bash
# Generate delta-sig predicate
stella binary diff --before old.so --after new.so --output delta.json
# Generate and attest in one step
stella binary attest --before old.so --after new.so --sign --rekor
# Verify attestation
stella binary verify --predicate delta.json --signature sig.dsse
# Check against policy gate
stella binary gate --predicate delta.json --policy policy.yaml
```
### 15.5 Semantic Similarity Scoring
When `requireSemanticAnalysis` is enabled, the gate also checks:
| Threshold | Meaning |
|-----------|---------|
| > 0.9 | Near-identical (cosmetic changes) |
| 0.7 - 0.9 | Similar (refactoring, optimization) |
| 0.5 - 0.7 | Moderate changes (significant logic) |
| < 0.5 | Major rewrite (requires review) |
### 15.6 Evidence Storage
Delta-sig predicates are stored in the Evidence Locker and can be included in portable bundles for air-gapped verification.
---
## 16. References
### Internal
@@ -604,8 +717,10 @@ Pre-computed test cases with known results:
- [ghidriff Tool](https://github.com/clearbluejar/ghidriff)
- [SemDiff Paper (arXiv)](https://arxiv.org/abs/2308.01463)
- [SEI Semantic Equivalence Research](https://www.sei.cmu.edu/annual-reviews/2022-research-review/semantic-equivalence-checking-of-decompiled-binaries/)
- [in-toto Attestation Framework](https://in-toto.io/)
- [SLSA Provenance Spec](https://slsa.dev/provenance/v1)
---
*Document Version: 1.0.1*
*Last Updated: 2026-01-14*
*Document Version: 1.1.0*
*Last Updated: 2026-01-16*

View File

@@ -132,3 +132,101 @@ All observation documents are immutable. New information creates a new observati
- `EXCITITOR-GRAPH-24-*` relies on this schema to build overlays.
- `DOCS-LNM-22-002` (Link-Not-Merge documentation) references this file.
- `EXCITITOR-ATTEST-73-*` uses `document.digest` + `signature` to embed provenance in attestation payloads.
---
## Rekor Transparency Log Linkage
**Sprint Reference**: `SPRINT_20260117_002_EXCITITOR_vex_rekor_linkage`
VEX observations can be attested to the Sigstore Rekor transparency log, providing an immutable, publicly verifiable record of when each observation was recorded. This supports:
- **Auditability**: Independent verification that an observation existed at a specific time
- **Non-repudiation**: Cryptographic proof of observation provenance
- **Supply chain compliance**: Evidence for regulatory and security requirements
- **Offline verification**: Stored inclusion proofs enable air-gapped verification
### Rekor Linkage Fields
The following fields are added to `vex_observations` when an observation is attested:
| Field | Type | Description |
|-------|------|-------------|
| `rekor_uuid` | TEXT | Rekor entry UUID (64-char hex) |
| `rekor_log_index` | BIGINT | Monotonically increasing log position |
| `rekor_integrated_time` | TIMESTAMPTZ | When entry was integrated into log |
| `rekor_log_url` | TEXT | Rekor server URL where submitted |
| `rekor_inclusion_proof` | JSONB | RFC 6962 inclusion proof for offline verification |
| `rekor_linked_at` | TIMESTAMPTZ | When linkage was recorded locally |
### Schema Extension
```sql
-- V20260117__vex_rekor_linkage.sql
ALTER TABLE excititor.vex_observations
ADD COLUMN IF NOT EXISTS rekor_uuid TEXT,
ADD COLUMN IF NOT EXISTS rekor_log_index BIGINT,
ADD COLUMN IF NOT EXISTS rekor_integrated_time TIMESTAMPTZ,
ADD COLUMN IF NOT EXISTS rekor_log_url TEXT,
ADD COLUMN IF NOT EXISTS rekor_inclusion_proof JSONB,
ADD COLUMN IF NOT EXISTS rekor_linked_at TIMESTAMPTZ;
-- Indexes for Rekor queries
CREATE INDEX idx_vex_observations_rekor_uuid
ON excititor.vex_observations(rekor_uuid)
WHERE rekor_uuid IS NOT NULL;
CREATE INDEX idx_vex_observations_pending_rekor
ON excititor.vex_observations(created_at)
WHERE rekor_uuid IS NULL;
```
### API Endpoints
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/attestations/rekor/observations/{id}` | POST | Attest observation to Rekor |
| `/attestations/rekor/observations/batch` | POST | Batch attestation |
| `/attestations/rekor/observations/{id}/verify` | GET | Verify Rekor linkage |
| `/attestations/rekor/pending` | GET | List observations pending attestation |
### CLI Commands
```bash
# Show observation with Rekor details
stella vex observation show <id> --show-rekor
# Attest an observation to Rekor
stella vex observation attest <id> [--rekor-url URL]
# Verify Rekor linkage
stella vex observation verify-rekor <id> [--offline]
# List pending attestations
stella vex observation list-pending
```
### Inclusion Proof Structure
```jsonc
{
"treeSize": 1234567,
"rootHash": "base64-encoded-root-hash",
"logIndex": 12345,
"hashes": [
"base64-hash-1",
"base64-hash-2",
"base64-hash-3"
]
}
```
### Verification Modes
| Mode | Network | Use Case |
|------|---------|----------|
| Online | Required | Full verification against live Rekor |
| Offline | Not required | Verify using stored inclusion proof |
Offline mode uses the stored `rekor_inclusion_proof` to verify the Merkle path locally. This is essential for air-gapped environments.

View File

@@ -1,309 +0,0 @@
Heres a short, implementationready plan to turn your SBOMs into enforceable, cryptographic gates in Stella Ops—sequence, gate checks, and a compact threat model you can wire into a sprint.
---
# Minimal sequence (do now)
1. **CI build → Scanner/Sbomer**
Compute `sha256` of each artifact and emit CycloneDX 1.6 SBOM with `components[].hashes[]`. ([CycloneDX][1])
2. **Authority (DSSE sign)**
Canonicalize SBOM JSON; wrap as DSSE `payloadType` for attestations and sign (HSM/KMS key). ([in-toto][2])
3. **Router (Rekor v2)**
Upload DSSE / intoto Statement to Rekor v2; persist returned `uuid`, `logIndex`, `integratedTime`. ([Sigstore Blog][3])
4. **Vexer/Excititor (VEX)**
Emit OpenVEX/CSAF (or intoto predicate) referencing CycloneDX `serialNumber`/`bom-ref` and the Rekor `uuid`. ([in-toto][2])
5. **CI gate (OPA/Rego)**
Verify (a) DSSE signature chain, (b) `payloadType` matches expected, (c) Rekor inclusion (via `logIndex`/UUID), (d) allowed `predicateType`, (e) component hash equals subject digest. ([Witness][4])
---
# Pastein Rego (gate)
```rego
package stella.gate
deny[msg] {
input.attestation.payloadType != "application/vnd.cyclonedx+json"
msg = "unexpected payloadType"
}
deny[msg] {
not input.rekor.logIndex
msg = "missing rekor logIndex"
}
/* extend:
- verify DSSE signature against Authority key
- verify Rekor inclusion proof/integratedTime
- ensure predicateType {
"https://cyclonedx.org/schema/bom-1.6",
"https://openvex.org/v1"
}
- ensure subject digest == components[].hashes[].content
*/
```
---
# Compact threat model (top 3 + mitigations)
* **Tampering at rest** → Anchor in Rekor v2; verify inclusion + `integratedTime`; require DSSE signature with Authority HSM key. ([Sigstore Blog][3])
* **Timeshift / backdating** → Reject if `integratedTime` < pipeline build time skew; optional RFC3161 timestamping on uploads. (Policy check in Scheduler.) ([Sigstore Blog][3])
* **Provenance spoofing** Enforce valid `predicateType` (intoto/OpenVEX), and map `signatures[].keyid` to trusted Authority keys (Fulcio/HSM). ([in-toto][2])
---
# Where this lands in Stella
* **Scanner**: compute subject digests; emit artifact metadata.
* **Sbomer**: produce CycloneDX 1.6 with hashes, CBOM/attestations support ready. ([CycloneDX][1])
* **Authority**: create DSSE envelope + sign; maintain key roster & rotation. ([Gradle Documentation][5])
* **Router**: call Rekor v2; persist `uuid`/`logIndex`/`integratedTime` and expose `verifyRekor(uuid)`. ([Sigstore Blog][3])
* **Vexer/Excititor**: emit OpenVEX / intoto predicates linking `bom-ref` and Rekor `uuid`. ([in-toto][2])
---
# Final sprint checklist
* Enable DSSE wrapping + Authority signing in one CI pipeline; push to Rekor v2; store `logIndex`. ([Sigstore Blog][3])
* Add OPA policy to verify `payloadType`, Rekor presence, and digest match; fail CI on violation. ([Witness][4])
* Add Scheduler job to periodically reverify Rekor roots and enforce timeskew rules. ([Sigstore Blog][3])
**Why now:** CycloneDX 1.6 added attestations/CBOM, making SBOMs firstclass, signed evidence; Rekor v2 lowers cost and simplifies opsideal for anchoring these facts and gating releases. ([CycloneDX][1])
If you want, I can drop this into `docs/policies/OPA/stella.gate.rego` and a sample CI job for your GitLab pipeline next.
[1]: https://cyclonedx.org/news/cyclonedx-v1.6-released/?utm_source=chatgpt.com "CycloneDX v1.6 Released, Advances Software Supply ..."
[2]: https://in-toto.io/docs/specs/?utm_source=chatgpt.com "Specifications"
[3]: https://blog.sigstore.dev/rekor-v2-ga/?utm_source=chatgpt.com "Rekor v2 GA - Cheaper to run, simpler to maintain"
[4]: https://witness.dev/docs/docs/concepts/policy/?utm_source=chatgpt.com "Policies"
[5]: https://docs.gradle.com/develocity/dpg/current/?utm_source=chatgpt.com "Develocity Provenance Governor"
---
Heres a compact, engineerfirst guide to emitting a CycloneDX SBOM, wrapping it in a DSSE/intoto attestation, and anchoring it in Rekor v2so you can copy/paste shapes straight into your Sbomer Authority Router flow.
---
# Why this matters (quick background)
* **CycloneDX**: the SBOM format youll emit.
* **DSSE**: minimal, unambiguous envelope for signing arbitrary payloads (your SBOM).
* **intoto Statement**: standard wrapper with `subject` + `predicate` so policy engines can reason about artifacts.
* **Rekor (v2)**: transparency log anchor (UUID, index, integrated time) to verify later at gates.
---
# Minimal CycloneDX 1.6 SBOM (emit from `Sbomer`)
```json
{
"$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json",
"bomFormat": "CycloneDX",
"specVersion": "1.6",
"serialNumber": "urn:uuid:11111111-2222-3333-4444-555555555555",
"metadata": {
"component": {
"bom-ref": "stella-app",
"type": "application",
"name": "stella-app",
"version": "1.2.3"
}
},
"components": [
{
"bom-ref": "lib-a",
"type": "library",
"name": "lib-a",
"version": "0.1.0",
"hashes": [
{ "alg": "SHA-256", "content": "<hex-hash>" }
]
}
]
}
```
**Mustemit fields (Sbomer):** `specVersion`, `serialNumber`, `components[].bom-ref`, `components[].hashes[].(alg,content)`.
---
# Wrap SBOM with DSSE (signed by `Authority`)
```json
{
"payloadType": "application/vnd.cyclonedx+json",
"payload": "<base64(cyclonedx-bom.json)>",
"signatures": [
{ "keyid": "cosign:sha256:abcd...", "sig": "<base64-signature>" }
]
}
```
**Mustemit (Authority):** `payloadType`, `payload` (base64), `signatures[].keyid`, `signatures[].sig`.
---
# Optional: intoto Statement (produced by `Excititor/Vexer`)
```json
{
"_type": "https://in-toto.io/Statement/v0.1",
"subject": [
{ "name": "stella-app", "digest": { "sha256": "<artifact-sha256>" } }
],
"predicateType": "https://cyclonedx.org/schema/bom-1.6",
"predicate": {
"bomRef": "stella-app",
"uri": "oci://registry.example.com/stella-app@sha256:<digest>#sbom"
}
}
```
**Mustemit (Excititor/Vexer):** `predicateType` and a `predicate` your policy engine can dereference (embed SBOM or provide a pointer).
---
# Rekor v2 anchor (persist in `Router`, verify at gates)
```json
{
"uuid": "c3f2e4a8-...",
"logIndex": 123456,
"integratedTime": "2026-01-15T12:34:56Z"
}
```
**Muststore (Router):** `uuid`, `logIndex`, `integratedTime`.
---
# Endtoend checks (put these in your CI gate)
* **SBOM shape**: JSON Schema validate CycloneDX; ensure `serialNumber` + percomponent hashes exist.
* **DSSE**: verify signature over `payload` and `payloadType`; match `keyid` to trusted keys/profile.
* **intoto**: confirm `subject.digest` equals the release OCI digest; `predicateType` matches CycloneDX 1.6/1.7.
* **Rekor v2**: look up `uuid` confirm `logIndex` & `integratedTime` and verify inclusion proof.
---
# Stella Ops module contract (TL;DR)
* **Sbomer** emits CycloneDX 1.6/1.7 with `bom-ref` + hashes.
* **Authority** DSSE sign (`payloadType=application/vnd.cyclonedx+json`).
* **Excititor/Vexer** optional intoto Statement with CycloneDX predicate or pointer.
* **Router** store Rekor v2 tuple; expose verify endpoint for gates.
If you want, I can turn this into readytorun .NET 10 DTOs + validation (FluentValidation) and a tiny verifier CLI that checks all four layers in one go.
Heres a compact, auditorfriendly way to sign **binary diffs** so they fit cleanly into todays supplychain tooling (DSSE, intoto, Sigstore/Rekor) without inventing a new envelope.
---
# DSSE “deltasig” predicate for signed binary diffs (what & why)
* **Goal:** prove *exactly what changed* in a compiled artifact (perfunction patching, hotfixes/backports) and who signed itusing the standard **DSSE** (Dead Simple Signing Envelope) + **intoto predicate typing** so verifiers and transparency logs work outofthebox.
* **Why not just hash the whole file?** Fullfile hashes miss *where* and *how* a patch changed code. A delta predicate captures functionlevel changes with canonical digests, so auditors can verify the patch is minimal and intentional, and policy can gate on only approved backports applied.”
---
# Envelope strategy
* Keep the **DSSE envelope** as usual (`payloadType`, `payload`, `signatures`).
* The DSSE `payload` is a **canonical JSON** object typed as an intoto predicate.
* Predicate type (minimal): `stellaops/delta-sig/v1`.
This keeps interoperability with:
* **Sigstore/Rekor** (log DSSE envelopes),
* **intoto** (predicate typing & subject semantics),
* existing verification flows (cosign/sigstorepython/intotoverify).
---
# Minimal predicate schema
```json
{
"predicateType": "stellaops/delta-sig/v1",
"subject": [
{
"uri": "oci://registry.example.com/app@sha256:…",
"digest": { "algo": "sha256", "hex": "<artifact_sha256>" },
"filename": "bin/app",
"arch": "linux-amd64"
}
],
"delta": [
{
"function_id": "foo::bar(int,char)",
"addr": 140737488355328,
"old_hash": "<sha256_of_old_bytes>",
"new_hash": "<sha256_of_new_bytes>",
"hash_algo": "sha256",
"diff_len": 112,
"patch_offset": 4096,
"compressed_diff_b64": "<optional_zstd_or_gzip_b64>"
}
],
"tooling": {
"lifter": "ghidra",
"lifter_version": "11.1",
"canonical_ir": "llvm-ir-15"
},
"canonicalization": {
"json_canonicalization_version": "RFC8785"
},
"signer": {
"keyid": "SHA256:…",
"signer_name": "Release Engineering"
},
"signed_digest": {
"algo": "sha256",
"hex": "<sha256_of_canonical_payload_bytes>"
}
}
```
**Notes**
* Use **SHA256** for `subject.digest`, `old_hash`, `new_hash`, and `signed_digest` to maximize compatibility with Rekor/Sigstore. (If you control both ends, **BLAKE2b256** is a fine faster alternative.)
* `function_id` should be a **stable signature** (normalized symbol or demangled prototype); fall back to address + size if needed.
* `compressed_diff_b64` is optional but handy for reproducible patch replay.
---
# Signing & verification (practical)
1. **Produce canonical payload**
* Serialize JSON with **RFC 8785** canonicalization (no insignificant whitespace, deterministic key order).
2. **Wrap in DSSE**
* `payloadType`: `application/vnd.in-toto+json` (common) or a dedicated type string if you prefer.
* `payload`: base64 of canonical JSON bytes.
3. **Sign**
* Use **cosign** or **sigstorepython** to sign DSSE; store in **Rekor** (transparency).
4. **Verify**
* Check DSSE signature decode predicate verify each `old_hash`/`new_hash` against the target bytes optionally replay `compressed_diff_b64` and rehash to confirm `new_hash`.
Policy examples you can enforce:
* Only allow releases whose delta predicate touches ** N functions** and **no controlflow edges** outside whitelisted modules.
* Require `tooling.lifter` in an approved set and `signed_digest.algo == "sha256"`.
---
# Why this fits your stack (StellaOps, CI/CD, auditors)
* **Auditable:** functionlevel intent captured, reproducible verification, deterministic hashing.
* **Composable:** works with existing DSSE/intoto pipelines; attach to OCI artifacts or release manifests.
* **Gateable:** let release policy check the delta surface and signer identity before promotion.
* **Futureproof:** can add PQC keys later without changing the predicate.
If you want, I can generate:
* A JSON Schema (`$id`, types, enums, bounds) for `stellaops/delta-sig/v1`.
* A tiny reference **signer** (CLI) that emits canonical JSON + DSSE, and a **verifier** that checks functionlevel diffs against a binary.