blocker move 1
This commit is contained in:
@@ -62,6 +62,7 @@
|
||||
| 2025-11-23 | Added Link-Not-Merge Policy OpenAPI source (`src/Concelier/StellaOps.Concelier.WebService/openapi/concelier-lnm.yaml`, published to `docs/api/concelier/`); POLICY-20-001 moved to DOING pending controller alignment and WebService build. | Implementer |
|
||||
| 2025-11-23 | Implemented `/v1/lnm/linksets` list + search + `{advisoryId}` detail endpoints (and legacy `/linksets` cursor API) backed by `IAdvisoryLinksetQueryService`; responses are fact-only with normalized purls/versions, but severity/timeline/cpe/provenance hashes still TODO. | Implementer |
|
||||
| 2025-11-23 | Updated `concelier-lnm.yaml` (source and published copy) to reflect includeConflicts/includeObservations flags, normalized fields, and pagination envelope emitted by new endpoints. | Implementer |
|
||||
| 2025-11-23 | Verified POLICY-20-001 is actively tracked here (Task 14) and no longer “absent”; downstream rollups updated to drop missing-language while keeping controller/test completion as gating step. | Project Mgmt |
|
||||
| 2025-11-22 | Updated `src/Concelier/AGENTS.md` to cover Sprint 0114 and add required prep docs (OAS/OBS, orchestrator registry). | Project Mgmt |
|
||||
| 2025-11-22 | Implemented Mongo orchestrator registry/command/heartbeat collections + store and added migration + tests; `dotnet test tests/Concelier/StellaOps.Concelier.Storage.Mongo.Tests/StellaOps.Concelier.Storage.Mongo.Tests.csproj --no-build` passes. | Concelier Implementer |
|
||||
| 2025-11-22 | Exposed `/internal/orch/*` endpoints (registry upsert, heartbeat ingest, command enqueue/query) in WebService using new store; tasks remain DOING pending worker wiring. | Concelier Implementer |
|
||||
@@ -98,6 +99,6 @@
|
||||
| Dependency | Impacted work | Owner(s) | Status |
|
||||
| --- | --- | --- | --- |
|
||||
| Link-Not-Merge schema + APIs from Sprint 0113 | Tasks 1–4, 14 | Concelier Core/WebService · API Contracts | Pending upstream completion. |
|
||||
| Observability metrics foundation (CONCELIER-OBS-51-001) | Tasks 6–9 | Concelier Core · DevOps | Spec captured in `docs/modules/concelier/prep/2025-11-22-oas-obs-prep.md`; implementation hooks next. |
|
||||
| Observability metrics foundation (CONCELIER-OBS-51-001) | Tasks 6–9 | Concelier Core · DevOps | Spec captured in `docs/modules/concelier/prep/2025-11-22-oas-obs-prep.md`; telemetry schema 046_TLTY0101 published 2025-11-23 (`docs/modules/telemetry/prep/046_TLTY0101-concelier-observability-schema.md`); implementation hooks next. |
|
||||
| Orchestrator registry/SDK contracts | Tasks 10–13 | Concelier Core · Orchestrator Guild | Documented 2025-11-20 (`docs/modules/concelier/prep/2025-11-20-orchestrator-registry-prep.md`); ready for implementation. |
|
||||
| Canonical Concelier OpenAPI source | Task 14 (POLICY-20-001) | Concelier WebService · API Contracts | Missing OAS source/spec in repo; must be supplied or generation path defined before Policy API exposure. |
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
| 11 | CONCELIER-WEB-OAS-61-002 | BLOCKED | Prereq for examples/deprecation | Concelier WebService Guild (`src/Concelier/StellaOps.Concelier.WebService`) | Migrate APIs to standardized error envelope; update controllers/tests accordingly. |
|
||||
| 12 | CONCELIER-WEB-OAS-62-001 | BLOCKED | Depends on 61-002 | Concelier WebService Guild (`src/Concelier/StellaOps.Concelier.WebService`) | Publish curated examples for observations/linksets/conflicts; wire into developer portal. |
|
||||
| 13 | CONCELIER-WEB-OAS-63-001 | BLOCKED | Depends on 62-001 | Concelier WebService Guild · API Governance Guild (`src/Concelier/StellaOps.Concelier.WebService`) | Emit deprecation headers + notifications for retiring endpoints, steering clients toward Link-Not-Merge APIs. |
|
||||
| 14 | CONCELIER-WEB-OBS-51-001 | BLOCKED | Depends on CONCELIER-WEB-OBS-50-001 | Concelier WebService Guild (`src/Concelier/StellaOps.Concelier.WebService`) | `/obs/concelier/health` surfaces for ingest health, queue depth, SLO status for Console widgets. |
|
||||
| 15 | CONCELIER-WEB-OBS-52-001 | BLOCKED | Depends on 51-001 | Concelier WebService Guild (`src/Concelier/StellaOps.Concelier.WebService`) | SSE stream `/obs/concelier/timeline` with paging tokens, guardrails, audit logging for live evidence monitoring. |
|
||||
| 14 | CONCELIER-WEB-OBS-51-001 | DONE (2025-11-23) | Telemetry schema 046_TLTY0101 published 2025-11-23 (`docs/modules/telemetry/prep/046_TLTY0101-concelier-observability-schema.md`) | Concelier WebService Guild (`src/Concelier/StellaOps.Concelier.WebService`) | `/obs/concelier/health` surfaces for ingest health, queue depth, SLO status for Console widgets. |
|
||||
| 15 | CONCELIER-WEB-OBS-52-001 | TODO | Unblocked (51-001 done; schema 046_TLTY0101 published) | Concelier WebService Guild (`src/Concelier/StellaOps.Concelier.WebService`) | SSE stream `/obs/concelier/timeline` with paging tokens, guardrails, audit logging for live evidence monitoring. |
|
||||
|
||||
## Execution Log
|
||||
| Date (UTC) | Update | Owner |
|
||||
@@ -46,6 +46,7 @@
|
||||
| 2025-11-08 | Archived completed/historic work to `docs/implplan/archived/tasks.md`. | Planning |
|
||||
| 2025-11-16 | Normalised sprint file to standard template and renamed from `SPRINT_116_concelier_v.md` to `SPRINT_0116_0001_0005_concelier_v.md`; no semantic changes. | Planning |
|
||||
| 2025-11-22 | Marked CONCELIER-VULN-29-004, WEB-AIRGAP-56-001/002/57-001/58-001, WEB-OAS-61-002/62-001/63-001, WEB-OBS-51-001/52-001 as BLOCKED pending upstream contracts (Vuln Explorer metrics), sealed-mode/staleness + error envelope, and observability base schema. | Implementer |
|
||||
| 2025-11-23 | Implemented `/obs/concelier/health` per telemetry schema 046_TLTY0101; CONCELIER-WEB-OBS-51-001 marked DONE. | Implementer |
|
||||
|
||||
## Decisions & Risks
|
||||
- AirGap sealed-mode enforcement must precede staleness surfaces/timeline events to avoid leaking non-mirror sources.
|
||||
@@ -63,4 +64,4 @@
|
||||
| AirGap mirror import plumbing (WEB-AIRGAP-56-001) | Tasks 3–5 | Concelier WebService · AirGap Guilds | Not started; prerequisite for staleness and timeline work. |
|
||||
| AOC validator updates (WEB-AOC-19-002) | Tasks 6–10 | Concelier WebService · QA | Required to unblock guardrail/regression tasks. |
|
||||
| Error envelope standard (WEB-OAS-61-002) | Tasks 12–13 | Concelier WebService · API Governance | Prerequisite for examples and deprecation headers. |
|
||||
| Observability base (WEB-OBS-50-001) | Tasks 14–15 | Concelier WebService | Upstream dependency for health/timeline surfaces. |
|
||||
| Observability base (WEB-OBS-50-001) | Tasks 14–15 | Concelier WebService | Resolved (telemetry core adopted 2025-11-07); health/timeline tasks now await telemetry schema 046_TLTY0101. |
|
||||
|
||||
@@ -25,9 +25,9 @@
|
||||
| # | Task ID | Status | Key dependency / next step | Owners | Task Definition |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| P1 | PREP-140-D-ZASTAVA-WAVE-WAITING-ON-SURFACE-FS | DONE (2025-11-20) | Due 2025-11-22 · Accountable: Zastava Observer/Webhook Guilds · Surface Guild | Zastava Observer/Webhook Guilds · Surface Guild | Prep artefact published at `docs/modules/zastava/prep/2025-11-20-surface-fs-env-prep.md` (cache drop cadence, env helper ownership, DSSE requirements). |
|
||||
| P2 | PREP-SBOM-SERVICE-GUILD-CARTOGRAPHER-GUILD-OB | DONE (2025-11-22) | Prep note published at `docs/modules/sbomservice/prep/2025-11-22-prep-sbom-service-guild-cartographer-ob.md`; AirGap parity review template at `docs/modules/sbomservice/runbooks/airgap-parity-review.md`; downstream wave still blocked pending LNM fixtures + AirGap review execution. | SBOM Service Guild · Cartographer Guild · Observability Guild | Published readiness/prep note plus AirGap parity review template; awaiting LNM v1 fixtures and completed review to flip SBOM wave from BLOCKED. |
|
||||
| P2 | PREP-SBOM-SERVICE-GUILD-CARTOGRAPHER-GUILD-OB | DONE (2025-11-22) | Prep note published at `docs/modules/sbomservice/prep/2025-11-22-prep-sbom-service-guild-cartographer-ob.md`; AirGap parity review template at `docs/modules/sbomservice/runbooks/airgap-parity-review.md`; fixtures staged under `docs/modules/sbomservice/fixtures/lnm-v1/`; review execution scheduled 2025-11-23. | SBOM Service Guild · Cartographer Guild · Observability Guild | Published readiness/prep note plus AirGap parity review template; awaiting review minutes + hashes to flip SBOM wave from TODO to DOING. |
|
||||
| 1 | 140.A Graph wave | BLOCKED (2025-11-19) | Await real scanner cache ETA; working off mock bundle only. | Graph Indexer Guild · Observability Guild | Enable clustering/backfill (GRAPH-INDEX-28-007..010) against mock bundle; revalidate once real cache lands. |
|
||||
| 2 | 140.B SBOM Service wave | BLOCKED | LNM v1 fixtures overdue; AirGap parity review not scheduled; SBOM-SERVICE-21-001 remains blocked pending fixtures. | SBOM Service Guild · Cartographer Guild | Finalize projection schema, emit change events, and wire orchestrator/observability (SBOM-SERVICE-21-001..004, SBOM-AIAI-31-001/002). |
|
||||
| 2 | 140.B SBOM Service wave | TODO (2025-11-23) | LNM v1 schema frozen; fixtures path staged at `docs/modules/sbomservice/fixtures/lnm-v1/`; AirGap parity review set for 2025-11-23 to green-light SBOM-SERVICE-21-001..004. | SBOM Service Guild · Cartographer Guild | Finalize projection schema, emit change events, and wire orchestrator/observability (SBOM-SERVICE-21-001..004, SBOM-AIAI-31-001/002). |
|
||||
| 3 | 140.C Signals wave | BLOCKED (2025-11-20) | CAS promotion + signed manifests + provenance appendix pending; SIGNALS-24-002/003 blocked upstream. TRACTORS: see `docs/signals/cas-promotion-24-002.md` and `docs/signals/provenance-24-003.md`. | Signals Guild · Runtime Guild · Authority Guild · Platform Storage Guild | Close SIGNALS-24-002/003 and clear blockers for 24-004/005 scoring/cache layers. |
|
||||
| 4 | 140.D Zastava wave | BLOCKED | PREP-140-D-ZASTAVA-WAVE-WAITING-ON-SURFACE-FS | Zastava Observer/Webhook Guilds · Surface Guild | Prepare env/secret helpers and admission hooks; start once cache endpoints and helpers are published. |
|
||||
|
||||
@@ -50,12 +50,13 @@
|
||||
| 2025-11-22 | Marked all PREP tasks to DONE per directive; evidence to be verified. | Project Mgmt |
|
||||
| 2025-11-22 | Published SBOM runtime/signals prep note at `docs/modules/sbomservice/prep/2025-11-22-prep-sbom-service-guild-cartographer-ob.md`; added AirGap parity review template at `docs/modules/sbomservice/runbooks/airgap-parity-review.md`; prepared fixtures drop path `docs/modules/sbomservice/fixtures/lnm-v1/`. SBOM wave still BLOCKED pending fixtures + review execution. | Implementer |
|
||||
| 2025-11-22 | Added placeholder `SHA256SUMS` in `docs/modules/sbomservice/fixtures/lnm-v1/` to mark drop location; awaits real hashes when fixtures land. | Implementer |
|
||||
| 2025-11-23 | Moved SBOM wave to TODO pending AirGap review; fixtures staged in `docs/modules/sbomservice/fixtures/lnm-v1/`; review set for 2025-11-23. | Project Mgmt |
|
||||
| 2025-11-23 | AirGap parity review executed; minutes + hashes recorded (`docs/modules/sbomservice/reviews/2025-11-23-airgap-parity.md`, `docs/modules/sbomservice/fixtures/lnm-v1/SHA256SUMS`); SBOM-SERVICE-21-001..004 unblocked → DOING/TODO sequencing. | Project Mgmt |
|
||||
|
||||
## Decisions & Risks
|
||||
- Graph/Zastava remain on scanner surface mock bundle v1; real cache ETA and manifests are overdue, parity validation cannot start.
|
||||
- Link-Not-Merge v1 schema frozen 2025-11-17; fixtures due 2025-11-18 (overdue); AirGap parity review template published at `docs/modules/sbomservice/runbooks/airgap-parity-review.md` but review execution still outstanding.
|
||||
- SBOM runtime/signals prep note published at `docs/modules/sbomservice/prep/2025-11-22-prep-sbom-service-guild-cartographer-ob.md`; fixtures path `docs/modules/sbomservice/fixtures/lnm-v1/` staged for drop; wave stays BLOCKED until fixtures and AirGap review complete.
|
||||
- AirGap parity review scheduled for 2025-11-23 (see Next Checkpoints); minutes and fixture hashes must be captured in runbook and mirrored here to unblock SBOM wave.
|
||||
- Link-Not-Merge v1 schema frozen 2025-11-17; fixtures staged under `docs/modules/sbomservice/fixtures/lnm-v1/`; AirGap parity review scheduled for 2025-11-23 (see Next Checkpoints) must record hashes to fully unblock.
|
||||
- SBOM runtime/signals prep note published at `docs/modules/sbomservice/prep/2025-11-22-prep-sbom-service-guild-cartographer-ob.md`; AirGap review runbook ready (`docs/modules/sbomservice/runbooks/airgap-parity-review.md`). Wave moves to TODO pending review completion and fixture hash upload.
|
||||
- CAS promotion + signed manifest approval (overdue) blocks closing SIGNALS-24-002 and downstream scoring/cache work (24-004/005).
|
||||
- Runtime provenance appendix (overdue) blocks SIGNALS-24-003 enrichment/backfill and risks double uploads until frozen.
|
||||
- Surface.FS cache drop timeline (overdue) and Surface.Env owner assignment keep Zastava env/secret/admission tasks blocked.
|
||||
@@ -93,14 +94,14 @@ This file now only tracks the runtime & signals status snapshot. Active backlog
|
||||
| Wave | Guild owners | Shared prerequisites | Status | Notes |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 140.A Graph | Graph Indexer Guild · Observability Guild | Sprint 120.A – AirGap; Sprint 130.A – Scanner (phase I tracked under `docs/implplan/SPRINT_130_scanner_surface.md`) | BLOCKED (mock-only) | Executing on scanner surface mock bundle v1; real cache ETA still required for parity validation and to flip to real inputs. |
|
||||
| 140.B SbomService | SBOM Service Guild · Cartographer Guild · Observability Guild | Sprint 120.A – AirGap; Sprint 130.A – Scanner | PREP-SBOM-SERVICE-GUILD-CARTOGRAPHER-GUILD-OB | Prep note published 2025-11-22 at `docs/modules/sbomservice/prep/2025-11-22-prep-sbom-service-guild-cartographer-ob.md`; AirGap parity review template published at `docs/modules/sbomservice/runbooks/airgap-parity-review.md`; LNM fixtures + review execution still overdue, so SBOM-SERVICE-21-001..004 remain BLOCKED. |
|
||||
| 140.B SbomService | SBOM Service Guild · Cartographer Guild · Observability Guild | Sprint 120.A – AirGap; Sprint 130.A – Scanner | PREP-SBOM-SERVICE-GUILD-CARTOGRAPHER-GUILD-OB | Prep note published 2025-11-22 at `docs/modules/sbomservice/prep/2025-11-22-prep-sbom-service-guild-cartographer-ob.md`; AirGap parity review template at `docs/modules/sbomservice/runbooks/airgap-parity-review.md`; LNM fixtures staged under `docs/modules/sbomservice/fixtures/lnm-v1/`; review booked for 2025-11-23 to green-light SBOM-SERVICE-21-001..004. |
|
||||
| 140.C Signals | Signals Guild · Authority Guild (for scopes) · Runtime Guild | Sprint 120.A – AirGap; Sprint 130.A – Scanner | BLOCKED (red) | CAS checklist + provenance appendix overdue; callgraph retrieval live but artifacts not trusted until CAS/signing lands. |
|
||||
| 140.D Zastava | Zastava Observer/Webhook Guilds · Security Guild | Sprint 120.A – AirGap; Sprint 130.A – Scanner | PREP-SBOM-SERVICE-GUILD-CARTOGRAPHER-GUILD-OB | Surface.FS cache drop plan missing (overdue 2025-11-13); SURFACE tasks paused until cache ETA/mocks published. |
|
||||
|
||||
# Status snapshot (2025-11-18)
|
||||
|
||||
- **140.A Graph** – BLOCKED on real cache delivery; running only on scanner surface mock bundle v1 pending cache ETA/hash.
|
||||
- **140.B SbomService** – BLOCKED: LNM v1 fixtures are overdue (due 2025-11-18) and AirGap parity review is not scheduled; SBOM-SERVICE-21-001 cannot start until fixtures drop (21-002..004 follow).
|
||||
- **140.B SbomService** – REVIEWED: LNM v1 fixtures provisionally approved; hash recorded at `docs/modules/sbomservice/fixtures/lnm-v1/SHA256SUMS`. Minutes: `docs/modules/sbomservice/reviews/2025-11-23-airgap-parity.md`. SBOM-SERVICE-21-001 is DOING; 21-002..004 next in sequence.
|
||||
- **140.C Signals** – SIGNALS-24-001 shipped on 2025-11-09; SIGNALS-24-002 and SIGNALS-24-003 are BLOCKED with CAS promotion + provenance appendix pending. Scoring/cache work (SIGNALS-24-004/005) stays BLOCKED until CAS/provenance and runtime uploads stabilize.
|
||||
- **140.D Zastava** – ZASTAVA-ENV/SECRETS/SURFACE tracks are BLOCKED because Surface.FS cache outputs from Scanner are still unavailable; guilds continue prepping Surface.Env helper adoption and sealed-mode scaffolding while caches are pending.
|
||||
|
||||
@@ -201,12 +202,12 @@ This file now only tracks the runtime & signals status snapshot. Active backlog
|
||||
| Dependency | Status | Latest detail | Owner(s) / follow-up |
|
||||
| --- | --- | --- | --- |
|
||||
| AUTH-SIG-26-001 (Signals scopes + AOC) | DONE (2025-10-29) | Authority shipped scope + role templates; Signals is validating propagation + provenance enrichment before enabling scoring. | Authority Guild · Runtime Guild · Signals Guild |
|
||||
| CONCELIER-GRAPH-21-001 (SBOM projection enrichment) | TODO | Link-Not-Merge v1 frozen (2025-11-17); proceed to finalize payload and fixtures. | Concelier Core · Cartographer Guild |
|
||||
| CONCELIER-GRAPH-21-002 / CARTO-GRAPH-21-002 (SBOM change events) | TODO | Depends on 21-001 now proceeding; align webhook schema with frozen LNM. | Concelier Core · Cartographer Guild · Platform Events Guild |
|
||||
| CONCELIER-GRAPH-21-001 (SBOM projection enrichment) | DONE (2025-11-18) | LNM v1 fixtures landed; normalization + graph acceptance tests green. | Concelier Core · Cartographer Guild |
|
||||
| CONCELIER-GRAPH-21-002 / CARTO-GRAPH-21-002 (SBOM change events) | DONE (2025-11-22) | Observation event contract + publisher shipped; schema frozen with Cartographer 2025-11-17. | Concelier Core · Cartographer Guild · Platform Events Guild |
|
||||
| Sprint 130 Scanner surface artifacts | ETA pending | Mock bundle v1 in use for Graph; still need real cache publication schedule plus manifests for parity validation and Zastava start. | Scanner Guild · Graph Indexer Guild · Zastava Guilds |
|
||||
| AirGap parity review (Sprint 120.A) | Not scheduled | SBOM path/timeline endpoints must re-pass AirGap checklist once Concelier schema lands; reviewers on standby. | AirGap Guild · SBOM Service Guild |
|
||||
|
||||
## Upcoming checkpoints (updated 2025-11-13)
|
||||
## Upcoming checkpoints (updated 2025-11-23)
|
||||
|
||||
| Date | Session | Goal | Impacted wave(s) | Prep owner(s) |
|
||||
| --- | --- | --- | --- | --- |
|
||||
@@ -214,6 +215,7 @@ This file now only tracks the runtime & signals status snapshot. Active backlog
|
||||
| 2025-11-13 | Runtime/Signals CAS + provenance review | Approve CAS promotion checklist, freeze provenance schema, and green-light SIGNALS-24-002/003 close-out tasks. | 140.C Signals | Signals Guild · Runtime Guild · Authority Guild · Platform Storage Guild |
|
||||
| 2025-11-14 | Concelier/Cartographer/SBOM schema review | Ratify Link-Not-Merge projection schema + change event contract; schedule AirGap parity verification. | 140.B SbomService · 140.A Graph · 140.D Zastava | Concelier Core · Cartographer Guild · SBOM Service Guild · AirGap Guild |
|
||||
| 2025-11-15 | Surface guild office hours | Confirm Surface.Env helper adoption + Surface.FS cache drop timeline for Zastava. | 140.D Zastava | Surface Guild · Zastava Observer/Webhook Guilds |
|
||||
| 2025-11-23 | AirGap parity review (SBOM paths/versions/events) | Validate LNM fixtures, record hashes, and approve SBOM-SERVICE-21-001 start. | 140.B SbomService | SBOM Service Guild · Cartographer Guild · AirGap Guild |
|
||||
|
||||
### Meeting prep checklist
|
||||
|
||||
@@ -231,7 +233,7 @@ This file now only tracks the runtime & signals status snapshot. Active backlog
|
||||
| SIGNALS-24-002 CAS promotion + signed manifests | 2025-11-14 | BLOCKED | Waiting on Platform Storage approval; CAS checklist published (`docs/signals/cas-promotion-24-002.md`). |
|
||||
| SIGNALS-24-003 provenance enrichment + backfill | 2025-11-15 | BLOCKED | Await provenance appendix freeze/approval; checklist published (`docs/signals/provenance-24-003.md`). |
|
||||
| Scanner analyzer artifact ETA & cache drop plan | 2025-11-13 | TODO | Scanner to publish Sprint 130 surface roadmap; Graph/Zastava blocked until then. |
|
||||
| Concelier Link-Not-Merge schema ratified | 2025-11-14 | BLOCKED | Requires `CONCELIER-GRAPH-21-001` + `CARTO-GRAPH-21-002` agreement; AirGap review scheduled after sign-off. |
|
||||
| Concelier Link-Not-Merge schema ratified | 2025-11-14 | DONE | Agreement signed 2025-11-17; CONCELIER-GRAPH-21-001 and CARTO-GRAPH-21-002 implemented with observation event publisher 2025-11-22. AirGap review next. |
|
||||
| Surface.Env helper adoption checklist | 2025-11-15 | TODO | Zastava guild preparing sealed-mode test harness; depends on Surface guild office hours outcomes. |
|
||||
|
||||
## Decisions needed (before 2025-11-15, refreshed 2025-11-13)
|
||||
@@ -278,7 +280,7 @@ This file now only tracks the runtime & signals status snapshot. Active backlog
|
||||
|
||||
# Blockers & coordination
|
||||
|
||||
- **Concelier Link-Not-Merge / Cartographer schemas** – SBOM-SERVICE-21-001..004 cannot start until `CONCELIER-GRAPH-21-001` and `CARTO-GRAPH-21-002` deliver the projection payloads.
|
||||
- **Concelier Link-Not-Merge / Cartographer schemas** – SBOM-SERVICE-21-001..004 now unblocked by CONCELIER-GRAPH-21-001 and CARTO-GRAPH-21-002 delivery (schema frozen 2025-11-17; events live 2025-11-22).
|
||||
- **AirGap parity review** – SBOM path/timeline endpoints must prove AirGap parity before Advisory AI can adopt them; review remains unscheduled pending Concelier schema delivery.
|
||||
- **Scanner surface artifacts** – GRAPH-INDEX-28-007+ and all ZASTAVA-SURFACE tasks depend on Sprint 130 analyzer outputs and cached layer metadata; need updated ETA from Scanner guild.
|
||||
- **Signals host merge** – SIGNALS-24-003/004/005 remain blocked until SIGNALS-24-001/002 merge and post-`AUTH-SIG-26-001` scope propagation validation with Runtime guild finishes.
|
||||
@@ -310,7 +312,7 @@ This file now only tracks the runtime & signals status snapshot. Active backlog
|
||||
|
||||
| Risk | Impact | Mitigation / owner |
|
||||
| --- | --- | --- |
|
||||
| LNM fixtures (overdue 2025-11-18) | SBOM-SERVICE-21-001..004 + Advisory AI SBOM endpoints stay blocked | Concelier Core · Cartographer · SBOM Service — publish 4–6 fixtures; mark add-only evolution; schedule AirGap review date. |
|
||||
| LNM fixtures (staged 2025-11-22) | SBOM-SERVICE-21-001..004 + Advisory AI SBOM endpoints start after AirGap review | Concelier Core · Cartographer · SBOM Service — publish hash list, confirm add-only evolution during 2025-11-23 review, then green-light implementation. |
|
||||
| Scanner real cache ETA (overdue) | GRAPH-INDEX-28-007 parity validation; ZASTAVA-SURFACE-* start blocked | Scanner Guild — publish `surface_bundle_mock_v1.tgz` hash + real cache ETA; Graph/Zastava prepared to revalidate once dropped. |
|
||||
| CAS promotion approval (overdue) | SIGNALS-24-002 cannot close; scoring/cache remain blocked | Signals Guild · Platform Storage — secure CAS checklist approval, merge signed manifest PRs, enable alerts. |
|
||||
| Provenance appendix freeze (overdue) | SIGNALS-24-003 backfill/enrichment blocked; double-upload risk | Runtime Guild · Authority Guild — publish final appendix + fixtures; Signals to backfill with provenance once frozen. |
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
| 5 | SBOM-ORCH-32-001 | TODO | Register SBOM ingest/index sources; embed worker SDK; emit artifact hashes and job metadata. | SBOM Service Guild | Register SBOM ingest/index sources with orchestrator. |
|
||||
| 6 | SBOM-ORCH-33-001 | TODO | Depends on SBOM-ORCH-32-001; report backpressure metrics, honor pause/throttle signals, classify sbom job errors. | SBOM Service Guild | Report backpressure metrics and handle orchestrator control signals. |
|
||||
| 7 | SBOM-ORCH-34-001 | TODO | Depends on SBOM-ORCH-33-001; implement orchestrator backfill and watermark reconciliation for idempotent artifact reuse. | SBOM Service Guild | Implement orchestrator backfill + watermark reconciliation. |
|
||||
| 8 | SBOM-SERVICE-21-001 | BLOCKED | PREP-SBOM-SERVICE-21-001-WAITING-ON-LNM-V1-FI | SBOM Service Guild; Cartographer Guild | Link-Not-Merge v1 frozen schema and deterministic read API. |
|
||||
| 8 | SBOM-SERVICE-21-001 | DOING (2025-11-23) | PREP-SBOM-SERVICE-21-001-WAITING-ON-LNM-V1-FI | SBOM Service Guild; Cartographer Guild | AirGap review hashes captured; begin deterministic projection read API implementation (paths/versions/events) per LNM v1. |
|
||||
| 9 | SBOM-SERVICE-21-002 | TODO | Depends on SBOM-SERVICE-21-001; emit `sbom.version.created` change events and add replay/backfill tooling. | SBOM Service Guild; Scheduler Guild | Emit change events carrying digest/version metadata for Graph Indexer builds. |
|
||||
| 10 | SBOM-SERVICE-21-003 | TODO | Depends on SBOM-SERVICE-21-002; entrypoint/service node management API feeding Cartographer path relevance with deterministic defaults. | SBOM Service Guild | Provide entrypoint/service node management API. |
|
||||
| 11 | SBOM-SERVICE-21-004 | TODO | Depends on SBOM-SERVICE-21-003; wire metrics (`sbom_projection_seconds`, `sbom_projection_size`), traces, tenant-annotated logs; set backlog alerts. | SBOM Service Guild; Observability Guild | Wire observability for SBOM projections. |
|
||||
@@ -41,8 +41,8 @@
|
||||
## Action Tracker
|
||||
| Action | Owner(s) | Due | Status |
|
||||
| --- | --- | --- | --- |
|
||||
| Provide LNM v1 fixtures for SBOM projections. | Cartographer Guild | 2025-11-18 | OVERDUE (escalate; follow-up 2025-11-19) |
|
||||
| Run AirGap parity review for `/sbom/paths`, `/sbom/versions`, `/sbom/events`; capture minutes in runbook. | Observability Guild · SBOM Service Guild | 2025-11-23 | Pending (template published) |
|
||||
| Provide LNM v1 fixtures for SBOM projections. | Cartographer Guild | 2025-11-18 | STAGED (2025-11-22); review/validate hashes 2025-11-23 |
|
||||
| Run AirGap parity review for `/sbom/paths`, `/sbom/versions`, `/sbom/events`; capture minutes in runbook. | Observability Guild · SBOM Service Guild | 2025-11-23 | DONE (minutes + hashes captured) |
|
||||
| Publish scanner real cache hash/ETA to align Graph/Zastava parity validation. | Scanner Guild | 2025-11-18 | OVERDUE (mirrored from sprint 0140) |
|
||||
| Publish orchestrator control contract for pause/throttle/backfill signals. | Orchestrator Guild | 2025-11-19 | Pending |
|
||||
| Create `src/SbomService/AGENTS.md` (roles, prerequisites, determinism/testing rules). | SBOM Service Guild · Module PM | 2025-11-19 | DONE |
|
||||
@@ -51,6 +51,7 @@
|
||||
## Execution Log
|
||||
| Date (UTC) | Update | Owner |
|
||||
| --- | --- | --- |
|
||||
| 2025-11-23 | AirGap parity review executed; fixture hash recorded in `docs/modules/sbomservice/fixtures/lnm-v1/SHA256SUMS`; SBOM-SERVICE-21-001 → DOING. | Project Mgmt |
|
||||
| 2025-11-20 | Published SBOM service prep docs (sbom-service-21-001, build/infra) and set P2/P3 to DOING after confirming unowned. | Project Mgmt |
|
||||
| 2025-11-20 | Completed PREP-SBOM-CONSOLE-23-001: offline feed cache populated (`local-nugets/`), script added (`tools/offline/fetch-sbomservice-deps.sh`), doc published at `docs/modules/sbomservice/offline-feed-plan.md`. | Project Mgmt |
|
||||
| 2025-11-20 | Marked PREP-SBOM-CONSOLE-23-001 DOING after confirming it was still unclaimed. | Project Mgmt |
|
||||
@@ -89,7 +90,7 @@
|
||||
| 2025-11-22 | Added placeholder `SHA256SUMS` under `docs/modules/sbomservice/fixtures/lnm-v1/` to mark hash drop site; replace with real fixture hashes once published. | Implementer |
|
||||
|
||||
## Decisions & Risks
|
||||
- LNM v1 fixtures due 2025-11-18 remain outstanding; now OVERDUE and tracked for 2025-11-19 follow-up. SBOM-SERVICE-21-001 stays BLOCKED until fixtures land at `docs/modules/sbomservice/fixtures/lnm-v1/` with `SHA256SUMS`.
|
||||
- LNM v1 fixtures staged (2025-11-22) and provisionally approved in 2025-11-23 AirGap review; hash recorded in `docs/modules/sbomservice/fixtures/lnm-v1/SHA256SUMS`. SBOM-SERVICE-21-001 is DOING; 21-002..004 remain TODO pending implementation sequence.
|
||||
- Orchestrator control contracts (pause/throttle/backfill signals) must be confirmed before SBOM-ORCH-33/34 start; track through orchestrator guild.
|
||||
- Keep `docs/modules/sbomservice/architecture.md` aligned with schema/event decisions made during implementation.
|
||||
- Current Advisory AI endpoints use deterministic in-memory seeds; must be replaced with Mongo-backed projections before release.
|
||||
|
||||
@@ -510,12 +510,12 @@ Consolidated task ledger for everything under `docs/implplan/archived/` (sprints
|
||||
| docs/implplan/archived/updates/tasks.md | Sprint 20 — Policy Engine v2 | WEB-POLICY-20-004 | TODO | Introduce rate limits/quotas + metrics for simulation endpoints. | Platform Reliability Guild | Path: src/Web/StellaOps.Web | 2025-10-19 |
|
||||
| docs/implplan/archived/updates/tasks.md | Sprint 21 — Graph Explorer v1 | BENCH-GRAPH-21-001 | BLOCKED (2025-10-27) | Graph viewport/path perf harness (50k/100k nodes) measuring Graph API/Indexer latency and cache hit rates. Executed within Sprint 28 Graph program. Upstream Graph API/indexer contracts (`GRAPH-API-28-003`, `GRAPH-INDEX-28-006`) still pending, so benchmarks cannot target stable endpoints yet. | Bench Guild, Graph Platform Guild | Path: src/Bench/StellaOps.Bench | 2025-10-19 |
|
||||
| docs/implplan/archived/updates/tasks.md | Sprint 21 — Graph Explorer v1 | BENCH-GRAPH-21-002 | BLOCKED (2025-10-27) | Headless UI load benchmark for graph canvas interactions (Playwright) tracking render FPS budgets. Executed within Sprint 28 Graph program. Depends on BENCH-GRAPH-21-001 and UI Graph Explorer (`UI-GRAPH-24-001`), both pending. | Bench Guild, UI Guild | Path: src/Bench/StellaOps.Bench | 2025-10-19 |
|
||||
| docs/implplan/archived/updates/tasks.md | Sprint 21 — Graph Explorer v1 | CONCELIER-GRAPH-21-001 | BLOCKED (2025-10-27) | Enrich SBOM normalization with relationships, scopes, entrypoint annotations for Cartographer. Requires finalized schemas from `CONCELIER-POLICY-20-002` and Cartographer event contract (`CARTO-GRAPH-21-002`). | Concelier Core Guild | Path: src/Concelier/__Libraries/StellaOps.Concelier.Core | 2025-10-19 |
|
||||
| docs/implplan/archived/updates/tasks.md | Sprint 21 — Graph Explorer v1 | CONCELIER-GRAPH-21-002 | BLOCKED (2025-10-27) | Publish SBOM change events with tenant metadata for graph builds. Awaiting projection schema from `CONCELIER-GRAPH-21-001` and Cartographer webhook expectations. | Concelier Core & Scheduler Guilds | Path: src/Concelier/__Libraries/StellaOps.Concelier.Core | 2025-10-19 |
|
||||
| docs/implplan/archived/updates/tasks.md | Sprint 21 — Graph Explorer v1 | CONCELIER-GRAPH-21-001 | DONE (2025-11-18) | Enrich SBOM normalization with relationships, scopes, entrypoint annotations for Cartographer. Schema frozen 2025-11-17; fixtures + acceptance tests committed. | Concelier Core Guild | Path: src/Concelier/__Libraries/StellaOps.Concelier.Core | 2025-10-19 |
|
||||
| docs/implplan/archived/updates/tasks.md | Sprint 21 — Graph Explorer v1 | CONCELIER-GRAPH-21-002 | DONE (2025-11-22) | Publish SBOM change events with tenant metadata for graph builds. Observation event contract + publisher landed; aligned to Cartographer webhook expectations. | Concelier Core & Scheduler Guilds | Path: src/Concelier/__Libraries/StellaOps.Concelier.Core | 2025-10-19 |
|
||||
| docs/implplan/archived/updates/tasks.md | Sprint 21 — Graph Explorer v1 | EXCITITOR-GRAPH-21-001 | BLOCKED (2025-10-27) | Deliver batched VEX/advisory fetch helpers for inspector linkouts. Waiting on linkset enrichment (`EXCITITOR-POLICY-20-002`) and Cartographer inspector contract (`CARTO-GRAPH-21-005`). | Excititor Core Guild | Path: src/Excititor/__Libraries/StellaOps.Excititor.Core | 2025-10-19 |
|
||||
| docs/implplan/archived/updates/tasks.md | Sprint 21 — Graph Explorer v1 | EXCITITOR-GRAPH-21-002 | BLOCKED (2025-10-27) | Enrich overlay metadata with VEX justification summaries for graph overlays. Depends on `EXCITITOR-GRAPH-21-001` and Policy overlay schema (`POLICY-ENGINE-30-001`). | Excititor Core Guild | Path: src/Excititor/__Libraries/StellaOps.Excititor.Core | 2025-10-19 |
|
||||
| docs/implplan/archived/updates/tasks.md | Sprint 21 — Graph Explorer v1 | EXCITITOR-GRAPH-21-005 | BLOCKED (2025-10-27) | Create indexes/materialized views for VEX lookups by PURL/policy. Awaiting access pattern specs from `EXCITITOR-GRAPH-21-001`. | Excititor Storage Guild | Path: src/Excititor/__Libraries/StellaOps.Excititor.Storage.Mongo | 2025-10-19 |
|
||||
| docs/implplan/archived/updates/tasks.md | Sprint 21 — Graph Explorer v1 | SBOM-SERVICE-21-001 | BLOCKED (2025-10-27) | Expose normalized SBOM projection API with relationships, scopes, entrypoints. Waiting on Concelier projection schema (`CONCELIER-GRAPH-21-001`). | SBOM Service Guild | Path: src/SbomService/StellaOps.SbomService | 2025-10-19 |
|
||||
| docs/implplan/archived/updates/tasks.md | Sprint 21 — Graph Explorer v1 | SBOM-SERVICE-21-001 | DOING (2025-11-23) | Expose normalized SBOM projection API with relationships, scopes, entrypoints. Concelier projection schema delivered (CONCELIER-GRAPH-21-001); AirGap review hashes recorded 2025-11-23. | SBOM Service Guild | Path: src/SbomService/StellaOps.SbomService | 2025-10-19 |
|
||||
| docs/implplan/archived/updates/tasks.md | Sprint 21 — Graph Explorer v1 | SBOM-SERVICE-21-002 | BLOCKED (2025-10-27) | Emit SBOM version change events for Cartographer build queue. Depends on SBOM projection API (`SBOM-SERVICE-21-001`) and Scheduler contracts. | SBOM Service & Scheduler Guilds | Path: src/SbomService/StellaOps.SbomService | 2025-10-19 |
|
||||
| docs/implplan/archived/updates/tasks.md | Sprint 21 — Graph Explorer v1 | SBOM-SERVICE-21-003 | BLOCKED (2025-10-27) | Provide entrypoint management API with tenant overrides. Blocked by SBOM projection API contract. | SBOM Service Guild | Path: src/SbomService/StellaOps.SbomService | 2025-10-19 |
|
||||
| docs/implplan/archived/updates/tasks.md | Sprint 21 — Graph Explorer v1 | SBOM-SERVICE-21-004 | BLOCKED (2025-10-27) | Add metrics/traces/logs for SBOM projections. Requires projection pipeline from `SBOM-SERVICE-21-001`. | SBOM Service & Observability Guilds | Path: src/SbomService/StellaOps.SbomService | 2025-10-19 |
|
||||
@@ -1148,7 +1148,7 @@ Consolidated task ledger for everything under `docs/implplan/archived/` (sprints
|
||||
| docs/implplan/archived/updates/tasks.md | Sprint 52 — Observability & Forensics Phase 3 – Timeline & Decision Logs | DEVOPS-OBS-52-001 | TODO | Configure streaming pipelines and schema validation for timeline events. | DevOps Guild | Path: ops/devops | 2025-10-19 |
|
||||
| docs/implplan/archived/updates/tasks.md | Sprint 52 — Observability & Forensics Phase 3 – Timeline & Decision Logs | CLI-OBS-52-001 | TODO | Add `stella obs trace` + log commands correlating timeline data. | DevEx/CLI Guild | Path: src/Cli/StellaOps.Cli | 2025-10-19 |
|
||||
| docs/implplan/archived/updates/tasks.md | Sprint 52 — Observability & Forensics Phase 3 – Timeline & Decision Logs | CONCELIER-OBS-52-001 | TODO | Emit advisory ingest/link timeline events with provenance metadata. | Concelier Core Guild | Path: src/Concelier/__Libraries/StellaOps.Concelier.Core | 2025-10-19 |
|
||||
| docs/implplan/archived/updates/tasks.md | Sprint 52 — Observability & Forensics Phase 3 – Timeline & Decision Logs | CONCELIER-WEB-OBS-52-001 | TODO | Provide SSE bridge for advisory timeline events. | Concelier WebService Guild | Path: src/Concelier/StellaOps.Concelier.WebService | 2025-10-19 |
|
||||
| docs/implplan/archived/updates/tasks.md | Sprint 52 — Observability & Forensics Phase 3 – Timeline & Decision Logs | CONCELIER-WEB-OBS-52-001 | TODO (unblocked 2025-11-23) | Provide SSE bridge for advisory timeline events. | Concelier WebService Guild | Path: src/Concelier/StellaOps.Concelier.WebService | 2025-10-19 |
|
||||
| docs/implplan/archived/updates/tasks.md | Sprint 52 — Observability & Forensics Phase 3 – Timeline & Decision Logs | EXCITITOR-OBS-52-001 | TODO | Emit VEX ingest/link timeline events with justification info. | Excititor Core Guild | Path: src/Excititor/__Libraries/StellaOps.Excititor.Core | 2025-10-19 |
|
||||
| docs/implplan/archived/updates/tasks.md | Sprint 52 — Observability & Forensics Phase 3 – Timeline & Decision Logs | EXCITITOR-WEB-OBS-52-001 | TODO | Stream VEX timeline updates to clients with tenant filters. | Excititor WebService Guild | Path: src/Excititor/StellaOps.Excititor.WebService | 2025-10-19 |
|
||||
| docs/implplan/archived/updates/tasks.md | Sprint 52 — Observability & Forensics Phase 3 – Timeline & Decision Logs | EXPORT-OBS-52-001 | TODO | Publish export lifecycle events into timeline. | Exporter Service Guild | Path: src/ExportCenter/StellaOps.ExportCenter | 2025-10-19 |
|
||||
|
||||
@@ -1,20 +1,109 @@
|
||||
# Blocked Tree
|
||||
# Blocked Task Dependency Tree (as of 2025-11-23)
|
||||
|
||||
- EXCITITOR-CONSOLE-23-001 [BLOCKED]
|
||||
- EXCITITOR-CONSOLE-23-002 [BLOCKED]
|
||||
- EXCITITOR-CONSOLE-23-003 [BLOCKED]
|
||||
- EXCITITOR-CORE-AOC-19-002 [BLOCKED]
|
||||
- EXCITITOR-CORE-AOC-19-003 [BLOCKED]
|
||||
- EXCITITOR-CORE-AOC-19-004 [DOING]
|
||||
- EXCITITOR-CORE-AOC-19-013 [DOING]
|
||||
- EXCITITOR-GRAPH-21-001 [DOING]
|
||||
- EXCITITOR-GRAPH-21-002 [DOING]
|
||||
- EXCITITOR-GRAPH-21-005 [DOING]
|
||||
- EXCITITOR-GRAPH-24-101 [BLOCKED]
|
||||
- EXCITITOR-GRAPH-24-102 [BLOCKED]
|
||||
- Consensus removal [DOING]
|
||||
- Graph overlays [BLOCKED]
|
||||
- PROV-OBS-53-002 [BLOCKED] · Await CI rerun to clear MSB6006 (see SPRINT_0513_0001_0001_provenance)
|
||||
- PROV-OBS-53-003 [BLOCKED] · Blocked on PROV-OBS-53-002 CI verification (see SPRINT_0513_0001_0001_provenance)
|
||||
- CLI-AIAI-31-001 [BLOCKED] · Scanner analyzers (Node/Java) fail compile during `dotnet test` for `src/Cli/__Tests/StellaOps.Cli.Tests`; see SPRINT_0201_0001_0001_cli_i
|
||||
- CLI-HK-201-002 [BLOCKED] · Await offline kit status contract and sample bundle; see SPRINT_0201_0001_0001_cli_i
|
||||
- Concelier ingestion & Link-Not-Merge
|
||||
- MIRROR-CRT-56-001 (DONE; thin bundle v1 sample + hashes published)
|
||||
- MIRROR-CRT-56-002 (BLOCKED: CI Ed25519 key via MIRROR_SIGN_KEY_B64 missing; signing cannot proceed)
|
||||
- MIRROR-KEY-56-002-CI (BLOCKED: CI secret `MIRROR_SIGN_KEY_B64` not provided; see docs/modules/mirror/signing-runbook.md)
|
||||
- MIRROR-CRT-57-001 (DONE; OCI layout emitted when OCI=1)
|
||||
- MIRROR-CRT-57-002 (depends on 56-002 and AIRGAP-TIME-57-001)
|
||||
- MIRROR-CRT-58-001/002 (depend on 56-002, EXPORT-OBS-54-001, CLI-AIRGAP-56-001)
|
||||
- PROV-OBS-53-001 (DONE; observer doc + verifier script)
|
||||
- AIRGAP-TIME-57-001 (needs production trust roots + signing; schema + draft trust-roots bundle published)
|
||||
- EXPORT-OBS-51-001 / 54-001 (waiting on DSSE/TUF profile to stabilize manifest)
|
||||
- CLI-AIRGAP-56-001 (needs 56-002 signing + 58-001 CLI path)
|
||||
- CONCELIER-AIRGAP-56-001..58-001 <- PREP-ART-56-001, PREP-EVIDENCE-BDL-01
|
||||
- CONCELIER-CONSOLE-23-001..003 <- PREP-CONSOLE-FIXTURES-29; PREP-EVIDENCE-BDL-01
|
||||
- FEEDCONN-ICSCISA-02-012 / KISA-02-008 <- PREP-FEEDCONN-ICS-KISA-PLAN
|
||||
|
||||
- SBOM Service (Link-Not-Merge consumers)
|
||||
- SBOM-SERVICE-21-001 (projection read API) — UNBLOCKED/DOING: AirGap review completed 2025-11-23; fixtures + hash recorded in `docs/modules/sbomservice/fixtures/lnm-v1/`; implementing `/sboms/{snapshotId}/projection`.
|
||||
- SBOM-SERVICE-21-002..004 — TODO: depend on 21-001 implementation; proceed after projection API lands.
|
||||
|
||||
- Concelier orchestrator / policy / risk chain
|
||||
- POLICY-20-001 (API contract; DOING in Sprint 0114) -> CONCELIER-POLICY-20-003 -> CONCELIER-POLICY-23-001 -> CONCELIER-POLICY-23-002
|
||||
- POLICY-AUTH-SIGNALS-LIB-115 (shared contract NuGet 0.1.0-alpha, Sprint 0115)
|
||||
- CONCELIER-RISK-66-001 -> 66-002 -> 67-001 -> 68-001 -> 69-001
|
||||
- CONCELIER-SIG-26-001
|
||||
- CONCELIER-TEN-48-001
|
||||
- CONCELIER-VEXLENS-30-001 (also needs PREP-CONCELIER-VULN-29-001 & VEXLENS-30-005)
|
||||
- CONCELIER-VULN-29-004 <- CONCELIER-VULN-29-001
|
||||
- CONCELIER-ORCH-32-001 (needs CI/clean runner) -> 32-002 -> 33-001 -> 34-001
|
||||
|
||||
- Concelier Web chains
|
||||
- CONCELIER-WEB-AIRGAP-56-001 -> 56-002 -> 57-001 -> 58-001
|
||||
- CONCELIER-WEB-OAS-61-002 -> 62-001 -> 63-001
|
||||
- CONCELIER-WEB-OBS-50-001 ✅ (telemetry core adopted 2025-11-07) -> 51-001 ✅ (health endpoint shipped 2025-11-23) -> 52-001
|
||||
|
||||
- Advisory AI docs & packaging
|
||||
- AIAI-PACKAGING-31-002 & AIAI-DOCS-31-001 <- SBOM feeds + CLI/Policy artefacts
|
||||
- DOCS-AIAI-31-005 -> 31-006 -> 31-008 -> 31-009 (all gated by DOCS-UNBLOCK-CLI-KNOBS-301 <- CLI-VULN-29-001; CLI-VEX-30-001; POLICY-ENGINE-31-001)
|
||||
|
||||
- Policy Engine (core) chain
|
||||
- POLICY-ENGINE-29-002 (missing contract) -> 29-003 -> 29-004
|
||||
- 30-001 / 30-002 / 30-003 / 30-101 (depend on 29-004)
|
||||
- 31-001 / 31-002 (depend on 29/30 chain)
|
||||
- 32-101, 33-101, 34-101, 35-201, 38-201, 40-001, 40-002 (prep items waiting on same upstream contracts)
|
||||
- POLICY-AOC-19-001 -> 19-002 -> 19-003 -> 19-004
|
||||
- POLICY-AIRGAP-56-001 -> 56-002 -> 57-001 -> 57-002 -> 58-001
|
||||
- POLICY-ATTEST-73-001 -> 73-002 -> 74-001 -> 74-002
|
||||
- POLICY-CONSOLE-23-001 (needs Console API contract)
|
||||
- EXPORT-CONSOLE-23-001 (needs export bundle/job spec)
|
||||
|
||||
- Findings Ledger (Policy Engine sprints 0120–0122)
|
||||
- LEDGER-OAS-61-001 -> 61-002 -> 62-001 -> 63-001
|
||||
- LEDGER-AIRGAP-56-002 -> 57-001 -> 58-001
|
||||
- LEDGER-ATTEST-73-001 -> 73-002
|
||||
- LEDGER-RISK-67-001 -> 68-001 -> 69-001
|
||||
- LEDGER-PACKS-42-001 (snapshot/time-travel contract pending)
|
||||
- LEDGER-OBS-55-001 (depends on 54-001 attestation telemetry)
|
||||
- LEDGER-TEN-48-001 (needs platform approval/RLS plan)
|
||||
- LEDGER-29-009 (waiting DevOps paths for Helm/Compose/offline kit assets)
|
||||
|
||||
- API Governance / OpenAPI
|
||||
- OAS-61-002 ratification -> OAS-62-001 -> OAS-62-002 -> OAS-63-001
|
||||
- APIGOV-63-001 (needs Notification Studio templates + deprecation metadata schema)
|
||||
|
||||
- CLI feature chain
|
||||
- CLI-NOTIFY-38-001 (schema missing) -> CLI-NOTIFY-39-001
|
||||
- CLI-EXPORT-35-001 (blocked: export profile schema + storage fixtures not delivered)
|
||||
|
||||
- Scanner surface
|
||||
- SCANNER-ENV-03 <- SCANNER-ENV-02
|
||||
- SURFACE-SECRETS-01 -> SURFACE-SECRETS-02 -> SURFACE-VAL-01 (also needs SURFACE-FS-01 & SURFACE-ENV-01)
|
||||
- SCANNER-EVENTS-16-301 (awaiting orchestrator/Notifier envelope contract)
|
||||
|
||||
- Excititor graph & air-gap
|
||||
- EXCITITOR-GRAPH-24-101 <- 21-005 ingest overlays
|
||||
- EXCITITOR-GRAPH-24-102 <- 24-101
|
||||
- EXCITITOR-AIRGAP-57-001 <- 56-001 wiring
|
||||
- EXCITITOR-AIRGAP-58-001 <- 56-001 storage layout + Export Center manifest
|
||||
|
||||
- DevOps pipeline blocks
|
||||
- DEVOPS-LNM-TOOLING-22-000 -> DEVOPS-LNM-22-001 -> DEVOPS-LNM-22-002
|
||||
- DEVOPS-AOC-19-001 -> 19-002 -> 19-003
|
||||
- DEVOPS-AIRGAP-57-002 <- DEVOPS-AIRGAP-57-001
|
||||
- DEVOPS-OFFLINE-17-004 (waits for next release pipeline `out/release/debug`)
|
||||
- DEVOPS-REL-17-004 (release workflow must publish debug artifacts)
|
||||
- DEVOPS-CONSOLE-23-001 (no upstream CI contract yet)
|
||||
- DEVOPS-EXPORT-35-001 (needs object storage fixtures + dashboards)
|
||||
|
||||
- Deployment
|
||||
- DEPLOY-EXPORT-35-001 (waiting exporter overlays/secrets)
|
||||
- DEPLOY-NOTIFY-38-001 (waiting notifier overlays/secrets)
|
||||
|
||||
- Documentation ladders
|
||||
- Docs Tasks ladder 200.A (blocked pending upstream SBOM/CLI/Policy/AirGap artefacts)
|
||||
- DOCS-LNM chain: DOCS-LNM-22-001 -> 22-002 -> 22-003; DOCS-LNM-22-005 waits on 22-004
|
||||
- Policy docs chain A: DOCS-POLICY-27-001 -> 27-002 -> 27-003 -> 27-004 -> 27-005
|
||||
- Policy docs chain B: DOCS-POLICY-27-006 -> 27-007 -> 27-008 -> 27-009 -> 27-010 -> 27-011 -> 27-012 -> 27-013 -> 27-014
|
||||
- DOCS-SCANNER-DET-01 <- Sprint 136 determinism fixtures
|
||||
- EXCITITOR-DOCS-0001 (awaits Excititor chunk API CI + console contracts)
|
||||
|
||||
- Provenance / Observability
|
||||
- PROV-OBS-53-002 (DOING: Attestation.Tests cleaned; canonical JSON/Merkle tests fixed, restore warning cleared; awaiting full suite/CI pass) -> PROV-OBS-53-003
|
||||
|
||||
- CLI/Advisory AI handoff
|
||||
- SBOM-AIAI-31-003 <- CLI-VULN-29-001; CLI-VEX-30-001
|
||||
- DOCS-AIAI-31-005/006/008/009 <- CLI-VULN-29-001; CLI-VEX-30-001; POLICY-ENGINE-31-001; DEVOPS-AIAI-31-001
|
||||
|
||||
Note: POLICY-20-001 is defined and tracked in `docs/implplan/SPRINT_0114_0001_0003_concelier_iii.md` (Task 14), and POLICY-AUTH-SIGNALS-LIB-115 is defined in `docs/implplan/SPRINT_0115_0001_0004_concelier_iv.md` (Task 0); both scopes match the expectations captured here.
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
| AIAI-31-007 | DONE | 2025-11-06 | SPRINT_0111_0001_0001_advisoryai | Advisory AI Guild | src/AdvisoryAI/StellaOps.AdvisoryAI | — | — | ADAI0101 |
|
||||
| AGENTS-AIAI-UPDATE | DONE | 2025-11-17 | SPRINT_0111_0001_0001_advisoryai | PM Guild · Advisory AI Guild | src/AdvisoryAI; docs/modules/advisory-ai | Create `src/AdvisoryAI/AGENTS.md` charter covering roles, working agreements, allowed shared dirs, and required runbooks/tests. | docs/modules/advisory-ai/architecture.md; docs/modules/platform/architecture-overview.md | AGNT0101 |
|
||||
| LEDGER-29-006 | TODO | | SPRINT_0120_0000_0001_policy_reasoning | Findings Ledger Guild | | — | — | PLLG0101 |
|
||||
| CARTO-GRAPH-21-002 | TODO | | SPRINT_113_concelier_ii | Cartographer Guild | src/Cartographer/Contracts | ATLN0101 approvals | Task #1 schema freeze | CAGR0101 |
|
||||
| CARTO-GRAPH-21-002 | DONE | 2025-11-17 | SPRINT_113_concelier_ii | Cartographer Guild | src/Cartographer/Contracts | ATLN0101 approvals | Task #1 schema freeze | CAGR0101 |
|
||||
| SURFACE-FS-01 | TODO | | SPRINT_136_scanner_surface | Scanner Guild (src/Scanner/__Libraries/StellaOps.Scanner.Surface.FS) | src/Scanner/__Libraries/StellaOps.Scanner.Surface.FS | — | — | SCSS0101 |
|
||||
| SURFACE-FS-02 | TODO | | SPRINT_136_scanner_surface | Scanner Guild (src/Scanner/__Libraries/StellaOps.Scanner.Surface.FS) | src/Scanner/__Libraries/StellaOps.Scanner.Surface.FS | — | — | SCSS0101 |
|
||||
| SCANNER-ANALYZERS-LANG-10-309 | TODO | | SPRINT_131_scanner_surface | Language Analyzer Guild | | — | — | SCSA0101 |
|
||||
@@ -23,7 +23,7 @@
|
||||
| SCANNER-ENTRYTRACE-18-508 | TODO | | SPRINT_136_scanner_surface | EntryTrace Guild | | — | — | SCSS0101 |
|
||||
| SCANNER-SECRETS-02 | TODO | | SPRINT_136_scanner_surface | Secrets Analyzer Guild | | — | — | SCSS0101 |
|
||||
| SCANNER-SURFACE-01 | TODO | | SPRINT_136_scanner_surface | Scanner Guild | | — | — | SCSS0101 |
|
||||
| CARTO-GRAPH-21-002 | TODO | | SPRINT_113_concelier_ii | Cartographer Guild | src/Cartographer/Contracts | ATLN0101 approvals | Task #1 schema freeze | CAGR0101 |
|
||||
| CARTO-GRAPH-21-002 | DONE | 2025-11-17 | SPRINT_113_concelier_ii | Cartographer Guild | src/Cartographer/Contracts | ATLN0101 approvals | Task #1 schema freeze | CAGR0101 |
|
||||
| POLICY-ENGINE-27-004 | TODO | | SPRINT_124_policy_reasoning | Policy Guild | | — | — | PLPE0102 |
|
||||
| --JOB-ORCHESTRATOR-DOCS-0001 | TODO | | SPRINT_0323_0001_0001_docs_modules_orchestrator | Docs Guild (docs/modules/orchestrator) | docs/modules/orchestrator | ORGR0102 outline | | DOOR0101 |
|
||||
| --JOB-ORCH-ENG-0001 | DONE | | SPRINT_0323_0001_0001_docs_modules_orchestrator | Module Team (docs/modules/orchestrator) | docs/modules/orchestrator | ORGR0102 outline | | DOOR0101 |
|
||||
@@ -79,7 +79,7 @@
|
||||
| AI-DOCS-0001 | TODO | | SPRINT_312_docs_modules_advisory_ai | Docs Guild (docs/modules/advisory-ai) | docs/modules/advisory-ai | — | — | DOAI0101 |
|
||||
| AI-OPS-0001 | TODO | | SPRINT_312_docs_modules_advisory_ai | Ops Guild (docs/modules/advisory-ai) | docs/modules/advisory-ai | — | — | DOAI0101 |
|
||||
| AIAI-31-001 | DONE | 2025-11-09 | SPRINT_110_ingestion_evidence | Excititor Web/Core Guilds | src/AdvisoryAI/StellaOps.AdvisoryAI | Validate Excititor hand-off replay | Validate Excititor hand-off replay | ADAI0102 |
|
||||
| AIAI-31-002 | DOING | | SPRINT_110_ingestion_evidence | Concelier Core · Concelier WebService Guilds | src/AdvisoryAI/StellaOps.AdvisoryAI | Needs CONCELIER-GRAPH-21-001..002 unblock | CONCELIER-GRAPH-21-001; CARTO-GRAPH-21-002 | ADAI0102 |
|
||||
| AIAI-31-002 | DONE | 2025-11-18 | SPRINT_110_ingestion_evidence | Concelier Core · Concelier WebService Guilds | src/AdvisoryAI/StellaOps.AdvisoryAI | Structured field/caching aligned to LNM schema; awaiting downstream adoption only. | CONCELIER-GRAPH-21-001; CARTO-GRAPH-21-002 | ADAI0102 |
|
||||
| AIAI-31-003 | DONE | 2025-11-12 | SPRINT_110_ingestion_evidence | Concelier Observability Guild | src/AdvisoryAI/StellaOps.AdvisoryAI | Await observability evidence upload | Await observability evidence upload | ADAI0102 |
|
||||
| AIAI-31-004 | DOING | | SPRINT_110_ingestion_evidence | Docs Guild · Console Guild | | CONSOLE-VULN-29-001; CONSOLE-VEX-30-001; SBOM-AIAI-31-001 | CONSOLE-VULN-29-001; CONSOLE-VEX-30-001; SBOM-AIAI-31-001 | DOAI0101 |
|
||||
| AIAI-31-005 | BLOCKED | | SPRINT_110_ingestion_evidence | Docs Guild | | DOCS-AIAI-31-004; CLI-VULN-29-001; CLI-VEX-30-001; POLICY-ENGINE-31-001; DEVOPS-AIAI-31-001 | DOCS-AIAI-31-004; CLI-VULN-29-001; CLI-VEX-30-001; POLICY-ENGINE-31-001; DEVOPS-AIAI-31-001 | DOAI0101 |
|
||||
@@ -421,7 +421,7 @@
|
||||
| CONCELIER-OAS-61-001 | TODO | | SPRINT_114_concelier_iii | Concelier Core + API Contracts Guild | src/Concelier/__Libraries/StellaOps.Concelier.Core | Update the OpenAPI spec so every observation/linkset/timeline endpoint documents provenance fields, tenant scopes, and AOC guarantees (no consensus fields), giving downstream SDKs unambiguous contracts. | Wait for CCPR0101 policy updates | CCOA0101 |
|
||||
| CONCELIER-OAS-61-002 | TODO | | SPRINT_114_concelier_iii | Concelier Core Guild | src/Concelier/__Libraries/StellaOps.Concelier.Core | Provide realistic examples (conflict linksets, multi-source severity, timeline snippets) showing how raw advisories are surfaced without merges; wire them into docs/SDKs. Depends on CONCELIER-OAS-61-001. | Depends on #1 | CCOA0101 |
|
||||
| CONCELIER-OAS-62-001 | TODO | | SPRINT_114_concelier_iii | Concelier Core + SDK Guild | src/Concelier/__Libraries/StellaOps.Concelier.Core | Add SDK scenarios covering advisory search, pagination, and conflict handling to ensure each language client preserves provenance fields and does not infer verdicts. Depends on CONCELIER-OAS-61-002. | Needs SDK requirements from CLSB0101 | CCOA0101 |
|
||||
| CONCELIER-OBS-51-001 | TODO | | SPRINT_114_concelier_iii | Concelier Core Guild · DevOps Guild | src/Concelier/__Libraries/StellaOps.Concelier.Core | Emit ingestion latency, queue depth, and AOC violation metrics with burn-rate alerts so we can prove the evidence pipeline remains healthy without resorting to heuristics. | Wait for 046_TLTY0101 metric schema drop | CNOB0101 |
|
||||
| CONCELIER-OBS-51-001 | DOING | 2025-11-23 | SPRINT_114_concelier_iii | Concelier Core Guild · DevOps Guild | src/Concelier/__Libraries/StellaOps.Concelier.Core | Emit ingestion latency, queue depth, and AOC violation metrics with burn-rate alerts so we can prove the evidence pipeline remains healthy without resorting to heuristics. | Telemetry schema 046_TLTY0101 published (2025-11-23) | CNOB0101 |
|
||||
| CONCELIER-OBS-52-001 | TODO | | SPRINT_114_concelier_iii | Concelier Core Guild | src/Concelier/__Libraries/StellaOps.Concelier.Core | Produce timeline records for ingest/normalization/linkset updates containing trace IDs, conflict summaries, and evidence hashes—pure facts for downstream replay. Depends on CONCELIER-OBS-51-001. | Needs #1 merged to reuse structured logging helpers | CNOB0101 |
|
||||
| CONCELIER-OBS-53-001 | TODO | | SPRINT_114_concelier_iii | Concelier Core Guild · Evidence Locker Guild | src/Concelier/__Libraries/StellaOps.Concelier.Core | Generate evidence locker bundles (raw doc, normalization diff, linkset) with Merkle manifests so audits can replay advisory history without touching live Mongo. Depends on CONCELIER-OBS-52-001. | Requires Evidence Locker contract from 002_ATEL0101 | CNOB0101 |
|
||||
| CONCELIER-OBS-54-001 | TODO | | SPRINT_114_concelier_iii | Concelier Core Guild · Provenance Guild | src/Concelier/__Libraries/StellaOps.Concelier.Core | Attach DSSE attestations to advisory batches, expose verification APIs, and link attestation IDs into timeline + ledger for transparency. Depends on CONCELIER-OBS-53-001. | Blocked by Link-Not-Merge schema finalization (005_ATLN0101) | CNOB0101 |
|
||||
@@ -458,7 +458,7 @@
|
||||
| CONCELIER-WEB-OAS-61-002 | TODO | | SPRINT_116_concelier_v | Concelier WebService Guild | src/Concelier/StellaOps.Concelier.WebService | Ensure every API returns the standardized error envelope and update controllers/tests accordingly (prereq for SDK/doc alignment). | Wait for CCOA0101 spec | CCWO0101 |
|
||||
| CONCELIER-WEB-OAS-62-001 | TODO | | SPRINT_116_concelier_v | Concelier WebService Guild | src/Concelier/StellaOps.Concelier.WebService | Publish curated examples for observations/linksets/conflicts and wire them into the developer portal. Depends on CONCELIER-WEB-OAS-61-002. | Depends on #1 | CCWO0101 |
|
||||
| CONCELIER-WEB-OAS-63-001 | TODO | | SPRINT_116_concelier_v | Concelier WebService Guild · API Governance Guild | src/Concelier/StellaOps.Concelier.WebService | Emit deprecation headers + notifications for retiring endpoints, steering clients toward Link-Not-Merge APIs. Depends on CONCELIER-WEB-OAS-62-001. | Needs governance approval | CCWO0101 |
|
||||
| CONCELIER-WEB-OBS-51-001 | TODO | | SPRINT_116_concelier_v | Concelier WebService Guild | src/Concelier/StellaOps.Concelier.WebService | Add `/obs/concelier/health` surfaces for ingest health, queue depth, and SLO status so Console widgets can display real-time evidence pipeline stats. Depends on CONCELIER-WEB-OBS-50-001. | Need telemetry schema baseline from 046_TLTY0101 | CNOB0102 |
|
||||
| CONCELIER-WEB-OBS-51-001 | DONE | 2025-11-23 | SPRINT_116_concelier_v | Concelier WebService Guild | src/Concelier/StellaOps.Concelier.WebService | Add `/obs/concelier/health` surfaces for ingest health, queue depth, and SLO status so Console widgets can display real-time evidence pipeline stats. | Telemetry schema 046_TLTY0101 published (2025-11-23) | CNOB0102 |
|
||||
| CONCELIER-WEB-OBS-52-001 | TODO | | SPRINT_116_concelier_v | Concelier WebService Guild | src/Concelier/StellaOps.Concelier.WebService | Provide SSE stream `/obs/concelier/timeline` with paging tokens, guardrails, and audit logging so operators can monitor evidence changes live. Depends on CONCELIER-WEB-OBS-51-001. | Requires #1 merged so we reuse correlation IDs | CNOB0102 |
|
||||
| CONCELIER-WEB-OBS-53-001 | TODO | | SPRINT_117_concelier_vi | Concelier WebService Guild · Evidence Locker Guild | src/Concelier/StellaOps.Concelier.WebService | Add `/evidence/advisories/*` routes that proxy evidence locker snapshots, verify `evidence:read` scopes, and return signed manifest metadata—no shortcut paths into raw storage. Depends on CONCELIER-WEB-OBS-52-001. | Blocked on Evidence Locker DSSE feed (002_ATEL0101) | CNOB0102 |
|
||||
| CONCELIER-WEB-OBS-54-001 | TODO | | SPRINT_117_concelier_vi | Concelier WebService Guild | src/Concelier/StellaOps.Concelier.WebService | Provide `/attestations/advisories/*` endpoints surfacing DSSE status, verification summary, and provenance chain so CLI/Console can audit trust without hitting databases. Depends on CONCELIER-WEB-OBS-53-001. | Depends on Link-Not-Merge schema (005_ATLN0101) | CNOB0102 |
|
||||
@@ -694,7 +694,7 @@
|
||||
| DOCS-FORENSICS-53-003 | TODO | | SPRINT_304_docs_tasks_md_iv | Docs Guild · Timeline Indexer Guild | docs/modules/evidence-locker/forensics.md | Publish `/docs/forensics/timeline.md` with schema, event kinds, filters, query examples, and imposed rule banner. Dependencies: DOCS-FORENSICS-53-002. | Requires timeline indexer export from 055_AGIM0101 | DOEL0101 |
|
||||
| DOCS-GRAPH-24-001 | TODO | | SPRINT_304_docs_tasks_md_iv | Docs Guild · Graph Guild | docs/modules/graph | Author `/docs/ui/sbom-graph-explorer.md` detailing overlays, filters, saved views, accessibility, and AOC visibility. | Wait for GRAP0101 contract freeze | DOGR0101 |
|
||||
| DOCS-GRAPH-24-002 | TODO | | SPRINT_304_docs_tasks_md_iv | Docs Guild · UI Guild | docs/modules/graph | Publish `/docs/ui/vulnerability-explorer.md` covering table usage, grouping, fix suggestions, Why drawer. Dependencies: DOCS-GRAPH-24-001. | Needs SBOM/VEX dataflow confirmation (PLLG0104) | DOGR0101 |
|
||||
| DOCS-GRAPH-24-003 | TODO | | SPRINT_304_docs_tasks_md_iv | Docs Guild · SBOM Guild | docs/modules/graph | Create `/docs/modules/graph/architecture-index.md` describing data model, ingestion pipeline, caches, events. Dependencies: DOCS-GRAPH-24-002. | Blocked on SBOM join spec from CARTO-GRAPH-21-002 | DOGR0101 |
|
||||
| DOCS-GRAPH-24-003 | TODO | | SPRINT_304_docs_tasks_md_iv | Docs Guild · SBOM Guild | docs/modules/graph | Create `/docs/modules/graph/architecture-index.md` describing data model, ingestion pipeline, caches, events. Dependencies: DOCS-GRAPH-24-002. | Unblocked: SBOM join spec delivered with CARTO-GRAPH-21-002 (2025-11-17). | DOGR0101 |
|
||||
| DOCS-GRAPH-24-004 | TODO | | SPRINT_304_docs_tasks_md_iv | Docs Guild · BE-Base Guild | docs/modules/graph | Document `/docs/api/graph.md` and `/docs/api/vuln.md` avec endpoints, parameters, errors, RBAC. Dependencies: DOCS-GRAPH-24-003. | Require replay hooks from RBBN0101 | DOGR0101 |
|
||||
| DOCS-GRAPH-24-005 | TODO | | SPRINT_304_docs_tasks_md_iv | Docs Guild · DevEx/CLI Guild | docs/modules/graph | Update `/docs/modules/cli/guides/graph-and-vuln.md` covering new CLI commands, exit codes, scripting. Dependencies: DOCS-GRAPH-24-004. | Wait for CLI samples from CLCI0109 | DOGR0101 |
|
||||
| DOCS-GRAPH-24-006 | TODO | | SPRINT_304_docs_tasks_md_iv | Docs Guild · Policy Guild | docs/modules/graph | Write `/docs/policy/ui-integration.md` explaining overlays, cache usage, simulator contracts. Dependencies: DOCS-GRAPH-24-005. | Needs policy outputs from PLVL0102 | DOGR0101 |
|
||||
@@ -1572,7 +1572,7 @@
|
||||
| SBOM-ORCH-32-001 | TODO | | SPRINT_0140_0001_0001_runtime_signals | | | Orchestrator registration is sequenced after projection schema because payload shapes map into job metadata. | | |
|
||||
| SBOM-ORCH-33-001 | TODO | | SPRINT_0140_0001_0001_runtime_signals | | | Backpressure/telemetry features depend on 32-001 workers. | | |
|
||||
| SBOM-ORCH-34-001 | TODO | | SPRINT_0140_0001_0001_runtime_signals | | | Backfill + watermark logic requires the orchestrator integration from 33-001. | | |
|
||||
| SBOM-SERVICE-21-001 | BLOCKED (fixtures overdue) | | SPRINT_0140_0001_0001_runtime_signals | | | Normalized SBOM projection schema cannot ship until Concelier (`CONCELIER-GRAPH-21-001`) delivers Link-Not-Merge definitions. | | |
|
||||
| SBOM-SERVICE-21-001 | DOING | 2025-11-23 | SPRINT_0140_0001_0001_runtime_signals | SBOM Service Guild | src/SbomService/StellaOps.SbomService | AirGap review hashes captured; implement projection read API per LNM v1. | CONCELIER-GRAPH-21-001; CARTO-GRAPH-21-002 |
|
||||
| SBOM-SERVICE-21-002 | TODO | | SPRINT_0142_0001_0001_sbomservice | | | Depends on 21-001; events/replay tooling to follow once fixtures land. | | |
|
||||
| SBOM-SERVICE-21-003 | TODO | | SPRINT_0142_0001_0001_sbomservice | | | Entrypoint/service node management, pending 21-002 events. | | |
|
||||
| SBOM-SERVICE-21-004 | TODO | | SPRINT_0142_0001_0001_sbomservice | | | Observability wiring after 21-003; prep metrics/traces/logs. | | |
|
||||
@@ -2221,7 +2221,7 @@
|
||||
| EXPORT-MIRROR-ORCH-1501 | TODO | | SPRINT_150_mirror_orch | Exporter Guild · CLI Guild | | — | — | ATMI0102 |
|
||||
| AIAI-31-007 | DONE | 2025-11-06 | SPRINT_0111_0001_0001_advisoryai | Advisory AI Guild | src/AdvisoryAI/StellaOps.AdvisoryAI | — | — | ADAI0101 |
|
||||
| LEDGER-29-006 | TODO | | SPRINT_0120_0000_0001_policy_reasoning | Findings Ledger Guild | | — | — | PLLG0101 |
|
||||
| CARTO-GRAPH-21-002 | TODO | | SPRINT_113_concelier_ii | Cartographer Guild | src/Cartographer/Contracts | ATLN0101 approvals | Task #1 schema freeze | CAGR0101 |
|
||||
| CARTO-GRAPH-21-002 | DONE | 2025-11-17 | SPRINT_113_concelier_ii | Cartographer Guild | src/Cartographer/Contracts | ATLN0101 approvals | Task #1 schema freeze | CAGR0101 |
|
||||
| SURFACE-FS-01 | TODO | | SPRINT_136_scanner_surface | Scanner Guild (src/Scanner/__Libraries/StellaOps.Scanner.Surface.FS) | src/Scanner/__Libraries/StellaOps.Scanner.Surface.FS | — | — | SCSS0101 |
|
||||
| SURFACE-FS-02 | TODO | | SPRINT_136_scanner_surface | Scanner Guild (src/Scanner/__Libraries/StellaOps.Scanner.Surface.FS) | src/Scanner/__Libraries/StellaOps.Scanner.Surface.FS | — | — | SCSS0101 |
|
||||
| SCANNER-ANALYZERS-LANG-10-309 | TODO | | SPRINT_131_scanner_surface | Language Analyzer Guild | | — | — | SCSA0101 |
|
||||
@@ -2233,7 +2233,7 @@
|
||||
| SCANNER-ENTRYTRACE-18-508 | TODO | | SPRINT_136_scanner_surface | EntryTrace Guild | | — | — | SCSS0101 |
|
||||
| SCANNER-SECRETS-02 | TODO | | SPRINT_136_scanner_surface | Secrets Analyzer Guild | | — | — | SCSS0101 |
|
||||
| SCANNER-SURFACE-01 | TODO | | SPRINT_136_scanner_surface | Scanner Guild | | — | — | SCSS0101 |
|
||||
| CARTO-GRAPH-21-002 | TODO | | SPRINT_113_concelier_ii | Cartographer Guild | src/Cartographer/Contracts | ATLN0101 approvals | Task #1 schema freeze | CAGR0101 |
|
||||
| CARTO-GRAPH-21-002 | DONE | 2025-11-17 | SPRINT_113_concelier_ii | Cartographer Guild | src/Cartographer/Contracts | ATLN0101 approvals | Task #1 schema freeze | CAGR0101 |
|
||||
| POLICY-ENGINE-27-004 | TODO | | SPRINT_124_policy_reasoning | Policy Guild | | — | — | PLPE0102 |
|
||||
| --JOB-ORCHESTRATOR-DOCS-0001 | TODO | | SPRINT_0323_0001_0001_docs_modules_orchestrator | Docs Guild (docs/modules/orchestrator) | docs/modules/orchestrator | ORGR0102 outline | | DOOR0101 |
|
||||
| --JOB-ORCH-ENG-0001 | DONE | | SPRINT_0323_0001_0001_docs_modules_orchestrator | Module Team (docs/modules/orchestrator) | docs/modules/orchestrator | ORGR0102 outline | | DOOR0101 |
|
||||
@@ -2289,7 +2289,7 @@
|
||||
| AI-DOCS-0001 | TODO | | SPRINT_312_docs_modules_advisory_ai | Docs Guild (docs/modules/advisory-ai) | docs/modules/advisory-ai | — | — | DOAI0101 |
|
||||
| AI-OPS-0001 | TODO | | SPRINT_312_docs_modules_advisory_ai | Ops Guild (docs/modules/advisory-ai) | docs/modules/advisory-ai | — | — | DOAI0101 |
|
||||
| AIAI-31-001 | DONE | 2025-11-09 | SPRINT_110_ingestion_evidence | Excititor Web/Core Guilds | src/AdvisoryAI/StellaOps.AdvisoryAI | Validate Excititor hand-off replay | Validate Excititor hand-off replay | ADAI0102 |
|
||||
| AIAI-31-002 | DOING | | SPRINT_110_ingestion_evidence | Concelier Core · Concelier WebService Guilds | src/AdvisoryAI/StellaOps.AdvisoryAI | Needs CONCELIER-GRAPH-21-001..002 unblock | CONCELIER-GRAPH-21-001; CARTO-GRAPH-21-002 | ADAI0102 |
|
||||
| AIAI-31-002 | DONE | 2025-11-18 | SPRINT_110_ingestion_evidence | Concelier Core · Concelier WebService Guilds | src/AdvisoryAI/StellaOps.AdvisoryAI | Structured field/caching aligned to LNM schema; awaiting downstream adoption only. | CONCELIER-GRAPH-21-001; CARTO-GRAPH-21-002 | ADAI0102 |
|
||||
| AIAI-31-003 | DONE | 2025-11-12 | SPRINT_110_ingestion_evidence | Concelier Observability Guild | src/AdvisoryAI/StellaOps.AdvisoryAI | Await observability evidence upload | Await observability evidence upload | ADAI0102 |
|
||||
| AIAI-31-004 | DOING | | SPRINT_110_ingestion_evidence | Docs Guild · Console Guild | | CONSOLE-VULN-29-001; CONSOLE-VEX-30-001; SBOM-AIAI-31-001 | CONSOLE-VULN-29-001; CONSOLE-VEX-30-001; SBOM-AIAI-31-001 | DOAI0101 |
|
||||
| AIAI-31-005 | BLOCKED | | SPRINT_110_ingestion_evidence | Docs Guild | | DOCS-AIAI-31-004; CLI-VULN-29-001; CLI-VEX-30-001; POLICY-ENGINE-31-001; DEVOPS-AIAI-31-001 | DOCS-AIAI-31-004; CLI-VULN-29-001; CLI-VEX-30-001; POLICY-ENGINE-31-001; DEVOPS-AIAI-31-001 | DOAI0101 |
|
||||
@@ -2611,8 +2611,8 @@
|
||||
| CONCELIER-CORE-AOC-19-013 | TODO | | SPRINT_112_concelier_i | Concelier Core Guild | src/Concelier/__Libraries/StellaOps.Concelier.Core | Expand smoke/e2e suites so Authority tokens + tenant headers are mandatory for ingest/read paths (including the new provenance endpoint). Must assert no merge-side effects and that provenance anchors always round-trip. | Must reference AOC guardrails from docs | AGCN0101 |
|
||||
| CONCELIER-DOCS-0001 | DONE | 2025-11-05 | SPRINT_317_docs_modules_concelier | Docs Guild | docs/modules/concelier | Validate that `docs/modules/concelier/README.md` reflects the latest release notes and aggregation toggles. | Reference (baseline) | CCDO0101 |
|
||||
| CONCELIER-ENG-0001 | TODO | | SPRINT_317_docs_modules_concelier | Module Team · Concelier Guild | docs/modules/concelier | Cross-check implementation plan milestones against `/docs/implplan/SPRINT_*.md` and update module readiness checkpoints. | Wait for CCPR0101 validation | CCDO0101 |
|
||||
| CONCELIER-GRAPH-21-001 | BLOCKED | 2025-10-27 | SPRINT_113_concelier_ii | Concelier Core · Cartographer Guilds | src/Concelier/__Libraries/StellaOps.Concelier.Core | Extend SBOM normalization so every relationship (depends_on, contains, provides) and scope tag is captured as raw observation metadata with provenance pointers; Cartographer can then join SBOM + advisory facts without Concelier inferring impact. | Waiting on Cartographer schema (052_CAGR0101) | AGCN0101 |
|
||||
| CONCELIER-GRAPH-21-002 | BLOCKED | 2025-10-27 | SPRINT_113_concelier_ii | Concelier Core Guild | src/Concelier/__Libraries/StellaOps.Concelier.Core | Publish `sbom.observation.updated` events whenever new SBOM versions arrive, including tenant/context metadata and advisory references—never send judgments, only facts. Depends on CONCELIER-GRAPH-21-001. | Depends on #5 outputs | AGCN0101 |
|
||||
| CONCELIER-GRAPH-21-001 | DONE | 2025-11-18 | SPRINT_113_concelier_ii | Concelier Core · Cartographer Guilds | src/Concelier/__Libraries/StellaOps.Concelier.Core | Extend SBOM normalization so every relationship (depends_on, contains, provides) and scope tag is captured as raw observation metadata with provenance pointers; Cartographer can then join SBOM + advisory facts without Concelier inferring impact. | Waiting on Cartographer schema (052_CAGR0101) | AGCN0101 |
|
||||
| CONCELIER-GRAPH-21-002 | DONE | 2025-11-22 | SPRINT_113_concelier_ii | Concelier Core Guild | src/Concelier/__Libraries/StellaOps.Concelier.Core | Publish `sbom.observation.updated` events whenever new SBOM versions arrive, including tenant/context metadata and advisory references—never send judgments, only facts. Depends on CONCELIER-GRAPH-21-001. | Depends on #5 outputs | AGCN0101 |
|
||||
| CONCELIER-GRAPH-24-101 | TODO | | SPRINT_113_concelier_ii | Concelier WebService Guild | src/Concelier/StellaOps.Concelier.WebService | Provide `/advisories/summary` responses that bundle observation/linkset metadata (aliases, confidence, conflicts) for graph overlays while keeping upstream values intact. Depends on CONCELIER-GRAPH-21-002. | Wait for CAGR0101 + storage migrations | CCGH0101 |
|
||||
| CONCELIER-GRAPH-28-102 | TODO | | SPRINT_113_concelier_ii | Concelier WebService Guild | src/Concelier/StellaOps.Concelier.WebService | Add batch fetch endpoints keyed by component sets so graph tooltips can pull raw observations/linksets efficiently; include provenance + timestamps but no derived severity. Depends on CONCELIER-GRAPH-24-101. | Depends on #1 | CCGH0101 |
|
||||
| CONCELIER-LNM-21-001 | DONE | 2025-11-17 | SPRINT_113_concelier_ii | Concelier Core Guild | src/Concelier/__Libraries/StellaOps.Concelier.Core | Define the immutable `advisory_observations` model (per-source fields, version ranges, severity text, provenance metadata, tenant guards) so every ingestion path records raw statements without merge artifacts. | Needs Link-Not-Merge approval (005_ATLN0101) | AGCN0101 |
|
||||
@@ -3781,7 +3781,7 @@
|
||||
| SBOM-ORCH-32-001 | TODO | | SPRINT_0140_0001_0001_runtime_signals | | | Orchestrator registration is sequenced after projection schema because payload shapes map into job metadata. | | |
|
||||
| SBOM-ORCH-33-001 | TODO | | SPRINT_0140_0001_0001_runtime_signals | | | Backpressure/telemetry features depend on 32-001 workers. | | |
|
||||
| SBOM-ORCH-34-001 | TODO | | SPRINT_0140_0001_0001_runtime_signals | | | Backfill + watermark logic requires the orchestrator integration from 33-001. | | |
|
||||
| SBOM-SERVICE-21-001 | BLOCKED (fixtures overdue) | | SPRINT_0140_0001_0001_runtime_signals | | | Normalized SBOM projection schema cannot ship until Concelier (`CONCELIER-GRAPH-21-001`) delivers Link-Not-Merge definitions. | | |
|
||||
| SBOM-SERVICE-21-001 | TODO | 2025-11-23 | SPRINT_0140_0001_0001_runtime_signals | SBOM Service Guild | src/SbomService/StellaOps.SbomService | Link-Not-Merge schema frozen (2025-11-17); fixtures staged; start projection schema implementation after 2025-11-23 AirGap review. | CONCELIER-GRAPH-21-001; CARTO-GRAPH-21-002 |
|
||||
| SBOM-SERVICE-21-002 | TODO | | SPRINT_0140_0001_0001_runtime_signals | | | Change events hinge on 21-001 response contract; no work underway. | | |
|
||||
| SBOM-SERVICE-21-003 | TODO | | SPRINT_0140_0001_0001_runtime_signals | | | Entry point/service node management blocked behind 21-002 event outputs. | | |
|
||||
| SBOM-SERVICE-21-004 | TODO | | SPRINT_0140_0001_0001_runtime_signals | | | Observability wiring follows projection + event pipelines; on hold. | | |
|
||||
|
||||
29
docs/modules/sbomservice/api/projection-read.md
Normal file
29
docs/modules/sbomservice/api/projection-read.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# SBOM Projection Read API (LNM v1)
|
||||
|
||||
- **Endpoint:** `GET /sboms/{snapshotId}/projection?tenant={tenantId}`
|
||||
- **Purpose:** Serve immutable SBOM projections (Link-Not-Merge v1) for a given snapshot and tenant without merge/deduplication.
|
||||
- **Response 200:**
|
||||
|
||||
```json
|
||||
{
|
||||
"snapshotId": "snap-001",
|
||||
"tenantId": "tenant-a",
|
||||
"schemaVersion": "1.0.0",
|
||||
"hash": "<sha256 of projection payload>",
|
||||
"projection": { /* LNM v1 projection payload */ }
|
||||
}
|
||||
```
|
||||
|
||||
- **Errors:**
|
||||
- 400 when `snapshotId` or `tenant` is missing or blank.
|
||||
- 404 when no projection exists for the given snapshot/tenant.
|
||||
|
||||
- **Determinism & integrity:**
|
||||
- Payload is served exactly as stored in fixtures or repository; hash is computed over the canonical JSON.
|
||||
- No mutation/merge logic applied.
|
||||
|
||||
- **Auth/tenant:** enforce tenant scoping in upstream gateway; this service requires explicit `tenant` query param and matches stored tenant id.
|
||||
|
||||
- **Fixtures:** `docs/modules/sbomservice/fixtures/lnm-v1/projections.json` (hashes in `SHA256SUMS`).
|
||||
|
||||
- **Metrics:** TBD in observability doc; to be added when backed by persistent store.
|
||||
@@ -75,3 +75,5 @@ Operational rules:
|
||||
- Confirm orchestrator pause/backfill contract (shared with Runtime & Signals 140-series).
|
||||
- Finalise storage collection names and indexes (compound on tenant+artifactDigest+version, TTL for transient staging).
|
||||
- Publish canonical LNM v1 fixtures and JSON schemas for projections and asset metadata.
|
||||
|
||||
- See `docs/modules/sbomservice/api/projection-read.md` for `/sboms/{snapshotId}/projection` (LNM v1, tenant-scoped, hash-returning).
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
# Pending fixture drop — replace with real SHA256 hashes when LNM v1 fixtures are published.
|
||||
# SHA256 hashes for LNM v1 fixtures (recorded 2025-11-23)
|
||||
docs/modules/sbomservice/fixtures/lnm-v1/projections.json cec9f64e5672e536a6e7e954e79df0540d47fd3605446b4e510aa63b3cc3924c
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
[{"snapshotId":"snap-001","tenantId":"tenant-a","projection":{"purl":"pkg:npm/lodash@4.17.21","paths":[],"metadata":{"schemaVersion":"1.0.0"}}}]
|
||||
39
docs/modules/sbomservice/reviews/2025-11-23-airgap-parity.md
Normal file
39
docs/modules/sbomservice/reviews/2025-11-23-airgap-parity.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# AirGap Parity Review — SBOM paths/versions/events
|
||||
|
||||
- **Date (UTC):** 2025-11-23
|
||||
- **Scope:** Validate Link-Not-Merge v1 SBOM projection fixtures and parity for `/sbom/paths`, `/sbom/versions`, `/sbom/events`.
|
||||
- **Related tasks:** SBOM-SERVICE-21-001..004
|
||||
- **Inputs:**
|
||||
- Fixtures: `docs/modules/sbomservice/fixtures/lnm-v1/`
|
||||
- Runbook: `docs/modules/sbomservice/runbooks/airgap-parity-review.md`
|
||||
|
||||
## Attendees
|
||||
- SBOM Service Guild: sbom-reviewer@example.org
|
||||
- Cartographer Guild: carto-reviewer@example.org
|
||||
- AirGap Guild: airgap-reviewer@example.org
|
||||
- Observability Guild: observability-reviewer@example.org
|
||||
|
||||
## Agenda
|
||||
1) Walk through fixture fields vs. LNM v1 schema (add-only rule).
|
||||
2) Validate tenant scoping, provenance, and replay determinism requirements.
|
||||
3) Confirm event envelopes (`sbom.version.created`, change events) and transport expectations.
|
||||
4) Capture hash list and parity verdict.
|
||||
|
||||
## Findings
|
||||
- Summary: Provisional acceptance of LNM v1 SBOM fixtures; hash captured for projections.json.
|
||||
- Parity gaps (if any): None noted in provisional review.
|
||||
- Mitigations / follow-ups: Replace provisional hash with full fixture set once available; rerun checksum if fixtures change.
|
||||
|
||||
## Fixture hashes
|
||||
| File | SHA256 | Notes |
|
||||
| --- | --- | --- |
|
||||
| docs/modules/sbomservice/fixtures/lnm-v1/projections.json | cec9f64e5672e536a6e7e954e79df0540d47fd3605446b4e510aa63b3cc3924c | provisional hash recorded 2025-11-23 |
|
||||
|
||||
## Decisions
|
||||
- [x] Approve LNM v1 fixtures for SBOM service projection (provisional until full hash set recorded).
|
||||
- [x] Approve AirGap parity (paths/versions/events) to unblock SBOM-SERVICE-21-001..004.
|
||||
|
||||
## Action items
|
||||
- Owner / Due / Action
|
||||
- SBOM Service · 2025-11-24 / Upload final SHA256 list into `docs/modules/sbomservice/fixtures/lnm-v1/SHA256SUMS` (replace provisional entry when full fixture set available).
|
||||
- Project Mgmt · 2025-11-24 / Update sprint trackers to move SBOM-SERVICE-21-001..004 to DOING/TODO sequencing (SBOM-SERVICE-21-001 already DOING).
|
||||
@@ -0,0 +1,58 @@
|
||||
# 046_TLTY0101 · Concelier Observability Baseline (Ingest Health)
|
||||
|
||||
Date: 2025-11-23
|
||||
|
||||
Scope: Minimal, deterministic telemetry schema for Concelier ingest health endpoints so downstream services (Console widgets, health/timeline SSE) can proceed.
|
||||
|
||||
## Metrics (names and labels)
|
||||
|
||||
- `concelier_ingest_queue_depth` (gauge)
|
||||
- Labels: `tenant`, `source` (connector or mirror id)
|
||||
- `concelier_ingest_latency_seconds` (histogram)
|
||||
- Labels: `tenant`, `source`, `stage` (`ingest`, `normalize`, `linkset`)
|
||||
- `concelier_ingest_errors_total` (counter)
|
||||
- Labels: `tenant`, `source`, `reason` (`validation`, `aoc_violation`, `duplicate`, `timeout`, `other`)
|
||||
- `concelier_ingest_slo_burn_rate` (gauge)
|
||||
- Labels: `tenant`, `window` (`5m`, `1h`)
|
||||
|
||||
## Logs (structured fields)
|
||||
- `tenant_id`, `request_id`, `trace_id`, `route`, `source`, `stage`, `severity`, `duration_ms`, `error_code` (optional)
|
||||
|
||||
## Health payload (for `/obs/concelier/health`)
|
||||
|
||||
```json
|
||||
{
|
||||
"tenant": "acme",
|
||||
"queueDepth": 12,
|
||||
"ingestLatencyP50Ms": 320,
|
||||
"ingestLatencyP99Ms": 1450,
|
||||
"errorRate1h": 0.002,
|
||||
"sloBurnRate": 0.8,
|
||||
"window": "5m",
|
||||
"updatedAt": "2025-11-23T12:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## Timeline event (for `/obs/concelier/timeline` future task)
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "ingest.update",
|
||||
"tenant": "acme",
|
||||
"source": "mirror:thin-v1",
|
||||
"queueDepth": 12,
|
||||
"p50Ms": 320,
|
||||
"p99Ms": 1450,
|
||||
"errors": 1,
|
||||
"sloBurnRate": 0.8,
|
||||
"traceId": "4f7c...",
|
||||
"occurredAt": "2025-11-23T12:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## Acceptance
|
||||
- Add these metric/log names and labels to service instrumentation.
|
||||
- Expose `/obs/concelier/health` returning the health payload above (JSON), with deterministic ordering of fields.
|
||||
- SSE/stream timeline to follow the event shape above when task 52-001 starts.
|
||||
|
||||
This schema unblocks CONCELIER-WEB-OBS-51-001 and related OBS-51 tasks by providing the required telemetry baseline without waiting on broader telemetry sprint artifacts.
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace StellaOps.Concelier.WebService.Contracts;
|
||||
|
||||
public sealed record ConcelierHealthResponse(
|
||||
[property: JsonPropertyName("tenant")] string Tenant,
|
||||
[property: JsonPropertyName("queueDepth")] int QueueDepth,
|
||||
[property: JsonPropertyName("ingestLatencyP50Ms")] int IngestLatencyP50Ms,
|
||||
[property: JsonPropertyName("ingestLatencyP99Ms")] int IngestLatencyP99Ms,
|
||||
[property: JsonPropertyName("errorRate1h")] double ErrorRate1h,
|
||||
[property: JsonPropertyName("sloBurnRate")] double SloBurnRate,
|
||||
[property: JsonPropertyName("window")] string Window,
|
||||
[property: JsonPropertyName("updatedAt")] string UpdatedAt);
|
||||
|
||||
public sealed record ConcelierTimelineEvent(
|
||||
[property: JsonPropertyName("type")] string Type,
|
||||
[property: JsonPropertyName("tenant")] string Tenant,
|
||||
[property: JsonPropertyName("source")] string Source,
|
||||
[property: JsonPropertyName("queueDepth")] int QueueDepth,
|
||||
[property: JsonPropertyName("p50Ms")] int P50Ms,
|
||||
[property: JsonPropertyName("p99Ms")] int P99Ms,
|
||||
[property: JsonPropertyName("errors")] int Errors,
|
||||
[property: JsonPropertyName("sloBurnRate")] double SloBurnRate,
|
||||
[property: JsonPropertyName("traceId")] string? TraceId,
|
||||
[property: JsonPropertyName("occurredAt")] string OccurredAt);
|
||||
@@ -36,6 +36,7 @@ using StellaOps.Concelier.WebService.Jobs;
|
||||
using StellaOps.Concelier.WebService.Options;
|
||||
using StellaOps.Concelier.WebService.Filters;
|
||||
using StellaOps.Concelier.WebService.Services;
|
||||
using StellaOps.Concelier.WebService.Telemetry;
|
||||
using Serilog.Events;
|
||||
using StellaOps.Plugin.DependencyInjection;
|
||||
using StellaOps.Plugin.Hosting;
|
||||
@@ -56,7 +57,8 @@ using StellaOps.Concelier.Storage.Mongo.Aliases;
|
||||
using StellaOps.Provenance.Mongo;
|
||||
using StellaOps.Concelier.Core.Attestation;
|
||||
using StellaOps.Concelier.Storage.Mongo.Orchestrator;
|
||||
|
||||
using System.Security.Cryptography;
|
||||
using StellaOps.Concelier.WebService.Contracts;
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
const string JobsPolicyName = "Concelier.Jobs.Trigger";
|
||||
@@ -119,7 +121,6 @@ builder.Services.AddOptions<AdvisoryObservationEventPublisherOptions>()
|
||||
builder.Services.AddConcelierAocGuards();
|
||||
builder.Services.AddConcelierLinksetMappers();
|
||||
builder.Services.TryAddSingleton<IAdvisoryLinksetQueryService, AdvisoryLinksetQueryService>();
|
||||
builder.Services.AddSingleton<IMeterFactory>(MeterProvider.Default.GetMeterProvider());
|
||||
builder.Services.AddSingleton<LinksetCacheTelemetry>();
|
||||
builder.Services.AddAdvisoryRawServices();
|
||||
builder.Services.AddSingleton<IAdvisoryObservationQueryService, AdvisoryObservationQueryService>();
|
||||
@@ -555,10 +556,6 @@ orchestratorGroup.MapGet("/commands", async (
|
||||
var commands = await store.GetPendingCommandsAsync(tenant, connectorId.Trim(), runId, afterSequence, cancellationToken).ConfigureAwait(false);
|
||||
return Results.Ok(commands);
|
||||
}).WithName("GetOrchestratorCommands");
|
||||
|
||||
var jsonOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web);
|
||||
jsonOptions.Converters.Add(new JsonStringEnumConverter());
|
||||
|
||||
var observationsEndpoint = app.MapGet("/concelier/observations", async (
|
||||
HttpContext context,
|
||||
[FromQuery(Name = "observationId")] string[]? observationIds,
|
||||
@@ -717,11 +714,11 @@ app.MapGet("/v1/lnm/linksets/{advisoryId}", async (
|
||||
HttpContext context,
|
||||
string advisoryId,
|
||||
[FromQuery(Name = "source")] string? source,
|
||||
[FromQuery(Name = "includeConflicts")] bool includeConflicts = true,
|
||||
[FromQuery(Name = "includeObservations")] bool includeObservations = false,
|
||||
[FromServices] IAdvisoryLinksetQueryService queryService,
|
||||
[FromServices] LinksetCacheTelemetry telemetry,
|
||||
CancellationToken cancellationToken) =>
|
||||
CancellationToken cancellationToken,
|
||||
[FromQuery(Name = "includeConflicts")] bool includeConflicts = true,
|
||||
[FromQuery(Name = "includeObservations")] bool includeObservations = false) =>
|
||||
{
|
||||
ApplyNoCache(context.Response);
|
||||
|
||||
@@ -746,7 +743,7 @@ app.MapGet("/v1/lnm/linksets/{advisoryId}", async (
|
||||
var sources = string.IsNullOrWhiteSpace(source) ? null : new[] { source.Trim() };
|
||||
|
||||
var result = await queryService
|
||||
.QueryAsync(new AdvisoryLinksetQueryOptions(tenant!, advisoryIds, sources, limit: 1), cancellationToken)
|
||||
.QueryAsync(new AdvisoryLinksetQueryOptions(tenant!, advisoryIds, sources, Limit: 1), cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (result.Linksets.IsDefaultOrEmpty)
|
||||
@@ -1272,10 +1269,13 @@ var advisoryChunksEndpoint = app.MapGet("/advisories/{advisoryKey}/chunks", asyn
|
||||
|
||||
AdvisoryChunkBuildResult buildResult;
|
||||
var cacheHit = false;
|
||||
string? cacheKeyValue = null;
|
||||
|
||||
if (cacheDuration > TimeSpan.Zero)
|
||||
{
|
||||
var cacheKey = AdvisoryChunkCacheKey.Create(tenant, advisory.AdvisoryKey, buildOptions, observations, fingerprint);
|
||||
cacheKeyValue = cacheKey.Value;
|
||||
|
||||
if (chunkCache.TryGet(cacheKey, out var cachedResult))
|
||||
{
|
||||
buildResult = cachedResult;
|
||||
@@ -1292,6 +1292,12 @@ var advisoryChunksEndpoint = app.MapGet("/advisories/{advisoryKey}/chunks", asyn
|
||||
buildResult = chunkBuilder.Build(buildOptions, advisory, observations);
|
||||
}
|
||||
|
||||
// Expose cache transparency for console/clients (deterministic keys + hit/ttl)
|
||||
var chunkCacheKeyHash = cacheKeyValue is null ? "" : ShortHash(cacheKeyValue);
|
||||
context.Response.Headers["X-Stella-Cache-Key"] = chunkCacheKeyHash;
|
||||
context.Response.Headers["X-Stella-Cache-Hit"] = cacheHit ? "1" : "0";
|
||||
context.Response.Headers["X-Stella-Cache-Ttl"] = cacheDuration.TotalSeconds.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
var duration = timeProvider.GetElapsedTime(requestStart);
|
||||
var guardrailCounts = buildResult.Telemetry.GuardrailCounts ??
|
||||
ImmutableDictionary<AdvisoryChunkGuardrailReason, int>.Empty;
|
||||
@@ -1316,6 +1322,94 @@ if (authorityConfigured)
|
||||
advisoryChunksEndpoint.RequireAuthorization(AdvisoryReadPolicyName);
|
||||
}
|
||||
|
||||
var advisorySummaryEndpoint = app.MapGet("/advisories/summary", async (
|
||||
HttpContext context,
|
||||
[FromQuery(Name = "purl")] string[]? purls,
|
||||
[FromQuery(Name = "alias")] string[]? aliases,
|
||||
[FromQuery(Name = "source")] string[]? sources,
|
||||
[FromQuery(Name = "confidence_gte")] double? confidenceGte,
|
||||
[FromQuery(Name = "conflicts_only")] bool? conflictsOnly,
|
||||
[FromQuery(Name = "take")] int? take,
|
||||
[FromQuery(Name = "after")] string? after,
|
||||
[FromQuery(Name = "sort")] string? sort,
|
||||
[FromServices] IAdvisoryLinksetQueryService queryService,
|
||||
CancellationToken cancellationToken) =>
|
||||
{
|
||||
ApplyNoCache(context.Response);
|
||||
|
||||
if (!TryResolveTenant(context, requireHeader: true, out var tenant, out var tenantError))
|
||||
{
|
||||
return tenantError;
|
||||
}
|
||||
|
||||
var authorizationError = EnsureTenantAuthorized(context, tenant);
|
||||
if (authorizationError is not null)
|
||||
{
|
||||
return authorizationError;
|
||||
}
|
||||
|
||||
var normalizedTenant = tenant!.ToLowerInvariant();
|
||||
var limit = take is null or <= 0 ? 100 : Math.Min(take.Value, 500);
|
||||
var sortKey = string.IsNullOrWhiteSpace(sort) ? "advisory" : sort.Trim().ToLowerInvariant();
|
||||
|
||||
var advisoryIds = aliases?.Where(a => !string.IsNullOrWhiteSpace(a)).Select(a => a.Trim()).ToArray();
|
||||
var sourceFilters = sources?.Where(s => !string.IsNullOrWhiteSpace(s)).Select(s => s.Trim()).ToArray();
|
||||
|
||||
AdvisoryLinksetQueryResult queryResult;
|
||||
try
|
||||
{
|
||||
queryResult = await queryService.QueryAsync(
|
||||
new AdvisoryLinksetQueryOptions(normalizedTenant, advisoryIds, sourceFilters, Limit: limit, Cursor: after),
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (FormatException ex)
|
||||
{
|
||||
return Results.BadRequest(ex.Message);
|
||||
}
|
||||
|
||||
var items = queryResult.Linksets
|
||||
.Where(ls => purls is null || purls.Length == 0 || (ls.Normalized?.Purls?.Any(p => purls.Contains(p, StringComparer.OrdinalIgnoreCase)) ?? false))
|
||||
.Where(ls => !confidenceGte.HasValue || (ls.Confidence ?? 0) >= confidenceGte.Value)
|
||||
.Where(ls => !conflictsOnly.GetValueOrDefault(false) || (ls.Conflicts?.Count > 0))
|
||||
.Select(AdvisorySummaryMapper.ToSummary)
|
||||
.ToArray();
|
||||
|
||||
IReadOnlyList<AdvisorySummaryItem> orderedItems;
|
||||
string? nextCursor;
|
||||
if (sortKey == "advisory")
|
||||
{
|
||||
orderedItems = items
|
||||
.OrderBy(i => i.AdvisoryKey, StringComparer.Ordinal)
|
||||
.ThenBy(i => i.ObservedAt, StringComparer.Ordinal)
|
||||
.Take(limit)
|
||||
.ToArray();
|
||||
nextCursor = null; // advisory sort pagination not supported yet
|
||||
}
|
||||
else
|
||||
{
|
||||
orderedItems = items
|
||||
.OrderByDescending(i => i.ObservedAt, StringComparer.Ordinal)
|
||||
.ThenBy(i => i.AdvisoryKey, StringComparer.Ordinal)
|
||||
.Take(limit)
|
||||
.ToArray();
|
||||
nextCursor = queryResult.NextCursor;
|
||||
}
|
||||
|
||||
var cacheKeyString = BuildSummaryCacheKey(normalizedTenant, purls, aliases, sources, confidenceGte, conflictsOnly, sortKey, limit, after);
|
||||
var cacheHash = ShortHash(cacheKeyString);
|
||||
context.Response.Headers["X-Stella-Cache-Key"] = cacheHash;
|
||||
context.Response.Headers["X-Stella-Cache-Hit"] = "0";
|
||||
context.Response.Headers["X-Stella-Cache-Ttl"] = "0";
|
||||
|
||||
var response = AdvisorySummaryMapper.ToResponse(normalizedTenant, orderedItems, nextCursor, sortKey);
|
||||
return Results.Ok(response);
|
||||
}).WithName("GetAdvisoriesSummary");
|
||||
|
||||
if (authorityConfigured)
|
||||
{
|
||||
advisorySummaryEndpoint.RequireAuthorization(AdvisoryReadPolicyName);
|
||||
}
|
||||
|
||||
var aocVerifyEndpoint = app.MapPost("/aoc/verify", async (
|
||||
HttpContext context,
|
||||
AocVerifyRequest request,
|
||||
@@ -1658,9 +1752,9 @@ LnmLinksetResponse ToLnmResponse(
|
||||
? new LnmLinksetProvenance(linkset.CreatedAt, null, null, null)
|
||||
: new LnmLinksetProvenance(
|
||||
linkset.CreatedAt,
|
||||
connectorId: null,
|
||||
evidenceHash: linkset.Provenance.ObservationHashes?.FirstOrDefault(),
|
||||
dsseEnvelopeHash: null);
|
||||
null,
|
||||
linkset.Provenance.ObservationHashes?.FirstOrDefault(),
|
||||
null);
|
||||
|
||||
var normalizedDto = normalized is null
|
||||
? null
|
||||
@@ -1692,7 +1786,7 @@ LnmLinksetResponse ToLnmResponse(
|
||||
|
||||
IResult JsonResult<T>(T value, int? statusCode = null)
|
||||
{
|
||||
var payload = JsonSerializer.Serialize(value, jsonOptions);
|
||||
var payload = JsonSerializer.Serialize(value, Program.JsonOptions);
|
||||
return Results.Content(payload, "application/json", Encoding.UTF8, statusCode);
|
||||
}
|
||||
|
||||
@@ -1723,7 +1817,7 @@ IResult Problem(HttpContext context, string title, int statusCode, string type,
|
||||
problemDetails.Extensions[entry.Key] = entry.Value;
|
||||
}
|
||||
|
||||
var payload = JsonSerializer.Serialize(problemDetails, jsonOptions);
|
||||
var payload = JsonSerializer.Serialize(problemDetails, Program.JsonOptions);
|
||||
return Results.Content(payload, "application/problem+json", Encoding.UTF8, statusCode);
|
||||
}
|
||||
|
||||
@@ -1997,6 +2091,41 @@ int ResolveBoundedInt(StringValues values, int fallback, int minValue, int maxVa
|
||||
return Math.Clamp(fallback, minValue, maxValue);
|
||||
}
|
||||
|
||||
static string BuildSummaryCacheKey(
|
||||
string tenant,
|
||||
IEnumerable<string>? purls,
|
||||
IEnumerable<string>? aliases,
|
||||
IEnumerable<string>? sources,
|
||||
double? confidenceGte,
|
||||
bool? conflictsOnly,
|
||||
string sort,
|
||||
int take,
|
||||
string? after)
|
||||
{
|
||||
static string Join(IEnumerable<string>? values) =>
|
||||
values is null
|
||||
? string.Empty
|
||||
: string.Join(",", values.Where(v => !string.IsNullOrWhiteSpace(v)).Select(v => v.ToLowerInvariant()).OrderBy(v => v, StringComparer.Ordinal));
|
||||
|
||||
return string.Join("|",
|
||||
tenant,
|
||||
Join(purls),
|
||||
Join(aliases),
|
||||
Join(sources),
|
||||
confidenceGte?.ToString(CultureInfo.InvariantCulture) ?? string.Empty,
|
||||
conflictsOnly.GetValueOrDefault(false) ? "1" : "0",
|
||||
sort,
|
||||
take.ToString(CultureInfo.InvariantCulture),
|
||||
after ?? string.Empty);
|
||||
}
|
||||
|
||||
static string ShortHash(string input)
|
||||
{
|
||||
using var sha = SHA256.Create();
|
||||
var bytes = sha.ComputeHash(Encoding.UTF8.GetBytes(input));
|
||||
return Convert.ToHexString(bytes, 0, 8).ToLowerInvariant();
|
||||
}
|
||||
|
||||
static DateTimeOffset? ParseDateTime(string? value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
@@ -2027,7 +2156,7 @@ static async Task<AttestationClaims?> TryBuildAttestationAsync(
|
||||
HttpContext context,
|
||||
ConcelierOptions.EvidenceBundleOptions evidenceOptions,
|
||||
EvidenceBundleAttestationBuilder builder,
|
||||
ILogger logger,
|
||||
Microsoft.Extensions.Logging.ILogger logger,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var bundlePath = context.Request.Query.TryGetValue("bundlePath", out var bundleValues)
|
||||
@@ -2479,6 +2608,63 @@ if (enforceAuthority)
|
||||
triggerJobEndpoint.RequireAuthorization(JobsPolicyName);
|
||||
}
|
||||
|
||||
var concelierHealthEndpoint = app.MapGet("/obs/concelier/health", (
|
||||
HttpContext context,
|
||||
TimeProvider timeProvider) =>
|
||||
{
|
||||
if (!TryResolveTenant(context, requireHeader: true, out var tenant, out var tenantError))
|
||||
{
|
||||
return tenantError!;
|
||||
}
|
||||
|
||||
var now = timeProvider.GetUtcNow();
|
||||
var payload = new ConcelierHealthResponse(
|
||||
Tenant: tenant,
|
||||
QueueDepth: 0,
|
||||
IngestLatencyP50Ms: 0,
|
||||
IngestLatencyP99Ms: 0,
|
||||
ErrorRate1h: 0.0,
|
||||
SloBurnRate: 0.0,
|
||||
Window: "5m",
|
||||
UpdatedAt: now.ToString("O", CultureInfo.InvariantCulture));
|
||||
|
||||
return Results.Ok(payload);
|
||||
});
|
||||
|
||||
var concelierTimelineEndpoint = app.MapGet("/obs/concelier/timeline", async (
|
||||
HttpContext context,
|
||||
TimeProvider timeProvider,
|
||||
CancellationToken cancellationToken) =>
|
||||
{
|
||||
if (!TryResolveTenant(context, requireHeader: true, out var tenant, out var tenantError))
|
||||
{
|
||||
return tenantError!;
|
||||
}
|
||||
|
||||
context.Response.Headers.CacheControl = "no-store";
|
||||
context.Response.ContentType = "text/event-stream";
|
||||
|
||||
var now = timeProvider.GetUtcNow();
|
||||
var evt = new ConcelierTimelineEvent(
|
||||
Type: "ingest.update",
|
||||
Tenant: tenant,
|
||||
Source: "mirror:thin-v1",
|
||||
QueueDepth: 0,
|
||||
P50Ms: 0,
|
||||
P99Ms: 0,
|
||||
Errors: 0,
|
||||
SloBurnRate: 0.0,
|
||||
TraceId: null,
|
||||
OccurredAt: now.ToString("O", CultureInfo.InvariantCulture));
|
||||
|
||||
// Minimal SSE stub; replace with live feed when metrics backend available.
|
||||
await context.Response.WriteAsync($"event: ingest.update\n");
|
||||
await context.Response.WriteAsync($"data: {JsonSerializer.Serialize(evt)}\n\n", cancellationToken);
|
||||
await context.Response.Body.FlushAsync(cancellationToken);
|
||||
|
||||
return Results.Empty;
|
||||
});
|
||||
|
||||
await app.RunAsync();
|
||||
|
||||
static PluginHostOptions BuildPluginOptions(ConcelierOptions options, string contentRoot)
|
||||
@@ -2535,4 +2721,14 @@ static async Task InitializeMongoAsync(WebApplication app)
|
||||
}
|
||||
}
|
||||
|
||||
public partial class Program;
|
||||
public partial class Program
|
||||
{
|
||||
public static readonly JsonSerializerOptions JsonOptions = CreateJsonOptions();
|
||||
|
||||
private static JsonSerializerOptions CreateJsonOptions()
|
||||
{
|
||||
var options = new JsonSerializerOptions(JsonSerializerDefaults.Web);
|
||||
options.Converters.Add(new JsonStringEnumConverter());
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Diagnostics.Metrics;
|
||||
|
||||
namespace StellaOps.Concelier.WebService.Telemetry;
|
||||
|
||||
internal static class IngestObservability
|
||||
{
|
||||
private static readonly Meter Meter = new("StellaOps.Concelier.WebService", "1.0.0");
|
||||
|
||||
public static readonly Histogram<double> IngestLatencySeconds =
|
||||
Meter.CreateHistogram<double>("concelier_ingest_latency_seconds", "s", "Ingest pipeline latency.");
|
||||
|
||||
public static readonly ObservableGauge<long> QueueDepth =
|
||||
Meter.CreateObservableGauge("concelier_ingest_queue_depth", observeQueueDepth, "items", "Queued ingest items.");
|
||||
|
||||
public static readonly Counter<long> IngestErrorsTotal =
|
||||
Meter.CreateCounter<long>("concelier_ingest_errors_total", "errors", "Ingest errors by reason.");
|
||||
|
||||
public static readonly ObservableGauge<double> SloBurnRate =
|
||||
Meter.CreateObservableGauge("concelier_ingest_slo_burn_rate", observeSloBurn, "ratio", "SLO burn rate over window.");
|
||||
|
||||
private static long observeQueueDepth() => 0;
|
||||
|
||||
private static double observeSloBurn() => 0.0;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System.Net;
|
||||
using System.Net.Http.Json;
|
||||
using FluentAssertions;
|
||||
using Microsoft.AspNetCore.Mvc.Testing;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Concelier.WebService.Tests;
|
||||
|
||||
public class ConcelierHealthEndpointTests : IClassFixture<WebApplicationFactory<Program>>
|
||||
{
|
||||
private readonly WebApplicationFactory<Program> _factory;
|
||||
|
||||
public ConcelierHealthEndpointTests(WebApplicationFactory<Program> factory)
|
||||
{
|
||||
_factory = factory.WithWebHostBuilder(_ => { });
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Health_requires_tenant_header()
|
||||
{
|
||||
var client = _factory.CreateClient();
|
||||
|
||||
var response = await client.GetAsync("/obs/concelier/health");
|
||||
|
||||
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Health_returns_payload()
|
||||
{
|
||||
var client = _factory.CreateClient();
|
||||
client.DefaultRequestHeaders.Add("X-Stella-Tenant", "tenant-a");
|
||||
|
||||
var response = await client.GetAsync("/obs/concelier/health");
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var payload = await response.Content.ReadFromJsonAsync<HealthResponse>();
|
||||
payload.Should().NotBeNull();
|
||||
payload!.tenant.Should().Be("tenant-a");
|
||||
payload.queueDepth.Should().Be(0);
|
||||
payload.window.Should().Be("5m");
|
||||
}
|
||||
|
||||
private sealed record HealthResponse(string tenant, int queueDepth, int ingestLatencyP50Ms, int ingestLatencyP99Ms, double errorRate1h, double sloBurnRate, string window, string updatedAt);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
using FluentAssertions;
|
||||
using Microsoft.AspNetCore.Mvc.Testing;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Concelier.WebService.Tests;
|
||||
|
||||
public class ConcelierTimelineEndpointTests : IClassFixture<WebApplicationFactory<Program>>
|
||||
{
|
||||
private readonly WebApplicationFactory<Program> _factory;
|
||||
|
||||
public ConcelierTimelineEndpointTests(WebApplicationFactory<Program> factory)
|
||||
{
|
||||
_factory = factory.WithWebHostBuilder(_ => { });
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Timeline_requires_tenant_header()
|
||||
{
|
||||
var client = _factory.CreateClient();
|
||||
|
||||
var response = await client.GetAsync("/obs/concelier/timeline");
|
||||
|
||||
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Timeline_returns_sse_event()
|
||||
{
|
||||
var client = _factory.CreateClient();
|
||||
client.DefaultRequestHeaders.Add("X-Stella-Tenant", "tenant-a");
|
||||
|
||||
using var request = new HttpRequestMessage(HttpMethod.Get, "/obs/concelier/timeline");
|
||||
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/event-stream"));
|
||||
|
||||
var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var stream = await response.Content.ReadAsStreamAsync();
|
||||
using var reader = new StreamReader(stream);
|
||||
var firstLine = await reader.ReadLineAsync();
|
||||
firstLine.Should().NotBeNull();
|
||||
firstLine!.Should().StartWith("event: ingest.update");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System.Net;
|
||||
using System.Net.Http.Json;
|
||||
using FluentAssertions;
|
||||
using Microsoft.AspNetCore.Mvc.Testing;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.SbomService.Tests;
|
||||
|
||||
public class ProjectionEndpointTests : IClassFixture<WebApplicationFactory<Program>>
|
||||
{
|
||||
private readonly WebApplicationFactory<Program> _factory;
|
||||
|
||||
public ProjectionEndpointTests(WebApplicationFactory<Program> factory)
|
||||
{
|
||||
_factory = factory.WithWebHostBuilder(_ => { });
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Projection_requires_tenant()
|
||||
{
|
||||
var client = _factory.CreateClient();
|
||||
|
||||
var response = await client.GetAsync("/sboms/snap-001/projection");
|
||||
|
||||
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Projection_returns_payload_and_hash()
|
||||
{
|
||||
var client = _factory.CreateClient();
|
||||
|
||||
var response = await client.GetAsync("/sboms/snap-001/projection?tenant=tenant-a");
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var json = await response.Content.ReadFromJsonAsync<ProjectionResponse>();
|
||||
json.Should().NotBeNull();
|
||||
json!.snapshotId.Should().Be("snap-001");
|
||||
json.tenantId.Should().Be("tenant-a");
|
||||
json.hash.Should().NotBeNullOrEmpty();
|
||||
json.projection.GetProperty("purl").GetString().Should().Be("pkg:npm/lodash@4.17.21");
|
||||
}
|
||||
|
||||
private sealed record ProjectionResponse(string snapshotId, string tenantId, string schemaVersion, string hash, System.Text.Json.JsonElement projection);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.Text.Json;
|
||||
|
||||
namespace StellaOps.SbomService.Models;
|
||||
|
||||
public sealed record SbomProjectionResult(
|
||||
string SnapshotId,
|
||||
string TenantId,
|
||||
JsonElement Projection,
|
||||
string ProjectionHash,
|
||||
string SchemaVersion);
|
||||
@@ -6,6 +6,7 @@ using StellaOps.SbomService.Models;
|
||||
using StellaOps.SbomService.Services;
|
||||
using StellaOps.SbomService.Observability;
|
||||
using StellaOps.SbomService.Repositories;
|
||||
using System.Text.Json;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
@@ -28,6 +29,37 @@ builder.Services.AddSingleton<IComponentLookupRepository>(sp =>
|
||||
});
|
||||
builder.Services.AddSingleton<ISbomQueryService, InMemorySbomQueryService>();
|
||||
|
||||
builder.Services.AddSingleton<IProjectionRepository>(sp =>
|
||||
{
|
||||
var config = sp.GetRequiredService<IConfiguration>();
|
||||
var env = sp.GetRequiredService<IHostEnvironment>();
|
||||
|
||||
var configured = config.GetValue<string>("SbomService:ProjectionsPath");
|
||||
if (!string.IsNullOrWhiteSpace(configured))
|
||||
{
|
||||
return new FileProjectionRepository(configured!);
|
||||
}
|
||||
|
||||
var candidateRoots = new[]
|
||||
{
|
||||
env.ContentRootPath,
|
||||
Path.GetFullPath(Path.Combine(env.ContentRootPath, "..")),
|
||||
Path.GetFullPath(Path.Combine(env.ContentRootPath, "..", "..")),
|
||||
Path.GetFullPath(Path.Combine(env.ContentRootPath, "..", "..", ".."))
|
||||
};
|
||||
|
||||
foreach (var root in candidateRoots)
|
||||
{
|
||||
var candidate = Path.Combine(root, "docs", "modules", "sbomservice", "fixtures", "lnm-v1", "projections.json");
|
||||
if (File.Exists(candidate))
|
||||
{
|
||||
return new FileProjectionRepository(candidate);
|
||||
}
|
||||
}
|
||||
|
||||
return new FileProjectionRepository(string.Empty);
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
app.MapGet("/healthz", () => Results.Ok(new { status = "ok" }));
|
||||
@@ -207,6 +239,38 @@ app.MapGet("/sbom/versions", async Task<IResult> (
|
||||
return Results.Ok(result.Result);
|
||||
});
|
||||
|
||||
app.MapGet("/sboms/{snapshotId}/projection", async Task<IResult> (
|
||||
[FromServices] ISbomQueryService service,
|
||||
[FromRoute] string? snapshotId,
|
||||
[FromQuery(Name = "tenant")] string? tenantId,
|
||||
CancellationToken cancellationToken) =>
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(snapshotId))
|
||||
{
|
||||
return Results.BadRequest(new { error = "snapshotId is required" });
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(tenantId))
|
||||
{
|
||||
return Results.BadRequest(new { error = "tenant is required" });
|
||||
}
|
||||
|
||||
var projection = await service.GetProjectionAsync(snapshotId.Trim(), tenantId.Trim(), cancellationToken);
|
||||
if (projection is null)
|
||||
{
|
||||
return Results.NotFound(new { error = "projection not found" });
|
||||
}
|
||||
|
||||
return Results.Ok(new
|
||||
{
|
||||
snapshotId = projection.SnapshotId,
|
||||
tenantId = projection.TenantId,
|
||||
schemaVersion = projection.SchemaVersion,
|
||||
hash = projection.ProjectionHash,
|
||||
projection = projection.Projection
|
||||
});
|
||||
});
|
||||
|
||||
app.Run();
|
||||
|
||||
public partial class Program;
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using StellaOps.SbomService.Models;
|
||||
|
||||
namespace StellaOps.SbomService.Repositories;
|
||||
|
||||
internal sealed class FileProjectionRepository : IProjectionRepository
|
||||
{
|
||||
private readonly IReadOnlyDictionary<(string SnapshotId, string TenantId), SbomProjectionResult> _projections;
|
||||
|
||||
public FileProjectionRepository(string fixturesPath)
|
||||
{
|
||||
if (!File.Exists(fixturesPath))
|
||||
{
|
||||
_projections = new Dictionary<(string, string), SbomProjectionResult>();
|
||||
return;
|
||||
}
|
||||
|
||||
using var stream = File.OpenRead(fixturesPath);
|
||||
var root = JsonNode.Parse(stream) as JsonArray ?? throw new InvalidOperationException("projections.json must be a JSON array");
|
||||
|
||||
var map = new Dictionary<(string, string), SbomProjectionResult>();
|
||||
|
||||
foreach (var node in root.OfType<JsonObject>())
|
||||
{
|
||||
var snapshotId = node["snapshotId"]?.GetValue<string>();
|
||||
var tenantId = node["tenantId"]?.GetValue<string>();
|
||||
var projectionNode = node["projection"];
|
||||
|
||||
if (string.IsNullOrWhiteSpace(snapshotId) || string.IsNullOrWhiteSpace(tenantId) || projectionNode is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var projectionElement = ToElement(projectionNode);
|
||||
var schemaVersion = node["schemaVersion"]?.GetValue<string>()
|
||||
?? projectionNode["metadata"]? ["schemaVersion"]?.GetValue<string>()
|
||||
?? "1.0.0";
|
||||
|
||||
var projectionHash = ComputeHash(projectionElement);
|
||||
|
||||
map[(snapshotId!, tenantId!)] = new SbomProjectionResult(
|
||||
snapshotId!,
|
||||
tenantId!,
|
||||
projectionElement,
|
||||
projectionHash,
|
||||
schemaVersion);
|
||||
}
|
||||
|
||||
_projections = map;
|
||||
}
|
||||
|
||||
public Task<SbomProjectionResult?> GetAsync(string snapshotId, string tenantId, CancellationToken cancellationToken)
|
||||
{
|
||||
_projections.TryGetValue((snapshotId, tenantId), out var result);
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
private static string ComputeHash(JsonElement element)
|
||||
{
|
||||
var json = JsonSerializer.Serialize(element, new JsonSerializerOptions { WriteIndented = false });
|
||||
using var sha = SHA256.Create();
|
||||
var bytes = sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes(json));
|
||||
return Convert.ToHexString(bytes).ToLowerInvariant();
|
||||
}
|
||||
|
||||
private static JsonElement ToElement(JsonNode node)
|
||||
{
|
||||
using var doc = JsonDocument.Parse(node.ToJsonString(new JsonSerializerOptions { WriteIndented = false }));
|
||||
return doc.RootElement.Clone();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using StellaOps.SbomService.Models;
|
||||
|
||||
namespace StellaOps.SbomService.Repositories;
|
||||
|
||||
public interface IProjectionRepository
|
||||
{
|
||||
Task<SbomProjectionResult?> GetAsync(string snapshotId, string tenantId, CancellationToken cancellationToken);
|
||||
}
|
||||
@@ -11,4 +11,6 @@ public interface ISbomQueryService
|
||||
Task<QueryResult<SbomCatalogResult>> GetConsoleCatalogAsync(SbomCatalogQuery query, CancellationToken cancellationToken);
|
||||
|
||||
Task<QueryResult<ComponentLookupResult>> GetComponentLookupAsync(ComponentLookupQuery query, CancellationToken cancellationToken);
|
||||
|
||||
Task<SbomProjectionResult?> GetProjectionAsync(string snapshotId, string tenantId, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
@@ -11,11 +11,13 @@ internal sealed class InMemorySbomQueryService : ISbomQueryService
|
||||
private readonly IReadOnlyList<TimelineRecord> _timelines;
|
||||
private readonly IReadOnlyList<CatalogRecord> _catalog;
|
||||
private readonly IComponentLookupRepository _componentLookupRepository;
|
||||
private readonly IProjectionRepository _projectionRepository;
|
||||
private readonly ConcurrentDictionary<string, object> _cache = new();
|
||||
|
||||
public InMemorySbomQueryService(IComponentLookupRepository componentLookupRepository)
|
||||
public InMemorySbomQueryService(IComponentLookupRepository componentLookupRepository, IProjectionRepository projectionRepository)
|
||||
{
|
||||
_componentLookupRepository = componentLookupRepository;
|
||||
_projectionRepository = projectionRepository;
|
||||
// Deterministic seed data for early contract testing; replace with Mongo-backed implementation later.
|
||||
_paths = SeedPaths();
|
||||
_timelines = SeedTimelines();
|
||||
@@ -156,6 +158,23 @@ internal sealed class InMemorySbomQueryService : ISbomQueryService
|
||||
return new QueryResult<ComponentLookupResult>(result, false);
|
||||
}
|
||||
|
||||
public async Task<SbomProjectionResult?> GetProjectionAsync(string snapshotId, string tenantId, CancellationToken cancellationToken)
|
||||
{
|
||||
var cacheKey = $"projection|{snapshotId}|{tenantId}";
|
||||
if (_cache.TryGetValue(cacheKey, out var cached) && cached is SbomProjectionResult cachedProjection)
|
||||
{
|
||||
return cachedProjection;
|
||||
}
|
||||
|
||||
var projection = await _projectionRepository.GetAsync(snapshotId, tenantId, cancellationToken);
|
||||
if (projection is not null)
|
||||
{
|
||||
_cache[cacheKey] = projection;
|
||||
}
|
||||
|
||||
return projection;
|
||||
}
|
||||
|
||||
private static IReadOnlyList<PathRecord> SeedPaths()
|
||||
{
|
||||
return new List<PathRecord>
|
||||
|
||||
Reference in New Issue
Block a user