Restructure solution layout by module
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled

This commit is contained in:
root
2025-10-28 15:10:40 +02:00
parent 4e3e575db5
commit 68da90a11a
4103 changed files with 192899 additions and 187024 deletions

View File

@@ -4,7 +4,7 @@
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).
- Service under `src/AdvisoryAI/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.

View File

@@ -1,12 +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. |
# 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. |

View File

@@ -1,16 +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.
# 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.

View File

@@ -1,18 +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. |
# 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. |

View File

@@ -1,16 +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.
# 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.

View File

@@ -1,19 +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. |
# 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. |

View File

@@ -1,16 +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.
# 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.

View File

@@ -1,19 +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. |
# 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. |

View File

@@ -1,15 +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.
# 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.

View File

@@ -1,13 +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. |
# 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. |

56
src/Aoc/StellaOps.Aoc.sln Normal file
View File

@@ -0,0 +1,56 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "__Libraries", "__Libraries", "{41F15E67-7190-CF23-3BC4-77E87134CADD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Aoc", "__Libraries\StellaOps.Aoc\StellaOps.Aoc.csproj", "{54CD9E36-B119-4970-B652-826363055F7D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "__Tests", "__Tests", "{56BCE1BF-7CBA-7CE8-203D-A88051F1D642}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Aoc.Tests", "__Tests\StellaOps.Aoc.Tests\StellaOps.Aoc.Tests.csproj", "{5CF1158D-64F6-4981-85CB-B43453A37329}"
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
{54CD9E36-B119-4970-B652-826363055F7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{54CD9E36-B119-4970-B652-826363055F7D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{54CD9E36-B119-4970-B652-826363055F7D}.Debug|x64.ActiveCfg = Debug|Any CPU
{54CD9E36-B119-4970-B652-826363055F7D}.Debug|x64.Build.0 = Debug|Any CPU
{54CD9E36-B119-4970-B652-826363055F7D}.Debug|x86.ActiveCfg = Debug|Any CPU
{54CD9E36-B119-4970-B652-826363055F7D}.Debug|x86.Build.0 = Debug|Any CPU
{54CD9E36-B119-4970-B652-826363055F7D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{54CD9E36-B119-4970-B652-826363055F7D}.Release|Any CPU.Build.0 = Release|Any CPU
{54CD9E36-B119-4970-B652-826363055F7D}.Release|x64.ActiveCfg = Release|Any CPU
{54CD9E36-B119-4970-B652-826363055F7D}.Release|x64.Build.0 = Release|Any CPU
{54CD9E36-B119-4970-B652-826363055F7D}.Release|x86.ActiveCfg = Release|Any CPU
{54CD9E36-B119-4970-B652-826363055F7D}.Release|x86.Build.0 = Release|Any CPU
{5CF1158D-64F6-4981-85CB-B43453A37329}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5CF1158D-64F6-4981-85CB-B43453A37329}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5CF1158D-64F6-4981-85CB-B43453A37329}.Debug|x64.ActiveCfg = Debug|Any CPU
{5CF1158D-64F6-4981-85CB-B43453A37329}.Debug|x64.Build.0 = Debug|Any CPU
{5CF1158D-64F6-4981-85CB-B43453A37329}.Debug|x86.ActiveCfg = Debug|Any CPU
{5CF1158D-64F6-4981-85CB-B43453A37329}.Debug|x86.Build.0 = Debug|Any CPU
{5CF1158D-64F6-4981-85CB-B43453A37329}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5CF1158D-64F6-4981-85CB-B43453A37329}.Release|Any CPU.Build.0 = Release|Any CPU
{5CF1158D-64F6-4981-85CB-B43453A37329}.Release|x64.ActiveCfg = Release|Any CPU
{5CF1158D-64F6-4981-85CB-B43453A37329}.Release|x64.Build.0 = Release|Any CPU
{5CF1158D-64F6-4981-85CB-B43453A37329}.Release|x86.ActiveCfg = Release|Any CPU
{5CF1158D-64F6-4981-85CB-B43453A37329}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{54CD9E36-B119-4970-B652-826363055F7D} = {41F15E67-7190-CF23-3BC4-77E87134CADD}
{5CF1158D-64F6-4981-85CB-B43453A37329} = {56BCE1BF-7CBA-7CE8-203D-A88051F1D642}
EndGlobalSection
EndGlobal

View File

@@ -1,25 +1,25 @@
using System.Collections.Immutable;
namespace StellaOps.Aoc;
public static class AocForbiddenKeys
{
private static readonly ImmutableHashSet<string> ForbiddenTopLevel = new[]
{
"severity",
"cvss",
"cvss_vector",
"effective_status",
"effective_range",
"merged_from",
"consensus_provider",
"reachability",
"asset_criticality",
"risk_score",
}.ToImmutableHashSet(StringComparer.OrdinalIgnoreCase);
public static bool IsForbiddenTopLevel(string propertyName) => ForbiddenTopLevel.Contains(propertyName);
public static bool IsDerivedField(string propertyName)
=> propertyName.StartsWith("effective_", StringComparison.OrdinalIgnoreCase);
}
using System.Collections.Immutable;
namespace StellaOps.Aoc;
public static class AocForbiddenKeys
{
private static readonly ImmutableHashSet<string> ForbiddenTopLevel = new[]
{
"severity",
"cvss",
"cvss_vector",
"effective_status",
"effective_range",
"merged_from",
"consensus_provider",
"reachability",
"asset_criticality",
"risk_score",
}.ToImmutableHashSet(StringComparer.OrdinalIgnoreCase);
public static bool IsForbiddenTopLevel(string propertyName) => ForbiddenTopLevel.Contains(propertyName);
public static bool IsDerivedField(string propertyName)
=> propertyName.StartsWith("effective_", StringComparison.OrdinalIgnoreCase);
}

View File

@@ -1,17 +1,17 @@
using System;
using System.Collections.Immutable;
namespace StellaOps.Aoc;
public sealed class AocGuardException : Exception
{
public AocGuardException(AocGuardResult result)
: base("AOC guard validation failed.")
{
Result = result ?? throw new ArgumentNullException(nameof(result));
}
public AocGuardResult Result { get; }
public ImmutableArray<AocViolation> Violations => Result.Violations;
}
using System;
using System.Collections.Immutable;
namespace StellaOps.Aoc;
public sealed class AocGuardException : Exception
{
public AocGuardException(AocGuardResult result)
: base("AOC guard validation failed.")
{
Result = result ?? throw new ArgumentNullException(nameof(result));
}
public AocGuardResult Result { get; }
public ImmutableArray<AocViolation> Violations => Result.Violations;
}

View File

@@ -1,22 +1,22 @@
using System.Text.Json;
namespace StellaOps.Aoc;
public static class AocGuardExtensions
{
public static AocGuardResult ValidateOrThrow(this IAocGuard guard, JsonElement document, AocGuardOptions? options = null)
{
if (guard is null)
{
throw new ArgumentNullException(nameof(guard));
}
var result = guard.Validate(document, options);
if (!result.IsValid)
{
throw new AocGuardException(result);
}
return result;
}
}
using System.Text.Json;
namespace StellaOps.Aoc;
public static class AocGuardExtensions
{
public static AocGuardResult ValidateOrThrow(this IAocGuard guard, JsonElement document, AocGuardOptions? options = null)
{
if (guard is null)
{
throw new ArgumentNullException(nameof(guard));
}
var result = guard.Validate(document, options);
if (!result.IsValid)
{
throw new AocGuardException(result);
}
return result;
}
}

View File

@@ -1,29 +1,29 @@
using System.Collections.Immutable;
namespace StellaOps.Aoc;
public sealed record AocGuardOptions
{
private static readonly ImmutableHashSet<string> DefaultRequiredTopLevel = new[]
{
"tenant",
"source",
"upstream",
"content",
"linkset",
}.ToImmutableHashSet(StringComparer.OrdinalIgnoreCase);
public static AocGuardOptions Default { get; } = new();
public ImmutableHashSet<string> RequiredTopLevelFields { get; init; } = DefaultRequiredTopLevel;
/// <summary>
/// When true, signature metadata is required under upstream.signature.
/// </summary>
public bool RequireSignatureMetadata { get; init; } = true;
/// <summary>
/// When true, tenant must be a non-empty string.
/// </summary>
public bool RequireTenant { get; init; } = true;
}
using System.Collections.Immutable;
namespace StellaOps.Aoc;
public sealed record AocGuardOptions
{
private static readonly ImmutableHashSet<string> DefaultRequiredTopLevel = new[]
{
"tenant",
"source",
"upstream",
"content",
"linkset",
}.ToImmutableHashSet(StringComparer.OrdinalIgnoreCase);
public static AocGuardOptions Default { get; } = new();
public ImmutableHashSet<string> RequiredTopLevelFields { get; init; } = DefaultRequiredTopLevel;
/// <summary>
/// When true, signature metadata is required under upstream.signature.
/// </summary>
public bool RequireSignatureMetadata { get; init; } = true;
/// <summary>
/// When true, tenant must be a non-empty string.
/// </summary>
public bool RequireTenant { get; init; } = true;
}

View File

@@ -1,14 +1,14 @@
using System.Collections.Immutable;
namespace StellaOps.Aoc;
public sealed record AocGuardResult(bool IsValid, ImmutableArray<AocViolation> Violations)
{
public static AocGuardResult Success { get; } = new(true, ImmutableArray<AocViolation>.Empty);
public static AocGuardResult FromViolations(IEnumerable<AocViolation> violations)
{
var array = violations.ToImmutableArray();
return array.IsDefaultOrEmpty ? Success : new(false, array);
}
}
using System.Collections.Immutable;
namespace StellaOps.Aoc;
public sealed record AocGuardResult(bool IsValid, ImmutableArray<AocViolation> Violations)
{
public static AocGuardResult Success { get; } = new(true, ImmutableArray<AocViolation>.Empty);
public static AocGuardResult FromViolations(IEnumerable<AocViolation> violations)
{
var array = violations.ToImmutableArray();
return array.IsDefaultOrEmpty ? Success : new(false, array);
}
}

View File

@@ -1,13 +1,13 @@
using System.Text.Json.Serialization;
namespace StellaOps.Aoc;
public sealed record AocViolation(
[property: JsonPropertyName("code")] AocViolationCode Code,
[property: JsonPropertyName("errorCode")] string ErrorCode,
[property: JsonPropertyName("path")] string Path,
[property: JsonPropertyName("message")] string Message)
{
public static AocViolation Create(AocViolationCode code, string path, string message)
=> new(code, code.ToErrorCode(), path, message);
}
using System.Text.Json.Serialization;
namespace StellaOps.Aoc;
public sealed record AocViolation(
[property: JsonPropertyName("code")] AocViolationCode Code,
[property: JsonPropertyName("errorCode")] string ErrorCode,
[property: JsonPropertyName("path")] string Path,
[property: JsonPropertyName("message")] string Message)
{
public static AocViolation Create(AocViolationCode code, string path, string message)
=> new(code, code.ToErrorCode(), path, message);
}

View File

@@ -1,34 +1,34 @@
namespace StellaOps.Aoc;
public enum AocViolationCode
{
None = 0,
ForbiddenField,
MergeAttempt,
IdempotencyViolation,
MissingProvenance,
SignatureInvalid,
DerivedFindingDetected,
UnknownField,
MissingRequiredField,
InvalidTenant,
InvalidSignatureMetadata,
}
public static class AocViolationCodeExtensions
{
public static string ToErrorCode(this AocViolationCode code) => code switch
{
AocViolationCode.ForbiddenField => "ERR_AOC_001",
AocViolationCode.MergeAttempt => "ERR_AOC_002",
AocViolationCode.IdempotencyViolation => "ERR_AOC_003",
AocViolationCode.MissingProvenance => "ERR_AOC_004",
AocViolationCode.SignatureInvalid => "ERR_AOC_005",
AocViolationCode.DerivedFindingDetected => "ERR_AOC_006",
AocViolationCode.UnknownField => "ERR_AOC_007",
AocViolationCode.MissingRequiredField => "ERR_AOC_004",
AocViolationCode.InvalidTenant => "ERR_AOC_004",
AocViolationCode.InvalidSignatureMetadata => "ERR_AOC_005",
_ => "ERR_AOC_000",
};
}
namespace StellaOps.Aoc;
public enum AocViolationCode
{
None = 0,
ForbiddenField,
MergeAttempt,
IdempotencyViolation,
MissingProvenance,
SignatureInvalid,
DerivedFindingDetected,
UnknownField,
MissingRequiredField,
InvalidTenant,
InvalidSignatureMetadata,
}
public static class AocViolationCodeExtensions
{
public static string ToErrorCode(this AocViolationCode code) => code switch
{
AocViolationCode.ForbiddenField => "ERR_AOC_001",
AocViolationCode.MergeAttempt => "ERR_AOC_002",
AocViolationCode.IdempotencyViolation => "ERR_AOC_003",
AocViolationCode.MissingProvenance => "ERR_AOC_004",
AocViolationCode.SignatureInvalid => "ERR_AOC_005",
AocViolationCode.DerivedFindingDetected => "ERR_AOC_006",
AocViolationCode.UnknownField => "ERR_AOC_007",
AocViolationCode.MissingRequiredField => "ERR_AOC_004",
AocViolationCode.InvalidTenant => "ERR_AOC_004",
AocViolationCode.InvalidSignatureMetadata => "ERR_AOC_005",
_ => "ERR_AOC_000",
};
}

View File

@@ -1,127 +1,127 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Text.Json;
namespace StellaOps.Aoc;
public interface IAocGuard
{
AocGuardResult Validate(JsonElement document, AocGuardOptions? options = null);
}
public sealed class AocWriteGuard : IAocGuard
{
public AocGuardResult Validate(JsonElement document, AocGuardOptions? options = null)
{
options ??= AocGuardOptions.Default;
var violations = ImmutableArray.CreateBuilder<AocViolation>();
var presentTopLevel = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (var property in document.EnumerateObject())
{
presentTopLevel.Add(property.Name);
if (AocForbiddenKeys.IsForbiddenTopLevel(property.Name))
{
violations.Add(AocViolation.Create(AocViolationCode.ForbiddenField, $"/{property.Name}", $"Field '{property.Name}' is forbidden in AOC documents."));
continue;
}
if (AocForbiddenKeys.IsDerivedField(property.Name))
{
violations.Add(AocViolation.Create(AocViolationCode.DerivedFindingDetected, $"/{property.Name}", $"Derived field '{property.Name}' must not be written during ingestion."));
}
}
foreach (var required in options.RequiredTopLevelFields)
{
if (!document.TryGetProperty(required, out var element) || element.ValueKind is JsonValueKind.Null or JsonValueKind.Undefined)
{
violations.Add(AocViolation.Create(AocViolationCode.MissingRequiredField, $"/{required}", $"Required field '{required}' is missing."));
continue;
}
if (options.RequireTenant && string.Equals(required, "tenant", StringComparison.OrdinalIgnoreCase))
{
if (element.ValueKind != JsonValueKind.String || string.IsNullOrWhiteSpace(element.GetString()))
{
violations.Add(AocViolation.Create(AocViolationCode.InvalidTenant, "/tenant", "Tenant must be a non-empty string."));
}
}
}
if (document.TryGetProperty("upstream", out var upstream) && upstream.ValueKind == JsonValueKind.Object)
{
if (!upstream.TryGetProperty("content_hash", out var contentHash) || contentHash.ValueKind != JsonValueKind.String || string.IsNullOrWhiteSpace(contentHash.GetString()))
{
violations.Add(AocViolation.Create(AocViolationCode.MissingProvenance, "/upstream/content_hash", "Upstream content hash is required."));
}
if (!upstream.TryGetProperty("signature", out var signature) || signature.ValueKind != JsonValueKind.Object)
{
if (options.RequireSignatureMetadata)
{
violations.Add(AocViolation.Create(AocViolationCode.MissingProvenance, "/upstream/signature", "Signature metadata is required."));
}
}
else if (options.RequireSignatureMetadata)
{
ValidateSignature(signature, violations);
}
}
else
{
violations.Add(AocViolation.Create(AocViolationCode.MissingRequiredField, "/upstream", "Upstream metadata is required."));
}
if (document.TryGetProperty("content", out var content) && content.ValueKind == JsonValueKind.Object)
{
if (!content.TryGetProperty("raw", out var raw) || raw.ValueKind is JsonValueKind.Null or JsonValueKind.Undefined)
{
violations.Add(AocViolation.Create(AocViolationCode.MissingProvenance, "/content/raw", "Raw upstream payload must be preserved."));
}
}
else
{
violations.Add(AocViolation.Create(AocViolationCode.MissingRequiredField, "/content", "Content metadata is required."));
}
if (!document.TryGetProperty("linkset", out var linkset) || linkset.ValueKind != JsonValueKind.Object)
{
violations.Add(AocViolation.Create(AocViolationCode.MissingRequiredField, "/linkset", "Linkset metadata is required."));
}
return AocGuardResult.FromViolations(violations);
}
private static void ValidateSignature(JsonElement signature, ImmutableArray<AocViolation>.Builder violations)
{
if (!signature.TryGetProperty("present", out var presentElement) || presentElement.ValueKind is not (JsonValueKind.True or JsonValueKind.False))
{
violations.Add(AocViolation.Create(AocViolationCode.InvalidSignatureMetadata, "/upstream/signature/present", "Signature metadata must include 'present' boolean."));
return;
}
var signaturePresent = presentElement.GetBoolean();
if (!signaturePresent)
{
return;
}
if (!signature.TryGetProperty("format", out var formatElement) || formatElement.ValueKind != JsonValueKind.String || string.IsNullOrWhiteSpace(formatElement.GetString()))
{
violations.Add(AocViolation.Create(AocViolationCode.InvalidSignatureMetadata, "/upstream/signature/format", "Signature format is required when signature is present."));
}
if (!signature.TryGetProperty("sig", out var sigElement) || sigElement.ValueKind != JsonValueKind.String || string.IsNullOrWhiteSpace(sigElement.GetString()))
{
violations.Add(AocViolation.Create(AocViolationCode.SignatureInvalid, "/upstream/signature/sig", "Signature payload is required when signature is present."));
}
if (!signature.TryGetProperty("key_id", out var keyIdElement) || keyIdElement.ValueKind != JsonValueKind.String || string.IsNullOrWhiteSpace(keyIdElement.GetString()))
{
violations.Add(AocViolation.Create(AocViolationCode.InvalidSignatureMetadata, "/upstream/signature/key_id", "Signature key identifier is required when signature is present."));
}
}
}
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Text.Json;
namespace StellaOps.Aoc;
public interface IAocGuard
{
AocGuardResult Validate(JsonElement document, AocGuardOptions? options = null);
}
public sealed class AocWriteGuard : IAocGuard
{
public AocGuardResult Validate(JsonElement document, AocGuardOptions? options = null)
{
options ??= AocGuardOptions.Default;
var violations = ImmutableArray.CreateBuilder<AocViolation>();
var presentTopLevel = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (var property in document.EnumerateObject())
{
presentTopLevel.Add(property.Name);
if (AocForbiddenKeys.IsForbiddenTopLevel(property.Name))
{
violations.Add(AocViolation.Create(AocViolationCode.ForbiddenField, $"/{property.Name}", $"Field '{property.Name}' is forbidden in AOC documents."));
continue;
}
if (AocForbiddenKeys.IsDerivedField(property.Name))
{
violations.Add(AocViolation.Create(AocViolationCode.DerivedFindingDetected, $"/{property.Name}", $"Derived field '{property.Name}' must not be written during ingestion."));
}
}
foreach (var required in options.RequiredTopLevelFields)
{
if (!document.TryGetProperty(required, out var element) || element.ValueKind is JsonValueKind.Null or JsonValueKind.Undefined)
{
violations.Add(AocViolation.Create(AocViolationCode.MissingRequiredField, $"/{required}", $"Required field '{required}' is missing."));
continue;
}
if (options.RequireTenant && string.Equals(required, "tenant", StringComparison.OrdinalIgnoreCase))
{
if (element.ValueKind != JsonValueKind.String || string.IsNullOrWhiteSpace(element.GetString()))
{
violations.Add(AocViolation.Create(AocViolationCode.InvalidTenant, "/tenant", "Tenant must be a non-empty string."));
}
}
}
if (document.TryGetProperty("upstream", out var upstream) && upstream.ValueKind == JsonValueKind.Object)
{
if (!upstream.TryGetProperty("content_hash", out var contentHash) || contentHash.ValueKind != JsonValueKind.String || string.IsNullOrWhiteSpace(contentHash.GetString()))
{
violations.Add(AocViolation.Create(AocViolationCode.MissingProvenance, "/upstream/content_hash", "Upstream content hash is required."));
}
if (!upstream.TryGetProperty("signature", out var signature) || signature.ValueKind != JsonValueKind.Object)
{
if (options.RequireSignatureMetadata)
{
violations.Add(AocViolation.Create(AocViolationCode.MissingProvenance, "/upstream/signature", "Signature metadata is required."));
}
}
else if (options.RequireSignatureMetadata)
{
ValidateSignature(signature, violations);
}
}
else
{
violations.Add(AocViolation.Create(AocViolationCode.MissingRequiredField, "/upstream", "Upstream metadata is required."));
}
if (document.TryGetProperty("content", out var content) && content.ValueKind == JsonValueKind.Object)
{
if (!content.TryGetProperty("raw", out var raw) || raw.ValueKind is JsonValueKind.Null or JsonValueKind.Undefined)
{
violations.Add(AocViolation.Create(AocViolationCode.MissingProvenance, "/content/raw", "Raw upstream payload must be preserved."));
}
}
else
{
violations.Add(AocViolation.Create(AocViolationCode.MissingRequiredField, "/content", "Content metadata is required."));
}
if (!document.TryGetProperty("linkset", out var linkset) || linkset.ValueKind != JsonValueKind.Object)
{
violations.Add(AocViolation.Create(AocViolationCode.MissingRequiredField, "/linkset", "Linkset metadata is required."));
}
return AocGuardResult.FromViolations(violations);
}
private static void ValidateSignature(JsonElement signature, ImmutableArray<AocViolation>.Builder violations)
{
if (!signature.TryGetProperty("present", out var presentElement) || presentElement.ValueKind is not (JsonValueKind.True or JsonValueKind.False))
{
violations.Add(AocViolation.Create(AocViolationCode.InvalidSignatureMetadata, "/upstream/signature/present", "Signature metadata must include 'present' boolean."));
return;
}
var signaturePresent = presentElement.GetBoolean();
if (!signaturePresent)
{
return;
}
if (!signature.TryGetProperty("format", out var formatElement) || formatElement.ValueKind != JsonValueKind.String || string.IsNullOrWhiteSpace(formatElement.GetString()))
{
violations.Add(AocViolation.Create(AocViolationCode.InvalidSignatureMetadata, "/upstream/signature/format", "Signature format is required when signature is present."));
}
if (!signature.TryGetProperty("sig", out var sigElement) || sigElement.ValueKind != JsonValueKind.String || string.IsNullOrWhiteSpace(sigElement.GetString()))
{
violations.Add(AocViolation.Create(AocViolationCode.SignatureInvalid, "/upstream/signature/sig", "Signature payload is required when signature is present."));
}
if (!signature.TryGetProperty("key_id", out var keyIdElement) || keyIdElement.ValueKind != JsonValueKind.String || string.IsNullOrWhiteSpace(keyIdElement.GetString()))
{
violations.Add(AocViolation.Create(AocViolationCode.InvalidSignatureMetadata, "/upstream/signature/key_id", "Signature key identifier is required when signature is present."));
}
}
}

View File

@@ -1,17 +1,17 @@
using Microsoft.Extensions.DependencyInjection;
namespace StellaOps.Aoc;
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddAocGuard(this IServiceCollection services)
{
if (services is null)
{
throw new ArgumentNullException(nameof(services));
}
services.AddSingleton<IAocGuard, AocWriteGuard>();
return services;
}
}
using Microsoft.Extensions.DependencyInjection;
namespace StellaOps.Aoc;
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddAocGuard(this IServiceCollection services)
{
if (services is null)
{
throw new ArgumentNullException(nameof(services));
}
services.AddSingleton<IAocGuard, AocWriteGuard>();
return services;
}
}

View File

@@ -1,12 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>preview</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.0-rc.2.25502.107" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>preview</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.0-rc.2.25502.107" />
</ItemGroup>
</Project>

View File

@@ -1,113 +1,113 @@
using System.Text.Json;
using StellaOps.Aoc;
namespace StellaOps.Aoc.Tests;
public sealed class AocWriteGuardTests
{
private static readonly AocWriteGuard Guard = new();
[Fact]
public void Validate_ReturnsSuccess_ForMinimalValidDocument()
{
using var document = JsonDocument.Parse("""
{
"tenant": "default",
"source": {"vendor": "osv"},
"upstream": {
"upstream_id": "GHSA-xxxx",
"content_hash": "sha256:abc",
"signature": { "present": false }
},
"content": {
"format": "OSV",
"raw": {"id": "GHSA-xxxx"}
},
"linkset": {}
}
""");
var result = Guard.Validate(document.RootElement);
Assert.True(result.IsValid);
Assert.Empty(result.Violations);
}
[Fact]
public void Validate_FlagsMissingTenant()
{
using var document = JsonDocument.Parse("""
{
"source": {"vendor": "osv"},
"upstream": {
"upstream_id": "GHSA-xxxx",
"content_hash": "sha256:abc",
"signature": { "present": false }
},
"content": {
"format": "OSV",
"raw": {"id": "GHSA-xxxx"}
},
"linkset": {}
}
""");
var result = Guard.Validate(document.RootElement);
Assert.False(result.IsValid);
Assert.Contains(result.Violations, v => v.ErrorCode == "ERR_AOC_004" && v.Path == "/tenant");
}
[Fact]
public void Validate_FlagsForbiddenField()
{
using var document = JsonDocument.Parse("""
{
"tenant": "default",
"severity": "high",
"source": {"vendor": "osv"},
"upstream": {
"upstream_id": "GHSA-xxxx",
"content_hash": "sha256:abc",
"signature": { "present": false }
},
"content": {
"format": "OSV",
"raw": {"id": "GHSA-xxxx"}
},
"linkset": {}
}
""");
var result = Guard.Validate(document.RootElement);
Assert.False(result.IsValid);
Assert.Contains(result.Violations, v => v.ErrorCode == "ERR_AOC_001" && v.Path == "/severity");
}
[Fact]
public void Validate_FlagsInvalidSignatureMetadata()
{
using var document = JsonDocument.Parse("""
{
"tenant": "default",
"source": {"vendor": "osv"},
"upstream": {
"upstream_id": "GHSA-xxxx",
"content_hash": "sha256:abc",
"signature": { "present": true, "format": "dsse" }
},
"content": {
"format": "OSV",
"raw": {"id": "GHSA-xxxx"}
},
"linkset": {}
}
""");
var result = Guard.Validate(document.RootElement);
Assert.False(result.IsValid);
Assert.Contains(result.Violations, v => v.ErrorCode == "ERR_AOC_005" && v.Path.Contains("/sig"));
}
}
using System.Text.Json;
using StellaOps.Aoc;
namespace StellaOps.Aoc.Tests;
public sealed class AocWriteGuardTests
{
private static readonly AocWriteGuard Guard = new();
[Fact]
public void Validate_ReturnsSuccess_ForMinimalValidDocument()
{
using var document = JsonDocument.Parse("""
{
"tenant": "default",
"source": {"vendor": "osv"},
"upstream": {
"upstream_id": "GHSA-xxxx",
"content_hash": "sha256:abc",
"signature": { "present": false }
},
"content": {
"format": "OSV",
"raw": {"id": "GHSA-xxxx"}
},
"linkset": {}
}
""");
var result = Guard.Validate(document.RootElement);
Assert.True(result.IsValid);
Assert.Empty(result.Violations);
}
[Fact]
public void Validate_FlagsMissingTenant()
{
using var document = JsonDocument.Parse("""
{
"source": {"vendor": "osv"},
"upstream": {
"upstream_id": "GHSA-xxxx",
"content_hash": "sha256:abc",
"signature": { "present": false }
},
"content": {
"format": "OSV",
"raw": {"id": "GHSA-xxxx"}
},
"linkset": {}
}
""");
var result = Guard.Validate(document.RootElement);
Assert.False(result.IsValid);
Assert.Contains(result.Violations, v => v.ErrorCode == "ERR_AOC_004" && v.Path == "/tenant");
}
[Fact]
public void Validate_FlagsForbiddenField()
{
using var document = JsonDocument.Parse("""
{
"tenant": "default",
"severity": "high",
"source": {"vendor": "osv"},
"upstream": {
"upstream_id": "GHSA-xxxx",
"content_hash": "sha256:abc",
"signature": { "present": false }
},
"content": {
"format": "OSV",
"raw": {"id": "GHSA-xxxx"}
},
"linkset": {}
}
""");
var result = Guard.Validate(document.RootElement);
Assert.False(result.IsValid);
Assert.Contains(result.Violations, v => v.ErrorCode == "ERR_AOC_001" && v.Path == "/severity");
}
[Fact]
public void Validate_FlagsInvalidSignatureMetadata()
{
using var document = JsonDocument.Parse("""
{
"tenant": "default",
"source": {"vendor": "osv"},
"upstream": {
"upstream_id": "GHSA-xxxx",
"content_hash": "sha256:abc",
"signature": { "present": true, "format": "dsse" }
},
"content": {
"format": "OSV",
"raw": {"id": "GHSA-xxxx"}
},
"linkset": {}
}
""");
var result = Guard.Validate(document.RootElement);
Assert.False(result.IsValid);
Assert.Contains(result.Violations, v => v.ErrorCode == "ERR_AOC_005" && v.Path.Contains("/sig"));
}
}

View File

@@ -0,0 +1,42 @@
<?xml version='1.0' encoding='utf-8'?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>preview</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<OutputType>Exe</OutputType>
<IsPackable>false</IsPackable>
<UseConcelierTestInfra>false</UseConcelierTestInfra>
</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="../../__Libraries/StellaOps.Aoc/StellaOps.Aoc.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,10 +1,10 @@
namespace StellaOps.Aoc.Tests;
public class UnitTest1
{
[Fact]
public void Test1()
{
}
}
namespace StellaOps.Aoc.Tests;
public class UnitTest1
{
[Fact]
public void Test1()
{
}
}

View File

@@ -1,15 +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`.
# 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`.

View File

@@ -10,7 +10,7 @@
| 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. |
| APIGOV-62-002 | TODO | API Governance Guild, DevOps Guild | APIGOV-62-001 | Automate changelog generation and publish signed artifacts to `src/Sdk/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 |

View File

@@ -4,8 +4,8 @@
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`.
- Author and review per-service OAS documents in `src/Api/StellaOps.Api.OpenApi/<service>/openapi.yaml`.
- Operate the aggregate composer producing `src/Api/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.

View File

@@ -1,19 +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. |
# 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. |

View File

@@ -1,15 +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.
# 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.

View File

@@ -1,13 +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. |
# 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. |

View File

@@ -1,14 +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.
# 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.

View File

@@ -1,13 +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. |
# 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. |

View File

@@ -1,14 +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.
# 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.

View File

@@ -1,13 +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. |
# 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. |

View File

@@ -0,0 +1,182 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StellaOps.Attestor", "StellaOps.Attestor", "{78C966F5-2242-D8EC-ADCA-A1A9C7F723A6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Attestor.Core", "StellaOps.Attestor\StellaOps.Attestor.Core\StellaOps.Attestor.Core.csproj", "{D44872A3-772A-43D7-B340-61253543F02B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Attestor.Infrastructure", "StellaOps.Attestor\StellaOps.Attestor.Infrastructure\StellaOps.Attestor.Infrastructure.csproj", "{BFADAB55-9D9D-456F-987B-A4536027BA77}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Attestor.Tests", "StellaOps.Attestor\StellaOps.Attestor.Tests\StellaOps.Attestor.Tests.csproj", "{E2546302-F0CD-43E6-9CD6-D4B5E711454C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Attestor.WebService", "StellaOps.Attestor\StellaOps.Attestor.WebService\StellaOps.Attestor.WebService.csproj", "{39CCDD3E-5802-4E72-BE0F-25F7172C74E6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Configuration", "..\__Libraries\StellaOps.Configuration\StellaOps.Configuration.csproj", "{0792B7D7-E298-4639-B3DC-AFAF427810E9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Authority.Plugins.Abstractions", "..\Authority\StellaOps.Authority\StellaOps.Authority.Plugins.Abstractions\StellaOps.Authority.Plugins.Abstractions.csproj", "{E93D1212-2745-4AD7-AD42-7666952A60C5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Cryptography", "..\__Libraries\StellaOps.Cryptography\StellaOps.Cryptography.csproj", "{9AE76C3A-0712-4DDA-A751-D0E8D59BD7A1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Auth.Abstractions", "..\Authority\StellaOps.Authority\StellaOps.Auth.Abstractions\StellaOps.Auth.Abstractions.csproj", "{ED2AB277-AA70-4593-869A-BB13DA55FD12}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.DependencyInjection", "..\__Libraries\StellaOps.DependencyInjection\StellaOps.DependencyInjection.csproj", "{6E844D37-2714-496B-8557-8FA2BF1744E8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Auth.Client", "..\Authority\StellaOps.Authority\StellaOps.Auth.Client\StellaOps.Auth.Client.csproj", "{44EB6890-FB96-405B-8CEC-A1EEB38474CE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Auth.ServerIntegration", "..\Authority\StellaOps.Authority\StellaOps.Auth.ServerIntegration\StellaOps.Auth.ServerIntegration.csproj", "{36FBCE51-0429-4F2B-87FD-95B37941001D}"
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
{D44872A3-772A-43D7-B340-61253543F02B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D44872A3-772A-43D7-B340-61253543F02B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D44872A3-772A-43D7-B340-61253543F02B}.Debug|x64.ActiveCfg = Debug|Any CPU
{D44872A3-772A-43D7-B340-61253543F02B}.Debug|x64.Build.0 = Debug|Any CPU
{D44872A3-772A-43D7-B340-61253543F02B}.Debug|x86.ActiveCfg = Debug|Any CPU
{D44872A3-772A-43D7-B340-61253543F02B}.Debug|x86.Build.0 = Debug|Any CPU
{D44872A3-772A-43D7-B340-61253543F02B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D44872A3-772A-43D7-B340-61253543F02B}.Release|Any CPU.Build.0 = Release|Any CPU
{D44872A3-772A-43D7-B340-61253543F02B}.Release|x64.ActiveCfg = Release|Any CPU
{D44872A3-772A-43D7-B340-61253543F02B}.Release|x64.Build.0 = Release|Any CPU
{D44872A3-772A-43D7-B340-61253543F02B}.Release|x86.ActiveCfg = Release|Any CPU
{D44872A3-772A-43D7-B340-61253543F02B}.Release|x86.Build.0 = Release|Any CPU
{BFADAB55-9D9D-456F-987B-A4536027BA77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BFADAB55-9D9D-456F-987B-A4536027BA77}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BFADAB55-9D9D-456F-987B-A4536027BA77}.Debug|x64.ActiveCfg = Debug|Any CPU
{BFADAB55-9D9D-456F-987B-A4536027BA77}.Debug|x64.Build.0 = Debug|Any CPU
{BFADAB55-9D9D-456F-987B-A4536027BA77}.Debug|x86.ActiveCfg = Debug|Any CPU
{BFADAB55-9D9D-456F-987B-A4536027BA77}.Debug|x86.Build.0 = Debug|Any CPU
{BFADAB55-9D9D-456F-987B-A4536027BA77}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BFADAB55-9D9D-456F-987B-A4536027BA77}.Release|Any CPU.Build.0 = Release|Any CPU
{BFADAB55-9D9D-456F-987B-A4536027BA77}.Release|x64.ActiveCfg = Release|Any CPU
{BFADAB55-9D9D-456F-987B-A4536027BA77}.Release|x64.Build.0 = Release|Any CPU
{BFADAB55-9D9D-456F-987B-A4536027BA77}.Release|x86.ActiveCfg = Release|Any CPU
{BFADAB55-9D9D-456F-987B-A4536027BA77}.Release|x86.Build.0 = Release|Any CPU
{E2546302-F0CD-43E6-9CD6-D4B5E711454C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E2546302-F0CD-43E6-9CD6-D4B5E711454C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E2546302-F0CD-43E6-9CD6-D4B5E711454C}.Debug|x64.ActiveCfg = Debug|Any CPU
{E2546302-F0CD-43E6-9CD6-D4B5E711454C}.Debug|x64.Build.0 = Debug|Any CPU
{E2546302-F0CD-43E6-9CD6-D4B5E711454C}.Debug|x86.ActiveCfg = Debug|Any CPU
{E2546302-F0CD-43E6-9CD6-D4B5E711454C}.Debug|x86.Build.0 = Debug|Any CPU
{E2546302-F0CD-43E6-9CD6-D4B5E711454C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E2546302-F0CD-43E6-9CD6-D4B5E711454C}.Release|Any CPU.Build.0 = Release|Any CPU
{E2546302-F0CD-43E6-9CD6-D4B5E711454C}.Release|x64.ActiveCfg = Release|Any CPU
{E2546302-F0CD-43E6-9CD6-D4B5E711454C}.Release|x64.Build.0 = Release|Any CPU
{E2546302-F0CD-43E6-9CD6-D4B5E711454C}.Release|x86.ActiveCfg = Release|Any CPU
{E2546302-F0CD-43E6-9CD6-D4B5E711454C}.Release|x86.Build.0 = Release|Any CPU
{39CCDD3E-5802-4E72-BE0F-25F7172C74E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{39CCDD3E-5802-4E72-BE0F-25F7172C74E6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{39CCDD3E-5802-4E72-BE0F-25F7172C74E6}.Debug|x64.ActiveCfg = Debug|Any CPU
{39CCDD3E-5802-4E72-BE0F-25F7172C74E6}.Debug|x64.Build.0 = Debug|Any CPU
{39CCDD3E-5802-4E72-BE0F-25F7172C74E6}.Debug|x86.ActiveCfg = Debug|Any CPU
{39CCDD3E-5802-4E72-BE0F-25F7172C74E6}.Debug|x86.Build.0 = Debug|Any CPU
{39CCDD3E-5802-4E72-BE0F-25F7172C74E6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{39CCDD3E-5802-4E72-BE0F-25F7172C74E6}.Release|Any CPU.Build.0 = Release|Any CPU
{39CCDD3E-5802-4E72-BE0F-25F7172C74E6}.Release|x64.ActiveCfg = Release|Any CPU
{39CCDD3E-5802-4E72-BE0F-25F7172C74E6}.Release|x64.Build.0 = Release|Any CPU
{39CCDD3E-5802-4E72-BE0F-25F7172C74E6}.Release|x86.ActiveCfg = Release|Any CPU
{39CCDD3E-5802-4E72-BE0F-25F7172C74E6}.Release|x86.Build.0 = Release|Any CPU
{0792B7D7-E298-4639-B3DC-AFAF427810E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0792B7D7-E298-4639-B3DC-AFAF427810E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0792B7D7-E298-4639-B3DC-AFAF427810E9}.Debug|x64.ActiveCfg = Debug|Any CPU
{0792B7D7-E298-4639-B3DC-AFAF427810E9}.Debug|x64.Build.0 = Debug|Any CPU
{0792B7D7-E298-4639-B3DC-AFAF427810E9}.Debug|x86.ActiveCfg = Debug|Any CPU
{0792B7D7-E298-4639-B3DC-AFAF427810E9}.Debug|x86.Build.0 = Debug|Any CPU
{0792B7D7-E298-4639-B3DC-AFAF427810E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0792B7D7-E298-4639-B3DC-AFAF427810E9}.Release|Any CPU.Build.0 = Release|Any CPU
{0792B7D7-E298-4639-B3DC-AFAF427810E9}.Release|x64.ActiveCfg = Release|Any CPU
{0792B7D7-E298-4639-B3DC-AFAF427810E9}.Release|x64.Build.0 = Release|Any CPU
{0792B7D7-E298-4639-B3DC-AFAF427810E9}.Release|x86.ActiveCfg = Release|Any CPU
{0792B7D7-E298-4639-B3DC-AFAF427810E9}.Release|x86.Build.0 = Release|Any CPU
{E93D1212-2745-4AD7-AD42-7666952A60C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E93D1212-2745-4AD7-AD42-7666952A60C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E93D1212-2745-4AD7-AD42-7666952A60C5}.Debug|x64.ActiveCfg = Debug|Any CPU
{E93D1212-2745-4AD7-AD42-7666952A60C5}.Debug|x64.Build.0 = Debug|Any CPU
{E93D1212-2745-4AD7-AD42-7666952A60C5}.Debug|x86.ActiveCfg = Debug|Any CPU
{E93D1212-2745-4AD7-AD42-7666952A60C5}.Debug|x86.Build.0 = Debug|Any CPU
{E93D1212-2745-4AD7-AD42-7666952A60C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E93D1212-2745-4AD7-AD42-7666952A60C5}.Release|Any CPU.Build.0 = Release|Any CPU
{E93D1212-2745-4AD7-AD42-7666952A60C5}.Release|x64.ActiveCfg = Release|Any CPU
{E93D1212-2745-4AD7-AD42-7666952A60C5}.Release|x64.Build.0 = Release|Any CPU
{E93D1212-2745-4AD7-AD42-7666952A60C5}.Release|x86.ActiveCfg = Release|Any CPU
{E93D1212-2745-4AD7-AD42-7666952A60C5}.Release|x86.Build.0 = Release|Any CPU
{9AE76C3A-0712-4DDA-A751-D0E8D59BD7A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9AE76C3A-0712-4DDA-A751-D0E8D59BD7A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9AE76C3A-0712-4DDA-A751-D0E8D59BD7A1}.Debug|x64.ActiveCfg = Debug|Any CPU
{9AE76C3A-0712-4DDA-A751-D0E8D59BD7A1}.Debug|x64.Build.0 = Debug|Any CPU
{9AE76C3A-0712-4DDA-A751-D0E8D59BD7A1}.Debug|x86.ActiveCfg = Debug|Any CPU
{9AE76C3A-0712-4DDA-A751-D0E8D59BD7A1}.Debug|x86.Build.0 = Debug|Any CPU
{9AE76C3A-0712-4DDA-A751-D0E8D59BD7A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9AE76C3A-0712-4DDA-A751-D0E8D59BD7A1}.Release|Any CPU.Build.0 = Release|Any CPU
{9AE76C3A-0712-4DDA-A751-D0E8D59BD7A1}.Release|x64.ActiveCfg = Release|Any CPU
{9AE76C3A-0712-4DDA-A751-D0E8D59BD7A1}.Release|x64.Build.0 = Release|Any CPU
{9AE76C3A-0712-4DDA-A751-D0E8D59BD7A1}.Release|x86.ActiveCfg = Release|Any CPU
{9AE76C3A-0712-4DDA-A751-D0E8D59BD7A1}.Release|x86.Build.0 = Release|Any CPU
{ED2AB277-AA70-4593-869A-BB13DA55FD12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ED2AB277-AA70-4593-869A-BB13DA55FD12}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ED2AB277-AA70-4593-869A-BB13DA55FD12}.Debug|x64.ActiveCfg = Debug|Any CPU
{ED2AB277-AA70-4593-869A-BB13DA55FD12}.Debug|x64.Build.0 = Debug|Any CPU
{ED2AB277-AA70-4593-869A-BB13DA55FD12}.Debug|x86.ActiveCfg = Debug|Any CPU
{ED2AB277-AA70-4593-869A-BB13DA55FD12}.Debug|x86.Build.0 = Debug|Any CPU
{ED2AB277-AA70-4593-869A-BB13DA55FD12}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ED2AB277-AA70-4593-869A-BB13DA55FD12}.Release|Any CPU.Build.0 = Release|Any CPU
{ED2AB277-AA70-4593-869A-BB13DA55FD12}.Release|x64.ActiveCfg = Release|Any CPU
{ED2AB277-AA70-4593-869A-BB13DA55FD12}.Release|x64.Build.0 = Release|Any CPU
{ED2AB277-AA70-4593-869A-BB13DA55FD12}.Release|x86.ActiveCfg = Release|Any CPU
{ED2AB277-AA70-4593-869A-BB13DA55FD12}.Release|x86.Build.0 = Release|Any CPU
{6E844D37-2714-496B-8557-8FA2BF1744E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6E844D37-2714-496B-8557-8FA2BF1744E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6E844D37-2714-496B-8557-8FA2BF1744E8}.Debug|x64.ActiveCfg = Debug|Any CPU
{6E844D37-2714-496B-8557-8FA2BF1744E8}.Debug|x64.Build.0 = Debug|Any CPU
{6E844D37-2714-496B-8557-8FA2BF1744E8}.Debug|x86.ActiveCfg = Debug|Any CPU
{6E844D37-2714-496B-8557-8FA2BF1744E8}.Debug|x86.Build.0 = Debug|Any CPU
{6E844D37-2714-496B-8557-8FA2BF1744E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6E844D37-2714-496B-8557-8FA2BF1744E8}.Release|Any CPU.Build.0 = Release|Any CPU
{6E844D37-2714-496B-8557-8FA2BF1744E8}.Release|x64.ActiveCfg = Release|Any CPU
{6E844D37-2714-496B-8557-8FA2BF1744E8}.Release|x64.Build.0 = Release|Any CPU
{6E844D37-2714-496B-8557-8FA2BF1744E8}.Release|x86.ActiveCfg = Release|Any CPU
{6E844D37-2714-496B-8557-8FA2BF1744E8}.Release|x86.Build.0 = Release|Any CPU
{44EB6890-FB96-405B-8CEC-A1EEB38474CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{44EB6890-FB96-405B-8CEC-A1EEB38474CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{44EB6890-FB96-405B-8CEC-A1EEB38474CE}.Debug|x64.ActiveCfg = Debug|Any CPU
{44EB6890-FB96-405B-8CEC-A1EEB38474CE}.Debug|x64.Build.0 = Debug|Any CPU
{44EB6890-FB96-405B-8CEC-A1EEB38474CE}.Debug|x86.ActiveCfg = Debug|Any CPU
{44EB6890-FB96-405B-8CEC-A1EEB38474CE}.Debug|x86.Build.0 = Debug|Any CPU
{44EB6890-FB96-405B-8CEC-A1EEB38474CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{44EB6890-FB96-405B-8CEC-A1EEB38474CE}.Release|Any CPU.Build.0 = Release|Any CPU
{44EB6890-FB96-405B-8CEC-A1EEB38474CE}.Release|x64.ActiveCfg = Release|Any CPU
{44EB6890-FB96-405B-8CEC-A1EEB38474CE}.Release|x64.Build.0 = Release|Any CPU
{44EB6890-FB96-405B-8CEC-A1EEB38474CE}.Release|x86.ActiveCfg = Release|Any CPU
{44EB6890-FB96-405B-8CEC-A1EEB38474CE}.Release|x86.Build.0 = Release|Any CPU
{36FBCE51-0429-4F2B-87FD-95B37941001D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{36FBCE51-0429-4F2B-87FD-95B37941001D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{36FBCE51-0429-4F2B-87FD-95B37941001D}.Debug|x64.ActiveCfg = Debug|Any CPU
{36FBCE51-0429-4F2B-87FD-95B37941001D}.Debug|x64.Build.0 = Debug|Any CPU
{36FBCE51-0429-4F2B-87FD-95B37941001D}.Debug|x86.ActiveCfg = Debug|Any CPU
{36FBCE51-0429-4F2B-87FD-95B37941001D}.Debug|x86.Build.0 = Debug|Any CPU
{36FBCE51-0429-4F2B-87FD-95B37941001D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{36FBCE51-0429-4F2B-87FD-95B37941001D}.Release|Any CPU.Build.0 = Release|Any CPU
{36FBCE51-0429-4F2B-87FD-95B37941001D}.Release|x64.ActiveCfg = Release|Any CPU
{36FBCE51-0429-4F2B-87FD-95B37941001D}.Release|x64.Build.0 = Release|Any CPU
{36FBCE51-0429-4F2B-87FD-95B37941001D}.Release|x86.ActiveCfg = Release|Any CPU
{36FBCE51-0429-4F2B-87FD-95B37941001D}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{D44872A3-772A-43D7-B340-61253543F02B} = {78C966F5-2242-D8EC-ADCA-A1A9C7F723A6}
{BFADAB55-9D9D-456F-987B-A4536027BA77} = {78C966F5-2242-D8EC-ADCA-A1A9C7F723A6}
{E2546302-F0CD-43E6-9CD6-D4B5E711454C} = {78C966F5-2242-D8EC-ADCA-A1A9C7F723A6}
{39CCDD3E-5802-4E72-BE0F-25F7172C74E6} = {78C966F5-2242-D8EC-ADCA-A1A9C7F723A6}
EndGlobalSection
EndGlobal

View File

@@ -1,24 +1,24 @@
# Attestor Guild
## Mission
Operate the StellaOps Attestor service: accept signed DSSE envelopes from the Signer over mTLS, submit them to Rekor v2, persist inclusion proofs, and expose verification APIs for downstream services and operators.
## Teams On Call
- Team 11 (Attestor API)
- Team 12 (Attestor Observability) — partners on logging, metrics, and alerting
## Operating Principles
- Enforce mTLS + Authority tokens for every submission; never accept anonymous callers.
- Deterministic hashing, canonical JSON, and idempotent Rekor interactions (`bundleSha256` is the source of truth).
- Persist everything (entries, dedupe, audit) before acknowledging; background jobs must be resumable.
- Structured logs + metrics for each stage (`validate`, `submit`, `proof`, `persist`, `archive`).
- Update `TASKS.md`, architecture docs, and tests whenever behaviour changes.
# Attestor Guild
## Mission
Operate the StellaOps Attestor service: accept signed DSSE envelopes from the Signer over mTLS, submit them to Rekor v2, persist inclusion proofs, and expose verification APIs for downstream services and operators.
## Teams On Call
- Team 11 (Attestor API)
- Team 12 (Attestor Observability) — partners on logging, metrics, and alerting
## Operating Principles
- Enforce mTLS + Authority tokens for every submission; never accept anonymous callers.
- Deterministic hashing, canonical JSON, and idempotent Rekor interactions (`bundleSha256` is the source of truth).
- Persist everything (entries, dedupe, audit) before acknowledging; background jobs must be resumable.
- 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.
- `src/Attestor/StellaOps.Attestor/StellaOps.Attestor.WebService/` — Minimal API host and HTTP surface.
- `src/Attestor/StellaOps.Attestor/StellaOps.Attestor.Core/` — Domain contracts, submission/verification pipelines.
- `src/Attestor/StellaOps.Attestor/StellaOps.Attestor.Infrastructure/` — Mongo, Redis, Rekor, and archival implementations.
- `src/Attestor/StellaOps.Attestor/StellaOps.Attestor.Tests/` — Unit and integration tests.
---

View File

@@ -1,21 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>preview</LangVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\StellaOps.Attestor.Core\StellaOps.Attestor.Core.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.0-rc.2.25502.107" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.0-rc.2.25502.107" />
<PackageReference Include="Microsoft.Extensions.Options" Version="10.0.0-rc.2.25502.107" />
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.0-rc.2.25502.107" />
<PackageReference Include="MongoDB.Driver" Version="3.5.0" />
<PackageReference Include="StackExchange.Redis" Version="2.8.24" />
<PackageReference Include="AWSSDK.S3" Version="3.7.307.6" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>preview</LangVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\StellaOps.Attestor.Core\StellaOps.Attestor.Core.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.0-rc.2.25502.107" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.0-rc.2.25502.107" />
<PackageReference Include="Microsoft.Extensions.Options" Version="10.0.0-rc.2.25502.107" />
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.0-rc.2.25502.107" />
<PackageReference Include="MongoDB.Driver" Version="3.5.0" />
<PackageReference Include="StackExchange.Redis" Version="2.8.24" />
<PackageReference Include="AWSSDK.S3" Version="3.7.307.6" />
</ItemGroup>
</Project>

View File

@@ -1,3 +1,4 @@
<?xml version='1.0' encoding='utf-8'?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
@@ -19,7 +20,7 @@
<ProjectReference Include="..\StellaOps.Attestor.WebService\StellaOps.Attestor.WebService.csproj" />
<ProjectReference Include="..\StellaOps.Attestor.Infrastructure\StellaOps.Attestor.Infrastructure.csproj" />
<ProjectReference Include="..\StellaOps.Attestor.Core\StellaOps.Attestor.Core.csproj" />
<ProjectReference Include="..\..\StellaOps.Configuration\StellaOps.Configuration.csproj" />
<ProjectReference Include="..\..\StellaOps.DependencyInjection\StellaOps.DependencyInjection.csproj" />
<ProjectReference Include="../../../__Libraries/StellaOps.Configuration/StellaOps.Configuration.csproj" />
<ProjectReference Include="../../../__Libraries/StellaOps.DependencyInjection/StellaOps.DependencyInjection.csproj" />
</ItemGroup>
</Project>
</Project>

View File

@@ -1,3 +1,4 @@
<?xml version='1.0' encoding='utf-8'?>
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
@@ -20,11 +21,11 @@
<ItemGroup>
<ProjectReference Include="..\StellaOps.Attestor.Core\StellaOps.Attestor.Core.csproj" />
<ProjectReference Include="..\StellaOps.Attestor.Infrastructure\StellaOps.Attestor.Infrastructure.csproj" />
<ProjectReference Include="..\..\StellaOps.Configuration\StellaOps.Configuration.csproj" />
<ProjectReference Include="..\..\StellaOps.DependencyInjection\StellaOps.DependencyInjection.csproj" />
<ProjectReference Include="..\..\StellaOps.Cryptography\StellaOps.Cryptography.csproj" />
<ProjectReference Include="..\..\StellaOps.Authority\StellaOps.Auth.Abstractions\StellaOps.Auth.Abstractions.csproj" />
<ProjectReference Include="..\..\StellaOps.Authority\StellaOps.Auth.Client\StellaOps.Auth.Client.csproj" />
<ProjectReference Include="..\..\StellaOps.Authority\StellaOps.Auth.ServerIntegration\StellaOps.Auth.ServerIntegration.csproj" />
<ProjectReference Include="../../../__Libraries/StellaOps.Configuration/StellaOps.Configuration.csproj" />
<ProjectReference Include="../../../__Libraries/StellaOps.DependencyInjection/StellaOps.DependencyInjection.csproj" />
<ProjectReference Include="../../../__Libraries/StellaOps.Cryptography/StellaOps.Cryptography.csproj" />
<ProjectReference Include="../../../Authority/StellaOps.Authority/StellaOps.Auth.Abstractions/StellaOps.Auth.Abstractions.csproj" />
<ProjectReference Include="../../../Authority/StellaOps.Authority/StellaOps.Auth.Client/StellaOps.Auth.Client.csproj" />
<ProjectReference Include="../../../Authority/StellaOps.Authority/StellaOps.Auth.ServerIntegration/StellaOps.Auth.ServerIntegration.csproj" />
</ItemGroup>
</Project>
</Project>

View File

@@ -0,0 +1,303 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StellaOps.Authority", "StellaOps.Authority", "{BDB24B64-FE4E-C4BD-9F80-9428F98EDF6F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Auth.Abstractions", "StellaOps.Authority\StellaOps.Auth.Abstractions\StellaOps.Auth.Abstractions.csproj", "{336F7E73-0D75-4308-A20B-E8AB7964D27C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Auth.Abstractions.Tests", "StellaOps.Authority\StellaOps.Auth.Abstractions.Tests\StellaOps.Auth.Abstractions.Tests.csproj", "{CD7D0B36-386B-455D-A14B-E7857C255C42}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Auth.Client", "StellaOps.Authority\StellaOps.Auth.Client\StellaOps.Auth.Client.csproj", "{F2CEB8F7-C65B-407E-A11F-B02A39237355}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Configuration", "..\__Libraries\StellaOps.Configuration\StellaOps.Configuration.csproj", "{BF48C3E7-E1E8-4869-973F-22554F146FCE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Authority.Plugins.Abstractions", "StellaOps.Authority\StellaOps.Authority.Plugins.Abstractions\StellaOps.Authority.Plugins.Abstractions.csproj", "{91C7B100-D04A-4486-8A26-9D55234876D7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Cryptography", "..\__Libraries\StellaOps.Cryptography\StellaOps.Cryptography.csproj", "{00E2F0AF-32EC-4755-81AD-907532F48BBB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Auth.Client.Tests", "StellaOps.Authority\StellaOps.Auth.Client.Tests\StellaOps.Auth.Client.Tests.csproj", "{2346E499-C1F4-46C5-BB03-859FC56881D4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Auth.ServerIntegration", "StellaOps.Authority\StellaOps.Auth.ServerIntegration\StellaOps.Auth.ServerIntegration.csproj", "{412DAFA7-FDEA-418C-995B-7C7F51D89E00}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.DependencyInjection", "..\__Libraries\StellaOps.DependencyInjection\StellaOps.DependencyInjection.csproj", "{79CB2323-2370-419A-8B22-A193B3F3CE68}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Auth.ServerIntegration.Tests", "StellaOps.Authority\StellaOps.Auth.ServerIntegration.Tests\StellaOps.Auth.ServerIntegration.Tests.csproj", "{BE1E685F-33D8-47E5-B4FA-BC4DDED255D3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Authority", "StellaOps.Authority\StellaOps.Authority\StellaOps.Authority.csproj", "{614EDC46-4654-40F7-A779-8F127B8FD956}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Authority.Plugin.Standard", "StellaOps.Authority\StellaOps.Authority.Plugin.Standard\StellaOps.Authority.Plugin.Standard.csproj", "{4B12E120-E39B-44A7-A25E-D3151D5AE914}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Plugin", "..\__Libraries\StellaOps.Plugin\StellaOps.Plugin.csproj", "{7F9552C7-7E41-4EA6-9F5E-17E8049C9F10}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Authority.Storage.Mongo", "StellaOps.Authority\StellaOps.Authority.Storage.Mongo\StellaOps.Authority.Storage.Mongo.csproj", "{1FFF91AB-C2D2-4A12-A77B-AB9806116F7A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Cryptography.DependencyInjection", "..\__Libraries\StellaOps.Cryptography.DependencyInjection\StellaOps.Cryptography.DependencyInjection.csproj", "{208FE840-FFDD-43A5-9F64-F1F3C45C51F7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Auth.Security", "..\__Libraries\StellaOps.Auth.Security\StellaOps.Auth.Security.csproj", "{6EE9BB3A-A55F-4FDC-95F1-9304DB341AB1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Authority.Plugin.Standard.Tests", "StellaOps.Authority\StellaOps.Authority.Plugin.Standard.Tests\StellaOps.Authority.Plugin.Standard.Tests.csproj", "{168986E2-E127-4E03-BE45-4CC306E4E880}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Authority.Plugins.Abstractions.Tests", "StellaOps.Authority\StellaOps.Authority.Plugins.Abstractions.Tests\StellaOps.Authority.Plugins.Abstractions.Tests.csproj", "{A461EFE2-CBB1-4650-9CA0-05CECFAC3AE3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Authority.Tests", "StellaOps.Authority\StellaOps.Authority.Tests\StellaOps.Authority.Tests.csproj", "{24BBDF59-7B30-4620-8464-BDACB1AEF49D}"
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
{336F7E73-0D75-4308-A20B-E8AB7964D27C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{336F7E73-0D75-4308-A20B-E8AB7964D27C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{336F7E73-0D75-4308-A20B-E8AB7964D27C}.Debug|x64.ActiveCfg = Debug|Any CPU
{336F7E73-0D75-4308-A20B-E8AB7964D27C}.Debug|x64.Build.0 = Debug|Any CPU
{336F7E73-0D75-4308-A20B-E8AB7964D27C}.Debug|x86.ActiveCfg = Debug|Any CPU
{336F7E73-0D75-4308-A20B-E8AB7964D27C}.Debug|x86.Build.0 = Debug|Any CPU
{336F7E73-0D75-4308-A20B-E8AB7964D27C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{336F7E73-0D75-4308-A20B-E8AB7964D27C}.Release|Any CPU.Build.0 = Release|Any CPU
{336F7E73-0D75-4308-A20B-E8AB7964D27C}.Release|x64.ActiveCfg = Release|Any CPU
{336F7E73-0D75-4308-A20B-E8AB7964D27C}.Release|x64.Build.0 = Release|Any CPU
{336F7E73-0D75-4308-A20B-E8AB7964D27C}.Release|x86.ActiveCfg = Release|Any CPU
{336F7E73-0D75-4308-A20B-E8AB7964D27C}.Release|x86.Build.0 = Release|Any CPU
{CD7D0B36-386B-455D-A14B-E7857C255C42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CD7D0B36-386B-455D-A14B-E7857C255C42}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CD7D0B36-386B-455D-A14B-E7857C255C42}.Debug|x64.ActiveCfg = Debug|Any CPU
{CD7D0B36-386B-455D-A14B-E7857C255C42}.Debug|x64.Build.0 = Debug|Any CPU
{CD7D0B36-386B-455D-A14B-E7857C255C42}.Debug|x86.ActiveCfg = Debug|Any CPU
{CD7D0B36-386B-455D-A14B-E7857C255C42}.Debug|x86.Build.0 = Debug|Any CPU
{CD7D0B36-386B-455D-A14B-E7857C255C42}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CD7D0B36-386B-455D-A14B-E7857C255C42}.Release|Any CPU.Build.0 = Release|Any CPU
{CD7D0B36-386B-455D-A14B-E7857C255C42}.Release|x64.ActiveCfg = Release|Any CPU
{CD7D0B36-386B-455D-A14B-E7857C255C42}.Release|x64.Build.0 = Release|Any CPU
{CD7D0B36-386B-455D-A14B-E7857C255C42}.Release|x86.ActiveCfg = Release|Any CPU
{CD7D0B36-386B-455D-A14B-E7857C255C42}.Release|x86.Build.0 = Release|Any CPU
{F2CEB8F7-C65B-407E-A11F-B02A39237355}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F2CEB8F7-C65B-407E-A11F-B02A39237355}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F2CEB8F7-C65B-407E-A11F-B02A39237355}.Debug|x64.ActiveCfg = Debug|Any CPU
{F2CEB8F7-C65B-407E-A11F-B02A39237355}.Debug|x64.Build.0 = Debug|Any CPU
{F2CEB8F7-C65B-407E-A11F-B02A39237355}.Debug|x86.ActiveCfg = Debug|Any CPU
{F2CEB8F7-C65B-407E-A11F-B02A39237355}.Debug|x86.Build.0 = Debug|Any CPU
{F2CEB8F7-C65B-407E-A11F-B02A39237355}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F2CEB8F7-C65B-407E-A11F-B02A39237355}.Release|Any CPU.Build.0 = Release|Any CPU
{F2CEB8F7-C65B-407E-A11F-B02A39237355}.Release|x64.ActiveCfg = Release|Any CPU
{F2CEB8F7-C65B-407E-A11F-B02A39237355}.Release|x64.Build.0 = Release|Any CPU
{F2CEB8F7-C65B-407E-A11F-B02A39237355}.Release|x86.ActiveCfg = Release|Any CPU
{F2CEB8F7-C65B-407E-A11F-B02A39237355}.Release|x86.Build.0 = Release|Any CPU
{BF48C3E7-E1E8-4869-973F-22554F146FCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BF48C3E7-E1E8-4869-973F-22554F146FCE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BF48C3E7-E1E8-4869-973F-22554F146FCE}.Debug|x64.ActiveCfg = Debug|Any CPU
{BF48C3E7-E1E8-4869-973F-22554F146FCE}.Debug|x64.Build.0 = Debug|Any CPU
{BF48C3E7-E1E8-4869-973F-22554F146FCE}.Debug|x86.ActiveCfg = Debug|Any CPU
{BF48C3E7-E1E8-4869-973F-22554F146FCE}.Debug|x86.Build.0 = Debug|Any CPU
{BF48C3E7-E1E8-4869-973F-22554F146FCE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BF48C3E7-E1E8-4869-973F-22554F146FCE}.Release|Any CPU.Build.0 = Release|Any CPU
{BF48C3E7-E1E8-4869-973F-22554F146FCE}.Release|x64.ActiveCfg = Release|Any CPU
{BF48C3E7-E1E8-4869-973F-22554F146FCE}.Release|x64.Build.0 = Release|Any CPU
{BF48C3E7-E1E8-4869-973F-22554F146FCE}.Release|x86.ActiveCfg = Release|Any CPU
{BF48C3E7-E1E8-4869-973F-22554F146FCE}.Release|x86.Build.0 = Release|Any CPU
{91C7B100-D04A-4486-8A26-9D55234876D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{91C7B100-D04A-4486-8A26-9D55234876D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{91C7B100-D04A-4486-8A26-9D55234876D7}.Debug|x64.ActiveCfg = Debug|Any CPU
{91C7B100-D04A-4486-8A26-9D55234876D7}.Debug|x64.Build.0 = Debug|Any CPU
{91C7B100-D04A-4486-8A26-9D55234876D7}.Debug|x86.ActiveCfg = Debug|Any CPU
{91C7B100-D04A-4486-8A26-9D55234876D7}.Debug|x86.Build.0 = Debug|Any CPU
{91C7B100-D04A-4486-8A26-9D55234876D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{91C7B100-D04A-4486-8A26-9D55234876D7}.Release|Any CPU.Build.0 = Release|Any CPU
{91C7B100-D04A-4486-8A26-9D55234876D7}.Release|x64.ActiveCfg = Release|Any CPU
{91C7B100-D04A-4486-8A26-9D55234876D7}.Release|x64.Build.0 = Release|Any CPU
{91C7B100-D04A-4486-8A26-9D55234876D7}.Release|x86.ActiveCfg = Release|Any CPU
{91C7B100-D04A-4486-8A26-9D55234876D7}.Release|x86.Build.0 = Release|Any CPU
{00E2F0AF-32EC-4755-81AD-907532F48BBB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{00E2F0AF-32EC-4755-81AD-907532F48BBB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{00E2F0AF-32EC-4755-81AD-907532F48BBB}.Debug|x64.ActiveCfg = Debug|Any CPU
{00E2F0AF-32EC-4755-81AD-907532F48BBB}.Debug|x64.Build.0 = Debug|Any CPU
{00E2F0AF-32EC-4755-81AD-907532F48BBB}.Debug|x86.ActiveCfg = Debug|Any CPU
{00E2F0AF-32EC-4755-81AD-907532F48BBB}.Debug|x86.Build.0 = Debug|Any CPU
{00E2F0AF-32EC-4755-81AD-907532F48BBB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{00E2F0AF-32EC-4755-81AD-907532F48BBB}.Release|Any CPU.Build.0 = Release|Any CPU
{00E2F0AF-32EC-4755-81AD-907532F48BBB}.Release|x64.ActiveCfg = Release|Any CPU
{00E2F0AF-32EC-4755-81AD-907532F48BBB}.Release|x64.Build.0 = Release|Any CPU
{00E2F0AF-32EC-4755-81AD-907532F48BBB}.Release|x86.ActiveCfg = Release|Any CPU
{00E2F0AF-32EC-4755-81AD-907532F48BBB}.Release|x86.Build.0 = Release|Any CPU
{2346E499-C1F4-46C5-BB03-859FC56881D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2346E499-C1F4-46C5-BB03-859FC56881D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2346E499-C1F4-46C5-BB03-859FC56881D4}.Debug|x64.ActiveCfg = Debug|Any CPU
{2346E499-C1F4-46C5-BB03-859FC56881D4}.Debug|x64.Build.0 = Debug|Any CPU
{2346E499-C1F4-46C5-BB03-859FC56881D4}.Debug|x86.ActiveCfg = Debug|Any CPU
{2346E499-C1F4-46C5-BB03-859FC56881D4}.Debug|x86.Build.0 = Debug|Any CPU
{2346E499-C1F4-46C5-BB03-859FC56881D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2346E499-C1F4-46C5-BB03-859FC56881D4}.Release|Any CPU.Build.0 = Release|Any CPU
{2346E499-C1F4-46C5-BB03-859FC56881D4}.Release|x64.ActiveCfg = Release|Any CPU
{2346E499-C1F4-46C5-BB03-859FC56881D4}.Release|x64.Build.0 = Release|Any CPU
{2346E499-C1F4-46C5-BB03-859FC56881D4}.Release|x86.ActiveCfg = Release|Any CPU
{2346E499-C1F4-46C5-BB03-859FC56881D4}.Release|x86.Build.0 = Release|Any CPU
{412DAFA7-FDEA-418C-995B-7C7F51D89E00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{412DAFA7-FDEA-418C-995B-7C7F51D89E00}.Debug|Any CPU.Build.0 = Debug|Any CPU
{412DAFA7-FDEA-418C-995B-7C7F51D89E00}.Debug|x64.ActiveCfg = Debug|Any CPU
{412DAFA7-FDEA-418C-995B-7C7F51D89E00}.Debug|x64.Build.0 = Debug|Any CPU
{412DAFA7-FDEA-418C-995B-7C7F51D89E00}.Debug|x86.ActiveCfg = Debug|Any CPU
{412DAFA7-FDEA-418C-995B-7C7F51D89E00}.Debug|x86.Build.0 = Debug|Any CPU
{412DAFA7-FDEA-418C-995B-7C7F51D89E00}.Release|Any CPU.ActiveCfg = Release|Any CPU
{412DAFA7-FDEA-418C-995B-7C7F51D89E00}.Release|Any CPU.Build.0 = Release|Any CPU
{412DAFA7-FDEA-418C-995B-7C7F51D89E00}.Release|x64.ActiveCfg = Release|Any CPU
{412DAFA7-FDEA-418C-995B-7C7F51D89E00}.Release|x64.Build.0 = Release|Any CPU
{412DAFA7-FDEA-418C-995B-7C7F51D89E00}.Release|x86.ActiveCfg = Release|Any CPU
{412DAFA7-FDEA-418C-995B-7C7F51D89E00}.Release|x86.Build.0 = Release|Any CPU
{79CB2323-2370-419A-8B22-A193B3F3CE68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{79CB2323-2370-419A-8B22-A193B3F3CE68}.Debug|Any CPU.Build.0 = Debug|Any CPU
{79CB2323-2370-419A-8B22-A193B3F3CE68}.Debug|x64.ActiveCfg = Debug|Any CPU
{79CB2323-2370-419A-8B22-A193B3F3CE68}.Debug|x64.Build.0 = Debug|Any CPU
{79CB2323-2370-419A-8B22-A193B3F3CE68}.Debug|x86.ActiveCfg = Debug|Any CPU
{79CB2323-2370-419A-8B22-A193B3F3CE68}.Debug|x86.Build.0 = Debug|Any CPU
{79CB2323-2370-419A-8B22-A193B3F3CE68}.Release|Any CPU.ActiveCfg = Release|Any CPU
{79CB2323-2370-419A-8B22-A193B3F3CE68}.Release|Any CPU.Build.0 = Release|Any CPU
{79CB2323-2370-419A-8B22-A193B3F3CE68}.Release|x64.ActiveCfg = Release|Any CPU
{79CB2323-2370-419A-8B22-A193B3F3CE68}.Release|x64.Build.0 = Release|Any CPU
{79CB2323-2370-419A-8B22-A193B3F3CE68}.Release|x86.ActiveCfg = Release|Any CPU
{79CB2323-2370-419A-8B22-A193B3F3CE68}.Release|x86.Build.0 = Release|Any CPU
{BE1E685F-33D8-47E5-B4FA-BC4DDED255D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BE1E685F-33D8-47E5-B4FA-BC4DDED255D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BE1E685F-33D8-47E5-B4FA-BC4DDED255D3}.Debug|x64.ActiveCfg = Debug|Any CPU
{BE1E685F-33D8-47E5-B4FA-BC4DDED255D3}.Debug|x64.Build.0 = Debug|Any CPU
{BE1E685F-33D8-47E5-B4FA-BC4DDED255D3}.Debug|x86.ActiveCfg = Debug|Any CPU
{BE1E685F-33D8-47E5-B4FA-BC4DDED255D3}.Debug|x86.Build.0 = Debug|Any CPU
{BE1E685F-33D8-47E5-B4FA-BC4DDED255D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BE1E685F-33D8-47E5-B4FA-BC4DDED255D3}.Release|Any CPU.Build.0 = Release|Any CPU
{BE1E685F-33D8-47E5-B4FA-BC4DDED255D3}.Release|x64.ActiveCfg = Release|Any CPU
{BE1E685F-33D8-47E5-B4FA-BC4DDED255D3}.Release|x64.Build.0 = Release|Any CPU
{BE1E685F-33D8-47E5-B4FA-BC4DDED255D3}.Release|x86.ActiveCfg = Release|Any CPU
{BE1E685F-33D8-47E5-B4FA-BC4DDED255D3}.Release|x86.Build.0 = Release|Any CPU
{614EDC46-4654-40F7-A779-8F127B8FD956}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{614EDC46-4654-40F7-A779-8F127B8FD956}.Debug|Any CPU.Build.0 = Debug|Any CPU
{614EDC46-4654-40F7-A779-8F127B8FD956}.Debug|x64.ActiveCfg = Debug|Any CPU
{614EDC46-4654-40F7-A779-8F127B8FD956}.Debug|x64.Build.0 = Debug|Any CPU
{614EDC46-4654-40F7-A779-8F127B8FD956}.Debug|x86.ActiveCfg = Debug|Any CPU
{614EDC46-4654-40F7-A779-8F127B8FD956}.Debug|x86.Build.0 = Debug|Any CPU
{614EDC46-4654-40F7-A779-8F127B8FD956}.Release|Any CPU.ActiveCfg = Release|Any CPU
{614EDC46-4654-40F7-A779-8F127B8FD956}.Release|Any CPU.Build.0 = Release|Any CPU
{614EDC46-4654-40F7-A779-8F127B8FD956}.Release|x64.ActiveCfg = Release|Any CPU
{614EDC46-4654-40F7-A779-8F127B8FD956}.Release|x64.Build.0 = Release|Any CPU
{614EDC46-4654-40F7-A779-8F127B8FD956}.Release|x86.ActiveCfg = Release|Any CPU
{614EDC46-4654-40F7-A779-8F127B8FD956}.Release|x86.Build.0 = Release|Any CPU
{4B12E120-E39B-44A7-A25E-D3151D5AE914}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4B12E120-E39B-44A7-A25E-D3151D5AE914}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4B12E120-E39B-44A7-A25E-D3151D5AE914}.Debug|x64.ActiveCfg = Debug|Any CPU
{4B12E120-E39B-44A7-A25E-D3151D5AE914}.Debug|x64.Build.0 = Debug|Any CPU
{4B12E120-E39B-44A7-A25E-D3151D5AE914}.Debug|x86.ActiveCfg = Debug|Any CPU
{4B12E120-E39B-44A7-A25E-D3151D5AE914}.Debug|x86.Build.0 = Debug|Any CPU
{4B12E120-E39B-44A7-A25E-D3151D5AE914}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4B12E120-E39B-44A7-A25E-D3151D5AE914}.Release|Any CPU.Build.0 = Release|Any CPU
{4B12E120-E39B-44A7-A25E-D3151D5AE914}.Release|x64.ActiveCfg = Release|Any CPU
{4B12E120-E39B-44A7-A25E-D3151D5AE914}.Release|x64.Build.0 = Release|Any CPU
{4B12E120-E39B-44A7-A25E-D3151D5AE914}.Release|x86.ActiveCfg = Release|Any CPU
{4B12E120-E39B-44A7-A25E-D3151D5AE914}.Release|x86.Build.0 = Release|Any CPU
{7F9552C7-7E41-4EA6-9F5E-17E8049C9F10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7F9552C7-7E41-4EA6-9F5E-17E8049C9F10}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7F9552C7-7E41-4EA6-9F5E-17E8049C9F10}.Debug|x64.ActiveCfg = Debug|Any CPU
{7F9552C7-7E41-4EA6-9F5E-17E8049C9F10}.Debug|x64.Build.0 = Debug|Any CPU
{7F9552C7-7E41-4EA6-9F5E-17E8049C9F10}.Debug|x86.ActiveCfg = Debug|Any CPU
{7F9552C7-7E41-4EA6-9F5E-17E8049C9F10}.Debug|x86.Build.0 = Debug|Any CPU
{7F9552C7-7E41-4EA6-9F5E-17E8049C9F10}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7F9552C7-7E41-4EA6-9F5E-17E8049C9F10}.Release|Any CPU.Build.0 = Release|Any CPU
{7F9552C7-7E41-4EA6-9F5E-17E8049C9F10}.Release|x64.ActiveCfg = Release|Any CPU
{7F9552C7-7E41-4EA6-9F5E-17E8049C9F10}.Release|x64.Build.0 = Release|Any CPU
{7F9552C7-7E41-4EA6-9F5E-17E8049C9F10}.Release|x86.ActiveCfg = Release|Any CPU
{7F9552C7-7E41-4EA6-9F5E-17E8049C9F10}.Release|x86.Build.0 = Release|Any CPU
{1FFF91AB-C2D2-4A12-A77B-AB9806116F7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1FFF91AB-C2D2-4A12-A77B-AB9806116F7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1FFF91AB-C2D2-4A12-A77B-AB9806116F7A}.Debug|x64.ActiveCfg = Debug|Any CPU
{1FFF91AB-C2D2-4A12-A77B-AB9806116F7A}.Debug|x64.Build.0 = Debug|Any CPU
{1FFF91AB-C2D2-4A12-A77B-AB9806116F7A}.Debug|x86.ActiveCfg = Debug|Any CPU
{1FFF91AB-C2D2-4A12-A77B-AB9806116F7A}.Debug|x86.Build.0 = Debug|Any CPU
{1FFF91AB-C2D2-4A12-A77B-AB9806116F7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1FFF91AB-C2D2-4A12-A77B-AB9806116F7A}.Release|Any CPU.Build.0 = Release|Any CPU
{1FFF91AB-C2D2-4A12-A77B-AB9806116F7A}.Release|x64.ActiveCfg = Release|Any CPU
{1FFF91AB-C2D2-4A12-A77B-AB9806116F7A}.Release|x64.Build.0 = Release|Any CPU
{1FFF91AB-C2D2-4A12-A77B-AB9806116F7A}.Release|x86.ActiveCfg = Release|Any CPU
{1FFF91AB-C2D2-4A12-A77B-AB9806116F7A}.Release|x86.Build.0 = Release|Any CPU
{208FE840-FFDD-43A5-9F64-F1F3C45C51F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{208FE840-FFDD-43A5-9F64-F1F3C45C51F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{208FE840-FFDD-43A5-9F64-F1F3C45C51F7}.Debug|x64.ActiveCfg = Debug|Any CPU
{208FE840-FFDD-43A5-9F64-F1F3C45C51F7}.Debug|x64.Build.0 = Debug|Any CPU
{208FE840-FFDD-43A5-9F64-F1F3C45C51F7}.Debug|x86.ActiveCfg = Debug|Any CPU
{208FE840-FFDD-43A5-9F64-F1F3C45C51F7}.Debug|x86.Build.0 = Debug|Any CPU
{208FE840-FFDD-43A5-9F64-F1F3C45C51F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{208FE840-FFDD-43A5-9F64-F1F3C45C51F7}.Release|Any CPU.Build.0 = Release|Any CPU
{208FE840-FFDD-43A5-9F64-F1F3C45C51F7}.Release|x64.ActiveCfg = Release|Any CPU
{208FE840-FFDD-43A5-9F64-F1F3C45C51F7}.Release|x64.Build.0 = Release|Any CPU
{208FE840-FFDD-43A5-9F64-F1F3C45C51F7}.Release|x86.ActiveCfg = Release|Any CPU
{208FE840-FFDD-43A5-9F64-F1F3C45C51F7}.Release|x86.Build.0 = Release|Any CPU
{6EE9BB3A-A55F-4FDC-95F1-9304DB341AB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6EE9BB3A-A55F-4FDC-95F1-9304DB341AB1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6EE9BB3A-A55F-4FDC-95F1-9304DB341AB1}.Debug|x64.ActiveCfg = Debug|Any CPU
{6EE9BB3A-A55F-4FDC-95F1-9304DB341AB1}.Debug|x64.Build.0 = Debug|Any CPU
{6EE9BB3A-A55F-4FDC-95F1-9304DB341AB1}.Debug|x86.ActiveCfg = Debug|Any CPU
{6EE9BB3A-A55F-4FDC-95F1-9304DB341AB1}.Debug|x86.Build.0 = Debug|Any CPU
{6EE9BB3A-A55F-4FDC-95F1-9304DB341AB1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6EE9BB3A-A55F-4FDC-95F1-9304DB341AB1}.Release|Any CPU.Build.0 = Release|Any CPU
{6EE9BB3A-A55F-4FDC-95F1-9304DB341AB1}.Release|x64.ActiveCfg = Release|Any CPU
{6EE9BB3A-A55F-4FDC-95F1-9304DB341AB1}.Release|x64.Build.0 = Release|Any CPU
{6EE9BB3A-A55F-4FDC-95F1-9304DB341AB1}.Release|x86.ActiveCfg = Release|Any CPU
{6EE9BB3A-A55F-4FDC-95F1-9304DB341AB1}.Release|x86.Build.0 = Release|Any CPU
{168986E2-E127-4E03-BE45-4CC306E4E880}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{168986E2-E127-4E03-BE45-4CC306E4E880}.Debug|Any CPU.Build.0 = Debug|Any CPU
{168986E2-E127-4E03-BE45-4CC306E4E880}.Debug|x64.ActiveCfg = Debug|Any CPU
{168986E2-E127-4E03-BE45-4CC306E4E880}.Debug|x64.Build.0 = Debug|Any CPU
{168986E2-E127-4E03-BE45-4CC306E4E880}.Debug|x86.ActiveCfg = Debug|Any CPU
{168986E2-E127-4E03-BE45-4CC306E4E880}.Debug|x86.Build.0 = Debug|Any CPU
{168986E2-E127-4E03-BE45-4CC306E4E880}.Release|Any CPU.ActiveCfg = Release|Any CPU
{168986E2-E127-4E03-BE45-4CC306E4E880}.Release|Any CPU.Build.0 = Release|Any CPU
{168986E2-E127-4E03-BE45-4CC306E4E880}.Release|x64.ActiveCfg = Release|Any CPU
{168986E2-E127-4E03-BE45-4CC306E4E880}.Release|x64.Build.0 = Release|Any CPU
{168986E2-E127-4E03-BE45-4CC306E4E880}.Release|x86.ActiveCfg = Release|Any CPU
{168986E2-E127-4E03-BE45-4CC306E4E880}.Release|x86.Build.0 = Release|Any CPU
{A461EFE2-CBB1-4650-9CA0-05CECFAC3AE3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A461EFE2-CBB1-4650-9CA0-05CECFAC3AE3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A461EFE2-CBB1-4650-9CA0-05CECFAC3AE3}.Debug|x64.ActiveCfg = Debug|Any CPU
{A461EFE2-CBB1-4650-9CA0-05CECFAC3AE3}.Debug|x64.Build.0 = Debug|Any CPU
{A461EFE2-CBB1-4650-9CA0-05CECFAC3AE3}.Debug|x86.ActiveCfg = Debug|Any CPU
{A461EFE2-CBB1-4650-9CA0-05CECFAC3AE3}.Debug|x86.Build.0 = Debug|Any CPU
{A461EFE2-CBB1-4650-9CA0-05CECFAC3AE3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A461EFE2-CBB1-4650-9CA0-05CECFAC3AE3}.Release|Any CPU.Build.0 = Release|Any CPU
{A461EFE2-CBB1-4650-9CA0-05CECFAC3AE3}.Release|x64.ActiveCfg = Release|Any CPU
{A461EFE2-CBB1-4650-9CA0-05CECFAC3AE3}.Release|x64.Build.0 = Release|Any CPU
{A461EFE2-CBB1-4650-9CA0-05CECFAC3AE3}.Release|x86.ActiveCfg = Release|Any CPU
{A461EFE2-CBB1-4650-9CA0-05CECFAC3AE3}.Release|x86.Build.0 = Release|Any CPU
{24BBDF59-7B30-4620-8464-BDACB1AEF49D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{24BBDF59-7B30-4620-8464-BDACB1AEF49D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{24BBDF59-7B30-4620-8464-BDACB1AEF49D}.Debug|x64.ActiveCfg = Debug|Any CPU
{24BBDF59-7B30-4620-8464-BDACB1AEF49D}.Debug|x64.Build.0 = Debug|Any CPU
{24BBDF59-7B30-4620-8464-BDACB1AEF49D}.Debug|x86.ActiveCfg = Debug|Any CPU
{24BBDF59-7B30-4620-8464-BDACB1AEF49D}.Debug|x86.Build.0 = Debug|Any CPU
{24BBDF59-7B30-4620-8464-BDACB1AEF49D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{24BBDF59-7B30-4620-8464-BDACB1AEF49D}.Release|Any CPU.Build.0 = Release|Any CPU
{24BBDF59-7B30-4620-8464-BDACB1AEF49D}.Release|x64.ActiveCfg = Release|Any CPU
{24BBDF59-7B30-4620-8464-BDACB1AEF49D}.Release|x64.Build.0 = Release|Any CPU
{24BBDF59-7B30-4620-8464-BDACB1AEF49D}.Release|x86.ActiveCfg = Release|Any CPU
{24BBDF59-7B30-4620-8464-BDACB1AEF49D}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{336F7E73-0D75-4308-A20B-E8AB7964D27C} = {BDB24B64-FE4E-C4BD-9F80-9428F98EDF6F}
{CD7D0B36-386B-455D-A14B-E7857C255C42} = {BDB24B64-FE4E-C4BD-9F80-9428F98EDF6F}
{F2CEB8F7-C65B-407E-A11F-B02A39237355} = {BDB24B64-FE4E-C4BD-9F80-9428F98EDF6F}
{91C7B100-D04A-4486-8A26-9D55234876D7} = {BDB24B64-FE4E-C4BD-9F80-9428F98EDF6F}
{2346E499-C1F4-46C5-BB03-859FC56881D4} = {BDB24B64-FE4E-C4BD-9F80-9428F98EDF6F}
{412DAFA7-FDEA-418C-995B-7C7F51D89E00} = {BDB24B64-FE4E-C4BD-9F80-9428F98EDF6F}
{BE1E685F-33D8-47E5-B4FA-BC4DDED255D3} = {BDB24B64-FE4E-C4BD-9F80-9428F98EDF6F}
{614EDC46-4654-40F7-A779-8F127B8FD956} = {BDB24B64-FE4E-C4BD-9F80-9428F98EDF6F}
{4B12E120-E39B-44A7-A25E-D3151D5AE914} = {BDB24B64-FE4E-C4BD-9F80-9428F98EDF6F}
{1FFF91AB-C2D2-4A12-A77B-AB9806116F7A} = {BDB24B64-FE4E-C4BD-9F80-9428F98EDF6F}
{168986E2-E127-4E03-BE45-4CC306E4E880} = {BDB24B64-FE4E-C4BD-9F80-9428F98EDF6F}
{A461EFE2-CBB1-4650-9CA0-05CECFAC3AE3} = {BDB24B64-FE4E-C4BD-9F80-9428F98EDF6F}
{24BBDF59-7B30-4620-8464-BDACB1AEF49D} = {BDB24B64-FE4E-C4BD-9F80-9428F98EDF6F}
EndGlobalSection
EndGlobal

View File

@@ -14,7 +14,7 @@ Own the StellaOps Authority host service: ASP.NET minimal API, OpenIddict flows,
- Coordinate with plugin teams before altering plugin-facing contracts.
## Key Directories
- `src/StellaOps.Authority/` — host app
- `src/StellaOps.Authority.Tests/` — integration/unit tests
- `src/StellaOps.Authority.Storage.Mongo/` — data access helpers
- `src/StellaOps.Authority.Plugin.Standard/` — default identity provider plugin
- `src/Authority/StellaOps.Authority/` — host app
- `src/Authority/StellaOps.Authority/StellaOps.Authority.Tests/` — integration/unit tests
- `src/Authority/StellaOps.Authority/StellaOps.Authority.Storage.Mongo/` — data access helpers
- `src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard/` — default identity provider plugin

View File

@@ -1,54 +1,54 @@
using StellaOps.Auth.Abstractions;
using Xunit;
namespace StellaOps.Auth.Abstractions.Tests;
public class StellaOpsScopesTests
{
[Theory]
[InlineData(StellaOpsScopes.AdvisoryRead)]
[InlineData(StellaOpsScopes.AdvisoryIngest)]
[InlineData(StellaOpsScopes.VexRead)]
[InlineData(StellaOpsScopes.VexIngest)]
[InlineData(StellaOpsScopes.AocVerify)]
[InlineData(StellaOpsScopes.SignalsRead)]
[InlineData(StellaOpsScopes.SignalsWrite)]
[InlineData(StellaOpsScopes.SignalsAdmin)]
[InlineData(StellaOpsScopes.PolicyWrite)]
[InlineData(StellaOpsScopes.PolicyAuthor)]
[InlineData(StellaOpsScopes.PolicySubmit)]
[InlineData(StellaOpsScopes.PolicyApprove)]
[InlineData(StellaOpsScopes.PolicyReview)]
[InlineData(StellaOpsScopes.PolicyOperate)]
[InlineData(StellaOpsScopes.PolicyAudit)]
[InlineData(StellaOpsScopes.PolicyRun)]
[InlineData(StellaOpsScopes.PolicySimulate)]
[InlineData(StellaOpsScopes.FindingsRead)]
[InlineData(StellaOpsScopes.EffectiveWrite)]
[InlineData(StellaOpsScopes.GraphRead)]
[InlineData(StellaOpsScopes.VulnRead)]
[InlineData(StellaOpsScopes.GraphWrite)]
[InlineData(StellaOpsScopes.GraphExport)]
[InlineData(StellaOpsScopes.GraphSimulate)]
[InlineData(StellaOpsScopes.OrchRead)]
[InlineData(StellaOpsScopes.OrchOperate)]
[InlineData(StellaOpsScopes.ExportViewer)]
[InlineData(StellaOpsScopes.ExportOperator)]
[InlineData(StellaOpsScopes.ExportAdmin)]
public void All_IncludesNewScopes(string scope)
{
Assert.Contains(scope, StellaOpsScopes.All);
}
[Theory]
[InlineData("Advisory:Read", StellaOpsScopes.AdvisoryRead)]
[InlineData(" VEX:Ingest ", StellaOpsScopes.VexIngest)]
[InlineData("AOC:VERIFY", StellaOpsScopes.AocVerify)]
[InlineData(" Signals:Write ", StellaOpsScopes.SignalsWrite)]
[InlineData("Policy:Author", StellaOpsScopes.PolicyAuthor)]
[InlineData("Export.Admin", StellaOpsScopes.ExportAdmin)]
public void Normalize_NormalizesToLowerCase(string input, string expected)
{
Assert.Equal(expected, StellaOpsScopes.Normalize(input));
}
}
using StellaOps.Auth.Abstractions;
using Xunit;
namespace StellaOps.Auth.Abstractions.Tests;
public class StellaOpsScopesTests
{
[Theory]
[InlineData(StellaOpsScopes.AdvisoryRead)]
[InlineData(StellaOpsScopes.AdvisoryIngest)]
[InlineData(StellaOpsScopes.VexRead)]
[InlineData(StellaOpsScopes.VexIngest)]
[InlineData(StellaOpsScopes.AocVerify)]
[InlineData(StellaOpsScopes.SignalsRead)]
[InlineData(StellaOpsScopes.SignalsWrite)]
[InlineData(StellaOpsScopes.SignalsAdmin)]
[InlineData(StellaOpsScopes.PolicyWrite)]
[InlineData(StellaOpsScopes.PolicyAuthor)]
[InlineData(StellaOpsScopes.PolicySubmit)]
[InlineData(StellaOpsScopes.PolicyApprove)]
[InlineData(StellaOpsScopes.PolicyReview)]
[InlineData(StellaOpsScopes.PolicyOperate)]
[InlineData(StellaOpsScopes.PolicyAudit)]
[InlineData(StellaOpsScopes.PolicyRun)]
[InlineData(StellaOpsScopes.PolicySimulate)]
[InlineData(StellaOpsScopes.FindingsRead)]
[InlineData(StellaOpsScopes.EffectiveWrite)]
[InlineData(StellaOpsScopes.GraphRead)]
[InlineData(StellaOpsScopes.VulnRead)]
[InlineData(StellaOpsScopes.GraphWrite)]
[InlineData(StellaOpsScopes.GraphExport)]
[InlineData(StellaOpsScopes.GraphSimulate)]
[InlineData(StellaOpsScopes.OrchRead)]
[InlineData(StellaOpsScopes.OrchOperate)]
[InlineData(StellaOpsScopes.ExportViewer)]
[InlineData(StellaOpsScopes.ExportOperator)]
[InlineData(StellaOpsScopes.ExportAdmin)]
public void All_IncludesNewScopes(string scope)
{
Assert.Contains(scope, StellaOpsScopes.All);
}
[Theory]
[InlineData("Advisory:Read", StellaOpsScopes.AdvisoryRead)]
[InlineData(" VEX:Ingest ", StellaOpsScopes.VexIngest)]
[InlineData("AOC:VERIFY", StellaOpsScopes.AocVerify)]
[InlineData(" Signals:Write ", StellaOpsScopes.SignalsWrite)]
[InlineData("Policy:Author", StellaOpsScopes.PolicyAuthor)]
[InlineData("Export.Admin", StellaOpsScopes.ExportAdmin)]
public void Normalize_NormalizesToLowerCase(string input, string expected)
{
Assert.Equal(expected, StellaOpsScopes.Normalize(input));
}
}

Some files were not shown because too many files have changed in this diff Show More