Restructure solution layout by module
	
		
			
	
		
	
	
		
	
		
			Some checks failed
		
		
	
	
		
			
				
	
				Docs CI / lint-and-preview (push) Has been cancelled
				
			
		
		
	
	
				
					
				
			
		
			Some checks failed
		
		
	
	Docs CI / lint-and-preview (push) Has been cancelled
				
			This commit is contained in:
		| @@ -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. | ||||
| 
 | ||||
| @@ -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. | | ||||
| @@ -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. | ||||
| @@ -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. | | ||||
| @@ -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. | ||||
| @@ -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. | | ||||
| @@ -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. | ||||
| @@ -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. | | ||||
| @@ -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. | ||||
| @@ -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
									
								
							
							
						
						
									
										56
									
								
								src/Aoc/StellaOps.Aoc.sln
									
									
									
									
									
										Normal 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 | ||||
| @@ -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); | ||||
| } | ||||
| @@ -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; | ||||
| } | ||||
| @@ -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; | ||||
|     } | ||||
| } | ||||
| @@ -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; | ||||
| } | ||||
| @@ -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); | ||||
|     } | ||||
| } | ||||
| @@ -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); | ||||
| } | ||||
| @@ -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", | ||||
|     }; | ||||
| } | ||||
| @@ -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.")); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -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; | ||||
|     } | ||||
| } | ||||
| @@ -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> | ||||
| @@ -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")); | ||||
|     } | ||||
| } | ||||
| @@ -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> | ||||
| @@ -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() | ||||
|     { | ||||
| 
 | ||||
|     } | ||||
| } | ||||
| @@ -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`. | ||||
| @@ -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 | | ||||
| @@ -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. | ||||
| @@ -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. | | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -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. | ||||
| @@ -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. | | ||||
| @@ -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. | ||||
| @@ -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. | | ||||
| @@ -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. | ||||
| @@ -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. | | ||||
							
								
								
									
										182
									
								
								src/Attestor/StellaOps.Attestor.sln
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										182
									
								
								src/Attestor/StellaOps.Attestor.sln
									
									
									
									
									
										Normal 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 | ||||
| @@ -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. | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| @@ -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> | ||||
| @@ -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> | ||||
| @@ -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> | ||||
							
								
								
									
										303
									
								
								src/Authority/StellaOps.Authority.sln
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										303
									
								
								src/Authority/StellaOps.Authority.sln
									
									
									
									
									
										Normal 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 | ||||
| @@ -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 | ||||
| @@ -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
		Reference in New Issue
	
	Block a user