feat: Add new projects to solution and implement contract testing documentation
- Added "StellaOps.Policy.Engine", "StellaOps.Cartographer", and "StellaOps.SbomService" projects to the StellaOps solution. - Created AGENTS.md to outline the Contract Testing Guild Charter, detailing mission, scope, and definition of done. - Established TASKS.md for the Contract Testing Task Board, outlining tasks for Sprint 62 and Sprint 63 related to mock servers and replay testing.
This commit is contained in:
22
src/StellaOps.AdvisoryAI/AGENTS.md
Normal file
22
src/StellaOps.AdvisoryAI/AGENTS.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Advisory AI Guild Charter (Epic 8)
|
||||
|
||||
## Mission
|
||||
Deliver the Advisory AI assistant service that synthesizes advisory/VEX evidence, policy context, and SBOM data into summaries, conflict explanations, and remediation hints—always with citations and guardrails.
|
||||
|
||||
## Scope
|
||||
- Service under `src/StellaOps.AdvisoryAI` (retrievers, deterministics, orchestrator, guardrails, inference adapters, REST APIs).
|
||||
- Batch processing for CLI/automation, caching, observability, and integration with Console, CLI, and downstream systems.
|
||||
- Coordination across Conseiller, Excitator, VEX Lens, SBOM Service, Policy Engine, Findings Ledger, Web Gateway, Authority, DevOps, and Docs.
|
||||
|
||||
## Principles
|
||||
1. **Evidence preservation** – Raw advisory/VEX documents remain untouched; AI outputs reference them with citations.
|
||||
2. **Deterministic scaffolding** – Retrieval, mapping, and validators are deterministic; model variability is constrained.
|
||||
3. **Guardrails everywhere** – Redaction, injection defense, output validation, and audit logging are non-optional.
|
||||
4. **Policy-aware** – Outputs respect selected policy versions, thresholds, and trust configs.
|
||||
5. **Explainable** – Each result carries structured JSON, rationale, and provenance; humans can audit every statement.
|
||||
|
||||
## Definition of Done
|
||||
- Retrievers/deterministic tools implemented with tests and docs.
|
||||
- API endpoints documented (OpenAPI), RBAC enforced, guardrails active.
|
||||
- Console/CLI integrations operational; telemetry dashboards live.
|
||||
- Documentation suite published with compliance checklist.
|
||||
12
src/StellaOps.AdvisoryAI/TASKS.md
Normal file
12
src/StellaOps.AdvisoryAI/TASKS.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Advisory AI Task Board — Epic 8
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AIAI-31-001 | TODO | Advisory AI Guild | CONCELIER-VULN-29-001, EXCITITOR-VULN-29-001 | Implement structured and vector retrievers for advisories/VEX with paragraph anchors and citation metadata. | Retrievers return deterministic chunks with source IDs/sections; unit tests cover CSAF/OSV/vendor formats. |
|
||||
| AIAI-31-002 | TODO | Advisory AI Guild, SBOM Service Guild | SBOM-VULN-29-001 | Build SBOM context retriever (purl version timelines, dependency paths, env flags, blast radius estimator). | Retriever returns paths/metrics under SLA; tests cover ecosystems. |
|
||||
| AIAI-31-003 | TODO | Advisory AI Guild | AIAI-31-001..002 | Implement deterministic toolset (version comparators, range checks, dependency analysis, policy lookup) exposed via orchestrator. | Tools validated with property tests; outputs cached; docs updated. |
|
||||
| AIAI-31-004 | TODO | Advisory AI Guild | AIAI-31-001..003, AUTH-VULN-29-001 | Build orchestration pipeline for Summary/Conflict/Remediation tasks (prompt templates, tool calls, token budgets, caching). | Pipeline executes tasks deterministically; caches keyed by tuple+policy; integration tests cover tasks. |
|
||||
| AIAI-31-005 | TODO | Advisory AI Guild, Security Guild | AIAI-31-004 | Implement guardrails (redaction, injection defense, output validation, citation enforcement) and fail-safe handling. | Guardrails block adversarial inputs; output validator enforces schemas; security tests pass. |
|
||||
| AIAI-31-006 | TODO | Advisory AI Guild | AIAI-31-004..005 | Expose REST API endpoints (`/advisory/ai/*`) with RBAC, rate limits, OpenAPI schemas, and batching support. | Endpoints deployed with schema validation; rate limits enforced; integration tests cover error codes. |
|
||||
| AIAI-31-007 | TODO | Advisory AI Guild, Observability Guild | AIAI-31-004..006 | Instrument metrics (`advisory_ai_latency`, `guardrail_blocks`, `validation_failures`, `citation_coverage`), logs, and traces; publish dashboards/alerts. | Telemetry live; dashboards approved; alerts configured. |
|
||||
| AIAI-31-008 | TODO | Advisory AI Guild, DevOps Guild | AIAI-31-006..007 | Package inference on-prem container, remote inference toggle, Helm/Compose manifests, scaling guidance, offline kit instructions. | Deployment docs merged; smoke deploy executed; offline kit updated; feature flags documented. |
|
||||
| AIAI-31-009 | TODO | Advisory AI Guild, QA Guild | AIAI-31-001..006 | Develop unit/golden/property/perf tests, injection harness, and regression suite; ensure determinism with seeded caches. | Test suite green; golden outputs stored; injection tests pass; perf targets documented. |
|
||||
16
src/StellaOps.AirGap.Controller/AGENTS.md
Normal file
16
src/StellaOps.AirGap.Controller/AGENTS.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# StellaOps AirGap Controller Guild Charter
|
||||
|
||||
## Mission
|
||||
Own the sealing state machine, status APIs, and enforcement hooks that keep StellaOps compliant in sealed air-gapped environments while respecting the imposed rule.
|
||||
|
||||
## Scope
|
||||
- Persisted air-gap state (`sealed`, policy hash, time anchor metadata) and RBAC enforcement.
|
||||
- HTTP endpoints for seal/unseal/status and integration with Authority scopes.
|
||||
- Startup diagnostics that refuse to run when sealing requirements are unmet.
|
||||
- Coordination with DevOps for Kubernetes/Compose egress policies.
|
||||
- Telemetry and audit events reflecting sealing actions and violations.
|
||||
|
||||
## Definition of Done
|
||||
- Deterministic tests for seal/unseal transitions and audit logging.
|
||||
- Integration tests covering RBAC, sealed-mode refusal, and policy hash validation.
|
||||
- Documentation hooks updated in `/docs/airgap/` for each shipped feature.
|
||||
18
src/StellaOps.AirGap.Controller/TASKS.md
Normal file
18
src/StellaOps.AirGap.Controller/TASKS.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# AirGap Controller Task Board — Epic 16: Air-Gapped Mode
|
||||
|
||||
## Sprint 56 – Sealing Foundations
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AIRGAP-CTL-56-001 | TODO | AirGap Controller Guild | AUTH-OBS-50-001 | Implement `airgap_state` persistence, seal/unseal state machine, and Authority scope checks (`airgap:seal`, `airgap:status:read`). | State table created with migrations; seal/unseal transitions audited; unit tests cover happy/error paths. |
|
||||
| AIRGAP-CTL-56-002 | TODO | AirGap Controller Guild, DevOps Guild | AIRGAP-CTL-56-001, DEVOPS-AIRGAP-56-001 | Expose `GET /system/airgap/status`, `POST /system/airgap/seal`, integrate policy hash validation, and return staleness/time anchor placeholders. | APIs documented with OpenAPI; RBAC enforced; integration tests cover unauthorized/sealed states. |
|
||||
|
||||
## Sprint 57 – Enforcement & Diagnostics
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AIRGAP-CTL-57-001 | TODO | AirGap Controller Guild | AIRGAP-CTL-56-002 | Add startup diagnostics that block application run when sealed flag set but egress policies missing; emit audit + telemetry. | Startup guard tested with simulated failure; telemetry includes `airgap_sealed=true`; docs updated. |
|
||||
| AIRGAP-CTL-57-002 | TODO | AirGap Controller Guild, Observability Guild | AIRGAP-CTL-56-002, TELEMETRY-OBS-50-001 | Instrument seal/unseal events with trace/log fields and timeline emission (`airgap.sealed`, `airgap.unsealed`). | Timeline events validated; logs include actor/tenant/policy hash; integration test covers duplication suppression. |
|
||||
|
||||
## Sprint 58 – Time Anchor & Drift
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AIRGAP-CTL-58-001 | TODO | AirGap Controller Guild, AirGap Time Guild | AIRGAP-CTL-56-002, AIRGAP-TIME-57-001 | Persist time anchor metadata, compute drift seconds, and surface staleness budgets in status API. | Time anchor stored with bundle ID; drift calculation validated in tests; status API returns staleness metrics. |
|
||||
16
src/StellaOps.AirGap.Importer/AGENTS.md
Normal file
16
src/StellaOps.AirGap.Importer/AGENTS.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# StellaOps AirGap Importer Guild Charter
|
||||
|
||||
## Mission
|
||||
Deliver offline bundle verification and ingestion tooling for sealed environments, covering DSSE/TUF validation, catalog updates, and audit logging under the imposed rule.
|
||||
|
||||
## Scope
|
||||
- TUF metadata verification, DSSE signature checks, Merkle root validation.
|
||||
- Import pipelines writing bundle catalogs, object-store layouts, and audit entries.
|
||||
- CLI + API surfaces for dry-run verification, import, and status queries.
|
||||
- Integration hooks for Conseiller, Excitator, Policy Engine, and Export Center.
|
||||
- Negative-case handling (tampering, expired signatures, root rotation) with operator guidance.
|
||||
|
||||
## Definition of Done
|
||||
- Deterministic fixtures for valid/invalid bundles committed.
|
||||
- Integration tests prove catalog + object-store updates are idempotent.
|
||||
- Import audit trail viewable via API and timeline events.
|
||||
19
src/StellaOps.AirGap.Importer/TASKS.md
Normal file
19
src/StellaOps.AirGap.Importer/TASKS.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# AirGap Importer Task Board — Epic 16: Air-Gapped Mode
|
||||
|
||||
## Sprint 56 – Verification Primitives
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AIRGAP-IMP-56-001 | TODO | AirGap Importer Guild | PROV-OBS-53-001 | Implement DSSE verification helpers, TUF metadata parser (`root.json`, `snapshot.json`, `timestamp.json`), and Merkle root calculator. | Verifier returns structured results; unit tests cover valid/invalid signatures and tampering scenarios. |
|
||||
| AIRGAP-IMP-56-002 | TODO | AirGap Importer Guild, Security Guild | AIRGAP-IMP-56-001 | Introduce root rotation policy validation (dual approval) and signer trust store management. | Rotation policy enforced; tests cover valid rotation and rollback; docs stub updated. |
|
||||
|
||||
## Sprint 57 – Catalog & Storage Writes
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AIRGAP-IMP-57-001 | TODO | AirGap Importer Guild | AIRGAP-IMP-56-001, DEVOPS-AIRGAP-56-002 | Write `bundle_catalog` and `bundle_items` repositories with RLS + deterministic migrations. | Catalog tables created; integration tests ensure tenant/global scoping; determinism check passes. |
|
||||
| AIRGAP-IMP-57-002 | TODO | AirGap Importer Guild, DevOps Guild | AIRGAP-IMP-57-001 | Implement object-store loader storing artifacts under tenant/global mirror paths with Zstandard decompression and checksum validation. | Import writes deduplicated objects; checksum mismatches raise errors; storage layout documented. |
|
||||
|
||||
## Sprint 58 – Import Workflows
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AIRGAP-IMP-58-001 | TODO | AirGap Importer Guild, CLI Guild | AIRGAP-IMP-57-002, CLI-AIRGAP-56-001 | Implement API (`POST /airgap/import`, `/airgap/verify`) and CLI commands wiring verification + catalog updates, including diff preview. | CLI/API share validation engine; diff preview surfaces metadata changes; audit entries recorded with trace IDs. |
|
||||
| AIRGAP-IMP-58-002 | TODO | AirGap Importer Guild, Observability Guild | AIRGAP-IMP-58-001, TELEMETRY-OBS-50-001 | Emit timeline events (`airgap.import.started|completed|failed`) and telemetry metrics (bundle bytes, duration, warnings). | Events/metrics validated in integration tests; docs cross-link to observability dashboards. |
|
||||
16
src/StellaOps.AirGap.Policy/AGENTS.md
Normal file
16
src/StellaOps.AirGap.Policy/AGENTS.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# StellaOps AirGap Policy Guild Charter
|
||||
|
||||
## Mission
|
||||
Provide the shared enforcement layer (`EgressPolicy`, job plan validators, sealed-mode gates) that keeps all services compliant with Air-Gapped Mode requirements.
|
||||
|
||||
## Scope
|
||||
- `EgressPolicy` facade replacing raw HTTP client usage.
|
||||
- Static analysis/linting to detect unauthorized network calls.
|
||||
- Task Runner and orchestrator validators flagging disallowed destinations.
|
||||
- Shared error contract (`AIRGAP_EGRESS_BLOCKED`) and remediation messages.
|
||||
- Test harnesses simulating sealed/unsealed execution paths.
|
||||
|
||||
## Definition of Done
|
||||
- Every service imports the facade; CI fails on direct HTTP client usage.
|
||||
- Sealed-mode unit tests cover panic/remediation behavior across host types.
|
||||
- Documentation updated in `/docs/dev/airgap-contracts.md` for adoption patterns.
|
||||
19
src/StellaOps.AirGap.Policy/TASKS.md
Normal file
19
src/StellaOps.AirGap.Policy/TASKS.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# AirGap Policy Task Board — Epic 16: Air-Gapped Mode
|
||||
|
||||
## Sprint 56 – Facade & Contracts
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AIRGAP-POL-56-001 | TODO | AirGap Policy Guild | TELEMETRY-OBS-50-001 | Implement `StellaOps.AirGap.Policy` package exposing `EgressPolicy` facade with sealed/unsealed branches and remediation-friendly errors. | Facade package builds/tests; integration tests simulate sealed/unsealed; error contract documented. |
|
||||
| AIRGAP-POL-56-002 | TODO | AirGap Policy Guild, DevEx Guild | AIRGAP-POL-56-001 | Create Roslyn analyzer/code fix warning on raw `HttpClient` usage outside approved wrappers; add CI integration. | Analyzer packaged; CI fails on intentional violation; docs updated for opt-in. |
|
||||
|
||||
## Sprint 57 – Service Adoption Wave 1
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AIRGAP-POL-57-001 | TODO | AirGap Policy Guild, BE-Base Platform Guild | AIRGAP-POL-56-001 | Update core web services (Web, Exporter, Policy, Findings, Authority) to use `EgressPolicy`; ensure configuration wiring for sealed mode. | Services compile with facade; sealed-mode tests run in CI; configuration docs updated. |
|
||||
| AIRGAP-POL-57-002 | TODO | AirGap Policy Guild, Task Runner Guild | AIRGAP-POL-56-001, TASKRUN-OBS-50-001 | Implement Task Runner job plan validator rejecting network steps unless marked internal allow-list. | Validator blocks forbidden steps; tests cover allow/deny; error surfaces remediation text. |
|
||||
|
||||
## Sprint 58 – Service Adoption Wave 2
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AIRGAP-POL-58-001 | TODO | AirGap Policy Guild, Observability Guild | AIRGAP-POL-57-001 | Ensure Observability exporters only target local endpoints in sealed mode; disable remote sinks with warning. | Exporters respect sealed flag; timeline/log message emitted; docs updated. |
|
||||
| AIRGAP-POL-58-002 | TODO | AirGap Policy Guild, CLI Guild | AIRGAP-POL-56-001, CLI-OBS-50-001 | Add CLI sealed-mode guard that refuses commands needing egress and surfaces remediation. | CLI returns `AIRGAP_EGRESS_BLOCKED`; tests cover sealed/unsealed flows; help text updated. |
|
||||
15
src/StellaOps.AirGap.Time/AGENTS.md
Normal file
15
src/StellaOps.AirGap.Time/AGENTS.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# StellaOps AirGap Time Guild Charter
|
||||
|
||||
## Mission
|
||||
Manage trusted time anchors and staleness budgets for sealed environments, ensuring deterministic behavior when external time sources are unavailable.
|
||||
|
||||
## Scope
|
||||
- Parse signed time tokens from Mirror Bundles and validate signatures.
|
||||
- Persist `time_anchor` metadata and compute drift/staleness metrics.
|
||||
- Provide helpers for UI/API staleness badges and job gating.
|
||||
- Integrate with Notifications to alert on approaching drift thresholds.
|
||||
|
||||
## Definition of Done
|
||||
- Test vectors for time tokens committed alongside verification code.
|
||||
- Drift calculations deterministic and configurable per tenant.
|
||||
- Documentation updates for `/docs/airgap/staleness-and-time.md` with examples.
|
||||
13
src/StellaOps.AirGap.Time/TASKS.md
Normal file
13
src/StellaOps.AirGap.Time/TASKS.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# AirGap Time Task Board — Epic 16: Air-Gapped Mode
|
||||
|
||||
## Sprint 57 – Time Anchor Validation
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AIRGAP-TIME-57-001 | TODO | AirGap Time Guild | PROV-OBS-54-001, AIRGAP-IMP-56-001 | Implement signed time token parser (Roughtime/RFC3161), verify signatures against bundle trust roots, and expose normalized anchor representation. | Parser handles both token formats; tests cover valid/expired/tampered tokens; documentation stubbed. |
|
||||
| AIRGAP-TIME-57-002 | TODO | AirGap Time Guild, Observability Guild | AIRGAP-TIME-57-001 | Add telemetry counters for time anchors (`airgap_time_anchor_age_seconds`) and alerts for approaching thresholds. | Metrics registered; alert templates created; integration test ensures emission on stale anchor. |
|
||||
|
||||
## Sprint 58 – Drift & Staleness Enforcement
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AIRGAP-TIME-58-001 | TODO | AirGap Time Guild | AIRGAP-TIME-57-001, AIRGAP-CTL-56-002 | Persist drift baseline, compute per-content staleness (advisories, VEX, policy) based on bundle metadata, and surface through controller status API. | Drift/staleness values exposed via API; unit tests cover threshold calculations; docs updated. |
|
||||
| AIRGAP-TIME-58-002 | TODO | AirGap Time Guild, Notifications Guild | AIRGAP-TIME-58-001, NOTIFY-OBS-51-001 | Emit notifications and timeline events when staleness budgets breached or approaching. | Notifications dispatched with remediation; timeline events recorded; CLI shows warning banner. |
|
||||
15
src/StellaOps.Api.Governance/AGENTS.md
Normal file
15
src/StellaOps.Api.Governance/AGENTS.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# API Governance Guild Charter
|
||||
|
||||
## Mission
|
||||
Enforce API contract quality through linting, compatibility checks, version policy automation, and changelog generation.
|
||||
|
||||
## Scope
|
||||
- Maintain lint rule set, compatibility diff tooling, and CI integration.
|
||||
- Gate PRs on contract validation, example coverage, and naming conventions.
|
||||
- Produce automated changelogs and deprecation notices from OAS diffs.
|
||||
- Coordinate with Notifications Studio for deprecation broadcasts.
|
||||
|
||||
## Definition of Done
|
||||
- CI gate prevents merging incompatible or non-conforming specs.
|
||||
- Version bump tooling produces signed changelog artifacts per release.
|
||||
- Governance documentation kept current in `/docs/contributing/api-contracts.md`.
|
||||
18
src/StellaOps.Api.Governance/TASKS.md
Normal file
18
src/StellaOps.Api.Governance/TASKS.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# API Governance Task Board — Epic 17: SDKs & OpenAPI Docs
|
||||
|
||||
## Sprint 61 – Lint & CI Integration
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| APIGOV-61-001 | TODO | API Governance Guild | OAS-61-002 | Configure spectral/linters with Stella rules; add CI job failing on violations. | Lint pipeline runs on PRs; rule set documented; intentional violations blocked. |
|
||||
| APIGOV-61-002 | TODO | API Governance Guild | APIGOV-61-001 | Implement example coverage checker ensuring every operation has at least one request/response example. | Coverage job integrated; failing operations listed in CI output. |
|
||||
|
||||
## Sprint 62 – Compatibility & Changelog
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| APIGOV-62-001 | TODO | API Governance Guild | APIGOV-61-001 | Build compatibility diff tool producing additive/breaking reports comparing prior release. | Diff output consumed in CI; failing on breaking changes unless override provided. |
|
||||
| APIGOV-62-002 | TODO | API Governance Guild, DevOps Guild | APIGOV-62-001 | Automate changelog generation and publish signed artifacts to `src/StellaOps.Sdk.Release` pipeline. | Changelog pipeline produces markdown + JSON; signatures verified; docs updated. |
|
||||
|
||||
## Sprint 63 – Deprecation & Notifications
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| APIGOV-63-001 | TODO | API Governance Guild, Notifications Guild | APIGOV-62-002 | Integrate deprecation metadata into Notification Studio templates for API sunset events. | Deprecation pipeline triggers notifier template; staging test proves delivery. |
|
||||
16
src/StellaOps.Api.OpenApi/AGENTS.md
Normal file
16
src/StellaOps.Api.OpenApi/AGENTS.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# StellaOps API Contracts Guild Charter
|
||||
|
||||
## Mission
|
||||
Maintain OpenAPI 3.1 specifications for every StellaOps service, compose the aggregate spec, and ensure API contract consistency across releases.
|
||||
|
||||
## Scope
|
||||
- Author and review per-service OAS documents in `src/StellaOps.Api.OpenApi/<service>/openapi.yaml`.
|
||||
- Operate the aggregate composer producing `src/StellaOps.Api.OpenApi/stella.yaml`.
|
||||
- Provide shared components, schema libraries, and example catalogs.
|
||||
- Coordinate with service guilds on contract changes, examples, and versioning.
|
||||
- Own CI validation, linting, and compatibility diff tooling for OAS artifacts.
|
||||
|
||||
## Definition of Done
|
||||
- All public endpoints represented in OAS with validated request/response examples.
|
||||
- Aggregate spec builds deterministically and passes lint + compatibility checks.
|
||||
- Change logs generated with every release and linked to developer portal updates.
|
||||
19
src/StellaOps.Api.OpenApi/TASKS.md
Normal file
19
src/StellaOps.Api.OpenApi/TASKS.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# API OpenAPI Task Board — Epic 17: SDKs & OpenAPI Docs
|
||||
|
||||
## Sprint 61 – Spec Foundations
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| OAS-61-001 | TODO | API Contracts Guild | — | Scaffold per-service OpenAPI 3.1 files with shared components, info blocks, and initial path stubs. | All services have baseline `openapi.yaml`; shared components library established; lint passes. |
|
||||
| OAS-61-002 | TODO | API Contracts Guild, DevOps Guild | OAS-61-001 | Implement aggregate composer (`stella.yaml`) resolving `$ref`s and merging shared components; wire into CI. | Aggregate spec builds deterministically; CI artifact published; documentation updated. |
|
||||
|
||||
## Sprint 62 – Examples & Error Envelope
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| OAS-62-001 | TODO | API Contracts Guild, Service Guilds | OAS-61-001 | Populate request/response examples for top 50 endpoints, including standard error envelope. | Examples validated via CI; error envelope consistent across services. |
|
||||
| OAS-62-002 | TODO | API Contracts Guild | OAS-61-002 | Add custom lint rules enforcing pagination, idempotency headers, naming conventions, and example coverage. | Lint job fails on violations; documentation for rules published. |
|
||||
|
||||
## Sprint 63 – Compatibility & Discovery
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| OAS-63-001 | TODO | API Contracts Guild | OAS-61-002 | Implement compatibility diff tooling comparing previous release specs; classify breaking vs additive changes. | Diff tool integrated in CI; PRs flagged on breaking changes. |
|
||||
| OAS-63-002 | TODO | API Contracts Guild, Gateway Guild | OAS-62-002 | Add `/.well-known/openapi` discovery endpoint schema metadata (extensions, version info). | Discovery endpoints defined in spec; linked to implementation tasks. |
|
||||
15
src/StellaOps.Attestor.Envelope/AGENTS.md
Normal file
15
src/StellaOps.Attestor.Envelope/AGENTS.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Attestation Envelope Guild Charter
|
||||
|
||||
## Mission
|
||||
Provide deterministic DSSE envelope handling with multi-signature support, canonical serialization, hashing, and integrity safeguards for all Stella attestations.
|
||||
|
||||
## Scope
|
||||
- DSSE encoding/decoding, canonical JSON handling, and detached payload support.
|
||||
- Multi-signature verification, key identification, and cryptographic primitives.
|
||||
- Integration with KMS drivers and transparency log witness utilities.
|
||||
- Fuzz and property testing for envelope parsing and normalization.
|
||||
|
||||
## Definition of Done
|
||||
- Envelope APIs produce canonical payloads and support multiple signatures deterministically.
|
||||
- Verification detects tampering, mismatched subjects, and unsupported algorithms.
|
||||
- Property and fuzz tests cover canonicalization and signature edge cases.
|
||||
13
src/StellaOps.Attestor.Envelope/TASKS.md
Normal file
13
src/StellaOps.Attestor.Envelope/TASKS.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Attestation Envelope Task Board — Epic 19: Attestor Console
|
||||
|
||||
## Sprint 72 – Foundations
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| ATTEST-ENVELOPE-72-001 | TODO | Envelope Guild | — | Implement DSSE canonicalization, JSON normalization, multi-signature structures, and hashing helpers. | Canonicalization deterministic (property tests); hash matches DSSE spec; unit tests green. |
|
||||
| ATTEST-ENVELOPE-72-002 | TODO | Envelope Guild | ATTEST-ENVELOPE-72-001 | Support compact and expanded JSON output, payload compression, and detached payload references. | API returns both variants; payload compression toggles tested; docs updated. |
|
||||
|
||||
## Sprint 73 – Crypto Integration
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| ATTEST-ENVELOPE-73-001 | TODO | Envelope Guild, KMS Guild | ATTEST-ENVELOPE-72-001 | Implement Ed25519 & ECDSA signature create/verify helpers, key identification (`keyid`) scheme, and error mapping. | Sign/verify tests pass with fixtures; invalid signatures produce deterministic errors. |
|
||||
| ATTEST-ENVELOPE-73-002 | TODO | Envelope Guild | ATTEST-ENVELOPE-73-001 | Add fuzz tests for envelope parsing, signature verification, and canonical JSON round-trips. | Fuzz suite integrated; coverage metrics recorded; no regressions. |
|
||||
14
src/StellaOps.Attestor.Types/AGENTS.md
Normal file
14
src/StellaOps.Attestor.Types/AGENTS.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Attestation Payloads Guild Charter
|
||||
|
||||
## Mission
|
||||
Define strongly typed, versioned schemas for all attestation payloads and provide validation utilities for generating and verifying evidence.
|
||||
|
||||
## Scope
|
||||
- JSON Schemas, code generation, and documentation for each attestation type.
|
||||
- Normalization and validation logic shared across services, CLI, and SDKs.
|
||||
- Sample payloads and golden fixtures used in contract tests and docs.
|
||||
|
||||
## Definition of Done
|
||||
- Payload types compiled into Go/TypeScript models with validation helpers.
|
||||
- Schemas published with semantic versioning and change logs.
|
||||
- Golden samples maintained with acceptance tests and doc integration.
|
||||
13
src/StellaOps.Attestor.Types/TASKS.md
Normal file
13
src/StellaOps.Attestor.Types/TASKS.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Attestation Payloads Task Board — Epic 19: Attestor Console
|
||||
|
||||
## Sprint 72 – Schema Definition
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| ATTEST-TYPES-72-001 | TODO | Attestation Payloads Guild | — | Draft JSON Schemas for BuildProvenance v1, SBOMAttestation v1, VEXAttestation v1, ScanResults v1, PolicyEvaluation v1, RiskProfileEvidence v1, CustomEvidence v1. | Schemas validated with test fixtures; docs stubbed; versioned under `schemas/`. |
|
||||
| ATTEST-TYPES-72-002 | TODO | Attestation Payloads Guild | ATTEST-TYPES-72-001 | Generate Go/TS models from schemas with validation helpers and canonical JSON serialization. | Code generation integrated; lints pass; unit tests cover round-trips. |
|
||||
|
||||
## Sprint 73 – Fixtures & Docs
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| ATTEST-TYPES-73-001 | TODO | Attestation Payloads Guild | ATTEST-TYPES-72-002 | Create golden payload samples for each type; integrate into tests and documentation. | Golden fixtures stored; tests compare outputs; docs embed examples. |
|
||||
| ATTEST-TYPES-73-002 | TODO | Attestation Payloads Guild, Docs Guild | ATTEST-TYPES-73-001 | Publish schema reference docs (`/docs/attestor/payloads.md`) with annotated JSON examples. | Doc merged with banner; examples validated by tests. |
|
||||
14
src/StellaOps.Attestor.Verify/AGENTS.md
Normal file
14
src/StellaOps.Attestor.Verify/AGENTS.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Attestation Verification Guild Charter
|
||||
|
||||
## Mission
|
||||
Implement the verification engine that enforces attestation policies, issuer trust, transparency requirements, and produces audit-ready reports.
|
||||
|
||||
## Scope
|
||||
- Verification pipeline integrating DSSE validation, issuer/key trust, Policy Studio rules, freshness checks, and transparency proofs.
|
||||
- Caching and reporting for verification results.
|
||||
- Error codes and explainability artifacts for UI/CLI consumption.
|
||||
|
||||
## Definition of Done
|
||||
- Verification passes/fails deterministically with detailed report structures.
|
||||
- Caching improves performance without sacrificing correctness.
|
||||
- Policies enforce scope-based rules and waivers, with unit/integration coverage.
|
||||
13
src/StellaOps.Attestor.Verify/TASKS.md
Normal file
13
src/StellaOps.Attestor.Verify/TASKS.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Attestation Verification Task Board — Epic 19: Attestor Console
|
||||
|
||||
## Sprint 73 – Policy Integration
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| ATTEST-VERIFY-73-001 | TODO | Verification Guild, Policy Guild | VERPOL-73-001, ATTESTOR-73-002 | Implement verification engine: policy evaluation, issuer trust resolution, freshness, signature count, transparency checks; produce structured reports. | Engine returns report DTOs; policy rules honored; unit tests cover pass/fail scenarios. |
|
||||
| ATTEST-VERIFY-73-002 | TODO | Verification Guild | ATTEST-VERIFY-73-001 | Add caching layer keyed by `(subject, envelope_id, policy_version)` with TTL and invalidation on new evidence. | Cache reduces repeated verification cost; tests cover cache hits/misses. |
|
||||
|
||||
## Sprint 74 – Explainability & Observability
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| ATTEST-VERIFY-74-001 | TODO | Verification Guild, Observability Guild | ATTEST-VERIFY-73-001 | Emit telemetry (spans/metrics) tagged by subject, issuer, policy, result; integrate with dashboards. | Metrics visible; spans present; SLO thresholds defined. |
|
||||
| ATTEST-VERIFY-74-002 | TODO | Verification Guild, Docs Guild | ATTEST-VERIFY-73-001 | Document verification report schema and explainability in `/docs/attestor/workflows.md`. | Documentation merged; examples verified via tests. |
|
||||
@@ -14,8 +14,26 @@ Operate the StellaOps Attestor service: accept signed DSSE envelopes from the Si
|
||||
- Structured logs + metrics for each stage (`validate`, `submit`, `proof`, `persist`, `archive`).
|
||||
- Update `TASKS.md`, architecture docs, and tests whenever behaviour changes.
|
||||
|
||||
## Key Directories
|
||||
- `src/StellaOps.Attestor/StellaOps.Attestor.WebService/` — Minimal API host and HTTP surface.
|
||||
- `src/StellaOps.Attestor/StellaOps.Attestor.Core/` — Domain contracts, submission/verification pipelines.
|
||||
- `src/StellaOps.Attestor/StellaOps.Attestor.Infrastructure/` — Mongo, Redis, Rekor, and archival implementations.
|
||||
- `src/StellaOps.Attestor/StellaOps.Attestor.Tests/` — Unit and integration tests.
|
||||
## Key Directories
|
||||
- `src/StellaOps.Attestor/StellaOps.Attestor.WebService/` — Minimal API host and HTTP surface.
|
||||
- `src/StellaOps.Attestor/StellaOps.Attestor.Core/` — Domain contracts, submission/verification pipelines.
|
||||
- `src/StellaOps.Attestor/StellaOps.Attestor.Infrastructure/` — Mongo, Redis, Rekor, and archival implementations.
|
||||
- `src/StellaOps.Attestor/StellaOps.Attestor.Tests/` — Unit and integration tests.
|
||||
|
||||
---
|
||||
|
||||
## Epic 19 Charter — Attestor Console
|
||||
|
||||
### Mission
|
||||
Deliver the API, workers, and storage that power signing, verification, and lifecycle management of supply-chain attestations across StellaOps.
|
||||
|
||||
### Scope
|
||||
- DSSE envelope ingestion and retrieval.
|
||||
- Verification pipeline orchestration, caching, and policy evaluation.
|
||||
- Issuer/key registries, transparency log integration, and audit logging.
|
||||
- Bulk verification workflows and air-gap bundle support.
|
||||
|
||||
### Definition of Done
|
||||
- Signing and verification APIs operate deterministically with full explainability.
|
||||
- Policy enforcement integrated with Authority & Tenancy scopes.
|
||||
- Transparency proof handling, key rotation, and revocation workflows implemented.
|
||||
|
||||
@@ -6,5 +6,36 @@
|
||||
| ATTESTOR-VERIFY-11-202 | DONE (2025-10-19) | Attestor Guild | — | `/rekor/verify` + retrieval endpoints validating signatures and Merkle proofs. | ✅ `GET /api/v1/rekor/entries/{uuid}` surfaces cached entries with optional backend refresh and handles not-found/refresh flows.<br>✅ `POST /api/v1/rekor/verify` accepts UUID, bundle, or artifact hash inputs; verifies DSSE signatures, Merkle proofs, and checkpoint anchors.<br>✅ Verification output returns `{ok, uuid, index, logURL, checkedAt}` with failure diagnostics for invalid proofs.<br>✅ Unit/integration tests exercise cache hits, backend refresh, invalid bundle/proof scenarios, and checkpoint trust anchor enforcement. |
|
||||
| ATTESTOR-OBS-11-203 | DONE (2025-10-19) | Attestor Guild | — | Telemetry, alerting, mTLS hardening, and archive workflow for Attestor. | ✅ Structured logs, metrics, and optional traces record submission latency, proof fetch outcomes, verification results, and Rekor error buckets with correlation IDs.<br>✅ mTLS enforcement hardened (peer allowlist, SAN checks, rate limiting) and documented; TLS settings audited for modern ciphers only.<br>✅ Alerting/dashboard pack covers error rates, proof backlog, Redis/Mongo health, and archive job failures; runbook updated.<br>✅ Archive workflow includes retention policy jobs, failure alerts, and periodic verification of stored bundles and proofs. |
|
||||
|
||||
> Remark (2025-10-19): Wave 0 prerequisites reviewed (none outstanding); ATTESTOR-API-11-201, ATTESTOR-VERIFY-11-202, and ATTESTOR-OBS-11-203 tracked as DOING per Wave 0A kickoff.
|
||||
> Remark (2025-10-19): Dual-log submissions, signature/proof verification, and observability hardening landed; attestor endpoints now rate-limited per client with correlation-ID logging and updated docs/tests.
|
||||
> Remark (2025-10-19): Wave 0 prerequisites reviewed (none outstanding); ATTESTOR-API-11-201, ATTESTOR-VERIFY-11-202, and ATTESTOR-OBS-11-203 tracked as DOING per Wave 0A kickoff.
|
||||
> Remark (2025-10-19): Dual-log submissions, signature/proof verification, and observability hardening landed; attestor endpoints now rate-limited per client with correlation-ID logging and updated docs/tests.
|
||||
|
||||
---
|
||||
|
||||
## Epic 19 — Attestor Console Roadmap
|
||||
|
||||
### Sprint 72 – Foundations
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| ATTESTOR-72-001 | TODO | Attestor Service Guild | ATTEST-ENVELOPE-72-001 | Scaffold service (REST API skeleton, storage interfaces, KMS integration stubs) and DSSE validation pipeline. | Service builds/tests; signing & verification stubs wired; lint/CI green. |
|
||||
| ATTESTOR-72-002 | TODO | Attestor Service Guild | ATTESTOR-72-001 | Implement attestation store (DB tables, object storage integration), CRUD, and indexing strategies. | Migrations applied; CRUD API functional; storage integration unit tests pass. |
|
||||
|
||||
### Sprint 73 – Signing & Verification
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| ATTESTOR-73-001 | TODO | Attestor Service Guild, KMS Guild | ATTESTOR-72-002, KMS-72-001 | Implement signing endpoint with Ed25519/ECDSA support, KMS integration, and audit logging. | `POST /v1/attestations:sign` functional; audit entries recorded; tests cover success/failure. |
|
||||
| ATTESTOR-73-002 | TODO | Attestor Service Guild, Policy Guild | ATTESTOR-72-002, VERPOL-73-001 | Build verification pipeline evaluating DSSE signatures, issuer trust, and verification policies; persist reports. | Verification endpoint returns structured report; results cached; contract tests pass. |
|
||||
| ATTESTOR-73-003 | TODO | Attestor Service Guild | ATTESTOR-73-002 | Implement listing/fetch APIs with filters (subject, type, issuer, scope, date). | API documented; pagination works; contract tests green. |
|
||||
|
||||
### Sprint 74 – Transparency & Bulk
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| ATTESTOR-74-001 | TODO | Attestor Service Guild | ATTESTOR-73-002, TRANSP-74-001 | Integrate transparency witness client, inclusion proof verification, and caching. | Witness proofs stored; verification fails on missing/inconsistent proofs; metrics emitted. |
|
||||
| ATTESTOR-74-002 | TODO | Attestor Service Guild | ATTESTOR-73-002 | Implement bulk verification worker + API with progress tracking, rate limits, and caching. | Bulk job API functional; worker processes batches; telemetry recorded. |
|
||||
|
||||
### Sprint 75 – Air Gap & Hardening
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| ATTESTOR-75-001 | TODO | Attestor Service Guild, Export Guild | ATTESTOR-74-002, EXPORT-ATTEST-74-001 | Add export/import flows for attestation bundles and offline verification mode. | Bundles generated/imported; offline verification path documented; tests cover missing witness data. |
|
||||
| ATTESTOR-75-002 | TODO | Attestor Service Guild, Security Guild | ATTESTOR-73-002 | Harden APIs with rate limits, auth scopes, threat model mitigations, and fuzz testing. | Rate limiting enforced; fuzz tests run in CI; threat model actions resolved. |
|
||||
|
||||
*** End Task Board ***
|
||||
|
||||
@@ -1,31 +1,136 @@
|
||||
# Authority Host Task Board (UTC 2025-10-10)
|
||||
# Authority Host Task Board — Epic 1: Aggregation-Only Contract
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AUTH-AOC-19-001 | TODO | Authority Core & Security Guild | — | Introduce scopes `advisory:read`, `advisory:ingest`, `vex:read`, `vex:ingest`, `aoc:verify` with configuration binding, migrations, and offline kit defaults. | Scopes published in metadata/OpenAPI, configuration validates scope lists, tests cover token issuance + enforcement. |
|
||||
| AUTH-AOC-19-002 | TODO | Authority Core & Security Guild | AUTH-AOC-19-001 | Propagate tenant claim + scope enforcement for ingestion identities; ensure cross-tenant writes/read blocked and audit logs capture tenant context. | Tenant claim injected into downstream services; forbidden cross-tenant access rejected; audit/log fixtures updated. |
|
||||
| AUTH-AOC-19-003 | TODO | Authority Core & Docs Guild | AUTH-AOC-19-001 | Update Authority docs and sample configs to describe new scopes, tenancy enforcement, and verify endpoints. | Docs and examples refreshed; release notes prepared; smoke tests confirm new scopes required. |
|
||||
|
||||
## Policy Engine v2
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| CORE5B.DOC | DONE (2025-10-12) | Authority Core, Docs Guild | CORE5 | Document token persistence, revocation semantics, and enrichment expectations for resource servers/plugins. | ✅ `docs/11_AUTHORITY.md` + plugin guide updated with claims + token store notes; ✅ Samples include revocation sync guidance. |
|
||||
| CORE9.REVOCATION | DONE (2025-10-12) | Authority Core, Security Guild | CORE5 | Implement revocation list persistence + export hooks (API + CLI). | ✅ Revoked tokens denied; ✅ Export endpoint/CLI returns manifest; ✅ Tests cover offline bundle flow. |
|
||||
| CORE10.JWKS | DONE (2025-10-12) | Authority Core, DevOps | CORE9.REVOCATION | Provide JWKS rotation with pluggable key loader + documentation. | ✅ Signing/encryption keys rotate without downtime; ✅ JWKS endpoint updates; ✅ Docs describe rotation SOP. |
|
||||
| CORE8.RL | DONE (2025-10-12) | Authority Core | CORE8 | Deliver ASP.NET rate limiter plumbing (request metadata, dependency injection hooks) needed by Security Guild. | ✅ `/token` & `/authorize` pipelines expose limiter hooks; ✅ Tests cover throttle behaviour baseline. |
|
||||
| SEC2.HOST | DONE (2025-10-12) | Security Guild, Authority Core | SEC2.A (audit contract) | Hook audit logger into OpenIddict handlers and bootstrap endpoints. | ✅ Audit events populated with correlationId, IP, client_id; ✅ Mongo login attempts persisted; ✅ Tests verify on success/failure/lockout. |
|
||||
| SEC3.HOST | DONE (2025-10-11) | Security Guild | CORE8.RL, SEC3.A (rate policy) | Apply rate limiter policies (`AddRateLimiter`) to `/token` and `/internal/*` endpoints with configuration binding. | ✅ Policies configurable via `StellaOpsAuthorityOptions.Security.RateLimiting`; ✅ Integration tests hit 429 after limit; ✅ Docs updated. |
|
||||
| SEC4.HOST | DONE (2025-10-12) | Security Guild, DevOps | SEC4.A (revocation schema) | Implement CLI/HTTP surface to export revocation bundle + detached JWS using `StellaOps.Cryptography`. | ✅ `stellaops auth revoke export` CLI/endpoint returns JSON + `.jws`; ✅ Verification script passes; ✅ Operator docs updated. |
|
||||
| SEC4.KEY | DONE (2025-10-12) | Security Guild, DevOps | SEC4.HOST | Integrate signing keys with provider registry (initial ES256). | ✅ Keys loaded via `ICryptoProvider` signer; ✅ Rotation SOP documented. |
|
||||
| SEC5.HOST | DONE (2025-10-14) | Security Guild | SEC5.A (threat model) | Feed Authority-specific mitigations (rate limiting, audit, revocation) into threat model + backlog. | ✅ Threat model updated; ✅ Backlog issues reference mitigations; ✅ Review sign-off captured. |
|
||||
| SEC5.HOST-INVITES | DONE (2025-10-14) | Security Guild, Authority Core | SEC5.D | Implement bootstrap invite persistence, APIs, and background cleanup with audit coverage. | ✅ Invite store + endpoints complete; ✅ Cleanup service expires unused invites; ✅ Audit events for create/consume/expire; ✅ Build/tests green. |
|
||||
> Remark (2025-10-14): Background sweep emits invite expiry audits; integration test added.
|
||||
| SEC5.HOST-REPLAY | DONE (2025-10-14) | Security Guild, Zastava | SEC5.E | Persist token usage metadata and surface suspected replay heuristics. | ✅ Validation handlers record device metadata; ✅ Suspected replay flagged via audit/logs; ✅ Tests cover regression cases. |
|
||||
> Remark (2025-10-14): Token validation handler logs suspected replay audits with device metadata; coverage via unit/integration tests.
|
||||
| SEC3.BUILD | DONE (2025-10-11) | Authority Core, Security Guild | SEC3.HOST, FEEDMERGE-COORD-02-900 | Track normalized-range dependency fallout and restore full test matrix once Concelier range primitives land. | ✅ Concelier normalized range libraries merged; ✅ Authority + Configuration test suites (`dotnet test src/StellaOps.Authority.sln`, `dotnet test src/StellaOps.Configuration.Tests/StellaOps.Configuration.Tests.csproj`) pass without Concelier compile failures; ✅ Status recorded here/Sprints (authority-core broadcast not available). |
|
||||
| AUTHCORE-BUILD-OPENIDDICT | DONE (2025-10-14) | Authority Core | SEC2.HOST | Adapt host/audit handlers for OpenIddict 6.4 API surface (no `OpenIddictServerTransaction`) and restore Authority solution build. | ✅ Build `dotnet build src/StellaOps.Authority.sln` succeeds; ✅ Audit correlation + tamper logging verified under new abstractions; ✅ Tests updated. |
|
||||
| AUTHCORE-STORAGE-DEVICE-TOKENS | DONE (2025-10-14) | Authority Core, Storage Guild | AUTHCORE-BUILD-OPENIDDICT | Reintroduce `AuthorityTokenDeviceDocument` + projections removed during refactor so storage layer compiles. | ✅ Document type restored with mappings/migrations; ✅ Storage tests cover device artifacts; ✅ Authority solution build green. |
|
||||
| AUTHCORE-BOOTSTRAP-INVITES | DONE (2025-10-14) | Authority Core, DevOps | AUTHCORE-STORAGE-DEVICE-TOKENS | Wire bootstrap invite cleanup service against restored document schema and re-enable lifecycle tests. | ✅ `BootstrapInviteCleanupService` passes integration tests; ✅ Operator guide updated if behavior changes; ✅ Build/test matrices green. |
|
||||
| AUTHSTORAGE-MONGO-08-001 | DONE (2025-10-19) | Authority Core & Storage Guild | — | Harden Mongo session usage with causal consistency for mutations and follow-up reads. | • Scoped middleware/service creates `IClientSessionHandle` with causal consistency + majority read/write concerns<br>• Stores accept optional session parameter and reuse it for write + immediate reads<br>• GraphQL/HTTP pipelines updated to flow session through post-mutation queries<br>• Replica-set integration test exercises primary election and verifies read-your-write guarantees |
|
||||
| AUTH-PLUGIN-COORD-08-002 | DONE (2025-10-20) | Authority Core, Plugin Platform Guild | PLUGIN-DI-08-001 | Coordinate scoped-service adoption for Authority plug-in registrars and background jobs ahead of PLUGIN-DI-08-002 implementation. | ✅ Workshop completed 2025-10-20 15:00–16:05 UTC with notes/action log in `docs/dev/authority-plugin-di-coordination.md`; ✅ Follow-up backlog updates assigned via documented action items ahead of PLUGIN-DI-08-002 delivery. |
|
||||
| AUTH-DPOP-11-001 | DONE (2025-10-20) | Authority Core & Security Guild | — | Implement DPoP proof validation + nonce handling for high-value audiences per architecture. | ✅ Redis-configurable nonce store surfaced via `security.senderConstraints.dpop.nonce` with sample YAML and architecture docs refreshed<br>✅ High-value audience enforcement uses normalised required audiences to avoid whitespace/case drift<br>✅ Operator guide updated with Redis-backed nonce snippet and env-var override guidance; integration test already covers nonce challenge |
|
||||
> Remark (2025-10-20): `etc/authority.yaml.sample` gains senderConstraint sections (rate limits, DPoP, mTLS), docs (`docs/ARCHITECTURE_AUTHORITY.md`, `docs/11_AUTHORITY.md`, plan) refreshed. `ResolveNonceAudience` now relies on `NormalizedAudiences` and options trim persisted values. `dotnet test StellaOps.Authority.sln` attempted (2025-10-20 15:12 UTC) but failed on `NU1900` because the mirrored NuGet service index `https://mirrors.ablera.dev/nuget/nuget-mirror/v3/index.json` was unreachable; no project build executed.
|
||||
| AUTH-MTLS-11-002 | DONE (2025-10-23) | Authority Core & Security Guild | — | Add OAuth mTLS client credential support with certificate-bound tokens and introspection updates. | ✅ Deterministic provisioning/storage for certificate bindings (thumbprint/subject/issuer/serial/SAN)<br>✅ Audience enforcement auto-switches to mTLS via `security.senderConstraints.mtls.enforceForAudiences`<br>✅ Validator matches binding metadata with rotation grace and emits confirmation thumbprints<br>✅ Introspection returns `cnf.x5t#S256`; docs & sample config refreshed; Authority test suite green |
|
||||
> Remark (2025-10-23): Audience enforcement now rejects non-mTLS clients targeting high-value audiences; certificate validator checks binding subject/issuer/serial/SAN values and returns deterministic error codes. Docs (`docs/11_AUTHORITY.md`, `docs/ARCHITECTURE_AUTHORITY.md`, `docs/dev/authority-dpop-mtls-plan.md`) and `etc/authority.yaml.sample` updated. `dotnet test src/StellaOps.Authority/StellaOps.Authority.sln` (2025-10-23 18:07 UTC) succeeded.
|
||||
> Remark (2025-10-19, AUTHSTORAGE-MONGO-08-001): Prerequisites re-checked (none outstanding). Session accessor wired through Authority pipeline; stores accept optional sessions; added replica-set election regression test for read-your-write.
|
||||
> Remark (2025-10-19, AUTH-DPOP-11-001): Handler, nonce store, and persistence hooks merged; Redis-backed configuration + end-to-end nonce enforcement still open. (Superseded by 2025-10-20 update above.)
|
||||
| AUTH-POLICY-20-001 | TODO | Authority Core & Security Guild | AUTH-AOC-19-001 | Add scopes `policy:write`, `policy:submit`, `policy:approve`, `policy:run`, `findings:read`, `effective:write` with configuration binding and issuer policy updates. | Scopes available in metadata; token issuance validated; offline kit defaults updated; tests cover scope combinations. |
|
||||
| AUTH-POLICY-20-002 | TODO | Authority Core & Security Guild | AUTH-POLICY-20-001, AUTH-AOC-19-002 | Enforce Policy Engine service identity with `effective:write` and ensure API gateway enforces scopes/tenant claims for new endpoints. | Gateway policies updated; unauthorized requests rejected in tests; audit logs capture scope usage. |
|
||||
| AUTH-POLICY-20-003 | TODO | Authority Core & Docs Guild | AUTH-POLICY-20-001 | Update Authority configuration/docs with policy scopes, service identities, and approval workflows; include compliance checklist. | Docs refreshed; samples updated; release notes prepared; doc lint passes. |
|
||||
|
||||
> Update status columns (TODO / DOING / DONE / BLOCKED) together with code changes. Always run `dotnet test src/StellaOps.Authority.sln` when touching host logic.
|
||||
## Graph Explorer v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AUTH-GRAPH-21-001 | TODO | Authority Core & Security Guild | AUTH-POLICY-20-001 | Define scopes `graph:write`, `graph:read`, `graph:export`, `graph:simulate`, update metadata/OpenAPI, and add OFFLINE kit defaults. | Scopes exposed via discovery docs; smoke tests ensure enforcement; offline kit updated. |
|
||||
| AUTH-GRAPH-21-002 | TODO | Authority Core & Security Guild | AUTH-GRAPH-21-001, AUTH-AOC-19-002 | Wire gateway enforcement for new graph scopes, Cartographer service identity, and tenant propagation across graph APIs. | Gateway config updated; unauthorized access blocked in integration tests; audit logs include graph scope usage. |
|
||||
| AUTH-GRAPH-21-003 | TODO | Authority Core & Docs Guild | AUTH-GRAPH-21-001 | Update security docs and samples describing graph access roles, least privilege guidance, and service identities. | Docs merged with compliance checklist; examples refreshed; release notes prepared. |
|
||||
|
||||
## Policy Engine + Editor v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AUTH-POLICY-23-001 | TODO | Authority Core & Security Guild | AUTH-POLICY-20-001 | Introduce fine-grained scopes `policy:read`, `policy:edit`, `policy:approve`, `policy:activate`, `policy:simulate`; update issuer templates and metadata. | Scopes exposed; integration tests confirm enforcement; offline kit updated. |
|
||||
| AUTH-POLICY-23-002 | TODO | Authority Core & Security Guild | AUTH-POLICY-23-001 | Implement optional two-person rule for activation: require two distinct `policy:activate` approvals when configured; emit audit logs. | Activation endpoint enforces rule; audit logs contain approver IDs; tests cover 2-person path. |
|
||||
| AUTH-POLICY-23-003 | TODO | Authority Core & Docs Guild | AUTH-POLICY-23-001 | Update documentation and sample configs for policy roles, approval workflow, and signing requirements. | Docs updated with reviewer checklist; configuration examples validated. |
|
||||
|
||||
## Graph & Vuln Explorer v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AUTH-GRAPH-24-001 | TODO | Authority Core & Security Guild | AUTH-GRAPH-21-001 | Extend scopes to include `vuln:read` and signed permalinks with scoped claims for Graph/Vuln Explorer; update metadata. | Scopes published; permalinks validated; integration tests cover RBAC. |
|
||||
|
||||
## Orchestrator Dashboard
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AUTH-ORCH-32-001 | TODO | Authority Core & Security Guild | — | Define `orch:read` scope, register `Orch.Viewer` role, update discovery metadata, and seed offline defaults. | Scope/role available in metadata; integration tests confirm read-only enforcement; offline kit updated. |
|
||||
| AUTH-ORCH-33-001 | TODO | Authority Core & Security Guild | AUTH-ORCH-32-001 | Add `Orch.Operator` role/scopes for control actions, require reason/ticket attributes, and update issuer templates. | Operator tokens issued; action endpoints enforce scope + reason; audit logs capture operator info; docs refreshed. |
|
||||
| AUTH-ORCH-34-001 | TODO | Authority Core & Security Guild | AUTH-ORCH-33-001 | Introduce `Orch.Admin` role with quota/backfill scopes, enforce audit reason on quota changes, and update offline defaults/docs. | Admin role available; quotas/backfills require scope + reason; tests confirm tenant isolation; documentation updated. |
|
||||
|
||||
## StellaOps Console (Sprint 23)
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AUTH-CONSOLE-23-001 | TODO | Authority Core & Security Guild | AUTH-POLICY-20-001 | Register StellaOps Console confidential client with OIDC PKCE support, short-lived ID/access tokens, `console:*` audience claims, and SPA-friendly refresh (token exchange endpoint). Publish discovery metadata + offline kit defaults. | Client registration committed, configuration templates updated, integration tests validate PKCE + scope issuance, security review recorded. |
|
||||
| AUTH-CONSOLE-23-002 | TODO | Authority Core & Security Guild | AUTH-CONSOLE-23-001, AUTH-AOC-19-002 | Expose tenant catalog, user profile, and token introspection endpoints required by Console (fresh-auth prompts, scope checks); enforce tenant header requirements and audit logging with correlation IDs. | Endpoints ship with RBAC enforcement, audit logs include tenant+scope, integration tests cover unauthorized/tenant-mismatch scenarios. |
|
||||
| AUTH-CONSOLE-23-003 | TODO | Authority Core & Docs Guild | AUTH-CONSOLE-23-001, AUTH-CONSOLE-23-002 | Update security docs/config samples for Console flows (PKCE, tenant badge, fresh-auth for admin actions, session inactivity timeouts) with compliance checklist. | Docs merged, config samples validated, release notes updated, ops runbook references new flows. |
|
||||
|
||||
## Policy Studio (Sprint 27)
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AUTH-POLICY-27-001 | TODO | Authority Core & Security Guild | AUTH-POLICY-20-001, AUTH-CONSOLE-23-001 | Define Policy Studio roles (`policy:author`, `policy:review`, `policy:approve`, `policy:operate`, `policy:audit`) with tenant-scoped claims, update issuer metadata, and seed offline kit defaults. | Scopes/roles exposed via discovery docs; tokens issued with correct claims; integration tests cover role combinations; docs updated. |
|
||||
| AUTH-POLICY-27-002 | TODO | Authority Core & Security Guild | AUTH-POLICY-27-001, REGISTRY-API-27-007 | Provide attestation signing service bindings (OIDC token exchange, cosign integration) and enforce publish/promote scope checks, fresh-auth requirements, and audit logging. | Publish/promote requests require fresh auth + correct scopes; attestations signed with validated identity; audit logs enriched with digest + tenant; integration tests pass. |
|
||||
| AUTH-POLICY-27-003 | TODO | Authority Core & Docs Guild | AUTH-POLICY-27-001, AUTH-POLICY-27-002 | Update Authority configuration/docs for Policy Studio roles, signing policies, approval workflows, and CLI integration; include compliance checklist. | Docs merged; samples validated; governance checklist appended; release notes updated. |
|
||||
|
||||
## Exceptions v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AUTH-EXC-25-001 | TODO | Authority Core & Security Guild | AUTH-POLICY-23-001 | Introduce exception scopes (`exceptions:read`, `exceptions:write`, `exceptions:approve`) and approval routing configuration with MFA gating. | Scopes published in metadata; routing matrix validated; integration tests enforce scope + MFA rules. |
|
||||
| AUTH-EXC-25-002 | TODO | Authority Core & Docs Guild | AUTH-EXC-25-001 | Update documentation/samples for exception roles, routing matrix, MFA requirements, and audit trail references. | Docs merged with compliance checklist; samples verified. |
|
||||
|
||||
## Reachability v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AUTH-SIG-26-001 | TODO | Authority Core & Security Guild | AUTH-EXC-25-001 | Add `signals:read`, `signals:write`, `signals:admin` scopes, issue `SignalsUploader` role template, and enforce AOC for sensor identities. | Scopes exposed; configuration validated; integration tests ensure RBAC + AOC enforcement. |
|
||||
|
||||
## Vulnerability Explorer (Sprint 29)
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AUTH-VULN-29-001 | TODO | Authority Core & Security Guild | AUTH-POLICY-27-001 | Define Vuln Explorer scopes/roles (`vuln:view`, `vuln:investigate`, `vuln:operate`, `vuln:audit`) with ABAC attributes (env, owner, business_tier) and update discovery metadata/offline kit defaults. | Roles/scopes published; issuer templates updated; integration tests cover ABAC filters; docs refreshed. |
|
||||
| AUTH-VULN-29-002 | TODO | Authority Core & Security Guild | AUTH-VULN-29-001, LEDGER-29-002 | Enforce CSRF/anti-forgery tokens for workflow actions, sign attachment tokens, and record audit logs with ledger event hashes. | Workflow calls require valid tokens; audit logs include ledger references; security tests cover token expiry/abuse. |
|
||||
| AUTH-VULN-29-003 | TODO | Authority Core & Docs Guild | AUTH-VULN-29-001..002 | Update security docs/config samples for Vuln Explorer roles, ABAC policies, attachment signing, and ledger verification guidance. | Docs merged with compliance checklist; configuration examples validated; release notes updated. |
|
||||
|
||||
## Advisory AI (Sprint 31)
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AUTH-AIAI-31-001 | TODO | Authority Core & Security Guild | AUTH-VULN-29-001 | Define Advisory AI scopes (`advisory-ai:view`, `advisory-ai:operate`, `advisory-ai:admin`) and remote inference toggles; update discovery metadata/offline defaults. | Scopes/flags published; integration tests cover RBAC + opt-in settings; docs updated. |
|
||||
| AUTH-AIAI-31-002 | TODO | Authority Core & Security Guild | AUTH-AIAI-31-001, AIAI-31-006 | Enforce anonymized prompt logging, tenant consent for remote inference, and audit logging of assistant tasks. | Logging/audit flows verified; privacy review passed; docs updated. |
|
||||
|
||||
## Export Center
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AUTH-EXPORT-35-001 | TODO | Authority Core & Security Guild | AUTH-AOC-19-001 | Introduce `Export.Viewer`, `Export.Operator`, `Export.Admin` scopes, configure issuer templates, and update discovery metadata/offline defaults. | Scopes available; metadata updated; tests ensure enforcement; offline kit defaults refreshed. |
|
||||
| AUTH-EXPORT-37-001 | TODO | Authority Core & Security Guild | AUTH-EXPORT-35-001, WEB-EXPORT-37-001 | Enforce admin-only access for scheduling, retention, encryption key references, and verify endpoints with audit reason capture. | Admin scope required; audit logs include reason/ticket; integration tests cover denial cases; docs updated. |
|
||||
|
||||
## Notifications Studio
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AUTH-NOTIFY-38-001 | TODO | Authority Core & Security Guild | — | Define `Notify.Viewer`, `Notify.Operator`, `Notify.Admin` scopes/roles, update discovery metadata, offline defaults, and issuer templates. | Scopes available; metadata updated; tests ensure enforcement; offline kit defaults refreshed. |
|
||||
| AUTH-NOTIFY-40-001 | TODO | Authority Core & Security Guild | AUTH-NOTIFY-38-001, WEB-NOTIFY-40-001 | Implement signed ack token key rotation, webhook allowlists, admin-only escalation settings, and audit logging of ack actions. | Ack tokens signed/rotated; webhook allowlists enforced; admin enforcement validated; audit logs capture ack/resolution. |
|
||||
|
||||
## CLI Parity & Task Packs
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AUTH-PACKS-41-001 | TODO | Authority Core & Security Guild | AUTH-AOC-19-001 | Define CLI SSO profiles and pack scopes (`Packs.Read`, `Packs.Write`, `Packs.Run`, `Packs.Approve`), update discovery metadata, offline defaults, and issuer templates. | Scopes available; metadata updated; tests ensure enforcement; offline kit templates refreshed. |
|
||||
| AUTH-PACKS-43-001 | TODO | Authority Core & Security Guild | AUTH-PACKS-41-001, ORCH-SVC-42-101 | Enforce pack signing policies, approval RBAC checks, CLI CI token scopes, and audit logging for approvals. | Signing policies enforced; approvals require correct roles; CI token scope tests pass; audit logs recorded. |
|
||||
|
||||
## Authority-Backed Scopes & Tenancy (Epic 14)
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AUTH-TEN-47-001 | TODO | Authority Core & Security Guild | AUTH-AOC-19-001 | Align Authority with OIDC/JWT claims (tenants, projects, scopes), implement JWKS caching/rotation, publish scope grammar, and enforce required claims on tokens. | Tokens include tenant/project claims; JWKS cache validated; docs updated; imposed rule noted. |
|
||||
| AUTH-TEN-49-001 | TODO | Authority Core & Security Guild | AUTH-TEN-47-001 | Implement service accounts & delegation tokens (`act` chain), per-tenant quotas, audit stream of auth decisions, and revocation APIs. | Service tokens minted with scopes/TTL; delegation logged; quotas configurable; audit stream live; docs updated. |
|
||||
|
||||
## Observability & Forensics (Epic 15)
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AUTH-OBS-50-001 | TODO | Authority Core & Security Guild | AUTH-AOC-19-001 | Introduce scopes `obs:read`, `timeline:read`, `timeline:write`, `evidence:create`, `evidence:read`, `evidence:hold`, `attest:read`, and `obs:incident` (all tenant-scoped). Update discovery metadata, offline defaults, and scope grammar docs. | Scopes exposed via metadata; issuer templates updated; offline kit seeded; integration tests cover new scopes. |
|
||||
| AUTH-OBS-52-001 | TODO | Authority Core & Security Guild | AUTH-OBS-50-001, TIMELINE-OBS-52-003, EVID-OBS-53-003 | Configure resource server policies for Timeline Indexer, Evidence Locker, Exporter, and Observability APIs enforcing new scopes + tenant claims. Emit audit events including scope usage and trace IDs. | Policies deployed; unauthorized access blocked; audit logs prove scope usage; contract tests updated. |
|
||||
| AUTH-OBS-55-001 | TODO | Authority Core & Security Guild, Ops Guild | AUTH-OBS-50-001, WEB-OBS-55-001 | Harden incident mode authorization: require `obs:incident` scope + fresh auth, log activation reason, and expose verification endpoint for auditors. Update docs/runbooks. | Incident activate/deactivate requires scope; audit entries logged; docs updated with imposed rule reminder. |
|
||||
|
||||
## Air-Gapped Mode (Epic 16)
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AUTH-AIRGAP-56-001 | TODO | Authority Core & Security Guild | AIRGAP-CTL-56-001 | Provision new scopes (`airgap:seal`, `airgap:import`, `airgap:status:read`) in configuration metadata, offline kit defaults, and issuer templates. | Scopes exposed in discovery docs; offline kit updated; integration tests cover issuance. |
|
||||
| AUTH-AIRGAP-56-002 | TODO | Authority Core & Security Guild | AUTH-AIRGAP-56-001, AIRGAP-IMP-58-001 | Audit import actions with actor, tenant, bundle ID, and trace ID; expose `/authority/audit/airgap` endpoint. | Audit records persisted; endpoint paginates results; tests cover RBAC + filtering. |
|
||||
| AUTH-AIRGAP-57-001 | TODO | Authority Core & Security Guild, DevOps Guild | AUTH-AIRGAP-56-001, DEVOPS-AIRGAP-57-002 | Enforce sealed-mode CI gating by refusing token issuance when declared sealed install lacks sealing confirmation. | CI scenario validated; error surfaces remediation; docs updated. |
|
||||
|
||||
## SDKs & OpenAPI (Epic 17)
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| AUTH-OAS-61-001 | TODO | Authority Core & Security Guild, API Contracts Guild | OAS-61-001 | Document Authority authentication/token endpoints in OAS with scopes, examples, and error envelopes. | Spec complete with security schemes; lint passes. |
|
||||
| AUTH-OAS-61-002 | TODO | Authority Core & Security Guild | AUTH-OAS-61-001 | Implement `/.well-known/openapi` with scope metadata, supported grant types, and build version. | Endpoint deployed; contract tests cover discovery. |
|
||||
| AUTH-OAS-62-001 | TODO | Authority Core & Security Guild, SDK Generator Guild | AUTH-OAS-61-001, SDKGEN-63-001 | Provide SDK helpers for OAuth2/PAT flows, tenancy override header; add integration tests. | SDKs expose auth helpers; tests cover token issuance; docs updated. |
|
||||
| AUTH-OAS-63-001 | TODO | Authority Core & Security Guild, API Governance Guild | APIGOV-63-001 | Emit deprecation headers and notifications for legacy auth endpoints. | Headers emitted; notifications verified; migration guide published. |
|
||||
|
||||
54
src/StellaOps.Bench/Scanner.Analyzers/README.md
Normal file
54
src/StellaOps.Bench/Scanner.Analyzers/README.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Scanner Analyzer Microbench Harness
|
||||
|
||||
The bench harness exercises the language analyzers against representative filesystem layouts so that regressions are caught before they ship.
|
||||
|
||||
## Layout
|
||||
- `StellaOps.Bench.ScannerAnalyzers/` – .NET 10 console harness that executes the real language analyzers (and fallback metadata walks for ecosystems that are still underway).
|
||||
- `config.json` – Declarative list of scenarios the harness executes. Each scenario points at a directory in `samples/`.
|
||||
- `baseline.csv` – Reference numbers captured on the 4 vCPU warm rig described in `docs/12_PERFORMANCE_WORKBOOK.md`. CI publishes fresh CSVs so perf trends stay visible.
|
||||
|
||||
## Current scenarios
|
||||
- `node_monorepo_walk` → runs the Node analyzer across `samples/runtime/npm-monorepo`.
|
||||
- `java_demo_archive` → runs the Java analyzer against `samples/runtime/java-demo/libs/demo.jar`.
|
||||
- `python_site_packages_walk` → temporary metadata walk over `samples/runtime/python-venv` until the Python analyzer lands.
|
||||
|
||||
## Running locally
|
||||
|
||||
```bash
|
||||
dotnet run \
|
||||
--project src/StellaOps.Bench/Scanner.Analyzers/StellaOps.Bench.ScannerAnalyzers/StellaOps.Bench.ScannerAnalyzers.csproj \
|
||||
-- \
|
||||
--repo-root . \
|
||||
--out src/StellaOps.Bench/Scanner.Analyzers/baseline.csv \
|
||||
--json out/bench/scanner-analyzers/latest.json \
|
||||
--prom out/bench/scanner-analyzers/latest.prom \
|
||||
--commit "$(git rev-parse HEAD)"
|
||||
```
|
||||
|
||||
The harness prints a table to stdout and writes the CSV (if `--out` is specified) with the following headers:
|
||||
|
||||
```
|
||||
scenario,iterations,sample_count,mean_ms,p95_ms,max_ms
|
||||
```
|
||||
|
||||
Additional outputs:
|
||||
- `--json` emits a deterministic report consumable by Grafana/automation (schema `1.0`, see `docs/12_PERFORMANCE_WORKBOOK.md`).
|
||||
- `--prom` exports Prometheus-compatible gauges (`scanner_analyzer_bench_*`), which CI uploads for dashboards and alerts.
|
||||
|
||||
Use `--iterations` to override the default (5 passes per scenario) and `--threshold-ms` to customize the failure budget. Budgets default to 5 000 ms (or per-scenario overrides in `config.json`), aligned with the SBOM compose objective. Provide `--baseline path/to/baseline.csv` (defaults to the repo baseline) to compare against historical numbers—regressions ≥ 20 % on the `max_ms` metric or breaches of the configured threshold will fail the run.
|
||||
|
||||
Metadata options:
|
||||
- `--captured-at 2025-10-23T12:00:00Z` to inject a deterministic timestamp (otherwise `UtcNow`).
|
||||
- `--commit` and `--environment` annotate the JSON report for dashboards.
|
||||
- `--regression-limit 1.15` adjusts the ratio guard (default 1.20 ⇒ +20 %).
|
||||
|
||||
## Adding scenarios
|
||||
1. Drop the fixture tree under `samples/<area>/...`.
|
||||
2. Append a new scenario entry to `config.json` describing:
|
||||
- `id` – snake_case scenario name (also used in CSV).
|
||||
- `label` – human-friendly description shown in logs.
|
||||
- `root` – path to the directory that will be scanned.
|
||||
- For analyzer-backed scenarios, set `analyzers` to the list of language analyzer ids (for example, `["node"]`).
|
||||
- For temporary metadata walks (used until the analyzer ships), provide `parser` (`node` or `python`) and the `matcher` glob describing files to parse.
|
||||
3. Re-run the harness (`dotnet run … --out baseline.csv --json out/.../new.json --prom out/.../new.prom`).
|
||||
4. Commit both the fixture and updated baseline.
|
||||
@@ -0,0 +1,37 @@
|
||||
using System.Text;
|
||||
using StellaOps.Bench.ScannerAnalyzers.Baseline;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Bench.ScannerAnalyzers.Tests;
|
||||
|
||||
public sealed class BaselineLoaderTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task LoadAsync_ReadsCsvIntoDictionary()
|
||||
{
|
||||
var csv = """
|
||||
scenario,iterations,sample_count,mean_ms,p95_ms,max_ms
|
||||
node_monorepo_walk,5,4,9.4303,36.1354,45.0012
|
||||
python_site_packages_walk,5,10,12.1000,18.2000,26.3000
|
||||
""";
|
||||
|
||||
var path = await WriteTempFileAsync(csv);
|
||||
|
||||
var result = await BaselineLoader.LoadAsync(path, CancellationToken.None);
|
||||
|
||||
Assert.Equal(2, result.Count);
|
||||
var entry = Assert.Contains("node_monorepo_walk", result);
|
||||
Assert.Equal(5, entry.Iterations);
|
||||
Assert.Equal(4, entry.SampleCount);
|
||||
Assert.Equal(9.4303, entry.MeanMs, 4);
|
||||
Assert.Equal(36.1354, entry.P95Ms, 4);
|
||||
Assert.Equal(45.0012, entry.MaxMs, 4);
|
||||
}
|
||||
|
||||
private static async Task<string> WriteTempFileAsync(string content)
|
||||
{
|
||||
var path = Path.Combine(Path.GetTempPath(), $"baseline-{Guid.NewGuid():N}.csv");
|
||||
await File.WriteAllTextAsync(path, content, Encoding.UTF8);
|
||||
return path;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using System.Text.Json;
|
||||
using StellaOps.Bench.ScannerAnalyzers;
|
||||
using StellaOps.Bench.ScannerAnalyzers.Baseline;
|
||||
using StellaOps.Bench.ScannerAnalyzers.Reporting;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Bench.ScannerAnalyzers.Tests;
|
||||
|
||||
public sealed class BenchmarkJsonWriterTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task WriteAsync_EmitsMetadataAndScenarioDetails()
|
||||
{
|
||||
var metadata = new BenchmarkJsonMetadata("1.0", DateTimeOffset.Parse("2025-10-23T12:00:00Z"), "abc123", "ci");
|
||||
var result = new ScenarioResult(
|
||||
"scenario",
|
||||
"Scenario",
|
||||
SampleCount: 5,
|
||||
MeanMs: 10,
|
||||
P95Ms: 12,
|
||||
MaxMs: 20,
|
||||
Iterations: 5,
|
||||
ThresholdMs: 5000);
|
||||
var baseline = new BaselineEntry("scenario", 5, 5, 9, 11, 10);
|
||||
var report = new BenchmarkScenarioReport(result, baseline, 1.2);
|
||||
|
||||
var path = Path.Combine(Path.GetTempPath(), $"bench-{Guid.NewGuid():N}.json");
|
||||
await BenchmarkJsonWriter.WriteAsync(path, metadata, new[] { report }, CancellationToken.None);
|
||||
|
||||
using var document = JsonDocument.Parse(await File.ReadAllTextAsync(path));
|
||||
var root = document.RootElement;
|
||||
|
||||
Assert.Equal("1.0", root.GetProperty("schemaVersion").GetString());
|
||||
Assert.Equal("abc123", root.GetProperty("commit").GetString());
|
||||
var scenario = root.GetProperty("scenarios")[0];
|
||||
Assert.Equal("scenario", scenario.GetProperty("id").GetString());
|
||||
Assert.Equal(20, scenario.GetProperty("maxMs").GetDouble());
|
||||
Assert.Equal(10, scenario.GetProperty("baseline").GetProperty("maxMs").GetDouble());
|
||||
Assert.True(scenario.GetProperty("regression").GetProperty("breached").GetBoolean());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using StellaOps.Bench.ScannerAnalyzers;
|
||||
using StellaOps.Bench.ScannerAnalyzers.Baseline;
|
||||
using StellaOps.Bench.ScannerAnalyzers.Reporting;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Bench.ScannerAnalyzers.Tests;
|
||||
|
||||
public sealed class BenchmarkScenarioReportTests
|
||||
{
|
||||
[Fact]
|
||||
public void RegressionRatio_ComputedWhenBaselinePresent()
|
||||
{
|
||||
var result = new ScenarioResult(
|
||||
"scenario",
|
||||
"Scenario",
|
||||
SampleCount: 5,
|
||||
MeanMs: 10,
|
||||
P95Ms: 12,
|
||||
MaxMs: 20,
|
||||
Iterations: 5,
|
||||
ThresholdMs: 5000);
|
||||
|
||||
var baseline = new BaselineEntry(
|
||||
"scenario",
|
||||
Iterations: 5,
|
||||
SampleCount: 5,
|
||||
MeanMs: 8,
|
||||
P95Ms: 11,
|
||||
MaxMs: 15);
|
||||
|
||||
var report = new BenchmarkScenarioReport(result, baseline, regressionLimit: 1.2);
|
||||
|
||||
Assert.True(report.MaxRegressionRatio.HasValue);
|
||||
Assert.Equal(20d / 15d, report.MaxRegressionRatio.Value, 6);
|
||||
Assert.True(report.RegressionBreached);
|
||||
Assert.Contains("+33.3%", report.BuildRegressionFailureMessage());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RegressionRatio_NullWhenBaselineMissing()
|
||||
{
|
||||
var result = new ScenarioResult(
|
||||
"scenario",
|
||||
"Scenario",
|
||||
SampleCount: 5,
|
||||
MeanMs: 10,
|
||||
P95Ms: 12,
|
||||
MaxMs: 20,
|
||||
Iterations: 5,
|
||||
ThresholdMs: 5000);
|
||||
|
||||
var report = new BenchmarkScenarioReport(result, baseline: null, regressionLimit: 1.2);
|
||||
|
||||
Assert.Null(report.MaxRegressionRatio);
|
||||
Assert.False(report.RegressionBreached);
|
||||
Assert.Null(report.BuildRegressionFailureMessage());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using StellaOps.Bench.ScannerAnalyzers;
|
||||
using StellaOps.Bench.ScannerAnalyzers.Baseline;
|
||||
using StellaOps.Bench.ScannerAnalyzers.Reporting;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Bench.ScannerAnalyzers.Tests;
|
||||
|
||||
public sealed class PrometheusWriterTests
|
||||
{
|
||||
[Fact]
|
||||
public void Write_EmitsMetricsForScenario()
|
||||
{
|
||||
var result = new ScenarioResult(
|
||||
"scenario_a",
|
||||
"Scenario A",
|
||||
SampleCount: 5,
|
||||
MeanMs: 10,
|
||||
P95Ms: 12,
|
||||
MaxMs: 20,
|
||||
Iterations: 5,
|
||||
ThresholdMs: 5000);
|
||||
var baseline = new BaselineEntry("scenario_a", 5, 5, 9, 11, 18);
|
||||
var report = new BenchmarkScenarioReport(result, baseline, 1.2);
|
||||
|
||||
var path = Path.Combine(Path.GetTempPath(), $"metrics-{Guid.NewGuid():N}.prom");
|
||||
PrometheusWriter.Write(path, new[] { report });
|
||||
|
||||
var contents = File.ReadAllText(path);
|
||||
Assert.Contains("scanner_analyzer_bench_max_ms{scenario=\"scenario_a\"} 20", contents);
|
||||
Assert.Contains("scanner_analyzer_bench_regression_ratio{scenario=\"scenario_a\"}", contents);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\StellaOps.Bench.ScannerAnalyzers\StellaOps.Bench.ScannerAnalyzers.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace StellaOps.Bench.ScannerAnalyzers.Baseline;
|
||||
|
||||
internal sealed record BaselineEntry(
|
||||
string ScenarioId,
|
||||
int Iterations,
|
||||
int SampleCount,
|
||||
double MeanMs,
|
||||
double P95Ms,
|
||||
double MaxMs);
|
||||
@@ -0,0 +1,88 @@
|
||||
using System.Globalization;
|
||||
|
||||
namespace StellaOps.Bench.ScannerAnalyzers.Baseline;
|
||||
|
||||
internal static class BaselineLoader
|
||||
{
|
||||
public static async Task<IReadOnlyDictionary<string, BaselineEntry>> LoadAsync(string path, CancellationToken cancellationToken)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
throw new ArgumentException("Baseline path must be provided.", nameof(path));
|
||||
}
|
||||
|
||||
var resolved = Path.GetFullPath(path);
|
||||
if (!File.Exists(resolved))
|
||||
{
|
||||
throw new FileNotFoundException($"Baseline file not found at {resolved}", resolved);
|
||||
}
|
||||
|
||||
var result = new Dictionary<string, BaselineEntry>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
await using var stream = new FileStream(resolved, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
using var reader = new StreamReader(stream);
|
||||
string? line;
|
||||
var isFirst = true;
|
||||
|
||||
while ((line = await reader.ReadLineAsync().ConfigureAwait(false)) is not null)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isFirst)
|
||||
{
|
||||
isFirst = false;
|
||||
if (line.StartsWith("scenario,", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
var entry = ParseLine(line);
|
||||
result[entry.ScenarioId] = entry;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static BaselineEntry ParseLine(string line)
|
||||
{
|
||||
var parts = line.Split(',', StringSplitOptions.TrimEntries);
|
||||
if (parts.Length < 6)
|
||||
{
|
||||
throw new InvalidDataException($"Baseline CSV row malformed: '{line}'");
|
||||
}
|
||||
|
||||
var scenarioId = parts[0];
|
||||
var iterations = ParseInt(parts[1], nameof(BaselineEntry.Iterations));
|
||||
var sampleCount = ParseInt(parts[2], nameof(BaselineEntry.SampleCount));
|
||||
var meanMs = ParseDouble(parts[3], nameof(BaselineEntry.MeanMs));
|
||||
var p95Ms = ParseDouble(parts[4], nameof(BaselineEntry.P95Ms));
|
||||
var maxMs = ParseDouble(parts[5], nameof(BaselineEntry.MaxMs));
|
||||
|
||||
return new BaselineEntry(scenarioId, iterations, sampleCount, meanMs, p95Ms, maxMs);
|
||||
}
|
||||
|
||||
private static int ParseInt(string value, string field)
|
||||
{
|
||||
if (!int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsed))
|
||||
{
|
||||
throw new InvalidDataException($"Failed to parse integer {field} from '{value}'.");
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
private static double ParseDouble(string value, string field)
|
||||
{
|
||||
if (!double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var parsed))
|
||||
{
|
||||
throw new InvalidDataException($"Failed to parse double {field} from '{value}'.");
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace StellaOps.Bench.ScannerAnalyzers;
|
||||
|
||||
internal sealed record BenchmarkConfig
|
||||
{
|
||||
[JsonPropertyName("iterations")]
|
||||
public int? Iterations { get; init; }
|
||||
|
||||
[JsonPropertyName("thresholdMs")]
|
||||
public double? ThresholdMs { get; init; }
|
||||
|
||||
[JsonPropertyName("scenarios")]
|
||||
public List<BenchmarkScenarioConfig> Scenarios { get; init; } = new();
|
||||
|
||||
public static async Task<BenchmarkConfig> LoadAsync(string path)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
throw new ArgumentException("Config path is required.", nameof(path));
|
||||
}
|
||||
|
||||
await using var stream = File.OpenRead(path);
|
||||
var config = await JsonSerializer.DeserializeAsync<BenchmarkConfig>(stream, SerializerOptions).ConfigureAwait(false);
|
||||
if (config is null)
|
||||
{
|
||||
throw new InvalidOperationException($"Failed to parse benchmark config '{path}'.");
|
||||
}
|
||||
|
||||
if (config.Scenarios.Count == 0)
|
||||
{
|
||||
throw new InvalidOperationException("config.scenarios must declare at least one scenario.");
|
||||
}
|
||||
|
||||
foreach (var scenario in config.Scenarios)
|
||||
{
|
||||
scenario.Validate();
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
private static JsonSerializerOptions SerializerOptions => new()
|
||||
{
|
||||
PropertyNameCaseInsensitive = true,
|
||||
ReadCommentHandling = JsonCommentHandling.Skip,
|
||||
AllowTrailingCommas = true,
|
||||
};
|
||||
}
|
||||
|
||||
internal sealed record BenchmarkScenarioConfig
|
||||
{
|
||||
[JsonPropertyName("id")]
|
||||
public string? Id { get; init; }
|
||||
|
||||
[JsonPropertyName("label")]
|
||||
public string? Label { get; init; }
|
||||
|
||||
[JsonPropertyName("root")]
|
||||
public string? Root { get; init; }
|
||||
|
||||
[JsonPropertyName("analyzers")]
|
||||
public List<string>? Analyzers { get; init; }
|
||||
|
||||
[JsonPropertyName("matcher")]
|
||||
public string? Matcher { get; init; }
|
||||
|
||||
[JsonPropertyName("parser")]
|
||||
public string? Parser { get; init; }
|
||||
|
||||
[JsonPropertyName("thresholdMs")]
|
||||
public double? ThresholdMs { get; init; }
|
||||
|
||||
public bool HasAnalyzers => Analyzers is { Count: > 0 };
|
||||
|
||||
public void Validate()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Id))
|
||||
{
|
||||
throw new InvalidOperationException("scenario.id is required.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(Root))
|
||||
{
|
||||
throw new InvalidOperationException($"Scenario '{Id}' must specify a root path.");
|
||||
}
|
||||
|
||||
if (HasAnalyzers)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(Parser))
|
||||
{
|
||||
throw new InvalidOperationException($"Scenario '{Id}' must specify parser or analyzers.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(Matcher))
|
||||
{
|
||||
throw new InvalidOperationException($"Scenario '{Id}' must specify matcher when parser is used.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,393 @@
|
||||
using System.Globalization;
|
||||
using StellaOps.Bench.ScannerAnalyzers.Baseline;
|
||||
using StellaOps.Bench.ScannerAnalyzers.Reporting;
|
||||
using StellaOps.Bench.ScannerAnalyzers.Scenarios;
|
||||
|
||||
namespace StellaOps.Bench.ScannerAnalyzers;
|
||||
|
||||
internal static class Program
|
||||
{
|
||||
public static async Task<int> Main(string[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
var options = ProgramOptions.Parse(args);
|
||||
var config = await BenchmarkConfig.LoadAsync(options.ConfigPath).ConfigureAwait(false);
|
||||
|
||||
var iterations = options.Iterations ?? config.Iterations ?? 5;
|
||||
var thresholdMs = options.ThresholdMs ?? config.ThresholdMs ?? 5000;
|
||||
var repoRoot = ResolveRepoRoot(options.RepoRoot, options.ConfigPath);
|
||||
var regressionLimit = options.RegressionLimit ?? 1.2d;
|
||||
var capturedAt = (options.CapturedAtUtc ?? DateTimeOffset.UtcNow).ToUniversalTime();
|
||||
|
||||
var baseline = await LoadBaselineDictionaryAsync(options.BaselinePath, CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
var results = new List<ScenarioResult>();
|
||||
var reports = new List<BenchmarkScenarioReport>();
|
||||
var failures = new List<string>();
|
||||
|
||||
foreach (var scenario in config.Scenarios)
|
||||
{
|
||||
var runner = ScenarioRunnerFactory.Create(scenario);
|
||||
var scenarioRoot = ResolveScenarioRoot(repoRoot, scenario.Root!);
|
||||
|
||||
var execution = await runner.ExecuteAsync(scenarioRoot, iterations, CancellationToken.None).ConfigureAwait(false);
|
||||
var stats = ScenarioStatistics.FromDurations(execution.Durations);
|
||||
var scenarioThreshold = scenario.ThresholdMs ?? thresholdMs;
|
||||
|
||||
var result = new ScenarioResult(
|
||||
scenario.Id!,
|
||||
scenario.Label ?? scenario.Id!,
|
||||
execution.SampleCount,
|
||||
stats.MeanMs,
|
||||
stats.P95Ms,
|
||||
stats.MaxMs,
|
||||
iterations,
|
||||
scenarioThreshold);
|
||||
|
||||
results.Add(result);
|
||||
|
||||
if (stats.MaxMs > scenarioThreshold)
|
||||
{
|
||||
failures.Add($"{scenario.Id} exceeded threshold: {stats.MaxMs:F2} ms > {scenarioThreshold:F2} ms");
|
||||
}
|
||||
|
||||
baseline.TryGetValue(result.Id, out var baselineEntry);
|
||||
var report = new BenchmarkScenarioReport(result, baselineEntry, regressionLimit);
|
||||
if (report.BuildRegressionFailureMessage() is { } regressionFailure)
|
||||
{
|
||||
failures.Add(regressionFailure);
|
||||
}
|
||||
|
||||
reports.Add(report);
|
||||
}
|
||||
|
||||
TablePrinter.Print(results);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(options.CsvOutPath))
|
||||
{
|
||||
CsvWriter.Write(options.CsvOutPath!, results);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(options.JsonOutPath))
|
||||
{
|
||||
var metadata = new BenchmarkJsonMetadata(
|
||||
"1.0",
|
||||
capturedAt,
|
||||
options.Commit,
|
||||
options.Environment);
|
||||
|
||||
await BenchmarkJsonWriter.WriteAsync(options.JsonOutPath!, metadata, reports, CancellationToken.None).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(options.PrometheusOutPath))
|
||||
{
|
||||
PrometheusWriter.Write(options.PrometheusOutPath!, reports);
|
||||
}
|
||||
|
||||
if (failures.Count > 0)
|
||||
{
|
||||
Console.Error.WriteLine();
|
||||
Console.Error.WriteLine("Performance threshold exceeded:");
|
||||
foreach (var failure in failures)
|
||||
{
|
||||
Console.Error.WriteLine($" - {failure}");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.Error.WriteLine(ex.Message);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<IReadOnlyDictionary<string, BaselineEntry>> LoadBaselineDictionaryAsync(string? baselinePath, CancellationToken cancellationToken)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(baselinePath))
|
||||
{
|
||||
return new Dictionary<string, BaselineEntry>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
var resolved = Path.GetFullPath(baselinePath);
|
||||
if (!File.Exists(resolved))
|
||||
{
|
||||
return new Dictionary<string, BaselineEntry>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
return await BaselineLoader.LoadAsync(resolved, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static string ResolveRepoRoot(string? overridePath, string configPath)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(overridePath))
|
||||
{
|
||||
return Path.GetFullPath(overridePath);
|
||||
}
|
||||
|
||||
var configDirectory = Path.GetDirectoryName(configPath);
|
||||
if (string.IsNullOrWhiteSpace(configDirectory))
|
||||
{
|
||||
return Directory.GetCurrentDirectory();
|
||||
}
|
||||
|
||||
return Path.GetFullPath(Path.Combine(configDirectory, "..", ".."));
|
||||
}
|
||||
|
||||
private static string ResolveScenarioRoot(string repoRoot, string relativeRoot)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(relativeRoot))
|
||||
{
|
||||
throw new InvalidOperationException("Scenario root is required.");
|
||||
}
|
||||
|
||||
var combined = Path.GetFullPath(Path.Combine(repoRoot, relativeRoot));
|
||||
if (!PathUtilities.IsWithinRoot(repoRoot, combined))
|
||||
{
|
||||
throw new InvalidOperationException($"Scenario root '{relativeRoot}' escapes repository root '{repoRoot}'.");
|
||||
}
|
||||
|
||||
if (!Directory.Exists(combined))
|
||||
{
|
||||
throw new DirectoryNotFoundException($"Scenario root '{combined}' does not exist.");
|
||||
}
|
||||
|
||||
return combined;
|
||||
}
|
||||
|
||||
private sealed record ProgramOptions(
|
||||
string ConfigPath,
|
||||
int? Iterations,
|
||||
double? ThresholdMs,
|
||||
string? CsvOutPath,
|
||||
string? JsonOutPath,
|
||||
string? PrometheusOutPath,
|
||||
string? RepoRoot,
|
||||
string? BaselinePath,
|
||||
DateTimeOffset? CapturedAtUtc,
|
||||
string? Commit,
|
||||
string? Environment,
|
||||
double? RegressionLimit)
|
||||
{
|
||||
public static ProgramOptions Parse(string[] args)
|
||||
{
|
||||
var configPath = DefaultConfigPath();
|
||||
var baselinePath = DefaultBaselinePath();
|
||||
int? iterations = null;
|
||||
double? thresholdMs = null;
|
||||
string? csvOut = null;
|
||||
string? jsonOut = null;
|
||||
string? promOut = null;
|
||||
string? repoRoot = null;
|
||||
DateTimeOffset? capturedAt = null;
|
||||
string? commit = null;
|
||||
string? environment = null;
|
||||
double? regressionLimit = null;
|
||||
|
||||
for (var index = 0; index < args.Length; index++)
|
||||
{
|
||||
var current = args[index];
|
||||
switch (current)
|
||||
{
|
||||
case "--config":
|
||||
EnsureNext(args, index);
|
||||
configPath = Path.GetFullPath(args[++index]);
|
||||
break;
|
||||
case "--iterations":
|
||||
EnsureNext(args, index);
|
||||
iterations = int.Parse(args[++index], CultureInfo.InvariantCulture);
|
||||
break;
|
||||
case "--threshold-ms":
|
||||
EnsureNext(args, index);
|
||||
thresholdMs = double.Parse(args[++index], CultureInfo.InvariantCulture);
|
||||
break;
|
||||
case "--out":
|
||||
case "--csv":
|
||||
EnsureNext(args, index);
|
||||
csvOut = args[++index];
|
||||
break;
|
||||
case "--json":
|
||||
EnsureNext(args, index);
|
||||
jsonOut = args[++index];
|
||||
break;
|
||||
case "--prom":
|
||||
case "--prometheus":
|
||||
EnsureNext(args, index);
|
||||
promOut = args[++index];
|
||||
break;
|
||||
case "--baseline":
|
||||
EnsureNext(args, index);
|
||||
baselinePath = args[++index];
|
||||
break;
|
||||
case "--repo-root":
|
||||
case "--samples":
|
||||
EnsureNext(args, index);
|
||||
repoRoot = args[++index];
|
||||
break;
|
||||
case "--captured-at":
|
||||
EnsureNext(args, index);
|
||||
capturedAt = DateTimeOffset.Parse(args[++index], CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
|
||||
break;
|
||||
case "--commit":
|
||||
EnsureNext(args, index);
|
||||
commit = args[++index];
|
||||
break;
|
||||
case "--environment":
|
||||
EnsureNext(args, index);
|
||||
environment = args[++index];
|
||||
break;
|
||||
case "--regression-limit":
|
||||
EnsureNext(args, index);
|
||||
regressionLimit = double.Parse(args[++index], CultureInfo.InvariantCulture);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException($"Unknown argument: {current}", nameof(args));
|
||||
}
|
||||
}
|
||||
|
||||
return new ProgramOptions(configPath, iterations, thresholdMs, csvOut, jsonOut, promOut, repoRoot, baselinePath, capturedAt, commit, environment, regressionLimit);
|
||||
}
|
||||
|
||||
private static string DefaultConfigPath()
|
||||
{
|
||||
var binaryDir = AppContext.BaseDirectory;
|
||||
var projectRoot = Path.GetFullPath(Path.Combine(binaryDir, "..", "..", ".."));
|
||||
var configDirectory = Path.GetFullPath(Path.Combine(projectRoot, ".."));
|
||||
return Path.Combine(configDirectory, "config.json");
|
||||
}
|
||||
|
||||
private static string? DefaultBaselinePath()
|
||||
{
|
||||
var binaryDir = AppContext.BaseDirectory;
|
||||
var projectRoot = Path.GetFullPath(Path.Combine(binaryDir, "..", "..", ".."));
|
||||
var benchRoot = Path.GetFullPath(Path.Combine(projectRoot, ".."));
|
||||
var baselinePath = Path.Combine(benchRoot, "baseline.csv");
|
||||
return File.Exists(baselinePath) ? baselinePath : baselinePath;
|
||||
}
|
||||
|
||||
private static void EnsureNext(string[] args, int index)
|
||||
{
|
||||
if (index + 1 >= args.Length)
|
||||
{
|
||||
throw new ArgumentException("Missing value for argument.", nameof(args));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private sealed record ScenarioStatistics(double MeanMs, double P95Ms, double MaxMs)
|
||||
{
|
||||
public static ScenarioStatistics FromDurations(IReadOnlyList<double> durations)
|
||||
{
|
||||
if (durations.Count == 0)
|
||||
{
|
||||
return new ScenarioStatistics(0, 0, 0);
|
||||
}
|
||||
|
||||
var sorted = durations.ToArray();
|
||||
Array.Sort(sorted);
|
||||
|
||||
var total = 0d;
|
||||
foreach (var value in durations)
|
||||
{
|
||||
total += value;
|
||||
}
|
||||
|
||||
var mean = total / durations.Count;
|
||||
var p95 = Percentile(sorted, 95);
|
||||
var max = sorted[^1];
|
||||
|
||||
return new ScenarioStatistics(mean, p95, max);
|
||||
}
|
||||
|
||||
private static double Percentile(IReadOnlyList<double> sorted, double percentile)
|
||||
{
|
||||
if (sorted.Count == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var rank = (percentile / 100d) * (sorted.Count - 1);
|
||||
var lower = (int)Math.Floor(rank);
|
||||
var upper = (int)Math.Ceiling(rank);
|
||||
var weight = rank - lower;
|
||||
|
||||
if (upper >= sorted.Count)
|
||||
{
|
||||
return sorted[lower];
|
||||
}
|
||||
|
||||
return sorted[lower] + weight * (sorted[upper] - sorted[lower]);
|
||||
}
|
||||
}
|
||||
|
||||
private static class TablePrinter
|
||||
{
|
||||
public static void Print(IEnumerable<ScenarioResult> results)
|
||||
{
|
||||
Console.WriteLine("Scenario | Count | Mean(ms) | P95(ms) | Max(ms)");
|
||||
Console.WriteLine("---------------------------- | ----- | --------- | --------- | ----------");
|
||||
foreach (var row in results)
|
||||
{
|
||||
Console.WriteLine(string.Join(" | ", new[]
|
||||
{
|
||||
row.IdColumn,
|
||||
row.SampleCountColumn,
|
||||
row.MeanColumn,
|
||||
row.P95Column,
|
||||
row.MaxColumn
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class CsvWriter
|
||||
{
|
||||
public static void Write(string path, IEnumerable<ScenarioResult> results)
|
||||
{
|
||||
var resolvedPath = Path.GetFullPath(path);
|
||||
var directory = Path.GetDirectoryName(resolvedPath);
|
||||
if (!string.IsNullOrEmpty(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
using var stream = new FileStream(resolvedPath, FileMode.Create, FileAccess.Write, FileShare.None);
|
||||
using var writer = new StreamWriter(stream);
|
||||
writer.WriteLine("scenario,iterations,sample_count,mean_ms,p95_ms,max_ms");
|
||||
|
||||
foreach (var row in results)
|
||||
{
|
||||
writer.Write(row.Id);
|
||||
writer.Write(',');
|
||||
writer.Write(row.Iterations.ToString(CultureInfo.InvariantCulture));
|
||||
writer.Write(',');
|
||||
writer.Write(row.SampleCount.ToString(CultureInfo.InvariantCulture));
|
||||
writer.Write(',');
|
||||
writer.Write(row.MeanMs.ToString("F4", CultureInfo.InvariantCulture));
|
||||
writer.Write(',');
|
||||
writer.Write(row.P95Ms.ToString("F4", CultureInfo.InvariantCulture));
|
||||
writer.Write(',');
|
||||
writer.Write(row.MaxMs.ToString("F4", CultureInfo.InvariantCulture));
|
||||
writer.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static class PathUtilities
|
||||
{
|
||||
public static bool IsWithinRoot(string root, string candidate)
|
||||
{
|
||||
var relative = Path.GetRelativePath(root, candidate);
|
||||
if (string.IsNullOrEmpty(relative) || relative == ".")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return !relative.StartsWith("..", StringComparison.Ordinal) && !Path.IsPathRooted(relative);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using StellaOps.Bench.ScannerAnalyzers.Baseline;
|
||||
|
||||
namespace StellaOps.Bench.ScannerAnalyzers.Reporting;
|
||||
|
||||
internal static class BenchmarkJsonWriter
|
||||
{
|
||||
private static readonly JsonSerializerOptions SerializerOptions = new(JsonSerializerDefaults.Web)
|
||||
{
|
||||
WriteIndented = true,
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
|
||||
};
|
||||
|
||||
public static async Task WriteAsync(
|
||||
string path,
|
||||
BenchmarkJsonMetadata metadata,
|
||||
IReadOnlyList<BenchmarkScenarioReport> reports,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(path);
|
||||
ArgumentNullException.ThrowIfNull(metadata);
|
||||
ArgumentNullException.ThrowIfNull(reports);
|
||||
|
||||
var resolved = Path.GetFullPath(path);
|
||||
var directory = Path.GetDirectoryName(resolved);
|
||||
if (!string.IsNullOrEmpty(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
var document = new BenchmarkJsonDocument(
|
||||
metadata.SchemaVersion,
|
||||
metadata.CapturedAtUtc,
|
||||
metadata.Commit,
|
||||
metadata.Environment,
|
||||
reports.Select(CreateScenario).ToArray());
|
||||
|
||||
await using var stream = new FileStream(resolved, FileMode.Create, FileAccess.Write, FileShare.None);
|
||||
await JsonSerializer.SerializeAsync(stream, document, SerializerOptions, cancellationToken).ConfigureAwait(false);
|
||||
await stream.FlushAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static BenchmarkJsonScenario CreateScenario(BenchmarkScenarioReport report)
|
||||
{
|
||||
var baseline = report.Baseline;
|
||||
return new BenchmarkJsonScenario(
|
||||
report.Result.Id,
|
||||
report.Result.Label,
|
||||
report.Result.Iterations,
|
||||
report.Result.SampleCount,
|
||||
report.Result.MeanMs,
|
||||
report.Result.P95Ms,
|
||||
report.Result.MaxMs,
|
||||
report.Result.ThresholdMs,
|
||||
baseline is null
|
||||
? null
|
||||
: new BenchmarkJsonScenarioBaseline(
|
||||
baseline.Iterations,
|
||||
baseline.SampleCount,
|
||||
baseline.MeanMs,
|
||||
baseline.P95Ms,
|
||||
baseline.MaxMs),
|
||||
new BenchmarkJsonScenarioRegression(
|
||||
report.MaxRegressionRatio,
|
||||
report.MeanRegressionRatio,
|
||||
report.RegressionLimit,
|
||||
report.RegressionBreached));
|
||||
}
|
||||
|
||||
private sealed record BenchmarkJsonDocument(
|
||||
string SchemaVersion,
|
||||
DateTimeOffset CapturedAt,
|
||||
string? Commit,
|
||||
string? Environment,
|
||||
IReadOnlyList<BenchmarkJsonScenario> Scenarios);
|
||||
|
||||
private sealed record BenchmarkJsonScenario(
|
||||
string Id,
|
||||
string Label,
|
||||
int Iterations,
|
||||
int SampleCount,
|
||||
double MeanMs,
|
||||
double P95Ms,
|
||||
double MaxMs,
|
||||
double ThresholdMs,
|
||||
BenchmarkJsonScenarioBaseline? Baseline,
|
||||
BenchmarkJsonScenarioRegression Regression);
|
||||
|
||||
private sealed record BenchmarkJsonScenarioBaseline(
|
||||
int Iterations,
|
||||
int SampleCount,
|
||||
double MeanMs,
|
||||
double P95Ms,
|
||||
double MaxMs);
|
||||
|
||||
private sealed record BenchmarkJsonScenarioRegression(
|
||||
double? MaxRatio,
|
||||
double? MeanRatio,
|
||||
double Limit,
|
||||
bool Breached);
|
||||
}
|
||||
|
||||
internal sealed record BenchmarkJsonMetadata(
|
||||
string SchemaVersion,
|
||||
DateTimeOffset CapturedAtUtc,
|
||||
string? Commit,
|
||||
string? Environment);
|
||||
@@ -0,0 +1,55 @@
|
||||
using StellaOps.Bench.ScannerAnalyzers.Baseline;
|
||||
|
||||
namespace StellaOps.Bench.ScannerAnalyzers.Reporting;
|
||||
|
||||
internal sealed class BenchmarkScenarioReport
|
||||
{
|
||||
private const double RegressionLimitDefault = 1.2d;
|
||||
|
||||
public BenchmarkScenarioReport(ScenarioResult result, BaselineEntry? baseline, double? regressionLimit = null)
|
||||
{
|
||||
Result = result ?? throw new ArgumentNullException(nameof(result));
|
||||
Baseline = baseline;
|
||||
RegressionLimit = regressionLimit is { } limit && limit > 0 ? limit : RegressionLimitDefault;
|
||||
MaxRegressionRatio = CalculateRatio(result.MaxMs, baseline?.MaxMs);
|
||||
MeanRegressionRatio = CalculateRatio(result.MeanMs, baseline?.MeanMs);
|
||||
}
|
||||
|
||||
public ScenarioResult Result { get; }
|
||||
|
||||
public BaselineEntry? Baseline { get; }
|
||||
|
||||
public double RegressionLimit { get; }
|
||||
|
||||
public double? MaxRegressionRatio { get; }
|
||||
|
||||
public double? MeanRegressionRatio { get; }
|
||||
|
||||
public bool RegressionBreached => MaxRegressionRatio.HasValue && MaxRegressionRatio.Value >= RegressionLimit;
|
||||
|
||||
public string? BuildRegressionFailureMessage()
|
||||
{
|
||||
if (!RegressionBreached || MaxRegressionRatio is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var percentage = (MaxRegressionRatio.Value - 1d) * 100d;
|
||||
return $"{Result.Id} exceeded regression budget: max {Result.MaxMs:F2} ms vs baseline {Baseline!.MaxMs:F2} ms (+{percentage:F1}%)";
|
||||
}
|
||||
|
||||
private static double? CalculateRatio(double current, double? baseline)
|
||||
{
|
||||
if (!baseline.HasValue)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (baseline.Value <= 0d)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return current / baseline.Value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace StellaOps.Bench.ScannerAnalyzers.Reporting;
|
||||
|
||||
internal static class PrometheusWriter
|
||||
{
|
||||
public static void Write(string path, IReadOnlyList<BenchmarkScenarioReport> reports)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(path);
|
||||
ArgumentNullException.ThrowIfNull(reports);
|
||||
|
||||
var resolved = Path.GetFullPath(path);
|
||||
var directory = Path.GetDirectoryName(resolved);
|
||||
if (!string.IsNullOrEmpty(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
var builder = new StringBuilder();
|
||||
builder.AppendLine("# HELP scanner_analyzer_bench_duration_ms Analyzer benchmark duration metrics in milliseconds.");
|
||||
builder.AppendLine("# TYPE scanner_analyzer_bench_duration_ms gauge");
|
||||
|
||||
foreach (var report in reports)
|
||||
{
|
||||
var scenarioLabel = Escape(report.Result.Id);
|
||||
AppendMetric(builder, "scanner_analyzer_bench_mean_ms", scenarioLabel, report.Result.MeanMs);
|
||||
AppendMetric(builder, "scanner_analyzer_bench_p95_ms", scenarioLabel, report.Result.P95Ms);
|
||||
AppendMetric(builder, "scanner_analyzer_bench_max_ms", scenarioLabel, report.Result.MaxMs);
|
||||
AppendMetric(builder, "scanner_analyzer_bench_threshold_ms", scenarioLabel, report.Result.ThresholdMs);
|
||||
|
||||
if (report.Baseline is { } baseline)
|
||||
{
|
||||
AppendMetric(builder, "scanner_analyzer_bench_baseline_max_ms", scenarioLabel, baseline.MaxMs);
|
||||
AppendMetric(builder, "scanner_analyzer_bench_baseline_mean_ms", scenarioLabel, baseline.MeanMs);
|
||||
}
|
||||
|
||||
if (report.MaxRegressionRatio is { } ratio)
|
||||
{
|
||||
AppendMetric(builder, "scanner_analyzer_bench_regression_ratio", scenarioLabel, ratio);
|
||||
AppendMetric(builder, "scanner_analyzer_bench_regression_limit", scenarioLabel, report.RegressionLimit);
|
||||
AppendMetric(builder, "scanner_analyzer_bench_regression_breached", scenarioLabel, report.RegressionBreached ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
File.WriteAllText(resolved, builder.ToString(), Encoding.UTF8);
|
||||
}
|
||||
|
||||
private static void AppendMetric(StringBuilder builder, string metric, string scenarioLabel, double value)
|
||||
{
|
||||
builder.Append(metric);
|
||||
builder.Append("{scenario=\"");
|
||||
builder.Append(scenarioLabel);
|
||||
builder.Append("\"} ");
|
||||
builder.AppendLine(value.ToString("G17", CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
private static string Escape(string value) => value.Replace("\\", "\\\\", StringComparison.Ordinal).Replace("\"", "\\\"", StringComparison.Ordinal);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Globalization;
|
||||
|
||||
namespace StellaOps.Bench.ScannerAnalyzers;
|
||||
|
||||
internal sealed record ScenarioResult(
|
||||
string Id,
|
||||
string Label,
|
||||
int SampleCount,
|
||||
double MeanMs,
|
||||
double P95Ms,
|
||||
double MaxMs,
|
||||
int Iterations,
|
||||
double ThresholdMs)
|
||||
{
|
||||
public string IdColumn => Id.Length <= 28 ? Id.PadRight(28) : Id[..28];
|
||||
|
||||
public string SampleCountColumn => SampleCount.ToString(CultureInfo.InvariantCulture).PadLeft(5);
|
||||
|
||||
public string MeanColumn => MeanMs.ToString("F2", CultureInfo.InvariantCulture).PadLeft(9);
|
||||
|
||||
public string P95Column => P95Ms.ToString("F2", CultureInfo.InvariantCulture).PadLeft(9);
|
||||
|
||||
public string MaxColumn => MaxMs.ToString("F2", CultureInfo.InvariantCulture).PadLeft(10);
|
||||
}
|
||||
@@ -0,0 +1,285 @@
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
using StellaOps.Scanner.Analyzers.Lang;
|
||||
using StellaOps.Scanner.Analyzers.Lang.Go;
|
||||
using StellaOps.Scanner.Analyzers.Lang.Java;
|
||||
using StellaOps.Scanner.Analyzers.Lang.Node;
|
||||
using StellaOps.Scanner.Analyzers.Lang.DotNet;
|
||||
using StellaOps.Scanner.Analyzers.Lang.Python;
|
||||
|
||||
namespace StellaOps.Bench.ScannerAnalyzers.Scenarios;
|
||||
|
||||
internal interface IScenarioRunner
|
||||
{
|
||||
Task<ScenarioExecutionResult> ExecuteAsync(string rootPath, int iterations, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
internal sealed record ScenarioExecutionResult(double[] Durations, int SampleCount);
|
||||
|
||||
internal static class ScenarioRunnerFactory
|
||||
{
|
||||
public static IScenarioRunner Create(BenchmarkScenarioConfig scenario)
|
||||
{
|
||||
if (scenario.HasAnalyzers)
|
||||
{
|
||||
return new LanguageAnalyzerScenarioRunner(scenario.Analyzers!);
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(scenario.Parser) || string.IsNullOrWhiteSpace(scenario.Matcher))
|
||||
{
|
||||
throw new InvalidOperationException($"Scenario '{scenario.Id}' missing parser or matcher configuration.");
|
||||
}
|
||||
|
||||
return new MetadataWalkScenarioRunner(scenario.Parser, scenario.Matcher);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class LanguageAnalyzerScenarioRunner : IScenarioRunner
|
||||
{
|
||||
private readonly IReadOnlyList<Func<ILanguageAnalyzer>> _analyzerFactories;
|
||||
|
||||
public LanguageAnalyzerScenarioRunner(IEnumerable<string> analyzerIds)
|
||||
{
|
||||
if (analyzerIds is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(analyzerIds));
|
||||
}
|
||||
|
||||
_analyzerFactories = analyzerIds
|
||||
.Where(static id => !string.IsNullOrWhiteSpace(id))
|
||||
.Select(CreateFactory)
|
||||
.ToArray();
|
||||
|
||||
if (_analyzerFactories.Count == 0)
|
||||
{
|
||||
throw new InvalidOperationException("At least one analyzer id must be provided.");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ScenarioExecutionResult> ExecuteAsync(string rootPath, int iterations, CancellationToken cancellationToken)
|
||||
{
|
||||
if (iterations <= 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(iterations), iterations, "Iterations must be positive.");
|
||||
}
|
||||
|
||||
var analyzers = _analyzerFactories.Select(factory => factory()).ToArray();
|
||||
var engine = new LanguageAnalyzerEngine(analyzers);
|
||||
var durations = new double[iterations];
|
||||
var componentCount = -1;
|
||||
|
||||
for (var i = 0; i < iterations; i++)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var context = new LanguageAnalyzerContext(rootPath, TimeProvider.System);
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
var result = await engine.AnalyzeAsync(context, cancellationToken).ConfigureAwait(false);
|
||||
stopwatch.Stop();
|
||||
|
||||
durations[i] = stopwatch.Elapsed.TotalMilliseconds;
|
||||
|
||||
var currentCount = result.Components.Count;
|
||||
if (componentCount < 0)
|
||||
{
|
||||
componentCount = currentCount;
|
||||
}
|
||||
else if (componentCount != currentCount)
|
||||
{
|
||||
throw new InvalidOperationException($"Analyzer output count changed between iterations ({componentCount} vs {currentCount}).");
|
||||
}
|
||||
}
|
||||
|
||||
if (componentCount < 0)
|
||||
{
|
||||
componentCount = 0;
|
||||
}
|
||||
|
||||
return new ScenarioExecutionResult(durations, componentCount);
|
||||
}
|
||||
|
||||
private static Func<ILanguageAnalyzer> CreateFactory(string analyzerId)
|
||||
{
|
||||
var id = analyzerId.Trim().ToLowerInvariant();
|
||||
return id switch
|
||||
{
|
||||
"java" => static () => new JavaLanguageAnalyzer(),
|
||||
"go" => static () => new GoLanguageAnalyzer(),
|
||||
"node" => static () => new NodeLanguageAnalyzer(),
|
||||
"dotnet" => static () => new DotNetLanguageAnalyzer(),
|
||||
"python" => static () => new PythonLanguageAnalyzer(),
|
||||
_ => throw new InvalidOperationException($"Unsupported analyzer '{analyzerId}'."),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class MetadataWalkScenarioRunner : IScenarioRunner
|
||||
{
|
||||
private readonly Regex _matcher;
|
||||
private readonly string _parserKind;
|
||||
|
||||
public MetadataWalkScenarioRunner(string parserKind, string globPattern)
|
||||
{
|
||||
_parserKind = parserKind?.Trim().ToLowerInvariant() ?? throw new ArgumentNullException(nameof(parserKind));
|
||||
_matcher = GlobToRegex(globPattern ?? throw new ArgumentNullException(nameof(globPattern)));
|
||||
}
|
||||
|
||||
public async Task<ScenarioExecutionResult> ExecuteAsync(string rootPath, int iterations, CancellationToken cancellationToken)
|
||||
{
|
||||
if (iterations <= 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(iterations), iterations, "Iterations must be positive.");
|
||||
}
|
||||
|
||||
var durations = new double[iterations];
|
||||
var sampleCount = -1;
|
||||
|
||||
for (var i = 0; i < iterations; i++)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
var files = EnumerateMatchingFiles(rootPath);
|
||||
if (files.Count == 0)
|
||||
{
|
||||
throw new InvalidOperationException($"Parser '{_parserKind}' matched zero files under '{rootPath}'.");
|
||||
}
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
await ParseAsync(file).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
stopwatch.Stop();
|
||||
durations[i] = stopwatch.Elapsed.TotalMilliseconds;
|
||||
|
||||
if (sampleCount < 0)
|
||||
{
|
||||
sampleCount = files.Count;
|
||||
}
|
||||
else if (sampleCount != files.Count)
|
||||
{
|
||||
throw new InvalidOperationException($"File count changed between iterations ({sampleCount} vs {files.Count}).");
|
||||
}
|
||||
}
|
||||
|
||||
if (sampleCount < 0)
|
||||
{
|
||||
sampleCount = 0;
|
||||
}
|
||||
|
||||
return new ScenarioExecutionResult(durations, sampleCount);
|
||||
}
|
||||
|
||||
private async ValueTask ParseAsync(string filePath)
|
||||
{
|
||||
switch (_parserKind)
|
||||
{
|
||||
case "node":
|
||||
{
|
||||
using var stream = File.OpenRead(filePath);
|
||||
using var document = await JsonDocument.ParseAsync(stream).ConfigureAwait(false);
|
||||
|
||||
if (!document.RootElement.TryGetProperty("name", out var name) || name.ValueKind != JsonValueKind.String)
|
||||
{
|
||||
throw new InvalidOperationException($"package.json '{filePath}' missing name.");
|
||||
}
|
||||
|
||||
if (!document.RootElement.TryGetProperty("version", out var version) || version.ValueKind != JsonValueKind.String)
|
||||
{
|
||||
throw new InvalidOperationException($"package.json '{filePath}' missing version.");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "python":
|
||||
{
|
||||
var (name, version) = await ParsePythonMetadataAsync(filePath).ConfigureAwait(false);
|
||||
if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(version))
|
||||
{
|
||||
throw new InvalidOperationException($"METADATA '{filePath}' missing Name/Version.");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException($"Unknown parser '{_parserKind}'.");
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<(string? Name, string? Version)> ParsePythonMetadataAsync(string filePath)
|
||||
{
|
||||
using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete);
|
||||
using var reader = new StreamReader(stream);
|
||||
|
||||
string? name = null;
|
||||
string? version = null;
|
||||
|
||||
while (await reader.ReadLineAsync().ConfigureAwait(false) is { } line)
|
||||
{
|
||||
if (line.StartsWith("Name:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
name ??= line[5..].Trim();
|
||||
}
|
||||
else if (line.StartsWith("Version:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
version ??= line[8..].Trim();
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(version))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (name, version);
|
||||
}
|
||||
|
||||
private IReadOnlyList<string> EnumerateMatchingFiles(string rootPath)
|
||||
{
|
||||
var files = new List<string>();
|
||||
var stack = new Stack<string>();
|
||||
stack.Push(rootPath);
|
||||
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
var current = stack.Pop();
|
||||
foreach (var directory in Directory.EnumerateDirectories(current))
|
||||
{
|
||||
stack.Push(directory);
|
||||
}
|
||||
|
||||
foreach (var file in Directory.EnumerateFiles(current))
|
||||
{
|
||||
var relative = Path.GetRelativePath(rootPath, file).Replace('\\', '/');
|
||||
if (_matcher.IsMatch(relative))
|
||||
{
|
||||
files.Add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
private static Regex GlobToRegex(string pattern)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(pattern))
|
||||
{
|
||||
throw new ArgumentException("Glob pattern is required.", nameof(pattern));
|
||||
}
|
||||
|
||||
var normalized = pattern.Replace("\\", "/");
|
||||
normalized = normalized.Replace("**", "\u0001");
|
||||
normalized = normalized.Replace("*", "\u0002");
|
||||
|
||||
var escaped = Regex.Escape(normalized);
|
||||
escaped = escaped.Replace("\u0001/", "(?:.*/)?", StringComparison.Ordinal);
|
||||
escaped = escaped.Replace("\u0001", ".*", StringComparison.Ordinal);
|
||||
escaped = escaped.Replace("\u0002", "[^/]*", StringComparison.Ordinal);
|
||||
|
||||
return new Regex("^" + escaped + "$", RegexOptions.Compiled | RegexOptions.CultureInvariant);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\StellaOps.Scanner.Analyzers.Lang\StellaOps.Scanner.Analyzers.Lang.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\StellaOps.Scanner.Analyzers.Lang.Go\StellaOps.Scanner.Analyzers.Lang.Go.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\StellaOps.Scanner.Analyzers.Lang.Node\StellaOps.Scanner.Analyzers.Lang.Node.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\StellaOps.Scanner.Analyzers.Lang.Java\StellaOps.Scanner.Analyzers.Lang.Java.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\StellaOps.Scanner.Analyzers.Lang.DotNet\StellaOps.Scanner.Analyzers.Lang.DotNet.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\StellaOps.Scanner.Analyzers.Lang.Python\StellaOps.Scanner.Analyzers.Lang.Python.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<InternalsVisibleTo Include="StellaOps.Bench.ScannerAnalyzers.Tests" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
7
src/StellaOps.Bench/Scanner.Analyzers/baseline.csv
Normal file
7
src/StellaOps.Bench/Scanner.Analyzers/baseline.csv
Normal file
@@ -0,0 +1,7 @@
|
||||
scenario,iterations,sample_count,mean_ms,p95_ms,max_ms
|
||||
node_monorepo_walk,5,4,6.0975,21.7421,26.8537
|
||||
java_demo_archive,5,1,6.2007,23.4837,29.1143
|
||||
go_buildinfo_fixture,5,2,6.1949,22.6851,27.9196
|
||||
dotnet_multirid_fixture,5,2,11.4884,37.7460,46.4850
|
||||
python_site_packages_scan,5,3,5.6420,18.2943,22.3739
|
||||
python_pip_cache_fixture,5,1,5.8598,13.2855,15.6256
|
||||
|
54
src/StellaOps.Bench/Scanner.Analyzers/config.json
Normal file
54
src/StellaOps.Bench/Scanner.Analyzers/config.json
Normal file
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"thresholdMs": 5000,
|
||||
"iterations": 5,
|
||||
"scenarios": [
|
||||
{
|
||||
"id": "node_monorepo_walk",
|
||||
"label": "Node.js analyzer on monorepo fixture",
|
||||
"root": "samples/runtime/npm-monorepo",
|
||||
"analyzers": [
|
||||
"node"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "java_demo_archive",
|
||||
"label": "Java analyzer on demo jar",
|
||||
"root": "samples/runtime/java-demo",
|
||||
"analyzers": [
|
||||
"java"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "go_buildinfo_fixture",
|
||||
"label": "Go analyzer on build-info binary",
|
||||
"root": "src/StellaOps.Scanner.Analyzers.Lang.Go.Tests/Fixtures/lang/go/basic",
|
||||
"analyzers": [
|
||||
"go"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "dotnet_multirid_fixture",
|
||||
"label": ".NET analyzer on multi-RID fixture",
|
||||
"root": "src/StellaOps.Scanner.Analyzers.Lang.Tests/Fixtures/lang/dotnet/multi",
|
||||
"analyzers": [
|
||||
"dotnet"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "python_site_packages_scan",
|
||||
"label": "Python analyzer on sample virtualenv",
|
||||
"root": "samples/runtime/python-venv",
|
||||
"analyzers": [
|
||||
"python"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "python_pip_cache_fixture",
|
||||
"label": "Python analyzer verifying RECORD hashes",
|
||||
"root": "src/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Fixtures/lang/python/pip-cache",
|
||||
"analyzers": [
|
||||
"python"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
31
src/StellaOps.Bench/Scanner.Analyzers/lang/README.md
Normal file
31
src/StellaOps.Bench/Scanner.Analyzers/lang/README.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Scanner Language Analyzer Benchmarks
|
||||
|
||||
This directory will capture benchmark results for language analyzers (Node, Python, Go, .NET, Rust).
|
||||
|
||||
Pending tasks:
|
||||
- LA1: Node analyzer microbench CSV + flamegraph.
|
||||
- LA2: Python hash throughput CSV.
|
||||
- LA3: Go build info extraction benchmarks.
|
||||
- LA4: .NET RID dedupe performance matrix.
|
||||
- LA5: Rust heuristic coverage comparisons.
|
||||
|
||||
Results should be committed as deterministic CSV/JSON outputs with accompanying methodology notes.
|
||||
|
||||
## Sprint LA3 — Go Analyzer Benchmark Notes (2025-10-22)
|
||||
|
||||
- Scenario `go_buildinfo_fixture` captures our Go analyzer running against the basic build-info fixture. The Oct 23 baseline (`baseline.csv`) shows a mean duration of **35.03 ms** (p95 136.55 ms, max 170.16 ms) over 5 iterations on the current rig; earlier Oct 21 measurement recorded **4.02 ms** mean when the analyzer was profiled on the warm perf runner.
|
||||
- Comparative run against Syft v1.29.1 on the same fixture (captured 2025-10-21) reported a mean of **5.18 ms** (p95 18.64 ms, max 23.51 ms); raw measurements live in `go/syft-comparison-20251021.csv`.
|
||||
- Bench command (from repo root):\
|
||||
`dotnet run --project src/StellaOps.Bench/Scanner.Analyzers/StellaOps.Bench.ScannerAnalyzers/StellaOps.Bench.ScannerAnalyzers.csproj -- --config src/StellaOps.Bench/Scanner.Analyzers/config.json --out src/StellaOps.Bench/Scanner.Analyzers/baseline.csv`
|
||||
|
||||
## Sprint LA4 — .NET Analyzer Benchmark Notes (2025-10-23)
|
||||
|
||||
- Scenario `dotnet_multirid_fixture` exercises the .NET analyzer against the multi-RID test fixture that merges two applications and four runtime identifiers. Latest baseline run (Release build, 5 iterations) records a mean duration of **29.19 ms** (p95 106.62 ms, max 132.30 ms) with a stable component count of 2.
|
||||
- Syft v1.29.1 scanning the same fixture (`syft scan dir:…`) averaged **1 546 ms** (p95 ≈2 100 ms, max ≈2 100 ms) while also reporting duplicate packages; raw numbers captured in `dotnet/syft-comparison-20251023.csv`.
|
||||
- The new scenario is declared in `src/StellaOps.Bench/Scanner.Analyzers/config.json`; rerun the bench command above after rebuilding analyzers to refresh baselines and comparison data.
|
||||
|
||||
## Sprint LA2 — Python Analyzer Benchmark Notes (2025-10-23)
|
||||
|
||||
- Added two Python scenarios to `config.json`: the virtualenv sample (`python_site_packages_scan`) and the RECORD-heavy pip cache fixture (`python_pip_cache_fixture`).
|
||||
- Baseline run (Release build, 5 iterations) records means of **5.64 ms** (p95 18.29 ms) for the virtualenv and **5.86 ms** (p95 13.29 ms) for the pip cache verifier; raw numbers stored in `python/hash-throughput-20251023.csv`.
|
||||
- The pip cache fixture exercises `PythonRecordVerifier` with 12 RECORD rows (7 hashed) and mismatched layer coverage, giving a repeatable hash-validation throughput reference for regression gating.
|
||||
@@ -0,0 +1,2 @@
|
||||
scenario,iterations,sample_count,mean_ms,p95_ms,max_ms
|
||||
syft_dotnet_multirid_fixture,5,2,1546.1609,2099.6870,2099.6870
|
||||
|
@@ -0,0 +1,2 @@
|
||||
scenario,iterations,sample_count,mean_ms,p95_ms,max_ms
|
||||
syft_go_buildinfo_fixture,5,2,5.1840,18.6375,23.5120
|
||||
|
@@ -0,0 +1,3 @@
|
||||
scenario,iterations,sample_count,mean_ms,p95_ms,max_ms
|
||||
python_site_packages_scan,5,3,5.6420,18.2943,22.3739
|
||||
python_pip_cache_fixture,5,1,5.8598,13.2855,15.6256
|
||||
|
43
src/StellaOps.Bench/TASKS.md
Normal file
43
src/StellaOps.Bench/TASKS.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Benchmarks Task Board
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| BENCH-SCANNER-10-001 | DONE | Bench Guild, Scanner Team | SCANNER-ANALYZERS-LANG-10-303 | Analyzer microbench harness (node_modules, site-packages) + baseline CSV. | Harness committed under `src/StellaOps.Bench/Scanner.Analyzers`; baseline CSV recorded; CI job publishes results. |
|
||||
| BENCH-SCANNER-10-002 | DONE (2025-10-21) | Bench Guild, Language Analyzer Guild | SCANNER-ANALYZERS-LANG-10-301..309 | Wire real language analyzers into bench harness & refresh baselines post-implementation. | Harness executes analyzer assemblies end-to-end; updated baseline committed; CI trend doc linked. |
|
||||
| BENCH-IMPACT-16-001 | TODO | Bench Guild, Scheduler Team | SCHED-IMPACT-16-301 | ImpactIndex throughput bench (resolve 10k productKeys) + RAM profile. | Benchmark script ready; baseline metrics recorded; alert thresholds defined. |
|
||||
| BENCH-NOTIFY-15-001 | TODO | Bench Guild, Notify Team | NOTIFY-ENGINE-15-301 | Notify dispatch throughput bench (vary rule density) with results CSV. | Bench executed; results stored; regression alert configured. |
|
||||
|
||||
## Policy Engine v2
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| BENCH-POLICY-20-001 | TODO | Bench Guild, Policy Guild | POLICY-ENGINE-20-002, POLICY-ENGINE-20-006 | Build policy evaluation benchmark suite (100k components, 1M advisories) capturing latency, throughput, memory. | Bench harness committed; baseline metrics recorded; ties into CI dashboards. |
|
||||
| BENCH-POLICY-20-002 | TODO | Bench Guild, Policy Guild, Scheduler Guild | BENCH-POLICY-20-001, SCHED-WORKER-20-302 | Add incremental run benchmark measuring delta evaluation vs full; capture SLA compliance. | Incremental bench executed; results stored; regression alerts configured. |
|
||||
|
||||
## Graph Explorer v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| BENCH-GRAPH-21-001 | TODO | Bench Guild, Cartographer Guild | CARTO-GRAPH-21-004, CARTO-GRAPH-21-006 | Build graph viewport/path benchmark harness simulating 50k/100k nodes; record latency, memory, tile cache hit rates. | Harness committed; baseline metrics logged; integrates with perf dashboards. |
|
||||
| BENCH-GRAPH-21-002 | TODO | Bench Guild, UI Guild | BENCH-GRAPH-21-001, UI-GRAPH-21-001 | Add headless UI load benchmark (Playwright) for graph canvas interactions to track render times and FPS budgets. | Benchmark runs in CI; results exported; alert thresholds defined. |
|
||||
|
||||
## Link-Not-Merge v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| BENCH-LNM-22-001 | TODO | Bench Guild, Concelier Guild | CONCELIER-LNM-21-002 | Create ingest benchmark simulating 500 advisory observations/sec, measuring correlator latency and Mongo throughput; publish baseline metrics. | Harness added; baseline stored; alerts wired for SLA breach. |
|
||||
| BENCH-LNM-22-002 | TODO | Bench Guild, Excititor Guild | EXCITITOR-LNM-21-002 | Build VEX ingestion/correlation perf test focusing on alias/product matching and event emission latency. | Benchmark executed; metrics captured; CI integration established. |
|
||||
|
||||
## Graph & Vuln Explorer v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| BENCH-GRAPH-24-001 | TODO | Bench Guild, SBOM Service Guild | SBOM-GRAPH-24-002 | Develop SBOM graph performance benchmark measuring build time, memory, and cache warm latency for 40k-node assets. | Benchmark runs in CI; baseline metrics recorded; alerts configured. |
|
||||
| BENCH-GRAPH-24-002 | TODO | Bench Guild, UI Guild | UI-GRAPH-24-001..005 | Implement UI interaction benchmarks (filter/zoom/table operations) citing p95 latency; integrate with perf dashboards. | UI perf metrics collected; thresholds enforced; documentation updated. |
|
||||
|
||||
## Reachability v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| BENCH-SIG-26-001 | TODO | Bench Guild, Signals Guild | SIGNALS-24-004 | Develop benchmark for reachability scoring pipeline (facts/sec, latency, memory) using synthetic callgraphs/runtime batches. | Benchmark runs in CI; baseline metrics recorded; alerts configured. |
|
||||
| BENCH-SIG-26-002 | TODO | Bench Guild, Policy Guild | POLICY-ENGINE-80-001 | Measure policy evaluation overhead with reachability cache hot/cold; ensure ≤8 ms p95 added latency. | Benchmark integrated; results tracked in dashboards; regression alerts set. |
|
||||
17
src/StellaOps.Cartographer/AGENTS.md
Normal file
17
src/StellaOps.Cartographer/AGENTS.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# StellaOps.Cartographer — Agent Charter
|
||||
|
||||
## Mission
|
||||
Build and operate the Cartographer service that materializes immutable SBOM property graphs, precomputes layout tiles, and hydrates policy/VEX overlays so other services (API, UI, CLI) can navigate and reason about dependency relationships with context.
|
||||
|
||||
## Responsibilities
|
||||
- Ingest normalized SBOM projections (CycloneDX/SPDX) and generate versioned graph snapshots with tenant-aware storage.
|
||||
- Maintain overlay workers that merge Policy Engine effective findings and VEX metadata onto graph nodes/edges, including path relevance computation.
|
||||
- Serve graph APIs for viewport tiles, paths, filters, exports, simulation overlays, and diffing.
|
||||
- Coordinate with Policy Engine, Scheduler, Conseiller, Excitator, and Authority to keep overlays current, respect RBAC, and uphold determinism guarantees.
|
||||
- Deliver observability (metrics/traces/logs) and performance benchmarks for large graphs (≥50k nodes).
|
||||
|
||||
## Expectations
|
||||
- Keep builds deterministic; snapshots are write-once and content-addressed.
|
||||
- Tenancy and scope enforcement must match Authority policies (`graph:*`, `sbom:read`, `findings:read`).
|
||||
- Update `TASKS.md`, `SPRINTS.md` when status changes.
|
||||
- Provide fixtures and documentation so UI/CLI teams can simulate graphs offline.
|
||||
17
src/StellaOps.Cartographer/Program.cs
Normal file
17
src/StellaOps.Cartographer/Program.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
builder.Configuration
|
||||
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||
.AddEnvironmentVariables("CARTOGRAPHER_");
|
||||
|
||||
builder.Services.AddOptions();
|
||||
builder.Services.AddLogging();
|
||||
|
||||
// TODO: register Cartographer graph builders, overlay workers, and Authority client once implementations land.
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
app.MapGet("/healthz", () => Results.Ok(new { status = "ok" }));
|
||||
app.MapGet("/readyz", () => Results.Ok(new { status = "warming" }));
|
||||
|
||||
app.Run();
|
||||
16
src/StellaOps.Cartographer/StellaOps.Cartographer.csproj
Normal file
16
src/StellaOps.Cartographer/StellaOps.Cartographer.csproj
Normal file
@@ -0,0 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\StellaOps.Configuration\StellaOps.Configuration.csproj" />
|
||||
<ProjectReference Include="..\StellaOps.DependencyInjection\StellaOps.DependencyInjection.csproj" />
|
||||
<ProjectReference Include="..\StellaOps.Policy.Engine\StellaOps.Policy.Engine.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
12
src/StellaOps.Cartographer/TASKS.md
Normal file
12
src/StellaOps.Cartographer/TASKS.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Cartographer Task Board — Epic 3: Graph Explorer v1
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| CARTO-GRAPH-21-001 | TODO | Cartographer Guild | SBOM-SERVICE-21-001 | Define graph storage schema: snapshot catalog, node/edge collections, overlay tables, sharding strategy, indexes, and retention rules. Document migration/rollback. | Mongo collections + indexes created via bootstrapper; schema doc drafted; integration tests verify tenant isolation and sharding. |
|
||||
| CARTO-GRAPH-21-002 | TODO | Cartographer Guild | CARTO-GRAPH-21-001 | Implement SBOM projection reader consuming normalized CycloneDX/SPDX from SBOM Service; validate fixtures and handle entrypoint tagging. | Reader ingests sample SBOMs (CycloneDX/SPDX); entrypoints resolved; unit tests cover malformed SBOM handling. |
|
||||
| CARTO-GRAPH-21-003 | TODO | Cartographer Guild | CARTO-GRAPH-21-002 | Build graph constructor deduping PURLs, emitting typed nodes/edges with metadata (licenses, supplier, hashes, scope). | Graph snapshots generated deterministically for fixtures; duplicate suppression verified; stats recorded. |
|
||||
| CARTO-GRAPH-21-004 | TODO | Cartographer Guild | CARTO-GRAPH-21-003 | Implement layout & tiling pipeline (global force layout + zoom tiles) and persist tiles to blob/object storage with manifests. | Layout tiles produced for fixtures; bbox metadata recorded; perf target (<10 min for 50k nodes) documented. |
|
||||
| CARTO-GRAPH-21-005 | TODO | Cartographer Guild | CARTO-GRAPH-21-003, POLICY-ENGINE-30-001 | Overlay worker hydrating policy effective findings/VEX data, computing path relevance from entrypoints, and supporting simulation overlays. | Overlay documents created for selected policies; path relevance validated via unit tests; SLA metric recorded. |
|
||||
| CARTO-GRAPH-21-006 | TODO | Cartographer Guild, BE-Base Platform Guild | CARTO-GRAPH-21-005 | Expose Cartographer APIs (versions, viewport tiles, node lookup, path queries, filters, diff, export, simulate) with pagination and streaming support. | API endpoints documented, tested, and OpenAPI published; large responses stream without timeouts; error codes mapped. |
|
||||
| CARTO-GRAPH-21-007 | TODO | Cartographer Guild, Scheduler Guild | CARTO-GRAPH-21-005, SCHED-WORKER-21-201 | Build backfill + incremental overlay jobs listening to policy/SBOM change events; ensure eventual consistency SLA (<2 min). | Change stream consumers enqueue work; retries/backoff implemented; observability metrics emit overlay lag. |
|
||||
| CARTO-GRAPH-21-008 | TODO | Cartographer Guild, QA Guild | CARTO-GRAPH-21-004..007 | Add unit/property/integration tests, synthetic 50k/100k perf suites, chaos scenarios (missing overlays, cyclic graphs), and determinism checks. | Test suite green; perf benchmarks logged; regression pipeline enforces determinism. |
|
||||
| CARTO-GRAPH-21-009 | TODO | Cartographer Guild, DevOps Guild | CARTO-GRAPH-21-006 | Provide deployment artefacts (Helm/Compose), configuration docs, and Offline Kit bundle notes for Cartographer. | Deployment descriptors merged; docs updated; offline kit includes seeds/layout caches; smoke tests added. |
|
||||
@@ -23,5 +23,10 @@
|
||||
## Reference Materials
|
||||
- `docs/ARCHITECTURE_CONCELIER.md` for database operations surface area.
|
||||
- Backend OpenAPI/contract docs (once available) for job triggers and scanner endpoints.
|
||||
- Existing module AGENTS/TASKS files for style and coordination cues.
|
||||
- `docs/09_API_CLI_REFERENCE.md` (section 3) for the user-facing synopsis of the CLI verbs and flags.
|
||||
- Existing module AGENTS/TASKS files for style and coordination cues.
|
||||
- `docs/09_API_CLI_REFERENCE.md` (section 3) for the user-facing synopsis of the CLI verbs and flags.
|
||||
|
||||
### Attestor Command Guild
|
||||
- Owns the `stella attest` verb family (sign, verify, list, fetch) plus key lifecycle helpers (create, import, rotate, revoke).
|
||||
- Ensures all attestation flows use the official SDK transport, support offline bundles, and surface JSON/table outputs for automation.
|
||||
- Guards parity with attestor service policies (verification policies, explainability) and keeps fixtures/tests covering file-based and KMS-backed keys.
|
||||
|
||||
@@ -1,24 +1,182 @@
|
||||
If you are working on this file you need to read docs/ARCHITECTURE_EXCITITOR.md and ./AGENTS.md).
|
||||
# TASKS
|
||||
| Task | Owner(s) | Depends on | Notes |
|
||||
|---|---|---|---|
|
||||
|Bootstrap configuration fallback (env → appsettings{{.json/.yaml}})|DevEx/CLI|Core|**DONE** – CLI loads `API_KEY`/`STELLAOPS_BACKEND_URL` from environment or local settings, defaulting to empty strings when unset.|
|
||||
|Introduce command host & routing skeleton|DevEx/CLI|Configuration|**DONE** – System.CommandLine (v2.0.0-beta5) router stitched with `scanner`, `scan`, `db`, and `config` verbs.|
|
||||
|Scanner artifact download/install commands|Ops Integrator|Backend contracts|**DONE** – `scanner download` caches bundles, validates SHA-256 (plus optional RSA signature), installs via `docker load`, persists metadata, and retries with exponential backoff.|
|
||||
|Scan execution & result upload workflow|Ops Integrator, QA|Scanner cmd|**DONE** – `scan run` drives container scans against directories, emits artefacts in `ResultsDirectory`, auto-uploads on success, and `scan upload` covers manual retries.|
|
||||
|Concelier DB operations passthrough|DevEx/CLI|Backend, Concelier APIs|**DONE** – `db fetch|merge|export` trigger `/jobs/*` endpoints with parameter binding and consistent exit codes.|
|
||||
|CLI observability & tests|QA|Command host|**DONE** – Added console logging defaults & configuration bootstrap tests; future metrics hooks tracked separately.|
|
||||
|Authority auth commands|DevEx/CLI|Auth libraries|**DONE** – `auth login/logout/status` wrap the shared auth client, manage token cache, and surface status messages.|
|
||||
|Document authority workflow in CLI help & quickstart|Docs/CLI|Authority auth commands|**DONE (2025-10-10)** – CLI help now surfaces Authority config fields and docs/09 + docs/10 describe env vars, auth login/status flow, and cache location.|
|
||||
|Authority whoami command|DevEx/CLI|Authority auth commands|**DONE (2025-10-10)** – Added `auth whoami` verb that displays subject/audience/expiry from cached tokens and handles opaque tokens gracefully.|
|
||||
|Expose auth client resilience settings|DevEx/CLI|Auth libraries LIB5|**DONE (2025-10-10)** – CLI options now bind resilience knobs, `AddStellaOpsAuthClient` honours them, and tests cover env overrides.|
|
||||
|Document advanced Authority tuning|Docs/CLI|Expose auth client resilience settings|**DONE (2025-10-10)** – docs/09 and docs/10 describe retry/offline settings with env examples and point to the integration guide.|
|
||||
|Surface password policy diagnostics in CLI output|DevEx/CLI, Security Guild|AUTHSEC-CRYPTO-02-004|**DONE (2025-10-15)** – CLI startup runs the Authority plug-in analyzer, logs weakened password policy warnings with manifest paths, added unit tests (`dotnet test src/StellaOps.Cli.Tests`) and updated docs/09 with remediation guidance.|
|
||||
|EXCITITOR-CLI-01-001 – Add `excititor` command group|DevEx/CLI|EXCITITOR-WEB-01-001|DONE (2025-10-18) – Introduced `excititor` verbs (init/pull/resume/list-providers/export/verify/reconcile) with token-auth backend calls, provenance-friendly logging, and regression coverage.|
|
||||
|EXCITITOR-CLI-01-002 – Export download & attestation UX|DevEx/CLI|EXCITITOR-CLI-01-001, EXCITITOR-EXPORT-01-001|DONE (2025-10-19) – CLI export prints digest/size/Rekor metadata, `--output` downloads with SHA-256 verification + cache reuse, and unit coverage validated via `dotnet test src/StellaOps.Cli.Tests`.|
|
||||
|EXCITITOR-CLI-01-003 – CLI docs & examples for Excititor|Docs/CLI|EXCITITOR-CLI-01-001|**DOING (2025-10-19)** – Update docs/09_API_CLI_REFERENCE.md and quickstart snippets to cover Excititor verbs, offline guidance, and attestation verification workflow.|
|
||||
|CLI-RUNTIME-13-005 – Runtime policy test verbs|DevEx/CLI|SCANNER-RUNTIME-12-302, ZASTAVA-WEBHOOK-12-102|**DONE (2025-10-19)** – Added `runtime policy test` command (stdin/file support, JSON output), backend client method + typed models, verdict table output, docs/tests updated (`dotnet test src/StellaOps.Cli.Tests`).|
|
||||
|CLI-OFFLINE-13-006 – Offline kit workflows|DevEx/CLI|DEVOPS-OFFLINE-14-002|**DONE (2025-10-21)** – Added `offline kit pull/import/status` commands with resumable downloads, digest/metadata validation, metrics, docs updates, and regression coverage (`dotnet test src/StellaOps.Cli.Tests`).|
|
||||
|CLI-PLUGIN-13-007 – Plugin packaging|DevEx/CLI|CLI-RUNTIME-13-005, CLI-OFFLINE-13-006|DONE (2025-10-22) – Packaged non-core verbs as restart-time plug-ins with manifest + loader updates and tests ensuring no hot reload.|
|
||||
|CLI-RUNTIME-13-008 – Runtime policy contract sync|DevEx/CLI, Scanner WebService Guild|SCANNER-RUNTIME-12-302|**DONE (2025-10-19)** – CLI runtime table/JSON now align with SCANNER-RUNTIME-12-302 (SBOM referrers, quieted provenance, confidence, verified Rekor); docs/09 updated with joint sign-off note.|
|
||||
|CLI-RUNTIME-13-009 – Runtime policy smoke fixture|DevEx/CLI, QA Guild|CLI-RUNTIME-13-005|**DONE (2025-10-19)** – Spectre console harness + regression tests cover table and `--json` output paths for `runtime policy test`, using stubbed backend and integrated into `dotnet test` suite.|
|
||||
# CLI Task Board — Epic 1: Aggregation-Only Contract
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| CLI-AOC-19-001 | TODO | DevEx/CLI Guild | CONCELIER-WEB-AOC-19-001, EXCITITOR-WEB-AOC-19-001 | Implement `stella sources ingest --dry-run` printing would-write payloads with forbidden field scan results and guard status. | Command displays diff-safe JSON, highlights forbidden fields, exits non-zero on guard violation, and has unit tests. |
|
||||
| CLI-AOC-19-002 | TODO | DevEx/CLI Guild | CLI-AOC-19-001 | Add `stella aoc verify` command supporting `--since`/`--limit`, mapping `ERR_AOC_00x` to exit codes, with JSON/table output. | Command integrates with both services, exit codes documented, regression tests green. |
|
||||
| CLI-AOC-19-003 | TODO | Docs/CLI Guild | CLI-AOC-19-001, CLI-AOC-19-002 | Update CLI reference and quickstart docs to cover new commands, exit codes, and offline verification workflows. | Docs updated; examples recorded; release notes mention new commands. |
|
||||
|
||||
## Policy Engine v2
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| CLI-POLICY-20-001 | TODO | DevEx/CLI Guild | WEB-POLICY-20-001 | Add `stella policy new|edit|submit|approve` commands with local editor integration, version pinning, and approval workflow wiring. | Commands round-trip policy drafts with temp files; approval requires correct scopes; unit tests cover happy/error paths. |
|
||||
| CLI-POLICY-20-002 | TODO | DevEx/CLI Guild | CLI-POLICY-20-001, WEB-POLICY-20-001, WEB-POLICY-20-002 | Implement `stella policy simulate` with SBOM/env arguments and diff output (table/JSON), handling exit codes for `ERR_POL_*`. | Simulation outputs deterministic diffs; JSON schema documented; tests validate exit codes + piping of env variables. |
|
||||
| CLI-POLICY-20-003 | TODO | DevEx/CLI Guild, Docs Guild | CLI-POLICY-20-002, WEB-POLICY-20-003, DOCS-POLICY-20-006 | Extend `stella findings ls|get` commands for policy-filtered retrieval with pagination, severity filters, and explain output. | Commands stream paginated results; explain view renders rationale entries; docs/help updated; end-to-end tests cover filters. |
|
||||
|
||||
## Graph Explorer v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| CLI-GRAPH-21-001 | TODO | DevEx/CLI Guild, Cartographer Guild | CARTO-GRAPH-21-006, WEB-GRAPH-21-001 | Implement `stella sbom graph build/export/query/diff` commands with RBAC-aware behavior, streaming outputs, and offline mode. | Commands execute against local fixtures; GraphML/JSONL exports match API; scope errors mapped to `ERR_Graph_*`; unit tests added. |
|
||||
| CLI-GRAPH-21-002 | TODO | DevEx/CLI Guild | CLI-GRAPH-21-001, WEB-GRAPH-21-004 | Add path query and simulation options (k-shortest paths, policy selection, filters) with JSON output suitable for CI. | Path query returns expected JSON schema; simulation overlay toggles; regression tests cover CLI-to-API contract. |
|
||||
| CLI-GRAPH-21-003 | TODO | DevEx/CLI Guild, Docs Guild | CLI-GRAPH-21-001, DOCS-GRAPH-21-005 | Document CLI usage and provide golden fixtures for CI; ensure exit codes align with `ERR_Graph_*`. | Docs updated; fixtures stored under `samples/graph/`; CI job runs CLI smoke; exit codes verified. |
|
||||
|
||||
## Link-Not-Merge v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| CLI-LNM-22-001 | TODO | DevEx/CLI Guild | WEB-LNM-21-001 | Implement `stella advisory obs get/linkset show/export` commands with JSON/OSV output, pagination, and conflict display; ensure `ERR_AGG_*` mapping. | Commands fetch observation/linkset data; exports validated against fixtures; unit tests cover error handling. |
|
||||
| CLI-LNM-22-002 | TODO | DevEx/CLI Guild | WEB-LNM-21-002 | Implement `stella vex obs get/linkset show` commands with product filters, status filters, and JSON output for CI usage. | Commands support filters + streaming; integration tests use sample linksets; docs updated. |
|
||||
|
||||
## Policy Engine + Editor v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| CLI-POLICY-23-004 | TODO | DevEx/CLI Guild | WEB-POLICY-23-001 | Add `stella policy lint` command validating SPL files with compiler diagnostics; support JSON output. | Command returns lint diagnostics; exit codes documented; tests cover error scenarios. |
|
||||
| CLI-POLICY-23-005 | TODO | DevEx/CLI Guild | WEB-POLICY-23-002 | Implement `stella policy activate` with scheduling window, approval enforcement, and summary output. | Activation command integrates with API, handles 2-person rule failures; tests cover success/error. |
|
||||
| CLI-POLICY-23-006 | TODO | DevEx/CLI Guild | WEB-POLICY-23-004 | Provide `stella policy history` and `stella policy explain` commands to pull run history and explanation trees. | Commands output JSON/table; integration tests with fixtures; docs updated. |
|
||||
|
||||
## Graph & Vuln Explorer v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| CLI-GRAPH-24-001 | TODO | DevEx/CLI Guild | WEB-GRAPH-24-001 | Add `stella graph show|search|diff` commands with JSON/table outputs, pagination, depth controls, and RBAC-aware error handling. | Commands return graph data; diff output validated with fixtures; unit tests cover pagination/error cases. |
|
||||
| CLI-GRAPH-24-002 | TODO | DevEx/CLI Guild | WEB-GRAPH-24-002 | Implement `stella graph simulate upgrade|policy` commands including progress feedback, diff summary, and exit codes for failure/timeouts. | Simulation commands integrate with API; regression tests exercise upgrade/policy scenarios; docs updated. |
|
||||
|
||||
## Exceptions v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| CLI-EXC-25-001 | TODO | DevEx/CLI Guild | WEB-EXC-25-001 | Implement `stella exceptions list|draft|propose|approve|revoke` commands with JSON/table output, validation, and workflow exit codes. | Commands exercise end-to-end workflow; unit/integration tests cover errors; docs updated. |
|
||||
| CLI-EXC-25-002 | TODO | DevEx/CLI Guild | WEB-EXC-25-002 | Extend `stella policy simulate` with `--with-exception`/`--without-exception` flags to preview exception impact. | Simulation handles overrides; regression tests cover presence/absence; help text updated. |
|
||||
|
||||
## Reachability v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| CLI-SIG-26-001 | TODO | DevEx/CLI Guild | WEB-SIG-26-001 | Implement `stella reachability upload-callgraph` and `stella reachability list/explain` commands with streaming upload, pagination, and exit codes. | Commands operate end-to-end; integration tests with fixtures; docs updated. |
|
||||
| CLI-SIG-26-002 | TODO | DevEx/CLI Guild | WEB-SIG-26-003 | Extend `stella policy simulate` with reachability override flags (`--reachability-state`, `--reachability-score`). | Simulation command accepts overrides; regression tests cover adjustments; help text updated. |
|
||||
|
||||
## Policy Studio (Sprint 27)
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| CLI-POLICY-27-001 | TODO | DevEx/CLI Guild | REGISTRY-API-27-001, WEB-POLICY-27-001 | Implement policy workspace commands (`stella policy init`, `edit`, `lint`, `compile`, `test`) with template selection, local cache, JSON output, and deterministic temp directories. | Commands operate offline with cached templates; diagnostics mirror API responses; unit tests cover happy/error paths; help text updated. |
|
||||
| CLI-POLICY-27-002 | TODO | DevEx/CLI Guild | REGISTRY-API-27-006, WEB-POLICY-27-002 | Add submission/review workflow commands (`stella policy version bump`, `submit`, `review comment`, `approve`, `reject`) supporting reviewer assignment, changelog capture, and exit codes. | Workflow commands enforce required approvers; comments upload correctly; integration tests cover approval failure; docs updated. |
|
||||
| CLI-POLICY-27-003 | TODO | DevEx/CLI Guild | REGISTRY-API-27-005, SCHED-CONSOLE-27-001 | Implement `stella policy simulate` enhancements (quick vs batch, SBOM selectors, heatmap summary, manifest download) with `--json` and Markdown report output for CI. | CLI can trigger batch sim, poll progress, download artifacts; outputs deterministic schemas; CI sample workflow documented; tests cover cancellation/timeouts. |
|
||||
| CLI-POLICY-27-004 | TODO | DevEx/CLI Guild | REGISTRY-API-27-007, REGISTRY-API-27-008, AUTH-POLICY-27-002 | Add lifecycle commands for publish/promote/rollback/sign (`stella policy publish --sign`, `promote --env`, `rollback`) with attestation verification and canary arguments. | Commands enforce signing requirement, support dry-run, produce audit logs; integration tests cover promotion + rollback; documentation updated. |
|
||||
| CLI-POLICY-27-005 | TODO | DevEx/CLI Guild, Docs Guild | DOCS-CONSOLE-27-007, DOCS-POLICY-27-007 | Update CLI reference and samples for Policy Studio including JSON schemas, exit codes, and CI snippets. | CLI docs merged with screenshots/transcripts; parity matrix updated; acceptance tests ensure `--help` examples compile. |
|
||||
|
||||
## Vulnerability Explorer (Sprint 29)
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| CLI-VULN-29-001 | TODO | DevEx/CLI Guild | VULN-API-29-002, AUTH-VULN-29-001 | Implement `stella vuln list` with grouping, paging, filters, `--json/--csv`, and policy selection. | Command returns deterministic output; paging works; regression tests cover filters/grouping. |
|
||||
| CLI-VULN-29-002 | TODO | DevEx/CLI Guild | VULN-API-29-003 | Implement `stella vuln show` displaying evidence, policy rationale, paths, ledger summary; support `--json` for automation. | Output matches schema; evidence rendered with provenance; tests cover missing data. |
|
||||
| CLI-VULN-29-003 | TODO | DevEx/CLI Guild | VULN-API-29-004, LEDGER-29-005 | Add workflow commands (`assign`, `comment`, `accept-risk`, `verify-fix`, `target-fix`, `reopen`) with filter selection (`--filter`) and idempotent retries. | Commands create ledger events; exit codes documented; integration tests cover role enforcement. |
|
||||
| CLI-VULN-29-004 | TODO | DevEx/CLI Guild | VULN-API-29-005 | Implement `stella vuln simulate` producing delta summaries and optional Markdown report for CI. | CLI simulation returns diff tables + JSON; tests verify diff correctness; docs updated. |
|
||||
| CLI-VULN-29-005 | TODO | DevEx/CLI Guild | VULN-API-29-008 | Add `stella vuln export` and `stella vuln bundle verify` commands to trigger/download evidence bundles and verify signatures. | Export command streams to file; verify command checks signatures; tests cover success/failure. |
|
||||
| CLI-VULN-29-006 | TODO | DevEx/CLI Guild, Docs Guild | DOCS-VULN-29-004, DOCS-VULN-29-005 | Update CLI docs/examples for Vulnerability Explorer with compliance checklist and CI snippets. | Docs merged; automated examples validated; compliance checklist appended. |
|
||||
|
||||
## VEX Lens (Sprint 30)
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| CLI-VEX-30-001 | TODO | DevEx/CLI Guild | VEXLENS-30-007 | Implement `stella vex consensus list` with filters, paging, policy selection, `--json/--csv`. | Command returns deterministic output; regression tests cover filters/paging; docs updated. |
|
||||
| CLI-VEX-30-002 | TODO | DevEx/CLI Guild | VEXLENS-30-007 | Implement `stella vex consensus show` displaying quorum, evidence, rationale, signature status. | Output matches schema; tests cover conflicting evidence; docs updated. |
|
||||
| CLI-VEX-30-003 | TODO | DevEx/CLI Guild | VEXLENS-30-007 | Implement `stella vex simulate` for trust/threshold overrides with JSON diff output. | Simulation command returns diff summary; tests cover policy scenarios; docs updated. |
|
||||
| CLI-VEX-30-004 | TODO | DevEx/CLI Guild | VEXLENS-30-007 | Implement `stella vex export` for consensus NDJSON bundles with signature verification helper. | Export & verify commands operational; tests cover file output; docs updated. |
|
||||
|
||||
## Advisory AI (Sprint 31)
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| CLI-AIAI-31-001 | TODO | DevEx/CLI Guild | AIAI-31-006 | Implement `stella advise summarize` command with JSON/Markdown outputs and citation display. | Command returns summary + JSON; citations preserved; tests cover filters. |
|
||||
| CLI-AIAI-31-002 | TODO | DevEx/CLI Guild | AIAI-31-006 | Implement `stella advise explain` showing conflict narrative and structured rationale. | Output matches schemas; tests cover disputed cases. |
|
||||
| CLI-AIAI-31-003 | TODO | DevEx/CLI Guild | AIAI-31-006 | Implement `stella advise remediate` generating remediation plans with `--strategy` filters and file output. | Plans saved to file; exit codes documented; tests cover version mapping. |
|
||||
| CLI-AIAI-31-004 | TODO | DevEx/CLI Guild | AIAI-31-006 | Implement `stella advise batch` for summaries/conflicts/remediation with progress + multi-status responses. | Batch command handles 207 responses; tests cover partial failures. |
|
||||
|
||||
## Export Center (Epic 10)
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| CLI-EXPORT-35-001 | TODO | DevEx/CLI Guild | WEB-EXPORT-35-001, AUTH-EXPORT-35-001 | Implement `stella export profiles|runs` list/show, `run create`, `run status`, and resumable download commands with manifest/provenance retrieval. | Commands respect viewer/operator scopes; downloads resume via range requests; integration tests cover filters and offline mode. |
|
||||
| CLI-EXPORT-36-001 | TODO | DevEx/CLI Guild | CLI-EXPORT-35-001, WEB-EXPORT-36-001 | Add distribution commands (`stella export distribute`, `run download --resume` enhancements) and improved status polling with progress bars. | Distribution commands push OCI/object storage; status polling handles SSE fallback; tests cover failure cases. |
|
||||
| CLI-EXPORT-37-001 | TODO | DevEx/CLI Guild | CLI-EXPORT-36-001, WEB-EXPORT-37-001 | Provide scheduling (`stella export schedule`), retention, and `export verify` commands performing signature/hash validation. | Scheduling/retention commands enforce admin scopes; verify command checks signatures/hashes; examples documented; tests cover success/failure. |
|
||||
## Orchestrator Dashboard (Epic 9)
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| CLI-ORCH-32-001 | TODO | DevEx/CLI Guild | WEB-ORCH-32-001, AUTH-ORCH-32-001 | Implement `stella orch sources|runs|jobs` list/show commands with filters, pagination, table/JSON output, and deterministic exit codes. | Commands respect viewer scope; JSON schema documented; integration tests cover filters/paging/offline mode. |
|
||||
| CLI-ORCH-33-001 | TODO | DevEx/CLI Guild | CLI-ORCH-32-001, WEB-ORCH-33-001, AUTH-ORCH-33-001 | Add action verbs (`sources test|pause|resume|sync-now`, `jobs retry|cancel|tail`) with streaming output, reason prompts, and retry/backoff handling. | Actions succeed with operator scope; streaming tail resilient to reconnect; tests cover permission failures and retries. |
|
||||
| CLI-ORCH-34-001 | TODO | DevEx/CLI Guild | CLI-ORCH-33-001, WEB-ORCH-34-001, AUTH-ORCH-34-001 | Provide backfill wizard (`--from/--to --dry-run`), quota management (`quotas get|set`), and safety guardrails for orchestrator GA. | Backfill preview output matches API; quota updates require reason; CLI docs/help updated; regression tests cover dry-run + failure paths. |
|
||||
|
||||
## Notifications Studio (Epic 11)
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| CLI-NOTIFY-38-001 | TODO | DevEx/CLI Guild | WEB-NOTIFY-38-001, AUTH-NOTIFY-38-001 | Implement `stella notify rules|templates|incidents` commands (list/create/update/test/ack) with file inputs, JSON output, and RBAC-aware flow. | Commands invoke notifier APIs successfully; rule test uses local events file; integration tests cover create/test/ack; help docs updated. |
|
||||
| CLI-NOTIFY-39-001 | TODO | DevEx/CLI Guild | CLI-NOTIFY-38-001, WEB-NOTIFY-39-001 | Add simulation (`stella notify simulate`) and digest commands with diff output and schedule triggering, including dry-run mode. | Simulation command returns deterministic diff; digest command triggers run and polls status; tests cover filters and failures. |
|
||||
| CLI-NOTIFY-40-001 | TODO | DevEx/CLI Guild | CLI-NOTIFY-39-001, WEB-NOTIFY-40-001 | Provide ack token redemption workflow, escalation management, localization previews, and channel health checks. | Ack redemption validates signed tokens; escalation commands manage schedules; localization preview shows variants; integration tests cover negative cases. |
|
||||
|
||||
## CLI Parity & Task Packs (Epic 12)
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| CLI-CORE-41-001 | TODO | DevEx/CLI Guild | AUTH-PACKS-41-001 | Implement CLI core features: config precedence, profiles/contexts, auth flows, output renderer (json/yaml/table), error mapping, global flags, telemetry opt-in. | CLI loads config deterministically; auth works (device/PAT); outputs render correctly; tests cover precedence and exit codes. |
|
||||
| CLI-PARITY-41-001 | TODO | DevEx/CLI Guild | CLI-CORE-41-001 | Deliver parity command groups (`policy`, `sbom`, `vuln`, `vex`, `advisory`, `export`, `orchestrator`) with `--explain`, deterministic outputs, and parity matrix entries. | Commands match Console behavior; parity matrix green for covered actions; integration tests cover major flows. |
|
||||
| CLI-PARITY-41-002 | TODO | DevEx/CLI Guild | CLI-PARITY-41-001, WEB-NOTIFY-38-001 | Implement `notify`, `aoc`, `auth` command groups, idempotency keys, shell completions, config docs, and parity matrix export tooling. | Commands functional; completions generated; docs updated; parity matrix auto-exported; CI checks gating. |
|
||||
| CLI-PACKS-42-001 | TODO | DevEx/CLI Guild | CLI-CORE-41-001, PACKS-REG-41-001, TASKRUN-41-001 | Implement Task Pack commands (`pack plan/run/push/pull/verify`) with schema validation, expression sandbox, plan/simulate engine, remote execution. | Pack commands operational; plan/sim produce accurate graph; remote run streams logs; schema validation enforced. |
|
||||
| CLI-PACKS-43-001 | TODO | DevEx/CLI Guild | CLI-PACKS-42-001, TASKRUN-42-001 | Deliver advanced pack features (approvals pause/resume, secret injection, localization, man pages, offline cache). | Approvals handled; secrets redacted; localization supported; man pages built; offline cache documented; integration tests cover scenarios. |
|
||||
|
||||
## Authority-Backed Scopes & Tenancy (Epic 14)
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| CLI-TEN-47-001 | TODO | DevEx/CLI Guild | AUTH-TEN-47-001 | Implement `stella login`, `whoami`, `tenants list`, persistent profiles, secure token storage, and `--tenant` override with validation. | Commands functional across platforms; tokens stored securely; tenancy header set on requests; integration tests cover login/tenant switch. |
|
||||
| CLI-TEN-49-001 | TODO | DevEx/CLI Guild | CLI-TEN-47-001, AUTH-TEN-49-001 | Add service account token minting, delegation (`stella token delegate`), impersonation banner, and audit-friendly logging. | Service tokens minted with scopes/TTL; delegation recorded; CLI displays impersonation banner; docs updated. |
|
||||
|
||||
## Observability & Forensics (Epic 15)
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| CLI-OBS-50-001 | TODO | DevEx/CLI Guild | TELEMETRY-OBS-50-002, WEB-OBS-50-001 | Ensure CLI HTTP client propagates `traceparent` headers for all commands, prints correlation IDs on failure, and records trace IDs in verbose logs (scrubbed). | Trace headers observed in integration tests; verbose logs include trace IDs; redaction guard verified. |
|
||||
| CLI-OBS-51-001 | TODO | DevEx/CLI Guild | CLI-OBS-50-001, WEB-OBS-51-001 | Implement `stella obs top` command streaming service health metrics, SLO status, and burn-rate alerts with TUI view and JSON output. | Command streams metrics; JSON output documented; integration tests cover streaming and exit codes. |
|
||||
| CLI-OBS-52-001 | TODO | DevEx/CLI Guild | CLI-OBS-51-001, TIMELINE-OBS-52-003 | Add `stella obs trace <trace_id>` and `stella obs logs --from/--to` commands that correlate timeline events, logs, and evidence links with pagination + guardrails. | Commands fetch timeline/log data; paging tokens handled; fixtures stored under `samples/obs/`; tests cover errors. |
|
||||
| CLI-FORENSICS-53-001 | TODO | DevEx/CLI Guild, Evidence Locker Guild | CLI-OBS-52-001, EVID-OBS-53-003 | Implement `stella forensic snapshot create --case` and `snapshot list/show` commands invoking evidence locker APIs, surfacing manifest digests, and storing local cache metadata. | Snapshot commands functional; manifests displayed; cache metadata deterministic; docs/help updated. |
|
||||
| CLI-FORENSICS-54-001 | TODO | DevEx/CLI Guild, Provenance Guild | CLI-FORENSICS-53-001, PROV-OBS-54-001 | Provide `stella forensic verify <bundle>` command validating checksums, DSSE signatures, and timeline chain-of-custody. Support JSON/pretty output and exit codes for CI. | Verification works with sample bundles; tests cover success/failure; docs updated. |
|
||||
| CLI-FORENSICS-54-002 | TODO | DevEx/CLI Guild, Provenance Guild | CLI-FORENSICS-54-001 | Implement `stella forensic attest show <artifact>` listing attestation details (signer, timestamp, subjects) and verifying signatures. | Command prints attestation summary; verification errors flagged; tests cover offline mode. |
|
||||
| CLI-OBS-55-001 | TODO | DevEx/CLI Guild, DevOps Guild | CLI-OBS-52-001, WEB-OBS-55-001, DEVOPS-OBS-55-001 | Add `stella obs incident-mode enable|disable|status` commands with confirmation guards, cooldown timers, and audit logging. | Commands manage incident mode; audit logs verified; tests cover permissions and cooldown. |
|
||||
|
||||
## Air-Gapped Mode (Epic 16)
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| CLI-AIRGAP-56-001 | TODO | DevEx/CLI Guild | MIRROR-CRT-56-001, AIRGAP-IMP-56-001 | Implement `stella mirror create|verify` and `stella airgap verify` commands with DSSE/TUF results, dry-run mode, and deterministic manifests. | Commands produce deterministic bundles; verify outputs structured DSSE/TUF results; integration tests cover tampering scenarios. |
|
||||
| CLI-AIRGAP-57-001 | TODO | DevEx/CLI Guild | CLI-AIRGAP-56-001, AIRGAP-IMP-58-001 | Add `stella airgap import` with diff preview, bundle scope selection (`--tenant`, `--global`), audit logging, and progress reporting. | Import updates catalog; diff preview rendered; audit entries include bundle ID + scope; tests cover idempotent re-import. |
|
||||
| CLI-AIRGAP-57-002 | TODO | DevEx/CLI Guild | CLI-AIRGAP-56-001, AIRGAP-CTL-56-002 | Provide `stella airgap seal|status` commands surfacing sealing state, drift, staleness metrics, and remediation guidance with safe confirmation prompts. | Status command prints drift/staleness; seal requires confirmation + scope; integration tests cover RBAC denials. |
|
||||
| CLI-AIRGAP-58-001 | TODO | DevEx/CLI Guild, Evidence Locker Guild | CLI-AIRGAP-57-001, CLI-FORENSICS-54-001 | Implement `stella airgap export evidence` helper for portable evidence packages, including checksum manifest and verification. | Command generates portable bundle; verification step validates signatures; docs/help updated with examples. |
|
||||
|
||||
## SDKs & OpenAPI (Epic 17)
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| CLI-SDK-62-001 | TODO | DevEx/CLI Guild, SDK Generator Guild | SDKGEN-63-001 | Replace bespoke HTTP clients with official SDK (TS/Go) for all CLI commands; ensure modular transport for air-gapped mode. | CLI builds using SDK; regression suite passes; telemetry shows SDK version. |
|
||||
| CLI-SDK-62-002 | TODO | DevEx/CLI Guild | CLI-SDK-62-001, APIGOV-61-001 | Update CLI error handling to surface standardized API error envelope with `error.code` and `trace_id`. | CLI displays envelope data; integration tests cover new output. |
|
||||
| CLI-SDK-63-001 | TODO | DevEx/CLI Guild, API Governance Guild | OAS-61-002 | Expose `stella api spec download` command retrieving aggregate OAS and verifying checksum/ETag. | Command downloads + verifies spec; docs updated; tests cover failure cases. |
|
||||
| CLI-SDK-64-001 | TODO | DevEx/CLI Guild, SDK Release Guild | SDKREL-63-001 | Add CLI subcommand `stella sdk update` to fetch latest SDK manifests/changelogs; integrate with Notifications for deprecations. | Command lists versions/changelogs; notifications triggered on updates. |
|
||||
|
||||
## Risk Profiles (Epic 18)
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| CLI-RISK-66-001 | TODO | DevEx/CLI Guild, Policy Guild | POLICY-RISK-67-002 | Implement `stella risk profile list|get|create|publish` commands with schema validation and scope selectors. | Commands operate against API; validation errors surfaced; tests cover CRUD. |
|
||||
| CLI-RISK-66-002 | TODO | DevEx/CLI Guild, Risk Engine Guild | RISK-ENGINE-69-001 | Ship `stella risk simulate` supporting SBOM/asset inputs, diff mode, and export to JSON/CSV. | Simulation runs via CLI; output tested; docs updated. |
|
||||
| CLI-RISK-67-001 | TODO | DevEx/CLI Guild, Findings Ledger Guild | LEDGER-RISK-67-001 | Provide `stella risk results` with filtering, severity thresholds, explainability fetch. | Results command returns paginated data; explaination fetch command outputs artifact; tests pass. |
|
||||
| CLI-RISK-68-001 | TODO | DevEx/CLI Guild, Export Guild | RISK-BUNDLE-70-001 | Add `stella risk bundle verify` and integrate with offline risk bundles. | Verification command validates signatures; integration tests cover tampered bundle. |
|
||||
|
||||
## Attestor Console (Epic 19)
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| CLI-ATTEST-73-001 | TODO | CLI Attestor Guild | ATTESTOR-73-001, SDKGEN-63-001 | Implement `stella attest sign` (payload selection, subject digest, key reference, output format) using official SDK transport. | Command signs envelopes; tests cover file/KMS keys; docs updated. |
|
||||
| CLI-ATTEST-73-002 | TODO | CLI Attestor Guild | ATTESTOR-73-002 | Implement `stella attest verify` with policy selection, explainability output, and JSON/table formatting. | Verification command returns structured report; exit codes match pass/fail; integration tests pass. |
|
||||
| CLI-ATTEST-74-001 | TODO | CLI Attestor Guild | ATTESTOR-73-003 | Implement `stella attest list` with filters (subject, type, issuer, scope) and pagination. | Command outputs table/JSON; tests cover filters. |
|
||||
| CLI-ATTEST-74-002 | TODO | CLI Attestor Guild | ATTESTOR-73-003 | Implement `stella attest fetch` to download envelopes and payloads to disk. | Fetch command saves files; checks digests; tests cover air-gap use. |
|
||||
| CLI-ATTEST-75-001 | TODO | CLI Attestor Guild, KMS Guild | KMS-72-001 | Implement `stella attest key create|import|rotate|revoke` commands. | Key commands work with file/KMS drivers; tests cover rotation/revocation. |
|
||||
| CLI-ATTEST-75-002 | TODO | CLI Attestor Guild, Export Guild | ATTESTOR-75-001 | Add support for building/verifying attestation bundles in CLI. | Bundle commands functional; verification catches tampering; docs updated. |
|
||||
|
||||
@@ -1,21 +1,106 @@
|
||||
# TASKS
|
||||
| Task | Owner(s) | Depends on | Notes |
|
||||
|---|---|---|---|
|
||||
|JobCoordinator implementation (create/get/mark status)|BE-Core|Storage.Mongo|DONE – `JobCoordinator` drives Mongo-backed runs.|
|
||||
|Cron scheduling loop with TimeProvider|BE-Core|Core|DONE – `JobSchedulerHostedService` evaluates cron expressions.|
|
||||
|Single-flight/lease semantics|BE-Core|Storage.Mongo|DONE – lease acquisition backed by `MongoLeaseStore`.|
|
||||
|Trigger API contract (Result mapping)|BE-Core|WebService|DONE – `JobTriggerResult` outcomes map to HTTP statuses.|
|
||||
|Run telemetry enrichment|BE-Core|Observability|DONE – `JobDiagnostics` ties activities & counters into coordinator/scheduler paths.|
|
||||
|Deterministic params hashing|BE-Core|Core|DONE – `JobParametersHasher` creates SHA256 hash.|
|
||||
|Golden tests for timeout/cancel|QA|Core|DONE – JobCoordinatorTests cover cancellation timeout path.|
|
||||
|JobSchedulerBuilder options registry coverage|BE-Core|Core|DONE – added scheduler tests confirming cron/timeout/lease metadata persists via JobSchedulerOptions.|
|
||||
|Plugin discovery + DI glue with PluginHost|BE-Core|Plugin libs|DONE – JobPluginRegistrationExtensions now loads PluginHost routines and wires connector/exporter registrations.|
|
||||
|Harden lease release error handling in JobCoordinator|BE-Core|Storage.Mongo|DONE – lease release failures now logged, wrapped, and drive run failure status; fire-and-forget execution guarded. Verified with `dotnet test --no-build --filter JobCoordinator`.|
|
||||
|Validate job trigger parameters for serialization|BE-Core|WebService|DONE – trigger parameters normalized/serialized with defensive checks returning InvalidParameters on failure. Full-suite `dotnet test --no-build` currently red from live connector fixture drift (Oracle/JVN/RedHat).|
|
||||
|FEEDCORE-ENGINE-03-001 Canonical merger implementation|BE-Core|Merge|DONE – `CanonicalMerger` applies GHSA/NVD/OSV conflict rules with deterministic provenance and comprehensive unit coverage. **Coordination:** Connector leads must align mapper outputs with the canonical field expectations before 2025-10-18 so Merge can activate the path globally.|
|
||||
|FEEDCORE-ENGINE-03-002 Field precedence and tie-breaker map|BE-Core|Merge|DONE – field precedence and freshness overrides enforced via `FieldPrecedence` map with tie-breakers and analytics capture. **Reminder:** Storage/Merge owners review precedence overrides when onboarding new feeds to ensure `decisionReason` tagging stays consistent.|
|
||||
|Canonical merger parity for description/CWE/canonical metric|BE-Core|Models|DONE (2025-10-15) – merger now populates description/CWEs/canonical metric id with provenance and regression tests cover the new decisions.|
|
||||
|Reference normalization & freshness instrumentation cleanup|BE-Core, QA|Models|DONE (2025-10-15) – reference keys normalized, freshness overrides applied to union fields, and new tests assert decision logging.|
|
||||
|FEEDCORE-ENGINE-07-001 – Advisory event log & asOf queries|Team Core Engine & Storage Analytics|FEEDSTORAGE-DATA-07-001|**DONE (2025-10-19)** – Implemented `AdvisoryEventLog` service plus repository contracts, canonical hashing, and lower-cased key normalization with replay support; documented determinism guarantees. Tests: `dotnet test src/StellaOps.Concelier.Core.Tests/StellaOps.Concelier.Core.Tests.csproj`.|
|
||||
|FEEDCORE-ENGINE-07-002 – Noise prior computation service|Team Core Engine & Data Science|FEEDCORE-ENGINE-07-001|**DONE (2025-10-21)** – Build rule-based learner capturing false-positive priors per package/env, persist summaries, and expose APIs for Excititor/scan suppressors with reproducible statistics.|
|
||||
|FEEDCORE-ENGINE-07-003 – Unknown state ledger & confidence seeding|Team Core Engine & Storage Analytics|FEEDCORE-ENGINE-07-001|DONE (2025-10-21) – Persisted `unknown_vuln_range/unknown_origin/ambiguous_fix` markers with seeded confidence bands, exposed query surface for Policy, and added canonical serialization fixtures + regression tests.|
|
||||
# TASKS — Epic 1: Aggregation-Only Contract
|
||||
> **AOC Reminder:** ingestion aggregates and links only—no precedence, normalization, or severity computation. Derived data lives in Policy/overlay services.
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|---|---|---|---|---|
|
||||
| CONCELIER-CORE-AOC-19-001 `AOC write guard` | TODO | Concelier Core Guild | WEB-AOC-19-001 | Implement repository interceptor that inspects write payloads for forbidden AOC keys, validates provenance/signature presence, and maps violations to `ERR_AOC_00x`. |
|
||||
| CONCELIER-CORE-AOC-19-002 `Deterministic linkset extraction` | TODO | Concelier Core Guild | CONCELIER-CORE-AOC-19-001 | Build canonical linkset mappers for CVE/GHSA/PURL/CPE/reference extraction from upstream raw payloads, ensuring reconciled-from metadata is tracked and deterministic. |
|
||||
| CONCELIER-CORE-AOC-19-003 `Idempotent append-only upsert` | TODO | Concelier Core Guild | CONCELIER-STORE-AOC-19-002 | Implement idempotent upsert path using `(vendor, upstreamId, contentHash, tenant)` key, emitting supersedes pointers for new revisions and preventing duplicate inserts. |
|
||||
| CONCELIER-CORE-AOC-19-004 `Remove ingestion normalization` | TODO | Concelier Core Guild | CONCELIER-CORE-AOC-19-002, POLICY-AOC-19-003 | Strip normalization/dedup/severity logic from ingestion pipelines, delegate derived computations to Policy Engine, and update exporters/tests to consume raw documents only. |
|
||||
|
||||
## Policy Engine v2
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| CONCELIER-POLICY-20-002 `Linkset enrichment for policy` | TODO | Concelier Core Guild, Policy Guild | CONCELIER-CORE-AOC-19-002, POLICY-ENGINE-20-001 | Strengthen linkset builders with vendor-specific equivalence tables, NEVRA/PURL normalization, and version range parsing to maximize policy join recall; update fixtures + docs. |
|
||||
|
||||
## Graph Explorer v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| CONCELIER-GRAPH-21-001 `SBOM projection enrichment` | TODO | Concelier Core Guild, Cartographer Guild | CONCELIER-POLICY-20-002, CARTO-GRAPH-21-002 | Extend SBOM normalization to emit full relationship graph (depends_on/contains/provides), scope tags, entrypoint annotations, and component metadata required by Cartographer. |
|
||||
| CONCELIER-GRAPH-21-002 `Change events` | TODO | Concelier Core Guild, Scheduler Guild | CONCELIER-GRAPH-21-001 | Publish change events (new SBOM version, relationship delta) for Cartographer build queue; ensure events include tenant/context metadata. |
|
||||
|
||||
## Link-Not-Merge v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| CONCELIER-LNM-21-001 `Advisory observation schema` | TODO | Concelier Core Guild | CONCELIER-CORE-AOC-19-001 | Introduce immutable `advisory_observations` model with AOC metadata, raw payload pointers, normalized fields, and tenancy guardrails; publish schema definition. |
|
||||
| CONCELIER-LNM-21-002 `Linkset builder` | TODO | Concelier Core Guild, Data Science Guild | CONCELIER-LNM-21-001 | Implement correlation pipeline (alias graph, PURL overlap, CVSS vector equality, fuzzy title match) that produces `advisory_linksets` with confidence + conflict annotations. |
|
||||
| CONCELIER-LNM-21-003 `Conflict annotator` | TODO | Concelier Core Guild | CONCELIER-LNM-21-002 | Detect field disagreements (severity, CVSS, ranges, references) and record structured conflicts on linksets; surface to API/UI. |
|
||||
| CONCELIER-LNM-21-004 `Merge code removal` | TODO | Concelier Core Guild | CONCELIER-LNM-21-002 | Excise existing merge/dedup logic, enforce immutability on observations, and add guards/tests to prevent future merges. |
|
||||
| CONCELIER-LNM-21-005 `Event emission` | TODO | Concelier Core Guild, Platform Events Guild | CONCELIER-LNM-21-002 | Emit `advisory.linkset.updated` events with delta payloads for downstream Policy Engine/Cartographer consumers; ensure idempotent delivery. |
|
||||
|
||||
## Policy Engine + Editor v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| CONCELIER-POLICY-23-001 `Evidence indexes` | TODO | Concelier Core Guild | CONCELIER-LNM-21-002 | Add secondary indexes/materialized views to accelerate policy lookups (alias, severity per observation, correlation confidence). Document query contracts for runtime. |
|
||||
| CONCELIER-POLICY-23-002 `Event guarantees` | TODO | Concelier Core Guild, Platform Events Guild | CONCELIER-LNM-21-005 | Ensure `advisory.linkset.updated` emits at-least-once with idempotent keys and include policy-relevant metadata (confidence, conflict summary). |
|
||||
|
||||
## Graph & Vuln Explorer v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| CONCELIER-GRAPH-24-001 `Advisory overlay inputs` | TODO | Concelier Core Guild | CONCELIER-POLICY-23-001 | Expose raw advisory observations/linksets with tenant filters for overlay services; no derived counts/severity in ingestion. |
|
||||
|
||||
## Reachability v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| CONCELIER-SIG-26-001 `Vulnerable symbol exposure` | TODO | Concelier Core Guild, Signals Guild | SIGNALS-24-002 | Expose advisory metadata (affected symbols/functions) via API to enrich reachability scoring; update fixtures. |
|
||||
|
||||
## Orchestrator Dashboard
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| CONCELIER-ORCH-32-001 `Source registry integration` | TODO | Concelier Core Guild | ORCH-SVC-32-001, AUTH-ORCH-32-001 | Register Concelier data sources with orchestrator (metadata, schedules, rate policies) and wire provenance IDs/security scopes. |
|
||||
| CONCELIER-ORCH-32-002 `Worker SDK adoption` | TODO | Concelier Core Guild | CONCELIER-ORCH-32-001, WORKER-GO-32-001, WORKER-PY-32-001 | Embed orchestrator worker SDK in ingestion loops, emit heartbeats/progress/artifact hashes, and enforce idempotency keys. |
|
||||
| CONCELIER-ORCH-33-001 `Control hook compliance` | TODO | Concelier Core Guild | CONCELIER-ORCH-32-002, ORCH-SVC-33-001, ORCH-SVC-33-002 | Honor orchestrator throttle/pause/retry actions, surface structured error classes, and persist safe checkpoints for resume. |
|
||||
| CONCELIER-ORCH-34-001 `Backfill + ledger linkage` | TODO | Concelier Core Guild | CONCELIER-ORCH-33-001, ORCH-SVC-33-003, ORCH-SVC-34-001 | Execute orchestrator-driven backfills, reuse artifact hashes to avoid duplicates, and link provenance to run ledger exports. |
|
||||
|
||||
## Authority-Backed Scopes & Tenancy (Epic 14)
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| CONCELIER-TEN-48-001 `Tenant-aware linking` | TODO | Concelier Core Guild | AUTH-TEN-47-001 | Ensure advisory normalization/linking runs per tenant with RLS enforcing isolation; emit capability endpoint reporting `merge=false`; update events with tenant context. |
|
||||
|
||||
## Observability & Forensics (Epic 15)
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| CONCELIER-OBS-50-001 `Telemetry adoption` | TODO | Concelier Core Guild, Observability Guild | TELEMETRY-OBS-50-001, TELEMETRY-OBS-50-002 | Replace ad-hoc logging with telemetry core across ingestion/linking pipelines; ensure spans/logs include tenant, source vendor, upstream id, content hash, and trace IDs. |
|
||||
| CONCELIER-OBS-51-001 `Metrics & SLOs` | TODO | Concelier Core Guild, DevOps Guild | CONCELIER-OBS-50-001, TELEMETRY-OBS-51-001 | Emit metrics for ingest latency (cold/warm), queue depth, aoc violation rate, and publish SLO burn-rate alerts (ingest P95 <30s cold / <5s warm). Ship dashboards + alert configs. |
|
||||
| CONCELIER-OBS-52-001 `Timeline events` | TODO | Concelier Core Guild | CONCELIER-OBS-50-001, TIMELINE-OBS-52-002 | Emit `timeline_event` records for advisory ingest/normalization/linkset creation with provenance, trace IDs, conflict summaries, and evidence placeholders. |
|
||||
| CONCELIER-OBS-53-001 `Evidence snapshots` | TODO | Concelier Core Guild, Evidence Locker Guild | CONCELIER-OBS-52-001, EVID-OBS-53-002 | Produce advisory evaluation bundle payloads (raw doc, linkset, normalization diff) for evidence locker; ensure Merkle manifests seeded with content hashes. |
|
||||
| CONCELIER-OBS-54-001 `Attestation & verification` | TODO | Concelier Core Guild, Provenance Guild | CONCELIER-OBS-53-001, PROV-OBS-54-001 | Attach DSSE attestations for advisory processing batches, expose verification API to confirm bundle integrity, and link attestation IDs back to timeline + ledger. |
|
||||
| CONCELIER-OBS-55-001 `Incident mode hooks` | TODO | Concelier Core Guild, DevOps Guild | CONCELIER-OBS-51-001, DEVOPS-OBS-55-001 | Increase sampling, capture raw payload snapshots, and extend retention under incident mode; emit activation events + guardrails against PII leak. |
|
||||
|
||||
## Air-Gapped Mode (Epic 16)
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| CONCELIER-AIRGAP-56-001 `Mirror ingestion adapters` | TODO | Concelier Core Guild | AIRGAP-IMP-57-002, MIRROR-CRT-56-001 | Add mirror source adapters reading advisories from imported bundles, preserving source metadata and bundle IDs. Ensure ingestion remains append-only. |
|
||||
| CONCELIER-AIRGAP-56-002 `Bundle catalog linking` | TODO | Concelier Core Guild, AirGap Importer Guild | CONCELIER-AIRGAP-56-001, AIRGAP-IMP-57-001 | Persist `bundle_id`, `merkle_root`, and time anchor references on observations/linksets for provenance. |
|
||||
| CONCELIER-AIRGAP-57-001 `Sealed-mode source restrictions` | TODO | Concelier Core Guild, AirGap Policy Guild | CONCELIER-AIRGAP-56-001, AIRGAP-POL-56-001 | Enforce sealed-mode egress rules by disallowing non-mirror connectors and surfacing remediation errors. |
|
||||
| CONCELIER-AIRGAP-57-002 `Staleness annotations` | TODO | Concelier Core Guild, AirGap Time Guild | CONCELIER-AIRGAP-56-002, AIRGAP-TIME-58-001 | Compute staleness metadata for advisories per bundle and expose via API for Console/CLI badges. |
|
||||
| CONCELIER-AIRGAP-58-001 `Portable advisory evidence` | TODO | Concelier Core Guild, Evidence Locker Guild | CONCELIER-OBS-53-001, EVID-OBS-54-001 | Package advisory evidence fragments into portable evidence bundles for cross-domain transfer. |
|
||||
|
||||
## SDKs & OpenAPI (Epic 17)
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| CONCELIER-OAS-61-001 `Spec coverage` | TODO | Concelier Core Guild, API Contracts Guild | OAS-61-001 | Update Concelier OAS with advisory observation/linkset endpoints, standard pagination, and source provenance fields. |
|
||||
| CONCELIER-OAS-61-002 `Examples library` | TODO | Concelier Core Guild | CONCELIER-OAS-61-001 | Provide rich examples for advisories, linksets, conflict annotations used by SDK + docs. |
|
||||
| CONCELIER-OAS-62-001 `SDK smoke tests` | TODO | Concelier Core Guild, SDK Generator Guild | CONCELIER-OAS-61-001, SDKGEN-63-001 | Add SDK tests covering advisory search, pagination, and conflict handling; ensure source metadata surfaced. |
|
||||
| CONCELIER-OAS-63-001 `Deprecation headers` | TODO | Concelier Core Guild, API Governance Guild | APIGOV-63-001 | Implement deprecation header support and timeline events for retiring endpoints. |
|
||||
|
||||
## Risk Profiles (Epic 18)
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| CONCELIER-RISK-66-001 `CVSS/KEV providers` | TODO | Concelier Core Guild, Risk Engine Guild | RISK-ENGINE-67-001 | Expose CVSS, KEV, fix availability data via provider APIs with source metadata preserved. |
|
||||
| CONCELIER-RISK-66-002 `Fix availability signals` | TODO | Concelier Core Guild | CONCELIER-RISK-66-001 | Provide structured fix availability and release metadata consumable by risk engine; document provenance. |
|
||||
| CONCELIER-RISK-67-001 `Source consensus metrics` | TODO | Concelier Core Guild | CONCELIER-RISK-66-001 | Add consensus counts and confidence scores for linked advisories; ensure explainability includes source digests. |
|
||||
| CONCELIER-RISK-68-001 `Policy Studio integration` | TODO | Concelier Core Guild, Policy Studio Guild | POLICY-RISK-68-001 | Surface advisory fields in Policy Studio profile editor (signal pickers, reducers). |
|
||||
| CONCELIER-RISK-69-001 `Notification hooks` | TODO | Concelier Core Guild, Notifications Guild | CONCELIER-RISK-66-002 | Emit events when advisory signals change impacting risk scores (e.g., fix available). |
|
||||
|
||||
## Attestor Console (Epic 19)
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| CONCELIER-ATTEST-73-001 `ScanResults attestation inputs` | TODO | Concelier Core Guild, Attestor Service Guild | ATTEST-TYPES-72-001 | Provide normalized advisory data and linkset digests needed for ScanResults attestations. |
|
||||
| CONCELIER-ATTEST-73-002 `Transparency metadata` | TODO | Concelier Core Guild | CONCELIER-ATTEST-73-001 | Ensure Conseiller exposes source digests for transparency proofs and explainability. |
|
||||
|
||||
@@ -24,3 +24,10 @@
|
||||
|FEEDMERGE-COORD-02-901 Connector deadline check-ins|BE-Merge|FEEDMERGE-COORD-02-900|**TODO (due 2025-10-21)** – Confirm Cccs/Cisco normalized-rule branches land, capture `concelier.merge.normalized_rules*` counter screenshots, and update coordination docs with the results.|
|
||||
|FEEDMERGE-COORD-02-902 ICS-CISA normalized-rule decision support|BE-Merge, Models|FEEDMERGE-COORD-02-900|**TODO (due 2025-10-23)** – Review ICS-CISA sample advisories, confirm SemVer reuse vs new firmware scheme, pre-stage Models ticket template, and document outcome in coordination docs + tracker files.|
|
||||
|FEEDMERGE-COORD-02-903 KISA firmware scheme review|BE-Merge, Models|FEEDMERGE-COORD-02-900|**TODO (due 2025-10-24)** – Pair with KISA team on proposed firmware scheme (`kisa.build` or variant), ensure builder alignment, open Models ticket if required, and log decision in coordination docs + tracker files.|
|
||||
|
||||
## Link-Not-Merge v1 Transition
|
||||
| Task | Owner(s) | Depends on | Notes |
|
||||
|---|---|---|---|
|
||||
|MERGE-LNM-21-001 Migration plan authoring|BE-Merge, Architecture Guild|CONCELIER-LNM-21-101|Draft `no-merge` migration playbook, documenting backfill strategy, feature flag rollout, and rollback steps for legacy merge pipeline deprecation.|
|
||||
|MERGE-LNM-21-002 Merge service deprecation|BE-Merge|MERGE-LNM-21-001|Refactor or retire `AdvisoryMergeService` and related pipelines, ensuring callers transition to observation/linkset APIs; add compile-time analyzer preventing merge service usage.|
|
||||
|MERGE-LNM-21-003 Determinism/test updates|QA Guild, BE-Merge|MERGE-LNM-21-002|Replace merge determinism suites with observation/linkset regression tests verifying no data mutation and conflicts remain visible.|
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
# TASKS
|
||||
| Task | Owner(s) | Depends on | Notes |
|
||||
|---|---|---|---|
|
||||
|MongoBootstrapper to create collections/indexes|BE-Storage|Storage.Mongo|DONE – `MongoBootstrapper` ensures collections & indexes incl. TTL on locks.ttlAt.|
|
||||
|SourceState repository (get/set/backoff)|BE-Conn-Base|Storage.Mongo|DONE – implemented `MongoSourceStateRepository`.|
|
||||
|Document/DTO stores with SHA/metadata|BE-Conn-Base|Storage.Mongo|DONE – DocumentStore and DtoStore provide upsert/status lookups.|
|
||||
|AdvisoryStore (GetAllAsync etc.)|BE-Export|Models|DONE – AdvisoryStore handles upsert + recent/advisory fetches.|
|
||||
|Job store (runs/active/recent)|BE-Core|Storage.Mongo|DONE – `MongoJobStore` covers create/start/complete queries.|
|
||||
|Alias and reference secondary indexes|BE-Storage|Models|DONE – bootstrapper builds alias/reference indexes.|
|
||||
|MergeEvent store|BE-Merge|Models|DONE – MergeEventStore appends/retrieves recent events.|
|
||||
|ExportState store|BE-Export|Exporters|DONE – ExportStateStore upserts and retrieves exporter metadata.|
|
||||
|Performance tests for large advisories|QA|Storage.Mongo|DONE – `AdvisoryStorePerformanceTests` exercises large payload upsert/find throughput budgets.|
|
||||
|Migration playbook for schema/index changes|BE-Storage|Storage.Mongo|DONE – `MongoMigrationRunner` executes `IMongoMigration` steps recorded in `schema_migrations`; see `MIGRATIONS.md`.|
|
||||
|Raw document retention/TTL strategy|BE-Storage|Storage.Mongo|DONE – retention options flow into `RawDocumentRetentionService` and TTL migrations for `document`/GridFS indexes.|
|
||||
|Persist last failure reason in SourceState|BE-Storage|Storage.Mongo|DONE – `MongoSourceStateRepository.MarkFailureAsync` stores `lastFailureReason` with length guard + reset on success.|
|
||||
|AdvisoryStore range primitives deserialization|BE-Storage|Models|DONE – BSON helpers handle `RangePrimitives`; regression test covers SemVer/NEVRA/EVR envelopes persisted through Mongo.|
|
||||
|FEEDSTORAGE-DATA-03-001 Merge event provenance audit prep|BE-Storage|Merge|DONE – merge events now persist field-level decision reasons via `MergeFieldDecision` documents for analytics. **Coordination:** log any new precedence signals to storage@ so indexes/serializers stay aligned.|
|
||||
|FEEDSTORAGE-DATA-02-001 Normalized range dual-write + backfill|BE-Storage|Core|**DONE (2025-10-12)** – `AdvisoryStore` honors `EnableSemVerStyle`, dual-writes normalized docs, and SemVer backfill migration registered for staged rollout.|
|
||||
|FEEDSTORAGE-TESTS-02-004 Restore AdvisoryStore build after normalized versions refactor|QA|Storage.Mongo|DONE – storage tests updated to cover normalized version payloads and new provenance fields. **Heads-up:** QA to watch for fixture bumps touching normalized rule arrays when connectors roll out support.|
|
||||
|FEEDSTORAGE-DATA-02-002 Provenance decision persistence|BE-Storage|Models `FEEDMODELS-SCHEMA-01-002`|**DONE (2025-10-12)** – Normalized documents carry decision reasons/source/timestamps with regression coverage verifying SemVer notes + provenance fallbacks.|
|
||||
|FEEDSTORAGE-DATA-02-003 Normalized versions index creation|BE-Storage|Normalization, Mongo bootstrapper|**DONE (2025-10-12)** – Bootstrapper seeds `normalizedVersions.*` indexes when SemVer style is enabled; docs/tests confirm index presence.|
|
||||
|FEEDSTORAGE-DATA-04-001 Advisory payload parity (description/CWEs/canonical metric)|BE-Storage|Models, Core|DONE (2025-10-15) – Mongo payloads round-trip new advisory fields; serializer/tests updated, no migration required beyond optional backfill.|
|
||||
|FEEDSTORAGE-MONGO-08-001 Causal-consistent session plumbing|BE-Storage|Concelier Core DI|**DONE (2025-10-19)** – Scoped session provider now caches causal-consistent handles per scope, repositories accept optional sessions end-to-end, and new Mongo session consistency tests cover read-your-write + post-stepdown monotonic reads.|
|
||||
|FEEDSTORAGE-DATA-07-001 Advisory statement & conflict collections|Team Normalization & Storage Backbone|FEEDMERGE-ENGINE-07-001|**DONE (2025-10-19)** – Added immutable `advisory_statements`/`advisory_conflicts` collections, bootstrapper + migration ensuring vulnerability/asOf + hash indexes, new stores (`AdvisoryStatementStore`, `AdvisoryConflictStore`), and docs outlining rollback. Tests: `dotnet test src/StellaOps.Concelier.Storage.Mongo.Tests/StellaOps.Concelier.Storage.Mongo.Tests.csproj`.|
|
||||
# TASKS — Epic 1: Aggregation-Only Contract
|
||||
> **AOC Reminder:** storage enforces append-only raw documents; no precedence/severity/normalization in ingestion collections.
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|---|---|---|---|---|
|
||||
| CONCELIER-STORE-AOC-19-001 `advisory_raw schema validator` | TODO | Concelier Storage Guild | Mongo cluster ops sign-off | Author MongoDB JSON schema enforcing required fields (`source`, `upstream`, `content`, `linkset`, `tenant`) and forbidding normalized/severity fields. Include migration toggles for staged rollout. |
|
||||
| CONCELIER-STORE-AOC-19-002 `idempotency unique index` | TODO | Concelier Storage Guild | CONCELIER-STORE-AOC-19-001 | Create compound unique index on `(source.vendor, upstream.upstream_id, upstream.content_hash, tenant)` with backfill script verifying existing data, and document offline validator bootstrap. |
|
||||
| CONCELIER-STORE-AOC-19-003 `append-only supersedes migration` | TODO | Concelier Storage Guild | CONCELIER-STORE-AOC-19-002 | Introduce migration that freezes legacy `advisories` writes, copies data into `_backup_*`, and backfills supersedes pointers for raw revisions. Provide rollback plan. |
|
||||
| CONCELIER-STORE-AOC-19-004 `validator deployment playbook` | TODO | Concelier Storage Guild, DevOps Guild | CONCELIER-STORE-AOC-19-001 | Update `MIGRATIONS.md` and Offline Kit docs to cover enabling validators, rolling restarts, and validator smoke tests for air-gapped installs. |
|
||||
|
||||
## Policy Engine v2
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| CONCELIER-POLICY-20-003 `Selection cursors` | TODO | Concelier Storage Guild | CONCELIER-STORE-AOC-19-002, POLICY-ENGINE-20-003 | Add advisory/vex selection cursors (per policy run) with change stream checkpoints, indexes, and offline migration scripts to support incremental evaluations. |
|
||||
|
||||
## Link-Not-Merge v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| CONCELIER-LNM-21-101 `Observations collections` | TODO | Concelier Storage Guild | CONCELIER-LNM-21-001 | Provision `advisory_observations` and `advisory_linksets` collections with hashed shard keys, TTL for ingest metadata, and required indexes (`aliases`, `purls`, `observation_ids`). |
|
||||
| CONCELIER-LNM-21-102 `Migration tooling` | TODO | Concelier Storage Guild, DevOps Guild | CONCELIER-LNM-21-101 | Backfill legacy merged advisories into observation/linkset collections, create tombstones for merged docs, and supply rollback scripts. |
|
||||
| CONCELIER-LNM-21-103 `Blob/store wiring` | TODO | Concelier Storage Guild | CONCELIER-LNM-21-101 | Store large raw payloads in object storage with pointers from observations; update bootstrapper/offline kit to seed sample blobs. |
|
||||
|
||||
@@ -1,28 +1,86 @@
|
||||
# TASKS
|
||||
| Task | Owner(s) | Depends on | Notes |
|
||||
|---|---|---|---|
|
||||
|FEEDWEB-EVENTS-07-001 Advisory event replay API|Concelier WebService Guild|FEEDCORE-ENGINE-07-001|**DONE (2025-10-19)** – Added `/concelier/advisories/{vulnerabilityKey}/replay` endpoint with optional `asOf`, hex hashes, and conflict payloads; integration covered via `dotnet test src/StellaOps.Concelier.WebService.Tests/StellaOps.Concelier.WebService.Tests.csproj`.|
|
||||
|Bind & validate ConcelierOptions|BE-Base|WebService|DONE – options bound/validated with failure logging.|
|
||||
|Mongo service wiring|BE-Base|Storage.Mongo|DONE – wiring delegated to `AddMongoStorage`.|
|
||||
|Bootstrapper execution on start|BE-Base|Storage.Mongo|DONE – startup calls `MongoBootstrapper.InitializeAsync`.|
|
||||
|Plugin host options finalization|BE-Base|Plugins|DONE – default plugin directories/search patterns configured.|
|
||||
|Jobs API contract tests|QA|Core|DONE – WebServiceEndpointsTests now cover success payloads, filtering, and trigger outcome mapping.|
|
||||
|Health/Ready probes|DevOps|Ops|DONE – `/health` and `/ready` endpoints implemented.|
|
||||
|Serilog + OTEL integration hooks|BE-Base|Observability|DONE – `TelemetryExtensions` wires Serilog + OTEL with configurable exporters.|
|
||||
|Register built-in jobs (sources/exporters)|BE-Base|Core|DONE – AddBuiltInConcelierJobs adds fallback scheduler definitions for core connectors and exporters via reflection.|
|
||||
|HTTP problem details consistency|BE-Base|WebService|DONE – API errors now emit RFC7807 responses with trace identifiers and typed problem categories.|
|
||||
|Request logging and metrics|BE-Base|Observability|DONE – Serilog request logging enabled with enriched context and web.jobs counters published via OpenTelemetry.|
|
||||
|Endpoint smoke tests (health/ready/jobs error paths)|QA|WebService|DONE – WebServiceEndpointsTests assert success and problem responses for health, ready, and job trigger error paths.|
|
||||
|Batch job definition last-run lookup|BE-Base|Core|DONE – definitions endpoint now precomputes kinds array and reuses batched last-run dictionary; manual smoke verified via local GET `/jobs/definitions`.|
|
||||
|Add no-cache headers to health/readiness/jobs APIs|BE-Base|WebService|DONE – helper applies Cache-Control/Pragma/Expires on all health/ready/jobs endpoints; awaiting automated probe tests once connector fixtures stabilize.|
|
||||
|Authority configuration parity (FSR1)|DevEx/Concelier|Authority options schema|**DONE (2025-10-10)** – Options post-config loads clientSecretFile fallback, validators normalize scopes/audiences, and sample config documents issuer/credential/bypass settings.|
|
||||
|Document authority toggle & scope requirements|Docs/Concelier|Authority integration|**DONE (2025-10-21)** – Quickstart now documents staging flag, client credentials, env overrides; operator guide refresh merged. Remaining copy polishing is tracked under `DOCS-CONCELIER-07-201` in `docs/TASKS.md`.|
|
||||
|Plumb Authority client resilience options|BE-Base|Auth libraries LIB5|**DONE (2025-10-12)** – `Program.cs` wires `authority.resilience.*` + client scopes into `AddStellaOpsAuthClient`; new integration test asserts binding and retries.|
|
||||
|Author ops guidance for resilience tuning|Docs/Concelier|Plumb Authority client resilience options|**DONE (2025-10-12)** – `docs/21_INSTALL_GUIDE.md` + `docs/ops/concelier-authority-audit-runbook.md` document resilience profiles for connected vs air-gapped installs and reference monitoring cues.|
|
||||
|Document authority bypass logging patterns|Docs/Concelier|FSR3 logging|**DONE (2025-10-12)** – Updated operator guides clarify `Concelier.Authorization.Audit` fields (route/status/subject/clientId/scopes/bypass/remote) and SIEM triggers.|
|
||||
|Update Concelier operator guide for enforcement cutoff|Docs/Concelier|FSR1 rollout|**DONE (2025-10-12)** – Installation guide emphasises disabling `allowAnonymousFallback` before 2025-12-31 UTC and connects audit signals to the rollout checklist.|
|
||||
|Rename plugin drop directory to namespaced path|BE-Base|Plugins|**DONE (2025-10-19)** – Build outputs now target `StellaOps.Concelier.PluginBinaries`/`StellaOps.Authority.PluginBinaries`, plugin host defaults updated, config/docs refreshed, and `dotnet test src/StellaOps.Concelier.WebService.Tests/StellaOps.Concelier.WebService.Tests.csproj --no-restore` covers the change.|
|
||||
|Authority resilience adoption|Concelier WebService, Docs|Plumb Authority client resilience options|**BLOCKED (2025-10-10)** – Roll out retry/offline knobs to deployment docs and confirm CLI parity once LIB5 lands; unblock after resilience options wired and tested.|
|
||||
|CONCELIER-WEB-08-201 – Mirror distribution endpoints|Concelier WebService Guild|CONCELIER-EXPORT-08-201, DEVOPS-MIRROR-08-001|**DONE (2025-10-20)** – Mirror endpoints now enforce per-domain rate limits, emit cache headers, honour Authority/WWW-Authenticate, and docs cover auth + smoke workflows.|
|
||||
> Remark (2025-10-20): Updated ops runbook with token/rate-limit checks and added API tests for Retry-After + unauthorized flows.|
|
||||
|Wave 0B readiness checkpoint|Team WebService & Authority|Wave 0A completion|BLOCKED (2025-10-19) – FEEDSTORAGE-MONGO-08-001 closed, but remaining Wave 0A items (AUTH-DPOP-11-001, AUTH-MTLS-11-002, PLUGIN-DI-08-001) still open; maintain current DOING workstreams only.|
|
||||
# TASKS — Epic 1: Aggregation-Only Contract
|
||||
> **AOC Reminder:** service links and exposes raw data only—no precedence, severity, or hint computation inside Concelier APIs.
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|---|---|---|---|---|
|
||||
| CONCELIER-WEB-AOC-19-001 `Raw ingestion endpoints` | TODO | Concelier WebService Guild | CONCELIER-CORE-AOC-19-001, CONCELIER-STORE-AOC-19-001 | Implement `POST /ingest/advisory`, `GET /advisories/raw*`, and `POST /aoc/verify` minimal API endpoints. Enforce new Authority scopes, inject tenant claims, and surface `AOCWriteGuard` to repository calls. |
|
||||
| CONCELIER-WEB-AOC-19-002 `AOC observability` | TODO | Concelier WebService Guild, Observability Guild | CONCELIER-WEB-AOC-19-001 | Emit `ingestion_write_total`, `aoc_violation_total`, latency histograms, and tracing spans (`ingest.fetch/transform/write`, `aoc.guard`). Wire structured logging to include tenant, source vendor, upstream id, and content hash. |
|
||||
| CONCELIER-WEB-AOC-19-003 `Schema/guard unit tests` | TODO | QA Guild | CONCELIER-WEB-AOC-19-001 | Add unit tests covering schema validation failures, forbidden field rejections (`ERR_AOC_001/002/006/007`), idempotent upserts, and supersedes chains using deterministic fixtures. |
|
||||
| CONCELIER-WEB-AOC-19-004 `End-to-end ingest verification` | TODO | Concelier WebService Guild, QA Guild | CONCELIER-WEB-AOC-19-003, CONCELIER-CORE-AOC-19-002 | Create integration tests ingesting large advisory batches (cold/warm) validating linkset enrichment, metrics emission, and reproducible outputs. Capture load-test scripts + doc notes for Offline Kit dry runs. |
|
||||
|
||||
## Policy Engine v2
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| CONCELIER-POLICY-20-001 `Policy selection endpoints` | TODO | Concelier WebService Guild | WEB-POLICY-20-001, CONCELIER-CORE-AOC-19-004 | Add batch advisory lookup APIs (`/policy/select/advisories`, `/policy/select/vex`) optimized for PURL/ID lists with pagination, tenant scoping, and explain metadata. |
|
||||
|
||||
## StellaOps Console (Sprint 23)
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| CONCELIER-CONSOLE-23-001 `Advisory aggregation views` | TODO | Concelier WebService Guild, BE-Base Platform Guild | CONCELIER-LNM-21-201, CONCELIER-LNM-21-202 | Expose `/console/advisories` endpoints returning aggregation groups (per linkset) with source chips, severity summaries, and provenance metadata for Console list + dashboard cards. Support filters by source, ecosystem, published/modified window, tenant enforcement. |
|
||||
| CONCELIER-CONSOLE-23-002 `Dashboard deltas API` | TODO | Concelier WebService Guild | CONCELIER-CONSOLE-23-001, CONCELIER-LNM-21-203 | Provide aggregated advisory delta counts (new, modified, conflicting) for Console dashboard + live status ticker; emit structured events for queue lag metrics. Ensure deterministic counts across repeated queries. |
|
||||
| CONCELIER-CONSOLE-23-003 `Search fan-out helpers` | TODO | Concelier WebService Guild | CONCELIER-CONSOLE-23-001 | Deliver fast lookup endpoints for CVE/GHSA/purl search (linksets, observations) returning evidence fragments for Console global search; implement caching + scope guards. |
|
||||
|
||||
## Graph Explorer v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| CONCELIER-GRAPH-21-003 `SBOM projection API` | TODO | Concelier WebService Guild, Cartographer Guild | CONCELIER-GRAPH-21-001 | Expose normalized SBOM projection endpoint (`/sboms/{id}/projections/graph`) with pagination, tenant guard, and versioning metadata for Cartographer builds. |
|
||||
| CONCELIER-GRAPH-21-004 `Entry point registry` | TODO | Concelier WebService Guild | CONCELIER-GRAPH-21-003, SBOM-SERVICE-21-001 | Provide entrypoint/service node lookup API for Cartographer path relevance (configurable overrides, tagging) and document contract. |
|
||||
|
||||
## Link-Not-Merge v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| CONCELIER-LNM-21-201 `Observation APIs` | TODO | Concelier WebService Guild, BE-Base Platform Guild | CONCELIER-LNM-21-001 | Add REST endpoints for advisory observations (`GET /advisories/observations`) with filters (alias, purl, source), pagination, and tenancy enforcement. |
|
||||
| CONCELIER-LNM-21-202 `Linkset APIs` | TODO | Concelier WebService Guild | CONCELIER-LNM-21-002, CONCELIER-LNM-21-003 | Implement linkset read/export endpoints (`/advisories/linksets/{id}`, `/advisories/by-purl/{purl}`, `/advisories/linksets/{id}/export`, `/evidence`) with correlation/conflict payloads and `ERR_AGG_*` mapping. |
|
||||
| CONCELIER-LNM-21-203 `Ingest events` | TODO | Concelier WebService Guild, Platform Events Guild | CONCELIER-LNM-21-005 | Publish NATS/Redis events for new observations/linksets and ensure idempotent consumer contracts; document event schemas. |
|
||||
|
||||
## Graph & Vuln Explorer v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| CONCELIER-GRAPH-24-101 `Advisory summary API` | TODO | Concelier WebService Guild | CONCELIER-GRAPH-24-001 | Expose `/advisories/summary` returning raw linkset/observation metadata for overlay services; no derived severity or fix hints. |
|
||||
| CONCELIER-GRAPH-24-102 `Evidence batch API` | TODO | Concelier WebService Guild | CONCELIER-LNM-21-201 | Add batch fetch for advisory observations/linksets keyed by component sets to feed Graph overlay tooltips efficiently. |
|
||||
|
||||
## Vulnerability Explorer (Sprint 29)
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| CONCELIER-VULN-29-001 `Advisory key normalization` | TODO | Concelier WebService Guild, Data Integrity Guild | CONCELIER-LNM-21-001 | Normalize advisory identifiers (CVE/GHSA/vendor) into canonical `advisory_key`, persist `links[]`, expose raw payload snapshots for Explorer evidence tabs. Include migration/backfill scripts. |
|
||||
| CONCELIER-VULN-29-002 `Evidence retrieval API` | TODO | Concelier WebService Guild | CONCELIER-VULN-29-001, VULN-API-29-003 | Provide `/vuln/evidence/advisories/{advisory_key}` returning raw advisory docs with provenance, filtering by tenant and source. |
|
||||
| CONCELIER-VULN-29-004 `Observability enhancements` | TODO | Concelier WebService Guild, Observability Guild | CONCELIER-VULN-29-001 | Instrument metrics/logs for advisory normalization (key collisions, withdrawn flags), emit events consumed by Vuln Explorer resolver. |
|
||||
|
||||
## Advisory AI (Sprint 31)
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| CONCELIER-AIAI-31-001 `Paragraph anchors` | TODO | Concelier WebService Guild | CONCELIER-VULN-29-001 | Expose advisory chunk API returning paragraph anchors, section metadata, and token-safe text for Advisory AI retrieval. |
|
||||
| CONCELIER-AIAI-31-002 `Structured fields` | TODO | Concelier WebService Guild | CONCELIER-AIAI-31-001 | Ensure normalized advisories expose workaround/fix/CVSS fields via API; add caching for summary queries. |
|
||||
| CONCELIER-AIAI-31-003 `Advisory AI telemetry` | TODO | Concelier WebService Guild, Observability Guild | CONCELIER-AIAI-31-001 | Emit metrics/logs for chunk requests, cache hits, and guardrail blocks triggered by advisory payloads. |
|
||||
|
||||
## Observability & Forensics (Epic 15)
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| CONCELIER-WEB-OBS-50-001 `Telemetry adoption` | TODO | Concelier WebService Guild | TELEMETRY-OBS-50-001, CONCELIER-OBS-50-001 | Adopt telemetry core in web service host, ensure ingest + read endpoints emit trace/log fields (`tenant_id`, `route`, `decision_effect`), and add correlation IDs to responses. |
|
||||
| CONCELIER-WEB-OBS-51-001 `Observability APIs` | TODO | Concelier WebService Guild | CONCELIER-WEB-OBS-50-001, WEB-OBS-51-001 | Surface ingest health metrics, queue depth, and SLO status via `/obs/concelier/health` endpoint for Console widgets, with caching and tenant partitioning. |
|
||||
| CONCELIER-WEB-OBS-52-001 `Timeline streaming` | TODO | Concelier WebService Guild | CONCELIER-WEB-OBS-50-001, TIMELINE-OBS-52-003 | Provide SSE stream `/obs/concelier/timeline` bridging to Timeline Indexer with paging tokens, guardrails, and audit logging. |
|
||||
| CONCELIER-WEB-OBS-53-001 `Evidence locker integration` | TODO | Concelier WebService Guild, Evidence Locker Guild | CONCELIER-OBS-53-001, EVID-OBS-53-003 | Add `/evidence/advisories/*` routes invoking evidence locker snapshots, verifying tenant scopes (`evidence:read`), and returning signed manifest metadata. |
|
||||
| CONCELIER-WEB-OBS-54-001 `Attestation exposure` | TODO | Concelier WebService Guild | CONCELIER-OBS-54-001, PROV-OBS-54-001 | Provide `/attestations/advisories/*` read APIs surfacing DSSE status, verification summary, and provenance chain for Console/CLI. |
|
||||
| CONCELIER-WEB-OBS-55-001 `Incident mode toggles` | TODO | Concelier WebService Guild, DevOps Guild | CONCELIER-OBS-55-001, WEB-OBS-55-001 | Implement incident mode toggle endpoints, propagate to orchestrator/locker, and document cooldown/backoff semantics. |
|
||||
|
||||
## Air-Gapped Mode (Epic 16)
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| CONCELIER-WEB-AIRGAP-56-001 `Mirror import APIs` | TODO | Concelier WebService Guild | AIRGAP-IMP-58-001, CONCELIER-AIRGAP-56-001 | Extend ingestion endpoints to register mirror bundle sources, expose bundle catalog queries, and block external feed URLs in sealed mode. |
|
||||
| CONCELIER-WEB-AIRGAP-56-002 `Airgap status surfaces` | TODO | Concelier WebService Guild | CONCELIER-AIRGAP-57-002, AIRGAP-CTL-56-002 | Add staleness metadata and bundle provenance to advisory APIs (`/advisories/observations`, `/advisories/linksets`). |
|
||||
| CONCELIER-WEB-AIRGAP-57-001 `Error remediation` | TODO | Concelier WebService Guild, AirGap Policy Guild | AIRGAP-POL-56-001 | Map sealed-mode violations to `AIRGAP_EGRESS_BLOCKED` responses with user guidance. |
|
||||
| CONCELIER-WEB-AIRGAP-58-001 `Import timeline emission` | TODO | Concelier WebService Guild, AirGap Importer Guild | CONCELIER-WEB-AIRGAP-56-001, TIMELINE-OBS-53-001 | Emit timeline events for bundle ingestion operations with bundle ID, scope, and actor metadata. |
|
||||
|
||||
## SDKs & OpenAPI (Epic 17)
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| CONCELIER-WEB-OAS-61-001 `/.well-known/openapi` | TODO | Concelier WebService Guild | OAS-61-001 | Implement discovery endpoint emitting Concelier spec with version metadata and ETag. |
|
||||
| CONCELIER-WEB-OAS-61-002 `Error envelope migration` | TODO | Concelier WebService Guild | APIGOV-61-001 | Ensure all API responses use standardized error envelope; update controllers/tests. |
|
||||
| CONCELIER-WEB-OAS-62-001 `Examples expansion` | TODO | Concelier WebService Guild | CONCELIER-OAS-61-002 | Add curated examples for advisory observations/linksets/conflicts; integrate into dev portal. |
|
||||
| CONCELIER-WEB-OAS-63-001 `Deprecation headers` | TODO | Concelier WebService Guild, API Governance Guild | APIGOV-63-001 | Add Sunset/Deprecation headers for retiring endpoints and update documentation/notifications. |
|
||||
|
||||
14
src/StellaOps.Cryptography.Kms/AGENTS.md
Normal file
14
src/StellaOps.Cryptography.Kms/AGENTS.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# KMS & Key Management Guild Charter
|
||||
|
||||
## Mission
|
||||
Provide key management abstractions and drivers (file, cloud KMS, HSM, FIDO2) for signing and verification workflows.
|
||||
|
||||
## Scope
|
||||
- Key store interfaces, secure configuration loading, and audit logging.
|
||||
- Drivers for file-based development keys, cloud KMS providers, PKCS#11 HSMs, and FIDO2 devices.
|
||||
- Key rotation, revocation, and attestation for keys used in signing.
|
||||
|
||||
## Definition of Done
|
||||
- KMS API supports signing, verification, key metadata, rotation, and revocation.
|
||||
- Drivers pass integration tests and security review.
|
||||
- CLI/Console can manage keys using these abstractions.
|
||||
13
src/StellaOps.Cryptography.Kms/TASKS.md
Normal file
13
src/StellaOps.Cryptography.Kms/TASKS.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# KMS Task Board — Epic 19: Attestor Console
|
||||
|
||||
## Sprint 72 – Abstractions & File Driver
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| KMS-72-001 | TODO | KMS Guild | — | Implement KMS interface (sign, verify, metadata, rotate, revoke) and file-based key driver with encrypted at-rest storage. | Interface + file driver operational; unit tests cover sign/verify/rotation; lint passes. |
|
||||
| KMS-72-002 | TODO | KMS Guild | KMS-72-001 | Add CLI support for importing/exporting file-based keys with password protection. | CLI commands functional; docs updated; integration tests pass. |
|
||||
|
||||
## Sprint 73 – Cloud & HSM Integration
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| KMS-73-001 | TODO | KMS Guild | KMS-72-001 | Add cloud KMS driver (e.g., AWS KMS, GCP KMS) with signing and key metadata retrieval. | Cloud driver tested with mock; configuration documented; security review sign-off. |
|
||||
| KMS-73-002 | TODO | KMS Guild | KMS-72-001 | Implement PKCS#11/HSM driver plus FIDO2 signing support for high assurance workflows. | HSM/FIDO2 drivers tested with hardware stubs; error handling documented. |
|
||||
15
src/StellaOps.DevPortal.Site/AGENTS.md
Normal file
15
src/StellaOps.DevPortal.Site/AGENTS.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Developer Portal Guild Charter
|
||||
|
||||
## Mission
|
||||
Deliver the StellaOps developer portal with interactive API reference, SDK documentation, runnable examples, and offline export capability.
|
||||
|
||||
## Scope
|
||||
- Static site generator integrating OpenAPI specs, code examples, and SDK docs.
|
||||
- Search, schema diagrams, try-it console (non-prod), copy-curl snippets.
|
||||
- Version selector for API major versions and changelog integration.
|
||||
- Offline bundle build compatible with air-gapped environments.
|
||||
|
||||
## Definition of Done
|
||||
- Portal rebuilds deterministically from specs/examples; CI publishes artifacts.
|
||||
- Search, schema visuals, examples verified via automated tests.
|
||||
- Offline bundle renders without external dependencies.
|
||||
19
src/StellaOps.DevPortal.Site/TASKS.md
Normal file
19
src/StellaOps.DevPortal.Site/TASKS.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Developer Portal Task Board — Epic 17: SDKs & OpenAPI Docs
|
||||
|
||||
## Sprint 62 – Static Generator Foundations
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| DEVPORT-62-001 | TODO | Developer Portal Guild | OAS-61-002 | Select static site generator, integrate aggregate spec, build navigation + search scaffolding. | Portal builds locally; nav/search operational; CI pipeline in place. |
|
||||
| DEVPORT-62-002 | TODO | Developer Portal Guild | DEVPORT-62-001 | Implement schema viewer, example rendering, copy-curl snippets, and version selector UI. | Schema diagrams render; examples tested; version selector toggles spec; accessibility check passes. |
|
||||
|
||||
## Sprint 63 – Try-It & Integration
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| DEVPORT-63-001 | TODO | Developer Portal Guild, Platform Guild | DEVPORT-62-002 | Add Try-It console pointing at sandbox environment with token onboarding and scope info. | Try-It executes against sandbox; safeguards enforce read-only; telemetry recorded. |
|
||||
| DEVPORT-63-002 | TODO | Developer Portal Guild, SDK Generator Guild | DEVPORT-62-002, SDKGEN-63-001..4 | Embed language-specific SDK snippets and quick starts generated from tested examples. | Snippets pulled from CI-verified examples; portal tests ensure freshness. |
|
||||
|
||||
## Sprint 64 – Offline Bundle & QA
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| DEVPORT-64-001 | TODO | Developer Portal Guild, Export Center Guild | DEVPORT-63-001, SDKREL-64-002 | Provide offline build target bundling HTML, specs, SDK archives; ensure no external assets. | Offline bundle verified in sealed environment; docs updated. |
|
||||
| DEVPORT-64-002 | TODO | Developer Portal Guild | DEVPORT-63-001 | Add automated accessibility tests, link checker, and performance budgets. | CI checks added; budgets enforced; reports archived. |
|
||||
28
src/StellaOps.EvidenceLocker/AGENTS.md
Normal file
28
src/StellaOps.EvidenceLocker/AGENTS.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Evidence Locker Service — Agent Charter
|
||||
|
||||
## Mission
|
||||
Implement the append-only, tenant-scoped evidence locker detailed in Epic 15. Produce immutable evidence bundles, manage legal holds, and expose verification APIs for Console and CLI consumers under the imposed rule.
|
||||
|
||||
## Responsibilities
|
||||
- Define object store layout, metadata DB schemas, and retention policies.
|
||||
- Build bundle assembly pipelines (evaluation, job, export) with Merkle manifests and DSSE signing.
|
||||
- Provide verification, download, and legal hold APIs with audit trails.
|
||||
- Integrate with Timeline Indexer, Exporter, Orchestrator, Policy Engine, Concelier, and Excitator for provenance linking.
|
||||
|
||||
## Coordination
|
||||
- Work with Provenance Guild for signature tooling.
|
||||
- Partner with DevOps Guild on storage backends and WORM options.
|
||||
- Align with Security Guild on redaction and access enforcement.
|
||||
|
||||
## Definition of Done
|
||||
- Deterministic bundle generation proven via integration tests.
|
||||
- Object store interactions tested in offline mode.
|
||||
- Runbooks in `/docs/forensics/evidence-locker.md` updated per release.
|
||||
|
||||
## Module Layout
|
||||
- `StellaOps.EvidenceLocker.Core/` — domain models, bundle contracts, deterministic hashing helpers.
|
||||
- `StellaOps.EvidenceLocker.Infrastructure/` — storage abstractions, persistence plumbing, and external integrations.
|
||||
- `StellaOps.EvidenceLocker.WebService/` — HTTP entry points (minimal API host, OpenAPI, auth).
|
||||
- `StellaOps.EvidenceLocker.Worker/` — background assembly/verification pipelines.
|
||||
- `StellaOps.EvidenceLocker.Tests/` — unit tests (xUnit) for core/infrastructure components.
|
||||
- `StellaOps.EvidenceLocker.sln` — solution aggregating the module projects.
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace StellaOps.EvidenceLocker.Core;
|
||||
|
||||
public class Class1
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" ?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace StellaOps.EvidenceLocker.Infrastructure;
|
||||
|
||||
public class Class1
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" ?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
|
||||
<ProjectReference Include="..\StellaOps.EvidenceLocker.Core\StellaOps.EvidenceLocker.Core.csproj"/>
|
||||
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,135 @@
|
||||
<?xml version="1.0" ?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
|
||||
|
||||
|
||||
<OutputType>Exe</OutputType>
|
||||
|
||||
|
||||
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
|
||||
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
|
||||
<UseConcelierTestInfra>false</UseConcelierTestInfra>
|
||||
|
||||
|
||||
<LangVersion>preview</LangVersion>
|
||||
|
||||
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
|
||||
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
|
||||
|
||||
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1"/>
|
||||
|
||||
|
||||
|
||||
|
||||
<PackageReference Include="xunit.v3" Version="3.0.0"/>
|
||||
|
||||
|
||||
|
||||
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.3"/>
|
||||
|
||||
|
||||
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
|
||||
|
||||
|
||||
<Content Include="xunit.runner.json" CopyToOutputDirectory="PreserveNewest"/>
|
||||
|
||||
|
||||
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
|
||||
|
||||
|
||||
<Using Include="Xunit"/>
|
||||
|
||||
|
||||
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
|
||||
|
||||
|
||||
<ProjectReference Include="..\StellaOps.EvidenceLocker.Core\StellaOps.EvidenceLocker.Core.csproj"/>
|
||||
|
||||
|
||||
|
||||
|
||||
<ProjectReference Include="..\StellaOps.EvidenceLocker.Infrastructure\StellaOps.EvidenceLocker.Infrastructure.csproj"/>
|
||||
|
||||
|
||||
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace StellaOps.EvidenceLocker.Tests;
|
||||
|
||||
public class UnitTest1
|
||||
{
|
||||
[Fact]
|
||||
public void Test1()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"$schema": "https://xunit.net/schema/current/xunit.runner.schema.json"
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Add services to the container.
|
||||
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
|
||||
builder.Services.AddOpenApi();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.MapOpenApi();
|
||||
}
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
var summaries = new[]
|
||||
{
|
||||
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
|
||||
};
|
||||
|
||||
app.MapGet("/weatherforecast", () =>
|
||||
{
|
||||
var forecast = Enumerable.Range(1, 5).Select(index =>
|
||||
new WeatherForecast
|
||||
(
|
||||
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
|
||||
Random.Shared.Next(-20, 55),
|
||||
summaries[Random.Shared.Next(summaries.Length)]
|
||||
))
|
||||
.ToArray();
|
||||
return forecast;
|
||||
})
|
||||
.WithName("GetWeatherForecast");
|
||||
|
||||
app.Run();
|
||||
|
||||
record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
|
||||
{
|
||||
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": false,
|
||||
"applicationUrl": "http://localhost:5115",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": false,
|
||||
"applicationUrl": "https://localhost:7010;http://localhost:5115",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" ?>
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.0-rc.1.25451.107"/>
|
||||
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
|
||||
<ProjectReference Include="..\StellaOps.EvidenceLocker.Core\StellaOps.EvidenceLocker.Core.csproj"/>
|
||||
|
||||
|
||||
<ProjectReference Include="..\StellaOps.EvidenceLocker.Infrastructure\StellaOps.EvidenceLocker.Infrastructure.csproj"/>
|
||||
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,6 @@
|
||||
@StellaOps.EvidenceLocker.WebService_HostAddress = http://localhost:5115
|
||||
|
||||
GET {{StellaOps.EvidenceLocker.WebService_HostAddress}}/weatherforecast/
|
||||
Accept: application/json
|
||||
|
||||
###
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
using StellaOps.EvidenceLocker.Worker;
|
||||
|
||||
var builder = Host.CreateApplicationBuilder(args);
|
||||
builder.Services.AddHostedService<Worker>();
|
||||
|
||||
var host = builder.Build();
|
||||
host.Run();
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"profiles": {
|
||||
"StellaOps.EvidenceLocker.Worker": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"environmentVariables": {
|
||||
"DOTNET_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" ?>
|
||||
<Project Sdk="Microsoft.NET.Sdk.Worker">
|
||||
|
||||
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
|
||||
<UserSecretsId>dotnet-StellaOps.EvidenceLocker.Worker-c74bd053-c14b-412b-a177-12e15fdbe207</UserSecretsId>
|
||||
|
||||
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.0-rc.1.25451.107"/>
|
||||
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
|
||||
<ProjectReference Include="..\StellaOps.EvidenceLocker.Core\StellaOps.EvidenceLocker.Core.csproj"/>
|
||||
|
||||
|
||||
<ProjectReference Include="..\StellaOps.EvidenceLocker.Infrastructure\StellaOps.EvidenceLocker.Infrastructure.csproj"/>
|
||||
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace StellaOps.EvidenceLocker.Worker;
|
||||
|
||||
public class Worker(ILogger<Worker> logger) : BackgroundService
|
||||
{
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
if (logger.IsEnabled(LogLevel.Information))
|
||||
{
|
||||
logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
|
||||
}
|
||||
await Task.Delay(1000, stoppingToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
}
|
||||
}
|
||||
90
src/StellaOps.EvidenceLocker/StellaOps.EvidenceLocker.sln
Normal file
90
src/StellaOps.EvidenceLocker/StellaOps.EvidenceLocker.sln
Normal file
@@ -0,0 +1,90 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31903.59
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.EvidenceLocker.Core", "StellaOps.EvidenceLocker.Core\StellaOps.EvidenceLocker.Core.csproj", "{217D54F6-D07F-4B1E-8598-7DCAF0BD65C7}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.EvidenceLocker.Infrastructure", "StellaOps.EvidenceLocker.Infrastructure\StellaOps.EvidenceLocker.Infrastructure.csproj", "{BF61F2F5-4ECA-4DA6-AC6B-102C39D225A1}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.EvidenceLocker.WebService", "StellaOps.EvidenceLocker.WebService\StellaOps.EvidenceLocker.WebService.csproj", "{392D1580-C75B-4CB2-8F26-45C65268A191}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.EvidenceLocker.Worker", "StellaOps.EvidenceLocker.Worker\StellaOps.EvidenceLocker.Worker.csproj", "{B384F421-48D0-48EB-A63F-0AF28EBC75EB}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.EvidenceLocker.Tests", "StellaOps.EvidenceLocker.Tests\StellaOps.EvidenceLocker.Tests.csproj", "{B9D6DCF2-1C6F-41E5-8D63-118BD0751839}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{217D54F6-D07F-4B1E-8598-7DCAF0BD65C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{217D54F6-D07F-4B1E-8598-7DCAF0BD65C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{217D54F6-D07F-4B1E-8598-7DCAF0BD65C7}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{217D54F6-D07F-4B1E-8598-7DCAF0BD65C7}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{217D54F6-D07F-4B1E-8598-7DCAF0BD65C7}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{217D54F6-D07F-4B1E-8598-7DCAF0BD65C7}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{217D54F6-D07F-4B1E-8598-7DCAF0BD65C7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{217D54F6-D07F-4B1E-8598-7DCAF0BD65C7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{217D54F6-D07F-4B1E-8598-7DCAF0BD65C7}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{217D54F6-D07F-4B1E-8598-7DCAF0BD65C7}.Release|x64.Build.0 = Release|Any CPU
|
||||
{217D54F6-D07F-4B1E-8598-7DCAF0BD65C7}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{217D54F6-D07F-4B1E-8598-7DCAF0BD65C7}.Release|x86.Build.0 = Release|Any CPU
|
||||
{BF61F2F5-4ECA-4DA6-AC6B-102C39D225A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BF61F2F5-4ECA-4DA6-AC6B-102C39D225A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BF61F2F5-4ECA-4DA6-AC6B-102C39D225A1}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{BF61F2F5-4ECA-4DA6-AC6B-102C39D225A1}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{BF61F2F5-4ECA-4DA6-AC6B-102C39D225A1}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{BF61F2F5-4ECA-4DA6-AC6B-102C39D225A1}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{BF61F2F5-4ECA-4DA6-AC6B-102C39D225A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BF61F2F5-4ECA-4DA6-AC6B-102C39D225A1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BF61F2F5-4ECA-4DA6-AC6B-102C39D225A1}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{BF61F2F5-4ECA-4DA6-AC6B-102C39D225A1}.Release|x64.Build.0 = Release|Any CPU
|
||||
{BF61F2F5-4ECA-4DA6-AC6B-102C39D225A1}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{BF61F2F5-4ECA-4DA6-AC6B-102C39D225A1}.Release|x86.Build.0 = Release|Any CPU
|
||||
{392D1580-C75B-4CB2-8F26-45C65268A191}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{392D1580-C75B-4CB2-8F26-45C65268A191}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{392D1580-C75B-4CB2-8F26-45C65268A191}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{392D1580-C75B-4CB2-8F26-45C65268A191}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{392D1580-C75B-4CB2-8F26-45C65268A191}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{392D1580-C75B-4CB2-8F26-45C65268A191}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{392D1580-C75B-4CB2-8F26-45C65268A191}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{392D1580-C75B-4CB2-8F26-45C65268A191}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{392D1580-C75B-4CB2-8F26-45C65268A191}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{392D1580-C75B-4CB2-8F26-45C65268A191}.Release|x64.Build.0 = Release|Any CPU
|
||||
{392D1580-C75B-4CB2-8F26-45C65268A191}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{392D1580-C75B-4CB2-8F26-45C65268A191}.Release|x86.Build.0 = Release|Any CPU
|
||||
{B384F421-48D0-48EB-A63F-0AF28EBC75EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B384F421-48D0-48EB-A63F-0AF28EBC75EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B384F421-48D0-48EB-A63F-0AF28EBC75EB}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B384F421-48D0-48EB-A63F-0AF28EBC75EB}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B384F421-48D0-48EB-A63F-0AF28EBC75EB}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B384F421-48D0-48EB-A63F-0AF28EBC75EB}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B384F421-48D0-48EB-A63F-0AF28EBC75EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B384F421-48D0-48EB-A63F-0AF28EBC75EB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B384F421-48D0-48EB-A63F-0AF28EBC75EB}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B384F421-48D0-48EB-A63F-0AF28EBC75EB}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B384F421-48D0-48EB-A63F-0AF28EBC75EB}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B384F421-48D0-48EB-A63F-0AF28EBC75EB}.Release|x86.Build.0 = Release|Any CPU
|
||||
{B9D6DCF2-1C6F-41E5-8D63-118BD0751839}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B9D6DCF2-1C6F-41E5-8D63-118BD0751839}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B9D6DCF2-1C6F-41E5-8D63-118BD0751839}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B9D6DCF2-1C6F-41E5-8D63-118BD0751839}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B9D6DCF2-1C6F-41E5-8D63-118BD0751839}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B9D6DCF2-1C6F-41E5-8D63-118BD0751839}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B9D6DCF2-1C6F-41E5-8D63-118BD0751839}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B9D6DCF2-1C6F-41E5-8D63-118BD0751839}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B9D6DCF2-1C6F-41E5-8D63-118BD0751839}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B9D6DCF2-1C6F-41E5-8D63-118BD0751839}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B9D6DCF2-1C6F-41E5-8D63-118BD0751839}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B9D6DCF2-1C6F-41E5-8D63-118BD0751839}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
19
src/StellaOps.EvidenceLocker/TASKS.md
Normal file
19
src/StellaOps.EvidenceLocker/TASKS.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Evidence Locker Task Board — Epic 15: Observability & Forensics
|
||||
|
||||
## Sprint 53 – Evidence Bundle Foundations
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| EVID-OBS-53-001 | TODO | Evidence Locker Guild | TELEMETRY-OBS-50-001, DEVOPS-OBS-50-003 | Bootstrap `StellaOps.Evidence.Locker` service with Postgres schema for `evidence_bundles`, `evidence_artifacts`, `evidence_holds`, tenant RLS, and object-store abstraction (WORM optional). | Service builds/tests; migrations deterministic; storage abstraction has local filesystem + S3 drivers; compliance checklist recorded. |
|
||||
| EVID-OBS-53-002 | TODO | Evidence Locker Guild, Orchestrator Guild | EVID-OBS-53-001, ORCH-OBS-53-001 | Implement bundle builders for evaluation/job/export snapshots collecting inputs, outputs, env digests, run metadata. Generate Merkle tree + manifest skeletons and persist root hash. | Builders cover three bundle types; integration tests verify deterministic manifests; root hash stored; docs stubbed. |
|
||||
| EVID-OBS-53-003 | TODO | Evidence Locker Guild, Security Guild | EVID-OBS-53-002 | Expose REST APIs (`POST /evidence/snapshot`, `GET /evidence/:id`, `POST /evidence/verify`, `POST /evidence/hold/:case_id`) with audit logging, tenant enforcement, and size quotas. | APIs documented via OpenAPI; tests cover RBAC/legal hold; size quota rejection returns structured error; audit logs validated. |
|
||||
|
||||
## Sprint 54 – Provenance Integration
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| EVID-OBS-54-001 | TODO | Evidence Locker Guild, Provenance Guild | EVID-OBS-53-003, PROV-OBS-53-002 | Attach DSSE signing and RFC3161 timestamping to bundle manifests; validate against Provenance verification library. Wire legal hold retention extension and chain-of-custody events for Timeline Indexer. | Bundles signed; verification tests pass; timeline events emitted; timestamp optional but documented; retention updates recorded. |
|
||||
| EVID-OBS-54-002 | TODO | Evidence Locker Guild, DevEx/CLI Guild | EVID-OBS-54-001, CLI-FORENSICS-54-001 | Provide bundle download/export packaging (tgz) with checksum manifest, offline verification instructions, and sample fixture for CLI tests. | Packaging script deterministic; CLI verifies sample; offline instructions documented; checksum cross-check done. |
|
||||
|
||||
## Sprint 55 – Incident Mode & Retention
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| EVID-OBS-55-001 | TODO | Evidence Locker Guild, DevOps Guild | EVID-OBS-54-001, DEVOPS-OBS-55-001 | Implement incident mode hooks increasing retention window, capturing additional debug artefacts, and emitting activation/deactivation events to Timeline Indexer + Notifier. | Incident mode extends retention per config; activation events emitted; tests cover revert to baseline; runbook updated. |
|
||||
@@ -1,9 +1,96 @@
|
||||
If you are working on this file you need to read docs/ARCHITECTURE_EXCITITOR.md and ./AGENTS.md).
|
||||
# TASKS
|
||||
| Task | Owner(s) | Depends on | Notes |
|
||||
|---|---|---|---|
|
||||
|EXCITITOR-CORE-01-001 – Canonical VEX domain records|Team Excititor Core & Policy|docs/ARCHITECTURE_EXCITITOR.md|DONE (2025-10-15) – Introduced `VexClaim`, `VexConsensus`, provider metadata, export manifest records, and deterministic JSON serialization with tests covering canonical ordering and query signatures.|
|
||||
|EXCITITOR-CORE-01-002 – Trust-weighted consensus resolver|Team Excititor Core & Policy|EXCITITOR-CORE-01-001|DONE (2025-10-15) – Added consensus resolver, baseline policy (tier weights + justification gate), telemetry output, and tests covering acceptance, conflict ties, and determinism.|
|
||||
|EXCITITOR-CORE-01-003 – Shared contracts & query signatures|Team Excititor Core & Policy|EXCITITOR-CORE-01-001|DONE (2025-10-15) – Published connector/normalizer/exporter/attestation abstractions and expanded deterministic `VexQuerySignature`/hash utilities with test coverage.|
|
||||
|EXCITITOR-CORE-02-001 – Context signal schema prep|Team Excititor Core & Policy|EXCITITOR-POLICY-02-001|DONE (2025-10-19) – Added `VexSignalSnapshot` (severity/KEV/EPSS) to claims/consensus, updated canonical serializer + resolver plumbing, documented storage follow-up, and validated via `dotnet test src/StellaOps.Excititor.Core.Tests/StellaOps.Excititor.Core.Tests.csproj`.|
|
||||
|EXCITITOR-CORE-02-002 – Deterministic risk scoring engine|Team Excititor Core & Policy|EXCITITOR-CORE-02-001, EXCITITOR-POLICY-02-001|BACKLOG – Introduce the scoring calculator invoked by consensus, persist score envelopes with audit trails, and add regression fixtures covering gate/boost behaviour before enabling exports.|
|
||||
# TASKS — Epic 1: Aggregation-Only Contract
|
||||
> **AOC Reminder:** ingestion captures raw VEX statements/linksets only—no precedence, suppression, or severity derivation within Excititor.
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|---|---|---|---|---|
|
||||
| EXCITITOR-CORE-AOC-19-001 `AOC guard & provenance enforcement` | TODO | Excititor Core Guild | WEB-AOC-19-001 | Introduce repository interceptor validating provenance/signatures, rejecting forbidden fields (`severity`, `consensus`, etc.), and surfacing `ERR_AOC_00x` codes. |
|
||||
| EXCITITOR-CORE-AOC-19-002 `VEX linkset extraction` | TODO | Excititor Core Guild | EXCITITOR-CORE-AOC-19-001 | Implement deterministic extraction of advisory IDs, component PURLs, and references into `linkset`, capturing reconciled-from metadata for traceability. |
|
||||
| EXCITITOR-CORE-AOC-19-003 `Idempotent VEX raw upsert` | TODO | Excititor Core Guild | EXCITITOR-STORE-AOC-19-002 | Enforce `(vendor, upstreamId, contentHash, tenant)` uniqueness, generate supersedes chains, and ensure append-only versioning of raw VEX documents. |
|
||||
| EXCITITOR-CORE-AOC-19-004 `Remove ingestion consensus` | TODO | Excititor Core Guild | EXCITITOR-CORE-AOC-19-002, POLICY-AOC-19-003 | Excise consensus/merge/severity logic from Excititor ingestion paths, updating exports/tests to rely on Policy Engine materializations instead. |
|
||||
|
||||
## Policy Engine v2
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-POLICY-20-002 `Scope-aware linksets` | TODO | Excititor Core Guild, Policy Guild | EXCITITOR-CORE-AOC-19-002, POLICY-ENGINE-20-001 | Enhance VEX linkset extraction with scope resolution (product/component) + version range matching to boost policy join accuracy; refresh fixtures/tests. |
|
||||
|
||||
## Graph Explorer v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-GRAPH-21-001 `Inspector linkouts` | TODO | Excititor Core Guild, Cartographer Guild | EXCITITOR-POLICY-20-002, CARTO-GRAPH-21-005 | Provide batched VEX/advisory reference fetches keyed by graph node PURLs so UI inspector can display raw documents and justification metadata. |
|
||||
| EXCITITOR-GRAPH-21-002 `Overlay enrichment` | TODO | Excititor Core Guild | EXCITITOR-GRAPH-21-001, POLICY-ENGINE-30-001 | Ensure overlay metadata includes VEX justification summaries and document versions for Cartographer overlays; update fixtures/tests. |
|
||||
|
||||
## Link-Not-Merge v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-LNM-21-001 `VEX observation model` | TODO | Excititor Core Guild | EXCITITOR-CORE-AOC-19-001 | Define immutable `vex_observations` schema capturing raw statements, product PURLs, justification, and AOC metadata. |
|
||||
| EXCITITOR-LNM-21-002 `Linkset correlator` | TODO | Excititor Core Guild | EXCITITOR-LNM-21-001 | Build correlation pipeline combining alias + product PURL signals to form `vex_linksets` with confidence metrics. |
|
||||
| EXCITITOR-LNM-21-003 `Conflict annotator` | TODO | Excititor Core Guild | EXCITITOR-LNM-21-002 | Record status/justification disagreements within linksets and expose structured conflicts. |
|
||||
| EXCITITOR-LNM-21-004 `Merge removal` | TODO | Excititor Core Guild | EXCITITOR-LNM-21-002 | Remove legacy VEX merge logic, enforce immutability, and add guards/tests to prevent future merges. |
|
||||
| EXCITITOR-LNM-21-005 `Event emission` | TODO | Excititor Core Guild, Platform Events Guild | EXCITITOR-LNM-21-002 | Emit `vex.linkset.updated` events for downstream consumers with delta descriptions and tenant context. |
|
||||
|
||||
## Policy Engine + Editor v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-POLICY-23-001 `Evidence indexes` | TODO | Excititor Core Guild | EXCITITOR-LNM-21-002 | Provide indexes/materialized views for policy runtime (status, justification, product PURL) to accelerate queries; document contract. |
|
||||
| EXCITITOR-POLICY-23-002 `Event guarantees` | TODO | Excititor Core Guild, Platform Events Guild | EXCITITOR-LNM-21-005 | Ensure `vex.linkset.updated` events include correlation confidence, conflict summaries, and idempotent ids for evaluator consumption. |
|
||||
|
||||
## Graph & Vuln Explorer v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-GRAPH-24-001 `VEX overlay inputs` | TODO | Excititor Core Guild | EXCITITOR-POLICY-23-001 | Expose raw VEX statements/linksets scoped for overlay services; no suppression/precedence logic in ingestion. |
|
||||
|
||||
## Reachability v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-SIG-26-001 `Vendor exploitability hints` | TODO | Excititor Core Guild, Signals Guild | SIGNALS-24-004 | Surface vendor-provided exploitability indicators and affected symbol lists to Signals service via projection endpoints. |
|
||||
|
||||
## Authority-Backed Scopes & Tenancy (Epic 14)
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-TEN-48-001 `Tenant-aware VEX linking` | TODO | Excititor Core Guild | AUTH-TEN-47-001 | Apply tenant context to VEX linkers, enable RLS, and expose capability endpoint confirming aggregation-only behavior. |
|
||||
|
||||
## Observability & Forensics (Epic 15)
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-OBS-50-001 `Telemetry adoption` | TODO | Excititor Core Guild, Observability Guild | TELEMETRY-OBS-50-001, TELEMETRY-OBS-50-002 | Integrate telemetry core across VEX ingestion/linking, ensuring spans/logs capture tenant, product scope, upstream id, justification hash, and trace IDs. |
|
||||
| EXCITITOR-OBS-51-001 `Metrics & SLOs` | TODO | Excititor Core Guild, DevOps Guild | EXCITITOR-OBS-50-001, TELEMETRY-OBS-51-001 | Publish metrics for VEX ingest latency, scope resolution success, conflict rate, signature verification failures. Define SLOs (link latency P95 <30s) and configure burn-rate alerts. |
|
||||
| EXCITITOR-OBS-52-001 `Timeline events` | TODO | Excititor Core Guild | EXCITITOR-OBS-50-001, TIMELINE-OBS-52-002 | Emit `timeline_event` entries for VEX ingest/linking/outcome changes with trace IDs, justification summaries, and evidence placeholders. |
|
||||
| EXCITITOR-OBS-53-001 `Evidence snapshots` | TODO | Excititor Core Guild, Evidence Locker Guild | EXCITITOR-OBS-52-001, EVID-OBS-53-002 | Build evidence payloads for VEX statements (raw doc, normalization diff, precedence notes) and push to evidence locker with Merkle manifests. |
|
||||
| EXCITITOR-OBS-54-001 `Attestation & verification` | TODO | Excititor Core Guild, Provenance Guild | EXCITITOR-OBS-53-001, PROV-OBS-54-001 | Attach DSSE attestations to VEX batch processing, verify chain-of-custody via Provenance library, and link attestation IDs to timeline + ledger. |
|
||||
| EXCITITOR-OBS-55-001 `Incident mode` | TODO | Excititor Core Guild, DevOps Guild | EXCITITOR-OBS-51-001, DEVOPS-OBS-55-001 | Implement incident sampling bump, additional raw payload retention, and activation events for VEX pipelines with redaction guard rails. |
|
||||
|
||||
## Air-Gapped Mode (Epic 16)
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-AIRGAP-56-001 `Mirror ingestion adapters` | TODO | Excititor Core Guild | AIRGAP-IMP-57-002, MIRROR-CRT-56-001 | Add mirror-based VEX ingestion, preserving statement digests and bundle IDs. |
|
||||
| EXCITITOR-AIRGAP-56-002 `Bundle provenance` | TODO | Excititor Core Guild, AirGap Importer Guild | EXCITITOR-AIRGAP-56-001, AIRGAP-IMP-57-001 | Persist bundle metadata on VEX observations/linksets with provenance references. |
|
||||
| EXCITITOR-AIRGAP-57-001 `Sealed-mode enforcement` | TODO | Excititor Core Guild, AirGap Policy Guild | EXCITITOR-AIRGAP-56-001, AIRGAP-POL-56-001 | Block non-mirror connectors in sealed mode and surface remediation errors. |
|
||||
| EXCITITOR-AIRGAP-57-002 `Staleness annotations` | TODO | Excititor Core Guild, AirGap Time Guild | EXCITITOR-AIRGAP-56-002, AIRGAP-TIME-58-001 | Annotate VEX statements with staleness metrics and expose via API. |
|
||||
| EXCITITOR-AIRGAP-58-001 `Portable VEX evidence` | TODO | Excititor Core Guild, Evidence Locker Guild | EXCITITOR-OBS-53-001, EVID-OBS-54-001 | Package VEX evidence segments into portable evidence bundles linked to timeline. |
|
||||
|
||||
## SDKs & OpenAPI (Epic 17)
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-OAS-61-001 `Spec coverage` | TODO | Excititor Core Guild, API Contracts Guild | OAS-61-001 | Update VEX OAS to include observation/linkset endpoints with provenance fields and examples. |
|
||||
| EXCITITOR-OAS-61-002 `Example catalog` | TODO | Excititor Core Guild | EXCITITOR-OAS-61-001 | Provide examples for VEX justifications, statuses, conflicts; ensure SDK docs reference them. |
|
||||
| EXCITITOR-OAS-62-001 `SDK smoke tests` | TODO | Excititor Core Guild, SDK Generator Guild | EXCITITOR-OAS-61-001, SDKGEN-63-001 | Add SDK scenarios for VEX observation queries and conflict handling to language smoke suites. |
|
||||
| EXCITITOR-OAS-63-001 `Deprecation headers` | TODO | Excititor Core Guild, API Governance Guild | APIGOV-63-001 | Add deprecation metadata and notifications for legacy VEX routes. |
|
||||
|
||||
## Risk Profiles (Epic 18)
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-RISK-66-001 `VEX gate provider` | TODO | Excititor Core Guild, Risk Engine Guild | RISK-ENGINE-67-002 | Supply VEX status and justification data for risk engine gating with full source provenance. |
|
||||
| EXCITITOR-RISK-66-002 `Reachability inputs` | TODO | Excititor Core Guild | EXCITITOR-RISK-66-001 | Provide component/product scoping metadata enabling reachability and runtime factor mapping. |
|
||||
| EXCITITOR-RISK-67-001 `Explainability metadata` | TODO | Excititor Core Guild | EXCITITOR-RISK-66-001 | Include VEX justification, status reasoning, and source digests in explainability artifacts. |
|
||||
| EXCITITOR-RISK-68-001 `Policy Studio integration` | TODO | Excititor Core Guild, Policy Studio Guild | POLICY-RISK-68-001 | Surface VEX-specific gates/weights within profile editor UI and validation messages. |
|
||||
|
||||
## Attestor Console (Epic 19)
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-ATTEST-73-001 `VEX attestation payloads` | TODO | Excititor Core Guild, Attestation Payloads Guild | ATTEST-TYPES-72-001 | Provide VEX statement metadata (supplier identity, justification, scope) required for VEXAttestation payloads. |
|
||||
| EXCITITOR-ATTEST-73-002 `Chain provenance` | TODO | Excititor Core Guild | EXCITITOR-ATTEST-73-001 | Expose linkage from VEX statements to subject/product for chain of custody graph. |
|
||||
|
||||
@@ -1,11 +1,27 @@
|
||||
If you are working on this file you need to read docs/ARCHITECTURE_EXCITITOR.md and ./AGENTS.md).
|
||||
# TASKS
|
||||
| Task | Owner(s) | Depends on | Notes |
|
||||
|---|---|---|---|
|
||||
|EXCITITOR-STORAGE-01-001 – Collection schemas & class maps|Team Excititor Storage|EXCITITOR-CORE-01-001|DONE (2025-10-15) – Added Mongo mapping registry with raw/export entities and service registration groundwork.|
|
||||
|EXCITITOR-STORAGE-01-002 – Migrations & indices bootstrap|Team Excititor Storage|EXCITITOR-STORAGE-01-001|**DONE (2025-10-16)** – Add bootstrapper creating indices (claims by vulnId/product, exports by querySignature, etc.) and migrations for existing deployments.<br>2025-10-16: Introduced migration runner + hosted service, initial index migration covers raw/providers/consensus/exports/cache, and tests use Mongo2Go to verify execution.|
|
||||
|EXCITITOR-STORAGE-01-003 – Repository layer & transactional flows|Team Excititor Storage|EXCITITOR-STORAGE-01-001|**DONE (2025-10-16)** – Added GridFS-backed raw store with transactional upserts (including fallback for non-replicaset Mongo), export/cache repository coordination, and coverage verifying cache TTL + GridFS round-trips.|
|
||||
|EXCITITOR-STORAGE-01-004 – Provider/consensus/cache mappings|Team Excititor Storage|EXCITITOR-STORAGE-01-001|**DONE (2025-10-16)** – Registered MongoDB class maps for provider/consensus/cache records with forward-compatible field handling and added coverage ensuring GridFS-linked cache entries round-trip cleanly.|
|
||||
|EXCITITOR-STORAGE-02-001 – Statement events & scoring signals|Team Excititor Storage|EXCITITOR-CORE-02-001|DONE (2025-10-19) – Added immutable `vex.statements` collection + claim store, extended consensus persistence with severity/KEV/EPSS signals, shipped migration `20251019-consensus-signals-statements`, and updated docs. Tests: `dotnet test src/StellaOps.Excititor.Core.Tests/StellaOps.Excititor.Core.Tests.csproj` & `dotnet test src/StellaOps.Excititor.Storage.Mongo.Tests/StellaOps.Excititor.Storage.Mongo.Tests.csproj`; worker/web suites pending due to NU1903 (`Microsoft.Extensions.Caching.Memory`) advisory.|
|
||||
|EXCITITOR-STORAGE-03-001 – Statement backfill tooling|Team Excititor Storage|EXCITITOR-STORAGE-02-001|**DONE (2025-10-19)** – Shipped Mongo-backed statement replay service + `/excititor/admin/backfill-statements`, wired CLI command `stellaops excititor backfill-statements`, added integration tests, and documented the runbook in `docs/dev/EXCITITOR_STATEMENT_BACKFILL.md`.|
|
||||
|EXCITITOR-STORAGE-MONGO-08-001 – Session + causal consistency hardening|Team Excititor Storage|EXCITITOR-STORAGE-01-003|**DONE (2025-10-19)** – Completed session-aware overloads across all repositories, persisted claims/signals/connector state with new Mongo records, updated orchestrators/workers to reuse scoped sessions, and added replica-set consistency tests (`dotnet test src/StellaOps.Excititor.Storage.Mongo.Tests/StellaOps.Excititor.Storage.Mongo.Tests.csproj`). GridFS operations fall back to majority semantics due to driver limits; transactions cover metadata writes to preserve determinism.|
|
||||
# TASKS — Epic 1: Aggregation-Only Contract
|
||||
> **AOC Reminder:** storage enforces raw VEX documents only—no consensus/precedence data in ingestion collections.
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|---|---|---|---|---|
|
||||
| EXCITITOR-STORE-AOC-19-001 `vex_raw schema validator` | TODO | Excititor Storage Guild | Mongo cluster ops sign-off | Define Mongo JSON schema for `vex_raw` enforcing required fields and forbidding derived/consensus/severity fields. Ship unit tests with Mongo2Go to validate rejects. |
|
||||
| EXCITITOR-STORE-AOC-19-002 `idempotency unique index` | TODO | Excititor Storage Guild | EXCITITOR-STORE-AOC-19-001 | Create `(source.vendor, upstream.upstream_id, upstream.content_hash, tenant)` unique index with backfill checker, updating migrations + bootstrapper for offline installs. |
|
||||
| EXCITITOR-STORE-AOC-19-003 `append-only migration plan` | TODO | Excititor Storage Guild | EXCITITOR-STORE-AOC-19-002 | Migrate legacy consensus collections to `_backup_*`, seed supersedes chain for raw docs, and document rollback path + dry-run verification. |
|
||||
| EXCITITOR-STORE-AOC-19-004 `validator deployment docset` | TODO | Excititor Storage Guild, DevOps Guild | EXCITITOR-STORE-AOC-19-001 | Update migration runbooks and Offline Kit packaging to bundle schema validator scripts, with smoke instructions for air-gapped clusters. |
|
||||
|
||||
## Policy Engine v2
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-POLICY-20-003 `Selection cursors` | TODO | Excititor Storage Guild | EXCITITOR-STORE-AOC-19-002, POLICY-ENGINE-20-003 | Introduce VEX selection cursor collections + indexes powering incremental policy runs; bundle change-stream checkpoint migrations and Offline Kit tooling. |
|
||||
|
||||
## Graph Explorer v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-GRAPH-21-005 `Inspector indexes` | TODO | Excititor Storage Guild | EXCITITOR-GRAPH-21-001 | Add indexes/materialized views for VEX lookups by PURL/policy to support Cartographer inspector performance; document migrations. |
|
||||
|
||||
## Link-Not-Merge v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-LNM-21-101 `Observations collections` | TODO | Excititor Storage Guild | EXCITITOR-LNM-21-001 | Provision `vex_observations`/`vex_linksets` collections with shard keys, indexes over aliases & product PURLs, and multi-tenant guards. |
|
||||
| EXCITITOR-LNM-21-102 `Migration/backfill` | TODO | Excititor Storage Guild, DevOps Guild | EXCITITOR-LNM-21-101 | Backfill legacy merged VEX docs into observations/linksets, add provenance notes, and produce rollback scripts. |
|
||||
|
||||
@@ -1,9 +1,86 @@
|
||||
If you are working on this file you need to read docs/ARCHITECTURE_EXCITITOR.md and ./AGENTS.md).
|
||||
# TASKS
|
||||
| Task | Owner(s) | Depends on | Notes |
|
||||
|---|---|---|---|
|
||||
|EXCITITOR-WEB-01-001 – Minimal API bootstrap & DI|Team Excititor WebService|EXCITITOR-CORE-01-003, EXCITITOR-STORAGE-01-003|**DONE (2025-10-17)** – Minimal API host composes storage/export/attestation/artifact stores, binds Mongo/attestation options, and exposes `/excititor/status` + health endpoints with regression coverage in `StatusEndpointTests`.|
|
||||
|EXCITITOR-WEB-01-002 – Ingest & reconcile endpoints|Team Excititor WebService|EXCITITOR-WEB-01-001|**DONE (2025-10-20)** – `/excititor/init`, `/excititor/ingest/run`, `/excititor/ingest/resume`, `/excititor/reconcile` enforce `vex.admin`, normalize provider lists, and return deterministic summaries; covered via unit tests (`dotnet test src/StellaOps.Excititor.WebService.Tests/StellaOps.Excititor.WebService.Tests.csproj --filter FullyQualifiedName~IngestEndpointsTests`).|
|
||||
|EXCITITOR-WEB-01-003 – Export & verify endpoints|Team Excititor WebService|EXCITITOR-WEB-01-001, EXCITITOR-EXPORT-01-001, EXCITITOR-ATTEST-01-001|**DOING (2025-10-19)** – Prereqs confirmed (EXCITITOR-WEB-01-001, EXCITITOR-EXPORT-01-001, EXCITITOR-ATTEST-01-001); preparing `/excititor/export*` surfaces and `/excititor/verify` with artifact/attestation metadata caching strategy.|
|
||||
|EXCITITOR-WEB-01-004 – Resolve API & signed responses|Team Excititor WebService|EXCITITOR-WEB-01-001, EXCITITOR-ATTEST-01-002|**DONE (2025-10-20)** – Added `vex.read` scope enforcement, signed consensus/attestation envelopes, docs updates, and expanded tests (auth, unauthorized/forbidden). Mirror/ingest DTO casing fixed to restore builds.|
|
||||
|EXCITITOR-WEB-01-005 – Mirror distribution endpoints|Team Excititor WebService|EXCITITOR-EXPORT-01-007, DEVOPS-MIRROR-08-001|**DONE (2025-10-19)** – `/excititor/mirror` surfaces domain listings, indices, metadata, and downloads with quota/auth checks; tests cover Happy-path listing/download (`dotnet test src/StellaOps.Excititor.WebService.Tests/StellaOps.Excititor.WebService.Tests.csproj`).|
|
||||
# TASKS — Epic 1: Aggregation-Only Contract
|
||||
> **AOC Reminder:** Excititor WebService publishes raw statements/linksets only; derived precedence/severity belongs to Policy overlays.
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|---|---|---|---|---|
|
||||
| EXCITITOR-WEB-AOC-19-001 `Raw VEX ingestion APIs` | TODO | Excititor WebService Guild | EXCITITOR-CORE-AOC-19-001, EXCITITOR-STORE-AOC-19-001 | Implement `POST /ingest/vex`, `GET /vex/raw*`, and `POST /aoc/verify` endpoints. Enforce Authority scopes, tenant injection, and guard pipeline to ensure only immutable VEX facts are persisted. |
|
||||
| EXCITITOR-WEB-AOC-19-002 `AOC observability + metrics` | TODO | Excititor WebService Guild, Observability Guild | EXCITITOR-WEB-AOC-19-001 | Export metrics (`ingestion_write_total`, `aoc_violation_total`, signature verification counters) and tracing spans matching Conseiller naming. Ensure structured logging includes tenant, source vendor, upstream id, and content hash. |
|
||||
| EXCITITOR-WEB-AOC-19-003 `Guard + schema test harness` | TODO | QA Guild | EXCITITOR-WEB-AOC-19-001 | Add unit/integration tests for schema validation, forbidden field rejection (`ERR_AOC_001/006/007`), and supersedes behavior using CycloneDX-VEX & CSAF fixtures with deterministic expectations. |
|
||||
| EXCITITOR-WEB-AOC-19-004 `Batch ingest validation` | TODO | Excititor WebService Guild, QA Guild | EXCITITOR-WEB-AOC-19-003, EXCITITOR-CORE-AOC-19-002 | Build large fixture ingest covering mixed VEX statuses, verifying raw storage parity, metrics, and CLI `aoc verify` compatibility. Document load test/runbook updates. |
|
||||
|
||||
## Policy Engine v2
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-POLICY-20-001 `Policy selection endpoints` | TODO | Excititor WebService Guild | WEB-POLICY-20-001, EXCITITOR-CORE-AOC-19-004 | Provide VEX lookup APIs supporting PURL/advisory batching, scope filtering, and tenant enforcement with deterministic ordering + pagination. |
|
||||
|
||||
## StellaOps Console (Sprint 23)
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-CONSOLE-23-001 `VEX aggregation views` | TODO | Excititor WebService Guild, BE-Base Platform Guild | EXCITITOR-LNM-21-201, EXCITITOR-LNM-21-202 | Expose `/console/vex` endpoints returning grouped VEX statements per advisory/component with status chips, justification metadata, precedence trace pointers, and tenant-scoped filters for Console explorer. |
|
||||
| EXCITITOR-CONSOLE-23-002 `Dashboard VEX deltas` | TODO | Excititor WebService Guild | EXCITITOR-CONSOLE-23-001, EXCITITOR-LNM-21-203 | Provide aggregated counts for VEX overrides (new, not_affected, revoked) powering Console dashboard + live status ticker; emit metrics for policy explain integration. |
|
||||
| EXCITITOR-CONSOLE-23-003 `VEX search helpers` | TODO | Excititor WebService Guild | EXCITITOR-CONSOLE-23-001 | Deliver rapid lookup endpoints of VEX by advisory/component for Console global search; ensure response includes provenance and precedence context; include caching and RBAC. |
|
||||
|
||||
## Graph Explorer v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-GRAPH-21-003 `Inspector fetch API` | TODO | Excititor WebService Guild, Cartographer Guild | EXCITITOR-GRAPH-21-001 | Expose batch endpoints for retrieving VEX statements + advisory metadata by PURL/component for Graph Explorer inspector. |
|
||||
| EXCITITOR-GRAPH-21-004 `Overlay subscription` | TODO | Excititor WebService Guild | EXCITITOR-GRAPH-21-003, CARTO-GRAPH-21-007 | Emit events (NATS/Redis) when new VEX docs land so Cartographer can refresh overlays; include tenant/policy references. |
|
||||
|
||||
## Link-Not-Merge v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-LNM-21-201 `Observation APIs` | TODO | Excititor WebService Guild, BE-Base Platform Guild | EXCITITOR-LNM-21-001 | Add VEX observation read endpoints with filters, pagination, RBAC, and tenant scoping. |
|
||||
| EXCITITOR-LNM-21-202 `Linkset APIs` | TODO | Excititor WebService Guild | EXCITITOR-LNM-21-002, EXCITITOR-LNM-21-003 | Implement linkset read/export/evidence endpoints returning correlation/conflict payloads and map errors to `ERR_AGG_*`. |
|
||||
| EXCITITOR-LNM-21-203 `Event publishing` | TODO | Excititor WebService Guild, Platform Events Guild | EXCITITOR-LNM-21-005 | Publish `vex.linkset.updated` events, document schema, and ensure idempotent delivery. |
|
||||
|
||||
## Graph & Vuln Explorer v1
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-GRAPH-24-101 `VEX summary API` | TODO | Excititor WebService Guild | EXCITITOR-GRAPH-24-001 | Provide endpoints delivering VEX status summaries per component/asset for Vuln Explorer integration. |
|
||||
| EXCITITOR-GRAPH-24-102 `Evidence batch API` | TODO | Excititor WebService Guild | EXCITITOR-LNM-21-201 | Add batch VEX observation retrieval optimized for Graph overlays/tooltips. |
|
||||
|
||||
## Vulnerability Explorer (Sprint 29)
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-VULN-29-001 `VEX key normalization` | TODO | Excititor WebService Guild | EXCITITOR-LNM-21-001 | Canonicalize VEX advisory/product keys (map to `advisory_key`, capture product scopes); expose original sources in `links[]`; backfill existing records. |
|
||||
| EXCITITOR-VULN-29-002 `Evidence retrieval` | TODO | Excititor WebService Guild | EXCITITOR-VULN-29-001, VULN-API-29-003 | Provide `/vuln/evidence/vex/{advisory_key}` returning raw VEX statements filtered by tenant/product scope for Explorer evidence tabs. |
|
||||
| EXCITITOR-VULN-29-004 `Observability` | TODO | Excititor WebService Guild, Observability Guild | EXCITITOR-VULN-29-001 | Add metrics/logs for VEX normalization, suppression scopes, withdrawn statements; emit events consumed by Vuln Explorer resolver. |
|
||||
|
||||
## Advisory AI (Sprint 31)
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-AIAI-31-001 `Justification enrichment` | TODO | Excititor WebService Guild | EXCITITOR-VULN-29-001 | Expose normalized VEX justifications, product trees, and paragraph anchors for Advisory AI conflict explanations. |
|
||||
| EXCITITOR-AIAI-31-002 `VEX chunk API` | TODO | Excititor WebService Guild | EXCITITOR-AIAI-31-001, VEXLENS-30-006 | Provide `/vex/evidence/chunks` endpoint returning tenant-scoped VEX statements with signature metadata and scope scores for RAG. |
|
||||
| EXCITITOR-AIAI-31-003 `Telemetry` | TODO | Excititor WebService Guild, Observability Guild | EXCITITOR-AIAI-31-001 | Emit metrics/logs for VEX chunk usage, signature verification failures, and guardrail triggers. |
|
||||
|
||||
## Observability & Forensics (Epic 15)
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-WEB-OBS-50-001 `Telemetry adoption` | TODO | Excititor WebService Guild | TELEMETRY-OBS-50-001, EXCITITOR-OBS-50-001 | Adopt telemetry core for VEX APIs, ensure responses include trace IDs & correlation headers, and update structured logging for read endpoints. |
|
||||
| EXCITITOR-WEB-OBS-51-001 `Observability health endpoints` | TODO | Excititor WebService Guild | EXCITITOR-WEB-OBS-50-001, WEB-OBS-51-001 | Implement `/obs/excititor/health` summarizing ingest/link SLOs, signature failure counts, and conflict trends for Console dashboards. |
|
||||
| EXCITITOR-WEB-OBS-52-001 `Timeline streaming` | TODO | Excititor WebService Guild | EXCITITOR-WEB-OBS-50-001, TIMELINE-OBS-52-003 | Provide SSE bridge for VEX timeline events with tenant filters, pagination, and guardrails. |
|
||||
| EXCITITOR-WEB-OBS-53-001 `Evidence APIs` | TODO | Excititor WebService Guild, Evidence Locker Guild | EXCITITOR-OBS-53-001, EVID-OBS-53-003 | Expose `/evidence/vex/*` endpoints that fetch locker bundles, enforce scopes, and surface verification metadata. |
|
||||
| EXCITITOR-WEB-OBS-54-001 `Attestation APIs` | TODO | Excititor WebService Guild | EXCITITOR-OBS-54-001, PROV-OBS-54-001 | Add `/attestations/vex/*` endpoints returning DSSE verification state, builder identity, and chain-of-custody links. |
|
||||
| EXCITITOR-WEB-OBS-55-001 `Incident mode toggles` | TODO | Excititor WebService Guild, DevOps Guild | EXCITITOR-OBS-55-001, WEB-OBS-55-001 | Provide incident mode API for VEX pipelines with activation audit logs and retention override previews. |
|
||||
|
||||
## Air-Gapped Mode (Epic 16)
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-WEB-AIRGAP-56-001 | TODO | Excititor WebService Guild | AIRGAP-IMP-58-001, EXCITITOR-AIRGAP-56-001 | Support mirror bundle registration via APIs, expose bundle provenance in VEX responses, and block external connectors in sealed mode. |
|
||||
| EXCITITOR-WEB-AIRGAP-56-002 | TODO | Excititor WebService Guild, AirGap Time Guild | EXCITITOR-WEB-AIRGAP-56-001, AIRGAP-TIME-58-001 | Return VEX staleness metrics and time anchor info in API responses for Console/CLI use. |
|
||||
| EXCITITOR-WEB-AIRGAP-57-001 | TODO | Excititor WebService Guild, AirGap Policy Guild | AIRGAP-POL-56-001 | Map sealed-mode violations to standardized error payload with remediation guidance. |
|
||||
| EXCITITOR-WEB-AIRGAP-58-001 | TODO | Excititor WebService Guild, AirGap Importer Guild | EXCITITOR-WEB-AIRGAP-56-001, TIMELINE-OBS-53-001 | Emit timeline events for VEX bundle imports with bundle ID, scope, and actor metadata. |
|
||||
|
||||
## SDKs & OpenAPI (Epic 17)
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-WEB-OAS-61-001 | TODO | Excititor WebService Guild | OAS-61-001 | Implement `/.well-known/openapi` discovery endpoint with spec version metadata. |
|
||||
| EXCITITOR-WEB-OAS-61-002 | TODO | Excititor WebService Guild | APIGOV-61-001 | Standardize error envelope responses and update controller/unit tests. |
|
||||
| EXCITITOR-WEB-OAS-62-001 | TODO | Excititor WebService Guild | EXCITITOR-OAS-61-002 | Add curated examples for VEX observation/linkset endpoints and ensure portal displays them. |
|
||||
| EXCITITOR-WEB-OAS-63-001 | TODO | Excititor WebService Guild, API Governance Guild | APIGOV-63-001 | Emit deprecation headers and update docs for retiring VEX APIs. |
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
If you are working on this file you need to read docs/ARCHITECTURE_EXCITITOR.md and ./AGENTS.md).
|
||||
# TASKS
|
||||
| Task | Owner(s) | Depends on | Notes |
|
||||
|---|---|---|---|
|
||||
|EXCITITOR-WORKER-01-001 – Worker host & scheduling|Team Excititor Worker|EXCITITOR-STORAGE-01-003, EXCITITOR-WEB-01-001|**DONE (2025-10-17)** – Worker project bootstraps provider schedules from configuration, integrates plugin catalog discovery, and emits structured logs/metrics-ready events via `VexWorkerHostedService`; scheduling logic covered by `VexWorkerOptionsTests`.|
|
||||
|EXCITITOR-WORKER-01-002 – Resume tokens & retry policy|Team Excititor Worker|EXCITITOR-WORKER-01-001|DONE (2025-10-21) – Worker flows resume tokens through `VexConnectorContext`, persists success/failure metadata with jittered exponential backoff and quarantine scheduling, and ships unit coverage for skip/backoff/resume behaviour.|
|
||||
|EXCITITOR-WORKER-01-003 – Verification & cache GC loops|Team Excititor Worker|EXCITITOR-WORKER-01-001, EXCITITOR-ATTEST-01-003, EXCITITOR-EXPORT-01-002|TODO – Add scheduled attestation re-verification and cache pruning routines, surfacing metrics for export reuse ratios.|
|
||||
|EXCITITOR-WORKER-01-004 – TTL refresh & stability damper|Team Excititor Worker|EXCITITOR-WORKER-01-001, EXCITITOR-CORE-02-001|DONE (2025-10-21) – Added configurable TTL refresh service with trust-weighted dampers, component fingerprint bypass, and Mongo-backed hold promotion to stabilize consensus updates.|
|
||||
|EXCITITOR-WORKER-02-001 – Resolve Microsoft.Extensions.Caching.Memory advisory|Team Excititor Worker|EXCITITOR-WORKER-01-001|DONE (2025-10-21) – Upgraded Excititor dependencies to `Microsoft.Extensions.*` 10.0.0-preview.7.25380.108, re-enabled attestation fixtures, and reran worker/webservice regression suites without NU1903 warnings.|
|
||||
|EXCITITOR-WORKER-02-001-REVIEW – Review Microsoft.Extensions.* upgrade|Team Excititor Worker (Review)|EXCITITOR-WORKER-02-001|TODO – Peer review for dependency bump/attestation fixture changes; verify connector coverage updates and approve release note entry.|
|
||||
# TASKS — Epic 1: Aggregation-Only Contract
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|---|---|---|---|---|
|
||||
| EXCITITOR-WORKER-AOC-19-001 `Raw pipeline rewiring` | TODO | Excititor Worker Guild | EXCITITOR-CORE-AOC-19-001 | Update ingest pipelines to persist upstream documents directly into `vex_raw` via the new repository guard. Remove consensus/folding hooks and ensure retries respect append-only semantics. |
|
||||
| EXCITITOR-WORKER-AOC-19-002 `Signature & checksum enforcement` | TODO | Excititor Worker Guild | EXCITITOR-WORKER-AOC-19-001 | Add signature verification + checksum computation before writes, capturing failure reasons mapped to `ERR_AOC_005`, with structured logs/metrics for verification results. |
|
||||
| EXCITITOR-WORKER-AOC-19-003 `Deterministic batching tests` | TODO | QA Guild | EXCITITOR-WORKER-AOC-19-001 | Extend worker integration tests to replay large VEX batches ensuring idempotent upserts, supersedes chaining, and guard enforcement across restart scenarios. |
|
||||
|
||||
## Orchestrator Dashboard
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Notes |
|
||||
|----|--------|----------|------------|-------|
|
||||
| EXCITITOR-ORCH-32-001 `Worker SDK adoption` | TODO | Excititor Worker Guild | ORCH-SVC-32-005, WORKER-GO-32-001, WORKER-PY-32-001 | Integrate orchestrator worker SDK in Excititor ingestion jobs, emit heartbeats/progress/artifact hashes, and register source metadata. |
|
||||
| EXCITITOR-ORCH-33-001 `Control compliance` | TODO | Excititor Worker Guild | EXCITITOR-ORCH-32-001, ORCH-SVC-33-001, ORCH-SVC-33-002 | Honor orchestrator pause/throttle/retry actions, classify error outputs, and persist restart checkpoints. |
|
||||
| EXCITITOR-ORCH-34-001 `Backfill & circuit breaker` | TODO | Excititor Worker Guild | EXCITITOR-ORCH-33-001, ORCH-SVC-33-003, ORCH-SVC-34-001 | Implement orchestrator-driven backfills, apply circuit breaker reset rules, and ensure artifact dedupe alignment. |
|
||||
|
||||
14
src/StellaOps.ExportCenter.AttestationBundles/AGENTS.md
Normal file
14
src/StellaOps.ExportCenter.AttestationBundles/AGENTS.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Attestation Bundle Export Guild Charter
|
||||
|
||||
## Mission
|
||||
Enable offline transfer and verification of attestations by building signed bundles containing envelopes, issuer metadata, and optional transparency log segments.
|
||||
|
||||
## Scope
|
||||
- Bundle construction via Export Center, including manifest, checksums, DSSE signatures.
|
||||
- CLI tooling for bundle verification and import.
|
||||
- Coordination with risk/attestor services for air-gap workflows.
|
||||
|
||||
## Definition of Done
|
||||
- Bundles build reproducibly with manifest + signatures and pass verification tooling.
|
||||
- Importer applies bundles to air-gapped Attestor Store safely.
|
||||
- Documentation covers offline workflows with imposed rule banner.
|
||||
13
src/StellaOps.ExportCenter.AttestationBundles/TASKS.md
Normal file
13
src/StellaOps.ExportCenter.AttestationBundles/TASKS.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Attestation Bundle Export Task Board — Epic 19: Attestor Console
|
||||
|
||||
## Sprint 74 – Builder
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| EXPORT-ATTEST-74-001 | TODO | Attestation Bundle Guild, Attestor Service Guild | ATTESTOR-73-003 | Implement export job producing attestation bundles with manifest, checksums, DSSE signature, and optional transparency log segments. | Bundle built in staging; manifest recorded; signature verification tests pass. |
|
||||
| EXPORT-ATTEST-74-002 | TODO | Attestation Bundle Guild, DevOps Guild | EXPORT-ATTEST-74-001 | Integrate bundle job into CI/offline kit packaging with checksum publication. | Pipeline publishes bundle artifact + checksums; documentation updated. |
|
||||
|
||||
## Sprint 75 – Verification & Import
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| EXPORT-ATTEST-75-001 | TODO | Attestation Bundle Guild, CLI Attestor Guild | EXPORT-ATTEST-74-001 | Provide CLI command `stella attest bundle verify/import` for air-gap usage. | CLI verifies/signatures; import seeds attestor store; tests cover corrupted bundle. |
|
||||
| EXPORT-ATTEST-75-002 | TODO | Attestation Bundle Guild, Docs Guild | EXPORT-ATTEST-75-001 | Document `/docs/attestor/airgap.md` with bundle workflows and verification steps. | Doc merged with banner; examples verified. |
|
||||
14
src/StellaOps.ExportCenter.DevPortalOffline/AGENTS.md
Normal file
14
src/StellaOps.ExportCenter.DevPortalOffline/AGENTS.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# DevPortal Offline Export Guild Charter
|
||||
|
||||
## Mission
|
||||
Package developer portal assets, OpenAPI specs, and SDK binaries into reproducible bundles for air-gapped environments.
|
||||
|
||||
## Scope
|
||||
- Integrate with Export Center to produce `devportal --offline` bundles.
|
||||
- Manage checksum manifests, DSSE signatures, and provenance.
|
||||
- Provide validation tooling for operators importing bundles.
|
||||
|
||||
## Definition of Done
|
||||
- Offline bundle builds reproducibly with signed manifests and verification scripts.
|
||||
- Export job documented and available via CLI/Console.
|
||||
- Operators can validate bundle integrity without external services.
|
||||
7
src/StellaOps.ExportCenter.DevPortalOffline/TASKS.md
Normal file
7
src/StellaOps.ExportCenter.DevPortalOffline/TASKS.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# DevPortal Offline Export Task Board — Epic 17: SDKs & OpenAPI Docs
|
||||
|
||||
## Sprint 64 – Bundle Implementation
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| DVOFF-64-001 | TODO | DevPortal Offline Guild, Exporter Guild | DEVPORT-64-001, SDKREL-64-002 | Implement Export Center job `devportal --offline` bundling portal HTML, specs, SDK artifacts, changelogs, and verification manifest. | Job executes in staging; manifest contains checksums + DSSE signatures; docs updated. |
|
||||
| DVOFF-64-002 | TODO | DevPortal Offline Guild, AirGap Controller Guild | DVOFF-64-001 | Provide verification CLI (`stella devportal verify bundle.tgz`) ensuring integrity before import. | CLI command validates signatures; integration test covers corrupted bundle; runbook updated. |
|
||||
14
src/StellaOps.ExportCenter.RiskBundles/AGENTS.md
Normal file
14
src/StellaOps.ExportCenter.RiskBundles/AGENTS.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Risk Bundle Export Guild Charter
|
||||
|
||||
## Mission
|
||||
Produce offline-ready bundles of risk scoring factor datasets and provider metadata for air-gapped environments.
|
||||
|
||||
## Scope
|
||||
- Export Center job `risk-bundle` that packages KEV/EPSS feeds, reachability indexes, runtime evidence snapshots, and metadata.
|
||||
- DSSE signing, checksum manifests, and verification tooling.
|
||||
- Coordination with Risk Engine providers to declare required assets and TTLs.
|
||||
|
||||
## Definition of Done
|
||||
- Bundles build reproducibly with manifests and signatures; verification CLI available.
|
||||
- Provider metadata enumerates datasets, TTLs, and schema versions.
|
||||
- Air-gapped installations can load bundles and detect missing assets loudly.
|
||||
13
src/StellaOps.ExportCenter.RiskBundles/TASKS.md
Normal file
13
src/StellaOps.ExportCenter.RiskBundles/TASKS.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Risk Bundle Export Task Board — Epic 18: Risk Scoring Profiles
|
||||
|
||||
## Sprint 69 – Bundle Builder
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| RISK-BUNDLE-69-001 | TODO | Risk Bundle Export Guild, Risk Engine Guild | RISK-ENGINE-67-003 | Implement `stella export risk-bundle` job producing tarball with provider datasets, manifests, and DSSE signatures. | Bundle builds in staging; manifest lists datasets + TTL; signatures verified. |
|
||||
| RISK-BUNDLE-69-002 | TODO | Risk Bundle Export Guild, DevOps Guild | RISK-BUNDLE-69-001 | Integrate bundle job into CI/offline kit pipelines with checksum publication. | CI produces bundle artifact; checksums in release metadata; docs updated. |
|
||||
|
||||
## Sprint 70 – Verification & Docs
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| RISK-BUNDLE-70-001 | TODO | Risk Bundle Export Guild, CLI Guild | RISK-BUNDLE-69-001 | Provide CLI `stella risk bundle verify` command to validate bundles before import. | CLI verifies DSSE + checksums; integration tests cover tampered bundle. |
|
||||
| RISK-BUNDLE-70-002 | TODO | Risk Bundle Export Guild, Docs Guild | RISK-BUNDLE-69-002 | Publish `/docs/airgap/risk-bundles.md` detailing build/import/verification workflows. | Doc merged with banner; examples validated. |
|
||||
18
src/StellaOps.ExportCenter/AGENTS.md
Normal file
18
src/StellaOps.ExportCenter/AGENTS.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# StellaOps Exporter Service — Agent Charter
|
||||
|
||||
## Mission
|
||||
Deliver the Export Center service described in Epic 10. Provide reproducible, signed bundles (JSON, Trivy DB, mirror) that respect AOC boundaries, tenant isolation, and imposed rule propagation across all consuming components.
|
||||
|
||||
## Key Responsibilities
|
||||
- Maintain planner, adapters, signing, and distribution layers for export profiles.
|
||||
- Coordinate with Orchestrator for job scheduling, Findings Ledger for data streaming, Policy Engine/VEX Lens for snapshots, and Authority for RBAC scopes.
|
||||
- Guarantee deterministic outputs, provenance, and cryptographic signatures for every export profile.
|
||||
- Support Console/CLI experiences, DevOps automation, and Offline Kit packaging without violating sovereignty or redaction requirements.
|
||||
|
||||
## Module Layout
|
||||
- `StellaOps.ExportCenter.Core/` — export profile domain logic, planners, and validation.
|
||||
- `StellaOps.ExportCenter.Infrastructure/` — storage providers, signing adapters, integration clients.
|
||||
- `StellaOps.ExportCenter.WebService/` — REST API surface (profiles, runs, downloads, SSE).
|
||||
- `StellaOps.ExportCenter.Worker/` — export execution pipelines and background schedulers.
|
||||
- `StellaOps.ExportCenter.Tests/` — unit tests and future fixture harnesses.
|
||||
- `StellaOps.ExportCenter.sln` — module solution wiring projects together.
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace StellaOps.ExportCenter.Core;
|
||||
|
||||
public class Class1
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" ?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace StellaOps.ExportCenter.Infrastructure;
|
||||
|
||||
public class Class1
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" ?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
|
||||
<ProjectReference Include="..\StellaOps.ExportCenter.Core\StellaOps.ExportCenter.Core.csproj"/>
|
||||
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,135 @@
|
||||
<?xml version="1.0" ?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
|
||||
|
||||
|
||||
<OutputType>Exe</OutputType>
|
||||
|
||||
|
||||
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
|
||||
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
|
||||
<UseConcelierTestInfra>false</UseConcelierTestInfra>
|
||||
|
||||
|
||||
<LangVersion>preview</LangVersion>
|
||||
|
||||
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
|
||||
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
|
||||
|
||||
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1"/>
|
||||
|
||||
|
||||
|
||||
|
||||
<PackageReference Include="xunit.v3" Version="3.0.0"/>
|
||||
|
||||
|
||||
|
||||
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.3"/>
|
||||
|
||||
|
||||
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
|
||||
|
||||
|
||||
<Content Include="xunit.runner.json" CopyToOutputDirectory="PreserveNewest"/>
|
||||
|
||||
|
||||
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
|
||||
|
||||
|
||||
<Using Include="Xunit"/>
|
||||
|
||||
|
||||
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
|
||||
|
||||
|
||||
<ProjectReference Include="..\StellaOps.ExportCenter.Core\StellaOps.ExportCenter.Core.csproj"/>
|
||||
|
||||
|
||||
|
||||
|
||||
<ProjectReference Include="..\StellaOps.ExportCenter.Infrastructure\StellaOps.ExportCenter.Infrastructure.csproj"/>
|
||||
|
||||
|
||||
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace StellaOps.ExportCenter.Tests;
|
||||
|
||||
public class UnitTest1
|
||||
{
|
||||
[Fact]
|
||||
public void Test1()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"$schema": "https://xunit.net/schema/current/xunit.runner.schema.json"
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user