up
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
devportal-offline / build-offline (push) Has been cancelled
Mirror Thin Bundle Sign & Verify / mirror-sign (push) Has been cancelled

This commit is contained in:
StellaOps Bot
2025-11-28 00:45:16 +02:00
parent 3b96b2e3ea
commit 1c6730a1d2
95 changed files with 14504 additions and 463 deletions

View File

@@ -0,0 +1,254 @@
# Portable Evidence Bundle Verification Guide
This document describes how Advisory AI teams can verify the integrity and authenticity of portable evidence bundles produced by StellaOps Excititor for sealed deployments.
## Overview
Portable evidence bundles are self-contained ZIP archives that include:
- Evidence locker manifest with cryptographic Merkle root
- DSSE attestation envelope (when signing is enabled)
- Raw evidence items organized by provider
- Audit timeline events
- Bundle manifest with content index
## Bundle Structure
```
evidence-bundle-{tenant}-{timestamp}.zip
├── manifest.json # VexLockerManifest with Merkle root
├── attestation.json # DSSE envelope (optional)
├── evidence/
│ └── {provider}/
│ └── sha256_{digest}.json
├── timeline.json # Audit timeline events
├── bundle-manifest.json # Index of all contents
└── VERIFY.md # Verification instructions
```
## Verification Steps
### Step 1: Extract and Validate Structure
```bash
# Extract the bundle
unzip evidence-bundle-*.zip -d evidence-bundle/
# Verify expected files exist
ls -la evidence-bundle/
# Should see: manifest.json, bundle-manifest.json, evidence/, timeline.json, VERIFY.md
```
### Step 2: Verify Evidence Item Integrity
Each evidence item's content hash must match its filename:
```bash
cd evidence-bundle/evidence
# For each provider directory
for provider in */; do
for file in "$provider"*.json; do
# Extract expected hash from filename (sha256_xxxx.json -> xxxx)
expected=$(basename "$file" .json | sed 's/sha256_//')
# Compute actual hash
actual=$(sha256sum "$file" | cut -d' ' -f1)
if [ "$expected" != "$actual" ]; then
echo "MISMATCH: $file"
fi
done
done
```
### Step 3: Verify Merkle Root
The Merkle root provides cryptographic proof that all evidence items are included without modification.
#### Python Verification Script
```python
#!/usr/bin/env python3
import json
import hashlib
from pathlib import Path
def compute_merkle_root(hashes):
"""Compute Merkle root from list of hex hashes."""
if len(hashes) == 0:
return hashlib.sha256(b'').hexdigest()
if len(hashes) == 1:
return hashes[0]
# Pad to even number
if len(hashes) % 2 != 0:
hashes = hashes + [hashes[-1]]
# Compute next level
next_level = []
for i in range(0, len(hashes), 2):
combined = bytes.fromhex(hashes[i] + hashes[i+1])
next_level.append(hashlib.sha256(combined).hexdigest())
return compute_merkle_root(next_level)
def verify_bundle(bundle_path):
"""Verify a portable evidence bundle."""
bundle_path = Path(bundle_path)
# Load manifest
with open(bundle_path / 'manifest.json') as f:
manifest = json.load(f)
# Extract hashes, sorted by observationId then providerId
items = sorted(manifest['items'],
key=lambda x: (x['observationId'], x['providerId'].lower()))
hashes = []
for item in items:
content_hash = item['contentHash']
# Strip sha256: prefix if present
if content_hash.startswith('sha256:'):
content_hash = content_hash[7:]
hashes.append(content_hash.lower())
# Compute Merkle root
computed_root = 'sha256:' + compute_merkle_root(hashes)
expected_root = manifest['merkleRoot']
if computed_root == expected_root:
print(f"✓ Merkle root verified: {computed_root}")
return True
else:
print(f"✗ Merkle root mismatch!")
print(f" Expected: {expected_root}")
print(f" Computed: {computed_root}")
return False
if __name__ == '__main__':
import sys
if len(sys.argv) != 2:
print(f"Usage: {sys.argv[0]} <bundle-directory>")
sys.exit(1)
success = verify_bundle(sys.argv[1])
sys.exit(0 if success else 1)
```
### Step 4: Verify Attestation (if present)
When `attestation.json` exists, verify the DSSE envelope:
```bash
# Check if attestation exists
if [ -f "evidence-bundle/attestation.json" ]; then
# Extract attestation metadata
jq '.' evidence-bundle/attestation.json
# Verify signature using appropriate tool
# For Sigstore/cosign attestations:
# cosign verify-attestation --type custom ...
fi
```
#### Attestation Fields
| Field | Description |
|-------|-------------|
| `dsseEnvelope` | Base64-encoded DSSE envelope |
| `envelopeDigest` | SHA-256 hash of the envelope |
| `predicateType` | in-toto predicate type URI |
| `signatureType` | Signature algorithm (e.g., "ES256") |
| `keyId` | Signing key identifier |
| `issuer` | Certificate issuer |
| `subject` | Certificate subject |
| `signedAt` | Signing timestamp (ISO-8601) |
| `transparencyLogRef` | Rekor transparency log entry URL |
### Step 5: Validate Timeline
The timeline provides audit trail of bundle creation:
```bash
# View timeline events
jq '.' evidence-bundle/timeline.json
# Check for any failed events
jq '.[] | select(.errorCode != null)' evidence-bundle/timeline.json
```
#### Timeline Event Types
| Event Type | Description |
|------------|-------------|
| `airgap.import.started` | Bundle import initiated |
| `airgap.import.completed` | Import succeeded |
| `airgap.import.failed` | Import failed (check errorCode) |
## Error Codes Reference
| Code | Description | Resolution |
|------|-------------|------------|
| `AIRGAP_EGRESS_BLOCKED` | External URL blocked in sealed mode | Use mirror/portable media |
| `AIRGAP_SOURCE_UNTRUSTED` | Publisher not allowlisted | Contact administrator |
| `AIRGAP_SIGNATURE_MISSING` | Required signature absent | Re-export with signing |
| `AIRGAP_SIGNATURE_INVALID` | Signature verification failed | Check key/certificate |
| `AIRGAP_PAYLOAD_STALE` | Timestamp exceeds tolerance | Re-create bundle |
| `AIRGAP_PAYLOAD_MISMATCH` | Hash doesn't match metadata | Verify transfer integrity |
## Advisory AI Integration
### Quick Integrity Check
For automated pipelines, use the bundle manifest:
```python
import json
with open('bundle-manifest.json') as f:
manifest = json.load(f)
# Key fields for Advisory AI
print(f"Bundle ID: {manifest['bundleId']}")
print(f"Merkle Root: {manifest['merkleRoot']}")
print(f"Item Count: {manifest['itemCount']}")
print(f"Has Attestation: {manifest['hasAttestation']}")
```
### Evidence Lookup
Find evidence for specific observations:
```python
# Index evidence by observation ID
evidence_index = {e['observationId']: e for e in manifest['evidence']}
# Lookup specific observation
obs_id = 'obs-123-abc'
if obs_id in evidence_index:
entry = evidence_index[obs_id]
file_path = f"evidence/{entry['providerId']}/sha256_{entry['contentHash'][7:]}.json"
```
### Provenance Chain
Build complete provenance from bundle:
1. `bundle-manifest.json` → Bundle creation metadata
2. `manifest.json` → Evidence locker snapshot
3. `attestation.json` → Cryptographic attestation
4. `timeline.json` → Audit trail
## Offline Verification
For fully air-gapped environments:
1. Transfer bundle via approved media
2. Extract to isolated verification system
3. Run verification scripts without network
4. Document verification results for audit
## Support
For questions or issues:
- Review bundle contents with `jq` and standard Unix tools
- Check timeline for error codes and messages
- Contact StellaOps support with bundle ID and merkle root

View File

@@ -31,10 +31,10 @@
| 5 | CONCELIER-LNM-21-001 | DONE | Start of Link-Not-Merge chain | Concelier Core Guild (`src/Concelier/__Libraries/StellaOps.Concelier.Core`) | Define immutable `advisory_observations` model (per-source fields, version ranges, severity text, provenance metadata, tenant guards). |
| 6 | CONCELIER-LNM-21-002 | DONE (2025-11-22) | PREP-CONCELIER-LNM-21-002-WAITING-ON-FINALIZE | Concelier Core Guild · Data Science Guild (`src/Concelier/__Libraries/StellaOps.Concelier.Core`) | Correlation pipelines output linksets with confidence + conflict markers, avoiding value collapse. |
| 7 | CONCELIER-LNM-21-003 | DONE (2025-11-22) | Depends on 21-002 | Concelier Core Guild (`src/Concelier/__Libraries/StellaOps.Concelier.Core`) | Record disagreements (severity, CVSS, references) as structured conflict entries. |
| 8 | CONCELIER-LNM-21-004 | BLOCKED (awaits 21-003) | Depends on 21-003; CI runner now available, proceed once guardrail plan approved. | Concelier Core Guild (`src/Concelier/__Libraries/StellaOps.Concelier.Core`) | Remove legacy merge/dedup logic; add guardrails/tests to keep ingestion append-only; document linkset supersession. |
| 9 | CONCELIER-LNM-21-005 | BLOCKED (awaits 21-004) | Awaiting 21-004 completion; CI runner available for event emission tests. | Concelier Core Guild · Platform Events Guild (`src/Concelier/__Libraries/StellaOps.Concelier.Core`) | Emit `advisory.linkset.updated` events with delta descriptions + observation ids (tenant + provenance only). |
| 10 | CONCELIER-LNM-21-101-DEV | BLOCKED (awaits 21-005) | Depends on 21-005; CI runner available for Storage.Mongo validation. | Concelier Storage Guild (`src/Concelier/__Libraries/StellaOps.Concelier.Storage.Mongo`) | Provision Mongo collections (`advisory_observations`, `advisory_linksets`) with hashed shard keys, tenant indexes, TTL for ingest metadata. |
| 11 | CONCELIER-LNM-21-102-DEV | BLOCKED (awaits 21-101-DEV) | Backfill/rollback tooling waits on 21-101-DEV completion; CI runner available for migrations. | Concelier Storage Guild · DevOps Guild (`src/Concelier/__Libraries/StellaOps.Concelier.Storage.Mongo`) | Backfill legacy merged advisories; seed tombstones; provide rollback tooling for Offline Kit. |
| 8 | CONCELIER-LNM-21-004 | DONE (2025-11-27) | Completed: AOC write guards + tests + docs | Concelier Core Guild (`src/Concelier/__Libraries/StellaOps.Concelier.Core`) | Remove legacy merge/dedup logic; add guardrails/tests to keep ingestion append-only; document linkset supersession. |
| 9 | CONCELIER-LNM-21-005 | DONE (2025-11-27) | Completed: Event contract + publisher interfaces + tests + docs | Concelier Core Guild · Platform Events Guild (`src/Concelier/__Libraries/StellaOps.Concelier.Core`) | Emit `advisory.linkset.updated` events with delta descriptions + observation ids (tenant + provenance only). |
| 10 | CONCELIER-LNM-21-101-DEV | DONE (2025-11-27) | Completed: Sharding + TTL migration + event collection | Concelier Storage Guild (`src/Concelier/__Libraries/StellaOps.Concelier.Storage.Mongo`) | Provision Mongo collections (`advisory_observations`, `advisory_linksets`) with hashed shard keys, tenant indexes, TTL for ingest metadata. |
| 11 | CONCELIER-LNM-21-102-DEV | TODO | Unblocked by 21-101-DEV completion; CI runner available for migrations. | Concelier Storage Guild · DevOps Guild (`src/Concelier/__Libraries/StellaOps.Concelier.Storage.Mongo`) | Backfill legacy merged advisories; seed tombstones; provide rollback tooling for Offline Kit. |
| 12 | CONCELIER-LNM-21-103-DEV | BLOCKED (awaits 21-102-DEV) | Requires 21-102-DEV completion; CI runner available for object-store bootstrap tests. | Concelier Storage Guild (`src/Concelier/__Libraries/StellaOps.Concelier.Storage.Mongo`) | Move large raw payloads to object storage with deterministic pointers; update bootstrapper/offline seeds; preserve provenance metadata. |
| 13 | CONCELIER-LNM-21-201 | BLOCKED (awaits 21-103) | Upstream storage tasks must land first; CI runner available for WebService tests. | Concelier WebService Guild · BE-Base Platform Guild (`src/Concelier/StellaOps.Concelier.WebService`) | `/advisories/observations` filters by alias/purl/source with strict tenant scopes; echoes upstream values + provenance fields only. |
| 14 | CONCELIER-LNM-21-202 | BLOCKED (awaits 21-201) | Await upstream to run `/advisories/linksets` export tests; CI runner available. | Concelier WebService Guild (`src/Concelier/StellaOps.Concelier.WebService`) | `/advisories/linksets`/`export`/`evidence` endpoints surface correlation + conflict payloads and `ERR_AGG_*` mapping; no synthesis/merge. |
@@ -46,6 +46,9 @@
## Execution Log
| Date (UTC) | Update | Owner |
| --- | --- | --- |
| 2025-11-27 | CONCELIER-LNM-21-101-DEV DONE: Created `EnsureLinkNotMergeShardingAndTtlMigration` adding hashed shard key indexes on `tenantId` for horizontal scaling, optional TTL indexes for `ObservationRetention`/`LinksetRetention`/`EventRetention` options, and `advisory_linkset_events` collection for linkset event outbox. Updated `MongoStorageOptions` with retention properties. Registered both `EnsureLinkNotMergeCollectionsMigration` and new sharding/TTL migration in DI. | Implementer |
| 2025-11-27 | CONCELIER-LNM-21-005 DONE: Implemented `advisory.linkset.updated@1` event infrastructure (`AdvisoryLinksetUpdatedEvent`, `IAdvisoryLinksetEventPublisher`, `IAdvisoryLinksetEventOutbox`, `AdvisoryLinksetEventPublisherOptions`). Added 9 unit tests covering delta computation, conflict summaries, and provenance mapping. Documented event contract at `docs/modules/concelier/events/advisory.linkset.updated@1.md`. | Implementer |
| 2025-11-27 | CONCELIER-LNM-21-004 DONE: Implemented AOC write guard infrastructure (`IAdvisoryObservationWriteGuard`, `AdvisoryObservationWriteGuard`, `AppendOnlyViolationException`). Added 13 unit tests covering Proceed/SkipIdentical/RejectMutation dispositions. Documented AOC and linkset supersession model in `docs/modules/concelier/link-not-merge-schema.md`. Legacy merge logic already deprecated with `[Obsolete]` and gated by `NoMergeEnabled` flag (defaults true). | Implementer |
| 2025-11-25 | CONCELIER-GRAPH-24-101 DONE: built WebService.Tests and executed `dotnet test ... --filter AdvisorySummary` successfully; TRX: n/a (local). | Implementer |
| 2025-11-25 | CONCELIER-GRAPH-28-102 DONE: batch evidence API implemented (`/v1/evidence/batch`), contract documented at `docs/modules/concelier/api/evidence-batch.md`, and integration test added (`EvidenceBatch_ReturnsEmptyCollectionsWhenUnknown`). | Implementer |
| 2025-11-25 | CI runner delivered via DEVOPS-CONCELIER-CI-24-101; CONCELIER-GRAPH-24-101 executed; 28-102 remains blocked pending contract/fixtures. | Concelier Implementer |

View File

@@ -10,9 +10,9 @@ Task ID | State | Task description | Owners (Source)
--- | --- | --- | ---
EXCITITOR-VEXLENS-30-001 `VEX evidence enrichers` | DONE | Ensure every observation exported to VEX Lens carries issuer hints, signature blobs, product tree snippets, and staleness metadata so the lens can compute consensus without calling back into Excititor. **Completed:** Enhanced `OpenVexSourceEntry` with enrichment fields (issuerHint, signatureType, keyId, transparencyLogRef, trustWeight, trustTier, stalenessSeconds, productTreeSnippet). Updated `OpenVexStatementMerger.BuildSources()` to extract from VexClaim. Enhanced `OpenVexExportSource` JSON serialization. | Excititor WebService Guild, VEX Lens Guild (src/Excititor/StellaOps.Excititor.WebService)
EXCITITOR-VULN-29-001 `VEX key canonicalization` | DONE | Canonicalize advisory/product keys (map to `advisory_key`, capture scope metadata) while preserving original identifiers in `links[]`; run backfill + regression tests. **Completed:** Created `VexAdvisoryKeyCanonicalizer` (CVE/GHSA/RHSA/DSA/USN) and `VexProductKeyCanonicalizer` (PURL/CPE/RPM/DEB/OCI) in `Core/Canonicalization/`. All 47 tests passing. Supports extracting PURLs/CPEs from component identifiers. | Excititor WebService Guild (src/Excititor/StellaOps.Excititor.WebService)
EXCITITOR-VULN-29-002 `Evidence retrieval APIs` | TODO | Provide `/vuln/evidence/vex/{advisory_key}` returning tenant-scoped raw statements, provenance, and attestation references for Vuln Explorer evidence tabs. Depends on EXCITITOR-VULN-29-001. | Excititor WebService Guild (src/Excititor/StellaOps.Excititor.WebService)
EXCITITOR-VULN-29-004 `Observability` | TODO | Add metrics/logs for normalization errors, suppression scopes, withdrawn statements, and feed them to Vuln Explorer + Advisory AI dashboards. Depends on EXCITITOR-VULN-29-002. | Excititor WebService Guild, Observability Guild (src/Excititor/StellaOps.Excititor.WebService)
EXCITITOR-VULN-29-002 `Evidence retrieval APIs` | DONE | Provide `/vuln/evidence/vex/{advisory_key}` returning tenant-scoped raw statements, provenance, and attestation references for Vuln Explorer evidence tabs. Depends on EXCITITOR-VULN-29-001. **Completed:** Created endpoint at `/vuln/evidence/vex/{advisory_key}` in `EvidenceEndpoints.cs`. Uses `VexAdvisoryKeyCanonicalizer` for key normalization (CVE, GHSA, RHSA, DSA, USN). Returns canonical key, scope, aliases, and statements with provenance (documentDigest, format, sourceUri, revision) and attestation metadata (signatureType, issuer, subject, keyId, verifiedAt, transparencyLogRef, trustWeight, trustTier). Supports cursor-based pagination. | Excititor WebService Guild (src/Excititor/StellaOps.Excititor.WebService)
EXCITITOR-VULN-29-004 `Observability` | DONE | Add metrics/logs for normalization errors, suppression scopes, withdrawn statements, and feed them to Vuln Explorer + Advisory AI dashboards. Depends on EXCITITOR-VULN-29-002. **Completed:** Created `NormalizationTelemetry.cs` with comprehensive metrics: advisory/product key canonicalization (success/error counters, scope distribution), evidence retrieval (request counts, statement count histogram, latency histogram), normalization errors by provider/type, suppression scope tracking, withdrawn statement detection/replacements. Registered meter in `TelemetryExtensions.cs`. Added telemetry calls to evidence endpoint. | Excititor WebService Guild, Observability Guild (src/Excititor/StellaOps.Excititor.WebService)
EXCITITOR-STORE-AOC-19-001 `vex_raw schema validator` | DONE | Ship Mongo JSON Schema + validator tooling (including Offline Kit instructions) so operators can prove Excititor stores only immutable evidence. **Completed:** Created `VexRawSchemaValidator` in `Storage.Mongo/Validation/` with `Validate()`, `ValidateBatch()`, `GetJsonSchema()` methods. Added Offline Kit docs at `docs/airgap/vex-raw-schema-validation.md`. | Excititor Storage Guild (src/Excititor/__Libraries/StellaOps.Excititor.Storage.Mongo)
EXCITITOR-STORE-AOC-19-002 `Idempotency index & migration` | DONE | Create unique indexes, run migrations/backfills, and document rollback steps for the new schema validator. Depends on EXCITITOR-STORE-AOC-19-001. **Completed:** Created `VexRawIdempotencyIndexMigration` with unique indexes (provider+source+digest), query indexes (digest+provider), and time-based index. Added rollback docs at `docs/airgap/vex-raw-migration-rollback.md`. Registered migration in ServiceCollectionExtensions. | Excititor Storage Guild, DevOps Guild (src/Excititor/__Libraries/StellaOps.Excititor.Storage.Mongo)
EXCITITOR-AIRGAP-56-001 `Mirror registration APIs` | TODO | Support mirror bundle registration + provenance exposure, including sealed-mode error mapping and staleness metrics surfaced via API responses. | Excititor WebService Guild (src/Excititor/StellaOps.Excititor.WebService)
EXCITITOR-AIRGAP-58-001 `Portable evidence bundles` | TODO | Produce portable evidence bundles linked to timeline + attestation metadata for sealed deployments, and document verifier steps for Advisory AI teams. Depends on EXCITITOR-AIRGAP-56-001. | Excititor Core Guild, Evidence Locker Guild (src/Excititor/__Libraries/StellaOps.Excititor.Core)
EXCITITOR-AIRGAP-56-001 `Mirror registration APIs` | DONE | Support mirror bundle registration + provenance exposure, including sealed-mode error mapping and staleness metrics surfaced via API responses. **Completed:** Added query methods to `IAirgapImportStore` (ListAsync, FindByBundleIdAsync, CountAsync). Created `AirgapMirrorContracts.cs` with response types for bundle listing/detail/timeline and `AirgapErrorMapping` for structured sealed-mode errors with categories (validation, sealed_mode, trust, duplicate, not_found). Created `MirrorRegistrationEndpoints.cs` with `/airgap/v1/mirror/bundles` endpoints for listing, detail with provenance, and timeline queries. Added `StalenessCalculator` for computing staleness metrics with age categories (fresh, recent, stale, old, very_old). | Excititor WebService Guild (src/Excititor/StellaOps.Excititor.WebService)
EXCITITOR-AIRGAP-58-001 `Portable evidence bundles` | DONE | Produce portable evidence bundles linked to timeline + attestation metadata for sealed deployments, and document verifier steps for Advisory AI teams. Depends on EXCITITOR-AIRGAP-56-001. **Completed:** Created `PortableEvidenceBundleBuilder` in `Core/Evidence/` with ZIP bundle creation including: manifest.json (VexLockerManifest with Merkle root), attestation.json (DSSE envelope), evidence items by provider, timeline.json (audit trail), bundle-manifest.json (content index), VERIFY.md (inline verification guide). Added comprehensive verification docs at `docs/airgap/portable-evidence-bundle-verification.md` with Python/Bash scripts for Merkle root verification, attestation checking, timeline validation, and Advisory AI integration patterns. | Excititor Core Guild, Evidence Locker Guild (src/Excititor/__Libraries/StellaOps.Excititor.Core)

View File

@@ -16,8 +16,8 @@ Focus: Policy & Reasoning focus on Policy (phase II).
| 3 | POLICY-ENGINE-20-003 | DONE (2025-11-27) | SelectionJoin models, PurlEquivalence table, and SelectionJoinService implemented in `src/Policy/StellaOps.Policy.Engine/SelectionJoin/` | Policy Guild, Concelier Core Guild, Excititor Core Guild / src/Policy/StellaOps.Policy.Engine |
| 4 | POLICY-ENGINE-20-004 | DONE (2025-11-27) | Materialization writer implemented in `src/Policy/StellaOps.Policy.Engine/Materialization/` with `EffectiveFinding` models, append-only history, tenant scoping, and trace references | Policy Guild, Platform Storage Guild / src/Policy/StellaOps.Policy.Engine |
| 5 | POLICY-ENGINE-20-005 | DONE (2025-11-27) | Determinism guard implemented in `src/Policy/StellaOps.Policy.Engine/DeterminismGuard/` with static analyzer (`ProhibitedPatternAnalyzer`), runtime sandbox (`DeterminismGuardService`, `EvaluationScope`), and guarded evaluator integration (`GuardedPolicyEvaluator`) | Policy Guild, Security Engineering / src/Policy/StellaOps.Policy.Engine |
| 6 | POLICY-ENGINE-20-006 | TODO | Implement incremental orchestrator reacting to advisory/vex/SBOM change streams and scheduling partial policy re-evaluations (Deps: POLICY-ENGINE-20-005) | Policy Guild, Scheduler Worker Guild / src/Policy/StellaOps.Policy.Engine |
| 7 | POLICY-ENGINE-20-007 | TODO | Emit structured traces/logs of rule hits with sampling controls, metrics (`rules_fired_total`, `vex_overrides_total`), and expose explain trace exports (Deps: POLICY-ENGINE-20-006) | Policy Guild, Observability Guild / src/Policy/StellaOps.Policy.Engine |
| 6 | POLICY-ENGINE-20-006 | DONE (2025-11-27) | Incremental orchestrator implemented in `src/Policy/StellaOps.Policy.Engine/IncrementalOrchestrator/` with `PolicyChangeEvent` models (advisory/VEX/SBOM change types), `IncrementalPolicyOrchestrator` (batching, deduplication, retry logic), and `IncrementalOrchestratorBackgroundService` (continuous processing, metrics) | Policy Guild, Scheduler Worker Guild / src/Policy/StellaOps.Policy.Engine |
| 7 | POLICY-ENGINE-20-007 | DONE (2025-11-27) | Structured traces implemented in `src/Policy/StellaOps.Policy.Engine/Telemetry/` with `RuleHitTrace.cs` (trace models, statistics), `RuleHitTraceCollector.cs` (sampling controls, exporters), and `ExplainTraceExport.cs` (JSON/NDJSON/Text/Markdown export formats) | Policy Guild, Observability Guild / src/Policy/StellaOps.Policy.Engine |
| 8 | POLICY-ENGINE-20-008 | TODO | Add unit/property/golden/perf suites covering policy compilation, evaluation correctness, determinism, and SLA targets (Deps: POLICY-ENGINE-20-007) | Policy Guild, QA Guild / src/Policy/StellaOps.Policy.Engine |
| 9 | POLICY-ENGINE-20-009 | TODO | Define Mongo schemas/indexes for `policies`, `policy_runs`, and `effective_finding_*`; implement migrations and tenant enforcement (Deps: POLICY-ENGINE-20-008) | Policy Guild, Storage Guild / src/Policy/StellaOps.Policy.Engine |
| 10 | POLICY-ENGINE-27-001 | TODO | Extend compile outputs to include rule coverage metadata, symbol table, inline documentation, and rule index for editor autocomplete; persist deterministic hashes (Deps: POLICY-ENGINE-20-009) | Policy Guild / src/Policy/StellaOps.Policy.Engine |
@@ -29,6 +29,7 @@ Focus: Policy & Reasoning focus on Policy (phase II).
## Execution Log
| Date (UTC) | Update | Owner |
| --- | --- | --- |
| 2025-11-27 | POLICY-ENGINE-20-006: Completed incremental orchestrator - `PolicyChangeEvent.cs` (change event models with factory for advisory/VEX/SBOM changes, deterministic content hashing, batching), `IncrementalPolicyOrchestrator.cs` (event processing with idempotency, retry logic, priority-based batching), `IncrementalOrchestratorBackgroundService.cs` (continuous processing with metrics). Status → DONE. | Implementer |
| 2025-11-27 | POLICY-ENGINE-20-005: Completed determinism guard - `DeterminismViolation.cs` (violation models/options), `ProhibitedPatternAnalyzer.cs` (static analysis with regex patterns for DateTime.Now, Random, Guid.NewGuid, HttpClient, File.Read, etc.), `DeterminismGuardService.cs` (runtime sandbox with EvaluationScope, DeterministicTimeProvider), `GuardedPolicyEvaluator.cs` (integration layer). Status → DONE. | Implementer |
| 2025-11-27 | POLICY-ENGINE-20-004: Completed materialization writer - `EffectiveFindingModels.cs` (document schema), `EffectiveFindingWriter.cs` (upsert + append-only history). Tenant-scoped collections, trace references, content hash deduplication. Status → DONE. | Implementer |
| 2025-11-27 | POLICY-ENGINE-20-003: Completed selection joiners - `SelectionJoinModels.cs` (tuple models), `PurlEquivalence.cs` (equivalence table with package key extraction), `SelectionJoinService.cs` (deterministic batching, multi-index lookup). Status → DONE. | Implementer |

View File

@@ -11,7 +11,7 @@ Focus: Policy & Reasoning focus on Policy (phase IV).
| # | Task ID & handle | State | Key dependency / next step | Owners |
| --- | --- | --- | --- | --- |
| 1 | POLICY-ENGINE-40-003 | DONE | Provide API/SDK utilities for consumers (Web Scanner, Graph Explorer) to request policy decisions with source evidence summaries (top severity sources, conflict counts) (Deps: POLICY-ENGINE-40-002) | Policy Guild, Web Scanner Guild / src/Policy/StellaOps.Policy.Engine |
| 2 | POLICY-ENGINE-50-001 | TODO | Implement SPL compiler: validate YAML, canonicalize, produce signed bundle, store artifact in object storage, write `policy_revisions` with AOC metadata (Deps: POLICY-ENGINE-40-003) | Policy Guild, Platform Security / src/Policy/StellaOps.Policy.Engine |
| 2 | POLICY-ENGINE-50-001 | DONE | Implement SPL compiler: validate YAML, canonicalize, produce signed bundle, store artifact in object storage, write `policy_revisions` with AOC metadata (Deps: POLICY-ENGINE-40-003) | Policy Guild, Platform Security / src/Policy/StellaOps.Policy.Engine |
| 3 | POLICY-ENGINE-50-002 | TODO | Build runtime evaluator executing compiled plans over advisory/vex linksets + SBOM asset metadata with deterministic caching (Redis) and fallback path (Deps: POLICY-ENGINE-50-001) | Policy Guild, Runtime Guild / src/Policy/StellaOps.Policy.Engine |
| 4 | POLICY-ENGINE-50-003 | TODO | Implement evaluation/compilation metrics, tracing, and structured logs (`policy_eval_seconds`, `policy_compiles_total`, explanation sampling) (Deps: POLICY-ENGINE-50-002) | Policy Guild, Observability Guild / src/Policy/StellaOps.Policy.Engine |
| 5 | POLICY-ENGINE-50-004 | TODO | Build event pipeline: subscribe to linkset/SBOM updates, schedule re-eval jobs, emit `policy.effective.updated` events with diff metadata (Deps: POLICY-ENGINE-50-003) | Policy Guild, Platform Events Guild / src/Policy/StellaOps.Policy.Engine |
@@ -29,6 +29,13 @@ Focus: Policy & Reasoning focus on Policy (phase IV).
## Notes & Risks (2025-11-27)
- POLICY-ENGINE-40-003 implementation complete: Added `PolicyDecisionModels.cs`, `PolicyDecisionService.cs`, `PolicyDecisionEndpoint.cs`, and `PolicyDecisionServiceTests.cs`. Service registered in `Program.cs`. All 9 tests pass.
- POLICY-ENGINE-50-001 implementation complete: Extended SPL compiler with AOC (Attestation of Compliance) metadata support:
- Added `PolicyAocMetadata`, `PolicyProvenance`, `PolicyAttestationRef` records to `PolicyPackRecord.cs`
- Added `PolicyProvenanceInput`, `PolicyAocMetadataResponse` to `PolicyBundleModels.cs`
- Updated `PolicyBundleService` to capture compilation ID, source/artifact digests, complexity metrics, provenance
- Added 4 new tests for AOC metadata in `PolicyBundleServiceTests.cs` (all pass)
- Existing YAML validation via `PolicyBinder`, canonicalization via `PolicyCompilationService`, signed bundles via `PolicyBundleService`, storage via `IPolicyPackRepository` all integrate with new AOC metadata
- Pre-existing test issue: `EvidenceSummaryServiceTests.Summarize_BuildsDeterministicSummary` fails due to date derivation mismatch (unrelated to current changes)
- Pre-existing build issues resolved:
- `StellaOps.Telemetry.Core`: Fixed TelemetryContext API (added CorrelationId/TraceId aliases, Current/Context property aliases), added Grpc.AspNetCore package, removed duplicate FrameworkReference.
- `StellaOps.Policy.RiskProfile`: Fixed JsonSchema.Net v5 API changes (`ValidationResults``EvaluationResults`), `JsonDocument.Parse` signature.
@@ -40,3 +47,4 @@ Focus: Policy & Reasoning focus on Policy (phase IV).
| --- | --- | --- |
| 2025-11-27 | Started POLICY-ENGINE-40-003; implemented PolicyDecisionService, PolicyDecisionEndpoint, PolicyDecisionModels, tests. Blocked by pre-existing build issues in Telemetry.Core and RiskProfile projects. | Implementer |
| 2025-11-27 | Fixed pre-existing build issues (TelemetryContext API mismatch, JsonSchema.Net v5 API changes, OpenTelemetry Meter API changes, test project missing packages/namespaces). All 9 PolicyDecisionServiceTests pass. POLICY-ENGINE-40-003 marked DONE. | Implementer |
| 2025-11-27 | Implemented POLICY-ENGINE-50-001: Extended SPL compiler with AOC metadata support. Added PolicyAocMetadata, PolicyProvenance, PolicyAttestationRef models. Updated PolicyBundleService to capture compilation metadata, source/artifact digests, complexity metrics, provenance info. Added 4 new tests (all pass). POLICY-ENGINE-50-001 marked DONE. | Implementer |

View File

@@ -15,8 +15,8 @@ Dependency: Sprint 133 - 4. Scanner.IV — Scanner & Surface focus on Scanner (p
| `SCANNER-ANALYZERS-PYTHON-23-001` | DONE | Build input normalizer & virtual filesystem for wheels, sdists, editable installs, zipapps, site-packages trees, and container roots. Detect Python version targets (`pyproject.toml`, `runtime.txt`, Dockerfile) + virtualenv layout deterministically. | Python Analyzer Guild (src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.Python) | — |
| `SCANNER-ANALYZERS-PYTHON-23-002` | DONE | Entrypoint discovery: module `__main__`, console_scripts entry points, `scripts`, zipapp main, `manage.py`/gunicorn/celery patterns. Capture invocation context (module vs package, argv wrappers). | Python Analyzer Guild (src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.Python) | SCANNER-ANALYZERS-PYTHON-23-001 |
| `SCANNER-ANALYZERS-PYTHON-23-003` | DONE | Static import graph builder using AST and bytecode fallback. Support `import`, `from ... import`, relative imports, `importlib.import_module`, `__import__` with literal args, `pkgutil.extend_path`. | Python Analyzer Guild (src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.Python) | SCANNER-ANALYZERS-PYTHON-23-002 |
| `SCANNER-ANALYZERS-PYTHON-23-004` | TODO | Python resolver engine (importlib semantics) handling namespace packages (PEP 420), package discovery order, `.pth` files, `sys.path` composition, zipimport, and site-packages precedence across virtualenv/container roots. | Python Analyzer Guild (src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.Python) | SCANNER-ANALYZERS-PYTHON-23-003 |
| `SCANNER-ANALYZERS-PYTHON-23-005` | TODO | Packaging adapters: pip editable (`.egg-link`), Poetry/Flit layout, Conda prefix, `.dist-info/RECORD` cross-check, container layer overlays. | Python Analyzer Guild (src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.Python) | SCANNER-ANALYZERS-PYTHON-23-004 |
| `SCANNER-ANALYZERS-PYTHON-23-004` | DONE | Python resolver engine (importlib semantics) handling namespace packages (PEP 420), package discovery order, `.pth` files, `sys.path` composition, zipimport, and site-packages precedence across virtualenv/container roots. | Python Analyzer Guild (src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.Python) | SCANNER-ANALYZERS-PYTHON-23-003 |
| `SCANNER-ANALYZERS-PYTHON-23-005` | DONE | Packaging adapters: pip editable (`.egg-link`), Poetry/Flit layout, Conda prefix, `.dist-info/RECORD` cross-check, container layer overlays. | Python Analyzer Guild (src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.Python) | SCANNER-ANALYZERS-PYTHON-23-004 |
| `SCANNER-ANALYZERS-PYTHON-23-006` | TODO | Detect native extensions (`*.so`, `*.pyd`), CFFI modules, ctypes loaders, embedded WASM, and runtime capability signals (subprocess, multiprocessing, ctypes, eval). | Python Analyzer Guild (src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.Python) | SCANNER-ANALYZERS-PYTHON-23-005 |
| `SCANNER-ANALYZERS-PYTHON-23-007` | TODO | Framework/config heuristics: Django, Flask, FastAPI, Celery, AWS Lambda handlers, Gunicorn, Click/Typer CLIs, logging configs, pyproject optional dependencies. Tagged as hints only. | Python Analyzer Guild (src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.Python) | SCANNER-ANALYZERS-PYTHON-23-006 |
| `SCANNER-ANALYZERS-PYTHON-23-008` | TODO | Produce AOC-compliant observations: entrypoints, components (modules/packages/native), edges (import, namespace, dynamic-hint, native-extension) with reason codes/confidence and resolver traces. | Python Analyzer Guild (src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.Python) | SCANNER-ANALYZERS-PYTHON-23-007 |

View File

@@ -19,6 +19,6 @@ Dependency: Sprint 134 - 5. Scanner.V — Scanner & Surface focus on Scanner (ph
| `SCANNER-ANALYZERS-RUBY-28-009` | DONE | Fixture suite + performance benchmarks (Rails, Rack, Sinatra, Sidekiq, legacy, .gem, container) with golden outputs. | Ruby Analyzer Guild, QA Guild (src/Scanner/StellaOps.Scanner.Analyzers.Lang.Ruby) | SCANNER-ANALYZERS-RUBY-28-008 |
| `SCANNER-ANALYZERS-RUBY-28-010` | DONE | Optional runtime evidence integration (if provided logs/metrics) with path hashing, without altering static precedence. | Ruby Analyzer Guild, Signals Guild (src/Scanner/StellaOps.Scanner.Analyzers.Lang.Ruby) | SCANNER-ANALYZERS-RUBY-28-009 |
| `SCANNER-ANALYZERS-RUBY-28-011` | DONE | Package analyzer plug-in, add CLI (`stella ruby inspect`), refresh Offline Kit documentation. | Ruby Analyzer Guild, DevOps Guild (src/Scanner/StellaOps.Scanner.Analyzers.Lang.Ruby) | SCANNER-ANALYZERS-RUBY-28-010 |
| `SCANNER-ANALYZERS-RUBY-28-012` | TODO | Policy signal emitter: rubygems drift, native extension flags, dangerous constructs counts, TLS verify posture, dynamic require eval warnings. | Ruby Analyzer Guild (src/Scanner/StellaOps.Scanner.Analyzers.Lang.Ruby) | SCANNER-ANALYZERS-RUBY-28-011 |
| `SCANNER-ANALYZERS-RUBY-28-012` | DONE | Policy signal emitter: rubygems drift, native extension flags, dangerous constructs counts, TLS verify posture, dynamic require eval warnings. | Ruby Analyzer Guild (src/Scanner/StellaOps.Scanner.Analyzers.Lang.Ruby) | SCANNER-ANALYZERS-RUBY-28-011 |
| `SCANNER-ENTRYTRACE-18-502` | TODO | Expand chain walker with init shim/user-switch/supervisor recognition plus env/workdir accumulation and guarded edges. | EntryTrace Guild (src/Scanner/__Libraries/StellaOps.Scanner.EntryTrace) | SCANNER-ENTRYTRACE-18-508 |
| `SCANNER-ENTRYTRACE-18-503` | TODO | Introduce target classifier + EntryPlan handoff with confidence scoring for ELF/Java/.NET/Node/Python and user/workdir context. | EntryTrace Guild (src/Scanner/__Libraries/StellaOps.Scanner.EntryTrace) | SCANNER-ENTRYTRACE-18-502 |

View File

@@ -19,10 +19,10 @@ Dependency: Sprint 135 - 6. Scanner.VI — Scanner & Surface focus on Scanner (p
| `SURFACE-ENV-04` | DONE (2025-11-27) | Wire env helper into Zastava Observer/Webhook containers. | Zastava Guild (src/Scanner/__Libraries/StellaOps.Scanner.Surface.Env) | SURFACE-ENV-02 |
| `SURFACE-ENV-05` | TODO | Update Helm/Compose/offline kit templates with new env knobs and documentation. | Ops Guild (src/Scanner/__Libraries/StellaOps.Scanner.Surface.Env) | SURFACE-ENV-03, SURFACE-ENV-04 |
| `SCANNER-EVENTS-16-301` | BLOCKED (2025-10-26) | Emit orchestrator-compatible envelopes (`scanner.event.*`) and update integration tests to verify Notifier ingestion (no Redis queue coupling). | Scanner WebService Guild (src/Scanner/StellaOps.Scanner.WebService) | — |
| `SCANNER-GRAPH-21-001` | TODO | Provide webhook/REST endpoint for Cartographer to request policy overlays and runtime evidence for graph nodes, ensuring determinism and tenant scoping. | Scanner WebService Guild, Cartographer Guild (src/Scanner/StellaOps.Scanner.WebService) | — |
| `SCANNER-LNM-21-001` | TODO | Update `/reports` and `/policy/runtime` payloads to consume advisory/vex linksets, exposing source severity arrays and conflict summaries alongside effective verdicts. | Scanner WebService Guild, Policy Guild (src/Scanner/StellaOps.Scanner.WebService) | — |
| `SCANNER-GRAPH-21-001` | DONE (2025-11-27) | Provide webhook/REST endpoint for Cartographer to request policy overlays and runtime evidence for graph nodes, ensuring determinism and tenant scoping. | Scanner WebService Guild, Cartographer Guild (src/Scanner/StellaOps.Scanner.WebService) | — |
| `SCANNER-LNM-21-001` | BLOCKED (2025-11-27) | Update `/reports` and `/policy/runtime` payloads to consume advisory/vex linksets, exposing source severity arrays and conflict summaries alongside effective verdicts. Blocked: requires Concelier HTTP client integration or shared library; no existing Concelier dependency in Scanner WebService. | Scanner WebService Guild, Policy Guild (src/Scanner/StellaOps.Scanner.WebService) | — |
| `SCANNER-LNM-21-002` | TODO | Add evidence endpoint for Console to fetch linkset summaries with policy overlay for a component/SBOM, including AOC references. | Scanner WebService Guild, UI Guild (src/Scanner/StellaOps.Scanner.WebService) | SCANNER-LNM-21-001 |
| `SCANNER-SECRETS-03` | TODO | Use Surface.Secrets to retrieve registry credentials when interacting with CAS/referrers. | BuildX Plugin Guild, Security Guild (src/Scanner/StellaOps.Scanner.Sbomer.BuildXPlugin) | SCANNER-SECRETS-02 |
| `SCANNER-SECRETS-03` | DONE (2025-11-27) | Use Surface.Secrets to retrieve registry credentials when interacting with CAS/referrers. | BuildX Plugin Guild, Security Guild (src/Scanner/StellaOps.Scanner.Sbomer.BuildXPlugin) | SCANNER-SECRETS-02 |
| `SURFACE-SECRETS-01` | DONE (2025-11-23) | Security-approved schema published at `docs/modules/scanner/design/surface-secrets-schema.md`; proceed to provider wiring. | Scanner Guild, Security Guild (src/Scanner/__Libraries/StellaOps.Scanner.Surface.Secrets) | — |
| `SURFACE-SECRETS-02` | DONE (2025-11-23) | Provider chain implemented (primary + fallback) with DI wiring; tests updated (`StellaOps.Scanner.Surface.Secrets.Tests`). | Scanner Guild (src/Scanner/__Libraries/StellaOps.Scanner.Surface.Secrets) | SURFACE-SECRETS-01 |
| `SURFACE-SECRETS-03` | DONE (2025-11-27) | Add Kubernetes/File/Offline backends with deterministic caching and audit hooks. | Scanner Guild (src/Scanner/__Libraries/StellaOps.Scanner.Surface.Secrets) | SURFACE-SECRETS-02 |
@@ -39,9 +39,9 @@ Dependency: Sprint 135 - 6. Scanner.VI — Scanner & Surface focus on Scanner (p
| `SCANNER-ENG-0027` | TODO | Deliver Windows policy/offline integration per `design/windows-analyzer.md` §56. | Scanner Guild, Policy Guild, Offline Kit Guild (docs/modules/scanner) | — |
| `SCHED-SURFACE-02` | TODO | Integrate Scheduler worker prefetch using Surface manifest reader and persist manifest pointers with rerun plans. | Scheduler Worker Guild (src/Scheduler/__Libraries/StellaOps.Scheduler.Worker) | SURFACE-FS-02, SCHED-SURFACE-01. Reference `docs/modules/scanner/design/surface-fs-consumers.md` §3 for implementation checklist |
| `ZASTAVA-SURFACE-02` | TODO | Use Surface manifest reader helpers to resolve `cas://` pointers and enrich drift diagnostics with manifest provenance. | Zastava Observer Guild (src/Zastava/StellaOps.Zastava.Observer) | SURFACE-FS-02, ZASTAVA-SURFACE-01. Reference `docs/modules/scanner/design/surface-fs-consumers.md` §4 for integration steps |
| `SURFACE-FS-03` | TODO | Integrate Surface.FS writer into Scanner Worker analyzer pipeline to persist layer + entry-trace fragments. | Scanner Guild (src/Scanner/__Libraries/StellaOps.Scanner.Surface.FS) | SURFACE-FS-02 |
| `SURFACE-FS-04` | TODO | Integrate Surface.FS reader into Zastava Observer runtime drift loop. | Zastava Guild (src/Scanner/__Libraries/StellaOps.Scanner.Surface.FS) | SURFACE-FS-02 |
| `SURFACE-FS-05` | TODO | Expose Surface.FS pointers via Scanner WebService reports and coordinate rescan planning with Scheduler. | Scanner Guild, Scheduler Guild (src/Scanner/__Libraries/StellaOps.Scanner.Surface.FS) | SURFACE-FS-03 |
| `SURFACE-FS-03` | DONE (2025-11-27) | Integrate Surface.FS writer into Scanner Worker analyzer pipeline to persist layer + entry-trace fragments. | Scanner Guild (src/Scanner/__Libraries/StellaOps.Scanner.Surface.FS) | SURFACE-FS-02 |
| `SURFACE-FS-04` | DONE (2025-11-27) | Integrate Surface.FS reader into Zastava Observer runtime drift loop. | Zastava Guild (src/Scanner/__Libraries/StellaOps.Scanner.Surface.FS) | SURFACE-FS-02 |
| `SURFACE-FS-05` | DONE (2025-11-27) | Expose Surface.FS pointers via Scanner WebService reports and coordinate rescan planning with Scheduler. | Scanner Guild, Scheduler Guild (src/Scanner/__Libraries/StellaOps.Scanner.Surface.FS) | SURFACE-FS-03 |
| `SURFACE-FS-06` | TODO | Update scanner-engine guide and offline kit docs with Surface.FS workflow. | Docs Guild (src/Scanner/__Libraries/StellaOps.Scanner.Surface.FS) | SURFACE-FS-02..05 |
| `SCANNER-SURFACE-04` | TODO | DSSE-sign every `layer.fragments` payload, emit `_composition.json`, and persist DSSE envelopes so offline kits can replay deterministically (see `docs/modules/scanner/deterministic-sbom-compose.md` §2.1). | Scanner Worker Guild (src/Scanner/StellaOps.Scanner.Worker) | SCANNER-SURFACE-01, SURFACE-FS-03 |
| `SURFACE-FS-07` | TODO | Extend Surface.FS manifest schema with `composition.recipe`, fragment attestation metadata, and verification helpers per deterministic SBOM spec. | Scanner Guild (src/Scanner/__Libraries/StellaOps.Scanner.Surface.FS) | SCANNER-SURFACE-04 |
@@ -65,6 +65,12 @@ Dependency: Sprint 135 - 6. Scanner.VI — Scanner & Surface focus on Scanner (p
| 2025-11-27 | Added Surface.Secrets project reference to BuildX plugin; implemented TryResolveAttestationToken() to fetch attestation secrets from Surface.Secrets; Worker/WebService already had configurators for CAS/registry/attestation secrets. SURFACE-SECRETS-04 DONE. | Implementer |
| 2025-11-27 | Verified Zastava Observer/Webhook already have ObserverSurfaceSecrets/WebhookSurfaceSecrets classes using ISurfaceSecretProvider for CAS and attestation secrets. SURFACE-SECRETS-05 DONE. | Implementer |
| 2025-11-27 | SURFACE-SECRETS-06 marked BLOCKED: requires Ops Guild input on Helm/Compose patterns for Surface.Secrets provider configuration (kubernetes/file/inline). Added to Decisions & Risks. | Implementer |
| 2025-11-27 | Integrated ISurfaceManifestWriter into SurfaceManifestStageExecutor to persist manifest documents to file-system store for offline/air-gapped scenarios; build verified. SURFACE-FS-03 DONE. | Implementer |
| 2025-11-27 | Added IRuntimeSurfaceFsClient injection to RuntimePostureEvaluator, enriching drift evidence with manifest digest/artifacts/metadata; added `zastava_surface_manifest_failures_total` metric with reason labels. SURFACE-FS-04 DONE. | Implementer |
| 2025-11-27 | Added TryResolveCasCredentials() to BuildX plugin using Surface.Secrets to fetch CAS access credentials; fixed attestation token resolution to use correct parser method. SCANNER-SECRETS-03 DONE. | Implementer |
| 2025-11-27 | Verified SurfacePointerService already exposes Surface.FS pointers (SurfaceManifestDocument, SurfaceManifestArtifact, manifest URI/digest) via reports endpoint. SURFACE-FS-05 DONE. | Implementer |
| 2025-11-27 | Added POST /policy/overlay endpoint for Cartographer integration: accepts graph nodes, returns deterministic overlays with sha256(tenant\|nodeId\|overlayKind) IDs, includes runtime evidence. Added PolicyOverlayRequestDto/ResponseDto contracts. SCANNER-GRAPH-21-001 DONE. | Implementer |
| 2025-11-27 | SCANNER-LNM-21-001 marked BLOCKED: Scanner WebService has no existing Concelier integration; requires HTTP client or shared library reference to Concelier.Core for linkset consumption. Added to Decisions & Risks. | Implementer |
| 2025-11-23 | Published Security-approved Surface.Secrets schema (`docs/modules/scanner/design/surface-secrets-schema.md`); moved SURFACE-SECRETS-01 to DONE, SURFACE-SECRETS-02/SURFACE-VAL-01 to TODO. | Security Guild |
| 2025-11-23 | Implemented Surface.Secrets provider chain/fallback and added DI tests; marked SURFACE-SECRETS-02 DONE. | Scanner Guild |
| 2025-11-23 | Pinned Surface.Env package version `0.1.0-alpha.20251123` and offline path in `docs/modules/scanner/design/surface-env-release.md`; SCANNER-ENV-03 moved to TODO. | BuildX Plugin Guild |

View File

@@ -7,7 +7,7 @@ Depends on: Sprint 180.A - Cli.IV
Summary: Experience & SDKs focus on Cli (phase V).
Task ID | State | Task description | Owners (Source)
--- | --- | --- | ---
CLI-TEN-47-001 | TODO | Implement `stella login`, `whoami`, `tenants list`, persistent profiles, secure token storage, and `--tenant` override with validation. | DevEx/CLI Guild (src/Cli/StellaOps.Cli)
CLI-TEN-47-001 | DOING | Implement `stella login`, `whoami`, `tenants list`, persistent profiles, secure token storage, and `--tenant` override with validation. Partial: `auth login`, `auth whoami` already exist; `tenants list` implemented. Remaining: persistent profiles, secure token storage enhancements, `--tenant` override validation. | DevEx/CLI Guild (src/Cli/StellaOps.Cli)
CLI-TEN-49-001 | TODO | Add service account token minting, delegation (`stella token delegate`), impersonation banner, and audit-friendly logging. Dependencies: CLI-TEN-47-001. | DevEx/CLI Guild (src/Cli/StellaOps.Cli)
CLI-VEX-30-001 | TODO | Implement `stella vex consensus list` with filters, paging, policy selection, `--json/--csv`. | DevEx/CLI Guild (src/Cli/StellaOps.Cli)
CLI-VEX-30-002 | TODO | Implement `stella vex consensus show` displaying quorum, evidence, rationale, signature status. Dependencies: CLI-VEX-30-001. | DevEx/CLI Guild (src/Cli/StellaOps.Cli)

View File

@@ -0,0 +1,88 @@
# advisory.linkset.updated@1 · Event contract
Purpose: unblock CONCELIER-LNM-21-005 by freezing the platform event shape for linkset changes emitted by Concelier. This is the only supported event for linkset churn; downstreams subscribe for graph overlays, policy evaluations, and replay bundles.
## Envelope & transport
- Subject: `concelier.advisory.linkset.updated.v1`
- Type/version: `advisory.linkset.updated@1`
- Transport: NATS (primary), Redis Stream `concelier:advisory.linkset.updated:v1` (fallback). Both carry the same DSSE envelope.
- DSSE payloadType: `application/vnd.stellaops.advisory.linkset.updated.v1+json`.
- Signature: Ed25519 via Platform Events signer; attach Rekor UUID when available. Offline kits treat the envelope as the source of truth.
## Payload (JSON)
| Field | Type | Rules |
| --- | --- | --- |
| `eventId` | string (uuid) | Generated by publisher; idempotency key. |
| `tenantId` | string | `urn:tenant:{uuid}`; required for multi-tenant routing. |
| `linksetId` | string (ObjectId) | Mongo `_id` of the linkset document. |
| `advisoryId` | string | Upstream advisory identifier (e.g., CVE, GHSA, vendor id). |
| `source` | string | Linkset source/adapter identifier (lowercase). |
| `observationIds` | string[] | Array of observation ObjectIds included in this linkset; sorted ASCII. |
| `delta` | object | Change description: `{ type, observationsAdded, observationsRemoved, confidenceChanged, conflictsChanged }`. |
| `confidence` | number (01, nullable) | Correlation confidence score; null if not computed. |
| `conflicts` | object[] | Array of `{ field, reason, sourceIds[] }` conflict summaries; sorted by field then reason. |
| `provenance` | object | `{ observationHashes[], toolVersion?, policyHash? }` for replay/audit. |
| `createdAt` | string (ISO-8601 UTC) | Timestamp when linkset was built. |
| `replayCursor` | string | Monotone cursor for offline bundle ordering (tick from createdAt). |
| `builtByJobId` | string (optional) | Job ID that built this linkset. |
| `traceId` | string (optional) | Propagated from ingest job/request; aids join with logs/metrics. |
### Delta object
| Field | Type | Rules |
| --- | --- | --- |
| `type` | string | `"created"` or `"updated"`. |
| `observationsAdded` | string[] | Observation IDs added since previous version. |
| `observationsRemoved` | string[] | Observation IDs removed since previous version. |
| `confidenceChanged` | boolean | True if confidence score changed. |
| `conflictsChanged` | boolean | True if conflicts array changed. |
### Determinism & ordering
- Arrays sorted ASCII; objects field-sorted when hashing.
- `eventId` + `replayCursor` provide exactly-once consumer handling; duplicates must be ignored when observation hashes unchanged.
- No judgments: only raw facts, delta descriptions, and provenance pointers; any derived severity/merge content is forbidden.
### Error contracts for Scheduler
- Retryable NATS/Redis failures use backoff capped at 30s; after 5 attempts, emit `concelier.events.dlq` with the same envelope and `error` field describing transport failure.
- Consumers must NACK on schema validation failure; publisher logs `ERR_EVENT_SCHEMA` and quarantines the offending linkset id.
## Sample payload
```json
{
"eventId": "550e8400-e29b-41d4-a716-446655440000",
"tenantId": "urn:tenant:acme-corp",
"linksetId": "6744abcd1234567890abcdef",
"advisoryId": "CVE-2024-1234",
"source": "nvd",
"observationIds": ["674400001234567890abcdef", "674400001234567890abcde0"],
"delta": {
"type": "created",
"observationsAdded": ["674400001234567890abcdef", "674400001234567890abcde0"],
"observationsRemoved": [],
"confidenceChanged": true,
"conflictsChanged": false
},
"confidence": 0.85,
"conflicts": [],
"provenance": {
"observationHashes": ["sha256:abc123", "sha256:def456"],
"toolVersion": "1.0.0",
"policyHash": null
},
"createdAt": "2025-11-27T12:00:00.000Z",
"replayCursor": "638688000000000000",
"builtByJobId": "job-12345",
"traceId": "trace-67890"
}
```
## Schema
`advisory.linkset.updated@1.schema.json` provides a JSON Schema (draft 2020-12) for runtime validation; any additional fields are rejected.
## Implementation (LNM-21-005)
- Event type defined in `StellaOps.Concelier.Core.Linksets.AdvisoryLinksetUpdatedEvent`.
- Publisher interface: `IAdvisoryLinksetEventPublisher`.
- Outbox interface: `IAdvisoryLinksetEventOutbox`.
- Configuration: `AdvisoryLinksetEventPublisherOptions`.
## Change control
- Add-only. Adjusting delta types or conflict codes requires new version `advisory.linkset.updated@2` and a sprint note.

View File

@@ -78,6 +78,33 @@ _Frozen v1 (add-only) — approved 2025-11-17 for CONCELIER-LNM-21-001/002/101._
- **Deterministic keying:** `_id` derived from `hash(tenantId|source|advisoryId|provenance.sourceArtifactSha)` to keep inserts idempotent in replay.
- **Normalization guardrails:** version ranges must be stored as raw-from-source; no inferred merges.
## Append-Only Contract (AOC) — LNM-21-004
The Aggregation-Only Contract (AOC) ensures observations are immutable after creation. This is enforced by `IAdvisoryObservationWriteGuard`.
### Write disposition rules
| Existing Hash | New Hash | Disposition | Action |
|--------------|----------|-------------|--------|
| null/empty | any | `Proceed` | Insert new observation |
| X | X (identical) | `SkipIdentical` | Idempotent re-insert, no write |
| X | Y (different) | `RejectMutation` | Reject with `AppendOnlyViolationException` |
### Supersession model
When an advisory source publishes a revised version of an advisory:
1. A **new observation** is created with its own unique `observationId` and `contentHash`.
2. The new observation MAY carry a `supersedesId` pointing to the previous observation.
3. The **original observation remains immutable** — it is never updated or deleted.
4. Linksets are rebuilt to include all non-superseded observations; superseded observations remain queryable for audit but excluded from active linkset aggregation.
### Implementation checklist (LNM-21-004)
- [x] `IAdvisoryObservationWriteGuard` interface with `ValidateWrite(observation, existingContentHash)` method.
- [x] `AdvisoryObservationWriteGuard` implementation enforcing append-only semantics.
- [x] `AppendOnlyViolationException` for mutation rejections.
- [x] DI registration via `AddConcelierAocGuards()` extension.
- [x] Unit tests covering Proceed/SkipIdentical/RejectMutation scenarios.
- [x] Legacy merge logic deprecated with `[Obsolete]` and gated by `NoMergeEnabled` feature flag (defaults to `true`).
- [x] Roslyn analyzer `StellaOps.Concelier.Analyzers.NoMergeApiAnalyzer` emits warnings for merge API usage.
## Linkset document
```json
{