Add new features and tests for AirGap and Time modules
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
- Introduced `SbomService` tasks documentation. - Updated `StellaOps.sln` to include new projects: `StellaOps.AirGap.Time` and `StellaOps.AirGap.Importer`. - Added unit tests for `BundleImportPlanner`, `DsseVerifier`, `ImportValidator`, and other components in the `StellaOps.AirGap.Importer.Tests` namespace. - Implemented `InMemoryBundleRepositories` for testing bundle catalog and item repositories. - Created `MerkleRootCalculator`, `RootRotationPolicy`, and `TufMetadataValidator` tests. - Developed `StalenessCalculator` and `TimeAnchorLoader` tests in the `StellaOps.AirGap.Time.Tests` namespace. - Added `fetch-sbomservice-deps.sh` script for offline dependency fetching.
This commit is contained in:
21
docs/modules/attestor/replay-prep.md
Normal file
21
docs/modules/attestor/replay-prep.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Attestor Replay Prep — PREP-ATTEST-REPLAY-187-003 (Draft)
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Attestor Guild
|
||||
Scope: Capture prerequisites for wiring Attestor/Rekor anchoring to replay manifests once scanner record payloads are available.
|
||||
|
||||
## Expected inputs
|
||||
- Replay record schema v1 (from `docs/modules/evidence-locker/replay-payload-contract.md`).
|
||||
- Evidence Locker bundle location/pointer for replay artefacts.
|
||||
|
||||
## Attestation plan
|
||||
- DSSE envelope type: `stella.replay.manifest` (draft).
|
||||
- Payload fields: `{record_id, bundle_sha256, policy_run_id?, timestamp}`; signer: Attestor service key; optional Rekor entry when online.
|
||||
- Verification endpoint proposal: `POST /attestations/replay/verify` accepting bundle pointer + DSSE; returns chain-of-custody summary.
|
||||
|
||||
## Open dependencies
|
||||
- Final replay record schema and bundle pointer format.
|
||||
- Authority policy on signer identity and Rekor usage in air-gap.
|
||||
|
||||
## Handoff
|
||||
Use this note to unblock PREP-ATTEST-REPLAY-187-003; update when scanner payloads and Authority decisions land.
|
||||
30
docs/modules/cli/guides/replay-cli-prep.md
Normal file
30
docs/modules/cli/guides/replay-cli-prep.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# CLI Replay Prep — PREP-CLI-REPLAY-187-002 (Draft)
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: DevEx/CLI Guild
|
||||
Scope: Define inputs/outputs and offline behaviour needed for CLI replay commands (`scan --record`, `verify`, `replay`, `diff`).
|
||||
|
||||
## Command surface (proposed)
|
||||
- `stella scan --record <image>` → emits replay record NDJSON to stdout or `--out bundle.ndjson`.
|
||||
- `stella replay --bundle <bundle.ndjson>` → re-run verification offline; accepts `--policy-bundle` to pin policy version.
|
||||
- `stella diff --bundle <a> --bundle <b>` → compare findings/signals with deterministic ordering; output NDJSON.
|
||||
- `stella verify --bundle <bundle.ndjson>` → signature/hash verification of replay bundle.
|
||||
|
||||
## Inputs
|
||||
- Replay record schema v1 from Evidence Locker (see `docs/modules/evidence-locker/replay-payload-contract.md`).
|
||||
- Policy export bundle contract (see `docs/modules/policy/design/export-console-bundle-contract.md`) for policy pinning.
|
||||
|
||||
## Outputs
|
||||
- Deterministic NDJSON; file names content-addressed (`sha256` of payload).
|
||||
- Exit codes: 0 success, 2 validation error, 3 signature mismatch.
|
||||
|
||||
## Offline/air-gap considerations
|
||||
- No network fetch; all references resolve to local bundle paths.
|
||||
- Trust roots loaded from CLI config or `--trust-root` file; DSSE verification optional flag `--no-verify` default false.
|
||||
|
||||
## Open decisions
|
||||
- Exact flag names for trust root and policy bundle; align with CLI UX guidelines.
|
||||
- Where to persist cache/metadata (if any) in offline mode.
|
||||
|
||||
## Handoff
|
||||
Treat this as the prep artefact for PREP-CLI-REPLAY-187-002. Update once replay record schema is finalized.
|
||||
57
docs/modules/concelier/operations/console-lnm-consumption.md
Normal file
57
docs/modules/concelier/operations/console-lnm-consumption.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Console Consumption of LNM Linksets (Sprint 110)
|
||||
|
||||
Goal: unblock CONCELIER-CONSOLE-23-001..003 by defining how Console reads Link-Not-Merge (LNM) data now that the schema is frozen (2025-11-17) and cache plan exists.
|
||||
|
||||
## Data sources
|
||||
- Primary collection: `advisory_linksets` (see `docs/modules/concelier/link-not-merge-schema.md`).
|
||||
- Cache: `advisory_linkset_cache` (see `docs/modules/concelier/operations/lnm-cache-plan.md`). Console should read from cache when present; fall back to live rebuild otherwise.
|
||||
|
||||
## API shape (WebService)
|
||||
- Endpoint to expose via Console: `GET /v1/lnm/linksets/{advisoryId}`
|
||||
- Query: `source` (required), `tenant`, optional `includeConflicts=true|false` (default true).
|
||||
- Response JSON (deterministic key order):
|
||||
```json
|
||||
{
|
||||
"advisoryId": "GHSA-123",
|
||||
"source": "ghsa",
|
||||
"observations": ["<mongoId>", "<mongoId2>"],
|
||||
"normalized": {
|
||||
"purls": ["pkg:npm/foo@1.0.0"],
|
||||
"versions": ["1.0.0"],
|
||||
"ranges": [],
|
||||
"severities": [{"system":"cvssv3","score":7.5}]
|
||||
},
|
||||
"conflicts": [
|
||||
{"field":"severities","reason":"disagreement","values":["7.5","9.8"]}
|
||||
],
|
||||
"provenance": {
|
||||
"observationHashes": ["..."],
|
||||
"toolVersion": "lnm-1.0"
|
||||
},
|
||||
"createdAt": "2025-11-20T00:00:00Z"
|
||||
}
|
||||
```
|
||||
- Sorting: observations sorted by `source, advisoryId, fetchedAt` before hashing; response preserves that order.
|
||||
- Caching: when cache hit, return cached document; when miss, rebuild, write cache, then return.
|
||||
|
||||
## Console rendering contract
|
||||
- Fields to surface:
|
||||
- `normalized.purls` (list) and `normalized.versions`
|
||||
- `conflicts` if non-empty: show field + reason text; keep order as returned.
|
||||
- `provenance.observationHashes` as “evidence anchors” (list); do not prettify.
|
||||
- Tenant header required; no cross-tenant leakage. Scope `concelier:lnm.read`.
|
||||
|
||||
## Error handling
|
||||
- 404 when linkset missing for advisory/source.
|
||||
- 409 when tenant header missing/invalid.
|
||||
- Deterministic error body: `{ "error": "<code>", "message": "..." }`.
|
||||
|
||||
## Telemetry (reuse existing meters)
|
||||
- Increment `lnm.cache.hit_total` / `lnm.cache.write_total` as defined in cache plan.
|
||||
- Log template on returns: `lnm_console_success tenant={Tenant} advisoryId={AdvisoryId} source={Source} cached={Cached}`.
|
||||
|
||||
## Owners
|
||||
- Concelier Console Guild (primary)
|
||||
- Concelier Core Guild (review)
|
||||
|
||||
This document is authoritative for CONCELIER-CONSOLE-23-001..003 in Sprint 110.
|
||||
33
docs/modules/concelier/operations/lnm-cache-plan.md
Normal file
33
docs/modules/concelier/operations/lnm-cache-plan.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Concelier LNM Cache Plan (Sprint 110)
|
||||
|
||||
Purpose: finalize structured caching fields now that Link-Not-Merge (LNM) schema is frozen (2025-11-17) and Evidence Locker contract is published.
|
||||
|
||||
## Cache payload shape
|
||||
- Source: `advisory_linksets` collection (see `docs/modules/concelier/link-not-merge-schema.md`).
|
||||
- Cache entry key: `{tenant}:{advisoryId}:{source}`.
|
||||
- Cached fields (deterministic order):
|
||||
- `observations` (ObjectId list, already sorted by source, advisoryId, fetchedAt)
|
||||
- `normalized.purls`, `normalized.versions`, `normalized.ranges`, `normalized.severities`
|
||||
- `conflicts` array (field, reason, values)
|
||||
- `provenance.observationHashes`
|
||||
- `builtByJobId`, `createdAt`
|
||||
- Exclude mutable/derived fields; cache is rebuilt on ingestion replay, not updated in place.
|
||||
|
||||
## Storage & eviction
|
||||
- Collection: `advisory_linkset_cache` (per-tenant index `{tenantId:1, advisoryId:1, source:1}` unique).
|
||||
- Eviction: TTL on `createdAt` disabled by default; cache is replaced when a newer `provenance.observationHashes` differs.
|
||||
- Determinism: cache documents written via canonical JSON writer (sorted keys); timestamps UTC.
|
||||
|
||||
## API exposure
|
||||
- WebService: surface cached linksets via existing `/v1/lnm/linksets/{advisoryId}?source=...` (read-through); if cache miss, rebuild synchronously and store.
|
||||
- Console: may rely on this cache for Advisory AI surfaces; no new payload fields required.
|
||||
|
||||
## Telemetry
|
||||
- Meter `StellaOps.Concelier.Linksets` (existing) to add counters: `lnm.cache.write_total{result}`, `lnm.cache.hit_total{source}`; histogram `lnm.cache.rebuild_ms` for synchronous rebuilds. (To be wired in subsequent sprint.)
|
||||
|
||||
## Alignment
|
||||
- Schema source of truth: `docs/modules/concelier/link-not-merge-schema.md` (frozen v1).
|
||||
- Evidence Locker contract: `docs/modules/evidence-locker/attestation-contract.md` informs provenance fields; no shape changes required.
|
||||
|
||||
## Ownership
|
||||
- Concelier Core + WebService guilds.
|
||||
@@ -0,0 +1,20 @@
|
||||
# Concelier AirGap Prep — PREP-CONCELIER-AIRGAP-56-001..58-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Concelier Core · AirGap Guilds
|
||||
Scope: Capture mirror bundle/staleness requirements for Concelier ingestion under sealed mode.
|
||||
|
||||
## Dependencies
|
||||
- Mirror thin bundle milestones (bundle_id, provenance, staleness_budget) from Mirror sprint 56-001.
|
||||
- AirGap controller staleness/time anchor fields.
|
||||
|
||||
## Needed contract
|
||||
- Ingestion must accept `bundle_id`, `provenance`, `staleness_seconds_remaining` on advisory/linkset endpoints.
|
||||
- Reject non-mirror sources when sealed; surface `AIRGAP_EGRESS_BLOCKED` per Concelier AirGap response contract.
|
||||
|
||||
## Open decisions
|
||||
- Exact header names for bundle/staleness metadata.
|
||||
- Whether to cache bundle provenance per tenant.
|
||||
|
||||
## Handoff
|
||||
Use as PREP artefact for 56-001..58-001 chain; update when mirror bundle schema and controller staleness fields are finalized.
|
||||
16
docs/modules/concelier/prep/2025-11-20-attest-73-001-prep.md
Normal file
16
docs/modules/concelier/prep/2025-11-20-attest-73-001-prep.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# Concelier Attestation Prep — PREP-CONCELIER-ATTEST-73-001/002
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Concelier Core · Evidence Locker Guild
|
||||
Scope: Define attestation scope/signoff pending for Evidence Locker integration.
|
||||
|
||||
## Needs
|
||||
- Evidence Locker attestation scope and DSSE profile.
|
||||
- Endpoint contract for attestation verification of Concelier exports.
|
||||
|
||||
## Open decisions
|
||||
- Signer identity and Rekor usage in sealed mode.
|
||||
- What evidence hashes to include (bundle_id, merkle_root).
|
||||
|
||||
## Handoff
|
||||
Use as PREP artefact; update once EvidenceLocker publishes scope and profile.
|
||||
@@ -0,0 +1,16 @@
|
||||
# Concelier Console Schema Prep — PREP-CONCELIER-CONSOLE-23-001..003
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Concelier Console Guild
|
||||
Scope: Provide schema samples for Console evidence bundles and identifiers.
|
||||
|
||||
## Needed artefacts
|
||||
- Sample schema for console evidence bundle IDs and fields (linkset refs, advisory ids, staleness metadata).
|
||||
- Example payloads for CONCELIER-CONSOLE-23-001..003.
|
||||
|
||||
## Open decisions
|
||||
- ID format for console evidence bundle (ulid vs hash).
|
||||
- Required fields for linkage to LNM outputs.
|
||||
|
||||
## Handoff
|
||||
Use as PREP artefact; fill once LNM schema freeze and console bundle id rules are provided.
|
||||
@@ -0,0 +1,12 @@
|
||||
# Feed Remediation Prep — PREP-FEEDCONN-ICSCISA-02-012 / KISA-02-008
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Concelier Feed Owners
|
||||
Scope: Capture remediation plan for problematic feeds.
|
||||
|
||||
## Items to collect
|
||||
- Current ingestion endpoints and auth for ICSCISA-02-012, KISA-02-008.
|
||||
- Known issues and required remediation steps (validation fixes, throttling, schema tweaks).
|
||||
|
||||
## Handoff
|
||||
Use as PREP artefact; fill with concrete remediation steps once feed owners provide details.
|
||||
@@ -0,0 +1,42 @@
|
||||
# Concelier PREP Notes — 2025-11-20
|
||||
|
||||
Owner: Concelier Core Guild · Scheduler Guild · Data Science Guild
|
||||
Scope: Provide traceable prep outputs for PREP-CONCELIER-GRAPH-21-002-PLATFORM-EVENTS-S and PREP-CONCELIER-LNM-21-002-WAITING-ON-FINALIZE so downstream tasks can proceed without blocking on missing contracts.
|
||||
|
||||
## 1) `sbom.observation.updated` platform event (Graph-21-002)
|
||||
- Goal: publish deterministic, facts-only observation updates for graph overlays; no derived judgments.
|
||||
- Proposed envelope (draft for Scheduler/Platform Events review):
|
||||
- `event_type`: `sbom.observation.updated`
|
||||
- `tenant_id` (string, required)
|
||||
- `advisory_ids` (array of strings; upstream IDs as-ingested)
|
||||
- `observation_ids` (array of stable per-observation IDs emitted by LNM storage)
|
||||
- `source` (string; advisory source slug)
|
||||
- `version_range` (string; original upstream semantics)
|
||||
- `occurred_at` (ISO-8601 UTC, produced by Concelier at write time; deterministic)
|
||||
- `trace` (object; optional provenance pointers, DSSE envelope digest with alg/id fields)
|
||||
- Delivery and wiring expectations:
|
||||
- Publisher lives in `StellaOps.Concelier.Core` after linkset/observation persistence.
|
||||
- Scheduler binding: NATS/Redis topic `concelier.sbom.observation.updated`; ack + idempotent replay friendly; max delivery once semantics via message ID = `<tenant>:<observation_id>::<digest>`.
|
||||
- Telemetry: counter `concelier_events_observation_updated_total{tenant,source,result}`; log template includes `tenant`, `advisory_id`, `observation_id`, `event_id`.
|
||||
- Offline posture: allow emitting into local bus, enqueue to file-backed spool when offline; retry with deterministic ordering by `(tenant, observation_id)`.
|
||||
- Open questions to resolve in impl task:
|
||||
- Final topic naming and DSSE requirement (optional vs required per deployment).
|
||||
- Whether to include component alias list in the event payload or expect consumers to join via API.
|
||||
|
||||
## 2) LNM fixtures + precedence markers (LNM-21-002)
|
||||
- Goal: unblock correlation pipelines and downstream linkset tasks by defining required fixture shape and precedence rules.
|
||||
- Fixture requirements (additive to frozen LNM v1 schema):
|
||||
- Provide at least three sources with conflicting severity/CVSS to exercise conflict markers.
|
||||
- Include overlapping version ranges to validate precedence tie-breakers.
|
||||
- Each fixture must include `provenance` (source, fetch_time, collector) and `confidence` hints.
|
||||
- Precedence rule proposal for review:
|
||||
1. Prefer explicit source ranking table (to be agreed) over recency.
|
||||
2. If ranking ties, prefer narrower version ranges, then higher confidence, then stable lexical order of `(source, advisory_id)`.
|
||||
3. Never collapse conflicting fields; emit `conflicts[]` entries with reason codes `severity-disagree`, `cvss-disagree`, `reference-disagree`.
|
||||
- Delivery path for fixtures once agreed: `src/Concelier/seed-data/lnm/v1/fixtures/*.json` with deterministic ordering; wire into `StellaOps.Concelier.Core.Tests` harness.
|
||||
- Next actions captured for implementation task:
|
||||
- Confirm ranking table and conflict reason code list with Cartographer/Data Science.
|
||||
- Drop initial fixtures into the above path and reference them from the implementation tasks’ tests.
|
||||
|
||||
## Handoff
|
||||
- This document is the published prep artefact requested by PREP-CONCELIER-GRAPH-21-002-PLATFORM-EVENTS-S and PREP-CONCELIER-LNM-21-002-WAITING-ON-FINALIZE. Downstream tasks should cite this file until the final schemas/fixtures are merged.
|
||||
@@ -0,0 +1,44 @@
|
||||
# Concelier Web AirGap Prep — PREP-CONCELIER-WEB-AIRGAP-57-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Concelier WebService Guild · AirGap Policy Guild
|
||||
Scope: Define remediation payloads and staleness plumbing for sealed-mode violations, dependent on WEB-AIRGAP-56-002.
|
||||
|
||||
## Dependencies
|
||||
- WEB-AIRGAP-56-001: mirror bundle registration + sealed-mode enforcement.
|
||||
- WEB-AIRGAP-56-002: staleness + bundle provenance metadata surfaces.
|
||||
- AirGap controller scopes (seal/unseal) and time anchor semantics from AirGap Controller/Time guilds.
|
||||
|
||||
## Proposed payload mapping (EGRESS blocked)
|
||||
- Error code: `AIRGAP_EGRESS_BLOCKED`.
|
||||
- Shape:
|
||||
```json
|
||||
{
|
||||
"error": "AIRGAP_EGRESS_BLOCKED",
|
||||
"message": "Direct internet fetches disabled in sealed mode; use mirror bundle sources only.",
|
||||
"bundle_required": true,
|
||||
"staleness_seconds": 0,
|
||||
"remediation": [
|
||||
"Import mirror bundle via /airgap/import or offline kit",
|
||||
"Ensure sealed mode is set with valid time anchor",
|
||||
"Retry with cached/mirrored sources enabled"
|
||||
]
|
||||
}
|
||||
```
|
||||
- Determinism: fixed ordering of fields, remediation list sorted.
|
||||
|
||||
## Staleness surfacing
|
||||
- Staleness derived from bundle metadata supplied by 56-002 (`bundle_id`, `provenance`, `staleness_budget_seconds`).
|
||||
- Responses include `staleness_seconds_remaining` and `bundle_id` when available.
|
||||
|
||||
## Observability
|
||||
- Emit timeline event `concelier.airgap.egress_blocked` with `{tenant_id, bundle_id?, endpoint, request_id}`.
|
||||
- Metric: `concelier_airgap_egress_blocked_total` (counter) tagged by endpoint.
|
||||
|
||||
## Open decisions
|
||||
- Final error envelope format (depends on WEB-OAS-61-002 standard envelope).
|
||||
- Exact header name for staleness metadata (suggest `x-concelier-bundle-staleness`).
|
||||
- Whether to include advisory key/linkset ids in the blocked response.
|
||||
|
||||
## Handoff
|
||||
Use this as the PREP artefact for WEB-AIRGAP-57-001. Update once 56-002 and error envelope standard are finalized.
|
||||
43
docs/modules/evidence-locker/attestation-contract.md
Normal file
43
docs/modules/evidence-locker/attestation-contract.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Evidence Locker Attestation Contract (v1 · frozen 2025-11-20)
|
||||
|
||||
Scope: Evidence Bundle v1 produced by Evidence Locker and consumed by Concelier, Excititor, Export Center, CLI, and Policy Engine.
|
||||
|
||||
## Predicates & subjects
|
||||
- **Subject**: OCI manifest digest (`sha256:<digest>`) of the bundle, plus optional replay pack digest.
|
||||
- **Predicates (DSSE/In-Toto)**
|
||||
- `stellaops.evidence.bundle.v1`: declares bundle layout (manifests, CAS paths, replay log offsets).
|
||||
- `stellaops.evidence.transparency.v1`: optional Rekor log inclusion proof (UUID, log index, root hash at inclusion).
|
||||
- `stellaops.evidence.integrity.v1`: hashes for each payload (SBOMs, VEX, policy packs, telemetry snapshots), keyed by logical path.
|
||||
|
||||
## Required claim set
|
||||
- `bundle_id` (UUID v4)
|
||||
- `produced_at` (UTC ISO-8601)
|
||||
- `producer` (`evidence-locker:<region>`)
|
||||
- `subject_digest` (OCI digest string)
|
||||
- `hashes` (map: logical path → sha256)
|
||||
- `sbom` (array of SPDX/CycloneDX digests and mediaTypes)
|
||||
- `vex` (array of VEX doc digests and schema versions)
|
||||
- `replay_manifest` (optional; digest + sequence number)
|
||||
- `transparency` (optional; Rekor UUID, logIndex, rootHash)
|
||||
- `signing_profile` (`sovereign-default` | `fips` | `gost` | `pq-experimental`)
|
||||
|
||||
## Bundling & signing rules
|
||||
- DSSE envelope using the module’s configured crypto provider; keys must be short-lived (<24h) and recorded in provider registry.
|
||||
- Hash list and subject digest MUST match the on-disk CAS objects; deterministic sort by logical path.
|
||||
- Rekor entry is optional; when absent, set `transparency=null` and add `transparency_reason="offline"` to provenance note.
|
||||
|
||||
## Verification plan
|
||||
- Verify DSSE signature against provider registry (per profile) and check key expiry.
|
||||
- Recompute sha256 for every CAS object; fail if any mismatch.
|
||||
- If `transparency` present, verify inclusion proof against bundled Rekor root; fail closed on mismatch.
|
||||
- Emit verification report JSON and store beside bundle as `verify.json` (deterministic key order).
|
||||
|
||||
## Fixtures
|
||||
- Sample bundle + report: `docs/samples/evidence-locker/bundle-v1-sample.tar.gz` (sha256 TBD at publish time).
|
||||
- Sample attestation envelope: `docs/samples/evidence-locker/attestation-v1-sample.json`.
|
||||
|
||||
## Ownership
|
||||
- Primary: Evidence Locker Guild.
|
||||
- Reviewers: Concelier Core Guild, Excititor Guild, Export Center Guild, Policy Guild.
|
||||
|
||||
This contract is authoritative for Sprint 110 and blocks CONCELIER-ATTEST-73-001/002 and EXCITITOR-ATTEST-01-003/73-001/73-002.
|
||||
@@ -0,0 +1,21 @@
|
||||
# ICryptoProviderRegistry Prep — PREP-EVID-CRYPTO-90-001 (Draft)
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Evidence Locker Guild · Security Guild
|
||||
Scope: Capture requirements for crypto provider registry readiness to support sovereign/region-specific profiles.
|
||||
|
||||
## Required capabilities
|
||||
- Registry interface to resolve crypto providers by profile ID (e.g., `default`, `ru-offline`, `fips140`, `eidass`).
|
||||
- Provider metadata: `{algorithms[], key_formats[], offline_supported, hsm_supported, oq_ready}`.
|
||||
- Deterministic selection rules: prefer tenant-scoped overrides, fall back to platform defaults; no network fetch.
|
||||
|
||||
## Integration points
|
||||
- Evidence Locker signing pipeline to request provider by profile when sealing bundles.
|
||||
- Replay validation to know which algorithms/hashes are acceptable for DSSE verification.
|
||||
|
||||
## Dependencies
|
||||
- Final list of sovereign profiles from Security Guild.
|
||||
- Key storage/backing (KMS/HSM) availability per profile.
|
||||
|
||||
## Handoff
|
||||
Use this as the prep artefact for PREP-EVID-CRYPTO-90-001; update once profile list and key storage rules are confirmed.
|
||||
42
docs/modules/evidence-locker/replay-payload-contract.md
Normal file
42
docs/modules/evidence-locker/replay-payload-contract.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Replay Payload Contract (Draft) — PREP-EVID-REPLAY-187-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Evidence Locker Guild · Scanner Guild · CLI Guild
|
||||
Scope: Capture expected scanner record payloads needed by Evidence Locker replay APIs.
|
||||
|
||||
## 1) Payload envelope
|
||||
- Content type: `application/vnd.stella.replay.record+json;version=1`.
|
||||
- Fields:
|
||||
- `record_id` (ULID, assigned by Scanner).
|
||||
- `tenant_id` (string).
|
||||
- `source` (enum): `scanner`, `attestor`, `cli`.
|
||||
- `digest` (hex): SHA-256 of canonical payload bytes.
|
||||
- `created_at` (RFC3339 UTC).
|
||||
- `schema_version`: `replay.record.v1`.
|
||||
|
||||
## 2) Scanner record body (expected from Sprint 0186)
|
||||
- `image_digest` (string, required).
|
||||
- `sbom_digest` (string, optional) with SBOM pointer.
|
||||
- `observations` (array) of `{type, component_purl?, location, evidence, confidence}`.
|
||||
- `signals` (array) for runtime/static signals with `{name, value, units?, confidence}`.
|
||||
- `attestations` (array) of DSSE statement references `{type, uri, sha256}`.
|
||||
- `provenance` (object): `{scanner_version, policy_profile, worker_id}`.
|
||||
|
||||
## 3) Evidence Locker ingestion contract
|
||||
- API: `POST /replay/records` (internal) accepting NDJSON stream (`record_envelope + body`).
|
||||
- Validation:
|
||||
- hash must match `digest` supplied; timestamps UTC.
|
||||
- tenant_id must match auth principal or delegated token.
|
||||
- schema_version must equal `replay.record.v1` until upgraded.
|
||||
- Storage layout proposal: bucket prefix `replay/records/{tenant_id}/{record_id}.ndjson`, immutable; metadata indexed in Mongo with `{record_id, image_digest, created_at}`.
|
||||
|
||||
## 4) Open dependencies
|
||||
- Scanner team to freeze exact `observations` and `signals` schema in Sprint 0186.
|
||||
- Need DSSE profile for `attestations` (Authority/Attestor alignment).
|
||||
- CLI replay commands depend on finalized pointer format to retrieve records.
|
||||
|
||||
## 5) Next actions
|
||||
- Once Sprint 0186 publishes sample payloads, update this doc with enumerated observation/signal types and add JSON schema file under `docs/modules/evidence-locker/schemas/replay-record-v1.json`.
|
||||
|
||||
## 6) Handoff
|
||||
Reference this document from sprint trackers for PREP-EVID-REPLAY-187-001 and related CLI/Attestor PREP tasks. Update when upstream payloads are available.
|
||||
23
docs/modules/evidence-locker/validate-bundle-prep.md
Normal file
23
docs/modules/evidence-locker/validate-bundle-prep.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Validate Bundle Prep — PREP-VALIDATE-BUNDLE-187-005 (Draft)
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: QA Guild · CLI Guild · Docs Guild
|
||||
Scope: Define validation steps for replay bundles once schemas freeze.
|
||||
|
||||
## Validation checklist (proposed)
|
||||
- Verify archive hash vs manifest `bundle.manifest.json` (`sha256`).
|
||||
- Verify DSSE signature (if present) against trusted keys.
|
||||
- Recompute Merkle root of bundle file tree; compare to manifest.
|
||||
- Schema validation: replay records conform to `replay.record.v1`; policy export bundle conforms to `policy.export.console.v1` when included.
|
||||
- Determinism: run `stella replay` twice on same bundle and assert identical outputs (hash comparison).
|
||||
|
||||
## Fixtures/tests
|
||||
- Place golden bundles under `tests/EvidenceLocker/Fixtures/replay/` with expected hashes and DSSE signatures.
|
||||
- CLI validation test: `stella verify --bundle <fixture>` returns exit code 0 and prints `verified: true`.
|
||||
|
||||
## Open dependencies
|
||||
- Final schemas from Evidence Locker and Policy export contracts.
|
||||
- Trust root list for DSSE verification (Authority decision).
|
||||
|
||||
## Handoff
|
||||
Use this prep doc for PREP-VALIDATE-BUNDLE-187-005; expand with concrete fixtures once schemas are frozen.
|
||||
@@ -608,12 +608,14 @@ excititor:
|
||||
|
||||
### 9.1 WebService endpoints
|
||||
|
||||
With storage configured, the WebService exposes the following ingress and diagnostic APIs:
|
||||
With storage configured, the WebService exposes the following ingress and diagnostic APIs (deterministic ordering, offline-friendly):
|
||||
|
||||
* `GET /excititor/status` – returns the active storage configuration and registered artifact stores.
|
||||
* `GET /excititor/health` – simple liveness probe.
|
||||
* `POST /excititor/statements` – accepts normalized VEX statements and persists them via `IVexClaimStore`; use this for migrations/backfills.
|
||||
* `GET /excititor/statements/{vulnId}/{productKey}?since=` – returns the immutable statement log for a vulnerability/product pair.
|
||||
* `POST /vex/evidence/chunks` – submits aggregation-only chunks (OpenAPI: `schemas/vex-chunk-api.yaml`); responds with deterministic `chunk_digest` and queue id. Telemetry published under meter `StellaOps.Excititor.Chunks` (see Operations).
|
||||
* `POST /v1/attestations/verify` – verifies Evidence Locker attestations for exports/chunks using `IVexAttestationVerifier`; returns `{ valid, diagnostics }` (deterministic key order). Aligns with Evidence Locker contract v1.
|
||||
* `POST /excititor/resolve` – requires `vex.read` scope; accepts up to 256 `(vulnId, productKey)` pairs via `productKeys` or `purls` and returns deterministic consensus results, decision telemetry, and a signed envelope (`artifact` digest, optional signer signature, optional attestation metadata + DSSE envelope). Returns **409 Conflict** when the requested `policyRevisionId` mismatches the active snapshot.
|
||||
|
||||
Run the ingestion endpoint once after applying migration `20251019-consensus-signals-statements` to repopulate historical statements with the new severity/KEV/EPSS signal fields.
|
||||
|
||||
43
docs/modules/excititor/attestation-plan.md
Normal file
43
docs/modules/excititor/attestation-plan.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Excititor Attestation Plan (Sprint 110)
|
||||
|
||||
## Goals
|
||||
- Align Excititor chunk API and attestation envelopes with Evidence Locker contract.
|
||||
- Provide offline-ready chunk submission/attestation flow for VEX evidence.
|
||||
|
||||
## Chunk API shape (`/vex/evidence/chunks`)
|
||||
- POST body (NDJSON, deterministic order by `chunk_id`):
|
||||
```json
|
||||
{
|
||||
"chunk_id": "uuid",
|
||||
"tenant": "acme",
|
||||
"source": "ghsa",
|
||||
"schema": "stellaops.vex.chunk.v1",
|
||||
"items": [ {"advisory_id":"GHSA-123","status":"affected","purl":"pkg:npm/foo@1.0.0"} ],
|
||||
"provenance": {"fetched_at":"2025-11-20T00:00:00Z","artifact_sha":"abc"}
|
||||
}
|
||||
```
|
||||
- At submission, Excititor returns `chunk_digest` (sha256 of canonical JSON) and queue id.
|
||||
|
||||
## Attestation envelope
|
||||
- Subject: `chunk_digest` from above.
|
||||
- Predicates attached:
|
||||
- `stellaops.vex.chunk.meta.v1` (tenant, source, schema version, item count).
|
||||
- `stellaops.vex.chunk.integrity.v1` (sha256 per item block, canonical order).
|
||||
- Optional `stellaops.transparency.v1` (Rekor UUID/logIndex) when online.
|
||||
- Envelope format: DSSE using Evidence Locker provider registry; signing profile mirrors Evidence Locker bundle profile for tenant.
|
||||
|
||||
## DSSE bundling rules
|
||||
- Deterministic JSON (sorted keys) before hashing.
|
||||
- Canonical NDJSON for chunk payload; no gzip inside envelope.
|
||||
- Attach verification report alongside attestation as `chunk-verify.json` (hashes + signature check results).
|
||||
|
||||
## Sample payloads
|
||||
- `docs/samples/excititor/chunk-sample.ndjson`
|
||||
- `docs/samples/excititor/chunk-attestation-sample.json`
|
||||
|
||||
## Integration points
|
||||
- Evidence Locker contract v1 (see `docs/modules/evidence-locker/attestation-contract.md`).
|
||||
- Concelier LNM schemas (observations remain aggregation-only; attestation is evidence, not merge).
|
||||
|
||||
## Ownership
|
||||
- Excititor Guild (primary); Evidence Locker Guild reviewer.
|
||||
@@ -0,0 +1,36 @@
|
||||
# Connector signer metadata (v1.0.0)
|
||||
|
||||
**Scope.** Defines the canonical, offline-friendly metadata for Excititor connectors that validate signed feeds (MSRC CSAF, Oracle OVAL, Ubuntu OVAL, StellaOps mirror OpenVEX). The file is consumed by WebService/Worker composition roots and by Offline Kits to pin trust material deterministically.
|
||||
|
||||
**Location & format.**
|
||||
- Schema: `docs/modules/excititor/schemas/connector-signer-metadata.schema.json` (JSON Schema 2020‑12).
|
||||
- Sample: `docs/samples/excititor/connector-signer-metadata-sample.json` (aligns with schema).
|
||||
- Expected production artifact: NDJSON or JSON stamped per release; store in offline kits alongside connector bundles.
|
||||
|
||||
## Required fields (summary)
|
||||
- `schemaVersion` — must be `1.0.0`.
|
||||
- `generatedAt` — ISO-8601 UTC timestamp for the metadata file.
|
||||
- `connectors[]` — one entry per connector:
|
||||
- `connectorId` — stable slug, e.g., `excititor-msrc-csaf`.
|
||||
- `provider { name, slug }` — human label and slug.
|
||||
- `issuerTier` — `tier-0`, `tier-1`, `tier-2`, or `untrusted` (aligns with trust weighting).
|
||||
- `signers[]` — one per signing path; each has `usage` (`csaf|oval|openvex|bulk-meta|attestation`) and `fingerprints[]` (algorithm + format + value). Optional `keyLocator` and `certificateChain` for offline key retrieval.
|
||||
- `bundle` — reference to the sealed bundle containing the feed/signing material (`kind`: `oci-referrer|oci-tag|file|tuf`, plus `uri`, optional `digest`, `publishedAt`).
|
||||
- Optional `validFrom`, `validTo`, `revoked`, `notes` for rollover and incident handling.
|
||||
|
||||
## Rollover / migration guidance
|
||||
1) **Author the metadata** using the schema and place the JSON next to connector bundles in the offline kit (`out/connectors/<provider>/signer-metadata.json`).
|
||||
2) **Validate** with `dotnet tool run njsonschema validate connector-signer-metadata.schema.json connector-signer-metadata.json` (or `ajv validate`).
|
||||
3) **Wire connector code** to load the file on startup (Worker + WebService) and pin signers per `connectorId`; reject feeds whose fingerprints are absent or marked `revoked=true` or out of `validFrom/To` range.
|
||||
- Connectors look for `STELLAOPS_CONNECTOR_SIGNER_METADATA_PATH` (absolute/relative) and enrich provenance metadata automatically when present.
|
||||
4) **Rollover keys** by appending a new `signers` entry and setting a future `validFrom`; keep the previous signer until all mirrors have caught up. Use `issuerTier` downgrades to quarantine while keeping history.
|
||||
5) **Mirror references**: store the referenced bundles/keys under OCI tags or TUF targets already shipped in the offline kit so no live network is required.
|
||||
6) **Record decisions** in sprint Decisions & Risks when changing trust tiers or fingerpints; update this doc if formats change.
|
||||
|
||||
## Sample entries (non-production)
|
||||
See `docs/samples/excititor/connector-signer-metadata-sample.json` for MSRC, Oracle, Ubuntu, and StellaOps example entries. These fingerprints are illustrative only; replace with real values before shipping.
|
||||
|
||||
## Consumer expectations
|
||||
- Deterministic: sort connectors alphabetically before persistence; avoid clock-based defaults.
|
||||
- Offline-first: all `keyLocator`/`bundle.uri` values must resolve inside the air-gap kit (OCI/TUF/file).
|
||||
- Observability: emit a structured warning when metadata is missing or stale (>7 days) and fail closed for missing signers.
|
||||
24
docs/modules/excititor/operations/chunk-api-user-guide.md
Normal file
24
docs/modules/excititor/operations/chunk-api-user-guide.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Using the Chunk API
|
||||
|
||||
Endpoint: `POST /vex/evidence/chunks`
|
||||
- Content-Type: `application/x-ndjson`
|
||||
- See schema: `docs/modules/excititor/schemas/vex-chunk-api.yaml`
|
||||
|
||||
Response: `202 Accepted`
|
||||
```json
|
||||
{ "chunk_digest": "sha256:…", "queue_id": "uuid" }
|
||||
```
|
||||
|
||||
Operational notes
|
||||
- Deterministic hashing: server recomputes `chunk_digest` from canonical JSON; mismatches return 400.
|
||||
- Limits: default 500 items, max 2000 (aligned with Program.cs guard).
|
||||
- Telemetry: metrics under `StellaOps.Excititor.Chunks` (see chunk-telemetry.md).
|
||||
- Headers: correlation/trace headers echoed (`X-Stella-TraceId`, `X-Stella-CorrelationId`).
|
||||
|
||||
Example curl
|
||||
```bash
|
||||
curl -X POST https://excitor.local/vex/evidence/chunks \
|
||||
-H "Authorization: Bearer <token>" \
|
||||
-H "Content-Type: application/x-ndjson" \
|
||||
--data-binary @docs/samples/excititor/chunk-sample.ndjson
|
||||
```
|
||||
26
docs/modules/excititor/operations/chunk-telemetry.md
Normal file
26
docs/modules/excititor/operations/chunk-telemetry.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Excititor Chunk Telemetry (Sprint 110)
|
||||
|
||||
## Metrics (Meter: `StellaOps.Excititor.Chunks`)
|
||||
- `vex_chunks_ingested_total` (counter) — tags: `tenant`, `source`, `status` (`accepted|rejected`), `reason` (nullable for accepted). Increments per chunk submitted.
|
||||
- `vex_chunks_item_count` (histogram, unit=items) — records item count per chunk.
|
||||
- `vex_chunks_payload_bytes` (histogram, unit=bytes) — measured from NDJSON payload length.
|
||||
- `vex_chunks_latency_ms` (histogram) — end-to-end ingestion latency per request.
|
||||
|
||||
## Logs
|
||||
- `vex.chunk.ingest.accepted` — includes `chunk_id`, `tenant`, `source`, `item_count`, `chunk_digest`.
|
||||
- `vex.chunk.ingest.rejected` — includes `chunk_id`, `tenant`, `source`, `reason`, validation errors (summarized).
|
||||
|
||||
## Wiring steps
|
||||
1. Register `ChunkTelemetry` as singleton with shared `Meter` instance.
|
||||
2. In `/vex/evidence/chunks` handler, compute `chunk_digest` deterministically from canonical JSON and emit counters/histograms via `ChunkTelemetry`.
|
||||
3. Log using structured templates above; avoid request bodies in logs.
|
||||
4. Expose metrics via default ASP.NET metrics export (Prometheus/OpenTelemetry) already configured in WebService.
|
||||
|
||||
## Determinism & offline posture
|
||||
- Do not include host-specific paths or timestamps in metric dimensions.
|
||||
- Histogram buckets: use standard OTEL defaults; no runtime-generated buckets.
|
||||
- Keep meter name stable; adding new instruments requires version note in sprint Decisions & Risks.
|
||||
|
||||
## Ownership
|
||||
- Implementer: Excititor Observability Guild
|
||||
- Reviewers: Evidence Locker Guild (for parity with attestation metrics)
|
||||
@@ -0,0 +1,125 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://stellaops.dev/schemas/excititor/connector-signer-metadata.schema.json",
|
||||
"title": "Excititor Connector Signer Metadata",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["schemaVersion", "generatedAt", "connectors"],
|
||||
"properties": {
|
||||
"schemaVersion": {
|
||||
"type": "string",
|
||||
"pattern": "^1\\.0\\.0$"
|
||||
},
|
||||
"generatedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"connectors": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"$ref": "#/$defs/connector"
|
||||
}
|
||||
}
|
||||
},
|
||||
"$defs": {
|
||||
"connector": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"connectorId",
|
||||
"provider",
|
||||
"issuerTier",
|
||||
"signers"
|
||||
],
|
||||
"properties": {
|
||||
"connectorId": {
|
||||
"type": "string",
|
||||
"pattern": "^[a-z0-9:-\\.]+$"
|
||||
},
|
||||
"provider": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["name", "slug"],
|
||||
"properties": {
|
||||
"name": { "type": "string", "minLength": 3 },
|
||||
"slug": { "type": "string", "pattern": "^[a-z0-9-]+$" }
|
||||
}
|
||||
},
|
||||
"issuerTier": {
|
||||
"type": "string",
|
||||
"enum": ["tier-0", "tier-1", "tier-2", "untrusted"]
|
||||
},
|
||||
"signers": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": { "$ref": "#/$defs/signer" }
|
||||
},
|
||||
"bundle": { "$ref": "#/$defs/bundleRef" },
|
||||
"validFrom": { "type": "string", "format": "date" },
|
||||
"validTo": { "type": "string", "format": "date" },
|
||||
"revoked": { "type": "boolean", "default": false },
|
||||
"notes": { "type": "string", "maxLength": 2000 }
|
||||
}
|
||||
},
|
||||
"signer": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["usage", "fingerprints"],
|
||||
"properties": {
|
||||
"usage": {
|
||||
"type": "string",
|
||||
"enum": ["csaf", "oval", "openvex", "bulk-meta", "attestation"]
|
||||
},
|
||||
"fingerprints": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": { "$ref": "#/$defs/fingerprint" }
|
||||
},
|
||||
"keyLocator": {
|
||||
"type": "string",
|
||||
"description": "Path or URL (mirror/OCI/TUF) where the signing key or certificate chain can be retrieved in offline kits."
|
||||
},
|
||||
"certificateChain": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"description": "Optional PEM-encoded certificates for x509/cosign keys."
|
||||
}
|
||||
}
|
||||
},
|
||||
"fingerprint": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["alg", "value"],
|
||||
"properties": {
|
||||
"alg": {
|
||||
"type": "string",
|
||||
"enum": ["sha256", "sha512", "sha1"]
|
||||
},
|
||||
"format": {
|
||||
"type": "string",
|
||||
"enum": ["pgp", "x509-spki", "x509-ski", "cosign", "pem"]
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"minLength": 16,
|
||||
"maxLength": 128
|
||||
}
|
||||
}
|
||||
},
|
||||
"bundleRef": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["kind", "uri"],
|
||||
"properties": {
|
||||
"kind": {
|
||||
"type": "string",
|
||||
"enum": ["oci-referrer", "oci-tag", "file", "tuf"]
|
||||
},
|
||||
"uri": { "type": "string", "minLength": 8 },
|
||||
"digest": { "type": "string", "minLength": 32 },
|
||||
"publishedAt": { "type": "string", "format": "date-time" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
82
docs/modules/excititor/schemas/vex-chunk-api.yaml
Normal file
82
docs/modules/excititor/schemas/vex-chunk-api.yaml
Normal file
@@ -0,0 +1,82 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: StellaOps Excititor Chunk API
|
||||
version: "0.1.0"
|
||||
description: |
|
||||
Frozen for Sprint 110 (EXCITITOR-AIAI-31-002). Aligns with Evidence Locker attestation contract v1.
|
||||
servers:
|
||||
- url: https://excitor.local
|
||||
paths:
|
||||
/vex/evidence/chunks:
|
||||
post:
|
||||
summary: Submit VEX evidence chunk (aggregation-only)
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/x-ndjson:
|
||||
schema:
|
||||
$ref: '#/components/schemas/VexChunk'
|
||||
responses:
|
||||
'202':
|
||||
description: Accepted for processing
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [chunk_digest, queue_id]
|
||||
properties:
|
||||
chunk_digest:
|
||||
type: string
|
||||
description: sha256 of canonical chunk JSON
|
||||
queue_id:
|
||||
type: string
|
||||
description: Background job identifier
|
||||
'400':
|
||||
description: Validation error
|
||||
components:
|
||||
schemas:
|
||||
VexChunk:
|
||||
type: object
|
||||
required: [chunk_id, tenant, source, schema, items, provenance]
|
||||
properties:
|
||||
chunk_id:
|
||||
type: string
|
||||
format: uuid
|
||||
tenant:
|
||||
type: string
|
||||
source:
|
||||
type: string
|
||||
description: feed id (e.g., ghsa, nvd)
|
||||
schema:
|
||||
type: string
|
||||
enum: [stellaops.vex.chunk.v1]
|
||||
items:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [advisory_id, status, purl]
|
||||
properties:
|
||||
advisory_id:
|
||||
type: string
|
||||
status:
|
||||
type: string
|
||||
enum: [affected, unaffected, under_investigation, fixed, unknown]
|
||||
purl:
|
||||
type: string
|
||||
justification:
|
||||
type: string
|
||||
last_observed:
|
||||
type: string
|
||||
format: date-time
|
||||
provenance:
|
||||
type: object
|
||||
required: [fetched_at, artifact_sha]
|
||||
properties:
|
||||
fetched_at:
|
||||
type: string
|
||||
format: date-time
|
||||
artifact_sha:
|
||||
type: string
|
||||
signature:
|
||||
type: object
|
||||
nullable: true
|
||||
@@ -0,0 +1,17 @@
|
||||
# Export Crypto Prep — PREP-EXPORT-CRYPTO-90-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Exporter Service · Security Guild
|
||||
Scope: Capture crypto requirements pending Nov-18 review and reference implementation.
|
||||
|
||||
## Needs
|
||||
- Mapping of signing/encryption algorithms per export profile.
|
||||
- Integration with `ICryptoProviderRegistry` (same as Evidence Locker) for provider selection.
|
||||
- Hashing defaults (sha256) and optional sha512/sha3 for high-assurance paths.
|
||||
|
||||
## Open decisions
|
||||
- Final provider list and key storage (KMS/HSM) per profile.
|
||||
- Whether to sign both manifest and per-artifact hashes.
|
||||
|
||||
## Handoff
|
||||
Use as prep artefact for EXPORT-CRYPTO-90-001; fill once Security delivers profile list and reference implementation.
|
||||
@@ -0,0 +1,15 @@
|
||||
# Exporter Service Blocker — PREP-EXPORTER-SERVICE-BLOCKED-WAITING-ON-EVID
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Planning
|
||||
Scope: Document EvidenceLocker dependency blocking exporter service.
|
||||
|
||||
## Blocker
|
||||
- EvidenceLocker spec not published; need replay/export bundle schemas and ICryptoProviderRegistry availability.
|
||||
|
||||
## What we need
|
||||
- Bundle schema pointers (from EvidenceLocker) and retention rules.
|
||||
- Sample payloads to mirror into exporter tests.
|
||||
|
||||
## Handoff
|
||||
Use this note to track unblock; update when EvidenceLocker spec is available.
|
||||
@@ -0,0 +1,29 @@
|
||||
# Export Notifications Schema Prep — PREP-EXPORT-NOTIFY-SCHEMA-OBS-52
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Notifications Guild · Exporter Service
|
||||
Scope: Define notification envelope/payloads for export lifecycle events.
|
||||
|
||||
## Event types
|
||||
- `export.started`, `export.completed`, `export.failed`.
|
||||
|
||||
## Envelope (proposed)
|
||||
```json
|
||||
{
|
||||
"type": "export.completed",
|
||||
"export_id": "...",
|
||||
"profile_id": "...",
|
||||
"tenant_id": "...",
|
||||
"artifact_counts": {"json": 2, "mirror": 1},
|
||||
"sha256": "...",
|
||||
"created_at": "2025-11-20T00:00:00Z"
|
||||
}
|
||||
```
|
||||
- Deterministic key ordering; timestamps UTC.
|
||||
|
||||
## Open decisions
|
||||
- Channel/transport (NATS vs Redis streams vs webhooks).
|
||||
- Required retry/backoff policy and DLQ routing.
|
||||
|
||||
## Handoff
|
||||
Use this prep doc for PREP-EXPORT-NOTIFY-SCHEMA-OBS-52; update once transport + DLQ policy are chosen.
|
||||
@@ -0,0 +1,17 @@
|
||||
# Export Telemetry Prep — PREP-EXPORT-OBS-50-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Exporter Service · Observability Guild
|
||||
Scope: Define telemetry schema for exporter service bootstrap.
|
||||
|
||||
## Proposed metrics/logs
|
||||
- Metrics (Prometheus/Otel): `export_runs_total{profile, tenant}`, `export_run_duration_seconds`, `export_artifacts_total{type}`, `export_failures_total`, `export_bytes_total`.
|
||||
- Logs: structured with fields `{export_id, profile, tenant, artifact_type, status, duration_ms}`.
|
||||
- Traces: span names `export.run`, `export.plan`, `export.write`; tags include `profile`, `tenant`, `artifact_count`.
|
||||
|
||||
## Open decisions
|
||||
- Histogram buckets for duration/bytes.
|
||||
- Required correlation IDs for downstream Console ingestion.
|
||||
|
||||
## Handoff
|
||||
Use this as PREP artefact for EXPORT-OBS-50-001; update buckets and trace tags once Observability finalizes naming.
|
||||
@@ -0,0 +1,21 @@
|
||||
# Export Risk Bundle Prep — PREP-EXPORT-RISK-69-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Exporter Service · Risk Bundle Export Guild
|
||||
Scope: Capture provider selection rules and schema needs for risk bundle job handler.
|
||||
|
||||
## Provider selection (proposed)
|
||||
- Inputs: `risk_profile_id`, `tenant_id`, `preferred_provider`, `fallback_provider`.
|
||||
- Selection order: tenant override → profile default → system default.
|
||||
- Providers must advertise capabilities `{formats[], signing_profiles[]}`.
|
||||
|
||||
## Manifest expectations
|
||||
- Fields: `bundle_id`, `profile_id`, `provider_id`, `inputs_hash`, `created_at`, `artifacts[] {path, sha256, media_type}`.
|
||||
- Deterministic ordering and sha256 for all artifacts.
|
||||
|
||||
## Open decisions
|
||||
- Final list of providers and signing profiles.
|
||||
- Whether to embed policy/export bundle pointers.
|
||||
|
||||
## Handoff
|
||||
Use this as PREP artefact for EXPORT-RISK-69-001; update provider list and manifest once phase I artifacts land.
|
||||
@@ -0,0 +1,21 @@
|
||||
# Export Service Bootstrap Prep — PREP-EXPORT-SVC-35-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Exporter Service
|
||||
Scope: Capture phase I readiness for exporter service project/migrations.
|
||||
|
||||
## Project baseline
|
||||
- Service: minimal API (net10.0), Postgres storage for `export_profiles`, `export_runs`, `export_inputs`, `export_distributions`.
|
||||
- Tests: xUnit + integration harness with deterministic timestamps.
|
||||
|
||||
## Schema notes
|
||||
- `export_profiles`: `{id, name, tenant_id?, config_json}`.
|
||||
- `export_runs`: `{id, profile_id, tenant_id, status, started_at, completed_at, artifact_counts JSONB}`.
|
||||
- Deterministic defaults: UTC timestamps; snake_case columns.
|
||||
|
||||
## Open decisions
|
||||
- Final Postgres schema (indices, enums for status).
|
||||
- Whether to store metrics snapshots inline or via observability pipeline.
|
||||
|
||||
## Handoff
|
||||
Use this as PREP artefact for EXPORT-SVC-35-001; update once phase I readiness and synthetic telemetry feeds are defined.
|
||||
@@ -0,0 +1,20 @@
|
||||
# Export Service Planner Prep — PREP-EXPORT-SVC-35-002
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Exporter Service
|
||||
Scope: Planner + scope resolver for exports, depends on 35-001 bootstrap.
|
||||
|
||||
## Planner inputs
|
||||
- `profile_id`, `tenant_id`, `inputs` (bundle pointers), `priority`.
|
||||
- `limits`: max artifacts, max runtime.
|
||||
|
||||
## Outputs
|
||||
- Plan document `{plan_id, profile_id, tenant_id, steps[], estimated_bytes, estimated_duration_ms}`.
|
||||
- Steps sorted; deterministic hashing of plan.
|
||||
|
||||
## Open decisions
|
||||
- Step types allowed (json adapters, mirror, manifest signing).
|
||||
- How to surface rejection reasons to upstream services.
|
||||
|
||||
## Handoff
|
||||
Use as prep artefact; update once 35-001 schema is fixed.
|
||||
@@ -0,0 +1,16 @@
|
||||
# Export JSON Adapter Prep — PREP-EXPORT-SVC-35-003
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Exporter Service
|
||||
Scope: JSON adapters (`json:raw`, `json:policy`) normalization/redaction/compression.
|
||||
|
||||
## Deliverable shape
|
||||
- Adapter config: `{type, redactions[], compress: bool, normalize_paths: bool}`.
|
||||
- Output manifest entry: `{path, sha256, media_type, original_size, compressed_size?}`.
|
||||
|
||||
## Open decisions
|
||||
- Redaction rules list and ordering.
|
||||
- Compression algorithm (gzip vs zstd) and level defaults.
|
||||
|
||||
## Handoff
|
||||
Prep artefact for 35-003; align with plan model once 35-002 is fixed.
|
||||
@@ -0,0 +1,17 @@
|
||||
# Export Mirror Adapter Prep — PREP-EXPORT-SVC-35-004
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Exporter Service
|
||||
Scope: Mirror (full) adapter producing filesystem layout, indexes, manifests, README.
|
||||
|
||||
## Layout proposal
|
||||
- root manifest `mirror.manifest.json` with Merkle root.
|
||||
- Directories: `artifacts/`, `indexes/`, `docs/README.md`.
|
||||
- Deterministic ordering, UTC timestamps.
|
||||
|
||||
## Open decisions
|
||||
- Which indexes required (by profile vs dataset).
|
||||
- Manifest fields alignment with Mirror thin bundle.
|
||||
|
||||
## Handoff
|
||||
Use as prep artefact; fill fields once 35-003 outputs and mirror schema decisions are in.
|
||||
@@ -0,0 +1,16 @@
|
||||
# Export Manifest/Signing Prep — PREP-EXPORT-SVC-35-005
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Exporter Service · Security Guild
|
||||
Scope: Manifest/provenance writer + KMS signing/attestation.
|
||||
|
||||
## Proposed manifest
|
||||
- `export_id`, `profile_id`, `tenant_id`, `artifacts[] {path, sha256, media_type}`, `created_at`, `inputs_hash`, `signatures[]`.
|
||||
- DSSE envelope for manifest; signer from ICryptoProviderRegistry.
|
||||
|
||||
## Open decisions
|
||||
- Signing profile list and KMS/HSM mapping.
|
||||
- Rekor/Transparency use in offline vs online.
|
||||
|
||||
## Handoff
|
||||
Prep artefact for 35-005; update once crypto profile and provider registry decisions land.
|
||||
4
docs/modules/findings-ledger/README.md
Normal file
4
docs/modules/findings-ledger/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
# Findings Ledger
|
||||
|
||||
Start here for ledger docs.
|
||||
70
docs/modules/findings-ledger/export-http-surface.md
Normal file
70
docs/modules/findings-ledger/export-http-surface.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# Findings Ledger Export HTTP Surface
|
||||
|
||||
Prep task: PREP-LEDGER-EXPORT-35-001-NO-HTTP-API-SURFACE (Sprint 0121)
|
||||
|
||||
## Goals
|
||||
- Publish an HTTP surface for deterministic, offline-friendly exports of Findings Ledger data (findings, VEX, advisories, SBOMs) so downstream SDK/OpenAPI tasks can proceed.
|
||||
- Define filter contract, pagination, media types, and provenance fields required by Evidence Locker and Policy Engine consumers.
|
||||
|
||||
## Non-goals
|
||||
- Implementing the endpoints (covered by LEDGER-EXPORT-35-001).
|
||||
- Final OAS/SDK generation (tracked in PREP-LEDGER-OAS-61-001/002/62-001/63-001).
|
||||
|
||||
## Base Service
|
||||
- Host: findings-ledger service (minimal API) under `src/Findings/StellaOps.Findings.Ledger`.
|
||||
- Base path: `/ledger/export`.
|
||||
- Auth: service-to-service bearer token; require `scope=ledger.export.read`.
|
||||
- Tenancy: `X-Stella-Tenant` header (strictly required); responses never mix tenants.
|
||||
- Determinism: server sorts by `(event_sequence, projection_version, cycle_hash)`; pagination tokens encode the last emitted tuple and filter set. No wall-clock dependence.
|
||||
- Media types: default `application/x-ndjson`; clients may request `application/json` (array) for small result sets. Always emit `Content-Encoding: gzip` when `Accept-Encoding` allows.
|
||||
|
||||
## Endpoints
|
||||
|
||||
### 1) Findings
|
||||
- `GET /ledger/export/findings`
|
||||
- Filters (all optional unless noted):
|
||||
- `shape` (required): `canonical` \| `compact` (controls payload shape; compact strips verbose provenance fields for air-gap bundles)
|
||||
- `since_sequence` (long, ≥0), `until_sequence` (long, inclusive) — enables range slicing.
|
||||
- `since_observed_at`, `until_observed_at` (ISO-8601 UTC) — observation window.
|
||||
- `advisory_id` (repeatable), `component_purl` (repeatable), `finding_status` (`open|fixed|dismissed`), `severity` (`critical|high|medium|low|unknown`).
|
||||
- `risk_profile_version` (string) — filters by attached risk profile revision.
|
||||
- Response item (canonical shape):
|
||||
- `finding_id`, `event_sequence`, `observed_at`, `component` (purl, version, source), `advisories` (ids, cwes), `status`, `severity`, `risk` (score, severity, profile_version, explanation_id), `projection_version`, `cycle_hash`, `evidence_bundle_ref` (digest, dsse_digest, timeline_ref), `provenance` (ledger_root, projector_version, policy_version, datasource_ids).
|
||||
|
||||
### 2) VEX
|
||||
- `GET /ledger/export/vex`
|
||||
- Filters: `shape`, `since_sequence/until_sequence`, `since_observed_at/until_observed_at`, `product_id` (repeatable), `advisory_id`, `status` (`affected|not_affected|under_investigation`), `statement_type` (`exploitation|justification`).
|
||||
- Response item adds `vex_statement_id`, `product` (purl or CPE), `status_justification`, `known_exploited` (bool), `timestamp`, `projection_version`, `cycle_hash`, `provenance`.
|
||||
|
||||
### 3) Advisories
|
||||
- `GET /ledger/export/advisories`
|
||||
- Filters: `shape`, `since_sequence/until_sequence`, `severity`, `source` (feed id), `cwe_id`, `kev` (bool), `cvss_version`, `cvss_score_min`, `cvss_score_max`.
|
||||
- Response item: `advisory_id`, `source`, `title`, `description`, `cwes`, `cvss` (version, vector, base_score), `published`, `modified`, `status`, `epss` (score, percentile), `projection_version`, `cycle_hash`, `provenance`.
|
||||
|
||||
### 4) SBOMs
|
||||
- `GET /ledger/export/sboms`
|
||||
- Filters: `shape`, `since_sequence/until_sequence`, `since_observed_at/until_observed_at`, `subject_digest` (OCI digest), `sbom_format` (`spdx-json` \| `cyclonedx-json`), `component_purl` (repeatable), `contains_native` (bool), `slsa_build_type` (string).
|
||||
- Response item: `sbom_id`, `subject` (digest, media_type), `sbom_format`, `created_at`, `components_count`, `has_vulnerabilities` (bool), `materials` (digests), `projection_version`, `cycle_hash`, `provenance`.
|
||||
|
||||
## Pagination
|
||||
- Cursor param: `page_token` (opaque base64url JSON: `{ "last": { "event_sequence": long, "projection_version": string, "cycle_hash": string }, "filters_hash": sha256 }`).
|
||||
- Page size: `page_size` (default 500, max 5000). Server rejects if `page_size` differs across pages for same token.
|
||||
- Response envelope (for both NDJSON and JSON array):
|
||||
- Header `X-Stella-Next-Page-Token` when more data exists.
|
||||
- Header `X-Stella-Result-Count` with items count.
|
||||
- When `Prefer: return=minimal` is set, omit envelope body for NDJSON; clients rely on headers.
|
||||
|
||||
## Error Contract
|
||||
- 400: unknown filter, invalid range, or filter combination mismatch with `filters_hash` inside `page_token`.
|
||||
- 401/403: missing or insufficient scope.
|
||||
- 409: requested `shape` not compatible with downstream air-gap mode (compact requested where policy mandates canonical).
|
||||
- 429: enforcement of determinism guard (server detected projection drift vs cycle_hash); include `X-Stella-Drift-Reason`.
|
||||
|
||||
## Observability & Determinism Hooks
|
||||
- Emit structured logs `ledger.export.request` and `ledger.export.emit` with tenant, endpoint, filters_hash, page_size, result_count, duration_ms.
|
||||
- Counters: `ledger_export_items_total{endpoint,tenant}` and `ledger_export_failures_total{endpoint,reason}`.
|
||||
- Traces: span name `ledger.export.{endpoint}`; attach `filters_hash`, `page_size`, `next_page_token_present` attributes.
|
||||
|
||||
## artefact location
|
||||
- This document: `docs/modules/findings-ledger/export-http-surface.md` (hash stability: keep deterministic ordering as authored on 2025-11-20).
|
||||
- Link from sprint 0121 PREP-LEDGER-EXPORT-35-001; downstream tasks should reference this path for contract details.
|
||||
28
docs/modules/findings-ledger/oas-baseline.md
Normal file
28
docs/modules/findings-ledger/oas-baseline.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Findings Ledger OAS baseline (v1)
|
||||
|
||||
**Scope.** Establish the canonical OpenAPI baseline and API host definitions for Findings Ledger. This satisfies PREP-LEDGER-OAS-61-001 and unblocks downstream OAS/SDK/OBS tasks (61-002..63-001).
|
||||
|
||||
**What shipped (2025-11-20).**
|
||||
- Published baseline OAS document: `docs/modules/findings-ledger/openapi/findings-ledger.v1.yaml` (OpenAPI 3.0.3).
|
||||
- Servers: `https://{env}.ledger.api.stellaops.local` (env ∈ dev/staging/prod/airgap) and offline `https://ledger.{region}.offline.bundle`.
|
||||
- Security: `bearerAuth` (JWT) and `mTLS` declared; tenant header `X-Stella-Tenant` required.
|
||||
- Paths included:
|
||||
- `GET /v1/ledger/events` (deterministic paging by chain/sequence; cursor header).
|
||||
- `POST /v1/ledger/events` (append; validates hashes; 409 on non-deterministic input).
|
||||
- `GET /v1/ledger/projections/findings` (projection read with `cycleHash`).
|
||||
- Schemas align with `docs/modules/findings-ledger/schema.md` (ledger events, projections, hashes, provenance fields).
|
||||
|
||||
**Usage / next steps.**
|
||||
- Export to renderer or client generation from `findings-ledger.v1.yaml`; keep schema source of truth in YAML, not code-first.
|
||||
- Downstream tasks (61-002, 62-001, 63-001) should extend this spec with SDK/validation/deprecation headers but **must not** change base paths, security schemes, or canonical field names.
|
||||
- When new fields are added, update both `schema.md` and the YAML and bump `info.version` with changelog entry.
|
||||
|
||||
**Determinism & offline posture.**
|
||||
- Stable ordering: events sorted by `(chainId, sequence)`; projections do not perform consensus/merges.
|
||||
- No external calls required at runtime; offline host is declared for bundle deployments.
|
||||
- Hash fields (`eventHash`, `previousHash`, `merkleLeafHash`, `cycleHash`) remain lowercase hex SHA-256 per schema.
|
||||
|
||||
**Artifact locations.**
|
||||
- OAS YAML: `docs/modules/findings-ledger/openapi/findings-ledger.v1.yaml`
|
||||
- Schema reference: `docs/modules/findings-ledger/schema.md`
|
||||
- Export surface reference (for later OAS extensions): `docs/modules/findings-ledger/export-http-surface.md`
|
||||
264
docs/modules/findings-ledger/openapi/findings-ledger.v1.yaml
Normal file
264
docs/modules/findings-ledger/openapi/findings-ledger.v1.yaml
Normal file
@@ -0,0 +1,264 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: StellaOps Findings Ledger API
|
||||
version: 1.0.0-beta1
|
||||
description: >-
|
||||
Canonical, aggregation-only surface for append-only findings events, projections, and
|
||||
Merkle anchoring metadata. Aligns with schema in docs/modules/findings-ledger/schema.md.
|
||||
servers:
|
||||
- url: https://{env}.ledger.api.stellaops.local
|
||||
description: Default environment-scoped host
|
||||
variables:
|
||||
env:
|
||||
default: prod
|
||||
enum: [dev, staging, prod, airgap]
|
||||
- url: https://ledger.{region}.offline.bundle
|
||||
description: Offline bundle host for air-gapped deployments
|
||||
variables:
|
||||
region:
|
||||
default: local
|
||||
enum: [local]
|
||||
security:
|
||||
- bearerAuth: []
|
||||
- mTLS: []
|
||||
paths:
|
||||
/v1/ledger/events:
|
||||
get:
|
||||
summary: List ledger events
|
||||
operationId: listLedgerEvents
|
||||
tags: [ledger]
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/TenantId'
|
||||
- name: chainId
|
||||
in: query
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
- name: sinceSequence
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
minimum: 0
|
||||
- name: limit
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
default: 200
|
||||
maximum: 1000
|
||||
responses:
|
||||
'200':
|
||||
description: Paged ledger events in deterministic order (chainId, sequence_No asc)
|
||||
headers:
|
||||
Req-Cursor:
|
||||
schema:
|
||||
type: string
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/LedgerEventPage'
|
||||
post:
|
||||
summary: Append deterministic ledger event
|
||||
operationId: appendLedgerEvent
|
||||
tags: [ledger]
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/TenantId'
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/LedgerEventAppendRequest'
|
||||
responses:
|
||||
'201':
|
||||
description: Event persisted
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/LedgerEvent'
|
||||
'409':
|
||||
description: Hash/sequence conflict (non-deterministic input)
|
||||
/v1/ledger/projections/findings:
|
||||
get:
|
||||
summary: Get latest projection for findings
|
||||
operationId: listFindingProjections
|
||||
tags: [projections]
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/TenantId'
|
||||
- name: findingId
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
- name: policyVersion
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
- name: status
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
- name: limit
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
default: 200
|
||||
maximum: 1000
|
||||
responses:
|
||||
'200':
|
||||
description: Projection rows with cycleHash for replay validation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FindingProjectionPage'
|
||||
components:
|
||||
securitySchemes:
|
||||
bearerAuth:
|
||||
type: http
|
||||
scheme: bearer
|
||||
bearerFormat: JWT
|
||||
mTLS:
|
||||
type: mutualTLS
|
||||
parameters:
|
||||
TenantId:
|
||||
name: X-Stella-Tenant
|
||||
in: header
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
schemas:
|
||||
LedgerEvent:
|
||||
type: object
|
||||
required: [event]
|
||||
properties:
|
||||
event:
|
||||
type: object
|
||||
required: [id, type, tenant, chainId, sequence, policyVersion, occurredAt, recordedAt, payload]
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
format: uuid
|
||||
type:
|
||||
type: string
|
||||
description: ledger_event_type (see schema.md §2.2)
|
||||
tenant:
|
||||
type: string
|
||||
chainId:
|
||||
type: string
|
||||
format: uuid
|
||||
sequence:
|
||||
type: integer
|
||||
policyVersion:
|
||||
type: string
|
||||
finding:
|
||||
type: object
|
||||
properties:
|
||||
id: { type: string }
|
||||
artifactId: { type: string }
|
||||
vulnId: { type: string }
|
||||
actor:
|
||||
type: object
|
||||
properties:
|
||||
id: { type: string }
|
||||
type: { type: string }
|
||||
occurredAt:
|
||||
type: string
|
||||
format: date-time
|
||||
recordedAt:
|
||||
type: string
|
||||
format: date-time
|
||||
payload:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
evidenceBundleRef:
|
||||
type: string
|
||||
eventHash:
|
||||
type: string
|
||||
previousHash:
|
||||
type: string
|
||||
merkleLeafHash:
|
||||
type: string
|
||||
LedgerEventPage:
|
||||
type: object
|
||||
required: [items]
|
||||
properties:
|
||||
items:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/LedgerEvent'
|
||||
nextCursor:
|
||||
type: string
|
||||
LedgerEventAppendRequest:
|
||||
type: object
|
||||
required: [id, type, tenant, chainId, sequence, policyVersion, occurredAt, payload]
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
format: uuid
|
||||
type:
|
||||
type: string
|
||||
tenant:
|
||||
type: string
|
||||
chainId:
|
||||
type: string
|
||||
format: uuid
|
||||
sequence:
|
||||
type: integer
|
||||
policyVersion:
|
||||
type: string
|
||||
finding:
|
||||
type: object
|
||||
properties:
|
||||
id: { type: string }
|
||||
artifactId: { type: string }
|
||||
vulnId: { type: string }
|
||||
actor:
|
||||
type: object
|
||||
properties:
|
||||
id: { type: string }
|
||||
type: { type: string }
|
||||
occurredAt:
|
||||
type: string
|
||||
format: date-time
|
||||
payload:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
evidenceBundleRef:
|
||||
type: string
|
||||
previousHash:
|
||||
type: string
|
||||
description: Optional; validated if supplied
|
||||
merkleLeafHash:
|
||||
type: string
|
||||
description: Optional; server recomputes to validate determinism
|
||||
FindingProjection:
|
||||
type: object
|
||||
required: [tenantId, findingId, policyVersion, status, cycleHash]
|
||||
properties:
|
||||
tenantId: { type: string }
|
||||
findingId: { type: string }
|
||||
policyVersion: { type: string }
|
||||
status: { type: string }
|
||||
severity:
|
||||
type: number
|
||||
format: double
|
||||
labels:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
currentEventId:
|
||||
type: string
|
||||
format: uuid
|
||||
cycleHash:
|
||||
type: string
|
||||
updatedAt:
|
||||
type: string
|
||||
format: date-time
|
||||
FindingProjectionPage:
|
||||
type: object
|
||||
required: [items]
|
||||
properties:
|
||||
items:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/FindingProjection'
|
||||
nextCursor:
|
||||
type: string
|
||||
@@ -0,0 +1,19 @@
|
||||
# Ledger OAS Prep — PREP-LEDGER-OAS-61-001/61-002/62-001/63-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Findings Ledger Guild · API Contracts Guild · SDK Generator Guild
|
||||
Scope: Capture OAS baseline, HTTP surface, SDK generation, and deprecation flow for ledger service.
|
||||
|
||||
## What’s needed
|
||||
- Baseline OAS for ledger API host (61-001).
|
||||
- Confirm endpoints and auth scopes to publish (61-002 depends on 61-001).
|
||||
- SDK generation targets and language list (62-001).
|
||||
- Deprecation header plan once SDK validated (63-001).
|
||||
|
||||
## Open decisions
|
||||
- Hostname/versioning scheme for ledger API.
|
||||
- Auth scopes per endpoint.
|
||||
- Languages for SDK generation and package naming.
|
||||
|
||||
## Handoff
|
||||
Use this prep doc for LEDGER-OAS-61-001/61-002/62-001/63-001; update once API contract is drafted.
|
||||
@@ -0,0 +1,12 @@
|
||||
# Ledger Observability Prep — PREP-LEDGER-OBS-54-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Findings Ledger Guild · Provenance Guild
|
||||
Scope: Minimal API surface for `/ledger/attestations` and observability hooks.
|
||||
|
||||
## Needs
|
||||
- HTTP surface spec (routes, auth scopes) to host `/ledger/attestations`.
|
||||
- Telemetry fields to include provenance IDs.
|
||||
|
||||
## Handoff
|
||||
Use as PREP artefact; update once API contract is drafted.
|
||||
@@ -0,0 +1,9 @@
|
||||
# Ledger Packs Snapshot Prep — PREP-LEDGER-PACKS-42-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Findings Ledger Guild · Mirror Creator Guild
|
||||
Scope: Snapshot/time-travel contract for packs simulation.
|
||||
|
||||
## Needs
|
||||
- Snapshot format and bundle layout for pack simulation/time-travel.
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# Ledger Risk Schema Prep — PREP-LEDGER-RISK-66-001/002
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Findings Ledger Guild · Risk Engine Guild
|
||||
|
||||
## Needs
|
||||
- Risk engine schema/contract inputs: `risk_score`, `risk_severity`, `profile_version`, `explanation_id`, indexes.
|
||||
- Migration plan to add fields.
|
||||
|
||||
## Handoff
|
||||
Use as PREP artefact; update when risk field definitions and rollout plan are available.
|
||||
@@ -0,0 +1,17 @@
|
||||
# Ledger Risk Prep — PREP-LEDGER-RISK-68-001 / 69-001 / TEN-48-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Findings Ledger Guild · Export Guild · Observability Guild · Platform
|
||||
|
||||
## 68-001 (scored findings export) needs
|
||||
- Inputs from 67-001 + Export Center contract for scored findings.
|
||||
- Metrics dimensions alignment with Observability.
|
||||
|
||||
## 69-001 (metrics) needs
|
||||
- Final metrics fields driven by 67-001/68-001 outputs.
|
||||
|
||||
## TEN-48-001 (RLS/partitioning) needs
|
||||
- Platform-approved tenant/project partitioning and RLS policy.
|
||||
|
||||
## Handoff
|
||||
Use as PREP artefact for the above tasks; update when upstream exports and RLS decisions are available.
|
||||
@@ -0,0 +1,38 @@
|
||||
# Ledger attestation HTTP surface (prep for LEDGER-OBS-54-001 / 55-001)
|
||||
|
||||
**Goal.** Provide the minimal HTTP contract to expose ledger attestation verifications so PREP-LEDGER-OBS-55-001 can proceed. This complements the OAS baseline (`docs/modules/findings-ledger/openapi/findings-ledger.v1.yaml`) and schema (`docs/modules/findings-ledger/schema.md`).
|
||||
|
||||
## Endpoint
|
||||
- `GET /v1/ledger/attestations`
|
||||
- Tenant header: `X-Stella-Tenant` (required).
|
||||
- Auth: bearer `scope=ledger.attest.read` or mTLS.
|
||||
- Query params:
|
||||
- `artifactId` (string, optional; OCI digest or SBOM id)
|
||||
- `findingId` (string, optional)
|
||||
- `attestationId` (uuid, optional)
|
||||
- `status` (`verified|failed|unknown`, optional)
|
||||
- `sinceRecordedAt` / `untilRecordedAt` (ISO-8601 UTC)
|
||||
- `limit` (int, default 200, max 1000)
|
||||
- Ordering: deterministic by `recordedAt ASC, attestationId ASC`.
|
||||
- Response: JSON array (or NDJSON when `Accept: application/x-ndjson`). Each item:
|
||||
- `attestationId` (uuid)
|
||||
- `artifactId` (string)
|
||||
- `findingId` (string)
|
||||
- `verificationStatus` (`verified|failed|unknown`)
|
||||
- `verificationTime` (ISO-8601 UTC)
|
||||
- `dsseDigest` (sha256)
|
||||
- `rekorEntryId` (string, optional)
|
||||
- `evidenceBundleRef` (string, optional)
|
||||
- `ledgerEventId` (uuid) — source ledger event that linked the attestation
|
||||
- `recordedAt` (ISO-8601 UTC)
|
||||
- `merkleLeafHash` (sha256)
|
||||
- `rootHash` (sha256)
|
||||
|
||||
## Determinism/offline posture
|
||||
- Sorting keys are fixed; pagination token encodes `{recordedAt, attestationId, filtersHash}`.
|
||||
- No live Rekor calls; `rekorEntryId` is stored reference only.
|
||||
- Hashes remain lowercase SHA-256; times are UTC.
|
||||
|
||||
## Artefact location
|
||||
- This prep doc: `docs/modules/findings-ledger/prep/ledger-attestations-http.md`.
|
||||
- Add path to OAS in a follow-on increment (LEDGER-OAS-61-002/63-001) once approved.
|
||||
26
docs/modules/mirror/assembler.md
Normal file
26
docs/modules/mirror/assembler.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Mirror Assembler Staffing & Milestones (Sprint 110.D)
|
||||
|
||||
## Staffing
|
||||
- **Primary owner:** Alex Kim (Mirror Creator Guild)
|
||||
- **Backup:** Priya Desai (Exporter Guild)
|
||||
- **Observers:** AirGap Time Guild, CLI Guild
|
||||
|
||||
## Milestones
|
||||
1. **M0 recap (done 2025-11-19):** thin bundle sample + layout note (`docs/modules/mirror/milestone-0-thin-bundle.md`).
|
||||
2. **M1 (due 2025-11-26):** implement deterministic assembler with manifest + CAS layout; DSSE signing profile `sovereign-default`; produce sample bundle tarball + hash.
|
||||
3. **M1.1 (due 2025-11-28):** TUF metadata generation (`root.json`, `snapshot.json`, `timestamp.json`) and mirror index manifest.
|
||||
4. **M2 (due 2025-12-05):** integrate time-anchor metadata (AirGap Time), export automation hooks (Export Center), and CLI verification path.
|
||||
|
||||
## Responsibilities
|
||||
- Alex Kim: assembler core, DSSE signing, CAS layout.
|
||||
- Priya Desai: TUF metadata + exporter handoff.
|
||||
- AirGap Time Guild: time-anchor schema + verification guidance.
|
||||
- CLI Guild: `stella mirror verify` wiring and offline cache checks.
|
||||
|
||||
## Artefact locations
|
||||
- Assembler design: `docs/modules/mirror/thin-bundle-assembler.md`
|
||||
- Staffing/plan (this doc): `docs/modules/mirror/assembler.md`
|
||||
- Sample bundles: `out/mirror/thin/mirror-thin-m0-sample.tar.gz` (future M1/M2 under `out/mirror/thin/`)
|
||||
|
||||
## Risks
|
||||
- If M1 slips past 2025-11-26, Export Center and CLI tracks block; escalate to Exporter guild lead.
|
||||
22
docs/modules/mirror/prep-56-001-thin-bundle.md
Normal file
22
docs/modules/mirror/prep-56-001-thin-bundle.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Mirror Thin Bundle Prep — PREP-MIRROR-CRT-56-001 (Draft)
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Mirror Guild (Assembler)
|
||||
Scope: Capture requirements to start thin bundle v1 when upstream Sprint 110.D artefacts land.
|
||||
|
||||
## Dependencies
|
||||
- Sprint 110.D assembler foundation (missing in repo).
|
||||
- Trust root list and TUF metadata locations from release pipeline.
|
||||
|
||||
## Proposed thin bundle v1 shape
|
||||
- Container: tar.gz deterministic; root manifest `mirror.thin.manifest.json`.
|
||||
- Fields: `bundle_id`, `schema_version`=`mirror.thin.v1`, `created_at`, `source_registry`, `artifacts[] {digest, media_type, size}`, `trust_roots[]`, optional `attestations[]`.
|
||||
- Merkle root over files for audit.
|
||||
|
||||
## Open decisions
|
||||
- Exact artifact set included in “thin” scope (SBOM only vs SBOM+metadata).
|
||||
- Required signatures (DSSE/Sigstore) and signer identities.
|
||||
- Retention/GC policy for thin bundles.
|
||||
|
||||
## Handoff
|
||||
Use this as the PREP artefact for PREP-MIRROR-CRT-56-001; update when assembler foundation drops so schema can be finalized and aligned with `docs/modules/mirror/thin-bundle-assembler.md`.
|
||||
@@ -0,0 +1,12 @@
|
||||
# Orchestrator AirGap Prep — PREP-ORCH-AIRGAP-56-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Orchestrator Service Guild · AirGap Policy Guild
|
||||
Scope: Awaiting AirGap readiness; capture sealed-mode contract needs for orchestrator.
|
||||
|
||||
## Needs
|
||||
- Sealed-mode contract from AirGap controller (seal/unseal scopes, staleness fields).
|
||||
- Mirror bundle pointers to include with orchestrator jobs.
|
||||
|
||||
## Handoff
|
||||
Use as prep artefact; update once AirGap 56-001 contract is published.
|
||||
@@ -0,0 +1,9 @@
|
||||
# Orchestrator AirGap Prep — PREP-ORCH-AIRGAP-56-002
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Scope: Downstream of 56-001; needs sealed-mode staleness propagation.
|
||||
|
||||
## Needs
|
||||
- From 56-001: seal contract and bundle pointers.
|
||||
- Staleness propagation rules to orchestrator runs.
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
# Orchestrator AirGap Prep — PREP-ORCH-AIRGAP-57-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Scope: Dependent on 56-002; timeline events for AirGap imports.
|
||||
|
||||
## Needs
|
||||
- Event types/fields for bundle import timeline.
|
||||
- Alignment with AirGap mirror bundle IDs and staleness.
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# Orchestrator AirGap Prep — PREP-ORCH-AIRGAP-58-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Scope: Dependent on 57-001; Evidence Locker integration for sealed mode.
|
||||
|
||||
## Needs
|
||||
- Evidence Locker bundle pointers and attestation requirements in sealed mode.
|
||||
|
||||
12
docs/modules/orchestrator/prep/2025-11-20-oas-61-001-prep.md
Normal file
12
docs/modules/orchestrator/prep/2025-11-20-oas-61-001-prep.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Orchestrator OAS Prep — PREP-ORCH-OAS-61-001/61-002/62-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Scope: Telemetry contract inputs and OAS baseline for orchestrator APIs.
|
||||
|
||||
## Needs
|
||||
- Telemetry/contract inputs from sprint 150.A (not yet published).
|
||||
- OAS baseline for orchestrator host.
|
||||
- SDK generation targets (depends on OAS v1).
|
||||
|
||||
## Handoff
|
||||
Use as prep artefact for OAS 61/62 chain; update when telemetry inputs published.
|
||||
17
docs/modules/orchestrator/prep/2025-11-20-svc-41-101-prep.md
Normal file
17
docs/modules/orchestrator/prep/2025-11-20-svc-41-101-prep.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Orchestrator Pack-Run Prep — PREP-ORCH-SVC-41-101 / 42-101 / TEN-48-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Orchestrator Service Guild
|
||||
|
||||
## 41-101 needs
|
||||
- Envelope + DAL from 38-101 to register pack runs.
|
||||
- Storage schema for pack-run records.
|
||||
|
||||
## 42-101 needs
|
||||
- Stream contract from 41-101 (pack-run plumbing) to drive streaming.
|
||||
|
||||
## TEN-48-001 needs
|
||||
- Tenant context plumbing for job DAL/routes.
|
||||
|
||||
## Handoff
|
||||
Use as prep artefact; update when 38-101 envelope lands and DAL schema is fixed.
|
||||
@@ -2,5 +2,8 @@
|
||||
|
||||
| Task ID | State | Notes |
|
||||
| --- | --- | --- |
|
||||
| `PREP-EXPORT-CONSOLE-23-001` | DOING (2025-11-20) | Drafted export bundle + scheduler job contract (see `docs/modules/policy/design/export-console-bundle-contract.md`); waiting on DSSE/storage decisions from Console/Scheduler/Authority. |
|
||||
| `PREP-POLICY-AIRGAP-56-001` | DOING (2025-11-20) | Drafted mirror bundle schema for air-gap/ sealed mode (see `docs/modules/policy/design/policy-mirror-bundle-schema.md`); waiting on trust-root and retention policy decisions. |
|
||||
| `PREP-POLICY-ENGINE-30-001` | DOING (2025-11-20) | Drafted overlay projection contract (see `docs/modules/policy/design/policy-overlay-projection.md`); waiting on 29-004 metrics/log schema from Platform/Observability. |
|
||||
| `SCANNER-POLICY-0001` | DONE (2025-11-10) | Ruby component predicates implemented in engine/tests, DSL docs updated, offline kit verifies `seed-data/analyzers/ruby/git-sources`. |
|
||||
| `DOCS-AIAI-31-006` | DONE (2025-11-13) | Published `docs/policy/assistant-parameters.md` capturing Advisory AI configuration knobs (inference/guardrails/cache/queue) and linked it from the module architecture dossier. |
|
||||
|
||||
55
docs/modules/policy/design/export-console-bundle-contract.md
Normal file
55
docs/modules/policy/design/export-console-bundle-contract.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# Export Console Bundle Contract (Draft) — PREP-EXPORT-CONSOLE-23-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Policy Guild · Scheduler Guild · Observability Guild
|
||||
Scope: Define the evidence bundle exported by Policy Engine for Console replay/verification and the scheduler job contract that produces it.
|
||||
|
||||
## 1) Manifest format
|
||||
- Container: tar.gz (deterministic ordering, UTC mtime `1970-01-01T00:00:00Z`), content-addressed by SHA-256 of archive bytes.
|
||||
- Root manifest: `bundle.manifest.json` (unsigned) and `bundle.manifest.dsse` (signed, optional until Rekor/Authority hookup).
|
||||
- `bundle.manifest.json` fields:
|
||||
- `bundle_id` (string, required): GUID/ULID assigned by Policy Engine.
|
||||
- `policy_run_id` (string, required): ID of originating policy run.
|
||||
- `tenant_id` (string, required): tenant scope.
|
||||
- `policy_version` (string, required): semantic version or commit hash of the policy set evaluated.
|
||||
- `inputs_hash` (hex): SHA-256 of normalized inputs (SBOM, advisories, VEX) used for the run.
|
||||
- `generated_at` (string, RFC3339 UTC): timestamp of bundle creation.
|
||||
- `schema_version` (string): `policy.export.console.v1`.
|
||||
- `artifacts`: array of artefact descriptors with `{path, media_type, sha256, purpose}`; expected purposes: `policy-run-summary`, `effective-findings`, `inputs`, `logs`, `metrics`.
|
||||
- `signatures`: optional array referencing DSSE statement(s) with signer identity and key hint.
|
||||
|
||||
## 2) Artefact layout
|
||||
- `summary/policy-run.json`: minimal run summary (status, duration, rule counts, decision stats).
|
||||
- `findings/effective.ndjson`: deterministic NDJSON list of effective findings emitted by the run (sorted by `finding_id`).
|
||||
- `inputs/sbom/*.json`: normalized SBOM slices (content-addressed references pointing back to source digests).
|
||||
- `inputs/advisories/*.json`: advisories snapshot used during evaluation.
|
||||
- `inputs/vex/*.json`: VEX statements snapshot.
|
||||
- `telemetry/logs.ndjson`: structured logs with correlation IDs and runner metadata (no secrets, scrub file paths).
|
||||
- `telemetry/metrics.json`: counters/histograms for run (p50/p95 latency, evaluated rules, facts ingested).
|
||||
|
||||
## 3) Scheduler job contract
|
||||
- Job type: `policy.export.console`.
|
||||
- Inputs:
|
||||
- `policy_run_id` (required)
|
||||
- `tenant_id` (required)
|
||||
- `priority` (enum: background|interactive; default background)
|
||||
- `include_logs` (bool, default true)
|
||||
- Outputs:
|
||||
- `bundle_pointer` (URI/path) to stored bundle in Evidence Locker/Export Center bucket.
|
||||
- `bundle_id`, `sha256`.
|
||||
- Events:
|
||||
- Progress events to Observability stream `{job_id, state, percent, bundle_id?, error?}`.
|
||||
- Completion emits `policy.export.console.completed` with bundle metadata for Console ingestion.
|
||||
|
||||
## 4) Determinism & security
|
||||
- All NDJSON/JSON sorted by stable keys; floats avoided; timestamps UTC RFC3339.
|
||||
- No inline PII; tenant-scoped file paths must be redacted or normalized.
|
||||
- Offline-friendly: no external references; all URIs either `bundle://` or content hashes.
|
||||
|
||||
## 5) Open items / decisions needed
|
||||
- Signer identity and DSSE profile (Rekor optional) — awaiting Authority/Attestor alignment.
|
||||
- Exact location for bundle storage (Evidence Locker vs Export Center) — propose Evidence Locker namespace `policy-console/` with retention 30d.
|
||||
- Metrics schema: align with Observability guild’s latest counters/histogram names.
|
||||
|
||||
## 6) Handoff
|
||||
Cite this file in sprint trackers for PREP-EXPORT-CONSOLE-23-001. When upstream decisions land, update schema_version and finalize DSSE profile.
|
||||
27
docs/modules/policy/design/policy-deterministic-evaluator.md
Normal file
27
docs/modules/policy/design/policy-deterministic-evaluator.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Deterministic Evaluator Spec (Draft) — PREP-POLICY-ENGINE-20-002
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Policy Guild
|
||||
Scope: Define deterministic evaluator requirements for Policy Engine to unblock POLICY-ENGINE-20-002.
|
||||
|
||||
## Determinism rules
|
||||
- Evaluation order: lexical by rule ID within policy set; stable tie-breaker by condition hash.
|
||||
- Data types: disallow host clock/network; only allow provided inputs; random seeded with fixed seed per run.
|
||||
- Outputs: sorted by finding_id; numeric outputs with fixed precision (3 decimals) and invariant culture.
|
||||
- Time handling: all timestamps in inputs are treated as UTC; now() not permitted.
|
||||
|
||||
## Engine contract
|
||||
- Input envelope: `{policy_set_id, policy_version, inputs_hash, tenant_id, run_id}`.
|
||||
- Execution context: immutable; no mutations to global state; cache keyed by inputs_hash + policy_version.
|
||||
- Result envelope: `{run_id, policy_set_id, policy_version, findings[], metrics{duration_ms, rules_evaluated}}`.
|
||||
|
||||
## Testing strategy
|
||||
- Golden runs: same inputs produce identical outputs/hashes across runs and machines.
|
||||
- Property tests: altering rule order must not change result ordering; injecting clock skew should be rejected.
|
||||
|
||||
## Open decisions
|
||||
- Whether to allow parallel rule evaluation if output ordering remains deterministic (requires stable merge logic).
|
||||
- Exact numeric tolerance/rounding strategy.
|
||||
|
||||
## Handoff
|
||||
Use this as the PREP artefact for PREP-POLICY-ENGINE-20-002. Update once numeric rounding and parallelism decisions are finalized.
|
||||
46
docs/modules/policy/design/policy-mirror-bundle-schema.md
Normal file
46
docs/modules/policy/design/policy-mirror-bundle-schema.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Policy Mirror Bundle Schema (Draft) — PREP-POLICY-AIRGAP-56-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Policy Guild · Cartographer Guild
|
||||
Scope: Define sealed/offline-ready mirror bundle schema for policy packs to unblock air-gap ingestion (Mirror Bundles v1).
|
||||
|
||||
## 1) Bundle container
|
||||
- Format: tar.gz with deterministic ordering, UTC mtime `1970-01-01T00:00:00Z`.
|
||||
- Root: `mirror.manifest.json` plus optional `mirror.manifest.dsse` (post-quantum ready profile TBD).
|
||||
|
||||
## 2) Manifest fields
|
||||
- `bundle_id` (string, required): ULID.
|
||||
- `schema_version` (string): `policy.mirror.v1`.
|
||||
- `created_at` (RFC3339 UTC).
|
||||
- `producer` (object): `{name, version, build}` of the mirror tool.
|
||||
- `provenance` (object): `{source_registry, source_digest, fetch_time, trust_roots[]}`.
|
||||
- `policies` (array) of policy pack descriptors:
|
||||
- `pack_id` (string): content-addressed ID of the pack archive.
|
||||
- `version` (string): semver or commit hash.
|
||||
- `sha256` (string): hash of pack bytes.
|
||||
- `signatures[]` (optional): detached signatures (Sigstore/DSSE) with key hints.
|
||||
- `metadata` (object): `{rules_count, dependencies, min_engine_version}`.
|
||||
- `attestations` (optional array): references to DSSE statements covering manifest or pack artefacts.
|
||||
- `integrity` (object): `{merkle_root, entries[]}` mirroring file tree for audit.
|
||||
|
||||
## 3) File layout
|
||||
- `packs/{pack_id}.tar.gz`: raw policy pack.
|
||||
- `signatures/{pack_id}.sig`: detached signature per pack (optional).
|
||||
- `notes/compliance.md`: optional compliance notes per pack.
|
||||
|
||||
## 4) Sealed-mode rules
|
||||
- Whole-bundle DSSE signature required when `sealed=true` (header flag in manifest).
|
||||
- No post-fetch mutation; ingest must verify merkle root and DSSE before unpack.
|
||||
- Trust roots pinned per bundle (`provenance.trust_roots[]`), defaulting to org-configured roots when absent.
|
||||
|
||||
## 5) Determinism & validation
|
||||
- All arrays sorted; use lowercase hex for hashes.
|
||||
- Validation checklist: bundle hash matches manifest; merkle root recomputes; DSSE signer authorized; engine version compatibility enforced before import.
|
||||
|
||||
## 6) Open decisions
|
||||
- Final DSSE profile (FIPS/eIDAS/GOST) depending on deployment region.
|
||||
- Retention/GC policy for stale mirror bundles in sealed mode.
|
||||
- Whether to embed policy docs or keep external references; draft assumes external docs are excluded for air-gap safety.
|
||||
|
||||
## 7) Handoff
|
||||
Treat this file as the publishable artefact for PREP-POLICY-AIRGAP-56-001. Update when Authority/Platform finalize DSSE and trust-root policies.
|
||||
55
docs/modules/policy/design/policy-overlay-projection.md
Normal file
55
docs/modules/policy/design/policy-overlay-projection.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# Policy Overlay Projection Contract (Draft) — PREP-POLICY-ENGINE-30-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Policy Guild · Cartographer Guild · Platform/Observability Guild
|
||||
Scope: Define the overlay projection output that depends on metrics/logging outputs from POLICY-ENGINE-29-004. Intended to unblock POLICY-ENGINE-30-001 and downstream 30-00x tasks.
|
||||
|
||||
## 1) Inputs
|
||||
- `policy_run_id` (required)
|
||||
- `tenant_id` (required)
|
||||
- Metrics/logging envelope from 29-004 (pending): expected fields include run duration, rule evaluation counts, fact ingest counts, cache hit/miss, scheduler job metadata.
|
||||
- Optional: advisory/KB versions, SBOM/VEX digests, risk profile version.
|
||||
|
||||
## 2) Overlay projection shape (proposed)
|
||||
```json
|
||||
{
|
||||
"overlay_id": "ulid",
|
||||
"policy_run_id": "...",
|
||||
"tenant_id": "...",
|
||||
"generated_at": "2025-11-20T00:00:00Z",
|
||||
"schema_version": "policy.overlay.v1",
|
||||
"metrics": {
|
||||
"duration_ms": 1234,
|
||||
"rules_evaluated": 4200,
|
||||
"facts_ingested": 98765,
|
||||
"cache_hit_rate": 0.92,
|
||||
"p95_rule_latency_ms": 8
|
||||
},
|
||||
"logs_pointer": "bundle://telemetry/logs.ndjson",
|
||||
"inputs": {
|
||||
"sbom_digest": "sha256:...",
|
||||
"advisories_digest": "sha256:...",
|
||||
"vex_digest": "sha256:..."
|
||||
},
|
||||
"provenance": {
|
||||
"engine_version": "x.y.z",
|
||||
"profile": "policy-default",
|
||||
"scheduler_job_id": "..."
|
||||
}
|
||||
}
|
||||
```
|
||||
- Determinism: sorted keys; timestamps UTC; numeric metrics fixed to 3 decimal places where fractional.
|
||||
- Overlay acts as the query surface for simulation/change events (30-002/30-003) and UI overlays.
|
||||
|
||||
## 3) Storage & API
|
||||
- Stored as NDJSON under `overlays/{tenant_id}/{policy_run_id}.ndjson` in policy engine store; referenced by Export/Console bundle.
|
||||
- API (proposed): `GET /policy-runs/{policy_run_id}/overlay` with ETag = sha256 of payload; `POST /policy-runs/{policy_run_id}/overlay/rebuild` for re-projection when metrics contract changes.
|
||||
|
||||
## 4) Open dependencies / decisions
|
||||
- Need final metrics/logging schema from 29-004 to lock `metrics` section (owner: Platform/Observability).
|
||||
- Confirm cache metrics naming and units.
|
||||
- Confirm whether overlay should embed inline logs vs pointer.
|
||||
- Clarify retention/GC policy for overlays (suggest 30d, aligned with export bundles).
|
||||
|
||||
## 5) Handoff
|
||||
Use this document as the PREP artefact for POLICY-ENGINE-30-001. Update once 29-004 publishes metrics/logging outputs; then fix schema_version to `overlay.v1` and add JSON Schema under `docs/modules/policy/schemas/`.
|
||||
@@ -0,0 +1,16 @@
|
||||
# Risk Profile Library Prep — PREP-POLICY-RISK-66-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Risk Profile Schema Guild
|
||||
Scope: Scaffold requirements for `StellaOps.Policy.RiskProfile` project and storage contract.
|
||||
|
||||
## Needs
|
||||
- Project skeleton (net10.0) under `src/Policy/StellaOps.Policy.RiskProfile` with schema/validators.
|
||||
- Storage contract: collections/fields for risk profiles; deterministic hashing rules.
|
||||
|
||||
## Open decisions
|
||||
- Exact schema fields and validation rules.
|
||||
- Versioning strategy (semver vs commit hash) for profiles.
|
||||
|
||||
## Handoff
|
||||
Use as PREP artefact; update once schema fields and storage strategy are agreed.
|
||||
27
docs/modules/sbomservice/offline-feed-plan.md
Normal file
27
docs/modules/sbomservice/offline-feed-plan.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# SBOM Service Offline Feed Plan (prep for PREP-SBOM-CONSOLE-23-001)
|
||||
|
||||
## Problem
|
||||
SbomService builds/tests were failing restore due to missing NuGet packages (notably `Microsoft.IdentityModel.Tokens >= 8.14.0` and `Pkcs11Interop >= 4.1.0`). Offline/air-gap posture requires a cached feed.
|
||||
|
||||
## What landed (2025-11-20)
|
||||
- Offline cache populated under `local-nugets/packages/` via `tools/offline/fetch-sbomservice-deps.sh`.
|
||||
- Key package hashes:
|
||||
- `Microsoft.IdentityModel.Tokens.8.14.0.nupkg` · SHA256 `00b78c7b7023132e1d6b31d305e47524732dce6faca92dd16eb8d05a835bba7a`
|
||||
- `Pkcs11Interop.4.1.0.nupkg` · SHA256 `8d2b323a3abb9de47a06a3c3b662aa526ee5c1637b70db072c66dc28e6f14c1e`
|
||||
- Script: `tools/offline/fetch-sbomservice-deps.sh` (idempotent) hydrates required packages into `local-nugets/packages` using a minimal probe project with `--ignore-failed-sources` to stay air-gap friendly.
|
||||
|
||||
## How to use
|
||||
```bash
|
||||
# refresh cache if versions change
|
||||
./tools/offline/fetch-sbomservice-deps.sh
|
||||
|
||||
# run SbomService tests offline
|
||||
DOTNET_NOLOGO=1 dotnet test src/SbomService/StellaOps.SbomService.Tests/StellaOps.SbomService.Tests.csproj --no-build --ignore-failed-sources
|
||||
```
|
||||
|
||||
## Next actions
|
||||
- If additional packages surface during `dotnet restore`, append them to the probe project in the script and re-run.
|
||||
- Keep `local-nugets/` under version control for deterministic builds; update hashes when packages change.
|
||||
|
||||
## Owners
|
||||
- SBOM Service Guild · Build/Infra (sprint 0142_0001_0001).
|
||||
15
docs/modules/sbomservice/prep/2025-11-20-build-infra-prep.md
Normal file
15
docs/modules/sbomservice/prep/2025-11-20-build-infra-prep.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Build/Infra Prep — PREP-BUILD-INFRA-SBOM-SERVICE-GUILD-BLOCKED-M
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: SBOM Service Guild
|
||||
Scope: Document restore/build blocking issues awaiting vetted feed/cache.
|
||||
|
||||
## Blocker summary
|
||||
- Multiple restore attempts hang/fail; need vetted NuGet feed/cache for SBOM Service solution.
|
||||
|
||||
## Needed actions
|
||||
- Provide approved offline feed snapshot for SBOM Service dependencies.
|
||||
- CI runner with feed configured to validate restore.
|
||||
|
||||
## Handoff
|
||||
Use as PREP artefact; update once feed snapshot is supplied and restore passes.
|
||||
@@ -0,0 +1,20 @@
|
||||
# SBOM Service Prep — PREP-SBOM-SERVICE-21-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: SBOM Service Guild · Cartographer Guild
|
||||
Scope: Waiting on LNM v1 fixtures to freeze normalized SBOM projection read API.
|
||||
|
||||
## Needed inputs
|
||||
- LNM v1 fixtures (due 2025-11-18 UTC) for schema alignment.
|
||||
|
||||
## Proposed API surface (draft)
|
||||
- `GET /sboms/{id}/projection` with query `page`, `page_size`, `tenant_id`.
|
||||
- Response includes `components[]`, `licenses[]`, `hashes[]`, `provenance`.
|
||||
- Deterministic ordering, tenant enforcement.
|
||||
|
||||
## Open decisions
|
||||
- Pagination defaults and max page size.
|
||||
- Which hash algorithms to expose.
|
||||
|
||||
## Handoff
|
||||
Use as PREP artefact; finalize once fixtures arrive.
|
||||
118
docs/modules/scanner/design/analyzer-prep-0132.md
Normal file
118
docs/modules/scanner/design/analyzer-prep-0132.md
Normal file
@@ -0,0 +1,118 @@
|
||||
# Scanner Analyzer Prep · Sprint 0132
|
||||
|
||||
This note captures the unblockers promised in PREP tasks for Sprint 0132. Each subsection gives the artifact location, assumption set, and the handoff needed by downstream implementation tasks.
|
||||
|
||||
## SCANNER-ANALYZERS-LANG-11-003 (runtime fusion)
|
||||
- **Objective:** Define the runtime evidence ingest contract to merge AssemblyLoad/Resolving/PInvoke signals with static edges from 11-002.
|
||||
- **Inputs required:**
|
||||
- Static edge export format from 11-002 (AssemblyRef/ModuleRef/PInvoke with reason codes).
|
||||
- Event listener tap points: `AssemblyLoadContext.Resolving`, `AssemblyLoad`, `NativeLibrary.SetDllImportResolver`, `DynamicDependency` attributes, and optional ETW provider `Microsoft-Windows-DotNETRuntime` (keyword 0x8, task AssemblyLoad).
|
||||
- **Runtime evidence envelope (AOC-aligned):**
|
||||
```json
|
||||
{
|
||||
"runtime_observation_id": "uuid",
|
||||
"assembly_name": "System.Text.Json",
|
||||
"kind": "assembly-load|p-invoke|dynamic-dependency",
|
||||
"source": "Resolving|AssemblyLoad|NativeLibrary|ETW",
|
||||
"details": {
|
||||
"requested_name": "System.Text.Json",
|
||||
"resolved_path": "<normalized absolute path>",
|
||||
"assembly_version": "8.0.0.0",
|
||||
"culture": "neutral",
|
||||
"package_purl": "pkg:nuget/system.text.json@8.0.0",
|
||||
"confidence": 0.72,
|
||||
"reason_code": "runtime-resolve"
|
||||
},
|
||||
"timestamp_utc": "2025-11-20T00:00:00Z"
|
||||
}
|
||||
```
|
||||
- **Merge rules for downstream 11-003 implementation:**
|
||||
- De-dup edges by (assembly_name, resolved_path, kind).
|
||||
- Prefer static edge confidence when present; runtime adds `confidence_bonus = +0.1` but never exceeds 1.0.
|
||||
- Keep provenance: `edge.provenance = { "static": bool, "runtime": bool }`.
|
||||
- **Publication:** This doc section is the frozen location for the runtime ingest contract; downstream tasks should reference this path.
|
||||
|
||||
## SCANNER-ANALYZERS-LANG-11-004 (observation export → writer/SBOM)
|
||||
- **Objective:** Define the observation payload emitted to Scanner writer and SBOM entrypoint tagging.
|
||||
- **Export envelope (AOC-compliant):**
|
||||
```json
|
||||
{
|
||||
"entrypoints": [
|
||||
{
|
||||
"label": "app",
|
||||
"rids": ["win-x64","linux-x64"],
|
||||
"tfms": ["net8.0","net8.0-windows"],
|
||||
"command": "dotnet ./bin/app.dll",
|
||||
"sources": ["src/App/Program.cs"],
|
||||
"rank": 1
|
||||
}
|
||||
],
|
||||
"dependency_edges": [
|
||||
{
|
||||
"from": "app",
|
||||
"to": "pkg:nuget/system.text.json@8.0.0",
|
||||
"reason_code": "assembly-ref",
|
||||
"confidence": 0.86,
|
||||
"provenance": {"static": true, "runtime": false}
|
||||
}
|
||||
],
|
||||
"environment_profiles": {
|
||||
"tfm": "net8.0",
|
||||
"rid": "linux-x64",
|
||||
"host_policy": "portable",
|
||||
"features": ["singlefile:false","trimmed:false","nativeaot:false"]
|
||||
}
|
||||
}
|
||||
```
|
||||
- **Writer handoff:**
|
||||
- Serialize as deterministic JSON (sorted keys) to the Scanner writer contract `writer/observations/lang/dotnet`.
|
||||
- Attach `sbom_entrypoint_tags` derived from entrypoint labels to feed SBOM Service tagging.
|
||||
- **Publication:** Payload shape and field meanings fixed here for Sprint 0132 downstream work.
|
||||
|
||||
## SCANNER-ANALYZERS-LANG-11-005 (fixtures & benchmarks)
|
||||
- **Objective:** Provide fixture plan so QA can start without waiting on further design.
|
||||
- **Fixture matrix:**
|
||||
- Framework-dependent: `net8.0`, `net9.0-preview` sample apps (console + web minimal API).
|
||||
- Self-contained: `linux-x64` trimmed vs non-trimmed.
|
||||
- Single-file: `win-x64` single-file publish, include native hosting bundle.
|
||||
- NativeAOT: `linux-x64` HelloWorld + P/Invoke stub.
|
||||
- Multi-RID: RID graph `linux-x64`, `linux-arm64`, `win-x64` with RID fallback expectations.
|
||||
- **Locations:** place fixtures under `src/Scanner/__Tests/Fixtures/DotNet/11-005/*`; store expected observation JSON in `__Tests/Fixtures/DotNet/11-005/expected/*.json` with sorted keys.
|
||||
- **Bench envelopes:**
|
||||
- Target <150 ms p95 per project scan on dev laptop, <25 MB heap delta; capture via BenchmarkDotNet and report to `__Benchmarks/11-005.md`.
|
||||
- **Determinism:** lock timestamps to `1970-01-01T00:00:00Z` in serialized outputs; stable ordering by (entrypoint label, dependency to PURL, reason_code).
|
||||
|
||||
## SCANNER-ANALYZERS-NATIVE-20-002 (ELF declared-dependency writer contract)
|
||||
- **Objective:** Unblock writer schema so native analyzer can emit DT_NEEDED/DT_RPATH/DT_RUNPATH data.
|
||||
- **Edge record (per ELF binary):**
|
||||
```json
|
||||
{
|
||||
"image": "libssl.so.3",
|
||||
"build_id": "cafef00d",
|
||||
"rpath": ["$ORIGIN/lib","/usr/lib"],
|
||||
"runpath": ["$ORIGIN","/opt/openssl"],
|
||||
"needed": [
|
||||
{"name": "libcrypto.so.3", "slot": 0, "version": "OPENSSL_3.0", "reason_code": "elf-dtneeded"},
|
||||
{"name": "libpthread.so.0", "slot": 1, "version": null, "reason_code": "elf-dtneeded"}
|
||||
],
|
||||
"interpreter": "/lib64/ld-linux-x86-64.so.2",
|
||||
"origin": "virtual-fs",
|
||||
"confidence": 0.82
|
||||
}
|
||||
```
|
||||
- **Writer path:** `writer/observations/native/elf-declared-deps` (append-only NDJSON; sorted by image name then slot).
|
||||
- **Redaction:** no host absolute paths; resolve `$ORIGIN` using virtual image root only.
|
||||
- **Publication:** schema above is the agreed baseline for downstream tasks; time-boxed to Sprint 0132.
|
||||
|
||||
## SCANNER-ANALYZERS-NODE-22-001 (isolated runner / scoped build graph)
|
||||
- **Objective:** Provide a deterministic way to run Node analyzer tests without fanning out the whole solution.
|
||||
- **Approach:**
|
||||
- Add target solution filter: `src/Scanner/StellaOps.Scanner.Analyzers.Lang.Node.slnf` including only Node projects + shared test utilities.
|
||||
- Introduce `Directory.Build.props` override for `Lang.Node` tests to disable cross-solution restore (`DisableTransitiveProjectReferences=true`).
|
||||
- Test command for CI + local: `dotnet test src/Scanner/StellaOps.Scanner.Analyzers.Lang.Node.Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests.csproj /p:DisableTransitiveProjectReferences=true --no-restore --logger:"console;verbosity=minimal"`.
|
||||
- Cache seeds: copy pnpm/Yarn fixtures into `obj/fixtures-cache` during test init; deterministic zip timestamps set to `1980-01-01`.
|
||||
- **Publication:** This runbook unblocks execution while broader solution build contention is resolved; downstream tasks should adopt this invocation until Sprint 131 completes.
|
||||
|
||||
---
|
||||
**Owners:** Scanner EPDR Guild (DotNet), SBOM Service Guild, Native Analyzer Guild, Node Analyzer Guild.
|
||||
**Status:** All PREP artifacts published 2025-11-20.
|
||||
33
docs/modules/scanner/prep/2025-11-20-analyzers-prep.md
Normal file
33
docs/modules/scanner/prep/2025-11-20-analyzers-prep.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Scanner Analyzers PREP Notes — 2025-11-20
|
||||
|
||||
Owner: Scanner EPDR Guild · Signals Guild · SBOM Service Guild · Native Analyzer Guild
|
||||
Scope: Prep deliverables for PREP-SCANNER-ANALYZERS-LANG-11-003-DEPENDS-ON, PREP-SCANNER-ANALYZERS-LANG-11-004-DEPENDS-ON, and PREP-SCANNER-ANALYZERS-NATIVE-20-002-AWAIT-DE.
|
||||
|
||||
## 1) LANG-11-003 runtime evidence ingest (dependent on 11-002)
|
||||
- Required upstream: static analyzer outputs from 11-002 (AssemblyRef/ModuleRef/PInvoke/reflection edges with reason codes/confidence).
|
||||
- Runtime harness spec (draft):
|
||||
- Listener surfaces `AssemblyLoad`, `Resolving`, `FirstChanceException` events; optional OS-specific providers gated by feature flag `scanner:analyzers:dotnet:runtime-capture` (default off).
|
||||
- Output shape fed into merger: `runtime_edges[]` with fields `{from_entrypoint, to_identity, reason_code, confidence, evidence}`; `evidence` captures event type, payload fragment, timestamp (UTC ISO-8601), and source provider.
|
||||
- Merge rules: prefer static edges; runtime edges only add new edges or upgrade confidence; no removals.
|
||||
- Test plan stub: targeted harness tests under `StellaOps.Scanner.Analyzers.Lang.DotNet.Tests` using recorded ETW/EventListener traces; determinism enforced via sorted edges and normalized timestamps.
|
||||
|
||||
## 2) LANG-11-004 normalized observation export (dependent on 11-003)
|
||||
- Export contract (AOC compliant) to Scanner writer:
|
||||
- `entrypoints[]` with `{id, assembly_name, mvid, tfm, rid, kind}`.
|
||||
- `dependency_edges[]` with `{from_entrypoint, to_component, reason_code, confidence, source={static|runtime|declared}, evidence_ref}`.
|
||||
- `environment_profiles[]` capturing loader configuration (search paths, probing settings) without host-specific absolute paths; deterministic ordering.
|
||||
- Integration expectations:
|
||||
- Writer API endpoint path: `scanner/writer/analyzers/dotnet/runtime-static-fusion` (to be aligned with writer team).
|
||||
- SBOM tagging: entrypoints annotated with export IDs; avoid adding derived severity.
|
||||
- Testing hook: golden JSON exports under `src/Scanner/__Tests/Fixtures/lang11/export/*.json`, referenced by `ObservationExportTests` once 11-003 is ready.
|
||||
|
||||
## 3) NATIVE-20-002 declared-dependency writer (await declared-dependency contract)
|
||||
- Scope: emit declared dependencies from ELF dynamic sections with `reason_code=elf-dtneeded`, include `rpath/runpath` and symbol version needs when present.
|
||||
- Contract expectations:
|
||||
- Writer record fields: `{binary_id, needed_soname, search_path_hint[], runpath[], build_id, interpreter, version_need[]}`; all ordered deterministically.
|
||||
- Input parser must normalize duplicate `DT_NEEDED` entries and preserve order of appearance.
|
||||
- Dependencies: needs finalized declared-dependency writer interface from Scanner writer team; block remains until contract lands, but this prep defines expected payload shape and ordering.
|
||||
- Test stub guidance: place fixtures under `src/Scanner/__Tests/Fixtures/native/elf-dtneeded/*` with baseline YAML/JSON; benchmark target <25ms per binary on baseline fixtures.
|
||||
|
||||
## Handoff
|
||||
- This document is the published prep artefact requested by the above PREP tasks. Implementation tasks should cite this file until upstream contracts arrive.
|
||||
26
docs/modules/scanner/prep/2025-11-20-java-21-005-prep.md
Normal file
26
docs/modules/scanner/prep/2025-11-20-java-21-005-prep.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Java Analyzer Prep — SCANNER-ANALYZERS-JAVA-21-005 (PREP)
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Java Analyzer Guild
|
||||
Scope: Capture prerequisites and fixture expectations to unblock SCANNER-ANALYZERS-JAVA-21-005 once upstream build issues clear.
|
||||
|
||||
## Blocking issues observed
|
||||
- Repository build fails in Concelier due to missing `CoreLinksets` Mongo interfaces; prevents running targeted Java analyzer tests.
|
||||
- Targeted `dotnet test` stalls during restore/build on shared runner; needs clean CI slot or scoped solution.
|
||||
|
||||
## Required upstream artifacts
|
||||
- Concelier/CoreLinksets packages or mocks to let Java analyzer tests restore/build.
|
||||
- CI job or local script to run Java analyzer tests in isolation (`StellaOps.Scanner.Analyzers.Lang.Java.Tests.csproj`) without full solution restore.
|
||||
|
||||
## Expected outputs once unblocked
|
||||
- Framework config extraction evidence covering Spring Boot imports, app/bootstrap configs, web.xml/fragments, JPA/CDI/JAXB configs, logging files, Graal native-image configs.
|
||||
- JNI/native hint detection: System.load/Library literals, bundled native libs, Graal JNI configs with component metadata.
|
||||
- Deterministic hashing of config evidence (SHA-256) with stable ordering.
|
||||
|
||||
## Test/fixture plan
|
||||
- Fixtures under `src/Scanner/__Tests/Fixtures/java/21-005/*` capturing the above configs.
|
||||
- Regression tests in `StellaOps.Scanner.Analyzers.Lang.Java.Tests/FrameworkConfigTests.cs` asserting evidence presence and hashes.
|
||||
- Add CI note: prefer `dotnet test ...Java.Tests.csproj --filter Category=FrameworkConfig` once solutions restore cleanly.
|
||||
|
||||
## Handoff
|
||||
Use this document as the published prep artefact for PREP-SCANNER-ANALYZERS-JAVA-21-005-TESTS-BLOC. Update once Concelier/CoreLinksets dependency is resolved or CI isolation is available.
|
||||
26
docs/modules/scanner/prep/2025-11-20-java-21-008-prep.md
Normal file
26
docs/modules/scanner/prep/2025-11-20-java-21-008-prep.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Java Analyzer Prep — SCANNER-ANALYZERS-JAVA-21-008
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Java Analyzer Guild
|
||||
Scope: Resolver + AOC writer emitting entrypoints/components/edges with reason codes/confidence; depends on 21-007 outputs.
|
||||
|
||||
## Dependencies
|
||||
- 21-007 manifest metadata collector outputs (signers, manifest attributes) required to seed resolver inputs.
|
||||
- CoreLinksets/Concelier build health to allow Java analyzer test runs.
|
||||
|
||||
## Proposed resolver outputs
|
||||
- `entrypoints[]`: `{id, path, manifest_main_class?, agent_class?, start_class?, module}`.
|
||||
- `components[]`: modules/JARs with `{purl?, sha256, module_name?, signed?, signer_ids[]}`.
|
||||
- `edges[]`: `{from_entrypoint, to_component, reason_code (jpms|cp|spi|reflect|jni|runtime), confidence, evidence}`.
|
||||
- Deterministic ordering: sort edges by (from_entrypoint, to_component, reason_code).
|
||||
|
||||
## Tests/fixtures
|
||||
- Place fixtures under `src/Scanner/__Tests/Fixtures/java/21-008/*` covering jpms, classpath, SPI, reflection, JNI cases.
|
||||
- Regression tests: `ResolverOutputs_AreDeterministic` and `EdgesIncludeReasonAndConfidence`.
|
||||
|
||||
## Open decisions
|
||||
- Exact confidence scale (0–1 vs categorical) to align with downstream Surface.
|
||||
- Whether to emit runtime edges in this task vs deferring to 21-010.
|
||||
|
||||
## Handoff
|
||||
Use this doc as the PREP artefact for 21-008; update once 21-007 outputs and confidence scale are finalized.
|
||||
28
docs/modules/scanner/prep/2025-11-20-lang-11-001-prep.md
Normal file
28
docs/modules/scanner/prep/2025-11-20-lang-11-001-prep.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# .NET Lang Analyzer Prep — SCANNER-ANALYZERS-LANG-11-001
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Scanner EPDR Guild · Language Analyzer Guild
|
||||
Scope: Entrypoint resolver mapping project/publish artifacts to deterministic entrypoint identities; PREP covers test isolation and hang debugging.
|
||||
|
||||
## Blocking issues
|
||||
- `dotnet test` hangs/returns empty output on shared runner; high restore/build fan-out.
|
||||
- Concelier/CoreLinksets build errors encountered during prior attempts.
|
||||
|
||||
## Proposed mitigation
|
||||
- Add CI job to run `dotnet test src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests.csproj --filter Category=Entrypoints --blame-hang-timeout 45s` on clean agent.
|
||||
- Provide scoped solution `StellaOps.Scanner.Analyzers.Lang.DotNet.slnf` to limit restore.
|
||||
|
||||
## Expected outputs
|
||||
- Entrypoints array: `{id, assembly_name, mvid, tfm, rid, kind}` with deterministic ID hashing (`sha256` over path+tfm+rid).
|
||||
- Environment profiles: loader/probing settings minus host absolute paths.
|
||||
|
||||
## Test/fixtures
|
||||
- Fixtures under `src/Scanner/__Tests/Fixtures/dotnet/entrypoints/*` for framework-dependent, self-contained, NativeAOT, multi-RID, single-file, trimmed builds.
|
||||
- Golden outputs sorted by entrypoint id; verify hash stability across OS.
|
||||
|
||||
## Open decisions
|
||||
- Hash input shape for `id` (include project GUID?): to confirm with Signals guild.
|
||||
- Whether to allow RID inference from runtimeconfig vs RID graph; requires Signals sign-off.
|
||||
|
||||
## Handoff
|
||||
Treat this as the PREP artefact for PREP-SCANNER-ANALYZERS-LANG-11-001; update once CI isolation and hash rules are confirmed.
|
||||
27
docs/modules/scheduler/prep/2025-11-20-surface-fs-pointer.md
Normal file
27
docs/modules/scheduler/prep/2025-11-20-surface-fs-pointer.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Surface FS Pointer Contract (Draft) — PREP-SCHED-SURFACE-01
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Scheduler Worker Guild
|
||||
Scope: Define pointer model for Surface FS to unblock scheduler worker planning.
|
||||
|
||||
## Pointer model
|
||||
- Identifier: `surfacefs://<tenant>/<dataset>/<version>`.
|
||||
- Fields:
|
||||
- `tenant_id`
|
||||
- `dataset` (e.g., `sbom`, `findings`, `reachability`)
|
||||
- `version` (content hash or monotonic version)
|
||||
- `storage_uri` (unset/relative in sealed mode; content-addressed path recommended)
|
||||
- `created_at` (RFC3339 UTC)
|
||||
- Deterministic JSON serialization with sorted keys.
|
||||
|
||||
## Scheduler usage
|
||||
- Workers receive pointer in job payload; pointer is immutable per job.
|
||||
- Cache key = `surface_fs_pointer`.
|
||||
- Validation: ensure `dataset` is allowlisted; reject untrusted storage_uri when sealed mode is on.
|
||||
|
||||
## Open decisions
|
||||
- Final allowlist of datasets.
|
||||
- Whether inline `storage_uri` is permitted under sealed mode or requires local mirror resolution.
|
||||
|
||||
## Handoff
|
||||
Use this doc as the PREP artefact for PREP-SCHED-SURFACE-01; update once datasets and sealed-mode rule are agreed.
|
||||
21
docs/modules/scheduler/prep/2025-11-20-worker-23-101-prep.md
Normal file
21
docs/modules/scheduler/prep/2025-11-20-worker-23-101-prep.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Scheduler Worker PREP — SCHED-WORKER-23-101
|
||||
|
||||
Status: Draft (2025-11-20)
|
||||
Owners: Scheduler Worker Guild · Policy Guild
|
||||
Scope: Capture activation event contract and throttle source needed for worker 23-101.
|
||||
|
||||
## Required inputs
|
||||
- Activation event schema from Policy guild: expected fields `{job_id, policy_run_id, tenant_id, priority, throttle_source}`.
|
||||
- Throttle source definition (static config vs dynamic policy signals).
|
||||
|
||||
## Proposed contract
|
||||
- Event type: `scheduler.policy.activation.requested`.
|
||||
- Payload: `{job_id, policy_run_id, tenant_id, priority, requested_at_utc, throttle_source}`.
|
||||
- Throttle source values: `scheduler-default`, `policy-signal`, `manual-override` (to be confirmed).
|
||||
|
||||
## Open decisions
|
||||
- Whether to carry bundle pointers (policy/export) in the activation event.
|
||||
- Retry/backoff policy if Policy service is down.
|
||||
|
||||
## Handoff
|
||||
Use this doc as PREP artefact for SCHED-WORKER-23-101; update once Policy guild provides final schema/throttle rules.
|
||||
Reference in New Issue
Block a user