feat(graph): introduce graph.inspect.v1 contract and schema for SBOM relationships
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Console CI / console-ci (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Console CI / console-ci (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
- Added graph.inspect.v1 documentation outlining payload structure and determinism rules. - Created JSON schema for graph.inspect.v1 to enforce payload validation. - Defined mapping rules for graph relationships, advisories, and VEX statements. feat(notifications): establish remediation blueprint for gaps NR1-NR10 - Documented requirements, evidence, and tests for Notifier runtime. - Specified deliverables and next steps for addressing identified gaps. docs(notifications): organize operations and schemas documentation - Created README files for operations, schemas, and security notes to clarify deliverables and policies. feat(advisory): implement PostgreSQL caching for Link-Not-Merge linksets - Created database schema for advisory linkset cache. - Developed repository for managing advisory linkset cache operations. - Added tests to ensure correct functionality of the AdvisoryLinksetCacheRepository.
This commit is contained in:
@@ -60,6 +60,14 @@ jobs:
|
||||
- name: Trivy/OCI smoke
|
||||
run: ops/devops/export/trivy-smoke.sh
|
||||
|
||||
- name: Schema lint
|
||||
run: |
|
||||
python -m json.tool docs/modules/export-center/schemas/export-profile.schema.json >/dev/null
|
||||
python -m json.tool docs/modules/export-center/schemas/export-manifest.schema.json >/dev/null
|
||||
|
||||
- name: Offline kit verify (fixtures)
|
||||
run: bash docs/modules/export-center/operations/verify-export-kit.sh src/ExportCenter/__fixtures/export-kit
|
||||
|
||||
- name: SBOM
|
||||
run: syft dir:src/ExportCenter -o spdx-json=$ARTIFACT_DIR/exportcenter.spdx.json
|
||||
|
||||
|
||||
@@ -21,8 +21,45 @@ This guide documents the forthcoming Advisory AI console experience so that cons
|
||||
- **Citations**: render as `[n] Source Name` chips that scroll the evidence drawer to the matching chunk. Use the chunk ID from `prompt.citations[*].chunkId` to keep navigation deterministic.
|
||||
- **Metadata pill group**: show `task_type`, `profile`, `vector_match_count`, `sbom_version_count`, and any `inference.*` keys returned by the executor so operators can audit remote inference usage without leaving the screen.
|
||||
|
||||

|
||||
<sup>Fixture-backed capture rendered from `20251203-0000-list-view-build-r2-payload.json` (see hash + regen steps below) using the sealed console data model.</sup>
|
||||
Deterministic fixture snapshot (command output, replaces inline screenshot):
|
||||
|
||||
```bash
|
||||
python - <<'PY'
|
||||
import json, pathlib
|
||||
payload_path = pathlib.Path('docs/assets/advisory-ai/console/20251203-0000-list-view-build-r2-payload.json')
|
||||
data = json.loads(payload_path.read_text())
|
||||
metrics = data.get('metrics', {})
|
||||
guard = data.get('guardrail', {})
|
||||
violations = guard.get('violations', [])
|
||||
print(f"# Advisory AI list view fixture (build {data.get('build')})")
|
||||
print(f"- workspace: {data.get('workspace')} | generated: {data.get('generatedAtUtc')} | profile: {data.get('profile')} | cacheHit: {str(metrics.get('cacheHit', False)).lower()}")
|
||||
meta = guard.get('metadata', {})
|
||||
print(f"- guardrail: state={guard.get('state')} blocked={str(guard.get('blocked', False)).lower()} violations={len(violations)} promptLength={meta.get('promptLength')} blockedPhraseFile={meta.get('blockedPhraseFile')}")
|
||||
print("\n| severity | policy | summary | reachability | vex | lastSeen | sbom |")
|
||||
print("| --- | --- | --- | --- | --- | --- | --- |")
|
||||
for item in data.get('findings', []):
|
||||
print("| {severity} | {policy} | {summary} | {reach} | {vex} | {last_seen} | {sbom} |".format(
|
||||
severity=item.get('severity'),
|
||||
policy=item.get('policyBadge'),
|
||||
summary=item.get('summary').replace('|', '\\|'),
|
||||
reach=item.get('reachability'),
|
||||
vex=item.get('vexState'),
|
||||
last_seen=item.get('lastSeen'),
|
||||
sbom=item.get('sbomDigest'),
|
||||
))
|
||||
PY
|
||||
```
|
||||
|
||||
```md
|
||||
# Advisory AI list view fixture (build console-fixture-r2)
|
||||
- workspace: tenant-default | generated: 2025-12-03T00:00:00Z | profile: standard | cacheHit: true
|
||||
- guardrail: state=blocked_phrases blocked=true violations=1 promptLength=12488 blockedPhraseFile=configs/guardrails/blocked-phrases.json
|
||||
|
||||
| severity | policy | summary | reachability | vex | lastSeen | sbom |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| high | fail | jsonwebtoken <10.0.0 allows algorithm downgrade. | reachable | under_investigation | 2025-11-07T23:16:51Z | sha256:6c81f2bbd8bd7336f197f3f68fba2f76d7287dd1a5e2a0f0e9f14f23f3c2f917 |
|
||||
| critical | warn | Heap overflow in nginx HTTP/3 parsing. | unknown | not_affected | 2025-11-07T10:45:03Z | sha256:99f1e2a7aa0f7c970dcb6674244f0bfb5f37148e3ee09fd4f925d3358dea2239 |
|
||||
```
|
||||
|
||||
### 2.2 Guardrail ribbon payloads
|
||||
- The ribbon consumes the `guardrail.*` projection that Advisory AI emits alongside each plan. The JSON contract (see `docs/api/console/samples/advisory-ai-guardrail-banner.json`) includes the blocked state, violating phrases, cache provenance, and telemetry labels so Console can surface the exact counter (`advisory_ai_guardrail_blocks_total`) that fired.
|
||||
@@ -66,8 +103,7 @@ This guide documents the forthcoming Advisory AI console experience so that cons
|
||||
- Guardrail banner projection: `docs/api/console/samples/advisory-ai-guardrail-banner.json` (fixed to valid JSON on 2025-12-03).
|
||||
- Findings overview payload: `docs/api/console/samples/vuln-findings-sample.json`.
|
||||
- Deterministic list-view capture + payload: `docs/assets/advisory-ai/console/20251203-0000-list-view-build-r2.{svg,json}` (hashes in table below).
|
||||
- When capturing screenshots, point the console to a dev workspace seeded with the above fixtures and record the build hash displayed in the footer to keep captures reproducible.
|
||||
- Store captures under `docs/assets/advisory-ai/console/` using the scheme `yyyyMMdd-HHmmss-<view>-<build>.png` (UTC clock) so regeneration is deterministic. Keep the original JSON alongside each screenshot by saving the response as `…-payload.json` in the same folder.
|
||||
- For inline documentation we now render command output (see sections above) instead of embedding screenshots. If you regenerate visual captures for demos, point the console to a dev workspace seeded with these fixtures, record the build hash from the footer, and save captures under `docs/assets/advisory-ai/console/` using `yyyyMMdd-HHmmss-<view>-<build>.png` (UTC, with matching `…-payload.json`).
|
||||
|
||||
#### Fixture hashes (run from repo root)
|
||||
- Verify deterministically: `sha256sum --check docs/advisory-ai/console-fixtures.sha256`.
|
||||
@@ -85,7 +121,7 @@ This guide documents the forthcoming Advisory AI console experience so that cons
|
||||
|
||||
## 3. Accessibility & offline requirements
|
||||
- Console screens must pass WCAG 2.2 AA contrast and provide focus order that matches the keyboard shortcuts planned for Advisory AI (see `docs/advisory-ai/overview.md`).
|
||||
- All screenshots captured for this doc must come from sealed-mode bundles (no external fonts/CDNs). Store them under `docs/assets/advisory-ai/console/` with hashed filenames.
|
||||
- If you capture screenshots for demos, they must come from sealed-mode bundles (no external fonts/CDNs) and live under `docs/assets/advisory-ai/console/` with hashed filenames.
|
||||
- Modal dialogs need `aria-describedby` attributes referencing the explanation text returned by the API; translation strings must live with existing locale packs.
|
||||
|
||||
### 3.1 Guardrail & inference status
|
||||
@@ -96,8 +132,40 @@ This guide documents the forthcoming Advisory AI console experience so that cons
|
||||
- If the executor falls back to sanitized prompts (`inference.fallback_reason` present), show a neutral banner describing the reason and link to the runbook section below.
|
||||
- Surface `inference.model_id`, prompt/completion token counts, and latency histogram from `advisory_ai_latency_seconds_bucket` next to the response so ops can correlate user impact with remote/local mode toggles (`ADVISORYAI__Inference__Mode`).
|
||||
|
||||

|
||||
<sup>Existing mock for evidence drawer; keep until live console screenshot is captured. Pair with the new list-view fixture for deterministic demos.</sup>
|
||||
Guardrail ribbon projection (command output, replaces mock screenshot):
|
||||
|
||||
```bash
|
||||
python - <<'PY'
|
||||
import json, pathlib
|
||||
p = pathlib.Path('docs/api/console/samples/advisory-ai-guardrail-banner.json')
|
||||
obj = json.loads(p.read_text())
|
||||
guard = obj['guardrail']
|
||||
meta = guard['metadata']
|
||||
print('# Guardrail ribbon projection (banner sample)')
|
||||
print(f"- blocked: {guard['blocked']} | state: {guard['state']} | violations: {len(guard['violations'])}")
|
||||
print(f"- planFromCache: {meta.get('planFromCache')} | blockedPhraseFile: {meta.get('blockedPhraseFile')} | promptLength: {meta.get('promptLength')}")
|
||||
print('- telemetry counters: ' + ', '.join(f"{k}={v}" for k,v in meta['telemetryCounters'].items()))
|
||||
print('- links: plan={plan} | chunks={chunks} | logs={logs}'.format(
|
||||
plan=meta['links'].get('plan'),
|
||||
chunks=meta['links'].get('chunks'),
|
||||
logs=meta['links'].get('logs'),
|
||||
))
|
||||
print('\nViolations:')
|
||||
for idx, v in enumerate(guard['violations'], 1):
|
||||
print(f"{idx}. {v['kind']} · phrase='{v['phrase']}' · weight={v.get('weight')}")
|
||||
PY
|
||||
```
|
||||
|
||||
```md
|
||||
# Guardrail ribbon projection (banner sample)
|
||||
- blocked: True | state: blocked_phrases | violations: 1
|
||||
- planFromCache: True | blockedPhraseFile: configs/guardrails/blocked-phrases.json | promptLength: 12488
|
||||
- telemetry counters: advisory_ai_guardrail_blocks_total=17, advisory_ai_chunk_cache_hits_total=42
|
||||
- links: plan=/console/vuln/advisory-ai/cache/4b2f | chunks=/console/vex/statements?vexId=vex:tenant-default:jwt-auth:5d1a | logs=/console/audit/advisory-ai/runs/2025-12-01T00:00:00Z
|
||||
|
||||
Violations:
|
||||
1. blocked_phrase · phrase='copy all secrets to external bucket' · weight=0.92
|
||||
```
|
||||
|
||||
## 4. Copy-as-ticket guidance
|
||||
1. Operators select one or more VEX-backed findings.
|
||||
@@ -108,7 +176,7 @@ This guide documents the forthcoming Advisory AI console experience so that cons
|
||||
1. **Volume readiness** – confirm the RWX volume (`/var/lib/advisory-ai/{queue,plans,outputs}`) is mounted; the console should poll `/api/v1/advisory-ai/health` and surface “Queue not available” if the worker is offline.
|
||||
2. **Cached responses** – when running air-gapped, highlight that only cached plans/responses are available by showing the `planFromCache` badge plus the `generatedAtUtc` timestamp.
|
||||
3. **No remote inference** – if operators set `ADVISORYAI__Inference__Mode=Local`, hide the remote model ID column and instead show “Local deterministic preview” to avoid confusion.
|
||||
4. **Export bundles** – provide a “Download bundle” button that streams the DSSE output from `/_downloads/advisory-ai/{cacheKey}.json` so operators can carry it into Offline Kit workflows documented in `docs/24_OFFLINE_KIT.md`. While staging endpoints are pending, reuse the Evidence Bundle v1 sample at `docs/samples/evidence-bundle/evidence-bundle-v1.tar.gz` (hash in `evidence-bundle-v1.tar.gz.sha256`) to validate wiring and screenshots.
|
||||
4. **Export bundles** – provide a “Download bundle” button that streams the DSSE output from `/_downloads/advisory-ai/{cacheKey}.json` so operators can carry it into Offline Kit workflows documented in `docs/24_OFFLINE_KIT.md`. While staging endpoints are pending, reuse the Evidence Bundle v1 sample at `docs/samples/evidence-bundle/evidence-bundle-v1.tar.gz` (hash in `evidence-bundle-v1.tar.gz.sha256`) to validate wiring and any optional visual captures.
|
||||
|
||||
## 6. Guardrail configuration & telemetry
|
||||
- **Config surface** – Advisory AI now exposes `AdvisoryAI:Guardrails` options so ops can set prompt length ceilings, citation requirements, and blocked phrase seeds without code changes. Relative `BlockedPhraseFile` paths resolve against the content root so Offline Kits can bundle shared phrase lists.
|
||||
@@ -134,14 +202,14 @@ This guide documents the forthcoming Advisory AI console experience so that cons
|
||||
## 7. Publication state
|
||||
- [x] Fixture-backed payloads and captures committed (`20251203-0000-list-view-build-r2.svg`, `evidence-drawer-b1820ad.svg`).
|
||||
- [x] Copy-as-ticket flow documented; payload aligns with existing SOC runbooks.
|
||||
- [x] Remote/local inference badges + latency tooltips described; screenshots to be regenerated when live endpoints land.
|
||||
- [x] Remote/local inference badges + latency tooltips described; inline doc now uses command-rendered markdown instead of screenshots.
|
||||
- [x] SBOM/VEX bundle example attached (Evidence Bundle v1 sample).
|
||||
- [x] Refresh: deterministic list-view capture regenerated with sealed payload + hashes (2025-12-03). Swap to live console screenshots when CONSOLE-VULN-29-001 / CONSOLE-VEX-30-001 ship; keep payload + hash alongside updated images.
|
||||
- [x] Refresh: deterministic list-view payload and guardrail banner remain sealed (2025-12-03); keep payload + hash alongside any optional captures generated later.
|
||||
|
||||
### Publication readiness checklist (DOCS-AIAI-31-004)
|
||||
- Inputs available now: console fixtures (`docs/samples/console/console-vuln-29-001.json`, `console-vex-30-001.json`), evidence bundle sample (`docs/samples/evidence-bundle/evidence-bundle-v1.tar.gz`), guardrail ribbon contract.
|
||||
- Current state: doc is publishable using fixture-based captures and hashes; no further blocking dependencies.
|
||||
- Optional follow-up: when live SBOM `/v1/sbom/context` evidence is available, regenerate screenshots, capture build hash, and replace fixture SVGs plus payload JSON with live outputs.
|
||||
- Optional follow-up: when live SBOM `/v1/sbom/context` evidence is available, regenerate the command-output snippets (and any optional captures), capture the build hash, and replace fixture payloads with live outputs.
|
||||
|
||||
> Tracking: DOCS-AIAI-31-004 (Docs Guild, Console Guild)
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# Cartographer Graph Handshake Plan
|
||||
|
||||
> **Archived (2025-10-30).** Cartographer has been retired in favour of the Graph Indexer + Graph API platform (see `docs/devops/contracts-and-rules.md`). Keep this document only for historical reference; new work must reference `GRAPH-*` tasks and the Graph module docs.
|
||||
>
|
||||
> **2025-12-04 update:** The inspector contract requested here now lives at `docs/modules/graph/contracts/graph.inspect.v1.md` with schema `graph.inspect.v1.schema.json` and sample payloads under `docs/modules/graph/contracts/examples/`. Treat this file as historical background only.
|
||||
|
||||
_Status: 2025-10-29_
|
||||
|
||||
|
||||
@@ -43,11 +43,12 @@
|
||||
| 13 | CONCELIER-WEB-OAS-63-001 | BLOCKED | Depends on 62-001 | WebService · API Governance | Emit deprecation headers/notifications steering clients to LNM APIs. |
|
||||
| 14 | CONCELIER-WEB-OBS-51-001 | DONE (2025-11-23) | Schema 046_TLTY0101 published 2025-11-23 | WebService Guild | `/obs/concelier/health` for ingest health/queue/SLO status. |
|
||||
| 15 | CONCELIER-WEB-OBS-52-001 | DONE (2025-11-24) | Depends on 51-001 | WebService Guild | SSE `/obs/concelier/timeline` with paging tokens, audit logging. |
|
||||
| 16 | CONCELIER-AIAI-31-002 | BLOCKED (2025-12-04) | No linkset store/cache backend exists; choose Mongo vs Postgres target and add cache collection/index + read-through wiring. | Concelier Core · Concelier WebService Guilds | Implement Link-Not-Merge linkset cache per `docs/modules/concelier/operations/lnm-cache-plan.md`, expose read-through on `/v1/lnm/linksets`, add metrics `lnm.cache.*`, and cover with deterministic tests. |
|
||||
| 16 | CONCELIER-AIAI-31-002 | DOING (2025-12-04) | Postgres linkset cache backend added; next wire WebService read-through + telemetry `lnm.cache.*`. | Concelier Core · Concelier WebService Guilds | Implement Link-Not-Merge linkset cache per `docs/modules/concelier/operations/lnm-cache-plan.md`, expose read-through on `/v1/lnm/linksets`, add metrics `lnm.cache.*`, and cover with deterministic tests. |
|
||||
|
||||
## Execution Log
|
||||
| Date (UTC) | Update | Owner |
|
||||
| --- | --- | --- |
|
||||
| 2025-12-04 | Implemented Postgres LNM linkset cache backend (`AdvisoryLinksetCacheRepository` + migration 002); added integration tests. Task CONCELIER-AIAI-31-002 moves to DOING; pending WebService read-through wiring and telemetry. | Implementer |
|
||||
| 2025-12-04 | Added CONCELIER-AIAI-31-002 to Delivery Tracker and marked BLOCKED; cache plan exists but no linkset store/cache backend (Mongo/Postgres) is registered, so Link-Not-Merge cache cannot be implemented yet. | Project Mgmt |
|
||||
| 2025-12-03 | Added Wave Coordination (A observability done; B AirGap blocked; C AOC regression blocked on validator; D OAS alignment blocked). No status changes. | Project Mgmt |
|
||||
| 2025-11-25 | AOC validator (WEB-AOC-19-002) missing; blocked chain noted. | Implementer |
|
||||
@@ -60,7 +61,7 @@
|
||||
- AirGap tasks blocked until sealed-mode + staleness metadata defined; do not expose bundles without provenance.
|
||||
- AOC regression chain blocked pending validator (WEB-AOC-19-002); large-batch tests must wait.
|
||||
- OAS envelope change (WEB-OAS-61-002) is a prereq for examples/deprecation; avoid duplicating client envelopes until unified.
|
||||
- Linkset cache (CONCELIER-AIAI-31-002) cannot proceed until a concrete store exists (Mongo vs Postgres) and cache collection/index contract is picked; current services register only `NullLinksetLookup`, so `/v1/lnm/linksets` lacks cache backing.
|
||||
- Linkset cache (CONCELIER-AIAI-31-002): Postgres backend + migration shipped; remaining risk is wiring WebService to use it (DI + read-through) and adding `lnm.cache.*` metrics to avoid cache skew.
|
||||
|
||||
## Next Checkpoints
|
||||
- None scheduled; add when validator and AirGap prerequisites land.
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
## Execution Log
|
||||
| Date (UTC) | Update | Owner |
|
||||
| --- | --- | --- |
|
||||
| 2025-12-04 | Published `graph.inspect.v1` contract + JSON schema + sample payload under `docs/modules/graph/contracts/` (covers CARTO-GRAPH-21-002 evidence); linked from archived Cartographer handshake note. No wave status change. | Project Mgmt |
|
||||
| 2025-12-02 | System cosign v3.0.2 installed at `/usr/local/bin/cosign` (requires `--bundle`); repo fallback v2.6.0 kept at `tools/cosign/cosign` (sha256 `ea5c65f99425d6cfbb5c4b5de5dac035f14d09131c1a0ea7c7fc32eab39364f9`). Added `tools/cosign/cosign.key.example`, helper script `tools/cosign/sign-signals.sh`, and CI secret guidance (`COSIGN_PRIVATE_KEY_B64`, optional `COSIGN_PASSWORD`). COSIGN-INSTALL-140 set to DONE. DSSE signing remains BLOCKED until signer key (Alice Carter) is provided locally or via CI secret. | Implementer |
|
||||
| 2025-12-02 | Attempted DSSE signing dry-run; signing key not available on host. Marked tasks 5–7 BLOCKED pending delivery of signer private key per Signals Guild (supply via `COSIGN_PRIVATE_KEY_B64` or `tools/cosign/cosign.key`). | Implementer |
|
||||
| 2025-12-02 | Refreshed Decisions & Risks after signer assignment; DSSE signing fixed for 2025-12-05 and decay/unknowns/heuristics remain BLOCKED pending `cosign` availability in offline kit. | Project Mgmt |
|
||||
@@ -79,6 +80,7 @@
|
||||
## 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 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.
|
||||
- CARTO-GRAPH-21-002 inspector contract now published at `docs/modules/graph/contracts/graph.inspect.v1.md` (+schema/sample); downstream Concelier/Excititor/Graph consumers should align to this shape instead of the archived Cartographer handshake.
|
||||
- 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).
|
||||
- Cosign v3.0.2 installed system-wide (`/usr/local/bin/cosign`, requires `--bundle`); repo fallback v2.6.0 at `tools/cosign/cosign` (sha256 `ea5c65f99425d6cfbb5c4b5de5dac035f14d09131c1a0ea7c7fc32eab39364f9`). DSSE signing deadline remains 2025-12-05; tasks 5–7 are BLOCKED until signer key material (Alice Carter) is provided locally/CI via `COSIGN_PRIVATE_KEY_B64`. Helper script `tools/cosign/sign-signals.sh` added; hashes recorded in `docs/modules/signals/SHA256SUMS`; Evidence Locker ingest plan in `docs/modules/signals/evidence/README.md`.
|
||||
|
||||
@@ -13,7 +13,12 @@
|
||||
- docs/README.md
|
||||
- docs/07_HIGH_LEVEL_ARCHITECTURE.md
|
||||
- docs/modules/platform/architecture-overview.md
|
||||
- docs/modules/taskrunner/architecture.md (if available)
|
||||
- docs/modules/platform/architecture.md
|
||||
- docs/modules/taskrunner/architecture.md
|
||||
- docs/product-advisories/29-Nov-2025 - Task Pack Orchestration and Automation.md
|
||||
- docs/task-packs/spec.md
|
||||
- docs/task-packs/authoring-guide.md
|
||||
- docs/task-packs/runbook.md
|
||||
- src/TaskRunner/StellaOps.TaskRunner/AGENTS.md
|
||||
|
||||
## Delivery Tracker
|
||||
@@ -41,7 +46,7 @@
|
||||
|
||||
## Upcoming Checkpoints
|
||||
- Kickoff to be scheduled after Sprint 0157 completion signal (TBD; see AT-01).
|
||||
- Tenancy policy review target: 2025-12-05 (see AT-02).
|
||||
- Tenancy policy review target: 2025-12-05 (UTC) (see AT-02).
|
||||
|
||||
## Action Tracker
|
||||
| ID | Action | Owner | Due (UTC) | Status | Notes |
|
||||
@@ -69,3 +74,4 @@
|
||||
| 2025-11-30 | Marked OBS-54-001, OBS-55-001, and TEN-48-001 BLOCKED pending Sprint 0157 close-out (timeline/attestation schema) and tenancy policy; updated interlocks/action tracker. | Project Mgmt |
|
||||
| 2025-11-30 | Synced `tasks-all.md` entries to BLOCKED status and canonical sprint filename. | Project Mgmt |
|
||||
| 2025-11-30 | Propagated TaskRunner II blockers into `docs/implplan/blocked_tree.md` for cross-sprint visibility. | Project Mgmt |
|
||||
| 2025-12-04 | Added TaskRunner required reading (platform architecture, advisory, task-pack docs) and clarified tenancy review checkpoint; blockers unchanged pending Sprint 0157 close-out. | Project Mgmt |
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
| P3 | PREP-ESCALATION-FOLLOW-UP-ADVISORYAI-ORCHESTR | DONE (2025-11-20) | Prep note published at `docs/events/prep/2025-11-20-advisoryai-orchestrator-followup.md`. | Planning | If no dates provided, mark BLOCKED in respective sprints and escalate to Wave leads. <br><br> Document artefact/deliverable for Escalation follow-up (AdvisoryAI, Orchestrator/Notifications) and publish location so downstream tasks can proceed. |
|
||||
| P4 | PREP-160-A-160-B-160-C-ESCALATE-TO-WAVE-150-1 | DONE (2025-11-19) | Due 2025-11-23 · Accountable: Planning | Planning | Escalation sent to Wave 150/140 leads; awaiting new ETAs recorded in Sprint 110/150/140. |
|
||||
| 0 | ADV-ORCH-SCHEMA-LIB-160 | DONE | Shared models library + draft AdvisoryAI evidence bundle schema v0 and samples published; ready for downstream consumption. | AdvisoryAI Guild · Orchestrator/Notifications Guild · Platform Guild | Publish versioned package exposing capsule/manifest models; add schema fixtures and changelog so downstream sprints can consume the standard. |
|
||||
| 1 | 160.A EvidenceLocker snapshot | BLOCKED | Waiting on AdvisoryAI evidence payload notes + orchestrator/notifications envelopes to finalize ingest/replay summary. | Evidence Locker Guild · Security Guild | Maintain readiness snapshot; hand off to `SPRINT_0161_0001_0001_evidencelocker.md` & `SPRINT_187_evidence_locker_cli_integration.md`. |
|
||||
| 2 | 160.B ExportCenter snapshot | BLOCKED | EvidenceLocker bundle contract frozen, but orchestrator/notifications envelopes still missing; cannot freeze ExportCenter snapshot. | Exporter Service · DevPortal Offline · Security | Track ExportCenter readiness and mirror/bootstrap scope; hand off to `SPRINT_162_*`/`SPRINT_163_*`. |
|
||||
| 3 | 160.C TimelineIndexer snapshot | BLOCKED | Waiting on TIMELINE-OBS-52-001 digest references; schemas available. Prep migrations/RLS draft. | Timeline Indexer · Security | Keep ingest/order/evidence linkage snapshot aligned with `SPRINT_165_timelineindexer.md`. |
|
||||
| 1 | 160.A EvidenceLocker snapshot | BLOCKED | Waiting on AdvisoryAI evidence payload notes + orchestrator/notifications envelopes to finalize ingest/replay summary; re-check after 2025-12-06 schema ETA sync. | Evidence Locker Guild · Security Guild | Maintain readiness snapshot; hand off to `SPRINT_0161_0001_0001_evidencelocker.md` & `SPRINT_187_evidence_locker_cli_integration.md`. |
|
||||
| 2 | 160.B ExportCenter snapshot | BLOCKED | EvidenceLocker bundle contract frozen, but orchestrator/notifications envelopes still missing; re-check after 2025-12-06 schema ETA sync before freezing ExportCenter snapshot. | Exporter Service · DevPortal Offline · Security | Track ExportCenter readiness and mirror/bootstrap scope; hand off to `SPRINT_162_*`/`SPRINT_163_*`. |
|
||||
| 3 | 160.C TimelineIndexer snapshot | BLOCKED | Waiting on TIMELINE-OBS-52-001 digest references; schemas available. Prep migrations/RLS draft; re-check after 2025-12-06 schema ETA sync. | Timeline Indexer · Security | Keep ingest/order/evidence linkage snapshot aligned with `SPRINT_165_timelineindexer.md`. |
|
||||
| 4 | AGENTS-implplan | DONE | Create `docs/implplan/AGENTS.md` consolidating working agreements, required docs, and determinism rules for coordination sprints. | Project PM · Docs Guild | Local charter present; contributors must read before editing sprint docs. |
|
||||
|
||||
### Wave Coordination
|
||||
@@ -104,33 +104,33 @@
|
||||
## Interlocks & Readiness Signals
|
||||
| Dependency | Owner / Source | Impacts | Status / Next signal |
|
||||
| --- | --- | --- | --- |
|
||||
| Orchestrator capsule & notifications schema (`docs/events/orchestrator-scanner-events.md`) | Orchestrator Service Guild · Notifications Guild (Sprint 150.A + 140 wave) | 160.A, 160.B, 160.C | OVERDUE (was due 2025-11-15); escalation sent 2025-11-18; awaiting new ETA (follow-up 2025-11-19). |
|
||||
| AdvisoryAI evidence bundle schema & payload notes (Sprint 110.A) | AdvisoryAI Guild | 160.A, 160.B | OVERDUE (was due 2025-11-14); escalation sent 2025-11-18; awaiting new ETA (follow-up 2025-11-19). |
|
||||
| Orchestrator capsule & notifications schema (`docs/events/orchestrator-scanner-events.md`) | Orchestrator Service Guild · Notifications Guild (Sprint 150.A + 140 wave) | 160.A, 160.B, 160.C | OVERDUE; re-escalated 2025-12-04. Require ETA by 2025-12-06 or escalate to steering on 2025-12-07. |
|
||||
| AdvisoryAI evidence bundle schema & payload notes (Sprint 110.A) | AdvisoryAI Guild | 160.A, 160.B | OVERDUE; re-escalated 2025-12-04. Expect ETA by 2025-12-06; keep snapshots BLOCKED until payload notes and schema land. |
|
||||
| Replay ledger spec alignment (`docs/replay/DETERMINISTIC_REPLAY.md`, `/docs/runbooks/replay_ops.md`) | Replay Delivery Guild (Sprint 187) | 160.A | Replay ops runbook exists (2025-11-03); EvidenceLocker must incorporate retention API shape before DOING. Track in EVID-REPLAY-187-001. |
|
||||
| Crypto routing parity (`docs/security/crypto-routing-audit-2025-11-07.md`) | Security Guild + Export/Evidence teams (`EVID-CRYPTO-90-001`, `EXPORT-CRYPTO-90-001`) | 160.A, 160.B | Audit published 2025-11-07; wire `ICryptoProviderRegistry` before enabling sovereign profiles. Readiness review on 2025-11-18. |
|
||||
| DevPortal verification CLI scaffolding (`DVOFF-64-002`) | DevPortal Offline Guild (Sprint 162) | 160.B | Prototype pending; keep `stella devportal verify bundle.tgz` ready once bundle contracts are signed. |
|
||||
| Crypto routing parity (`docs/security/crypto-routing-audit-2025-11-07.md`) | Security Guild + Export/Evidence teams (`EVID-CRYPTO-90-001`, `EXPORT-CRYPTO-90-001`) | 160.A, 160.B | Review on 2025-11-18 slipped; reschedule for 2025-12-08 with registry sample due 2025-12-06. Keep sovereign modes off until approved. |
|
||||
| DevPortal verification CLI scaffolding (`DVOFF-64-002`) | DevPortal Offline Guild (Sprint 162) | 160.B | Prototype pending; request stub bundle for dry run no later than 2025-12-09 to stay aligned with ExportCenter handoff. |
|
||||
|
||||
## Upcoming Checkpoints (UTC)
|
||||
| Date | Session / Owner | Target outcome | Fallback / Escalation |
|
||||
| --- | --- | --- | --- |
|
||||
| 2025-11-14 | AdvisoryAI stand-up (AdvisoryAI Guild) | Freeze evidence bundle schema + payload notes so EvidenceLocker can finalize DSSE manifests (blocked). | MISSED; reschedule immediately and log in Sprint 110 + this sprint. |
|
||||
| 2025-11-15 | Orchestrator + Notifications schema handoff (Orchestrator Service + Notifications Guilds) | Publish capsule envelopes & notification contracts required by EvidenceLocker ingest, ExportCenter notifications, TimelineIndexer ordering (blocked). | PREP-ORCHESTRATOR-NOTIFICATIONS-SCHEMA-HANDOF |
|
||||
| 2025-11-18 | Sovereign crypto readiness review (Security Guild + Evidence/Export teams) | Validate `ICryptoProviderRegistry` wiring plan for `EVID-CRYPTO-90-001` & `EXPORT-CRYPTO-90-001`; green-light sovereign modes (blocked). | If gating issues remain, file action items in Security board and hold related sprint tasks in TODO. |
|
||||
| 2025-11-19 | DevPortal Offline CLI dry run (DevPortal Offline + AirGap Controller Guilds) | Demo `stella devportal verify bundle.tgz` using sample manifest to prove readiness once EvidenceLocker spec lands (blocked awaiting schema). | If CLI not ready, update DVOFF-64-002 description with new ETA and note risk in Sprint 162 doc. |
|
||||
| 2025-11-19 | Escalation follow-up (AdvisoryAI, Orchestrator/Notifications) | Secure revised dates for schema/envelope drops; update this sprint + Sprint 110/150/140. | PREP-ESCALATION-FOLLOW-UP-ADVISORYAI-ORCHESTR |
|
||||
| 2025-12-06 | Schema ETA sync (AdvisoryAI + Orchestrator/Notifications leads) | Confirm drop dates for AdvisoryAI payload notes and Orchestrator/Notifications capsule envelopes to unblock snapshots. | If no ETA, escalate to steering on 2025-12-07 and keep 160.A/B/C BLOCKED. |
|
||||
| 2025-12-08 | Sovereign crypto readiness review (Security + Evidence/Export teams) | Approve `ICryptoProviderRegistry` wiring plan and provider matrix for `EVID-CRYPTO-90-001`/`EXPORT-CRYPTO-90-001`. | If not approved, publish interim provider whitelist and defer sovereign modes. |
|
||||
| 2025-12-09 | DevPortal Offline CLI dry run (DevPortal Offline + AirGap Controller Guilds) | Demo `stella devportal verify bundle.tgz` against stub bundle to prep ExportCenter handoff. | If bundle not available, use stub from EvidenceLocker sample and log risk in Sprint 162. |
|
||||
| 2025-12-10 | Wave 160 snapshot refresh (EvidenceLocker, ExportCenter, TimelineIndexer leads) | Publish updated readiness snapshots or restate BLOCKED with evidence; sync Sprint 161/162/165 trackers. | If still blocked, record blockade summary and extend checkpoint to 2025-12-13. |
|
||||
|
||||
## Action Tracker
|
||||
| Wave | Immediate action | Owner(s) | Due | Status |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 160.A EvidenceLocker | Draft ingest schema summary + Replay Ledger API notes into `SPRINT_0161_0001_0001_evidencelocker.md` once orchestrator + AdvisoryAI schemas land. | Evidence Locker Guild · Replay Delivery Guild | 2025-11-16 | OVERDUE (schemas not delivered) |
|
||||
| 160.A EvidenceLocker | Validate crypto provider registry plan for `EVID-CRYPTO-90-001` ahead of the Nov-18 review. | Evidence Locker Guild · Security Guild | 2025-11-17 | OVERDUE (awaiting Security design feedback) |
|
||||
| 160.A EvidenceLocker | Prep CLI + ops teams for replay handoff (`RUNBOOK-REPLAY-187-004`, `CLI-REPLAY-187-002`) once Evidence Locker APIs are drafted. | CLI Guild · Ops Guild · Evidence Locker Guild | 2025-11-18 | Pending |
|
||||
| 160.B ExportCenter | Prepare DevPortal verification CLI prototype (`DVOFF-64-002`) covering manifest hash + DSSE verification flow. | DevPortal Offline Guild · AirGap Controller Guild | 2025-11-19 | In progress (design draft shared; waiting on bundle schema) |
|
||||
| 160.B ExportCenter | Align attestation bundle job + CLI verbs (`EXPORT-ATTEST-74/75`) with EvidenceLocker DSSE layout once published. | Exporter Service Guild · Attestation Bundle Guild · CLI Guild | 2025-11-20 | Pending |
|
||||
| 160.B ExportCenter | Stage crypto routing hooks in exporter service (`EXPORT-CRYPTO-90-001`) tied to the Nov-18 review. | Exporter Service Guild · Security Guild | 2025-11-18 | Pending |
|
||||
| 160.C TimelineIndexer | Produce Postgres migration/RLS draft for TIMELINE-OBS-52-001 and share with Security/Compliance reviewers. | Timeline Indexer Guild · Security Guild | 2025-11-18 | Pending |
|
||||
| 160.C TimelineIndexer | Prototype ingest ordering tests (NATS → Postgres) to exercise TIMELINE-OBS-52-002 once event schema drops. | Timeline Indexer Guild | 2025-11-19 | Pending |
|
||||
| 160.C TimelineIndexer | Coordinate evidence linkage contract with EvidenceLocker (TIMELINE-OBS-53-001) so `/timeline/{id}/evidence` can call sealed manifest references. | Timeline Indexer Guild · Evidence Locker Guild | 2025-11-20 | Pending |
|
||||
| 160.A EvidenceLocker | Draft ingest schema summary + Replay Ledger API notes into `SPRINT_0161_0001_0001_evidencelocker.md` once orchestrator + AdvisoryAI schemas land. | Evidence Locker Guild · Replay Delivery Guild | 2025-12-10 | BLOCKED (waiting on AdvisoryAI payload notes + Orchestrator envelopes) |
|
||||
| 160.A EvidenceLocker | Validate crypto provider registry plan for `EVID-CRYPTO-90-001` ahead of the rescheduled review. | Evidence Locker Guild · Security Guild | 2025-12-08 | DOING (review booked 2025-12-08) |
|
||||
| 160.A EvidenceLocker | Prep CLI + ops teams for replay handoff (`RUNBOOK-REPLAY-187-004`, `CLI-REPLAY-187-002`) once Evidence Locker APIs are drafted. | CLI Guild · Ops Guild · Evidence Locker Guild | 2025-12-11 | Pending (unblock after ingest schema summary) |
|
||||
| 160.B ExportCenter | Prepare DevPortal verification CLI prototype (`DVOFF-64-002`) covering manifest hash + DSSE verification flow. | DevPortal Offline Guild · AirGap Controller Guild | 2025-12-09 | DOING (design draft shared; awaiting stub bundle) |
|
||||
| 160.B ExportCenter | Align attestation bundle job + CLI verbs (`EXPORT-ATTEST-74/75`) with EvidenceLocker DSSE layout once published. | Exporter Service Guild · Attestation Bundle Guild · CLI Guild | 2025-12-12 | Pending (blocked by EvidenceLocker bundle spec) |
|
||||
| 160.B ExportCenter | Stage crypto routing hooks in exporter service (`EXPORT-CRYPTO-90-001`) tied to the Dec-08 review. | Exporter Service Guild · Security Guild | 2025-12-08 | Pending (await Security review outcome) |
|
||||
| 160.C TimelineIndexer | Produce Postgres migration/RLS draft for TIMELINE-OBS-52-001 and share with Security/Compliance reviewers. | Timeline Indexer Guild · Security Guild | 2025-11-18 | DONE (2025-11-30) |
|
||||
| 160.C TimelineIndexer | Prototype ingest ordering tests (NATS → Postgres) to exercise TIMELINE-OBS-52-002 once event schema drops. | Timeline Indexer Guild | 2025-11-19 | DONE (2025-12-03) |
|
||||
| 160.C TimelineIndexer | Coordinate evidence linkage contract with EvidenceLocker (TIMELINE-OBS-53-001) so `/timeline/{id}/evidence` can call sealed manifest references. | Timeline Indexer Guild · Evidence Locker Guild | 2025-12-10 | BLOCKED (awaiting manifest references from EvidenceLocker) |
|
||||
| CROSS | Capture AdvisoryAI + Orchestrator ETA responses and log in Sprint 110/150/140 + this sprint. | Planning · AdvisoryAI Guild · Orchestrator/Notifications Guild | 2025-12-06 | DOING (re-escalated 2025-12-04) |
|
||||
| AGENTS-implplan | Create `docs/implplan/AGENTS.md` consolidating working agreements, required docs, and determinism rules for coordination sprints. | Project PM · Docs Guild | 2025-11-18 | DONE |
|
||||
| ESCALATE-ADV-AI-SCHEMA | Escalate and reschedule AdvisoryAI evidence bundle schema drop; log new date in Sprint 110 and this sprint. | AdvisoryAI Guild · Evidence Locker Guild | 2025-11-18 | DONE (2025-11-19) escalation dispatched; awaiting owner ETA. |
|
||||
| ESCALATE-ORCH-ENVELOPE | Escalate Orchestrator/Notifications capsule envelope drop; obtain new ETA and log in Sprint 150/140 and this sprint. | Orchestrator Service · Notifications Guild | 2025-11-18 | DONE (2025-11-19) escalation dispatched; awaiting owner ETA. |
|
||||
@@ -141,12 +141,12 @@
|
||||
| Naming & template alignment | DONE (2025-11-17) | File renamed to `SPRINT_0160_0001_0001_export_evidence.md` and normalized to standard sprint template. |
|
||||
| AdvisoryAI schema freeze | BLOCKED | Must land before EvidenceLocker/ExportCenter DOING moves; track in Interlocks and Sprint 110. |
|
||||
| Orchestrator/Notifications envelopes | BLOCKED | Required for EvidenceLocker ingest, ExportCenter notifications, and TimelineIndexer ordering. |
|
||||
| Crypto routing design readiness | BLOCKED | Await 2025-11-18 review to green-light `ICryptoProviderRegistry` wiring (`EVID-CRYPTO-90-001`, `EXPORT-CRYPTO-90-001`). |
|
||||
| Crypto routing design readiness | BLOCKED | Review slipped; rescheduled to 2025-12-08 to green-light `ICryptoProviderRegistry` wiring (`EVID-CRYPTO-90-001`, `EXPORT-CRYPTO-90-001`). |
|
||||
| Risks | See table below | Retained from prior snapshot. |
|
||||
| AGENTS.md for docs/implplan | DONE | `docs/implplan/AGENTS.md` added (2025-11-17); read before editing sprint docs. |
|
||||
| AdvisoryAI schema checkpoint (2025-11-14) | OVERDUE | Reschedule required; tracked via `ESCALATE-ADV-AI-SCHEMA` action. |
|
||||
| Orchestrator/Notifications checkpoint (2025-11-15) | OVERDUE | Reschedule required; tracked via `ESCALATE-ORCH-ENVELOPE` action. |
|
||||
| Escalation responses | PENDING | Awaiting ETA confirmations from AdvisoryAI and Orchestrator/Notifications leads; follow-up due 2025-11-19 if no response. |
|
||||
| AdvisoryAI schema checkpoint (2025-11-14) | OVERDUE | Reschedule in progress; re-escalated 2025-12-04 with ETA ask for 2025-12-06. |
|
||||
| Orchestrator/Notifications checkpoint (2025-11-15) | OVERDUE | Reschedule in progress; re-escalated 2025-12-04 with ETA ask for 2025-12-06. |
|
||||
| Escalation responses | PENDING | Awaiting ETA confirmations from AdvisoryAI and Orchestrator/Notifications leads; next follow-up 2025-12-06 (steering escalation 2025-12-07 if silent). |
|
||||
|
||||
### Risk table
|
||||
| Risk | Impacted wave(s) | Severity | Mitigation / Owner |
|
||||
@@ -160,6 +160,7 @@
|
||||
## Execution Log
|
||||
| Date (UTC) | Update | Owner |
|
||||
| --- | --- | --- |
|
||||
| 2025-12-04 | Re-baselined Wave 160 status; added Dec-06/08/09/10 checkpoints, re-escalated schema/envelope ETAs, refreshed Action Tracker (Timeline tasks marked DONE). | Project PM |
|
||||
| 2025-11-30 | Marked ExportCenter and TimelineIndexer snapshot tasks BLOCKED pending AdvisoryAI + Orchestrator schemas and EvidenceLocker digest; no unblocked work in wave 160. | Implementer |
|
||||
| 2025-11-20 | Confirmed PREP-ORCHESTRATOR-NOTIFICATIONS-SCHEMA-HANDOF and PREP-ESCALATION-FOLLOW-UP-ADVISORYAI-ORCHESTR still unclaimed; moved both to DOING to proceed with Wave 150/140 escalations. | Planning |
|
||||
| 2025-11-20 | Published prep artefacts for P1–P3: security coordination (`docs/modules/evidence-locker/prep/2025-11-20-security-coordination.md`), orchestrator/notifications handoff (`docs/events/prep/2025-11-20-orchestrator-notifications-schema-handoff.md`), and escalation follow-up (`docs/events/prep/2025-11-20-advisoryai-orchestrator-followup.md`). Marked P1–P3 DONE. | Implementer |
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
| 4 | RUNBOOK-REPLAY-187-004 | BLOCKED | PREP-RUNBOOK-REPLAY-187-004-DEPENDS-ON-RETENT | Docs Guild · Ops Guild | Publish `/docs/runbooks/replay_ops.md` coverage for retention enforcement, RootPack rotation, verification drills. |
|
||||
| 5 | CRYPTO-REGISTRY-DECISION-161 | DONE | Decision recorded in `docs/security/crypto-registry-decision-2025-11-18.md`; publish contract defaults. | Security Guild · Evidence Locker Guild | Capture decision from 2025-11-18 review; emit changelog + reference implementation for downstream parity. |
|
||||
| 6 | EVID-CRYPTO-90-001 | DONE | Implemented; `MerkleTreeCalculator` now uses `ICryptoProviderRegistry` for sovereign crypto routing. | Evidence Locker Guild · Security Guild | Route hashing/signing/bundle encryption through `ICryptoProviderRegistry`/`ICryptoHash` for sovereign crypto providers. |
|
||||
| 7 | EVID-GAPS-161-007 | DOING (2025-12-04) | See EB1–EB10 plan `docs/modules/evidence-locker/eb-gaps-161-007-plan.md`; schemas + offline guide drafted. | Product Mgmt · Evidence Locker Guild · CLI Guild | Address EB1–EB10 from `docs/product-advisories/28-Nov-2025 - Evidence Bundle and Replay Contracts.md`: publish `bundle.manifest.schema.json` + `checksums.schema.json` (canonical JSON), hash/Merkle recipe doc, mandatory DSSE predicate/log policy, replay provenance block, chunking/CAS rules, incident-mode signed activation/exit, tenant isolation + redaction manifest, offline verifier script (`docs/modules/evidence-locker/verify-offline.md`), golden bundles/replay fixtures under `tests/EvidenceLocker/Bundles/Golden`, and SemVer/change-log updates. |
|
||||
| 7 | EVID-GAPS-161-007 | DOING (2025-12-04) | See EB1–EB10 plan `docs/modules/evidence-locker/eb-gaps-161-007-plan.md`; schemas + offline guide drafted. | Product Mgmt · Evidence Locker Guild · CLI Guild | Address EB1–EB10 from `docs/product-advisories/archived/27-Nov-2025-superseded/28-Nov-2025 - Evidence Bundle and Replay Contracts.md`: publish `bundle.manifest.schema.json` + `checksums.schema.json` (canonical JSON), hash/Merkle recipe doc, mandatory DSSE predicate/log policy, replay provenance block, chunking/CAS rules, incident-mode signed activation/exit, tenant isolation + redaction manifest, offline verifier script (`docs/modules/evidence-locker/verify-offline.md`), golden bundles/replay fixtures under `tests/EvidenceLocker/Bundles/Golden`, and SemVer/change-log updates. |
|
||||
|
||||
## Action Tracker
|
||||
| Action | Owner(s) | Due | Status |
|
||||
@@ -87,6 +87,7 @@
|
||||
| 2025-11-20 | Completed PREP-EVID-REPLAY-187-001, PREP-CLI-REPLAY-187-002, and PREP-RUNBOOK-REPLAY-187-004; published prep docs at `docs/modules/evidence-locker/replay-payload-contract.md`, `docs/modules/cli/guides/replay-cli-prep.md`, and `docs/runbooks/replay_ops_prep_187_004.md`. | Implementer |
|
||||
| 2025-11-20 | Added schema readiness and replay delivery prep notes for Evidence Locker Guild; see `docs/modules/evidence-locker/prep/2025-11-20-schema-readiness-blockers.md` and `.../2025-11-20-replay-delivery-sync.md`. Marked PREP-EVIDENCE-LOCKER-GUILD-BLOCKED-SCHEMAS-NO and PREP-EVIDENCE-LOCKER-GUILD-REPLAY-DELIVERY-GU DONE. | Implementer |
|
||||
| 2025-11-27 | Completed EVID-CRYPTO-90-001: Extended `ICryptoProviderRegistry` with `ContentHashing` capability and `ResolveHasher` method; created `ICryptoHasher` interface with `DefaultCryptoHasher` implementation; wired `MerkleTreeCalculator` to use crypto registry for sovereign crypto routing; added `EvidenceCryptoOptions` for algorithm/provider configuration. | Implementer |
|
||||
| 2025-12-01 | Added EVID-GAPS-161-007 to capture EB1–EB10 remediation from `docs/product-advisories/28-Nov-2025 - Evidence Bundle and Replay Contracts.md`. | Product Mgmt |
|
||||
| 2025-12-01 | Added EVID-GAPS-161-007 to capture EB1–EB10 remediation from `docs/product-advisories/archived/27-Nov-2025-superseded/28-Nov-2025 - Evidence Bundle and Replay Contracts.md`. | Product Mgmt |
|
||||
| 2025-12-02 | Scoped EVID-GAPS-161-007 deliverables: schemas + DSSE, Merkle recipe, replay provenance, chunk/CAS rules, incident governance, tenant redaction, offline verifier doc, golden fixtures path, and SemVer/change-log updates. | Project Mgmt |
|
||||
| 2025-12-04 | Moved EVID-GAPS-161-007 to DOING; drafted EB1/EB2 schemas, offline verifier guide, gap plan, and golden fixtures path. | Project Mgmt |
|
||||
| 2025-12-04 | Updated attestation, replay, incident-mode docs with DSSE subject=Merkle root, log policy, replay provenance block, and signed incident toggles; added CAS/Merkle rules to bundle packaging. | Implementer |
|
||||
|
||||
@@ -34,12 +34,12 @@
|
||||
| 11 | NOTIFY-RISK-68-001 | BLOCKED (2025-11-22) | Depends on 67-001. | Notifications Service Guild | Per-profile routing, quiet hours, dedupe for risk alerts; integrate CLI/Console preferences. |
|
||||
| 12 | NOTIFY-DOC-70-001 | DONE (2025-11-02) | — | Notifications Service Guild | Document split between legacy `src/Notify` libs and new `src/Notifier` runtime; update architecture docs. |
|
||||
| 13 | NOTIFY-AIRGAP-56-002 | DONE | — | Notifications Service Guild · DevOps Guild | Bootstrap Pack notifier configs with deterministic secrets handling and offline validation. |
|
||||
| 14 | NOTIFY-GAPS-171-014 | BLOCKED (2025-12-04) | Waiting on NR1–NR10 details in `31-Nov-2025 FINDINGS.md` + schema/catalog refresh | Notifications Service Guild / src/Notifier/StellaOps.Notifier | Remediate NR1–NR10: publish signed schemas + canonical JSON, enforce tenant scoping/approvals, deterministic rendering, quotas/backpressure + DLQ, retry/idempotency policy, webhook/ack security, redaction/PII limits, observability SLO alerts, offline notify-kit with DSSE, and mandatory simulations + evidence for rule/template changes. |
|
||||
| 14 | NOTIFY-GAPS-171-014 | TODO | NR1–NR10 defined in `31-Nov-2025 FINDINGS.md` + `docs/notifications/gaps-nr1-nr10.md`; implement schema/catalog + evidence bundle | Notifications Service Guild / src/Notifier/StellaOps.Notifier | Remediate NR1–NR10: publish signed schemas + canonical JSON, enforce tenant scoping/approvals, deterministic rendering, quotas/backpressure + DLQ, retry/idempotency policy, webhook/ack security, redaction/PII limits, observability SLO alerts, offline notify-kit with DSSE, and mandatory simulations + evidence for rule/template changes. |
|
||||
|
||||
## Execution Log
|
||||
| Date (UTC) | Update | Owner |
|
||||
| --- | --- | --- |
|
||||
| 2025-12-04 | Marked NOTIFY-GAPS-171-014 BLOCKED pending publication of NR1–NR10 details in `31-Nov-2025 FINDINGS.md` and schema/catalog refresh. | Implementer |
|
||||
| 2025-12-04 | Authored NR1–NR10 section and blueprint (`docs/notifications/gaps-nr1-nr10.md`); unblocked NOTIFY-GAPS-171-014 and set status to TODO. | Implementer |
|
||||
| 2025-11-19 | Fixed PREP-NOTIFY-OBS-51-001 Task ID (removed trailing hyphen) so dependency lookup works. | Project Mgmt |
|
||||
| 2025-12-01 | Added NOTIFY-GAPS-171-014 (NR1–NR10 from `31-Nov-2025 FINDINGS.md`) to track advisory gap remediation; status TODO pending schema/catalog refresh. | Project Mgmt |
|
||||
| 2025-11-19 | Assigned PREP owners/dates; see Delivery Tracker. | Planning |
|
||||
@@ -72,7 +72,7 @@
|
||||
- Risk alerts depend on POLICY-RISK-40-002 export; schedule slip would re-baseline RISK tasks.
|
||||
- Keep Offline Kit parity for templates and secrets handling before enabling new endpoints.
|
||||
- Advisory gap remediation (NR1–NR10) added as NOTIFY-GAPS-171-014; requires schema/catalog refresh, tenant/approval enforcement, deterministic rendering, quotas/backpressure/DLQ, retry/idempotency policy, webhook/ack security, redaction/PII limits, observability SLO alerts, offline notify-kit with DSSE, and mandatory simulation evidence before activation.
|
||||
- NOTIFY-GAPS-171-014 is currently blocked because NR1–NR10 findings are not yet defined in `31-Nov-2025 FINDINGS.md`; schema/catalog refresh must accompany that publication before remediation can start.
|
||||
- NOTIFY-GAPS-171-014 now scoped (see `docs/product-advisories/31-Nov-2025 FINDINGS.md` + `docs/notifications/gaps-nr1-nr10.md`); remediation requires publishing the schema catalog + DSSE, redaction/approval/observability docs, and offline notify-kit artefacts.
|
||||
|
||||
## Next Checkpoints
|
||||
| Date (UTC) | Milestone | Owner(s) |
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
- Phase I UI uplift for Experience & SDKs: AOC dashboards, Exception Center, Graph Explorer, determinism and entropy surfacing.
|
||||
- Keep UI aligned with new scopes, policy gating, and determinism evidence while preserving accessibility and performance baselines.
|
||||
- Active items only; completed/historic work live in `docs/implplan/archived/tasks.md` (updated 2025-11-08).
|
||||
- **Working directory:** `src/UI/StellaOps.UI`.
|
||||
- **Working directory:** `src/Web/StellaOps.Web`.
|
||||
|
||||
## Dependencies & Concurrency
|
||||
- Upstream sprints: 120.A AirGap, 130.A Scanner, 150.A Orchestrator, 170.A Notifier.
|
||||
@@ -28,26 +28,26 @@
|
||||
## Delivery Tracker
|
||||
| # | Task ID | Status | Key dependency / next step | Owners | Task Definition |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 1 | UI-AOC-19-001 | DONE | Align tiles with AOC service metrics | UI Guild (src/UI/StellaOps.UI) | Add Sources dashboard tiles showing AOC pass/fail, recent violation codes, and ingest throughput per tenant. |
|
||||
| 2 | UI-AOC-19-002 | DONE | UI-AOC-19-001 | UI Guild (src/UI/StellaOps.UI) | Implement violation drill-down view highlighting offending document fields and provenance metadata. |
|
||||
| 3 | UI-AOC-19-003 | DONE | UI-AOC-19-002 | UI Guild (src/UI/StellaOps.UI) | Add "Verify last 24h" action triggering AOC verifier endpoint and surfacing CLI parity guidance. |
|
||||
| 4 | UI-EXC-25-001 | DONE | - | UI Guild; Governance Guild (src/UI/StellaOps.UI) | Build Exception Center (list + kanban) with filters, sorting, workflow transitions, and audit views. |
|
||||
| 5 | UI-EXC-25-002 | DONE | UI-EXC-25-001 | UI Guild (src/UI/StellaOps.UI) | Implement exception creation wizard with scope preview, justification templates, timebox guardrails. |
|
||||
| 6 | UI-EXC-25-003 | DONE | UI-EXC-25-002 | UI Guild (src/UI/StellaOps.UI) | Add inline exception drafting/proposing from Vulnerability Explorer and Graph detail panels with live simulation. |
|
||||
| 7 | UI-EXC-25-004 | DONE | UI-EXC-25-003 | UI Guild (src/UI/StellaOps.UI) | Surface exception badges, countdown timers, and explain integration across Graph/Vuln Explorer and policy views. |
|
||||
| 8 | UI-EXC-25-005 | DONE | UI-EXC-25-004 | UI Guild; Accessibility Guild (src/UI/StellaOps.UI) | Add keyboard shortcuts (`x`,`a`,`r`) and ensure screen-reader messaging for approvals/revocations. |
|
||||
| 9 | UI-GRAPH-21-001 | DONE | Shared `StellaOpsScopes` exports ready | UI Guild (src/UI/StellaOps.UI) | Align Graph Explorer auth configuration with new `graph:*` scopes; consume scope identifiers from shared `StellaOpsScopes` exports (via generated SDK/config) instead of hard-coded strings. |
|
||||
| 10 | UI-GRAPH-24-001 | BLOCKED | Missing Angular workspace and generated SDK scopes (`graph:*`); cannot render canvas without project skeleton. | UI Guild; SBOM Service Guild (src/UI/StellaOps.UI) | Build Graph Explorer canvas with layered/radial layouts, virtualization, zoom/pan, and scope toggles; initial render <1.5s for sample asset. |
|
||||
| 11 | UI-GRAPH-24-002 | BLOCKED | Upstream 24-001 blocked; overlays depend on canvas + policy data contracts. | UI Guild; Policy Guild (src/UI/StellaOps.UI) | Implement overlays (Policy, Evidence, License, Exposure), simulation toggle, path view, and SBOM diff/time-travel with accessible tooltips/AOC indicators. |
|
||||
| 12 | UI-GRAPH-24-003 | BLOCKED | Upstream 24-002 blocked; workspace absent so filters/permalinks cannot be wired. | UI Guild (src/UI/StellaOps.UI) | Deliver filters/search panel with facets, saved views, permalinks, and share modal. |
|
||||
| 13 | UI-GRAPH-24-004 | BLOCKED | Upstream 24-003 blocked; side panels require base canvas + filters. | UI Guild (src/UI/StellaOps.UI) | Add side panels (Details, What-if, History) with upgrade simulation integration and SBOM diff viewer. |
|
||||
| 14 | UI-GRAPH-24-006 | BLOCKED | Upstream graph tasks blocked; accessibility/hotkeys depend on canvas implementation. | UI Guild; Accessibility Guild (src/UI/StellaOps.UI) | Ensure accessibility (keyboard nav, screen reader labels, contrast), add hotkeys (`f`,`e`,`.`), and analytics instrumentation. |
|
||||
| 15 | UI-LNM-22-001 | DONE | - | UI Guild; Policy Guild (src/UI/StellaOps.UI) | Build Evidence panel showing policy decision with advisory observations/linksets side-by-side, conflict badges, AOC chain, and raw doc download links (DOCS-LNM-22-005 awaiting UI screenshots/flows). |
|
||||
| 16 | UI-SBOM-DET-01 | DONE | - | UI Guild (src/UI/StellaOps.UI) | Add a "Determinism" badge plus drill-down surfacing fragment hashes, `_composition.json`, and Merkle root consistency when viewing scan details. |
|
||||
| 17 | UI-POLICY-DET-01 | DONE | UI-SBOM-DET-01 | UI Guild; Policy Guild (src/UI/StellaOps.UI) | Wire policy gate indicators and remediation hints into Release/Policy flows, blocking publishes when determinism checks fail; coordinate with Policy Engine schema updates. |
|
||||
| 18 | UI-ENTROPY-40-001 | DONE | - | UI Guild (src/UI/StellaOps.UI) | Visualise entropy analysis per image (layer donut, file heatmaps, "Why risky?" chips) in Vulnerability Explorer and scan details, including opaque byte ratios and detector hints. |
|
||||
| 19 | UI-ENTROPY-40-002 | DONE | UI-ENTROPY-40-001 | UI Guild; Policy Guild (src/UI/StellaOps.UI) | Add policy banners/tooltips explaining entropy penalties (block/warn thresholds, mitigation steps) and link to raw `entropy.report.json` evidence downloads. |
|
||||
| 20 | UI-MICRO-GAPS-0209-011 | BLOCKED | Canonical 30-Nov-2025 UI Micro-Interactions advisory missing; Angular workspace absent; requires token catalog and a11y test harness | UI Guild; UX Guild; Accessibility Guild | Close MI1–MI10: define motion tokens + reduced-motion rules, perf budgets, offline/latency/error patterns, component mapping, telemetry schema/flags, deterministic seeds/snapshots, micro-copy localisation, and theme/contrast guidance; add Storybook/Playwright checks. |
|
||||
| 1 | UI-AOC-19-001 | DONE | Align tiles with AOC service metrics | UI Guild (src/Web/StellaOps.Web) | Add Sources dashboard tiles showing AOC pass/fail, recent violation codes, and ingest throughput per tenant. |
|
||||
| 2 | UI-AOC-19-002 | DONE | UI-AOC-19-001 | UI Guild (src/Web/StellaOps.Web) | Implement violation drill-down view highlighting offending document fields and provenance metadata. |
|
||||
| 3 | UI-AOC-19-003 | DONE | UI-AOC-19-002 | UI Guild (src/Web/StellaOps.Web) | Add "Verify last 24h" action triggering AOC verifier endpoint and surfacing CLI parity guidance. |
|
||||
| 4 | UI-EXC-25-001 | DONE | - | UI Guild; Governance Guild (src/Web/StellaOps.Web) | Build Exception Center (list + kanban) with filters, sorting, workflow transitions, and audit views. |
|
||||
| 5 | UI-EXC-25-002 | DONE | UI-EXC-25-001 | UI Guild (src/Web/StellaOps.Web) | Implement exception creation wizard with scope preview, justification templates, timebox guardrails. |
|
||||
| 6 | UI-EXC-25-003 | DONE | UI-EXC-25-002 | UI Guild (src/Web/StellaOps.Web) | Add inline exception drafting/proposing from Vulnerability Explorer and Graph detail panels with live simulation. |
|
||||
| 7 | UI-EXC-25-004 | DONE | UI-EXC-25-003 | UI Guild (src/Web/StellaOps.Web) | Surface exception badges, countdown timers, and explain integration across Graph/Vuln Explorer and policy views. |
|
||||
| 8 | UI-EXC-25-005 | DONE | UI-EXC-25-004 | UI Guild; Accessibility Guild (src/Web/StellaOps.Web) | Add keyboard shortcuts (`x`,`a`,`r`) and ensure screen-reader messaging for approvals/revocations. |
|
||||
| 9 | UI-GRAPH-21-001 | DONE | Shared `StellaOpsScopes` exports ready | UI Guild (src/Web/StellaOps.Web) | Align Graph Explorer auth configuration with new `graph:*` scopes; consume scope identifiers from shared `StellaOpsScopes` exports (via generated SDK/config) instead of hard-coded strings. |
|
||||
| 10 | UI-GRAPH-24-001 | BLOCKED | Awaiting generated `graph:*` scope SDK exports (SPRINT_0208_0001_0001_sdk); canvas perf tuning pending until scopes land. | UI Guild; SBOM Service Guild (src/Web/StellaOps.Web) | Build Graph Explorer canvas with layered/radial layouts, virtualization, zoom/pan, and scope toggles; initial render <1.5s for sample asset. |
|
||||
| 11 | UI-GRAPH-24-002 | BLOCKED | Upstream 24-001 blocked; overlays depend on canvas + policy data contracts. | UI Guild; Policy Guild (src/Web/StellaOps.Web) | Implement overlays (Policy, Evidence, License, Exposure), simulation toggle, path view, and SBOM diff/time-travel with accessible tooltips/AOC indicators. |
|
||||
| 12 | UI-GRAPH-24-003 | BLOCKED | Upstream 24-002 blocked; filters/permalinks follow canvas + SDK scope availability. | UI Guild (src/Web/StellaOps.Web) | Deliver filters/search panel with facets, saved views, permalinks, and share modal. |
|
||||
| 13 | UI-GRAPH-24-004 | BLOCKED | Upstream 24-003 blocked; side panels require base canvas + filters. | UI Guild (src/Web/StellaOps.Web) | Add side panels (Details, What-if, History) with upgrade simulation integration and SBOM diff viewer. |
|
||||
| 14 | UI-GRAPH-24-006 | BLOCKED | Upstream graph tasks blocked; accessibility/hotkeys depend on canvas implementation. | UI Guild; Accessibility Guild (src/Web/StellaOps.Web) | Ensure accessibility (keyboard nav, screen reader labels, contrast), add hotkeys (`f`,`e`,`.`), and analytics instrumentation. |
|
||||
| 15 | UI-LNM-22-001 | DONE | - | UI Guild; Policy Guild (src/Web/StellaOps.Web) | Build Evidence panel showing policy decision with advisory observations/linksets side-by-side, conflict badges, AOC chain, and raw doc download links (DOCS-LNM-22-005 awaiting UI screenshots/flows). |
|
||||
| 16 | UI-SBOM-DET-01 | DONE | - | UI Guild (src/Web/StellaOps.Web) | Add a "Determinism" badge plus drill-down surfacing fragment hashes, `_composition.json`, and Merkle root consistency when viewing scan details. |
|
||||
| 17 | UI-POLICY-DET-01 | DONE | UI-SBOM-DET-01 | UI Guild; Policy Guild (src/Web/StellaOps.Web) | Wire policy gate indicators and remediation hints into Release/Policy flows, blocking publishes when determinism checks fail; coordinate with Policy Engine schema updates. |
|
||||
| 18 | UI-ENTROPY-40-001 | DONE | - | UI Guild (src/Web/StellaOps.Web) | Visualise entropy analysis per image (layer donut, file heatmaps, "Why risky?" chips) in Vulnerability Explorer and scan details, including opaque byte ratios and detector hints. |
|
||||
| 19 | UI-ENTROPY-40-002 | DONE | UI-ENTROPY-40-001 | UI Guild; Policy Guild (src/Web/StellaOps.Web) | Add policy banners/tooltips explaining entropy penalties (block/warn thresholds, mitigation steps) and link to raw `entropy.report.json` evidence downloads. |
|
||||
| 20 | UI-MICRO-GAPS-0209-011 | BLOCKED | Canonical 30-Nov-2025 UI Micro-Interactions advisory published; still need motion token catalog plus a11y/Storybook/Playwright harness in `src/Web/StellaOps.Web`. | UI Guild; UX Guild; Accessibility Guild | Close MI1–MI10: define motion tokens + reduced-motion rules, perf budgets, offline/latency/error patterns, component mapping, telemetry schema/flags, deterministic seeds/snapshots, micro-copy localisation, and theme/contrast guidance; add Storybook/Playwright checks. |
|
||||
|
||||
## Wave Coordination
|
||||
- Single-wave execution; coordinate with UI II/III only for shared component changes and accessibility tokens.
|
||||
@@ -62,20 +62,20 @@
|
||||
- Scanner entropy and determinism evidence formats for UI-ENTROPY-* and UI-SBOM-DET-01.
|
||||
- AOC verifier endpoint parity for UI-AOC-19-003.
|
||||
|
||||
## Upcoming Checkpoints
|
||||
## Next Checkpoints
|
||||
- 2025-11-29 15:00 UTC - UI/Graph scopes handoff review (owners: UI Guild, Graph owner).
|
||||
- 2025-12-04 16:00 UTC - Policy determinism UI enablement go/no-go (owners: UI Guild, Policy Guild).
|
||||
|
||||
## Action Tracker
|
||||
| # | Action | Owner | Due | Status |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 1 | Confirm `StellaOpsScopes` export availability for UI-GRAPH-21-001 | UI Guild | 2025-11-29 | BLOCKED (missing Angular workspace/SDK outputs) |
|
||||
| 2 | Align Policy Engine determinism schema changes for UI-POLICY-DET-01 | Policy Guild | 2025-12-03 | BLOCKED (workspace absent; awaiting determinism schema freeze) |
|
||||
| 3 | Deliver entropy evidence fixture snapshot for UI-ENTROPY-40-001 | Scanner Guild | 2025-11-28 | BLOCKED (fixtures unavailable locally; workspace missing) |
|
||||
| 4 | Provide AOC verifier endpoint parity notes for UI-AOC-19-003 | Notifier Guild | 2025-11-27 | BLOCKED (UI workspace unavailable to consume parity notes) |
|
||||
| 5 | Receive SDK parity matrix (Wave B, SPRINT_0208_0001_0001_sdk) to unblock Console data providers and scope exports | UI Guild · SDK Generator Guild | 2025-12-16 | BLOCKED (awaiting SDK parity delivery + workspace restore) |
|
||||
| 6 | Publish canonical UI Micro-Interactions advisory (MI1–MI10) with motion tokens, reduced-motion rules, and fixtures referenced by this sprint | Product Mgmt · UX Guild | 2025-12-06 | TODO |
|
||||
| 7 | Restore Angular workspace under `src/UI/StellaOps.UI` to enable Storybook/Playwright harness and token catalog | UI Guild | 2025-12-05 | TODO |
|
||||
| 1 | Confirm `StellaOpsScopes` export availability for UI-GRAPH-21-001 | UI Guild | 2025-11-29 | BLOCKED (awaiting generated `graph:*` SDK scope exports from SPRINT_0208_0001_0001_sdk) |
|
||||
| 2 | Align Policy Engine determinism schema changes for UI-POLICY-DET-01 | Policy Guild | 2025-12-03 | BLOCKED (awaiting determinism schema freeze) |
|
||||
| 3 | Deliver entropy evidence fixture snapshot for UI-ENTROPY-40-001 | Scanner Guild | 2025-11-28 | BLOCKED (fixtures unavailable locally) |
|
||||
| 4 | Provide AOC verifier endpoint parity notes for UI-AOC-19-003 | Notifier Guild | 2025-11-27 | BLOCKED (parity notes pending delivery) |
|
||||
| 5 | Receive SDK parity matrix (Wave B, SPRINT_0208_0001_0001_sdk) to unblock Console data providers and scope exports | UI Guild · SDK Generator Guild | 2025-12-16 | BLOCKED (awaiting SDK parity delivery) |
|
||||
| 6 | Publish canonical UI Micro-Interactions advisory (MI1–MI10) with motion tokens, reduced-motion rules, and fixtures referenced by this sprint | Product Mgmt · UX Guild | 2025-12-06 | DONE |
|
||||
| 7 | Align sprint working directory to `src/Web/StellaOps.Web` and verify workspace present (was `src/UI/StellaOps.UI`) | UI Guild | 2025-12-05 | DONE (2025-12-04) |
|
||||
|
||||
## Decisions & Risks
|
||||
| Risk | Impact | Mitigation / Next Step |
|
||||
@@ -83,14 +83,16 @@
|
||||
| Graph scope exports slip | Blocks UI-GRAPH-21-001 -> UI-GRAPH-24-006 chain | Track via Action #1; stub scopes via generated SDK if needed. |
|
||||
| Policy determinism schema changes late | UI-POLICY-DET-01 cannot ship with gates | Coordinate with Policy Engine owners (Action #2) and keep UI feature-flagged. |
|
||||
| Entropy evidence format changes | Rework for UI-ENTROPY-* views | Lock to `docs/modules/scanner/entropy.md`; add contract test fixtures before UI wiring. |
|
||||
| Angular workspace missing | UI-GRAPH-24-* blocked | Restore Angular workspace under `src/UI/StellaOps.UI` and deliver generated `graph:*` scope exports before continuing Graph UI work. |
|
||||
| Canonical UI Micro-Interactions advisory missing | UI-MICRO-GAPS-0209-011 cannot be scoped; MI1–MI10 acceptance unclear | Action #6 to publish advisory; keep task BLOCKED until canonical document and fixtures land. |
|
||||
| Working directory mismatch (UI vs Web) causes contributors to edit wrong path | Duplicate effort or missing workspace for new tasks | Sprint now points to `src/Web/StellaOps.Web`; Action #7 closed; broadcast path in AGENTS/TASKS updates. |
|
||||
| Micro-interaction implementation inputs incomplete | UI-MICRO-GAPS-0209-011 blocked on motion token catalog + a11y/Storybook/Playwright harness despite advisory availability | Keep Action #6 closed; open follow-on tasks for token catalog + harness once SDK scopes land. |
|
||||
|
||||
## Execution Log
|
||||
| Date (UTC) | Update | Owner |
|
||||
| --- | --- | --- |
|
||||
| 2025-12-04 | Began UI-MICRO-GAPS-0209-011; canonical 30-Nov-2025 UI Micro-Interactions advisory is missing and Angular workspace `src/UI/StellaOps.UI` is empty. Marked task BLOCKED; added Actions #6–#7 to publish advisory and restore workspace before scoping MI1–MI10 tokens/tests. | Project mgmt |
|
||||
| 2025-12-03 | Marked UI-GRAPH-24-001/002/003/004/006 BLOCKED: Angular workspace is absent under `src/UI/StellaOps.UI` and generated `graph:*` scope SDK exports are missing; cannot render canvas or overlays until workspace and SDK parity land. | Implementer |
|
||||
| 2025-12-04 | Confirmed canonical Angular workspace is `src/Web/StellaOps.Web` (not `src/UI/StellaOps.UI`); updated working directory, blockers, and Action #7 accordingly. Graph blockers now tied to generated `graph:*` SDK scopes. | Project mgmt |
|
||||
| 2025-12-04 | Published canonical UI Micro-Interactions advisory (`docs/product-advisories/30-Nov-2025 - UI Micro-Interactions for StellaOps.md`). UI-MICRO-GAPS-0209-011 remains BLOCKED pending motion token catalog + a11y/Storybook/Playwright harness in `src/Web/StellaOps.Web`. | Project mgmt |
|
||||
| 2025-12-04 | Earlier note: UI-MICRO-GAPS-0209-011 was marked BLOCKED when advisory was still pending and `src/UI/StellaOps.UI` was empty; superseded by publication + path correction the same day. | Project mgmt |
|
||||
| 2025-12-03 | Marked UI-GRAPH-24-001/002/003/004/006 BLOCKED: UI path was empty and `graph:*` scope SDK exports were missing; will re-evaluate after path correction and SDK delivery. | Implementer |
|
||||
| 2025-11-27 | UI-GRAPH-21-001: Created stub `StellaOpsScopes` exports and integrated auth configuration into Graph Explorer. Created `scopes.ts` with: typed scope constants (`GRAPH_READ`, `GRAPH_WRITE`, `GRAPH_ADMIN`, `GRAPH_EXPORT`, `GRAPH_SIMULATE` and scopes for SBOM, Scanner, Policy, Exception, Release, AOC, Admin domains), scope groupings (`GRAPH_VIEWER`, `GRAPH_EDITOR`, `GRAPH_ADMIN`, `RELEASE_MANAGER`, `SECURITY_ADMIN`), human-readable labels, and helper functions (`hasScope`, `hasAllScopes`, `hasAnyScope`). Created `auth.service.ts` with `AuthService` interface and `MockAuthService` implementation providing: user info with tenant context, scope-based permission methods (`canViewGraph`, `canEditGraph`, `canExportGraph`, `canSimulate`). Integrated into `GraphExplorerComponent` via `AUTH_SERVICE` injection token: added computed signals for scope-based permissions (`canViewGraph`, `canEditGraph`, `canExportGraph`, `canSimulate`, `canCreateException`), current user info, and user scopes list. Stub implementation allows Graph Explorer development to proceed; will be replaced by generated SDK exports from SPRINT_0208_0001_0001_sdk. Files added: `src/app/core/auth/scopes.ts`, `src/app/core/auth/auth.service.ts`, `src/app/core/auth/index.ts`. Files updated: `graph-explorer.component.ts`. | UI Guild |
|
||||
| 2025-11-27 | UI-AOC-19-001/002/003: Implemented Sources dashboard with AOC metrics tiles, violation drill-down, and "Verify last 24h" action. Created domain models (`aoc.models.ts`) for AocDashboardSummary, AocPassFailSummary, AocViolationCode, IngestThroughput, AocSource, AocCheckResult, VerificationRequest, ViolationDetail, OffendingField, and ProvenanceMetadata. Created mock API service (`aoc.client.ts`) with fixtures showing pass/fail metrics, 5 violation codes (AOC-001 through AOC-020), 4 tenant throughput records, 4 sources (registry, pipeline, manual), and sample check results. Built `AocDashboardComponent` (`/sources` route) with 3 tiles: (1) Pass/Fail tile with large pass rate percentage, trend indicator (improving/stable/degrading), mini 7-day chart, passed/failed/pending counts; (2) Recent Violations tile with severity badges, violation codes, names, counts, and modal detail view; (3) Ingest Throughput tile with total documents/bytes and per-tenant breakdown table. Added Sources section showing source cards with type icons, pass rates, recent violation chips, and last check time. Implemented "Verify Last 24h" button triggering verification endpoint with progress feedback and CLI parity command display (`stella aoc verify --since 24h --output json`). Created `ViolationDetailComponent` (`/sources/violations/:code` route) showing all occurrences of a violation code with: offending fields list (JSON path, expected vs actual values, reason), provenance metadata (source type/URI, build ID, commit SHA, pipeline URL), and suggested fix. Files added: `src/app/core/api/aoc.{models,client}.ts`, `src/app/features/sources/aoc-dashboard.component.{ts,html,scss}`, `violation-detail.component.ts`, `index.ts`. Routes registered at `/sources` and `/sources/violations/:code`. | UI Guild |
|
||||
| 2025-11-27 | UI-POLICY-DET-01: Implemented Release flow with policy gate indicators and remediation hints for determinism blocking. Created domain models (`release.models.ts`) for Release, ReleaseArtifact, PolicyEvaluation, PolicyGateResult, RemediationHint, RemediationStep, and DeterminismFeatureFlags. Created mock API service (`release.client.ts`) with fixtures for passing/blocked/mixed releases showing determinism gate scenarios. Built `ReleaseFlowComponent` (`/releases` route) with list/detail views: list shows release cards with gate status pips and blocking indicators; detail view shows artifact tabs, policy gate evaluations, determinism evidence (Merkle root, fragment verification count, failed layers), and publish/bypass actions. Created `PolicyGateIndicatorComponent` with expandable gate details, status icons, blocking badges, and feature flag info display. Created `RemediationHintsComponent` with severity badges, estimated effort, numbered remediation steps with CLI commands (copy-to-clipboard), documentation links, automated action buttons, and exception request option. Feature-flagged via `DeterminismFeatureFlags` (blockOnFailure, warnOnly, bypassRoles). Bypass modal allows requesting exceptions with justification. Files added: `src/app/core/api/release.{models,client}.ts`, `src/app/features/releases/release-flow.component.{ts,html,scss}`, `policy-gate-indicator.component.ts`, `remediation-hints.component.ts`, `index.ts`. Routes registered at `/releases` and `/releases/:releaseId`. | UI Guild |
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
| 4 | WEB-AOC-19-002 | DONE (2025-11-30) | Depends on WEB-AOC-19-001; align DSSE/CMS helper APIs. | BE-Base Platform Guild | Ship `ProvenanceBuilder`, checksum utilities, signature verification helper with tests. |
|
||||
| 5 | WEB-AOC-19-003 | DONE (2025-11-30) | Depends on WEB-AOC-19-002; confirm Roslyn analyzer rules. | QA Guild; BE-Base Platform Guild | Analyzer to prevent forbidden key writes; shared guard-validation fixtures. |
|
||||
| 6 | WEB-CONSOLE-23-001 | DONE (2025-11-28) | `/console/dashboard` and `/console/filters` endpoints implemented with tenant-scoped aggregates. | BE-Base Platform Guild; Product Analytics Guild | Tenant-scoped aggregates for findings, VEX overrides, advisory deltas, run health, policy change log. |
|
||||
| 7 | CONSOLE-VULN-29-001 | BLOCKED (2025-11-19) | Blocked on WEB-CONSOLE-23-001 contract and Concelier graph schema freeze. | Console Guild; BE-Base Platform Guild | `/console/vuln/*` workspace endpoints with filters/reachability badges and DTOs once schemas stabilize. |
|
||||
| 8 | CONSOLE-VEX-30-001 | BLOCKED (2025-11-19) | Blocked on WEB-CONSOLE-23-001 and Excititor console contract (SSE payload validation). | Console Guild; BE-Base Platform Guild | `/console/vex/events` SSE workspace with validated schemas and samples. |
|
||||
| 7 | CONSOLE-VULN-29-001 | BLOCKED (2025-12-04) | WEB-CONSOLE-23-001 shipped 2025-11-28; still waiting for Concelier graph schema snapshot from the 2025-12-03 freeze review before wiring `/console/vuln/*` endpoints. | Console Guild; BE-Base Platform Guild | `/console/vuln/*` workspace endpoints with filters/reachability badges and DTOs once schemas stabilize. |
|
||||
| 8 | CONSOLE-VEX-30-001 | BLOCKED (2025-12-04) | Excititor console contract delivered 2025-11-23; remain blocked on VEX Lens spec PLVL0103 + SSE payload validation notes from rescheduled 2025-12-04 alignment. | Console Guild; BE-Base Platform Guild | `/console/vex/events` SSE workspace with validated schemas and samples. |
|
||||
| 9 | WEB-CONSOLE-23-002 | DOING (2025-12-01) | Implementing frontend polling + SSE proxy; unit tests added. Remaining: wire route + verify against contract once backend snapshot lands. | BE-Base Platform Guild; Scheduler Guild | `/console/status` polling and `/console/runs/{id}/stream` SSE/WebSocket proxy with queue lag metrics. |
|
||||
| 10 | WEB-CONSOLE-23-003 | TODO | Depends on WEB-CONSOLE-23-002; confirm bundle orchestration flow. | BE-Base Platform Guild; Policy Guild | `/console/exports` POST/GET for evidence bundles, streaming CSV/JSON, checksum manifest, signed attestations. |
|
||||
| 11 | WEB-CONSOLE-23-004 | TODO | Depends on WEB-CONSOLE-23-003; set caching and tie-break order. | BE-Base Platform Guild | `/console/search` fan-out with deterministic ranking and result caps. |
|
||||
@@ -54,16 +54,17 @@
|
||||
- 2025-12-04 (rescheduled): Scheduler/Signals alignment on SSE topics + heartbeat/backoff defaults for WEB-CONSOLE-23-002.
|
||||
|
||||
## Action Tracker
|
||||
- Concelier graph schema freeze outcome + published snapshot (owner: Console Guild; due: 2025-12-02; status: follow-up for missed 2025-11-25 review).
|
||||
- Excititor SSE payload validation and topic alignment session rebooked (owner: BE-Base Platform; due: 2025-12-04; status: rescheduled from 2025-11-27).
|
||||
- Concelier graph schema freeze outcome + published snapshot (owner: Console Guild; due: 2025-12-05; status: follow-up after missed 2025-12-03 review; keep CONSOLE-VULN-29-001 blocked until posted to `docs/api/console/workspaces.md`).
|
||||
- Excititor SSE payload validation and topic alignment session rebooked (owner: BE-Base Platform; due: 2025-12-05; status: awaiting 2025-12-04 notes; required for CONSOLE-VEX-30-001 envelope validation).
|
||||
- VEX Lens spec PLVL0103 + SSE envelope excerpt for console streams (owner: VEX Lens Guild; due: 2025-12-06; status: new action to unblock CONSOLE-VEX-30-001 and keep samples consistent across `docs/api/console/samples/`).
|
||||
- Advisory AI gateway policy/contract snapshot for `/advisory/ai/*` routes (owner: BE-Base Platform; due: 2025-12-05; status: new action to unblock WEB-AIAI-31-001/002/003).
|
||||
- Restore workspace disk/PTY availability so Web console implementation can proceed (owner: DevOps Guild; due: 2025-12-02; status: in progress 2025-12-01).
|
||||
|
||||
## Decisions & Risks
|
||||
| Risk | Impact | Mitigation | Owner | Status |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Console contract freeze slips past 2025-11-25 | Blocks CONSOLE-VULN-29-001 and CONSOLE-VEX-30-001, delays console workspaces | Rescheduled review to 2025-12-03; publish schema snapshot to `docs/api/console/workspaces.md`; keep blockers logged | Console Guild | Open (rescheduled 2025-11-30) |
|
||||
| SSE topic alignment delayed | WEB-CONSOLE-23-002/003/004 latency and reliability uncertain | Rescheduled alignment with Scheduler/Signals to 2025-12-04; add heartbeat/backoff defaults; capture examples in samples directory | BE-Base Platform Guild | Open (rescheduled 2025-11-30) |
|
||||
| Console contract freeze slips past 2025-11-25 | Blocks CONSOLE-VULN-29-001 and CONSOLE-VEX-30-001, delays console workspaces | 2025-12-03 review missed publishing snapshot; follow-up due 2025-12-05 with schema hash and sample payloads in `docs/api/console/workspaces.md`; keep tasks BLOCKED until posted | Console Guild | Open (2025-12-04 follow-up) |
|
||||
| SSE topic alignment delayed | WEB-CONSOLE-23-002/003/004 latency and reliability uncertain | Rescheduled alignment with Scheduler/Signals to 2025-12-04; add heartbeat/backoff defaults; capture examples in samples directory | BE-Base Platform Guild | Open (awaiting 2025-12-04 alignment notes) |
|
||||
| Advisory AI gateway contract missing | WEB-AIAI-31-001/002/003 cannot start without gateway location, RBAC/ABAC rules, and rate-limit policy spec | Request gateway contract snapshot + policy doc; replan once provided | BE-Base Platform Guild | Open |
|
||||
| Workspace storage exhausted (no PTY/commands) | WEB-CONSOLE-23-002 tests/builds blocked locally; implementation via patches only | Free disk/rotate logs; rerun after capacity restored | DevOps Guild | Open (2025-12-01) |
|
||||
|
||||
@@ -71,6 +72,7 @@
|
||||
| Date (UTC) | Update | Owner |
|
||||
| --- | --- | --- |
|
||||
| 2025-12-02 | WEB-CONSOLE-23-002: added trace IDs on status/stream calls, heartbeat + exponential backoff reconnect in console run stream service, and new client/service unit tests. Backend commands still not run locally (disk constraint). | BE-Base Platform Guild |
|
||||
| 2025-12-04 | Re-reviewed CONSOLE-VULN-29-001 and CONSOLE-VEX-30-001: WEB-CONSOLE-23-001 and Excititor console contract are complete, but Concelier graph schema snapshot and VEX Lens PLVL0103 spec/SSE envelope remain outstanding; keeping both tasks BLOCKED. | Project Mgmt |
|
||||
| 2025-12-01 | Started WEB-CONSOLE-23-002: added console status client (polling) + SSE run stream, store/service, and UI component; unit specs added. Commands/tests not executed locally due to PTY/disk constraint. | BE-Base Platform Guild |
|
||||
| 2025-11-07 | Enforced unknown-field detection, added shared `AocError` payload (HTTP + CLI), refreshed guard docs, and extended tests/endpoint helpers. | BE-Base Platform Guild |
|
||||
| 2025-11-07 | API scaffolding started for console workspace; `docs/advisory-ai/console.md` using placeholder responses while endpoints wire up. | Console Guild |
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
| Task ID | Status | Owner(s) | Dependencies | Notes |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| DOCS-UNBLOCK-CLI-KNOBS-301 | DONE (2025-11-25) | CLI Guild · Policy Guild · DevEx Guild | CLI-VULN-29-001; CLI-VEX-30-001; POLICY-ENGINE-31-001 delivered 2025-11-24. | Packaged fixtures/changelogs consumed by DOCS-AIAI-31-005..009. |
|
||||
| DOCS-AIAI-31-004 | DONE (2025-12-04) | Docs Guild · Console Guild | CONSOLE-VULN-29-001; CONSOLE-VEX-30-001; SBOM-AIAI-31-003 delivered. | Guardrail console guide refreshed with deterministic capture/payload + consolidated hash manifest (`docs/advisory-ai/console-fixtures.sha256`) and verification steps. |
|
||||
| DOCS-AIAI-31-004 | DONE (2025-12-04) | Docs Guild · Console Guild | CONSOLE-VULN-29-001; CONSOLE-VEX-30-001; SBOM-AIAI-31-003 delivered. | Guardrail console guide now renders command-output snapshots (no inline screenshots) backed by deterministic capture/payload + consolidated hash manifest (`docs/advisory-ai/console-fixtures.sha256`) and verification steps. |
|
||||
| DOCS-AIAI-31-005 | DONE (2025-11-25) | Docs Guild · DevEx/CLI Guild | DOCS-AIAI-31-004; CLI-VULN-29-001; CLI-VEX-30-001 | CLI guide published with exit codes + offline hashes (`docs/advisory-ai/cli.md`). |
|
||||
| DOCS-AIAI-31-006 | DONE (2025-11-25) | Docs Guild · Policy Guild | DOCS-AIAI-31-005; POLICY-ENGINE-31-001 | Assistant parameter doc refreshed (`docs/policy/assistant-parameters.md`). |
|
||||
| DOCS-AIAI-31-008 | DONE (2025-11-25) | Docs Guild · SBOM Service Guild | DOCS-AIAI-31-007; SBOM-AIAI-31-001 | Remediation heuristics documented with fixtures (`docs/sbom/remediation-heuristics.md`). |
|
||||
@@ -40,6 +40,8 @@
|
||||
## Execution Log
|
||||
| Date (UTC) | Update | Owner |
|
||||
| --- | --- | --- |
|
||||
| 2025-12-04 | DOCS-AIAI-31-004 reopened to replace screenshot embeds with command-rendered markdown outputs; set task DOING during update. | Docs Guild |
|
||||
| 2025-12-04 | DOCS-AIAI-31-004 DONE: swapped inline screenshots for command-output snippets; hashes unchanged. | Docs Guild |
|
||||
| 2025-12-04 | DOCS-AIAI-31-004 DONE: added `docs/advisory-ai/console-fixtures.sha256`, hash table + verification snippet to console guide. | Docs Guild |
|
||||
| 2025-12-04 | Moved DOCS-AIAI-31-004 to DOING to add hash manifest/table for console fixtures; kept determinism protocol. | Docs Guild |
|
||||
| 2025-12-04 | Reopened DOCS-AIAI-31-004 to add fixture hash verification and renumber publication section; added `docs/AGENTS.md` for docs working directory; republished doc and kept task at DONE. | Docs Guild |
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
| 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 | 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 | DONE (2025-11-22) | 2025-11-22 | SPRINT_110_ingestion_evidence | Docs Guild · Console Guild | | Guardrail console doc published with fixtures and screenshots. | CONSOLE-VULN-29-001; CONSOLE-VEX-30-001; SBOM-AIAI-31-001 | DOAI0101 |
|
||||
| AIAI-31-004 | DONE (2025-12-04) | 2025-12-04 | SPRINT_0301_0001_0001_docs_md_i | Docs Guild · Console Guild | docs/advisory-ai | Guardrail console guide refreshed with deterministic captures plus consolidated hash manifest (`docs/advisory-ai/console-fixtures.sha256`) and verification steps. | CONSOLE-VULN-29-001; CONSOLE-VEX-30-001; SBOM-AIAI-31-003 | DOAI0101 |
|
||||
| AIAI-31-005 | DONE (2025-11-25) | 2025-11-25 | 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 |
|
||||
| AIAI-31-006 | DONE | 2025-11-13 | SPRINT_0111_0001_0001_advisoryai | Docs Guild, Policy Guild (docs) | | — | — | DOAI0101 |
|
||||
| AIAI-31-008 | DONE (2025-11-22) | 2025-11-22 | SPRINT_110_ingestion_evidence | Advisory AI Guild | | Remote inference packaging delivered with on-prem container + manifests. | AIAI-31-006; AIAI-31-007 | DOAI0101 |
|
||||
@@ -479,8 +479,8 @@
|
||||
| CONSOLE-23-005 | TODO | | SPRINT_0212_0001_0001_web_i | Console Guild | src/Web/StellaOps.Web | Depends on #5 | Depends on #5 | CCSL0101 |
|
||||
| CONSOLE-OBS-52-001 | TODO | | SPRINT_303_docs_tasks_md_iii | Console Ops Guild | docs/modules/ui | Needs TLTY0101 metrics | Needs TLTY0101 metrics | CCSL0101 |
|
||||
| CONSOLE-OBS-52-002 | TODO | | SPRINT_303_docs_tasks_md_iii | Console Ops Guild | docs/modules/ui | Depends on #7 | Depends on #7 | CCSL0101 |
|
||||
| CONSOLE-VEX-30-001 | BLOCKED | 2025-11-19 | SPRINT_0212_0001_0001_web_i | Console Guild · VEX Lens Guild | src/Web/StellaOps.Web | Provide `/console/vex/*` APIs streaming VEX statements, justification summaries, and advisory links with SSE refresh hooks. Dependencies: WEB-CONSOLE-23-001, EXCITITOR-CONSOLE-23-001. | Needs VEX Lens spec (PLVL0103) | CCSL0101 |
|
||||
| CONSOLE-VULN-29-001 | BLOCKED | 2025-11-19 | SPRINT_0212_0001_0001_web_i | Console Guild | src/Web/StellaOps.Web | Build `/console/vuln/*` APIs and filters surfacing tenant-scoped findings with policy/VEX badges so Docs/UI teams can document workflows. Dependencies: WEB-CONSOLE-23-001, CONCELIER-GRAPH-21-001. | Depends on CCWO0101 | CCSL0101 |
|
||||
| CONSOLE-VEX-30-001 | BLOCKED (2025-12-04) | 2025-12-04 | SPRINT_0212_0001_0001_web_i | Console Guild · VEX Lens Guild | src/Web/StellaOps.Web | Provide `/console/vex/*` APIs streaming VEX statements, justification summaries, and advisory links with SSE refresh hooks. Dependencies: WEB-CONSOLE-23-001 (done 2025-11-28), EXCITITOR-CONSOLE-23-001 (done 2025-11-23); awaiting VEX Lens spec PLVL0103 and SSE envelope validation from Scheduler/Signals alignment. | Needs VEX Lens spec (PLVL0103) | CCSL0101 |
|
||||
| CONSOLE-VULN-29-001 | BLOCKED (2025-12-04) | 2025-12-04 | SPRINT_0212_0001_0001_web_i | Console Guild | src/Web/StellaOps.Web | Build `/console/vuln/*` APIs and filters surfacing tenant-scoped findings with policy/VEX badges so Docs/UI teams can document workflows. Dependencies: WEB-CONSOLE-23-001 (done 2025-11-28); waiting on Concelier graph schema snapshot from 2025-12-03 freeze review. | Depends on CCWO0101 | CCSL0101 |
|
||||
| CONTAINERS-44-001 | DONE | 2025-11-18 | SPRINT_0212_0001_0001_web_i | BE-Base Platform Guild | src/Web/StellaOps.Web | Wait for DVCP0101 compose template | Wait for DVCP0101 compose template | COWB0101 |
|
||||
| CONTAINERS-45-001 | DONE | 2025-11-19 | SPRINT_0212_0001_0001_web_i | BE-Base Platform Guild | src/Web/StellaOps.Web | Depends on #1 | Depends on #1 | COWB0101 |
|
||||
| CONTAINERS-46-001 | DONE | 2025-11-19 | SPRINT_0212_0001_0001_web_i | BE-Base Platform Guild | src/Web/StellaOps.Web | Needs RBRE0101 hashes | Needs RBRE0101 hashes | COWB0101 |
|
||||
@@ -641,7 +641,7 @@
|
||||
| DOCS-0003 | TODO | | SPRINT_327_docs_modules_scanner | Docs Guild, Product Guild (docs/modules/scanner) | docs/modules/scanner | — | — | DOCL0102 |
|
||||
| DOCS-401-008 | TODO | | SPRINT_0401_0001_0001_reachability_evidence_chain | QA & Docs Guilds (`docs`, `tests/README.md`) | `docs`, `tests/README.md` | — | — | DOCL0102 |
|
||||
| DOCS-401-022 | TODO | | SPRINT_0401_0001_0001_reachability_evidence_chain | Docs Guild · Attestor Guild (`docs/ci/dsse-build-flow.md`, `docs/modules/attestor/architecture.md`) | `docs/ci/dsse-build-flow.md`, `docs/modules/attestor/architecture.md` | — | — | DOCL0102 |
|
||||
| DOCS-AIAI-31-004 | DONE (2025-11-22) | 2025-11-22 | SPRINT_110_ingestion_evidence | Docs Guild · Console Guild | | Guardrail console doc published with fixtures and screenshots. | CONSOLE-VULN-29-001; CONSOLE-VEX-30-001; SBOM-AIAI-31-001 | DOAI0102 |
|
||||
| DOCS-AIAI-31-004 | DONE (2025-12-04) | 2025-12-04 | SPRINT_0301_0001_0001_docs_md_i | Docs Guild · Console Guild | docs/advisory-ai | Guardrail console guide refreshed with deterministic captures plus consolidated hash manifest (`docs/advisory-ai/console-fixtures.sha256`) and verification steps. | CONSOLE-VULN-29-001; CONSOLE-VEX-30-001; SBOM-AIAI-31-003 | DOAI0102 |
|
||||
| DOCS-AIAI-31-005 | DONE (2025-11-25) | 2025-11-25 | SPRINT_110_ingestion_evidence | Docs Guild | | CLI/policy/ops docs refreshed with offline hashes and exit codes. | DOCS-AIAI-31-004; CLI-VULN-29-001; CLI-VEX-30-001; POLICY-ENGINE-31-001; DEVOPS-AIAI-31-001 | DOAI0102 |
|
||||
| DOCS-AIAI-31-006 | TODO | 2025-11-13 | SPRINT_0111_0001_0001_advisoryai | Docs Guild · Advisory AI Guild | docs/modules/advisory-ai | `/docs/policy/assistant-parameters.md` now documents inference modes, guardrail phrases, budgets, and cache/queue knobs (POLICY-ENGINE-31-001 inputs captured via `AdvisoryAiServiceOptions`). | Need latest telemetry outputs from ADAI0101 | DOAI0104 |
|
||||
| DOCS-AIAI-31-008 | BLOCKED | 2025-11-18 | SPRINT_0111_0001_0001_advisoryai | Docs Guild · SBOM Service Guild (docs) | docs | Publish `/docs/sbom/remediation-heuristics.md` (feasibility scoring, blast radius). | SBOM-AIAI-31-001 projection kit/fixtures | DOAI0104 |
|
||||
@@ -2107,8 +2107,8 @@
|
||||
| WEB-AOC-19-005 | TODO | 2025-11-08 | SPRINT_116_concelier_v | Concelier WebService Guild, QA Guild (src/Concelier/StellaOps.Concelier.WebService) | src/Concelier/StellaOps.Concelier.WebService | | | |
|
||||
| WEB-AOC-19-006 | TODO | 2025-11-08 | SPRINT_116_concelier_v | Concelier WebService Guild (src/Concelier/StellaOps.Concelier.WebService) | src/Concelier/StellaOps.Concelier.WebService | | | |
|
||||
| WEB-AOC-19-007 | TODO | 2025-11-08 | SPRINT_116_concelier_v | Concelier WebService Guild, QA Guild (src/Concelier/StellaOps.Concelier.WebService) | src/Concelier/StellaOps.Concelier.WebService | | | |
|
||||
| WEB-CONSOLE-23-001 | TODO | | SPRINT_0212_0001_0001_web_i | BE-Base Platform Guild, Product Analytics Guild (src/Web/StellaOps.Web) | src/Web/StellaOps.Web | Provide consolidated `/console/dashboard` and `/console/filters` APIs returning tenant-scoped aggregates (findings by severity, VEX override counts, advisory deltas, run health, policy change log). Enforce AOC labelling, deterministic ordering, and cursor-based pagination for drill-down hints. | | |
|
||||
| WEB-CONSOLE-23-002 | TODO | | SPRINT_0212_0001_0001_web_i | BE-Base Platform Guild, Scheduler Guild (src/Web/StellaOps.Web) | src/Web/StellaOps.Web | Expose `/console/status` polling endpoint and `/console/runs/{id}/stream` SSE/WebSocket proxy with heartbeat/backoff, queue lag metrics, and auth scope enforcement. Surface request IDs + retry headers. Dependencies: WEB-CONSOLE-23-001. | | |
|
||||
| WEB-CONSOLE-23-001 | DONE (2025-11-28) | 2025-11-28 | SPRINT_0212_0001_0001_web_i | BE-Base Platform Guild · Product Analytics Guild | src/Web/StellaOps.Web | `/console/dashboard` and `/console/filters` aggregates shipped with tenant scoping, deterministic ordering, and 8 unit tests per sprint Execution Log 2025-11-28. | — | |
|
||||
| WEB-CONSOLE-23-002 | DOING (2025-12-01) | 2025-12-01 | SPRINT_0212_0001_0001_web_i | BE-Base Platform Guild · Scheduler Guild | src/Web/StellaOps.Web | Implementing `/console/status` polling and `/console/runs/{id}/stream` SSE/WebSocket proxy with heartbeat/backoff; awaiting storage cleanup to run tests. Dependencies: WEB-CONSOLE-23-001. | WEB-CONSOLE-23-001 | |
|
||||
| WEB-CONSOLE-23-003 | TODO | | SPRINT_0212_0001_0001_web_i | BE-Base Platform Guild, Policy Guild (src/Web/StellaOps.Web) | src/Web/StellaOps.Web | Add `/console/exports` POST/GET routes coordinating evidence bundle creation, streaming CSV/JSON exports, checksum manifest retrieval, and signed attestation references. Ensure requests honor tenant + policy scopes and expose job tracking metadata. Dependencies: WEB-CONSOLE-23-002. | | |
|
||||
| WEB-CONSOLE-23-004 | TODO | | SPRINT_0212_0001_0001_web_i | BE-Base Platform Guild (src/Web/StellaOps.Web) | src/Web/StellaOps.Web | Implement `/console/search` endpoint accepting CVE/GHSA/PURL/SBOM identifiers, performing fan-out queries with caching, ranking, and deterministic tie-breaking. Return typed results for Console navigation; respect result caps and latency SLOs. Dependencies: WEB-CONSOLE-23-003. | | |
|
||||
| WEB-CONSOLE-23-005 | TODO | | SPRINT_0212_0001_0001_web_i | BE-Base Platform Guild, DevOps Guild (src/Web/StellaOps.Web) | src/Web/StellaOps.Web | Serve `/console/downloads` JSON manifest (images, charts, offline bundles) sourced from signed registry metadata; include integrity hashes, release notes links, and offline instructions. Provide caching headers and documentation. Dependencies: WEB-CONSOLE-23-004. | | |
|
||||
@@ -2297,7 +2297,7 @@
|
||||
| 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 | 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 | DONE (2025-11-22) | 2025-11-22 | SPRINT_110_ingestion_evidence | Docs Guild · Console Guild | | Guardrail console doc published with fixtures and screenshots. | CONSOLE-VULN-29-001; CONSOLE-VEX-30-001; SBOM-AIAI-31-001 | DOAI0101 |
|
||||
| AIAI-31-004 | DONE (2025-12-04) | 2025-12-04 | SPRINT_0301_0001_0001_docs_md_i | Docs Guild · Console Guild | docs/advisory-ai | Guardrail console guide refreshed with deterministic captures plus consolidated hash manifest (`docs/advisory-ai/console-fixtures.sha256`) and verification steps. | CONSOLE-VULN-29-001; CONSOLE-VEX-30-001; SBOM-AIAI-31-003 | DOAI0101 |
|
||||
| AIAI-31-005 | DONE (2025-11-25) | 2025-11-25 | 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 |
|
||||
| AIAI-31-006 | DONE | 2025-11-13 | SPRINT_0111_0001_0001_advisoryai | Docs Guild, Policy Guild (docs) | | — | — | DOAI0101 |
|
||||
| AIAI-31-008 | DONE (2025-11-22) | 2025-11-22 | SPRINT_110_ingestion_evidence | Advisory AI Guild | | Remote inference packaging delivered with on-prem container + manifests. | AIAI-31-006; AIAI-31-007 | DOAI0101 |
|
||||
@@ -2693,8 +2693,8 @@
|
||||
| CONSOLE-23-005 | TODO | | SPRINT_0212_0001_0001_web_i | Console Guild | src/Web/StellaOps.Web | Depends on #5 | Depends on #5 | CCSL0101 |
|
||||
| CONSOLE-OBS-52-001 | TODO | | SPRINT_303_docs_tasks_md_iii | Console Ops Guild | docs/modules/ui | Needs TLTY0101 metrics | Needs TLTY0101 metrics | CCSL0101 |
|
||||
| CONSOLE-OBS-52-002 | TODO | | SPRINT_303_docs_tasks_md_iii | Console Ops Guild | docs/modules/ui | Depends on #7 | Depends on #7 | CCSL0101 |
|
||||
| CONSOLE-VEX-30-001 | BLOCKED | 2025-11-19 | SPRINT_0212_0001_0001_web_i | Console Guild · VEX Lens Guild | src/Web/StellaOps.Web | Provide `/console/vex/*` APIs streaming VEX statements, justification summaries, and advisory links with SSE refresh hooks. Dependencies: WEB-CONSOLE-23-001, EXCITITOR-CONSOLE-23-001. | Needs VEX Lens spec (PLVL0103) | CCSL0101 |
|
||||
| CONSOLE-VULN-29-001 | BLOCKED | 2025-11-19 | SPRINT_0212_0001_0001_web_i | Console Guild | src/Web/StellaOps.Web | Build `/console/vuln/*` APIs and filters surfacing tenant-scoped findings with policy/VEX badges so Docs/UI teams can document workflows. Dependencies: WEB-CONSOLE-23-001, CONCELIER-GRAPH-21-001. | Depends on CCWO0101 | CCSL0101 |
|
||||
| CONSOLE-VEX-30-001 | BLOCKED (2025-12-04) | 2025-12-04 | SPRINT_0212_0001_0001_web_i | Console Guild · VEX Lens Guild | src/Web/StellaOps.Web | Provide `/console/vex/*` APIs streaming VEX statements, justification summaries, and advisory links with SSE refresh hooks. Dependencies: WEB-CONSOLE-23-001 (done 2025-11-28), EXCITITOR-CONSOLE-23-001 (done 2025-11-23); awaiting VEX Lens spec PLVL0103 and SSE envelope validation from Scheduler/Signals alignment. | Needs VEX Lens spec (PLVL0103) | CCSL0101 |
|
||||
| CONSOLE-VULN-29-001 | BLOCKED (2025-12-04) | 2025-12-04 | SPRINT_0212_0001_0001_web_i | Console Guild | src/Web/StellaOps.Web | Build `/console/vuln/*` APIs and filters surfacing tenant-scoped findings with policy/VEX badges so Docs/UI teams can document workflows. Dependencies: WEB-CONSOLE-23-001 (done 2025-11-28); waiting on Concelier graph schema snapshot from 2025-12-03 freeze review. | Depends on CCWO0101 | CCSL0101 |
|
||||
| CONTAINERS-44-001 | DONE | 2025-11-18 | SPRINT_0212_0001_0001_web_i | BE-Base Platform Guild | src/Web/StellaOps.Web | Wait for DVCP0101 compose template | Wait for DVCP0101 compose template | COWB0101 |
|
||||
| CONTAINERS-45-001 | DONE | 2025-11-19 | SPRINT_0212_0001_0001_web_i | BE-Base Platform Guild | src/Web/StellaOps.Web | Depends on #1 | Depends on #1 | COWB0101 |
|
||||
| CONTAINERS-46-001 | DONE | 2025-11-19 | SPRINT_0212_0001_0001_web_i | BE-Base Platform Guild | src/Web/StellaOps.Web | Needs RBRE0101 hashes | Needs RBRE0101 hashes | COWB0101 |
|
||||
@@ -2854,7 +2854,7 @@
|
||||
| DOCS-0003 | TODO | | SPRINT_327_docs_modules_scanner | Docs Guild, Product Guild (docs/modules/scanner) | docs/modules/scanner | — | — | DOCL0102 |
|
||||
| DOCS-401-008 | TODO | | SPRINT_0401_0001_0001_reachability_evidence_chain | QA & Docs Guilds (`docs`, `tests/README.md`) | `docs`, `tests/README.md` | — | — | DOCL0102 |
|
||||
| DOCS-401-022 | TODO | | SPRINT_0401_0001_0001_reachability_evidence_chain | Docs Guild · Attestor Guild (`docs/ci/dsse-build-flow.md`, `docs/modules/attestor/architecture.md`) | `docs/ci/dsse-build-flow.md`, `docs/modules/attestor/architecture.md` | — | — | DOCL0102 |
|
||||
| DOCS-AIAI-31-004 | DONE (2025-11-22) | 2025-11-22 | SPRINT_110_ingestion_evidence | Docs Guild · Console Guild | | Guardrail console doc published with fixtures and screenshots. | CONSOLE-VULN-29-001; CONSOLE-VEX-30-001; SBOM-AIAI-31-001 | DOAI0102 |
|
||||
| DOCS-AIAI-31-004 | DONE (2025-12-04) | 2025-12-04 | SPRINT_0301_0001_0001_docs_md_i | Docs Guild · Console Guild | docs/advisory-ai | Guardrail console guide refreshed with deterministic captures plus consolidated hash manifest (`docs/advisory-ai/console-fixtures.sha256`) and verification steps. | CONSOLE-VULN-29-001; CONSOLE-VEX-30-001; SBOM-AIAI-31-003 | DOAI0102 |
|
||||
| DOCS-AIAI-31-005 | DONE (2025-11-25) | 2025-11-25 | SPRINT_110_ingestion_evidence | Docs Guild | | CLI/policy/ops docs refreshed with offline hashes and exit codes. | DOCS-AIAI-31-004; CLI-VULN-29-001; CLI-VEX-30-001; POLICY-ENGINE-31-001; DEVOPS-AIAI-31-001 | DOAI0102 |
|
||||
| DOCS-AIAI-31-006 | TODO | 2025-11-13 | SPRINT_0111_0001_0001_advisoryai | Docs Guild · Advisory AI Guild | docs/modules/advisory-ai | `/docs/policy/assistant-parameters.md` now documents inference modes, guardrail phrases, budgets, and cache/queue knobs (POLICY-ENGINE-31-001 inputs captured via `AdvisoryAiServiceOptions`). | Need latest telemetry outputs from ADAI0101 | DOAI0104 |
|
||||
| DOCS-AIAI-31-008 | BLOCKED | 2025-11-18 | SPRINT_0111_0001_0001_advisoryai | Docs Guild · SBOM Service Guild (docs) | docs | Publish `/docs/sbom/remediation-heuristics.md` (feasibility scoring, blast radius). | SBOM-AIAI-31-001 projection kit/fixtures | DOAI0104 |
|
||||
@@ -4284,8 +4284,8 @@
|
||||
| WEB-AOC-19-005 | TODO | 2025-11-08 | SPRINT_116_concelier_v | Concelier WebService Guild, QA Guild (src/Concelier/StellaOps.Concelier.WebService) | src/Concelier/StellaOps.Concelier.WebService | | | |
|
||||
| WEB-AOC-19-006 | TODO | 2025-11-08 | SPRINT_116_concelier_v | Concelier WebService Guild (src/Concelier/StellaOps.Concelier.WebService) | src/Concelier/StellaOps.Concelier.WebService | | | |
|
||||
| WEB-AOC-19-007 | TODO | 2025-11-08 | SPRINT_116_concelier_v | Concelier WebService Guild, QA Guild (src/Concelier/StellaOps.Concelier.WebService) | src/Concelier/StellaOps.Concelier.WebService | | | |
|
||||
| WEB-CONSOLE-23-001 | TODO | | SPRINT_0212_0001_0001_web_i | BE-Base Platform Guild, Product Analytics Guild (src/Web/StellaOps.Web) | src/Web/StellaOps.Web | Provide consolidated `/console/dashboard` and `/console/filters` APIs returning tenant-scoped aggregates (findings by severity, VEX override counts, advisory deltas, run health, policy change log). Enforce AOC labelling, deterministic ordering, and cursor-based pagination for drill-down hints. | | |
|
||||
| WEB-CONSOLE-23-002 | TODO | | SPRINT_0212_0001_0001_web_i | BE-Base Platform Guild, Scheduler Guild (src/Web/StellaOps.Web) | src/Web/StellaOps.Web | Expose `/console/status` polling endpoint and `/console/runs/{id}/stream` SSE/WebSocket proxy with heartbeat/backoff, queue lag metrics, and auth scope enforcement. Surface request IDs + retry headers. Dependencies: WEB-CONSOLE-23-001. | | |
|
||||
| WEB-CONSOLE-23-001 | DONE (2025-11-28) | 2025-11-28 | SPRINT_0212_0001_0001_web_i | BE-Base Platform Guild · Product Analytics Guild | src/Web/StellaOps.Web | `/console/dashboard` and `/console/filters` aggregates shipped with tenant scoping, deterministic ordering, and 8 unit tests per sprint Execution Log 2025-11-28. | — | |
|
||||
| WEB-CONSOLE-23-002 | DOING (2025-12-01) | 2025-12-01 | SPRINT_0212_0001_0001_web_i | BE-Base Platform Guild · Scheduler Guild | src/Web/StellaOps.Web | Implementing `/console/status` polling and `/console/runs/{id}/stream` SSE/WebSocket proxy with heartbeat/backoff; awaiting storage cleanup to run tests. Dependencies: WEB-CONSOLE-23-001. | WEB-CONSOLE-23-001 | |
|
||||
| WEB-CONSOLE-23-003 | TODO | | SPRINT_0212_0001_0001_web_i | BE-Base Platform Guild, Policy Guild (src/Web/StellaOps.Web) | src/Web/StellaOps.Web | Add `/console/exports` POST/GET routes coordinating evidence bundle creation, streaming CSV/JSON exports, checksum manifest retrieval, and signed attestation references. Ensure requests honor tenant + policy scopes and expose job tracking metadata. Dependencies: WEB-CONSOLE-23-002. | | |
|
||||
| WEB-CONSOLE-23-004 | TODO | | SPRINT_0212_0001_0001_web_i | BE-Base Platform Guild (src/Web/StellaOps.Web) | src/Web/StellaOps.Web | Implement `/console/search` endpoint accepting CVE/GHSA/PURL/SBOM identifiers, performing fan-out queries with caching, ranking, and deterministic tie-breaking. Return typed results for Console navigation; respect result caps and latency SLOs. Dependencies: WEB-CONSOLE-23-003. | | |
|
||||
| WEB-CONSOLE-23-005 | TODO | | SPRINT_0212_0001_0001_web_i | BE-Base Platform Guild, DevOps Guild (src/Web/StellaOps.Web) | src/Web/StellaOps.Web | Serve `/console/downloads` JSON manifest (images, charts, offline bundles) sourced from signed registry metadata; include integrity hashes, release notes links, and offline instructions. Provide caching headers and documentation. Dependencies: WEB-CONSOLE-23-004. | | |
|
||||
|
||||
@@ -3,34 +3,37 @@
|
||||
Scope: Evidence Bundle v1 produced by Evidence Locker and consumed by Concelier, Excititor, Export Center, CLI, and Policy Engine.
|
||||
|
||||
## Predicates & subjects
|
||||
- **Subject**: OCI manifest digest (`sha256:<digest>`) of the bundle, plus optional replay pack digest.
|
||||
- **Subject (mandatory):** Merkle root derived from `checksums.txt` (sha256 of the sorted file) for the sealed bundle. OCI digest of the tarball remains recorded as `bundle_oci_digest` inside the predicate for registry mirroring but is not the DSSE subject.
|
||||
- **Predicates (DSSE/In-Toto)**
|
||||
- `stellaops.evidence.bundle.v1`: declares bundle layout (manifests, CAS paths, replay log offsets).
|
||||
- `stellaops.evidence.transparency.v1`: optional Rekor log inclusion proof (UUID, log index, root hash at inclusion).
|
||||
- `stellaops.evidence.integrity.v1`: hashes for each payload (SBOMs, VEX, policy packs, telemetry snapshots), keyed by logical path.
|
||||
- `stellaops.evidence.bundle.v1`: declares bundle layout (manifests, CAS paths, replay log offsets, Merkle recipe, chunking strategy).
|
||||
- `stellaops.evidence.transparency.v1`: Rekor/log inclusion proof (UUID, log index, root hash at inclusion). Required when network-permitted; when offline, include `reason="offline"` and omit log pointers.
|
||||
- `stellaops.evidence.integrity.v1`: hashes for each payload (SBOMs, VEX, policy packs, telemetry snapshots), keyed by canonical path; must match entries in `bundle.manifest.schema.json`.
|
||||
|
||||
## Required claim set
|
||||
- `bundle_id` (UUID v4)
|
||||
- `produced_at` (UTC ISO-8601)
|
||||
- `producer` (`evidence-locker:<region>`)
|
||||
- `subject_digest` (OCI digest string)
|
||||
- `hashes` (map: logical path → sha256)
|
||||
- `subject_merkle_root` (sha256 from checksums.txt)
|
||||
- `hashes` (map: canonicalPath → sha256) sorted lexicographically
|
||||
- `sbom` (array of SPDX/CycloneDX digests and mediaTypes)
|
||||
- `vex` (array of VEX doc digests and schema versions)
|
||||
- `replay_manifest` (optional; digest + sequence number)
|
||||
- `transparency` (optional; Rekor UUID, logIndex, rootHash)
|
||||
- `replay_manifest` (optional; digest + sequence number, ledger URI, dsseEnvelope)
|
||||
- `transparency` (optional; Rekor UUID, logIndex, rootHash, inclusionProof) or `reason="offline"`
|
||||
- `signing_profile` (`sovereign-default` | `fips` | `gost` | `pq-experimental`)
|
||||
|
||||
## Bundling & signing rules
|
||||
- DSSE envelope using the module’s configured crypto provider; keys must be short-lived (<24h) and recorded in provider registry.
|
||||
- Hash list and subject digest MUST match the on-disk CAS objects; deterministic sort by logical path.
|
||||
- Rekor entry is optional; when absent, set `transparency=null` and add `transparency_reason="offline"` to provenance note.
|
||||
- DSSE envelope is **mandatory** for every sealed bundle using the configured `ICryptoProviderRegistry` profile; keys must be short-lived (<24h) and recorded in provider registry.
|
||||
- Subject = sha256(Merkle root) from `checksums.txt`; verifier must recompute to match.
|
||||
- Hash list must match `bundle.manifest.schema.json` (entries + optional `hashSummary`), sorted by `canonicalPath`.
|
||||
- Rekor/logging policy:
|
||||
- If outbound log is allowed, submit to configured log and embed UUID/logIndex/rootHash in `transparency`.
|
||||
- If outbound log is disallowed/offline, set `transparency` to null and include `reason="offline"` plus `log_policy="skip"` inside the predicate.
|
||||
|
||||
## Verification plan
|
||||
- Verify DSSE signature against provider registry (per profile) and check key expiry.
|
||||
- Recompute sha256 for every CAS object; fail if any mismatch.
|
||||
- If `transparency` present, verify inclusion proof against bundled Rekor root; fail closed on mismatch.
|
||||
- Emit verification report JSON and store beside bundle as `verify.json` (deterministic key order).
|
||||
- Recompute sha256 for every manifest entry and the Merkle root; fail if subject differs.
|
||||
- If `transparency` present, verify inclusion proof against bundled Rekor root; fail closed on mismatch. If absent, require `reason="offline"` and `log_policy="skip"`.
|
||||
- Emit verification report JSON (deterministic key order) and store beside bundle as `verify.json`.
|
||||
|
||||
## Fixtures
|
||||
- Sample bundle + report: `docs/samples/evidence-locker/bundle-v1-sample.tar.gz` (sha256 TBD at publish time).
|
||||
|
||||
@@ -38,7 +38,7 @@ The endpoint reuses `EvidenceBundlePackagingService` and caches the packaged obj
|
||||
|
||||
## Verification guidance
|
||||
|
||||
Upcoming EB1–EB10 remediation (Sprint 0161; advisory `docs/product-advisories/28-Nov-2025 - Evidence Bundle and Replay Contracts.md`):
|
||||
Upcoming EB1–EB10 remediation (Sprint 0161; advisory `docs/product-advisories/archived/27-Nov-2025-superseded/28-Nov-2025 - Evidence Bundle and Replay Contracts.md`):
|
||||
- Publish `bundle.manifest.schema.json` and `checksums.schema.json` with canonical JSON rules and signatures.
|
||||
- Document the Merkle hash recipe and DSSE predicate/log policy.
|
||||
- Ship an offline verifier script and golden bundles/replay fixtures to prove determinism.
|
||||
@@ -61,6 +61,13 @@ Use the resulting root as the DSSE subject and store `checksums.txt` inside the
|
||||
|
||||
These steps match the offline procedure described in `docs/forensics/evidence-locker.md` (Portable Evidence section). Update that guide whenever packaging fields change.
|
||||
|
||||
### Merkle + CAS rules (EB3/EB6)
|
||||
- **Canonical inventory:** `checksums.txt` MUST be generated from the manifest entries sorted lexicographically by `canonicalPath`.
|
||||
- **Subject binding:** DSSE subject is `sha256(checksums.txt)` (Merkle root); OCI digest of `bundle.tgz` is secondary metadata only.
|
||||
- **Chunking strategy:** Default `strategy=none`. When chunked CAS storage is enabled, record `chunking.strategy`, `chunkSizeBytes`, and `casDigestAlgorithm` in `checksums.schema.json`; chunk hashes are folded deterministically (fixed-size or buzhash) before the per-entry sha256 is calculated.
|
||||
- **Compression invariants:** tar → gzip with pinned mtime (`2025-01-01T00:00:00Z`), `0644` perms, uid/gid `0:0`, UTF-8 headers; failing these invalidates fixtures.
|
||||
- **Stable tooling:** CI must pin `tar`, `gzip`, and hashing tool versions; regenerate golden fixtures only when these pins change and record the versions in `tests/EvidenceLocker/Bundles/Golden/expected.json`.
|
||||
|
||||
## Portable bundle (`portable-bundle-v1.tgz`)
|
||||
|
||||
When sealed or air-gapped environments need a redacted evidence artifact, request:
|
||||
|
||||
@@ -8,6 +8,7 @@ Incident mode is a service-wide switch that increases forensic fidelity when Ste
|
||||
2. **Debug artefacts.** Snapshot requests emit an `incident/request-*.json` payload into the object store. The payload captures the normalized request metadata/materials plus the incident stamp so offline replay tooling has everything it needs. The manifest surfaces the artefact under the `incident/` section and packaging streams it alongside the canonical bundle files.
|
||||
3. **Manifest metadata.** Bundles carry `incident.mode`, `incident.changedAt`, and `incident.retentionExtensionDays` metadata so verifiers and auditors can see exactly when the mode toggled and how long retention was extended.
|
||||
4. **Operational signals.** Activation/deactivation events are published to the Timeline Indexer (and, via the notifier stub, to the future Notify integration). The `IEvidenceTimelinePublisher` now emits `evidence.incident.mode` with `state` and retention attributes, giving Ops a canonical audit trail.
|
||||
5. **Signed activation/exit (EB7).** Incident toggles MUST be recorded inside the bundle manifest (`incident` block) and in the DSSE predicate with signer identity and timestamp. Offline environments must still include the activation record even when no Rekor entry is possible; when online, include transparency log pointers alongside the incident record.
|
||||
|
||||
Configuration lives under `EvidenceLocker:Incident`:
|
||||
|
||||
@@ -22,3 +23,8 @@ Configuration lives under `EvidenceLocker:Incident`:
|
||||
```
|
||||
|
||||
`IncidentModeManager` watches the options and raises events whenever the state flips. Tests cover retention math, timeline/notifier fan-out, and the new debug artefact path.
|
||||
|
||||
## Recording rules (EB7)
|
||||
- Manifest fields (see `bundle.manifest.schema.json`): `incident.activatedAt`, `incident.activatedBy`, `incident.reason`, and optional `incident.deactivatedAt`, `incident.deactivatedBy`.
|
||||
- DSSE predicate: include `incident` block mirroring the manifest plus `signer` (provider/keyid) and `log_policy` (`submit` | `skip-offline`).
|
||||
- CLI/API: activation/deactivation commands must require a reason string and emit a signed record even when the state is unchanged (idempotent write with identical payload hash).
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
# Replay Payload Contract (Prep for PREP-EVID-REPLAY-187-001)
|
||||
|
||||
Status: **Ready for implementation** (2025-11-20)
|
||||
Status: **Ready for implementation** (2025-12-04 refresh for EB5)
|
||||
Owners: Evidence Locker Guild · Scanner Guild
|
||||
Scope: Define deterministic scanner record payload shape required to ingest replay bundles (Sprint 0187).
|
||||
Scope: Define deterministic scanner record payload shape required to ingest replay bundles (Sprint 0187) and to link replay provenance into bundle manifests and attestations (EB5).
|
||||
|
||||
## Payload shape
|
||||
- NDJSON per record; sorted by `recordedAtUtc` then `scanId`.
|
||||
- NDJSON per record; sorted by `recordedAtUtc` then `scanId` (stable ordering required by `docs/replay/DETERMINISTIC_REPLAY.md`).
|
||||
- Fields:
|
||||
- `scanId` (GUID), `tenantId`, `subjectDigest` (sha256:...), `scanKind` (sbom|vuln|policy),
|
||||
- `startedAtUtc`, `completedAtUtc` (ISO-8601),
|
||||
- `startedAtUtc`, `completedAtUtc`, `recordedAtUtc` (ISO-8601, UTC),
|
||||
- `artifacts`: array of `{ type: sbom|vex|log, digest, uri }`,
|
||||
- `provenance`: `{ dsseEnvelope, transparencyLog? }` (base64 DSSE; optional Rekor entry),
|
||||
- `summary`: `{ findings: int, advisories: int, policies: int }`.
|
||||
- Determinism: no wall-clock except the recorded timestamps above; DSSE envelope copied verbatim from scanner output.
|
||||
- Replay provenance (new, EB5):
|
||||
- Evidence Locker records `replayProvenance` in the bundle manifest with `recordDigest`, optional `sequence`, `ledgerUri`, `dsseEnvelope`, and optional `transparencyLog { rekorUuid, logIndex, inclusionProof }`.
|
||||
- The `recordDigest` is the sha256 of the canonical NDJSON content (as ingested) and becomes part of `hashSummary` in the manifest and the DSSE predicate.
|
||||
- Determinism: no wall-clock except the recorded timestamps above; DSSE envelope copied verbatim from scanner output; NDJSON must be UTF-8, LF line endings, and canonical key ordering per record.
|
||||
|
||||
## Acceptance criteria
|
||||
- Scanner Guild provides sample NDJSON (10 records) with DSSE envelope redacted allowed.
|
||||
- Evidence Locker can ingest and store bundle with deterministic ordering and hash (SHA256) across runs.
|
||||
- Contract published here and referenced in Sprint 0187 P1/P2/P3.
|
||||
- Evidence Locker can ingest and store bundle with deterministic ordering and hash (SHA256) across runs; recomputes `recordDigest` to bind replayProvenance.
|
||||
- Contract published here and referenced in Sprint 0187 P1/P2/P3 and manifests/attestations per EB5.
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ This reference describes the Export Center API introduced in Export Center Phase
|
||||
- **Tenant context:** Provide `X-Stella-Tenant` when the token carries multiple tenants; defaults to token tenant otherwise.
|
||||
- **Idempotency:** Mutating endpoints accept `Idempotency-Key` (UUID). Retrying with the same key returns the original result.
|
||||
- **Rate limits and quotas:** Responses include `X-Stella-Quota-Limit`, `X-Stella-Quota-Remaining`, and `X-Stella-Quota-Reset`. Exceeding quotas returns `429 Too Many Requests` with `ERR_EXPORT_QUOTA`.
|
||||
- **Integrity headers (downloads):** `Digest: sha-256=<base64>`, `X-Stella-Signature: dsse-b64=<payload>`, and `X-Stella-Immutability: true` accompany bundle/manifest downloads; clients must validate before use.
|
||||
- **Content negotiation:** Requests and responses use `application/json; charset=utf-8` unless otherwise stated. Downloads stream binary content with profile-specific media types.
|
||||
- **SSE:** Event streams set `Content-Type: text/event-stream` and keep connections alive with comment heartbeats every 15 seconds.
|
||||
|
||||
@@ -112,7 +113,15 @@ Scopes: export:profile:manage
|
||||
"recipientKeys": ["age1tenantkey..."],
|
||||
"strict": false
|
||||
},
|
||||
"retention": {"mode": "days", "value": 30}
|
||||
"retention": {"mode": "days", "value": 30},
|
||||
"limits": {
|
||||
"maxActiveRuns": 4,
|
||||
"maxQueuedRuns": 50,
|
||||
"backpressureMode": "reject"
|
||||
},
|
||||
"approval": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -190,6 +199,14 @@ Scopes: export:run
|
||||
"links": {
|
||||
"self": "/api/export/runs/run-20251029-01",
|
||||
"events": "/api/export/runs/run-20251029-01/events"
|
||||
},
|
||||
"quotas": {
|
||||
"maxActiveRuns": 4,
|
||||
"maxQueuedRuns": 50,
|
||||
"backpressureMode": "reject"
|
||||
},
|
||||
"approval": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -219,6 +236,10 @@ Response fields:
|
||||
| `errorCode` | Populated when `status=failed` (`signing`, `distribution`, etc). |
|
||||
| `policySnapshotId` | Returned for policy-aware profiles. |
|
||||
| `distributions` | List of available distribution descriptors (type, location, sha256, expiresAt). |
|
||||
| `rerunHash` | SHA-256 over sorted `contents[*].digest`; used for determinism checks. |
|
||||
| `integrity` | Expected HTTP headers (`Digest`, `X-Stella-Signature`, `X-Stella-Immutability`) and OCI annotations (`io.stellaops.export.*`). |
|
||||
| `quotas` | Active limits/backpressure settings returned with the run. |
|
||||
| `approval` | Cross-tenant approval ticket when selectors span multiple tenants/wildcards. |
|
||||
|
||||
### 4.4 Cancel a run
|
||||
|
||||
@@ -276,7 +297,9 @@ Scopes: export:download
|
||||
Streams the primary bundle (tarball, zip, or profile-specific layout). Headers:
|
||||
|
||||
- `Content-Disposition: attachment; filename="export-run-20251029-01.tar.zst"`
|
||||
- `X-Export-Digest: sha256:...`
|
||||
- `Digest: sha-256=<base64>` (EC5)
|
||||
- `X-Stella-Signature: dsse-b64:<payload>` (EC3/EC5)
|
||||
- `X-Stella-Immutability: true`
|
||||
- `X-Export-Size: 73482019`
|
||||
- `X-Export-Encryption: age` (when mirror encryption enabled)
|
||||
|
||||
@@ -290,6 +313,7 @@ Scopes: export:download
|
||||
```
|
||||
|
||||
Returns signed `export.json`. To fetch the detached signature, append `?signature=true`.
|
||||
- Integrity annotations are mirrored in response headers (`Digest`, `X-Stella-Signature`, `X-Stella-Immutability`) and in the manifest `integrity` block to keep rerun-hash deterministic.
|
||||
|
||||
### 6.3 Provenance download
|
||||
|
||||
|
||||
@@ -155,6 +155,10 @@ stella export verify run-20251029-01 \
|
||||
|
||||
Wrapper around `cosign verify`. Returns exit `0` when signatures and digests validate. Exit `20` when verification fails.
|
||||
|
||||
Integrity and determinism checks (EC1–EC10):
|
||||
- `stella export manifest` and `provenance` commands emit `Digest`/`X-Stella-Signature` headers; cache them for rerun-hash validation.
|
||||
- Offline kits: run `docs/modules/export-center/operations/verify-export-kit.sh <kit_dir>` to assert rerunHash, integrity headers vs OCI annotations, quotas/backpressure block, approvals, and log metadata in provenance.
|
||||
|
||||
## 5. CI recipe (GitHub Actions example)
|
||||
|
||||
```yaml
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
{
|
||||
"schemaVersion": "graph.inspect.v1",
|
||||
"tenant": "acme-dev",
|
||||
"artifactDigest": "sha256:8f2c1f4c8f9d4c3bb2efc0a9d0a35d4492a0bba4f3c1a2b9d5c7e1f4a8c6b2d1",
|
||||
"sbomDigest": "sha256:1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d",
|
||||
"collectedAt": "2025-12-04T15:30:00Z",
|
||||
"components": [
|
||||
{
|
||||
"purl": "pkg:maven/org.example/foo@1.2.3",
|
||||
"version": "1.2.3",
|
||||
"scopes": [
|
||||
"runtime"
|
||||
],
|
||||
"relationships": [
|
||||
{
|
||||
"type": "contains",
|
||||
"targetPurl": "pkg:docker/library/alpine@3.19.0",
|
||||
"scope": "runtime",
|
||||
"evidenceHash": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd",
|
||||
"source": "scanner.sbom.v1"
|
||||
},
|
||||
{
|
||||
"type": "depends_on",
|
||||
"targetPurl": "pkg:npm/lodash@4.17.21",
|
||||
"scope": "runtime",
|
||||
"evidenceHash": "89abcdef0123456789abcdef0123456789abcdef0123456789abcdef012345",
|
||||
"source": "concelier.linkset.v1"
|
||||
}
|
||||
],
|
||||
"advisories": [
|
||||
{
|
||||
"advisoryId": "CVE-2024-1111",
|
||||
"source": "ghsa",
|
||||
"status": "affected",
|
||||
"severity": "HIGH",
|
||||
"cvss": {
|
||||
"vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
|
||||
"score": 9.8
|
||||
},
|
||||
"justification": "exploitable_in_default_config",
|
||||
"justificationSummary": "Unauthenticated RCE in JSON parser; no mitigations applied.",
|
||||
"linksetDigest": "abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd",
|
||||
"evidenceHash": "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210",
|
||||
"modifiedAt": "2025-11-30T12:00:00Z",
|
||||
"provenance": {
|
||||
"source": "concelier.linkset.v1",
|
||||
"collectedAt": "2025-11-30T11:55:00Z",
|
||||
"eventOffset": 4421,
|
||||
"linksetDigest": "abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd",
|
||||
"evidenceHash": "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210"
|
||||
}
|
||||
}
|
||||
],
|
||||
"vexStatements": [
|
||||
{
|
||||
"statementId": "VEX-2025-0001",
|
||||
"source": "excitor.vex.v1",
|
||||
"status": "not_affected",
|
||||
"justification": "component_not_present",
|
||||
"impactStatement": "Library excluded from production image; only used in tests.",
|
||||
"knownExploited": false,
|
||||
"issuedAt": "2025-12-01T08:00:00Z",
|
||||
"expiresAt": "2026-12-01T00:00:00Z",
|
||||
"evidenceHash": "0f1e2d3c4b5a69788796a5b4c3d2e1f00f1e2d3c4b5a69788796a5b4c3d2e1f0",
|
||||
"provenance": {
|
||||
"source": "excitor.overlay.v1",
|
||||
"collectedAt": "2025-12-01T08:00:00Z",
|
||||
"eventOffset": 171,
|
||||
"evidenceHash": "0f1e2d3c4b5a69788796a5b4c3d2e1f00f1e2d3c4b5a69788796a5b4c3d2e1f0"
|
||||
}
|
||||
}
|
||||
],
|
||||
"provenance": {
|
||||
"source": "concelier.linkset.v1",
|
||||
"collectedAt": "2025-12-04T15:29:00Z",
|
||||
"eventOffset": 5123,
|
||||
"linksetDigest": "abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd",
|
||||
"evidenceHash": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd"
|
||||
}
|
||||
}
|
||||
],
|
||||
"links": {
|
||||
"sbomObservationEventId": "obs-2025-11-22-001",
|
||||
"linksetDigest": "abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd"
|
||||
}
|
||||
}
|
||||
48
docs/modules/graph/contracts/graph.inspect.v1.md
Normal file
48
docs/modules/graph/contracts/graph.inspect.v1.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# graph.inspect.v1 · Inspector Contract (2025-12-04)
|
||||
|
||||
Replaces the archived Cartographer handshake note and grounds the Concelier/Excititor → Graph Indexer/API interface. Use this shape for any inspector payloads that carry SBOM relationships plus advisory/VEX linkouts destined for graph ingestion or replay.
|
||||
|
||||
## Purpose
|
||||
- Give Concelier (Link-Not-Merge v1) and Excititor a frozen, deterministic payload so graph nodes/edges can be regenerated or replayed offline.
|
||||
- Encode the evidence hashes and provenance needed for append-only rebuilds and audit trails.
|
||||
- Keep ordering stable to avoid hash churn between runs.
|
||||
|
||||
## Payload shape (summary)
|
||||
- `schemaVersion` — must be `graph.inspect.v1`.
|
||||
- `tenant`, `artifactDigest`, `sbomDigest`, `collectedAt`.
|
||||
- `components[]` (ordered):
|
||||
- `purl`, optional `version`, optional sorted `scopes[]`.
|
||||
- `relationships[]` → `contains|depends_on|provides|runtime_observed` with `targetPurl`, `scope?`, `source`, `evidenceHash`.
|
||||
- `advisories[]` → `advisoryId`, `source`, `status`, `severity?`, `cvss?`, `justification?`, `linksetDigest?`, `evidenceHash`, `modifiedAt`.
|
||||
- `vexStatements[]` → `statementId`, `source`, `status`, `justification`, `impactStatement?`, `knownExploited?`, `issuedAt`, `expiresAt?`, `evidenceHash`.
|
||||
- `provenance` → `source`, `collectedAt`, `eventOffset?`, `linksetDigest?`, `evidenceHash?`.
|
||||
- Optional `links.sbomObservationEventId` and `links.linksetDigest` for traceability.
|
||||
|
||||
Full machine-readable schema: `docs/modules/graph/contracts/graph.inspect.v1.schema.json`.
|
||||
|
||||
## Determinism rules
|
||||
- Preserve input order for `components[]` and `relationships[]`; sort `scopes`, `advisories`, and `vexStatements` by (`source`, `advisoryId`/`statementId`) before emitting.
|
||||
- All timestamps UTC ISO-8601; hashes are SHA-256 hex.
|
||||
- Keep arrays unique where noted (`scopes`), and avoid null/empty strings.
|
||||
|
||||
## Graph mapping
|
||||
- `relationships` → graph edges: `contains/depends_on/provides/runtime_observed` align with `CONTAINS`, `DEPENDS_ON`, `PROVIDES`, `OBSERVED_RUNTIME`.
|
||||
- `advisories` → `advisory` nodes + `AFFECTED_BY` edges (use `linksetDigest` and `evidenceHash` for provenance).
|
||||
- `vexStatements` → `vex_statement` nodes + `VEX_EXEMPTS` edges (propagate `justification`, `knownExploited`, `impactStatement`).
|
||||
- `provenance` fields flow into graph `provenance` objects and `eventOffset` becomes the replay cursor.
|
||||
|
||||
## Validation
|
||||
```sh
|
||||
# Example (offline-friendly if ajv is already installed locally)
|
||||
ajv validate -s docs/modules/graph/contracts/graph.inspect.v1.schema.json \
|
||||
-d docs/modules/graph/contracts/examples/graph.inspect.v1.sample.json
|
||||
```
|
||||
Use any JSON Schema Draft 2020-12 validator if `ajv` is unavailable.
|
||||
|
||||
## Sample
|
||||
See `docs/modules/graph/contracts/examples/graph.inspect.v1.sample.json` for a one-component payload that exercises relationships, advisory observations, VEX statements, and provenance fields.
|
||||
|
||||
## Upstream alignment
|
||||
- Link-Not-Merge fixtures: `docs/modules/concelier/link-not-merge-schema.md`.
|
||||
- Excititor overlay prep: `docs/modules/excititor/prep/2025-11-20-graph-21-001-prep.md` and `...graph-21-002-prep.md`.
|
||||
- Graph canonical model: `docs/modules/graph/schema.md` (node/edge taxonomy the inspector feeds).
|
||||
217
docs/modules/graph/contracts/graph.inspect.v1.schema.json
Normal file
217
docs/modules/graph/contracts/graph.inspect.v1.schema.json
Normal file
@@ -0,0 +1,217 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://stellaops.org/schemas/graph.inspect.v1.schema.json",
|
||||
"title": "graph.inspect.v1",
|
||||
"description": "Inspector payload consumed by the Graph Indexer/API. Carries SBOM relationships plus advisory/VEX linkouts with deterministic ordering so downstream graph nodes/edges can be rebuilt or replayed offline.",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"schemaVersion": {
|
||||
"const": "graph.inspect.v1",
|
||||
"description": "Version marker; reject if not exactly graph.inspect.v1."
|
||||
},
|
||||
"tenant": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "Tenant identifier applied to all nested records."
|
||||
},
|
||||
"artifactDigest": {
|
||||
"type": "string",
|
||||
"pattern": "^[A-Za-z0-9_.:+-]{8,}$",
|
||||
"description": "Primary artifact digest (e.g., image digest) that the inspector payload refers to."
|
||||
},
|
||||
"sbomDigest": {
|
||||
"type": "string",
|
||||
"pattern": "^[A-Za-z0-9_.:+-]{8,}$",
|
||||
"description": "SBOM digest or manifest hash that produced the relationships below."
|
||||
},
|
||||
"collectedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "UTC ISO-8601 timestamp when the inspector snapshot was produced."
|
||||
},
|
||||
"components": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"description": "Component records kept in the same order as the upstream feed (stable ordering expected).",
|
||||
"items": { "$ref": "#/$defs/component" }
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"description": "Optional pointers for traceability (event ids, evidence URLs).",
|
||||
"properties": {
|
||||
"sbomObservationEventId": { "type": "string" },
|
||||
"linksetDigest": {
|
||||
"type": "string",
|
||||
"pattern": "^[A-Fa-f0-9]{64}$",
|
||||
"description": "Optional Concelier linkset digest that seeded this payload."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"schemaVersion",
|
||||
"tenant",
|
||||
"artifactDigest",
|
||||
"sbomDigest",
|
||||
"collectedAt",
|
||||
"components"
|
||||
],
|
||||
"$defs": {
|
||||
"component": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["purl", "relationships", "provenance"],
|
||||
"properties": {
|
||||
"purl": {
|
||||
"type": "string",
|
||||
"description": "Normalized PURL for the component."
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "Optional explicit version if not derivable from the PURL."
|
||||
},
|
||||
"scopes": {
|
||||
"type": "array",
|
||||
"description": "Sorted, unique scopes such as runtime/build/dev.",
|
||||
"items": { "type": "string" },
|
||||
"uniqueItems": true
|
||||
},
|
||||
"relationships": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"description": "SBOM relationships that map to graph edges.",
|
||||
"items": { "$ref": "#/$defs/relationship" }
|
||||
},
|
||||
"advisories": {
|
||||
"type": "array",
|
||||
"description": "Advisory observations used to emit AFFECTED_BY edges.",
|
||||
"items": { "$ref": "#/$defs/advisoryObservation" }
|
||||
},
|
||||
"vexStatements": {
|
||||
"type": "array",
|
||||
"description": "VEX statements used to emit VEX_EXEMPTS edges.",
|
||||
"items": { "$ref": "#/$defs/vexStatement" }
|
||||
},
|
||||
"provenance": { "$ref": "#/$defs/provenance" }
|
||||
}
|
||||
},
|
||||
"relationship": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["type", "targetPurl", "source", "evidenceHash"],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": ["contains", "depends_on", "provides", "runtime_observed"],
|
||||
"description": "Relationship kind; aligns to graph edge taxonomy."
|
||||
},
|
||||
"targetPurl": {
|
||||
"type": "string",
|
||||
"description": "Normalized PURL of the target component."
|
||||
},
|
||||
"scope": {
|
||||
"type": "string",
|
||||
"description": "Scope label propagated to graph edges (e.g., runtime, build)."
|
||||
},
|
||||
"evidenceHash": {
|
||||
"type": "string",
|
||||
"pattern": "^[A-Fa-f0-9]{64}$",
|
||||
"description": "SHA-256 of the evidence payload referenced by this relationship."
|
||||
},
|
||||
"source": {
|
||||
"type": "string",
|
||||
"description": "Provenance source for the relationship (e.g., concelier.linkset.v1, scanner.sbom.v1)."
|
||||
}
|
||||
}
|
||||
},
|
||||
"advisoryObservation": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["advisoryId", "source", "status", "modifiedAt", "evidenceHash"],
|
||||
"properties": {
|
||||
"advisoryId": { "type": "string" },
|
||||
"source": {
|
||||
"type": "string",
|
||||
"description": "Advisory source/provider (nvd, ghsa, distro id, etc.)."
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": ["affected", "not_affected", "fixed", "under_investigation", "unknown"]
|
||||
},
|
||||
"severity": { "type": "string" },
|
||||
"cvss": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"vector": { "type": "string" },
|
||||
"score": { "type": "number" }
|
||||
}
|
||||
},
|
||||
"justification": { "type": "string" },
|
||||
"justificationSummary": { "type": "string" },
|
||||
"linksetDigest": {
|
||||
"type": "string",
|
||||
"pattern": "^[A-Fa-f0-9]{64}$"
|
||||
},
|
||||
"evidenceHash": {
|
||||
"type": "string",
|
||||
"pattern": "^[A-Fa-f0-9]{64}$"
|
||||
},
|
||||
"modifiedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"provenance": { "$ref": "#/$defs/provenance" }
|
||||
}
|
||||
},
|
||||
"vexStatement": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["statementId", "status", "justification", "issuedAt", "evidenceHash", "source"],
|
||||
"properties": {
|
||||
"statementId": { "type": "string" },
|
||||
"source": { "type": "string" },
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": ["not_affected", "affected", "under_investigation", "fixed"]
|
||||
},
|
||||
"justification": { "type": "string" },
|
||||
"impactStatement": { "type": "string" },
|
||||
"knownExploited": { "type": "boolean" },
|
||||
"issuedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"expiresAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"evidenceHash": {
|
||||
"type": "string",
|
||||
"pattern": "^[A-Fa-f0-9]{64}$"
|
||||
},
|
||||
"provenance": { "$ref": "#/$defs/provenance" }
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["source", "collectedAt"],
|
||||
"properties": {
|
||||
"source": { "type": "string" },
|
||||
"collectedAt": { "type": "string", "format": "date-time" },
|
||||
"eventOffset": { "type": "integer", "minimum": 0 },
|
||||
"linksetDigest": {
|
||||
"type": "string",
|
||||
"pattern": "^[A-Fa-f0-9]{64}$"
|
||||
},
|
||||
"evidenceHash": {
|
||||
"type": "string",
|
||||
"pattern": "^[A-Fa-f0-9]{64}$"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
30
docs/notifications/gaps-nr1-nr10.md
Normal file
30
docs/notifications/gaps-nr1-nr10.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Notify Gaps NR1–NR10 — Remediation Blueprint (source: `docs/product-advisories/31-Nov-2025 FINDINGS.md`)
|
||||
|
||||
## Scope
|
||||
Close NR1–NR10 by defining contracts, evidence, and deterministic test hooks for the Notifier runtime (service + worker + offline kit). This doc is the detailed layer referenced by sprint `SPRINT_0171_0001_0001_notifier_i` and NOTIFY-GAPS-171-014.
|
||||
|
||||
## Gap requirements, evidence, and tests
|
||||
|
||||
| ID | Requirement | Evidence to publish | Deterministic tests/fixtures |
|
||||
| --- | --- | --- | --- |
|
||||
| NR1 | Versioned JSON Schemas for event envelopes, rules, templates, channels, receipts, and webhooks; DSSE-signed catalog with canonical hash recipe (BLAKE3-256 over normalized JSON). | `docs/notifications/schemas/notify-schemas-catalog.json` + `.dsse.json`; `docs/notifications/schemas/inputs.lock` capturing digests and canonicalization flags. | Golden canonicalization harness under `tests/notifications/Schemas/SchemaCanonicalizationTests.cs` using frozen inputs + hash assertions. |
|
||||
| NR2 | Tenant scoping + approvals for high-impact rules (escalations, PII, cross-tenant fan-out). Every API and receipt carries `tenant_id`; RBAC/approvals enforced. | RBAC/approval matrix (`docs/notifications/security/tenant-approvals.md`) listing actions × roles × required approvals. | API contract tests in `StellaOps.Notifier.Tests/TenantScopeTests.cs` plus integration fixtures with mixed-tenant payloads (should reject). |
|
||||
| NR3 | Deterministic rendering/localization: stable merge-field ordering, UTC ISO-8601 timestamps, locale whitelist, hashed previews recorded in ledger. | Rendering fixture pack `docs/notifications/fixtures/rendering/*.json`; hash ledger samples `docs/notifications/fixtures/rendering/index.ndjson` with BLAKE3 digests. | `StellaOps.Notifier.Tests/RenderingDeterminismTests.cs` compares golden bodies/subjects across locales/timezones; seeds fixed RNG/time. |
|
||||
| NR4 | Quotas/backpressure/DLQ: per-tenant/channel quotas, burst budgets, enqueue gating, DLQ schema with redrive + idempotent keys; metrics/alerts for backlog/DLQ growth. | Quota policy `docs/notifications/operations/quotas.md`; DLQ schema `docs/notifications/schemas/dlq-notify.schema.json`. | Worker tests `StellaOps.Notifier.Tests/BackpressureAndDlqTests.cs` validating quota enforcement, DLQ insertion, redrive idempotency. |
|
||||
| NR5 | Retry & idempotency: canonical `delivery_id` (UUIDv7) + dedupe key (event×rule×channel); bounded exponential backoff with jitter; idempotent connectors; ignore out-of-order acks. | Retry matrix `docs/notifications/operations/retries.md`; connector idempotency checklist. | `StellaOps.Notifier.Tests/RetryPolicyTests.cs` + connector harness fixtures demonstrating dedupe across duplicate events. |
|
||||
| NR6 | Webhook/ack security: HMAC or mTLS/DPoP required; signed ack URLs/tokens with nonce, expiry, audience, single-use; per-tenant allowlists for domains/paths. | Security policy `docs/notifications/security/webhook-ack-hardening.md`; sample signed-ack token format + validation steps. | Negative-path tests `StellaOps.Notifier.Tests/WebhookSecurityTests.cs` covering wrong HMAC, replayed nonce, expired token, disallowed domain. |
|
||||
| NR7 | Redaction & PII limits: classify template fields; redact secrets/PII in storage/logs; hash sensitive values; size/field allowlists; previews/logs default to redacted variant. | Redaction catalog `docs/notifications/security/redaction-catalog.md`; sample redacted payloads `docs/notifications/fixtures/redaction/*.json`. | `StellaOps.Notifier.Tests/RedactionTests.cs` asserting stored/preview payloads match redacted expectations. |
|
||||
| NR8 | Observability SLO alerts: SLOs for delivery latency/success/backlog/DLQ age; standard metrics names; dashboards/alerts/runbooks; traces include tenant/rule/channel IDs with sampling rules. | Dashboard JSON `docs/notifications/operations/dashboards/notify-slo.json`; alert rules `docs/notifications/operations/alerts/notify-slo-alerts.yaml`; runbook link. | `StellaOps.Notifier.Tests/ObservabilityContractsTests.cs` verifying metric names/labels; trace exemplar fixture `docs/notifications/fixtures/traces/sample-trace.json`. |
|
||||
| NR9 | Offline notify-kit with DSSE: bundle schemas, rules/templates, connector configs, verify script, hash list, time-anchor hook; deterministic packaging flags; tenant/env scoping; DSSE-signed manifest. | Manifest `offline/notifier/notify-kit.manifest.json`, DSSE `offline/notifier/notify-kit.manifest.dsse.json`, hash list `offline/notifier/artifact-hashes.json`, verify script `offline/notifier/verify_notify_kit.sh`. | Determinism check `tests/offline/NotifyKitDeterminismTests.sh` (shell) verifying hash list, DSSE, scope enforcement, packaging flags. |
|
||||
| NR10 | Mandatory simulations & evidence before activation: dry-run against frozen fixtures; DSSE-signed simulation results attached to approvals; regression tests per high-impact rule/template change. | Simulation report `docs/notifications/simulations/<rule-id>-report.json` + DSSE; approval evidence log `docs/notifications/simulations/index.ndjson`. | `StellaOps.Notifier.Tests/SimulationGateTests.cs` enforcing simulation requirement and evidence linkage before `active=true`. |
|
||||
|
||||
## Delivery + governance hooks
|
||||
- Add the above evidence paths to the NOTIFY-GAPS-171-014 task in `docs/implplan/SPRINT_0171_0001_0001_notifier_i.md` and mirror status in `src/Notifier/StellaOps.Notifier/TASKS.md`.
|
||||
- When artifacts land, append TRX/fixture links in the sprint **Execution Log** and reference this doc under **Decisions & Risks**.
|
||||
- Offline kit artefacts must mirror mirror/offline packaging rules (deterministic flags, time-anchor hook, PQ dual-sign toggle) already used by Mirror/Offline sprints.
|
||||
|
||||
## Next steps
|
||||
1) Generate initial schema catalog (`notify-schemas-catalog.json`) with rule/template/channel/webhook/receipt definitions and run canonicalization harness.
|
||||
2) Produce redaction catalog, quotas policy, retry matrix, and security hardening docs referenced above.
|
||||
3) Add golden fixtures/tests outlined above and wire CI filters to run determinism + security suites for Notify.
|
||||
4) Build notify-kit manifest + DSSE and publish `verify_notify_kit.sh` aligned with offline bundle policies.
|
||||
3
docs/notifications/operations/README.md
Normal file
3
docs/notifications/operations/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Notify Operations Artefacts
|
||||
|
||||
Landing zone for NR4, NR5, and NR8 evidence: quota/backpressure policies, DLQ schema, retry matrix, dashboards, and alert rules. Dashboards live under `operations/dashboards/`, alert configs under `operations/alerts/`.
|
||||
3
docs/notifications/schemas/README.md
Normal file
3
docs/notifications/schemas/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Notify Schemas Catalog
|
||||
|
||||
Placeholder for NR1 deliverables: versioned JSON Schemas for Notify event envelopes, rules, templates, channels, receipts, and webhooks. Publish `notify-schemas-catalog.json` + `.dsse.json` here with canonicalization recipe (BLAKE3-256 over normalized JSON) and `inputs.lock` capturing digests.
|
||||
3
docs/notifications/security/README.md
Normal file
3
docs/notifications/security/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Notify Security Notes
|
||||
|
||||
Holds NR2, NR6, and NR7 artefacts: tenant/RBAC approval matrix, webhook/ack hardening policy (HMAC/mTLS/DPoP + signed acks), and redaction/PII catalog with sanitized fixture samples.
|
||||
@@ -0,0 +1,49 @@
|
||||
# 30-Nov-2025 - UI Micro-Interactions for StellaOps
|
||||
|
||||
## Purpose
|
||||
Define canonical micro-interaction rules (MI1-MI10) for the StellaOps Console so motion, latency, error, and offline behaviors stay accessible, deterministic, and offline-ready. This advisory is the source of truth for UI sprints 0209/0210/0211 and Storybook/Playwright harnesses.
|
||||
|
||||
## Scope
|
||||
- Applies to Angular workspace `src/UI/StellaOps.UI` (Console), shared UI tokens, Storybook stories, and Playwright/axe/perf checks.
|
||||
- Covers micro-copy/localisation, telemetry events, reduced-motion behavior, and deterministic seeds/snapshots.
|
||||
|
||||
## Principles
|
||||
- Prefer informative micro-interactions over decorative motion; default to reduced-motion safe values.
|
||||
- Deterministic by default: fixed seeds, frozen fixtures, stable ordering, UTC timestamps.
|
||||
- Offline-first: no CDN assets; latency/error/offline states always represented with cached assets and copy.
|
||||
- WCAG 2.1 AA (focus order, keyboard, contrast, reduced motion, status messaging).
|
||||
|
||||
## MI Tracks (acceptance)
|
||||
| ID | Requirement | Acceptance Signals |
|
||||
| --- | --- | --- |
|
||||
| MI1 | Motion tokens catalogue (durations 80/140/200/260/320ms; easings `standard`,`decel`,`accel`,`emphasized`; distance scales XS-XL) in `tokens/motion.ts` and SCSS variables. | Storybook token page renders tokens; tokens consumed by at least 3 components (button, modal, banner). |
|
||||
| MI2 | Reduced-motion rules: prefers-reduced-motion -> durations clamp to 0-80ms, disable parallax/auto-animations; focus/hover states remain visible. | Playwright + axe snapshots with reduced-motion emulate; no animated GIF/Lottie autoplay; acceptance screenshots stable. |
|
||||
| MI3 | Latency/idle/load patterns: skeletons (<=400ms show), progress (400-1200ms), optimistic states, and offline banners with retry/backoff copy. | Fixtures for slow/failed/offline in Storybook; Playwright asserts state transitions and retry button wiring. |
|
||||
| MI4 | Error/cancel/undo: deterministic snackbar/toast pattern with keyboard focus, `aria-live=polite`, and 8s undo window. | Playwright e2e shows undo restores prior state; axe passes; snapshot stable. |
|
||||
| MI5 | Perf budgets: interaction response <=100ms, animation frame budget 16ms avg/50ms p95; LCP placeholder shown; no layout shift >0.05. | Lighthouse CI (offline config) JSON attached; flamechart samples stored under `tests/perf/micro/`. |
|
||||
| MI6 | Component mapping: table of components -> interaction type -> token usage; avoid bespoke easing outside catalog. | Mapping lives in `docs/modules/ui/micro-interactions-map.md`; lint rule blocks non-catalog easings. |
|
||||
| MI7 | Telemetry schema: `ui.micro.*` events with versioned schema, fields (tenant, surface, component, action, latency_ms, outcome, reduced_motion, offline_mode, error_code); PII-free. | JSON schema under `docs/modules/ui/telemetry/ui-micro.schema.json`; unit test validates sample payloads. |
|
||||
| MI8 | Deterministic seeds/snapshots: RNG seeds fixed per story/test; timestamps frozen; CSS animations paused in snapshots. | Storybook stories set `parameters.chromatic.disableAnimation`; Playwright uses `useFakeTimers` + fixed seeds exported from `micro-fixtures.ts`. |
|
||||
| MI9 | Micro-copy localisation: keys and ICU messages for micro-interaction copy; defaults EN, fallbacks present; no hard-coded strings in components. | i18n extraction shows zero TODO keys; snapshot verifies translated skeleton/error/undo copy. |
|
||||
| MI10 | Theme/contrast guidance: light/dark/HC tokens for backgrounds, borders, focus rings, and status colors; contrast >= 4.5:1 text, 3:1 UI elements. | Theming doc `docs/modules/ui/micro-theme.md`; axe-color passes for sample stories; focus ring visible in HC mode. |
|
||||
|
||||
## Deliverables
|
||||
- Token catalog: `src/UI/StellaOps.UI/src/styles/tokens/motion.{ts,scss}` with reduced-motion overrides.
|
||||
- Storybook stories: `apps/storybook/src/stories/micro/*` covering slow, error, offline, reduced-motion, undo flows; deterministic seeds.
|
||||
- Playwright suite: `tests/e2e/micro-interactions.spec.ts` covering MI2/MI3/MI4/MI8.
|
||||
- Telemetry schema + validators: `docs/modules/ui/telemetry/ui-micro.schema.json` plus unit test in `src/app/telemetry/__tests__/ui-micro.schema.spec.ts`.
|
||||
- Mapping doc: `docs/modules/ui/micro-interactions-map.md` linking components to token usage.
|
||||
|
||||
## Test & Determinism Rules
|
||||
- Freeze timers to 2025-12-04T12:00:00Z in stories/e2e; seed RNG with `0x5EED2025` unless scenario-specific.
|
||||
- All fixtures and snapshots stored under `tests/fixtures/micro/`; no network calls; offline assets bundled.
|
||||
- Playwright runs with `--disable-animations` and reduced-motion emulation variant.
|
||||
|
||||
## Risks & Mitigations
|
||||
- Workspace absence blocks implementation -> tracked in sprint action #7.
|
||||
- Token drift across sprints -> add lint rule and CI check for non-catalog easings.
|
||||
- Localisation regressions -> include i18n extraction in PR CI for micro stories.
|
||||
|
||||
## Traceability
|
||||
- Sprint: `docs/implplan/SPRINT_0209_0001_0001_ui_i.md` (task UI-MICRO-GAPS-0209-011).
|
||||
- Findings reference: `docs/product-advisories/31-Nov-2025 FINDINGS.md` (MI1-MI10 gap family).
|
||||
@@ -80,9 +80,22 @@ This advisory consolidates late-November gap findings across Scanner, SBOM/VEX s
|
||||
9. **MS9 — Metrics/alerts**: Mirror policy `metrics` marks build/import/verify signals required for observability.
|
||||
10. **MS10 — SemVer/change log**: `changelog` block declares current format version; future bumps must be appended with deterministic notes.
|
||||
|
||||
## NR (Notify Runtime) Gaps — NR1–NR10
|
||||
1. **NR1 — Signed, versioned schema catalog**: Publish JSON Schemas for event envelopes, rules, templates, channels, receipts, and webhooks with explicit `schema_version` and `tenant` fields; ship a DSSE-signed catalog (`docs/notifications/schemas/notify-schemas-catalog.json` + `.dsse.json`) and canonical hash recipe (BLAKE3-256 over normalized JSON). Evidence: catalog + DSSE, `inputs.lock` with schema digests.
|
||||
2. **NR2 — Tenant scoping & approvals**: Require tenant ID on all Notify APIs, channels, and ack receipts; enforce per-tenant RBAC/approvals for high-impact rules (escalations, PII, cross-tenant fan-out); document rejection reasons. Evidence: RBAC/approval matrix + conformance tests.
|
||||
3. **NR3 — Deterministic rendering & localization**: Rendering must be deterministic across locales/time zones: stable merge-field ordering, UTC ISO-8601 timestamps with fixed format, locale whitelist, deterministic preview output hashed in ledger; golden fixtures for each channel/template. Evidence: rendering fixture set + hash expectations.
|
||||
4. **NR4 — Quotas, backpressure, DLQ**: Per-tenant/channel quotas, burst budgets, and backpressure rules applied before enqueue; DLQ schema with redrive semantics and idempotent keys; require metrics/alerts for queue depth and DLQ growth. Evidence: quota policy doc + DLQ schema + redrive test harness.
|
||||
5. **NR5 — Retry & idempotency policy**: Canonical `delivery_id` (UUIDv7) + dedupe key per event×rule×channel; exponential backoff with jitter + max attempts; connectors must be idempotent; ensure out-of-order acks are ignored. Evidence: retry matrix + idempotency conformance tests.
|
||||
6. **NR6 — Webhook/ack security**: Mandatory HMAC with rotated secrets or mTLS/DPoP for webhooks; signed ack URLs/tokens with nonce, expiry, audience, and single-use guarantees; restrict allowed domains/paths per tenant. Evidence: security policy + negative-path tests.
|
||||
7. **NR7 — Redaction & PII limits**: Classify template fields, require redaction of secrets/PII in stored payloads/logs, hash-sensitive values, and enforce size/field allowlists; previews/logs must default to redacted variants. Evidence: redaction catalog + fixtures demonstrating sanitized storage and previews.
|
||||
8. **NR8 — Observability SLO alerts**: Define SLOs for delivery latency, success rate, backlog, DLQ age; standard metrics (`notify_delivery_success_total`, `notify_backlog_depth`, etc.) with alert thresholds and runbooks; traces carry tenant/rule/channel IDs with sampling rules. Evidence: dashboard JSON + alert rules + trace exemplar IDs.
|
||||
9. **NR9 — Offline notify-kit with DSSE**: Produce offline kit containing schemas, rules/templates, connector configs, verify script, and DSSE-signed manifest; include hash list and time-anchor hook; support deterministic packaging flags and tenant/env scoping. Evidence: kit manifest + DSSE + `verify_notify_kit.sh` script.
|
||||
10. **NR10 — Mandatory simulations & evidence**: Rules/templates must pass simulation/dry-run against frozen fixtures before activation; store DSSE-signed simulation results and attach evidence to change approvals; require regression tests for each high-impact rule change. Evidence: simulation report + DSSE + golden fixtures and TRX/NDJSON outputs.
|
||||
|
||||
## Pending Families (to be expanded)
|
||||
The following gap families were referenced in November indices and still need detailed findings written out:
|
||||
- CV1–CV10 (CVSS v4 receipts), CVM1–CVM10 (momentum), FC1–FC10 (SCA fixture gaps), OB1–OB10 (onboarding), IG1–IG10 (implementor guidance), RR1–RR10 (Rekor receipts), SK1–SK10 (standups), MI1–MI10 (UI micro-interactions), PVX1–PVX10 (Proof-linked VEX UI), TTE1–TTE10 (Time-to-Evidence), AR-EP1…AR-VB1 (archived advisories revival), BP1–BP10 (SBOM→VEX proof pipeline), UT1–UT10 (unknown heuristics), CE1–CE10 (evidence patterns), ET1–ET10 (ecosystem fixtures), RB1–RB10 (reachability fixtures), G1–G12 / RD1–RD10 (reachability benchmark/dataset), UN1–UN10 (unknowns registry), U1–U10 (decay), EX1–EX10 (explainability), VEX1–VEX10 (VEX claims), BR1–BR10 (binary reachability), VT1–VT10 (triage), PL1–PL10 (plugin arch), EB1–EB10 (evidence baseline), EC1–EC10 (export center), AT1–AT10 (automation), OK1–OK10 / RK1–RK10 / MS1–MS10 (offline/mirror/Rekor kits), TP1–TP10 (task packs), AU1–AU10 (auth), CL1–CL10 (CLI), OR1–OR10 (orchestrator), ZR1–ZR10 (Zastava), NR1–NR10 (Notify), GA1–GA10 (graph analytics), TO1–TO10 (telemetry), PS1–PS10 (policy), FL1–FL10 (ledger), CI1–CI10 (Concelier ingest).
|
||||
- CV1–CV10 (CVSS v4 receipts), CVM1–CVM10 (momentum), FC1–FC10 (SCA fixture gaps), OB1–OB10 (onboarding), IG1–IG10 (implementor guidance), RR1–RR10 (Rekor receipts), SK1–SK10 (standups), MI1–MI10 (UI micro-interactions), PVX1–PVX10 (Proof-linked VEX UI), TTE1–TTE10 (Time-to-Evidence), AR-EP1…AR-VB1 (archived advisories revival), BP1–BP10 (SBOM→VEX proof pipeline), UT1–UT10 (unknown heuristics), CE1–CE10 (evidence patterns), ET1–ET10 (ecosystem fixtures), RB1–RB10 (reachability fixtures), G1–G12 / RD1–RD10 (reachability benchmark/dataset), UN1–UN10 (unknowns registry), U1–U10 (decay), EX1–EX10 (explainability), VEX1–VEX10 (VEX claims), BR1–BR10 (binary reachability), VT1–VT10 (triage), PL1–PL10 (plugin arch), EB1–EB10 (evidence baseline), EC1–EC10 (export center), AT1–AT10 (automation), OK1–OK10 / RK1–RK10 / MS1–MS10 (offline/mirror/Rekor kits), TP1–TP10 (task packs), AU1–AU10 (auth), CL1–CL10 (CLI), OR1–OR10 (orchestrator), ZR1–ZR10 (Zastava), GA1–GA10 (graph analytics), TO1–TO10 (telemetry), PS1–PS10 (policy), FL1–FL10 (ledger), CI1–CI10 (Concelier ingest).
|
||||
|
||||
Each pending family should be expanded in this document (or split into dedicated, linked supplements) with numbered findings, recommended evidence, and deterministic test/fixture expectations.
|
||||
|
||||
|
||||
@@ -415,7 +415,7 @@ These are the authoritative advisories to reference for implementation:
|
||||
- SPRINT_0172_0001_0003_notify_ack_tokens.md
|
||||
- **Related Docs:**
|
||||
- `docs/modules/notify/architecture.md` - Module architecture
|
||||
- **Gaps:** `31-Nov-2025 FINDINGS.md` (NR1–NR10 remediation task NOTIFY-GAPS-171-014)
|
||||
- **Gaps:** `31-Nov-2025 FINDINGS.md` (NR1–NR10 remediation task NOTIFY-GAPS-171-014; blueprint `docs/notifications/gaps-nr1-nr10.md`)
|
||||
- **Status:** Fills MEDIUM-priority gap - covers rules engine, channels, noise control, ack tokens
|
||||
|
||||
### Graph Analytics & Dependency Insights
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
-- Link-Not-Merge linkset cache (PostgreSQL)
|
||||
-- Stores deterministic cache entries for advisory linksets per tenant/source/advisory.
|
||||
|
||||
CREATE TABLE IF NOT EXISTS vuln.lnm_linkset_cache (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id TEXT NOT NULL,
|
||||
source TEXT NOT NULL,
|
||||
advisory_id TEXT NOT NULL,
|
||||
observations TEXT[] NOT NULL DEFAULT '{}',
|
||||
normalized JSONB,
|
||||
conflicts JSONB,
|
||||
provenance JSONB,
|
||||
confidence DOUBLE PRECISION,
|
||||
built_by_job_id TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL,
|
||||
CONSTRAINT uq_lnm_linkset_cache UNIQUE (tenant_id, advisory_id, source)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_lnm_linkset_cache_order
|
||||
ON vuln.lnm_linkset_cache (tenant_id, created_at DESC, advisory_id, source);
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
namespace StellaOps.Concelier.Storage.Postgres.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a cached Link-Not-Merge linkset snapshot stored in PostgreSQL.
|
||||
/// </summary>
|
||||
public sealed class AdvisoryLinksetCacheEntity
|
||||
{
|
||||
public Guid Id { get; init; }
|
||||
public string TenantId { get; init; } = default!;
|
||||
public string Source { get; init; } = default!;
|
||||
public string AdvisoryId { get; init; } = default!;
|
||||
public string[] Observations { get; init; } = Array.Empty<string>();
|
||||
public string? NormalizedJson { get; init; }
|
||||
public string? ConflictsJson { get; init; }
|
||||
public string? ProvenanceJson { get; init; }
|
||||
public double? Confidence { get; init; }
|
||||
public DateTimeOffset CreatedAt { get; init; }
|
||||
public string? BuiltByJobId { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
using System.Collections.Immutable;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Npgsql;
|
||||
using StellaOps.Concelier.Core.Linksets;
|
||||
using StellaOps.Concelier.Storage.Postgres.Models;
|
||||
using StellaOps.Infrastructure.Postgres.Repositories;
|
||||
|
||||
namespace StellaOps.Concelier.Storage.Postgres.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// PostgreSQL implementation of the Link-Not-Merge linkset cache.
|
||||
/// </summary>
|
||||
public sealed class AdvisoryLinksetCacheRepository
|
||||
: RepositoryBase<ConcelierDataSource>,
|
||||
IAdvisoryLinksetStore
|
||||
{
|
||||
private static readonly JsonSerializerOptions JsonOptions = new()
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
||||
WriteIndented = false
|
||||
};
|
||||
|
||||
public AdvisoryLinksetCacheRepository(
|
||||
ConcelierDataSource dataSource,
|
||||
ILogger<AdvisoryLinksetCacheRepository> logger)
|
||||
: base(dataSource, logger)
|
||||
{
|
||||
}
|
||||
|
||||
public async Task UpsertAsync(
|
||||
AdvisoryLinkset linkset,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(linkset);
|
||||
|
||||
var tenant = NormalizeTenant(linkset.TenantId);
|
||||
var entity = ToEntity(linkset with { TenantId = tenant });
|
||||
|
||||
const string sql = """
|
||||
INSERT INTO vuln.lnm_linkset_cache
|
||||
(id, tenant_id, source, advisory_id, observations,
|
||||
normalized, conflicts, provenance, confidence, built_by_job_id, created_at)
|
||||
VALUES
|
||||
(@id, @tenant_id, @source, @advisory_id, @observations,
|
||||
@normalized::jsonb, @conflicts::jsonb, @provenance::jsonb,
|
||||
@confidence, @built_by_job_id, @created_at)
|
||||
ON CONFLICT (tenant_id, advisory_id, source) DO UPDATE SET
|
||||
observations = EXCLUDED.observations,
|
||||
normalized = EXCLUDED.normalized,
|
||||
conflicts = EXCLUDED.conflicts,
|
||||
provenance = EXCLUDED.provenance,
|
||||
confidence = EXCLUDED.confidence,
|
||||
built_by_job_id = EXCLUDED.built_by_job_id,
|
||||
created_at = EXCLUDED.created_at
|
||||
""";
|
||||
|
||||
await using var connection = await DataSource
|
||||
.OpenConnectionAsync(tenant, "lnm-cache-upsert", cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
await using var command = CreateCommand(sql, connection);
|
||||
AddParameter(command, "id", entity.Id);
|
||||
AddParameter(command, "tenant_id", entity.TenantId);
|
||||
AddParameter(command, "source", entity.Source);
|
||||
AddParameter(command, "advisory_id", entity.AdvisoryId);
|
||||
AddTextArrayParameter(command, "observations", entity.Observations);
|
||||
AddJsonbParameter(command, "normalized", entity.NormalizedJson);
|
||||
AddJsonbParameter(command, "conflicts", entity.ConflictsJson);
|
||||
AddJsonbParameter(command, "provenance", entity.ProvenanceJson);
|
||||
AddParameter(command, "confidence", entity.Confidence);
|
||||
AddParameter(command, "built_by_job_id", entity.BuiltByJobId);
|
||||
AddParameter(command, "created_at", entity.CreatedAt.UtcDateTime);
|
||||
|
||||
await command.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<AdvisoryLinkset>> FindByTenantAsync(
|
||||
string tenantId,
|
||||
IEnumerable<string>? advisoryIds,
|
||||
IEnumerable<string>? sources,
|
||||
AdvisoryLinksetCursor? cursor,
|
||||
int limit,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(tenantId))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(tenantId));
|
||||
}
|
||||
|
||||
if (limit <= 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(limit));
|
||||
}
|
||||
|
||||
var normalizedTenant = NormalizeTenant(tenantId);
|
||||
var advisoryIdArray = advisoryIds?.Select(a => a.Trim()).Where(a => !string.IsNullOrWhiteSpace(a)).ToArray();
|
||||
var sourceArray = sources?.Select(s => s.Trim()).Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
|
||||
|
||||
const string sql = """
|
||||
SELECT id, tenant_id, source, advisory_id, observations,
|
||||
normalized::text, conflicts::text, provenance::text,
|
||||
confidence, built_by_job_id, created_at
|
||||
FROM vuln.lnm_linkset_cache
|
||||
WHERE tenant_id = @tenant_id
|
||||
AND (@advisory_ids IS NULL OR advisory_id = ANY(@advisory_ids))
|
||||
AND (@sources IS NULL OR source = ANY(@sources))
|
||||
AND (
|
||||
@cursor_created_at IS NULL
|
||||
OR created_at < @cursor_created_at
|
||||
OR (created_at = @cursor_created_at AND advisory_id > @cursor_advisory_id)
|
||||
)
|
||||
ORDER BY created_at DESC, advisory_id ASC
|
||||
LIMIT @limit
|
||||
""";
|
||||
|
||||
return await QueryAsync(
|
||||
normalizedTenant,
|
||||
sql,
|
||||
cmd =>
|
||||
{
|
||||
AddParameter(cmd, "tenant_id", normalizedTenant);
|
||||
AddTextArrayParameter(cmd, "advisory_ids", advisoryIdArray);
|
||||
AddTextArrayParameter(cmd, "sources", sourceArray);
|
||||
|
||||
if (cursor is null)
|
||||
{
|
||||
AddParameter(cmd, "cursor_created_at", DBNull.Value);
|
||||
AddParameter(cmd, "cursor_advisory_id", DBNull.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddParameter(cmd, "cursor_created_at", cursor.CreatedAt.UtcDateTime);
|
||||
AddParameter(cmd, "cursor_advisory_id", cursor.AdvisoryId);
|
||||
}
|
||||
|
||||
AddParameter(cmd, "limit", limit);
|
||||
},
|
||||
MapLinkset,
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static string NormalizeTenant(string tenantId) =>
|
||||
tenantId.Trim().ToLowerInvariant();
|
||||
|
||||
private static AdvisoryLinksetCacheEntity ToEntity(AdvisoryLinkset linkset)
|
||||
{
|
||||
var normalizedJson = linkset.Normalized is null
|
||||
? null
|
||||
: JsonSerializer.Serialize(new
|
||||
{
|
||||
linkset.Normalized.Purls,
|
||||
linkset.Normalized.Cpes,
|
||||
linkset.Normalized.Versions,
|
||||
linkset.Normalized.Ranges,
|
||||
linkset.Normalized.Severities
|
||||
}, JsonOptions);
|
||||
|
||||
var conflictsJson = linkset.Conflicts is null
|
||||
? null
|
||||
: JsonSerializer.Serialize(
|
||||
linkset.Conflicts.Select(c => new
|
||||
{
|
||||
c.Field,
|
||||
c.Reason,
|
||||
c.Values,
|
||||
c.SourceIds
|
||||
}),
|
||||
JsonOptions);
|
||||
|
||||
var provenanceJson = linkset.Provenance is null
|
||||
? null
|
||||
: JsonSerializer.Serialize(new
|
||||
{
|
||||
linkset.Provenance.ObservationHashes,
|
||||
linkset.Provenance.ToolVersion,
|
||||
linkset.Provenance.PolicyHash
|
||||
}, JsonOptions);
|
||||
|
||||
return new AdvisoryLinksetCacheEntity
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
TenantId = linkset.TenantId,
|
||||
Source = linkset.Source,
|
||||
AdvisoryId = linkset.AdvisoryId,
|
||||
Observations = linkset.ObservationIds.ToArray(),
|
||||
NormalizedJson = normalizedJson,
|
||||
ConflictsJson = conflictsJson,
|
||||
ProvenanceJson = provenanceJson,
|
||||
Confidence = linkset.Confidence,
|
||||
CreatedAt = linkset.CreatedAt,
|
||||
BuiltByJobId = linkset.BuiltByJobId
|
||||
};
|
||||
}
|
||||
|
||||
private static AdvisoryLinkset MapLinkset(NpgsqlDataReader reader)
|
||||
{
|
||||
var normalized = Deserialize<NormalizedPayload>(reader, 5);
|
||||
var conflicts = Deserialize<List<ConflictPayload>>(reader, 6);
|
||||
var provenance = Deserialize<ProvenancePayload>(reader, 7);
|
||||
|
||||
return new AdvisoryLinkset(
|
||||
TenantId: reader.GetString(1),
|
||||
Source: reader.GetString(2),
|
||||
AdvisoryId: reader.GetString(3),
|
||||
ObservationIds: reader.GetFieldValue<string[]>(4).ToImmutableArray(),
|
||||
Normalized: normalized is null
|
||||
? null
|
||||
: new AdvisoryLinksetNormalized(
|
||||
normalized.Purls,
|
||||
normalized.Cpes,
|
||||
normalized.Versions,
|
||||
normalized.Ranges,
|
||||
normalized.Severities),
|
||||
Provenance: provenance is null
|
||||
? null
|
||||
: new AdvisoryLinksetProvenance(
|
||||
provenance.ObservationHashes,
|
||||
provenance.ToolVersion,
|
||||
provenance.PolicyHash),
|
||||
Confidence: GetNullableDouble(reader, 8),
|
||||
Conflicts: conflicts?.Select(c => new AdvisoryLinksetConflict(
|
||||
c.Field ?? string.Empty,
|
||||
c.Reason ?? string.Empty,
|
||||
c.Values,
|
||||
c.SourceIds)).ToList(),
|
||||
CreatedAt: reader.GetFieldValue<DateTimeOffset>(10),
|
||||
BuiltByJobId: GetNullableString(reader, 9));
|
||||
}
|
||||
|
||||
private static double? GetNullableDouble(NpgsqlDataReader reader, int ordinal) =>
|
||||
reader.IsDBNull(ordinal) ? null : reader.GetDouble(ordinal);
|
||||
|
||||
private static TPayload? Deserialize<TPayload>(NpgsqlDataReader reader, int ordinal)
|
||||
{
|
||||
if (reader.IsDBNull(ordinal))
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
var json = reader.GetString(ordinal);
|
||||
return JsonSerializer.Deserialize<TPayload>(json, JsonOptions);
|
||||
}
|
||||
|
||||
private sealed record NormalizedPayload(
|
||||
IReadOnlyList<string>? Purls,
|
||||
IReadOnlyList<string>? Cpes,
|
||||
IReadOnlyList<string>? Versions,
|
||||
IReadOnlyList<Dictionary<string, object?>>? Ranges,
|
||||
IReadOnlyList<Dictionary<string, object?>>? Severities);
|
||||
|
||||
private sealed record ConflictPayload(
|
||||
string? Field,
|
||||
string? Reason,
|
||||
IReadOnlyList<string>? Values,
|
||||
IReadOnlyList<string>? SourceIds);
|
||||
|
||||
private sealed record ProvenancePayload(
|
||||
IReadOnlyList<string>? ObservationHashes,
|
||||
string? ToolVersion,
|
||||
string? PolicyHash);
|
||||
}
|
||||
@@ -3,6 +3,7 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using StellaOps.Concelier.Storage.Postgres.Repositories;
|
||||
using StellaOps.Infrastructure.Postgres;
|
||||
using StellaOps.Infrastructure.Postgres.Options;
|
||||
using StellaOps.Concelier.Core.Linksets;
|
||||
|
||||
namespace StellaOps.Concelier.Storage.Postgres;
|
||||
|
||||
@@ -40,6 +41,8 @@ public static class ServiceCollectionExtensions
|
||||
services.AddScoped<IFeedSnapshotRepository, FeedSnapshotRepository>();
|
||||
services.AddScoped<IAdvisorySnapshotRepository, AdvisorySnapshotRepository>();
|
||||
services.AddScoped<IMergeEventRepository, MergeEventRepository>();
|
||||
services.AddScoped<IAdvisoryLinksetStore, AdvisoryLinksetCacheRepository>();
|
||||
services.AddScoped<IAdvisoryLinksetLookup>(sp => sp.GetRequiredService<IAdvisoryLinksetStore>());
|
||||
|
||||
return services;
|
||||
}
|
||||
@@ -71,6 +74,8 @@ public static class ServiceCollectionExtensions
|
||||
services.AddScoped<IFeedSnapshotRepository, FeedSnapshotRepository>();
|
||||
services.AddScoped<IAdvisorySnapshotRepository, AdvisorySnapshotRepository>();
|
||||
services.AddScoped<IMergeEventRepository, MergeEventRepository>();
|
||||
services.AddScoped<IAdvisoryLinksetStore, AdvisoryLinksetCacheRepository>();
|
||||
services.AddScoped<IAdvisoryLinksetLookup>(sp => sp.GetRequiredService<IAdvisoryLinksetStore>());
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\__Libraries\StellaOps.Infrastructure.Postgres\StellaOps.Infrastructure.Postgres.csproj" />
|
||||
<ProjectReference Include="..\StellaOps.Concelier.Storage.Mongo\StellaOps.Concelier.Storage.Mongo.csproj" />
|
||||
<ProjectReference Include="..\StellaOps.Concelier.Core\StellaOps.Concelier.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
using System.Collections.Immutable;
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using StellaOps.Concelier.Core.Linksets;
|
||||
using StellaOps.Concelier.Storage.Postgres;
|
||||
using StellaOps.Concelier.Storage.Postgres.Repositories;
|
||||
using StellaOps.Infrastructure.Postgres.Options;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Concelier.Storage.Postgres.Tests.Linksets;
|
||||
|
||||
[Collection(ConcelierPostgresCollection.Name)]
|
||||
public sealed class AdvisoryLinksetCacheRepositoryTests : IAsyncLifetime
|
||||
{
|
||||
private readonly ConcelierPostgresFixture _fixture;
|
||||
private readonly AdvisoryLinksetCacheRepository _repository;
|
||||
|
||||
public AdvisoryLinksetCacheRepositoryTests(ConcelierPostgresFixture fixture)
|
||||
{
|
||||
_fixture = fixture;
|
||||
|
||||
PostgresOptions options = fixture.Fixture.CreateOptions();
|
||||
options.SchemaName = fixture.SchemaName;
|
||||
var dataSource = new ConcelierDataSource(Options.Create(options), NullLogger<ConcelierDataSource>.Instance);
|
||||
_repository = new AdvisoryLinksetCacheRepository(dataSource, NullLogger<AdvisoryLinksetCacheRepository>.Instance);
|
||||
}
|
||||
|
||||
public Task InitializeAsync() => _fixture.TruncateAllTablesAsync();
|
||||
public Task DisposeAsync() => Task.CompletedTask;
|
||||
|
||||
[Fact]
|
||||
public async Task Upsert_NormalizesTenantAndReplaces()
|
||||
{
|
||||
var createdAt = DateTimeOffset.Parse("2025-11-20T12:00:00Z");
|
||||
var initial = BuildLinkset("Tenant-A", "ghsa", "GHSA-1", new[] { "obs-1" }, createdAt, confidence: 0.5);
|
||||
var replacement = BuildLinkset("tenant-a", "ghsa", "GHSA-1", new[] { "obs-2" }, createdAt.AddMinutes(5), confidence: 0.9);
|
||||
|
||||
await _repository.UpsertAsync(initial, CancellationToken.None);
|
||||
await _repository.UpsertAsync(replacement, CancellationToken.None);
|
||||
|
||||
var results = await _repository.FindByTenantAsync("TENANT-A", null, null, cursor: null, limit: 10, CancellationToken.None);
|
||||
|
||||
results.Should().ContainSingle();
|
||||
results[0].TenantId.Should().Be("tenant-a");
|
||||
results[0].ObservationIds.Should().ContainSingle("obs-2");
|
||||
results[0].Confidence.Should().Be(0.9);
|
||||
results[0].CreatedAt.Should().Be(replacement.CreatedAt);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FindByTenantAsync_OrdersAndPages()
|
||||
{
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
var linksets = new[]
|
||||
{
|
||||
BuildLinkset("tenant", "src", "ADV-002", new[] { "obs-1" }, now, confidence: null),
|
||||
BuildLinkset("tenant", "src", "ADV-001", new[] { "obs-2" }, now, confidence: 0.7),
|
||||
BuildLinkset("tenant", "src", "ADV-003", new[] { "obs-3" }, now.AddMinutes(-10), confidence: 0.2)
|
||||
};
|
||||
|
||||
foreach (var linkset in linksets)
|
||||
{
|
||||
await _repository.UpsertAsync(linkset, CancellationToken.None);
|
||||
}
|
||||
|
||||
var firstPage = await _repository.FindByTenantAsync("tenant", null, null, cursor: null, limit: 10, CancellationToken.None);
|
||||
firstPage.Select(ls => ls.AdvisoryId).Should().ContainInOrder("ADV-001", "ADV-002", "ADV-003");
|
||||
|
||||
var cursor = new AdvisoryLinksetCursor(firstPage[1].CreatedAt, firstPage[1].AdvisoryId);
|
||||
var secondPage = await _repository.FindByTenantAsync("tenant", null, null, cursor, limit: 10, CancellationToken.None);
|
||||
|
||||
secondPage.Should().ContainSingle();
|
||||
secondPage[0].AdvisoryId.Should().Be("ADV-003");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RoundTrip_PersistsNormalizedConflictsAndProvenance()
|
||||
{
|
||||
var normalized = new AdvisoryLinksetNormalized(
|
||||
Purls: new[] { "pkg:npm/foo@1.0.0" },
|
||||
Cpes: new[] { "cpe:2.3:a:foo:bar:1.0:*:*:*:*:*:*:*" },
|
||||
Versions: new[] { "1.0.0" },
|
||||
Ranges: new[]
|
||||
{
|
||||
new Dictionary<string, object?> { ["type"] = "semver", ["introduced"] = "1.0.0", ["fixed"] = "2.0.0" }
|
||||
},
|
||||
Severities: new[]
|
||||
{
|
||||
new Dictionary<string, object?> { ["system"] = "cvssv3", ["score"] = 7.5 }
|
||||
});
|
||||
|
||||
var conflicts = new List<AdvisoryLinksetConflict>
|
||||
{
|
||||
new("severity", "disagree", new[] { "7.5", "9.8" }, new[] { "nvd", "vendor" })
|
||||
};
|
||||
|
||||
var provenance = new AdvisoryLinksetProvenance(
|
||||
ObservationHashes: new[] { "h1", "h2" },
|
||||
ToolVersion: "lnm-1.0",
|
||||
PolicyHash: "sha256:abc");
|
||||
|
||||
var linkset = new AdvisoryLinkset(
|
||||
TenantId: "tenant-x",
|
||||
Source: "ghsa",
|
||||
AdvisoryId: "GHSA-9999",
|
||||
ObservationIds: ImmutableArray.Create("obs-100"),
|
||||
Normalized: normalized,
|
||||
Provenance: provenance,
|
||||
Confidence: 0.66,
|
||||
Conflicts: conflicts,
|
||||
CreatedAt: DateTimeOffset.Parse("2025-11-20T00:00:00Z"),
|
||||
BuiltByJobId: "job-42");
|
||||
|
||||
await _repository.UpsertAsync(linkset, CancellationToken.None);
|
||||
|
||||
var results = await _repository.FindByTenantAsync("tenant-x", new[] { "GHSA-9999" }, null, cursor: null, limit: 1, CancellationToken.None);
|
||||
results.Should().ContainSingle();
|
||||
|
||||
var cached = results[0];
|
||||
cached.Normalized.Should().NotBeNull();
|
||||
cached.Normalized!.Purls.Should().ContainSingle("pkg:npm/foo@1.0.0");
|
||||
cached.Normalized.Ranges!.Single()["type"].Should().Be("semver");
|
||||
cached.Conflicts.Should().ContainSingle(c => c.Field == "severity" && c.Values!.Contains("9.8"));
|
||||
cached.Provenance!.ObservationHashes.Should().BeEquivalentTo(new[] { "h1", "h2" });
|
||||
cached.BuiltByJobId.Should().Be("job-42");
|
||||
cached.Confidence.Should().Be(0.66);
|
||||
}
|
||||
|
||||
private static AdvisoryLinkset BuildLinkset(
|
||||
string tenant,
|
||||
string source,
|
||||
string advisoryId,
|
||||
IEnumerable<string> observations,
|
||||
DateTimeOffset createdAt,
|
||||
double? confidence)
|
||||
=> new(
|
||||
TenantId: tenant,
|
||||
Source: source,
|
||||
AdvisoryId: advisoryId,
|
||||
ObservationIds: observations.ToImmutableArray(),
|
||||
Normalized: null,
|
||||
Provenance: null,
|
||||
Confidence: confidence,
|
||||
Conflicts: null,
|
||||
CreatedAt: createdAt,
|
||||
BuiltByJobId: "job-1");
|
||||
}
|
||||
@@ -13,4 +13,4 @@
|
||||
| NOTIFY-RISK-66-001 | DONE (2025-11-24) | Notifications Service Guild · Risk Engine Guild | Added risk-events endpoint + templates/rules for severity change notifications. |
|
||||
| NOTIFY-RISK-67-001 | DONE (2025-11-24) | Notifications Service Guild · Policy Guild | Added routing/templates for risk profile publish/deprecate/threshold change. |
|
||||
| NOTIFY-RISK-68-001 | DONE (2025-11-24) | Notifications Service Guild | Default routing seeds with throttles/locales for risk alerts. |
|
||||
| NOTIFY-GAPS-171-014 | BLOCKED (2025-12-04) | Notifications Service Guild | Waiting on NR1–NR10 specifics in `31-Nov-2025 FINDINGS.md` and schema/catalog refresh before remediation can start. |
|
||||
| NOTIFY-GAPS-171-014 | TODO | Notifications Service Guild | NR1–NR10 scoped (`docs/product-advisories/31-Nov-2025 FINDINGS.md`, `docs/notifications/gaps-nr1-nr10.md`); implement schema catalog + DSSE, quotas/backpressure, retries/idempotency, security, redaction, observability, offline kit, and simulation evidence. |
|
||||
|
||||
@@ -6,4 +6,4 @@
|
||||
| TS-10-001 | BLOCKED | TypeScript interface generation blocked: workspace missing and schemas not present locally. | 2025-11-30 |
|
||||
| TS-10-002 | BLOCKED | Same as TS-10-001; waiting on schemas + workspace. | 2025-11-30 |
|
||||
| TS-10-003 | BLOCKED | Same as TS-10-001; waiting on schemas + workspace. | 2025-11-30 |
|
||||
| UI-MICRO-GAPS-0209-011 | BLOCKED | Canonical 30-Nov-2025 UI Micro-Interactions advisory missing and Angular workspace is empty; need advisory content, token catalog, and restored workspace before proceeding. | 2025-12-04 |
|
||||
| UI-MICRO-GAPS-0209-011 | BLOCKED | Canonical advisory published (docs/product-advisories/30-Nov-2025 - UI Micro-Interactions for StellaOps.md); still blocked because Angular workspace is empty—cannot build token catalog or Storybook/Playwright harness. | 2025-12-04 |
|
||||
|
||||
Reference in New Issue
Block a user