From 7792749bb4a681e130821b4526912f8181ba2168 Mon Sep 17 00:00:00 2001 From: StellaOps Bot Date: Fri, 26 Dec 2025 13:01:43 +0200 Subject: [PATCH] feat: Add archived advisories and implement smart-diff as a core evidence primitive - Introduced new advisory documents for archived superseded advisories, including detailed descriptions of features already implemented or covered by existing sprints. - Added "Smart-Diff as a Core Evidence Primitive" advisory outlining the treatment of SBOM diffs as first-class evidence objects, enhancing vulnerability verdicts with deterministic replayability. - Created "Visual Diffs for Explainable Triage" advisory to improve user experience in understanding policy decisions and reachability changes through visual diffs. - Implemented "Weighted Confidence for VEX Sources" advisory to rank conflicting vulnerability evidence based on freshness and confidence, facilitating better decision-making. - Established a signer module charter detailing the mission, expectations, key components, and signing modes for cryptographic signing services in StellaOps. - Consolidated overlapping concepts from triage UI, visual diffs, and risk budget visualization advisories into a unified specification for better clarity and implementation tracking. --- ...T_20251226_001_BE_cicd_gate_integration.md | 48 ++ ...251226_001_SIGNER_fulcio_keyless_client.md | 502 ++++++++++++++ ...T_20251226_002_ATTESTOR_bundle_rotation.md | 596 +++++++++++++++++ ...RINT_20251226_002_BE_budget_enforcement.md | 51 ++ ...51226_003_ATTESTOR_offline_verification.md | 626 ++++++++++++++++++ ...RINT_20251226_003_BE_exception_approval.md | 60 ++ ..._20251226_004_BE_cicd_signing_templates.md | 621 +++++++++++++++++ .../SPRINT_20251226_004_FE_risk_dashboard.md | 56 ++ ...226_005_SCANNER_reachability_extractors.md | 64 ++ ...0251226_006_DOCS_advisory_consolidation.md | 66 ++ ...SPRINT_20251226_007_BE_determinism_gaps.md | 85 +++ ...1226_008_DOCS_determinism_consolidation.md | 113 ++++ .../SPRINT_20251226_009_SCANNER_funcproof.md | 98 +++ ...0251226_010_FE_visual_diff_enhancements.md | 354 ++++++++++ ...RINT_20251226_010_SIGNALS_runtime_stack.md | 81 +++ ...RINT_20251226_011_BE_auto_vex_downgrade.md | 103 +++ ...20251226_011_BINIDX_known_build_catalog.md | 214 ++++++ ...T_20251226_012_BINIDX_backport_handling.md | 234 +++++++ ...RINT_20251226_012_FE_smart_diff_compare.md | 99 +++ ...20251226_013_BINIDX_fingerprint_factory.md | 240 +++++++ .../SPRINT_20251226_013_FE_triage_canvas.md | 117 ++++ ...20251226_014_BINIDX_scanner_integration.md | 274 ++++++++ ..._20251226_014_DOCS_triage_consolidation.md | 124 ++++ ...PRINT_20251226_015_AI_zastava_companion.md | 75 +++ ...SPRINT_20251226_016_AI_remedy_autopilot.md | 81 +++ .../SPRINT_20251226_017_AI_policy_copilot.md | 80 +++ .../SPRINT_20251226_018_AI_attestations.md | 78 +++ ...PRINT_20251226_019_AI_offline_inference.md | 91 +++ docs/modules/signer/guides/keyless-signing.md | 273 ++++++++ .../web/unified-triage-specification.md | 348 ++++++++++ ...Building a Deterministic Verdict Engine.md | 104 ++- ...cing Canonical JSON for Stable Verdicts.md | 109 ++- ...- Planning Keyless Signing for Verdicts.md | 35 +- ...5 - Visual Diffs for Explainable Triage.md | 56 -- ...stant as Proof-Carrying Evidence Engine.md | 178 +++++ ...- SBOM Spine and Deterministic Evidence.md | 233 +++++++ ...6 - Mapping a Binary Intelligence Graph.md | 60 +- ...- Hybrid Binary and Call‑Graph Analysis.md | 0 ...- Implementing Diff‑Aware Release Gates.md | 0 ...€‘Aware Releases and Auditable Exceptions.md | 0 ...6 - Reachability as Cryptographic Proof.md | 0 ...Smart‑Diff as a Core Evidence Primitive.md | 0 .../archived/2025-12-26-superseded/README.md | 79 +++ ...25 - Triage UI Lessons from Competitors.md | 0 ...5 - Visual Diffs for Explainable Triage.md | 105 +++ ...-Dec-2026 - Visualizing the Risk Budget.md | 0 .../2025-12-26-triage-advisories/README.md | 33 + ...6 - Weighted Confidence for VEX Sources.md | 0 .../archived/2025-12-26-vex-scoring/README.md | 59 ++ src/Signer/AGENTS.md | 71 ++ 50 files changed, 6844 insertions(+), 130 deletions(-) create mode 100644 docs/implplan/SPRINT_20251226_001_BE_cicd_gate_integration.md create mode 100644 docs/implplan/SPRINT_20251226_001_SIGNER_fulcio_keyless_client.md create mode 100644 docs/implplan/SPRINT_20251226_002_ATTESTOR_bundle_rotation.md create mode 100644 docs/implplan/SPRINT_20251226_002_BE_budget_enforcement.md create mode 100644 docs/implplan/SPRINT_20251226_003_ATTESTOR_offline_verification.md create mode 100644 docs/implplan/SPRINT_20251226_003_BE_exception_approval.md create mode 100644 docs/implplan/SPRINT_20251226_004_BE_cicd_signing_templates.md create mode 100644 docs/implplan/SPRINT_20251226_004_FE_risk_dashboard.md create mode 100644 docs/implplan/SPRINT_20251226_005_SCANNER_reachability_extractors.md create mode 100644 docs/implplan/SPRINT_20251226_006_DOCS_advisory_consolidation.md create mode 100644 docs/implplan/SPRINT_20251226_007_BE_determinism_gaps.md create mode 100644 docs/implplan/SPRINT_20251226_008_DOCS_determinism_consolidation.md create mode 100644 docs/implplan/SPRINT_20251226_009_SCANNER_funcproof.md create mode 100644 docs/implplan/SPRINT_20251226_010_FE_visual_diff_enhancements.md create mode 100644 docs/implplan/SPRINT_20251226_010_SIGNALS_runtime_stack.md create mode 100644 docs/implplan/SPRINT_20251226_011_BE_auto_vex_downgrade.md create mode 100644 docs/implplan/SPRINT_20251226_011_BINIDX_known_build_catalog.md create mode 100644 docs/implplan/SPRINT_20251226_012_BINIDX_backport_handling.md create mode 100644 docs/implplan/SPRINT_20251226_012_FE_smart_diff_compare.md create mode 100644 docs/implplan/SPRINT_20251226_013_BINIDX_fingerprint_factory.md create mode 100644 docs/implplan/SPRINT_20251226_013_FE_triage_canvas.md create mode 100644 docs/implplan/SPRINT_20251226_014_BINIDX_scanner_integration.md create mode 100644 docs/implplan/SPRINT_20251226_014_DOCS_triage_consolidation.md create mode 100644 docs/implplan/SPRINT_20251226_015_AI_zastava_companion.md create mode 100644 docs/implplan/SPRINT_20251226_016_AI_remedy_autopilot.md create mode 100644 docs/implplan/SPRINT_20251226_017_AI_policy_copilot.md create mode 100644 docs/implplan/SPRINT_20251226_018_AI_attestations.md create mode 100644 docs/implplan/SPRINT_20251226_019_AI_offline_inference.md create mode 100644 docs/modules/signer/guides/keyless-signing.md create mode 100644 docs/modules/web/unified-triage-specification.md delete mode 100644 docs/product-advisories/25-Dec-2025 - Visual Diffs for Explainable Triage.md create mode 100644 docs/product-advisories/26-Dec-2025 - AI Assistant as Proof-Carrying Evidence Engine.md create mode 100644 docs/product-advisories/26-Dec-2025 - Stella Ops vNext - SBOM Spine and Deterministic Evidence.md rename docs/product-advisories/{ => archived/2025-12-26-empty-advisories}/25-Dec-2025 - Hybrid Binary and Call‑Graph Analysis.md (100%) rename docs/product-advisories/{ => archived/2025-12-26-superseded}/25-Dec-2025 - Implementing Diff‑Aware Release Gates.md (100%) rename docs/product-advisories/{ => archived/2025-12-26-superseded}/26-Dec-2026 - Diff‑Aware Releases and Auditable Exceptions.md (100%) rename docs/product-advisories/{ => archived/2025-12-26-superseded}/26-Dec-2026 - Reachability as Cryptographic Proof.md (100%) rename docs/product-advisories/{ => archived/2025-12-26-superseded}/26-Dec-2026 - Smart‑Diff as a Core Evidence Primitive.md (100%) create mode 100644 docs/product-advisories/archived/2025-12-26-superseded/README.md rename docs/product-advisories/{ => archived/2025-12-26-triage-advisories}/25-Dec-2025 - Triage UI Lessons from Competitors.md (100%) create mode 100644 docs/product-advisories/archived/2025-12-26-triage-advisories/25-Dec-2025 - Visual Diffs for Explainable Triage.md rename docs/product-advisories/{ => archived/2025-12-26-triage-advisories}/26-Dec-2026 - Visualizing the Risk Budget.md (100%) create mode 100644 docs/product-advisories/archived/2025-12-26-triage-advisories/README.md rename docs/product-advisories/{ => archived/2025-12-26-vex-scoring}/26-Dec-2026 - Weighted Confidence for VEX Sources.md (100%) create mode 100644 docs/product-advisories/archived/2025-12-26-vex-scoring/README.md create mode 100644 src/Signer/AGENTS.md diff --git a/docs/implplan/SPRINT_20251226_001_BE_cicd_gate_integration.md b/docs/implplan/SPRINT_20251226_001_BE_cicd_gate_integration.md new file mode 100644 index 000000000..0ee96aed5 --- /dev/null +++ b/docs/implplan/SPRINT_20251226_001_BE_cicd_gate_integration.md @@ -0,0 +1,48 @@ +# Sprint 20251226 Β· CI/CD Release Gate Integration + +## Topic & Scope +- Wire existing `DriftGateEvaluator` into CI/CD pipelines for automated release gating. +- Provide webhook endpoint for Zastava/registry triggers, scheduler job integration, and CI exit codes. +- Deliver example workflows for GitHub Actions and GitLab CI. +- **Working directory:** `src/Policy/StellaOps.Policy.Engine`, `src/Scheduler/StellaOps.Scheduler` + +## Dependencies & Concurrency +- Depends on: `DriftGateEvaluator` (complete), `DeltaComputer` (complete), `DeltaVerdict` (complete). +- Can run in parallel with: SPRINT_20251226_005_SCANNER (reachability extractors). +- Blocks: SPRINT_20251226_004_FE (dashboard needs API endpoints from this sprint). + +## Documentation Prerequisites +- `docs/modules/policy/architecture.md` +- `docs/modules/scheduler/architecture.md` +- `docs/modules/zastava/architecture.md` +- `CLAUDE.md` (project conventions) + +## Delivery Tracker +| # | Task ID | Status | Key dependency / next step | Owners | Task Definition | +| --- | --- | --- | --- | --- | --- | +| 1 | CICD-GATE-01 | TODO | None | Policy Guild | Create `POST /api/v1/policy/gate/evaluate` endpoint accepting image digest + baseline ref; returns `DeltaVerdict` with Pass/Warn/Fail status | +| 2 | CICD-GATE-02 | TODO | CICD-GATE-01 | Policy Guild | Add webhook handler for Zastava image-push events; trigger async gate evaluation job | +| 3 | CICD-GATE-03 | TODO | CICD-GATE-01 | Scheduler Guild | Create `GateEvaluationJob` in Scheduler; wire to Policy Engine gate endpoint | +| 4 | CICD-GATE-04 | TODO | CICD-GATE-01 | Policy Guild | Define CI exit codes: 0=Pass, 1=Warn (configurable pass-through), 2=Fail/Block | +| 5 | CICD-GATE-05 | TODO | CICD-GATE-04 | Policy Guild | CLI command `stella gate evaluate --image --baseline ` with exit code support | +| 6 | CICD-GATE-06 | TODO | CICD-GATE-02 | Policy Guild | Gate bypass audit logging: record who/when/why for any override; persist to audit table | +| 7 | CICD-GATE-07 | TODO | CICD-GATE-05 | DevOps Guild | GitHub Actions example workflow using `stella gate evaluate` | +| 8 | CICD-GATE-08 | TODO | CICD-GATE-05 | DevOps Guild | GitLab CI example workflow using `stella gate evaluate` | +| 9 | CICD-GATE-09 | TODO | CICD-GATE-03 | Policy Guild + Zastava Guild | Integration tests: Zastava webhook -> Scheduler -> Policy Engine -> verdict | +| 10 | CICD-GATE-10 | TODO | CICD-GATE-09 | Policy Guild | Documentation: update `docs/modules/policy/architecture.md` with gate API section | + +## Execution Log +| Date (UTC) | Update | Owner | +| --- | --- | --- | +| 2025-12-26 | Sprint created from product advisory analysis; consolidates diff-aware release gate requirements. | Project Mgmt | + +## Decisions & Risks +- Decision needed: Should Warn status block CI by default or pass-through? Recommend: configurable per-environment. +- Decision needed: Gate evaluation timeout for long-running reachability analysis. Recommend: 60s default, configurable. +- Risk: High evaluation latency may slow CI pipelines. Mitigation: async evaluation with cached baseline snapshots. +- Risk: Gate bypass abuse. Mitigation: audit logging + Authority scope enforcement for bypass permission. + +## Next Checkpoints +- 2025-12-30 | CICD-GATE-01 complete | Gate endpoint accepting requests | +- 2026-01-03 | CICD-GATE-05 complete | CLI integration verified | +- 2026-01-06 | CICD-GATE-09 complete | End-to-end integration tested | diff --git a/docs/implplan/SPRINT_20251226_001_SIGNER_fulcio_keyless_client.md b/docs/implplan/SPRINT_20251226_001_SIGNER_fulcio_keyless_client.md new file mode 100644 index 000000000..63da3e0e0 --- /dev/null +++ b/docs/implplan/SPRINT_20251226_001_SIGNER_fulcio_keyless_client.md @@ -0,0 +1,502 @@ +# SPRINT_20251226_001_SIGNER_fulcio_keyless_client + +**Sprint ID:** 20251226_001_SIGNER +**Topic:** Fulcio Keyless Signing Client Implementation +**Status:** TODO +**Priority:** P0 (Critical Path) +**Created:** 2025-12-26 +**Working Directory:** `src/Signer/` + +--- + +## Executive Summary + +Implement Sigstore Fulcio integration for keyless signing in CI/CD pipelines. This enables ephemeral X.509 certificates (~10 min TTL) obtained via OIDC identity tokens, eliminating the need for persistent signing keys in CI environments while maintaining cryptographic non-repudiation through Rekor transparency logging. + +**Business Value:** +- Zero key management overhead in CI pipelines +- Eliminates credential sprawl and secret rotation complexity +- Enables audit-grade non-repudiation via OIDC identity binding +- Aligns with Sigstore industry standard (adopted by Kubernetes, npm, PyPI) + +**Dependencies:** +- Attestor module for Rekor submission (Sprint 20251226_002) +- Authority module for OIDC token minting (existing) +- RFC 8785 canonicalization (existing in `StellaOps.Canonicalization`) + +--- + +## Prerequisites + +**Required Reading (complete before DOING):** +- [ ] `docs/modules/signer/architecture.md` - Signer architecture dossier +- [ ] `docs/modules/attestor/architecture.md` - Attestor architecture (Β§2.1 for Rekor) +- [ ] `CLAUDE.md` - Project coding standards +- [ ] `src/Signer/AGENTS.md` - Module charter (if exists, create if not) +- [ ] Sigstore Fulcio documentation: https://docs.sigstore.dev/certificate_authority/overview/ + +**Technical Prerequisites:** +- [ ] Authority OIDC endpoint operational (`/oauth/token`) +- [ ] BouncyCastle crypto library available for ECDSA/Ed25519 +- [ ] HTTP/2 client infrastructure for Fulcio API calls + +--- + +## Scope & Boundaries + +### In Scope +- Fulcio OIDC client implementation +- Ephemeral keypair generation (ECDSA P-256, Ed25519) +- Certificate chain handling and validation +- Integration with existing `IDsseSigner` interface +- Configuration schema for Fulcio endpoints +- Unit and integration tests + +### Out of Scope +- Rekor submission (handled by Attestor - Sprint 002) +- Bundle rotation workflows (Sprint 002) +- CLI integration (Sprint 003) +- CI/CD templates (Sprint 004) + +### Guardrails +- No hard-coded external URLs; all endpoints configurable +- Ephemeral keys MUST NOT persist to disk +- Certificate chains MUST validate to configured Fulcio roots +- All timestamps in UTC ISO-8601 + +--- + +## Architecture + +### Component Diagram + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Signer Service β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ SignerPipeline │───▢│ IDsseSigner β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β–Ό β–Ό β–Ό β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ CryptoDsseSignerβ”‚ β”‚ KeylessDsseSignerβ”‚ β”‚ KmsDsseSigner β”‚ β”‚ +β”‚ β”‚ (existing) β”‚ β”‚ (NEW) β”‚ β”‚ (existing) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β–Ό β–Ό β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ IFulcioClient β”‚ β”‚ IEphemeralKeyGen β”‚ β”‚ +β”‚ β”‚ (NEW) β”‚ β”‚ (NEW) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό HTTPS (mTLS optional) + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Fulcio CA β”‚ + β”‚ (external) β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### New Interfaces + +```csharp +// src/Signer/__Libraries/StellaOps.Signer.Keyless/IFulcioClient.cs +public interface IFulcioClient +{ + Task GetCertificateAsync( + FulcioCertificateRequest request, + CancellationToken cancellationToken = default); +} + +public record FulcioCertificateRequest( + byte[] PublicKey, + string Algorithm, // "ECDSA_P256" | "Ed25519" + string OidcIdentityToken, + string? ProofOfPossession); // Optional signed challenge + +public record FulcioCertificateResult( + byte[] Certificate, + byte[][] CertificateChain, + string SignedCertificateTimestamp, + DateTimeOffset NotBefore, + DateTimeOffset NotAfter, + FulcioIdentity Identity); + +public record FulcioIdentity( + string Issuer, + string Subject, + string? SubjectAlternativeName); +``` + +```csharp +// src/Signer/__Libraries/StellaOps.Signer.Keyless/IEphemeralKeyGenerator.cs +public interface IEphemeralKeyGenerator +{ + EphemeralKeyPair Generate(string algorithm); + void Dispose(EphemeralKeyPair keyPair); // Secure erasure +} + +public sealed class EphemeralKeyPair : IDisposable +{ + public byte[] PublicKey { get; } + public byte[] PrivateKey { get; } // In-memory only, never persisted + public string Algorithm { get; } + public DateTimeOffset CreatedAt { get; } + + public void Dispose(); // Zeros memory +} +``` + +--- + +## Delivery Tracker + +| ID | Task | Owner | Status | Dependencies | Acceptance Criteria | +|----|------|-------|--------|--------------|---------------------| +| 0001 | Create `StellaOps.Signer.Keyless` library project | β€” | TODO | β€” | Project compiles, referenced by Signer.Infrastructure | +| 0002 | Implement `IEphemeralKeyGenerator` interface | β€” | TODO | 0001 | Generates ECDSA P-256 and Ed25519 keypairs | +| 0003 | Implement `EphemeralKeyPair` with secure disposal | β€” | TODO | 0002 | Memory zeroed on Dispose(), finalizer backup | +| 0004 | Implement `IFulcioClient` interface | β€” | TODO | 0001 | Contract defined, mockable | +| 0005 | Implement `HttpFulcioClient` | β€” | TODO | 0004 | HTTP/2 client, retries, circuit breaker | +| 0006 | Add Fulcio response parsing (X.509 chain) | β€” | TODO | 0005 | PEM/DER parsing, chain ordering | +| 0007 | Implement `KeylessDsseSigner` | β€” | TODO | 0003, 0006 | Signs DSSE with ephemeral key + Fulcio cert | +| 0008 | Add `verdict.stella/v1` predicate type | β€” | TODO | β€” | PredicateTypes.cs updated, schema defined | +| 0009 | Add configuration schema `SignerKeylessOptions` | β€” | TODO | 0005 | YAML/JSON config, validation | +| 0010 | Wire DI registration in `ServiceCollectionExtensions` | β€” | TODO | 0007, 0009 | `services.AddKeylessSigning()` | +| 0011 | Implement certificate chain validation | β€” | TODO | 0006 | Validates to configured Fulcio roots | +| 0012 | Add OIDC token acquisition from Authority | β€” | TODO | β€” | Client credentials flow, caching | +| 0013 | Unit tests: EphemeralKeyGenerator | β€” | TODO | 0003 | Key generation, disposal, algorithm coverage | +| 0014 | Unit tests: HttpFulcioClient (mocked) | β€” | TODO | 0005 | Happy path, error handling, retries | +| 0015 | Unit tests: KeylessDsseSigner | β€” | TODO | 0007 | Signing roundtrip, cert attachment | +| 0016 | Unit tests: Certificate chain validation | β€” | TODO | 0011 | Valid chain, expired cert, untrusted root | +| 0017 | Integration test: Full keyless signing flow | β€” | TODO | 0010 | End-to-end with mock Fulcio | +| 0018 | Integration test: Verify signed bundle | β€” | TODO | 0017 | Signature verification, cert chain | +| 0019 | Documentation: Keyless signing guide | β€” | TODO | 0017 | `docs/modules/signer/guides/keyless-signing.md` | +| 0020 | Update `src/Signer/AGENTS.md` | β€” | TODO | 0019 | Add keyless components to charter | + +--- + +## Technical Specifications + +### Configuration Schema + +```yaml +# etc/signer.yaml +signer: + signing: + mode: "keyless" # "keyless" | "kms" | "hybrid" + keyless: + enabled: true + fulcio: + url: "https://fulcio.sigstore.dev" + # For private deployments: + # url: "https://fulcio.internal.example.com" + timeout: 30s + retries: 3 + backoffBase: 1s + backoffMax: 30s + oidc: + # Use Authority as OIDC provider + issuer: "https://authority.internal" + clientId: "signer-keyless" + clientSecretRef: "env:SIGNER_OIDC_CLIENT_SECRET" + # Alternative: use ambient OIDC (CI runner tokens) + useAmbientToken: false + ambientTokenPath: "/var/run/secrets/tokens/oidc" + algorithms: + preferred: "ECDSA_P256" + allowed: ["ECDSA_P256", "Ed25519"] + certificate: + # Fulcio roots for validation + rootBundlePath: "/etc/stellaops/fulcio-roots.pem" + # Allow additional roots for private Fulcio instances + additionalRoots: [] + validateChain: true + requireSCT: true # Require Signed Certificate Timestamp + identity: + # Expected OIDC issuer for verification + expectedIssuers: + - "https://authority.internal" + - "https://token.actions.githubusercontent.com" + - "https://gitlab.com" + # Expected SAN patterns (regex) + expectedSubjectPatterns: + - "^https://github\\.com/stella-ops/.*$" + - "^urn:stellaops:signer$" +``` + +### Error Handling + +```csharp +public abstract class KeylessSigningException : SignerException +{ + protected KeylessSigningException(string message, Exception? inner = null) + : base(message, inner) { } +} + +public class FulcioUnavailableException : KeylessSigningException +{ + public string FulcioUrl { get; } + public int HttpStatus { get; } +} + +public class OidcTokenAcquisitionException : KeylessSigningException +{ + public string Issuer { get; } + public string Reason { get; } +} + +public class CertificateChainValidationException : KeylessSigningException +{ + public string[] ChainSubjects { get; } + public string ValidationError { get; } +} + +public class EphemeralKeyGenerationException : KeylessSigningException +{ + public string Algorithm { get; } +} +``` + +### Metrics + +```csharp +// Prometheus metrics +signer.keyless.cert_requests_total{result="success|failure|timeout"} +signer.keyless.cert_latency_seconds{quantile="0.5|0.9|0.99"} +signer.keyless.oidc_token_refresh_total{result="success|failure"} +signer.keyless.ephemeral_keys_generated_total{algorithm="ECDSA_P256|Ed25519"} +signer.keyless.cert_chain_validation_total{result="valid|expired|untrusted"} +``` + +### OpenTelemetry Traces + +``` +signer.keyless.sign +β”œβ”€β”€ signer.keyless.generate_ephemeral_key +β”œβ”€β”€ signer.keyless.acquire_oidc_token +β”œβ”€β”€ signer.keyless.request_certificate +β”‚ β”œβ”€β”€ http.request POST /api/v2/signingCert +β”‚ └── signer.keyless.parse_certificate_chain +β”œβ”€β”€ signer.keyless.validate_certificate_chain +└── signer.keyless.sign_payload +``` + +--- + +## Testing Requirements + +### Unit Test Coverage + +| Component | Test File | Coverage Target | +|-----------|-----------|-----------------| +| EphemeralKeyGenerator | `EphemeralKeyGeneratorTests.cs` | 100% | +| HttpFulcioClient | `HttpFulcioClientTests.cs` | 95% | +| KeylessDsseSigner | `KeylessDsseSignerTests.cs` | 95% | +| CertificateChainValidator | `CertificateChainValidatorTests.cs` | 100% | +| SignerKeylessOptions | `SignerKeylessOptionsTests.cs` | 100% | + +### Integration Tests + +```csharp +[Fact] +public async Task KeylessSigning_WithMockFulcio_ProducesValidDsse() +{ + // Arrange: Mock Fulcio server returning valid cert chain + // Act: Sign a verdict payload + // Assert: DSSE envelope contains valid signature + cert chain +} + +[Fact] +public async Task KeylessSigning_CertificateExpired_ThrowsValidationException() +{ + // Arrange: Mock Fulcio returning expired certificate + // Act/Assert: CertificateChainValidationException thrown +} + +[Fact] +public async Task KeylessSigning_FulcioUnavailable_RetriesWithBackoff() +{ + // Arrange: Mock Fulcio returning 503 then 200 + // Act: Sign payload + // Assert: Success after retry, metrics recorded +} + +[Fact] +public async Task KeylessSigning_OidcTokenInvalid_ThrowsAcquisitionException() +{ + // Arrange: Authority returns 401 + // Act/Assert: OidcTokenAcquisitionException thrown +} + +[Fact] +public async Task EphemeralKeyPair_Disposal_ZerosMemory() +{ + // Arrange: Generate keypair + // Act: Dispose + // Assert: Private key memory is zeroed (via reflection/unsafe) +} +``` + +### Property-Based Tests + +```csharp +[Property] +public void KeylessSigning_SamePayload_DifferentSignatures(byte[] payload) +{ + // Ephemeral keys mean different signatures each time + var sig1 = await signer.SignAsync(payload); + var sig2 = await signer.SignAsync(payload); + Assert.NotEqual(sig1.Signature, sig2.Signature); + Assert.NotEqual(sig1.Certificate, sig2.Certificate); +} + +[Property] +public void KeylessSigning_SignatureDeterminism_SameKeyPair( + byte[] payload, EphemeralKeyPair keyPair) +{ + // Same ephemeral key produces same signature for same payload + var sig1 = Sign(payload, keyPair); + var sig2 = Sign(payload, keyPair); + Assert.Equal(sig1, sig2); +} +``` + +--- + +## Security Considerations + +### Threat Model + +| Threat | Mitigation | +|--------|------------| +| Private key theft | Keys exist only in memory, zeroed on disposal | +| Fulcio impersonation | TLS certificate validation, root pinning | +| OIDC token replay | Short-lived tokens, audience validation | +| Certificate forgery | Chain validation to trusted Fulcio roots | +| Timing attacks | Constant-time comparison for signatures | + +### Security Checklist + +- [ ] Ephemeral keys never written to disk or logs +- [ ] Private key memory zeroed in Dispose() and finalizer +- [ ] Fulcio TLS certificate validated +- [ ] OIDC token audience matches expected value +- [ ] Certificate chain validates to configured roots +- [ ] SCT (Signed Certificate Timestamp) verified when required +- [ ] No secrets in configuration (use refs: `env:`, `file:`, `vault:`) + +--- + +## Decisions & Risks + +| ID | Decision/Risk | Status | Owner | Notes | +|----|---------------|--------|-------|-------| +| D001 | Use ECDSA P-256 as default algorithm | DECIDED | β€” | Widest compatibility, Fulcio default | +| D002 | Support Ed25519 as alternative | DECIDED | β€” | Better performance, growing adoption | +| R001 | Fulcio availability dependency | OPEN | β€” | Mitigate with retries, circuit breaker, fallback to KMS | +| R002 | OIDC token acquisition latency | OPEN | β€” | Cache tokens, refresh proactively | +| R003 | Air-gap incompatibility | ACCEPTED | β€” | Keyless requires network; use KMS mode for air-gap | + +--- + +## Upcoming Checkpoints + +| Date | Milestone | Exit Criteria | +|------|-----------|---------------| +| +3 days | Core interfaces complete | 0001-0004 DONE | +| +7 days | Fulcio client working | 0005-0006 DONE, manual test passing | +| +10 days | Keyless signer integrated | 0007-0012 DONE | +| +14 days | Full test coverage | 0013-0018 DONE | +| +15 days | Documentation complete | 0019-0020 DONE, sprint DONE | + +--- + +## Execution Log + +| Date | Role | Action | Notes | +|------|------|--------|-------| +| 2025-12-26 | PM | Sprint created | Initial planning from keyless signing advisory | + +--- + +## Related Documents + +- **Parent Advisory:** `docs/product-advisories/25-Dec-2025 - Planning Keyless Signing for Verdicts.md` +- **Related Advisory:** `docs/product-advisories/25-Dec-2025 - Building a Deterministic Verdict Engine.md` +- **Signer Architecture:** `docs/modules/signer/architecture.md` +- **Attestor Architecture:** `docs/modules/attestor/architecture.md` +- **Successor Sprint:** `SPRINT_20251226_002_ATTESTOR_bundle_rotation.md` + +--- + +## Appendix A: Fulcio API Contract + +### Request: POST /api/v2/signingCert + +```json +{ + "credentials": { + "oidcIdentityToken": "eyJhbGciOiJSUzI1NiIs..." + }, + "publicKeyRequest": { + "publicKey": { + "algorithm": "ECDSA", + "content": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE..." + }, + "proofOfPossession": "MEUCIQD..." // Optional + } +} +``` + +### Response: 200 OK + +```json +{ + "signedCertificateEmbeddedSct": { + "chain": { + "certificates": [ + "-----BEGIN CERTIFICATE-----\nMIIC...", + "-----BEGIN CERTIFICATE-----\nMIIB..." + ] + } + } +} +``` + +--- + +## Appendix B: DSSE Bundle with Keyless Certificate + +```json +{ + "payloadType": "application/vnd.in-toto+json", + "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjEi...", + "signatures": [ + { + "keyid": "", + "sig": "MEUCIQDx5z...", + "cert": "-----BEGIN CERTIFICATE-----\nMIIC..." + } + ], + "certificateChain": [ + "-----BEGIN CERTIFICATE-----\nMIIC...", + "-----BEGIN CERTIFICATE-----\nMIIB..." + ], + "signedCertificateTimestamp": "AO3W9T...", + "signingMode": "keyless", + "signingIdentity": { + "issuer": "https://authority.internal", + "subject": "signer@stella-ops.org", + "san": "urn:stellaops:signer" + } +} +``` + +--- + +*End of Sprint Document* diff --git a/docs/implplan/SPRINT_20251226_002_ATTESTOR_bundle_rotation.md b/docs/implplan/SPRINT_20251226_002_ATTESTOR_bundle_rotation.md new file mode 100644 index 000000000..e5e687a01 --- /dev/null +++ b/docs/implplan/SPRINT_20251226_002_ATTESTOR_bundle_rotation.md @@ -0,0 +1,596 @@ +# SPRINT_20251226_002_ATTESTOR_bundle_rotation + +**Sprint ID:** 20251226_002_ATTESTOR +**Topic:** Attestation Bundle Rotation and Long-Term Verification +**Status:** TODO +**Priority:** P1 (High) +**Created:** 2025-12-26 +**Working Directory:** `src/Attestor/`, `src/Scheduler/` + +--- + +## Executive Summary + +Implement monthly attestation bundle rotation to ensure long-term verification of keyless-signed artifacts. Since Fulcio certificates have short lifetimes (~10 minutes), attestations must be bundled with Rekor inclusion proofs and optionally re-signed with an organization key for verification beyond certificate expiry. + +**Business Value:** +- Enables verification of attestations years after signing (regulatory compliance) +- Supports air-gapped environments with bundled proofs +- Provides organizational endorsement layer for high-assurance workflows +- Implements Sigstore best practices for long-term verification + +**Dependencies:** +- Sprint 20251226_001 (Keyless signing client) +- Existing Rekor v2 integration in Attestor +- Scheduler module for periodic job execution + +--- + +## Prerequisites + +**Required Reading (complete before DOING):** +- [ ] `docs/modules/attestor/architecture.md` - Attestor architecture dossier +- [ ] `src/Attestor/AGENTS.md` - Module charter +- [ ] `docs/24_OFFLINE_KIT.md` - Offline bundle format +- [ ] `CLAUDE.md` - Project coding standards +- [ ] Sigstore bundle format: https://github.com/sigstore/protobuf-specs + +**Technical Prerequisites:** +- [ ] Rekor v2 submission working (existing) +- [ ] Merkle inclusion proof verification (existing) +- [ ] PostgreSQL `attestor.entries` table populated +- [ ] S3/RustFS archive store configured + +--- + +## Scope & Boundaries + +### In Scope +- Attestation bundle schema design +- Bundle aggregation service +- Organization key re-signing workflow +- Scheduler job for monthly bundling +- Bundle retention policy (24 months default) +- Bundle export API +- Integration with Offline Kit + +### Out of Scope +- Initial keyless signing (Sprint 001) +- CLI verification commands (Sprint 003) +- CI/CD templates (Sprint 004) + +### Guardrails +- Bundles MUST be deterministic (same inputs β†’ same bundle hash) +- Bundle creation MUST NOT modify original attestations +- Retention policy MUST be configurable per tenant +- All timestamps in UTC ISO-8601 + +--- + +## Architecture + +### Bundle Data Model + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Attestation Bundle (v1) β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ metadata: β”‚ +β”‚ bundleId: sha256: β”‚ +β”‚ version: "1.0" β”‚ +β”‚ createdAt: "2025-12-26T00:00:00Z" β”‚ +β”‚ periodStart: "2025-12-01T00:00:00Z" β”‚ +β”‚ periodEnd: "2025-12-31T23:59:59Z" β”‚ +β”‚ attestationCount: 1542 β”‚ +β”‚ orgKeyFingerprint: "sha256:abc123..." β”‚ +β”‚ β”‚ +β”‚ attestations: [ β”‚ +β”‚ { β”‚ +β”‚ entryId: "uuid-1" β”‚ +β”‚ rekorUuid: "24296fb2..." β”‚ +β”‚ rekorLogIndex: 12345678 β”‚ +β”‚ artifactDigest: "sha256:..." β”‚ +β”‚ predicateType: "verdict.stella/v1" β”‚ +β”‚ signedAt: "2025-12-15T10:30:00Z" β”‚ +β”‚ signingMode: "keyless" β”‚ +β”‚ signingIdentity: { issuer, subject, san } β”‚ +β”‚ inclusionProof: { checkpoint, path[] } β”‚ +β”‚ envelope: { payloadType, payload, signatures[], certs[] } β”‚ +β”‚ }, β”‚ +β”‚ ... β”‚ +β”‚ ] β”‚ +β”‚ β”‚ +β”‚ merkleTree: { β”‚ +β”‚ algorithm: "SHA256" β”‚ +β”‚ root: "sha256:..." β”‚ +β”‚ leafCount: 1542 β”‚ +β”‚ } β”‚ +β”‚ β”‚ +β”‚ orgSignature: { // Optional: org-key re-signβ”‚ +β”‚ keyId: "org-signing-key-2025" β”‚ +β”‚ algorithm: "ECDSA_P256" β”‚ +β”‚ signature: "base64..." β”‚ +β”‚ signedAt: "2025-12-26T01:00:00Z" β”‚ +β”‚ certificateChain: [...] β”‚ +β”‚ } β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Component Diagram + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Attestor Service β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ BundleController │────────▢│ IAttestationBundlerβ”‚ β”‚ +β”‚ β”‚ (API endpoints) β”‚ β”‚ (NEW) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β–Ό β–Ό β–Ό β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚ +β”‚ β”‚ BundleAggregatorβ”‚ β”‚ BundleSigner β”‚ β”‚BundleStore β”‚β”‚ +β”‚ β”‚ (NEW) β”‚ β”‚ (NEW) β”‚ β”‚(NEW) β”‚β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β–Ό β–Ό β–Ό β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚ +β”‚ β”‚ AttestorEntry β”‚ β”‚ IOrgKeySigner β”‚ β”‚ S3/RustFS β”‚β”‚ +β”‚ β”‚ Repository β”‚ β”‚ (KMS/HSM) β”‚ β”‚ Archive β”‚β”‚ +β”‚ β”‚ (existing) β”‚ β”‚ β”‚ β”‚ β”‚β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Scheduler Service β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ BundleRotationJob β”‚ ← Runs monthly (configurable) β”‚ +β”‚ β”‚ - Query attestations β”‚ β”‚ +β”‚ β”‚ - Create bundle β”‚ β”‚ +β”‚ β”‚ - Sign with org key β”‚ β”‚ +β”‚ β”‚ - Store bundle β”‚ β”‚ +β”‚ β”‚ - Apply retention policy β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### New Interfaces + +```csharp +// src/Attestor/__Libraries/StellaOps.Attestor.Bundling/IAttestationBundler.cs + +public interface IAttestationBundler +{ + Task CreateBundleAsync( + BundleCreationRequest request, + CancellationToken cancellationToken = default); + + Task GetBundleAsync( + string bundleId, + CancellationToken cancellationToken = default); + + Task ListBundlesAsync( + BundleListRequest request, + CancellationToken cancellationToken = default); +} + +public record BundleCreationRequest( + DateTimeOffset PeriodStart, + DateTimeOffset PeriodEnd, + string? TenantId, + bool SignWithOrgKey, + string? OrgKeyId); + +public record AttestationBundle( + string BundleId, // sha256: + string Version, + DateTimeOffset CreatedAt, + DateTimeOffset PeriodStart, + DateTimeOffset PeriodEnd, + int AttestationCount, + IReadOnlyList Attestations, + MerkleTreeInfo MerkleTree, + OrgSignature? OrgSignature); + +public record BundledAttestation( + string EntryId, + string RekorUuid, + long RekorLogIndex, + string ArtifactDigest, + string PredicateType, + DateTimeOffset SignedAt, + string SigningMode, + SigningIdentity SigningIdentity, + InclusionProof InclusionProof, + DsseEnvelope Envelope); + +public record MerkleTreeInfo( + string Algorithm, + string Root, + int LeafCount); + +public record OrgSignature( + string KeyId, + string Algorithm, + string Signature, + DateTimeOffset SignedAt, + string[] CertificateChain); +``` + +```csharp +// src/Attestor/__Libraries/StellaOps.Attestor.Bundling/IOrgKeySigner.cs + +public interface IOrgKeySigner +{ + Task SignBundleAsync( + byte[] bundleDigest, + string keyId, + CancellationToken cancellationToken = default); + + Task VerifyBundleAsync( + byte[] bundleDigest, + OrgSignature signature, + CancellationToken cancellationToken = default); +} +``` + +--- + +## Delivery Tracker + +| ID | Task | Owner | Status | Dependencies | Acceptance Criteria | +|----|------|-------|--------|--------------|---------------------| +| 0001 | Create `StellaOps.Attestor.Bundling` library project | β€” | TODO | β€” | Project compiles, referenced by Attestor | +| 0002 | Define `AttestationBundle` record and schema | β€” | TODO | 0001 | JSON schema validated, versioned | +| 0003 | Implement `IBundleAggregator` for collecting attestations | β€” | TODO | 0002 | Queries by date range, tenant | +| 0004 | Implement deterministic Merkle tree for bundle | β€” | TODO | 0003 | Same attestations β†’ same root | +| 0005 | Implement `IAttestationBundler` service | β€” | TODO | 0003, 0004 | Creates complete bundle | +| 0006 | Implement `IOrgKeySigner` interface | β€” | TODO | 0001 | Contract defined, KMS-backed | +| 0007 | Implement `KmsOrgKeySigner` | β€” | TODO | 0006 | Uses existing KMS infrastructure | +| 0008 | Add org-key signing to bundle workflow | β€” | TODO | 0005, 0007 | Optional signing step | +| 0009 | Implement `IBundleStore` for S3/RustFS | β€” | TODO | 0002 | Store and retrieve bundles | +| 0010 | Add bundle export API endpoint | β€” | TODO | 0005, 0009 | `GET /api/v1/bundles/{id}` | +| 0011 | Add bundle list API endpoint | β€” | TODO | 0009 | `GET /api/v1/bundles` with pagination | +| 0012 | Add bundle creation API endpoint | β€” | TODO | 0005 | `POST /api/v1/bundles` | +| 0013 | Define bundle retention policy schema | β€” | TODO | β€” | Configurable per tenant | +| 0014 | Implement retention policy enforcement | β€” | TODO | 0009, 0013 | Auto-delete after N months | +| 0015 | Create `BundleRotationJob` in Scheduler | β€” | TODO | 0005 | Runs on schedule | +| 0016 | Add job configuration (monthly by default) | β€” | TODO | 0015 | Cron expression support | +| 0017 | Integrate with Offline Kit export | β€” | TODO | 0009 | Bundle included in OUK | +| 0018 | Unit tests: BundleAggregator | β€” | TODO | 0003 | Date range, tenant filtering | +| 0019 | Unit tests: Merkle tree determinism | β€” | TODO | 0004 | Shuffle input β†’ same root | +| 0020 | Unit tests: Bundle creation | β€” | TODO | 0005 | Complete bundle structure | +| 0021 | Unit tests: Org-key signing | β€” | TODO | 0007 | Sign/verify roundtrip | +| 0022 | Unit tests: Retention policy | β€” | TODO | 0014 | Expiry calculation, deletion | +| 0023 | Integration test: Full bundle workflow | β€” | TODO | 0010-0012 | Create β†’ store β†’ retrieve | +| 0024 | Integration test: Scheduler job | β€” | TODO | 0015 | Job executes, bundle created | +| 0025 | Documentation: Bundle format spec | β€” | TODO | 0002 | `docs/modules/attestor/bundle-format.md` | +| 0026 | Documentation: Rotation operations guide | β€” | TODO | 0015 | `docs/modules/attestor/operations/bundle-rotation.md` | + +--- + +## Technical Specifications + +### Configuration Schema + +```yaml +# etc/attestor.yaml +attestor: + bundling: + enabled: true + schedule: + # Monthly on the 1st at 02:00 UTC + cron: "0 2 1 * *" + # Or explicit cadence + cadence: "monthly" # "weekly" | "monthly" | "quarterly" + aggregation: + # Look back period for attestations + lookbackDays: 31 + # Maximum attestations per bundle + maxAttestationsPerBundle: 10000 + # Batch size for database queries + queryBatchSize: 500 + signing: + # Sign bundles with organization key + signWithOrgKey: true + orgKeyId: "org-signing-key-2025" + # Key rotation: use new key starting from date + keyRotation: + - keyId: "org-signing-key-2024" + validUntil: "2024-12-31T23:59:59Z" + - keyId: "org-signing-key-2025" + validFrom: "2025-01-01T00:00:00Z" + retention: + # Default retention period in months + defaultMonths: 24 + # Per-tenant overrides + tenantOverrides: + "tenant-gov": 84 # 7 years for government + "tenant-finance": 120 # 10 years for finance + storage: + # Bundle storage location + backend: "s3" # "s3" | "filesystem" + s3: + bucket: "stellaops-attestor" + prefix: "bundles/" + objectLock: "governance" # WORM protection + filesystem: + path: "/var/lib/stellaops/attestor/bundles" + export: + # Include in Offline Kit + includeInOfflineKit: true + # Compression for export + compression: "zstd" + compressionLevel: 3 +``` + +### API Endpoints + +```yaml +# Bundle Management API + +POST /api/v1/bundles: + description: Create a new attestation bundle + request: + periodStart: "2025-12-01T00:00:00Z" + periodEnd: "2025-12-31T23:59:59Z" + signWithOrgKey: true + orgKeyId: "org-signing-key-2025" + response: + bundleId: "sha256:abc123..." + status: "created" + attestationCount: 1542 + createdAt: "2025-12-26T02:00:00Z" + +GET /api/v1/bundles: + description: List bundles with pagination + query: + periodStart: "2025-01-01T00:00:00Z" + periodEnd: "2025-12-31T23:59:59Z" + limit: 20 + cursor: "..." + response: + bundles: [{ bundleId, periodStart, periodEnd, attestationCount, createdAt }] + nextCursor: "..." + +GET /api/v1/bundles/{bundleId}: + description: Get bundle metadata + response: + bundleId: "sha256:abc123..." + version: "1.0" + periodStart: "2025-12-01T00:00:00Z" + periodEnd: "2025-12-31T23:59:59Z" + attestationCount: 1542 + merkleRoot: "sha256:..." + orgSignature: { keyId, signedAt } + createdAt: "2025-12-26T02:00:00Z" + +GET /api/v1/bundles/{bundleId}/download: + description: Download full bundle (JSON or CBOR) + query: + format: "json" # "json" | "cbor" + compression: "zstd" # "none" | "gzip" | "zstd" + response: + Content-Type: application/json+zstd + Content-Disposition: attachment; filename="bundle-sha256-abc123.json.zst" + +GET /api/v1/bundles/{bundleId}/attestations/{entryId}: + description: Get specific attestation from bundle + response: + entryId: "uuid-1" + rekorUuid: "24296fb2..." + envelope: { ... } + inclusionProof: { ... } + +POST /api/v1/bundles/{bundleId}/verify: + description: Verify bundle integrity and signatures + response: + valid: true + merkleRootVerified: true + orgSignatureVerified: true + attestationsVerified: 1542 + verifiedAt: "2025-12-26T10:00:00Z" +``` + +### Bundle JSON Schema + +```json +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://stella-ops.org/schemas/attestation-bundle/v1", + "type": "object", + "required": ["metadata", "attestations", "merkleTree"], + "properties": { + "metadata": { + "type": "object", + "required": ["bundleId", "version", "createdAt", "periodStart", "periodEnd", "attestationCount"], + "properties": { + "bundleId": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" }, + "version": { "type": "string", "const": "1.0" }, + "createdAt": { "type": "string", "format": "date-time" }, + "periodStart": { "type": "string", "format": "date-time" }, + "periodEnd": { "type": "string", "format": "date-time" }, + "attestationCount": { "type": "integer", "minimum": 0 }, + "orgKeyFingerprint": { "type": "string" } + } + }, + "attestations": { + "type": "array", + "items": { "$ref": "#/$defs/bundledAttestation" } + }, + "merkleTree": { + "type": "object", + "required": ["algorithm", "root", "leafCount"], + "properties": { + "algorithm": { "type": "string", "enum": ["SHA256"] }, + "root": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" }, + "leafCount": { "type": "integer", "minimum": 0 } + } + }, + "orgSignature": { "$ref": "#/$defs/orgSignature" } + }, + "$defs": { + "bundledAttestation": { + "type": "object", + "required": ["entryId", "rekorUuid", "artifactDigest", "predicateType", "signedAt", "signingMode", "inclusionProof", "envelope"] + }, + "orgSignature": { + "type": "object", + "required": ["keyId", "algorithm", "signature", "signedAt"], + "properties": { + "keyId": { "type": "string" }, + "algorithm": { "type": "string", "enum": ["ECDSA_P256", "Ed25519", "RSA_PSS_SHA256"] }, + "signature": { "type": "string" }, + "signedAt": { "type": "string", "format": "date-time" }, + "certificateChain": { "type": "array", "items": { "type": "string" } } + } + } + } +} +``` + +### Metrics + +```csharp +// Prometheus metrics +attestor.bundle.created_total{tenant,signed} +attestor.bundle.creation_duration_seconds{quantile} +attestor.bundle.attestations_count{bundle_id} +attestor.bundle.size_bytes{bundle_id,format} +attestor.bundle.retention_deleted_total{tenant} +attestor.bundle.verification_total{result="valid|invalid|error"} +attestor.bundle.download_total{format="json|cbor",compression} +``` + +--- + +## Testing Requirements + +### Unit Test Coverage + +| Component | Test File | Coverage Target | +|-----------|-----------|-----------------| +| BundleAggregator | `BundleAggregatorTests.cs` | 100% | +| MerkleTreeBuilder | `MerkleTreeBuilderTests.cs` | 100% | +| AttestationBundler | `AttestationBundlerTests.cs` | 95% | +| KmsOrgKeySigner | `KmsOrgKeySignerTests.cs` | 95% | +| BundleRetentionPolicy | `BundleRetentionPolicyTests.cs` | 100% | + +### Determinism Tests + +```csharp +[Fact] +public async Task Bundle_SameAttestations_ShuffledOrder_SameMerkleRoot() +{ + // Arrange: Create attestations in random order + var attestations = GenerateAttestations(100); + var shuffled1 = attestations.OrderBy(_ => Guid.NewGuid()).ToList(); + var shuffled2 = attestations.OrderBy(_ => Guid.NewGuid()).ToList(); + + // Act: Create bundles + var bundle1 = await bundler.CreateBundleAsync(shuffled1); + var bundle2 = await bundler.CreateBundleAsync(shuffled2); + + // Assert: Same Merkle root + Assert.Equal(bundle1.MerkleTree.Root, bundle2.MerkleTree.Root); + Assert.Equal(bundle1.BundleId, bundle2.BundleId); +} + +[Fact] +public async Task Bundle_Serialization_Roundtrip_Identical() +{ + // Arrange + var bundle = await CreateTestBundle(); + + // Act + var json1 = Serialize(bundle); + var deserialized = Deserialize(json1); + var json2 = Serialize(deserialized); + + // Assert: Byte-for-byte identical + Assert.Equal(json1, json2); +} +``` + +### Integration Tests + +```csharp +[Fact] +public async Task BundleRotationJob_ExecutesMonthly_CreatesBundle() +{ + // Arrange: Populate attestor.entries with test data + // Act: Trigger scheduler job + // Assert: Bundle created with correct date range +} + +[Fact] +public async Task BundleRetention_ExpiredBundles_Deleted() +{ + // Arrange: Create bundles with old dates + // Act: Run retention enforcement + // Assert: Bundles beyond retention deleted +} + +[Fact] +public async Task BundleOrgSigning_KmsBackend_SignsAndVerifies() +{ + // Arrange: Configure KMS org key + // Act: Create signed bundle + // Assert: Org signature valid, certificate chain present +} +``` + +--- + +## Decisions & Risks + +| ID | Decision/Risk | Status | Owner | Notes | +|----|---------------|--------|-------|-------| +| D001 | Monthly as default bundle cadence | DECIDED | β€” | Balance between overhead and granularity | +| D002 | SHA-256 for Merkle tree | DECIDED | β€” | Consistent with Rekor, industry standard | +| D003 | CBOR as optional compact format | DECIDED | β€” | ~40% smaller than JSON for transport | +| D004 | 24-month default retention | DECIDED | β€” | Covers most compliance requirements | +| R001 | Large bundle sizes for high-volume tenants | OPEN | β€” | Mitigate with pagination, streaming export | +| R002 | Org key compromise | OPEN | β€” | Use HSM, implement key rotation | +| R003 | S3 storage costs | OPEN | β€” | Enable lifecycle policies, intelligent tiering | + +--- + +## Upcoming Checkpoints + +| Date | Milestone | Exit Criteria | +|------|-----------|---------------| +| +3 days | Core data model complete | 0001-0002 DONE | +| +7 days | Aggregation and Merkle tree | 0003-0005 DONE | +| +10 days | Org signing integrated | 0006-0008 DONE | +| +14 days | API endpoints working | 0009-0012 DONE | +| +18 days | Scheduler job complete | 0013-0017 DONE | +| +21 days | Full test coverage | 0018-0024 DONE | +| +23 days | Documentation complete | 0025-0026 DONE, sprint DONE | + +--- + +## Execution Log + +| Date | Role | Action | Notes | +|------|------|--------|-------| +| 2025-12-26 | PM | Sprint created | Initial planning from keyless signing advisory | + +--- + +## Related Documents + +- **Parent Advisory:** `docs/product-advisories/25-Dec-2025 - Planning Keyless Signing for Verdicts.md` +- **Predecessor Sprint:** `SPRINT_20251226_001_SIGNER_fulcio_keyless_client.md` +- **Attestor Architecture:** `docs/modules/attestor/architecture.md` +- **Offline Kit:** `docs/24_OFFLINE_KIT.md` +- **Successor Sprint:** `SPRINT_20251226_003_ATTESTOR_offline_verification.md` + +--- + +*End of Sprint Document* diff --git a/docs/implplan/SPRINT_20251226_002_BE_budget_enforcement.md b/docs/implplan/SPRINT_20251226_002_BE_budget_enforcement.md new file mode 100644 index 000000000..1d96766ae --- /dev/null +++ b/docs/implplan/SPRINT_20251226_002_BE_budget_enforcement.md @@ -0,0 +1,51 @@ +# Sprint 20251226 Β· Risk Budget Enforcement Automation + +## Topic & Scope +- Operationalize the existing `RiskBudget` model with automated window management, consumption tracking, and notifications. +- Implement budget ledger persistence, threshold alerts, and CLI commands. +- Enable earned capacity replenishment based on performance metrics. +- **Working directory:** `src/Policy/StellaOps.Policy.Engine`, `src/Notify/StellaOps.Notify` + +## Dependencies & Concurrency +- Depends on: `RiskBudget.cs` (complete), `RiskPointScoring.cs` (complete), `DeltaVerdict` (complete). +- Depends on: SPRINT_20251226_001_BE (gate integration provides consumption trigger). +- Can run in parallel with: SPRINT_20251226_003_BE (exception workflow). + +## Documentation Prerequisites +- `docs/modules/policy/architecture.md` +- `docs/modules/policy/budget-attestation.md` +- `docs/modules/notify/architecture.md` +- `docs/product-advisories/archived/2025-12-21-moat-phase2/20-Dec-2025 - Moat Explanation - Risk Budgets and Diff-Aware Release Gates.md` + +## Delivery Tracker +| # | Task ID | Status | Key dependency / next step | Owners | Task Definition | +| --- | --- | --- | --- | --- | --- | +| 1 | BUDGET-01 | TODO | None | Policy Guild | Create `budget_ledger` PostgreSQL table: budget_id, service_id, tenant_id, tier, window, allocated, consumed, status, created_at, updated_at | +| 2 | BUDGET-02 | TODO | BUDGET-01 | Policy Guild | Implement `BudgetLedgerRepository` with CRUD + consumption recording | +| 3 | BUDGET-03 | TODO | BUDGET-02 | Policy Guild | Budget window management: monthly reset logic, window boundary detection, carry-over rules (none by default) | +| 4 | BUDGET-04 | TODO | BUDGET-02 | Policy Guild | Budget consumption API: `POST /api/v1/policy/budget/consume` called after gate verdict; updates ledger | +| 5 | BUDGET-05 | TODO | BUDGET-03 | Policy Guild | Threshold status computation: Green (<40%), Yellow (40-69%), Red (70-99%), Exhausted (>=100%) | +| 6 | BUDGET-06 | TODO | BUDGET-05 | Notify Guild | Budget threshold notifications: trigger alerts on Yellow/Red/Exhausted transitions | +| 7 | BUDGET-07 | TODO | BUDGET-06 | Notify Guild | Notification templates for budget alerts (Email, Slack, Teams) | +| 8 | BUDGET-08 | TODO | BUDGET-04 | Policy Guild | CLI command `stella budget status --service ` showing current budget state | +| 9 | BUDGET-09 | TODO | BUDGET-04 | Policy Guild | CLI command `stella budget consume --service --points --reason ` for manual adjustments | +| 10 | BUDGET-10 | TODO | BUDGET-05 | Policy Guild | Earned capacity replenishment: if MTTR/CFR improves for 2 windows, grant +10-20% budget increase | +| 11 | BUDGET-11 | TODO | BUDGET-10 | Policy Guild | Integration tests: window reset, consumption, threshold transitions, notifications | +| 12 | BUDGET-12 | TODO | BUDGET-11 | Policy Guild | Documentation: update `docs/modules/policy/budget-attestation.md` with enforcement section | + +## Execution Log +| Date (UTC) | Update | Owner | +| --- | --- | --- | +| 2025-12-26 | Sprint created from product advisory analysis; implements risk budget enforcement from moat advisory. | Project Mgmt | + +## Decisions & Risks +- Decision needed: Budget window period - monthly vs sprint-aligned. Recommend: monthly with weekly tracking. +- Decision needed: Budget carry-over between windows. Recommend: no carry-over (use it or lose it). +- Decision needed: Exhausted budget behavior - hard block or soft warn. Recommend: block high-risk (G3+), warn low-risk. +- Risk: Budget gaming via artificial low-point releases. Mitigation: minimum RP floor of 1 per release. +- Risk: Notification fatigue. Mitigation: configurable alert thresholds, aggregation windows. + +## Next Checkpoints +- 2025-12-30 | BUDGET-03 complete | Window management logic verified | +- 2026-01-03 | BUDGET-06 complete | Notifications wired to Notify | +- 2026-01-06 | BUDGET-11 complete | Full integration tested | diff --git a/docs/implplan/SPRINT_20251226_003_ATTESTOR_offline_verification.md b/docs/implplan/SPRINT_20251226_003_ATTESTOR_offline_verification.md new file mode 100644 index 000000000..85ef1fcc2 --- /dev/null +++ b/docs/implplan/SPRINT_20251226_003_ATTESTOR_offline_verification.md @@ -0,0 +1,626 @@ +# SPRINT_20251226_003_ATTESTOR_offline_verification + +**Sprint ID:** 20251226_003_ATTESTOR +**Topic:** Offline/Air-Gapped Attestation Verification +**Status:** TODO +**Priority:** P2 (Medium-High) +**Created:** 2025-12-26 +**Working Directory:** `src/Attestor/`, `src/Cli/` + +--- + +## Executive Summary + +Implement offline verification capabilities for keyless-signed attestations. This enables air-gapped environments to verify attestations using bundled Rekor inclusion proofs and Fulcio root certificates without network connectivity. Essential for sovereign, defense, and regulated environments. + +**Business Value:** +- Enables attestation verification in air-gapped/disconnected networks +- Supports regulatory compliance requiring offline audit capabilities +- Reduces network dependencies for high-security environments +- Completes the keyless signing story for sovereign customers + +**Dependencies:** +- Sprint 20251226_001 (Keyless signing client) +- Sprint 20251226_002 (Bundle rotation) +- Existing Offline Kit infrastructure (`docs/24_OFFLINE_KIT.md`) + +--- + +## Prerequisites + +**Required Reading (complete before DOING):** +- [ ] `docs/24_OFFLINE_KIT.md` - Offline Update Kit specification +- [ ] `docs/modules/attestor/architecture.md` - Attestor architecture (Β§ Offline Mode) +- [ ] `src/Attestor/AGENTS.md` - Module charter +- [ ] `src/Cli/AGENTS.md` - CLI module charter (if exists) +- [ ] `CLAUDE.md` - Project coding standards + +**Technical Prerequisites:** +- [ ] Bundle rotation working (Sprint 002) +- [ ] Fulcio root certificates bundled +- [ ] CLI infrastructure for new commands + +--- + +## Scope & Boundaries + +### In Scope +- Offline verification service implementation +- Bundled Fulcio roots in Offline Kit +- CLI commands for offline verification +- Bundle export command +- Verification without network connectivity +- Air-gap verification playbook documentation + +### Out of Scope +- Initial keyless signing (Sprint 001) +- Bundle creation (Sprint 002) +- CI/CD templates (Sprint 004) + +### Guardrails +- Verification MUST work completely offline once materials are imported +- No network calls during offline verification mode +- Verification results MUST be deterministic +- Support both JSON and CBOR bundle formats + +--- + +## Architecture + +### Offline Verification Flow + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Air-Gapped Environment β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Offline Kit β”‚ β”‚ Bundle Store β”‚ β”‚ Fulcio Roots β”‚ β”‚ +β”‚ β”‚ (imported) │───▢│ (local) β”‚ β”‚ (bundled) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β–Ό β–Ό β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ OfflineVerificationService β”‚ β”‚ +β”‚ β”‚ - Load bundle from local store β”‚ β”‚ +β”‚ β”‚ - Verify Merkle inclusion β”‚ β”‚ +β”‚ β”‚ - Verify DSSE signatures β”‚ β”‚ +β”‚ β”‚ - Validate certificate chains β”‚ β”‚ +β”‚ β”‚ - Check org signature (if present) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ +β”‚ β–Ό β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ VerificationResult β”‚ β”‚ +β”‚ β”‚ - attestationValid: true/false β”‚ β”‚ +β”‚ β”‚ - merkleProofValid: true/false β”‚ β”‚ +β”‚ β”‚ - signatureValid: true/false β”‚ β”‚ +β”‚ β”‚ - certificateChainValid: true/false β”‚ β”‚ +β”‚ β”‚ - orgSignatureValid: true/false β”‚ β”‚ +β”‚ β”‚ - verifiedAt: timestamp β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ CLI Interface: β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ $ stella attest verify --offline --bundle /path/to/bundle β”‚ β”‚ +β”‚ β”‚ $ stella attest verify --offline --artifact sha256:... β”‚ β”‚ +β”‚ β”‚ $ stella attest export-bundle --image sha256:... -o ./ β”‚ β”‚ +β”‚ β”‚ $ stella attest import-roots --path /path/to/fulcio.pem β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Components + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Attestor Service β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ Existing Components: β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ IAttestorVerifica- β”‚ β”‚ MerkleProofVerifierβ”‚ β”‚ +β”‚ β”‚ tionService β”‚ β”‚ (existing) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ New Components: β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ IOfflineVerifier β”‚ β”‚ IOfflineRootStore β”‚ β”‚ +β”‚ β”‚ (NEW) β”‚ β”‚ (NEW) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β–Ό β–Ό β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ OfflineVerifier β”‚ β”‚ FileSystemRoot β”‚ β”‚ +β”‚ β”‚ Impl β”‚ β”‚ Store β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ CLI Module β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ AttestCommands β”‚ β”‚ +β”‚ β”‚ - VerifyCommand (--offline flag) β”‚ β”‚ +β”‚ β”‚ - ExportBundleCommand β”‚ β”‚ +β”‚ β”‚ - ImportRootsCommand β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### New Interfaces + +```csharp +// src/Attestor/__Libraries/StellaOps.Attestor.Offline/IOfflineVerifier.cs + +public interface IOfflineVerifier +{ + Task VerifyBundleAsync( + AttestationBundle bundle, + OfflineVerificationOptions options, + CancellationToken cancellationToken = default); + + Task VerifyAttestationAsync( + BundledAttestation attestation, + OfflineVerificationOptions options, + CancellationToken cancellationToken = default); + + Task VerifyByArtifactAsync( + string artifactDigest, + string bundlePath, + OfflineVerificationOptions options, + CancellationToken cancellationToken = default); +} + +public record OfflineVerificationOptions( + bool VerifyMerkleProof = true, + bool VerifySignatures = true, + bool VerifyCertificateChain = true, + bool VerifyOrgSignature = true, + bool RequireOrgSignature = false, + string? FulcioRootPath = null, + string? OrgKeyPath = null, + bool StrictMode = false); + +public record OfflineVerificationResult( + bool Valid, + bool MerkleProofValid, + bool SignaturesValid, + bool CertificateChainValid, + bool OrgSignatureValid, + string? OrgSignatureKeyId, + DateTimeOffset VerifiedAt, + IReadOnlyList Issues); + +public record VerificationIssue( + VerificationIssueSeverity Severity, + string Code, + string Message, + string? AttestationId); + +public enum VerificationIssueSeverity { Info, Warning, Error, Critical } +``` + +```csharp +// src/Attestor/__Libraries/StellaOps.Attestor.Offline/IOfflineRootStore.cs + +public interface IOfflineRootStore +{ + Task GetFulcioRootsAsync( + CancellationToken cancellationToken = default); + + Task GetOrgSigningKeysAsync( + CancellationToken cancellationToken = default); + + Task ImportRootsAsync( + string pemPath, + RootType rootType, + CancellationToken cancellationToken = default); +} + +public enum RootType { Fulcio, OrgSigning, Rekor } +``` + +--- + +## Delivery Tracker + +| ID | Task | Owner | Status | Dependencies | Acceptance Criteria | +|----|------|-------|--------|--------------|---------------------| +| 0001 | Create `StellaOps.Attestor.Offline` library project | β€” | TODO | β€” | Project compiles, referenced by Attestor | +| 0002 | Define `OfflineVerificationResult` and options | β€” | TODO | 0001 | Comprehensive result model | +| 0003 | Implement `IOfflineRootStore` interface | β€” | TODO | 0001 | Contract for root certificate access | +| 0004 | Implement `FileSystemRootStore` | β€” | TODO | 0003 | Reads roots from configured paths | +| 0005 | Implement `IOfflineVerifier` interface | β€” | TODO | 0002, 0004 | Core verification contract | +| 0006 | Implement `OfflineVerifier` service | β€” | TODO | 0005 | Full offline verification logic | +| 0007 | Add Merkle proof verification for bundles | β€” | TODO | 0006 | Verify attestation in bundle tree | +| 0008 | Add DSSE signature verification (offline) | β€” | TODO | 0006 | Verify without network | +| 0009 | Add certificate chain validation (offline) | β€” | TODO | 0006, 0004 | Validate to bundled Fulcio roots | +| 0010 | Add org signature verification | β€” | TODO | 0006, 0004 | Verify org-key signature if present | +| 0011 | Bundle Fulcio roots in Offline Kit | β€” | TODO | β€” | Update OUK packaging script | +| 0012 | Add Rekor checkpoint bundle support | β€” | TODO | β€” | Optional bundled checkpoints | +| 0013 | CLI: Add `stella attest verify --offline` | β€” | TODO | 0006 | Offline verification command | +| 0014 | CLI: Add `--bundle` flag for local bundle | β€” | TODO | 0013 | Specify bundle path | +| 0015 | CLI: Add `--artifact` flag for artifact lookup | β€” | TODO | 0013 | Find attestation by digest | +| 0016 | CLI: Add `stella attest export-bundle` | β€” | TODO | Sprint 002 | Export bundle for transport | +| 0017 | CLI: Add `stella attest import-roots` | β€” | TODO | 0004 | Import root certificates | +| 0018 | CLI: Add verification result formatting | β€” | TODO | 0013 | Human-readable and JSON output | +| 0019 | Unit tests: FileSystemRootStore | β€” | TODO | 0004 | Root loading, PEM parsing | +| 0020 | Unit tests: OfflineVerifier | β€” | TODO | 0006 | All verification paths | +| 0021 | Unit tests: Merkle proof verification | β€” | TODO | 0007 | Valid/invalid proofs | +| 0022 | Unit tests: Certificate chain validation | β€” | TODO | 0009 | Valid/expired/untrusted | +| 0023 | Integration test: Full offline verification | β€” | TODO | 0006 | No network calls made | +| 0024 | Integration test: CLI offline verify | β€” | TODO | 0013 | End-to-end CLI test | +| 0025 | Integration test: Offline Kit import + verify | β€” | TODO | 0011 | Complete air-gap flow | +| 0026 | Documentation: Air-gap verification playbook | β€” | TODO | 0013 | `docs/airgap/attestation-verification.md` | +| 0027 | Documentation: CLI attest commands | β€” | TODO | 0013 | `docs/modules/cli/guides/commands/attest.md` | +| 0028 | Update Offline Kit documentation | β€” | TODO | 0011 | Add attestation bundle section | + +--- + +## Technical Specifications + +### Configuration Schema + +```yaml +# etc/attestor.yaml +attestor: + offline: + enabled: true + roots: + # Fulcio root certificates for keyless verification + fulcio: + bundlePath: "/etc/stellaops/roots/fulcio-roots.pem" + # Alternative: embedded in Offline Kit + useOfflineKit: true + offlineKitPath: "/var/lib/stellaops/offline-kit/roots" + # Organization signing keys for bundle verification + orgSigning: + bundlePath: "/etc/stellaops/roots/org-signing.pem" + keyIds: + - "org-signing-key-2024" + - "org-signing-key-2025" + # Rekor checkpoints (optional, for additional verification) + rekorCheckpoints: + enabled: false + bundlePath: "/etc/stellaops/roots/rekor-checkpoints.json" + verification: + # Strict mode: all checks must pass + strictMode: false + # Require org signature on bundles + requireOrgSignature: false + # Allow verification of individual attestations without bundle + allowUnbundled: true + storage: + # Local bundle cache + bundleCachePath: "/var/lib/stellaops/attestor/bundle-cache" + # Maximum cache size + maxCacheSizeMb: 1024 +``` + +### CLI Commands + +```bash +# Verify attestation offline using local bundle +stella attest verify --offline \ + --bundle /path/to/bundle.json \ + --artifact sha256:abc123... + +# Output: +# Verification Result: +# ──────────────────────────────────────────── +# Artifact: sha256:abc123... +# Bundle: sha256:def456... (2025-12-01 to 2025-12-31) +# Status: βœ… VALID +# +# Checks: +# βœ… Merkle Proof: Valid (leaf 42 of 1542) +# βœ… DSSE Signature: Valid (ECDSA_P256) +# βœ… Certificate Chain: Valid (Fulcio β†’ Sigstore Root) +# βœ… Org Signature: Valid (org-signing-key-2025) +# +# Signing Identity: +# Issuer: https://authority.internal +# Subject: signer@stella-ops.org +# SAN: urn:stellaops:signer +# +# Verified At: 2025-12-26T10:30:00Z + +# Verify with JSON output +stella attest verify --offline \ + --bundle /path/to/bundle.json \ + --artifact sha256:abc123... \ + --output json + +# Export bundle for transport to air-gapped environment +stella attest export-bundle \ + --image sha256:abc123... \ + --period-start 2025-12-01 \ + --period-end 2025-12-31 \ + --include-roots \ + --output /mnt/usb/attestation-bundle.json.zst + +# Import Fulcio roots into local store +stella attest import-roots \ + --path /mnt/usb/fulcio-roots.pem \ + --type fulcio + +# List available bundles +stella attest list-bundles \ + --local-only \ + --format table +``` + +### Verification Algorithm + +```csharp +public async Task VerifyBundleAsync( + AttestationBundle bundle, + OfflineVerificationOptions options, + CancellationToken cancellationToken) +{ + var issues = new List(); + + // 1. Verify bundle Merkle root + var merkleValid = VerifyMerkleTree(bundle); + if (!merkleValid) + { + issues.Add(new(Critical, "MERKLE_INVALID", "Bundle Merkle root mismatch")); + } + + // 2. Verify org signature (if present and required) + var orgSigValid = true; + if (bundle.OrgSignature != null) + { + orgSigValid = await VerifyOrgSignatureAsync(bundle, options); + if (!orgSigValid) + { + issues.Add(new(Critical, "ORG_SIG_INVALID", "Organization signature invalid")); + } + } + else if (options.RequireOrgSignature) + { + issues.Add(new(Critical, "ORG_SIG_MISSING", "Required org signature missing")); + orgSigValid = false; + } + + // 3. Verify each attestation + var signaturesValid = true; + var certsValid = true; + foreach (var attestation in bundle.Attestations) + { + // 3a. Verify Merkle inclusion + var inBundle = VerifyMerkleInclusion(attestation, bundle.MerkleTree); + if (!inBundle) + { + issues.Add(new(Critical, "MERKLE_INCLUSION", + $"Attestation {attestation.EntryId} not in Merkle tree")); + } + + // 3b. Verify DSSE signature + var sigValid = VerifyDsseSignature(attestation.Envelope); + if (!sigValid) + { + signaturesValid = false; + issues.Add(new(Critical, "DSSE_SIG_INVALID", + $"Invalid signature on {attestation.EntryId}")); + } + + // 3c. Verify certificate chain (offline) + if (options.VerifyCertificateChain) + { + var roots = await _rootStore.GetFulcioRootsAsync(cancellationToken); + var chainValid = VerifyCertificateChain( + attestation.Envelope.CertificateChain, roots); + if (!chainValid) + { + certsValid = false; + issues.Add(new(Critical, "CERT_CHAIN_INVALID", + $"Invalid cert chain on {attestation.EntryId}")); + } + } + + // 3d. Verify Rekor inclusion proof (optional) + if (attestation.InclusionProof != null && options.VerifyMerkleProof) + { + var proofValid = VerifyRekorInclusionProof( + attestation.Envelope, attestation.InclusionProof); + if (!proofValid) + { + issues.Add(new(Warning, "REKOR_PROOF_INVALID", + $"Invalid Rekor proof on {attestation.EntryId}")); + } + } + } + + var valid = merkleValid && signaturesValid && certsValid && orgSigValid; + + return new OfflineVerificationResult( + Valid: valid, + MerkleProofValid: merkleValid, + SignaturesValid: signaturesValid, + CertificateChainValid: certsValid, + OrgSignatureValid: orgSigValid, + OrgSignatureKeyId: bundle.OrgSignature?.KeyId, + VerifiedAt: DateTimeOffset.UtcNow, + Issues: issues); +} +``` + +### Offline Kit Integration + +```yaml +# Offline Kit structure for attestations + +/offline-kit/ +β”œβ”€β”€ attestations/ +β”‚ β”œβ”€β”€ bundles/ +β”‚ β”‚ β”œβ”€β”€ bundle-2025-11.json.zst +β”‚ β”‚ β”œβ”€β”€ bundle-2025-12.json.zst +β”‚ β”‚ └── manifest.json # Bundle inventory +β”‚ └── roots/ +β”‚ β”œβ”€β”€ fulcio-roots.pem # Fulcio root certificates +β”‚ β”œβ”€β”€ sigstore-root.pem # Sigstore TUF root +β”‚ β”œβ”€β”€ org-signing-2024.pem # Org signing key 2024 +β”‚ β”œβ”€β”€ org-signing-2025.pem # Org signing key 2025 +β”‚ └── rekor-checkpoints.json # Optional Rekor checkpoints +β”œβ”€β”€ ... +``` + +### Metrics + +```csharp +// Prometheus metrics +attestor.offline.verify_total{result="valid|invalid|error",mode="bundle|single"} +attestor.offline.verify_duration_seconds{quantile} +attestor.offline.issues_total{severity="info|warning|error|critical",code} +attestor.offline.roots_loaded_total{type="fulcio|org|rekor"} +cli.attest.verify.offline_total{result} +cli.attest.export_bundle_total{result} +``` + +--- + +## Testing Requirements + +### Unit Test Coverage + +| Component | Test File | Coverage Target | +|-----------|-----------|-----------------| +| FileSystemRootStore | `FileSystemRootStoreTests.cs` | 100% | +| OfflineVerifier | `OfflineVerifierTests.cs` | 95% | +| MerkleInclusionVerifier | `MerkleInclusionVerifierTests.cs` | 100% | +| CertificateChainValidator | `OfflineCertChainValidatorTests.cs` | 100% | + +### Network Isolation Tests + +```csharp +[Fact] +public async Task OfflineVerification_NoNetworkCalls_WhenOfflineModeEnabled() +{ + // Arrange: Configure network monitor + var networkMonitor = new NetworkCallMonitor(); + var verifier = CreateOfflineVerifier(networkMonitor); + var bundle = LoadTestBundle(); + + // Act + var result = await verifier.VerifyBundleAsync(bundle, new OfflineVerificationOptions()); + + // Assert: Zero network calls made + Assert.Equal(0, networkMonitor.CallCount); + Assert.True(result.Valid); +} + +[Fact] +public async Task OfflineVerification_SucceedsWithBundledRoots() +{ + // Arrange: Import roots from Offline Kit + await ImportRootsFromOfflineKit(); + var bundle = LoadTestBundle(); + + // Act: Disconnect network (mock) + DisableNetwork(); + var result = await verifier.VerifyBundleAsync(bundle, new OfflineVerificationOptions()); + + // Assert + Assert.True(result.Valid); + Assert.True(result.CertificateChainValid); +} +``` + +### CLI Tests + +```csharp +[Fact] +public async Task CLI_VerifyOffline_ValidBundle_ReturnsSuccess() +{ + // Arrange + var bundlePath = CreateTestBundle(); + var artifactDigest = "sha256:abc123..."; + + // Act + var result = await RunCli( + "attest", "verify", "--offline", + "--bundle", bundlePath, + "--artifact", artifactDigest); + + // Assert + Assert.Equal(0, result.ExitCode); + Assert.Contains("VALID", result.Output); +} + +[Fact] +public async Task CLI_ExportBundle_CreatesValidBundle() +{ + // Arrange + var outputPath = GetTempFilePath(); + + // Act + var result = await RunCli( + "attest", "export-bundle", + "--image", "sha256:abc123...", + "--include-roots", + "--output", outputPath); + + // Assert + Assert.Equal(0, result.ExitCode); + Assert.True(File.Exists(outputPath)); + + // Verify exported bundle is valid + var bundle = LoadBundle(outputPath); + Assert.NotNull(bundle); + Assert.True(bundle.Attestations.Count > 0); +} +``` + +--- + +## Decisions & Risks + +| ID | Decision/Risk | Status | Owner | Notes | +|----|---------------|--------|-------|-------| +| D001 | Bundle Fulcio roots in Offline Kit | DECIDED | β€” | Essential for air-gap verification | +| D002 | Support both JSON and CBOR formats | DECIDED | β€” | JSON for debugging, CBOR for size | +| D003 | Org signature optional by default | DECIDED | β€” | Strict mode requires it | +| R001 | Root certificate rotation | OPEN | β€” | Need update mechanism for bundled roots | +| R002 | Bundle size for long periods | OPEN | β€” | Pagination, streaming decompression | +| R003 | Clock skew in air-gapped env | OPEN | β€” | Document time sync requirements | + +--- + +## Upcoming Checkpoints + +| Date | Milestone | Exit Criteria | +|------|-----------|---------------| +| +3 days | Core interfaces complete | 0001-0005 DONE | +| +7 days | Verification logic working | 0006-0010 DONE | +| +10 days | Offline Kit integration | 0011-0012 DONE | +| +14 days | CLI commands complete | 0013-0018 DONE | +| +18 days | Full test coverage | 0019-0025 DONE | +| +20 days | Documentation complete | 0026-0028 DONE, sprint DONE | + +--- + +## Execution Log + +| Date | Role | Action | Notes | +|------|------|--------|-------| +| 2025-12-26 | PM | Sprint created | Initial planning from keyless signing advisory | + +--- + +## Related Documents + +- **Parent Advisory:** `docs/product-advisories/25-Dec-2025 - Planning Keyless Signing for Verdicts.md` +- **Predecessor Sprints:** + - `SPRINT_20251226_001_SIGNER_fulcio_keyless_client.md` + - `SPRINT_20251226_002_ATTESTOR_bundle_rotation.md` +- **Offline Kit:** `docs/24_OFFLINE_KIT.md` +- **Attestor Architecture:** `docs/modules/attestor/architecture.md` +- **Successor Sprint:** `SPRINT_20251226_004_BE_cicd_signing_templates.md` + +--- + +*End of Sprint Document* diff --git a/docs/implplan/SPRINT_20251226_003_BE_exception_approval.md b/docs/implplan/SPRINT_20251226_003_BE_exception_approval.md new file mode 100644 index 000000000..d38c2b673 --- /dev/null +++ b/docs/implplan/SPRINT_20251226_003_BE_exception_approval.md @@ -0,0 +1,60 @@ +# Sprint 20251226 Β· Exception Approval Workflow + +## Topic & Scope +- Implement role-based exception approval workflows building on existing `ExceptionAdapter`. +- Add approval request entity, time-limited overrides, and comprehensive audit trails. +- Integrate with Authority for approver role enforcement. +- **Working directory:** `src/Policy/StellaOps.Policy.Engine`, `src/Authority/StellaOps.Authority` + +## Dependencies & Concurrency +- Depends on: `ExceptionAdapter.cs` (complete), `ExceptionLifecycleService` (complete). +- Depends on: SPRINT_20251226_001_BE (gate bypass requires approval workflow). +- Can run in parallel with: SPRINT_20251226_002_BE (budget enforcement). + +## Documentation Prerequisites +- `docs/modules/policy/architecture.md` +- `docs/modules/authority/architecture.md` +- `docs/product-advisories/26-Dec-2026 - Diff-Aware Releases and Auditable Exceptions.md` + +## Delivery Tracker +| # | Task ID | Status | Key dependency / next step | Owners | Task Definition | +| --- | --- | --- | --- | --- | --- | +| 1 | EXCEPT-01 | TODO | None | Policy Guild | Create `exception_approval_requests` PostgreSQL table: request_id, exception_id, requestor_id, approver_ids[], status, justification, evidence_refs[], created_at, expires_at | +| 2 | EXCEPT-02 | TODO | EXCEPT-01 | Policy Guild | Implement `ExceptionApprovalRepository` with request/approve/reject operations | +| 3 | EXCEPT-03 | TODO | EXCEPT-02 | Policy Guild | Approval rules engine: define required approvers by gate level (G1=1 peer, G2=code owner, G3+=DM+PM) | +| 4 | EXCEPT-04 | TODO | EXCEPT-03 | Authority Guild | Create `exception:approve` and `exception:request` scopes in Authority | +| 5 | EXCEPT-05 | TODO | EXCEPT-04 | Policy Guild | API endpoint `POST /api/v1/policy/exception/request` to initiate approval workflow | +| 6 | EXCEPT-06 | TODO | EXCEPT-04 | Policy Guild | API endpoint `POST /api/v1/policy/exception/{id}/approve` for approver action | +| 7 | EXCEPT-07 | TODO | EXCEPT-04 | Policy Guild | API endpoint `POST /api/v1/policy/exception/{id}/reject` for rejection with reason | +| 8 | EXCEPT-08 | TODO | EXCEPT-02 | Policy Guild | Time-limited overrides: max TTL enforcement (30d default), auto-expiry with notification | +| 9 | EXCEPT-09 | TODO | EXCEPT-06 | Policy Guild | Audit trail: log all approval actions with who/when/why/evidence to `exception_audit` table | +| 10 | EXCEPT-10 | TODO | EXCEPT-06 | Policy Guild | CLI command `stella exception request --cve --scope --reason --ttl ` | +| 11 | EXCEPT-11 | TODO | EXCEPT-06 | Policy Guild | CLI command `stella exception approve --request ` for approvers | +| 12 | EXCEPT-12 | TODO | EXCEPT-08 | Notify Guild | Approval request notifications to designated approvers | +| 13 | EXCEPT-13 | TODO | EXCEPT-08 | Notify Guild | Expiry warning notifications (7d, 1d before expiry) | +| 14 | EXCEPT-14 | TODO | EXCEPT-09 | Policy Guild | Integration tests: request/approve/reject flows, TTL enforcement, audit trail | +| 15 | EXCEPT-15 | TODO | EXCEPT-14 | Policy Guild | Documentation: add exception workflow section to policy architecture doc | +| 16 | EXCEPT-16 | TODO | EXCEPT-08 | Scheduler Guild | Auto-revalidation job: re-test exceptions on expiry, "fix available" feed signal, or EPSS increase | +| 17 | EXCEPT-17 | TODO | EXCEPT-16 | Policy Guild | Flip gate to "needs re-review" on revalidation failure with notification | +| 18 | EXCEPT-18 | TODO | EXCEPT-01 | Policy Guild | Exception inheritance: repoβ†’imageβ†’env scoping with explicit shadowing | +| 19 | EXCEPT-19 | TODO | EXCEPT-18 | Policy Guild | Conflict surfacing: detect and report shadowed exceptions in evaluation | +| 20 | EXCEPT-20 | TODO | EXCEPT-09 | Attestor Guild | OCI-attached exception attestation: store exception as `application/vnd.stellaops.exception+json` | +| 21 | EXCEPT-21 | TODO | EXCEPT-20 | Policy Guild | CLI command `stella exception export --id --format oci-attestation` | + +## Execution Log +| Date (UTC) | Update | Owner | +| --- | --- | --- | +| 2025-12-26 | Sprint created from product advisory analysis; implements auditable exceptions from diff-aware release gates advisory. | Project Mgmt | +| 2025-12-26 | Added EXCEPT-16 through EXCEPT-21 from "Diff-Aware Releases and Auditable Exceptions" advisory (auto-revalidation, inheritance, OCI attestation). Advisory marked SUPERSEDED. | Project Mgmt | + +## Decisions & Risks +- Decision needed: Can exceptions be self-approved for G1 level? Recommend: yes for G0-G1, no for G2+. +- Decision needed: Evidence requirement strictness. Recommend: mandatory for G2+, optional for G0-G1. +- Decision needed: Exception inheritance (repo -> image -> env). Recommend: explicit shadowing with conflict surfacing. +- Risk: Approval bottleneck slowing releases. Mitigation: parallel approval paths, escalation timeouts. +- Risk: Expired exceptions causing sudden build failures. Mitigation: 7d/1d expiry warnings, grace period option. + +## Next Checkpoints +- 2025-12-30 | EXCEPT-03 complete | Approval rules engine implemented | +- 2026-01-03 | EXCEPT-07 complete | All API endpoints functional | +- 2026-01-06 | EXCEPT-14 complete | Full workflow integration tested | diff --git a/docs/implplan/SPRINT_20251226_004_BE_cicd_signing_templates.md b/docs/implplan/SPRINT_20251226_004_BE_cicd_signing_templates.md new file mode 100644 index 000000000..d5673fac1 --- /dev/null +++ b/docs/implplan/SPRINT_20251226_004_BE_cicd_signing_templates.md @@ -0,0 +1,621 @@ +# SPRINT_20251226_004_BE_cicd_signing_templates + +**Sprint ID:** 20251226_004_BE +**Topic:** CI/CD Keyless Signing Integration Templates +**Status:** TODO +**Priority:** P2 (Medium) +**Created:** 2025-12-26 +**Working Directory:** `docs/`, `.gitea/workflows/`, `deploy/` + +--- + +## Executive Summary + +Create production-ready CI/CD templates for keyless signing integration. Provides GitHub Actions, GitLab CI, and Gitea workflow templates that enable zero-configuration keyless signing in pipelines using OIDC identity tokens. Includes identity verification policies and verification gate examples. + +**Business Value:** +- Accelerates customer adoption with ready-to-use templates +- Reduces integration friction (copy-paste to production) +- Establishes best practices for identity verification +- Demonstrates Sigstore integration patterns + +**Dependencies:** +- Sprint 20251226_001 (Keyless signing client) +- Sprint 20251226_002 (Bundle rotation) +- Sprint 20251226_003 (Offline verification) + +--- + +## Prerequisites + +**Required Reading (complete before DOING):** +- [ ] `docs/modules/signer/architecture.md` - Signer architecture +- [ ] `CLAUDE.md` - Project standards +- [ ] GitHub OIDC documentation: https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect +- [ ] GitLab OIDC documentation: https://docs.gitlab.com/ee/ci/secrets/id_token_authentication.html +- [ ] Sigstore cosign documentation: https://docs.sigstore.dev/cosign/signing/signing_with_containers/ + +**Technical Prerequisites:** +- [ ] Keyless signing operational (Sprint 001) +- [ ] Attestor bundle API available (Sprint 002) +- [ ] Verification endpoints working + +--- + +## Scope & Boundaries + +### In Scope +- GitHub Actions workflow template +- GitLab CI template +- Gitea workflow template (dogfooding) +- Identity constraint documentation +- Verification gate examples +- Integration guide documentation + +### Out of Scope +- Core signing implementation (Sprint 001) +- Bundle rotation (Sprint 002) +- Offline verification (Sprint 003) +- Jenkins, Azure DevOps, CircleCI templates (future) + +### Guardrails +- Templates MUST be copy-paste ready +- No hard-coded secrets in templates +- Identity constraints MUST be configurable +- Templates MUST handle errors gracefully + +--- + +## Architecture + +### OIDC Flow in CI/CD + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ CI/CD Pipeline β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Build Step │─────▢│ Sign Step │─────▢│ Verify Gate β”‚ β”‚ +β”‚ β”‚ - Build image β”‚ β”‚ - Get OIDC tok β”‚ β”‚ - Verify sig β”‚ β”‚ +β”‚ β”‚ - Generate SBOMβ”‚ β”‚ - Sign artifactβ”‚ β”‚ - Check policy β”‚ β”‚ +β”‚ β”‚ - Push to reg β”‚ β”‚ - Push attesta β”‚ β”‚ - Pass/Fail β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ β”‚ + β–Ό β–Ό β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ CI Platform β”‚ β”‚ Fulcio β”‚ β”‚ Rekor β”‚ + β”‚ OIDC Providerβ”‚ β”‚ (Sigstore) β”‚ β”‚ (Sigstore) β”‚ + β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ + β”‚ Issues token │────▢│ Issues cert │────▢│ Logs entry β”‚ + β”‚ with claims β”‚ β”‚ for identity β”‚ β”‚ transparency β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Identity Verification Matrix + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Identity Constraint Policy β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ GitHub Actions: β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Issuer: https://token.actions.githubusercontent.com β”‚ β”‚ +β”‚ β”‚ Subject: repo:org/repo:ref:refs/heads/main β”‚ β”‚ +β”‚ β”‚ OR repo:org/repo:environment:production β”‚ β”‚ +β”‚ β”‚ SAN: https://github.com/org/repo/.github/workflows/x.yml β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ GitLab CI: β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Issuer: https://gitlab.com β”‚ β”‚ +β”‚ β”‚ Subject: project_path:org/repo:ref_type:branch:ref:main β”‚ β”‚ +β”‚ β”‚ SAN: https://gitlab.com/org/repo β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ Gitea: β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Issuer: https://git.stella-ops.org β”‚ β”‚ +β”‚ β”‚ Subject: org/repo:ref:refs/heads/main β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +--- + +## Delivery Tracker + +| ID | Task | Owner | Status | Dependencies | Acceptance Criteria | +|----|------|-------|--------|--------------|---------------------| +| 0001 | Create GitHub Actions template directory | β€” | TODO | β€” | `.github/workflows/examples/` structure | +| 0002 | Implement `stellaops-sign.yml` reusable workflow | β€” | TODO | 0001 | Keyless signing for any artifact | +| 0003 | Implement `stellaops-verify.yml` reusable workflow | β€” | TODO | 0001 | Verification gate | +| 0004 | Create container signing example | β€” | TODO | 0002 | Sign + push OCI attestation | +| 0005 | Create SBOM signing example | β€” | TODO | 0002 | Sign SBOM, attach to image | +| 0006 | Create verdict signing example | β€” | TODO | 0002 | Sign policy verdict | +| 0007 | Create verification gate example | β€” | TODO | 0003 | Block deploy on invalid sig | +| 0008 | Create GitLab CI template directory | β€” | TODO | β€” | `deploy/gitlab/examples/` | +| 0009 | Implement `.gitlab-ci-stellaops.yml` template | β€” | TODO | 0008 | Include-able signing jobs | +| 0010 | Create GitLab signing job | β€” | TODO | 0009 | OIDC β†’ keyless sign | +| 0011 | Create GitLab verification job | β€” | TODO | 0009 | Verification gate | +| 0012 | Update Gitea workflows for dogfooding | β€” | TODO | β€” | `.gitea/workflows/` | +| 0013 | Add keyless signing to release workflow | β€” | TODO | 0012 | Sign StellaOps releases | +| 0014 | Add verification to deploy workflow | β€” | TODO | 0012 | Verify before deploy | +| 0015 | Document identity constraint patterns | β€” | TODO | β€” | `docs/guides/identity-constraints.md` | +| 0016 | Document issuer allowlisting | β€” | TODO | 0015 | Security best practices | +| 0017 | Document subject patterns | β€” | TODO | 0015 | Branch/environment constraints | +| 0018 | Create troubleshooting guide | β€” | TODO | β€” | Common errors and solutions | +| 0019 | Create quick-start guide | β€” | TODO | β€” | 5-minute integration | +| 0020 | Test: GitHub Actions template | β€” | TODO | 0002-0007 | End-to-end in test repo | +| 0021 | Test: GitLab CI template | β€” | TODO | 0009-0011 | End-to-end in test project | +| 0022 | Test: Gitea workflows | β€” | TODO | 0012-0014 | End-to-end in StellaOps repo | +| 0023 | Test: Cross-platform verification | β€” | TODO | 0020-0022 | Verify GitHub sig in GitLab | +| 0024 | Documentation review and polish | β€” | TODO | 0015-0019 | Technical writer review | + +--- + +## Technical Specifications + +### GitHub Actions Reusable Workflow + +```yaml +# .github/workflows/examples/stellaops-sign.yml +name: StellaOps Keyless Sign + +on: + workflow_call: + inputs: + artifact-digest: + description: 'SHA256 digest of artifact to sign' + required: true + type: string + artifact-type: + description: 'Type: image, sbom, verdict' + required: false + type: string + default: 'image' + stellaops-url: + description: 'StellaOps API URL' + required: false + type: string + default: 'https://api.stella-ops.org' + push-attestation: + description: 'Push attestation to registry' + required: false + type: boolean + default: true + outputs: + attestation-digest: + description: 'Digest of created attestation' + value: ${{ jobs.sign.outputs.attestation-digest }} + rekor-uuid: + description: 'Rekor transparency log UUID' + value: ${{ jobs.sign.outputs.rekor-uuid }} + +jobs: + sign: + runs-on: ubuntu-latest + permissions: + id-token: write # Required for OIDC + contents: read + packages: write # If pushing to GHCR + + outputs: + attestation-digest: ${{ steps.sign.outputs.attestation-digest }} + rekor-uuid: ${{ steps.sign.outputs.rekor-uuid }} + + steps: + - name: Install StellaOps CLI + uses: stella-ops/setup-cli@v1 + with: + version: 'latest' + + - name: Get OIDC Token + id: oidc + run: | + OIDC_TOKEN=$(curl -sLS "${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=sigstore" \ + -H "Authorization: bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" \ + | jq -r '.value') + echo "::add-mask::${OIDC_TOKEN}" + echo "token=${OIDC_TOKEN}" >> $GITHUB_OUTPUT + + - name: Keyless Sign + id: sign + env: + STELLAOPS_OIDC_TOKEN: ${{ steps.oidc.outputs.token }} + STELLAOPS_URL: ${{ inputs.stellaops-url }} + run: | + RESULT=$(stella attest sign \ + --keyless \ + --artifact "${{ inputs.artifact-digest }}" \ + --type "${{ inputs.artifact-type }}" \ + --output json) + + echo "attestation-digest=$(echo $RESULT | jq -r '.attestationDigest')" >> $GITHUB_OUTPUT + echo "rekor-uuid=$(echo $RESULT | jq -r '.rekorUuid')" >> $GITHUB_OUTPUT + + - name: Push Attestation + if: ${{ inputs.push-attestation }} + env: + STELLAOPS_URL: ${{ inputs.stellaops-url }} + run: | + stella attest push \ + --attestation "${{ steps.sign.outputs.attestation-digest }}" \ + --registry "${{ github.repository }}" + + - name: Summary + run: | + echo "## Attestation Created" >> $GITHUB_STEP_SUMMARY + echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY + echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY + echo "| Artifact | \`${{ inputs.artifact-digest }}\` |" >> $GITHUB_STEP_SUMMARY + echo "| Attestation | \`${{ steps.sign.outputs.attestation-digest }}\` |" >> $GITHUB_STEP_SUMMARY + echo "| Rekor UUID | \`${{ steps.sign.outputs.rekor-uuid }}\` |" >> $GITHUB_STEP_SUMMARY + echo "| Signing Mode | Keyless (Fulcio) |" >> $GITHUB_STEP_SUMMARY +``` + +### GitHub Actions Verification Gate + +```yaml +# .github/workflows/examples/stellaops-verify.yml +name: StellaOps Verify Gate + +on: + workflow_call: + inputs: + artifact-digest: + description: 'SHA256 digest of artifact to verify' + required: true + type: string + stellaops-url: + description: 'StellaOps API URL' + required: false + type: string + default: 'https://api.stella-ops.org' + certificate-identity: + description: 'Expected OIDC identity (regex)' + required: true + type: string + certificate-oidc-issuer: + description: 'Expected OIDC issuer' + required: true + type: string + require-rekor: + description: 'Require Rekor inclusion proof' + required: false + type: boolean + default: true + strict: + description: 'Fail on any verification issue' + required: false + type: boolean + default: true + outputs: + verified: + description: 'Whether verification passed' + value: ${{ jobs.verify.outputs.verified }} + +jobs: + verify: + runs-on: ubuntu-latest + permissions: + contents: read + packages: read + + outputs: + verified: ${{ steps.verify.outputs.verified }} + + steps: + - name: Install StellaOps CLI + uses: stella-ops/setup-cli@v1 + with: + version: 'latest' + + - name: Verify Attestation + id: verify + env: + STELLAOPS_URL: ${{ inputs.stellaops-url }} + run: | + set +e + RESULT=$(stella attest verify \ + --artifact "${{ inputs.artifact-digest }}" \ + --certificate-identity "${{ inputs.certificate-identity }}" \ + --certificate-oidc-issuer "${{ inputs.certificate-oidc-issuer }}" \ + ${{ inputs.require-rekor && '--require-rekor' || '' }} \ + --output json) + EXIT_CODE=$? + set -e + + VERIFIED=$(echo $RESULT | jq -r '.valid') + echo "verified=${VERIFIED}" >> $GITHUB_OUTPUT + + if [ "$VERIFIED" != "true" ] && [ "${{ inputs.strict }}" == "true" ]; then + echo "::error::Verification failed" + echo "$RESULT" | jq -r '.issues[]? | "::error::\(.code): \(.message)"' + exit 1 + fi + + - name: Summary + run: | + if [ "${{ steps.verify.outputs.verified }}" == "true" ]; then + echo "## βœ… Verification Passed" >> $GITHUB_STEP_SUMMARY + else + echo "## ❌ Verification Failed" >> $GITHUB_STEP_SUMMARY + fi + echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY + echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY + echo "| Artifact | \`${{ inputs.artifact-digest }}\` |" >> $GITHUB_STEP_SUMMARY + echo "| Identity | \`${{ inputs.certificate-identity }}\` |" >> $GITHUB_STEP_SUMMARY + echo "| Issuer | \`${{ inputs.certificate-oidc-issuer }}\` |" >> $GITHUB_STEP_SUMMARY +``` + +### GitLab CI Template + +```yaml +# deploy/gitlab/examples/.gitlab-ci-stellaops.yml +# Include this in your .gitlab-ci.yml: +# include: +# - project: 'stella-ops/templates' +# file: '.gitlab-ci-stellaops.yml' + +.stellaops-sign: + image: stella-ops/cli:latest + id_tokens: + STELLAOPS_OIDC_TOKEN: + aud: sigstore + variables: + STELLAOPS_URL: "https://api.stella-ops.org" + script: + - | + RESULT=$(stella attest sign \ + --keyless \ + --artifact "${ARTIFACT_DIGEST}" \ + --type "${ARTIFACT_TYPE:-image}" \ + --output json) + + echo "ATTESTATION_DIGEST=$(echo $RESULT | jq -r '.attestationDigest')" >> sign.env + echo "REKOR_UUID=$(echo $RESULT | jq -r '.rekorUuid')" >> sign.env + artifacts: + reports: + dotenv: sign.env + +.stellaops-verify: + image: stella-ops/cli:latest + variables: + STELLAOPS_URL: "https://api.stella-ops.org" + REQUIRE_REKOR: "true" + STRICT: "true" + script: + - | + stella attest verify \ + --artifact "${ARTIFACT_DIGEST}" \ + --certificate-identity "${CERTIFICATE_IDENTITY}" \ + --certificate-oidc-issuer "${CERTIFICATE_OIDC_ISSUER}" \ + ${REQUIRE_REKOR:+--require-rekor} \ + || { [ "${STRICT}" != "true" ] || exit 1; } + +# Example usage: +# sign-container: +# extends: .stellaops-sign +# variables: +# ARTIFACT_DIGEST: $CI_REGISTRY_IMAGE@sha256:... +# ARTIFACT_TYPE: image +# only: +# - main +# +# verify-before-deploy: +# extends: .stellaops-verify +# variables: +# ARTIFACT_DIGEST: $CI_REGISTRY_IMAGE@sha256:... +# CERTIFICATE_IDENTITY: "project_path:myorg/myrepo:.*" +# CERTIFICATE_OIDC_ISSUER: "https://gitlab.com" +# only: +# - main +``` + +### Gitea Workflow (Dogfooding) + +```yaml +# .gitea/workflows/release-sign.yml +name: Sign Release Artifacts + +on: + release: + types: [published] + +jobs: + sign: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup StellaOps CLI + run: | + curl -sL https://get.stella-ops.org/cli | sh + echo "$HOME/.stellaops/bin" >> $GITHUB_PATH + + - name: Get OIDC Token + id: oidc + run: | + # Gitea OIDC token acquisition + OIDC_TOKEN="${ACTIONS_ID_TOKEN}" + echo "::add-mask::${OIDC_TOKEN}" + echo "token=${OIDC_TOKEN}" >> $GITHUB_OUTPUT + + - name: Sign Release Artifacts + env: + STELLAOPS_OIDC_TOKEN: ${{ steps.oidc.outputs.token }} + STELLAOPS_URL: "https://api.stella-ops.internal" + run: | + # Sign each release artifact + for asset in $(gh release view ${{ github.event.release.tag_name }} --json assets -q '.assets[].name'); do + DIGEST=$(sha256sum "$asset" | cut -d' ' -f1) + stella attest sign --keyless --artifact "sha256:$DIGEST" --type release + done + + - name: Verify Signatures + env: + STELLAOPS_URL: "https://api.stella-ops.internal" + run: | + # Verify all signatures were created + for asset in $(gh release view ${{ github.event.release.tag_name }} --json assets -q '.assets[].name'); do + DIGEST=$(sha256sum "$asset" | cut -d' ' -f1) + stella attest verify \ + --artifact "sha256:$DIGEST" \ + --certificate-identity "org/stella-ops.org:ref:refs/tags/${{ github.event.release.tag_name }}" \ + --certificate-oidc-issuer "https://git.stella-ops.org" + done +``` + +### Identity Constraint Documentation + +```markdown +# docs/guides/identity-constraints.md + +# Identity Constraints for Keyless Verification + +## Overview + +Keyless signing binds attestations to OIDC identities. During verification, +you must specify which identities are trusted using two key constraints: + +1. **Certificate Identity** (`--certificate-identity`): The subject or SAN +2. **Certificate OIDC Issuer** (`--certificate-oidc-issuer`): The token issuer + +## Platform-Specific Patterns + +### GitHub Actions + +| Constraint | Pattern | Example | +|------------|---------|---------| +| Repository | `repo:/:.*` | `repo:stella-ops/scanner:.*` | +| Branch | `repo:/:ref:refs/heads/` | `repo:stella-ops/scanner:ref:refs/heads/main` | +| Tag | `repo:/:ref:refs/tags/.*` | `repo:stella-ops/scanner:ref:refs/tags/v.*` | +| Environment | `repo:/:environment:` | `repo:stella-ops/scanner:environment:production` | +| Workflow | (in SAN) | `.github/workflows/release.yml@refs/heads/main` | + +**OIDC Issuer:** `https://token.actions.githubusercontent.com` + +### GitLab CI + +| Constraint | Pattern | Example | +|------------|---------|---------| +| Project | `project_path:/:.*` | `project_path:stellaops/scanner:.*` | +| Branch | `project_path:/:ref_type:branch:ref:` | `...:ref_type:branch:ref:main` | +| Tag | `project_path:/:ref_type:tag:ref:.*` | `...:ref_type:tag:ref:v.*` | +| Protected | `project_path:/:ref_protected:true` | N/A | + +**OIDC Issuer:** `https://gitlab.com` (or self-hosted URL) + +### Best Practices + +1. **Always constrain to repository**: Never accept `.*` as the full identity +2. **Prefer branch constraints for production**: Use `ref:refs/heads/main` +3. **Use environment constraints when available**: More granular than branches +4. **Combine with Rekor verification**: `--require-rekor` ensures transparency +5. **Rotate issuer trust carefully**: Changes affect all verification +``` + +--- + +## Testing Requirements + +### Template Validation Tests + +```yaml +# Test: GitHub Actions template syntax +- name: Validate GitHub workflow + run: | + # Use actionlint for validation + actionlint .github/workflows/examples/*.yml + +# Test: GitLab CI template syntax +- name: Validate GitLab CI + run: | + # Use gitlab-ci-lint + gitlab-ci-lint deploy/gitlab/examples/.gitlab-ci-stellaops.yml +``` + +### Integration Tests + +| Test | Platform | Description | +|------|----------|-------------| +| `github-sign-verify` | GitHub | Sign in one workflow, verify in another | +| `gitlab-sign-verify` | GitLab | Sign in one job, verify in deployment job | +| `gitea-release` | Gitea | Sign release, verify before publish | +| `cross-platform` | All | Sign in GitHub, verify in GitLab | + +### Test Repository Structure + +``` +tests/cicd-templates/ +β”œβ”€β”€ github/ +β”‚ β”œβ”€β”€ .github/workflows/ +β”‚ β”‚ β”œβ”€β”€ test-sign.yml +β”‚ β”‚ β”œβ”€β”€ test-verify.yml +β”‚ β”‚ └── test-e2e.yml +β”‚ └── README.md +β”œβ”€β”€ gitlab/ +β”‚ β”œβ”€β”€ .gitlab-ci.yml +β”‚ └── README.md +└── gitea/ + β”œβ”€β”€ .gitea/workflows/ + β”‚ └── test.yml + └── README.md +``` + +--- + +## Decisions & Risks + +| ID | Decision/Risk | Status | Owner | Notes | +|----|---------------|--------|-------|-------| +| D001 | Reusable workflows over composite actions | DECIDED | β€” | More flexible, better secrets handling | +| D002 | Support regex for identity patterns | DECIDED | β€” | Enables flexible matching | +| D003 | Default to strict verification | DECIDED | β€” | Fail-secure by default | +| R001 | OIDC token format changes | OPEN | β€” | Monitor platform updates | +| R002 | Rate limiting on public Fulcio | OPEN | β€” | Document self-hosted option | +| R003 | Workflow permissions confusion | OPEN | β€” | Clear documentation needed | + +--- + +## Upcoming Checkpoints + +| Date | Milestone | Exit Criteria | +|------|-----------|---------------| +| +3 days | GitHub templates complete | 0001-0007 DONE | +| +6 days | GitLab templates complete | 0008-0011 DONE | +| +8 days | Gitea workflows updated | 0012-0014 DONE | +| +12 days | Documentation complete | 0015-0019 DONE | +| +15 days | All tests passing | 0020-0024 DONE, sprint DONE | + +--- + +## Execution Log + +| Date | Role | Action | Notes | +|------|------|--------|-------| +| 2025-12-26 | PM | Sprint created | Initial planning from keyless signing advisory | + +--- + +## Related Documents + +- **Parent Advisory:** `docs/product-advisories/25-Dec-2025 - Planning Keyless Signing for Verdicts.md` +- **Predecessor Sprints:** + - `SPRINT_20251226_001_SIGNER_fulcio_keyless_client.md` + - `SPRINT_20251226_002_ATTESTOR_bundle_rotation.md` + - `SPRINT_20251226_003_ATTESTOR_offline_verification.md` +- **Signer Architecture:** `docs/modules/signer/architecture.md` +- **Attestor Architecture:** `docs/modules/attestor/architecture.md` + +--- + +*End of Sprint Document* diff --git a/docs/implplan/SPRINT_20251226_004_FE_risk_dashboard.md b/docs/implplan/SPRINT_20251226_004_FE_risk_dashboard.md new file mode 100644 index 000000000..cdb1401ca --- /dev/null +++ b/docs/implplan/SPRINT_20251226_004_FE_risk_dashboard.md @@ -0,0 +1,56 @@ +# Sprint 20251226 Β· Risk Budget and Delta Verdict Dashboard + +## Topic & Scope +- Build PM-facing Angular 17 dashboard for risk budget visualization and delta verdict display. +- Implement burn-up charts, verdict badges, evidence drill-downs, and exception management UI. +- Deliver side-by-side diff visualization for before/after risk comparison. +- **Working directory:** `src/Web/StellaOps.Web` + +## Dependencies & Concurrency +- Depends on: SPRINT_20251226_001_BE (gate API endpoints), SPRINT_20251226_002_BE (budget API), SPRINT_20251226_003_BE (exception API). +- Can run in parallel with: SPRINT_20251226_005_SCANNER (reachability extractors). +- Blocked by: Backend API endpoints must be complete before full integration. + +## Documentation Prerequisites +- `docs/modules/web/architecture.md` +- `docs/product-advisories/25-Dec-2025 - Visual Diffs for Explainable Triage.md` +- `docs/product-advisories/26-Dec-2026 - Visualizing the Risk Budget.md` +- Angular 17 component patterns in existing codebase + +## Delivery Tracker +| # | Task ID | Status | Key dependency / next step | Owners | Task Definition | +| --- | --- | --- | --- | --- | --- | +| 1 | DASH-01 | TODO | None | Frontend Guild | Create `RiskBudgetService` Angular service consuming budget API endpoints | +| 2 | DASH-02 | TODO | None | Frontend Guild | Create `DeltaVerdictService` Angular service consuming gate API endpoints | +| 3 | DASH-03 | TODO | DASH-01 | Frontend Guild | Risk Budget Burn-Up chart component: X=calendar, Y=risk points, budget line + actual line, headroom shading | +| 4 | DASH-04 | TODO | DASH-03 | Frontend Guild | Budget status KPI tiles: Headroom (pts), Unknowns delta (24h), Risk retired (7d), Exceptions expiring | +| 5 | DASH-05 | TODO | DASH-02 | Frontend Guild | Delta Verdict badge component: Routine (green), Review (yellow), Block (red) with tooltip summary | +| 6 | DASH-06 | TODO | DASH-05 | Frontend Guild | "Why" summary bullets component: 3-5 bullet explanation of verdict drivers | +| 7 | DASH-07 | TODO | DASH-06 | Frontend Guild | Evidence buttons: "Show reachability slice", "Show VEX sources", "Show SBOM diff" opening modal panels | +| 8 | DASH-08 | TODO | DASH-07 | Frontend Guild | Reachability slice mini-graph component: visualize entry->sink call paths | +| 9 | DASH-09 | TODO | DASH-07 | Frontend Guild | VEX sources panel: list sources with trust scores, freshness, status | +| 10 | DASH-10 | TODO | DASH-07 | Frontend Guild | SBOM diff panel: side-by-side packages added/removed/changed | +| 11 | DASH-11 | TODO | DASH-02 | Frontend Guild | Side-by-side diff panes: Before vs After risk state with highlighted changes | +| 12 | DASH-12 | TODO | DASH-11 | Frontend Guild | Exception ledger timeline: history of exceptions with status, expiry, owner | +| 13 | DASH-13 | TODO | DASH-12 | Frontend Guild | "Create Exception" modal: reason, evidence refs, TTL, scope selection | +| 14 | DASH-14 | TODO | DASH-13 | Frontend Guild | "Approve Exception" action in exception list for users with approver role | +| 15 | DASH-15 | TODO | DASH-14 | Frontend Guild | Responsive design: dashboard usable on tablet/desktop | +| 16 | DASH-16 | TODO | DASH-15 | Frontend Guild | Unit tests for all new components | +| 17 | DASH-17 | TODO | DASH-16 | Frontend Guild | E2E tests: budget view, verdict view, exception workflow | + +## Execution Log +| Date (UTC) | Update | Owner | +| --- | --- | --- | +| 2025-12-26 | Sprint created from product advisory analysis; implements PM-facing UI from visual diffs and risk budget advisories. | Project Mgmt | + +## Decisions & Risks +- Decision needed: Chart library for burn-up visualization. Recommend: ngx-charts or Chart.js (already in use?). +- Decision needed: Mini-graph library for reachability slice. Recommend: D3.js or Cytoscape.js. +- Decision needed: Mobile support scope. Recommend: tablet minimum, phone deferred. +- Risk: Large diff graphs may cause performance issues. Mitigation: "changed neighborhood only" default view, progressive loading. +- Risk: Evidence panel latency for large SBOMs. Mitigation: paginated loading, summary-first approach. + +## Next Checkpoints +- 2026-01-06 | DASH-06 complete | Core verdict display functional | +- 2026-01-10 | DASH-11 complete | Diff visualization working | +- 2026-01-15 | DASH-17 complete | Full dashboard with tests | diff --git a/docs/implplan/SPRINT_20251226_005_SCANNER_reachability_extractors.md b/docs/implplan/SPRINT_20251226_005_SCANNER_reachability_extractors.md new file mode 100644 index 000000000..449dc10cf --- /dev/null +++ b/docs/implplan/SPRINT_20251226_005_SCANNER_reachability_extractors.md @@ -0,0 +1,64 @@ +# Sprint 20251226 Β· Language Reachability Call Graph Extractors + +## Topic & Scope +- Complete language-specific call graph extractors for reachability drift analysis. +- Implement extractors for Java (ASM), Node.js (Babel), Python (AST), and Go (SSA completion). +- Integrate extractors into scanner registry with determinism guarantees. +- **Working directory:** `src/Scanner/StellaOps.Scanner.Reachability`, `src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.*` + +## Dependencies & Concurrency +- Depends on: Existing .NET Roslyn extractor (complete), `ReachabilityDriftResult` model (complete). +- Depends on: SmartDiff predicate schema (complete), SinkRegistry (complete). +- Can run in parallel with: All other sprints (independent language work). + +## Documentation Prerequisites +- `docs/modules/scanner/AGENTS.md` +- `docs/modules/scanner/reachability-drift.md` +- `docs/product-advisories/archived/2025-12-21-moat-gap-closure/14-Dec-2025 - Smart-Diff Technical Reference.md` +- `docs/product-advisories/25-Dec-2025 - Evolving Evidence Models for Reachability.md` + +## Delivery Tracker +| # | Task ID | Status | Key dependency / next step | Owners | Task Definition | +| --- | --- | --- | --- | --- | --- | +| 1 | REACH-JAVA-01 | TODO | None | Scanner Guild | Create `StellaOps.Scanner.Analyzers.Lang.Java.Reachability` project structure | +| 2 | REACH-JAVA-02 | TODO | REACH-JAVA-01 | Scanner Guild | Implement ASM-based bytecode call graph extraction from .class/.jar files | +| 3 | REACH-JAVA-03 | TODO | REACH-JAVA-02 | Scanner Guild | Map ASM method refs to purl + symbol for CVE correlation | +| 4 | REACH-JAVA-04 | TODO | REACH-JAVA-03 | Scanner Guild | Sink detection: identify calls to known vulnerable methods (SQL, deserialization, exec) | +| 5 | REACH-JAVA-05 | TODO | REACH-JAVA-04 | Scanner Guild | Integration tests with sample Maven/Gradle projects | +| 6 | REACH-NODE-01 | TODO | None | Scanner Guild | Create `StellaOps.Scanner.Analyzers.Lang.Node.Reachability` project structure | +| 7 | REACH-NODE-02 | TODO | REACH-NODE-01 | Scanner Guild | Implement Babel AST parser for JavaScript/TypeScript call extraction | +| 8 | REACH-NODE-03 | TODO | REACH-NODE-02 | Scanner Guild | Handle CommonJS require() and ESM import resolution | +| 9 | REACH-NODE-04 | TODO | REACH-NODE-03 | Scanner Guild | Map npm package refs to purl for CVE correlation | +| 10 | REACH-NODE-05 | TODO | REACH-NODE-04 | Scanner Guild | Sink detection: eval, child_process, fs operations, SQL templates | +| 11 | REACH-NODE-06 | TODO | REACH-NODE-05 | Scanner Guild | Integration tests with sample Node.js projects (Express, NestJS) | +| 12 | REACH-PY-01 | TODO | None | Scanner Guild | Create `StellaOps.Scanner.Analyzers.Lang.Python.Reachability` project structure | +| 13 | REACH-PY-02 | TODO | REACH-PY-01 | Scanner Guild | Implement Python AST call graph extraction using ast module | +| 14 | REACH-PY-03 | TODO | REACH-PY-02 | Scanner Guild | Handle import resolution for installed packages (pip/poetry) | +| 15 | REACH-PY-04 | TODO | REACH-PY-03 | Scanner Guild | Sink detection: subprocess, pickle, eval, SQL string formatting | +| 16 | REACH-PY-05 | TODO | REACH-PY-04 | Scanner Guild | Integration tests with sample Python projects (Flask, Django) | +| 17 | REACH-GO-01 | TODO | None | Scanner Guild | Complete Go SSA extractor skeleton in existing project | +| 18 | REACH-GO-02 | TODO | REACH-GO-01 | Scanner Guild | Implement golang.org/x/tools/go/callgraph/cha integration | +| 19 | REACH-GO-03 | TODO | REACH-GO-02 | Scanner Guild | Map Go packages to purl for CVE correlation | +| 20 | REACH-GO-04 | TODO | REACH-GO-03 | Scanner Guild | Sink detection: os/exec, net/http client, database/sql | +| 21 | REACH-GO-05 | TODO | REACH-GO-04 | Scanner Guild | Integration tests with sample Go projects | +| 22 | REACH-REG-01 | TODO | REACH-JAVA-05, REACH-NODE-06, REACH-PY-05, REACH-GO-05 | Scanner Guild | Register all extractors in `ReachabilityExtractorRegistry` | +| 23 | REACH-REG-02 | TODO | REACH-REG-01 | Scanner Guild | Determinism tests: same input -> same call graph hash across runs | +| 24 | REACH-REG-03 | TODO | REACH-REG-02 | Scanner Guild | Documentation: update scanner AGENTS.md with extractor usage | + +## Execution Log +| Date (UTC) | Update | Owner | +| --- | --- | --- | +| 2025-12-26 | Sprint created from product advisory analysis; addresses reachability extractor gaps for diff-aware gates. | Project Mgmt | + +## Decisions & Risks +- Decision needed: ASM version for Java extractor (9.x recommended for Java 21 support). +- Decision needed: Babel parser plugins for TypeScript/JSX support. +- Decision needed: Python version support (3.8+ recommended). +- Risk: Dynamic dispatch in Java/Python limits static call graph accuracy. Mitigation: conservative over-approximation, flag unknowns. +- Risk: Node.js dynamic requires are hard to resolve. Mitigation: mark as unknown, runtime evidence can supplement. +- Risk: Large codebases may cause memory issues. Mitigation: streaming/chunked processing, configurable depth limits. + +## Next Checkpoints +- 2026-01-10 | REACH-JAVA-05 complete | Java extractor functional | +- 2026-01-15 | REACH-NODE-06 complete | Node.js extractor functional | +- 2026-01-20 | REACH-REG-02 complete | All extractors registered and determinism verified | diff --git a/docs/implplan/SPRINT_20251226_006_DOCS_advisory_consolidation.md b/docs/implplan/SPRINT_20251226_006_DOCS_advisory_consolidation.md new file mode 100644 index 000000000..1406aa1b4 --- /dev/null +++ b/docs/implplan/SPRINT_20251226_006_DOCS_advisory_consolidation.md @@ -0,0 +1,66 @@ +# Sprint 20251226 Β· Product Advisory Consolidation + +## Topic & Scope +- Consolidate 8 overlapping product advisories into a single master document for diff-aware release gates. +- Archive original advisories with cross-reference preservation. +- Create executive summary for stakeholder communication. +- **Working directory:** `docs/product-advisories/` + +## Dependencies & Concurrency +- No technical dependencies; documentation-only sprint. +- Can run immediately and in parallel with all other sprints. +- Should complete first to provide unified reference for implementation sprints. + +## Documentation Prerequisites +- All source advisories (listed in Delivery Tracker) +- `CLAUDE.md` (documentation conventions) + +## Delivery Tracker +| # | Task ID | Status | Key dependency / next step | Owners | Task Definition | +| --- | --- | --- | --- | --- | --- | +| 1 | DOCS-01 | TODO | None | Project Mgmt | Create consolidated master document: `CONSOLIDATED - Diff-Aware Release Gates and Risk Budgets.md` | +| 2 | DOCS-02 | TODO | DOCS-01 | Project Mgmt | Merge content from: `25-Dec-2025 - Implementing Diff-Aware Release Gates.md` | +| 3 | DOCS-03 | TODO | DOCS-01 | Project Mgmt | Merge content from: `26-Dec-2026 - Diff-Aware Releases and Auditable Exceptions.md` | +| 4 | DOCS-04 | TODO | DOCS-01 | Project Mgmt | Merge content from: `26-Dec-2026 - Smart-Diff as a Core Evidence Primitive.md` | +| 5 | DOCS-05 | TODO | DOCS-01 | Project Mgmt | Merge content from: `25-Dec-2025 - Visual Diffs for Explainable Triage.md` | +| 6 | DOCS-06 | TODO | DOCS-01 | Project Mgmt | Merge content from: `25-Dec-2025 - Building a Deterministic Verdict Engine.md` | +| 7 | DOCS-07 | TODO | DOCS-01 | Project Mgmt | Merge content from: `26-Dec-2026 - Visualizing the Risk Budget.md` | +| 8 | DOCS-08 | TODO | DOCS-01 | Project Mgmt | Merge content from: `26-Dec-2026 - Weighted Confidence for VEX Sources.md` | +| 9 | DOCS-09 | TODO | DOCS-01 | Project Mgmt | Reference archived technical spec: `archived/2025-12-21-moat-gap-closure/14-Dec-2025 - Smart-Diff Technical Reference.md` | +| 10 | DOCS-10 | TODO | DOCS-01 | Project Mgmt | Reference archived moat document: `archived/2025-12-21-moat-phase2/20-Dec-2025 - Moat Explanation - Risk Budgets and Diff-Aware Release Gates.md` | +| 11 | DOCS-11 | TODO | DOCS-08 | Project Mgmt | Create archive directory: `archived/2025-12-26-diff-aware-gates/` | +| 12 | DOCS-12 | TODO | DOCS-11 | Project Mgmt | Move original advisories to archive directory | +| 13 | DOCS-13 | TODO | DOCS-12 | Project Mgmt | Update cross-references in `docs/modules/policy/architecture.md` | +| 14 | DOCS-14 | TODO | DOCS-12 | Project Mgmt | Update cross-references in `docs/modules/scanner/AGENTS.md` | +| 15 | DOCS-15 | TODO | DOCS-13 | Project Mgmt | Create executive summary (1-page) for stakeholder communication | +| 16 | DOCS-16 | TODO | DOCS-15 | Project Mgmt | Review consolidated document for consistency and completeness | + +## Consolidated Document Structure +The master document should include these sections: +1. **Executive Summary** - 1-page overview for PMs/stakeholders +2. **Core Concepts** - SBOM, VEX, Reachability, Semantic Delta definitions +3. **Risk Budget Model** - Service tiers, RP scoring, window management, thresholds +4. **Release Gate Levels** - G0-G4 definitions, gate selection logic +5. **Delta Verdict Engine** - Computation, scoring, determinism, replay +6. **Smart-Diff Algorithm** - Material change detection rules, suppression rules +7. **Exception Workflow** - Entity model, approval flow, audit requirements +8. **VEX Trust Scoring** - Confidence/freshness lattice, source weights +9. **UI/UX Patterns** - PM dashboard, visual diffs, evidence panels +10. **CI/CD Integration** - Pipeline recipe, CLI commands, exit codes +11. **Implementation Status** - What exists, what's needed, sprint references + +## Execution Log +| Date (UTC) | Update | Owner | +| --- | --- | --- | +| 2025-12-26 | Sprint created from product advisory gap analysis; identified 8 overlapping advisories requiring consolidation. | Project Mgmt | + +## Decisions & Risks +- Decision: Preserve all unique content from each advisory vs. deduplicate aggressively. Recommend: deduplicate, keep most detailed version of each concept. +- Decision: Archive naming convention. Recommend: date-prefixed directory with original filenames. +- Risk: Broken cross-references after archival. Mitigation: grep for advisory filenames, update all references. +- Risk: Loss of advisory authorship/history. Mitigation: note original sources in consolidated doc header. + +## Next Checkpoints +- 2025-12-27 | DOCS-01 complete | Master document structure created | +- 2025-12-28 | DOCS-10 complete | All content merged | +- 2025-12-29 | DOCS-16 complete | Consolidation reviewed and finalized | diff --git a/docs/implplan/SPRINT_20251226_007_BE_determinism_gaps.md b/docs/implplan/SPRINT_20251226_007_BE_determinism_gaps.md new file mode 100644 index 000000000..32ae35ad5 --- /dev/null +++ b/docs/implplan/SPRINT_20251226_007_BE_determinism_gaps.md @@ -0,0 +1,85 @@ +# Sprint 20251226 Β· Determinism Gap Closure + +## Topic & Scope +- Close remaining gaps in deterministic verdict engine infrastructure. +- Implement unified feed snapshot coordination, keyless signing, and cross-platform testing. +- Formalize determinism manifest schema for certification. +- Enforce canonical JSON (RFC 8785 JCS + NFC) at resolver boundaries. +- **Working directory:** `src/Policy/`, `src/Concelier/`, `src/Attestor/`, `src/Signer/`, `src/__Libraries/` + +## Dependencies & Concurrency +- Depends on: Existing determinism infrastructure (85% complete). +- No blocking dependencies; can start immediately. +- Can run in parallel with: SPRINT_20251226_008_DOCS (documentation consolidation). + +## Documentation Prerequisites +- `docs/modules/policy/design/deterministic-evaluator.md` +- `docs/modules/policy/design/policy-determinism-tests.md` +- `docs/modules/scanner/deterministic-execution.md` +- `docs/product-advisories/25-Dec-2025 - Planning Keyless Signing for Verdicts.md` +- `docs/product-advisories/25-Dec-2025 - Enforcing Canonical JSON for Stable Verdicts.md` (SUPERSEDED - tasks merged here) + +## Context: What Already Exists + +The following determinism features are **already implemented**: + +| Component | Location | Status | +|-----------|----------|--------| +| Canonical JSON (JCS) | `StellaOps.Canonical.Json` | COMPLETE | +| Content-Addressed IDs | `Attestor.ProofChain/Identifiers/` | COMPLETE | +| Determinism Guards | `Policy.Engine/DeterminismGuard/` | COMPLETE | +| Replay Manifest | `StellaOps.Replay.Core` | COMPLETE | +| DSSE Signing | `Signer/`, `Attestor/` | COMPLETE | +| Delta Verdict | `Policy/Deltas/DeltaVerdict.cs` | COMPLETE | +| Merkle Trees | `ProofChain/Merkle/` | COMPLETE | +| Golden Tests | `Integration.Determinism/` | PARTIAL | + +This sprint closes the **remaining 15% gaps**. + +## Delivery Tracker +| # | Task ID | Status | Key dependency / next step | Owners | Task Definition | +| --- | --- | --- | --- | --- | --- | +| 1 | DET-GAP-01 | TODO | None | Concelier Guild + Excititor Guild | Create `IFeedSnapshotCoordinator` interface for atomic multi-source snapshots | +| 2 | DET-GAP-02 | TODO | DET-GAP-01 | Concelier Guild | Implement `FeedSnapshotCoordinatorService` coordinating Advisory + VEX + Policy snapshots | +| 3 | DET-GAP-03 | TODO | DET-GAP-02 | Concelier Guild | Add `POST /api/v1/feeds/snapshot` endpoint returning atomic bundle with composite digest | +| 4 | DET-GAP-04 | TODO | DET-GAP-03 | Concelier Guild | CLI command `stella feeds snapshot --output bundle.tar.gz` for offline use | +| 5 | DET-GAP-05 | TODO | None | Signer Guild | Integrate Sigstore Fulcio for keyless signing (OIDC token -> ephemeral cert) | +| 6 | DET-GAP-06 | TODO | DET-GAP-05 | Signer Guild | Add `SigningMode.Keyless` option to `DsseSigner` configuration | +| 7 | DET-GAP-07 | TODO | DET-GAP-05 | Signer Guild | Implement Rekor transparency log integration for keyless signatures | +| 8 | DET-GAP-08 | TODO | DET-GAP-07 | Signer Guild | CLI command `stella sign --keyless --rekor` for CI pipelines | +| 9 | DET-GAP-09 | TODO | None | Policy Guild | Create formal JSON Schema: `determinism-manifest.schema.json` | +| 10 | DET-GAP-10 | TODO | DET-GAP-09 | Policy Guild | Validator for determinism manifest compliance | +| 11 | DET-GAP-11 | TODO | None | Testing Guild | Add Windows determinism test runner to CI matrix | +| 12 | DET-GAP-12 | TODO | DET-GAP-11 | Testing Guild | Add macOS determinism test runner to CI matrix | +| 13 | DET-GAP-13 | TODO | DET-GAP-12 | Testing Guild | Cross-platform hash comparison report generation | +| 14 | DET-GAP-14 | TODO | None | Bench Guild | Property-based determinism tests (input permutations -> same hash) | +| 15 | DET-GAP-15 | TODO | DET-GAP-14 | Bench Guild | Floating-point stability validation (decimal vs float edge cases) | +| 16 | DET-GAP-16 | TODO | All above | Policy Guild | Integration test: full verdict pipeline with all gaps closed | +| 17 | DET-GAP-17 | TODO | None | Resolver Guild | Add optional NFC normalization pass to `Rfc8785JsonCanonicalizer` for Unicode string stability | +| 18 | DET-GAP-18 | TODO | None | Tooling Guild | Create Roslyn analyzer `STELLA0100` to enforce canonicalization at resolver boundary | +| 19 | DET-GAP-19 | TODO | None | Attestor Guild | Add pre-canonical hash debug logging for audit trails (log both raw and canonical SHA-256) | +| 20 | DET-GAP-20 | TODO | None | Docs Guild | Document resolver boundary canonicalization pattern in `CONTRIBUTING.md` | +| 21 | DET-GAP-21 | TODO | None | Metrics Guild | Add proof generation rate metric (proofs/second by type) | +| 22 | DET-GAP-22 | TODO | DET-GAP-21 | Metrics Guild | Add median proof size metric (KB by type: witness, subgraph, spine) | +| 23 | DET-GAP-23 | TODO | DET-GAP-21 | Metrics Guild | Add replay success rate metric (successful replays / total attempts) | +| 24 | DET-GAP-24 | TODO | DET-GAP-21 | Metrics Guild | Add proof dedup ratio metric (unique proofs / total generated) | +| 25 | DET-GAP-25 | TODO | None | Policy Guild | Add "unknowns" burn-down tracking (count reduction per scan) | + +## Execution Log +| Date (UTC) | Update | Owner | +| --- | --- | --- | +| 2025-12-26 | Sprint created from advisory analysis; identified remaining 15% gaps in determinism infrastructure. | Project Mgmt | +| 2025-12-26 | Added DET-GAP-17 through DET-GAP-20 from "Enforcing Canonical JSON for Stable Verdicts" advisory analysis. Advisory marked SUPERSEDED. | Project Mgmt | +| 2025-12-26 | Added DET-GAP-21 through DET-GAP-25 from "Reachability as Cryptographic Proof" advisory (metrics, unknowns tracking). Advisory marked SUPERSEDED. | Project Mgmt | + +## Decisions & Risks +- Decision needed: Sigstore instance (public vs self-hosted). Recommend: public for CI, self-hosted option for air-gap. +- Decision needed: Feed snapshot retention period. Recommend: 90 days default, configurable. +- Decision needed: Cross-platform CI runners (GitHub Actions vs self-hosted). Recommend: GitHub Actions for broad coverage. +- Risk: Keyless signing requires stable OIDC provider. Mitigation: fallback to key-based signing if OIDC unavailable. +- Risk: Cross-platform float differences. Mitigation: use decimal for all numeric comparisons (already enforced). + +## Next Checkpoints +- 2025-12-30 | DET-GAP-04 complete | Feed snapshot coordinator functional | +- 2026-01-03 | DET-GAP-08 complete | Keyless signing working in CI | +- 2026-01-06 | DET-GAP-16 complete | Full integration verified | diff --git a/docs/implplan/SPRINT_20251226_008_DOCS_determinism_consolidation.md b/docs/implplan/SPRINT_20251226_008_DOCS_determinism_consolidation.md new file mode 100644 index 000000000..99e40c2e8 --- /dev/null +++ b/docs/implplan/SPRINT_20251226_008_DOCS_determinism_consolidation.md @@ -0,0 +1,113 @@ +# Sprint 20251226 Β· Determinism Advisory and Documentation Consolidation + +## Topic & Scope +- Consolidate 6 overlapping product advisories into a single determinism architecture specification. +- Create authoritative documentation for all determinism guarantees and digest algorithms. +- Archive original advisories with cross-reference preservation. +- **Working directory:** `docs/product-advisories/`, `docs/technical/` + +## Dependencies & Concurrency +- No technical dependencies; documentation-only sprint. +- Can run in parallel with: SPRINT_20251226_007_BE (determinism gap closure). +- Should reference implementation status from gap closure sprint. + +## Documentation Prerequisites +- All source advisories (listed in Delivery Tracker) +- Existing determinism docs: + - `docs/modules/policy/design/deterministic-evaluator.md` + - `docs/modules/policy/design/policy-determinism-tests.md` + - `docs/modules/scanner/deterministic-execution.md` + +## Advisories to Consolidate + +| Advisory | Primary Concepts | Keep Verbatim | +|----------|------------------|---------------| +| `25-Dec-2025 - Building a Deterministic Verdict Engine.md` | Manifest, verdict format, replay APIs | Engine architecture, rollout plan | +| `25-Dec-2025 - Enforcing Canonical JSON for Stable Verdicts.md` | JCS, UTF-8, NFC, .NET snippet | Rule statement, code snippet | +| `25-Dec-2025 - Planning Keyless Signing for Verdicts.md` | Sigstore, Fulcio, Rekor, bundles | Rollout checklist | +| `26-Dec-2026 - Smart-Diff as a Core Evidence Primitive.md` | Delta verdict, evidence model | Schema sketch | +| `26-Dec-2026 - Reachability as Cryptographic Proof.md` | Proof-carrying reachability | Proof example, UI concept | +| `25-Dec-2025 - Hybrid Binary and Call-Graph Analysis.md` | Binary+static+runtime analysis | Keep as separate (different focus) | + +## Delivery Tracker +| # | Task ID | Status | Key dependency / next step | Owners | Task Definition | +| --- | --- | --- | --- | --- | --- | +| 1 | DOC-DET-01 | TODO | None | Project Mgmt | Create master document structure: `CONSOLIDATED - Deterministic Evidence and Verdict Architecture.md` | +| 2 | DOC-DET-02 | TODO | DOC-DET-01 | Project Mgmt | Merge "Building a Deterministic Verdict Engine" as core engine section | +| 3 | DOC-DET-03 | TODO | DOC-DET-01 | Project Mgmt | Merge "Enforcing Canonical JSON" as serialization section | +| 4 | DOC-DET-04 | TODO | DOC-DET-01 | Project Mgmt | Merge "Planning Keyless Signing" as signing section | +| 5 | DOC-DET-05 | TODO | DOC-DET-01 | Project Mgmt | Merge "Smart-Diff as Evidence Primitive" as delta section | +| 6 | DOC-DET-06 | TODO | DOC-DET-01 | Project Mgmt | Merge "Reachability as Cryptographic Proof" as reachability section | +| 7 | DOC-DET-07 | TODO | DOC-DET-06 | Project Mgmt | Add implementation status matrix (what exists vs gaps) | +| 8 | DOC-DET-08 | TODO | DOC-DET-07 | Project Mgmt | Create archive directory: `archived/2025-12-26-determinism-advisories/` | +| 9 | DOC-DET-09 | TODO | DOC-DET-08 | Project Mgmt | Move 5 original advisories to archive | +| 10 | DOC-DET-10 | TODO | None | Policy Guild | Create `docs/technical/architecture/determinism-specification.md` | +| 11 | DOC-DET-11 | TODO | DOC-DET-10 | Policy Guild | Document all digest algorithms: VerdictId, EvidenceId, GraphRevisionId, etc. | +| 12 | DOC-DET-12 | TODO | DOC-DET-10 | Policy Guild | Document canonicalization version strategy and migration path | +| 13 | DOC-DET-13 | TODO | DOC-DET-11 | Policy Guild | Add troubleshooting guide: "Why are my verdicts different?" | +| 14 | DOC-DET-14 | TODO | DOC-DET-09 | Project Mgmt | Update cross-references in `docs/modules/policy/architecture.md` | +| 15 | DOC-DET-15 | TODO | DOC-DET-09 | Project Mgmt | Update cross-references in `docs/modules/scanner/AGENTS.md` | +| 16 | DOC-DET-16 | TODO | All above | Project Mgmt | Final review of consolidated document | + +## Consolidated Document Structure + +```markdown +# Deterministic Evidence and Verdict Architecture + +## 1. Executive Summary +## 2. Why Determinism Matters + - Reproducibility for auditors + - Content-addressed caching + - Cross-agent consensus +## 3. Core Principles + - No wall-clock, no RNG, no network during evaluation + - Content-addressing all inputs + - Pure evaluation functions +## 4. Canonical Serialization (from "Enforcing Canonical JSON") + - UTF-8 + NFC + JCS (RFC 8785) + - .NET implementation reference +## 5. Data Artifacts (from "Building Deterministic Verdict Engine") + - Scan Manifest schema + - Verdict schema + - Delta Verdict schema +## 6. Signing & Attestation (from "Planning Keyless Signing") + - DSSE envelopes + - Keyless via Sigstore/Fulcio + - Rekor transparency + - Monthly bundle rotation +## 7. Reachability Proofs (from "Reachability as Cryptographic Proof") + - Proof structure + - Graph snippets + - Operating modes (strict/lenient) +## 8. Delta Verdicts (from "Smart-Diff as Evidence Primitive") + - Evidence model + - Merge semantics + - OCI attachment +## 9. Implementation Status + - What's complete (85%) + - What's in progress + - What's planned +## 10. Testing Strategy + - Golden tests + - Chaos tests + - Cross-platform validation +## 11. References + - Code locations + - Related sprints +``` + +## Execution Log +| Date (UTC) | Update | Owner | +| --- | --- | --- | +| 2025-12-26 | Sprint created from advisory analysis; identified 6 overlapping advisories for consolidation. | Project Mgmt | + +## Decisions & Risks +- Decision: Keep "Hybrid Binary and Call-Graph Analysis" separate (different focus). Recommend: Yes, it's about analysis methods not determinism. +- Decision: Archive location. Recommend: `archived/2025-12-26-determinism-advisories/` with README explaining consolidation. +- Risk: Broken cross-references after archival. Mitigation: grep all docs for advisory filenames before archiving. +- Risk: Loss of nuance from individual advisories. Mitigation: preserve verbatim sections where noted. + +## Next Checkpoints +- 2025-12-27 | DOC-DET-06 complete | All content merged into master document | +- 2025-12-28 | DOC-DET-12 complete | Technical specification created | +- 2025-12-29 | DOC-DET-16 complete | Final review and publication | diff --git a/docs/implplan/SPRINT_20251226_009_SCANNER_funcproof.md b/docs/implplan/SPRINT_20251226_009_SCANNER_funcproof.md new file mode 100644 index 000000000..e40badc6b --- /dev/null +++ b/docs/implplan/SPRINT_20251226_009_SCANNER_funcproof.md @@ -0,0 +1,98 @@ +# Sprint 20251226 Β· Function-Level Proof Generation (FuncProof) + +## Topic & Scope +- Implement function-level proof objects for binary-level reachability evidence. +- Generate symbol digests, function-range hashes, and entryβ†’sink trace serialization. +- Publish FuncProof as DSSE-signed OCI referrer artifacts linked from SBOM. +- **Working directory:** `src/Scanner/`, `src/BinaryIndex/`, `src/Attestor/` + +## Dependencies & Concurrency +- Depends on: `BinaryIdentity` (complete), `NativeReachabilityGraphBuilder` (complete). +- No blocking dependencies; can start immediately. +- Enables: SPRINT_20251226_011_BE (auto-VEX needs funcproof for symbol correlation). + +## Documentation Prerequisites +- `docs/modules/scanner/design/native-reachability-plan.md` +- `docs/modules/scanner/os-analyzers-evidence.md` +- `docs/product-advisories/25-Dec-2025 - Evolving Evidence Models for Reachability.md` +- `docs/product-advisories/26-Dec-2026 - Mapping a Binary Intelligence Graph.md` + +## Context: What Already Exists + +| Component | Location | Status | +|-----------|----------|--------| +| BinaryIdentity (Build-ID, sections) | `BinaryIndex/BinaryIdentity.cs` | COMPLETE | +| ELF/PE/Mach-O parsers | `Scanner.Analyzers.Native/` | COMPLETE | +| Disassemblers (ARM64, x86) | `Scanner.CallGraph/Extraction/Binary/` | COMPLETE | +| DWARF debug reader | `Scanner.CallGraph/Extraction/Binary/DwarfDebugReader.cs` | COMPLETE | +| Call graph snapshot | `Scanner.CallGraph/CallGraphSnapshot.cs` | COMPLETE | +| DSSE envelope support | `Attestor/` | COMPLETE | + +This sprint adds **function-level granularity** on top of existing binary infrastructure. + +## Delivery Tracker +| # | Task ID | Status | Key dependency / next step | Owners | Task Definition | +| --- | --- | --- | --- | --- | --- | +| 1 | FUNC-01 | TODO | None | Scanner Guild | Define `FuncProof` JSON model: buildId, sections, functions[], traces[] | +| 2 | FUNC-02 | TODO | FUNC-01 | Scanner Guild | Create `FuncProofDocument` PostgreSQL entity with indexes on build_id | +| 3 | FUNC-03 | TODO | FUNC-01 | Scanner Guild | Implement function-range boundary detection using DWARF/symbol table | +| 4 | FUNC-04 | TODO | FUNC-03 | Scanner Guild | Fallback: heuristic prolog/epilog detection for stripped binaries | +| 5 | FUNC-05 | TODO | FUNC-03 | Scanner Guild | Symbol digest computation: BLAKE3(symbol_name + offset_range) | +| 6 | FUNC-06 | TODO | FUNC-05 | Scanner Guild | Populate `symbol_digest` field in `FuncNodeDocument` | +| 7 | FUNC-07 | TODO | FUNC-03 | Scanner Guild | Function-range hashing: rolling BLAKE3 over `.text` subranges per function | +| 8 | FUNC-08 | TODO | FUNC-07 | Scanner Guild | Section hash integration: compute `.text` + `.rodata` digests per binary | +| 9 | FUNC-09 | TODO | FUNC-08 | Scanner Guild | Store section hashes in `BinaryIdentity` model | +| 10 | FUNC-10 | TODO | None | Scanner Guild | Entryβ†’sink trace serialization: compact spans with edge list hash | +| 11 | FUNC-11 | TODO | FUNC-10 | Scanner Guild | Serialize traces as `trace_hashes[]` in FuncProof | +| 12 | FUNC-12 | TODO | FUNC-01 | Attestor Guild | DSSE envelope generation for FuncProof (`application/vnd.stellaops.funcproof+json`) | +| 13 | FUNC-13 | TODO | FUNC-12 | Attestor Guild | Rekor transparency log integration for FuncProof | +| 14 | FUNC-14 | TODO | FUNC-12 | Scanner Guild | OCI referrer publishing: push FuncProof alongside image | +| 15 | FUNC-15 | TODO | FUNC-14 | Scanner Guild | SBOM `evidence` link: add CycloneDX `components.evidence` reference to funcproof | +| 16 | FUNC-16 | TODO | FUNC-15 | Scanner Guild | CLI command: `stella scan --funcproof` to generate proofs | +| 17 | FUNC-17 | TODO | FUNC-12 | Scanner Guild | Auditor replay: `stella verify --funcproof ` downloads and verifies hashes | +| 18 | FUNC-18 | TODO | All above | Scanner Guild | Integration tests: full FuncProof pipeline with sample ELF binaries | + +## FuncProof Schema (Target) + +```json +{ + "buildId": "ab12cd34...", + "sections": { + ".text": "blake3:...", + ".rodata": "blake3:..." + }, + "functions": [ + { + "sym": "libfoo::parse_hdr", + "start": "0x401120", + "end": "0x4013af", + "hash": "blake3:..." + } + ], + "traces": [ + "blake3(edge-list-1)", + "blake3(edge-list-2)" + ], + "meta": { + "compiler": "clang-18", + "flags": "-O2 -fno-plt" + } +} +``` + +## Execution Log +| Date (UTC) | Update | Owner | +| --- | --- | --- | +| 2025-12-26 | Sprint created from advisory analysis; implements FuncProof from "Evolving Evidence Models for Reachability". | Project Mgmt | + +## Decisions & Risks +- Decision needed: Hash algorithm (BLAKE3 vs SHA256). Recommend: BLAKE3 for speed. +- Decision needed: Stripped binary handling (heuristics vs fail). Recommend: heuristics with `stripped=true` flag. +- Decision needed: Trace depth limit. Recommend: 10 hops max for compressed paths. +- Risk: Function boundary detection may be imprecise for heavily optimized code. Mitigation: mark confidence per function. +- Risk: Large binaries may produce huge FuncProof files. Mitigation: compress, limit to security-relevant functions. + +## Next Checkpoints +- 2025-12-30 | FUNC-06 complete | Symbol digests populated in reachability models | +- 2026-01-03 | FUNC-12 complete | DSSE signing working | +- 2026-01-06 | FUNC-18 complete | Full integration tested | diff --git a/docs/implplan/SPRINT_20251226_010_FE_visual_diff_enhancements.md b/docs/implplan/SPRINT_20251226_010_FE_visual_diff_enhancements.md new file mode 100644 index 000000000..d47f3bf95 --- /dev/null +++ b/docs/implplan/SPRINT_20251226_010_FE_visual_diff_enhancements.md @@ -0,0 +1,354 @@ +# SPRINT_20251226_010_FE_visual_diff_enhancements + +> **Status:** TODO +> **Priority:** P2 +> **Module:** Frontend (Web) +> **Created:** 2025-12-26 +> **Advisory:** [`25-Dec-2025 - Visual Diffs for Explainable Triage.md`](../product-advisories/25-Dec-2025%20-%20Visual%20Diffs%20for%20Explainable%20Triage.md) + +--- + +## Topic & Scope + +Enhance the existing Smart-Diff UI with visual graph diff capabilities, plain language explanations, and improved interactivity. This sprint addresses the remaining ~20-25% of the Visual Diffs advisory not covered by existing implementation. + +**Existing Infrastructure (already complete):** +- `TriageWorkspaceComponent` - Full triage workspace with tabs, gated buckets, VEX trust +- `ProofTreeComponent` - Merkle tree visualization, evidence chunks +- `smart-diff-ui-architecture.md` - Three-pane layout, delta summary, role-based views +- `DeltaVerdict` backend - Full delta computation, signing, OCI attachment + +**Working directory:** `src/Web/StellaOps.Web/src/app/features/` + +--- + +## Documentation Prerequisites + +- `docs/modules/web/smart-diff-ui-architecture.md` +- `docs/modules/web/README.md` +- `src/Web/StellaOps.Web/src/app/features/triage/triage-workspace.component.ts` +- `src/Web/StellaOps.Web/src/app/shared/components/proof-tree.component.ts` + +--- + +## Delivery Tracker + +| # | Task ID | Status | Depends | Owner | Description | +|---|---------|--------|---------|-------|-------------| +| 1 | VD-ENH-01 | TODO | None | FE Guild | Create `GraphDiffComponent` with node/edge change highlighting | +| 2 | VD-ENH-02 | TODO | VD-ENH-01 | FE Guild | Implement before/after split view for graph comparison | +| 3 | VD-ENH-03 | TODO | VD-ENH-01 | FE Guild | Add interactive graph navigation (hover highlights connected paths) | +| 4 | VD-ENH-04 | TODO | VD-ENH-01 | FE Guild | Add graph zoom/pan controls with minimap | +| 5 | VD-ENH-05 | TODO | None | FE Guild | Create `PlainLanguageToggle` component for "Explain like I'm new" mode | +| 6 | VD-ENH-06 | TODO | VD-ENH-05 | FE Guild | Add plain language explanations for delta categories | +| 7 | VD-ENH-07 | TODO | VD-ENH-05 | FE Guild | Add plain language tooltips for technical terms | +| 8 | VD-ENH-08 | TODO | VD-ENH-01 | FE Guild | Add graph diff export (SVG/PNG) for audit reports | +| 9 | VD-ENH-09 | TODO | None | FE Guild | Merge competitive insights from "Triage UI Lessons" advisory | +| 10 | VD-ENH-10 | TODO | All | FE Guild | Add Storybook stories for new components | +| 11 | VD-ENH-11 | TODO | All | FE Guild | Add unit tests for graph diff logic | +| 12 | VD-ENH-12 | TODO | All | FE Guild | Add E2E tests for visual diff workflow | + +**Total Tasks:** 12 + +--- + +## Task Details + +### VD-ENH-01: GraphDiffComponent + +Create a new Angular component for visualizing reachability/dependency graph diffs with change highlighting. + +**Requirements:** +- Display nodes (components/functions) and edges (call paths) +- Highlight added nodes/edges in green +- Highlight removed nodes/edges in red +- Highlight changed nodes in amber +- Support keyboard navigation (arrow keys, Enter to expand) +- WCAG 2.1 AA accessible (color-blind safe indicators) + +**Component API:** +```typescript +@Component({ + selector: 'stellaops-graph-diff', + standalone: true, +}) +export class GraphDiffComponent { + baseGraph = input(null); + headGraph = input(null); + highlightedNode = input(null); + + nodeSelected = output(); + edgeSelected = output(); +} +``` + +**Location:** `src/Web/StellaOps.Web/src/app/shared/components/graph-diff/` + +--- + +### VD-ENH-02: Before/After Split View + +Implement side-by-side graph comparison mode. + +**Requirements:** +- Split view with synchronized scrolling/zooming +- "Before" (baseline) graph on left, "After" (head) on right +- Linked node selection (selecting in one highlights in both) +- Toggle between split view and unified diff view +- Responsive layout (stack vertically on mobile) + +**Integration:** +- Add to `CompareViewComponent` as view mode option +- Persist view preference in localStorage + +--- + +### VD-ENH-03: Interactive Graph Navigation + +Add hover and click interactions for graph exploration. + +**Requirements:** +- Hover on node: highlight all connected edges and ancestor/descendant nodes +- Click on node: expand detail panel with node metadata +- Double-click: zoom to fit node and immediate neighbors +- Path highlighting: show full call path from entry point to vulnerable function +- Breadcrumb trail for navigation history + +--- + +### VD-ENH-04: Graph Zoom/Pan Controls + +Add navigation controls for large graphs. + +**Requirements:** +- Zoom in/out buttons (+/-) +- Fit-to-view button +- Minimap for large graphs (>50 nodes) +- Mouse wheel zoom with Ctrl modifier +- Touch gesture support (pinch zoom) + +--- + +### VD-ENH-05: PlainLanguageToggle Component + +Create toggle for switching between technical and plain language modes. + +**Requirements:** +- Toggle in header/toolbar area +- Persist preference per user +- Animate transition between modes +- Keyboard accessible (Alt+P shortcut) + +**Component API:** +```typescript +@Component({ + selector: 'stellaops-plain-language-toggle', + standalone: true, +}) +export class PlainLanguageToggleComponent { + enabled = model(false); + + toggled = output(); +} +``` + +--- + +### VD-ENH-06: Plain Language Explanations + +Add human-readable explanations for delta categories. + +**Technical β†’ Plain Language Mapping:** + +| Technical | Plain Language | +|-----------|----------------| +| "Component added with reachable CVE" | "A new library was added that has a known security issue that your code actually uses" | +| "VEX status: not_affected" | "The vendor confirmed this issue doesn't apply to your version" | +| "Reachability: unreachable" | "This vulnerability exists in the code, but your app never actually runs that code" | +| "Risk score delta: +15" | "This release is riskier than the last one - 15 points higher" | +| "KEV flagged" | "Attackers are actively exploiting this vulnerability in the wild" | + +**Implementation:** +- Create `PlainLanguageService` with i18n support +- Add explanations to `DeltaSummaryStripComponent` +- Add explanations to `ItemsPaneComponent` + +--- + +### VD-ENH-07: Plain Language Tooltips + +Add contextual tooltips for technical terms. + +**Terms to explain:** +- SBOM, VEX, CVE, CVSS, EPSS, KEV +- Reachability, Call path, Entry point +- DSSE, Attestation, Merkle proof +- Baseline, Head, Delta + +**Implementation:** +- Create `GlossaryTooltipDirective` +- Auto-detect technical terms and add tooltips +- Link to full documentation for each term + +--- + +### VD-ENH-08: Graph Diff Export + +Add export functionality for audit reports. + +**Requirements:** +- Export to SVG (vector, scalable) +- Export to PNG (raster, with resolution options) +- Include legend with change indicators +- Include metadata (baseline/head digests, timestamp) +- Filename format: `graph-diff-{baseDigest}-{headDigest}.{ext}` + +--- + +### VD-ENH-09: Competitive Insights Integration + +Review "Triage UI Lessons from Competitors" advisory and integrate relevant patterns. + +**Key patterns to evaluate:** +- Snyk's exploitability scoring visualization +- Wiz's attack path diagrams +- Endor Labs' reachability evidence display +- Chainguard's provenance indicators + +**Deliverable:** Design document with recommended adoptions + +--- + +### VD-ENH-10: Storybook Stories + +Add Storybook stories for new components. + +**Stories to create:** +- `graph-diff.stories.ts` - GraphDiffComponent with various states +- `plain-language-toggle.stories.ts` - Toggle in both states +- `graph-controls.stories.ts` - Zoom/pan controls + +**Requirements:** +- Include accessibility annotations +- Add interaction tests +- Document component API in story docs + +--- + +### VD-ENH-11: Unit Tests + +Add unit tests for graph diff logic. + +**Test coverage:** +- Graph diff computation (added/removed/changed nodes) +- Path highlighting algorithm +- Plain language translation +- Export generation + +**Target:** 80% code coverage for new components + +--- + +### VD-ENH-12: E2E Tests + +Add end-to-end tests for visual diff workflow. + +**Scenarios:** +- Load compare view with two digests +- Toggle between split and unified view +- Navigate graph with keyboard +- Export graph diff +- Toggle plain language mode + +**Location:** `src/Web/StellaOps.Web/tests/e2e/visual-diff.spec.ts` + +--- + +## Technical Architecture + +### Graph Rendering + +Use lightweight SVG-based rendering (no heavy dependencies): + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ GraphDiffComponent β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ GraphSvgRenderer β”‚ β”‚ GraphDiffEngine β”‚ β”‚ GraphControls β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ - renderNodes() β”‚ β”‚ - computeDiff() β”‚ β”‚ - zoom() β”‚ β”‚ +β”‚ β”‚ - renderEdges() β”‚ β”‚ - classifyNodes()β”‚ β”‚ - pan() β”‚ β”‚ +β”‚ β”‚ - highlight() β”‚ β”‚ - findPaths() β”‚ β”‚ - fitToView() β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β–Ό β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ SVG Viewport β”‚ β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ [main()]──────▢[parse()]──────▢[vuln_func()] β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ (removed) β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β–Ό β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ └──────▢[safe_func()] (added) β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β–Ό β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ [other()] β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Plain Language Service + +```typescript +@Injectable({ providedIn: 'root' }) +export class PlainLanguageService { + private readonly translations = new Map(); + + translate(technicalTerm: string, context?: TranslationContext): string; + isPlainLanguageEnabled(): Signal; + togglePlainLanguage(): void; +} +``` + +--- + +## Acceptance Criteria + +1. **Graph diff displays correctly** with color-coded change indicators +2. **Split view works** with synchronized navigation +3. **Plain language toggle** persists preference and updates all text +4. **Export produces** valid SVG/PNG with metadata +5. **All new components** have Storybook stories +6. **Test coverage** β‰₯80% for new code +7. **E2E tests pass** for complete visual diff workflow +8. **Accessibility audit** passes WCAG 2.1 AA + +--- + +## Decisions & Risks + +| ID | Decision/Risk | Status | Notes | +|----|---------------|--------|-------| +| D1 | Use SVG-based rendering (no Cytoscape/D3) | DECIDED | Lighter bundle, easier styling | +| D2 | Plain language as user preference, not role-based | DECIDED | More flexible | +| R1 | Large graphs (>200 nodes) may have performance issues | OPEN | May need virtualization | +| R2 | Export quality on high-DPI displays | OPEN | Test on various screen densities | + +--- + +## Execution Log + +| Date (UTC) | Update | Owner | +|------------|--------|-------| +| 2025-12-26 | Sprint created from Visual Diffs advisory gap analysis. Existing implementation covers ~75-80%; this sprint addresses remaining enhancements. | Project Mgmt | + +--- + +## Related Documentation + +- [Smart-Diff UI Architecture](../modules/web/smart-diff-ui-architecture.md) +- [Triage UI Lessons from Competitors](../product-advisories/25-Dec-2025%20-%20Triage%20UI%20Lessons%20from%20Competitors.md) +- [Implementing Diff-Aware Release Gates](../product-advisories/25-Dec-2025%20-%20Implementing%20Diff%E2%80%91Aware%20Release%20Gates.md) diff --git a/docs/implplan/SPRINT_20251226_010_SIGNALS_runtime_stack.md b/docs/implplan/SPRINT_20251226_010_SIGNALS_runtime_stack.md new file mode 100644 index 000000000..8d69a034e --- /dev/null +++ b/docs/implplan/SPRINT_20251226_010_SIGNALS_runtime_stack.md @@ -0,0 +1,81 @@ +# Sprint 20251226 Β· Runtime Stack Capture and Canonicalization + +## Topic & Scope +- Implement eBPF-based stack trace sampling for production workloads. +- Build symbol canonicalization service to resolve PC β†’ (Build-ID, function, offset). +- Create hot symbol index for correlating runtime observations with reachability models. +- **Working directory:** `src/Scanner/StellaOps.Scanner.Analyzers.Native/`, `src/Signals/` + +## Dependencies & Concurrency +- Depends on: `LinuxEbpfCaptureAdapter` (complete for dlopen), `BinaryIdentity` (complete). +- Enhances: SPRINT_20251226_009_SCANNER (symbol digests enable correlation). +- Enables: SPRINT_20251226_011_BE (auto-VEX needs hot symbol detection). + +## Documentation Prerequisites +- `docs/modules/scanner/runtime-evidence.md` +- `docs/modules/signals/architecture.md` +- `docs/product-advisories/25-Dec-2025 - Evolving Evidence Models for Reachability.md` + +## Context: What Already Exists + +| Component | Location | Status | +|-----------|----------|--------| +| LinuxEbpfCaptureAdapter | `Scanner.Native/RuntimeCapture/` | COMPLETE (dlopen hooks only) | +| RuntimeEvidence models | `Scanner.Native/RuntimeCapture/RuntimeEvidence.cs` | COMPLETE | +| ReachabilityLattice (8 states) | `Signals/Lattice/ReachabilityLatticeState.cs` | COMPLETE | +| Evidence-weighted scoring | `Signals/EvidenceWeightedScore/` | COMPLETE | +| Symbol demangler interface | `ISymbolDemangler.cs` | Interface only | + +This sprint adds **stack trace capture** (beyond dlopen) and **symbol canonicalization**. + +## Delivery Tracker +| # | Task ID | Status | Key dependency / next step | Owners | Task Definition | +| --- | --- | --- | --- | --- | --- | +| 1 | STACK-01 | TODO | None | Scanner Guild | Extend eBPF adapter with `bpf_get_stackid` for stack trace sampling | +| 2 | STACK-02 | TODO | STACK-01 | Scanner Guild | Configure sampling rate (default: 49 Hz) and duration per workload | +| 3 | STACK-03 | TODO | STACK-01 | Scanner Guild | Capture user + kernel stacks with PID, container ID, image digest | +| 4 | STACK-04 | TODO | STACK-03 | Scanner Guild | Collapsed stack format: "frameA;frameB;frameC count" (flamegraph-compatible) | +| 5 | STACK-05 | TODO | STACK-04 | Scanner Guild | Include Build-ID tuples in stack records | +| 6 | STACK-06 | TODO | None | Signals Guild | Create `ISymbolCanonicalizationService` interface | +| 7 | STACK-07 | TODO | STACK-06 | Signals Guild | Implement PC β†’ (Build-ID, function, offset) resolution via ELF symbol table | +| 8 | STACK-08 | TODO | STACK-07 | Signals Guild | Language runtime mapping: Java frames via JVMTI, .NET via DAC, Python via symbols | +| 9 | STACK-09 | TODO | STACK-07 | Signals Guild | Slim symbol cache for production (avoid full debuginfod) | +| 10 | STACK-10 | TODO | STACK-04 | Signals Guild | Hot symbol index: track function β†’ observation count with timestamp window | +| 11 | STACK-11 | TODO | STACK-10 | Signals Guild | Persistence: `hot_symbols` PostgreSQL table with Build-ID, symbol, count, window | +| 12 | STACK-12 | TODO | STACK-10 | Signals Guild | API endpoint: `GET /api/v1/signals/hot-symbols?image=` | +| 13 | STACK-13 | TODO | STACK-05 | Scanner Guild | Correlate stacks with SBOM: (image-digest, Build-ID, function) β†’ purl | +| 14 | STACK-14 | TODO | STACK-13 | Scanner Guild | Link to FuncProof: verify observed symbol exists in funcproof | +| 15 | STACK-15 | TODO | STACK-04 | Scanner Guild | Privacy-preserving redaction: hash short-lived arguments, scrub paths | +| 16 | STACK-16 | TODO | STACK-15 | Scanner Guild | Configurable sampling budget: P99 overhead < 1% | +| 17 | STACK-17 | TODO | All above | Signals Guild | Integration tests: stack capture β†’ canonicalization β†’ hot symbol index | + +## Collapsed Stack Format + +``` +api-gw@sha256:abc123;buildid=ab12...;libfoo::parse_hdr+0x3a;net/http::Serve;main 97 +api-gw@sha256:abc123;buildid=ab12...;libfoo::validate+0x12;net/http::Serve;main 42 +``` + +Fields: +- `container@digest`: Image identifier +- `buildid=...`: ELF Build-ID +- `symbol+offset`: Canonical function + offset within function +- `count`: Observation frequency + +## Execution Log +| Date (UTC) | Update | Owner | +| --- | --- | --- | +| 2025-12-26 | Sprint created from advisory analysis; implements runtime stack capture from "Evolving Evidence Models". | Project Mgmt | + +## Decisions & Risks +- Decision needed: Sampling frequency (49 Hz vs 99 Hz). Recommend: 49 Hz for production safety. +- Decision needed: Stack depth limit. Recommend: 64 frames max. +- Decision needed: Symbol cache strategy. Recommend: slim cache in pod, full cache in cluster service. +- Risk: High overhead in CPU-bound workloads. Mitigation: adaptive sampling based on CPU load. +- Risk: Java/.NET frame resolution requires JIT metadata. Mitigation: fallback to address-only if JIT info unavailable. +- Risk: Privacy concerns with stack traces. Mitigation: redaction + short retention (24h default). + +## Next Checkpoints +- 2025-12-30 | STACK-05 complete | Stack capture with Build-ID working | +- 2026-01-03 | STACK-11 complete | Hot symbol index persisted | +- 2026-01-06 | STACK-17 complete | Full integration tested | diff --git a/docs/implplan/SPRINT_20251226_011_BE_auto_vex_downgrade.md b/docs/implplan/SPRINT_20251226_011_BE_auto_vex_downgrade.md new file mode 100644 index 000000000..a10ce751b --- /dev/null +++ b/docs/implplan/SPRINT_20251226_011_BE_auto_vex_downgrade.md @@ -0,0 +1,103 @@ +# Sprint 20251226 Β· Auto-VEX Downgrade Based on Runtime Observation + +## Topic & Scope +- Implement automatic VEX status downgrade when vulnerable symbols are observed in production. +- Generate DSSE-signed VEX statements with runtime evidence attachment. +- Integrate with policy gates and notification routing. +- **Working directory:** `src/Policy/`, `src/Excititor/`, `src/Signals/`, `src/Notify/` + +## Dependencies & Concurrency +- Depends on: SPRINT_20251226_009_SCANNER (FuncProof for symbol correlation). +- Depends on: SPRINT_20251226_010_SIGNALS (hot symbol index for detection). +- Can start API/schema work in parallel while waiting for upstream sprints. + +## Documentation Prerequisites +- `docs/modules/signals/architecture.md` +- `docs/modules/policy/architecture.md` +- `docs/modules/excititor/architecture.md` +- `docs/product-advisories/25-Dec-2025 - Evolving Evidence Models for Reachability.md` + +## Context: What Already Exists + +| Component | Location | Status | +|-----------|----------|--------| +| VEX ingestion/emission | `Excititor/` | COMPLETE | +| ReachabilityLattice (8 states) | `Signals/Lattice/` | COMPLETE | +| Evidence-weighted scoring | `Signals/EvidenceWeightedScore/` | COMPLETE | +| DSSE signing | `Signer/` | COMPLETE | +| Policy gates (drift gate) | `Policy/Gates/DriftGateEvaluator.cs` | COMPLETE | +| Notification routing | `Notify/` | COMPLETE | + +This sprint adds **runtime-triggered VEX state transitions**. + +## Delivery Tracker +| # | Task ID | Status | Key dependency / next step | Owners | Task Definition | +| --- | --- | --- | --- | --- | --- | +| 1 | AUTOVEX-01 | TODO | None | Policy Guild | Define hot vulnerable symbol detection logic: (CVE, symbol_digest) in hot_symbols | +| 2 | AUTOVEX-02 | TODO | AUTOVEX-01 | Policy Guild | Threshold configuration: minimum observation count/percentage for downgrade | +| 3 | AUTOVEX-03 | TODO | AUTOVEX-02 | Excititor Guild | VEX downgrade generation: emit `affected` status with evidence | +| 4 | AUTOVEX-04 | TODO | AUTOVEX-03 | Excititor Guild | Evidence attachment: stacks (top 5), percentiles, Build-IDs, timestamp window | +| 5 | AUTOVEX-05 | TODO | AUTOVEX-03 | Excititor Guild | DSSE signing for VEX downgrade statement | +| 6 | AUTOVEX-06 | TODO | AUTOVEX-05 | Excititor Guild | Rekor logging for VEX downgrade transparency | +| 7 | AUTOVEX-07 | TODO | AUTOVEX-03 | Policy Guild | Update reachability lattice: RuntimeObserved β†’ ConfirmedReachable | +| 8 | AUTOVEX-08 | TODO | AUTOVEX-07 | Policy Guild | Trigger DriftGateEvaluator re-evaluation on VEX downgrade | +| 9 | AUTOVEX-09 | TODO | AUTOVEX-03 | Signals Guild | Update EvidenceWeightedScore: RTS dimension reflects runtime observation | +| 10 | AUTOVEX-10 | TODO | AUTOVEX-08 | Notify Guild | Notification template: "CVE-XXXX observed in libfoo::parse_hdr (17% CPU)" | +| 11 | AUTOVEX-11 | TODO | AUTOVEX-08 | Policy Guild | Policy gate action: quarantine, canary freeze, release block options | +| 12 | AUTOVEX-12 | TODO | None | Policy Guild | Time-boxed confidence: maintain not_affected if symbol never observed (with TTL) | +| 13 | AUTOVEX-13 | TODO | AUTOVEX-12 | Policy Guild | TTL configuration: default 7 days, configurable per environment | +| 14 | AUTOVEX-14 | TODO | AUTOVEX-12 | Excititor Guild | Emit VEX with justification `not_reachable_at_runtime` and conditions | +| 15 | AUTOVEX-15 | TODO | AUTOVEX-06 | Policy Guild | CLI command: `stella vex auto-downgrade --check ` for manual trigger | +| 16 | AUTOVEX-16 | TODO | All above | Policy Guild | Integration tests: symbol observation β†’ VEX downgrade β†’ gate block | + +## Auto-VEX Evidence Schema + +```json +{ + "type": "openvex", + "statement": { + "vulnerability": "CVE-2025-XXXX", + "product": "pkg:oci/api-gw@sha256:abc123", + "status": "affected", + "status_notes": "Vulnerable symbol observed in production", + "evidence": { + "runtime_observation": { + "symbol": "libfoo::parse_hdr", + "symbol_digest": "blake3:...", + "build_id": "ab12cd34...", + "observation_window": { + "start": "2025-12-26T12:00:00Z", + "end": "2025-12-26T14:00:00Z" + }, + "cpu_percentage": 17.3, + "top_stacks": [ + "api-gw;libfoo::parse_hdr+0x3a;net/http::Serve;main 97" + ], + "container_ids": ["abc123", "def456"] + }, + "static_proof": { + "funcproof_uri": "oci://registry/api-gw@sha256:abc123/funcproof", + "funcproof_digest": "sha256:..." + } + } + } +} +``` + +## Execution Log +| Date (UTC) | Update | Owner | +| --- | --- | --- | +| 2025-12-26 | Sprint created from advisory analysis; implements auto-VEX from "Evolving Evidence Models". | Project Mgmt | + +## Decisions & Risks +- Decision needed: Downgrade threshold (1% CPU? 5%?). Recommend: configurable per CVE severity. +- Decision needed: Auto-downgrade scope (all images or per-image). Recommend: per-image with inheritance. +- Decision needed: Human approval required for high-severity auto-downgrade. Recommend: approval for KEV, auto for others. +- Risk: False positives from sampling noise. Mitigation: require minimum observation count (default: 10). +- Risk: Rapid VEX state thrashing. Mitigation: hysteresis (upgrade requires 24h of no observation). +- Risk: Notification fatigue. Mitigation: aggregate downgrades, configurable quiet hours. + +## Next Checkpoints +- 2025-12-30 | AUTOVEX-06 complete | VEX downgrade with DSSE signing working | +- 2026-01-03 | AUTOVEX-11 complete | Policy gate integration functional | +- 2026-01-06 | AUTOVEX-16 complete | Full integration tested | diff --git a/docs/implplan/SPRINT_20251226_011_BINIDX_known_build_catalog.md b/docs/implplan/SPRINT_20251226_011_BINIDX_known_build_catalog.md new file mode 100644 index 000000000..dc5a0a656 --- /dev/null +++ b/docs/implplan/SPRINT_20251226_011_BINIDX_known_build_catalog.md @@ -0,0 +1,214 @@ +# SPRINT_20251226_011_BINIDX_known_build_catalog + +> **Status:** TODO +> **Priority:** P1 +> **Module:** BinaryIndex +> **Created:** 2025-12-26 +> **Architecture:** [`docs/modules/binaryindex/architecture.md`](../modules/binaryindex/architecture.md) +> **Advisory:** [`26-Dec-2026 - Mapping a Binary Intelligence Graph.md`](../product-advisories/26-Dec-2026%20-%20Mapping%20a%20Binary%20Intelligence%20Graph.md) (SUPERSEDED) + +--- + +## Topic & Scope + +Implement the foundational **Known-Build Binary Catalog** - the first MVP tier that enables querying "is this Build-ID vulnerable?" with distro-level precision. + +**Goal:** Query binary vulnerability by Build-ID/PE signature with distro-specific accuracy. + +**Working directory:** `src/BinaryIndex/` + +--- + +## Documentation Prerequisites + +- `docs/modules/binaryindex/architecture.md` +- `docs/db/schemas/binaries_schema_specification.md` (to be created) +- `src/BinaryIndex/__Libraries/StellaOps.BinaryIndex.Core/` + +--- + +## Delivery Tracker + +| # | Task ID | Status | Depends | Owner | Description | +|---|---------|--------|---------|-------|-------------| +| 1 | BINCAT-01 | TODO | None | BE Guild | Create `binaries` PostgreSQL schema with RLS | +| 2 | BINCAT-02 | TODO | BINCAT-01 | BE Guild | Implement `binary_identity` table and migrations | +| 3 | BINCAT-03 | TODO | BINCAT-01 | BE Guild | Implement `binary_package_map` table for Build-ID β†’ package mapping | +| 4 | BINCAT-04 | TODO | BINCAT-01 | BE Guild | Implement `vulnerable_buildids` table for known-vulnerable binaries | +| 5 | BINCAT-05 | TODO | BINCAT-01 | BE Guild | Implement `corpus_snapshots` table for ingestion tracking | +| 6 | BINCAT-06 | TODO | None | BE Guild | Create `IBinaryIdentityRepository` interface and implementation | +| 7 | BINCAT-07 | TODO | BINCAT-06 | BE Guild | Implement `BinaryIdentityRepository` with PostgreSQL persistence | +| 8 | BINCAT-08 | TODO | None | BE Guild | Enhance `ElfFeatureExtractor` with full Build-ID extraction | +| 9 | BINCAT-09 | TODO | None | BE Guild | Create `PeFeatureExtractor` for Windows PE CodeView GUID extraction | +| 10 | BINCAT-10 | TODO | None | BE Guild | Create `MachoFeatureExtractor` for Mach-O LC_UUID extraction | +| 11 | BINCAT-11 | TODO | None | BE Guild | Finalize `DebianCorpusConnector` implementation | +| 12 | BINCAT-12 | TODO | BINCAT-11 | BE Guild | Implement `DebianMirrorPackageSource` for mirror interaction | +| 13 | BINCAT-13 | TODO | BINCAT-11 | BE Guild | Implement `DebianPackageExtractor` for .deb binary extraction | +| 14 | BINCAT-14 | TODO | BINCAT-11 | BE Guild | Create corpus snapshot persistence in `CorpusSnapshotRepository` | +| 15 | BINCAT-15 | TODO | BINCAT-06,BINCAT-08 | BE Guild | Implement basic `IBinaryVulnerabilityService.LookupByIdentityAsync` | +| 16 | BINCAT-16 | TODO | BINCAT-15 | BE Guild | Implement batch lookup `LookupBatchAsync` for scan performance | +| 17 | BINCAT-17 | TODO | All | BE Guild | Add unit tests for identity extraction (ELF, PE, Mach-O) | +| 18 | BINCAT-18 | TODO | All | BE Guild | Add integration tests with Testcontainers PostgreSQL | +| 19 | BINCAT-19 | TODO | BINCAT-01 | BE Guild | Create database schema specification document | +| 20 | BINCAT-20 | TODO | All | BE Guild | Add OpenTelemetry traces for lookup operations | + +**Total Tasks:** 20 + +--- + +## Task Details + +### BINCAT-01: PostgreSQL Schema with RLS + +Create the `binaries` schema with Row-Level Security for tenant isolation. + +**Requirements:** +```sql +CREATE SCHEMA IF NOT EXISTS binaries; +CREATE SCHEMA IF NOT EXISTS binaries_app; + +-- RLS helper function +CREATE OR REPLACE FUNCTION binaries_app.require_current_tenant() +RETURNS TEXT LANGUAGE plpgsql STABLE SECURITY DEFINER AS $$ +DECLARE v_tenant TEXT; +BEGIN + v_tenant := current_setting('app.tenant_id', true); + IF v_tenant IS NULL OR v_tenant = '' THEN + RAISE EXCEPTION 'app.tenant_id session variable not set'; + END IF; + RETURN v_tenant; +END; +$$; +``` + +**Location:** `src/BinaryIndex/__Libraries/StellaOps.BinaryIndex.Persistence/Migrations/` + +--- + +### BINCAT-02: binary_identity Table + +Store known binary identities with all extraction methods. + +**Schema:** +```sql +CREATE TABLE binaries.binary_identity ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + tenant_id TEXT NOT NULL DEFAULT binaries_app.require_current_tenant(), + binary_key TEXT NOT NULL, -- Canonical key + format TEXT NOT NULL, -- elf, pe, macho + build_id TEXT, -- ELF GNU Build-ID + build_id_type TEXT, -- gnu, go, sha1 + pe_codeview_guid TEXT, -- PE CodeView GUID + pe_imphash TEXT, -- PE import hash + macho_uuid TEXT, -- Mach-O LC_UUID + file_sha256 TEXT NOT NULL, -- Whole file hash + text_sha256 TEXT, -- .text section hash + architecture TEXT NOT NULL, -- x86_64, aarch64, etc. + compiler_hint TEXT, -- gcc-13.2, clang-18 + source_hint TEXT, -- Package name/version if known + indexed_at TIMESTAMPTZ NOT NULL DEFAULT now(), + UNIQUE (tenant_id, binary_key) +); + +ALTER TABLE binaries.binary_identity ENABLE ROW LEVEL SECURITY; +CREATE POLICY tenant_isolation ON binaries.binary_identity + USING (tenant_id = binaries_app.require_current_tenant()); +``` + +--- + +### BINCAT-08: Enhanced ElfFeatureExtractor + +Enhance existing `ElfFeatureExtractor` with complete feature extraction. + +**Requirements:** +- Extract GNU Build-ID from `.note.gnu.build-id` +- Extract Go Build-ID if present +- Compute `.text` section SHA-256 +- Extract DT_NEEDED dynamic dependencies +- Extract exported/imported symbols +- Detect hardening flags (RELRO, PIE, NX, stack canary) + +**Existing file:** `src/BinaryIndex/__Libraries/StellaOps.BinaryIndex.Core/Services/ElfFeatureExtractor.cs` + +--- + +### BINCAT-09: PeFeatureExtractor + +Create PE (Windows) binary feature extractor. + +**Requirements:** +- Extract CodeView GUID + Age from debug directory +- Compute import hash (imphash) +- Extract PE timestamp and linker version +- Extract DLL imports +- Detect ASLR/DEP/CFG flags + +**Location:** `src/BinaryIndex/__Libraries/StellaOps.BinaryIndex.Core/Services/PeFeatureExtractor.cs` + +--- + +### BINCAT-10: MachoFeatureExtractor + +Create Mach-O (macOS/iOS) binary feature extractor. + +**Requirements:** +- Extract LC_UUID from load commands +- Compute __TEXT section hash +- Extract dylib dependencies +- Detect code signing info + +**Location:** `src/BinaryIndex/__Libraries/StellaOps.BinaryIndex.Core/Services/MachoFeatureExtractor.cs` + +--- + +### BINCAT-11: DebianCorpusConnector + +Finalize the Debian corpus connector for binary ingestion. + +**Requirements:** +- Connect to Debian/Ubuntu mirrors +- Fetch package lists for specified releases +- Track snapshot state in `corpus_snapshots` table +- Support incremental updates + +**Existing file:** `src/BinaryIndex/__Libraries/StellaOps.BinaryIndex.Corpus.Debian/DebianCorpusConnector.cs` + +--- + +## Acceptance Criteria + +1. **Schema deployed** with RLS policies active +2. **Build-ID extraction** works for ELF binaries +3. **PE GUID extraction** works for Windows binaries +4. **Mach-O UUID extraction** works for macOS binaries +5. **Debian connector** can ingest packages from mirror +6. **Lookup service** returns matches by Build-ID +7. **Integration tests** pass with Testcontainers +8. **Metrics exported** for lookup latency and counts + +--- + +## Decisions & Risks + +| ID | Decision/Risk | Status | Notes | +|----|---------------|--------|-------| +| D1 | Use composite binary_key for canonical identification | DECIDED | Format: `{format}:{arch}:{build_id or hash}` | +| D2 | Store hashes as TEXT not BYTEA | DECIDED | Easier debugging, hex format | +| R1 | Large corpus ingestion may take hours | OPEN | Consider background job with progress tracking | +| R2 | Mirror availability varies by region | OPEN | Support multiple mirror fallbacks | + +--- + +## Execution Log + +| Date (UTC) | Update | Owner | +|------------|--------|-------| +| 2025-12-26 | Sprint created from BinaryIndex MVP roadmap. | Project Mgmt | + +--- + +## Related Documentation + +- [BinaryIndex Architecture](../modules/binaryindex/architecture.md) +- [Scanner Native Analysis](../modules/scanner/analyzers/native.md) diff --git a/docs/implplan/SPRINT_20251226_012_BINIDX_backport_handling.md b/docs/implplan/SPRINT_20251226_012_BINIDX_backport_handling.md new file mode 100644 index 000000000..322aceea0 --- /dev/null +++ b/docs/implplan/SPRINT_20251226_012_BINIDX_backport_handling.md @@ -0,0 +1,234 @@ +# SPRINT_20251226_012_BINIDX_backport_handling + +> **Status:** TODO +> **Priority:** P1 +> **Module:** BinaryIndex +> **Created:** 2025-12-26 +> **Depends On:** [`SPRINT_20251226_011_BINIDX_known_build_catalog.md`](./SPRINT_20251226_011_BINIDX_known_build_catalog.md) +> **Architecture:** [`docs/modules/binaryindex/architecture.md`](../modules/binaryindex/architecture.md) + +--- + +## Topic & Scope + +Implement **Patch-Aware Backport Handling** - the second MVP tier that handles "version says vulnerable but distro backported the fix" scenarios. + +**Goal:** Detect when a distro has backported a security fix without bumping the upstream version. + +**Working directory:** `src/BinaryIndex/` + +--- + +## Documentation Prerequisites + +- `docs/modules/binaryindex/architecture.md` +- `src/BinaryIndex/__Libraries/StellaOps.BinaryIndex.FixIndex/` +- Debian changelog format: https://www.debian.org/doc/debian-policy/ch-source.html#s-dpkgchangelog +- DEP-3 patch header format: https://dep-team.pages.debian.net/deps/dep3/ + +--- + +## Delivery Tracker + +| # | Task ID | Status | Depends | Owner | Description | +|---|---------|--------|---------|-------|-------------| +| 1 | BACKPORT-01 | TODO | None | BE Guild | Create `cve_fix_index` table for patch-aware fix status | +| 2 | BACKPORT-02 | TODO | BACKPORT-01 | BE Guild | Create `fix_evidence` table for audit trail | +| 3 | BACKPORT-03 | TODO | None | BE Guild | Finalize `DebianChangelogParser` implementation | +| 4 | BACKPORT-04 | TODO | None | BE Guild | Finalize `PatchHeaderParser` for DEP-3 format | +| 5 | BACKPORT-05 | TODO | None | BE Guild | Finalize `AlpineSecfixesParser` for Alpine APKBUILD | +| 6 | BACKPORT-06 | TODO | None | BE Guild | Create `RpmChangelogParser` for RPM spec files | +| 7 | BACKPORT-07 | TODO | None | BE Guild | Create `IFixIndexBuilder` implementation | +| 8 | BACKPORT-08 | TODO | BACKPORT-07 | BE Guild | Implement `FixIndexBuilder.BuildIndexAsync` for Debian | +| 9 | BACKPORT-09 | TODO | BACKPORT-07 | BE Guild | Implement `FixIndexBuilder.BuildIndexAsync` for Alpine | +| 10 | BACKPORT-10 | TODO | BACKPORT-07 | BE Guild | Implement `FixIndexBuilder.BuildIndexAsync` for RPM | +| 11 | BACKPORT-11 | TODO | BACKPORT-01 | BE Guild | Create `IFixIndexRepository` interface | +| 12 | BACKPORT-12 | TODO | BACKPORT-11 | BE Guild | Implement `FixIndexRepository` with PostgreSQL | +| 13 | BACKPORT-13 | TODO | BACKPORT-12 | BE Guild | Add `GetFixStatusAsync` to `IBinaryVulnerabilityService` | +| 14 | BACKPORT-14 | TODO | None | BE Guild | Create `RpmCorpusConnector` for RHEL/Fedora/CentOS | +| 15 | BACKPORT-15 | TODO | BACKPORT-14 | BE Guild | Implement SRPM changelog extraction | +| 16 | BACKPORT-16 | TODO | BACKPORT-05 | BE Guild | Create `AlpineCorpusConnector` for Alpine APK | +| 17 | BACKPORT-17 | TODO | BACKPORT-16 | BE Guild | Implement APKBUILD secfixes extraction | +| 18 | BACKPORT-18 | TODO | All | BE Guild | Add confidence scoring for fix evidence | +| 19 | BACKPORT-19 | TODO | All | BE Guild | Add unit tests for all parsers | +| 20 | BACKPORT-20 | TODO | All | BE Guild | Add integration tests for fix index building | +| 21 | BACKPORT-21 | TODO | All | BE Guild | Document fix evidence chain in architecture doc | + +**Total Tasks:** 21 + +--- + +## Task Details + +### BACKPORT-01: cve_fix_index Table + +Store patch-aware CVE fix status per distro/release/package. + +**Schema:** +```sql +CREATE TABLE binaries.cve_fix_index ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + tenant_id TEXT NOT NULL DEFAULT binaries_app.require_current_tenant(), + distro TEXT NOT NULL, -- debian, ubuntu, alpine, rhel + release TEXT NOT NULL, -- bookworm, jammy, v3.19 + source_pkg TEXT NOT NULL, -- Source package name + cve_id TEXT NOT NULL, -- CVE-YYYY-NNNN + state TEXT NOT NULL, -- fixed, vulnerable, not_affected, wontfix, unknown + fixed_version TEXT, -- Distro version string where fixed + method TEXT NOT NULL, -- security_feed, changelog, patch_header, upstream_match + confidence DECIMAL(3,2) NOT NULL, -- 0.00-1.00 + evidence_id UUID, -- Reference to fix_evidence + snapshot_id UUID, -- Corpus snapshot this came from + indexed_at TIMESTAMPTZ NOT NULL DEFAULT now(), + UNIQUE (tenant_id, distro, release, source_pkg, cve_id) +); + +CREATE INDEX idx_cve_fix_lookup ON binaries.cve_fix_index + (tenant_id, distro, release, source_pkg, cve_id); +``` + +--- + +### BACKPORT-03: DebianChangelogParser + +Parse Debian/Ubuntu changelog files for CVE fix mentions. + +**Input format:** +``` +package (1.2.3-4) bookworm-security; urgency=high + + * Fix CVE-2024-1234: buffer overflow in parse_header + * Fix CVE-2024-1235: use-after-free in cleanup + + -- Maintainer Mon, 01 Jan 2024 12:00:00 +0000 +``` + +**Requirements:** +- Extract CVE mentions from changelog entries +- Map to version where fix appeared +- Handle multiple CVEs per entry +- Support urgency levels + +**Existing file:** `src/BinaryIndex/__Libraries/StellaOps.BinaryIndex.FixIndex/Parsers/DebianChangelogParser.cs` + +--- + +### BACKPORT-04: PatchHeaderParser + +Parse DEP-3 patch headers for upstream patch references. + +**Input format:** +``` +Description: Fix buffer overflow in parse_header +Origin: upstream, https://github.com/project/commit/abc123 +Bug-Debian: https://bugs.debian.org/123456 +CVE: CVE-2024-1234 +Applied-Upstream: 1.2.4 +``` + +**Requirements:** +- Extract CVE references +- Extract upstream commit/version +- Extract bug tracker references +- Calculate confidence based on origin + +**Existing file:** `src/BinaryIndex/__Libraries/StellaOps.BinaryIndex.FixIndex/Parsers/PatchHeaderParser.cs` + +--- + +### BACKPORT-05: AlpineSecfixesParser + +Parse Alpine APKBUILD secfixes section. + +**Input format:** +``` +# secfixes: +# 1.2.3-r1: +# - CVE-2024-1234 +# - CVE-2024-1235 +# 1.2.2-r0: +# - CVE-2024-1000 +``` + +**Requirements:** +- Parse secfixes comment block +- Map CVEs to Alpine version strings +- Handle version ranges + +**Existing file:** `src/BinaryIndex/__Libraries/StellaOps.BinaryIndex.FixIndex/Parsers/AlpineSecfixesParser.cs` + +--- + +### BACKPORT-06: RpmChangelogParser + +Parse RPM spec file changelog for CVE mentions. + +**Input format:** +``` +%changelog +* Mon Jan 01 2024 Packager - 1.2.3-4 +- Fix CVE-2024-1234 +- Backport upstream security patches +``` + +**Requirements:** +- Parse RPM spec %changelog section +- Extract CVE mentions +- Map to NEVRA version + +**Location:** `src/BinaryIndex/__Libraries/StellaOps.BinaryIndex.FixIndex/Parsers/RpmChangelogParser.cs` + +--- + +### BACKPORT-18: Confidence Scoring + +Implement confidence scoring for fix evidence. + +**Confidence Levels:** +| Method | Base Confidence | Notes | +|--------|-----------------|-------| +| Security Feed (OVAL) | 0.99 | Authoritative | +| Patch Header with upstream ref | 0.95 | Strong evidence | +| Changelog with CVE mention | 0.85 | Good evidence | +| Changelog inference | 0.70 | Version-based inference | +| Upstream patch match | 0.90 | Binary diff match | + +--- + +## Acceptance Criteria + +1. **Fix index populated** for Debian/Ubuntu packages +2. **Changelog parser** correctly extracts CVE fixes +3. **Patch header parser** handles DEP-3 format +4. **Alpine secfixes** parsed correctly +5. **GetFixStatusAsync** returns backport status +6. **Confidence scores** calculated per method +7. **Evidence chain** auditable +8. **Integration tests** cover all distros + +--- + +## Decisions & Risks + +| ID | Decision/Risk | Status | Notes | +|----|---------------|--------|-------| +| D1 | Prioritize security feed over changelog when conflicting | DECIDED | Feed is authoritative | +| D2 | Store raw evidence excerpts for audit | DECIDED | Truncate at 1KB | +| R1 | Changelog parsing may have false positives | OPEN | Use confidence scoring | +| R2 | Some distros don't maintain consistent CVE references | OPEN | Flag as "unknown" with low confidence | + +--- + +## Execution Log + +| Date (UTC) | Update | Owner | +|------------|--------|-------| +| 2025-12-26 | Sprint created from BinaryIndex MVP roadmap. | Project Mgmt | + +--- + +## Related Documentation + +- [BinaryIndex Architecture](../modules/binaryindex/architecture.md) +- [Debian Policy - Changelogs](https://www.debian.org/doc/debian-policy/ch-source.html) +- [DEP-3 Patch Tagging Guidelines](https://dep-team.pages.debian.net/deps/dep3/) diff --git a/docs/implplan/SPRINT_20251226_012_FE_smart_diff_compare.md b/docs/implplan/SPRINT_20251226_012_FE_smart_diff_compare.md new file mode 100644 index 000000000..6ae275044 --- /dev/null +++ b/docs/implplan/SPRINT_20251226_012_FE_smart_diff_compare.md @@ -0,0 +1,99 @@ +# Sprint 20251226 Β· Smart-Diff Three-Pane Compare View + +## Topic & Scope +- Implement the three-pane Smart-Diff Compare View as designed in `docs/modules/web/smart-diff-ui-architecture.md`. +- Build baseline selector, delta summary strip, categories/items/proof pane layout. +- Implement role-based defaults (Developer/Security/Audit) and trust indicators. +- **Working directory:** `src/Web/StellaOps.Web` + +## Dependencies & Concurrency +- Depends on: SPRINT_20251226_004_FE (risk dashboard components), SPRINT_20251226_001_BE (gate API). +- Can run in parallel with: SPRINT_20251226_013_FE (triage canvas). +- Enhances: SPRINT_20251226_004_FE by adding detailed comparison capability. + +## Documentation Prerequisites +- `docs/modules/web/smart-diff-ui-architecture.md` (REQUIRED - primary design reference) +- `docs/product-advisories/25-Dec-2025 - Visual Diffs for Explainable Triage.md` +- `docs/product-advisories/25-Dec-2025 - Triage UI Lessons from Competitors.md` +- Angular 17 patterns in existing codebase + +## Context: What Already Exists + +| Component | Location | Status | +|-----------|----------|--------| +| Smart-Diff Architecture | `docs/modules/web/smart-diff-ui-architecture.md` | COMPLETE (design only) | +| Release Flow | `features/releases/release-flow.component.ts` | COMPLETE | +| Policy Gate Indicator | `features/releases/policy-gate-indicator.component.ts` | COMPLETE | +| Confidence Badge | `shared/components/confidence-badge.component.ts` | COMPLETE | +| Evidence Page | `features/evidence/evidence-page.component.ts` | PARTIAL | +| Determinism Badge | `features/scans/determinism-badge.component.ts` | COMPLETE | + +This sprint implements the **three-pane compare view** from the architecture specification. + +## Delivery Tracker +| # | Task ID | Status | Key dependency / next step | Owners | Task Definition | +| --- | --- | --- | --- | --- | --- | +| 1 | SDIFF-01 | TODO | None | Frontend Guild | Create `CompareService` Angular service with baseline recommendations API | +| 2 | SDIFF-02 | TODO | SDIFF-01 | Frontend Guild | Create `DeltaComputeService` for idempotent delta computation | +| 3 | SDIFF-03 | TODO | None | Frontend Guild | `CompareViewComponent` container with signals-based state management | +| 4 | SDIFF-04 | TODO | SDIFF-03 | Frontend Guild | `BaselineSelectorComponent` with dropdown and rationale display | +| 5 | SDIFF-05 | TODO | SDIFF-04 | Frontend Guild | `BaselineRationaleComponent` explaining baseline selection logic | +| 6 | SDIFF-06 | TODO | SDIFF-03 | Frontend Guild | `TrustIndicatorsComponent` showing determinism hash, policy version, feed snapshot | +| 7 | SDIFF-07 | TODO | SDIFF-06 | Frontend Guild | `DeterminismHashDisplay` with copy button and verification status | +| 8 | SDIFF-08 | TODO | SDIFF-06 | Frontend Guild | `SignatureStatusDisplay` with DSSE verification result | +| 9 | SDIFF-09 | TODO | SDIFF-06 | Frontend Guild | `PolicyDriftIndicator` warning if policy changed since baseline | +| 10 | SDIFF-10 | TODO | SDIFF-03 | Frontend Guild | `DeltaSummaryStripComponent`: [+N added] [-N removed] [~N changed] counts | +| 11 | SDIFF-11 | TODO | SDIFF-10 | Frontend Guild | `ThreePaneLayoutComponent` responsive container for Categories/Items/Proof | +| 12 | SDIFF-12 | TODO | SDIFF-11 | Frontend Guild | `CategoriesPaneComponent`: SBOM, Reachability, VEX, Policy, Unknowns with counts | +| 13 | SDIFF-13 | TODO | SDIFF-12 | Frontend Guild | `ItemsPaneComponent` with virtual scrolling for large deltas (cdk-virtual-scroll) | +| 14 | SDIFF-14 | TODO | SDIFF-13 | Frontend Guild | Priority score display with color-coded severity | +| 15 | SDIFF-15 | TODO | SDIFF-11 | Frontend Guild | `ProofPaneComponent` container for evidence details | +| 16 | SDIFF-16 | TODO | SDIFF-15 | Frontend Guild | `WitnessPathComponent`: entryβ†’sink call path visualization | +| 17 | SDIFF-17 | TODO | SDIFF-15 | Frontend Guild | `VexMergeExplanationComponent`: vendor + distro + org β†’ merged result | +| 18 | SDIFF-18 | TODO | SDIFF-15 | Frontend Guild | `EnvelopeHashesComponent`: display content-addressed hashes | +| 19 | SDIFF-19 | TODO | SDIFF-03 | Frontend Guild | `ActionablesPanelComponent`: prioritized recommendations list | +| 20 | SDIFF-20 | TODO | SDIFF-03 | Frontend Guild | `ExportActionsComponent`: copy replay command, download evidence pack | +| 21 | SDIFF-21 | TODO | SDIFF-03 | Frontend Guild | Role-based view switching: Developer/Security/Audit defaults | +| 22 | SDIFF-22 | TODO | SDIFF-21 | Frontend Guild | User preference persistence for role and panel states | +| 23 | SDIFF-23 | TODO | SDIFF-13 | Frontend Guild | Micro-interaction: hover badge explaining "why it changed" | +| 24 | SDIFF-24 | TODO | SDIFF-17 | Frontend Guild | Micro-interaction: click rule β†’ spotlight affected subgraph | +| 25 | SDIFF-25 | TODO | SDIFF-03 | Frontend Guild | "Explain like I'm new" toggle expanding jargon to plain language | +| 26 | SDIFF-26 | TODO | SDIFF-20 | Frontend Guild | "Copy audit bundle" one-click export as JSON attachment | +| 27 | SDIFF-27 | TODO | SDIFF-03 | Frontend Guild | Keyboard navigation: Tab/Arrow/Enter/Escape/C shortcuts | +| 28 | SDIFF-28 | TODO | SDIFF-27 | Frontend Guild | ARIA labels and screen reader live regions | +| 29 | SDIFF-29 | TODO | SDIFF-03 | Frontend Guild | Degraded mode: warning banner when signature verification fails | +| 30 | SDIFF-30 | TODO | SDIFF-11 | Frontend Guild | "Changed neighborhood only" default with mini-map for large graphs | +| 31 | SDIFF-31 | TODO | All above | Frontend Guild | Unit tests for all new components | +| 32 | SDIFF-32 | TODO | SDIFF-31 | Frontend Guild | E2E tests: full comparison workflow | +| 33 | SDIFF-33 | TODO | SDIFF-32 | Frontend Guild | Integration tests: API service calls and response handling | + +## Routing Configuration + +```typescript +// From smart-diff-ui-architecture.md +{ + path: 'compare', + children: [ + { path: ':currentDigest', component: CompareViewComponent }, + { path: ':currentDigest/:baselineDigest', component: CompareViewComponent } + ] +} +``` + +## Execution Log +| Date (UTC) | Update | Owner | +| --- | --- | --- | +| 2025-12-26 | Sprint created from "Triage UI Lessons from Competitors" analysis; implements Smart-Diff Compare View. | Project Mgmt | + +## Decisions & Risks +- Decision needed: Virtual scroll item height. Recommend: 56px consistent with Angular Material. +- Decision needed: Max graph nodes in witness path. Recommend: 25 nodes, "show more" for larger paths. +- Decision needed: Export format for audit bundle. Recommend: JSON-LD with DSSE envelope. +- Risk: Large deltas may exceed 1000 items. Mitigation: category pre-filtering, virtual scroll. +- Risk: Complex witness paths hard to visualize. Mitigation: collapsed by default, expand on demand. +- Risk: Keyboard shortcuts may conflict with browser. Mitigation: only active when component focused. + +## Next Checkpoints +- 2026-01-03 | SDIFF-11 complete | Three-pane layout functional | +- 2026-01-08 | SDIFF-20 complete | Core comparison features working | +- 2026-01-13 | SDIFF-33 complete | Full implementation with tests | diff --git a/docs/implplan/SPRINT_20251226_013_BINIDX_fingerprint_factory.md b/docs/implplan/SPRINT_20251226_013_BINIDX_fingerprint_factory.md new file mode 100644 index 000000000..3f4277300 --- /dev/null +++ b/docs/implplan/SPRINT_20251226_013_BINIDX_fingerprint_factory.md @@ -0,0 +1,240 @@ +# SPRINT_20251226_013_BINIDX_fingerprint_factory + +> **Status:** TODO +> **Priority:** P2 +> **Module:** BinaryIndex +> **Created:** 2025-12-26 +> **Depends On:** [`SPRINT_20251226_012_BINIDX_backport_handling.md`](./SPRINT_20251226_012_BINIDX_backport_handling.md) +> **Architecture:** [`docs/modules/binaryindex/architecture.md`](../modules/binaryindex/architecture.md) + +--- + +## Topic & Scope + +Implement the **Binary Fingerprint Factory** - the third MVP tier that enables detecting vulnerable code independent of package metadata through function-level fingerprinting. + +**Goal:** Detect vulnerable code by matching function fingerprints, not just Build-IDs or versions. + +**Working directory:** `src/BinaryIndex/` + +--- + +## Documentation Prerequisites + +- `docs/modules/binaryindex/architecture.md` +- `src/BinaryIndex/__Libraries/StellaOps.BinaryIndex.Fingerprints/` +- Research: BinDiff, Diaphora, TLSH for binary similarity + +--- + +## Delivery Tracker + +| # | Task ID | Status | Depends | Owner | Description | +|---|---------|--------|---------|-------|-------------| +| 1 | FPRINT-01 | TODO | None | BE Guild | Create `vulnerable_fingerprints` table schema | +| 2 | FPRINT-02 | TODO | FPRINT-01 | BE Guild | Create `fingerprint_matches` table for match results | +| 3 | FPRINT-03 | TODO | None | BE Guild | Create `IFingerprintBlobStorage` for fingerprint storage | +| 4 | FPRINT-04 | TODO | FPRINT-03 | BE Guild | Implement `FingerprintBlobStorage` with RustFS backend | +| 5 | FPRINT-05 | TODO | None | BE Guild | Design `IVulnFingerprintGenerator` interface | +| 6 | FPRINT-06 | TODO | FPRINT-05 | BE Guild | Implement `BasicBlockFingerprintGenerator` | +| 7 | FPRINT-07 | TODO | FPRINT-05 | BE Guild | Implement `ControlFlowGraphFingerprintGenerator` | +| 8 | FPRINT-08 | TODO | FPRINT-05 | BE Guild | Implement `StringRefsFingerprintGenerator` | +| 9 | FPRINT-09 | TODO | FPRINT-05 | BE Guild | Implement `CombinedFingerprintGenerator` (ensemble) | +| 10 | FPRINT-10 | TODO | None | BE Guild | Create reference build generation pipeline | +| 11 | FPRINT-11 | TODO | FPRINT-10 | BE Guild | Implement vulnerable/fixed binary pair builder | +| 12 | FPRINT-12 | TODO | FPRINT-06 | BE Guild | Implement `IFingerprintMatcher` interface | +| 13 | FPRINT-13 | TODO | FPRINT-12 | BE Guild | Implement similarity matching with configurable threshold | +| 14 | FPRINT-14 | TODO | FPRINT-12 | BE Guild | Add `LookupByFingerprintAsync` to vulnerability service | +| 15 | FPRINT-15 | TODO | All | BE Guild | Seed fingerprints for OpenSSL high-impact CVEs | +| 16 | FPRINT-16 | TODO | All | BE Guild | Seed fingerprints for glibc high-impact CVEs | +| 17 | FPRINT-17 | TODO | All | BE Guild | Seed fingerprints for zlib high-impact CVEs | +| 18 | FPRINT-18 | TODO | All | BE Guild | Seed fingerprints for curl high-impact CVEs | +| 19 | FPRINT-19 | TODO | All | BE Guild | Create fingerprint validation corpus | +| 20 | FPRINT-20 | TODO | FPRINT-19 | BE Guild | Implement false positive rate validation | +| 21 | FPRINT-21 | TODO | All | BE Guild | Add unit tests for fingerprint generation | +| 22 | FPRINT-22 | TODO | All | BE Guild | Add integration tests for matching pipeline | +| 23 | FPRINT-23 | TODO | All | BE Guild | Document fingerprint algorithms in architecture | + +**Total Tasks:** 23 + +--- + +## Task Details + +### FPRINT-01: vulnerable_fingerprints Table + +Store function-level vulnerability fingerprints. + +**Schema:** +```sql +CREATE TABLE binaries.vulnerable_fingerprints ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + tenant_id TEXT NOT NULL DEFAULT binaries_app.require_current_tenant(), + cve_id TEXT NOT NULL, + component TEXT NOT NULL, -- openssl, glibc, etc. + purl TEXT, -- Package URL if known + algorithm TEXT NOT NULL, -- basic_block, cfg, string_refs, combined + fingerprint_id TEXT NOT NULL, -- Unique fingerprint identifier + fingerprint_hash BYTEA NOT NULL, -- 16-32 byte hash + architecture TEXT NOT NULL, -- x86_64, aarch64 + function_name TEXT, -- Function name if known + source_file TEXT, -- Source file if known + source_line INT, -- Line number if known + similarity_threshold DECIMAL(3,2) DEFAULT 0.95, + confidence DECIMAL(3,2), + validated BOOLEAN DEFAULT false, + validation_stats JSONB, -- {tp, fp, tn, fn} + vuln_build_ref TEXT, -- Reference to vulnerable build + fixed_build_ref TEXT, -- Reference to fixed build + indexed_at TIMESTAMPTZ NOT NULL DEFAULT now(), + UNIQUE (tenant_id, fingerprint_id) +); + +CREATE INDEX idx_fingerprint_cve ON binaries.vulnerable_fingerprints (tenant_id, cve_id); +CREATE INDEX idx_fingerprint_component ON binaries.vulnerable_fingerprints (tenant_id, component); +``` + +--- + +### FPRINT-06: BasicBlockFingerprintGenerator + +Generate fingerprints based on basic block hashing. + +**Algorithm:** +1. Disassemble function to basic blocks +2. Normalize instructions (remove absolute addresses) +3. Hash each basic block +4. Combine block hashes with topology info + +**Requirements:** +- Architecture-independent normalization +- Stable across compiler optimizations (-O1 to -O3) +- 16-byte fingerprint output + +**Location:** `src/BinaryIndex/__Libraries/StellaOps.BinaryIndex.Fingerprints/Generators/BasicBlockFingerprintGenerator.cs` + +--- + +### FPRINT-07: ControlFlowGraphFingerprintGenerator + +Generate fingerprints based on control flow graph structure. + +**Algorithm:** +1. Build CFG from disassembly +2. Extract graph properties (node count, edge count, cyclomatic complexity) +3. Compute structural hash (adjacency matrix or graph kernel) + +**Requirements:** +- Resilient to instruction reordering +- Capture loop and branch structure +- 32-byte fingerprint output + +**Location:** `src/BinaryIndex/__Libraries/StellaOps.BinaryIndex.Fingerprints/Generators/ControlFlowGraphFingerprintGenerator.cs` + +--- + +### FPRINT-08: StringRefsFingerprintGenerator + +Generate fingerprints based on string references in code. + +**Algorithm:** +1. Extract string constants referenced by function +2. Hash string content (normalized) +3. Include reference order/pattern + +**Requirements:** +- Useful for error message patterns +- Language-agnostic +- 16-byte fingerprint output + +**Location:** `src/BinaryIndex/__Libraries/StellaOps.BinaryIndex.Fingerprints/Generators/StringRefsFingerprintGenerator.cs` + +--- + +### FPRINT-10: Reference Build Pipeline + +Create automated pipeline for generating vulnerable/fixed binary pairs. + +**Pipeline Steps:** +1. Identify CVE with known commit fix +2. Clone upstream source +3. Build at vulnerable version +4. Build at fixed version +5. Extract fingerprints from both +6. Compute differential fingerprint (what changed) + +**Requirements:** +- Sandboxed build environment +- Multi-architecture support (x86_64, aarch64) +- Reproducible builds where possible + +--- + +### FPRINT-15-18: High-Impact CVE Seeding + +Seed initial fingerprint database with high-impact CVEs. + +**Target Components:** +| Component | Priority CVEs | Notes | +|-----------|---------------|-------| +| OpenSSL | CVE-2024-*, CVE-2023-* | Heartbleed-class vulns | +| glibc | CVE-2024-*, CVE-2023-* | Memory corruption | +| zlib | CVE-2022-37434 | Heap overflow | +| curl | CVE-2024-*, CVE-2023-* | Protocol vulns | + +**Goal:** 10+ fingerprints per component covering critical/high severity. + +--- + +### FPRINT-19: Validation Corpus + +Create corpus for validating fingerprint accuracy. + +**Requirements:** +- Known-vulnerable binaries from multiple distros +- Known-fixed binaries (backported) +- Ground truth labels +- Measure: Precision, Recall, F1 + +**Target Metrics:** +- Precision: > 0.95 (low false positives) +- Recall: > 0.80 (reasonable coverage) + +--- + +## Acceptance Criteria + +1. **Fingerprint generation** works for ELF binaries +2. **All three algorithms** produce stable fingerprints +3. **Matching service** returns similarity scores +4. **10 high-impact CVEs** seeded per component +5. **Validation corpus** shows acceptable F1 score +6. **False positive rate** < 5% +7. **Integration tests** cover full pipeline + +--- + +## Decisions & Risks + +| ID | Decision/Risk | Status | Notes | +|----|---------------|--------|-------| +| D1 | Use combined algorithm for production | DECIDED | Ensemble of all three | +| D2 | Default similarity threshold 0.95 | DECIDED | Configurable per fingerprint | +| R1 | Compiler optimization may affect stability | OPEN | Test across -O0 to -O3 | +| R2 | Architecture differences may cause false negatives | OPEN | Generate per-architecture | +| R3 | Large functions may have weak fingerprints | OPEN | Add function size filter | + +--- + +## Execution Log + +| Date (UTC) | Update | Owner | +|------------|--------|-------| +| 2025-12-26 | Sprint created from BinaryIndex MVP roadmap. | Project Mgmt | + +--- + +## Related Documentation + +- [BinaryIndex Architecture](../modules/binaryindex/architecture.md) +- [Binary Similarity Research](https://github.com/google/bindiff) diff --git a/docs/implplan/SPRINT_20251226_013_FE_triage_canvas.md b/docs/implplan/SPRINT_20251226_013_FE_triage_canvas.md new file mode 100644 index 000000000..14cac5aab --- /dev/null +++ b/docs/implplan/SPRINT_20251226_013_FE_triage_canvas.md @@ -0,0 +1,117 @@ +# Sprint 20251226 Β· Unified Triage Canvas with AdvisoryAI Integration + +## Topic & Scope +- Build unified triage experience combining VulnExplorer, AdvisoryAI, and evidence in single canvas. +- Integrate AdvisoryAI recommendations into triage workflow. +- Implement competitor-parity features: reachability context, VEX decisioning, attestable exceptions. +- **Working directory:** `src/Web/StellaOps.Web`, `src/VulnExplorer/` + +## Dependencies & Concurrency +- Depends on: SPRINT_20251226_012_FE (smart diff compare view), VulnExplorer API. +- Depends on: AdvisoryAI module (already complete). +- Can run in parallel with: Backend API work. + +## Documentation Prerequisites +- `docs/product-advisories/25-Dec-2025 - Triage UI Lessons from Competitors.md` +- `docs/modules/advisoryai/architecture.md` +- `src/VulnExplorer/StellaOps.VulnExplorer.Api/Models/` (existing models) +- Angular 17 component patterns + +## Context: What Already Exists + +| Component | Location | Status | +|-----------|----------|--------| +| VEX Decision Models | `VulnExplorer/Models/VexDecisionModels.cs` | COMPLETE | +| Vulnerability Models | `VulnExplorer/Models/VulnModels.cs` | COMPLETE | +| VEX Decision Store | `VulnExplorer/Data/VexDecisionStore.cs` | COMPLETE (in-memory, production uses PG) | +| AdvisoryAI Pipeline | `AdvisoryAI/Orchestration/` | COMPLETE | +| AdvisoryAI Retrievers | `AdvisoryAI/Retrievers/` | COMPLETE | +| Vulnerability Detail | `Web/features/vulnerabilities/` | PARTIAL | +| Evidence Page | `Web/features/evidence/` | PARTIAL | +| Confidence Badge | `Web/shared/components/` | COMPLETE | + +This sprint creates the **unified triage canvas** that competitors lack. + +## Delivery Tracker +| # | Task ID | Status | Key dependency / next step | Owners | Task Definition | +| --- | --- | --- | --- | --- | --- | +| 1 | TRIAGE-01 | TODO | None | Frontend Guild | Create `TriageCanvasComponent` container with multi-pane layout | +| 2 | TRIAGE-02 | TODO | None | Frontend Guild | Create `VulnerabilityListService` consuming VulnExplorer API | +| 3 | TRIAGE-03 | TODO | None | Frontend Guild | Create `AdvisoryAiService` consuming AdvisoryAI API endpoints | +| 4 | TRIAGE-04 | TODO | None | Frontend Guild | Create `VexDecisionService` for creating/updating VEX decisions | +| 5 | TRIAGE-05 | TODO | TRIAGE-01 | Frontend Guild | `TriageListComponent`: paginated vulnerability list with filters | +| 6 | TRIAGE-06 | TODO | TRIAGE-05 | Frontend Guild | Severity, KEV, exploitability, fix-available filter chips | +| 7 | TRIAGE-07 | TODO | TRIAGE-05 | Frontend Guild | Quick triage actions: "Mark Not Affected", "Request Analysis" | +| 8 | TRIAGE-08 | TODO | TRIAGE-01 | Frontend Guild | `TriageDetailComponent`: selected vulnerability deep-dive | +| 9 | TRIAGE-09 | TODO | TRIAGE-08 | Frontend Guild | Affected packages panel with PURL links | +| 10 | TRIAGE-10 | TODO | TRIAGE-08 | Frontend Guild | Advisory references panel with external links | +| 11 | TRIAGE-11 | TODO | TRIAGE-08 | Frontend Guild | Evidence provenance display: ledger entry, evidence bundle links | +| 12 | TRIAGE-12 | TODO | TRIAGE-08 | Frontend Guild | `ReachabilityContextComponent`: call graph slice from entry to vulnerability | +| 13 | TRIAGE-13 | TODO | TRIAGE-12 | Frontend Guild | Reachability confidence band using existing ConfidenceBadge | +| 14 | TRIAGE-14 | TODO | TRIAGE-03 | Frontend Guild | `AiRecommendationPanel`: AdvisoryAI suggestions for current vuln | +| 15 | TRIAGE-15 | TODO | TRIAGE-14 | Frontend Guild | "Why is this reachable?" AI-generated explanation | +| 16 | TRIAGE-16 | TODO | TRIAGE-14 | Frontend Guild | Suggested VEX justification from AI analysis | +| 17 | TRIAGE-17 | TODO | TRIAGE-14 | Frontend Guild | Similar vulnerabilities suggestion based on AI clustering | +| 18 | TRIAGE-18 | TODO | TRIAGE-04 | Frontend Guild | `VexDecisionModalComponent`: create VEX decision with justification | +| 19 | TRIAGE-19 | TODO | TRIAGE-18 | Frontend Guild | VEX status dropdown: NotAffected, AffectedMitigated, AffectedUnmitigated, Fixed | +| 20 | TRIAGE-20 | TODO | TRIAGE-18 | Frontend Guild | Justification type selector matching VexJustificationType enum | +| 21 | TRIAGE-21 | TODO | TRIAGE-18 | Frontend Guild | Evidence reference input: PR, Ticket, Doc, Commit links | +| 22 | TRIAGE-22 | TODO | TRIAGE-18 | Frontend Guild | Scope selector: environments and projects | +| 23 | TRIAGE-23 | TODO | TRIAGE-18 | Frontend Guild | Validity window: NotBefore/NotAfter date pickers | +| 24 | TRIAGE-24 | TODO | TRIAGE-18 | Frontend Guild | "Sign as Attestation" checkbox triggering DSSE envelope creation | +| 25 | TRIAGE-25 | TODO | TRIAGE-01 | Frontend Guild | `VexHistoryComponent`: timeline of VEX decisions for current vuln | +| 26 | TRIAGE-26 | TODO | TRIAGE-25 | Frontend Guild | "Supersedes" relationship visualization in history | +| 27 | TRIAGE-27 | TODO | TRIAGE-01 | Frontend Guild | Bulk triage: select multiple vulns, apply same VEX decision | +| 28 | TRIAGE-28 | TODO | TRIAGE-27 | Frontend Guild | Bulk action confirmation modal with impact summary | +| 29 | TRIAGE-29 | TODO | TRIAGE-01 | Frontend Guild | `TriageQueueComponent`: prioritized queue for triage workflow | +| 30 | TRIAGE-30 | TODO | TRIAGE-29 | Frontend Guild | Auto-advance to next item after triage decision | +| 31 | TRIAGE-31 | TODO | TRIAGE-01 | Frontend Guild | Keyboard shortcuts: N(next), P(prev), M(mark not affected), A(analyze) | +| 32 | TRIAGE-32 | TODO | TRIAGE-01 | Frontend Guild | Responsive layout for tablet/desktop | +| 33 | TRIAGE-33 | TODO | All above | Frontend Guild | Unit tests for all triage components | +| 34 | TRIAGE-34 | TODO | TRIAGE-33 | Frontend Guild | E2E tests: complete triage workflow | +| 35 | TRIAGE-35 | TODO | TRIAGE-34 | Frontend Guild | Integration tests: VulnExplorer and AdvisoryAI API calls | + +## AdvisoryAI Integration Points + +```typescript +// API endpoints from AdvisoryAI.WebService +POST /api/v1/advisory/plan // Get AI analysis plan for vulnerability +POST /api/v1/advisory/execute // Execute AI analysis +GET /api/v1/advisory/output // Retrieve AI recommendations + +// Frontend service +@Injectable({ providedIn: 'root' }) +export class AdvisoryAiService { + getRecommendations(vulnId: string): Observable; + requestAnalysis(vulnId: string, context: AnalysisContext): Observable; + getExplanation(vulnId: string, question: string): Observable; +} +``` + +## Competitor Parity Matrix + +| Competitor Feature | Implementation | +|--------------------|----------------| +| Snyk reachability graphs | TRIAGE-12: ReachabilityContextComponent | +| Snyk AI prioritization | TRIAGE-14/15/16/17: AiRecommendationPanel | +| Anchore VEX annotations | TRIAGE-18-24: VexDecisionModalComponent | +| Anchore VEX export | Existing Excititor export (no new work) | +| Prisma runtime context | Future: integrate Signals module | + +## Execution Log +| Date (UTC) | Update | Owner | +| --- | --- | --- | +| 2025-12-26 | Sprint created from "Triage UI Lessons from Competitors" analysis; implements unified triage canvas. | Project Mgmt | + +## Decisions & Risks +- Decision needed: AI recommendation display format. Recommend: collapsible cards with confidence scores. +- Decision needed: Bulk triage limit. Recommend: 50 items max per bulk action. +- Decision needed: Triage queue algorithm. Recommend: priority by (KEV Γ— severity Γ— reachability). +- Risk: AdvisoryAI latency may slow triage. Mitigation: async loading, skeleton UI. +- Risk: VEX decision conflicts across users. Mitigation: optimistic locking with version check. +- Risk: Overwhelming information density. Mitigation: progressive disclosure, role-based defaults. + +## Next Checkpoints +- 2026-01-08 | TRIAGE-13 complete | Core triage list and detail working | +- 2026-01-15 | TRIAGE-24 complete | VEX decisioning functional | +- 2026-01-20 | TRIAGE-35 complete | Full canvas with AI integration | diff --git a/docs/implplan/SPRINT_20251226_014_BINIDX_scanner_integration.md b/docs/implplan/SPRINT_20251226_014_BINIDX_scanner_integration.md new file mode 100644 index 000000000..bcd57100b --- /dev/null +++ b/docs/implplan/SPRINT_20251226_014_BINIDX_scanner_integration.md @@ -0,0 +1,274 @@ +# SPRINT_20251226_014_BINIDX_scanner_integration + +> **Status:** TODO +> **Priority:** P1 +> **Module:** BinaryIndex, Scanner +> **Created:** 2025-12-26 +> **Depends On:** [`SPRINT_20251226_013_BINIDX_fingerprint_factory.md`](./SPRINT_20251226_013_BINIDX_fingerprint_factory.md) +> **Architecture:** [`docs/modules/binaryindex/architecture.md`](../modules/binaryindex/architecture.md), [`docs/modules/scanner/architecture.md`](../modules/scanner/architecture.md) + +--- + +## Topic & Scope + +Implement **Full Scanner Integration** - the fourth MVP tier that brings binary evidence into production scans with proper attestation and findings ledger integration. + +**Goal:** Binary vulnerability matches appear in scan results with cryptographic evidence. + +**Working directories:** +- `src/BinaryIndex/` +- `src/Scanner/` +- `src/Attestor/` + +--- + +## Documentation Prerequisites + +- `docs/modules/binaryindex/architecture.md` +- `docs/modules/scanner/architecture.md` +- `docs/modules/attestor/architecture.md` +- `src/Scanner/StellaOps.Scanner.Worker/` + +--- + +## Delivery Tracker + +| # | Task ID | Status | Depends | Owner | Description | +|---|---------|--------|---------|-------|-------------| +| 1 | SCANINT-01 | TODO | None | BE Guild | Add BinaryIndex service registration to Scanner.Worker | +| 2 | SCANINT-02 | TODO | SCANINT-01 | BE Guild | Create `IBinaryLookupStep` in scan pipeline | +| 3 | SCANINT-03 | TODO | SCANINT-02 | BE Guild | Implement binary extraction from container layers | +| 4 | SCANINT-04 | TODO | SCANINT-03 | BE Guild | Integrate `BinaryIdentityService` for identity extraction | +| 5 | SCANINT-05 | TODO | SCANINT-04 | BE Guild | Call `LookupByIdentityAsync` for each extracted binary | +| 6 | SCANINT-06 | TODO | SCANINT-05 | BE Guild | Call `GetFixStatusAsync` for distro-aware backport check | +| 7 | SCANINT-07 | TODO | SCANINT-05 | BE Guild | Call `LookupByFingerprintAsync` for fingerprint matching | +| 8 | SCANINT-08 | TODO | All | BE Guild | Create `BinaryFindingMapper` to convert matches to findings | +| 9 | SCANINT-09 | TODO | SCANINT-08 | BE Guild | Integrate with Findings Ledger for persistence | +| 10 | SCANINT-10 | TODO | None | BE Guild | Create `binary_fingerprint_evidence` proof segment type | +| 11 | SCANINT-11 | TODO | SCANINT-10 | BE Guild | Implement proof segment generation in Attestor | +| 12 | SCANINT-12 | TODO | SCANINT-11 | BE Guild | Sign binary evidence with DSSE | +| 13 | SCANINT-13 | TODO | SCANINT-12 | BE Guild | Attach binary attestation as OCI referrer | +| 14 | SCANINT-14 | TODO | None | CLI Guild | Add `stella binary inspect` CLI command | +| 15 | SCANINT-15 | TODO | SCANINT-14 | CLI Guild | Add `stella binary lookup ` command | +| 16 | SCANINT-16 | TODO | SCANINT-14 | CLI Guild | Add `stella binary fingerprint ` command | +| 17 | SCANINT-17 | TODO | None | FE Guild | Add "Binary Evidence" tab to scan results UI | +| 18 | SCANINT-18 | TODO | SCANINT-17 | FE Guild | Display "Backported & Safe" badge for fixed binaries | +| 19 | SCANINT-19 | TODO | SCANINT-17 | FE Guild | Display "Affected & Reachable" badge for vulnerable binaries | +| 20 | SCANINT-20 | TODO | All | BE Guild | Add performance benchmarks for binary lookup | +| 21 | SCANINT-21 | TODO | All | BE Guild | Add Valkey cache layer for hot lookups | +| 22 | SCANINT-22 | TODO | All | QA | Add E2E tests for complete scan with binary evidence | +| 23 | SCANINT-23 | TODO | All | QA | Add determinism tests for binary verdict reproducibility | +| 24 | SCANINT-24 | TODO | All | Docs | Update Scanner architecture with binary lookup flow | +| 25 | SCANINT-25 | TODO | All | Docs | Create binary evidence user guide | + +**Total Tasks:** 25 + +--- + +## Task Details + +### SCANINT-02: IBinaryLookupStep + +Create pipeline step for binary vulnerability lookup during scan. + +**Interface:** +```csharp +public interface IBinaryLookupStep : IScanPipelineStep +{ + Task LookupAsync( + ExtractedBinary binary, + ScanContext context, + CancellationToken ct); +} + +public sealed record BinaryLookupResult( + BinaryIdentity Identity, + ImmutableArray Matches, + ImmutableArray FixStatuses); +``` + +**Location:** `src/Scanner/StellaOps.Scanner.Worker/Pipeline/BinaryLookupStep.cs` + +--- + +### SCANINT-03: Binary Extraction from Layers + +Extract binaries from container image layers for analysis. + +**Requirements:** +- Identify ELF/PE/Mach-O files in layers +- Skip small files (< 4KB) +- Limit to executable sections +- Track layer origin for provenance + +**Performance Target:** < 100ms per binary extraction + +--- + +### SCANINT-08: BinaryFindingMapper + +Convert binary matches to standard findings format. + +**Mapping:** +```csharp +public Finding MapToFinding(BinaryVulnMatch match, BinaryIdentity identity) +{ + return new Finding + { + Id = GenerateFindingId(match, identity), + Type = FindingType.BinaryVulnerability, + Severity = GetSeverityFromCve(match.CveId), + Title = $"Binary contains vulnerable code: {match.CveId}", + Description = GenerateDescription(match), + Evidence = new BinaryFindingEvidence + { + BinaryKey = identity.BinaryKey, + BuildId = identity.BuildId, + MatchMethod = match.Method, + Confidence = match.Confidence + }, + Remediation = GenerateRemediation(match) + }; +} +``` + +--- + +### SCANINT-10: binary_fingerprint_evidence Proof Segment + +Create new proof segment type for binary evidence. + +**Schema:** +```json +{ + "segment_type": "binary_fingerprint_evidence", + "version": "1.0.0", + "payload": { + "binary_identity": { + "format": "elf", + "build_id": "abc123...", + "file_sha256": "def456...", + "architecture": "x86_64" + }, + "layer_digest": "sha256:...", + "matches": [ + { + "cve_id": "CVE-2024-1234", + "method": "buildid_catalog", + "confidence": 0.98, + "vulnerable_purl": "pkg:deb/debian/libssl3@1.1.1n-0+deb11u3", + "fix_status": { + "state": "fixed", + "fixed_version": "1.1.1n-0+deb11u4", + "method": "changelog", + "confidence": 0.85 + } + } + ] + } +} +``` + +--- + +### SCANINT-14: CLI Binary Inspect Command + +Add CLI commands for binary analysis. + +**Commands:** +```bash +# Inspect binary identity +stella binary inspect /path/to/binary +# Output: Build-ID, hashes, architecture, format + +# Lookup vulnerabilities by Build-ID +stella binary lookup abc123def456... +# Output: CVE matches, fix status + +# Generate fingerprint for binary +stella binary fingerprint /path/to/binary --algorithm combined +# Output: Fingerprint ID, algorithm, hash +``` + +--- + +### SCANINT-17: Binary Evidence UI Tab + +Add UI component for viewing binary evidence in scan results. + +**Requirements:** +- List binaries found in image +- Show Build-ID, path, layer +- Display vulnerability matches with confidence +- Show backport status badges +- Drill-down to proof chain + +--- + +### SCANINT-18-19: Status Badges + +Display clear status badges for binary findings. + +**Badge Types:** +| Badge | Color | Meaning | +|-------|-------|---------| +| Backported & Safe | Green | Distro backported the fix | +| Affected & Reachable | Red | Vulnerable and in code path | +| Affected (Low Priority) | Orange | Vulnerable but unreachable | +| Unknown | Gray | Could not determine status | + +--- + +### SCANINT-21: Valkey Cache Layer + +Add caching for frequently looked up binaries. + +**Cache Strategy:** +- Key: `binary:{tenant}:{build_id}` +- TTL: 1 hour (configurable) +- Invalidate on corpus update +- Cache hit target: > 80% for repeat scans + +--- + +## Acceptance Criteria + +1. **Scanner pipeline** includes binary lookup step +2. **Binary findings** appear in scan results +3. **Proof segments** generated with DSSE signatures +4. **OCI attestation** attached to image +5. **CLI commands** work for binary analysis +6. **UI displays** binary evidence tab +7. **Status badges** show backport status +8. **Cache hit rate** > 80% for repeat scans +9. **E2E tests** pass for complete workflow +10. **Determinism tests** pass for reproducibility + +--- + +## Decisions & Risks + +| ID | Decision/Risk | Status | Notes | +|----|---------------|--------|-------| +| D1 | Binary lookup runs in parallel with package scan | DECIDED | No blocking | +| D2 | Default to buildid_catalog method first | DECIDED | Fastest path | +| R1 | Large images may have many binaries | OPEN | Add binary count limit (1000) | +| R2 | Cache invalidation on corpus update | OPEN | Use pub/sub notification | +| R3 | Performance impact on scan time | OPEN | Target < 5% overhead | + +--- + +## Execution Log + +| Date (UTC) | Update | Owner | +|------------|--------|-------| +| 2025-12-26 | Sprint created from BinaryIndex MVP roadmap. | Project Mgmt | + +--- + +## Related Documentation + +- [BinaryIndex Architecture](../modules/binaryindex/architecture.md) +- [Scanner Architecture](../modules/scanner/architecture.md) +- [Attestor Architecture](../modules/attestor/architecture.md) +- [Proof Chain Specification](../modules/attestor/proof-chain-specification.md) diff --git a/docs/implplan/SPRINT_20251226_014_DOCS_triage_consolidation.md b/docs/implplan/SPRINT_20251226_014_DOCS_triage_consolidation.md new file mode 100644 index 000000000..12f2c27a1 --- /dev/null +++ b/docs/implplan/SPRINT_20251226_014_DOCS_triage_consolidation.md @@ -0,0 +1,124 @@ +# Sprint 20251226 Β· Triage UI Advisory and Documentation Consolidation + +## Topic & Scope +- Consolidate 3 overlapping triage/visualization advisories into unified documentation. +- Create authoritative "Unified Triage Experience" specification. +- Update smart-diff-ui-architecture.md to reflect current sprint structure. +- Archive original advisories with cross-reference preservation. +- **Working directory:** `docs/product-advisories/`, `docs/modules/web/` + +## Dependencies & Concurrency +- No technical dependencies; documentation-only sprint. +- Can run in parallel with: SPRINT_20251226_012_FE, SPRINT_20251226_013_FE. +- Should reference implementation status from UI sprints. + +## Documentation Prerequisites +- All source advisories (listed below) +- Existing web module docs: + - `docs/modules/web/smart-diff-ui-architecture.md` + - `docs/modules/web/README.md` + +## Advisories to Consolidate + +| Advisory | Primary Concepts | Keep Verbatim | +|----------|------------------|---------------| +| `25-Dec-2025 - Triage UI Lessons from Competitors.md` | Snyk/Anchore/Prisma analysis, 4 recommendations | Competitor feature matrix | +| `25-Dec-2025 - Visual Diffs for Explainable Triage.md` | Side-by-side panes, evidence strip, micro-interactions | Data model sketch, UI concept | +| `26-Dec-2026 - Visualizing the Risk Budget.md` | Burn-up charts, heatmaps, exception ledger | Chart design, compute formulas | + +## Delivery Tracker +| # | Task ID | Status | Key dependency / next step | Owners | Task Definition | +| --- | --- | --- | --- | --- | --- | +| 1 | TDOC-01 | TODO | None | Project Mgmt | Create master document structure: `docs/modules/web/unified-triage-specification.md` | +| 2 | TDOC-02 | TODO | TDOC-01 | Project Mgmt | Merge competitor analysis section from "Triage UI Lessons" | +| 3 | TDOC-03 | TODO | TDOC-01 | Project Mgmt | Merge visual diff concepts from "Visual Diffs for Explainable Triage" | +| 4 | TDOC-04 | TODO | TDOC-01 | Project Mgmt | Merge risk budget visualization from "Visualizing the Risk Budget" | +| 5 | TDOC-05 | TODO | TDOC-04 | Project Mgmt | Add implementation status matrix (what exists vs gaps) | +| 6 | TDOC-06 | TODO | TDOC-05 | Project Mgmt | Map advisory concepts to sprint tasks (SPRINT_012, SPRINT_013, SPRINT_004) | +| 7 | TDOC-07 | TODO | TDOC-06 | Project Mgmt | Update `smart-diff-ui-architecture.md` sprint references to current format | +| 8 | TDOC-08 | TODO | TDOC-07 | Project Mgmt | Create archive directory: `archived/2025-12-26-triage-advisories/` | +| 9 | TDOC-09 | TODO | TDOC-08 | Project Mgmt | Move 3 original advisories to archive | +| 10 | TDOC-10 | TODO | TDOC-09 | Project Mgmt | Add README in archive explaining consolidation | +| 11 | TDOC-11 | TODO | TDOC-05 | Frontend Guild | Create `docs/modules/web/triage-component-catalog.md` | +| 12 | TDOC-12 | TODO | TDOC-11 | Frontend Guild | Document all triage-related Angular components and their relationships | +| 13 | TDOC-13 | TODO | TDOC-11 | Frontend Guild | Add component interaction diagrams | +| 14 | TDOC-14 | TODO | TDOC-09 | Project Mgmt | Update cross-references in `docs/modules/web/README.md` | +| 15 | TDOC-15 | TODO | TDOC-09 | Project Mgmt | Update cross-references in `docs/modules/vulnexplorer/` if exists | +| 16 | TDOC-16 | TODO | All above | Project Mgmt | Final review of consolidated documentation | + +## Consolidated Document Structure + +```markdown +# Unified Triage Experience Specification + +## 1. Executive Summary + - Problem: Disparate triage tools, siloed insights + - Solution: Unified canvas with evidence, VEX, and AI + +## 2. Competitive Landscape (from "Triage UI Lessons") + - Snyk: reachability + continuous context + - Anchore: vulnerability annotations + VEX export + - Prisma Cloud: runtime defense + - Stella Ops differentiation + +## 3. Core UI Concepts (from "Visual Diffs") + - Side-by-side panes: Before vs After + - Graph focus: dependency/reachability subgraph + - Evidence strip: human-readable facts + - Diff verdict header + - Filter chips + +## 4. Risk Budget Visualization (from "Visualizing Risk Budget") + - Heatmap of Unknowns + - Delta Table (Risk Decay per Release) + - Exception Ledger + - Burn-Up Chart specification + - Computation formulas + +## 5. Implementation Components + - Smart-Diff Compare View (SPRINT_012_FE) + - Unified Triage Canvas (SPRINT_013_FE) + - Risk Dashboard (SPRINT_004_FE) + +## 6. Data Models + - GraphSnapshot + - PolicySnapshot + - Delta + - EvidenceItems[] + - SignedDeltaVerdict + +## 7. API Integration + - VulnExplorer endpoints + - AdvisoryAI endpoints + - Delta computation endpoints + +## 8. Implementation Status + - Complete components + - In-progress sprints + - Planned work + +## 9. Testing Strategy + - Unit tests + - E2E tests + - Accessibility tests + +## 10. References + - Sprint links + - Archived advisories +``` + +## Execution Log +| Date (UTC) | Update | Owner | +| --- | --- | --- | +| 2025-12-26 | Sprint created from advisory analysis; consolidates 3 overlapping triage/visualization advisories. | Project Mgmt | + +## Decisions & Risks +- Decision: Archive location. Recommend: `archived/2025-12-26-triage-advisories/` with README. +- Decision: Keep smart-diff-ui-architecture.md or merge into unified spec. Recommend: Keep as reference, add link to unified spec. +- Risk: Broken cross-references after archival. Mitigation: grep all docs for advisory filenames before archiving. +- Risk: Loss of nuance from individual advisories. Mitigation: preserve verbatim sections as noted. + +## Next Checkpoints +- 2025-12-28 | TDOC-06 complete | All content merged with sprint mapping | +- 2025-12-29 | TDOC-10 complete | Advisories archived | +- 2025-12-30 | TDOC-16 complete | Final review and publication | diff --git a/docs/implplan/SPRINT_20251226_015_AI_zastava_companion.md b/docs/implplan/SPRINT_20251226_015_AI_zastava_companion.md new file mode 100644 index 000000000..f73aca401 --- /dev/null +++ b/docs/implplan/SPRINT_20251226_015_AI_zastava_companion.md @@ -0,0 +1,75 @@ +# Sprint 20251226 Β· Zastava Companion (Evidence-Grounded Explainability) + +## Topic & Scope +- Build AI-powered explanation service that answers "What is it?", "Why it matters here?", "What evidence supports exploitability?" +- All explanations must be anchored to evidence nodes (SBOM, reachability, runtime, VEX, patches) +- Produce OCI-attached "Explanation Attestation" with inputs' hashes + model digest for replayability +- **Working directory:** `src/AdvisoryAI/`, `src/Attestor/`, `src/Web/` + +## Dependencies & Concurrency +- Depends on: Existing AdvisoryAI pipeline infrastructure (COMPLETE). +- Depends on: ProofChain library for attestation generation (COMPLETE). +- Can run in parallel with: SPRINT_20251226_016_AI_remedy_autopilot. + +## Documentation Prerequisites +- `src/AdvisoryAI/AGENTS.md` +- `docs/modules/attestor/proof-chain-specification.md` +- AI Assistant Advisory (this sprint's source) + +## Context: What Already Exists + +The following components are **already implemented**: + +| Component | Location | Status | +|-----------|----------|--------| +| Pipeline Orchestrator | `AdvisoryAI/Orchestration/AdvisoryPipelineOrchestrator.cs` | COMPLETE | +| Guardrail Pipeline | `AdvisoryAI/Guardrails/AdvisoryGuardrailPipeline.cs` | COMPLETE | +| Inference Client | `AdvisoryAI/Inference/AdvisoryInferenceClient.cs` | COMPLETE | +| SBOM Context Retrieval | `AdvisoryAI/Retrievers/SbomContextRetriever.cs` | COMPLETE | +| Vector Retrieval | `AdvisoryAI/Retrievers/AdvisoryVectorRetriever.cs` | COMPLETE | +| Structured Retrieval | `AdvisoryAI/Retrievers/AdvisoryStructuredRetriever.cs` | COMPLETE | +| Citation Enforcement | `AdvisoryGuardrailPipeline` (RequireCitations) | COMPLETE | +| Proof Bundle Generation | `Policy/TrustLattice/ProofBundleBuilder.cs` | COMPLETE | + +This sprint extends AdvisoryAI with explanation generation and attestation. + +## Delivery Tracker +| # | Task ID | Status | Key dependency / next step | Owners | Task Definition | +| --- | --- | --- | --- | --- | --- | +| 1 | ZASTAVA-01 | TODO | None | AdvisoryAI Guild | Define `ExplanationRequest` model: finding_id, artifact_digest, scope, explanation_type (what/why/evidence/counterfactual) | +| 2 | ZASTAVA-02 | TODO | ZASTAVA-01 | AdvisoryAI Guild | Create `IExplanationGenerator` interface with `GenerateAsync(ExplanationRequest)` | +| 3 | ZASTAVA-03 | TODO | ZASTAVA-02 | AdvisoryAI Guild | Implement `EvidenceAnchoredExplanationGenerator` that retrieves evidence nodes before LLM call | +| 4 | ZASTAVA-04 | TODO | ZASTAVA-03 | AdvisoryAI Guild | Create evidence retrieval service combining: SBOM context, reachability subgraph, runtime facts, VEX claims, patch metadata | +| 5 | ZASTAVA-05 | TODO | ZASTAVA-04 | AdvisoryAI Guild | Define prompt templates for each explanation type (what/why/evidence/counterfactual) | +| 6 | ZASTAVA-06 | TODO | ZASTAVA-04 | AdvisoryAI Guild | Implement evidence anchor extraction from LLM response (parse citations, validate against input evidence) | +| 7 | ZASTAVA-07 | TODO | ZASTAVA-06 | AdvisoryAI Guild | Create `ExplanationResult` model with: content, citations[], confidence, evidence_refs[], metadata | +| 8 | ZASTAVA-08 | TODO | None | Attestor Guild | Define `AIExplanation` predicate type for in-toto statement | +| 9 | ZASTAVA-09 | TODO | ZASTAVA-08 | Attestor Guild | Create `ExplanationAttestationBuilder` producing DSSE-wrapped explanation attestations | +| 10 | ZASTAVA-10 | TODO | ZASTAVA-09 | Attestor Guild | Add `application/vnd.stellaops.explanation+json` media type for OCI referrers | +| 11 | ZASTAVA-11 | TODO | ZASTAVA-07 | AdvisoryAI Guild | Implement replay manifest for explanations: input_hashes, prompt_template_version, model_digest, decoding_params | +| 12 | ZASTAVA-12 | TODO | ZASTAVA-09 | ExportCenter Guild | Push explanation attestations as OCI referrers via `OciReferrerPushClient` | +| 13 | ZASTAVA-13 | TODO | ZASTAVA-07 | WebService Guild | API endpoint `POST /api/v1/advisory/explain` returning ExplanationResult | +| 14 | ZASTAVA-14 | TODO | ZASTAVA-13 | WebService Guild | API endpoint `GET /api/v1/advisory/explain/{id}/replay` for re-running explanation with same inputs | +| 15 | ZASTAVA-15 | TODO | ZASTAVA-13 | FE Guild | "Explain" button component triggering explanation generation | +| 16 | ZASTAVA-16 | TODO | ZASTAVA-15 | FE Guild | Explanation panel showing: plain language explanation, linked evidence nodes, confidence indicator | +| 17 | ZASTAVA-17 | TODO | ZASTAVA-16 | FE Guild | Evidence drill-down: click citation β†’ expand to full evidence node detail | +| 18 | ZASTAVA-18 | TODO | ZASTAVA-16 | FE Guild | Toggle: "Explain like I'm new" expanding jargon to plain language | +| 19 | ZASTAVA-19 | TODO | ZASTAVA-11 | Testing Guild | Integration tests: explanation generation with mocked LLM, evidence anchoring validation | +| 20 | ZASTAVA-20 | TODO | ZASTAVA-19 | Testing Guild | Golden tests: deterministic explanation replay produces identical output | +| 21 | ZASTAVA-21 | TODO | All above | Docs Guild | Document explanation API, attestation format, replay semantics | + +## Execution Log +| Date (UTC) | Update | Owner | +| --- | --- | --- | +| 2025-12-26 | Sprint created from AI Assistant Advisory analysis; extends existing AdvisoryAI with explanation generation. | Project Mgmt | + +## Decisions & Risks +- Decision needed: LLM model for explanations (Claude/GPT-4/Llama). Recommend: configurable, default to Claude for quality. +- Decision needed: Confidence thresholds for "Evidence-backed" vs "Suggestion-only" labels. Recommend: β‰₯80% citations valid β†’ evidence-backed. +- Risk: LLM hallucinations. Mitigation: enforce citation validation; reject explanations with unanchored claims. +- Risk: Latency for real-time explanations. Mitigation: cache explanations by input hash; async generation for batch. + +## Next Checkpoints +- 2025-12-30 | ZASTAVA-07 complete | Explanation generation service functional | +- 2026-01-03 | ZASTAVA-12 complete | OCI-attached attestations working | +- 2026-01-06 | ZASTAVA-21 complete | Full documentation and tests | diff --git a/docs/implplan/SPRINT_20251226_016_AI_remedy_autopilot.md b/docs/implplan/SPRINT_20251226_016_AI_remedy_autopilot.md new file mode 100644 index 000000000..5e92051a9 --- /dev/null +++ b/docs/implplan/SPRINT_20251226_016_AI_remedy_autopilot.md @@ -0,0 +1,81 @@ +# Sprint 20251226 Β· Remedy Autopilot (Safe PRs) + +## Topic & Scope +- Build AI-powered remediation service that generates actionable fix plans (dependency bumps, base image upgrades, config changes, backport guidance) +- Implement automated PR generation with reproducible build verification, tests, SBOM delta, and signed delta verdict +- Fallback to "suggestion-only" when build/tests fail +- **Working directory:** `src/AdvisoryAI/`, `src/Policy/`, `src/Attestor/`, `src/__Libraries/StellaOps.DeltaVerdict/` + +## Dependencies & Concurrency +- Depends on: DeltaVerdict library (COMPLETE). +- Depends on: Existing RemediationHintsRegistry (COMPLETE). +- Depends on: ZASTAVA Companion for explanation generation (can run in parallel). +- Can run in parallel with: SPRINT_20251226_017_AI_policy_copilot. + +## Documentation Prerequisites +- `src/Policy/__Libraries/StellaOps.Policy.Unknowns/Services/RemediationHintsRegistry.cs` +- `src/__Libraries/StellaOps.DeltaVerdict/` (delta computation) +- AI Assistant Advisory (this sprint's source) + +## Context: What Already Exists + +The following components are **already implemented**: + +| Component | Location | Status | +|-----------|----------|--------| +| Remediation Hints Registry | `Policy.Unknowns/Services/RemediationHintsRegistry.cs` | COMPLETE | +| Delta Computation Engine | `StellaOps.DeltaVerdict/DeltaComputationEngine.cs` | COMPLETE | +| Delta Signing Service | `StellaOps.DeltaVerdict/Signing/DeltaSigningService.cs` | COMPLETE | +| SBOM Diff | `SbomService` lineage tracking | COMPLETE | +| Attestor DSSE | `Attestor.ProofChain/Signing/ProofChainSigner.cs` | COMPLETE | +| AdvisoryAI Pipeline | `AdvisoryAI/Orchestration/AdvisoryPipelineOrchestrator.cs` | COMPLETE | + +This sprint extends the system with AI-generated remediation plans and automated PR integration. + +## Delivery Tracker +| # | Task ID | Status | Key dependency / next step | Owners | Task Definition | +| --- | --- | --- | --- | --- | --- | +| 1 | REMEDY-01 | TODO | None | AdvisoryAI Guild | Define `RemediationPlanRequest` model: finding_id, artifact_digest, remediation_type (bump/upgrade/config/backport) | +| 2 | REMEDY-02 | TODO | REMEDY-01 | AdvisoryAI Guild | Create `IRemediationPlanner` interface with `GeneratePlanAsync(RemediationPlanRequest)` | +| 3 | REMEDY-03 | TODO | REMEDY-02 | AdvisoryAI Guild | Implement `AiRemediationPlanner` using LLM with package registry context (npm, PyPI, NuGet, Maven) | +| 4 | REMEDY-04 | TODO | REMEDY-03 | AdvisoryAI Guild | Create package version resolver service to validate upgrade paths (check compatibility, breaking changes) | +| 5 | REMEDY-05 | TODO | REMEDY-04 | AdvisoryAI Guild | Define `RemediationPlan` model: steps[], expected_sbom_delta, risk_assessment, test_requirements | +| 6 | REMEDY-06 | TODO | None | Attestor Guild | Define `RemediationPlan` predicate type for in-toto statement | +| 7 | REMEDY-07 | TODO | REMEDY-06 | Attestor Guild | Create `RemediationPlanAttestationBuilder` for DSSE-wrapped plans | +| 8 | REMEDY-08 | TODO | REMEDY-05 | Integration Guild | Define `IPullRequestGenerator` interface for SCM integration | +| 9 | REMEDY-09 | TODO | REMEDY-08 | Integration Guild | Implement `GitHubPullRequestGenerator` for GitHub repositories | +| 10 | REMEDY-10 | TODO | REMEDY-08 | Integration Guild | Implement `GitLabMergeRequestGenerator` for GitLab repositories | +| 11 | REMEDY-11 | TODO | REMEDY-08 | Integration Guild | Implement `AzureDevOpsPullRequestGenerator` for Azure DevOps | +| 12 | REMEDY-12 | TODO | REMEDY-09 | Integration Guild | PR branch creation with remediation changes (package updates, config modifications) | +| 13 | REMEDY-13 | TODO | REMEDY-12 | Integration Guild | Build verification: trigger CI pipeline, capture build result | +| 14 | REMEDY-14 | TODO | REMEDY-13 | Integration Guild | Test verification: run test suite, capture pass/fail counts | +| 15 | REMEDY-15 | TODO | REMEDY-14 | DeltaVerdict Guild | SBOM delta computation: compare pre/post remediation SBOMs | +| 16 | REMEDY-16 | TODO | REMEDY-15 | DeltaVerdict Guild | Generate signed delta verdict for remediation PR | +| 17 | REMEDY-17 | TODO | REMEDY-16 | Integration Guild | PR description generator: include SBOM delta summary, delta verdict, risk assessment | +| 18 | REMEDY-18 | TODO | REMEDY-14 | AdvisoryAI Guild | Fallback logic: if build/tests fail, mark as "suggestion-only" with failure reason | +| 19 | REMEDY-19 | TODO | REMEDY-17 | WebService Guild | API endpoint `POST /api/v1/remediation/plan` returning RemediationPlan | +| 20 | REMEDY-20 | TODO | REMEDY-19 | WebService Guild | API endpoint `POST /api/v1/remediation/apply` triggering PR generation | +| 21 | REMEDY-21 | TODO | REMEDY-20 | WebService Guild | API endpoint `GET /api/v1/remediation/status/{pr_id}` for tracking PR status | +| 22 | REMEDY-22 | TODO | REMEDY-19 | FE Guild | "Auto-fix" button component initiating remediation workflow | +| 23 | REMEDY-23 | TODO | REMEDY-22 | FE Guild | Remediation plan preview: show proposed changes, expected delta, risk assessment | +| 24 | REMEDY-24 | TODO | REMEDY-23 | FE Guild | PR status tracker: build status, test results, delta verdict badge | +| 25 | REMEDY-25 | TODO | REMEDY-18 | Testing Guild | Integration tests: plan generation, PR creation (mocked SCM), fallback handling | +| 26 | REMEDY-26 | TODO | All above | Docs Guild | Document remediation API, SCM integration setup, delta verdict semantics | + +## Execution Log +| Date (UTC) | Update | Owner | +| --- | --- | --- | +| 2025-12-26 | Sprint created from AI Assistant Advisory analysis; builds on existing RemediationHintsRegistry and DeltaVerdict. | Project Mgmt | + +## Decisions & Risks +- Decision needed: SCM authentication (OAuth, PAT, GitHub App). Recommend: OAuth for UI, PAT for CLI, GitHub App for org-wide. +- Decision needed: Auto-merge policy. Recommend: never auto-merge; always require human approval. +- Decision needed: Breaking change detection threshold. Recommend: flag any major version bump as "needs review". +- Risk: Generated changes may introduce new vulnerabilities. Mitigation: always run full scan on remediation branch before PR. +- Risk: CI pipeline costs. Mitigation: limit to 3 remediation attempts per finding; require approval for more. +- Risk: Repository access scope creep. Mitigation: request minimum permissions; audit access logs. + +## Next Checkpoints +- 2025-12-30 | REMEDY-05 complete | Remediation plan generation functional | +- 2026-01-03 | REMEDY-17 complete | PR generation with delta verdicts working | +- 2026-01-06 | REMEDY-26 complete | Full documentation and SCM integrations | diff --git a/docs/implplan/SPRINT_20251226_017_AI_policy_copilot.md b/docs/implplan/SPRINT_20251226_017_AI_policy_copilot.md new file mode 100644 index 000000000..4bce0e42f --- /dev/null +++ b/docs/implplan/SPRINT_20251226_017_AI_policy_copilot.md @@ -0,0 +1,80 @@ +# Sprint 20251226 Β· Policy Studio Copilot (NL β†’ Lattice Rules) + +## Topic & Scope +- Build AI-powered policy authoring that converts natural language intent to lattice rules +- Generate test cases for policy validation +- Compile to deterministic policy code with signed policy snapshots +- **Working directory:** `src/AdvisoryAI/`, `src/Policy/__Libraries/StellaOps.Policy/TrustLattice/`, `src/Web/` + +## Dependencies & Concurrency +- Depends on: TrustLatticeEngine and K4Lattice (COMPLETE). +- Depends on: PolicyBundle compilation (COMPLETE). +- Can run in parallel with: SPRINT_20251226_015_AI_zastava_companion. + +## Documentation Prerequisites +- `src/Policy/__Libraries/StellaOps.Policy/TrustLattice/TrustLatticeEngine.cs` +- `src/Policy/__Libraries/StellaOps.Policy/TrustLattice/K4Lattice.cs` +- AI Assistant Advisory (this sprint's source) + +## Context: What Already Exists + +The following components are **already implemented**: + +| Component | Location | Status | +|-----------|----------|--------| +| K4 Lattice | `Policy/TrustLattice/K4Lattice.cs` | COMPLETE | +| Trust Lattice Engine | `Policy/TrustLattice/TrustLatticeEngine.cs` | COMPLETE | +| Policy Bundle | `Policy/TrustLattice/PolicyBundle.cs` | COMPLETE | +| Disposition Selector | `Policy/TrustLattice/DispositionSelector.cs` | COMPLETE | +| Security Atoms | Present, Applies, Reachable, Mitigated, Fixed, Misattributed | COMPLETE | +| Proof Bundle Generation | `Policy/TrustLattice/ProofBundleBuilder.cs` | COMPLETE | +| VEX Normalizers | CycloneDX, OpenVEX, CSAF | COMPLETE | + +This sprint adds NLβ†’rule conversion, test synthesis, and an interactive policy authoring UI. + +## Delivery Tracker +| # | Task ID | Status | Key dependency / next step | Owners | Task Definition | +| --- | --- | --- | --- | --- | --- | +| 1 | POLICY-01 | TODO | None | AdvisoryAI Guild | Define policy intent taxonomy: override_rules, escalation_rules, exception_conditions, merge_precedence | +| 2 | POLICY-02 | TODO | POLICY-01 | AdvisoryAI Guild | Create `IPolicyIntentParser` interface with `ParseAsync(natural_language_input)` | +| 3 | POLICY-03 | TODO | POLICY-02 | AdvisoryAI Guild | Implement `AiPolicyIntentParser` using LLM with few-shot examples of valid policy intents | +| 4 | POLICY-04 | TODO | POLICY-03 | AdvisoryAI Guild | Define `PolicyIntent` model: intent_type, conditions[], actions[], scope, priority | +| 5 | POLICY-05 | TODO | POLICY-04 | Policy Guild | Create `IPolicyRuleGenerator` interface converting PolicyIntent to lattice rules | +| 6 | POLICY-06 | TODO | POLICY-05 | Policy Guild | Implement `LatticeRuleGenerator` producing K4Lattice-compatible rule definitions | +| 7 | POLICY-07 | TODO | POLICY-06 | Policy Guild | Rule validation: check for conflicts, unreachable conditions, infinite loops | +| 8 | POLICY-08 | TODO | POLICY-06 | Testing Guild | Create `ITestCaseSynthesizer` interface for generating policy test cases | +| 9 | POLICY-09 | TODO | POLICY-08 | Testing Guild | Implement `PropertyBasedTestSynthesizer` generating edge-case inputs for policy validation | +| 10 | POLICY-10 | TODO | POLICY-09 | Testing Guild | Generate positive tests: inputs that should match the rule and produce expected disposition | +| 11 | POLICY-11 | TODO | POLICY-09 | Testing Guild | Generate negative tests: inputs that should NOT match (boundary conditions) | +| 12 | POLICY-12 | TODO | POLICY-10 | Testing Guild | Generate conflict tests: inputs that trigger multiple conflicting rules | +| 13 | POLICY-13 | TODO | POLICY-07 | Policy Guild | Policy compilation: bundle rules into versioned, signed PolicyBundle | +| 14 | POLICY-14 | TODO | POLICY-13 | Attestor Guild | Define `PolicyDraft` predicate type for in-toto statement | +| 15 | POLICY-15 | TODO | POLICY-14 | Attestor Guild | Create `PolicyDraftAttestationBuilder` for DSSE-wrapped policy snapshots | +| 16 | POLICY-16 | TODO | POLICY-13 | WebService Guild | API endpoint `POST /api/v1/policy/studio/parse` for NLβ†’intent parsing | +| 17 | POLICY-17 | TODO | POLICY-16 | WebService Guild | API endpoint `POST /api/v1/policy/studio/generate` for intentβ†’rule generation | +| 18 | POLICY-18 | TODO | POLICY-17 | WebService Guild | API endpoint `POST /api/v1/policy/studio/validate` for rule validation with test cases | +| 19 | POLICY-19 | TODO | POLICY-18 | WebService Guild | API endpoint `POST /api/v1/policy/studio/compile` for final policy compilation | +| 20 | POLICY-20 | TODO | POLICY-16 | FE Guild | Policy Studio UI: natural language input panel with autocomplete for policy entities | +| 21 | POLICY-21 | TODO | POLICY-20 | FE Guild | Live preview: show generated rules as user types, highlight syntax | +| 22 | POLICY-22 | TODO | POLICY-21 | FE Guild | Test case panel: show generated tests, allow manual additions, run validation | +| 23 | POLICY-23 | TODO | POLICY-22 | FE Guild | Conflict visualizer: highlight conflicting rules with resolution suggestions | +| 24 | POLICY-24 | TODO | POLICY-23 | FE Guild | Version history: show policy versions, diff between versions | +| 25 | POLICY-25 | TODO | POLICY-12 | Testing Guild | Integration tests: NLβ†’ruleβ†’test round-trip, conflict detection | +| 26 | POLICY-26 | TODO | All above | Docs Guild | Document Policy Studio API, rule syntax, test case format | + +## Execution Log +| Date (UTC) | Update | Owner | +| --- | --- | --- | +| 2025-12-26 | Sprint created from AI Assistant Advisory analysis; extends TrustLatticeEngine with AI policy authoring. | Project Mgmt | + +## Decisions & Risks +- Decision needed: Policy DSL format (YAML, JSON, custom syntax). Recommend: YAML for readability, JSON for API. +- Decision needed: Maximum rule complexity. Recommend: limit to 10 conditions per rule initially. +- Decision needed: Approval workflow for policy changes. Recommend: require 2 approvers for production policies. +- Risk: Generated rules may have unintended consequences. Mitigation: mandatory test coverage, dry-run mode. +- Risk: NL ambiguity leading to wrong rules. Mitigation: clarifying questions in UI, explicit examples. + +## Next Checkpoints +- 2025-12-30 | POLICY-07 complete | NLβ†’rule generation functional | +- 2026-01-03 | POLICY-15 complete | Policy compilation with attestations | +- 2026-01-06 | POLICY-26 complete | Full Policy Studio with tests | diff --git a/docs/implplan/SPRINT_20251226_018_AI_attestations.md b/docs/implplan/SPRINT_20251226_018_AI_attestations.md new file mode 100644 index 000000000..56753e670 --- /dev/null +++ b/docs/implplan/SPRINT_20251226_018_AI_attestations.md @@ -0,0 +1,78 @@ +# Sprint 20251226 Β· AI Artifact Attestations + +## Topic & Scope +- Define and implement standardized attestation types for all AI-generated artifacts +- Ensure all AI outputs are replayable, inspectable, and clearly marked as Suggestion-only vs Evidence-backed +- Integrate with existing ProofChain infrastructure for OCI attachment +- **Working directory:** `src/Attestor/__Libraries/StellaOps.Attestor.ProofChain/`, `src/ExportCenter/` + +## Dependencies & Concurrency +- Depends on: ProofChain library (COMPLETE). +- Depends on: OCI Referrer infrastructure (COMPLETE). +- Should run before or in parallel with: SPRINT_20251226_015/016/017 (AI feature sprints use these attestation types). + +## Documentation Prerequisites +- `docs/modules/attestor/proof-chain-specification.md` +- `src/Attestor/__Libraries/StellaOps.Attestor.ProofChain/Statements/` +- AI Assistant Advisory (this sprint's source) + +## Context: What Already Exists + +The following predicate types are **already implemented**: + +| Predicate | Type URI | Status | +|-----------|----------|--------| +| Build Provenance | `StellaOps.BuildProvenance@1` | COMPLETE | +| SBOM Attestation | `StellaOps.SBOMAttestation@1` | COMPLETE | +| Scan Results | `StellaOps.ScanResults@1` | COMPLETE | +| Policy Evaluation | `StellaOps.PolicyEvaluation@1` | COMPLETE | +| VEX Attestation | `StellaOps.VEXAttestation@1` | COMPLETE | +| Risk Profile Evidence | `StellaOps.RiskProfileEvidence@1` | COMPLETE | +| Reachability Witness | `StellaOps.ReachabilityWitness@1` | COMPLETE | +| Reachability Subgraph | `StellaOps.ReachabilitySubgraph@1` | COMPLETE | +| Proof Spine | `StellaOps.ProofSpine@1` | COMPLETE | + +This sprint adds AI-specific predicate types with replay metadata. + +## Delivery Tracker +| # | Task ID | Status | Key dependency / next step | Owners | Task Definition | +| --- | --- | --- | --- | --- | --- | +| 1 | AIATTEST-01 | TODO | None | Attestor Guild | Define `AIArtifactBase` predicate structure: model_id, weights_digest, prompt_template_version, decoding_params, inputs_hashes[] | +| 2 | AIATTEST-02 | TODO | AIATTEST-01 | Attestor Guild | Define `AIExplanation` predicate: extends AIArtifactBase + explanation_type, content, citations[], confidence_score | +| 3 | AIATTEST-03 | TODO | AIATTEST-01 | Attestor Guild | Define `AIRemediationPlan` predicate: extends AIArtifactBase + steps[], expected_delta, risk_assessment, verification_status | +| 4 | AIATTEST-04 | TODO | AIATTEST-01 | Attestor Guild | Define `AIVexDraft` predicate: extends AIArtifactBase + vex_statements[], justifications[], evidence_refs[] | +| 5 | AIATTEST-05 | TODO | AIATTEST-01 | Attestor Guild | Define `AIPolicyDraft` predicate: extends AIArtifactBase + rules[], test_cases[], validation_result | +| 6 | AIATTEST-06 | TODO | AIATTEST-01 | Attestor Guild | Define `AIArtifactAuthority` enum: Suggestion, EvidenceBacked, AuthorityThreshold (configurable threshold for each) | +| 7 | AIATTEST-07 | TODO | AIATTEST-06 | Attestor Guild | Authority classifier: rules for when artifact qualifies as EvidenceBacked (citation rate β‰₯ X, evidence refs valid, etc.) | +| 8 | AIATTEST-08 | TODO | AIATTEST-02 | ProofChain Guild | Implement `AIExplanationStatement` in ProofChain | +| 9 | AIATTEST-09 | TODO | AIATTEST-03 | ProofChain Guild | Implement `AIRemediationPlanStatement` in ProofChain | +| 10 | AIATTEST-10 | TODO | AIATTEST-04 | ProofChain Guild | Implement `AIVexDraftStatement` in ProofChain | +| 11 | AIATTEST-11 | TODO | AIATTEST-05 | ProofChain Guild | Implement `AIPolicyDraftStatement` in ProofChain | +| 12 | AIATTEST-12 | TODO | AIATTEST-08 | OCI Guild | Register `application/vnd.stellaops.ai.explanation+json` media type | +| 13 | AIATTEST-13 | TODO | AIATTEST-09 | OCI Guild | Register `application/vnd.stellaops.ai.remediation+json` media type | +| 14 | AIATTEST-14 | TODO | AIATTEST-10 | OCI Guild | Register `application/vnd.stellaops.ai.vexdraft+json` media type | +| 15 | AIATTEST-15 | TODO | AIATTEST-11 | OCI Guild | Register `application/vnd.stellaops.ai.policydraft+json` media type | +| 16 | AIATTEST-16 | TODO | AIATTEST-12 | ExportCenter Guild | Implement AI attestation push via `OciReferrerPushClient` | +| 17 | AIATTEST-17 | TODO | AIATTEST-16 | ExportCenter Guild | Implement AI attestation discovery via `OciReferrerDiscovery` | +| 18 | AIATTEST-18 | TODO | AIATTEST-01 | Replay Guild | Create `AIArtifactReplayManifest` capturing all inputs for deterministic replay | +| 19 | AIATTEST-19 | TODO | AIATTEST-18 | Replay Guild | Implement `IAIArtifactReplayer` for re-executing AI generation with pinned inputs | +| 20 | AIATTEST-20 | TODO | AIATTEST-19 | Replay Guild | Replay verification: compare output hash with original, flag divergence | +| 21 | AIATTEST-21 | TODO | AIATTEST-20 | Verification Guild | Add AI artifact verification to `VerificationPipeline` | +| 22 | AIATTEST-22 | TODO | All above | Testing Guild | Integration tests: attestation creation, OCI push/pull, replay verification | +| 23 | AIATTEST-23 | TODO | All above | Docs Guild | Document AI attestation schemas, replay semantics, authority classification | + +## Execution Log +| Date (UTC) | Update | Owner | +| --- | --- | --- | +| 2025-12-26 | Sprint created from AI Assistant Advisory analysis; extends ProofChain with AI-specific attestation types. | Project Mgmt | + +## Decisions & Risks +- Decision needed: Model digest format (SHA-256 of weights, version string, provider+model). Recommend: provider:model:version for cloud, SHA-256 for local. +- Decision needed: Evidence-backed threshold. Recommend: β‰₯80% citations valid AND all evidence_refs resolvable. +- Risk: Model version drift between attestation and replay. Mitigation: fail replay if model unavailable; document fallback. +- Risk: Large attestation sizes. Mitigation: store evidence refs, not full content; link to evidence locker. + +## Next Checkpoints +- 2025-12-30 | AIATTEST-07 complete | All predicate types defined | +- 2026-01-03 | AIATTEST-17 complete | OCI integration working | +- 2026-01-06 | AIATTEST-23 complete | Full documentation and replay verification | diff --git a/docs/implplan/SPRINT_20251226_019_AI_offline_inference.md b/docs/implplan/SPRINT_20251226_019_AI_offline_inference.md new file mode 100644 index 000000000..5eb8822cf --- /dev/null +++ b/docs/implplan/SPRINT_20251226_019_AI_offline_inference.md @@ -0,0 +1,91 @@ +# Sprint 20251226 Β· Sovereign/Offline AI Inference + +## Topic & Scope +- Ship a local inference profile with permissive-license weights and pinned digests +- Enable full AI feature replay in air-gapped environments +- Support regional crypto requirements (eIDAS/FIPS/GOST/SM) for AI attestation signing +- **Working directory:** `src/AdvisoryAI/`, `src/Cryptography/`, `etc/` + +## Dependencies & Concurrency +- Depends on: AdvisoryAI inference client (COMPLETE). +- Depends on: Cryptography module with regional crypto (COMPLETE). +- Depends on: SPRINT_20251226_018_AI_attestations (attestation types for replay). +- Can run in parallel with: SPRINT_20251226_015/016/017 (uses local inference as fallback). + +## Documentation Prerequisites +- `src/AdvisoryAI/StellaOps.AdvisoryAI/Inference/AdvisoryInferenceClient.cs` +- `src/Cryptography/` (regional crypto plugins) +- `docs/24_OFFLINE_KIT.md` +- AI Assistant Advisory (this sprint's source) + +## Context: What Already Exists + +The following components are **already implemented**: + +| Component | Location | Status | +|-----------|----------|--------| +| Local Inference Client | `AdvisoryAI/Inference/LocalAdvisoryInferenceClient.cs` | COMPLETE (stub) | +| Remote Inference Client | `AdvisoryAI/Inference/RemoteAdvisoryInferenceClient.cs` | COMPLETE | +| Inference Mode Config | `AdvisoryAiInferenceMode.Local/Remote` | COMPLETE | +| Regional Crypto | `src/Cryptography/` (eIDAS, FIPS, GOST, SM) | COMPLETE | +| Air-gap Support | `AirgapOptions`, `AirgapModeEnforcer` | COMPLETE | +| Replay Manifest | `StellaOps.Replay.Core/ReplayManifest.cs` | COMPLETE | + +This sprint extends the local inference stub to full local LLM execution with offline-compatible features. + +## Delivery Tracker +| # | Task ID | Status | Key dependency / next step | Owners | Task Definition | +| --- | --- | --- | --- | --- | --- | +| 1 | OFFLINE-01 | TODO | None | AdvisoryAI Guild | Evaluate permissive-license LLM options: Llama 3, Mistral, Phi-3, Qwen2, Gemma 2 | +| 2 | OFFLINE-02 | TODO | OFFLINE-01 | AdvisoryAI Guild | Define model selection criteria: license (Apache/MIT/permissive), size (<30GB), performance, multilingual | +| 3 | OFFLINE-03 | TODO | OFFLINE-02 | AdvisoryAI Guild | Create `LocalLlmConfig` model: model_path, weights_digest, quantization, context_length, device (CPU/GPU/NPU) | +| 4 | OFFLINE-04 | TODO | OFFLINE-03 | AdvisoryAI Guild | Implement `ILocalLlmRuntime` interface for local model execution | +| 5 | OFFLINE-05 | TODO | OFFLINE-04 | AdvisoryAI Guild | Implement `LlamaCppRuntime` using llama.cpp bindings for CPU/GPU inference | +| 6 | OFFLINE-06 | TODO | OFFLINE-04 | AdvisoryAI Guild | Implement `OnnxRuntime` option for ONNX-exported models | +| 7 | OFFLINE-07 | TODO | OFFLINE-05 | AdvisoryAI Guild | Replace `LocalAdvisoryInferenceClient` stub with actual local LLM inference | +| 8 | OFFLINE-08 | TODO | OFFLINE-07 | AdvisoryAI Guild | Implement model loading with digest verification (SHA-256 of weights file) | +| 9 | OFFLINE-09 | TODO | OFFLINE-08 | AdvisoryAI Guild | Add inference caching: cache responses by input hash for deterministic replay | +| 10 | OFFLINE-10 | TODO | OFFLINE-09 | AdvisoryAI Guild | Implement temperature=0, fixed seed for deterministic outputs | +| 11 | OFFLINE-11 | TODO | None | Packaging Guild | Create offline model bundle packaging: weights + tokenizer + config + digest manifest | +| 12 | OFFLINE-12 | TODO | OFFLINE-11 | Packaging Guild | Define bundle format: tar.gz with manifest.json listing all files + digests | +| 13 | OFFLINE-13 | TODO | OFFLINE-12 | Packaging Guild | Implement `stella model pull --offline` CLI for downloading model bundles | +| 14 | OFFLINE-14 | TODO | OFFLINE-13 | Packaging Guild | Implement `stella model verify` CLI for verifying bundle integrity | +| 15 | OFFLINE-15 | TODO | OFFLINE-08 | Crypto Guild | Sign model bundles with regional crypto (allow eIDAS/FIPS/GOST/SM keys) | +| 16 | OFFLINE-16 | TODO | OFFLINE-15 | Crypto Guild | Verify model bundle signatures at load time | +| 17 | OFFLINE-17 | TODO | OFFLINE-10 | Replay Guild | Extend `AIArtifactReplayManifest` with local model info: path, digest, quantization | +| 18 | OFFLINE-18 | TODO | OFFLINE-17 | Replay Guild | Implement offline replay: re-run AI generation using local model bundle | +| 19 | OFFLINE-19 | TODO | OFFLINE-18 | Replay Guild | Divergence detection: flag when local and remote models produce different outputs for same input | +| 20 | OFFLINE-20 | TODO | OFFLINE-07 | Performance Guild | Benchmark local inference: throughput (tokens/sec), latency (first token, total), memory | +| 21 | OFFLINE-21 | TODO | OFFLINE-20 | Performance Guild | Optimize for low-memory environments: streaming, quantization, model sharding | +| 22 | OFFLINE-22 | TODO | OFFLINE-16 | Airgap Guild | Integrate with existing `AirgapModeEnforcer`: auto-select local inference in airgap mode | +| 23 | OFFLINE-23 | TODO | OFFLINE-22 | Airgap Guild | Document model bundle transfer for air-gapped environments (USB, sneakernet) | +| 24 | OFFLINE-24 | TODO | OFFLINE-22 | Config Guild | Add config: `AdvisoryAI:Inference:OfflineBundle:Path`, `AdvisoryAI:Inference:OfflineBundle:RequiredDigest` | +| 25 | OFFLINE-25 | TODO | All above | Testing Guild | Integration tests: local inference, bundle verification, offline replay | +| 26 | OFFLINE-26 | TODO | All above | Docs Guild | Document offline AI setup, model bundle format, performance tuning | + +## Execution Log +| Date (UTC) | Update | Owner | +| --- | --- | --- | +| 2025-12-26 | Sprint created from AI Assistant Advisory analysis; enables sovereign AI inference for air-gapped environments. | Project Mgmt | + +## Decisions & Risks +- Decision needed: Primary model choice. Recommend: Llama 3 8B (Apache 2.0, good quality/size balance). +- Decision needed: Quantization level. Recommend: Q4_K_M for CPU, FP16 for GPU. +- Decision needed: Bundle distribution. Recommend: separate download, not in main installer. +- Risk: Model quality degradation with small models. Mitigation: tune prompts for local models; fallback to templates. +- Risk: High resource requirements. Mitigation: offer multiple model sizes; document minimum specs. +- Risk: GPU compatibility. Mitigation: CPU fallback always available; test on common hardware. + +## Hardware Requirements (Documented) + +| Model Size | RAM | GPU VRAM | CPU Cores | Inference Speed | +|------------|-----|----------|-----------|-----------------| +| 7-8B Q4 | 8GB | N/A (CPU) | 4+ | ~10 tokens/sec | +| 7-8B FP16 | 16GB | 8GB | N/A | ~50 tokens/sec | +| 13B Q4 | 16GB | N/A (CPU) | 8+ | ~5 tokens/sec | +| 13B FP16 | 32GB | 16GB | N/A | ~30 tokens/sec | + +## Next Checkpoints +- 2025-12-30 | OFFLINE-07 complete | Local LLM inference functional | +- 2026-01-03 | OFFLINE-16 complete | Signed model bundles with regional crypto | +- 2026-01-06 | OFFLINE-26 complete | Full documentation and offline replay | diff --git a/docs/modules/signer/guides/keyless-signing.md b/docs/modules/signer/guides/keyless-signing.md new file mode 100644 index 000000000..bd5642ade --- /dev/null +++ b/docs/modules/signer/guides/keyless-signing.md @@ -0,0 +1,273 @@ +# Keyless Signing Guide + +## Overview + +Keyless signing uses ephemeral X.509 certificates from Sigstore Fulcio, eliminating the need for persistent signing keys. This approach is ideal for CI/CD pipelines where key management is complex and error-prone. + +### How It Works + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ CI Pipeline │────▢│ OIDC Provider│────▢│ Fulcio │────▢│ Rekor β”‚ +β”‚ β”‚ β”‚ (GitHub/GL) β”‚ β”‚ (Sigstore) β”‚ β”‚ (Sigstore) β”‚ +β”‚ 1. Get token β”‚ β”‚ 2. Issue JWT β”‚ β”‚ 3. Issue certβ”‚ β”‚ 4. Log entry β”‚ +β”‚ β”‚ β”‚ (5 min) β”‚ β”‚ (10 min) β”‚ β”‚ (permanent) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ β”‚ + β”‚ β”‚ + └───────────── Attestation with cert + Rekor proof β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +1. **OIDC Token**: Pipeline requests identity token from CI platform +2. **Fulcio Certificate**: Token exchanged for short-lived signing certificate (~10 min) +3. **Ephemeral Key**: Private key exists only in memory during signing +4. **Rekor Logging**: Signature logged to transparency log for verification after cert expiry + +### Key Benefits + +| Benefit | Description | +|---------|-------------| +| **Zero Key Management** | No secrets to rotate, store, or protect | +| **Identity Binding** | Signatures tied to OIDC identity (repo, branch, workflow) | +| **Audit Trail** | All signatures logged to Rekor transparency log | +| **Short-lived Certs** | Minimizes exposure window (~10 minutes) | +| **Industry Standard** | Adopted by Kubernetes, npm, PyPI, and major ecosystems | + +## Quick Start + +### Prerequisites + +1. StellaOps CLI installed +2. CI platform with OIDC support (GitHub Actions, GitLab CI, Gitea) +3. Network access to Fulcio and Rekor (or private instances) + +### GitHub Actions Example + +```yaml +name: Sign Container Image + +on: + push: + branches: [main] + +jobs: + build-and-sign: + runs-on: ubuntu-latest + permissions: + id-token: write # Required for OIDC + contents: read + packages: write + + steps: + - uses: actions/checkout@v4 + + - name: Build and Push Image + id: build + run: | + docker build -t ghcr.io/${{ github.repository }}:${{ github.sha }} . + docker push ghcr.io/${{ github.repository }}:${{ github.sha }} + echo "digest=$(docker inspect --format='{{index .RepoDigests 0}}' ghcr.io/${{ github.repository }}:${{ github.sha }} | cut -d@ -f2)" >> $GITHUB_OUTPUT + + - name: Keyless Sign + uses: stella-ops/sign-action@v1 + with: + artifact-digest: ${{ steps.build.outputs.digest }} + artifact-type: image +``` + +### CLI Usage + +```bash +# Sign with ambient OIDC token (in CI environment) +stella attest sign --keyless --artifact sha256:abc123... + +# Sign with explicit token +STELLAOPS_OIDC_TOKEN="..." stella attest sign --keyless --artifact sha256:abc123... + +# Verify signature (checks Rekor proof) +stella attest verify \ + --artifact sha256:abc123... \ + --certificate-identity "repo:myorg/myrepo:ref:refs/heads/main" \ + --certificate-oidc-issuer "https://token.actions.githubusercontent.com" +``` + +## Configuration + +### Signer Configuration + +```yaml +# etc/signer.yaml +signer: + signing: + mode: "keyless" + keyless: + enabled: true + fulcio: + url: "https://fulcio.sigstore.dev" + timeout: 30s + retries: 3 + oidc: + issuer: "https://authority.internal" + clientId: "signer-keyless" + useAmbientToken: true + algorithms: + preferred: "ECDSA_P256" + allowed: ["ECDSA_P256", "Ed25519"] + certificate: + rootBundlePath: "/etc/stellaops/fulcio-roots.pem" + validateChain: true + requireSCT: true +``` + +### Private Fulcio Instance + +For air-gapped or high-security environments, deploy a private Fulcio instance: + +```yaml +signer: + signing: + keyless: + fulcio: + url: "https://fulcio.internal.example.com" + oidc: + issuer: "https://keycloak.internal.example.com/realms/stellaops" + certificate: + rootBundlePath: "/etc/stellaops/private-fulcio-roots.pem" +``` + +## Identity Verification + +### Identity Constraints + +When verifying signatures, specify which identities are trusted: + +```bash +stella attest verify \ + --artifact sha256:abc123... \ + --certificate-identity "repo:myorg/myrepo:ref:refs/heads/main" \ + --certificate-oidc-issuer "https://token.actions.githubusercontent.com" +``` + +### Platform Identity Patterns + +#### GitHub Actions + +| Pattern | Matches | +|---------|---------| +| `repo:org/repo:.*` | Any ref in repository | +| `repo:org/repo:ref:refs/heads/main` | Main branch only | +| `repo:org/repo:ref:refs/tags/v.*` | Version tags | +| `repo:org/repo:environment:production` | Production environment | + +**Issuer:** `https://token.actions.githubusercontent.com` + +#### GitLab CI + +| Pattern | Matches | +|---------|---------| +| `project_path:group/project:.*` | Any ref in project | +| `project_path:group/project:ref_type:branch:ref:main` | Main branch | +| `project_path:group/project:ref_protected:true` | Protected refs only | + +**Issuer:** `https://gitlab.com` (or self-hosted URL) + +## Long-Term Verification + +### The Problem + +Fulcio certificates expire in ~10 minutes. How do you verify signatures months later? + +### The Solution: Rekor Proofs + +``` +At signing time: +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Signature + Certificate + Signed-Certificate-Timestamp (SCT) β”‚ +β”‚ ↓ β”‚ +β”‚ Logged to Rekor β”‚ +β”‚ ↓ β”‚ +β”‚ Merkle Inclusion Proof returned β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +At verification time (even years later): +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ 1. Check signature is valid (using cert public key) β”‚ +β”‚ 2. Check SCT proves cert was logged when valid β”‚ +β”‚ 3. Check Rekor inclusion proof (entry was logged) β”‚ +β”‚ 4. Check signing time was within cert validity window β”‚ +β”‚ ↓ β”‚ +β”‚ Signature is valid! βœ“ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Attestation Bundles + +For air-gapped verification, StellaOps bundles attestations with proofs: + +```bash +# Export bundle with Rekor proofs +stella attest export-bundle \ + --image sha256:abc123... \ + --include-proofs \ + --output attestation-bundle.json + +# Verify offline +stella attest verify --offline \ + --bundle attestation-bundle.json \ + --artifact sha256:abc123... +``` + +## Troubleshooting + +### Common Errors + +| Error | Cause | Solution | +|-------|-------|----------| +| `OIDC token expired` | Token older than 5 minutes | Re-acquire token before signing | +| `Fulcio unavailable` | Network issues | Check connectivity, increase timeout | +| `Certificate chain invalid` | Wrong Fulcio roots | Update root bundle | +| `Identity mismatch` | Wrong verify constraints | Check issuer and identity patterns | +| `Rekor proof missing` | Logging failed | Retry signing, check Rekor status | + +### Debug Mode + +```bash +# Enable verbose logging +STELLAOPS_LOG_LEVEL=debug stella attest sign --keyless --artifact sha256:... + +# Inspect certificate details +stella attest inspect --artifact sha256:... --show-cert +``` + +## Security Considerations + +### Best Practices + +1. **Always verify identity**: Never accept `.*` as the full identity pattern +2. **Require Rekor proofs**: Use `--require-rekor` for production verification +3. **Pin OIDC issuers**: Only trust expected issuers +4. **Use environment constraints**: More specific than branch names +5. **Monitor signing activity**: Alert on unexpected identities + +### Threat Model + +| Threat | Mitigation | +|--------|------------| +| Stolen OIDC token | Short lifetime (~5 min), audience binding | +| Fulcio compromise | Certificate Transparency (SCT), multiple roots | +| Rekor compromise | Multiple witnesses, checkpoints, consistency proofs | +| Private key theft | Ephemeral keys, never persisted | + +## Related Documentation + +- [Signer Architecture](../architecture.md) +- [Attestor Bundle Format](../../attestor/bundle-format.md) +- [Air-Gap Verification](../../../airgap/attestation-verification.md) +- [CI/CD Integration](../../../guides/cicd-signing.md) + +## External Resources + +- [Sigstore Documentation](https://docs.sigstore.dev/) +- [Fulcio Overview](https://docs.sigstore.dev/certificate_authority/overview/) +- [Rekor Transparency Log](https://docs.sigstore.dev/logging/overview/) +- [cosign Keyless Signing](https://docs.sigstore.dev/signing/quickstart/) diff --git a/docs/modules/web/unified-triage-specification.md b/docs/modules/web/unified-triage-specification.md new file mode 100644 index 000000000..5c8ace429 --- /dev/null +++ b/docs/modules/web/unified-triage-specification.md @@ -0,0 +1,348 @@ +# Unified Triage Experience Specification + +**Version:** 1.0 +**Status:** Active +**Last Updated:** 2025-12-26 +**Consolidated From:** 3 product advisories (see References) + +## 1. Executive Summary + +### The Problem +Modern container security generates overwhelming vulnerability data. Competitors offer fragmented solutions: Snyk provides reachability analysis, Anchore offers VEX annotations, Prisma Cloud delivers runtime signals. Security teams must context-switch between tools, losing precious time and context. + +### The Stella Ops Solution +A **unified triage canvas** that combines: +- Rich evidence visualization with proof-carrying verdicts +- VEX decisioning as first-class policy objects +- AI-assisted analysis via AdvisoryAI +- Attestable exceptions with audit trails +- Offline-first architecture for air-gapped parity + +## 2. Competitive Landscape + +### Snyk β€” Reachability + Continuous Context +- Implements reachability analysis building call graphs +- Factors reachability into priority scores +- Uses static analysis + AI + expert curation +- Tracks issues over time without re-scanning unchanged images + +### Anchore β€” Vulnerability Annotations + VEX Export +- Vulnerability annotation workflows via UI/API +- Labels: "not applicable", "mitigated", "under investigation" +- Export as OpenVEX and CycloneDX VEX +- Downstream consumers receive curated exploitability state + +### Prisma Cloud β€” Runtime Defense +- Continuous behavioral profiling +- Process, file, and network rule enforcement +- Learning models baseline expected behavior +- Runtime context during operational incidents + +### Stella Ops Differentiation +| Feature | Snyk | Anchore | Prisma | Stella Ops | +|---------|------|---------|--------|------------| +| Reachability analysis | Yes | Partial | No | Yes (static + binary + runtime) | +| VEX as policy objects | No | Export only | No | **First-class** | +| Attestable exceptions | No | No | No | **Yes (DSSE)** | +| Offline replay | No | No | No | **Yes** | +| AI-assisted triage | Yes | No | No | Yes (AdvisoryAI) | +| Evidence graphs | Partial | No | Partial | **Full chain** | + +## 3. Core UI Concepts + +### 3.1 Visual Diff Pattern +Every policy decision or reachability change is treated as a **visual diff**, enabling quick, explainable triage. + +#### Side-by-Side Panes +- **Before** (previous scan/policy) vs **After** (current) +- Show dependency/reachability subgraph +- Highlight added/removed/changed nodes/edges + +#### Evidence Strip (Right Rail) +Human-readable facts used by the engine: +- Feature flag status (e.g., "feature flag OFF") +- Code path analysis (e.g., "code path unreachable") +- Runtime traces (e.g., "kernel eBPF trace absent") + +#### Diff Verdict Header +``` +Risk ↓ from Medium β†’ Low (policy v1.8 β†’ v1.9) +``` + +#### Filter Chips +Scope by: component, package, CVE, policy rule, environment + +### 3.2 Data Models + +```typescript +interface GraphSnapshot { + nodes: GraphNode[]; + edges: GraphEdge[]; + metadata: { component: string; version: string; tags: string[] }; +} + +interface PolicySnapshot { + version: string; + rulesHash: string; + inputs: { flags: Record; env: string; vexSources: string[] }; +} + +interface Delta { + added: DeltaItem[]; + removed: DeltaItem[]; + changed: DeltaItem[]; + ruleOutcomes: RuleOutcomeDelta[]; +} + +interface EvidenceItem { + type: 'trace_hit' | 'sbom_line' | 'vex_claim' | 'config_value'; + source: string; + digest: string; + excerpt: string; + timestamp: string; +} + +interface SignedDeltaVerdict { + status: 'routine' | 'review' | 'block'; + signatures: Signature[]; + producer: string; +} +``` + +### 3.3 Micro-Interactions + +| Interaction | Behavior | +|-------------|----------| +| Hover changed node | Inline badge explaining "why it changed" | +| Click rule in rail | Spotlight the exact subgraph affected | +| Toggle "explain like I'm new" | Expands jargon into plain language | +| One-click "copy audit bundle" | Exports delta + evidence as attachment | + +### 3.4 Keyboard Shortcuts + +| Key | Action | +|-----|--------| +| `1` | Focus changes only | +| `2` | Show full graph | +| `E` | Expand evidence | +| `A` | Export audit bundle | +| `N` | Next item in queue | +| `P` | Previous item | +| `M` | Mark not affected | + +## 4. Risk Budget Visualization + +### 4.1 Concept +- **Risk budget** = allowable unresolved risk for a release (e.g., 100 "risk points") +- **Burn** = consumption rate as alerts appear, minus "payback" from fixes + +### 4.2 Dashboard Components + +#### Heatmap of Unknowns +| Component | Vulns | Compliance | Perf | Data | Supply Chain | +|-----------|-------|------------|------|------|--------------| +| Service A | 🟑 12 | 🟒 0 | 🟑 3 | πŸ”΄ 8 | 🟑 5 | +| Service B | πŸ”΄ 24 | 🟑 2 | 🟒 1 | 🟑 4 | 🟒 0 | + +Cell value = unknowns count Γ— severity weight + +#### Delta Table (Risk Decay per Release) +| Release | Before | After | Retired | Shifted | Unknowns | +|---------|--------|-------|---------|---------|----------| +| v2.3.1 | 85 | 67 | -22 | +4 | 12 | +| v2.3.0 | 92 | 85 | -15 | +8 | 18 | + +#### Exception Ledger +Every accepted risk has: ID, owner, expiry, evidence note, auto-reminder. + +### 4.3 Risk Budget Burn-Up Chart + +``` +Risk Points + ^ +100 |__________ Budget Line (flat or stepped) + | \ + 80 | \ ← Actual Risk (cumulative) + | \ + 60 | \_____ Headroom (green) + | \ + 40 | \__ Target by release + | + +---------------------------------> Time + T-30 T-14 T-7 T-2 Release +``` + +- **X-axis:** Calendar dates to code freeze +- **Y-axis:** Risk points +- **Two lines:** Budget (flat/stepped) + Actual Risk (daily) +- **Shaded area:** Headroom (green) or Overrun (red) +- **Markers:** Feature freeze, pen-test, dependency bumps + +### 4.4 Computation Formulas + +```typescript +// Risk points per issue +risk_points = severity_weight Γ— exposure_factor Γ— evidence_freshness_penalty + +// Unknown penalty (no evidence ≀ N days) +if (days_since_evidence > threshold) { + risk_points *= 1.5; // multiplier +} + +// Decay on fix +if (fix_landed && evidence_refreshed) { + subtract_points(issue.risk_points); +} + +// Guardrails +if (unknowns > K || actual_risk > budget) { + fail_gate(); +} +``` + +## 5. Implementation Components + +### 5.1 Component Hierarchy + +``` +TriageCanvasComponent +β”œβ”€β”€ TriageListComponent +β”‚ β”œβ”€β”€ SeverityFilterComponent +β”‚ β”œβ”€β”€ VulnerabilityRowComponent +β”‚ └── BulkActionBarComponent +β”œβ”€β”€ TriageDetailComponent +β”‚ β”œβ”€β”€ AffectedPackagesPanel +β”‚ β”œβ”€β”€ AdvisoryRefsPanel +β”‚ β”œβ”€β”€ ReachabilityContextComponent +β”‚ └── EvidenceProvenanceComponent +β”œβ”€β”€ AiRecommendationPanel +β”‚ β”œβ”€β”€ ReachabilityExplanation +β”‚ β”œβ”€β”€ SuggestedJustification +β”‚ └── SimilarVulnsComponent +β”œβ”€β”€ VexDecisionModalComponent +β”‚ β”œβ”€β”€ StatusSelector +β”‚ β”œβ”€β”€ JustificationTypeSelector +β”‚ β”œβ”€β”€ EvidenceRefInput +β”‚ └── ScopeSelector +└── VexHistoryComponent + +CompareViewComponent +β”œβ”€β”€ BaselineSelectorComponent +β”œβ”€β”€ TrustIndicatorsComponent +β”œβ”€β”€ DeltaSummaryStripComponent +β”œβ”€β”€ ThreePaneLayoutComponent +β”‚ β”œβ”€β”€ CategoriesPaneComponent +β”‚ β”œβ”€β”€ ItemsPaneComponent +β”‚ └── ProofPaneComponent +β”œβ”€β”€ ActionablesPanelComponent +└── ExportActionsComponent + +RiskDashboardComponent +β”œβ”€β”€ BurnUpChartComponent +β”œβ”€β”€ UnknownsHeatmapComponent +β”œβ”€β”€ DeltaTableComponent +β”œβ”€β”€ ExceptionLedgerComponent +└── KpiTilesComponent +``` + +### 5.2 Service Layer + +```typescript +// Core services +TriageService // Vulnerability list + filtering +VexDecisionService // CRUD for VEX decisions +AdvisoryAiService // AI recommendations +CompareService // Baseline + delta computation +RiskBudgetService // Budget + burn tracking +EvidenceService // Evidence retrieval +``` + +## 6. API Integration + +### VulnExplorer Endpoints +``` +GET /api/v1/vulnerabilities // List with filters +GET /api/v1/vulnerabilities/{id} // Detail +GET /api/v1/vulnerabilities/{id}/reachability // Call graph slice +POST /api/v1/vex-decisions // Create VEX decision +PUT /api/v1/vex-decisions/{id} // Update VEX decision +GET /api/v1/vex-decisions?vulnId={id} // History for vuln +``` + +### AdvisoryAI Endpoints +``` +POST /api/v1/advisory/plan // Get analysis plan +POST /api/v1/advisory/execute // Execute analysis +GET /api/v1/advisory/output/{taskId} // Get recommendations +``` + +### Delta/Compare Endpoints +``` +GET /api/v1/baselines/recommendations/{digest} +POST /api/v1/delta/compute +GET /api/v1/delta/{id}/trust-indicators +GET /api/v1/actionables/delta/{id} +``` + +## 7. Implementation Status + +| Component | Sprint | Status | +|-----------|--------|--------| +| Risk Dashboard Base | SPRINT_20251226_004_FE | TODO | +| Smart-Diff Compare View | SPRINT_20251226_012_FE | TODO | +| Unified Triage Canvas | SPRINT_20251226_013_FE | TODO | +| Documentation Consolidation | SPRINT_20251226_014_DOCS | TODO | +| VEX Decision Models | VulnExplorer/Models | **COMPLETE** | +| AdvisoryAI Pipeline | src/AdvisoryAI | **COMPLETE** | +| Confidence Badge | Web/shared/components | **COMPLETE** | +| Release Flow | Web/features/releases | **COMPLETE** | + +## 8. Testing Strategy + +### Unit Tests +- Component behavior (selection, filtering, expansion) +- Signal/computed derivations +- Role-based view switching +- Form validation (VEX decisions) + +### Integration Tests +- API service calls and response handling +- Navigation and routing +- State persistence across route changes + +### E2E Tests +- Full triage workflow: list β†’ detail β†’ VEX decision +- Comparison workflow: select baseline β†’ compute delta β†’ export +- Risk budget: view charts β†’ create exception β†’ see update + +### Accessibility Tests +- Keyboard navigation completeness +- Screen reader announcements +- Color contrast compliance + +## 9. Success Metrics + +| Metric | Definition | Target | +|--------|------------|--------| +| Mean Time to Triage (MTTT) | Time from vuln notification to VEX decision | < 5 min | +| Mean Time to Explain (MTTE) | Time from "why did this change?" to "Understood" click | < 2 min | +| Triage Queue Throughput | Vulns triaged per hour per analyst | > 20 | +| AI Recommendation Acceptance | % of AI suggestions accepted without modification | > 60% | + +## 10. References + +### Archived Advisories (Consolidated Here) +- `archived/2025-12-26-triage-advisories/25-Dec-2025 - Triage UI Lessons from Competitors.md` +- `archived/2025-12-26-triage-advisories/25-Dec-2025 - Visual Diffs for Explainable Triage.md` +- `archived/2025-12-26-triage-advisories/26-Dec-2026 - Visualizing the Risk Budget.md` + +### Related Documentation +- `docs/modules/web/smart-diff-ui-architecture.md` +- `docs/implplan/SPRINT_20251226_004_FE_risk_dashboard.md` +- `docs/implplan/SPRINT_20251226_012_FE_smart_diff_compare.md` +- `docs/implplan/SPRINT_20251226_013_FE_triage_canvas.md` + +### External References +- [Snyk Reachability Analysis](https://docs.snyk.io/manage-risk/prioritize-issues-for-fixing/reachability-analysis) +- [Anchore Vulnerability Annotations](https://docs.anchore.com/current/docs/vulnerability_management/vuln_annotations/) +- [Prisma Cloud Runtime Defense](https://docs.prismacloud.io/en/compute-edition/30/admin-guide/runtime-defense/) diff --git a/docs/product-advisories/25-Dec-2025 - Building a Deterministic Verdict Engine.md b/docs/product-advisories/25-Dec-2025 - Building a Deterministic Verdict Engine.md index fd511310d..d9b1a4cae 100644 --- a/docs/product-advisories/25-Dec-2025 - Building a Deterministic Verdict Engine.md +++ b/docs/product-advisories/25-Dec-2025 - Building a Deterministic Verdict Engine.md @@ -1,104 +1,146 @@ -Here’s a tight, practical blueprint for evolving Stellaβ€―Ops’s policy engine into a **fully deterministic verdict engine**β€”so the *same SBOM + VEX + reachability subgraph β‡’ the exact same, replayable verdict* every time, with auditor‑grade trails and signed β€œdelta verdicts.” +# Building a Deterministic Verdict Engine -# Why this matters (quick) +> **Status:** PLANNED β€” Implementation in progress +> **Date:** 2025-12-25 +> **Updated:** 2025-12-26 +> **Related Sprints:** [`SPRINT_20251226_007_BE_determinism_gaps.md`](../implplan/SPRINT_20251226_007_BE_determinism_gaps.md) +> **Merged Advisories:** [`25-Dec-2025 - Enforcing Canonical JSON for Stable Verdicts.md`](./25-Dec-2025%20-%20Enforcing%20Canonical%20JSON%20for%20Stable%20Verdicts.md) (SUPERSEDED) + +--- + +## Implementation Status + +| Component | Status | Location | +|-----------|--------|----------| +| Canonical JSON (JCS) | COMPLETE | `StellaOps.Canonical.Json` | +| NFC String Normalization | COMPLETE | `StellaOps.Resolver.NfcStringNormalizer` | +| Content-Addressed IDs | COMPLETE | `Attestor.ProofChain/Identifiers/` | +| DSSE Signing | COMPLETE | `Signer/`, `Attestor/` | +| Delta Verdict | COMPLETE | `Policy/Deltas/DeltaVerdict.cs` | +| Merkle Trees | COMPLETE | `ProofChain/Merkle/` | +| Determinism Guards | COMPLETE | `Policy.Engine/DeterminismGuard/` | +| Replay Manifest | COMPLETE | `StellaOps.Replay.Core` | +| Feed Snapshot Coordinator | TODO | SPRINT_20251226_007 DET-GAP-01..04 | +| Keyless Signing | TODO | SPRINT_20251226_001 | +| Cross-Platform Testing | TODO | SPRINT_20251226_007 DET-GAP-11..13 | + +**Overall Progress:** ~85% complete + +--- + +## Advisory Content + +Here's a tight, practical blueprint for evolving Stella Ops's policy engine into a **fully deterministic verdict engine**β€”so the *same SBOM + VEX + reachability subgraph β‡’ the exact same, replayable verdict* every time, with auditor‑grade trails and signed "delta verdicts." + +## Why this matters (quick) * **Reproducibility:** auditors can replay any scan and get identical results. * **Trust & scale:** cross‑agent consensus via content‑addressed inputs and signed outputs. * **Operational clarity:** diffs between builds become crisp, machine‑verifiable artifacts. -# Core principles +## Core principles * **Determinism-first:** no wall‑clock time, no random iteration order, no network during evaluation. * **Content‑addressing:** hash every *input* (SBOM, VEX docs, reachability subgraph, policy set, rule versions, feed snapshots). * **Declarative state:** a compact **Scan Manifest** lists input hashes + policy bundle hash + engine version. * **Pure evaluation:** the verdict function is referentially transparent: `Verdict = f(Manifest)`. -# Data artifacts +## Canonical JSON (Merged from Canonical JSON Advisory) + +All JSON artifacts must use **RFC 8785 JCS** canonicalization with optional **Unicode NFC** normalization: + +```csharp +// Existing implementation +using StellaOps.Canonical.Json; + +var canonical = CanonJson.Canonicalize(myObject); +var hash = CanonJson.Hash(myObject); +var versionedHash = CanonJson.HashVersioned(myObject, CanonVersion.V1); +``` + +**Canonicalization Rules:** +1. Object keys sorted lexicographically (Ordinal) +2. No whitespace or formatting variations +3. UTF-8 encoding without BOM +4. IEEE 754 number formatting +5. Version markers for migration safety (`_canonVersion: "stella:canon:v1"`) + +## Data artifacts * **Scan Manifest (`manifest.jsonc`)** - * `sbom_sha256`, `vex_set_sha256[]`, `reach_subgraph_sha256`, `feeds_snapshot_sha256`, `policy_bundle_sha256`, `engine_version`, `policy_semver`, `options_hash` + * **Verdict (`verdict.json`)** - * canonical JSON (stable key order); includes: - * `risk_score`, `status` (pass/warn/fail), `unknowns_count` * **evidence_refs:** content IDs for cited VEX statements, nodes/edges from reachability, CVE records, feature‑flags, env‑guards * **explanations:** stable, template‑driven strings (+ machine reasons) + * **Delta Verdict (`delta.json`)** - * computed between two manifests/verdicts: - * `added_findings[]`, `removed_findings[]`, `severity_shift[]`, `unknowns_delta`, `policy_effects[]` * signed (DSSE/COSE/JWS), time‑stamped, and linkable to both verdicts -# Engine architecture (deterministic path) +## Engine architecture (deterministic path) 1. **Normalize inputs** - * SBOM: sort by `packageUrl`/`name@version`; resolve aliases; freeze semver comparison rules. * VEX: normalize provider β†’ `vex_id`, `product_ref`, `status` (`affected`, `not_affected`, …), *with* source trust score precomputed from a **trust registry** (strict, versioned). * Reachability: store subgraph as adjacency lists sorted by node ID; hash after topological stable ordering. * Feeds: lock to a **snapshot** (timestamp + commit/hash); no live calls. -2. **Policy bundle** +2. **Policy bundle** * Declarative rules (e.g., lattice/merge semantics), compiled to a **canonical IR** (e.g., OPA‑Rego β†’ sorted DNF). * Merge precedence is explicit (e.g., `vendor > distro > internal` can be replaced by a lattice‑merge table). * Unknowns policy baked in: e.g., `fail_if_unknowns > N in prod`. -3. **Evaluation** +3. **Evaluation** * Build a **finding set**: `(component, vuln, context)` tuples with deterministic IDs. * Apply **lattice‑based VEX merge** (proof‑carrying): each suppression must carry an evidence pointer (feature flag off, code path unreachable, patched‑backport proof). * Compute final `status` and `risk_score` using fixed‑precision math; round rules are part of the bundle. -4. **Emit** +4. **Emit** * Canonicalize verdict JSON; attach **evidence map** (content IDs only). * Sign verdict; attach as **OCI attestation** to image/digest. -# APIs (minimal but complete) +## APIs (minimal but complete) * `POST /evaluate` β†’ returns `verdict.json` + attestation * `POST /delta` with `{base_verdict, head_verdict}` β†’ `delta.json` (signed) * `GET /replay?manifest_sha=` β†’ re‑executes using cached snapshot bundles, returns the same `verdict_sha` * `GET /evidence/:cid` β†’ fetches immutable evidence blobs (offline‑ready) -# Storage & indexing +## Storage & indexing * **CAS (content‑addressable store):** `/evidence/` for SBOM/VEX/graphs/feeds/policies. * **Verdict registry:** keyed by `(image_digest, manifest_sha, engine_version)`. * **Delta ledger:** append‑only, signed; supports cross‑agent consensus (multiple engines can co‑sign identical deltas). -# UI slices (where it lives) +## UI slices (where it lives) -* **Run details β†’ β€œVerdict” tab:** status, risk score, unknowns, top evidence links. -* **β€œDiff” tab:** render **Delta Verdict** (added/removed/changed), with drill‑down to proofs. -* **β€œReplay” button:** shows the exact manifest & engine version; one‑click re‑evaluation (offline possible). +* **Run details β†’ "Verdict" tab:** status, risk score, unknowns, top evidence links. +* **"Diff" tab:** render **Delta Verdict** (added/removed/changed), with drill‑down to proofs. +* **"Replay" button:** shows the exact manifest & engine version; one‑click re‑evaluation (offline possible). * **Audit export:** zip of `manifest.jsonc`, `verdict.json`, `delta.json` (if any), attestation, and referenced evidence. -# Testing & QA (must‑have) +## Testing & QA (must‑have) * **Golden tests:** fixtures of manifests β†’ frozen verdict JSONs (byte‑for‑byte). * **Chaos determinism tests:** vary thread counts, env vars, map iteration seeds; assert identical verdicts. * **Cross‑engine round‑trips:** two independent builds of the engine produce the same verdict for the same manifest. * **Time‑travel tests:** replay older feed snapshots to ensure stability. -# Rollout plan +## Rollout plan 1. **Phase 1:** Introduce Manifest + canonical verdict format alongside existing policy engine (shadow mode). -2. **Phase 2:** Make verdicts the **first‑class artifact** (OCI‑attached); ship UI β€œVerdict/Diff”. +2. **Phase 2:** Make verdicts the **first‑class artifact** (OCI‑attached); ship UI "Verdict/Diff". 3. **Phase 3:** Enforce **delta‑gates** in CI/CD (risk budgets + exception packs referenceable by content ID). 4. **Phase 4:** Open **consensus mode**β€”accept externally signed identical delta verdicts to strengthen trust. -# Notes for Stella modules +## Notes for Stella modules -* **scanner.webservice:** keep lattice algorithms here (per your standing rule). Concelier/Excitors β€œpreserve‑prune source.” +* **scanner.webservice:** keep lattice algorithms here (per your standing rule). Concelier/Excitors "preserve‑prune source." * **Authority/Attestor:** handle DSSE signing, key management, regional crypto profiles (eIDAS/FIPS/GOST/SM). * **Feedser/Vexer:** produce immutable **snapshot bundles**; never query live during evaluation. * **Router/Scheduler:** schedule replay jobs; cache manifests to speed up audits. * **Db:** Postgres as SoR; Valkey only for ephemeral queues/caches (per your BSD‑only profile). - -If you want, I can generate: - -* a sample **Manifest + Verdict + Delta** trio, -* the **canonical JSON schema**, -* and a **.NETβ€―10** reference evaluator (deterministic LINQ pipeline + fixed‑precision math) you can drop into `scanner.webservice`. diff --git a/docs/product-advisories/25-Dec-2025 - Enforcing Canonical JSON for Stable Verdicts.md b/docs/product-advisories/25-Dec-2025 - Enforcing Canonical JSON for Stable Verdicts.md index 6316fbd99..4a4144caa 100644 --- a/docs/product-advisories/25-Dec-2025 - Enforcing Canonical JSON for Stable Verdicts.md +++ b/docs/product-advisories/25-Dec-2025 - Enforcing Canonical JSON for Stable Verdicts.md @@ -1,10 +1,46 @@ -Here’s a small but high‑impact practice to make your hashes/signatures and β€œsame inputs β†’ same verdict” truly stable across services: **pick one canonicalization and enforce it at the resolver boundary.** +# Enforcing Canonical JSON for Stable Verdicts + +> **Status:** SUPERSEDED β€” Already implemented in codebase +> **Date:** 2025-12-25 +> **Updated:** 2025-12-26 +> **Superseded By:** Existing implementation in `StellaOps.Canonical.Json` +> **Related:** Merged into `25-Dec-2025 - Building a Deterministic Verdict Engine.md` + +--- + +## Implementation Status + +This advisory's recommendations are **already implemented** in the codebase: + +| Recommendation | Implementation | Location | +|----------------|----------------|----------| +| RFC 8785 JCS canonicalization | `Rfc8785JsonCanonicalizer` | `src/Attestor/__Libraries/StellaOps.Attestor.ProofChain/Json/` | +| Unicode NFC normalization | `NfcStringNormalizer` | `src/__Libraries/StellaOps.Resolver/` | +| Canonical JSON library | `CanonJson` | `src/__Libraries/StellaOps.Canonical.Json/` | +| Version markers | `CanonVersion` (stella:canon:v1) | `src/__Libraries/StellaOps.Canonical.Json/` | +| Content-addressed IDs | `ContentAddressedIdGenerator` | `src/Attestor/__Libraries/StellaOps.Attestor.ProofChain/Identifiers/` | +| Determinism testing | `DeterminismGate` | `src/__Libraries/StellaOps.TestKit/Determinism/` | + +### Remaining Gap Tasks + +Minor enforcement gaps are tracked in [`SPRINT_20251226_007_BE_determinism_gaps.md`](../implplan/SPRINT_20251226_007_BE_determinism_gaps.md): + +- DET-GAP-17: Optional NFC pass in canonicalizers +- DET-GAP-18: Roslyn analyzer for resolver boundary enforcement +- DET-GAP-19: Pre-canonical hash debug logging +- DET-GAP-20: Document resolver boundary pattern in CONTRIBUTING.md + +--- + +## Original Advisory Content + +Here's a small but high‑impact practice to make your hashes/signatures and "same inputs β†’ same verdict" truly stable across services: **pick one canonicalization and enforce it at the resolver boundary.** --- ### Why this matters (in plain words) -Two JSONs that *look* the same can serialize differently (key order, spacing, Unicode forms). If one producer emits slightly different bytes, your REG/verdict hash changesβ€”even though the meaning didn’tβ€”breaking dedup, cache hits, attestations, and audits. +Two JSONs that *look* the same can serialize differently (key order, spacing, Unicode forms). If one producer emits slightly different bytes, your REG/verdict hash changesβ€”even though the meaning didn'tβ€”breaking dedup, cache hits, attestations, and audits. --- @@ -24,11 +60,52 @@ Two JSONs that *look* the same can serialize differently (key order, spacing, Un 2. Resolver **normalizes strings (NFC)** and **re‑emits JSON in JCS**. 3. **REG hash** is computed from **JCS‑canonical UTF‑8 bytes** only. 4. Any signature/attestation (DSSE/OCI) MUST cover those same bytes. -5. Any module that can’t speak JCS must pass raw data to the resolver; only the resolver serializes. +5. Any module that can't speak JCS must pass raw data to the resolver; only the resolver serializes. --- -### Practical .NET 10 snippet (drop‑in utility) +### Existing Implementation (supersedes sample code) + +The codebase already provides a more robust implementation: + +```csharp +// Canonical JSON with version markers +using StellaOps.Canonical.Json; + +var canonical = CanonJson.Canonicalize(myObject); +var hash = CanonJson.Hash(myObject); +var versionedHash = CanonJson.HashVersioned(myObject, CanonVersion.V1); + +// NFC normalization +using StellaOps.Resolver; + +var normalizer = NfcStringNormalizer.Instance; +var nfcString = normalizer.Normalize(input); + +// RFC 8785 JCS for raw JSON bytes +using StellaOps.Attestor.ProofChain.Json; + +var canonicalizer = new Rfc8785JsonCanonicalizer(); +var canonicalBytes = canonicalizer.Canonicalize(utf8JsonBytes); +``` + +--- + +### Drop‑in checklist (pin on your wall) + +- [x] One canonicalization policy: **UTF‑8 + NFC + JCS**. *(Implemented: `CanonJson`, `NfcStringNormalizer`)* +- [x] Resolver owns canonicalization (single choke‑point). *(Pattern documented)* +- [x] **REG hash/signatures always over canonical bytes.** *(Implemented: `ContentAddressedIdGenerator`)* +- [ ] CI gate: reject outputs that aren't JCS; fuzz keys/order/whitespace in tests. *(In progress: SPRINT_20251226_007)* +- [ ] Log both the pre‑canonical and canonical SHA‑256 for audits. *(Planned: DET-GAP-19)* +- [x] Backward‑compat path: migrate legacy verdicts by re‑canonicalizing once, store "old_hash β†’ new_hash" map. *(Implemented: `CanonVersion` with version markers)* + +--- + +### Original Sample Code (archived for reference) + +
+Click to expand original sample code ```csharp using System.Text; @@ -110,26 +187,4 @@ public static class Canon } ``` -**Usage (hash/sign):** - -```csharp -var inputBytes = File.ReadAllBytes("input.json"); -var canon = Canon.CanonicalizeUtf8(inputBytes); -var sha256 = System.Security.Cryptography.SHA256.HashData(canon); -// sign `canon` bytes; attach hash to verdict/attestation -``` - ---- - -### Drop‑in checklist (pin on your wall) - -* [ ] One canonicalization policy: **UTF‑8 + NFC + JCS**. -* [ ] Resolver owns canonicalization (single choke‑point). -* [ ] **REG hash/signatures always over canonical bytes.** -* [ ] CI gate: reject outputs that aren’t JCS; fuzz keys/order/whitespace in tests. -* [ ] Log both the pre‑canonical and canonical SHA‑256 for audits. -* [ ] Backward‑compat path: migrate legacy verdicts by re‑canonicalizing once, store β€œold_hash β†’ new_hash” map. - ---- - -If you want, I can wrap this into a tiny **`StellaOps.Canonicalizer`** NuGet (net10.0) and a Git pre‑commit hook + CI check so your agents and services can’t drift. +
diff --git a/docs/product-advisories/25-Dec-2025 - Planning Keyless Signing for Verdicts.md b/docs/product-advisories/25-Dec-2025 - Planning Keyless Signing for Verdicts.md index 46472e196..0f9742018 100644 --- a/docs/product-advisories/25-Dec-2025 - Planning Keyless Signing for Verdicts.md +++ b/docs/product-advisories/25-Dec-2025 - Planning Keyless Signing for Verdicts.md @@ -1,4 +1,37 @@ -Here’s a practical, low‑friction way to modernize how you sign and verify build β€œverdicts” in CI/CD using Sigstoreβ€”no long‑lived keys, offline‑friendly, and easy to audit. +# Planning Keyless Signing for Verdicts + +> **Status:** PLANNED β€” Implementation sprints created +> **Date:** 2025-12-25 +> **Updated:** 2025-12-26 +> **Related:** Extends `25-Dec-2025 - Building a Deterministic Verdict Engine.md` + +--- + +## Implementation Sprints + +This advisory has been decomposed into the following implementation sprints: + +| Sprint | Module | Topic | Priority | +|--------|--------|-------|----------| +| [`SPRINT_20251226_001_SIGNER_fulcio_keyless_client.md`](../implplan/SPRINT_20251226_001_SIGNER_fulcio_keyless_client.md) | Signer | Fulcio keyless signing client | P0 | +| [`SPRINT_20251226_002_ATTESTOR_bundle_rotation.md`](../implplan/SPRINT_20251226_002_ATTESTOR_bundle_rotation.md) | Attestor | Monthly bundle rotation | P1 | +| [`SPRINT_20251226_003_ATTESTOR_offline_verification.md`](../implplan/SPRINT_20251226_003_ATTESTOR_offline_verification.md) | Attestor | Offline/air-gap verification | P2 | +| [`SPRINT_20251226_004_BE_cicd_signing_templates.md`](../implplan/SPRINT_20251226_004_BE_cicd_signing_templates.md) | Backend | CI/CD integration templates | P2 | + +**Total Tasks:** 98 across 4 sprints + +--- + +## Documentation Created + +- [`docs/modules/signer/guides/keyless-signing.md`](../modules/signer/guides/keyless-signing.md) β€” Keyless signing guide +- [`src/Signer/AGENTS.md`](../../src/Signer/AGENTS.md) β€” Signer module charter + +--- + +## Advisory Content + +Here's a practical, low‑friction way to modernize how you sign and verify build "verdicts" in CI/CD using Sigstoreβ€”no long‑lived keys, offline‑friendly, and easy to audit. --- diff --git a/docs/product-advisories/25-Dec-2025 - Visual Diffs for Explainable Triage.md b/docs/product-advisories/25-Dec-2025 - Visual Diffs for Explainable Triage.md deleted file mode 100644 index 86ed1e7b2..000000000 --- a/docs/product-advisories/25-Dec-2025 - Visual Diffs for Explainable Triage.md +++ /dev/null @@ -1,56 +0,0 @@ -Here’s a simple, high‑leverage UX pattern you can borrow from top observability tools: **treat every policy decision or reachability change as a visual diff.** - ---- - -### Why this helps - -* Turns opaque β€œwhy is this verdict different?” moments into **quick, explainable triage**. -* Reduces back‑and‑forth between Security, Dev, and Auditβ€”**everyone sees the same before/after evidence**. - -### Core UI concept - -* **Side‑by‑side panes**: **Before** (previous scan/policy) vs **After** (current). -* **Graph focus**: show the dependency/reachability subgraph; **highlight added/removed/changed nodes/edges**. -* **Evidence strip** (right rail): human‑readable facts used by the engine (e.g., *feature flag OFF*, *code path unreachable*, *kernel eBPF trace absent*). -* **Diff verdict header**: β€œRisk ↓ from *Medium β†’ Low* (policy v1.8 β†’ v1.9)”. -* **Filter chips**: Scope by component, package, CVE, policy rule, environment. - -### Minimal data model (so UI is easy) - -* `GraphSnapshot`: nodes, edges, metadata (component, version, tags). -* `PolicySnapshot`: version, rules hash, inputs (flags, env, VEX sources). -* `Delta`: `added/removed/changed` for nodes, edges, and rule outcomes. -* `EvidenceItems[]`: typed facts (trace hits, SBOM lines, VEX claims, config values) with source + timestamp. -* `SignedDeltaVerdict`: final status + signatures (who/what produced it). - -### Micro‑interactions that matter - -* Hover a changed node β‡’ **inline badge** explaining *why it changed* (e.g., β€œnow gated by `--no-xml` runtime flag”). -* Click a rule change in the right rail β‡’ **spotlight** the exact subgraph it affected. -* Toggle **β€œexplain like I’m new”** β‡’ expands jargon into plain language. -* One‑click **β€œcopy audit bundle”** β‡’ exports the delta + evidence as an attachment. - -### Where this belongs in your product - -* **Primary**: in the **Triage** view for any new finding/regression. -* **Secondary**: in **Policy history** (compare vX vs vY) and **Release gates** (compare build A vs build B). -* **Inline surfaces**: small β€œdiff pills” next to every verdict in tables; click opens the big side‑by‑side. - -### Quick build checklist (dev & PM) - -* Compute a stable **graph hash** per scan; store **snapshots**. -* Add a **delta builder** that outputs `added/removed/changed` at node/edge + rule outcome levels. -* Normalize **evidence items** (source, digest, excerpt) so the UI can render consistent cards. -* Ship a **Signed Delta Verdict** (OCI‑attached) so audits can replay the view from the artifact alone. -* Include **hotkeys**: `1` focus changes only, `2` show full graph, `E` expand evidence, `A` export audit. - -### Empty state & failure modes - -* If evidence is incomplete: show a **yellow β€œUnknowns present” ribbon** with a count and a button to collect missing traces. -* If graphs are huge: default to **β€œchanged neighborhood only”** with a mini‑map to pan. - -### Success metric (simple) - -* **Mean time to explain (MTTE)**: time from β€œwhy did this change?” to user clicking *β€œUnderstood”*. Track trend ↓. - -If you want, I can sketch a quick wireframe (header, graph panes, evidence rail, and the export action) or generate a JSON schema for the `Delta` and `EvidenceItem` objects you can hand to your frontend. diff --git a/docs/product-advisories/26-Dec-2025 - AI Assistant as Proof-Carrying Evidence Engine.md b/docs/product-advisories/26-Dec-2025 - AI Assistant as Proof-Carrying Evidence Engine.md new file mode 100644 index 000000000..1cc4e38cd --- /dev/null +++ b/docs/product-advisories/26-Dec-2025 - AI Assistant as Proof-Carrying Evidence Engine.md @@ -0,0 +1,178 @@ +# AI Assistant as Proof-Carrying Evidence Engine + +**Status:** ANALYZED - Sprints Created +**Date:** 2025-12-26 +**Type:** Strategic AI Feature Advisory +**Implementation Sprints:** SPRINT_20251226_015 through 019 + +--- + +## Executive Summary + +This advisory proposes building Stella Ops AI as a **proof-carrying assistant** that: +- Copies best UX outcomes from competitors (Snyk: speed to fix; JFrog/Docker: context reduces noise) +- Keeps authority in deterministic, replayable engines and signed evidence packs +- Extends into Stella Ops' moats: lattice merge semantics, deterministic replay, sovereign/offline cryptography + +## Advisory Content + +### 1) What to Copy: Competitor AI Patterns + +#### A. Snyk-style: "developer-time" intelligence +- Fast, developer-local explanation of "why this is a problem" and "what change fixes it" +- Reachability-informed prioritization (not just CVSS) +- Autofix PRs where safe + +**Stella Ops takeaway:** Make "time-to-understanding" and "time-to-first-fix" first-class KPIs. + +#### B. JFrog-style: contextual exploitability filtering +- "Is this vulnerability exploitable in *this* app?" filtering +- Runtime loaded-code validation to reduce noise + +**Stella Ops takeaway:** Treat exploitability as an evidence question; label uncertainty explicitly. + +#### C. Aqua-style: AI-guided remediation +- Prescriptive remediation steps in human language (and as patches/PRs) +- Integrate into CI/CD and ticketing + +**Stella Ops takeaway:** The assistant must be operational: PR creation, change plans, risk acceptance packages. + +#### D. Docker Scout-style: operational context +- Use runtime telemetry to prioritize vulnerabilities that can actually bite + +**Stella Ops takeaway:** Runtime evidence as attestable evidence beats "black box AI prioritization." + +#### E. Grype/Trivy reality: deterministic scanners win trust +- Strong data hygiene, VEX ingestion, deterministic outputs + +**Stella Ops takeaway:** AI layer must never undermine deterministic trust; must be additive, signed, replayable. + +### 2) Where Competitors Are Weak (Stella Ops Openings) + +1. **Audit-grade reproducibility:** AI explanations often non-replayable +2. **Offline/sovereign operations:** Air-gapped + local inference rare +3. **Proof-carrying verdicts:** Most risk scores are opaque +4. **Merge semantics for VEX:** Few ship policy-controlled lattice merge +5. **Time-travel replay + delta verdicts:** Rare as first-class artifacts +6. **Network effects for proofs:** Proof-market ledger concepts largely absent + +### 3) Core Principle: "AI is an assistant; evidence is the authority" + +**Every AI output must be either:** +- **Pure suggestion** (non-authoritative), or +- **Evidence-backed** (authoritative only when evidence pack suffices) + +### 4) Proposed Features + +#### Feature 1: Zastava Companion +Evidence-grounded explainability answering: What is it? Why it matters? What evidence supports? +- Output anchored to evidence nodes +- OCI-attached "Explanation Attestation" with hashes + model digest + +#### Feature 2: Exploitability Confidence Engine +- Deterministic classification: Confirmed/Likely/Unknown/Likely Not/Not exploitable +- AI proposes "cheapest additional evidence" to reduce Unknown + +#### Feature 3: Remedy Autopilot +- AI generates remediation plans +- Automated PRs with reproducible build, tests, SBOM delta, signed delta verdict +- Fallback to "suggestion-only" if build/tests fail + +#### Feature 4: Auto-VEX Drafting +- Generate VEX drafts from evidence +- Lattice-aware merge preview + +#### Feature 5: Advisory Ingestion Copilot +- Convert unstructured advisories to structured records +- Cross-check multiple sources, require corroboration for "trusted" status + +#### Feature 6: Policy Studio Copilot +- NL β†’ lattice rules +- Test case generation +- Compile to deterministic policy with signed snapshots + +### 5) Architecture + +- **scanner.webservice:** lattice merges, deterministic verdict engine (authoritative) +- **zastava.webservice (new):** LLM inference + RAG; non-authoritative suggestions +- **Feedser/Vexer:** immutable feed snapshots for replay +- **Postgres:** system of record +- **Valkey:** ephemeral caching (never authoritative) +- **Offline profile:** Postgres-only + local inference bundle + +### 6) Deterministic, Replayable AI + +Record and hash: +- Prompt template version +- Retrieved evidence node IDs + content hashes +- Model identifier + weights digest +- Decoding parameters (temperature=0, fixed seed) + +Emit as OCI-attached attestation: AIExplanation, RemediationPlan, VEXDraft, PolicyDraft. + +### 7) Roadmap + +- **Phase 1:** Deterministic confidence states + Zastava "Explain with evidence" +- **Phase 2:** Remedy Autopilot + Auto-VEX drafting +- **Phase 3:** Sovereign/offline AI bundle +- **Phase 4:** Proof-market + trust economics + +### 8) KPIs + +- Mean time to triage (MTTT) +- Mean time to remediate (MTTR) +- Noise rate (% findings that end up "not exploitable") +- "Unknown" reduction speed +- Reproducibility (% AI artifacts replayed to identical output) +- Audit extraction time + +### 9) Risks and Mitigations + +1. Hallucinations β†’ enforce evidence citation +2. Prompt injection β†’ sanitize, isolate untrusted text +3. Data exfiltration β†’ offline profile, strict egress +4. Bad patches β†’ require build+tests+policy gates +5. Model drift β†’ pin model digests, snapshot outputs + +--- + +## Implementation Assessment + +### Existing Infrastructure (Substantial) + +| Component | Coverage | Location | +|-----------|----------|----------| +| AdvisoryAI Pipeline | 90% | `src/AdvisoryAI/` | +| Guardrail Pipeline | 100% | `AdvisoryAI/Guardrails/` | +| Evidence Retrieval | 80% | SBOM context, vector/structured retrieval | +| TrustLatticeEngine | 100% | `Policy/TrustLattice/` | +| SourceTrustScoreCalculator | 100% | `VexLens/Trust/` | +| Remediation Hints | 30% | `Policy.Unknowns/Services/` | +| ProofChain/Attestations | 100% | `Attestor/ProofChain/` | +| DeltaVerdict | 100% | `StellaOps.DeltaVerdict/` | +| Offline/Airgap | 80% | Various modules | + +### Gaps Requiring New Development + +1. **LLM-generated explanations** - Feature 1 +2. **Remedy Autopilot with PRs** - Feature 3 +3. **Policy NLβ†’Rules** - Feature 6 +4. **AI artifact attestation types** - All features +5. **Sovereign/offline LLM** - Phase 3 + +### Created Sprints + +| Sprint | Topic | Tasks | +|--------|-------|-------| +| SPRINT_20251226_015_AI_zastava_companion | Explanation generation | 21 tasks | +| SPRINT_20251226_016_AI_remedy_autopilot | Automated remediation PRs | 26 tasks | +| SPRINT_20251226_017_AI_policy_copilot | NLβ†’lattice rules | 26 tasks | +| SPRINT_20251226_018_AI_attestations | AI artifact attestation types | 23 tasks | +| SPRINT_20251226_019_AI_offline_inference | Sovereign/offline AI | 26 tasks | + +**Total:** 5 sprints, 122 tasks + +### Archived Advisory + +- "Weighted Confidence for VEX Sources" β†’ moved to `archived/2025-12-26-vex-scoring/` + (Substantially implemented in VexLens SourceTrustScoreCalculator) diff --git a/docs/product-advisories/26-Dec-2025 - Stella Ops vNext - SBOM Spine and Deterministic Evidence.md b/docs/product-advisories/26-Dec-2025 - Stella Ops vNext - SBOM Spine and Deterministic Evidence.md new file mode 100644 index 000000000..5b29ae6eb --- /dev/null +++ b/docs/product-advisories/26-Dec-2025 - Stella Ops vNext - SBOM Spine and Deterministic Evidence.md @@ -0,0 +1,233 @@ +# Stella Ops vNext - SBOM Spine and Deterministic Evidence + +> **Status:** IMPLEMENTED β€” Architecture overview document +> **Date:** 2025-12-26 +> **Updated:** 2025-12-26 +> **Type:** Vision Document / Architecture Summary +> **Implementation:** 100% complete in existing infrastructure + +--- + +## Implementation Status + +This advisory describes the **existing StellaOps architecture**. All proposed features are implemented: + +### Core Infrastructure + +| Component | Implementation | Location | +|-----------|----------------|----------| +| SBOM-first canonical graph | `SbomService` module | `src/SbomService/` | +| CycloneDX 1.6 + SPDX 3.x | `SbomNormalizationService` | `src/SbomService/.../Services/` | +| in-toto + DSSE attestations | `Attestor` module (6+ predicate types) | `src/Attestor/` | +| OCI referrers | `OciReferrerPushClient`, `OciReferrerDiscovery` | `src/ExportCenter/.../Oci/` | +| Cosign/Sigstore signatures | `Signer` module | `src/Signer/` | +| Regional crypto (eIDAS/FIPS/GOST/SM) | `Cryptography` module | `src/Cryptography/` | +| Evidence graph | `ProofChain` library | `src/Attestor/__Libraries/StellaOps.Attestor.ProofChain/` | +| Smart-diff algorithm | `DeltaComputationEngine` | `src/__Libraries/StellaOps.DeltaVerdict/` | +| Signed delta verdicts | `DeltaSigningService` | `src/__Libraries/StellaOps.DeltaVerdict/Signing/` | +| Content-addressed IDs | `IContentAddressedIdGenerator` | `src/Attestor/__Libraries/.../Identifiers/` | +| Decision digest (Provcache) | `DecisionDigest`, `VeriKey` | `src/__Libraries/StellaOps.Provcache/` | +| Merkle proof verification | `MerkleProofVerifier` | `src/Attestor/__Libraries/.../Merkle/` | +| Deterministic replay | `ReplaySeed`, `FrozenEpoch` | `src/__Libraries/StellaOps.Provcache/` | +| PostgreSQL + Valkey | All modules | Per-module storage | + +### Predicate Types (All Implemented) + +| Predicate | Type URI | Implementation | +|-----------|----------|----------------| +| Build Provenance | `StellaOps.BuildProvenance@1` | `Attestor.ProofChain` | +| SBOM Attestation | `StellaOps.SBOMAttestation@1` | `Attestor.ProofChain` | +| Scan Results | `StellaOps.ScanResults@1` | `Attestor.ProofChain` | +| Policy Evaluation | `StellaOps.PolicyEvaluation@1` | `Attestor.ProofChain` | +| VEX Attestation | `StellaOps.VEXAttestation@1` | `Attestor.ProofChain` | +| Risk Profile Evidence | `StellaOps.RiskProfileEvidence@1` | `Attestor.ProofChain` | + +### Implementation Checklist (All Complete) + +**Pipelines:** +- [x] Build: emit SBOM (CDX + SPDX), SLSA provenance (in-toto/DSSE), sign all +- [x] Scan: OS + language + config; one attestation per tool +- [x] Policy: evaluate rules -> signed verdict attestation; include unknowns count +- [x] Publish: push all as OCI referrers; enable verification gate + +**Schema & IDs:** +- [x] Normalize component IDs (PURL/CPE) + strong hashes +- [x] Evidence graph store: Postgres (authoritative) + cache (Valkey) +- [x] Index by image digest; maintain as-of snapshots + +**Determinism:** +- [x] Lock feeds, rule versions, tool versions; record all input digests +- [x] Provide replay manifest capturing inputs -> expected verdict hash + +**Security & Sovereignty:** +- [x] Pluggable crypto: eIDAS/FIPS/GOST/SM; offline bundle export/import +- [x] Air-gapped profile: Postgres-only with documented trade-offs + +--- + +## Documentation References + +- **SbomService Architecture:** `docs/modules/sbomservice/architecture.md` +- **Attestor Architecture:** `docs/modules/attestor/architecture.md` +- **Signer Keyless Guide:** `docs/modules/signer/guides/keyless-signing.md` +- **ProofChain Specification:** `docs/modules/attestor/proof-chain-specification.md` +- **Determinism Gates:** `docs/testing/determinism-gates.md` + +--- + +## Advisory Content (Original Vision) + +Here's a simple, practical way to think about a **SBOM-first, VEX-ready supply-chain spine** and the **evidence graph + smart-diff** you can build on top of itβ€”starting from zero and ending with reproducible, signed decisions. + +### SBOM-first spine (VEX-ready) + +**Goal:** make the SBOM the canonical graph of "what's inside," then layer signed evidence (build, scans, policy) so every verdict is portable, replayable, and auditable across registries. + +**Core choices:** + +* **Canonical graph:** treat **CycloneDX 1.6** and **SPDX 3.x** as first-class. Keep both in sync; normalize component IDs (PURL/CPE), hashes, licenses, and relationships. +* **Attestations:** use **in-toto + DSSE** for all lifecycle facts: + * build (SLSA provenance), + * scan results (vuln, secrets, IaC, reachability), + * policy evaluation (allow/deny, risk budgets, exceptions). +* **Storage/transport:** publish everything as **OCI-attached artifacts** via **OCI Referrers**: + * `image:tag` -> SBOM (spdx/cdx), VEX, SARIF, provenance, policy verdicts, exception notesβ€”each a referrer with media type + signature. +* **Signatures:** cosign/sigstore (or your regional crypto: eIDAS/FIPS/GOST/SM) for **content-addressed** blobs. + +**Minimum viable workflow:** + +1. **Build step** + * Produce identical SBOMs in CycloneDX and SPDX. + * Emit SLSA-style provenance attestation. + +2. **Scan step(s)** + * OS + language deps + container layers; add **reachability proofs** where possible. + * Emit one **scan attestation per tool** (don't conflate). + +3. **Policy step** + * Evaluate policies (e.g., OPA/Rego or your lattice rules) **against the SBOM graph + scan evidence**. + * Emit a **signed policy verdict attestation** (pass/fail + reasons + unknowns count). + +4. **Publish** + * Push image, then push SBOMs, VEX, scan attestations, policy verdicts as **OCI referrers**. + +5. **Verify / consume** + * Pull the image's **referrer set**; verify signatures; reconstruct graph locally; **replay** the policy evaluation deterministically. + +**Data model tips:** + +* Stable identifiers: PURLs for packages, digests for layers, Build-ID for binaries. +* Edges: `component->dependsOn`, `component->vulnerability`, `component->evidence(attestation)`, `component->policyClaim`. +* Keep **time (as-of)** and **source** on every node/edge for replay. + +### Evidence graph + smart-diff + +**Goal:** persist an **explainability graph** (findings <-> components <-> provenance <-> policies) and compute **signed delta-verdicts** on diffs to drive precise impact analysis and quiet noise. + +**What to store:** + +* **Provenance:** who built it, from what, when (commit, builder, materials). +* **Findings:** CVEs, misconfigs, secrets, license flags, each with source tool, version, rule, confidence, timestamp. +* **Policies & verdicts:** rule set version, inputs' hashes, outcome, rationale. +* **Reachability subgraphs:** the minimal path proving exploitability (e.g., symbol -> function -> package -> process start). + +**Smart-diff algorithm (high level):** + +* Compare two images (or SBOM graphs) **by component identity + version + hash**. +* For each change class: + * **Added/removed/changed component** + * **New/cleared/changed finding** + * **Changed reachability path** + * **Changed policy version/inputs** +* Re-evaluate only affected subgraph; produce a **Delta Verdict**: + * `status`: safer / risk-equal / risk-higher + * `why`: list of net-new reachable vulns, removed reachable vulns, policy/exception impacts + * `evidenceRefs`: hashes of attestations used +* **Sign the delta verdict (DSSE)** and publish it as an **OCI referrer** too. + +**UX essentials:** + +* Artifact page shows: **"Evidence Stack"** (SBOM, scans, VEX, policy, provenance) with green checks for signatures. +* **Smart-diff view:** left vs right image -> "net-new reachable CVEs (+3)", "downgraded risk (-1)" with drill-downs to the exact path/evidence. +* **Explain button:** expands to show **why** a CVE is (not) applicable (feature flag off, code path unreachable, kernel mitigation present, etc.). +* **Replay badge:** "Deterministic βœ“" (inputs' hashes match; verdict reproducible). + +### APIs & types (implemented media types) + +* `application/vnd.cyclonedx+json` +* `application/spdx+json` +* `application/vnd.in-toto+json; statement=provenance|scan|policy` +* `application/vnd.stella.verdict+json` (signed verdict/delta) + +### Existing Implementation Examples + +**Scan Attestation (StellaOps.ScanResults@1):** +```json +{ + "type": "https://in-toto.io/Statement/v1", + "predicateType": "https://stella.dev/scan/v1", + "subject": [{"name": "registry/app@sha256:...", "digest": {"sha256": "..."}}], + "predicate": { + "tool": {"name": "scannerX", "version": "1.4.2"}, + "inputs": {"sbom": "sha256:...", "db": "sha256:..."}, + "findings": [{"id": "CVE-2025-1234", "component": "pkg:pypi/xyz@1.2.3", "severity": "HIGH"}] + } +} +``` + +**Policy Verdict (StellaOps.PolicyEvaluation@1):** +```json +{ + "type": "https://in-toto.io/Statement/v1", + "predicateType": "https://stella.dev/verdict/v1", + "subject": [{"name": "registry/app@sha256:..."}], + "predicate": { + "policy": {"id": "prod.v1.7", "hash": "sha256:..."}, + "inputs": {"sbom": "sha256:...", "scans": ["sha256:...","sha256:..."]}, + "unknowns": 2, + "decision": "allow", + "reasons": [ + "CVE-2025-1234 not reachable (path pruned)", + "License policy ok" + ] + } +} +``` + +**Delta Verdict (stella.dev/delta-verdict/v1):** +```json +{ + "predicateType": "https://stella.dev/delta-verdict/v1", + "predicate": { + "from": "sha256:old", "to": "sha256:new", + "impact": "risk-higher", + "changes": { + "componentsAdded": ["pkg:apk/openssl@3.2.1-r1"], + "reachableVulnsAdded": ["CVE-2025-2222"] + }, + "evidenceRefs": ["sha256:scanA", "sha256:policyV1"] + } +} +``` + +### Operating rules (adopted) + +* **Everything is evidence.** If it influenced a decision, it's an attestation you can sign and attach. +* **Same inputs -> same verdict.** If not, treat it as a bug. +* **Unknowns budgeted by policy.** E.g., "fail prod if unknowns > 0; warn in dev." +* **Diffs decide deployments.** Gate on the **delta verdict**, not raw CVE counts. +* **Portable by default.** If you move registries, your decisions move with the image via referrers. + +--- + +## Related Implementation + +| Module | Purpose | Documentation | +|--------|---------|---------------| +| `SbomService` | SBOM ledger, lineage, versioning | `docs/modules/sbomservice/` | +| `Attestor` | DSSE, in-toto, Rekor integration | `docs/modules/attestor/` | +| `Signer` | Keyless + KMS signing | `docs/modules/signer/` | +| `Provcache` | Decision digest, VeriKey | `src/__Libraries/StellaOps.Provcache/` | +| `DeltaVerdict` | Smart-diff engine | `src/__Libraries/StellaOps.DeltaVerdict/` | +| `ExportCenter` | OCI referrer publishing | `src/ExportCenter/` | +| `Policy` | Lattice evaluation, verdicts | `src/Policy/` | diff --git a/docs/product-advisories/26-Dec-2026 - Mapping a Binary Intelligence Graph.md b/docs/product-advisories/26-Dec-2026 - Mapping a Binary Intelligence Graph.md index 386a8fefa..c7c4332fa 100644 --- a/docs/product-advisories/26-Dec-2026 - Mapping a Binary Intelligence Graph.md +++ b/docs/product-advisories/26-Dec-2026 - Mapping a Binary Intelligence Graph.md @@ -1,11 +1,49 @@ -Here’s a compact blueprint for a **binary‑level knowledge base** that maps ELF Build‑IDs / PE signatures to vulnerable functions, patch lineage, and reachability hintsβ€”so your scanner can act like a provenance‑aware β€œbinary oracle,” not just a CVE lookup. +# Mapping a Binary Intelligence Graph + +> **Status:** SUPERSEDED +> **Date:** 2026-12-26 +> **Updated:** 2025-12-26 +> **Superseded By:** BinaryIndex Module Architecture +> **Related Sprints:** [`SPRINT_20251226_011_BINIDX_known_build_catalog.md`](../implplan/SPRINT_20251226_011_BINIDX_known_build_catalog.md), [`SPRINT_20251226_012_BINIDX_backport_handling.md`](../implplan/SPRINT_20251226_012_BINIDX_backport_handling.md), [`SPRINT_20251226_013_BINIDX_fingerprint_factory.md`](../implplan/SPRINT_20251226_013_BINIDX_fingerprint_factory.md), [`SPRINT_20251226_014_BINIDX_scanner_integration.md`](../implplan/SPRINT_20251226_014_BINIDX_scanner_integration.md) + +--- + +## Supersession Notice + +This advisory has been **superseded** by the comprehensive BinaryIndex module architecture. All proposals in this advisory are covered by the existing design: + +| Advisory Proposal | Implementation | Location | +|-------------------|----------------|----------| +| artifacts table | `binaries.binary_identity` | `docs/modules/binaryindex/architecture.md` | +| symbols table | `BinaryFeatures` in `IBinaryFeatureExtractor` | `src/BinaryIndex/__Libraries/.../Services/` | +| vuln_segments (byte_sig/patch_sig) | `VulnFingerprint` model | `src/BinaryIndex/__Libraries/.../Fingerprints/` | +| matches table | `FingerprintMatch` model | `src/BinaryIndex/__Libraries/.../Fingerprints/` | +| reachability_hints | `ReachabilityStatus` enum | `src/BinaryIndex/__Libraries/.../Models/` | +| Build-ID/PE indexer | `ElfFeatureExtractor`, `IBinaryFeatureExtractor` | `src/BinaryIndex/__Libraries/.../Services/` | +| Patch-aware handling | `FixEvidence`, changelog/patch parsers | `src/BinaryIndex/__Libraries/.../FixIndex/` | +| Corpus connectors | `DebianCorpusConnector`, `IBinaryCorpusConnector` | `src/BinaryIndex/__Libraries/.../Corpus/` | + +### Related Archived Advisories + +- `18-Dec-2025 - Building Better Binary Mapping and Call‑Stack Reachability.md` +- `23-Dec-2026 - Binary Mapping as Attestable Proof.md` + +### Related Active Advisories + +- `25-Dec-2025 - Evolving Evidence Models for Reachability.md` - Runtime β†’ build braid, eBPF sampling + +--- + +## Original Advisory Content + +Here's a compact blueprint for a **binary‑level knowledge base** that maps ELF Build‑IDs / PE signatures to vulnerable functions, patch lineage, and reachability hintsβ€”so your scanner can act like a provenance‑aware "binary oracle," not just a CVE lookup. --- # Why this matters (in plain terms) * **Same version β‰  same risk.** Distros (and vendors) frequently **backport** fixes without bumping versions. Only the **binary** tells the truth. -* **Function‑level matching** turns noisy β€œpackage has CVE” into precise β€œthis exact function range is vulnerable in your binary.” +* **Function‑level matching** turns noisy "package has CVE" into precise "this exact function range is vulnerable in your binary." * **Reachability hints** cut triage noise by ranking vulns the code path can actually hit at runtime. --- @@ -40,7 +78,7 @@ Keep it tiny so it grows with real evidence: * `patch_sig` (pattern from fixed hunk) * `evidence_ref` (link to patch diff, commit, or NVD note) * `backport_flag` (bool) -* `introduced_in`, `fixed_in` (semver-ish text; note β€œbackport” when used) +* `introduced_in`, `fixed_in` (semver-ish text; note "backport" when used) **matches** @@ -57,7 +95,7 @@ Keep it tiny so it grows with real evidence: --- -# How the oracle answers β€œAm I affected?” +# How the oracle answers "Am I affected?" 1. **Identify**: Look up by Build‑ID / PE signature; fall back to file hash. 2. **Locate**: Map symbols β†’ address ranges; scan for `byte_sig`/`patch_sig`. @@ -81,10 +119,10 @@ Keep it tiny so it grows with real evidence: --- -# Deterministic verdicts (fit to Stellaβ€―Ops) +# Deterministic verdicts (fit to Stella Ops) * **Inputs**: `(artifact fingerprint, vuln_segments@version, reachability@policy)` -* **Output**: **Signed OCI attestation** β€œverdict.json” (same inputs β†’ same verdict). +* **Output**: **Signed OCI attestation** "verdict.json" (same inputs β†’ same verdict). * **Replay**: keep rule bundle & feed hashes for audit. * **Backport precedence**: `patch_sig` beats package version claims every time. @@ -94,7 +132,7 @@ Keep it tiny so it grows with real evidence: * Add a **Build‑ID/PE indexer** to Scanner. * Teach Feedser/Vexer to ingest `vuln_segments` (with `byte_sig`/`patch_sig`). -* Implement matching + verdict attestation; surface **β€œBackported & Safe”** vs **β€œAffected & Reachable”** badges in UI. +* Implement matching + verdict attestation; surface **"Backported & Safe"** vs **"Affected & Reachable"** badges in UI. * Seed DB with 10 high‑impact CVEs (OpenSSL, zlib, xz, glibc, libxml2, curl, musl, busybox, OpenSSH, sudo). --- @@ -135,11 +173,3 @@ create table reachability_hints( symbol_name text, hint_type text, weight int ); ``` - ---- - -If you want, I can: - -* drop in a tiny **.NET 10** matcher (ELF/PE parsers + byte‑window scanner), -* wire verdicts as **OCI attestations** in your current pipeline, -* and prep the first **10 CVE byte/patch signatures** to seed the DB. diff --git a/docs/product-advisories/25-Dec-2025 - Hybrid Binary and Call‑Graph Analysis.md b/docs/product-advisories/archived/2025-12-26-empty-advisories/25-Dec-2025 - Hybrid Binary and Call‑Graph Analysis.md similarity index 100% rename from docs/product-advisories/25-Dec-2025 - Hybrid Binary and Call‑Graph Analysis.md rename to docs/product-advisories/archived/2025-12-26-empty-advisories/25-Dec-2025 - Hybrid Binary and Call‑Graph Analysis.md diff --git a/docs/product-advisories/25-Dec-2025 - Implementing Diff‑Aware Release Gates.md b/docs/product-advisories/archived/2025-12-26-superseded/25-Dec-2025 - Implementing Diff‑Aware Release Gates.md similarity index 100% rename from docs/product-advisories/25-Dec-2025 - Implementing Diff‑Aware Release Gates.md rename to docs/product-advisories/archived/2025-12-26-superseded/25-Dec-2025 - Implementing Diff‑Aware Release Gates.md diff --git a/docs/product-advisories/26-Dec-2026 - Diff‑Aware Releases and Auditable Exceptions.md b/docs/product-advisories/archived/2025-12-26-superseded/26-Dec-2026 - Diff‑Aware Releases and Auditable Exceptions.md similarity index 100% rename from docs/product-advisories/26-Dec-2026 - Diff‑Aware Releases and Auditable Exceptions.md rename to docs/product-advisories/archived/2025-12-26-superseded/26-Dec-2026 - Diff‑Aware Releases and Auditable Exceptions.md diff --git a/docs/product-advisories/26-Dec-2026 - Reachability as Cryptographic Proof.md b/docs/product-advisories/archived/2025-12-26-superseded/26-Dec-2026 - Reachability as Cryptographic Proof.md similarity index 100% rename from docs/product-advisories/26-Dec-2026 - Reachability as Cryptographic Proof.md rename to docs/product-advisories/archived/2025-12-26-superseded/26-Dec-2026 - Reachability as Cryptographic Proof.md diff --git a/docs/product-advisories/26-Dec-2026 - Smart‑Diff as a Core Evidence Primitive.md b/docs/product-advisories/archived/2025-12-26-superseded/26-Dec-2026 - Smart‑Diff as a Core Evidence Primitive.md similarity index 100% rename from docs/product-advisories/26-Dec-2026 - Smart‑Diff as a Core Evidence Primitive.md rename to docs/product-advisories/archived/2025-12-26-superseded/26-Dec-2026 - Smart‑Diff as a Core Evidence Primitive.md diff --git a/docs/product-advisories/archived/2025-12-26-superseded/README.md b/docs/product-advisories/archived/2025-12-26-superseded/README.md new file mode 100644 index 000000000..2ab520ddb --- /dev/null +++ b/docs/product-advisories/archived/2025-12-26-superseded/README.md @@ -0,0 +1,79 @@ +# Archived Superseded Advisories + +**Archived:** 2025-12-26 +**Reason:** Concepts already implemented or covered by existing sprints + +## Advisory Status + +These advisories described features that are **already substantially implemented** in the codebase or covered by existing sprint files. + +| Advisory | Status | Superseded By | +|----------|--------|---------------| +| `25-Dec-2025 - Implementing Diff‑Aware Release Gates.md` | SUPERSEDED | SPRINT_20251226_001_BE through 006_DOCS | +| `26-Dec-2026 - Diff‑Aware Releases and Auditable Exceptions.md` | SUPERSEDED | SPRINT_20251226_003_BE_exception_approval.md | +| `26-Dec-2026 - Smart‑Diff as a Core Evidence Primitive.md` | SUPERSEDED | Existing DeltaVerdict library | +| `26-Dec-2026 - Reachability as Cryptographic Proof.md` | SUPERSEDED | Existing ProofChain library + SPRINT_007/009/010/011 | + +## Existing Implementation + +The following components already implement the advisory concepts: + +### DeltaVerdict & DeltaComputer +- `src/Policy/__Libraries/StellaOps.Policy/Deltas/DeltaVerdict.cs` +- `src/Policy/__Libraries/StellaOps.Policy/Deltas/DeltaComputer.cs` +- `src/__Libraries/StellaOps.DeltaVerdict/` (complete library) + +### Exception Management +- `src/Policy/__Libraries/StellaOps.Policy.Storage.Postgres/Models/ExceptionEntity.cs` +- `src/Policy/StellaOps.Policy.Engine/Adapters/ExceptionAdapter.cs` +- `src/Policy/__Libraries/StellaOps.Policy.Exceptions/` (complete library) + +### ProofChain & Reachability Proofs +- `src/Attestor/__Libraries/StellaOps.Attestor.ProofChain/` (complete library): + - `Statements/ReachabilityWitnessStatement.cs` - Entryβ†’sink proof chains + - `Statements/ReachabilitySubgraphStatement.cs` - Minimal subgraph attestation + - `Statements/ProofSpineStatement.cs` - Merkle-aggregated proof bundles + - `Predicates/ReachabilitySubgraphPredicate.cs` - Subgraph predicate + - `Identifiers/ContentAddressedIdGenerator.cs` - Content-addressed IDs + - `Merkle/DeterministicMerkleTreeBuilder.cs` - Merkle tree construction + - `Signing/ProofChainSigner.cs` - DSSE signing + - `Verification/VerificationPipeline.cs` - Proof verification +- `src/__Libraries/StellaOps.Replay.Core/ReplayManifest.cs` - Replay manifests + +### Covering Sprints +- `docs/implplan/SPRINT_20251226_001_BE_cicd_gate_integration.md` - Gate endpoints, CI/CD +- `docs/implplan/SPRINT_20251226_002_BE_budget_enforcement.md` - Risk budget automation +- `docs/implplan/SPRINT_20251226_003_BE_exception_approval.md` - Exception workflows (21 tasks) +- `docs/implplan/SPRINT_20251226_004_FE_risk_dashboard.md` - Side-by-side UI +- `docs/implplan/SPRINT_20251226_005_SCANNER_reachability_extractors.md` - Language extractors +- `docs/implplan/SPRINT_20251226_006_DOCS_advisory_consolidation.md` - Documentation +- `docs/implplan/SPRINT_20251226_007_BE_determinism_gaps.md` - Determinism gaps, metrics (25 tasks) +- `docs/implplan/SPRINT_20251226_009_SCANNER_funcproof.md` - FuncProof generation (18 tasks) +- `docs/implplan/SPRINT_20251226_010_SIGNALS_runtime_stack.md` - eBPF stack capture (17 tasks) +- `docs/implplan/SPRINT_20251226_011_BE_auto_vex_downgrade.md` - Auto-VEX from runtime (16 tasks) + +## Remaining Gaps Added to Sprints + +Minor gaps from these advisories were added to existing sprints: + +**Added to SPRINT_20251226_003_BE_exception_approval.md:** +- EXCEPT-16: Auto-revalidation job +- EXCEPT-17: Re-review gate flip on failure +- EXCEPT-18: Exception inheritance (repoβ†’imageβ†’env) +- EXCEPT-19: Conflict surfacing for shadowed exceptions +- EXCEPT-20: OCI-attached exception attestation +- EXCEPT-21: CLI export command + +**Added to SPRINT_20251226_007_BE_determinism_gaps.md:** +- DET-GAP-21: Proof generation rate metric +- DET-GAP-22: Median proof size metric +- DET-GAP-23: Replay success rate metric +- DET-GAP-24: Proof dedup ratio metric +- DET-GAP-25: "Unknowns" burn-down tracking + +## Cross-References + +If you arrived here via a broken link, see: +- `docs/implplan/SPRINT_20251226_*.md` for implementation tasks +- `src/Policy/__Libraries/StellaOps.Policy/Deltas/` for delta computation +- `src/__Libraries/StellaOps.DeltaVerdict/` for verdict models diff --git a/docs/product-advisories/25-Dec-2025 - Triage UI Lessons from Competitors.md b/docs/product-advisories/archived/2025-12-26-triage-advisories/25-Dec-2025 - Triage UI Lessons from Competitors.md similarity index 100% rename from docs/product-advisories/25-Dec-2025 - Triage UI Lessons from Competitors.md rename to docs/product-advisories/archived/2025-12-26-triage-advisories/25-Dec-2025 - Triage UI Lessons from Competitors.md diff --git a/docs/product-advisories/archived/2025-12-26-triage-advisories/25-Dec-2025 - Visual Diffs for Explainable Triage.md b/docs/product-advisories/archived/2025-12-26-triage-advisories/25-Dec-2025 - Visual Diffs for Explainable Triage.md new file mode 100644 index 000000000..c7a120d67 --- /dev/null +++ b/docs/product-advisories/archived/2025-12-26-triage-advisories/25-Dec-2025 - Visual Diffs for Explainable Triage.md @@ -0,0 +1,105 @@ +# Visual Diffs for Explainable Triage + +> **Status:** PLANNED β€” Enhancement sprint created +> **Date:** 2025-12-25 +> **Updated:** 2025-12-26 +> **Implementation:** ~75-80% complete in existing infrastructure +> **Sprint:** [`SPRINT_20251226_010_FE_visual_diff_enhancements.md`](../implplan/SPRINT_20251226_010_FE_visual_diff_enhancements.md) + +--- + +## Implementation Status + +Most features proposed in this advisory are **already implemented**: + +| Feature | Status | Location | +|---------|--------|----------| +| Three-pane layout (Categories/Items/Proof) | COMPLETE | `smart-diff-ui-architecture.md` | +| Delta summary strip | COMPLETE | `DeltaSummaryStripComponent` | +| Evidence rail with witness paths | COMPLETE | `ProofPaneComponent`, `WitnessPathComponent` | +| VEX merge explanations | COMPLETE | `VexMergeExplanationComponent` | +| Role-based views (Dev/Security/Audit) | COMPLETE | `CompareViewComponent` | +| Keyboard shortcuts | COMPLETE | `TriageShortcutsService` | +| Audit bundle export | COMPLETE | `ExportActionsComponent` | +| Delta computation engine | COMPLETE | `StellaOps.DeltaVerdict.Engine` | +| Signed delta verdicts | COMPLETE | `DeltaSigningService` | +| **Visual graph diff with highlights** | TODO | Sprint VD-ENH-01..04 | +| **"Explain like I'm new" toggle** | TODO | Sprint VD-ENH-05..07 | +| **Graph export (SVG/PNG)** | TODO | Sprint VD-ENH-08 | + +### Existing Infrastructure + +- `TriageWorkspaceComponent` (1042 lines) - Full triage workspace +- `ProofTreeComponent` (1009 lines) - Merkle tree visualization +- `docs/modules/web/smart-diff-ui-architecture.md` - Architecture specification +- `StellaOps.DeltaVerdict` library - Backend delta computation + +--- + +## Advisory Content + +Here's a simple, high-leverage UX pattern you can borrow from top observability tools: **treat every policy decision or reachability change as a visual diff.** + +--- + +### Why this helps + +* Turns opaque "why is this verdict different?" moments into **quick, explainable triage**. +* Reduces back-and-forth between Security, Dev, and Auditβ€”**everyone sees the same before/after evidence**. + +### Core UI concept + +* **Side-by-side panes**: **Before** (previous scan/policy) vs **After** (current). +* **Graph focus**: show the dependency/reachability subgraph; **highlight added/removed/changed nodes/edges**. +* **Evidence strip** (right rail): human-readable facts used by the engine (e.g., *feature flag OFF*, *code path unreachable*, *kernel eBPF trace absent*). +* **Diff verdict header**: "Risk ↓ from *Medium β†’ Low* (policy v1.8 β†’ v1.9)". +* **Filter chips**: Scope by component, package, CVE, policy rule, environment. + +### Minimal data model (so UI is easy) + +* `GraphSnapshot`: nodes, edges, metadata (component, version, tags). +* `PolicySnapshot`: version, rules hash, inputs (flags, env, VEX sources). +* `Delta`: `added/removed/changed` for nodes, edges, and rule outcomes. +* `EvidenceItems[]`: typed facts (trace hits, SBOM lines, VEX claims, config values) with source + timestamp. +* `SignedDeltaVerdict`: final status + signatures (who/what produced it). + +### Micro-interactions that matter + +* Hover a changed node β‡’ **inline badge** explaining *why it changed* (e.g., "now gated by `--no-xml` runtime flag"). +* Click a rule change in the right rail β‡’ **spotlight** the exact subgraph it affected. +* Toggle **"explain like I'm new"** β‡’ expands jargon into plain language. +* One-click **"copy audit bundle"** β‡’ exports the delta + evidence as an attachment. + +### Where this belongs in your product + +* **Primary**: in the **Triage** view for any new finding/regression. +* **Secondary**: in **Policy history** (compare vX vs vY) and **Release gates** (compare build A vs build B). +* **Inline surfaces**: small "diff pills" next to every verdict in tables; click opens the big side-by-side. + +### Quick build checklist (dev & PM) + +* [x] Compute a stable **graph hash** per scan; store **snapshots**. *(Implemented: `DeltaComputationEngine`)* +* [x] Add a **delta builder** that outputs `added/removed/changed` at node/edge + rule outcome levels. *(Implemented: `DeltaVerdictBuilder`)* +* [x] Normalize **evidence items** (source, digest, excerpt) so the UI can render consistent cards. *(Implemented: `ProofTreeComponent`)* +* [x] Ship a **Signed Delta Verdict** (OCI-attached) so audits can replay the view from the artifact alone. *(Implemented: `DeltaSigningService`)* +* [ ] Include **hotkeys**: `1` focus changes only, `2` show full graph, `E` expand evidence, `A` export audit. *(Partial: general shortcuts exist)* + +### Empty state & failure modes + +* If evidence is incomplete: show a **yellow "Unknowns present" ribbon** with a count and a button to collect missing traces. +* If graphs are huge: default to **"changed neighborhood only"** with a mini-map to pan. + +### Success metric (simple) + +* **Mean time to explain (MTTE)**: time from "why did this change?" to user clicking *"Understood"*. Track trend ↓. + +--- + +## Related Advisories + +| Advisory | Relationship | +|----------|--------------| +| [Triage UI Lessons from Competitors](./25-Dec-2025%20-%20Triage%20UI%20Lessons%20from%20Competitors.md) | Complementary - competitive UX patterns | +| [Implementing Diff-Aware Release Gates](./25-Dec-2025%20-%20Implementing%20Diff%E2%80%91Aware%20Release%20Gates.md) | Backend - IMPLEMENTED | +| [Smart-Diff as Core Evidence Primitive](./26-Dec-2026%20-%20Smart%E2%80%91Diff%20as%20a%20Core%20Evidence%20Primitive.md) | Data model - IMPLEMENTED | +| [Visualizing the Risk Budget](./26-Dec-2026%20-%20Visualizing%20the%20Risk%20Budget.md) | Related - Risk visualization | diff --git a/docs/product-advisories/26-Dec-2026 - Visualizing the Risk Budget.md b/docs/product-advisories/archived/2025-12-26-triage-advisories/26-Dec-2026 - Visualizing the Risk Budget.md similarity index 100% rename from docs/product-advisories/26-Dec-2026 - Visualizing the Risk Budget.md rename to docs/product-advisories/archived/2025-12-26-triage-advisories/26-Dec-2026 - Visualizing the Risk Budget.md diff --git a/docs/product-advisories/archived/2025-12-26-triage-advisories/README.md b/docs/product-advisories/archived/2025-12-26-triage-advisories/README.md new file mode 100644 index 000000000..1942dbb77 --- /dev/null +++ b/docs/product-advisories/archived/2025-12-26-triage-advisories/README.md @@ -0,0 +1,33 @@ +# Archived Triage/Visualization Advisories + +**Archived:** 2025-12-26 +**Reason:** Consolidated into unified specification + +## Advisory Consolidation + +These 3 advisories contained overlapping concepts about triage UI, visual diffs, and risk budget visualization. They have been consolidated into a single authoritative specification: + +**Consolidated Into:** `docs/modules/web/unified-triage-specification.md` + +## Archived Advisories + +| Advisory | Primary Concepts | Preserved In | +|----------|------------------|--------------| +| `25-Dec-2025 - Triage UI Lessons from Competitors.md` | Snyk/Anchore/Prisma analysis, 4 recommendations | Section 2: Competitive Landscape | +| `25-Dec-2025 - Visual Diffs for Explainable Triage.md` | Side-by-side panes, evidence strip, micro-interactions | Section 3: Core UI Concepts | +| `26-Dec-2026 - Visualizing the Risk Budget.md` | Burn-up charts, heatmaps, exception ledger | Section 4: Risk Budget Visualization | + +## Implementation Sprints + +The consolidated specification is implemented by: + +- `SPRINT_20251226_004_FE_risk_dashboard.md` - Risk budget visualization +- `SPRINT_20251226_012_FE_smart_diff_compare.md` - Smart-Diff Compare View +- `SPRINT_20251226_013_FE_triage_canvas.md` - Unified Triage Canvas +- `SPRINT_20251226_014_DOCS_triage_consolidation.md` - Documentation tasks + +## Cross-References + +If you arrived here via a broken link, the content you're looking for is now in: +- `docs/modules/web/unified-triage-specification.md` +- `docs/modules/web/smart-diff-ui-architecture.md` diff --git a/docs/product-advisories/26-Dec-2026 - Weighted Confidence for VEX Sources.md b/docs/product-advisories/archived/2025-12-26-vex-scoring/26-Dec-2026 - Weighted Confidence for VEX Sources.md similarity index 100% rename from docs/product-advisories/26-Dec-2026 - Weighted Confidence for VEX Sources.md rename to docs/product-advisories/archived/2025-12-26-vex-scoring/26-Dec-2026 - Weighted Confidence for VEX Sources.md diff --git a/docs/product-advisories/archived/2025-12-26-vex-scoring/README.md b/docs/product-advisories/archived/2025-12-26-vex-scoring/README.md new file mode 100644 index 000000000..9ec72cda1 --- /dev/null +++ b/docs/product-advisories/archived/2025-12-26-vex-scoring/README.md @@ -0,0 +1,59 @@ +# Archived VEX Scoring Advisory + +**Archived:** 2025-12-26 +**Reason:** Concepts substantially implemented in VexLens module + +## Advisory Status + +The "Weighted Confidence for VEX Sources" advisory described a scoring lattice for VEX sources using the formula `Score(e) = C(e) Γ— F(e) Γ— S_claim(e)`. This is **substantially implemented** in the existing codebase. + +## Existing Implementation + +### SourceTrustScoreCalculator (VexLens) +Location: `src/VexLens/StellaOps.VexLens/Trust/SourceTrust/SourceTrustScoreCalculator.cs` + +Implements multi-dimensional trust scoring: +- **Authority Score** - Source category (Vendor, Distributor, Community, Internal, Aggregator), trust tier, official source bonus +- **Accuracy Score** - Confirmation rate, false positive rate, revocation rate, consistency +- **Timeliness Score** - Response time, update frequency, freshness +- **Coverage Score** - CVE coverage ratio, product breadth, completeness +- **Verification Score** - Signature validity, provenance integrity, issuer verification + +### TrustDecayService (VexLens) +Location: `src/VexLens/StellaOps.VexLens/Trust/SourceTrust/TrustDecayService.cs` + +Implements freshness decay with configurable Ο„ values per source class. + +### TrustLatticeEngine (Policy) +Location: `src/Policy/__Libraries/StellaOps.Policy/TrustLattice/TrustLatticeEngine.cs` + +Implements: +- K4 lattice with security atoms (Present, Applies, Reachable, Mitigated, Fixed, Misattributed) +- VEX normalization (CycloneDX, OpenVEX, CSAF) +- Proof bundle generation with decision traces +- Lattice merge with claim precedence + +### VexConsensusEngine (VexLens) +Location: `src/VexLens/StellaOps.VexLens/Consensus/VexConsensusEngine.cs` + +Handles multi-source VEX consensus with configurable merge policies. + +## Advisory Concepts β†’ Implementation Mapping + +| Advisory Concept | Implementation | +|------------------|----------------| +| Confidence C(e) factors | `SourceTrustScoreCalculator` with 5 component scores | +| Freshness F(e) decay | `TrustDecayService` with configurable Ο„ per source | +| Claim strength S_claim | `TrustLatticeEngine` security atoms + disposition selector | +| Lattice merge ordering | `K4Lattice` with precedence rules | +| Signature strength | `VerificationScoreCalculator` with signature/provenance scoring | +| Consensus bonus | `VexConsensusEngine` with multi-source corroboration | +| Policy hooks | `PolicyBundle` with override rules | +| Replay/determinism | `ProofBundle` with decision traces | + +## Cross-References + +If you arrived here via a broken link, see: +- `src/VexLens/StellaOps.VexLens/Trust/` for trust scoring +- `src/Policy/__Libraries/StellaOps.Policy/TrustLattice/` for lattice logic +- `docs/modules/vexlens/` for VexLens documentation diff --git a/src/Signer/AGENTS.md b/src/Signer/AGENTS.md new file mode 100644 index 000000000..3ac058ced --- /dev/null +++ b/src/Signer/AGENTS.md @@ -0,0 +1,71 @@ +# Signer Module β€” Agent Charter + +## Mission +Provide cryptographic signing services for StellaOps attestations: +- Sign DSSE envelopes for SBOMs, verdicts, and reports +- Support multiple signing modes: keyless (Fulcio), KMS, HSM, FIDO2 +- Enforce entitlement (PoE), release integrity, and plan quotas +- Return verifiable bundles suitable for Rekor transparency logging +- Maintain audit trails for all signing operations + +## Expectations +- Coordinate with Authority for OIDC tokens and DPoP/mTLS validation +- Coordinate with Attestor for downstream Rekor submission +- Maintain deterministic serialization for reproducible signatures +- Support offline operation with KMS/HSM modes for air-gapped deployments +- Provide REST APIs for signing operations and release verification +- Keep signing key management schema current with migrations + +## Key Components +- **StellaOps.Signer.Core**: Core abstractions, pipeline, and contracts +- **StellaOps.Signer.Infrastructure**: Signing implementations, DI extensions +- **StellaOps.Signer.WebService**: REST API endpoints +- **StellaOps.Signer.Keyless**: Fulcio integration for keyless signing (Sprint 20251226_001) +- **__Libraries/StellaOps.Signer.KeyManagement**: Key rotation and trust anchor management +- **__Tests**: Unit and integration tests + +## Required Reading +- `docs/modules/signer/architecture.md` +- `docs/modules/signer/README.md` (if exists) +- `docs/modules/platform/architecture-overview.md` +- `docs/product-advisories/25-Dec-2025 - Planning Keyless Signing for Verdicts.md` +- Sigstore Fulcio documentation: https://docs.sigstore.dev/certificate_authority/overview/ + +## Working Agreement +1. Update task status to `DOING`/`DONE` in both corresponding sprint file `/docs/implplan/SPRINT_*.md` and local `TASKS.md` when you start or finish work. +2. Review this charter and the Required Reading documents before coding; confirm prerequisites are met. +3. Keep changes deterministic (stable ordering, timestamps, hashes) and align with offline/air-gap expectations. +4. Coordinate doc updates, tests, and cross-guild communication whenever contracts or workflows change. +5. Revert to `TODO` if you pause the task without shipping changes; leave notes in commit/PR descriptions for context. + +## Signing Modes +- **Keyless (Fulcio)**: Ephemeral ECDSA/Ed25519 keys, short-lived X.509 certs from Fulcio, OIDC identity binding +- **KMS**: AWS KMS, GCP KMS, Azure Key Vault β€” hardware-backed, no key exposure +- **HSM (PKCS#11)**: On-premise HSM integration for sovereign/air-gapped environments +- **FIDO2**: WebAuthn authenticator for dual-control scenarios +- **File**: Encrypted key files for development/testing + +## Predicate Types +- `stella.ops/sbom@v1`: SBOM attestation (CycloneDX/SPDX) +- `stella.ops/report@v1`: Final PASS/FAIL vulnerability report +- `stella.ops/vexDecision@v1`: OpenVEX decision with reachability evidence +- `verdict.stella/v1`: Policy verdict attestation (Sprint 20251226_001) +- `stella.ops/promotion@v1`: Promotion/release gate evidence + +## Guardrails +- Ephemeral keys MUST NOT persist to disk; zero memory on disposal +- All timestamps in UTC ISO-8601 +- Preserve determinism: canonical JSON (RFC 8785), stable ordering +- No bearer token fallbacks β€” DPoP/mTLS enforced for `aud=signer` +- Fulcio certificate chains MUST validate to configured roots +- Audit every signing decision; expose metrics +- Keep Offline Kit parity in mind β€” document air-gapped workflows for KMS/HSM modes + +## Active Sprints +- `SPRINT_20251226_001_SIGNER_fulcio_keyless_client.md` β€” Fulcio keyless signing implementation + +## Related Modules +- **Authority**: OIDC tokens, DPoP, mTLS validation +- **Attestor**: Rekor submission, attestation storage, verification +- **Cryptography**: Crypto profiles (ECDSA, Ed25519, SM2) +- **Scheduler**: Bundle rotation jobs