Add new features and tests for AirGap and Time modules
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled

- Introduced `SbomService` tasks documentation.
- Updated `StellaOps.sln` to include new projects: `StellaOps.AirGap.Time` and `StellaOps.AirGap.Importer`.
- Added unit tests for `BundleImportPlanner`, `DsseVerifier`, `ImportValidator`, and other components in the `StellaOps.AirGap.Importer.Tests` namespace.
- Implemented `InMemoryBundleRepositories` for testing bundle catalog and item repositories.
- Created `MerkleRootCalculator`, `RootRotationPolicy`, and `TufMetadataValidator` tests.
- Developed `StalenessCalculator` and `TimeAnchorLoader` tests in the `StellaOps.AirGap.Time.Tests` namespace.
- Added `fetch-sbomservice-deps.sh` script for offline dependency fetching.
This commit is contained in:
master
2025-11-20 23:29:54 +02:00
parent 65b1599229
commit 79b8e53441
182 changed files with 6660 additions and 1242 deletions

View File

@@ -0,0 +1,21 @@
# Attestor Replay Prep — PREP-ATTEST-REPLAY-187-003 (Draft)
Status: Draft (2025-11-20)
Owners: Attestor Guild
Scope: Capture prerequisites for wiring Attestor/Rekor anchoring to replay manifests once scanner record payloads are available.
## Expected inputs
- Replay record schema v1 (from `docs/modules/evidence-locker/replay-payload-contract.md`).
- Evidence Locker bundle location/pointer for replay artefacts.
## Attestation plan
- DSSE envelope type: `stella.replay.manifest` (draft).
- Payload fields: `{record_id, bundle_sha256, policy_run_id?, timestamp}`; signer: Attestor service key; optional Rekor entry when online.
- Verification endpoint proposal: `POST /attestations/replay/verify` accepting bundle pointer + DSSE; returns chain-of-custody summary.
## Open dependencies
- Final replay record schema and bundle pointer format.
- Authority policy on signer identity and Rekor usage in air-gap.
## Handoff
Use this note to unblock PREP-ATTEST-REPLAY-187-003; update when scanner payloads and Authority decisions land.

View File

@@ -0,0 +1,30 @@
# CLI Replay Prep — PREP-CLI-REPLAY-187-002 (Draft)
Status: Draft (2025-11-20)
Owners: DevEx/CLI Guild
Scope: Define inputs/outputs and offline behaviour needed for CLI replay commands (`scan --record`, `verify`, `replay`, `diff`).
## Command surface (proposed)
- `stella scan --record <image>` → emits replay record NDJSON to stdout or `--out bundle.ndjson`.
- `stella replay --bundle <bundle.ndjson>` → re-run verification offline; accepts `--policy-bundle` to pin policy version.
- `stella diff --bundle <a> --bundle <b>` → compare findings/signals with deterministic ordering; output NDJSON.
- `stella verify --bundle <bundle.ndjson>` → signature/hash verification of replay bundle.
## Inputs
- Replay record schema v1 from Evidence Locker (see `docs/modules/evidence-locker/replay-payload-contract.md`).
- Policy export bundle contract (see `docs/modules/policy/design/export-console-bundle-contract.md`) for policy pinning.
## Outputs
- Deterministic NDJSON; file names content-addressed (`sha256` of payload).
- Exit codes: 0 success, 2 validation error, 3 signature mismatch.
## Offline/air-gap considerations
- No network fetch; all references resolve to local bundle paths.
- Trust roots loaded from CLI config or `--trust-root` file; DSSE verification optional flag `--no-verify` default false.
## Open decisions
- Exact flag names for trust root and policy bundle; align with CLI UX guidelines.
- Where to persist cache/metadata (if any) in offline mode.
## Handoff
Treat this as the prep artefact for PREP-CLI-REPLAY-187-002. Update once replay record schema is finalized.

View File

@@ -0,0 +1,57 @@
# Console Consumption of LNM Linksets (Sprint 110)
Goal: unblock CONCELIER-CONSOLE-23-001..003 by defining how Console reads Link-Not-Merge (LNM) data now that the schema is frozen (2025-11-17) and cache plan exists.
## Data sources
- Primary collection: `advisory_linksets` (see `docs/modules/concelier/link-not-merge-schema.md`).
- Cache: `advisory_linkset_cache` (see `docs/modules/concelier/operations/lnm-cache-plan.md`). Console should read from cache when present; fall back to live rebuild otherwise.
## API shape (WebService)
- Endpoint to expose via Console: `GET /v1/lnm/linksets/{advisoryId}`
- Query: `source` (required), `tenant`, optional `includeConflicts=true|false` (default true).
- Response JSON (deterministic key order):
```json
{
"advisoryId": "GHSA-123",
"source": "ghsa",
"observations": ["<mongoId>", "<mongoId2>"],
"normalized": {
"purls": ["pkg:npm/foo@1.0.0"],
"versions": ["1.0.0"],
"ranges": [],
"severities": [{"system":"cvssv3","score":7.5}]
},
"conflicts": [
{"field":"severities","reason":"disagreement","values":["7.5","9.8"]}
],
"provenance": {
"observationHashes": ["..."],
"toolVersion": "lnm-1.0"
},
"createdAt": "2025-11-20T00:00:00Z"
}
```
- Sorting: observations sorted by `source, advisoryId, fetchedAt` before hashing; response preserves that order.
- Caching: when cache hit, return cached document; when miss, rebuild, write cache, then return.
## Console rendering contract
- Fields to surface:
- `normalized.purls` (list) and `normalized.versions`
- `conflicts` if non-empty: show field + reason text; keep order as returned.
- `provenance.observationHashes` as “evidence anchors” (list); do not prettify.
- Tenant header required; no cross-tenant leakage. Scope `concelier:lnm.read`.
## Error handling
- 404 when linkset missing for advisory/source.
- 409 when tenant header missing/invalid.
- Deterministic error body: `{ "error": "<code>", "message": "..." }`.
## Telemetry (reuse existing meters)
- Increment `lnm.cache.hit_total` / `lnm.cache.write_total` as defined in cache plan.
- Log template on returns: `lnm_console_success tenant={Tenant} advisoryId={AdvisoryId} source={Source} cached={Cached}`.
## Owners
- Concelier Console Guild (primary)
- Concelier Core Guild (review)
This document is authoritative for CONCELIER-CONSOLE-23-001..003 in Sprint 110.

View File

@@ -0,0 +1,33 @@
# Concelier LNM Cache Plan (Sprint 110)
Purpose: finalize structured caching fields now that Link-Not-Merge (LNM) schema is frozen (2025-11-17) and Evidence Locker contract is published.
## Cache payload shape
- Source: `advisory_linksets` collection (see `docs/modules/concelier/link-not-merge-schema.md`).
- Cache entry key: `{tenant}:{advisoryId}:{source}`.
- Cached fields (deterministic order):
- `observations` (ObjectId list, already sorted by source, advisoryId, fetchedAt)
- `normalized.purls`, `normalized.versions`, `normalized.ranges`, `normalized.severities`
- `conflicts` array (field, reason, values)
- `provenance.observationHashes`
- `builtByJobId`, `createdAt`
- Exclude mutable/derived fields; cache is rebuilt on ingestion replay, not updated in place.
## Storage & eviction
- Collection: `advisory_linkset_cache` (per-tenant index `{tenantId:1, advisoryId:1, source:1}` unique).
- Eviction: TTL on `createdAt` disabled by default; cache is replaced when a newer `provenance.observationHashes` differs.
- Determinism: cache documents written via canonical JSON writer (sorted keys); timestamps UTC.
## API exposure
- WebService: surface cached linksets via existing `/v1/lnm/linksets/{advisoryId}?source=...` (read-through); if cache miss, rebuild synchronously and store.
- Console: may rely on this cache for Advisory AI surfaces; no new payload fields required.
## Telemetry
- Meter `StellaOps.Concelier.Linksets` (existing) to add counters: `lnm.cache.write_total{result}`, `lnm.cache.hit_total{source}`; histogram `lnm.cache.rebuild_ms` for synchronous rebuilds. (To be wired in subsequent sprint.)
## Alignment
- Schema source of truth: `docs/modules/concelier/link-not-merge-schema.md` (frozen v1).
- Evidence Locker contract: `docs/modules/evidence-locker/attestation-contract.md` informs provenance fields; no shape changes required.
## Ownership
- Concelier Core + WebService guilds.

View File

@@ -0,0 +1,20 @@
# Concelier AirGap Prep — PREP-CONCELIER-AIRGAP-56-001..58-001
Status: Draft (2025-11-20)
Owners: Concelier Core · AirGap Guilds
Scope: Capture mirror bundle/staleness requirements for Concelier ingestion under sealed mode.
## Dependencies
- Mirror thin bundle milestones (bundle_id, provenance, staleness_budget) from Mirror sprint 56-001.
- AirGap controller staleness/time anchor fields.
## Needed contract
- Ingestion must accept `bundle_id`, `provenance`, `staleness_seconds_remaining` on advisory/linkset endpoints.
- Reject non-mirror sources when sealed; surface `AIRGAP_EGRESS_BLOCKED` per Concelier AirGap response contract.
## Open decisions
- Exact header names for bundle/staleness metadata.
- Whether to cache bundle provenance per tenant.
## Handoff
Use as PREP artefact for 56-001..58-001 chain; update when mirror bundle schema and controller staleness fields are finalized.

View File

@@ -0,0 +1,16 @@
# Concelier Attestation Prep — PREP-CONCELIER-ATTEST-73-001/002
Status: Draft (2025-11-20)
Owners: Concelier Core · Evidence Locker Guild
Scope: Define attestation scope/signoff pending for Evidence Locker integration.
## Needs
- Evidence Locker attestation scope and DSSE profile.
- Endpoint contract for attestation verification of Concelier exports.
## Open decisions
- Signer identity and Rekor usage in sealed mode.
- What evidence hashes to include (bundle_id, merkle_root).
## Handoff
Use as PREP artefact; update once EvidenceLocker publishes scope and profile.

View File

@@ -0,0 +1,16 @@
# Concelier Console Schema Prep — PREP-CONCELIER-CONSOLE-23-001..003
Status: Draft (2025-11-20)
Owners: Concelier Console Guild
Scope: Provide schema samples for Console evidence bundles and identifiers.
## Needed artefacts
- Sample schema for console evidence bundle IDs and fields (linkset refs, advisory ids, staleness metadata).
- Example payloads for CONCELIER-CONSOLE-23-001..003.
## Open decisions
- ID format for console evidence bundle (ulid vs hash).
- Required fields for linkage to LNM outputs.
## Handoff
Use as PREP artefact; fill once LNM schema freeze and console bundle id rules are provided.

View File

@@ -0,0 +1,12 @@
# Feed Remediation Prep — PREP-FEEDCONN-ICSCISA-02-012 / KISA-02-008
Status: Draft (2025-11-20)
Owners: Concelier Feed Owners
Scope: Capture remediation plan for problematic feeds.
## Items to collect
- Current ingestion endpoints and auth for ICSCISA-02-012, KISA-02-008.
- Known issues and required remediation steps (validation fixes, throttling, schema tweaks).
## Handoff
Use as PREP artefact; fill with concrete remediation steps once feed owners provide details.

View File

@@ -0,0 +1,42 @@
# Concelier PREP Notes — 2025-11-20
Owner: Concelier Core Guild · Scheduler Guild · Data Science Guild
Scope: Provide traceable prep outputs for PREP-CONCELIER-GRAPH-21-002-PLATFORM-EVENTS-S and PREP-CONCELIER-LNM-21-002-WAITING-ON-FINALIZE so downstream tasks can proceed without blocking on missing contracts.
## 1) `sbom.observation.updated` platform event (Graph-21-002)
- Goal: publish deterministic, facts-only observation updates for graph overlays; no derived judgments.
- Proposed envelope (draft for Scheduler/Platform Events review):
- `event_type`: `sbom.observation.updated`
- `tenant_id` (string, required)
- `advisory_ids` (array of strings; upstream IDs as-ingested)
- `observation_ids` (array of stable per-observation IDs emitted by LNM storage)
- `source` (string; advisory source slug)
- `version_range` (string; original upstream semantics)
- `occurred_at` (ISO-8601 UTC, produced by Concelier at write time; deterministic)
- `trace` (object; optional provenance pointers, DSSE envelope digest with alg/id fields)
- Delivery and wiring expectations:
- Publisher lives in `StellaOps.Concelier.Core` after linkset/observation persistence.
- Scheduler binding: NATS/Redis topic `concelier.sbom.observation.updated`; ack + idempotent replay friendly; max delivery once semantics via message ID = `<tenant>:<observation_id>::<digest>`.
- Telemetry: counter `concelier_events_observation_updated_total{tenant,source,result}`; log template includes `tenant`, `advisory_id`, `observation_id`, `event_id`.
- Offline posture: allow emitting into local bus, enqueue to file-backed spool when offline; retry with deterministic ordering by `(tenant, observation_id)`.
- Open questions to resolve in impl task:
- Final topic naming and DSSE requirement (optional vs required per deployment).
- Whether to include component alias list in the event payload or expect consumers to join via API.
## 2) LNM fixtures + precedence markers (LNM-21-002)
- Goal: unblock correlation pipelines and downstream linkset tasks by defining required fixture shape and precedence rules.
- Fixture requirements (additive to frozen LNM v1 schema):
- Provide at least three sources with conflicting severity/CVSS to exercise conflict markers.
- Include overlapping version ranges to validate precedence tie-breakers.
- Each fixture must include `provenance` (source, fetch_time, collector) and `confidence` hints.
- Precedence rule proposal for review:
1. Prefer explicit source ranking table (to be agreed) over recency.
2. If ranking ties, prefer narrower version ranges, then higher confidence, then stable lexical order of `(source, advisory_id)`.
3. Never collapse conflicting fields; emit `conflicts[]` entries with reason codes `severity-disagree`, `cvss-disagree`, `reference-disagree`.
- Delivery path for fixtures once agreed: `src/Concelier/seed-data/lnm/v1/fixtures/*.json` with deterministic ordering; wire into `StellaOps.Concelier.Core.Tests` harness.
- Next actions captured for implementation task:
- Confirm ranking table and conflict reason code list with Cartographer/Data Science.
- Drop initial fixtures into the above path and reference them from the implementation tasks tests.
## Handoff
- This document is the published prep artefact requested by PREP-CONCELIER-GRAPH-21-002-PLATFORM-EVENTS-S and PREP-CONCELIER-LNM-21-002-WAITING-ON-FINALIZE. Downstream tasks should cite this file until the final schemas/fixtures are merged.

View File

@@ -0,0 +1,44 @@
# Concelier Web AirGap Prep — PREP-CONCELIER-WEB-AIRGAP-57-001
Status: Draft (2025-11-20)
Owners: Concelier WebService Guild · AirGap Policy Guild
Scope: Define remediation payloads and staleness plumbing for sealed-mode violations, dependent on WEB-AIRGAP-56-002.
## Dependencies
- WEB-AIRGAP-56-001: mirror bundle registration + sealed-mode enforcement.
- WEB-AIRGAP-56-002: staleness + bundle provenance metadata surfaces.
- AirGap controller scopes (seal/unseal) and time anchor semantics from AirGap Controller/Time guilds.
## Proposed payload mapping (EGRESS blocked)
- Error code: `AIRGAP_EGRESS_BLOCKED`.
- Shape:
```json
{
"error": "AIRGAP_EGRESS_BLOCKED",
"message": "Direct internet fetches disabled in sealed mode; use mirror bundle sources only.",
"bundle_required": true,
"staleness_seconds": 0,
"remediation": [
"Import mirror bundle via /airgap/import or offline kit",
"Ensure sealed mode is set with valid time anchor",
"Retry with cached/mirrored sources enabled"
]
}
```
- Determinism: fixed ordering of fields, remediation list sorted.
## Staleness surfacing
- Staleness derived from bundle metadata supplied by 56-002 (`bundle_id`, `provenance`, `staleness_budget_seconds`).
- Responses include `staleness_seconds_remaining` and `bundle_id` when available.
## Observability
- Emit timeline event `concelier.airgap.egress_blocked` with `{tenant_id, bundle_id?, endpoint, request_id}`.
- Metric: `concelier_airgap_egress_blocked_total` (counter) tagged by endpoint.
## Open decisions
- Final error envelope format (depends on WEB-OAS-61-002 standard envelope).
- Exact header name for staleness metadata (suggest `x-concelier-bundle-staleness`).
- Whether to include advisory key/linkset ids in the blocked response.
## Handoff
Use this as the PREP artefact for WEB-AIRGAP-57-001. Update once 56-002 and error envelope standard are finalized.

View File

@@ -0,0 +1,43 @@
# Evidence Locker Attestation Contract (v1 · frozen 2025-11-20)
Scope: Evidence Bundle v1 produced by Evidence Locker and consumed by Concelier, Excititor, Export Center, CLI, and Policy Engine.
## Predicates & subjects
- **Subject**: OCI manifest digest (`sha256:<digest>`) of the bundle, plus optional replay pack digest.
- **Predicates (DSSE/In-Toto)**
- `stellaops.evidence.bundle.v1`: declares bundle layout (manifests, CAS paths, replay log offsets).
- `stellaops.evidence.transparency.v1`: optional Rekor log inclusion proof (UUID, log index, root hash at inclusion).
- `stellaops.evidence.integrity.v1`: hashes for each payload (SBOMs, VEX, policy packs, telemetry snapshots), keyed by logical path.
## Required claim set
- `bundle_id` (UUID v4)
- `produced_at` (UTC ISO-8601)
- `producer` (`evidence-locker:<region>`)
- `subject_digest` (OCI digest string)
- `hashes` (map: logical path → sha256)
- `sbom` (array of SPDX/CycloneDX digests and mediaTypes)
- `vex` (array of VEX doc digests and schema versions)
- `replay_manifest` (optional; digest + sequence number)
- `transparency` (optional; Rekor UUID, logIndex, rootHash)
- `signing_profile` (`sovereign-default` | `fips` | `gost` | `pq-experimental`)
## Bundling & signing rules
- DSSE envelope using the modules configured crypto provider; keys must be short-lived (<24h) and recorded in provider registry.
- Hash list and subject digest MUST match the on-disk CAS objects; deterministic sort by logical path.
- Rekor entry is optional; when absent, set `transparency=null` and add `transparency_reason="offline"` to provenance note.
## Verification plan
- Verify DSSE signature against provider registry (per profile) and check key expiry.
- Recompute sha256 for every CAS object; fail if any mismatch.
- If `transparency` present, verify inclusion proof against bundled Rekor root; fail closed on mismatch.
- Emit verification report JSON and store beside bundle as `verify.json` (deterministic key order).
## Fixtures
- Sample bundle + report: `docs/samples/evidence-locker/bundle-v1-sample.tar.gz` (sha256 TBD at publish time).
- Sample attestation envelope: `docs/samples/evidence-locker/attestation-v1-sample.json`.
## Ownership
- Primary: Evidence Locker Guild.
- Reviewers: Concelier Core Guild, Excititor Guild, Export Center Guild, Policy Guild.
This contract is authoritative for Sprint 110 and blocks CONCELIER-ATTEST-73-001/002 and EXCITITOR-ATTEST-01-003/73-001/73-002.

View File

@@ -0,0 +1,21 @@
# ICryptoProviderRegistry Prep — PREP-EVID-CRYPTO-90-001 (Draft)
Status: Draft (2025-11-20)
Owners: Evidence Locker Guild · Security Guild
Scope: Capture requirements for crypto provider registry readiness to support sovereign/region-specific profiles.
## Required capabilities
- Registry interface to resolve crypto providers by profile ID (e.g., `default`, `ru-offline`, `fips140`, `eidass`).
- Provider metadata: `{algorithms[], key_formats[], offline_supported, hsm_supported, oq_ready}`.
- Deterministic selection rules: prefer tenant-scoped overrides, fall back to platform defaults; no network fetch.
## Integration points
- Evidence Locker signing pipeline to request provider by profile when sealing bundles.
- Replay validation to know which algorithms/hashes are acceptable for DSSE verification.
## Dependencies
- Final list of sovereign profiles from Security Guild.
- Key storage/backing (KMS/HSM) availability per profile.
## Handoff
Use this as the prep artefact for PREP-EVID-CRYPTO-90-001; update once profile list and key storage rules are confirmed.

View File

@@ -0,0 +1,42 @@
# Replay Payload Contract (Draft) — PREP-EVID-REPLAY-187-001
Status: Draft (2025-11-20)
Owners: Evidence Locker Guild · Scanner Guild · CLI Guild
Scope: Capture expected scanner record payloads needed by Evidence Locker replay APIs.
## 1) Payload envelope
- Content type: `application/vnd.stella.replay.record+json;version=1`.
- Fields:
- `record_id` (ULID, assigned by Scanner).
- `tenant_id` (string).
- `source` (enum): `scanner`, `attestor`, `cli`.
- `digest` (hex): SHA-256 of canonical payload bytes.
- `created_at` (RFC3339 UTC).
- `schema_version`: `replay.record.v1`.
## 2) Scanner record body (expected from Sprint 0186)
- `image_digest` (string, required).
- `sbom_digest` (string, optional) with SBOM pointer.
- `observations` (array) of `{type, component_purl?, location, evidence, confidence}`.
- `signals` (array) for runtime/static signals with `{name, value, units?, confidence}`.
- `attestations` (array) of DSSE statement references `{type, uri, sha256}`.
- `provenance` (object): `{scanner_version, policy_profile, worker_id}`.
## 3) Evidence Locker ingestion contract
- API: `POST /replay/records` (internal) accepting NDJSON stream (`record_envelope + body`).
- Validation:
- hash must match `digest` supplied; timestamps UTC.
- tenant_id must match auth principal or delegated token.
- schema_version must equal `replay.record.v1` until upgraded.
- Storage layout proposal: bucket prefix `replay/records/{tenant_id}/{record_id}.ndjson`, immutable; metadata indexed in Mongo with `{record_id, image_digest, created_at}`.
## 4) Open dependencies
- Scanner team to freeze exact `observations` and `signals` schema in Sprint 0186.
- Need DSSE profile for `attestations` (Authority/Attestor alignment).
- CLI replay commands depend on finalized pointer format to retrieve records.
## 5) Next actions
- Once Sprint 0186 publishes sample payloads, update this doc with enumerated observation/signal types and add JSON schema file under `docs/modules/evidence-locker/schemas/replay-record-v1.json`.
## 6) Handoff
Reference this document from sprint trackers for PREP-EVID-REPLAY-187-001 and related CLI/Attestor PREP tasks. Update when upstream payloads are available.

View File

@@ -0,0 +1,23 @@
# Validate Bundle Prep — PREP-VALIDATE-BUNDLE-187-005 (Draft)
Status: Draft (2025-11-20)
Owners: QA Guild · CLI Guild · Docs Guild
Scope: Define validation steps for replay bundles once schemas freeze.
## Validation checklist (proposed)
- Verify archive hash vs manifest `bundle.manifest.json` (`sha256`).
- Verify DSSE signature (if present) against trusted keys.
- Recompute Merkle root of bundle file tree; compare to manifest.
- Schema validation: replay records conform to `replay.record.v1`; policy export bundle conforms to `policy.export.console.v1` when included.
- Determinism: run `stella replay` twice on same bundle and assert identical outputs (hash comparison).
## Fixtures/tests
- Place golden bundles under `tests/EvidenceLocker/Fixtures/replay/` with expected hashes and DSSE signatures.
- CLI validation test: `stella verify --bundle <fixture>` returns exit code 0 and prints `verified: true`.
## Open dependencies
- Final schemas from Evidence Locker and Policy export contracts.
- Trust root list for DSSE verification (Authority decision).
## Handoff
Use this prep doc for PREP-VALIDATE-BUNDLE-187-005; expand with concrete fixtures once schemas are frozen.

View File

@@ -608,12 +608,14 @@ excititor:
### 9.1 WebService endpoints
With storage configured, the WebService exposes the following ingress and diagnostic APIs:
With storage configured, the WebService exposes the following ingress and diagnostic APIs (deterministic ordering, offline-friendly):
* `GET /excititor/status` returns the active storage configuration and registered artifact stores.
* `GET /excititor/health` simple liveness probe.
* `POST /excititor/statements` accepts normalized VEX statements and persists them via `IVexClaimStore`; use this for migrations/backfills.
* `GET /excititor/statements/{vulnId}/{productKey}?since=` returns the immutable statement log for a vulnerability/product pair.
* `POST /vex/evidence/chunks` submits aggregation-only chunks (OpenAPI: `schemas/vex-chunk-api.yaml`); responds with deterministic `chunk_digest` and queue id. Telemetry published under meter `StellaOps.Excititor.Chunks` (see Operations).
* `POST /v1/attestations/verify` verifies Evidence Locker attestations for exports/chunks using `IVexAttestationVerifier`; returns `{ valid, diagnostics }` (deterministic key order). Aligns with Evidence Locker contract v1.
* `POST /excititor/resolve` requires `vex.read` scope; accepts up to 256 `(vulnId, productKey)` pairs via `productKeys` or `purls` and returns deterministic consensus results, decision telemetry, and a signed envelope (`artifact` digest, optional signer signature, optional attestation metadata + DSSE envelope). Returns **409 Conflict** when the requested `policyRevisionId` mismatches the active snapshot.
Run the ingestion endpoint once after applying migration `20251019-consensus-signals-statements` to repopulate historical statements with the new severity/KEV/EPSS signal fields.

View File

@@ -0,0 +1,43 @@
# Excititor Attestation Plan (Sprint 110)
## Goals
- Align Excititor chunk API and attestation envelopes with Evidence Locker contract.
- Provide offline-ready chunk submission/attestation flow for VEX evidence.
## Chunk API shape (`/vex/evidence/chunks`)
- POST body (NDJSON, deterministic order by `chunk_id`):
```json
{
"chunk_id": "uuid",
"tenant": "acme",
"source": "ghsa",
"schema": "stellaops.vex.chunk.v1",
"items": [ {"advisory_id":"GHSA-123","status":"affected","purl":"pkg:npm/foo@1.0.0"} ],
"provenance": {"fetched_at":"2025-11-20T00:00:00Z","artifact_sha":"abc"}
}
```
- At submission, Excititor returns `chunk_digest` (sha256 of canonical JSON) and queue id.
## Attestation envelope
- Subject: `chunk_digest` from above.
- Predicates attached:
- `stellaops.vex.chunk.meta.v1` (tenant, source, schema version, item count).
- `stellaops.vex.chunk.integrity.v1` (sha256 per item block, canonical order).
- Optional `stellaops.transparency.v1` (Rekor UUID/logIndex) when online.
- Envelope format: DSSE using Evidence Locker provider registry; signing profile mirrors Evidence Locker bundle profile for tenant.
## DSSE bundling rules
- Deterministic JSON (sorted keys) before hashing.
- Canonical NDJSON for chunk payload; no gzip inside envelope.
- Attach verification report alongside attestation as `chunk-verify.json` (hashes + signature check results).
## Sample payloads
- `docs/samples/excititor/chunk-sample.ndjson`
- `docs/samples/excititor/chunk-attestation-sample.json`
## Integration points
- Evidence Locker contract v1 (see `docs/modules/evidence-locker/attestation-contract.md`).
- Concelier LNM schemas (observations remain aggregation-only; attestation is evidence, not merge).
## Ownership
- Excititor Guild (primary); Evidence Locker Guild reviewer.

View File

@@ -0,0 +1,36 @@
# Connector signer metadata (v1.0.0)
**Scope.** Defines the canonical, offline-friendly metadata for Excititor connectors that validate signed feeds (MSRC CSAF, Oracle OVAL, Ubuntu OVAL, StellaOps mirror OpenVEX). The file is consumed by WebService/Worker composition roots and by Offline Kits to pin trust material deterministically.
**Location & format.**
- Schema: `docs/modules/excititor/schemas/connector-signer-metadata.schema.json` (JSON Schema 202012).
- Sample: `docs/samples/excititor/connector-signer-metadata-sample.json` (aligns with schema).
- Expected production artifact: NDJSON or JSON stamped per release; store in offline kits alongside connector bundles.
## Required fields (summary)
- `schemaVersion` — must be `1.0.0`.
- `generatedAt` — ISO-8601 UTC timestamp for the metadata file.
- `connectors[]` — one entry per connector:
- `connectorId` — stable slug, e.g., `excititor-msrc-csaf`.
- `provider { name, slug }` — human label and slug.
- `issuerTier``tier-0`, `tier-1`, `tier-2`, or `untrusted` (aligns with trust weighting).
- `signers[]` — one per signing path; each has `usage` (`csaf|oval|openvex|bulk-meta|attestation`) and `fingerprints[]` (algorithm + format + value). Optional `keyLocator` and `certificateChain` for offline key retrieval.
- `bundle` — reference to the sealed bundle containing the feed/signing material (`kind`: `oci-referrer|oci-tag|file|tuf`, plus `uri`, optional `digest`, `publishedAt`).
- Optional `validFrom`, `validTo`, `revoked`, `notes` for rollover and incident handling.
## Rollover / migration guidance
1) **Author the metadata** using the schema and place the JSON next to connector bundles in the offline kit (`out/connectors/<provider>/signer-metadata.json`).
2) **Validate** with `dotnet tool run njsonschema validate connector-signer-metadata.schema.json connector-signer-metadata.json` (or `ajv validate`).
3) **Wire connector code** to load the file on startup (Worker + WebService) and pin signers per `connectorId`; reject feeds whose fingerprints are absent or marked `revoked=true` or out of `validFrom/To` range.
- Connectors look for `STELLAOPS_CONNECTOR_SIGNER_METADATA_PATH` (absolute/relative) and enrich provenance metadata automatically when present.
4) **Rollover keys** by appending a new `signers` entry and setting a future `validFrom`; keep the previous signer until all mirrors have caught up. Use `issuerTier` downgrades to quarantine while keeping history.
5) **Mirror references**: store the referenced bundles/keys under OCI tags or TUF targets already shipped in the offline kit so no live network is required.
6) **Record decisions** in sprint Decisions & Risks when changing trust tiers or fingerpints; update this doc if formats change.
## Sample entries (non-production)
See `docs/samples/excititor/connector-signer-metadata-sample.json` for MSRC, Oracle, Ubuntu, and StellaOps example entries. These fingerprints are illustrative only; replace with real values before shipping.
## Consumer expectations
- Deterministic: sort connectors alphabetically before persistence; avoid clock-based defaults.
- Offline-first: all `keyLocator`/`bundle.uri` values must resolve inside the air-gap kit (OCI/TUF/file).
- Observability: emit a structured warning when metadata is missing or stale (>7 days) and fail closed for missing signers.

View File

@@ -0,0 +1,24 @@
# Using the Chunk API
Endpoint: `POST /vex/evidence/chunks`
- Content-Type: `application/x-ndjson`
- See schema: `docs/modules/excititor/schemas/vex-chunk-api.yaml`
Response: `202 Accepted`
```json
{ "chunk_digest": "sha256:…", "queue_id": "uuid" }
```
Operational notes
- Deterministic hashing: server recomputes `chunk_digest` from canonical JSON; mismatches return 400.
- Limits: default 500 items, max 2000 (aligned with Program.cs guard).
- Telemetry: metrics under `StellaOps.Excititor.Chunks` (see chunk-telemetry.md).
- Headers: correlation/trace headers echoed (`X-Stella-TraceId`, `X-Stella-CorrelationId`).
Example curl
```bash
curl -X POST https://excitor.local/vex/evidence/chunks \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/x-ndjson" \
--data-binary @docs/samples/excititor/chunk-sample.ndjson
```

View File

@@ -0,0 +1,26 @@
# Excititor Chunk Telemetry (Sprint 110)
## Metrics (Meter: `StellaOps.Excititor.Chunks`)
- `vex_chunks_ingested_total` (counter) — tags: `tenant`, `source`, `status` (`accepted|rejected`), `reason` (nullable for accepted). Increments per chunk submitted.
- `vex_chunks_item_count` (histogram, unit=items) — records item count per chunk.
- `vex_chunks_payload_bytes` (histogram, unit=bytes) — measured from NDJSON payload length.
- `vex_chunks_latency_ms` (histogram) — end-to-end ingestion latency per request.
## Logs
- `vex.chunk.ingest.accepted` — includes `chunk_id`, `tenant`, `source`, `item_count`, `chunk_digest`.
- `vex.chunk.ingest.rejected` — includes `chunk_id`, `tenant`, `source`, `reason`, validation errors (summarized).
## Wiring steps
1. Register `ChunkTelemetry` as singleton with shared `Meter` instance.
2. In `/vex/evidence/chunks` handler, compute `chunk_digest` deterministically from canonical JSON and emit counters/histograms via `ChunkTelemetry`.
3. Log using structured templates above; avoid request bodies in logs.
4. Expose metrics via default ASP.NET metrics export (Prometheus/OpenTelemetry) already configured in WebService.
## Determinism & offline posture
- Do not include host-specific paths or timestamps in metric dimensions.
- Histogram buckets: use standard OTEL defaults; no runtime-generated buckets.
- Keep meter name stable; adding new instruments requires version note in sprint Decisions & Risks.
## Ownership
- Implementer: Excititor Observability Guild
- Reviewers: Evidence Locker Guild (for parity with attestation metrics)

View File

@@ -0,0 +1,125 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://stellaops.dev/schemas/excititor/connector-signer-metadata.schema.json",
"title": "Excititor Connector Signer Metadata",
"type": "object",
"additionalProperties": false,
"required": ["schemaVersion", "generatedAt", "connectors"],
"properties": {
"schemaVersion": {
"type": "string",
"pattern": "^1\\.0\\.0$"
},
"generatedAt": {
"type": "string",
"format": "date-time"
},
"connectors": {
"type": "array",
"minItems": 1,
"items": {
"$ref": "#/$defs/connector"
}
}
},
"$defs": {
"connector": {
"type": "object",
"additionalProperties": false,
"required": [
"connectorId",
"provider",
"issuerTier",
"signers"
],
"properties": {
"connectorId": {
"type": "string",
"pattern": "^[a-z0-9:-\\.]+$"
},
"provider": {
"type": "object",
"additionalProperties": false,
"required": ["name", "slug"],
"properties": {
"name": { "type": "string", "minLength": 3 },
"slug": { "type": "string", "pattern": "^[a-z0-9-]+$" }
}
},
"issuerTier": {
"type": "string",
"enum": ["tier-0", "tier-1", "tier-2", "untrusted"]
},
"signers": {
"type": "array",
"minItems": 1,
"items": { "$ref": "#/$defs/signer" }
},
"bundle": { "$ref": "#/$defs/bundleRef" },
"validFrom": { "type": "string", "format": "date" },
"validTo": { "type": "string", "format": "date" },
"revoked": { "type": "boolean", "default": false },
"notes": { "type": "string", "maxLength": 2000 }
}
},
"signer": {
"type": "object",
"additionalProperties": false,
"required": ["usage", "fingerprints"],
"properties": {
"usage": {
"type": "string",
"enum": ["csaf", "oval", "openvex", "bulk-meta", "attestation"]
},
"fingerprints": {
"type": "array",
"minItems": 1,
"items": { "$ref": "#/$defs/fingerprint" }
},
"keyLocator": {
"type": "string",
"description": "Path or URL (mirror/OCI/TUF) where the signing key or certificate chain can be retrieved in offline kits."
},
"certificateChain": {
"type": "array",
"items": { "type": "string" },
"description": "Optional PEM-encoded certificates for x509/cosign keys."
}
}
},
"fingerprint": {
"type": "object",
"additionalProperties": false,
"required": ["alg", "value"],
"properties": {
"alg": {
"type": "string",
"enum": ["sha256", "sha512", "sha1"]
},
"format": {
"type": "string",
"enum": ["pgp", "x509-spki", "x509-ski", "cosign", "pem"]
},
"value": {
"type": "string",
"minLength": 16,
"maxLength": 128
}
}
},
"bundleRef": {
"type": "object",
"additionalProperties": false,
"required": ["kind", "uri"],
"properties": {
"kind": {
"type": "string",
"enum": ["oci-referrer", "oci-tag", "file", "tuf"]
},
"uri": { "type": "string", "minLength": 8 },
"digest": { "type": "string", "minLength": 32 },
"publishedAt": { "type": "string", "format": "date-time" }
}
}
}
}

View File

@@ -0,0 +1,82 @@
openapi: 3.1.0
info:
title: StellaOps Excititor Chunk API
version: "0.1.0"
description: |
Frozen for Sprint 110 (EXCITITOR-AIAI-31-002). Aligns with Evidence Locker attestation contract v1.
servers:
- url: https://excitor.local
paths:
/vex/evidence/chunks:
post:
summary: Submit VEX evidence chunk (aggregation-only)
requestBody:
required: true
content:
application/x-ndjson:
schema:
$ref: '#/components/schemas/VexChunk'
responses:
'202':
description: Accepted for processing
content:
application/json:
schema:
type: object
required: [chunk_digest, queue_id]
properties:
chunk_digest:
type: string
description: sha256 of canonical chunk JSON
queue_id:
type: string
description: Background job identifier
'400':
description: Validation error
components:
schemas:
VexChunk:
type: object
required: [chunk_id, tenant, source, schema, items, provenance]
properties:
chunk_id:
type: string
format: uuid
tenant:
type: string
source:
type: string
description: feed id (e.g., ghsa, nvd)
schema:
type: string
enum: [stellaops.vex.chunk.v1]
items:
type: array
items:
type: object
required: [advisory_id, status, purl]
properties:
advisory_id:
type: string
status:
type: string
enum: [affected, unaffected, under_investigation, fixed, unknown]
purl:
type: string
justification:
type: string
last_observed:
type: string
format: date-time
provenance:
type: object
required: [fetched_at, artifact_sha]
properties:
fetched_at:
type: string
format: date-time
artifact_sha:
type: string
signature:
type: object
nullable: true

View File

@@ -0,0 +1,17 @@
# Export Crypto Prep — PREP-EXPORT-CRYPTO-90-001
Status: Draft (2025-11-20)
Owners: Exporter Service · Security Guild
Scope: Capture crypto requirements pending Nov-18 review and reference implementation.
## Needs
- Mapping of signing/encryption algorithms per export profile.
- Integration with `ICryptoProviderRegistry` (same as Evidence Locker) for provider selection.
- Hashing defaults (sha256) and optional sha512/sha3 for high-assurance paths.
## Open decisions
- Final provider list and key storage (KMS/HSM) per profile.
- Whether to sign both manifest and per-artifact hashes.
## Handoff
Use as prep artefact for EXPORT-CRYPTO-90-001; fill once Security delivers profile list and reference implementation.

View File

@@ -0,0 +1,15 @@
# Exporter Service Blocker — PREP-EXPORTER-SERVICE-BLOCKED-WAITING-ON-EVID
Status: Draft (2025-11-20)
Owners: Planning
Scope: Document EvidenceLocker dependency blocking exporter service.
## Blocker
- EvidenceLocker spec not published; need replay/export bundle schemas and ICryptoProviderRegistry availability.
## What we need
- Bundle schema pointers (from EvidenceLocker) and retention rules.
- Sample payloads to mirror into exporter tests.
## Handoff
Use this note to track unblock; update when EvidenceLocker spec is available.

View File

@@ -0,0 +1,29 @@
# Export Notifications Schema Prep — PREP-EXPORT-NOTIFY-SCHEMA-OBS-52
Status: Draft (2025-11-20)
Owners: Notifications Guild · Exporter Service
Scope: Define notification envelope/payloads for export lifecycle events.
## Event types
- `export.started`, `export.completed`, `export.failed`.
## Envelope (proposed)
```json
{
"type": "export.completed",
"export_id": "...",
"profile_id": "...",
"tenant_id": "...",
"artifact_counts": {"json": 2, "mirror": 1},
"sha256": "...",
"created_at": "2025-11-20T00:00:00Z"
}
```
- Deterministic key ordering; timestamps UTC.
## Open decisions
- Channel/transport (NATS vs Redis streams vs webhooks).
- Required retry/backoff policy and DLQ routing.
## Handoff
Use this prep doc for PREP-EXPORT-NOTIFY-SCHEMA-OBS-52; update once transport + DLQ policy are chosen.

View File

@@ -0,0 +1,17 @@
# Export Telemetry Prep — PREP-EXPORT-OBS-50-001
Status: Draft (2025-11-20)
Owners: Exporter Service · Observability Guild
Scope: Define telemetry schema for exporter service bootstrap.
## Proposed metrics/logs
- Metrics (Prometheus/Otel): `export_runs_total{profile, tenant}`, `export_run_duration_seconds`, `export_artifacts_total{type}`, `export_failures_total`, `export_bytes_total`.
- Logs: structured with fields `{export_id, profile, tenant, artifact_type, status, duration_ms}`.
- Traces: span names `export.run`, `export.plan`, `export.write`; tags include `profile`, `tenant`, `artifact_count`.
## Open decisions
- Histogram buckets for duration/bytes.
- Required correlation IDs for downstream Console ingestion.
## Handoff
Use this as PREP artefact for EXPORT-OBS-50-001; update buckets and trace tags once Observability finalizes naming.

View File

@@ -0,0 +1,21 @@
# Export Risk Bundle Prep — PREP-EXPORT-RISK-69-001
Status: Draft (2025-11-20)
Owners: Exporter Service · Risk Bundle Export Guild
Scope: Capture provider selection rules and schema needs for risk bundle job handler.
## Provider selection (proposed)
- Inputs: `risk_profile_id`, `tenant_id`, `preferred_provider`, `fallback_provider`.
- Selection order: tenant override → profile default → system default.
- Providers must advertise capabilities `{formats[], signing_profiles[]}`.
## Manifest expectations
- Fields: `bundle_id`, `profile_id`, `provider_id`, `inputs_hash`, `created_at`, `artifacts[] {path, sha256, media_type}`.
- Deterministic ordering and sha256 for all artifacts.
## Open decisions
- Final list of providers and signing profiles.
- Whether to embed policy/export bundle pointers.
## Handoff
Use this as PREP artefact for EXPORT-RISK-69-001; update provider list and manifest once phase I artifacts land.

View File

@@ -0,0 +1,21 @@
# Export Service Bootstrap Prep — PREP-EXPORT-SVC-35-001
Status: Draft (2025-11-20)
Owners: Exporter Service
Scope: Capture phase I readiness for exporter service project/migrations.
## Project baseline
- Service: minimal API (net10.0), Postgres storage for `export_profiles`, `export_runs`, `export_inputs`, `export_distributions`.
- Tests: xUnit + integration harness with deterministic timestamps.
## Schema notes
- `export_profiles`: `{id, name, tenant_id?, config_json}`.
- `export_runs`: `{id, profile_id, tenant_id, status, started_at, completed_at, artifact_counts JSONB}`.
- Deterministic defaults: UTC timestamps; snake_case columns.
## Open decisions
- Final Postgres schema (indices, enums for status).
- Whether to store metrics snapshots inline or via observability pipeline.
## Handoff
Use this as PREP artefact for EXPORT-SVC-35-001; update once phase I readiness and synthetic telemetry feeds are defined.

View File

@@ -0,0 +1,20 @@
# Export Service Planner Prep — PREP-EXPORT-SVC-35-002
Status: Draft (2025-11-20)
Owners: Exporter Service
Scope: Planner + scope resolver for exports, depends on 35-001 bootstrap.
## Planner inputs
- `profile_id`, `tenant_id`, `inputs` (bundle pointers), `priority`.
- `limits`: max artifacts, max runtime.
## Outputs
- Plan document `{plan_id, profile_id, tenant_id, steps[], estimated_bytes, estimated_duration_ms}`.
- Steps sorted; deterministic hashing of plan.
## Open decisions
- Step types allowed (json adapters, mirror, manifest signing).
- How to surface rejection reasons to upstream services.
## Handoff
Use as prep artefact; update once 35-001 schema is fixed.

View File

@@ -0,0 +1,16 @@
# Export JSON Adapter Prep — PREP-EXPORT-SVC-35-003
Status: Draft (2025-11-20)
Owners: Exporter Service
Scope: JSON adapters (`json:raw`, `json:policy`) normalization/redaction/compression.
## Deliverable shape
- Adapter config: `{type, redactions[], compress: bool, normalize_paths: bool}`.
- Output manifest entry: `{path, sha256, media_type, original_size, compressed_size?}`.
## Open decisions
- Redaction rules list and ordering.
- Compression algorithm (gzip vs zstd) and level defaults.
## Handoff
Prep artefact for 35-003; align with plan model once 35-002 is fixed.

View File

@@ -0,0 +1,17 @@
# Export Mirror Adapter Prep — PREP-EXPORT-SVC-35-004
Status: Draft (2025-11-20)
Owners: Exporter Service
Scope: Mirror (full) adapter producing filesystem layout, indexes, manifests, README.
## Layout proposal
- root manifest `mirror.manifest.json` with Merkle root.
- Directories: `artifacts/`, `indexes/`, `docs/README.md`.
- Deterministic ordering, UTC timestamps.
## Open decisions
- Which indexes required (by profile vs dataset).
- Manifest fields alignment with Mirror thin bundle.
## Handoff
Use as prep artefact; fill fields once 35-003 outputs and mirror schema decisions are in.

View File

@@ -0,0 +1,16 @@
# Export Manifest/Signing Prep — PREP-EXPORT-SVC-35-005
Status: Draft (2025-11-20)
Owners: Exporter Service · Security Guild
Scope: Manifest/provenance writer + KMS signing/attestation.
## Proposed manifest
- `export_id`, `profile_id`, `tenant_id`, `artifacts[] {path, sha256, media_type}`, `created_at`, `inputs_hash`, `signatures[]`.
- DSSE envelope for manifest; signer from ICryptoProviderRegistry.
## Open decisions
- Signing profile list and KMS/HSM mapping.
- Rekor/Transparency use in offline vs online.
## Handoff
Prep artefact for 35-005; update once crypto profile and provider registry decisions land.

View File

@@ -0,0 +1,4 @@
# Findings Ledger
Start here for ledger docs.

View File

@@ -0,0 +1,70 @@
# Findings Ledger Export HTTP Surface
Prep task: PREP-LEDGER-EXPORT-35-001-NO-HTTP-API-SURFACE (Sprint 0121)
## Goals
- Publish an HTTP surface for deterministic, offline-friendly exports of Findings Ledger data (findings, VEX, advisories, SBOMs) so downstream SDK/OpenAPI tasks can proceed.
- Define filter contract, pagination, media types, and provenance fields required by Evidence Locker and Policy Engine consumers.
## Non-goals
- Implementing the endpoints (covered by LEDGER-EXPORT-35-001).
- Final OAS/SDK generation (tracked in PREP-LEDGER-OAS-61-001/002/62-001/63-001).
## Base Service
- Host: findings-ledger service (minimal API) under `src/Findings/StellaOps.Findings.Ledger`.
- Base path: `/ledger/export`.
- Auth: service-to-service bearer token; require `scope=ledger.export.read`.
- Tenancy: `X-Stella-Tenant` header (strictly required); responses never mix tenants.
- Determinism: server sorts by `(event_sequence, projection_version, cycle_hash)`; pagination tokens encode the last emitted tuple and filter set. No wall-clock dependence.
- Media types: default `application/x-ndjson`; clients may request `application/json` (array) for small result sets. Always emit `Content-Encoding: gzip` when `Accept-Encoding` allows.
## Endpoints
### 1) Findings
- `GET /ledger/export/findings`
- Filters (all optional unless noted):
- `shape` (required): `canonical` \| `compact` (controls payload shape; compact strips verbose provenance fields for air-gap bundles)
- `since_sequence` (long, ≥0), `until_sequence` (long, inclusive) — enables range slicing.
- `since_observed_at`, `until_observed_at` (ISO-8601 UTC) — observation window.
- `advisory_id` (repeatable), `component_purl` (repeatable), `finding_status` (`open|fixed|dismissed`), `severity` (`critical|high|medium|low|unknown`).
- `risk_profile_version` (string) — filters by attached risk profile revision.
- Response item (canonical shape):
- `finding_id`, `event_sequence`, `observed_at`, `component` (purl, version, source), `advisories` (ids, cwes), `status`, `severity`, `risk` (score, severity, profile_version, explanation_id), `projection_version`, `cycle_hash`, `evidence_bundle_ref` (digest, dsse_digest, timeline_ref), `provenance` (ledger_root, projector_version, policy_version, datasource_ids).
### 2) VEX
- `GET /ledger/export/vex`
- Filters: `shape`, `since_sequence/until_sequence`, `since_observed_at/until_observed_at`, `product_id` (repeatable), `advisory_id`, `status` (`affected|not_affected|under_investigation`), `statement_type` (`exploitation|justification`).
- Response item adds `vex_statement_id`, `product` (purl or CPE), `status_justification`, `known_exploited` (bool), `timestamp`, `projection_version`, `cycle_hash`, `provenance`.
### 3) Advisories
- `GET /ledger/export/advisories`
- Filters: `shape`, `since_sequence/until_sequence`, `severity`, `source` (feed id), `cwe_id`, `kev` (bool), `cvss_version`, `cvss_score_min`, `cvss_score_max`.
- Response item: `advisory_id`, `source`, `title`, `description`, `cwes`, `cvss` (version, vector, base_score), `published`, `modified`, `status`, `epss` (score, percentile), `projection_version`, `cycle_hash`, `provenance`.
### 4) SBOMs
- `GET /ledger/export/sboms`
- Filters: `shape`, `since_sequence/until_sequence`, `since_observed_at/until_observed_at`, `subject_digest` (OCI digest), `sbom_format` (`spdx-json` \| `cyclonedx-json`), `component_purl` (repeatable), `contains_native` (bool), `slsa_build_type` (string).
- Response item: `sbom_id`, `subject` (digest, media_type), `sbom_format`, `created_at`, `components_count`, `has_vulnerabilities` (bool), `materials` (digests), `projection_version`, `cycle_hash`, `provenance`.
## Pagination
- Cursor param: `page_token` (opaque base64url JSON: `{ "last": { "event_sequence": long, "projection_version": string, "cycle_hash": string }, "filters_hash": sha256 }`).
- Page size: `page_size` (default 500, max 5000). Server rejects if `page_size` differs across pages for same token.
- Response envelope (for both NDJSON and JSON array):
- Header `X-Stella-Next-Page-Token` when more data exists.
- Header `X-Stella-Result-Count` with items count.
- When `Prefer: return=minimal` is set, omit envelope body for NDJSON; clients rely on headers.
## Error Contract
- 400: unknown filter, invalid range, or filter combination mismatch with `filters_hash` inside `page_token`.
- 401/403: missing or insufficient scope.
- 409: requested `shape` not compatible with downstream air-gap mode (compact requested where policy mandates canonical).
- 429: enforcement of determinism guard (server detected projection drift vs cycle_hash); include `X-Stella-Drift-Reason`.
## Observability & Determinism Hooks
- Emit structured logs `ledger.export.request` and `ledger.export.emit` with tenant, endpoint, filters_hash, page_size, result_count, duration_ms.
- Counters: `ledger_export_items_total{endpoint,tenant}` and `ledger_export_failures_total{endpoint,reason}`.
- Traces: span name `ledger.export.{endpoint}`; attach `filters_hash`, `page_size`, `next_page_token_present` attributes.
## artefact location
- This document: `docs/modules/findings-ledger/export-http-surface.md` (hash stability: keep deterministic ordering as authored on 2025-11-20).
- Link from sprint 0121 PREP-LEDGER-EXPORT-35-001; downstream tasks should reference this path for contract details.

View File

@@ -0,0 +1,28 @@
# Findings Ledger OAS baseline (v1)
**Scope.** Establish the canonical OpenAPI baseline and API host definitions for Findings Ledger. This satisfies PREP-LEDGER-OAS-61-001 and unblocks downstream OAS/SDK/OBS tasks (61-002..63-001).
**What shipped (2025-11-20).**
- Published baseline OAS document: `docs/modules/findings-ledger/openapi/findings-ledger.v1.yaml` (OpenAPI 3.0.3).
- Servers: `https://{env}.ledger.api.stellaops.local` (env ∈ dev/staging/prod/airgap) and offline `https://ledger.{region}.offline.bundle`.
- Security: `bearerAuth` (JWT) and `mTLS` declared; tenant header `X-Stella-Tenant` required.
- Paths included:
- `GET /v1/ledger/events` (deterministic paging by chain/sequence; cursor header).
- `POST /v1/ledger/events` (append; validates hashes; 409 on non-deterministic input).
- `GET /v1/ledger/projections/findings` (projection read with `cycleHash`).
- Schemas align with `docs/modules/findings-ledger/schema.md` (ledger events, projections, hashes, provenance fields).
**Usage / next steps.**
- Export to renderer or client generation from `findings-ledger.v1.yaml`; keep schema source of truth in YAML, not code-first.
- Downstream tasks (61-002, 62-001, 63-001) should extend this spec with SDK/validation/deprecation headers but **must not** change base paths, security schemes, or canonical field names.
- When new fields are added, update both `schema.md` and the YAML and bump `info.version` with changelog entry.
**Determinism & offline posture.**
- Stable ordering: events sorted by `(chainId, sequence)`; projections do not perform consensus/merges.
- No external calls required at runtime; offline host is declared for bundle deployments.
- Hash fields (`eventHash`, `previousHash`, `merkleLeafHash`, `cycleHash`) remain lowercase hex SHA-256 per schema.
**Artifact locations.**
- OAS YAML: `docs/modules/findings-ledger/openapi/findings-ledger.v1.yaml`
- Schema reference: `docs/modules/findings-ledger/schema.md`
- Export surface reference (for later OAS extensions): `docs/modules/findings-ledger/export-http-surface.md`

View File

@@ -0,0 +1,264 @@
openapi: 3.0.3
info:
title: StellaOps Findings Ledger API
version: 1.0.0-beta1
description: >-
Canonical, aggregation-only surface for append-only findings events, projections, and
Merkle anchoring metadata. Aligns with schema in docs/modules/findings-ledger/schema.md.
servers:
- url: https://{env}.ledger.api.stellaops.local
description: Default environment-scoped host
variables:
env:
default: prod
enum: [dev, staging, prod, airgap]
- url: https://ledger.{region}.offline.bundle
description: Offline bundle host for air-gapped deployments
variables:
region:
default: local
enum: [local]
security:
- bearerAuth: []
- mTLS: []
paths:
/v1/ledger/events:
get:
summary: List ledger events
operationId: listLedgerEvents
tags: [ledger]
parameters:
- $ref: '#/components/parameters/TenantId'
- name: chainId
in: query
required: false
schema:
type: string
format: uuid
- name: sinceSequence
in: query
schema:
type: integer
minimum: 0
- name: limit
in: query
schema:
type: integer
default: 200
maximum: 1000
responses:
'200':
description: Paged ledger events in deterministic order (chainId, sequence_No asc)
headers:
Req-Cursor:
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/LedgerEventPage'
post:
summary: Append deterministic ledger event
operationId: appendLedgerEvent
tags: [ledger]
parameters:
- $ref: '#/components/parameters/TenantId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/LedgerEventAppendRequest'
responses:
'201':
description: Event persisted
content:
application/json:
schema:
$ref: '#/components/schemas/LedgerEvent'
'409':
description: Hash/sequence conflict (non-deterministic input)
/v1/ledger/projections/findings:
get:
summary: Get latest projection for findings
operationId: listFindingProjections
tags: [projections]
parameters:
- $ref: '#/components/parameters/TenantId'
- name: findingId
in: query
schema:
type: string
- name: policyVersion
in: query
schema:
type: string
- name: status
in: query
schema:
type: string
- name: limit
in: query
schema:
type: integer
default: 200
maximum: 1000
responses:
'200':
description: Projection rows with cycleHash for replay validation
content:
application/json:
schema:
$ref: '#/components/schemas/FindingProjectionPage'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
mTLS:
type: mutualTLS
parameters:
TenantId:
name: X-Stella-Tenant
in: header
required: true
schema:
type: string
schemas:
LedgerEvent:
type: object
required: [event]
properties:
event:
type: object
required: [id, type, tenant, chainId, sequence, policyVersion, occurredAt, recordedAt, payload]
properties:
id:
type: string
format: uuid
type:
type: string
description: ledger_event_type (see schema.md §2.2)
tenant:
type: string
chainId:
type: string
format: uuid
sequence:
type: integer
policyVersion:
type: string
finding:
type: object
properties:
id: { type: string }
artifactId: { type: string }
vulnId: { type: string }
actor:
type: object
properties:
id: { type: string }
type: { type: string }
occurredAt:
type: string
format: date-time
recordedAt:
type: string
format: date-time
payload:
type: object
additionalProperties: true
evidenceBundleRef:
type: string
eventHash:
type: string
previousHash:
type: string
merkleLeafHash:
type: string
LedgerEventPage:
type: object
required: [items]
properties:
items:
type: array
items:
$ref: '#/components/schemas/LedgerEvent'
nextCursor:
type: string
LedgerEventAppendRequest:
type: object
required: [id, type, tenant, chainId, sequence, policyVersion, occurredAt, payload]
properties:
id:
type: string
format: uuid
type:
type: string
tenant:
type: string
chainId:
type: string
format: uuid
sequence:
type: integer
policyVersion:
type: string
finding:
type: object
properties:
id: { type: string }
artifactId: { type: string }
vulnId: { type: string }
actor:
type: object
properties:
id: { type: string }
type: { type: string }
occurredAt:
type: string
format: date-time
payload:
type: object
additionalProperties: true
evidenceBundleRef:
type: string
previousHash:
type: string
description: Optional; validated if supplied
merkleLeafHash:
type: string
description: Optional; server recomputes to validate determinism
FindingProjection:
type: object
required: [tenantId, findingId, policyVersion, status, cycleHash]
properties:
tenantId: { type: string }
findingId: { type: string }
policyVersion: { type: string }
status: { type: string }
severity:
type: number
format: double
labels:
type: object
additionalProperties: true
currentEventId:
type: string
format: uuid
cycleHash:
type: string
updatedAt:
type: string
format: date-time
FindingProjectionPage:
type: object
required: [items]
properties:
items:
type: array
items:
$ref: '#/components/schemas/FindingProjection'
nextCursor:
type: string

View File

@@ -0,0 +1,19 @@
# Ledger OAS Prep — PREP-LEDGER-OAS-61-001/61-002/62-001/63-001
Status: Draft (2025-11-20)
Owners: Findings Ledger Guild · API Contracts Guild · SDK Generator Guild
Scope: Capture OAS baseline, HTTP surface, SDK generation, and deprecation flow for ledger service.
## Whats needed
- Baseline OAS for ledger API host (61-001).
- Confirm endpoints and auth scopes to publish (61-002 depends on 61-001).
- SDK generation targets and language list (62-001).
- Deprecation header plan once SDK validated (63-001).
## Open decisions
- Hostname/versioning scheme for ledger API.
- Auth scopes per endpoint.
- Languages for SDK generation and package naming.
## Handoff
Use this prep doc for LEDGER-OAS-61-001/61-002/62-001/63-001; update once API contract is drafted.

View File

@@ -0,0 +1,12 @@
# Ledger Observability Prep — PREP-LEDGER-OBS-54-001
Status: Draft (2025-11-20)
Owners: Findings Ledger Guild · Provenance Guild
Scope: Minimal API surface for `/ledger/attestations` and observability hooks.
## Needs
- HTTP surface spec (routes, auth scopes) to host `/ledger/attestations`.
- Telemetry fields to include provenance IDs.
## Handoff
Use as PREP artefact; update once API contract is drafted.

View File

@@ -0,0 +1,9 @@
# Ledger Packs Snapshot Prep — PREP-LEDGER-PACKS-42-001
Status: Draft (2025-11-20)
Owners: Findings Ledger Guild · Mirror Creator Guild
Scope: Snapshot/time-travel contract for packs simulation.
## Needs
- Snapshot format and bundle layout for pack simulation/time-travel.

View File

@@ -0,0 +1,11 @@
# Ledger Risk Schema Prep — PREP-LEDGER-RISK-66-001/002
Status: Draft (2025-11-20)
Owners: Findings Ledger Guild · Risk Engine Guild
## Needs
- Risk engine schema/contract inputs: `risk_score`, `risk_severity`, `profile_version`, `explanation_id`, indexes.
- Migration plan to add fields.
## Handoff
Use as PREP artefact; update when risk field definitions and rollout plan are available.

View File

@@ -0,0 +1,17 @@
# Ledger Risk Prep — PREP-LEDGER-RISK-68-001 / 69-001 / TEN-48-001
Status: Draft (2025-11-20)
Owners: Findings Ledger Guild · Export Guild · Observability Guild · Platform
## 68-001 (scored findings export) needs
- Inputs from 67-001 + Export Center contract for scored findings.
- Metrics dimensions alignment with Observability.
## 69-001 (metrics) needs
- Final metrics fields driven by 67-001/68-001 outputs.
## TEN-48-001 (RLS/partitioning) needs
- Platform-approved tenant/project partitioning and RLS policy.
## Handoff
Use as PREP artefact for the above tasks; update when upstream exports and RLS decisions are available.

View File

@@ -0,0 +1,38 @@
# Ledger attestation HTTP surface (prep for LEDGER-OBS-54-001 / 55-001)
**Goal.** Provide the minimal HTTP contract to expose ledger attestation verifications so PREP-LEDGER-OBS-55-001 can proceed. This complements the OAS baseline (`docs/modules/findings-ledger/openapi/findings-ledger.v1.yaml`) and schema (`docs/modules/findings-ledger/schema.md`).
## Endpoint
- `GET /v1/ledger/attestations`
- Tenant header: `X-Stella-Tenant` (required).
- Auth: bearer `scope=ledger.attest.read` or mTLS.
- Query params:
- `artifactId` (string, optional; OCI digest or SBOM id)
- `findingId` (string, optional)
- `attestationId` (uuid, optional)
- `status` (`verified|failed|unknown`, optional)
- `sinceRecordedAt` / `untilRecordedAt` (ISO-8601 UTC)
- `limit` (int, default 200, max 1000)
- Ordering: deterministic by `recordedAt ASC, attestationId ASC`.
- Response: JSON array (or NDJSON when `Accept: application/x-ndjson`). Each item:
- `attestationId` (uuid)
- `artifactId` (string)
- `findingId` (string)
- `verificationStatus` (`verified|failed|unknown`)
- `verificationTime` (ISO-8601 UTC)
- `dsseDigest` (sha256)
- `rekorEntryId` (string, optional)
- `evidenceBundleRef` (string, optional)
- `ledgerEventId` (uuid) — source ledger event that linked the attestation
- `recordedAt` (ISO-8601 UTC)
- `merkleLeafHash` (sha256)
- `rootHash` (sha256)
## Determinism/offline posture
- Sorting keys are fixed; pagination token encodes `{recordedAt, attestationId, filtersHash}`.
- No live Rekor calls; `rekorEntryId` is stored reference only.
- Hashes remain lowercase SHA-256; times are UTC.
## Artefact location
- This prep doc: `docs/modules/findings-ledger/prep/ledger-attestations-http.md`.
- Add path to OAS in a follow-on increment (LEDGER-OAS-61-002/63-001) once approved.

View File

@@ -0,0 +1,26 @@
# Mirror Assembler Staffing & Milestones (Sprint 110.D)
## Staffing
- **Primary owner:** Alex Kim (Mirror Creator Guild)
- **Backup:** Priya Desai (Exporter Guild)
- **Observers:** AirGap Time Guild, CLI Guild
## Milestones
1. **M0 recap (done 2025-11-19):** thin bundle sample + layout note (`docs/modules/mirror/milestone-0-thin-bundle.md`).
2. **M1 (due 2025-11-26):** implement deterministic assembler with manifest + CAS layout; DSSE signing profile `sovereign-default`; produce sample bundle tarball + hash.
3. **M1.1 (due 2025-11-28):** TUF metadata generation (`root.json`, `snapshot.json`, `timestamp.json`) and mirror index manifest.
4. **M2 (due 2025-12-05):** integrate time-anchor metadata (AirGap Time), export automation hooks (Export Center), and CLI verification path.
## Responsibilities
- Alex Kim: assembler core, DSSE signing, CAS layout.
- Priya Desai: TUF metadata + exporter handoff.
- AirGap Time Guild: time-anchor schema + verification guidance.
- CLI Guild: `stella mirror verify` wiring and offline cache checks.
## Artefact locations
- Assembler design: `docs/modules/mirror/thin-bundle-assembler.md`
- Staffing/plan (this doc): `docs/modules/mirror/assembler.md`
- Sample bundles: `out/mirror/thin/mirror-thin-m0-sample.tar.gz` (future M1/M2 under `out/mirror/thin/`)
## Risks
- If M1 slips past 2025-11-26, Export Center and CLI tracks block; escalate to Exporter guild lead.

View File

@@ -0,0 +1,22 @@
# Mirror Thin Bundle Prep — PREP-MIRROR-CRT-56-001 (Draft)
Status: Draft (2025-11-20)
Owners: Mirror Guild (Assembler)
Scope: Capture requirements to start thin bundle v1 when upstream Sprint 110.D artefacts land.
## Dependencies
- Sprint 110.D assembler foundation (missing in repo).
- Trust root list and TUF metadata locations from release pipeline.
## Proposed thin bundle v1 shape
- Container: tar.gz deterministic; root manifest `mirror.thin.manifest.json`.
- Fields: `bundle_id`, `schema_version`=`mirror.thin.v1`, `created_at`, `source_registry`, `artifacts[] {digest, media_type, size}`, `trust_roots[]`, optional `attestations[]`.
- Merkle root over files for audit.
## Open decisions
- Exact artifact set included in “thin” scope (SBOM only vs SBOM+metadata).
- Required signatures (DSSE/Sigstore) and signer identities.
- Retention/GC policy for thin bundles.
## Handoff
Use this as the PREP artefact for PREP-MIRROR-CRT-56-001; update when assembler foundation drops so schema can be finalized and aligned with `docs/modules/mirror/thin-bundle-assembler.md`.

View File

@@ -0,0 +1,12 @@
# Orchestrator AirGap Prep — PREP-ORCH-AIRGAP-56-001
Status: Draft (2025-11-20)
Owners: Orchestrator Service Guild · AirGap Policy Guild
Scope: Awaiting AirGap readiness; capture sealed-mode contract needs for orchestrator.
## Needs
- Sealed-mode contract from AirGap controller (seal/unseal scopes, staleness fields).
- Mirror bundle pointers to include with orchestrator jobs.
## Handoff
Use as prep artefact; update once AirGap 56-001 contract is published.

View File

@@ -0,0 +1,9 @@
# Orchestrator AirGap Prep — PREP-ORCH-AIRGAP-56-002
Status: Draft (2025-11-20)
Scope: Downstream of 56-001; needs sealed-mode staleness propagation.
## Needs
- From 56-001: seal contract and bundle pointers.
- Staleness propagation rules to orchestrator runs.

View File

@@ -0,0 +1,9 @@
# Orchestrator AirGap Prep — PREP-ORCH-AIRGAP-57-001
Status: Draft (2025-11-20)
Scope: Dependent on 56-002; timeline events for AirGap imports.
## Needs
- Event types/fields for bundle import timeline.
- Alignment with AirGap mirror bundle IDs and staleness.

View File

@@ -0,0 +1,8 @@
# Orchestrator AirGap Prep — PREP-ORCH-AIRGAP-58-001
Status: Draft (2025-11-20)
Scope: Dependent on 57-001; Evidence Locker integration for sealed mode.
## Needs
- Evidence Locker bundle pointers and attestation requirements in sealed mode.

View File

@@ -0,0 +1,12 @@
# Orchestrator OAS Prep — PREP-ORCH-OAS-61-001/61-002/62-001
Status: Draft (2025-11-20)
Scope: Telemetry contract inputs and OAS baseline for orchestrator APIs.
## Needs
- Telemetry/contract inputs from sprint 150.A (not yet published).
- OAS baseline for orchestrator host.
- SDK generation targets (depends on OAS v1).
## Handoff
Use as prep artefact for OAS 61/62 chain; update when telemetry inputs published.

View File

@@ -0,0 +1,17 @@
# Orchestrator Pack-Run Prep — PREP-ORCH-SVC-41-101 / 42-101 / TEN-48-001
Status: Draft (2025-11-20)
Owners: Orchestrator Service Guild
## 41-101 needs
- Envelope + DAL from 38-101 to register pack runs.
- Storage schema for pack-run records.
## 42-101 needs
- Stream contract from 41-101 (pack-run plumbing) to drive streaming.
## TEN-48-001 needs
- Tenant context plumbing for job DAL/routes.
## Handoff
Use as prep artefact; update when 38-101 envelope lands and DAL schema is fixed.

View File

@@ -2,5 +2,8 @@
| Task ID | State | Notes |
| --- | --- | --- |
| `PREP-EXPORT-CONSOLE-23-001` | DOING (2025-11-20) | Drafted export bundle + scheduler job contract (see `docs/modules/policy/design/export-console-bundle-contract.md`); waiting on DSSE/storage decisions from Console/Scheduler/Authority. |
| `PREP-POLICY-AIRGAP-56-001` | DOING (2025-11-20) | Drafted mirror bundle schema for air-gap/ sealed mode (see `docs/modules/policy/design/policy-mirror-bundle-schema.md`); waiting on trust-root and retention policy decisions. |
| `PREP-POLICY-ENGINE-30-001` | DOING (2025-11-20) | Drafted overlay projection contract (see `docs/modules/policy/design/policy-overlay-projection.md`); waiting on 29-004 metrics/log schema from Platform/Observability. |
| `SCANNER-POLICY-0001` | DONE (2025-11-10) | Ruby component predicates implemented in engine/tests, DSL docs updated, offline kit verifies `seed-data/analyzers/ruby/git-sources`. |
| `DOCS-AIAI-31-006` | DONE (2025-11-13) | Published `docs/policy/assistant-parameters.md` capturing Advisory AI configuration knobs (inference/guardrails/cache/queue) and linked it from the module architecture dossier. |

View File

@@ -0,0 +1,55 @@
# Export Console Bundle Contract (Draft) — PREP-EXPORT-CONSOLE-23-001
Status: Draft (2025-11-20)
Owners: Policy Guild · Scheduler Guild · Observability Guild
Scope: Define the evidence bundle exported by Policy Engine for Console replay/verification and the scheduler job contract that produces it.
## 1) Manifest format
- Container: tar.gz (deterministic ordering, UTC mtime `1970-01-01T00:00:00Z`), content-addressed by SHA-256 of archive bytes.
- Root manifest: `bundle.manifest.json` (unsigned) and `bundle.manifest.dsse` (signed, optional until Rekor/Authority hookup).
- `bundle.manifest.json` fields:
- `bundle_id` (string, required): GUID/ULID assigned by Policy Engine.
- `policy_run_id` (string, required): ID of originating policy run.
- `tenant_id` (string, required): tenant scope.
- `policy_version` (string, required): semantic version or commit hash of the policy set evaluated.
- `inputs_hash` (hex): SHA-256 of normalized inputs (SBOM, advisories, VEX) used for the run.
- `generated_at` (string, RFC3339 UTC): timestamp of bundle creation.
- `schema_version` (string): `policy.export.console.v1`.
- `artifacts`: array of artefact descriptors with `{path, media_type, sha256, purpose}`; expected purposes: `policy-run-summary`, `effective-findings`, `inputs`, `logs`, `metrics`.
- `signatures`: optional array referencing DSSE statement(s) with signer identity and key hint.
## 2) Artefact layout
- `summary/policy-run.json`: minimal run summary (status, duration, rule counts, decision stats).
- `findings/effective.ndjson`: deterministic NDJSON list of effective findings emitted by the run (sorted by `finding_id`).
- `inputs/sbom/*.json`: normalized SBOM slices (content-addressed references pointing back to source digests).
- `inputs/advisories/*.json`: advisories snapshot used during evaluation.
- `inputs/vex/*.json`: VEX statements snapshot.
- `telemetry/logs.ndjson`: structured logs with correlation IDs and runner metadata (no secrets, scrub file paths).
- `telemetry/metrics.json`: counters/histograms for run (p50/p95 latency, evaluated rules, facts ingested).
## 3) Scheduler job contract
- Job type: `policy.export.console`.
- Inputs:
- `policy_run_id` (required)
- `tenant_id` (required)
- `priority` (enum: background|interactive; default background)
- `include_logs` (bool, default true)
- Outputs:
- `bundle_pointer` (URI/path) to stored bundle in Evidence Locker/Export Center bucket.
- `bundle_id`, `sha256`.
- Events:
- Progress events to Observability stream `{job_id, state, percent, bundle_id?, error?}`.
- Completion emits `policy.export.console.completed` with bundle metadata for Console ingestion.
## 4) Determinism & security
- All NDJSON/JSON sorted by stable keys; floats avoided; timestamps UTC RFC3339.
- No inline PII; tenant-scoped file paths must be redacted or normalized.
- Offline-friendly: no external references; all URIs either `bundle://` or content hashes.
## 5) Open items / decisions needed
- Signer identity and DSSE profile (Rekor optional) — awaiting Authority/Attestor alignment.
- Exact location for bundle storage (Evidence Locker vs Export Center) — propose Evidence Locker namespace `policy-console/` with retention 30d.
- Metrics schema: align with Observability guilds latest counters/histogram names.
## 6) Handoff
Cite this file in sprint trackers for PREP-EXPORT-CONSOLE-23-001. When upstream decisions land, update schema_version and finalize DSSE profile.

View File

@@ -0,0 +1,27 @@
# Deterministic Evaluator Spec (Draft) — PREP-POLICY-ENGINE-20-002
Status: Draft (2025-11-20)
Owners: Policy Guild
Scope: Define deterministic evaluator requirements for Policy Engine to unblock POLICY-ENGINE-20-002.
## Determinism rules
- Evaluation order: lexical by rule ID within policy set; stable tie-breaker by condition hash.
- Data types: disallow host clock/network; only allow provided inputs; random seeded with fixed seed per run.
- Outputs: sorted by finding_id; numeric outputs with fixed precision (3 decimals) and invariant culture.
- Time handling: all timestamps in inputs are treated as UTC; now() not permitted.
## Engine contract
- Input envelope: `{policy_set_id, policy_version, inputs_hash, tenant_id, run_id}`.
- Execution context: immutable; no mutations to global state; cache keyed by inputs_hash + policy_version.
- Result envelope: `{run_id, policy_set_id, policy_version, findings[], metrics{duration_ms, rules_evaluated}}`.
## Testing strategy
- Golden runs: same inputs produce identical outputs/hashes across runs and machines.
- Property tests: altering rule order must not change result ordering; injecting clock skew should be rejected.
## Open decisions
- Whether to allow parallel rule evaluation if output ordering remains deterministic (requires stable merge logic).
- Exact numeric tolerance/rounding strategy.
## Handoff
Use this as the PREP artefact for PREP-POLICY-ENGINE-20-002. Update once numeric rounding and parallelism decisions are finalized.

View File

@@ -0,0 +1,46 @@
# Policy Mirror Bundle Schema (Draft) — PREP-POLICY-AIRGAP-56-001
Status: Draft (2025-11-20)
Owners: Policy Guild · Cartographer Guild
Scope: Define sealed/offline-ready mirror bundle schema for policy packs to unblock air-gap ingestion (Mirror Bundles v1).
## 1) Bundle container
- Format: tar.gz with deterministic ordering, UTC mtime `1970-01-01T00:00:00Z`.
- Root: `mirror.manifest.json` plus optional `mirror.manifest.dsse` (post-quantum ready profile TBD).
## 2) Manifest fields
- `bundle_id` (string, required): ULID.
- `schema_version` (string): `policy.mirror.v1`.
- `created_at` (RFC3339 UTC).
- `producer` (object): `{name, version, build}` of the mirror tool.
- `provenance` (object): `{source_registry, source_digest, fetch_time, trust_roots[]}`.
- `policies` (array) of policy pack descriptors:
- `pack_id` (string): content-addressed ID of the pack archive.
- `version` (string): semver or commit hash.
- `sha256` (string): hash of pack bytes.
- `signatures[]` (optional): detached signatures (Sigstore/DSSE) with key hints.
- `metadata` (object): `{rules_count, dependencies, min_engine_version}`.
- `attestations` (optional array): references to DSSE statements covering manifest or pack artefacts.
- `integrity` (object): `{merkle_root, entries[]}` mirroring file tree for audit.
## 3) File layout
- `packs/{pack_id}.tar.gz`: raw policy pack.
- `signatures/{pack_id}.sig`: detached signature per pack (optional).
- `notes/compliance.md`: optional compliance notes per pack.
## 4) Sealed-mode rules
- Whole-bundle DSSE signature required when `sealed=true` (header flag in manifest).
- No post-fetch mutation; ingest must verify merkle root and DSSE before unpack.
- Trust roots pinned per bundle (`provenance.trust_roots[]`), defaulting to org-configured roots when absent.
## 5) Determinism & validation
- All arrays sorted; use lowercase hex for hashes.
- Validation checklist: bundle hash matches manifest; merkle root recomputes; DSSE signer authorized; engine version compatibility enforced before import.
## 6) Open decisions
- Final DSSE profile (FIPS/eIDAS/GOST) depending on deployment region.
- Retention/GC policy for stale mirror bundles in sealed mode.
- Whether to embed policy docs or keep external references; draft assumes external docs are excluded for air-gap safety.
## 7) Handoff
Treat this file as the publishable artefact for PREP-POLICY-AIRGAP-56-001. Update when Authority/Platform finalize DSSE and trust-root policies.

View File

@@ -0,0 +1,55 @@
# Policy Overlay Projection Contract (Draft) — PREP-POLICY-ENGINE-30-001
Status: Draft (2025-11-20)
Owners: Policy Guild · Cartographer Guild · Platform/Observability Guild
Scope: Define the overlay projection output that depends on metrics/logging outputs from POLICY-ENGINE-29-004. Intended to unblock POLICY-ENGINE-30-001 and downstream 30-00x tasks.
## 1) Inputs
- `policy_run_id` (required)
- `tenant_id` (required)
- Metrics/logging envelope from 29-004 (pending): expected fields include run duration, rule evaluation counts, fact ingest counts, cache hit/miss, scheduler job metadata.
- Optional: advisory/KB versions, SBOM/VEX digests, risk profile version.
## 2) Overlay projection shape (proposed)
```json
{
"overlay_id": "ulid",
"policy_run_id": "...",
"tenant_id": "...",
"generated_at": "2025-11-20T00:00:00Z",
"schema_version": "policy.overlay.v1",
"metrics": {
"duration_ms": 1234,
"rules_evaluated": 4200,
"facts_ingested": 98765,
"cache_hit_rate": 0.92,
"p95_rule_latency_ms": 8
},
"logs_pointer": "bundle://telemetry/logs.ndjson",
"inputs": {
"sbom_digest": "sha256:...",
"advisories_digest": "sha256:...",
"vex_digest": "sha256:..."
},
"provenance": {
"engine_version": "x.y.z",
"profile": "policy-default",
"scheduler_job_id": "..."
}
}
```
- Determinism: sorted keys; timestamps UTC; numeric metrics fixed to 3 decimal places where fractional.
- Overlay acts as the query surface for simulation/change events (30-002/30-003) and UI overlays.
## 3) Storage & API
- Stored as NDJSON under `overlays/{tenant_id}/{policy_run_id}.ndjson` in policy engine store; referenced by Export/Console bundle.
- API (proposed): `GET /policy-runs/{policy_run_id}/overlay` with ETag = sha256 of payload; `POST /policy-runs/{policy_run_id}/overlay/rebuild` for re-projection when metrics contract changes.
## 4) Open dependencies / decisions
- Need final metrics/logging schema from 29-004 to lock `metrics` section (owner: Platform/Observability).
- Confirm cache metrics naming and units.
- Confirm whether overlay should embed inline logs vs pointer.
- Clarify retention/GC policy for overlays (suggest 30d, aligned with export bundles).
## 5) Handoff
Use this document as the PREP artefact for POLICY-ENGINE-30-001. Update once 29-004 publishes metrics/logging outputs; then fix schema_version to `overlay.v1` and add JSON Schema under `docs/modules/policy/schemas/`.

View File

@@ -0,0 +1,16 @@
# Risk Profile Library Prep — PREP-POLICY-RISK-66-001
Status: Draft (2025-11-20)
Owners: Risk Profile Schema Guild
Scope: Scaffold requirements for `StellaOps.Policy.RiskProfile` project and storage contract.
## Needs
- Project skeleton (net10.0) under `src/Policy/StellaOps.Policy.RiskProfile` with schema/validators.
- Storage contract: collections/fields for risk profiles; deterministic hashing rules.
## Open decisions
- Exact schema fields and validation rules.
- Versioning strategy (semver vs commit hash) for profiles.
## Handoff
Use as PREP artefact; update once schema fields and storage strategy are agreed.

View File

@@ -0,0 +1,27 @@
# SBOM Service Offline Feed Plan (prep for PREP-SBOM-CONSOLE-23-001)
## Problem
SbomService builds/tests were failing restore due to missing NuGet packages (notably `Microsoft.IdentityModel.Tokens >= 8.14.0` and `Pkcs11Interop >= 4.1.0`). Offline/air-gap posture requires a cached feed.
## What landed (2025-11-20)
- Offline cache populated under `local-nugets/packages/` via `tools/offline/fetch-sbomservice-deps.sh`.
- Key package hashes:
- `Microsoft.IdentityModel.Tokens.8.14.0.nupkg` · SHA256 `00b78c7b7023132e1d6b31d305e47524732dce6faca92dd16eb8d05a835bba7a`
- `Pkcs11Interop.4.1.0.nupkg` · SHA256 `8d2b323a3abb9de47a06a3c3b662aa526ee5c1637b70db072c66dc28e6f14c1e`
- Script: `tools/offline/fetch-sbomservice-deps.sh` (idempotent) hydrates required packages into `local-nugets/packages` using a minimal probe project with `--ignore-failed-sources` to stay air-gap friendly.
## How to use
```bash
# refresh cache if versions change
./tools/offline/fetch-sbomservice-deps.sh
# run SbomService tests offline
DOTNET_NOLOGO=1 dotnet test src/SbomService/StellaOps.SbomService.Tests/StellaOps.SbomService.Tests.csproj --no-build --ignore-failed-sources
```
## Next actions
- If additional packages surface during `dotnet restore`, append them to the probe project in the script and re-run.
- Keep `local-nugets/` under version control for deterministic builds; update hashes when packages change.
## Owners
- SBOM Service Guild · Build/Infra (sprint 0142_0001_0001).

View File

@@ -0,0 +1,15 @@
# Build/Infra Prep — PREP-BUILD-INFRA-SBOM-SERVICE-GUILD-BLOCKED-M
Status: Draft (2025-11-20)
Owners: SBOM Service Guild
Scope: Document restore/build blocking issues awaiting vetted feed/cache.
## Blocker summary
- Multiple restore attempts hang/fail; need vetted NuGet feed/cache for SBOM Service solution.
## Needed actions
- Provide approved offline feed snapshot for SBOM Service dependencies.
- CI runner with feed configured to validate restore.
## Handoff
Use as PREP artefact; update once feed snapshot is supplied and restore passes.

View File

@@ -0,0 +1,20 @@
# SBOM Service Prep — PREP-SBOM-SERVICE-21-001
Status: Draft (2025-11-20)
Owners: SBOM Service Guild · Cartographer Guild
Scope: Waiting on LNM v1 fixtures to freeze normalized SBOM projection read API.
## Needed inputs
- LNM v1 fixtures (due 2025-11-18 UTC) for schema alignment.
## Proposed API surface (draft)
- `GET /sboms/{id}/projection` with query `page`, `page_size`, `tenant_id`.
- Response includes `components[]`, `licenses[]`, `hashes[]`, `provenance`.
- Deterministic ordering, tenant enforcement.
## Open decisions
- Pagination defaults and max page size.
- Which hash algorithms to expose.
## Handoff
Use as PREP artefact; finalize once fixtures arrive.

View File

@@ -0,0 +1,118 @@
# Scanner Analyzer Prep · Sprint 0132
This note captures the unblockers promised in PREP tasks for Sprint 0132. Each subsection gives the artifact location, assumption set, and the handoff needed by downstream implementation tasks.
## SCANNER-ANALYZERS-LANG-11-003 (runtime fusion)
- **Objective:** Define the runtime evidence ingest contract to merge AssemblyLoad/Resolving/PInvoke signals with static edges from 11-002.
- **Inputs required:**
- Static edge export format from 11-002 (AssemblyRef/ModuleRef/PInvoke with reason codes).
- Event listener tap points: `AssemblyLoadContext.Resolving`, `AssemblyLoad`, `NativeLibrary.SetDllImportResolver`, `DynamicDependency` attributes, and optional ETW provider `Microsoft-Windows-DotNETRuntime` (keyword 0x8, task AssemblyLoad).
- **Runtime evidence envelope (AOC-aligned):**
```json
{
"runtime_observation_id": "uuid",
"assembly_name": "System.Text.Json",
"kind": "assembly-load|p-invoke|dynamic-dependency",
"source": "Resolving|AssemblyLoad|NativeLibrary|ETW",
"details": {
"requested_name": "System.Text.Json",
"resolved_path": "<normalized absolute path>",
"assembly_version": "8.0.0.0",
"culture": "neutral",
"package_purl": "pkg:nuget/system.text.json@8.0.0",
"confidence": 0.72,
"reason_code": "runtime-resolve"
},
"timestamp_utc": "2025-11-20T00:00:00Z"
}
```
- **Merge rules for downstream 11-003 implementation:**
- De-dup edges by (assembly_name, resolved_path, kind).
- Prefer static edge confidence when present; runtime adds `confidence_bonus = +0.1` but never exceeds 1.0.
- Keep provenance: `edge.provenance = { "static": bool, "runtime": bool }`.
- **Publication:** This doc section is the frozen location for the runtime ingest contract; downstream tasks should reference this path.
## SCANNER-ANALYZERS-LANG-11-004 (observation export → writer/SBOM)
- **Objective:** Define the observation payload emitted to Scanner writer and SBOM entrypoint tagging.
- **Export envelope (AOC-compliant):**
```json
{
"entrypoints": [
{
"label": "app",
"rids": ["win-x64","linux-x64"],
"tfms": ["net8.0","net8.0-windows"],
"command": "dotnet ./bin/app.dll",
"sources": ["src/App/Program.cs"],
"rank": 1
}
],
"dependency_edges": [
{
"from": "app",
"to": "pkg:nuget/system.text.json@8.0.0",
"reason_code": "assembly-ref",
"confidence": 0.86,
"provenance": {"static": true, "runtime": false}
}
],
"environment_profiles": {
"tfm": "net8.0",
"rid": "linux-x64",
"host_policy": "portable",
"features": ["singlefile:false","trimmed:false","nativeaot:false"]
}
}
```
- **Writer handoff:**
- Serialize as deterministic JSON (sorted keys) to the Scanner writer contract `writer/observations/lang/dotnet`.
- Attach `sbom_entrypoint_tags` derived from entrypoint labels to feed SBOM Service tagging.
- **Publication:** Payload shape and field meanings fixed here for Sprint 0132 downstream work.
## SCANNER-ANALYZERS-LANG-11-005 (fixtures & benchmarks)
- **Objective:** Provide fixture plan so QA can start without waiting on further design.
- **Fixture matrix:**
- Framework-dependent: `net8.0`, `net9.0-preview` sample apps (console + web minimal API).
- Self-contained: `linux-x64` trimmed vs non-trimmed.
- Single-file: `win-x64` single-file publish, include native hosting bundle.
- NativeAOT: `linux-x64` HelloWorld + P/Invoke stub.
- Multi-RID: RID graph `linux-x64`, `linux-arm64`, `win-x64` with RID fallback expectations.
- **Locations:** place fixtures under `src/Scanner/__Tests/Fixtures/DotNet/11-005/*`; store expected observation JSON in `__Tests/Fixtures/DotNet/11-005/expected/*.json` with sorted keys.
- **Bench envelopes:**
- Target <150 ms p95 per project scan on dev laptop, <25 MB heap delta; capture via BenchmarkDotNet and report to `__Benchmarks/11-005.md`.
- **Determinism:** lock timestamps to `1970-01-01T00:00:00Z` in serialized outputs; stable ordering by (entrypoint label, dependency to PURL, reason_code).
## SCANNER-ANALYZERS-NATIVE-20-002 (ELF declared-dependency writer contract)
- **Objective:** Unblock writer schema so native analyzer can emit DT_NEEDED/DT_RPATH/DT_RUNPATH data.
- **Edge record (per ELF binary):**
```json
{
"image": "libssl.so.3",
"build_id": "cafef00d",
"rpath": ["$ORIGIN/lib","/usr/lib"],
"runpath": ["$ORIGIN","/opt/openssl"],
"needed": [
{"name": "libcrypto.so.3", "slot": 0, "version": "OPENSSL_3.0", "reason_code": "elf-dtneeded"},
{"name": "libpthread.so.0", "slot": 1, "version": null, "reason_code": "elf-dtneeded"}
],
"interpreter": "/lib64/ld-linux-x86-64.so.2",
"origin": "virtual-fs",
"confidence": 0.82
}
```
- **Writer path:** `writer/observations/native/elf-declared-deps` (append-only NDJSON; sorted by image name then slot).
- **Redaction:** no host absolute paths; resolve `$ORIGIN` using virtual image root only.
- **Publication:** schema above is the agreed baseline for downstream tasks; time-boxed to Sprint 0132.
## SCANNER-ANALYZERS-NODE-22-001 (isolated runner / scoped build graph)
- **Objective:** Provide a deterministic way to run Node analyzer tests without fanning out the whole solution.
- **Approach:**
- Add target solution filter: `src/Scanner/StellaOps.Scanner.Analyzers.Lang.Node.slnf` including only Node projects + shared test utilities.
- Introduce `Directory.Build.props` override for `Lang.Node` tests to disable cross-solution restore (`DisableTransitiveProjectReferences=true`).
- Test command for CI + local: `dotnet test src/Scanner/StellaOps.Scanner.Analyzers.Lang.Node.Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests.csproj /p:DisableTransitiveProjectReferences=true --no-restore --logger:"console;verbosity=minimal"`.
- Cache seeds: copy pnpm/Yarn fixtures into `obj/fixtures-cache` during test init; deterministic zip timestamps set to `1980-01-01`.
- **Publication:** This runbook unblocks execution while broader solution build contention is resolved; downstream tasks should adopt this invocation until Sprint 131 completes.
---
**Owners:** Scanner EPDR Guild (DotNet), SBOM Service Guild, Native Analyzer Guild, Node Analyzer Guild.
**Status:** All PREP artifacts published 2025-11-20.

View File

@@ -0,0 +1,33 @@
# Scanner Analyzers PREP Notes — 2025-11-20
Owner: Scanner EPDR Guild · Signals Guild · SBOM Service Guild · Native Analyzer Guild
Scope: Prep deliverables for PREP-SCANNER-ANALYZERS-LANG-11-003-DEPENDS-ON, PREP-SCANNER-ANALYZERS-LANG-11-004-DEPENDS-ON, and PREP-SCANNER-ANALYZERS-NATIVE-20-002-AWAIT-DE.
## 1) LANG-11-003 runtime evidence ingest (dependent on 11-002)
- Required upstream: static analyzer outputs from 11-002 (AssemblyRef/ModuleRef/PInvoke/reflection edges with reason codes/confidence).
- Runtime harness spec (draft):
- Listener surfaces `AssemblyLoad`, `Resolving`, `FirstChanceException` events; optional OS-specific providers gated by feature flag `scanner:analyzers:dotnet:runtime-capture` (default off).
- Output shape fed into merger: `runtime_edges[]` with fields `{from_entrypoint, to_identity, reason_code, confidence, evidence}`; `evidence` captures event type, payload fragment, timestamp (UTC ISO-8601), and source provider.
- Merge rules: prefer static edges; runtime edges only add new edges or upgrade confidence; no removals.
- Test plan stub: targeted harness tests under `StellaOps.Scanner.Analyzers.Lang.DotNet.Tests` using recorded ETW/EventListener traces; determinism enforced via sorted edges and normalized timestamps.
## 2) LANG-11-004 normalized observation export (dependent on 11-003)
- Export contract (AOC compliant) to Scanner writer:
- `entrypoints[]` with `{id, assembly_name, mvid, tfm, rid, kind}`.
- `dependency_edges[]` with `{from_entrypoint, to_component, reason_code, confidence, source={static|runtime|declared}, evidence_ref}`.
- `environment_profiles[]` capturing loader configuration (search paths, probing settings) without host-specific absolute paths; deterministic ordering.
- Integration expectations:
- Writer API endpoint path: `scanner/writer/analyzers/dotnet/runtime-static-fusion` (to be aligned with writer team).
- SBOM tagging: entrypoints annotated with export IDs; avoid adding derived severity.
- Testing hook: golden JSON exports under `src/Scanner/__Tests/Fixtures/lang11/export/*.json`, referenced by `ObservationExportTests` once 11-003 is ready.
## 3) NATIVE-20-002 declared-dependency writer (await declared-dependency contract)
- Scope: emit declared dependencies from ELF dynamic sections with `reason_code=elf-dtneeded`, include `rpath/runpath` and symbol version needs when present.
- Contract expectations:
- Writer record fields: `{binary_id, needed_soname, search_path_hint[], runpath[], build_id, interpreter, version_need[]}`; all ordered deterministically.
- Input parser must normalize duplicate `DT_NEEDED` entries and preserve order of appearance.
- Dependencies: needs finalized declared-dependency writer interface from Scanner writer team; block remains until contract lands, but this prep defines expected payload shape and ordering.
- Test stub guidance: place fixtures under `src/Scanner/__Tests/Fixtures/native/elf-dtneeded/*` with baseline YAML/JSON; benchmark target <25ms per binary on baseline fixtures.
## Handoff
- This document is the published prep artefact requested by the above PREP tasks. Implementation tasks should cite this file until upstream contracts arrive.

View File

@@ -0,0 +1,26 @@
# Java Analyzer Prep — SCANNER-ANALYZERS-JAVA-21-005 (PREP)
Status: Draft (2025-11-20)
Owners: Java Analyzer Guild
Scope: Capture prerequisites and fixture expectations to unblock SCANNER-ANALYZERS-JAVA-21-005 once upstream build issues clear.
## Blocking issues observed
- Repository build fails in Concelier due to missing `CoreLinksets` Mongo interfaces; prevents running targeted Java analyzer tests.
- Targeted `dotnet test` stalls during restore/build on shared runner; needs clean CI slot or scoped solution.
## Required upstream artifacts
- Concelier/CoreLinksets packages or mocks to let Java analyzer tests restore/build.
- CI job or local script to run Java analyzer tests in isolation (`StellaOps.Scanner.Analyzers.Lang.Java.Tests.csproj`) without full solution restore.
## Expected outputs once unblocked
- Framework config extraction evidence covering Spring Boot imports, app/bootstrap configs, web.xml/fragments, JPA/CDI/JAXB configs, logging files, Graal native-image configs.
- JNI/native hint detection: System.load/Library literals, bundled native libs, Graal JNI configs with component metadata.
- Deterministic hashing of config evidence (SHA-256) with stable ordering.
## Test/fixture plan
- Fixtures under `src/Scanner/__Tests/Fixtures/java/21-005/*` capturing the above configs.
- Regression tests in `StellaOps.Scanner.Analyzers.Lang.Java.Tests/FrameworkConfigTests.cs` asserting evidence presence and hashes.
- Add CI note: prefer `dotnet test ...Java.Tests.csproj --filter Category=FrameworkConfig` once solutions restore cleanly.
## Handoff
Use this document as the published prep artefact for PREP-SCANNER-ANALYZERS-JAVA-21-005-TESTS-BLOC. Update once Concelier/CoreLinksets dependency is resolved or CI isolation is available.

View File

@@ -0,0 +1,26 @@
# Java Analyzer Prep — SCANNER-ANALYZERS-JAVA-21-008
Status: Draft (2025-11-20)
Owners: Java Analyzer Guild
Scope: Resolver + AOC writer emitting entrypoints/components/edges with reason codes/confidence; depends on 21-007 outputs.
## Dependencies
- 21-007 manifest metadata collector outputs (signers, manifest attributes) required to seed resolver inputs.
- CoreLinksets/Concelier build health to allow Java analyzer test runs.
## Proposed resolver outputs
- `entrypoints[]`: `{id, path, manifest_main_class?, agent_class?, start_class?, module}`.
- `components[]`: modules/JARs with `{purl?, sha256, module_name?, signed?, signer_ids[]}`.
- `edges[]`: `{from_entrypoint, to_component, reason_code (jpms|cp|spi|reflect|jni|runtime), confidence, evidence}`.
- Deterministic ordering: sort edges by (from_entrypoint, to_component, reason_code).
## Tests/fixtures
- Place fixtures under `src/Scanner/__Tests/Fixtures/java/21-008/*` covering jpms, classpath, SPI, reflection, JNI cases.
- Regression tests: `ResolverOutputs_AreDeterministic` and `EdgesIncludeReasonAndConfidence`.
## Open decisions
- Exact confidence scale (01 vs categorical) to align with downstream Surface.
- Whether to emit runtime edges in this task vs deferring to 21-010.
## Handoff
Use this doc as the PREP artefact for 21-008; update once 21-007 outputs and confidence scale are finalized.

View File

@@ -0,0 +1,28 @@
# .NET Lang Analyzer Prep — SCANNER-ANALYZERS-LANG-11-001
Status: Draft (2025-11-20)
Owners: Scanner EPDR Guild · Language Analyzer Guild
Scope: Entrypoint resolver mapping project/publish artifacts to deterministic entrypoint identities; PREP covers test isolation and hang debugging.
## Blocking issues
- `dotnet test` hangs/returns empty output on shared runner; high restore/build fan-out.
- Concelier/CoreLinksets build errors encountered during prior attempts.
## Proposed mitigation
- Add CI job to run `dotnet test src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests.csproj --filter Category=Entrypoints --blame-hang-timeout 45s` on clean agent.
- Provide scoped solution `StellaOps.Scanner.Analyzers.Lang.DotNet.slnf` to limit restore.
## Expected outputs
- Entrypoints array: `{id, assembly_name, mvid, tfm, rid, kind}` with deterministic ID hashing (`sha256` over path+tfm+rid).
- Environment profiles: loader/probing settings minus host absolute paths.
## Test/fixtures
- Fixtures under `src/Scanner/__Tests/Fixtures/dotnet/entrypoints/*` for framework-dependent, self-contained, NativeAOT, multi-RID, single-file, trimmed builds.
- Golden outputs sorted by entrypoint id; verify hash stability across OS.
## Open decisions
- Hash input shape for `id` (include project GUID?): to confirm with Signals guild.
- Whether to allow RID inference from runtimeconfig vs RID graph; requires Signals sign-off.
## Handoff
Treat this as the PREP artefact for PREP-SCANNER-ANALYZERS-LANG-11-001; update once CI isolation and hash rules are confirmed.

View File

@@ -0,0 +1,27 @@
# Surface FS Pointer Contract (Draft) — PREP-SCHED-SURFACE-01
Status: Draft (2025-11-20)
Owners: Scheduler Worker Guild
Scope: Define pointer model for Surface FS to unblock scheduler worker planning.
## Pointer model
- Identifier: `surfacefs://<tenant>/<dataset>/<version>`.
- Fields:
- `tenant_id`
- `dataset` (e.g., `sbom`, `findings`, `reachability`)
- `version` (content hash or monotonic version)
- `storage_uri` (unset/relative in sealed mode; content-addressed path recommended)
- `created_at` (RFC3339 UTC)
- Deterministic JSON serialization with sorted keys.
## Scheduler usage
- Workers receive pointer in job payload; pointer is immutable per job.
- Cache key = `surface_fs_pointer`.
- Validation: ensure `dataset` is allowlisted; reject untrusted storage_uri when sealed mode is on.
## Open decisions
- Final allowlist of datasets.
- Whether inline `storage_uri` is permitted under sealed mode or requires local mirror resolution.
## Handoff
Use this doc as the PREP artefact for PREP-SCHED-SURFACE-01; update once datasets and sealed-mode rule are agreed.

View File

@@ -0,0 +1,21 @@
# Scheduler Worker PREP — SCHED-WORKER-23-101
Status: Draft (2025-11-20)
Owners: Scheduler Worker Guild · Policy Guild
Scope: Capture activation event contract and throttle source needed for worker 23-101.
## Required inputs
- Activation event schema from Policy guild: expected fields `{job_id, policy_run_id, tenant_id, priority, throttle_source}`.
- Throttle source definition (static config vs dynamic policy signals).
## Proposed contract
- Event type: `scheduler.policy.activation.requested`.
- Payload: `{job_id, policy_run_id, tenant_id, priority, requested_at_utc, throttle_source}`.
- Throttle source values: `scheduler-default`, `policy-signal`, `manual-override` (to be confirmed).
## Open decisions
- Whether to carry bundle pointers (policy/export) in the activation event.
- Retry/backoff policy if Policy service is down.
## Handoff
Use this doc as PREP artefact for SCHED-WORKER-23-101; update once Policy guild provides final schema/throttle rules.