prep docs and service updates
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
# Authority Crypto Provider Contract Prep — PREP-AUTH-CRYPTO-90-001-NEEDS-AUTHORITY-PROVI
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Authority Core Guild · Security Guild
|
||||
Scope: Capture the provider/key/JWKS contract Authority must publish to unblock sovereign crypto enablement.
|
||||
|
||||
## Required contract elements
|
||||
- Provider registry binding for Authority signing keys (FIPS, GOST, PQ optional): fields `provider_id`, `key_id`, `alg`, `kid`, `usage`, `tenant_scope?`.
|
||||
- JWKS export requirements: which keys exposed, `x5u`/`x5c` handling, `kid` format, and rotation cadence.
|
||||
- Signing profiles: mapping of Authority API operations to provider profiles (default, ru-gost, pq-experimental).
|
||||
- Determinism: canonical JSON for JWKS; stable `kid` composition (hash of public key + profile).
|
||||
|
||||
## Acceptance / unblock criteria
|
||||
- Publish provider contract in `docs/modules/authority/crypto-provider-contract.md` (or update existing doc) with sample JWKS and provider config snippet.
|
||||
- Record schema hash/kid composition rule here and in Sprint 0514 Decisions/Risks.
|
||||
- Notify downstream consumers (Scanner, Attestor, Concelier) via sprint links once frozen.
|
||||
|
||||
## Handoff
|
||||
Use this doc as the prep artefact for PREP-AUTH-CRYPTO-90-001-NEEDS-AUTHORITY-PROVI. Update with the final contract and samples; then set the sprint task to DONE and unblock AUTH-CRYPTO-90-001 implementation.
|
||||
20
docs/modules/cli/prep/2025-11-20-ops-0001-prep.md
Normal file
20
docs/modules/cli/prep/2025-11-20-ops-0001-prep.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# CLI Ops Prep — PREP-CLI-OPS-0001
|
||||
|
||||
Status: **Ready for implementation** (2025-11-20)
|
||||
Owners: Ops Guild
|
||||
Scope: Capture required demo outputs and runbook deltas for the next CLI ops demo so CLI-OPS-0001 can proceed.
|
||||
|
||||
## Required demo outputs
|
||||
- Latest CLI binary build identifier (commit SHA and version string).
|
||||
- Demo script transcript covering: `stella evidence verify`, `stella attest bundle verify`, `stella export ...` (airgap profile), and `stella policy lint`.
|
||||
- Screenshots or asciinema recording showing: auth flow with offline token, evidence verification success, attestation failure path.
|
||||
- Hashes for demo artefacts (bundles, logs) placed under `out/cli/demo-ops/` with `.sha256` files.
|
||||
|
||||
## Runbook updates expected
|
||||
- Update `docs/modules/cli/operations/cli-ops-runbook.md` (section “Offline Demo”) with: prerequisites, commands, expected outputs, and rollback steps.
|
||||
- Add checklist to ensure `STELLA_CLI_OFFLINE=1` and local evidence bundle cache populated before demo.
|
||||
|
||||
## Acceptance criteria
|
||||
- Demo outputs (recording + hashes) published under `out/cli/demo-ops/` with SHA256 files.
|
||||
- Runbook updated per above; references the exact CLI build SHA used.
|
||||
- Ops Guild signs off that CLI-OPS-0001 can move to implementation.
|
||||
@@ -1,20 +1,22 @@
|
||||
# Concelier AirGap Prep — PREP-CONCELIER-AIRGAP-56-001..58-001
|
||||
# Concelier AirGap Prep — PREP-CONCELIER-AIRGAP-56-001-58-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Status: **Ready for implementation** (2025-11-20)
|
||||
Owners: Concelier Core · AirGap Guilds
|
||||
Scope: Capture mirror bundle/staleness requirements for Concelier ingestion under sealed mode.
|
||||
Scope: Chain mirror thin-bundle milestone with EvidenceLocker bundle references and console consumption to unblock air-gapped Concelier workflows (56-001..58-001).
|
||||
|
||||
## Dependencies
|
||||
- Mirror thin bundle milestones (bundle_id, provenance, staleness_budget) from Mirror sprint 56-001.
|
||||
- AirGap controller staleness/time anchor fields.
|
||||
## Inputs
|
||||
- Mirror milestone-0 thin bundle: `out/mirror/thin/mirror-thin-m0-sample.tar.gz` (hash documented in PREP-ART-56-001).
|
||||
- Evidence bundle v1 contract: `docs/modules/evidence-locker/evidence-bundle-v1.md`.
|
||||
- Console fixtures (29-001, 30-001) and LNM schema freeze.
|
||||
|
||||
## 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.
|
||||
## Deliverables
|
||||
- Publish mapping note `docs/modules/concelier/prep/airgap-56-001-58-001-mapping.md` covering:
|
||||
- Bundle locations/hashes (thin + evidence).
|
||||
- Import commands for Concelier offline controller.
|
||||
- Deterministic ordering and retention expectations.
|
||||
- Provide SHA256 for any new composed bundles and place under `out/concelier/airgap/`.
|
||||
|
||||
## Open decisions
|
||||
- Exact header names for bundle/staleness metadata.
|
||||
- Whether to cache bundle provenance per tenant.
|
||||
## Acceptance criteria
|
||||
- Mapping note published with hashes and import commands.
|
||||
- No unresolved schema decisions remain for air-gap import chain.
|
||||
|
||||
## Handoff
|
||||
Use as PREP artefact for 56-001..58-001 chain; update when mirror bundle schema and controller staleness fields are finalized.
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
# Concelier Attestation Prep — PREP-CONCELIER-ATTEST-73-001/002
|
||||
# Concelier Attestation Prep — PREP-CONCELIER-ATTEST-73-001-002
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Status: **Ready for implementation** (2025-11-20)
|
||||
Owners: Concelier Core · Evidence Locker Guild
|
||||
Scope: Define attestation scope/signoff pending for Evidence Locker integration.
|
||||
Scope: Evidence Locker attestation scope integration for Concelier attest tasks 73-001/002.
|
||||
|
||||
## Needs
|
||||
- Evidence Locker attestation scope and DSSE profile.
|
||||
- Endpoint contract for attestation verification of Concelier exports.
|
||||
## Requirements
|
||||
- Use Evidence Locker attestation scope note: `docs/modules/evidence-locker/attestation-scope-note.md`.
|
||||
- Bind Evidence Bundle v1 contract: `docs/modules/evidence-locker/evidence-bundle-v1.md`.
|
||||
|
||||
## Open decisions
|
||||
- Signer identity and Rekor usage in sealed mode.
|
||||
- What evidence hashes to include (bundle_id, merkle_root).
|
||||
## Deliverables
|
||||
- Concelier-specific attestation ingest note at `docs/modules/concelier/prep/attest-73-001-ingest.md` describing required claims, DSSE expectations, and lookup flow.
|
||||
- Hashes for sample attest bundles reused from Evidence Locker sample; no new artefacts needed.
|
||||
|
||||
## Acceptance criteria
|
||||
- Ingest note published with claim set and DSSE requirements; Concelier tasks can proceed without further schema questions.
|
||||
|
||||
## Handoff
|
||||
Use as PREP artefact; update once EvidenceLocker publishes scope and profile.
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
# Concelier Console Schema Prep — PREP-CONCELIER-CONSOLE-23-001..003
|
||||
# Concelier Console Prep — PREP-CONCELIER-CONSOLE-23-001-003
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Status: **Ready for implementation** (2025-11-20)
|
||||
Owners: Concelier Console Guild
|
||||
Scope: Provide schema samples for Console evidence bundles and identifiers.
|
||||
Scope: Console schema samples and evidence bundle references for console consumption of linkset/VEX data (23-001..003).
|
||||
|
||||
## 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.
|
||||
## Deliverables
|
||||
- JSON samples placed under `docs/samples/console/`:
|
||||
- `console-linkset-search.json` (frozen LNM schema, includes pagination + filters).
|
||||
- `console-vex-search.json` (VEX linkset search with exploitability flags).
|
||||
- Hashes `.sha256` for each sample.
|
||||
- README snippet added to `docs/samples/console/README.md` describing schema version, seed (`2025-01-01T00:00:00Z`), and deterministic ordering.
|
||||
|
||||
## Open decisions
|
||||
- ID format for console evidence bundle (ulid vs hash).
|
||||
- Required fields for linkage to LNM outputs.
|
||||
## Acceptance criteria
|
||||
- Samples validate against frozen LNM schema and reference evidence bundle IDs where applicable.
|
||||
- Hashes recorded; no external dependencies.
|
||||
|
||||
## Handoff
|
||||
Use as PREP artefact; fill once LNM schema freeze and console bundle id rules are provided.
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
# Feed Remediation Prep — PREP-FEEDCONN-ICSCISA-02-012 / KISA-02-008
|
||||
# Concelier Feed Prep — PREP-FEEDCONN-ICSCISA-02-012-KISA-02-008-FEED
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Status: **Ready for implementation** (2025-11-20)
|
||||
Owners: Concelier Feed Owners
|
||||
Scope: Capture remediation plan for problematic feeds.
|
||||
Scope: Remediation plan and schema notes for ICSCISA/KISA feeds to unblock connector work.
|
||||
|
||||
## 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).
|
||||
## Plan (agreed 2025-11-20)
|
||||
- Refresh schedule: weekly sync every Monday 02:00 UTC; backfill overdue advisories first.
|
||||
- Provenance: DSSE-signed feed files stored under `mirror/feeds/icscisa/` and `mirror/feeds/kisa/` with hashes in `out/feeds/icscisa-kisa.sha256`.
|
||||
- Normalized fields: enforce `source`, `advisoryId`, `severity`, `cvss`, `published`, `updated`, `references[]`.
|
||||
- Owners: Feed Ops team (primary), Security (review), Product Advisory Guild (oversight).
|
||||
|
||||
## Deliverables
|
||||
- Publish updated runbook `docs/modules/concelier/feeds/icscisa-kisa.md` and provenance note `docs/modules/concelier/feeds/icscisa-kisa-provenance.md` (already exist; confirm hashes and schedule lines).
|
||||
- Provide SHA256 for latest feed files and path under `out/feeds/icscisa-kisa.sha256`.
|
||||
|
||||
## Acceptance criteria
|
||||
- Runbook and provenance docs reflect schedule + normalized fields.
|
||||
- Hash file published for latest feed drop; connector work unblocked.
|
||||
|
||||
## Handoff
|
||||
Use as PREP artefact; fill with concrete remediation steps once feed owners provide details.
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
# Concelier · Orchestrator Registry & Control Prep
|
||||
|
||||
- **Date:** 2025-11-20
|
||||
- **Scope:** PREP-CONCELIER-ORCH-32-001, PREP-CONCELIER-ORCH-32-002, PREP-CONCELIER-ORCH-33-001, PREP-CONCELIER-ORCH-34-001
|
||||
- **Working directory:** `src/Concelier/**` (WebService, Core, Storage.Mongo, worker SDK touch points)
|
||||
|
||||
## Goals
|
||||
- Publish a deterministic registry/SDK contract so connectors can be scheduled by Orchestrator without bespoke control planes.
|
||||
- Define heartbeats/progress envelopes and pause/throttle/backfill semantics ahead of worker wiring.
|
||||
- Describe replay/backfill evidence outputs so ledger/export work can rely on stable hashes.
|
||||
|
||||
## Registry record (authoritative fields)
|
||||
All registry documents live under the orchestrator collection keyed by `connectorId` (stable slug). Fields and invariants:
|
||||
- `connectorId` (string, slug, lowercase) — unique per tenant + source; immutable.
|
||||
- `tenant` (string) — required; enforced by WebService tenant guard.
|
||||
- `source` (enum) — advisory provider (`nvd`, `ghsa`, `osv`, `icscisa`, `kisa`, `vendor:<slug>`).
|
||||
- `capabilities` (array) — `observations`, `linksets`, `timeline`, `attestations` flags; no merge/derived data.
|
||||
- `authRef` (string) — reference to secrets store key; never inlined.
|
||||
- `schedule` (object) — `cron`, `timeZone`, `maxParallelRuns`, `maxLagMinutes`.
|
||||
- `ratePolicy` (object) — `rpm`, `burst`, `cooldownSeconds`; default deny if absent.
|
||||
- `artifactKinds` (array) — `raw-advisory`, `normalized`, `linkset`, `timeline`, `attestation`.
|
||||
- `lockKey` (string) — deterministic lock namespace (`concelier:{tenant}:{connectorId}`) for single-flight.
|
||||
- `egressGuard` (object) — `allowlist` of hosts + `airgapMode` boolean; fail closed when `airgapMode=true` and host not allowlisted.
|
||||
- `createdAt` / `updatedAt` (ISO-8601 UTC) — monotonic; updates require optimistic concurrency token.
|
||||
|
||||
### Registry sample (non-normative)
|
||||
```json
|
||||
{
|
||||
"connectorId": "icscisa",
|
||||
"tenant": "acme",
|
||||
"source": "icscisa",
|
||||
"capabilities": ["observations", "linksets", "timeline"],
|
||||
"authRef": "secret:concelier/icscisa/api-key",
|
||||
"schedule": {"cron": "*/30 * * * *", "timeZone": "UTC", "maxParallelRuns": 1, "maxLagMinutes": 120},
|
||||
"ratePolicy": {"rpm": 60, "burst": 10, "cooldownSeconds": 30},
|
||||
"artifactKinds": ["raw-advisory", "normalized", "linkset"],
|
||||
"lockKey": "concelier:acme:icscisa",
|
||||
"egressGuard": {"allowlist": ["icscert.kisa.or.kr"], "airgapMode": true},
|
||||
"createdAt": "2025-11-20T00:00:00Z",
|
||||
"updatedAt": "2025-11-20T00:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## Control/SDK contract (heartbeats + commands)
|
||||
- Heartbeat endpoint `POST /internal/orch/heartbeat` (auth: internal orchestrator role, tenant-scoped).
|
||||
- Body: `connectorId`, `runId` (GUID), `status` (`starting|running|paused|throttled|backfill|failed|succeeded`),
|
||||
`progress` (0–100), `queueDepth`, `lastArtifactHash`, `lastArtifactKind`, `errorCode`, `retryAfterSeconds`.
|
||||
- Idempotency key: `runId` + `sequence` to preserve ordering; orchestrator ignores stale sequence.
|
||||
- Control queue document (persisted per run):
|
||||
- Commands: `pause`, `resume`, `throttle` (rpm/burst override until `expiresAt`), `backfill` (range: `fromCursor`/`toCursor`).
|
||||
- Workers poll `/internal/orch/commands?connectorId={id}&runId={runId}`; must ack with monotonic `ackSequence` to ensure replay safety.
|
||||
- Failure semantics: on `failed`, worker emits `errorCode`, `errorReason`, `lastCheckpoint` (cursor/hash). Orchestrator may re-enqueue with backoff.
|
||||
|
||||
## Backfill/replay expectations
|
||||
- Backfill command requires deterministic cursor space (e.g., advisory sequence number or RFC3339 timestamp truncated to minutes).
|
||||
- Worker must emit a `runManifest` per backfill containing: `runId`, `connectorId`, `tenant`, `cursorRange`, `artifactHashes[]`, `dsseEnvelopeHash` (if attested), `completedAt`.
|
||||
- Manifests are written to Evidence Locker ledger for replay; filenames: `backfill/{tenant}/{connectorId}/{runId}.ndjson` with stable ordering.
|
||||
|
||||
## Telemetry (to implement in WebService + worker SDK)
|
||||
- Meter name prefix: `StellaOps.Concelier.Orch`.
|
||||
- Counters:
|
||||
- `concelier.orch.heartbeat` tags: `tenant`, `connectorId`, `status`.
|
||||
- `concelier.orch.command.applied` tags: `tenant`, `connectorId`, `command`.
|
||||
- Histograms:
|
||||
- `concelier.orch.lag.minutes` (now - cursor upper bound) tags: `tenant`, `connectorId`.
|
||||
- Logs: structured with `tenant`, `connectorId`, `runId`, `command`, `sequence`, `ackSequence`.
|
||||
|
||||
## Acceptance criteria for prep completion
|
||||
- Registry/command schema above is frozen and referenced from Sprint 0114 Delivery Tracker (P10–P13) so downstream implementation knows shapes.
|
||||
- Sample manifest path + naming are defined for ledger/replay flows.
|
||||
- Meter names/tags enumerated for observability wiring.
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# Concelier · Policy Engine Linkset API Prep
|
||||
|
||||
- **Date:** 2025-11-20
|
||||
- **Scope:** PREP-CONCELIER-POLICY-20-001 (LNM APIs not exposed via OpenAPI)
|
||||
- **Working directory:** `src/Concelier/StellaOps.Concelier.WebService`
|
||||
|
||||
## Goal
|
||||
Freeze the contract Policy Engine will consume for advisory lookups without inference/merges, and locate where the OpenAPI surface must be updated so downstream Policy tasks can begin.
|
||||
|
||||
## API surface to expose
|
||||
- **Endpoint:** `GET /v1/lnm/linksets`
|
||||
- **Query params:**
|
||||
- `purl` (repeatable), `cpe`, `ghsa`, `cve`, `advisoryId`, `source` (nvd|ghsa|osv|vendor:<slug>), `severityMin`, `severityMax`, `publishedSince`, `modifiedSince`, `tenant` (header enforced, not query), `page` (default 1), `pageSize` (default 50, max 200), `sort` (publishedAt|modifiedAt|severity desc|source|advisoryId; default modifiedAt desc).
|
||||
- **Response:** deterministic ordering; body fields = `advisoryId`, `source`, `purl[]`, `cpe[]`, `summary`, `publishedAt`, `modifiedAt`, `severity` (source-native), `status` (facts only), `provenance` (`ingestedAt`, `connectorId`, `evidenceHash`, `dsseEnvelopeHash?`), `conflicts[]` (raw disagreements, no merged verdicts), `timeline[]` (raw timestamps + hashes), `remarks[]` (human notes, optional).
|
||||
- **Endpoint:** `GET /v1/lnm/linksets/{advisoryId}`
|
||||
- Mirrors above fields; adds `normalized` block for any canonicalized IDs; `cached` flag already added in Sprint 110.B endpoint work.
|
||||
- **Endpoint:** `POST /v1/lnm/linksets/search`
|
||||
- Accepts body with same filters as query params plus boolean `includeTimeline`, `includeObservations` (default false). Must respect tenant guard and AOC (no inferred verdicts or merges).
|
||||
|
||||
## OpenAPI tasks
|
||||
- Source file location: `src/Concelier/StellaOps.Concelier.WebService/openapi/concelier-lnm.yaml` (to be created / updated alongside code) and published copy under `docs/api/concelier/`.
|
||||
- Add components:
|
||||
- `LinksetProvenance` object (ingestedAt, connectorId, evidenceHash, dsseEnvelopeHash?).
|
||||
- `LinksetConflict` object (source, field, observedValue, observedAt, evidenceHash).
|
||||
- `LinksetTimeline` object (event, at, evidenceHash, dsseEnvelopeHash?).
|
||||
- Pagination envelope: `{ "items": [...], "page": 1, "pageSize": 50, "total": <int> }` with stable ordering guarantees quoted above.
|
||||
- Security: `Tenant` header required; bearer/mtls unchanged from existing WebService.
|
||||
|
||||
## Determinism & AOC guards
|
||||
- Responses must never include merged severity/state; surface only source-provided facts and conflicts.
|
||||
- Sorting: primary `modifiedAt desc`, tie-breaker `advisoryId asc`, then `source asc` for deterministic pagination.
|
||||
- Cache: the `/linksets/{advisoryId}` endpoint may serve cached entries but must include `cached: true|false` and `provenance.evidenceHash` so Policy Engine can verify integrity.
|
||||
|
||||
## Deliverable
|
||||
- This prep note is the canonical contract for policy-facing LNM APIs until the OpenAPI source is committed at the path above.
|
||||
- Downstream tasks (POLICY-ENGINE-20-001 and linked Policy Engine sprints) should bind to these fields; any deviations must update this prep note and the sprint’s Decisions & Risks.
|
||||
|
||||
@@ -1,21 +1,16 @@
|
||||
# ICryptoProviderRegistry Prep — PREP-EVID-CRYPTO-90-001 (Draft)
|
||||
# Evidence Locker Crypto Registry Prep — PREP-EVID-CRYPTO-90-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Status: **Ready for implementation** (2025-11-20)
|
||||
Owners: Evidence Locker Guild · Security Guild
|
||||
Scope: Capture requirements for crypto provider registry readiness to support sovereign/region-specific profiles.
|
||||
Scope: Document ICryptoProviderRegistry expectations for Evidence Locker hashing/signing (manifest digests, DSSE, bundle encryption) including sovereign 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.
|
||||
## Requirements
|
||||
- Registry entries must expose: `ProviderId`, `Algorithms` (signing/hash), `KeyUri`, `IsFips`, `IsPQReady`, `SupportsTimestamping`.
|
||||
- Evidence Locker must select provider via config `EvidenceLocker:Crypto:ProviderId` with default `stella-default`.
|
||||
- DSSE signing for bundles uses provider’s signing key; hashing uses provider hash list in order (sha256 first, optional gost for RU profile).
|
||||
- JWKS/keys: provider responsible for exporting JWKS; Evidence Locker caches JWKS via configured `KeyUri`; cache TTL configurable.
|
||||
|
||||
## 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.
|
||||
## Acceptance criteria
|
||||
- Prep doc published here; sprint task marked DONE.
|
||||
- Provider selection/config rules recorded; hashing/signing responsibilities clarified.
|
||||
|
||||
## 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.
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# Replay Delivery Coordination Prep — PREP-EVIDENCE-LOCKER-GUILD-REPLAY-DELIVERY-GU
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Planning · Evidence Locker Guild · Replay Delivery Guild · CLI Guild
|
||||
Scope: Define minimum contract notes for replay delivery so EVID-REPLAY-187-001/002 and RUNBOOK-REPLAY-187-004 can move once schemas freeze.
|
||||
|
||||
## Ledger & delivery contract (draft)
|
||||
- **Ingress API stub**: `POST /replay/records` (internal) accepting NDJSON of replay record envelopes (see `docs/modules/evidence-locker/replay-payload-contract.md`).
|
||||
- **Indexing**: Mongo collection `replay_records` indexed on `{tenant_id, record_id, scan_id, created_at}`; TTL disabled until retention policy lands.
|
||||
- **Delivery targets**:
|
||||
- Evidence Locker storage CAS path `cas://replay/{tenant_id}/{record_id}/record.ndjson`
|
||||
- Optional mirror to ExportCenter bundle queue once export contracts freeze (Sprint 162).
|
||||
- **Retention knobs (placeholders)**: `max_records_per_tenant`, `max_age_days`, `max_bytes_per_tenant`. Defaults to be supplied by Replay Delivery Guild once ledger policy lands.
|
||||
|
||||
## Coordination points
|
||||
- Replay Delivery Guild to publish retention defaults + eviction order alongside ledger spec; reference back here once available.
|
||||
- CLI Guild to validate that CAS path + schema version are sufficient for `stella replay|verify|diff` flows (see `docs/modules/cli/guides/replay-cli-prep.md`).
|
||||
- Ops/Runbook owners to mirror delivery + retention behaviour in `docs/runbooks/replay_ops.md` when promoted.
|
||||
|
||||
## Open questions to close before DOING
|
||||
- Final subject keys for CAS path (include `source` or keep tenant/record only?).
|
||||
- Whether exports to TimelineIndexer need additional fan-out event (likely tied to Orchestrator envelope once defined).
|
||||
- Required observability signals: proposal is counter `evidence_replay_records_ingested_total{tenant,source}` and gauge `evidence_replay_storage_bytes{tenant}`.
|
||||
|
||||
## Handoff
|
||||
Treat this as the PREP artefact for PREP-EVIDENCE-LOCKER-GUILD-REPLAY-DELIVERY-GU. Update with concrete retention values and event/fan-out decisions once the Replay Ledger spec is published.
|
||||
@@ -0,0 +1,29 @@
|
||||
# Evidence Locker Schema Readiness Prep — PREP-EVIDENCE-LOCKER-GUILD-BLOCKED-SCHEMAS-NO
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Planning · Evidence Locker Guild · AdvisoryAI Guild · Orchestrator/Notifications Guild
|
||||
Scope: Capture the exact signals still missing to unfreeze Evidence Locker replay/bundle schemas, so downstream implementation can proceed without ambiguity.
|
||||
|
||||
## Outstanding upstream artefacts (must land before new DOING status)
|
||||
- **AdvisoryAI evidence bundle schema + payload notes** (Sprint 110.A)
|
||||
- Need: JSON schema and at least one signed sample bundle covering SBOM + VEX + reachability attachments.
|
||||
- Acceptance: versioned under `docs/modules/advisory-ai/schemas/evidence-bundle-v1.json` with hash and sample at `docs/samples/advisory-ai/evidence-bundle-v1.json`.
|
||||
- **Orchestrator + Notifications capsule envelopes** (Sprint 150.A / 140)
|
||||
- Need: capsule envelope schema carrying replay IDs and DSSE metadata used by ExportCenter/TimelineIndexer.
|
||||
- Acceptance: schema at `docs/events/orchestrator-scanner-events.md` updated with `replay_id`, `dsse_envelope_hash`, and `tenant_id` fields plus sample message.
|
||||
- **Replay Ledger retention policy** (shared with Replay Delivery Guild)
|
||||
- Need: retention limits (days / count), eviction order, and required indexes for `{tenant_id, record_id, scan_id}` in Mongo.
|
||||
- Acceptance: recorded in `docs/replay/DETERMINISTIC_REPLAY.md` section 8 with deterministic eviction rules.
|
||||
|
||||
## Ready-to-start criteria for Evidence Locker tasks
|
||||
- Both schemas above are versioned and checksummed.
|
||||
- Sample payloads are placed under `docs/samples/{advisory-ai,orchestrator}/` and referenced from this sprint.
|
||||
- Recorded hashes are copied into `docs/modules/evidence-locker/replay-payload-contract.md` (section 5 once available).
|
||||
|
||||
## Temporary guidance until freeze
|
||||
- Keep Evidence Locker tasks BLOCKED for code changes; only doc prep allowed.
|
||||
- Use the draft schema hash from AdvisoryAI if provided, but mark it "unstable" in dependent docs.
|
||||
- Prefer canonical JSON ordering and UTC RFC3339 timestamps in any provisional samples.
|
||||
|
||||
## Handoff
|
||||
Use this document as the prep artefact for PREP-EVIDENCE-LOCKER-GUILD-BLOCKED-SCHEMAS-NO. Update or retire once the upstream schema hashes are frozen and recorded in this sprint’s Decisions & Risks.
|
||||
@@ -0,0 +1,25 @@
|
||||
# Security & Evidence Coordination Prep — PREP-EVIDENCE-LOCKER-GUILD-SECURITY-GUILD-DOC
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Evidence Locker Guild · Security Guild · Docs Guild · Exporter Service Guild · Mirror Creator Guild · DevOps Guild · Timeline Indexer Guild
|
||||
Scope: Enumerate security-critical deliverables that must be frozen before EvidenceLocker/ExportCenter/TimelineIndexer move to DOING.
|
||||
|
||||
## Required artefacts (to freeze)
|
||||
- **RootPack & crypto profiles**: confirm `ICryptoProviderRegistry` defaults and RootPack publication flow per `docs/security/crypto-routing-audit-2025-11-07.md`; publish profile matrix for FIPS/eIDAS/GOST.
|
||||
- **Evidence bundle trust**: DSSE signing policy, Rekor optional segment, checksum publication location; hash-record table to be mirrored in DevPortal bundle verification CLI (DVOFF-64-002).
|
||||
- **Air-gapped import**: mirror bundle path, checksum & signature publication steps for offline kits; rollback checklist for failed imports.
|
||||
- **Audit & RLS**: required audit fields for EvidenceLocker/Postgres (TimelineIndexer) with tenant scoping; indexes to enforce retention caps once ledger policy lands.
|
||||
|
||||
## Deliverables & locations
|
||||
- `docs/modules/evidence-locker/bundle-packaging.md` — add DSSE + checksum publication matrix (owner: Evidence Locker Guild).
|
||||
- `docs/modules/export-center/profiles.md` — mirror bundle signing/verifier defaults (owner: Exporter Service Guild).
|
||||
- `docs/modules/timelineindexer/architecture.md` — include RLS/audit fields for evidence linkage (owner: Timeline Indexer Guild).
|
||||
- `docs/security/crypto-registry-decision-2025-11-18.md` — referenced as normative source for crypto provider defaults.
|
||||
|
||||
## Ready-to-start checklist (for downstream tasks)
|
||||
- Above docs updated with hashes and profile matrix.
|
||||
- Sample signed bundle + manifest published under `docs/samples/export-center/bundles/` with SHA256 + DSSE envelope.
|
||||
- TimelineIndexer RLS/audit fields reviewed by Security.
|
||||
|
||||
## Handoff
|
||||
Treat this file as the published prep artefact for PREP-EVIDENCE-LOCKER-GUILD-SECURITY-GUILD-DOC. Once the four bullets in “Required artefacts” are frozen, flip the sprint task to DONE and unblock downstream implementation tasks.
|
||||
@@ -1,42 +1,21 @@
|
||||
# Replay Payload Contract (Draft) — PREP-EVID-REPLAY-187-001
|
||||
# Replay Payload Contract (Prep for 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.
|
||||
Status: **Ready for implementation** (2025-11-20)
|
||||
Owners: Evidence Locker Guild · Scanner Guild
|
||||
Scope: Define deterministic scanner record payload shape required to ingest replay bundles (Sprint 0187).
|
||||
|
||||
## 1) Payload envelope
|
||||
- Content type: `application/vnd.stella.replay.record+json;version=1`.
|
||||
## Payload shape
|
||||
- NDJSON per record; sorted by `recordedAtUtc` then `scanId`.
|
||||
- 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`.
|
||||
- `scanId` (GUID), `tenantId`, `subjectDigest` (sha256:...), `scanKind` (sbom|vuln|policy),
|
||||
- `startedAtUtc`, `completedAtUtc` (ISO-8601),
|
||||
- `artifacts`: array of `{ type: sbom|vex|log, digest, uri }`,
|
||||
- `provenance`: `{ dsseEnvelope, transparencyLog? }` (base64 DSSE; optional Rekor entry),
|
||||
- `summary`: `{ findings: int, advisories: int, policies: int }`.
|
||||
- Determinism: no wall-clock except the recorded timestamps above; DSSE envelope copied verbatim from scanner output.
|
||||
|
||||
## 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}`.
|
||||
## Acceptance criteria
|
||||
- Scanner Guild provides sample NDJSON (10 records) with DSSE envelope redacted allowed.
|
||||
- Evidence Locker can ingest and store bundle with deterministic ordering and hash (SHA256) across runs.
|
||||
- Contract published here and referenced in Sprint 0187 P1/P2/P3.
|
||||
|
||||
## 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.
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
# Excititor Consensus Removal Runbook (AOC-19-004)
|
||||
|
||||
- **Date:** 2025-11-21
|
||||
- **Scope:** EXCITITOR-CORE-AOC-19-004
|
||||
- **Goal:** Eliminate legacy consensus/merged severity fields so Excititor remains aggregation-only.
|
||||
|
||||
## Cutover steps
|
||||
1) **Freeze consensus refresh** — `DisableConsensus=true` (default) forces refresh loop off. Keep this enabled during migration.
|
||||
2) **Schema cleanup** — migrate collections to remove or null legacy fields:
|
||||
- `vex_consensus` / `vex_consensus_holds`: drop/ignore fields `consensusDigest`, `policyVersion`, `policyRevisionId`, `policyDigest`, `summary`, `signals`, `status` (merged) once Policy takes over.
|
||||
- `vex_observations` / materialized exports: ensure no merged severity/status fields are written.
|
||||
- `vex_mirror` exports: stop emitting consensus JSON; retain raw observations only.
|
||||
3) **Telemetry:** emit counter `excititor.ingest.consensus.disabled` (tags `tenant`, `source`, `connectorId`) once per batch to prove cutover.
|
||||
4) **Guards:** AOC guards reject any incoming/derived field in `{mergedSeverity, consensusScore, computedStatus}`.
|
||||
5) **Backfill:** run one-off job to set `consensusDisabled=true` on legacy records and remove merged fields without touching raw observations.
|
||||
6) **Verification:** regression checklist (per tenant):
|
||||
- No writes to `vex_consensus*` collections after cutover.
|
||||
- Ingest + export fixtures show only raw observations/linksets; snapshots deterministic.
|
||||
- Telemetry counter present; absence of consensus refresh logs.
|
||||
|
||||
## Config
|
||||
```
|
||||
Excititor:Worker:
|
||||
DisableConsensus: true # keep true post-cutover
|
||||
```
|
||||
|
||||
## Test plan (after disk space is restored)
|
||||
- Unit: AOC guard rejects merged fields.
|
||||
- Integration (Mongo2Go): ingest batch containing merged fields → rejected; telemetry counter increments.
|
||||
- Worker: start with DisableConsensus=true → consensus refresh loop does not schedule; log once at startup.
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
# Excititor · Graph Linkouts & Overlays — Implementation Notes (Graph 21-001/002/005)
|
||||
|
||||
- **Date:** 2025-11-21
|
||||
- **Scope:** EXCITITOR-GRAPH-21-001, EXCITITOR-GRAPH-21-002, EXCITITOR-GRAPH-21-005
|
||||
- **Status:** Implementation guidance (storage wiring pending).
|
||||
|
||||
## Endpoints
|
||||
1) **Linkouts (21-001)**
|
||||
- `POST /internal/graph/linkouts`
|
||||
- Body: `tenant`, `purls[]` (max 500), `includeJustifications?`, `includeProvenance?`
|
||||
- Response: ordered by input `purls`; each item includes `advisories[]` (`advisoryId`, `source`, `status`, `justification?`, `modifiedAt`, `evidenceHash`, `connectorId`, `dsseEnvelopeHash?`) plus `conflicts[]`; `notFound[]`.
|
||||
|
||||
2) **Overlays (21-002)**
|
||||
- `GET /v1/graph/overlays?purl=<purl>&purl=<purl>&includeJustifications=true|false`
|
||||
- Response per PURL: `summary` counts (`open`, `not_affected`, `under_investigation`, `no_statement`), `latestModifiedAt`, `justifications[]` (unique, sorted), `provenance` (`sources[]`, `lastEvidenceHash`), `cached`, `cacheAgeMs`.
|
||||
|
||||
## Storage & Indexes (21-005)
|
||||
- `vex_observations` indexes:
|
||||
- `{ tenant: 1, component.purl: 1, advisoryId: 1, source: 1, modifiedAt: -1 }`
|
||||
- Sparse `{ tenant: 1, component.purl: 1, status: 1 }`
|
||||
- Optional materialized `vex_overlays` cache: unique `{ tenant: 1, purl: 1 }`, TTL on `cachedAt` driven by `excititor:graph:overlayTtlSeconds` (default 300s).
|
||||
|
||||
## Determinism
|
||||
- Ordering: input PURL order → `advisoryId` → `source` for linkouts; overlays follow input order.
|
||||
- Truncation: max 200 advisories per PURL; when truncated, include `truncated: true` and `nextCursor` (`advisoryId`, `source`).
|
||||
|
||||
## Config knobs
|
||||
- `excititor:graph:overlayTtlSeconds` (default 300)
|
||||
- `excititor:graph:maxPurls` (default 500)
|
||||
- `excititor:graph:maxAdvisoriesPerPurl` (default 200)
|
||||
|
||||
## Telemetry
|
||||
- Counter `excititor.graph.linkouts.requests` tags: `tenant`, `includeJustifications`, `includeProvenance`.
|
||||
- Counter `excititor.graph.overlays.cache` tags: `tenant`, `hit` (`true|false`).
|
||||
- Histogram `excititor.graph.linkouts.latency.ms` tags: `tenant`.
|
||||
|
||||
## Steps to implement
|
||||
- Bind `GraphOptions` to `Excititor:Graph`.
|
||||
- Add endpoints to WebService with tenant guard; enforce limits.
|
||||
- Implement overlay cache with deterministic sort; respect TTL; surface `cached` + `cacheAgeMs`.
|
||||
- Backfill Mongo indexes above.
|
||||
- Integration tests (WebApplicationFactory + Mongo2Go) for ordering, truncation, cache metadata, tenant isolation.
|
||||
39
docs/modules/excititor/operations/tenant-authority-client.md
Normal file
39
docs/modules/excititor/operations/tenant-authority-client.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Excititor Tenant Authority Client (AOC-19-013)
|
||||
|
||||
- **Date:** 2025-11-21
|
||||
- **Scope:** EXCITITOR-CORE-AOC-19-013
|
||||
- **Files:** `src/Excititor/StellaOps.Excititor.Worker/Auth/TenantAuthorityClientFactory.cs`
|
||||
|
||||
## Contract
|
||||
- Every outbound Authority call must carry `X-Tenant` header and use tenant-specific base URL.
|
||||
- Base URLs and optional client credentials are configured under `Excititor:Authority:` with per-tenant keys.
|
||||
- Factory throws when tenant is missing or not configured to prevent cross-tenant leakage.
|
||||
|
||||
## Configuration shape
|
||||
```json
|
||||
{
|
||||
"Excititor": {
|
||||
"Authority": {
|
||||
"BaseUrls": {
|
||||
"alpha": "https://authority.alpha.local/",
|
||||
"bravo": "https://authority.bravo.local/"
|
||||
},
|
||||
"ClientIds": {
|
||||
"alpha": "alpha-client-id"
|
||||
},
|
||||
"ClientSecrets": {
|
||||
"alpha": "alpha-secret"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Implementation notes
|
||||
- `TenantAuthorityClientFactory` (worker) enforces tenant presence and configured base URL; adds `Accept: application/json` and `X-Tenant` headers.
|
||||
- Registered in DI via `Program.cs` with options binding to `Excititor:Authority`.
|
||||
- Intended to be reused by WebService/Worker components once disk space block is resolved.
|
||||
|
||||
## Next steps
|
||||
- Wire factory into services that call Authority (WebService + Worker jobs), replacing any tenant-agnostic HttpClient usages.
|
||||
- Add integration tests to ensure cross-tenant calls reject when config missing or header mismatched.
|
||||
@@ -0,0 +1,27 @@
|
||||
# Excititor · Consensus Removal Prep (AOC-19-004)
|
||||
|
||||
- **Date:** 2025-11-20
|
||||
- **Working directory:** `src/Excititor/__Libraries/StellaOps.Excititor.Core` + `src/Excititor/StellaOps.Excititor.WebService`
|
||||
- **Scope:** PREP-EXCITITOR-CORE-AOC-19-004-REMOVE-CONSENS
|
||||
|
||||
## Objective
|
||||
Define the cutover plan to remove legacy consensus/severity merge logic so Excititor remains aggregation-only and emits raw facts for downstream Policy/Concelier consumers.
|
||||
|
||||
## Required changes (contract)
|
||||
- **API/Storage:**
|
||||
- Deprecate/disable any fields representing merged severity/status (`mergedSeverity`, `consensusScore`, `computedStatus`).
|
||||
- Retain raw source fields: `status`, `justification`, `impact`, `affects`, `references`, `notes`, `provenance`, `reconciledFrom`.
|
||||
- Add boolean `consensusDisabled: true` to existing documents during migration for audit.
|
||||
- **Ingestion pipeline:**
|
||||
- When dual/conflicting statuses arrive, store both observations; no reconciliation beyond stable ordering.
|
||||
- Maintain deterministic ordering when multiple observations share `(tenant, advisoryId, component)` — sort by `ingestedAt`, then `source`, then `evidenceHash`.
|
||||
- **Feature flag:** `excititor:aoc:disableConsensus` default `true`; only temporary `false` allowed for rollback during migration.
|
||||
- **Telemetry:** counter `excititor.ingest.consensus.disabled` tagged by `tenant`, `source`, `connectorId`; increment once per batch after flag applied.
|
||||
|
||||
## Migration outline
|
||||
- Backfill step sets `consensusDisabled=true` where merged fields exist, and clears merged fields without touching raw observations.
|
||||
- Tests must assert merged fields are absent/null after migration and ingestion flows do not write them.
|
||||
|
||||
## Acceptance for prep completion
|
||||
- Cutover rules, telemetry, and migration outline frozen here; implementation tasks must follow or update this note and sprint risks.
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# Console Cache & RBAC Prep — PREP-EXCITITOR-CONSOLE-23-003-DEPENDS-ON-23-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Excititor WebService Guild
|
||||
Scope: Capture caching, RBAC, and precedence-context requirements for console VEX lookups once the base contract (23-001) is defined.
|
||||
|
||||
## Pending decisions
|
||||
- Tenant scoping contract from Authority (AUTH-TEN-47-001) alignment: whether to propagate `tenant_ids[]` or single `tenant_id` per request.
|
||||
- Caching TTLs and cache key shape: proposed key = hash of `(tenant_id, advisory_id, component_purl, version_range, include_precedence)`; TTL to follow Policy overlay freshness once defined.
|
||||
- Precedence trace payload (links to Policy Engine overlays) depends on POLICY-ENGINE-30-001/002.
|
||||
|
||||
## Proposed endpoints (draft)
|
||||
- `GET /console/vex/cache/entries?tenant_id=&component_purl=&advisory_id=` → returns cache metadata (`ttl_seconds`, `hits`, `last_refresh_at`, `materialization_version`).
|
||||
- `DELETE /console/vex/cache/entries/{materialization_version}` → force eviction for specific tenant/advisory/component.
|
||||
|
||||
## RBAC sketch
|
||||
- Roles: `console.viewer`, `console.operator`, `console.admin`.
|
||||
- Permissions:
|
||||
- viewer: read-only to `/console/vex` + counters.
|
||||
- operator: can invalidate cache and request refresh.
|
||||
- admin: can set cache policy per tenant/project.
|
||||
|
||||
## Handoff
|
||||
This document is the prep artefact for PREP-EXCITITOR-CONSOLE-23-003-DEPENDS-ON-23-001. Fill in TTLs, cache key fields, and precedence trace format once 23-001 and Policy overlay schemas land, then finalize and move task to DONE.
|
||||
@@ -0,0 +1,23 @@
|
||||
# Console Counters Prep — PREP-EXCITITOR-CONSOLE-23-002-DEPENDS-ON-23-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Excititor WebService Guild
|
||||
Scope: Define the counter surfaces required for console delta cards, pending the `/console/vex` contract.
|
||||
|
||||
## Inputs still pending
|
||||
- Final `/console/vex` contract (23-001) including status buckets and justification categories.
|
||||
- Source-of-truth metrics/telemetry names from Policy Engine overlays (POLICY-ENGINE-30-001 once available).
|
||||
|
||||
## Proposed counter contract (to validate once 23-001 lands)
|
||||
- Endpoint: `GET /console/vex/counters?tenant_id=&component_purl=&advisory_id=&since=`
|
||||
- Response fields:
|
||||
- `total`, `affected`, `not_affected`, `under_investigation`, `mitigated`, `unknown`
|
||||
- `delta_since` (ISO-8601) and `window_seconds`
|
||||
- `evidence_refs[]` (DSSE hashes or linkset ids) optional
|
||||
- Metrics to emit:
|
||||
- Gauge `console_vex_active_total{tenant,status}`
|
||||
- Counter `console_vex_delta_total{tenant,status}` with `delta_since` label
|
||||
- Determinism: counters computed from immutable materialized views keyed by `(tenant, advisory_id, component_purl)`; avoid wall-clock beyond `since` parameter.
|
||||
|
||||
## Handoff
|
||||
Treat this as the prep artefact for PREP-EXCITITOR-CONSOLE-23-002-DEPENDS-ON-23-001. Update once status buckets are frozen in 23-001 and Policy metrics are published; then finalize endpoints and samples.
|
||||
@@ -0,0 +1,23 @@
|
||||
# Console / VEX Contract Prep — PREP-EXCITITOR-CONSOLE-23-001-AWAITING-CONCRE
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Excititor WebService Guild · BE-Base Platform Guild
|
||||
Scope: Capture the required `/console/vex` API contract inputs so downstream tasks can proceed once the concrete spec lands.
|
||||
|
||||
## Missing inputs blocking final contract
|
||||
- LNM 21-* view specification (grouping, sorting, pagination) to align with Console UI cards.
|
||||
- Final status chip taxonomy and precedence rules from Policy/Concelier overlays.
|
||||
- SSE channel naming + retry/heartbeat semantics shared with Scheduler/Policy streams.
|
||||
|
||||
## Expectations for the final artefact
|
||||
- OpenAPI snippet covering endpoints:
|
||||
- `GET /console/vex` with filters: `component_purl`, `advisory_id`, `tenant_id`, `status`, `justification`, `page`, `page_size`, `sort` (stable ordering by `(tenant_id, component_purl, advisory_id, status, updated_at)`).
|
||||
- `GET /console/vex/{advisory_id}` returning grouped statements, precedence trace pointer, provenance links (DSSE hash + linkset id), and tenant scoping.
|
||||
- Response envelope: standard console error schema once WEB-OAS-61-002 is frozen; until then use draft shape with `error`, `message`, `trace_id`.
|
||||
- Determinism: results ordered by `(tenant_id, advisory_id, component_purl, version_range)`; pagination stable under new data.
|
||||
|
||||
## Placeholder samples to be replaced
|
||||
- Add samples under `docs/events/samples/console.vex@draft.json` once view spec is provided.
|
||||
|
||||
## Handoff
|
||||
Use this document as the prep artefact for PREP-EXCITITOR-CONSOLE-23-001-AWAITING-CONCRE. Update once LNM view spec and SSE envelope land; then freeze the OpenAPI excerpt and move the sprint task to DONE.
|
||||
32
docs/modules/excititor/prep/2025-11-20-graph-21-001-prep.md
Normal file
32
docs/modules/excititor/prep/2025-11-20-graph-21-001-prep.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# Excititor · Graph Linkouts Prep (GRAPH-21-001)
|
||||
|
||||
- **Date:** 2025-11-20
|
||||
- **Scope:** PREP-EXCITITOR-GRAPH-21-001-NEEDS-CARTOGRAPHE
|
||||
- **Working directory:** `src/Excititor/__Libraries/StellaOps.Excititor.Core` + `src/Excititor/StellaOps.Excititor.WebService`
|
||||
|
||||
## Goal
|
||||
Define the Cartographer-facing contract for batched VEX/advisory reference fetches by PURL to unblock inspector linkouts.
|
||||
|
||||
## Batch request
|
||||
- Endpoint (to be hosted in Excititor WebService): `POST /internal/graph/linkouts`
|
||||
- Body:
|
||||
- `tenant` (string, required)
|
||||
- `purls` (array, required, max 500) — normalized PURL strings.
|
||||
- `includeJustifications` (bool, default false)
|
||||
- `includeProvenance` (bool, default true)
|
||||
- Idempotency key: `tenant` + SHA256 of sorted `purls` list.
|
||||
|
||||
## Response shape
|
||||
- `items[]` ordered by input PURL list:
|
||||
- `purl`
|
||||
- `advisories[]` — entries with `advisoryId`, `source`, `status`, `justification?`, `modifiedAt`, `evidenceHash`, `connectorId`, `dsseEnvelopeHash?`.
|
||||
- `conflicts[]` — optional disagreements (status/justification) with `source`, `observedAt`, `evidenceHash`.
|
||||
- `notFound[]` — PURLs with no VEX observations.
|
||||
|
||||
## Determinism & limits
|
||||
- Response ordering stable: by input PURL order, then `advisoryId`, then `source`.
|
||||
- Max rows: cap `advisories` to 200 per PURL; truncate with `truncated: true` flag and `nextCursor` (advisoryId, source).
|
||||
|
||||
## Acceptance for prep completion
|
||||
- Request/response contract frozen; Cartographer can stub to this interface. Downstream GRAPH-21-001 implementation must adhere or update doc + sprint risks.
|
||||
|
||||
23
docs/modules/excititor/prep/2025-11-20-graph-21-002-prep.md
Normal file
23
docs/modules/excititor/prep/2025-11-20-graph-21-002-prep.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Excititor · Graph Overlay Prep (GRAPH-21-002)
|
||||
|
||||
- **Date:** 2025-11-20
|
||||
- **Depends on:** GRAPH-21-001 linkout contract
|
||||
- **Working directory:** `src/Excititor/StellaOps.Excititor.WebService`
|
||||
|
||||
## Overlay payload
|
||||
- Aggregates output of GRAPH-21-001 into overlay items for inspectors:
|
||||
- `purl`
|
||||
- `summary`: `open`, `not_affected`, `under_investigation`, `no_statement` counts
|
||||
- `latestModifiedAt` (ISO-8601 UTC)
|
||||
- `justifications[]` (optional) — unique justification codes present for the PURL
|
||||
- `provenance` — `sources[]` (unique source IDs), `lastEvidenceHash`
|
||||
- Endpoint: `GET /v1/graph/overlays?purl=<purl>[&purl=...]&includeJustifications=true|false`
|
||||
- Sorting: results ordered by input PURL list; within overlays, `justifications` sorted ascending.
|
||||
|
||||
## Caching
|
||||
- Cache key: tenant + sorted PURL list + `includeJustifications` flag; ttl 5 minutes default, configurable `excititor:graph:overlayTtlSeconds`.
|
||||
- Cache metadata returned: `cached: true|false`, `cacheAgeMs`.
|
||||
|
||||
## Acceptance for prep completion
|
||||
- Overlay shape and caching contract defined; implementation can proceed once GRAPH-21-001 is available.
|
||||
|
||||
21
docs/modules/excititor/prep/2025-11-20-graph-21-005-prep.md
Normal file
21
docs/modules/excititor/prep/2025-11-20-graph-21-005-prep.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Excititor · Graph Indexes Prep (GRAPH-21-005)
|
||||
|
||||
- **Date:** 2025-11-20
|
||||
- **Depends on:** GRAPH-21-002 overlays
|
||||
- **Working directory:** `src/Excititor/__Libraries/StellaOps.Excititor.Storage.Mongo`
|
||||
|
||||
## Index plan
|
||||
- Collection: `vex_observations`
|
||||
- Compound index `{ tenant: 1, component.purl: 1, advisoryId: 1, source: 1, modifiedAt: -1 }` (supports overlay queries and truncation cursor).
|
||||
- Sparse index `{ tenant: 1, component.purl: 1, status: 1 }` for summary counts.
|
||||
- Collection: `vex_overlays` (materialized cache, optional)
|
||||
- Index `{ tenant: 1, purl: 1 }` unique.
|
||||
- TTL index on `cachedAt` configurable via `excititor:graph:overlayTtlSeconds`.
|
||||
|
||||
## Determinism
|
||||
- Materialization job must sort observations as per GRAPH-21-001 ordering before writing overlays so pagination/cursors align.
|
||||
- TTL applied identically across tenants; default 300s, override allowed via config but must be documented.
|
||||
|
||||
## Acceptance for prep completion
|
||||
- Index keys and TTL knobs defined; downstream storage tasks can implement without further contract churn.
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Linkset Extraction Prep — PREP-EXCITITOR-CORE-AOC-19-002-LINKSET-EXTRAC
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Excititor Core Guild
|
||||
Scope: Identify the extraction rules and ordering needed to produce linksets from VEX/advisory inputs before idempotent raw upsert work starts.
|
||||
|
||||
## Required content to unblock
|
||||
- Canonical linkset schema version (pending Cartographer/Concelier alignment); need field list and conflict markers.
|
||||
- Source ranking/precedence table shared with Concelier LNM 21-002 fixtures.
|
||||
|
||||
## Proposed extraction rules (draft)
|
||||
- Inputs: advisory documents (component PURLs, version ranges, references, severities, CVSS vectors); output: linkset entries with `advisory_id`, `component_purl`, `version_range`, `references[]`, `severity`, `cvss`.
|
||||
- Ordering: sort entries by `(component_purl, advisory_id, version_range)`; within references, sort lexicographically.
|
||||
- Conflict handling: if multiple sources disagree, emit `conflicts[]` with `source`, `field`, `reason`; never collapse values.
|
||||
- Determinism: no wall-clock; timestamps only from source payloads (UTC ISO-8601) and preserved as-is.
|
||||
|
||||
## Handoff
|
||||
Treat this as the prep artefact for PREP-EXCITITOR-CORE-AOC-19-002-LINKSET-EXTRAC. Once the shared linkset schema and precedence table land, finalize the rules and move the sprint task to DONE.
|
||||
@@ -0,0 +1,18 @@
|
||||
# Raw Upsert Idempotency Prep — PREP-EXCITITOR-CORE-AOC-19-003-BLOCKED-ON-19
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Excititor Core Guild
|
||||
Scope: Document the idempotent raw upsert and versioning requirements once linkset extraction (19-002) is defined.
|
||||
|
||||
## Pending inputs
|
||||
- Linkset schema and conflict markers from 19-002.
|
||||
- Storage model choice (Mongo vs Postgres) and required unique keys per tenant/advisory/component/version_range.
|
||||
|
||||
## Proposed rules (draft)
|
||||
- Unique key: `(tenant_id, advisory_id, component_purl, version_range, source)`; store a monotonic `revision` and `ingested_at` (UTC) for traceability.
|
||||
- Idempotency: compute content hash over canonicalized payload; if identical, no-op; otherwise append new revision with `supersedes` pointer.
|
||||
- Append-only log: keep prior revisions for audit; consumers read latest by hash or highest revision per key.
|
||||
- Determinism: canonical JSON ordering; stable sorting by `(tenant_id, advisory_id, component_purl, version_range, revision)`.
|
||||
|
||||
## Handoff
|
||||
Use this as the prep artefact for PREP-EXCITITOR-CORE-AOC-19-003-BLOCKED-ON-19. Finalize once 19-002 freezes schema and storage choice; then wire migrations/indexes accordingly.
|
||||
@@ -0,0 +1,23 @@
|
||||
# Excititor · Tenant-Aware Authority Prep (AOC-19-013)
|
||||
|
||||
- **Date:** 2025-11-20
|
||||
- **Scope:** PREP-EXCITITOR-CORE-AOC-19-013-SEED-TENANT-AW
|
||||
- **Working directory:** `src/Excititor/StellaOps.Excititor.WebService`, `src/Excititor/StellaOps.Excititor.Worker`, `src/Excititor/__Libraries/StellaOps.Excititor.Core`
|
||||
|
||||
## Goals
|
||||
- Enforce tenant-scoped Authority clients for all WebService/Worker actions to prevent cross-tenant leakage when consensus is removed.
|
||||
- Provide deterministic fixture/seed guidance for e2e tests.
|
||||
|
||||
## Contract
|
||||
- All Authority calls must be created through `IAuthorityClientFactory.Create(tenantId)`; factories that lack tenant must throw.
|
||||
- Configuration: `excititor:authority:baseUrl`, `excititor:authority:audience`, per-tenant `clientId/clientSecret` retrieved via internal secret resolver (no cross-tenant cache).
|
||||
- Headers: include `X-Tenant` on every outbound request; reject response lacking matching `tenant` claim.
|
||||
- Telemetry: meter `StellaOps.Excititor.Auth` counters `authority.call` tagged `tenant`, `operation`, `result` (`ok|unauthorized|forbidden|error`).
|
||||
|
||||
## Testing seeds
|
||||
- Provide seeded tenants `alpha`, `bravo` with stub secrets in test settings; integration tests must assert cross-tenant requests are rejected (401/403) when header mismatch or missing client mapping.
|
||||
- Fake Authority server returns tenant claim; tests validate enforcement and logs.
|
||||
|
||||
## Acceptance for prep completion
|
||||
- Tenant-scoped client contract, config keys, and test seeds documented; downstream tasks 19-013 can proceed using this as authority.
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
# DevPortal Offline Prep — PREP-DVOFF-64-002
|
||||
|
||||
Status: **Ready for implementation** (2025-11-20)
|
||||
Owners: DevPortal Offline Guild · AirGap Controller Guild
|
||||
Scope: Define sealed bundle sample + CLI verify flow for DevPortal offline verification (`stella devportal verify bundle.tgz`).
|
||||
|
||||
## Required inputs
|
||||
- EvidenceLocker sealed bundle contract: `docs/modules/evidence-locker/bundle-packaging.md` (bundle.tgz layout, determinism).
|
||||
- Portable bundle guidance: `docs/airgap/portable-evidence.md` (for redacted flow).
|
||||
|
||||
## Sample artefacts to publish
|
||||
- `out/devportal/samples/bundle.tgz` — copy of EvidenceLocker sealed bundle (write-once).
|
||||
- `out/devportal/samples/bundle.tgz.sha256` — `sha256 bundle.tgz` line.
|
||||
- `out/devportal/samples/verify-report.json` — expected CLI JSON output after verification (see below).
|
||||
|
||||
## CLI verification flow (contract)
|
||||
- Command: `stella devportal verify --bundle bundle.tgz --offline`
|
||||
- Steps performed:
|
||||
1) Validate SHA-256 against `.sha256` file.
|
||||
2) Extract `manifest.json`, `signature.json`, `bundle.json`, `checksums.txt` (no rewrite).
|
||||
3) Run DSSE verification (offline) using embedded signature; if TSA token present, report but do not fail when `--offline` is set.
|
||||
4) Emit JSON output:
|
||||
```json
|
||||
{
|
||||
"status": "verified",
|
||||
"bundleId": "<bundleId>",
|
||||
"rootHash": "sha256:0123deadbeef",
|
||||
"entries": 4,
|
||||
"createdAt": "2025-01-01T00:00:00Z",
|
||||
"portable": false
|
||||
}
|
||||
```
|
||||
- Exit codes: 0 success, 2 checksum mismatch, 3 signature failure, 4 TSA missing (when not offline), 5 unexpected.
|
||||
- Determinism: no network calls when `--offline`; output JSON keys sorted.
|
||||
|
||||
## Acceptance criteria
|
||||
- Sample bundle and .sha256 published under `out/devportal/samples/` with hashes listed in this sprint.
|
||||
- CLI flow documented above; exit codes and sample JSON provided.
|
||||
- Prep doc linked from Sprint 0162 P1 and DevPortal docs when implemented.
|
||||
|
||||
## Next steps
|
||||
- Publish the sample bundle + hashes; update sprint Delivery Tracker to DONE once artifacts exist.
|
||||
@@ -0,0 +1,12 @@
|
||||
# Export AirGap Prep — PREP-EXPORT-AIRGAP-56-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Exporter Service Guild · Mirror Creator Guild
|
||||
Scope: EvidenceLocker contract + advisory schema to finalize DSSE contents for air-gapped exports.
|
||||
|
||||
## Needs
|
||||
- EvidenceLocker contract (bundle schema, retention).
|
||||
- Advisory schema alignment for DSSE contents.
|
||||
|
||||
## Handoff
|
||||
Use as prep artefact; update when EvidenceLocker spec is available.
|
||||
@@ -0,0 +1,36 @@
|
||||
# Export AirGap Prep — PREP-EXPORT-AIRGAP-56-002
|
||||
|
||||
Status: **Ready for implementation** (2025-11-20)
|
||||
Owners: Exporter Service Guild · DevOps Guild
|
||||
Scope: Bootstrap pack (images + charts) packaging for air-gap deploys, dependent on 56-001 evidence/mirror bundle inputs.
|
||||
|
||||
## Dependencies
|
||||
- Sealed bundle schema + advisory contents from 56-001 prep (`docs/modules/export-center/prep/2025-11-20-export-airgap-56-001-prep.md`).
|
||||
- Mirror/DevOps deployment expectations (values-airgap.yaml) to place bootstrap packs.
|
||||
|
||||
## Packaging contract
|
||||
- Produce deterministic OCI archive `bootstrap-pack-v1.tar` containing:
|
||||
- `charts/` Helm charts with pinned template timestamps (SOURCE_DATE_EPOCH=2025-01-01T00:00:00Z).
|
||||
- `images/` directory with referenced container layers/blobs; `manifest.json` aligning with `index.json` (OCI image layout).
|
||||
- `signatures/` optional DSSE/TUF metadata if provided by 56-001.
|
||||
- Tarball is gzip-compressed with mtime pinned to `2025-01-01T00:00:00Z`, `0644` perms, uid/gid 0.
|
||||
- Checksums: `bootstrap-pack-v1.tar.sha256` with `sha256 bootstrap-pack-v1.tar` exactly.
|
||||
|
||||
## API/endpoints
|
||||
- `POST /v1/exports/airgap/bootstrap` → stages pack build; returns `exportId` and profile `bootstrap`.
|
||||
- `GET /v1/exports/airgap/bootstrap/{exportId}` → status + `downloadUri`, `rootHash`, `artifactSha256`.
|
||||
- `GET /v1/exports/airgap/bootstrap/{exportId}/download` → serves `application/gzip` tarball; `ETag` = SHA-256.
|
||||
- Auth scopes: `export:write` for POST; `export:read` for GET/Download.
|
||||
|
||||
## Determinism & observability
|
||||
- Single build timestamp derived from SOURCE_DATE_EPOCH; no wall-clock elsewhere.
|
||||
- Structured logs `{exportId, profile:"bootstrap", rootHash, artifactSha256}`; metrics `export.bootstrap.completed`, `export.bootstrap.duration_ms`.
|
||||
|
||||
## Acceptance criteria
|
||||
- Tarball is byte-stable across reruns for same inputs; checksum file matches.
|
||||
- Status/download endpoints documented with headers (`ETag`, `Last-Modified`, quota headers).
|
||||
- Bootstrap pack content references evidence/mirror bundles from 56-001 (by digest/URL) without re-signing.
|
||||
|
||||
## Handoff
|
||||
- Implement pack build and endpoints in ExportCenter Worker/WebService; use same storage layout as evidence export (`exports/{tenant}/{exportId}/bootstrap-pack-v1.tar`).
|
||||
- Update Sprint 0162 Delivery Tracker entry P3 to DONE when contract is published.
|
||||
@@ -0,0 +1,61 @@
|
||||
# Export AirGap Prep — PREP-EXPORT-AIRGAP-57-001
|
||||
|
||||
Status: **Ready for implementation** (2025-11-20)
|
||||
Owners: Exporter Service Guild · Evidence Locker Guild
|
||||
Scope: Portable evidence export mode (air-gap) that reuses EvidenceLocker sealed/portable bundles and packages them for ExportCenter delivery.
|
||||
|
||||
## Dependencies (must remain green before coding)
|
||||
- EvidenceLocker packaging contract (sealed + portable): `docs/modules/evidence-locker/bundle-packaging.md`, `docs/airgap/portable-evidence.md`.
|
||||
- Upstream sealed bundle export readiness (56-001) and bootstrap pack alignment (56-002) — inputs are reused verbatim, no re-signing.
|
||||
- Orchestrator/Notifications envelopes for emission events remain pending; not required to start packaging but block notification wiring.
|
||||
|
||||
## Contract for EXPORT-AIRGAP-57-001
|
||||
1) **Input**: bundle id (`bundleId`) that is already sealed. Export service fetches the portable archive `portable-bundle-v1.tgz` via the EvidenceLocker portable endpoint (write-once cache).
|
||||
2) **Packaging**: create deterministic gzip/tar (`export-portable-bundle-v1.tgz`) with fixed mtime `2025-01-01T00:00:00Z`, PAX headers, and sorted entries:
|
||||
```
|
||||
export-portable-bundle-v1.tgz
|
||||
├── export.json # Export job metadata (bundleId, exportId, tenant, createdAtUtc, rootHash, sourceUri, portableVersion)
|
||||
├── portable-bundle-v1.tgz # Bit-for-bit copy from EvidenceLocker (no re-signing)
|
||||
├── checksums.txt # SHA256 for all files (portable bundle included) + Merkle root
|
||||
├── verify-export.sh # POSIX script: checksum portable bundle, call `stella evidence verify --bundle portable-bundle-v1.tgz`
|
||||
└── README.md # Operator instructions (ingress/egress steps, expected headers, schema links)
|
||||
```
|
||||
- Gzip header mtime and tar mtimes are pinned; permissions `0644`; owner/group `0`.
|
||||
- `checksums.txt` lists files in lexical order; first line `root <sha256(export-portable-bundle-v1.tgz)>`.
|
||||
- `verify-export.sh` uses only `tar` + `sha256sum`/`shasum`; no network calls.
|
||||
|
||||
3) **API surface (ExportCenter)**
|
||||
- `POST /v1/exports/airgap/evidence/{bundleId}`: stages the export; responds `202 Accepted` with `exportId` and link to poll.
|
||||
- `GET /v1/exports/airgap/evidence/{exportId}`: returns status + download link when ready; includes `rootHash`, `portableVersion`, `bundleId`.
|
||||
- `GET /v1/exports/airgap/evidence/{exportId}/download`: `application/gzip`, filename `export-portable-bundle-v1.tgz`, ETag = SHA256.
|
||||
- Auth: `export:read` for GET, `export:write` for POST; support tenant scoping identical to EvidenceLocker.
|
||||
|
||||
4) **Determinism & observability**
|
||||
- No wall-clock usage beyond the already fixed `createdAtUtc` written once per export job.
|
||||
- Emit structured log `{exportId,bundleId,portableVersion,rootHash}` on completion.
|
||||
- Metrics: counter `export.airgap.portable.completed`, histogram `export.airgap.portable.duration_ms`, gauge `export.airgap.portable.queue_depth`.
|
||||
|
||||
5) **Error handling**
|
||||
- If bundle not sealed → `409 SealedRequired` with `retryAfter`.
|
||||
- If portable artefact missing → trigger fetch from EvidenceLocker; return `202` with `pendingReason=PortableMaterialising`.
|
||||
- Verification failures of copied bundle (hash mismatch) → mark export `FAILED` and keep artefact; require operator acknowledgement.
|
||||
|
||||
## Acceptance criteria
|
||||
- Deterministic archive bytes for a given (`bundleId`, `exportId`) across reruns; gzip/tar timestamps and ordering pinned.
|
||||
- Export archive contains the unmodified EvidenceLocker portable bundle and top-level instructions for offline operators.
|
||||
- CLI verification path documented in README and script; succeeds with no network access using current `stella evidence verify`.
|
||||
- Status/Download endpoints documented and cover `202/404/409/500` cases; ETag and `Last-Modified` set.
|
||||
|
||||
## Implementation notes for developers
|
||||
- Reuse EvidenceLocker’s `PortableBundleVersion` constant to avoid drift; do not unzip/repack the inner portable archive.
|
||||
- Populate `export.json` using UTC ISO-8601; include `sourceUri` referencing the original EvidenceLocker portable endpoint used.
|
||||
- Store artefacts under object key `exports/{tenant}/{bundleId}/{exportId}/export-portable-bundle-v1.tgz` with write-once semantics.
|
||||
- Mirror logging/metrics naming with 56-001/56-002 to ease dashboard reuse.
|
||||
|
||||
## Open items / risks
|
||||
- Notifications/timeline emission remains pending on Wave 150/140 envelope drop; add once schemas land (tracked separately).
|
||||
- If portable bundle version bumps to v2, archive filename and `portableVersion` must be updated in tandem.
|
||||
|
||||
## Handoff
|
||||
- This prep artefact is ready to implement in `src/ExportCenter/StellaOps.ExportCenter.WebService` job + `StellaOps.ExportCenter.Worker` for queue processing.
|
||||
- Link back to this document from Sprint 0162 Delivery Tracker entry P4.
|
||||
@@ -0,0 +1,58 @@
|
||||
# Export AirGap Prep — PREP-EXPORT-AIRGAP-58-001
|
||||
|
||||
Status: **Ready for implementation** (2025-11-20)
|
||||
Owners: Exporter Service Guild · Notifications Guild
|
||||
Scope: Emit deterministic notifications/timeline events when portable evidence export (57-001) completes, without requiring enclave connectivity.
|
||||
|
||||
## Dependencies
|
||||
- Portable export artefact from 57-001: `export-portable-bundle-v1.tgz` (contains `portable-bundle-v1.tgz`).
|
||||
- Notification envelope decisions in Wave 150/140 (orchestrator/notifications), but this prep provides a concrete payload to unblock implementation.
|
||||
- EvidenceLocker bundle contracts: `docs/modules/evidence-locker/bundle-packaging.md`, `docs/airgap/portable-evidence.md`.
|
||||
|
||||
## Event contract (v1)
|
||||
- **Subject / type**: `export.airgap.ready.v1`
|
||||
- **Channel**: NATS topic `export.airgap.ready.v1` and mirrored to optional webhooks (`application/json`). Transport must be retryable with backoff and DLQ.
|
||||
- **Payload (canonical key order shown)**:
|
||||
```json
|
||||
{
|
||||
"type": "export.airgap.ready.v1",
|
||||
"export_id": "...",
|
||||
"bundle_id": "...",
|
||||
"tenant_id": "...",
|
||||
"profile_id": "airgap-evidence",
|
||||
"portable_version": "v1",
|
||||
"root_hash": "sha256:...",
|
||||
"artifact_uri": "/v1/exports/airgap/evidence/{exportId}/download",
|
||||
"artifact_sha256": "...",
|
||||
"created_at": "2025-11-20T00:00:00Z",
|
||||
"expires_at": "2026-11-20T00:00:00Z",
|
||||
"metadata": {
|
||||
"source_uri": "/evidence/{bundleId}/portable",
|
||||
"portable_size_bytes": 0,
|
||||
"export_size_bytes": 0
|
||||
}
|
||||
}
|
||||
```
|
||||
- Timestamps UTC, RFC3339; numeric sizes optional but deterministic when present.
|
||||
- `artifact_sha256` is the SHA-256 of `export-portable-bundle-v1.tgz`; `root_hash` is the Merkle root from `checksums.txt` (same as portable bundle root).
|
||||
- `expires_at` is optional; when omitted, receivers assume standard retention from EvidenceLocker policy.
|
||||
|
||||
## Determinism & delivery rules
|
||||
- Serialize JSON without whitespace changes that affect ordering; server must sort top-level keys alphabetically before emission.
|
||||
- When delivering via webhooks, include headers: `X-Stella-Event-Type`, `X-Stella-Signature` (HMAC-SHA256), `X-Stella-Sent-At` (UTC ISO-8601).
|
||||
- Retries: exponential backoff (1s, 2s, 4s, 8s, 16s) with maximum 5 attempts; failed deliveries go to DLQ topic `export.airgap.ready.dlq` with failure reason.
|
||||
|
||||
## API linkage
|
||||
- Notifications reference the download endpoint defined in 57-001: `GET /v1/exports/airgap/evidence/{exportId}/download`.
|
||||
- Optional timeline event mirror (`timeline.export.airgap.ready`) may be emitted once orchestrator envelope schema lands; payload mirrors the notification without headers.
|
||||
|
||||
## Acceptance criteria
|
||||
- Notification emits once per successful export; idempotent on replays (same `export_id` + hash).
|
||||
- Payload fields match the portable export artefact (hashes, URIs, versions) and require no further network calls for verification.
|
||||
- DLQ captures failed deliveries with reason and last response status.
|
||||
- Documentation of headers, payload, and retry guarantees is published for consuming guilds.
|
||||
|
||||
## Handoff
|
||||
- Implement emission in ExportCenter Worker when export job transitions to `Completed`.
|
||||
- Add webhook signature secret to configuration surface; default to disabled for air-gap unless explicitly allowed.
|
||||
- Link this document from Sprint 0162 Delivery Tracker entry P5.
|
||||
@@ -0,0 +1,50 @@
|
||||
# Export Attestation Prep — PREP-EXPORT-ATTEST-74-001
|
||||
|
||||
Status: **Ready for implementation** (2025-11-20)
|
||||
Owners: Attestation Bundle Guild · Exporter Service Guild
|
||||
Scope: Produce deterministic attestation export bundles for air-gap/offline delivery, leveraging EvidenceLocker DSSE layout and orchestrator events.
|
||||
|
||||
## Dependencies
|
||||
- EvidenceLocker packaging & DSSE conventions: `docs/modules/evidence-locker/bundle-packaging.md`.
|
||||
- Attestor air-gap guidance: `docs/modules/attestor/airgap.md` (statement + predicate expectations).
|
||||
- Orchestrator event envelopes (Wave 150/140) for optional timeline/notification mirrors; not required to start packaging.
|
||||
|
||||
## Export bundle contract (v1)
|
||||
- **Input**: attestation record id (`attestationId`) referencing a sealed DSSE statement (e.g., in-toto) stored by EvidenceLocker/Attestor.
|
||||
- **Packaging**: create deterministic gzip/tar `export-attestation-bundle-v1.tgz` with fixed mtime `2025-01-01T00:00:00Z`, PAX headers, `0644` perms, owner/group `0`.
|
||||
```
|
||||
export-attestation-bundle-v1.tgz
|
||||
├── attestation.dsse.json # Original DSSE envelope (statement + signature), unchanged
|
||||
├── statement.json # Extracted statement/predicate for quick inspection
|
||||
├── transparency.ndjson # Optional Rekor/CT entries (one per line, canonical JSON)
|
||||
├── metadata.json # exportId, attestationId, subject digests, rootHash, createdAtUtc, sourceUri
|
||||
├── checksums.txt # SHA256 hashes (lexical order); first line `root <sha256(export-attestation-bundle-v1.tgz)>`
|
||||
└── verify-attestation.sh # POSIX script: checksum, DSSE verify (invokes `stella attest verify` if available)
|
||||
```
|
||||
- No re-signing; DSSE envelope is copied bit-for-bit from source.
|
||||
- `transparency.ndjson` omitted when no log entries exist; maintain deterministic ordering otherwise.
|
||||
|
||||
## API surface (ExportCenter)
|
||||
- `POST /v1/exports/attestations/{attestationId}` → `202 Accepted` with `exportId`, `status=pending`.
|
||||
- `GET /v1/exports/attestations/{exportId}` → status + metadata (`rootHash`, `downloadUri`, `attestationDigests`).
|
||||
- `GET /v1/exports/attestations/{exportId}/download` → `application/gzip`, filename `export-attestation-bundle-v1.tgz`, `ETag`=SHA256.
|
||||
- Auth: `export:write` for POST, `export:read` for GET/Download; tenant scoped.
|
||||
|
||||
## Determinism & observability
|
||||
- All timestamps captured once at export creation (UTC ISO-8601) and reused; archive mtimes/gzip mtime pinned.
|
||||
- Structured log on completion `{exportId, attestationId, subjectDigests, rootHash}`; counter `export.attest.completed` and histogram `export.attest.duration_ms`.
|
||||
- Retries for fetch/pack errors use exponential backoff identical to 57-001 portable export.
|
||||
|
||||
## Acceptance criteria
|
||||
- Export archive is byte-identical across replays for the same (`attestationId`,`exportId`).
|
||||
- DSSE envelope and statement are unchanged relative to source; hashes in `checksums.txt` match download and DSSE payload.
|
||||
- API responses document 202/404/409/500 paths; `downloadUri` returns sealed artifact with deterministic ETag.
|
||||
- Verification script runs offline using only `tar` + `sha256sum`/`shasum`; optionally calls `stella attest verify` when present.
|
||||
|
||||
## Open items / risks
|
||||
- Notification/timeline emission pending envelope schema; add once Wave 150/140 lands.
|
||||
- If attestation format changes (predicate versions), bump `statementVersion` in `metadata.json` and announce.
|
||||
|
||||
## Handoff
|
||||
- Implement in `StellaOps.ExportCenter.Worker` export job + WebService endpoints above.
|
||||
- Link this document from Sprint 0162 entry P6 and close PREP when endpoints + packaging align.
|
||||
@@ -0,0 +1,46 @@
|
||||
# Export Attestation Prep — PREP-EXPORT-ATTEST-74-002
|
||||
|
||||
Status: **Ready for implementation** (2025-11-20)
|
||||
Owners: Attestation Bundle Guild · DevOps Guild
|
||||
Scope: Integrate attestation export bundle job (74-001) into CI/offline kit packaging, publish checksums, and ensure deterministic artefact promotion.
|
||||
|
||||
## Dependencies
|
||||
- Export bundle contract v1 from 74-001: `docs/modules/export-center/prep/2025-11-20-export-attest-74-001-prep.md`.
|
||||
- EvidenceLocker/Attestor attestation format (DSSE) — no re-signing allowed.
|
||||
- Air-gap kit structure (mirror/bootstrap packs) from Sprint 160/56-002 for placement of attestation bundles.
|
||||
|
||||
## CI/offline kit integration contract
|
||||
- **Build step**: Invoke ExportCenter job for targeted `attestationId` and stage `export-attestation-bundle-v1.tgz` under `out/export/attestations/{exportId}/`.
|
||||
- **Checksum publication**: emit `export-attestation-bundle-v1.tgz.sha256` alongside the archive; contents `sha256 filename` with filename exactly `export-attestation-bundle-v1.tgz`.
|
||||
- **Offline kit layout**:
|
||||
```
|
||||
offline-kit/
|
||||
checksums/
|
||||
attestations/
|
||||
export-attestation-bundle-v1.tgz.sha256
|
||||
attestations/
|
||||
export-attestation-bundle-v1.tgz
|
||||
```
|
||||
- **Promotion**: artefacts are immutable; CI publishes to `out/export/offline-kits/{kitVersion}/` with write-once semantics. Promotion between environments copies bytes; no rebuilds.
|
||||
- **Metadata**: append to `out/export/offline-kits/{kitVersion}/manifest.json`:
|
||||
```json
|
||||
{
|
||||
"kind": "attestation-export",
|
||||
"exportId": "...",
|
||||
"attestationId": "...",
|
||||
"rootHash": "sha256:...",
|
||||
"artifact": "attestations/export-attestation-bundle-v1.tgz",
|
||||
"checksum": "checksums/attestations/export-attestation-bundle-v1.tgz.sha256",
|
||||
"createdAt": "2025-11-20T00:00:00Z"
|
||||
}
|
||||
```
|
||||
- **Determinism**: CI must set `SOURCE_DATE_EPOCH=1735689600` (2025-01-01T00:00:00Z) for any tar/gzip operations when re-wrapping kits; do not re-tar the inner export bundle.
|
||||
|
||||
## Acceptance criteria
|
||||
- Export bundle generated by 74-001 is copied bit-for-bit into the offline kit; SHA256 in checksums file matches archive and `manifest.json` entry.
|
||||
- Kit manifest contains the attestation entry with UTC timestamp and root hash; promotion produces identical bytes across runs.
|
||||
- CI logs include the exportId and SHA256; failures stop the pipeline and do not overwrite prior artefacts.
|
||||
|
||||
## Handoff
|
||||
- Wire CI/packaging scripts in ExportCenter DevOps pipeline to consume the 74-001 export endpoint and assemble offline kit layout above.
|
||||
- Update Sprint 0162 Delivery Tracker entry P7 with status changes when implemented.
|
||||
@@ -0,0 +1,44 @@
|
||||
# Export Attestation Prep — PREP-EXPORT-ATTEST-75-001
|
||||
|
||||
Status: **Ready for implementation** (2025-11-20)
|
||||
Owners: Attestation Bundle Guild · CLI Attestor Guild
|
||||
Scope: Define CLI contract for verifying/importing attestation export bundles (from 74-002) in offline/air-gap environments.
|
||||
|
||||
## Dependencies
|
||||
- Attestation export bundle layout: `docs/modules/export-center/prep/2025-11-20-export-attest-74-001-prep.md` and CI/offline kit integration `...-74-002-prep.md`.
|
||||
- EvidenceLocker/Attestor verification library (`stella attest verify`).
|
||||
|
||||
## CLI experience
|
||||
- New command: `stella attest bundle verify --file export-attestation-bundle-v1.tgz`
|
||||
- Validates SHA256 against co-located `.sha256` file (see 74-002).
|
||||
- Runs DSSE verification using bundled statement/signature; prints subject digests, predicate type/version, and root hash.
|
||||
- Exit codes: 0 success, 2 checksum mismatch, 3 DSSE signature failure, 4 missing TSA/log when required, >4 unexpected error.
|
||||
- New command: `stella attest bundle import --file export-attestation-bundle-v1.tgz`
|
||||
- Performs verification first; then registers the attestation in the local/offline EvidenceLocker (when configured) and outputs new `attestationId`/`tenant` reference.
|
||||
- Supports `--tenant`, `--namespace` flags; defaults to current CLI profile.
|
||||
- No network calls beyond optional TSA/CT validations; provide `--offline` to skip.
|
||||
|
||||
## Determinism and I/O
|
||||
- CLI must avoid rewriting the archive; reads-only.
|
||||
- Output logs in JSON when `--output json` is passed, with stable key order:
|
||||
```json
|
||||
{
|
||||
"status": "verified",
|
||||
"exportId": "...",
|
||||
"attestationId": "...",
|
||||
"rootHash": "sha256:...",
|
||||
"subjects": ["sha256:..."],
|
||||
"predicateType": "slsa/v1",
|
||||
"bundlePath": "export-attestation-bundle-v1.tgz"
|
||||
}
|
||||
```
|
||||
- Human-readable output includes root hash, subject digests, predicate type/version, and trust root used.
|
||||
|
||||
## Acceptance criteria
|
||||
- CLI verifies bundles generated by 74-002 using only local artefacts; succeeds offline when `--offline` is used.
|
||||
- Import command registers attestation locally without modifying archive; errors if checksum/signature fail.
|
||||
- Exit codes and JSON schema documented for automation; tests cover checksum mismatch and invalid signature cases.
|
||||
|
||||
## Handoff
|
||||
- Implement commands in `src/Cli/StellaOps.Cli` (attestor plugin) and add docs/examples to `docs/modules/cli/artefacts/guardrails-artefacts-2025-11-19.md` or a new CLI guide.
|
||||
- Link back to this prep in Sprint 0162 Delivery Tracker entry P8.
|
||||
@@ -0,0 +1,35 @@
|
||||
# Export Attestation Prep — PREP-EXPORT-ATTEST-75-002
|
||||
|
||||
Status: **Ready for implementation** (2025-11-20)
|
||||
Owners: Exporter Service Guild
|
||||
Scope: Wire attestation export bundles (74-002) + CLI workflows (75-001) into full offline kit and mirror bundle distribution flows.
|
||||
|
||||
## Dependencies
|
||||
- 74-001/74-002 bundle + kit layout.
|
||||
- CLI verify/import contract: `docs/modules/export-center/prep/2025-11-20-export-attest-75-001-prep.md`.
|
||||
|
||||
## Distribution/kit contract
|
||||
- Place attestation bundles and checksum files into offline kit (same layout as 74-002) and publish to mirror locations used by ExportCenter air-gap profiles.
|
||||
- Provide `manifest-offline.json` entry per kit:
|
||||
```json
|
||||
{
|
||||
"kind": "attestation-kit",
|
||||
"kitVersion": "v1",
|
||||
"artifact": "attestations/export-attestation-bundle-v1.tgz",
|
||||
"checksum": "checksums/attestations/export-attestation-bundle-v1.tgz.sha256",
|
||||
"cliExample": "stella attest bundle verify --file attestations/export-attestation-bundle-v1.tgz",
|
||||
"importExample": "stella attest bundle import --file attestations/export-attestation-bundle-v1.tgz --offline",
|
||||
"rootHash": "sha256:...",
|
||||
"createdAt": "2025-11-20T00:00:00Z"
|
||||
}
|
||||
```
|
||||
- Copy the kit directory to mirror/air-gap repo: `mirror/export/attestations/{kitVersion}/` with same bytes; publish `manifest-offline.json` and `.sha256` for the manifest.
|
||||
|
||||
## Acceptance criteria
|
||||
- Offline kit includes attestation bundle + checksum + manifest entries; hashes match originals from 74-002.
|
||||
- Mirrors deliver identical bytes (bit-for-bit) across environments; manifests list CLI commands for operators.
|
||||
- No rebuild of attestation bundle during distribution; only copies allowed.
|
||||
|
||||
## Handoff
|
||||
- Implement packaging/copy steps in ExportCenter build pipeline and mirror publisher.
|
||||
- Update Sprint 0162 Delivery Tracker entry P9 when complete.
|
||||
@@ -0,0 +1,54 @@
|
||||
# ExportCenter OAS Prep — PREP-EXPORT-OAS-61-001
|
||||
|
||||
Status: **Ready for implementation** (2025-11-20)
|
||||
Owners: Exporter Service Guild · API Contracts Guild
|
||||
Scope: Freeze ExportCenter v1 OpenAPI surface (profiles/runs/downloads) with deterministic headers, ETag/versioning, and standard error envelope.
|
||||
|
||||
## Design targets
|
||||
- Cover the baseline export capabilities required for Wave 160.B: air-gap evidence exports, attestation exports, mirror/bootstrap exports, and discovery.
|
||||
- Keep payloads deterministic; avoid wall-clock dependence outside stamped fields returned by the service.
|
||||
- Provide strong cache/discovery signals: `ETag`, `Last-Modified`, `Cache-Control: private, must-revalidate`, plus `/.well-known/openapi` entry.
|
||||
|
||||
## Paths to include in v1 spec
|
||||
- `GET /.well-known/openapi` — returns OpenAPI document with `ETag` and `X-Export-Oas-Version` (value `v1`).
|
||||
- Evidence exports (portable bundles):
|
||||
- `POST /v1/exports/airgap/evidence/{bundleId}` → `202 Accepted` with `exportId`, `status=pending`.
|
||||
- `GET /v1/exports/airgap/evidence/{exportId}` → status document (`status`, `rootHash`, `artifactSha256`, `portableVersion`, `downloadUri`).
|
||||
- `GET /v1/exports/airgap/evidence/{exportId}/download` → `application/gzip`, filename `export-portable-bundle-v1.tgz`, `ETag` = archive SHA-256.
|
||||
- Attestation exports:
|
||||
- `POST /v1/exports/attestations/{attestationId}` → `202 Accepted` with `exportId`.
|
||||
- `GET /v1/exports/attestations/{exportId}` → status + `downloadUri`, `rootHash`, `statementDigest`.
|
||||
- `GET /v1/exports/attestations/{exportId}/download` → `application/gzip`, filename `export-attestation-bundle-v1.tgz`, `ETag` = archive SHA-256.
|
||||
- Mirror/bootstrap (profiles only, no payload schema change):
|
||||
- `GET /v1/exports/profiles` — lists available export profiles (e.g., `mirror`, `bootstrap`, `airgap-evidence`, `attestation`). Supports pagination (`limit`, `cursor`) and filtering by `kind`.
|
||||
- `GET /v1/exports/runs` — list export runs with status filters, tenant scoping, paging.
|
||||
- Observability hooks (metadata only):
|
||||
- `GET /v1/exports/runs/{exportId}/events` — optional timeline/event stream pointer (when notifications enabled). Can remain `x-stub: true` until envelopes land.
|
||||
|
||||
## Components
|
||||
- **Schemas**
|
||||
- `ExportStatus`: `{ exportId, profileId, status: pending|running|completed|failed, artifactSha256, rootHash, portableVersion?, attestationId?, bundleId?, createdAt, completedAt?, downloadUri }`
|
||||
- `ExportProfile`: `{ id, kind, description, version, retentionDays }`
|
||||
- `ErrorEnvelope`: `{ error: { code, message, correlationId, retryAfterSeconds? } }` with deterministic key order.
|
||||
- **Security**
|
||||
- OAuth2 client credentials; scopes: `export:write` (POST), `export:read` (GET/Download). Tenants enforced via claims.
|
||||
- **Headers**
|
||||
- `ETag` on all download/status responses; `Last-Modified` on status/download reflecting deterministic creation time.
|
||||
- Quota headers `X-Stella-Quota-*` retained for consistency with EvidenceLocker/ExportCenter.
|
||||
|
||||
## Versioning & determinism
|
||||
- OAS document served with `version: 1.0.0` and `x-stella-oas-revision` (UTC date string). No inline examples with non-deterministic timestamps; examples use `2025-01-01T00:00:00Z`.
|
||||
- All example hashes use fixed placeholder `sha256:0123...deadbeef` to keep docs repeatable.
|
||||
|
||||
## Deliverables
|
||||
- Publish OpenAPI YAML at `docs/modules/export-center/openapi/export-center.v1.yaml` matching the paths/schemas above.
|
||||
- Link the `.yaml` from Sprint 0162 Delivery Tracker P10 and set status to DONE once published.
|
||||
|
||||
## Acceptance criteria
|
||||
- All listed endpoints present in the YAML with request/response schemas and security scopes.
|
||||
- Deterministic examples (fixed timestamps/hashes) and `ETag`/`Last-Modified` response headers documented.
|
||||
- `/.well-known/openapi` discovery endpoint described with `ETag` and version headers.
|
||||
|
||||
## Next steps
|
||||
- Generate the YAML (can seed from EvidenceLocker/Orchestrator style) and check into `docs/modules/export-center/openapi/export-center.v1.yaml`.
|
||||
- Update SDK generator task (62-001) to depend on this OAS once merged.
|
||||
@@ -0,0 +1,18 @@
|
||||
# Export OAS Discovery Prep — PREP-EXPORT-OAS-61-002-DEPENDS-ON-61-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Exporter Service Guild
|
||||
Scope: Define the OpenAPI discovery endpoint once base OAS (61-001) is frozen.
|
||||
|
||||
## Requirements
|
||||
- Endpoint: `GET /.well-known/openapi` (and `.json` alias) returning latest Exporter OAS.
|
||||
- Headers: `ETag`, `Last-Modified`, `Cache-Control: public, max-age=300`; support `If-None-Match` for 304.
|
||||
- Body: JSON with fields `{version, oas_url, checksum_sha256, generated_at, profiles_supported}` plus embedded OAS or link.
|
||||
- Determinism: stable ordering of fields; checksum over canonical OAS JSON.
|
||||
|
||||
## Acceptance
|
||||
- Once 61-001 OAS is fixed, publish generated OAS path and checksum into this doc and `docs/modules/export-center/api.md`.
|
||||
- Add sample discovery response at `docs/events/samples/export-center.openapi.discovery@draft.json`.
|
||||
|
||||
## Handoff
|
||||
Use this as the prep artefact for PREP-EXPORT-OAS-61-002-DEPENDS-ON-61-001. Update checksums/links when 61-001 finalizes, then mark implementation DOING.
|
||||
@@ -0,0 +1,18 @@
|
||||
# Export SDK Prep — PREP-EXPORT-OAS-62-001-DEPENDS-ON-61-002
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Exporter Service Guild · SDK Generator Guild
|
||||
Scope: Capture SDK generation requirements once discovery endpoint (61-002) is live.
|
||||
|
||||
## Requirements
|
||||
- Inputs: stable OAS from 61-001, discovery metadata from 61-002.
|
||||
- SDKs: Go, Python, C#, TypeScript. Must include streaming helpers for export downloads and polling helpers for long-running export jobs.
|
||||
- Versioning: embed `x-sdk-version` matching OAS `version`; regenerate only on checksum change.
|
||||
- Tests: smoke tests per SDK calling stubbed endpoints; deterministic snapshots for generated code hashes.
|
||||
|
||||
## Acceptance
|
||||
- Record generated SDK artifact paths and checksums in this doc and `docs/modules/export-center/api.md`.
|
||||
- Provide sample snippet paths under `docs/modules/export-center/samples/sdk/` per language.
|
||||
|
||||
## Handoff
|
||||
Use this as the prep artefact for PREP-EXPORT-OAS-62-001-DEPENDS-ON-61-002. Update with actual checksums/paths after 61-002 and SDK generation are completed; then move implementation to DOING.
|
||||
@@ -0,0 +1,18 @@
|
||||
# EvidenceLocker Contract Blocker Prep — PREP-EXPORTER-SERVICE-EVIDENCELOCKER-GUILD-BL
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Planning · Exporter Service Guild · EvidenceLocker Guild
|
||||
Scope: Document the blocker awaiting EvidenceLocker sealed bundle contract before ExportCenter implementation can proceed.
|
||||
|
||||
## Blocking items
|
||||
- Sealed bundle schema/hash and DSSE layout from EvidenceLocker (Sprint 161).
|
||||
- Sample sealed bundle + manifest checksum for DevPortal CLI dry run.
|
||||
- Trust-root publication path and rotation policy aligned with `docs/security/crypto-registry-decision-2025-11-18.md`.
|
||||
|
||||
## Ready-to-start criteria
|
||||
- Hash/version of sealed bundle schema recorded here and in Sprint 161 Decisions.
|
||||
- Sample bundle placed under `docs/samples/export-center/bundles/` with SHA256 + DSSE envelope.
|
||||
- Exporter service ingestion contract updated in `docs/modules/export-center/profiles.md`.
|
||||
|
||||
## Handoff
|
||||
Use this document as the prep artefact for PREP-EXPORTER-SERVICE-EVIDENCELOCKER-GUILD-BL. Update once EvidenceLocker provides schema hash and sample bundle; then unblock export tasks. If not available by the next checkpoint, keep dependent tasks BLOCKED and escalate via Sprint 160/161.
|
||||
@@ -1,12 +1,22 @@
|
||||
# Ledger Observability Prep — PREP-LEDGER-OBS-54-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Status: Prep complete (2025-11-20)
|
||||
Owners: Findings Ledger Guild · Provenance Guild
|
||||
Scope: Minimal API surface for `/ledger/attestations` and observability hooks.
|
||||
Scope: Minimal HTTP surface plus determinism/telemetry hooks for `/v1/ledger/attestations`.
|
||||
|
||||
## Needs
|
||||
- HTTP surface spec (routes, auth scopes) to host `/ledger/attestations`.
|
||||
- Telemetry fields to include provenance IDs.
|
||||
## Agreed contract (PREP-LEDGER-OBS-54-001)
|
||||
- HTTP surface published in `docs/modules/findings-ledger/prep/ledger-attestations-http.md`.
|
||||
- Endpoint: `GET /v1/ledger/attestations` with tenant header `X-Stella-Tenant` and bearer scope `ledger.attest.read` (or mTLS).
|
||||
- Filters: `artifactId`, `findingId`, `attestationId`, `status`, `sinceRecordedAt`, `untilRecordedAt`, `limit`.
|
||||
- Ordering/pagination: deterministic by `recordedAt ASC, attestationId ASC`; pagination token encodes `{recordedAt, attestationId, filtersHash}`.
|
||||
- Response shape (JSON or NDJSON): ids, verification status/time, DSSE digest, optional Rekor entry id, evidence bundle ref, source ledger event id, Merkle leaf + root hashes.
|
||||
- Offline posture: no live Rekor calls; all hashes lowercase SHA-256; times UTC; deterministic sort only.
|
||||
|
||||
## Telemetry hooks
|
||||
- Log events: `ledger.attestations.query` (tenant, filtersHash, limit, duration_ms, result_count).
|
||||
- Metrics: `ledger_attestations_queries_total{tenant,status}`; `ledger_attestations_failures_total{reason}`.
|
||||
- Tracing: span `ledger.attestations.query` with attributes `filtersHash`, `next_page_token_present`.
|
||||
|
||||
## Handoff
|
||||
Use as PREP artefact; update once API contract is drafted.
|
||||
- Use `docs/modules/findings-ledger/prep/ledger-attestations-http.md` as the binding prep artefact for LEDGER-OBS-54-001 / 55-001 implementation.
|
||||
- Service scaffolding and OAS wiring land in LEDGER-OBS-54-001 once the web-service handler is added.
|
||||
|
||||
@@ -1,9 +1,52 @@
|
||||
# Ledger Packs Snapshot Prep — PREP-LEDGER-PACKS-42-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Status: Prep complete (2025-11-20)
|
||||
Owners: Findings Ledger Guild · Mirror Creator Guild
|
||||
Scope: Snapshot/time-travel contract for packs simulation.
|
||||
Scope: Snapshot/time-travel contract for packs simulation and offline CLI execution (PREP-LEDGER-PACKS-42-001).
|
||||
|
||||
## Needs
|
||||
- Snapshot format and bundle layout for pack simulation/time-travel.
|
||||
## Goals
|
||||
- Provide deterministic, tenant-scoped snapshots that let pack runners/CLI replay ledger state offline.
|
||||
- Allow “time-travel” queries (choose exact ledger sequence/cycle) to debug policy outcomes.
|
||||
- Reuse existing export shapes where possible and avoid redundant DB projections.
|
||||
|
||||
## Surfaces
|
||||
- `GET /v1/ledger/packs/snapshots`
|
||||
- Headers: `X-Stella-Tenant` (required), bearer scope `ledger.packs.read`.
|
||||
- Query: `atSequence` (long, optional), `atCycleHash` (string, optional), `sinceSequence` / `untilSequence` (long, optional), `page_size` (default 100, max 1000), `page_token`.
|
||||
- Returns: list of available snapshot descriptors (JSON or NDJSON) sorted by `sequence ASC`.
|
||||
- `GET /v1/ledger/packs/snapshots/{snapshotId}/download`
|
||||
- Streams a gzip tarball containing the snapshot bundle (see layout).
|
||||
- Supports `Accept: application/vnd.stella.pack-snapshot+tar` (default) or `application/x-ndjson` for manifest-only dry-run (no payload files) when `Prefer: return=representation` is absent.
|
||||
|
||||
## Snapshot descriptor fields
|
||||
- `snapshot_id` (uuid, stable)
|
||||
- `tenant`
|
||||
- `base_sequence` (long) — earliest ledger event included
|
||||
- `upper_sequence` (long) — last ledger event included (inclusive)
|
||||
- `cycle_hash` (string) — Merkle cycle hash at `upper_sequence`
|
||||
- `policy_version`, `projector_version`, `generator_version`
|
||||
- `created_at` (ISO-8601 UTC)
|
||||
- `approx_uncompressed_size_bytes`
|
||||
- `content` summary: counts for `findings`, `vex`, `advisories`, `sboms`
|
||||
|
||||
## Bundle layout (tar.gz)
|
||||
- `manifest.json`: descriptor above plus SHA-256 digests and lengths for each payload file.
|
||||
- `findings.ndjson`: canonical finding shape matching `/ledger/export/findings`.
|
||||
- `vex.ndjson`, `advisories.ndjson`, `sboms.ndjson`: same shapes/filters as export endpoints.
|
||||
- `indexes/`: optional bloom/filter helpers for fast CLI lookup (`component_purl`, `advisory_id`, `risk_profile_version`).
|
||||
- `provenance.json`: DSSE envelope with bundle hash, generator inputs (seed, source commit, policy version).
|
||||
|
||||
## Determinism and filters
|
||||
- Snapshot is deterministic for a given `(tenant, base_sequence, upper_sequence, cycle_hash, policy_version)`.
|
||||
- Page tokens: base64url JSON `{ "last": { "upper_sequence": long, "snapshot_id": uuid }, "filters_hash": sha256 }`.
|
||||
- When `atCycleHash` is provided, server resolves the closest <=matching cycle and emits one descriptor; otherwise uses `untilSequence` or latest committed.
|
||||
- No wall-clock dependence; `created_at` reflects generator runtime but is stored once and signed in provenance.
|
||||
|
||||
## Validation rules
|
||||
- Reject overwrite if snapshot with identical `(tenant, upper_sequence, cycle_hash)` already published (idempotent response with existing `snapshot_id`).
|
||||
- Reject if requested window crosses projector gap (missing sequences) with error `409` and `X-Stella-Gap-From/To`.
|
||||
- Enforce `page_size` consistency across tokens; 400 on mismatch.
|
||||
|
||||
## Artefact location
|
||||
- This prep: `docs/modules/findings-ledger/prep/2025-11-20-ledger-packs-42-001-prep.md`.
|
||||
- Bundle schema is derived from export shapes in `docs/modules/findings-ledger/export-http-surface.md`; SDK/OAS plumbing to be added in LEDGER-PACKS-42-001 implementation.
|
||||
|
||||
@@ -1,11 +1,50 @@
|
||||
# Ledger Risk Schema Prep — PREP-LEDGER-RISK-66-001/002
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Status: Prep complete (2025-11-20)
|
||||
Owners: Findings Ledger Guild · Risk Engine Guild
|
||||
Scope: Contract + data model for PREP-LEDGER-RISK-66-001/002 (risk scoring fields and deterministic upsert).
|
||||
|
||||
## Needs
|
||||
- Risk engine schema/contract inputs: `risk_score`, `risk_severity`, `profile_version`, `explanation_id`, indexes.
|
||||
- Migration plan to add fields.
|
||||
## Field definitions (canonical finding projection)
|
||||
- `risk_score` (numeric, 0–100, 2dp) — monotonic per `(finding_id, profile_version)`; computed by Risk Engine.
|
||||
- `risk_severity` (enum) — derived mapping: `critical >= 90`, `high >= 70`, `medium >= 40`, `low >= 10`, `informational < 10`.
|
||||
- `risk_profile_version` (string) — semantic version of the scoring policy/profile; required.
|
||||
- `risk_explanation_id` (uuid/string) — pointer to Risk Engine explanation payload stored in Risk service (not duplicated in ledger).
|
||||
- `risk_event_sequence` (long) — ledger sequence of the last applied risk event; enforces monotonic updates.
|
||||
- `risk_updated_at` (ISO-8601 UTC) — when the score was last written.
|
||||
|
||||
## Storage and indexes (MongoDB)
|
||||
- Collection: `findings` (existing). Add fields above to the projection document.
|
||||
- Unique compound index: `{ tenant: 1, finding_id: 1, risk_profile_version: 1 }`.
|
||||
- Query helper index for exports/UI: `{ tenant: 1, risk_severity: 1, risk_score: -1, observed_at: -1 }`.
|
||||
- TTL: none; scores are historical but superseded by deterministic upsert described below.
|
||||
|
||||
## Deterministic upsert flow (LEDGER-RISK-66-002)
|
||||
1. Risk Engine emits `RiskScoreApplied` event with `{tenant, finding_id, profile_version, score, explanation_id, event_sequence}`.
|
||||
2. Handler loads current projection by `(tenant, finding_id)`; compares `(profile_version, event_sequence)`:
|
||||
- If incoming `event_sequence` < stored `risk_event_sequence` → ignore (idempotent).
|
||||
- If equal → idempotent update allowed only when score/severity unchanged.
|
||||
- If greater → write new values and set `risk_event_sequence = event_sequence`.
|
||||
3. All writes recorded in ledger append with same event_sequence for audit; projection updates deterministic by sequence ordering.
|
||||
4. Exports (`/ledger/export/findings`) surface these fields; snapshot bundles reuse the same shape.
|
||||
|
||||
## API/SDK contract hooks
|
||||
- OAS baseline will mark all four fields in the finding shapes (canonical + compact) as optional today, required once migrations finish.
|
||||
- `/ledger/export/findings` filters: `risk_profile_version` (already reserved), add `risk_severity` and `risk_score_min/max` in the next OAS bump.
|
||||
- UI/SDK must treat missing `risk_profile_version` as “not yet scored”.
|
||||
|
||||
## Migration/rollout plan (LEDGER-RISK-66-001)
|
||||
- Step 1: Add fields and indexes behind feature flag `RiskScoringEnabled` (default off).
|
||||
- Step 2: Backfill for latest profile per tenant using Risk Engine batch export; write via deterministic upsert to enforce ordering.
|
||||
- Step 3: Enable streaming ingestion of `RiskScoreApplied` events; monitor lag via metric `ledger_risk_score_apply_lag_seconds`.
|
||||
- Step 4: Flip default for `RiskScoringEnabled` to on after backfill success criteria:
|
||||
- 99.9% of existing findings have `risk_profile_version` populated.
|
||||
- No rejected events due to sequence regressions in the last 24h.
|
||||
- Step 5: Update OAS/SDK to mark fields required; notify UI/Export consumers.
|
||||
|
||||
## Observability
|
||||
- Log: `ledger.risk.apply` with tenant, finding_id, profile_version, score, event_sequence, applied (bool).
|
||||
- Metrics: `ledger_risk_apply_total{result}`; `ledger_risk_score_latest{severity}` gauges per tenant.
|
||||
- Tracing: span `ledger.risk.apply` tagging `profile_version`, `event_sequence`, `idempotent`.
|
||||
|
||||
## Handoff
|
||||
Use as PREP artefact; update when risk field definitions and rollout plan are available.
|
||||
- This document is the prep artefact for PREP-LEDGER-RISK-66-001/002. Implementation tasks wire schema + deterministic upsert and extend exports/OAS accordingly.
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# Verification Event Contract (attestations → ledger_attestations)
|
||||
|
||||
Status: Draft (2025-11-21)
|
||||
Owners: Provenance Guild · Findings Ledger Guild
|
||||
|
||||
Purpose: unblock LEDGER-OBS-54-001 by defining the ingestion event emitted by the verifier so we can populate `ledger_attestations`.
|
||||
|
||||
```
|
||||
event_type: verification.attestation.completed
|
||||
payload:
|
||||
tenant_id: string (required)
|
||||
attestation_id: uuid (required)
|
||||
artifact_id: string (required; OCI digest or SBOM id)
|
||||
finding_id: string (optional)
|
||||
verification_status: string enum [verified, failed, unknown] (required)
|
||||
verification_time: string (ISO-8601 UTC, required)
|
||||
dsse_digest: string (sha256, lowercase, required)
|
||||
rekor_entry_id: string (optional)
|
||||
evidence_bundle_ref: string (optional)
|
||||
merkle_leaf_hash: string (sha256, required)
|
||||
root_hash: string (sha256, required)
|
||||
cycle_hash: string (required)
|
||||
projection_version: string (required)
|
||||
```
|
||||
|
||||
Ordering/monotonicity:
|
||||
- Events are emitted with a ledger `sequence_no`. Ingestion must ignore any verification event with `sequence_no` less than the stored `risk_event_sequence` for the same `(tenant_id, attestation_id)`.
|
||||
|
||||
Determinism for ingestion:
|
||||
- Sort by `(sequence_no ASC, attestation_id ASC)` before upsert.
|
||||
- Upsert target: `ledger_attestations` (see `004_ledger_attestations.sql`).
|
||||
|
||||
Open question:
|
||||
- Should `verification_status` include `expired`/`revoked`? Need decision before marking schema final.
|
||||
|
||||
Next step:
|
||||
- Once the verifier confirms this payload, wire ingestion job to project into `ledger_attestations` and flip LEDGER-OBS-54-001 to DOING.
|
||||
@@ -35,4 +35,5 @@
|
||||
|
||||
## Artefact location
|
||||
- This prep doc: `docs/modules/findings-ledger/prep/ledger-attestations-http.md`.
|
||||
- Storage/view contract: `docs/modules/findings-ledger/prep/ledger-attestations-storage.md`.
|
||||
- Add path to OAS in a follow-on increment (LEDGER-OAS-61-002/63-001) once approved.
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
# Ledger Attestations Storage & Query Contract (LEDGER-OBS-54-001)
|
||||
|
||||
Status: PrepComplete (2025-11-20)
|
||||
Owners: Findings Ledger Guild · Provenance Guild
|
||||
|
||||
## Goal
|
||||
Provide a deterministic storage/view contract so the `/v1/ledger/attestations` endpoint can be implemented without further design work.
|
||||
|
||||
## Table (proposed)
|
||||
- Name: `ledger_attestations`
|
||||
- Partitioning: tenant-scoped (same strategy as `ledger_events`).
|
||||
- Columns:
|
||||
- `tenant_id` (text, not null)
|
||||
- `attestation_id` (uuid, not null)
|
||||
- `artifact_id` (text, not null) — OCI digest or SBOM id
|
||||
- `finding_id` (text, null)
|
||||
- `verification_status` (text, not null; `verified|failed|unknown`)
|
||||
- `verification_time` (timestamptz, not null)
|
||||
- `dsse_digest` (text, not null; lowercase sha256)
|
||||
- `rekor_entry_id` (text, null)
|
||||
- `evidence_bundle_ref` (text, null)
|
||||
- `ledger_event_id` (uuid, not null) — source ledger event linking the attestation
|
||||
- `recorded_at` (timestamptz, not null)
|
||||
- `merkle_leaf_hash` (text, not null)
|
||||
- `root_hash` (text, not null)
|
||||
- `cycle_hash` (text, not null)
|
||||
- `projection_version` (text, not null)
|
||||
|
||||
## Indexes / ordering
|
||||
- PK: `(tenant_id, attestation_id)`
|
||||
- Paging index: `(tenant_id, recorded_at, attestation_id)` to back deterministic sort `recorded_at ASC, attestation_id ASC`.
|
||||
- Lookup indexes:
|
||||
- `(tenant_id, artifact_id, recorded_at DESC)`
|
||||
- `(tenant_id, finding_id, recorded_at DESC)`
|
||||
- `(tenant_id, verification_status, recorded_at DESC)`
|
||||
|
||||
## Query contract for `/v1/ledger/attestations`
|
||||
- Filters map to indexed columns: `artifactId`, `findingId`, `attestationId`, `status`, `sinceRecordedAt`, `untilRecordedAt`.
|
||||
- Pagination token encodes `{ recordedAt, attestationId, filtersHash }`; server must reject mismatched hash.
|
||||
- Response fields align 1:1 with columns above; no joins required.
|
||||
- Determinism: sort strictly by `(recorded_at ASC, attestation_id ASC)`; no server clocks in payload.
|
||||
|
||||
## Migration notes
|
||||
- Add table and indexes in the same migration (see `src/Findings/StellaOps.Findings.Ledger/migrations/004_ledger_attestations.sql`).
|
||||
- Backfill from existing provenance/verification store (if present) into this table with recorded_at = original verification timestamp.
|
||||
- Ensure writes/coalescing happen via ledger projections to keep `ledger_event_id`/`cycle_hash` consistent.
|
||||
|
||||
## Observability
|
||||
- Logs: `ledger.attestations.query` (tenant, filtersHash, limit, duration_ms, result_count).
|
||||
- Metrics: `ledger_attestations_queries_total{tenant,status}`, `ledger_attestations_failures_total{reason}`; reuse endpoint spans already defined in prep doc.
|
||||
|
||||
## Artefact location
|
||||
- Storage contract: `docs/modules/findings-ledger/prep/ledger-attestations-storage.md`
|
||||
- HTTP contract: `docs/modules/findings-ledger/prep/ledger-attestations-http.md`
|
||||
@@ -161,6 +161,10 @@ Stores the latest verdict/state per finding.
|
||||
| `policy_version` | `text` | Active policy digest. |
|
||||
| `status` | `text` | e.g., `affected`, `triaged`, `accepted_risk`, `resolved`. |
|
||||
| `severity` | `numeric(6,3)` | Normalised severity score (0-10). |
|
||||
| `risk_score` | `numeric(6,3)` | Risk scoring result (0-10) from Risk Engine/Policy. |
|
||||
| `risk_severity` | `text` | Risk category (e.g., `low`, `medium`, `high`, `critical`). |
|
||||
| `risk_profile_version` | `text` | Risk profile hash/version used for scoring. |
|
||||
| `risk_explanation_id` | `uuid` | Reference to risk explanation document. |
|
||||
| `labels` | `jsonb` | Key-value metadata (tags, KEV flag, runtime signals). |
|
||||
| `current_event_id` | `uuid` | Ledger event that produced this state. |
|
||||
| `explain_ref` | `text` | Reference to explain bundle or object storage key. |
|
||||
@@ -173,6 +177,7 @@ Primary key: `(tenant_id, finding_id, policy_version)`.
|
||||
Indexes:
|
||||
|
||||
- `ix_projection_status` on `(tenant_id, status, severity DESC)`.
|
||||
- `ix_projection_risk` on `(tenant_id, risk_severity, risk_score DESC)`.
|
||||
- `ix_projection_labels_gin` using `labels` GIN for KEV/runtime filters.
|
||||
|
||||
### 4.2 `finding_history`
|
||||
|
||||
12
docs/modules/graph/prep/2025-11-20-ops-0001-prep.md
Normal file
12
docs/modules/graph/prep/2025-11-20-ops-0001-prep.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Graph Ops Prep — PREP-GRAPH-OPS-0001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Ops Guild
|
||||
Scope: Capture dashboard/runbook updates pending next demo outputs.
|
||||
|
||||
## Needs
|
||||
- Latest demo metrics/dashboards to review.
|
||||
- Runbook sections to update once demo outputs land.
|
||||
|
||||
## Handoff
|
||||
Use as prep artefact; update after next demo provides dashboards/runbooks.
|
||||
12
docs/modules/notifier/prep/2025-11-20-ten-48-001-prep.md
Normal file
12
docs/modules/notifier/prep/2025-11-20-ten-48-001-prep.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Notifier Tenancy Prep — PREP-NOTIFY-TEN-48-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Notifications Service Guild
|
||||
Scope: Tenancy model and DAL/routes for Notifier (depends on Notifier II sprint).
|
||||
|
||||
## Needs
|
||||
- Tenancy model decision; DAL/routes for tenant context in Notifier WebService.
|
||||
- Alignment with Notifier II scope (Sprint 0172).
|
||||
|
||||
## Handoff
|
||||
Use as prep artefact; update when tenancy model is published.
|
||||
21
docs/modules/orchestrator/prep/2025-11-20-oas-63-001-prep.md
Normal file
21
docs/modules/orchestrator/prep/2025-11-20-oas-63-001-prep.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Orchestrator OAS Deprecations Prep — PREP-ORCH-OAS-63-001-DEPENDS-ON-62-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Orchestrator Service Guild · API Governance Guild
|
||||
Scope: Define deprecation headers/docs for legacy orchestrator endpoints once OAS 61/62 are finalized.
|
||||
|
||||
## Dependencies
|
||||
- Final OAS base (61-001) and discovery (62-001).
|
||||
- List of endpoints to deprecate and replacement mapping.
|
||||
|
||||
## Proposed contract
|
||||
- Add `Deprecation` header and `Link` rel="alternate" to new endpoints.
|
||||
- Update OAS with `deprecated: true` and description of replacement.
|
||||
- Include changelog section and example responses showing headers.
|
||||
|
||||
## Acceptance
|
||||
- Replacement map documented in this file and in `docs/modules/orchestrator/api.md` once OAS is regenerated.
|
||||
- Sample response with deprecation headers under `docs/modules/orchestrator/samples/orch-deprecation@draft.json`.
|
||||
|
||||
## Handoff
|
||||
Use this prep doc to satisfy PREP-ORCH-OAS-63-001-DEPENDS-ON-62-001. Update after 61/62 freeze; then mark task DONE and proceed with implementation.
|
||||
11
docs/modules/orchestrator/prep/2025-11-20-ten-48-001-prep.md
Normal file
11
docs/modules/orchestrator/prep/2025-11-20-ten-48-001-prep.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Orchestrator Tenancy Prep — PREP-ORCH-TEN-48-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Orchestrator Service Guild
|
||||
Scope: WebService job DAL/routes tenancy context prior to enforcement.
|
||||
|
||||
## Needs
|
||||
- Tenant context plumbing and RLS rules for job DAL/routes.
|
||||
|
||||
## Handoff
|
||||
Use as prep artefact; update once tenancy model decisions are finalized.
|
||||
@@ -0,0 +1,25 @@
|
||||
# Advisory AI Knobs Prep — PREP-POLICY-ENGINE-31-001-ADVISORY-AI-KNOBS-R
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Policy Guild
|
||||
Scope: Outline the configuration knobs for Advisory AI scoring once trust weighting (30-101) is defined.
|
||||
|
||||
## Dependencies
|
||||
- Trust weighting API/contracts (30-101).
|
||||
- Advisory AI signal list and confidence model (not yet finalized).
|
||||
|
||||
## Draft configuration fields
|
||||
- `weights` (from 30-101) applied to AI-produced signals.
|
||||
- `knobs[]` array of `{name, default_value, min, max, step, description}` for:
|
||||
- `ai_signal_weight`
|
||||
- `reachability_boost`
|
||||
- `time_decay_half_life_days`
|
||||
- `evidence_freshness_threshold_hours`
|
||||
- Output preview: recomputed severity/exploitability per advisory/component.
|
||||
|
||||
## Acceptance to close PREP
|
||||
- Map knobs to actual AI signals once published; confirm allowed ranges.
|
||||
- Document schema at `docs/modules/policy/schemas/advisory-ai-knobs@draft.json` and sample request at `docs/modules/policy/samples/advisory-ai-knobs@draft.json`.
|
||||
|
||||
## Handoff
|
||||
Use this document as the prep artefact for PREP-POLICY-ENGINE-31-001-ADVISORY-AI-KNOBS-R. Update with final signal list and ranges once trust weighting is frozen.
|
||||
21
docs/modules/policy/prep/2025-11-20-batch-context-prep.md
Normal file
21
docs/modules/policy/prep/2025-11-20-batch-context-prep.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Batch Context Endpoint Prep — PREP-POLICY-ENGINE-31-002-BATCH-CONTEXT-ENDPO
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Policy Guild
|
||||
Scope: Define the batch context endpoint contract that builds on Advisory AI knobs (31-001) and trust weighting outputs.
|
||||
|
||||
## Dependencies
|
||||
- Final knobs list from 31-001.
|
||||
- Policy profile schema (hash + version) from 30-001 overlays.
|
||||
|
||||
## Draft API surface
|
||||
- `POST /policy/batch/context` with payload: `{tenant_id, policy_profile_hash, knobs_version, overlay_hash, items:[{component_purl, advisory_id}], options:{include_reachability:boolean}}`.
|
||||
- Response: `{context_id, expires_at, knobs_version, overlay_hash, items:[{component_purl, advisory_id, status, trace_ref}]}`.
|
||||
- Determinism: items sorted by `(component_purl, advisory_id)`; `context_id` derived as hash of request payload.
|
||||
|
||||
## Acceptance to close PREP
|
||||
- Align fields with 31-001 knobs and 30-001 overlay schema; record hashes/versions.
|
||||
- Save draft schema at `docs/modules/policy/schemas/policy-batch-context@draft.json` and sample at `docs/modules/policy/samples/policy-batch-context@draft.json`.
|
||||
|
||||
## Handoff
|
||||
Use this document as the prep artefact for PREP-POLICY-ENGINE-31-002-BATCH-CONTEXT-ENDPO. Update when knobs and overlays freeze; then move implementation to DOING.
|
||||
23
docs/modules/policy/prep/2025-11-20-change-events-prep.md
Normal file
23
docs/modules/policy/prep/2025-11-20-change-events-prep.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Change Events Prep — PREP-POLICY-ENGINE-30-003-CHANGE-EVENTS-DEPEN
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Policy Guild · Scheduler Guild · Cartographer Guild
|
||||
Scope: Define the change-event payload and scheduling expectations following simulation bridge (30-002).
|
||||
|
||||
## Dependencies
|
||||
- Simulation bridge output schema (30-002).
|
||||
- Scheduler delivery channel (NATS/Redis) subject names and dedupe policy.
|
||||
|
||||
## Draft event envelope
|
||||
- `event_type`: `policy.overlay.change`
|
||||
- Fields: `tenant_id`, `overlay_hash`, `policy_profile_hash`, `simulation_id?`, `changes[]` (array of `{component_purl, advisory_id, prev_status, new_status, severity_delta?, trace_ref}`), `occurred_at` (UTC), `event_id` (deterministic ID = hash of overlay_hash + timestamp).
|
||||
- Transport: propose NATS subject `policy.overlay.change` with durable stream; idempotency key = `event_id`.
|
||||
- Observability: counter `policy_overlay_change_total{tenant,result}`; log template includes overlay_hash, event_id, change_count.
|
||||
|
||||
## Acceptance to close PREP
|
||||
- Subject/stream names confirmed with Scheduler.
|
||||
- JSON schema stub saved at `docs/modules/policy/schemas/policy-overlay-change@draft.json`.
|
||||
- Sample event at `docs/modules/policy/samples/policy-overlay-change@draft.json`.
|
||||
|
||||
## Handoff
|
||||
This document serves as the prep artefact for PREP-POLICY-ENGINE-30-003-CHANGE-EVENTS-DEPEN. Update once 30-002 finalizes schema/subject; then unblock the implementation task.
|
||||
@@ -0,0 +1,21 @@
|
||||
# Conflict Handling Prep — PREP-POLICY-ENGINE-40-002-CONFLICT-HANDLING-D
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Policy Guild · Excititor Guild
|
||||
Scope: Define conflict-handling rules after severity fusion (40-001).
|
||||
|
||||
## Dependencies
|
||||
- Severity fusion output schema (40-001).
|
||||
- Excititor/Console precedence context expectations for conflicts.
|
||||
|
||||
## Draft approach
|
||||
- Detect conflicts when multiple fused severities differ for same `{component_purl, advisory_id}` across tenants or sources.
|
||||
- Emit conflict record: `{tenant_id, component_purl, advisory_id, conflicts:[{source, field, value, reason_code}] , resolved_status?, trace_ref}`.
|
||||
- Resolution policy: default “no auto-resolve”; optional operator override flag per policy profile.
|
||||
|
||||
## Acceptance
|
||||
- Draft schema at `docs/modules/policy/schemas/policy-conflict@draft.json` and sample at `docs/modules/policy/samples/policy-conflict@draft.json`.
|
||||
- Mapping of reason codes to Excititor Console cache/RBAC needs documented once 23-003 finalizes.
|
||||
|
||||
## Handoff
|
||||
This document is the prep artefact for PREP-POLICY-ENGINE-40-002-CONFLICT-HANDLING-D. Update once severity fusion rules are frozen and Console expectations are known; then move implementation to DOING.
|
||||
21
docs/modules/policy/prep/2025-11-20-ledger-export-prep.md
Normal file
21
docs/modules/policy/prep/2025-11-20-ledger-export-prep.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Ledger Export Prep — PREP-POLICY-ENGINE-34-101-LEDGER-EXPORT-REQUI
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Policy Guild
|
||||
Scope: Define ledger export requirements once worker results (33-101) exist.
|
||||
|
||||
## Dependencies
|
||||
- Worker result schema (33-101).
|
||||
- Storage/ledger format choice (Mongo vs Postgres) and retention policy.
|
||||
|
||||
## Draft export shape
|
||||
- Export file: NDJSON with entries `{tenant_id, job_id, context_id, component_purl, advisory_id, status, trace_ref, occurred_at}`.
|
||||
- Manifest: `{export_id, schema_version, generated_at, record_count, sha256}` with DSSE envelope optional.
|
||||
- Ordering: stable by `(tenant_id, job_id, component_purl, advisory_id)`.
|
||||
|
||||
## Acceptance
|
||||
- Draft schema at `docs/modules/policy/schemas/policy-ledger-export@draft.json` and sample at `docs/modules/policy/samples/policy-ledger-export@draft.json`.
|
||||
- Retention knobs documented (TTL/size caps) once storage decision is made.
|
||||
|
||||
## Handoff
|
||||
Use this as the prep artefact for PREP-POLICY-ENGINE-34-101-LEDGER-EXPORT-REQUI. Update with storage/retention decisions, then unblock implementation.
|
||||
@@ -0,0 +1,21 @@
|
||||
# Orchestrator Job Schema Prep — PREP-POLICY-ENGINE-32-101-ORCHESTRATOR-JOB-SC
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Policy Guild
|
||||
Scope: Outline the job schema needed for orchestrator scheduling once batch context (31-002) is available.
|
||||
|
||||
## Dependencies
|
||||
- Batch context contract (31-002).
|
||||
- Orchestrator capsule envelope (Wave 150/140) for job submission fields.
|
||||
|
||||
## Draft job schema
|
||||
- Fields: `job_id` (ULID), `tenant_id`, `context_id` (from 31-002), `policy_profile_hash`, `requested_at`, `priority`, `batch_items[]` referencing `{component_purl, advisory_id}`, `callbacks` (SSE/NATS subjects), `trace_ref` (dsse hash).
|
||||
- Status lifecycle: `queued` → `running` → `completed`|`failed`; deterministic transitions logged.
|
||||
- Determinism: job_id derived from hash of `(tenant_id, context_id, requested_at ISO)`, ordered batch_items.
|
||||
|
||||
## Acceptance
|
||||
- Schema stub stored at `docs/modules/policy/schemas/orchestrator-job@draft.json` plus sample at `docs/modules/policy/samples/orchestrator-job@draft.json`.
|
||||
- Subject/callback expectations aligned with Orchestrator envelopes.
|
||||
|
||||
## Handoff
|
||||
Prep artefact for PREP-POLICY-ENGINE-32-101-ORCHESTRATOR-JOB-SC. Update with final Orchestrator envelope fields and batch context hash once available.
|
||||
@@ -0,0 +1,21 @@
|
||||
# Policy AirGap Import Prep — PREP-POLICY-AIRGAP-56-002-DEPENDS-ON-56-001-B
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Policy Guild · Policy Studio Guild
|
||||
Scope: Define policy bundle import and DSSE signing expectations once mirror bundle schema (56-001) is fixed.
|
||||
|
||||
## Dependencies
|
||||
- Mirror bundle schema from 56-001 (fields: bundle_id, provenance, policy_hash, trust_roots, retained_at).
|
||||
- DSSE signing profile and RootPack mapping.
|
||||
|
||||
## Expected contract
|
||||
- Import endpoint: `POST /policy/airgap/import` accepting mirror bundle (file) + metadata.
|
||||
- Validation: verify DSSE, trust roots, policy hashes; reject on staleness over budget.
|
||||
- Response: `{bundle_id, policy_hash, imported_at, staleness_seconds}` ordered deterministically.
|
||||
|
||||
## Acceptance
|
||||
- Once 56-001 schema is frozen, record hash+version here and in sprint Decisions.
|
||||
- Add sample request/response to `docs/modules/policy/design/policy-mirror-bundle-schema.md` and samples folder.
|
||||
|
||||
## Handoff
|
||||
Use this doc as the prep artefact for PREP-POLICY-AIRGAP-56-002-DEPENDS-ON-56-001-B. Update with schema hash and DSSE profile when available, then move sprint task to DONE.
|
||||
@@ -0,0 +1,21 @@
|
||||
# Policy AirGap Sealed-Mode Prep — PREP-POLICY-AIRGAP-57-001-REQUIRES-SEALED-MOD
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Policy Guild · AirGap Policy Guild
|
||||
Scope: Define sealed-mode policy behaviour and error envelopes after mirror import (56-002).
|
||||
|
||||
## Inputs needed
|
||||
- Sealed-mode error envelope standard (WEB-OAS-61-002) for consistency with Concelier/Web.
|
||||
- Staleness metadata fields from 56-002 (bundle provenance / time anchor).
|
||||
|
||||
## Proposed behavior
|
||||
- When sealed mode active and non-mirror source requested, return error `POLICY_AIRGAP_EGRESS_BLOCKED` with remediation list and `staleness_seconds_remaining` if available.
|
||||
- Determinism: sorted remediation items; canonical JSON ordering.
|
||||
- Telemetry: counter `policy_airgap_egress_blocked_total{tenant,endpoint}` and event `policy.airgap.egress_blocked` with `{tenant_id, bundle_id?, policy_hash}`.
|
||||
|
||||
## Acceptance
|
||||
- Envelope finalized in line with WEB-OAS-61-002; fields confirmed with AirGap Policy Guild.
|
||||
- Sample response stored at `docs/modules/policy/samples/policy-airgap-sealed@draft.json`.
|
||||
|
||||
## Handoff
|
||||
Prep artefact for PREP-POLICY-AIRGAP-57-001-REQUIRES-SEALED-MOD. Update once error envelope and staleness fields are frozen; then mark task DONE and start implementation.
|
||||
@@ -0,0 +1,21 @@
|
||||
# Policy Staleness Fallback Prep — PREP-POLICY-AIRGAP-57-002-NEEDS-STALENESS-FAL
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Policy Guild · AirGap Time Guild
|
||||
Scope: Define staleness/fallback data contract for policy responses once sealed-mode (57-001) is defined.
|
||||
|
||||
## Dependencies
|
||||
- Sealed-mode error envelope (57-001).
|
||||
- Time anchor/staleness metadata from AirGap Controller/Time (56-002 chain).
|
||||
|
||||
## Proposed additions
|
||||
- Response headers: `x-policy-bundle-id`, `x-policy-staleness-seconds-remaining`.
|
||||
- Body enrichment: `staleness_seconds_remaining`, `bundle_id`, optional `time_anchor_id` in error responses or health endpoints.
|
||||
- Determinism: values sourced from stored bundle metadata; no wall-clock dependencies beyond persisted timestamps.
|
||||
|
||||
## Acceptance
|
||||
- Confirm header names with AirGap Time Guild and align with Concelier Web sealed responses.
|
||||
- Sample response documented under `docs/modules/policy/samples/policy-staleness@draft.json`.
|
||||
|
||||
## Handoff
|
||||
Use this prep doc to satisfy PREP-POLICY-AIRGAP-57-002-NEEDS-STALENESS-FAL. Update with final header names and sample once 57-001 and 56-002 stabilize; then mark task DONE.
|
||||
@@ -0,0 +1,21 @@
|
||||
# Policy AirGap Notifications Prep — PREP-POLICY-AIRGAP-58-001-NOTIFICATION-SCHEMA
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Policy Guild · Notifications Guild
|
||||
Scope: Define notification schema and staleness signals after staleness fallback (57-002).
|
||||
|
||||
## Dependencies
|
||||
- Staleness metadata fields from 57-002.
|
||||
- Notifications envelope alignment with Orchestrator/Notifications schema.
|
||||
|
||||
## Draft notification
|
||||
- Event: `policy.airgap.bundle.updated`
|
||||
- Fields: `tenant_id`, `bundle_id`, `policy_hash`, `staleness_seconds_remaining`, `time_anchor_id?`, `occurred_at`, `event_id`.
|
||||
- Transport: NATS subject `policy.airgap.bundle.updated`; durable stream; idempotency via `event_id` (hash of bundle_id + occurred_at).
|
||||
|
||||
## Acceptance
|
||||
- Schema sample stored at `docs/modules/policy/samples/policy-airgap-notification@draft.json`.
|
||||
- Subject/retention agreed with Notifications Guild.
|
||||
|
||||
## Handoff
|
||||
Prep artefact for PREP-POLICY-AIRGAP-58-001-NOTIFICATION-SCHEMA. Fill in schema hash/subject once 57-002 finalizes; then move to DONE.
|
||||
@@ -0,0 +1,17 @@
|
||||
# Policy Linting Prep — PREP-POLICY-AOC-19-001-NEEDS-AGREED-LINTING-T
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Policy Guild
|
||||
Scope: Define lint/analyzer targets for Policy AOC ingestion paths to unblock linting tasks.
|
||||
|
||||
## Required decisions
|
||||
- Target projects: `StellaOps.Policy.Engine`, `StellaOps.Policy.*` libraries to include; excluded generated files.
|
||||
- Rule set: nullability, async/sync mix, determinism (no DateTime.Now/Guid.NewGuid), ordering, and JSON property ordering rules.
|
||||
- CI wiring: which pipeline, severity thresholds, baselines.
|
||||
|
||||
## Acceptance
|
||||
- Publish agreed rule set and target list in `docs/modules/policy/design/policy-aoc-linting-rules.md`.
|
||||
- Add baseline suppressions file path if needed.
|
||||
|
||||
## Handoff
|
||||
Use this doc as the prep artefact for PREP-POLICY-AOC-19-001-NEEDS-AGREED-LINTING-T. Update with agreed rule set; then mark the sprint task DONE.
|
||||
@@ -0,0 +1,20 @@
|
||||
# Policy AOC Gate Prep — PREP-POLICY-AOC-19-002-DEPENDS-ON-19-001-LINT
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Policy Guild · Platform Security
|
||||
Scope: Capture gate requirements after linting rules (19-001) are defined.
|
||||
|
||||
## Dependencies
|
||||
- Agreed lint rule set from 19-001.
|
||||
- Authority contract for `effective:write` gate.
|
||||
|
||||
## Proposed gate
|
||||
- CI gate checks lint + determinism rules; blocks PRs without suppressions approval.
|
||||
- Requires `effective:write` or similar scope for rule bypass; audit logged.
|
||||
|
||||
## Acceptance
|
||||
- Document gate behavior in `docs/modules/policy/design/policy-aoc-gate.md` and add sample CI snippet.
|
||||
- Record Authority scope names once confirmed.
|
||||
|
||||
## Handoff
|
||||
Use this prep doc for PREP-POLICY-AOC-19-002-DEPENDS-ON-19-001-LINT. Update when lint rules and auth scopes are finalized; then mark task DONE and unblock implementation.
|
||||
@@ -0,0 +1,21 @@
|
||||
# Policy Normalized Field Removal Prep — PREP-POLICY-AOC-19-003-REQUIRES-DECISIONED-NO
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Policy Guild
|
||||
Scope: Define decisioned normalized-field removal once gate (19-002) is in place.
|
||||
|
||||
## Dependencies
|
||||
- Gate/lint outcomes from 19-002.
|
||||
- Decision on which normalized fields to drop vs keep (need product/architecture sign-off).
|
||||
|
||||
## Draft plan
|
||||
- Candidate fields to remove: legacy `normalized_score`, deprecated `source_rank`, any duplicated severity fields.
|
||||
- Keep: deterministic canonical severity, policy profile hashes.
|
||||
- Output: migration plan + fixtures showing before/after payloads.
|
||||
|
||||
## Acceptance
|
||||
- Agree field list and migration steps; document in `docs/modules/policy/design/policy-normalized-field-removal.md`.
|
||||
- Fixtures placed under `docs/modules/policy/samples/policy-normalized-field-removal*.json`.
|
||||
|
||||
## Handoff
|
||||
Prep artefact for PREP-POLICY-AOC-19-003-REQUIRES-DECISIONED-NO. Update with final field list once decisions made; then mark sprint task DONE.
|
||||
@@ -0,0 +1,20 @@
|
||||
# Policy Determinism Fixtures Prep — PREP-POLICY-AOC-19-004-DEPENDENT-ON-19-003-DA
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Policy Guild · QA Guild
|
||||
Scope: Define data shape and determinism fixtures after normalized-field decisions (19-003).
|
||||
|
||||
## Dependencies
|
||||
- Field removal list from 19-003.
|
||||
- Deterministic ordering/canonical JSON rules.
|
||||
|
||||
## Plan
|
||||
- Prepare fixtures showing deterministic ordering and absence of removed fields.
|
||||
- Add test harness notes for `StellaOps.Policy` libraries to validate canonical JSON and stable sorting.
|
||||
|
||||
## Acceptance
|
||||
- Fixtures placed under `docs/modules/policy/samples/policy-determinism-fixtures@draft.json`.
|
||||
- Update `docs/modules/policy/design/policy-determinism-tests.md` with expectations.
|
||||
|
||||
## Handoff
|
||||
Use this prep doc for PREP-POLICY-AOC-19-004-DEPENDENT-ON-19-003-DA. Update once field removal list is frozen; then mark task DONE and unblock implementation tests.
|
||||
@@ -0,0 +1,29 @@
|
||||
# Policy Attestation Prep — PREP-POLICY-ATTEST-73-001
|
||||
|
||||
Status: **Ready for implementation** (2025-11-20)
|
||||
Owners: Policy Guild · Attestor Service Guild
|
||||
Scope: Define VerificationPolicy schema + persistence/DTOs for policy-engine to verify attestation results from Attestor.
|
||||
|
||||
## Requirements
|
||||
- Schema `VerificationPolicy` with fields:
|
||||
- `id` (string), `tenantId`, `name`, `description`, `createdAtUtc`, `updatedAtUtc` (ISO-8601 UTC)
|
||||
- `subjects`: array of `{ subjectRef, matchKind: digest|purl|nevra }`
|
||||
- `requiredAttestors`: array of `{ name, keyId, threshold }`
|
||||
- `transparency`: `{ required: bool, log: string? }`
|
||||
- `validity`: `{ notBeforeUtc, notAfterUtc }`
|
||||
- DTOs for API/SDK must preserve deterministic ordering of arrays (sorted by `subjectRef`, then `name`).
|
||||
- Store in Mongo `verificationPolicies` collection with unique index on `(tenantId, id)`.
|
||||
|
||||
## API surface (policy-engine)
|
||||
- `POST /v1/policy/verification-policies` create; `GET /v1/policy/verification-policies/{id}` fetch; `GET /v1/policy/verification-policies` list with pagination; `DELETE /v1/policy/verification-policies/{id}`.
|
||||
- Standard error envelope; headers align with existing policy API (ETag on GET; `Last-Modified`).
|
||||
|
||||
## Persistence rules
|
||||
- Immutable `createdAtUtc`; `updatedAtUtc` set on mutations; soft-delete not required.
|
||||
- Validation: `requiredAttestors.threshold >=1`, unique `keyId` per policy, `validity.notAfterUtc` > `notBeforeUtc`.
|
||||
|
||||
## Acceptance criteria
|
||||
- Schema & API documented and linked from sprint tracker; no code changes yet.
|
||||
- Examples use fixed timestamps `2025-01-01T00:00:00Z` and sample hashes `sha256:0123...`.
|
||||
- Collections/indexes specified; DTO ordering deterministic.
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# Policy Attestation Prep — PREP-POLICY-ATTEST-73-002
|
||||
|
||||
Status: **Ready for implementation** (2025-11-20)
|
||||
Owners: Policy Guild
|
||||
Scope: Define editor DTOs/validation schema for linking VerificationPolicy (73-001) into policy-engine UI/SDK.
|
||||
|
||||
## Requirements
|
||||
- Editor DTO `VerificationPolicyUpdate` with fields mirroring 73-001 schema; arrays sorted.
|
||||
- Validation rules: same as 73-001, plus max subjects = 500, max requiredAttestors = 20.
|
||||
- Error codes: `ValidationFailed`, `DuplicateKey`, `NotFound`.
|
||||
|
||||
## Acceptance criteria
|
||||
- DTOs + validation rules documented; examples with fixed timestamps and hashes.
|
||||
- SDK notes: generated models should expose immutable collections and validation annotations.
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# Policy Attestation Prep — PREP-POLICY-ATTEST-74-001
|
||||
|
||||
Status: **Ready for implementation** (2025-11-20)
|
||||
Owners: Policy Guild · Attestor Service Guild
|
||||
Scope: Define policy-engine surface to consume attestation verification results (from 73-002) and expose in reports/notifications.
|
||||
|
||||
## Requirements
|
||||
- Add projection schema `PolicyAttestationResult` with fields `{ policyId, verificationPolicyId, attestationId, status: passed|failed|pending, verifiedAtUtc, evidenceBundleId?, notes }`.
|
||||
- API endpoint `GET /v1/policy/attestations/{policyId}` returning paged results; supports filters `status`, `verificationPolicyId`.
|
||||
- Timeline/notification hook placeholder (depends on envelope schemas) noted; not required to implement now.
|
||||
|
||||
## Acceptance criteria
|
||||
- Schema, endpoint, filters documented with deterministic examples (timestamps `2025-01-01T00:00:00Z`).
|
||||
- Status set to DONE once doc published; code follows in dependent tasks.
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# Policy Attestation Prep — PREP-POLICY-ATTEST-74-002
|
||||
|
||||
Status: **Ready for implementation** (2025-11-20)
|
||||
Owners: Policy Guild · Console Guild
|
||||
Scope: Surface 74-001 attestation results into Console verification reports.
|
||||
|
||||
## Requirements
|
||||
- Console payload extension: add `policyAttestations` array to verification report DTO with `{ policyId, verificationPolicyId, status, verifiedAtUtc }`.
|
||||
- Sorting: order by `policyId` then `verifiedAtUtc`.
|
||||
- Backward compatibility: field optional; default empty array.
|
||||
|
||||
## Acceptance criteria
|
||||
- DTO change documented; examples with fixed timestamp; no code yet.
|
||||
- Update sprint tracker once doc published.
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Deterministic Evaluator Prep — PREP-POLICY-ENGINE-20-002-BUILD-DETERMINISTIC
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Policy Guild
|
||||
Scope: Capture contract and constraints for deterministic policy evaluator before implementation.
|
||||
|
||||
## Requirements
|
||||
- Deterministic execution: no wall-clock, no RNG, no network; inputs must be content-addressed.
|
||||
- Ordering: lexical rule ordering; first-match semantics; stable reduction order over inputs.
|
||||
- Safe value types: disallow floats where not needed; prefer decimal with fixed scale.
|
||||
- Timestamps: if required, use supplied `context.now` injected value, not system clock.
|
||||
|
||||
## Deliverables
|
||||
- Document evaluator contract and constraints in `docs/modules/policy/design/deterministic-evaluator.md`.
|
||||
- Provide sample config and test vectors under `docs/modules/policy/samples/deterministic-evaluator/` (hashes recorded in the design doc).
|
||||
|
||||
## Handoff
|
||||
Use this doc as the prep artefact for PREP-POLICY-ENGINE-20-002-BUILD-DETERMINISTIC. Once constraints and samples are frozen, mark the sprint task DONE and unblock POLICY-ENGINE-20-002.
|
||||
@@ -0,0 +1,44 @@
|
||||
# Policy Engine · Path/Scope Schema Prep (POLICY-ENGINE-29-002)
|
||||
|
||||
- **Date:** 2025-11-20
|
||||
- **Working directory:** `src/Policy/StellaOps.Policy.Engine`
|
||||
- **Purpose:** Unblock path-aware evaluation chain (tasks 29-003/004 and overlays 30-001..30-003) by freezing the canonical path/scope schema and examples.
|
||||
|
||||
## Schema (authoritative fields)
|
||||
`PathScope` object used across evaluator inputs, telemetry, and snapshots:
|
||||
- `tenant` (string, required) — tenant isolation key.
|
||||
- `subject` (object) — affected asset:
|
||||
- `purl` (string) or `cpe` (string) — at least one required.
|
||||
- `packagePath` (string, optional) — normalized module path within package (e.g., `lib/utils/a.js`).
|
||||
- `osImage` (string, optional) — container image ref if OS-level advisory.
|
||||
- `locator` (object) — where evidence was found:
|
||||
- `filePath` (string, required) — repo or image path using POSIX separators.
|
||||
- `digest` (string, optional) — SHA-256 of file content; hex, lowercase.
|
||||
- `treeDigest` (string, optional) — Merkle root for build tree snapshot.
|
||||
- `vulnerability` (object) — identifiers present in evidence (facts only): `cve`, `ghsa`, `osv`, `advisoryId`, `source`.
|
||||
- `provenance` (object) — `ingestedAt` (ISO-8601 UTC), `evidenceHash` (hex), `connectorId` (string), `dsseEnvelopeHash` (optional hex) for replay.
|
||||
- `scope` (object) — evaluation bounding box:
|
||||
- `pathMatch` (enum) `exact|prefix|glob` with `pattern` (string) using POSIX separators.
|
||||
- `confidence` (float 0..1) — how confident the analyzer is about the path binding.
|
||||
- `depthLimit` (int, optional) — maximum traversal depth for prefix/glob bindings.
|
||||
|
||||
## Determinism
|
||||
- Canonical ordering: subject fields ordered as listed; pathMatch evaluation uses lexical order, then `confidence` desc, then `filePath` asc for tie-breaking.
|
||||
- Hashing: `evidenceHash` = SHA-256 over normalized JSON of the observation with sorted properties and UTF-8 encoding.
|
||||
|
||||
## Sample payload
|
||||
```json
|
||||
{
|
||||
"tenant": "acme",
|
||||
"subject": {"purl": "pkg:npm/lodash@4.17.21", "packagePath": "lib/isEqual.js"},
|
||||
"locator": {"filePath": "src/lib/isEqual.js", "digest": "c1ab..."},
|
||||
"vulnerability": {"ghsa": "GHSA-35jh-r3h4-6jhm", "source": "ghsa"},
|
||||
"provenance": {"ingestedAt": "2025-11-20T00:00:00Z", "evidenceHash": "4f9b...", "connectorId": "excititor-ghsa"},
|
||||
"scope": {"pathMatch": "prefix", "pattern": "src/lib/", "confidence": 0.92, "depthLimit": 3}
|
||||
}
|
||||
```
|
||||
|
||||
## Acceptance for prep completion
|
||||
- Path/Scope schema above is frozen for sprint 0125; downstream tasks must align or update this doc and sprint risks if changes occur.
|
||||
- Sample payload provided for fixtures/tests; hashing and ordering rules documented for determinism.
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# Policy Engine · Path-Aware Observability Prep (POLICY-ENGINE-29-004)
|
||||
|
||||
- **Date:** 2025-11-20
|
||||
- **Depends on:** Path/Scope schema (29-002)
|
||||
- **Working directory:** `src/Policy/StellaOps.Policy.Engine`
|
||||
|
||||
## Metrics (Meter prefix `StellaOps.Policy.Engine`)
|
||||
- `policy.path.eval.total` (counter) — tags: `tenant`, `subject` (purl/cpe simplified), `result` (`allow|deny|error`), `ruleId` (short slug), `pathMatch` (`exact|prefix|glob`).
|
||||
- `policy.path.eval.duration.ms` (histogram) — tags: `tenant`, `subject`, `ruleId`.
|
||||
- `policy.path.eval.cache.hit` (counter) — tags: `tenant`, `cache` (`rule|decision`), `hit` (`true|false`).
|
||||
- `policy.path.eval.scope.mismatch` (counter) — tags: `tenant`, `reason` (`no-scope|depth-limit|confidence-low`).
|
||||
- `policy.path.eval.coverage` (gauge/exported via observable gauge) — value: % of observations with matching scope; tags: `tenant`, `source`.
|
||||
|
||||
## Logs
|
||||
- Structured log name `Policy.PathEval` with fields: `tenant`, `ruleId`, `subject` (purl/cpe), `filePath`, `pathMatch`, `pattern`, `confidence`, `decision`, `durationMs`, `evidenceHash`, `correlationId`.
|
||||
- Errors must include `errorCode` (enum: `scope-missing`, `scope-conflict`, `rule-missing`, `runtime-error`).
|
||||
|
||||
## Events (optional OTEL spans)
|
||||
- Span name: `policy.path.evaluate`; attributes mirror log fields plus `ruleVersion`, `treeDigest?`, `dsseEnvelopeHash?` for replay traces.
|
||||
|
||||
## Acceptance for prep completion
|
||||
- Metric/log/span names and required tags are frozen for downstream instrumentation.
|
||||
- Implementations must use path/scope schema from 29-002 for tag normalization.
|
||||
- Targets max cardinality: ruleId short slug (<=32 chars), subject truncated to package name (no version) to keep series bounded.
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
# Policy Engine · Overlay Projection Prep (POLICY-ENGINE-30-001)
|
||||
|
||||
- **Date:** 2025-11-20
|
||||
- **Depends on:** Path/Scope schema (29-002) and observability contract (29-004)
|
||||
- **Working directory:** `src/Policy/StellaOps.Policy.Engine`
|
||||
|
||||
## Projection contract
|
||||
- Input: `PathScope` documents (see 29-002) + `PolicyRule` definitions.
|
||||
- Output: `OverlayProjection` objects stored/snapshotted for replay:
|
||||
- `tenant` (string)
|
||||
- `ruleId` (string)
|
||||
- `subject` (purl/cpe, optional packagePath)
|
||||
- `scope` (copied from input)
|
||||
- `decision` (`allow|deny|warn|defer`)
|
||||
- `reasons[]` (machine-readable codes; e.g., `path-match`, `severity-threshold`, `capability-needed`)
|
||||
- `artifacts` (hash list) — `evidenceHash`, `treeDigest?`, `dsseEnvelopeHash?` used in evaluation
|
||||
- `effectiveAt` (ISO-8601 UTC) — time projection became active
|
||||
- `expiresAt?` (ISO-8601 UTC) — optional
|
||||
- `version` (int) — monotonic per ruleId
|
||||
|
||||
## Ordering & determinism
|
||||
- Projection list sorted by (`ruleId`, `subject.purl|cpe`, `scope.pathMatch`, `scope.pattern`, `effectiveAt`).
|
||||
- Hash for `artifacts.evidenceHash` reused from input to keep replay stable.
|
||||
|
||||
## Storage hints
|
||||
- Persist overlays as NDJSON under `overlay/{tenant}/{ruleId}/{version}.ndjson` for air-gapped export.
|
||||
- Snapshots include header line with schema version `overlay-projection-v1` followed by sorted projections.
|
||||
|
||||
## Acceptance for prep completion
|
||||
- Projection shape, ordering, and filenames are frozen for implementation tasks 30-001..30-003.
|
||||
- Downstream simulation/change-event work (30-002/30-003) must emit/consume this structure without mutation.
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# Policy Engine · Simulation Bridge Prep (POLICY-ENGINE-30-002)
|
||||
|
||||
- **Date:** 2025-11-20
|
||||
- **Depends on:** Overlay projection (30-001)
|
||||
- **Working directory:** `src/Policy/StellaOps.Policy.Engine`
|
||||
|
||||
## Simulation request schema
|
||||
- `tenant` (string)
|
||||
- `rules[]` (string) — ruleIds to simulate; if empty, simulate all active rules.
|
||||
- `overlays[]` (optional) — inline `OverlayProjection` objects to test hypothetical changes without persisting.
|
||||
- `paths[]` — array of `PathScope` inputs.
|
||||
- `mode` (`preview|whatif`) — `preview` returns decisions only; `whatif` also returns delta vs current overlays.
|
||||
- `seed` (int, optional) — for deterministic randomization if simulations sample paths.
|
||||
|
||||
## Response schema
|
||||
- `decisions[]` — per PathScope result: `pathScope`, `decision`, `reasons[]`, `ruleId`, `version`, `effectiveAt`.
|
||||
- `deltas[]` (only for `whatif`) — entries with `ruleId`, `baselineDecision`, `candidateDecision`, `diffReason`.
|
||||
- `metrics` — echo of counters: `evaluated`, `allowed`, `denied`, `warned`, `deferred` for quick UI.
|
||||
|
||||
## Determinism rules
|
||||
- When `seed` absent, use fixed seed `0xC0DEC0DE` for any randomized sampling.
|
||||
- Responses ordered by input `paths[]` index, then `ruleId`.
|
||||
|
||||
## Acceptance for prep completion
|
||||
- Simulation schemas are frozen; downstream UI/CLI harnesses can rely on shapes and ordering.
|
||||
- Delta semantics clarified to unblock change-event publication (30-003).
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
# Policy Engine · Change Events Prep (POLICY-ENGINE-30-003)
|
||||
|
||||
- **Date:** 2025-11-20
|
||||
- **Depends on:** Overlay projection (30-001) and simulation bridge (30-002)
|
||||
- **Working directory:** `src/Policy/StellaOps.Policy.Engine`
|
||||
|
||||
## Event envelope
|
||||
- Topic: `policy.overlay.changed`
|
||||
- Payload fields:
|
||||
- `tenant` (string)
|
||||
- `ruleId` (string)
|
||||
- `version` (int) — matches projection version
|
||||
- `changeType` (`created|updated|deprecated|deleted`)
|
||||
- `projection` (OverlayProjection) — single item; for `deleted`, include last-known `projection` with `decision: "defer"`.
|
||||
- `delta` (object, optional) — produced when triggered from simulation `whatif`: `baselineDecision`, `candidateDecision`, `diffReason`.
|
||||
- `artifacts` — `evidenceHash`, `treeDigest?`, `dsseEnvelopeHash?`
|
||||
- `emittedAt` (ISO-8601 UTC)
|
||||
- `correlationId` (string) — propagate from incoming request or run id.
|
||||
|
||||
## Delivery guarantees
|
||||
- At-least-once on the bus; projection storage is source of truth. Events carry idempotency key `tenant:ruleId:version`.
|
||||
- Ordering per `ruleId` is preserved by publishing after storage commit.
|
||||
|
||||
## Consumers
|
||||
- Scheduler uses events to enqueue re-evaluation jobs keyed by `tenant` + `ruleId`.
|
||||
- UI/CLI preview listens for `changeType` ≠ `created` to refresh overlays without polling.
|
||||
|
||||
## Acceptance for prep completion
|
||||
- Topic, payload, and idempotency key are fixed; downstream scheduler/UI/CLI can wire without further contract churn.
|
||||
|
||||
21
docs/modules/policy/prep/2025-11-20-severity-fusion-prep.md
Normal file
21
docs/modules/policy/prep/2025-11-20-severity-fusion-prep.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Severity Fusion Prep — PREP-POLICY-ENGINE-40-001-SEVERITY-FUSION-DEP
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Policy Guild · Concelier Guild
|
||||
Scope: Capture severity fusion requirements using violation events (38-201).
|
||||
|
||||
## Dependencies
|
||||
- Violation event schema (38-201).
|
||||
- Concelier severity sources + lattice rules; Policy weighting outputs (30-101).
|
||||
|
||||
## Draft fusion rules
|
||||
- Inputs: violation events with status + severity + advisory/confidence.
|
||||
- Rules: deterministic lattice; combine source severities with weights from 30-101; tie-break via Concelier source ranking; emit `severity_fused`, `reason_codes[]`, `sources[]` with weights.
|
||||
- Determinism: sort sources lexicographically; fixed numeric precision (scale 3).
|
||||
|
||||
## Acceptance
|
||||
- Schema draft at `docs/modules/policy/schemas/severity-fusion@draft.json` and sample at `docs/modules/policy/samples/severity-fusion@draft.json`.
|
||||
- Document weight caps and rounding rules.
|
||||
|
||||
## Handoff
|
||||
Prep artefact for PREP-POLICY-ENGINE-40-001-SEVERITY-FUSION-DEP. Finalize once violation events and Concelier severity ranking are frozen.
|
||||
@@ -0,0 +1,26 @@
|
||||
# Simulation Bridge Prep — PREP-POLICY-ENGINE-30-002-SIMULATION-BRIDGE-C
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Policy Guild · Cartographer Guild
|
||||
Scope: Capture the required simulation bridge inputs and outputs so POLICY-ENGINE-30-002 can start once overlay schema (30-001) lands.
|
||||
|
||||
## Dependencies
|
||||
- Overlay projection contract (30-001) — needs metrics/log schema from 29-004.
|
||||
- Cartographer graph API shape for reachability overlays.
|
||||
|
||||
## Proposed contract (to validate once 30-001 freezes)
|
||||
- Input: overlay projection payload from 30-001 plus reachability summaries from Cartographer.
|
||||
- Output (draft schema):
|
||||
- `simulation_id` (ULID), `tenant_id`, `scenario` descriptor.
|
||||
- `inputs`: overlay snapshot hash, policy profile hash, reachability baseline hash.
|
||||
- `results[]`: `{component_purl, advisory_id, status_before, status_after, reason, trace_ref}`.
|
||||
- `metrics`: duration, rule_eval_count, graph_nodes_touched.
|
||||
- Determinism: stable ordering by `(tenant_id, component_purl, advisory_id)`; timestamps UTC RFC3339.
|
||||
|
||||
## Acceptance to flip PREP to DONE
|
||||
- Overlay schema (30-001) version/Hash referenced in this file.
|
||||
- Draft JSON schema for simulation bridge saved under `docs/modules/policy/schemas/simulation-bridge@draft.json`.
|
||||
- Sample payload placed under `docs/modules/policy/samples/simulation-bridge@draft.json`.
|
||||
|
||||
## Handoff
|
||||
Use this as the prep artefact for PREP-POLICY-ENGINE-30-002-SIMULATION-BRIDGE-C. Update hashes and samples once 30-001 publishes the overlay schema; then move the implementation task to DOING.
|
||||
21
docs/modules/policy/prep/2025-11-20-snapshot-api-prep.md
Normal file
21
docs/modules/policy/prep/2025-11-20-snapshot-api-prep.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Snapshot API Prep — PREP-POLICY-ENGINE-35-201-SNAPSHOT-API-WAITS-
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Policy Guild
|
||||
Scope: Describe the snapshot API contract that follows ledger export (34-101).
|
||||
|
||||
## Dependencies
|
||||
- Ledger export schema (34-101).
|
||||
- Snapshot stream parameters (retention, pagination) from Policy data store.
|
||||
|
||||
## Draft API surface
|
||||
- `GET /policy/snapshots?tenant_id=&after_cursor=&limit=` → returns `{items:[{snapshot_id, generated_at, ledger_export_id, overlay_hash, status_counts}], next_cursor}`.
|
||||
- `GET /policy/snapshots/{snapshot_id}` → returns snapshot detail with materialized results (same ordering as ledger export).
|
||||
- Determinism: snapshot_id = hash of ledger_export_id + overlay_hash; ordering by `generated_at` then `snapshot_id`.
|
||||
|
||||
## Acceptance
|
||||
- Draft schema at `docs/modules/policy/schemas/policy-snapshot@draft.json` and sample at `docs/modules/policy/samples/policy-snapshot@draft.json`.
|
||||
- Cursor format defined (opaque base64 of `(generated_at, snapshot_id)` suggested).
|
||||
|
||||
## Handoff
|
||||
This document is the prep artefact for PREP-POLICY-ENGINE-35-201-SNAPSHOT-API-WAITS-. Update with cursor and retention details once ledger export shape is frozen.
|
||||
25
docs/modules/policy/prep/2025-11-20-trust-weighting-prep.md
Normal file
25
docs/modules/policy/prep/2025-11-20-trust-weighting-prep.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# Trust Weighting UI/API Prep — PREP-POLICY-ENGINE-30-101-TRUST-WEIGHTING-UI-
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Policy Guild
|
||||
Scope: Capture the UI/API surfaces for trust weighting once change events (30-003) are available.
|
||||
|
||||
## Dependencies
|
||||
- Change events payload (30-003) and overlay schema (30-001).
|
||||
- UI design tokens/UX from Console/Policy surfaces (not yet provided).
|
||||
|
||||
## Proposed API surface (draft)
|
||||
- `GET /policy/trust-weighting` → returns current weights per source (`cartographer`, `concelier`, `scanner`, `advisory_ai`, etc.) and effective profile hash.
|
||||
- `PUT /policy/trust-weighting` → accepts deterministic payload sorted by `source` with fields: `{source, weight, justification?, updated_at}`.
|
||||
- `GET /policy/trust-weighting/preview?overlay_hash=` → previews recalculated statuses using supplied weights (calls simulation bridge under the hood).
|
||||
|
||||
## Determinism & validation
|
||||
- Weights are decimals with fixed scale 3; sum not required to 1 but capped at max per policy profile.
|
||||
- Payloads canonical JSON ordering; timestamps UTC.
|
||||
|
||||
## Acceptance to close PREP
|
||||
- Align sources list with 30-003 change event fields and overlay inputs.
|
||||
- Document schema at `docs/modules/policy/schemas/trust-weighting@draft.json` and sample at `docs/modules/policy/samples/trust-weighting@draft.json`.
|
||||
|
||||
## Handoff
|
||||
Treat this as the prep artefact for PREP-POLICY-ENGINE-30-101-TRUST-WEIGHTING-UI-. Finalize once 30-003 is frozen and UI tokens arrive; then move implementation to DOING.
|
||||
22
docs/modules/policy/prep/2025-11-20-violation-events-prep.md
Normal file
22
docs/modules/policy/prep/2025-11-20-violation-events-prep.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Violation Events Prep — PREP-POLICY-ENGINE-38-201-VIOLATION-EVENTS-DE
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Policy Guild
|
||||
Scope: Define violation event payloads emitted after snapshot stream (35-201).
|
||||
|
||||
## Dependencies
|
||||
- Snapshot API/stream shape (35-201).
|
||||
- Severity fusion rules (40-001) to know which fields to emit.
|
||||
|
||||
## Draft event
|
||||
- `event_type`: `policy.violation.detected`
|
||||
- Fields: `tenant_id`, `snapshot_id`, `policy_profile_hash`, `component_purl`, `advisory_id`, `violation_code`, `severity`, `status`, `trace_ref`, `occurred_at`, `event_id` (hash of snapshot_id + component_purl + advisory_id).
|
||||
- Transport: NATS subject `policy.violation.detected`; durable stream; idempotency via `event_id`.
|
||||
- Metrics: `policy_violation_events_total{tenant,violation_code}`.
|
||||
|
||||
## Acceptance
|
||||
- Draft schema at `docs/modules/policy/schemas/policy-violation-event@draft.json` and sample at `docs/modules/policy/samples/policy-violation-event@draft.json`.
|
||||
- Confirm subject + retention with Scheduler/Notify.
|
||||
|
||||
## Handoff
|
||||
Use this doc as the prep artefact for PREP-POLICY-ENGINE-38-201-VIOLATION-EVENTS-DE. Update once snapshot stream and fusion rules are frozen; then unblock implementation.
|
||||
@@ -0,0 +1,22 @@
|
||||
# Worker Implementation Prep — PREP-POLICY-ENGINE-33-101-WORKER-IMPLEMENTATI
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Policy Guild
|
||||
Scope: Define worker execution contract that consumes orchestrator jobs (32-101).
|
||||
|
||||
## Dependencies
|
||||
- Job schema from 32-101.
|
||||
- Overlay + batch context schemas (30-001, 31-002).
|
||||
|
||||
## Draft execution contract
|
||||
- Worker input: job document with `context_id`, `batch_items`, `policy_profile_hash`, `callbacks`.
|
||||
- Output record: `{job_id, worker_id, started_at, completed_at, results[]}` where each result mirrors change-event format `{component_purl, advisory_id, status, trace_ref}`.
|
||||
- Idempotency: result hash over sorted results; retries compare hash and skip duplicate emission.
|
||||
- Metrics: `policy_worker_jobs_total{result}`, `policy_worker_duration_seconds` (histogram), `policy_worker_results_total{status}`.
|
||||
|
||||
## Acceptance
|
||||
- Save schema draft at `docs/modules/policy/schemas/policy-worker-result@draft.json` and sample result at `docs/modules/policy/samples/policy-worker-result@draft.json`.
|
||||
- Confirm dedupe strategy with Scheduler/Orchestrator.
|
||||
|
||||
## Handoff
|
||||
Prep artefact for PREP-POLICY-ENGINE-33-101-WORKER-IMPLEMENTATI. Finalize once job schema is fixed and dedupe/metric names are agreed.
|
||||
@@ -0,0 +1,23 @@
|
||||
# Policy Metrics/Logging Prep — PREP-POLICY-ENGINE-29-004
|
||||
|
||||
Status: Draft (2025-11-21)
|
||||
Owners: Policy Guild · Observability Guild
|
||||
Scope: Define metrics/logging outputs for path/scope-aware evaluation (POLICY-ENGINE-29-004) so downstream overlays/simulations can consume stable counters and traces.
|
||||
|
||||
Needs / open points
|
||||
- Ingest output shape from POLICY-ENGINE-29-003 (path/scope evaluator) to enumerate metric dimensions and labels.
|
||||
- Confirm sampling, cardinality guardrails, and redaction rules for evidence payloads.
|
||||
- Decide OpenTelemetry/ADI schema version and offline export format (NDJSON) for air-gapped runs.
|
||||
- Align log event IDs with change-event pipeline (30-003) to ensure replay determinism.
|
||||
|
||||
Draft contract (initial)
|
||||
- Metrics namespace: `stellaops.policy.eval.*`
|
||||
- Required counters: total_evaluations, policy_matches, policy_denies, evaluation_failures, overlay_projections_emitted.
|
||||
- Dimensions (tentative): tenant_id, policy_pack_id, overlay_id, scope_path, scheduler_job_id, evaluator_version, schema_version, environment (online/offline).
|
||||
- Logs: structured JSON; fields include evaluation_id (ULID), scope_path, matched_policies[], deny_reasons[], duration_ms, trace_id (optional), schema_version.
|
||||
- Export: NDJSON batch with deterministic ordering by evaluation_id; batching bounded by 1 MiB or 1k records; integrity hash (SHA256) over batch.
|
||||
|
||||
Next actions
|
||||
- Await path/scope payloads from POLICY-ENGINE-29-003 to lock dimensions and sample payloads.
|
||||
- Publish sample metric set and log envelope once upstream confirms.
|
||||
- Mirror into sprint execution log once finalized.
|
||||
@@ -0,0 +1,17 @@
|
||||
# Policy Path/Scope Schema Prep — PREP-POLICY-ENGINE-29-002
|
||||
|
||||
Status: Draft (2025-11-21)
|
||||
Owners: Policy Guild · SBOM Service Guild
|
||||
Scope: Define path/scope-aware evaluation schema (inputs/outputs) for POLICY-ENGINE-29-002 so downstream metrics, overlays, and simulations can bind to stable shapes.
|
||||
|
||||
Needs / open points
|
||||
- Enumerate canonical path selectors (SBOM node types, package coords, file paths) and disambiguation rules.
|
||||
- Decide scope precedence and evaluation order (lexical vs explicit priority).
|
||||
- Provide JSON Schema for evaluation request/response, including error surfaces and determinism requirements (ordering, nullability, defaults).
|
||||
- Align with SBOM Service envelopes and Graph coordinates to avoid divergent node IDs.
|
||||
- Sample payloads for common cases: single package, path tree, mixed ecosystem nodes.
|
||||
|
||||
Next actions
|
||||
- Draft initial JSON Schema and sample payloads once SBOM Service shares coordinate mapping rules.
|
||||
- Review with Observability Guild to ensure fields required by metrics/logging (29-004) are present.
|
||||
- Publish finalized schema to unblock 29-003 and downstream tasks.
|
||||
@@ -15,8 +15,28 @@
|
||||
- `sbom_snapshots` (immutable versions; tenant + artifact + digest + createdAt)
|
||||
- `sbom_projections` (materialised views keyed by snapshotId, entrypoint/service node flags)
|
||||
- `sbom_assets` (asset metadata, criticality/owner/env/exposure; append-only history)
|
||||
- `sbom_paths` (resolved dependency paths with runtime flags, blast-radius hints)
|
||||
- `sbom_events` (outbox for event delivery + watermark/backfill tracking)
|
||||
- `sbom_paths` (resolved dependency paths with runtime flags, blast-radius hints)
|
||||
- `sbom_events` (outbox for event delivery + watermark/backfill tracking)
|
||||
|
||||
### 2.1) SBOM + provenance spine (Nov 2026)
|
||||
|
||||
The service now owns an idempotent spine that converts OCI images into SBOMs and provenance bundles with DSSE and in-toto. The flow is intentionally air-gap ready:
|
||||
|
||||
- **Extract** OCI manifest/layers (hash becomes `contentAddress`).
|
||||
- **Build SBOM** in CycloneDX 1.6 and/or SPDX 3.0.1; canonicalize JSON before hashing (`sbomHash`).
|
||||
- **Sign** outputs as DSSE envelopes; predicate uses in-toto Statement with SLSA Provenance v1.
|
||||
- **Publish** attestations optionally to a transparency backend: `rekor`, `local-merkle`, or `null` (no-op). Local Merkle log keeps proofs for later sync when online.
|
||||
|
||||
Minimal APIs exposed by SbomService (idempotent by hash):
|
||||
|
||||
- `POST /sbom/ingest` `{ imageDigest, sbom, format, dsseSignature? }` → `{ sbomId, status: stored|already_present, sbomHash }` keyed by `contentAddress + sbomHash`.
|
||||
- `POST /attest/verify` `{ dsseEnvelope, expectedSubjects[] }` → `{ verified, predicateType, logIndex?, inclusionProof? }` and records attestation when verified.
|
||||
|
||||
Operational rules:
|
||||
|
||||
- Default media types: `application/vnd.cyclonedx+json`, `application/spdx+json`, `application/dsse+json`, `application/vnd.in-toto+json`.
|
||||
- If the same SBOM/attestation arrives again, return HTTP 200 with `"status":"already_present"` and do not create a new version.
|
||||
- Offline posture: no external calls required; Rekor publish remains optional and retryable when connectivity is restored.
|
||||
|
||||
## 3) APIs (first wave)
|
||||
- `GET /sbom/paths?purl=...&artifact=...&scope=...&env=...` — returns ordered paths with runtime_flag/blast_radius and nearest-safe-version hint; supports `cursor` pagination.
|
||||
|
||||
@@ -44,7 +44,15 @@ src/
|
||||
└─ StellaOps.Scanner.Sbomer.DockerImage/ # CLI‑driven scanner container
|
||||
```
|
||||
|
||||
Analyzer assemblies and buildx generators are packaged as **restart-time plug-ins** under `plugins/scanner/**` with manifests; services must restart to activate new plug-ins.
|
||||
Analyzer assemblies and buildx generators are packaged as **restart-time plug-ins** under `plugins/scanner/**` with manifests; services must restart to activate new plug-ins.
|
||||
|
||||
### 1.2 Native reachability upgrades (Nov 2026)
|
||||
|
||||
- **Stripped-binary pipeline**: native analyzers must recover functions even without symbols (prolog patterns, xrefs, PLT/GOT, vtables). Emit a tool-agnostic neutral JSON (NJIF) with functions, CFG/CG, and evidence tags. Keep heuristics deterministic and record toolchain hashes in the scan manifest.
|
||||
- **Synthetic roots**: treat `.preinit_array`, `.init_array`, legacy `.ctors`, and `_init` as graph entrypoints; add roots for constructors in each `DT_NEEDED` dependency. Tag edges from these roots with `phase=load` for explainers.
|
||||
- **Build-id capture**: read `.note.gnu.build-id` for every ELF, store hex build-id alongside soname/path, propagate into `SymbolID`/`code_id`, and expose it to SBOM + runtime joiners. If missing, fall back to file hash and mark source accordingly.
|
||||
- **PURL-resolved edges**: annotate call edges with the callee purl and `symbol_digest` so graphs merge with SBOM components. See `docs/reachability/purl-resolved-edges.md` for schema rules and acceptance tests.
|
||||
- **Unknowns emission**: when symbol → purl mapping or edge targets remain unresolved, emit structured Unknowns to Signals (see `docs/signals/unknowns-registry.md`) instead of dropping evidence.
|
||||
|
||||
### 1.1 Queue backbone (Redis / NATS)
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ Scope: Requirements and plan to provide an isolated/scoped runner so targeted No
|
||||
- Document usage in `src/Scanner/__Tests/README.md`.
|
||||
|
||||
## Blocking items
|
||||
- None identified; all inputs are local to the repo/offline feeds.
|
||||
- Upstream Concelier projects in solution filter currently do not build (`StellaOps.Concelier.Storage.Mongo` duplicate `AdvisoryObservationSourceDocument` definition and missing `NatsJSContext` type), so `dotnet test` fails before Node analyzer tests execute. Needs Concelier fix or temporary exclusion to validate runner.
|
||||
- 2025-11-20 follow-up: deduplication + JetStream package added in Concelier.Storage.Mongo and Scanner tests now set `UseConcelierTestInfra=false`, but the shared Directory.Build.props still injects Concelier connectors into the restore/build graph; Node tests remain blocked until Concelier test infra is fully detachable or those projects are excluded from the filter.
|
||||
|
||||
This note satisfies PREP-SCANNER-ANALYZERS-NODE-22-001-NEEDS-ISOL by defining the isolated runner plan and artefact locations.
|
||||
|
||||
16
docs/modules/scanner/prep/2025-11-21-scanner-records-prep.md
Normal file
16
docs/modules/scanner/prep/2025-11-21-scanner-records-prep.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# Scanner Record Payloads Prep — PREP-SCANNER-RECORDS
|
||||
|
||||
Status: Draft (2025-11-21)
|
||||
Owners: Scanner Guild · Policy Guild
|
||||
Scope: Stabilize record/observation payload schema for scanner workers so downstream policy/graph pipelines can rely on consistent envelopes.
|
||||
|
||||
Needs
|
||||
- Confirm per-language analyzer output fields (package coordinates, vuln refs, evidence hashes) and common envelope keys.
|
||||
- Decide deterministic ordering for findings within a record to support replay/air-gap.
|
||||
- Define maximum payload size, chunking rules, and checksum strategy (SHA256 over canonical JSON).
|
||||
- Align timestamp format (UTC, RFC3339) and monotonic sequencing for job-level ordering.
|
||||
|
||||
Next actions
|
||||
- Pull latest analyzer outputs from scanner worker prototypes and normalize into a shared JSON Schema.
|
||||
- Share sample NDJSON record set for Policy/Graph consumers.
|
||||
- Publish links into relevant sprints once schema draft is frozen.
|
||||
16
docs/modules/telemetry/prep/2025-11-20-obs-50-002-prep.md
Normal file
16
docs/modules/telemetry/prep/2025-11-20-obs-50-002-prep.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# Telemetry Context Propagation Prep — PREP-TELEMETRY-OBS-50-002
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Telemetry Core Guild
|
||||
Scope: Context propagation middleware/adapters for HTTP, gRPC, background jobs, CLI.
|
||||
|
||||
## Proposed propagation fields
|
||||
- `trace_id`, `span_id`, `tenant_id`, `actor`, `imposed_rule`, `correlation_id`.
|
||||
- Async resume harness for job queue workers.
|
||||
|
||||
## Open decisions
|
||||
- Final field names and required/optional list.
|
||||
- Which carriers (headers) per transport: HTTP (`x-` headers), gRPC metadata, CLI env.
|
||||
|
||||
## Handoff
|
||||
Use as prep artefact; update once field list and carriers are finalized.
|
||||
12
docs/modules/telemetry/prep/2025-11-20-obs-51-001-prep.md
Normal file
12
docs/modules/telemetry/prep/2025-11-20-obs-51-001-prep.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Telemetry Metrics Helpers Prep — PREP-TELEMETRY-OBS-51-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Telemetry Core Guild · Observability Guild
|
||||
Scope: Metrics helpers for golden signals with exemplar support and cardinality guards.
|
||||
|
||||
## Needs
|
||||
- Golden signal definitions (latency, errors, saturation, traffic) with exemplar tagging guidance.
|
||||
- Roslyn analyzer rules to prevent unsanitised labels.
|
||||
|
||||
## Handoff
|
||||
Prep artefact; fill when golden signal label set is finalized.
|
||||
21
docs/modules/zastava/prep/2025-11-20-surface-fs-env-prep.md
Normal file
21
docs/modules/zastava/prep/2025-11-20-surface-fs-env-prep.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Zastava Wave Prep — PREP-140-D-ZASTAVA-WAVE-WAITING-ON-SURFACE-FS
|
||||
|
||||
Status: **Ready for implementation** (2025-11-20)
|
||||
Owners: Zastava Observer/Webhook Guilds · Surface Guild
|
||||
Scope: Document Surface.FS cache drop plan and Surface.Env helper ownership/unseal steps to unblock Zastava runtime work.
|
||||
|
||||
## Decisions captured
|
||||
- Surface.FS cache drop cadence: daily at 02:00 UTC with retention of last 3 snapshots; manual invalidate via `/admin/cache/drop` with DSSE auth.
|
||||
- Surface.Env helper ownership: Surface Guild maintains helper; Zastava consumers read via sealed secret `SURFACE_ENV_CONFIG` injected per-tenant.
|
||||
- Secrets rotation: quarterly or on incident; DSSE-signed env bundle stored in sealed S3 bucket `surface-env-bundles/tenant/{id}`.
|
||||
|
||||
## Deliverables for implementation teams
|
||||
- Publish cache drop runbook under `docs/modules/zastava/runbooks/surface-fs-cache-drop.md` (owner Surface Guild).
|
||||
- Publish env helper schema & sample at `docs/modules/zastava/surface-env-helper.sample.yaml` with hash file.
|
||||
- Add checklist to Zastava admission hooks to verify `SURFACE_ENV_CONFIG` exists and DSSE signature matches Surface root.
|
||||
|
||||
## Acceptance criteria
|
||||
- Written runbook + sample helper schema available at the paths above.
|
||||
- Cache drop schedule and manual invalidate command documented with DSSE requirement.
|
||||
- Zastava tasks can consume helper without requiring further schema decisions.
|
||||
|
||||
Reference in New Issue
Block a user