Add unit tests for SBOM ingestion and transformation
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled

- Implement `SbomIngestServiceCollectionExtensionsTests` to verify the SBOM ingestion pipeline exports snapshots correctly.
- Create `SbomIngestTransformerTests` to ensure the transformation produces expected nodes and edges, including deduplication of license nodes and normalization of timestamps.
- Add `SbomSnapshotExporterTests` to test the export functionality for manifest, adjacency, nodes, and edges.
- Introduce `VexOverlayTransformerTests` to validate the transformation of VEX nodes and edges.
- Set up project file for the test project with necessary dependencies and configurations.
- Include JSON fixture files for testing purposes.
This commit is contained in:
master
2025-11-04 07:49:39 +02:00
parent f72c5c513a
commit 2eb6852d34
491 changed files with 39445 additions and 3917 deletions

View File

@@ -58,12 +58,20 @@ jobs:
PUBLISH_DIR: ${{ github.workspace }}/artifacts/publish/webservice
AUTHORITY_PUBLISH_DIR: ${{ github.workspace }}/artifacts/publish/authority
TEST_RESULTS_DIR: ${{ github.workspace }}/artifacts/test-results
STELLAOPS_TEST_MONGO_URI: ${{ secrets.STELLAOPS_TEST_MONGO_URI || vars.STELLAOPS_TEST_MONGO_URI }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Ensure Mongo test URI configured
run: |
if [ -z "${STELLAOPS_TEST_MONGO_URI:-}" ]; then
echo "::error::STELLAOPS_TEST_MONGO_URI must be provided via repository secrets or variables for Graph Indexer integration tests."
exit 1
fi
- name: Verify policy scope configuration
run: python3 scripts/verify-policy-scopes.py

1
.gitignore vendored
View File

@@ -32,3 +32,4 @@ out/offline-kit/web/**/*
**/.cache/**/*
**/dist/**/*
tmp/**/*
build/

View File

@@ -1,5 +0,0 @@
home = /usr/bin
include-system-site-packages = false
version = 3.12.3
executable = /usr/bin/python3.12
command = /usr/bin/python3 -m venv /mnt/e/dev/git.stella-ops.org/.venv

0
Captures Normal file
View File

View File

@@ -236,7 +236,7 @@ services:
environment:
DOTNET_ENVIRONMENT: Production
volumes:
- ../../etc/notify.prod.yaml:/app/etc/notify.yaml:ro
- ../../etc/notify.airgap.yaml:/app/etc/notify.yaml:ro
ports:
- "${NOTIFY_WEB_PORT:-9446}:8446"
networks:

View File

@@ -53,6 +53,14 @@ Authority persists every issued token in MongoDB so operators can audit or revok
Configuration sample (`etc/authority.yaml.sample`) seeds the client with a confidential secret so Console can negotiate the code exchange on the backend while browsers execute the PKCE dance.
### Policy Studio scopes & signing workflow
- **Role bundles:** Issue the dedicated Policy Studio roles per tenant (`role/policy-author`, `role/policy-reviewer`, `role/policy-approver`, `role/policy-operator`, `role/policy-auditor`). Each maps to the `policy:*` scopes described in [Policy Lifecycle & Approvals](policy/lifecycle.md#2-roles--authority-scopes).
- **Publish/promote scopes:** `policy:publish` and `policy:promote` are interactive-only. Authority rejects client-credential tokens; operators must log in via `stella auth login` (DPoP) and stay within the five-minute fresh-auth window.
- **Required metadata:** Publishing attaches `policy_reason`, `policy_ticket`, and `policy_digest` headers. The CLI surface (`stella policy publish --reason --ticket --sign`) maps flags to these fields automatically. Missing metadata returns `422 policy_attestation_metadata_missing`.
- **Attestations:** `stella policy publish --sign` produces a DSSE envelope stored in Policy Engine (`policy_attestations`) and on disk for Offline Kit evidence. Promotions (`stella policy promote --environment prod`) emit `policy.promoted` audit events referencing the attestation digest.
- **Compliance checklist:** Before activation, verify each item in [§10 Compliance Checklist](policy/lifecycle.md#10--compliance-checklist) — role mapping, simulation evidence, approval note, attestation signature, promotion note, activation health, offline parity.
### Advisory AI scopes & remote inference
- `advisory-ai:view` — read Advisory AI artefacts (summaries, remediation packs, cached outputs).
@@ -158,6 +166,7 @@ Graph Explorer introduces dedicated scopes: `graph:write` for Cartographer build
- **Scopes** `vuln:view` unlocks read-only access and permalink issuance, `vuln:investigate` allows triage actions (assignment, comments, remediation notes), `vuln:operate` unlocks state transitions and workflow execution, and `vuln:audit` exposes immutable ledgers/exports. The legacy `vuln:read` scope is still emitted for backward compatibility but new clients should request the granular scopes.
- **ABAC attributes** Tenant roles can project attribute filters (`env`, `owner`, `business_tier`) via the `attributes` block in `authority.yaml` (see the sample `role/vuln-*` definitions). Authority now enforces the same filters on token issuance: client-credential requests must supply `vuln_env`, `vuln_owner`, and `vuln_business_tier` parameters when multiple values are configured, and the values must match the configured allow-list (or `*`). The accepted value pattern is `[a-z0-9:_-]{1,128}`. Issued tokens embed the resolved filters as `stellaops:vuln_env`, `stellaops:vuln_owner`, and `stellaops:vuln_business_tier` claims, and Authority persists the resulting actor chain plus service-account metadata in Mongo for auditability.
- **Service accounts** Delegated Vuln Explorer identities (`svc-vuln-*`) should include the attribute filters in their seed definition. Authority enforces the supplied `attributes` during issuance and stores the selected values on the delegation token, making downstream revocation/audit exports aware of the effective ABAC envelope.
- **Attachment tokens** Evidence downloads require scoped tokens issued by Authority. `POST /vuln/attachments/tokens/issue` accepts ledger hashes plus optional metadata, signs the response with the primary Authority key, and records audit trails (`vuln.attachment.token.*`). `POST /vuln/attachments/tokens/verify` validates incoming tokens server-side. See “Attachment signing tokens” below.
- **Token request parameters** Minimum metadata for Vuln Explorer service accounts:
- `service_account`: requested service-account id (still required).
- `vuln_env`: single value or `*` (required when multiple environments are configured).
@@ -166,6 +175,40 @@ Graph Explorer introduces dedicated scopes: `graph:write` for Cartographer build
Authority rejects missing parameters with `invalid_request` and records the violation via `authority.vuln_attr_*` audit properties.
- **Signed links** `POST /permalinks/vuln` requires `vuln:view`. The resulting JWT carries `vuln:view` plus the transitional `vuln:read` scope to preserve older consumers. Validation remains unchanged: verify the signature against `/jwks`, confirm tenant alignment, honour expiry, and enforce the scopes before honouring the permalink payload.
##### Attachment signing tokens
- **Issuance.** `POST /vuln/attachments/tokens/issue` (scope `vuln:investigate`) accepts an attachment identifier, the authoritative ledger hash, and optional metadata map (`metadata[]`). Authority returns a DSSE-style payload signed with the primary EdDSA key, capped by the configured TTL (`authority.vulnerabilityExplorer.attachments.defaultLifetime`, default 30 minutes).
- **Verification.** Downstream services call `POST /vuln/attachments/tokens/verify` before honouring downloads. The endpoint enforces tenant, scope, ABAC attributes, TTL, and ledger hash matching, and emits `vuln.attachment.token.verify` audit events with the resolved metadata.
- **Audit trail.** Every issuance logs `vuln.attachment.token.issue` with `delegation.service_account`, `ledger.hash`, and `attachment.id` properties so Offline Kit operators can reconcile evidence access. Tokens also embed the actor chain (`act`) so consuming services can trace automation pipelines.
- **Example.**
```bash
curl -u vuln-explorer-worker:s3cr3t \
-H "Content-Type: application/json" \
-d '{
"attachmentId": "finding-7d9d/evidence-2",
"ledgerHash": "sha256:4a5160...",
"metadata": { "download": "supporting-log.zip" }
}' \
https://authority.example.com/vuln/attachments/tokens/issue
```
##### Ledger verification workflow
1. Resolve the attachments ledger entry (`finding_history`, `triage_actions`) and note the recorded hash/signature.
2. Verify the issued attachment token via `/vuln/attachments/tokens/verify`; the response echoes the canonical hash and expiry.
3. When downloading artefacts from Vuln Explorer, recompute the hash locally and compare it to both the ledger entry and the verified token payload.
4. Cross-check Authority audit events (`vuln.attachment.token.*`) to confirm who issued and consumed the token; Offline Kit mirrors include the same audit feed.
##### Vuln Explorer security checklist
- [ ] Map tenant roles to the granular `vuln:*` scopes and ABAC filters in `etc/authority.yaml.sample`.
- [ ] Require `vuln_env`, `vuln_owner`, and `vuln_business_tier` parameters for every delegated service-account request.
- [ ] Exercise `/vuln/attachments/tokens/issue` and `/vuln/attachments/tokens/verify` in CI to confirm attachment signing is enforced.
- [ ] Mirror Authority audit events (`vuln.attachment.token.*`, `authority.vuln_attr.*`) into your SOC pipeline.
- [ ] Update Offline Kit runbooks so operators verify attachment hashes against both ledger entries and Authority-issued tokens before distribution.
## 4. Revocation Pipeline
Authority centralises revocation in `authority_revocations` with deterministic categories:

View File

@@ -4,6 +4,10 @@
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|----|--------|----------|------------|-------------|---------------|
| DOCS-REPLAY-185-003 | TODO | Docs Guild, Platform Data Guild | REPLAY-CORE-185-001 | Author `docs/data/replay_schema.md` describing `replay_runs`, `replay_bundles`, and `replay_subjects` collections with indices and offline sync guidance referenced by `docs/implplan/SPRINT_185_replay_core.md`. | Doc merged with schema tables, index specs, and cross-links into platform overview. |
| DOCS-REPLAY-185-004 | TODO | Docs Guild, Platform Guild | REPLAY-CORE-185-001 | Expand `docs/replay/DEVS_GUIDE_REPLAY.md` with integration checklist and cross-links to sections 3 & 11 of `docs/replay/DETERMINISTIC_REPLAY.md`. | Guide updated with checklist; references validated; lint passes. |
| DOCS-REPLAY-186-004 | TODO | Docs Guild, Scanner Guild | SCAN-REPLAY-186-001 | Publish `docs/replay/TEST_STRATEGY.md` detailing golden replay, feed drift, and tool upgrade verification steps; link from scanner architecture doc. | New doc merged; links verified; CI scenario notes documented. |
| RUNBOOK-REPLAY-187-004 | TODO | Docs Guild, Ops Guild | EVID-REPLAY-187-001, CLI-REPLAY-187-002 | Create `/docs/runbooks/replay_ops.md` covering retention enforcement, RootPack rotation, offline kit workflows, and verification drills referencing `docs/replay/DETERMINISTIC_REPLAY.md`. | Runbook merged; rehearsal notes captured; cross-links added. |
| DOCS-OBS-50-002 | TODO | Docs Guild, Security Guild | TELEMETRY-OBS-50-002 | Author `/docs/observability/telemetry-standards.md` detailing common fields, scrubbing policy, sampling defaults, and redaction override procedure. | Doc merged; imposed rule banner present; examples validated with telemetry fixtures; security review sign-off captured. |
| DOCS-OBS-50-003 | TODO | Docs Guild, Observability Guild | TELEMETRY-OBS-50-001 | Create `/docs/observability/logging.md` covering structured log schema, dos/don'ts, tenant isolation, and copyable examples. | Doc merged with banner; sample logs redacted; lint passes; linked from coding standards. |
| DOCS-OBS-50-004 | TODO | Docs Guild, Observability Guild | TELEMETRY-OBS-50-002 | Draft `/docs/observability/tracing.md` explaining context propagation, async linking, CLI header usage, and sampling strategies. | Doc merged; imposed rule banner included; diagrams updated; references to CLI/Console features added. |
@@ -294,15 +298,24 @@
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|----|--------|----------|------------|-------------|---------------|
| DOCS-AIAI-31-001 | TODO | Docs Guild, Advisory AI Guild | AIAI-31-006 | Publish `/docs/advisory-ai/overview.md` covering capabilities, guardrails, RBAC. | Doc merged with diagrams; compliance checklist appended. |
| DOCS-AIAI-31-002 | TODO | Docs Guild, Advisory AI Guild | AIAI-31-004 | Author `/docs/advisory-ai/architecture.md` detailing RAG pipeline, deterministics, caching, model options. | Doc merged; architecture review done; checklist appended. |
| DOCS-AIAI-31-003 | TODO | Docs Guild, Advisory AI Guild | AIAI-31-006 | Write `/docs/advisory-ai/api.md` describing endpoints, schemas, errors, rate limits. | API doc aligned with OpenAPI; examples validated; checklist appended. |
| DOCS-AIAI-31-004 | TODO | Docs Guild, Console Guild | CONSOLE-VULN-29-001, CONSOLE-VEX-30-001 | Create `/docs/advisory-ai/console.md` with screenshots, a11y notes, copy-as-ticket instructions. | Doc merged; images stored; checklist appended. |
| DOCS-AIAI-31-005 | TODO | Docs Guild, DevEx/CLI Guild | CLI-VULN-29-001, CLI-VEX-30-001 | Publish `/docs/advisory-ai/cli.md` covering commands, exit codes, scripting patterns. | Doc merged; examples tested; checklist appended. |
| DOCS-AIAI-31-006 | TODO | Docs Guild, Policy Guild | POLICY-ENGINE-31-001 | Update `/docs/policy/assistant-parameters.md` covering temperature, token limits, ranking weights, TTLs. | Doc merged; policy review done; checklist appended. |
| DOCS-AIAI-31-007 | TODO | Docs Guild, Security Guild | AIAI-31-005 | Write `/docs/security/assistant-guardrails.md` detailing redaction, injection defense, logging. | Doc approved by Security; checklist appended. |
| DOCS-AIAI-31-008 | TODO | Docs Guild, SBOM Service Guild | SBOM-AIAI-31-001 | Publish `/docs/sbom/remediation-heuristics.md` (feasibility scoring, blast radius). | Doc merged; heuristics reviewed; checklist appended. |
| DOCS-AIAI-31-009 | TODO | Docs Guild, DevOps Guild | DEVOPS-AIAI-31-001 | Create `/docs/runbooks/assistant-ops.md` for warmup, cache priming, model outages, scaling. | Runbook merged; rehearsal logged; checklist appended. |
| DOCS-AIAI-31-001 | DONE (2025-11-03) | Docs Guild, Advisory AI Guild | AIAI-31-006 | Publish `/docs/advisory-ai/overview.md` covering capabilities, guardrails, RBAC. | Doc merged with diagrams; compliance checklist appended. |
> 2025-11-03: DOCS-AIAI-31-001 completed overview covers value proposition, guardrails, personas, observability, roadmap checklist.
| DOCS-AIAI-31-002 | DONE (2025-11-03) | Docs Guild, Advisory AI Guild | AIAI-31-004 | Author `/docs/advisory-ai/architecture.md` detailing RAG pipeline, deterministics, caching, model options. | Doc merged; architecture review done; checklist appended. |
> 2025-11-03: DOCS-AIAI-31-002 completed architecture deep dive documents pipeline, deterministic tooling, caching, profiles, and deployment guidance.
| DOCS-AIAI-31-003 | DONE (2025-11-03) | Docs Guild, Advisory AI Guild | AIAI-31-006 | Write `/docs/advisory-ai/api.md` describing endpoints, schemas, errors, rate limits. | API doc aligned with OpenAPI; examples validated; checklist appended. |
> 2025-11-03: DOCS-AIAI-31-003 completed `docs/advisory-ai/api.md` covers scopes, request/response schema, rate limits, error codes, observability, offline notes.
| DOCS-AIAI-31-004 | BLOCKED (2025-11-03) | Docs Guild, Console Guild | CONSOLE-VULN-29-001, CONSOLE-VEX-30-001, EXCITITOR-CONSOLE-23-001 | Create `/docs/advisory-ai/console.md` with screenshots, a11y notes, copy-as-ticket instructions. | Doc merged; images stored; checklist appended. |
> 2025-11-03: BLOCKED waiting for Console endpoints/widgets (CONSOLE-VULN-29-001, CONSOLE-VEX-30-001, EXCITITOR-CONSOLE-23-001) to land before documenting UI flows.
| DOCS-AIAI-31-005 | BLOCKED (2025-11-03) | Docs Guild, DevEx/CLI Guild | CLI-VULN-29-001, CLI-VEX-30-001, AIAI-31-004C | Publish `/docs/advisory-ai/cli.md` covering commands, exit codes, scripting patterns. | Doc merged; examples tested; checklist appended. |
> 2025-11-03: BLOCKED awaiting CLI implementation (`stella advise run`) and golden outputs (CLI-VULN-29-001, CLI-VEX-30-001, AIAI-31-004C).
| DOCS-AIAI-31-006 | BLOCKED (2025-11-03) | Docs Guild, Policy Guild | POLICY-ENGINE-31-001 | Update `/docs/policy/assistant-parameters.md` covering temperature, token limits, ranking weights, TTLs. | Doc merged; policy review done; checklist appended. |
> 2025-11-03: BLOCKED waiting for POLICY-ENGINE-31-001 to deliver Advisory AI parameter knobs.
| DOCS-AIAI-31-007 | BLOCKED (2025-11-03) | Docs Guild, Security Guild | AIAI-31-005 | Write `/docs/security/assistant-guardrails.md` detailing redaction, injection defense, logging. | Doc approved by Security; checklist appended. |
> 2025-11-03: BLOCKED guardrail implementation (AIAI-31-005) outstanding; documentation deferred.
| DOCS-AIAI-31-008 | BLOCKED (2025-11-03) | Docs Guild, SBOM Service Guild | SBOM-AIAI-31-001 | Publish `/docs/sbom/remediation-heuristics.md` (feasibility scoring, blast radius). | Doc merged; heuristics reviewed; checklist appended. |
> 2025-11-03: BLOCKED SBOM heuristic work (SBOM-AIAI-31-001) not yet delivered.
| DOCS-AIAI-31-009 | BLOCKED (2025-11-03) | Docs Guild, DevOps Guild | DEVOPS-AIAI-31-001 | Create `/docs/runbooks/assistant-ops.md` for warmup, cache priming, model outages, scaling. | Runbook merged; rehearsal logged; checklist appended. |
> 2025-11-03: BLOCKED awaiting DevOps ops playbook (DEVOPS-AIAI-31-001) and operational rehearsal input.
## Notifications Studio

210
docs/advisory-ai/api.md Normal file
View File

@@ -0,0 +1,210 @@
> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied.
# Advisory AI API Reference (Sprint 110 Preview)
_Updated: 2025-11-03 • Owner: Docs Guild & Advisory AI Guild • Status: In progress_
## 1. Overview
The Advisory AI service exposes deterministic, guardrail-enforced endpoints for generating advisory summaries, conflict explanations, and remediation plans. Each request is backed by the Aggregation-Only Contract (AOC); inputs originate from immutable Conseiller/Excititor evidence and SBOM context, and every output ships with verifiable citations and cache digests.
This document captures the API surface targeted for Sprint 110. The surface is gated behind Authority scopes and designed to operate identically online or offline (local inference profiles).
## 2. Base conventions
| Item | Value |
|------|-------|
| Base path | `/v1/advisory-ai` |
| Media types | `application/json` (request + response) |
| Authentication | OAuth2 access token (JWT, DPoP-bound or mTLS as per tenant policy) |
| Required scopes | See [Authentication & scopes](#3-authentication--scopes) |
| Idempotency | Requests are cached by `(taskType, advisoryKey, policyVersion, profile, artifactId/purl, preferredSections)` unless `forceRefresh` is `true` |
| Determinism | Guardrails reject outputs lacking citations; cache digests allow replay and offline verification |
## 3. Authentication & scopes
Advisory AI calls must include `aoc:verify` plus an Advisory AI scope. Authority enforces tenant binding for all combinations.
| Scope | Purpose | Typical principals |
|-------|---------|--------------------|
| `advisory-ai:view` | Read cached artefacts (`GET /outputs/{{hash}}`) | Console backend, evidence exporters |
| `advisory-ai:operate` | Submit inference jobs (`POST /summaries`, `/conflicts`, `/remediation`) | Platform services, CLI automation |
| `advisory-ai:admin` | Manage profiles & policy (`PATCH /profiles`, future) | Platform operators |
Requests without `aoc:verify` are rejected with `invalid_scope`. Tokens aimed at remote inference profiles must also satisfy tenant consent (`requireTenantConsent` in Authority config).
## 4. Profiles & inference selection
Profiles determine which model backend and guardrail stack execute the request. The `profile` field defaults to `default` (`fips-local`).
| Profile | Description |
|---------|-------------|
| `default` / `fips-local` | Local deterministic model packaged with Offline Kit; FIPS-compliant crypto |
| `gost-local` | Local profile using GOST-approved crypto stack |
| `cloud-openai` | Remote inference via cloud connector (disabled unless tenant consent flag set) |
| Custom | Installations may register additional profiles via Authority `advisory-ai` admin APIs |
## 5. Common request envelope
All task endpoints accept the same JSON payload; `taskType` is implied by the route.
```json
{
"advisoryKey": "csaf:redhat:RHSA-2025:1001",
"artifactId": "registry.stella-ops.internal/runtime/api",
"artifactPurl": "pkg:oci/runtime-api@sha256:d2c3...",
"policyVersion": "2025.10.1",
"profile": "fips-local",
"preferredSections": ["Summary", "Remediation"],
"forceRefresh": false
}
```
Field notes:
- `advisoryKey` **required**. Matches Conseiller advisory identifier or VEX statement key.
- `artifactId` / `artifactPurl` optional but recommended for remediation tasks (enables SBOM context).
- `policyVersion` locks evaluation to a specific Policy Engine digest. Omit for "current".
- `profile` selects inference profile (see §4). Unknown values return `400`.
- `preferredSections` prioritises advisory sections; the orchestrator still enforces AOC.
- `forceRefresh` bypasses cache, regenerating output and resealing DSSE bundle.
## 6. Responses & caching
Successful responses share a common envelope:
```json
{
"taskType": "Summary",
"profile": "fips-local",
"generatedAt": "2025-11-03T18:22:43Z",
"inputDigest": "sha256:6f3b...",
"outputHash": "sha256:1d7e...",
"ttlSeconds": 86400,
"content": {
"format": "markdown",
"body": "### Summary
1. [Vendor statement][1] ..."
},
"citations": [
{
"index": 1,
"kind": "advisory",
"sourceId": "concelier:csaf:redhat:RHSA-2025:1001:paragraph:12",
"uri": "https://access.redhat.com/errata/RHSA-2025:1001"
}
],
"context": {
"planCacheKey": "adv-summary:csaf:redhat:RHSA-2025:1001:fips-local",
"chunks": 42,
"vectorMatches": 12,
"sbom": {
"artifactId": "registry.stella-ops.internal/runtime/api",
"versionTimeline": 8,
"dependencyPaths": 5,
"dependencyNodes": 17
}
}
}
```
- `content.format` is `markdown` for human-readable payloads; machine-readable JSON attachments will use `json`. The CLI and Console render Markdown directly.
- `citations` indexes correspond to bracketed references in the Markdown body.
- `context.planCacheKey` lets operators resubmit the same request or inspect the plan (`GET /v1/advisory-ai/plans/`cacheKey``) optional when enabled.
- Cached copies honour tenant-specific TTLs (default 24h). Exceeding TTL triggers regeneration on next request.
## 7. Endpoints
### 7.1 `POST /v1/advisory-ai/summaries`
Generate or retrieve a cached advisory summary. Requires `advisory-ai:operate`.
- **Request body:** Common envelope (preferred sections default to `Summary`).
- **Response:** Summary output (see §6 example).
- **Errors:**
- `400 advisory.summary.missingAdvisoryKey` empty or malformed `advisoryKey`.
- `404 advisory.summary.advisoryNotFound` Conseiller cannot resolve the advisory or tenant forbidden.
- `409 advisory.summary.contextUnavailable` SBOM context still indexing; retry later.
### 7.2 `POST /v1/advisory-ai/conflicts`
Explain conflicting VEX statements, ranked by trust metadata.
- **Additional payload hints:** Set `preferredSections` to include `Conflicts` or targeted statement IDs.
- **Response extensions:** `content.format` remains Markdown; `context.conflicts` array highlights conflicting statement IDs and trust scores.
- **Errors:** include `404 advisory.conflict.vexNotFound`, `409 advisory.conflict.trustDataPending` (waiting on Excititor linksets).
### 7.3 `POST /v1/advisory-ai/remediation`
Produce remediation plan with fix versions and verification steps.
- **Additional payload hints:** Provide `artifactId` or `artifactPurl` to unlock SBOM timeline + dependency analysis.
- **Response extensions:** `content.format` Markdown plus `context.remediation` with recommended fix versions (`package`, `fixedVersion`, `rationale`).
- **Errors:** `422 advisory.remediation.noFixAvailable` (vendor has not published fix), `409 advisory.remediation.policyHold` (policy forbids automated remediation).
### 7.4 `GET /v1/advisory-ai/outputs/{{outputHash}}`
Fetch cached artefact (same envelope as §6). Requires `advisory-ai:view`.
- **Headers:** Supports `If-None-Match` with the `outputHash` (Etag) for cache validation.
- **Errors:** `404 advisory.output.notFound` if cache expired or tenant lacks access.
### 7.5 `GET /v1/advisory-ai/plans/{{cacheKey}}` (optional)
When plan preview is enabled (feature flag `advisoryAi.planPreview.enabled`), this endpoint returns the orchestration plan using `AdvisoryPipelinePlanResponse` (task metadata, chunk/vector counts). Requires `advisory-ai:operate`.
## 8. Error model
Errors follow a standard problem+JSON envelope:
```json
{
"status": 400,
"code": "advisory.summary.missingAdvisoryKey",
"message": "advisoryKey must be provided",
"traceId": "01HECAJ6RE8T5H4P6Q0XZ7ZD4T",
"retryAfter": 30
}
```
| HTTP | Code prefix | Meaning |
|------|-------------|---------|
| 400 | `advisory.summary.*`, `advisory.remediation.*` | Validation failures or unsupported profile/task combinations |
| 401 | `auth.invalid_token` | Token expired/invalid; ensure DPoP proof matches access token |
| 403 | `auth.insufficient_scope` | Missing `advisory-ai` scope or tenant consent |
| 404 | `advisory.*.notFound` | Advisory/key not available for tenant |
| 409 | `advisory.*.contextUnavailable` | Dependencies (SBOM, VEX, policy) not ready; retry after indicated seconds |
| 422 | `advisory.*.noFixAvailable` | Remediation cannot be produced given current evidence |
| 429 | `rate_limit.exceeded` | Caller breached tenant or profile rate limit; examine `Retry-After` |
| 503 | `advisory.backend.unavailable` | Model backend offline or remote profile disabled |
All errors include `traceId` for cross-service correlation and log search.
## 9. Rate limiting & quotas
Advisory AI honours per-tenant quotas configured under `advisoryAi.rateLimits`:
- Default: 30 summary/conflict requests per minute per tenant & profile.
- Remediation requests default to 10/minute due to heavier SBOM analysis.
- Cached `GET /outputs/{{hash}}` calls share the `advisory-ai:view` bucket (60/minute).
Limits are enforced at the gateway; the API returns `429` with standard `Retry-After` seconds. Operators can adjust limits via Authority configuration bundles and propagate offline using the Offline Kit.
## 10. Observability & audit
- Metrics: `advisory_ai_requests_total``tenant,task,profile``, `advisory_ai_latency_seconds`, `advisory_ai_validation_failures_total`, `advisory_ai_cache_hits_total`.
- Logs: Structured with `traceId`, `tenant`, `task`, `profile`, `outputHash`, `cacheStatus` (`hit`|`miss`|`bypass`). Prompt bodies are **never** logged; guardrail violations emit sanitized snippets only.
- Audit events: `advisory_ai.output.generated`, `advisory_ai.output.accessed`, `advisory_ai.guardrail.blocked` ship to the Authority audit stream with tenant + actor metadata.
## 11. Offline & sovereignty considerations
- Offline installations bundle prompt templates, guardrail configs, and local model weights. Remote profiles (`cloud-openai`) remain disabled unless operators explicitly enable them and record consent per tenant.
- Cached outputs include DSSE attestations when DSSE mode is enabled. Export Center ingests cached artefacts via `GET /outputs/{{hash}}` using `advisory-ai:view`.
- Force-refresh regenerates outputs using the same cache key, allowing auditors to replay evidence during compliance reviews.
## 12. Change log
| Date (UTC) | Change |
|------------|--------|
| 2025-11-03 | Initial sprint-110 preview covering summary/conflict/remediation endpoints, cache retrieval, plan preview, and error/rate limit model. |

View File

@@ -0,0 +1,168 @@
> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied.
# Advisory AI Architecture
_Updated: 2025-11-03 • Owner: Docs Guild & Advisory AI Guild • Status: Draft_
This document decomposes how Advisory AI transforms immutable evidence into deterministic, explainable outputs. It complements `docs/modules/advisory-ai/architecture.md` with service-level views, data flows, and integration checklists for Sprint 110.
## 1. High-level flow
```
Conseiller / Excititor / SBOM / Policy
| (retrievers)
v
+----------------------------+
| AdvisoryPipelineOrchestrator |
| (plan generation) |
+----------------------------+
| plan + cache key
v
+----------------------------+
| Guarded Prompt Runtime |
| (profile-specific) |
+----------------------------+
| validated output + citations
v
+----------------------------+
| Cache & Provenance |
| (Mongo + DSSE optional) |
+----------------------------+
| \
v v
REST API CLI / Console
```
Key stages:
1. **Retrieval** deterministic chunkers pull AOC-compliant data: Conseiller advisories, Excititor VEX statements, SBOM context, Policy explain traces, optional runtime telemetry.
2. **Plan generation** the orchestrator builds an `AdvisoryTaskPlan` (Summary / Conflict / Remediation) containing budgets, prompt template IDs, cache keys, and metadata.
3. **Guarded inference** profile-specific prompt runners execute with guardrails (redaction, injection defence, citation enforcement). Failures are logged and downstream consumers receive deterministic errors.
4. **Persistence** outputs are hashed (`outputHash`), referenced with `inputDigest`, optionally sealed with DSSE, and exposed for CLI/Console consumption.
## 2. Component responsibilities
| Component | Description | Notes |
|-----------|-------------|-------|
| `AdvisoryRetrievalService` | Facade that composes Conseiller/Excititor/SBOM/Policy clients into context packs. | Deterministic ordering; per-source limits enforced. |
| `AdvisoryPipelineOrchestrator` | Builds task plans, selects prompt templates, allocates token budgets. | Tenant-scoped; memoises by cache key. |
| `GuardrailService` | Applies redaction filters, prompt allowlists, validation schemas, and DSSE sealing. | Shares configuration with Security Guild. |
| `ProfileRegistry` | Maps profile IDs to runtime implementations (local model, remote connector). | Enforces tenant consent and allowlists. |
| `AdvisoryOutputStore` | Mongo collection storing cached artefacts plus provenance manifest. | TTL defaults 24h; DSSE metadata optional. |
| `AdvisoryPipelineWorker` | Background executor for queued jobs (future sprint once 004A wires queue). | Consumes `advisory.pipeline.execute` messages. |
## 3. Data contracts
### 3.1 `AdvisoryTaskRequest`
```json
{
"taskType": "Summary",
"advisoryKey": "csaf:redhat:RHSA-2025:1001",
"artifactId": "registry.stella-ops.internal/runtime/api",
"artifactPurl": "pkg:oci/runtime-api@sha256:d2c3...",
"policyVersion": "2025.10.1",
"profile": "fips-local",
"preferredSections": ["Summary", "Remediation"],
"forceRefresh": false
}
```
- `taskType``Summary|Conflict|Remediation`.
- Provide either `artifactId` or `artifactPurl` for remediation tasks (unlocks dependency analysis).
- `forceRefresh` bypasses cache and regenerates output (deterministic with identical inputs).
### 3.2 `AdvisoryPipelinePlanResponse`
Returned when plan preview is enabled; summarises chunk and vector usage so operators can verify evidence.
```json
{
"taskType": "Summary",
"cacheKey": "adv-summary:csaf:redhat:RHSA-2025:1001:fips-local",
"budget": { "promptTokens": 1024, "completionTokens": 256 },
"chunks": [{"documentId": "doc-1", "chunkId": "doc-1:0001", "section": "Summary"}],
"vectors": [{"query": "Summary query", "matches": [{"chunkId": "doc-1:0001", "score": 0.92}]}],
"sbom": {
"artifactId": "registry.stella-ops.internal/runtime/api",
"versionTimelineCount": 8,
"dependencyPathCount": 5,
"dependencyNodeCount": 17
}
}
```
### 3.3 Output envelope
See `docs/advisory-ai/api.md` §6. Each response includes `inputDigest`, `outputHash`, Markdown content, citations, TTL, and context summary to support offline replay.
## 4. Profiles & runtime selection
| Profile | Runtime | Crypto posture | Default availability |
|---------|---------|----------------|----------------------|
| `default` / `fips-local` | On-prem model (GPU/CPU) | FIPS-validated primitives | Enabled |
| `gost-local` | Sovereign local model | GOST algorithms | Opt-in |
| `cloud-openai` | Remote connector via secure gateway | Depends on hosting region | Disabled (requires tenant consent) |
| Custom | Operator-supplied | Matches declared policy | Disabled until Authority admin approves |
Profile selection is controlled via Authority configuration (`advisoryAi.allowedProfiles`). Remote profiles require tenant consent, allowlisted endpoints, and custom SLIs to track latency/error budgets.
## 5. Guardrails & validation pipeline
1. **Prompt preparation** sanitized context injected into templated prompts (Liquid/Handlebars). Sensitive tokens scrubbed before render.
2. **Prompt allowlist** each template fingerprinted; runtime rejects prompts whose hash is not documented.
3. **Response schema** JSON validator ensures sections, severity tags, and citation arrays meet contract.
4. **Citation resolution** referenced `[n]` items must map to context chunk identifiers.
5. **DSSE sealing (optional)** outputs can be sealed with the Advisory AI signing key; DSSE bundle stored alongside cache artefact.
6. **Audit trail** guardrail results logged (`advisory_ai.guardrail.blocked|passed`) with tenant and trace IDs.
## 6. Caching & storage model
| Field | Description |
|-------|-------------|
| `_id` | `outputHash` (sha256 of content body). |
| `inputDigest` | sha256 of canonical context pack. |
| `taskType` | Summary/Conflict/Remediation. |
| `profile` | Inference profile used. |
| `content` | Markdown/JSON body and format metadata. |
| `citations` | Array of `{index, kind, sourceId, uri}`. |
| `generatedAt` | UTC timestamp. |
| `ttlSeconds` | Derived from tenant configuration (default 86400). |
| `dsse` | Optional DSSE bundle metadata. |
Cache misses trigger orchestration and inference; hits return stored artefacts immediately. TTL expiry removes entries unless `forceRefresh` has already regenerated them.
## 7. Telemetry & SLOs
Metrics (registered in Observability backlog):
- `advisory_ai_requests_total{tenant,task,profile}`
- `advisory_ai_latency_seconds_bucket`
- `advisory_ai_guardrail_blocks_total`
- `advisory_ai_cache_hits_total`
- `advisory_ai_remote_profile_requests_total`
Logs include `traceId`, `tenant`, `task`, `profile`, `outputHash`, `cacheStatus` (`hit|miss|bypass`). Prompt bodies are never logged; guardrail violations log sanitized excerpts only.
Suggested SLOs:
- **Latency:** P95 ≤ 3s (local), ≤ 8s (remote).
- **Availability:** 99.5% successful responses per tenant over 7 days.
- **Guardrail block rate:** ≤ 1%; investigate higher values.
## 8. Deployment & offline guidance
- Package prompts, guardrail configs, profile manifests, and local model weights in the Offline Kit.
- Remote profiles remain disabled until Authority admins set `advisoryAi.remoteProfiles` and record tenant consent.
- Export Center reads cached outputs using `advisory-ai:view` and benefits from DSSE sealing when enabled.
## 9. Checklist
- [ ] `AdvisoryRetrievalService` wired to the SBOM context client (AIAI-31-002).
- [ ] Authority scopes (`advisory-ai:*`, `aoc:verify`) validated in staging.
- [ ] Guardrail library reviewed by Security Guild (AIAI-31-005).
- [ ] Cache TTLs/DSSE policy signed off by Platform & Compliance.
- [ ] Observability dashboards published (DOCS-OBS backlog).
- [ ] Offline Kit bundle updated with prompts, guardrails, local profile assets.
---
_For questions or contributions, contact the Advisory AI Guild (Slack #guild-advisory-ai) and tag Docs Guild reviewers._

View File

@@ -0,0 +1,102 @@
> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied.
# Advisory AI Overview
_Updated: 2025-11-03 • Owner: Docs Guild & Advisory AI Guild • Status: Draft_
Advisory AI is the retrieval-augmented assistant that synthesises Conseiller (advisory) and Excititor (VEX) evidence, Policy Engine context, and SBOM insights into explainable outputs. It operates under the Aggregation-Only Contract (AOC): no derived intelligence alters or mutates raw facts, and every generated recommendation is paired with verifiable provenance.
## 1. Value proposition
- **Summaries on demand** deterministically produce advisory briefs that highlight impact, exploitability, and mitigation steps with paragraph-level citations.
- **Conflict explainers** reconcile diverging VEX statements by exposing supplier trust metadata, confidence weights, and precedence logic.
- **Remediation planning** merge SBOM timelines, dependency paths, and policy thresholds to propose actionable remediation plans tailored to the requesting tenant.
- **Offline parity** the same workflows execute in air-gapped deployments using local inference profiles; cache artefacts can be exported as DSSE bundles for audits.
## 2. Architectural highlights
| Layer | Responsibilities | Key dependencies |
|-------|------------------|------------------|
| Retrievers | Fetch deterministic advisory/VEX/SBOM context, guardrail inputs, policy digests. | Conseiller, Excititor, SBOM Service, Policy Engine |
| Orchestrator | Builds `AdvisoryTaskPlan` objects (summary/conflict/remediation) with budgets and cache keys. | Deterministic toolset (AIAI-31-003), Authority scopes |
| Guardrails | Enforce redaction, structured prompts, citation validation, injection defence, and DSSE sealing. | Security Guild guardrail library |
| Outputs | Persist cache entries (hash + context manifest), expose via API/CLI/Console, emit telemetry. | Mongo cache store, Export Center, Observability stack |
See `docs/modules/advisory-ai/architecture.md` for deep technical diagrams and sequence flows.
## 3. Guardrails & compliance
1. **Aggregation-only** only raw facts from authorised sources are consumed; no on-the-fly enrichment beyond deterministic tooling.
2. **Citation-first** every sentence referencing external evidence must cite a canonical paragraph/statement identifier.
3. **Content filters** redaction, policy-based profanity filters, and prompt allowlists are applied before model invocation.
4. **Deterministic cache** outputs are stored with `inputDigest` and `outputHash`; force-refresh regenerates the same output unless upstream evidence changes.
5. **Audit & scope** Authority scopes (`advisory-ai:view|operate|admin`) plus `aoc:verify` are mandatory; audit events (`advisory_ai.output.generated`, etc.) flow to the Authority ledger.
## 4. Supported personas & surfaces
| Persona | Typical role | Access |
|---------|--------------|--------|
| **Operations engineer** | Reviews summaries/remediation recommendations during incident triage. | Console + `advisory-ai:view` |
| **Platform engineer** | Automates remediation planning via CI/CD or CLI. | CLI + API + `advisory-ai:operate` |
| **Security/Compliance** | Audits guardrail decisions, exports outputs for evidence lockers. | API/Export Center + `advisory-ai:view` |
| **Service owner** | Tunes profiles, remote inference settings, and rate limits. | Authority admin + `advisory-ai:admin` |
Surfaces:
- **Console**: dashboard widgets (pending in CONSOLE-AIAI backlog) render cached summaries and conflicts.
- **CLI**: `stella advise run <task>` (AIAI-31-004C) for automation scripts.
- **API**: `/v1/advisory-ai/*` endpoints documented in `docs/advisory-ai/api.md`.
## 5. Data sources & provenance
- **Advisories** Conseiller raw observations (CSAF/OSV) with paragraph anchors and supersedes chains.
- **VEX statements** Excititor VEX observations plus trust weights provided by VEX Lens.
- **SBOM context** SBOM Service timelines and dependency graphs (requires AIAI-31-002 completion).
- **Policy** Policy Engine explain traces, waivers, and risk ratings used to contextualise responses.
- **Runtime posture** Optional Zastava signals (exposure, admission status) when available.
All sources are referenced via content hashes (`content_hash`, `statement_id`, `timeline_entry_id`) ensuring reproducibility.
## 6. Profiles & deployment options
| Profile | Location | Notes |
|---------|----------|-------|
| `default` / `fips-local` | On-prem GPU/CPU | Packaged with Offline Kit; FIPS-approved crypto.
| `gost-local` | Sovereign clusters | GOST-compliant crypto & model pipeline.
| `cloud-openai` | Remote (optional) | Disabled by default; requires tenant consent and policy alignment.
| Custom profiles | Operator-defined | Managed via Authority `advisory-ai` admin APIs and documented policy bundles.
Offline deployments mirror prompts, guardrails, and weights within Offline Kits. Remote profiles must pass through Authority consent enforcement and strict allowlists.
## 7. Observability & SLOs
Metrics (pre-registered in Observability backlog):
- `advisory_ai_requests_total{tenant,task,profile}`
- `advisory_ai_latency_seconds_bucket`
- `advisory_ai_guardrail_blocks_total`
- `advisory_ai_cache_hits_total`
Suggested SLOs (subject to Observability sprint sign-off):
- P95 latency ≤ 3s for local profiles, ≤ 8s for remote profiles.
- Guardrail block rate < 1% (investigate above threshold).
- Cache hit ratio 60% for repeated advisory requests per tenant.
## 8. Roadmap & dependencies
| Area | Key tasks |
|------|----------|
| API delivery | DOCS-AIAI-31-003 (completed), AIAI-31-004A (service wiring), AIAI-31-006 (public endpoints). |
| Guardrails | AIAI-31-005, Security Guild reviews, DSSE provenance wiring (AIAI-31-004B). |
| CLI & Console | AIAI-31-004C (CLI), CONSOLE-AIAI tasks (dashboards, widgets). |
| Docs | DOCS-AIAI-31-002 (architecture deep-dive), DOCS-AIAI-31-004 (console guide), DOCS-AIAI-31-005 (CLI guide). |
## 9. Checklist
- [ ] SBOM context retriever (AIAI-31-002) completed and tested across ecosystems.
- [ ] Guardrail library integrated and security-reviewed.
- [ ] Authority scopes and consent toggles validated in staging.
- [ ] Telemetry dashboard reviewed with Observability guild.
- [ ] Offline kit bundle includes prompts, guardrail configs, local profile weights.
---
_For questions or contributions, contact the Advisory AI Guild (Slack #guild-advisory-ai) and tag Docs Guild reviewers._

View File

@@ -58,6 +58,8 @@ Air-Gapped Mode is the supported operating profile for deployments with **zero e
- **Authority scopes:** enforce `airgap:status:read`, `airgap:import`, and `airgap:seal` via tenant-scoped roles; require operator reason/ticket metadata for sealing.
- **Incident response:** maintain scripts for replaying imports, regenerating manifests, and exporting forensic data without egress.
- **EgressPolicy facade:** all services route outbound calls through `StellaOps.AirGap.Policy`. In sealed mode `EgressPolicy` enforces the `airgap.egressAllowlist`, auto-permits loopback targets, and raises `AIRGAP_EGRESS_BLOCKED` exceptions with remediation text (add host to allowlist or coordinate break-glass). Unsealed mode logs intents but does not block, giving operators a single toggle for rehearsals. Task Runner now feeds every `run.egress` declaration and runtime network hint into the shared policy during planning, preventing sealed-mode packs from executing unless destinations are declared and allow-listed.
- **CLI guard:** the CLI now routes outbound HTTP through the shared egress policy. When sealed, commands that would dial external endpoints (for example, `scanner download` or remote `sources ingest` URIs) are refused with `AIRGAP_EGRESS_BLOCKED` messaging and remediation guidance instead of attempting the network call.
- **Observability exporters:** `StellaOps.Telemetry.Core` now binds OTLP exporters to the configured egress policy. When sealed, any collector endpoint that is not loopback or allow-listed is skipped at startup and a structured warning is written so operators see the remediation guidance without leaving sealed mode.
- **Linting/CI:** enable the `StellaOps.AirGap.Policy.Analyzers` package in solution-level analyzers so CI fails on raw `HttpClient` usage. The analyzer emits `AIRGAP001` and the bundled code fix rewrites to `EgressHttpClientFactory.Create(...)`; treat analyzer warnings as errors in sealed-mode pipelines.
## Testing & verification

View File

@@ -0,0 +1,90 @@
# Portable Evidence Bundles (Sealed/Air-Gapped)
> Sprint 160 · Task EVID-OBS-60-001
> Audience: Evidence Locker operators, Air-Gap controllers, incident responders
Portable bundles let operators hand off sealed evidence across enclaves without exposing tenant identifiers or internal storage coordinates. The Evidence Locker produces a deterministic archive (`portable-bundle-v1.tgz`) that carries the manifest + signature alongside redacted metadata, checksum manifest, and an offline verification script.
## 1. When to use the portable flow
- **Sealed mode exports.** Regulatory or incident response teams that cannot access the primary enclave directly.
- **Chain-of-custody transfers.** Moving evidence into offline review systems while keeping the DSSE provenance intact.
- **Break-glass rehearsals.** Validating incident response playbooks without exposing internal bundle metadata.
Avoid portable bundles for regular intra-enclave automation; the full `bundle.tgz` already carries richer metadata for automated tooling.
## 2. Generating the bundle
1. Seal the evidence bundle as usual (`POST /evidence/snapshot` or via CLI).
2. Request the portable artefact using the new endpoint:
```
GET /evidence/{bundleId}/portable
Scope: evidence:read
```
Response headers mirror the standard download (`application/gzip`, `Content-Disposition: attachment; filename="portable-evidence-bundle-{bundleId}.tgz"`).
The Evidence Locker caches the portable archive using write-once semantics. Subsequent requests reuse the existing object and the audit log records whether the file was newly created or served from cache.
## 3. Archive layout
```
portable-bundle-v1.tgz
├── manifest.json # Canonical bundle manifest (identical to sealed bundle)
├── signature.json # DSSE signature + optional RFC3161 timestamp (base64 token)
├── bundle.json # Redacted metadata (bundleId, kind, rootHash, timestamps, incidentMetadata)
├── checksums.txt # Merkle root + per-entry SHA-256 digests
├── instructions-portable.txt # Human-readable guidance for sealed transfers
└── verify-offline.sh # POSIX shell helper (extract + checksum verify + reminder to run DSSE verification)
```
Redaction rules:
- No tenant identifiers, storage keys, descriptions, or free-form metadata.
- Incident metadata is retained *only* under the `incidentMetadata` object (`incident.mode`, `incident.changedAt`, etc.).
- `portableGeneratedAt` records when the archive was produced so downstream systems can reason about freshness.
## 4. Offline verification workflow
1. Copy `portable-bundle-v1.tgz` into the sealed environment (USB, sneaker-net, etc.).
2. Run the included helper from a POSIX shell:
```sh
chmod +x verify-offline.sh
./verify-offline.sh portable-bundle-v1.tgz
```
The script:
- extracts the archive into a temporary directory,
- validates `checksums.txt` using `sha256sum` (or `shasum -a 256`), and
- prints the Merkle root hash from `bundle.json`.
3. Complete provenance verification:
- Preferred: `stella evidence verify --bundle portable-bundle-v1.tgz`
- Alternative: supply `manifest.json` and `signature.json` to the evidence verifier library.
4. Record the verification output (root hash, timestamp) with the receiving enclaves evidence locker or incident ticket.
> **Note:** The DSSE payload is unchanged from the sealed bundle, so existing verification tooling does not need special handling for portable archives.
## 5. Importing into the receiving enclave
1. Upload the archive to the target Evidence Locker or attach it to the incident record.
2. Store the checksum report generated by `verify-offline.sh` alongside the archive.
3. If downstream automation needs enriched metadata, attach a private note referencing the original bundles tenant context—the portable archive intentionally omits it.
## 6. Troubleshooting
| Symptom | Likely cause | Remediation |
|--------|--------------|-------------|
| `verify-offline.sh` reports checksum failures | Transfer corruption | Re-transfer artefact; run `sha256sum portable-bundle-v1.tgz` on both sides and compare. |
| `stella evidence verify` cannot reach TSA | Sealed environment lacks TSA connectivity | Verification still succeeds using DSSE signature; capture the missing TSA warning in the import log. |
| `/portable` endpoint returns 400 | Bundle not yet sealed or signature missing | Wait for sealing to complete; ensure DSSE signing is enabled. |
| `/portable` returns 404 | Bundle not found or tenant mismatch | Confirm DPoP scope and tenant claim; refresh bundle status via `GET /evidence/{id}`. |
## 7. Change management
- Portable bundle versioning is encoded in the filename (`portable-bundle-v1.tgz`). When content or script behaviour changes, bump the version and announce in release notes.
- Any updates to `verify-offline.sh` must remain POSIX-sh compatible and avoid external dependencies beyond `tar`, `sha256sum`/`shasum`, and standard coreutils.
- Remember to update this guide and the bundle packaging dossier (`docs/modules/evidence-locker/bundle-packaging.md`) when fields or workflows change.

View File

@@ -0,0 +1,20 @@
%% Standard plug-in bootstrap sequence (Mermaid)
sequenceDiagram
autonumber
participant Operator as Operator / DevOps
participant Host as Authority Host
participant Registrar as StandardPluginRegistrar
participant Store as Credential Store
participant Audit as Audit Sink
participant Telemetry as Telemetry Pipeline
Operator->>Host: Deploy plugin manifest + offline secrets bundle
Host->>Registrar: Load options + validate capabilities
Registrar->>Store: Ensure collections + indexes
Registrar->>Store: Seed bootstrap principals (hashed passwords, roles)
Store-->>Registrar: Acknowledge deterministic bootstrap state
Registrar-->>Host: Register IIdentityProviderPlugin + capability metadata
Host->>Registrar: Invoke WarmupAsync (health checks, secret validation)
Registrar->>Audit: Emit authority.plugin.load event
Registrar->>Telemetry: Emit structured logs and counters
Host-->>Operator: Report readiness (plugin lifecycle complete)

View File

@@ -0,0 +1,112 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 360" role="img">
<title>Standard plug-in bootstrap sequence</title>
<defs>
<style>
.actor { fill: #1e293b; stroke: #334155; stroke-width: 2; rx: 12; ry: 12; }
.actor text { fill: #f8fafc; font: 14px "Segoe UI", sans-serif; }
.lifeline { stroke: #475569; stroke-width: 2; stroke-dasharray: 6 6; }
.arrow { fill: none; stroke: #38bdf8; stroke-width: 2.5; marker-end: url(#arrow); }
.label { fill: #e2e8f0; font: 13px "Segoe UI", sans-serif; }
.step { fill: #94a3b8; font: 12px "Segoe UI", sans-serif; }
</style>
<marker id="arrow" markerWidth="12" markerHeight="12" refX="10" refY="6" orient="auto">
<path d="M0,0 L12,6 L0,12 z" fill="#38bdf8" />
</marker>
</defs>
<g>
<rect class="actor" x="40" y="20" width="140" height="40" />
<text x="110" y="45" text-anchor="middle">Operator / DevOps</text>
<line class="lifeline" x1="110" y1="60" x2="110" y2="350" />
</g>
<g>
<rect class="actor" x="210" y="20" width="140" height="40" />
<text x="280" y="45" text-anchor="middle">Authority Host</text>
<line class="lifeline" x1="280" y1="60" x2="280" y2="350" />
</g>
<g>
<rect class="actor" x="380" y="20" width="150" height="40" />
<text x="455" y="45" text-anchor="middle">Standard Registrar</text>
<line class="lifeline" x1="455" y1="60" x2="455" y2="350" />
</g>
<g>
<rect class="actor" x="560" y="20" width="140" height="40" />
<text x="630" y="45" text-anchor="middle">Credential Store</text>
<line class="lifeline" x1="630" y1="60" x2="630" y2="350" />
</g>
<g>
<rect class="actor" x="720" y="20" width="120" height="40" />
<text x="780" y="45" text-anchor="middle">Audit Sink</text>
<line class="lifeline" x1="780" y1="60" x2="780" y2="350" />
</g>
<g>
<rect class="actor" x="870" y="20" width="120" height="40" />
<text x="930" y="45" text-anchor="middle">Telemetry</text>
<line class="lifeline" x1="930" y1="60" x2="930" y2="350" />
</g>
<g>
<text class="step" x="80" y="90">1</text>
<path class="arrow" d="M110 90 H270" />
<text class="label" x="190" y="82" text-anchor="middle">Deploy manifest + secrets bundle</text>
</g>
<g>
<text class="step" x="250" y="120">2</text>
<path class="arrow" d="M280 120 H440" />
<text class="label" x="360" y="112" text-anchor="middle">Load options and validate capabilities</text>
</g>
<g>
<text class="step" x="420" y="150">3</text>
<path class="arrow" d="M455 150 H630" />
<text class="label" x="540" y="142" text-anchor="middle">Ensure collections and indexes</text>
</g>
<g>
<text class="step" x="420" y="180">4</text>
<path class="arrow" d="M455 180 H630" />
<text class="label" x="540" y="172" text-anchor="middle">Seed bootstrap principals</text>
</g>
<g>
<text class="step" x="600" y="210">5</text>
<path class="arrow" d="M630 210 H460" />
<text class="label" x="540" y="202" text-anchor="middle">Return deterministic bootstrap state</text>
</g>
<g>
<text class="step" x="420" y="240">6</text>
<path class="arrow" d="M455 240 H280" />
<text class="label" x="360" y="232" text-anchor="middle">Registrar registers plugin + metadata</text>
</g>
<g>
<text class="step" x="250" y="270">7</text>
<path class="arrow" d="M280 270 H455" />
<text class="label" x="365" y="262" text-anchor="middle">Invoke WarmupAsync checks</text>
</g>
<g>
<text class="step" x="420" y="300">8</text>
<path class="arrow" d="M455 300 H780" />
<text class="label" x="620" y="292" text-anchor="middle">Emit authority.plugin.load audit event</text>
</g>
<g>
<text class="step" x="420" y="310">9</text>
<path class="arrow" d="M455 310 H930" />
<text class="label" x="700" y="302" text-anchor="middle">Forward structured logs and counters</text>
</g>
<g>
<text class="step" x="250" y="340">10</text>
<path class="arrow" d="M280 340 H110" />
<text class="label" x="200" y="332" text-anchor="middle">Report readiness to operator</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -0,0 +1,50 @@
%% Standard Authority plug-in component overview (Mermaid)
flowchart LR
subgraph Host["Authority Host"]
config[AuthorityPluginConfigurationLoader
(bind + validate options)]
pluginHost[PluginHost Registrar Loader
(IAuthorityPluginRegistrar)]
api[Minimal API Endpoints
/token, /device/code, /internal/*]
telemetry[Structured Telemetry
(logs - metrics - traces)]
end
subgraph StandardPlugin["Standard Identity Provider Plug-in"]
registrar[StandardPluginRegistrar
(registers services, capabilities)]
options[StandardPluginOptions
(offline YAML input)]
identity[IIdentityProviderPlugin
(password & bootstrap flows)]
store[StandardUserCredentialStore
(Mongo collections)]
capability[Capability Metadata
(password, bootstrap, clientProvisioning)]
end
subgraph External["External Systems"]
mongo[(MongoDB cluster
credential + lockout state)]
audit[(Audit Sink / Event Bus)]
secrets[Offline Secrets Bundle
(keys, salts, bootstrap users)]
opsRepo[(Offline Kit Assets)]
end
config --> registrar
pluginHost --> registrar
registrar --> options
registrar --> capability
registrar --> identity
identity --> store
identity --> audit
store --> mongo
options --> secrets
secrets --> registrar
api --> identity
telemetry --> opsRepo
pluginHost --> telemetry
capability --> pluginHost
audit --> telemetry

View File

@@ -0,0 +1,106 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 420" role="img">
<title>Authority Standard plug-in component topology</title>
<defs>
<style>
.cluster { fill: #0b1120; stroke: #1e293b; stroke-width: 2; rx: 20; ry: 20; }
.cluster-title { fill: #e2e8f0; font: 16px "Segoe UI", sans-serif; font-weight: 600; }
.node { fill: #1e293b; stroke: #334155; stroke-width: 2; rx: 12; ry: 12; }
.node text { fill: #f8fafc; font: 14px "Segoe UI", sans-serif; }
.node-small { fill: #0f172a; stroke: #334155; stroke-width: 2; rx: 12; ry: 12; }
.node-small text { fill: #e2e8f0; font: 13px "Segoe UI", sans-serif; }
.annotation { fill: #94a3b8; font: 12px "Segoe UI", sans-serif; }
.arrow { fill: none; stroke: #38bdf8; stroke-width: 2.5; marker-end: url(#arrow); }
</style>
<marker id="arrow" markerWidth="12" markerHeight="12" refX="10" refY="6" orient="auto">
<path d="M0,0 L12,6 L0,12 z" fill="#38bdf8" />
</marker>
</defs>
<rect class="cluster" x="30" y="60" width="260" height="320" rx="20" ry="20" />
<text class="cluster-title" x="65" y="88">Authority Host</text>
<g class="node">
<rect x="50" y="110" width="220" height="48" rx="12" ry="12" />
<text x="60" y="138">Configuration Loader</text>
<text class="annotation" x="60" y="156">AuthorityPluginConfigurationLoader</text>
</g>
<g class="node">
<rect x="50" y="175" width="220" height="52" rx="12" ry="12" />
<text x="60" y="205">PluginHost registrar loader</text>
<text class="annotation" x="60" y="223">IAuthorityPluginRegistrar</text>
</g>
<g class="node">
<rect x="50" y="245" width="220" height="52" rx="12" ry="12" />
<text x="60" y="275">Minimal API endpoints</text>
<text class="annotation" x="60" y="293">/token, /device/code, /internal/*</text>
</g>
<g class="node">
<rect x="50" y="315" width="220" height="52" rx="12" ry="12" />
<text x="60" y="345">Structured telemetry</text>
<text class="annotation" x="60" y="363">logs - metrics - traces</text>
</g>
<rect class="cluster" x="350" y="40" width="260" height="360" rx="20" ry="20" />
<text class="cluster-title" x="378" y="68">Standard plug-in</text>
<g class="node">
<rect x="370" y="90" width="220" height="50" rx="12" ry="12" />
<text x="380" y="118">StandardPluginRegistrar</text>
<text class="annotation" x="380" y="136">bind services &amp; capabilities</text>
</g>
<g class="node">
<rect x="370" y="155" width="220" height="50" rx="12" ry="12" />
<text x="380" y="183">StandardPluginOptions</text>
<text class="annotation" x="380" y="201">offline YAML configuration</text>
</g>
<g class="node">
<rect x="370" y="220" width="220" height="50" rx="12" ry="12" />
<text x="380" y="248">Capability metadata</text>
<text class="annotation" x="380" y="266">password - bootstrap - clientProvisioning</text>
</g>
<g class="node">
<rect x="370" y="285" width="220" height="48" rx="12" ry="12" />
<text x="380" y="313">IIdentityProviderPlugin</text>
<text class="annotation" x="380" y="331">password &amp; bootstrap flows</text>
</g>
<g class="node">
<rect x="370" y="345" width="220" height="48" rx="12" ry="12" />
<text x="380" y="373">StandardUserCredentialStore</text>
<text class="annotation" x="380" y="391">Mongo-backed state</text>
</g>
<rect class="cluster" x="670" y="60" width="260" height="320" rx="20" ry="20" />
<text class="cluster-title" x="715" y="88">External systems</text>
<g class="node-small">
<rect x="690" y="110" width="220" height="46" rx="12" ry="12" />
<text x="700" y="138">Offline secrets bundle</text>
<text class="annotation" x="700" y="156">keys - salts - bootstrap users</text>
</g>
<g class="node-small">
<rect x="690" y="170" width="220" height="46" rx="12" ry="12" />
<text x="700" y="198">MongoDB cluster</text>
<text class="annotation" x="700" y="216">credential &amp; lockout state</text>
</g>
<g class="node-small">
<rect x="690" y="230" width="220" height="46" rx="12" ry="12" />
<text x="700" y="258">Audit/event sink</text>
<text class="annotation" x="700" y="276">authority.security.* stream</text>
</g>
<g class="node-small">
<rect x="690" y="290" width="220" height="46" rx="12" ry="12" />
<text x="700" y="318">Offline kit exports</text>
<text class="annotation" x="700" y="336">docs/assets and config bundles</text>
</g>
<path class="arrow" d="M270 134 H340" />
<path class="arrow" d="M270 204 H340" />
<path class="arrow" d="M270 256 H340" />
<path class="arrow" d="M270 326 H340" />
<path class="arrow" d="M470 140 L470 176" />
<path class="arrow" d="M470 205 L470 236" />
<path class="arrow" d="M470 270 L470 308" />
<path class="arrow" d="M470 330 L470 362" />
<path class="arrow" d="M592 120 C630 104, 650 104, 670 120" />
<path class="arrow" d="M592 190 C630 180, 650 182, 670 196" />
<path class="arrow" d="M592 248 C630 246, 650 246, 670 250" />
<path class="arrow" d="M592 308 C630 308, 650 318, 670 326" />
<path class="arrow" d="M592 360 L670 360" />
</svg>

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@@ -21,6 +21,14 @@ Authority hosts follow a deterministic plug-in lifecycle. The exported diagram (
_Source:_ `docs/assets/authority/authority-plugin-lifecycle.mmd`
### 2.1 Component boundaries
The Standard plug-in ships with a small, opinionated surface: configuration is bound during registrar execution, capability metadata feeds the host, and credential/audit flows stay deterministic and offline-friendly. The component view below highlights those boundaries and where operators supply bundles (secrets, offline kits) for air-gapped installs.
![Standard plug-in component topology](../assets/authority/authority-plugin-component.svg)
_Source:_ `docs/assets/authority/authority-plugin-component.mmd`
**Data persistence primer:** the standard Mongo-backed plugin stores users in collections named `authority_users_<pluginName>` and lockout metadata in embedded documents. Additional plugins must document their storage layout and provide deterministic collection naming to honour the Offline Kit replication process.
## 3. Capability Metadata
@@ -111,6 +119,18 @@ Capability flags let the host reason about what your plug-in supports:
- Health checks should probe backing stores (e.g., Mongo `ping`) and return `AuthorityPluginHealthResult` so `/ready` can surface issues.
- When supporting additional factors (e.g., TOTP), implement `SupportsMfa` and document the enrolment flow for resource servers.
### 6.1 Bootstrap lifecycle
Standard plug-in installs begin with an operator-provided manifest and secrets bundle. The registrar validates those inputs, primes the credential store, and only then exposes the identity surface to the host. Every transition is observable (audit events + telemetry) and deterministic so air-gapped operators can replay the bootstrap evidence.
- Secrets bundles must already contain hashed bootstrap principals. Registrars re-hash only to upgrade algorithms (e.g., PBKDF2 to Argon2id) and log the outcome.
- `WarmupAsync` should fail fast when Mongo indexes or required secrets are missing; readiness stays `Unhealthy` until the registrar reports success.
- Audit and telemetry payloads (`authority.plugin.load`) are mirrored into Offline Kits so security reviewers can verify who seeded credentials and when.
![Standard plug-in bootstrap sequence](../assets/authority/authority-plugin-bootstrap-sequence.svg)
_Source:_ `docs/assets/authority/authority-plugin-bootstrap-sequence.mmd`
## 7. Configuration & Secrets
- Authority looks for manifests under `etc/authority.plugins/`. Each YAML file maps directly to a plug-in name.
- Support environment overrides using `STELLAOPS_AUTHORITY_PLUGINS__DESCRIPTORS__<NAME>__...`.

View File

@@ -41,5 +41,7 @@ The messages use structured properties (`Idx`, `Category`, `DocumentId`, `Severi
- Metrics carry Hangul `category` tags and logging keeps Hangul strings intact; this ensures air-gapped operators can validate native-language content without relying on MT.
- Fixtures live under `src/Concelier/__Tests/StellaOps.Concelier.Connector.Kisa.Tests/Fixtures/`. Regenerate with `UPDATE_KISA_FIXTURES=1 dotnet test src/Concelier/__Tests/StellaOps.Concelier.Connector.Kisa.Tests/StellaOps.Concelier.Connector.Kisa.Tests.csproj`.
- The regression suite asserts canonical mapping, state cleanup, and telemetry counters (`KisaConnectorTests.Telemetry_RecordsMetrics`) so QA can track instrumentation drift.
- When capturing new offline samples, use `scripts/kisa_capture_html.py` to mirror the RSS feed and write `detailDos.do?IDX=…` HTML into `seed-data/kisa/html/`; the SPA now embeds full advisory content in the HTML response while `rssDetailData.do` returns an error page for unauthenticated clients.
- 2025-11-03: Connector fetches `detailDos.do` HTML during the fetch phase and the parser now extracts vendor/product tables directly from the DOM when JSON detail API payloads are unavailable.
For operator docs, link to this brief when documenting Hangul handling or counter dashboards so localisation reviewers have a single reference point.

View File

@@ -14,13 +14,39 @@ Follow the sprint files below in order. Update task status in both `SPRINTS` and
- [Ops & Offline](./SPRINT_190_ops_offline.md)
- [Documentation & Process](./SPRINT_200_documentation_process.md)
> 2025-11-03: ATTESTOR-72-003 moved to DOING (Attestor Service Guild) running live TTL validation against local MongoDB/Redis processes (manual hosts, no Docker).
> 2025-11-03: ATTESTOR-72-003 marked DONE (Attestor Service Guild) Mongo/Redis TTL expiry logs archived under `docs/modules/attestor/evidence/2025-11-03-*.txt` with summary in `docs/modules/attestor/ttl-validation.md`.
> 2025-11-03: AIAI-31-004B moved to DOING (Advisory AI Guild) starting prompt assembler/guardrail plumbing, cache persistence contract, and DSSE provenance wiring.
> 2025-11-03: PLG7.RFC marked DONE (Auth Plugin Guild, Security Guild) LDAP plugin RFC accepted; review log stored at `docs/notes/2025-11-03-authority-plugin-ldap-review.md`, follow-up PLG7.IMPL-001..005 queued.
> 2025-11-03: PLG7.IMPL-001 marked DONE (Auth Plugin Guild) new `StellaOps.Authority.Plugin.Ldap` project/tests scaffolded with configuration normalization & validation; sample manifest refreshed and smoke tests run (`dotnet test`).
> 2025-11-03: AIAI-31-004B marked DONE (Advisory AI Guild) prompt assembler, guardrail hooks, DSSE-ready output persistence, and golden prompt tests landed.
> 2025-11-03: AIAI-31-005 moved to DOING (Advisory AI Guild) beginning guardrail enforcement (redaction, injection defence, output validator) implementation.
> 2025-11-03: AIAI-31-006 moved to DOING (Advisory AI Guild) starting Advisory AI REST API surface work (RBAC, rate limits, batching contract).
> 2025-11-03: EVID-OBS-53-001 moved to DOING (Evidence Locker Guild) bootstrapping Evidence Locker schema and storage abstractions.
> 2025-11-03: GRAPH-INDEX-28-002 marked DONE (Graph Indexer Guild) SBOM ingest transformer, processor, and metrics landed with refreshed fixtures/tests for license and base artifact determinism.
> 2025-11-03: GRAPH-INDEX-28-003 marked DONE (Graph Indexer Guild) advisory linkset snapshot model repaired, transformer finalized with dedupe/canonical provenance, fixtures refreshed, and overlay tests passing across the graph suite.
> 2025-11-03: GRAPH-INDEX-28-004 moved to DOING (Graph Indexer Guild) beginning VEX overlay integration with precedent/justification metadata.
> 2025-11-03: GRAPH-INDEX-28-004 marked DONE (Graph Indexer Guild) VEX snapshot/transformer merged with deterministic overlays, fixtures refreshed, and graph indexer tests passing.
> 2025-11-03: GRAPH-INDEX-28-005 moved to DOING (Graph Indexer Guild, Policy Guild) starting policy overlay hydration (`governs_with` nodes/edges) with explain hash references.
> 2025-11-03: GRAPH-INDEX-28-005 marked DONE (Graph Indexer Guild, Policy Guild) policy overlay snapshot/transformer landed with deterministic nodes/edges and fixture-backed tests; Mongo writer tests now probe `STELLAOPS_TEST_MONGO_URI`/localhost before falling back to Mongo2Go and skip when no mongod is reachable.
> 2025-11-03: GRAPH-INDEX-28-006 moved to DOING (Graph Indexer Guild) starting SBOM snapshot export with lineage metadata and diff-ready manifests.
> 2025-11-03: GRAPH-INDEX-28-006 marked DONE (Graph Indexer Guild) snapshot builder emits hashed manifest + adjacency, tests/documentation updated with Mongo requirements.
> 2025-11-03: EVID-OBS-53-001 marked DONE (Evidence Locker Guild) Postgres migrations, RLS policies, filesystem/S3 stores, and compliance checklist landed with tests.
> 2025-11-03: EVID-OBS-53-002 moved to DOING (Evidence Locker Guild, Orchestrator Guild) assembling evaluation/job/export bundle builders with Merkle manifest contract.
> 2025-11-03: EVID-OBS-53-002 marked DONE (Evidence Locker Guild, Orchestrator Guild) deterministic bundle builders persisted root hashes and landed manifest tests/docs stubs.
> 2025-11-03: AIRGAP-POL-57-002 confirmed DOING (AirGap Policy Guild, Task Runner Guild) continuing Task Runner sealed-mode egress validation and test sweep.
> 2025-11-03: AIRGAP-POL-57-002 marked DONE (AirGap Policy Guild, Task Runner Guild) worker now injects `IEgressPolicy`, filesystem dispatcher enforces sealed-mode egress, planner grants normalized, sealed-mode dispatcher test added; follow-up queued to lift remaining dispatchers/executors onto the shared policy before sealing the full worker loop.
> 2025-11-03: MERGE-LNM-21-001 moved to DOING (BE-Merge, Architecture Guild) drafting `no-merge` migration playbook outline and capturing rollout/backfill checkpoints.
> 2025-11-03: MERGE-LNM-21-001 marked DONE published `docs/migration/no-merge.md` with rollout, backfill, validation, and rollback guidance for the LNM cutover.
> 2025-11-04: GRAPH-INDEX-28-011 marked DONE (Graph Indexer Guild) SBOM ingest DI wiring now emits graph snapshots by default, snapshot root configurable via `STELLAOPS_GRAPH_SNAPSHOT_DIR`, and Graph Indexer tests exercised with Mongo URI guidance.
> 2025-11-03: MERGE-LNM-21-002 moved to DOING (BE-Merge) auditing `AdvisoryMergeService` call sites to scope removal and analyzer enforcement.
> 2025-11-03: DOCS-LNM-22-008 moved to DOING (Docs Guild, DevOps Guild) aligning migration playbook structure and readiness checklist.
> 2025-11-03: DOCS-LNM-22-008 marked DONE `/docs/migration/no-merge.md` published for DevOps/Export Center planning with checklist for cutover readiness.
> 2025-11-03: SCHED-CONSOLE-27-001 marked DONE (Scheduler WebService Guild, Policy Registry Guild) policy simulation endpoints now emit SSE retry/heartbeat, enforce metadata normalization, support Mongo-backed integration, and ship auth/stream coverage.
> 2025-11-03: SCHED-CONSOLE-27-002 moved to DOING (Scheduler WebService Guild, Observability Guild) wiring policy simulation telemetry endpoints, OTEL metrics, and Registry webhooks on completion/failure.
> 2025-11-03: FEEDCONN-KISA-02-008 moved to DOING (BE-Conn-KISA, Models) starting Hangul firmware range normalization and provenance mapping for KISA advisories.
> 2025-11-03: FEEDCONN-KISA-02-008 progress SemVer normalization wired through KISA mapper with provenance slugs, exclusive marker handling, and fresh connector tests for `이상`/`미만`/`초과` scenarios plus non-numeric fallback; follow-up review queued for additional phrasing coverage before closing. Captured current detail pages via `scripts/kisa_capture_html.py` so offline HTML is available under `seed-data/kisa/html/`.
> 2025-11-03: FEEDCONN-ICSCISA-02-012 marked DONE (BE-Conn-ICS-CISA) ICS CISA connector now emits semver-aware affected.version ranges with `ics-cisa` provenance, SourceFetchService RSS fallback passes the AOC guard, and the Fetch/Parse/Map integration test is green.
> 2025-11-01: SCANNER-ANALYZERS-LANG-10-308R marked DONE (Language Analyzer Guild) heuristics fixtures, benchmarks, and coverage comparison published.
> 2025-11-01: SCANNER-ANALYZERS-LANG-10-309R marked DONE (Language Analyzer Guild) Rust analyzer packaged with offline kit smoke tests and docs.
> 2025-11-01: ENTRYTRACE-SURFACE-01 moved to DOING (EntryTrace Guild) wiring Surface.Validation and Surface.FS reuse ahead of EntryTrace runs.
@@ -61,6 +87,12 @@ Follow the sprint files below in order. Update task status in both `SPRINTS` and
> 2025-11-02: AUTH-PACKS-41-001 added shared OpenSSL 1.1 test libs so Authority & Signals Mongo2Go suites run on OpenSSL 3.
> 2025-11-02: AUTH-NOTIFY-42-001 moved to DOING (Authority Core & Security Guild) investigating `/notify/ack-tokens/rotate` 500 responses when key metadata missing.
> 2025-11-02: AUTH-NOTIFY-42-001 marked DONE (Authority Core & Security Guild) bootstrap rotate defaults fixed, `StellaOpsBearer` test alias added, and notify ack rotation regression passes.
> 2025-11-03: AUTH-TEN-49-001 marked DONE (Authority Core & Security Guild) service account delegation (`act` chain) shipped with quota/audit coverage; Authority tests green.
> 2025-11-03: AUTH-VULN-29-003 marked DONE (Authority Core & Docs Guild) Vuln Explorer security docs, samples, and release notes refreshed for roles, ABAC policies, attachment signing, and ledger verification.
> 2025-11-03: ISSUER-30-003 marked DONE (Issuer Directory Guild, Policy Guild) trust override APIs/client finalized with cache invalidation/failure-path tests; Issuer Directory suite passing.
> 2025-11-03: AUTH-AIRGAP-56-001/56-002 marked DONE (Authority Core & Security Guild) air-gap scope catalog surfaced in discovery/OpenAPI and `/authority/audit/airgap` endpoint shipped with tests.
> 2025-11-03: AUTH-PACKS-41-001 marked DONE (Authority Core & Security Guild) packs scope bundle now emitted via discovery metadata, reflected in OpenAPI, and covered by Authority tests.
> 2025-11-03: AUTH-POLICY-27-003 marked DONE (Authority Core & Docs Guild) Policy Studio docs/config updated for publish/promote signing workflow, CLI commands, and compliance checklist.
> 2025-11-02: ENTRYTRACE-SURFACE-02 moved to DOING (EntryTrace Guild) replacing direct env/secret access with Surface.Secrets provider for EntryTrace runs.
> 2025-11-02: ENTRYTRACE-SURFACE-01 marked DONE (EntryTrace Guild) Surface.Validation + Surface.FS cache now drive EntryTrace reuse with regression tests.
> 2025-11-02: ENTRYTRACE-SURFACE-02 marked DONE (EntryTrace Guild) EntryTrace environment placeholders resolved via Surface.Secrets with updated docs/tests.
@@ -113,3 +145,8 @@ Follow the sprint files below in order. Update task status in both `SPRINTS` and
> 2025-11-02: AIAI-31-004 moved to DOING starting deterministic orchestration pipeline (summary/conflict/remediation flow).
> 2025-11-02: ISSUER-30-006 moved to DOING (Issuer Directory Guild, DevOps Guild) deployment manifests, backup/restore, secret handling, and offline kit docs in progress.
> 2025-11-04: EVID-OBS-55-001 moved to DOING (Evidence Locker Guild, DevOps Guild) enabling incident mode retention extension, debug artefacts, and timeline/notifier hooks.
> 2025-11-04: EVID-OBS-55-001 marked DONE (Evidence Locker Guild, DevOps Guild) incident mode retention, timeline events, notifier stubs, and incident artefact packaging shipped with tests/docs.
> 2025-11-04: EVID-OBS-60-001 moved to DOING (Evidence Locker Guild) starting sealed-mode portable evidence export flow with redacted bundle packaging and offline verification guidance.
> 2025-11-04: EVID-OBS-60-001 marked DONE (Evidence Locker Guild) `/evidence/{id}/portable` now emits `portable-bundle-v1.tgz` with sanitized metadata, offline verification script, docs (`docs/airgap/portable-evidence.md`) and unit/web coverage.
> 2025-11-04: DVOFF-64-001 moved to DOING (DevPortal Offline Guild, Exporter Guild) beginning `devportal --offline` export job bundling portal HTML, specs, SDKs, and changelog assets.

View File

@@ -18,7 +18,8 @@ ATTEST-VERIFY-74-001 | DONE | Emit telemetry (spans/metrics) tagged by subject,
ATTEST-VERIFY-74-002 | DONE (2025-11-01) | Document verification report schema and explainability in `/docs/modules/attestor/workflows.md`. Dependencies: ATTEST-VERIFY-73-001. | Verification Guild, Docs Guild (src/Attestor/StellaOps.Attestor.Verify/TASKS.md)
ATTESTOR-72-001 | DONE | Scaffold service (REST API skeleton, storage interfaces, KMS integration stubs) and DSSE validation pipeline. Dependencies: ATTEST-ENVELOPE-72-001. | Attestor Service Guild (src/Attestor/StellaOps.Attestor/TASKS.md)
ATTESTOR-72-002 | DONE | Implement attestation store (DB tables, object storage integration), CRUD, and indexing strategies. Dependencies: ATTESTOR-72-001. | Attestor Service Guild (src/Attestor/StellaOps.Attestor/TASKS.md)
ATTESTOR-72-003 | BLOCKED | Validate attestation store TTL against production-like Mongo/Redis stack; capture logs and remediation plan. Dependencies: ATTESTOR-72-002. | Attestor Service Guild, QA Guild (src/Attestor/StellaOps.Attestor/TASKS.md)
ATTESTOR-72-003 | DONE (2025-11-03) | Validate attestation store TTL against production-like Mongo/Redis stack; capture logs and remediation plan. Dependencies: ATTESTOR-72-002. | Attestor Service Guild, QA Guild (src/Attestor/StellaOps.Attestor/TASKS.md)
> 2025-11-03: Mongo 7.0.5 + Redis 7.2.4 (local processes) validated; TTL expiry evidence stored in `docs/modules/attestor/evidence/2025-11-03-mongo-ttl-validation.txt` and `...redis-ttl-validation.txt`, with summary in `docs/modules/attestor/ttl-validation.md`.
ATTESTOR-73-001 | DONE (2025-11-01) | Implement signing endpoint with Ed25519/ECDSA support, KMS integration, and audit logging. Dependencies: ATTESTOR-72-002, KMS-72-001. | Attestor Service Guild, KMS Guild (src/Attestor/StellaOps.Attestor/TASKS.md)
@@ -44,10 +45,12 @@ Task ID | State | Task description | Owners (Source)
--- | --- | --- | ---
AUTH-AIAI-31-001 | DONE (2025-11-01) | Define Advisory AI scopes (`advisory-ai:view`, `advisory-ai:operate`, `advisory-ai:admin`) and remote inference toggles; update discovery metadata/offline defaults. Dependencies: AUTH-VULN-29-001. | Authority Core & Security Guild (src/Authority/StellaOps.Authority/TASKS.md)
AUTH-AIAI-31-002 | DONE (2025-11-01) | Enforce anonymized prompt logging, tenant consent for remote inference, and audit logging of assistant tasks. Dependencies: AUTH-AIAI-31-001, AIAI-31-006. | Authority Core & Security Guild (src/Authority/StellaOps.Authority/TASKS.md)
AUTH-AIRGAP-56-001 | DOING (2025-11-01) | Provision new scopes (`airgap:seal`, `airgap:import`, `airgap:status:read`) in configuration metadata, offline kit defaults, and issuer templates. Dependencies: AIRGAP-CTL-56-001. | Authority Core & Security Guild (src/Authority/StellaOps.Authority/TASKS.md)
AUTH-AIRGAP-56-002 | DOING (2025-11-01) | Audit import actions with actor, tenant, bundle ID, and trace ID; expose `/authority/audit/airgap` endpoint. Dependencies: AUTH-AIRGAP-56-001, AIRGAP-IMP-58-001. | Authority Core & Security Guild (src/Authority/StellaOps.Authority/TASKS.md)
AUTH-AIRGAP-56-001 | DONE (2025-11-03) | Provision new scopes (`airgap:seal`, `airgap:import`, `airgap:status:read`) in configuration metadata, offline kit defaults, and issuer templates. Dependencies: AIRGAP-CTL-56-001. | Authority Core & Security Guild (src/Authority/StellaOps.Authority/TASKS.md)
AUTH-AIRGAP-56-002 | DONE (2025-11-03) | Audit import actions with actor, tenant, bundle ID, and trace ID; expose `/authority/audit/airgap` endpoint. Dependencies: AUTH-AIRGAP-56-001, AIRGAP-IMP-58-001. | Authority Core & Security Guild (src/Authority/StellaOps.Authority/TASKS.md)
AUTH-AIRGAP-57-001 | BLOCKED (2025-11-01) | Enforce sealed-mode CI gating by refusing token issuance when declared sealed install lacks sealing confirmation. Dependencies: AUTH-AIRGAP-56-001, DEVOPS-AIRGAP-57-002. | Authority Core & Security Guild, DevOps Guild (src/Authority/StellaOps.Authority/TASKS.md)
> 2025-11-01: AUTH-AIRGAP-57-001 blocked pending definition of sealed-confirmation evidence and configuration shape before gating (Authority Core & Security Guild, DevOps Guild).
> 2025-11-03: Air-gap scopes now surface via discovery metadata, OpenAPI, issuer templates, and offline kit defaults; Authority tests verify supported scope inventory (`stellaops_airgap_scopes_supported`).
> 2025-11-03: `/authority/audit/airgap` endpoint audited with Mongo store + pagination filters; integration tests cover record + list flows and RBAC.
AUTH-NOTIFY-38-001 | DONE (2025-11-01) | Define `Notify.Viewer`, `Notify.Operator`, `Notify.Admin` scopes/roles, update discovery metadata, offline defaults, and issuer templates. | Authority Core & Security Guild (src/Authority/StellaOps.Authority/TASKS.md)
> 2025-11-01: AUTH-NOTIFY-38-001 completed—Notify scope catalog, discovery metadata, docs, configuration samples, and service tests updated for new roles.
AUTH-NOTIFY-40-001 | DONE (2025-11-02) | Implement signed ack token key rotation, webhook allowlists, admin-only escalation settings, and audit logging of ack actions. Dependencies: AUTH-NOTIFY-38-001, WEB-NOTIFY-40-001. | Authority Core & Security Guild (src/Authority/StellaOps.Authority/TASKS.md)
@@ -66,9 +69,10 @@ AUTH-OBS-55-001 | DONE (2025-11-02) | Harden incident mode authorization: requir
> 2025-11-02: Resource servers now enforce a five-minute fresh-auth window for `obs:incident`, incident reasons are stamped into authorization audits and `/authority/audit/incident`, and sample configs/tests updated to require tenant headers across observability endpoints.
AUTH-ORCH-34-001 | DONE (2025-11-02) | Introduce `Orch.Admin` role with quota/backfill scopes, enforce audit reason on quota changes, and update offline defaults/docs. Dependencies: AUTH-ORCH-33-001. | Authority Core & Security Guild (src/Authority/StellaOps.Authority/TASKS.md)
> 2025-11-02: Added `orch:backfill` scope with required `backfill_reason`/`backfill_ticket`, tightened Authority handlers/tests, updated CLI configuration/env vars, and refreshed docs + samples for Orchestrator admins.
AUTH-PACKS-41-001 | DOING (2025-11-02) | Define CLI SSO profiles and pack scopes (`Packs.Read`, `Packs.Write`, `Packs.Run`, `Packs.Approve`), update discovery metadata, offline defaults, and issuer templates. Dependencies: AUTH-AOC-19-001. | Authority Core & Security Guild (src/Authority/StellaOps.Authority/TASKS.md)
AUTH-PACKS-41-001 | DONE (2025-11-03) | Define CLI SSO profiles and pack scopes (`Packs.Read`, `Packs.Write`, `Packs.Run`, `Packs.Approve`), update discovery metadata, offline defaults, and issuer templates. Dependencies: AUTH-AOC-19-001. | Authority Core & Security Guild (src/Authority/StellaOps.Authority/TASKS.md)
> 2025-11-02: Pack scope policies added, Authority samples/roles refreshed, and CLI SSO profiles documented for packs operators/publishers/approvers.
> 2025-11-02: Shared OpenSSL 1.1 shim now feeds Mongo2Go for Authority & Signals tests, keeping pack scope regressions and other Mongo flows working on OpenSSL 3 hosts.
> 2025-11-03: Discovery metadata now advertises `stellaops_packs_scopes_supported`; OpenAPI scope catalog and Authority tests updated. Offline kit config already aligned with `packs.*` roles.
AUTH-PACKS-43-001 | BLOCKED (2025-10-27) | Enforce pack signing policies, approval RBAC checks, CLI CI token scopes, and audit logging for approvals. Dependencies: AUTH-PACKS-41-001, TASKRUN-42-001, ORCH-SVC-42-101. | Authority Core & Security Guild (src/Authority/StellaOps.Authority/TASKS.md)
@@ -81,19 +85,27 @@ AUTH-POLICY-23-002 | BLOCKED (2025-10-29) | Implement optional two-person rule f
AUTH-POLICY-23-003 | BLOCKED (2025-10-29) | Update documentation and sample configs for policy roles, approval workflow, and signing requirements. Dependencies: AUTH-POLICY-23-001. | Authority Core & Docs Guild (src/Authority/StellaOps.Authority/TASKS.md)
AUTH-POLICY-27-002 | DONE (2025-11-02) | Provide attestation signing service bindings (OIDC token exchange, cosign integration) and enforce publish/promote scope checks, fresh-auth requirements, and audit logging. Dependencies: AUTH-POLICY-27-001, REGISTRY-API-27-007. | Authority Core & Security Guild (src/Authority/StellaOps.Authority/TASKS.md)
> 2025-11-02: Added interactive-only `policy:publish`/`policy:promote` scopes with metadata requirements (`policy_reason`, `policy_ticket`, `policy_digest`), fresh-auth validation, audit enrichment, and updated config/docs for operators.
AUTH-POLICY-27-003 | DOING (2025-11-02) | Update Authority configuration/docs for Policy Studio roles, signing policies, approval workflows, and CLI integration; include compliance checklist. Dependencies: AUTH-POLICY-27-001, AUTH-POLICY-27-002. | Authority Core & Docs Guild (src/Authority/StellaOps.Authority/TASKS.md)
AUTH-TEN-49-001 | DOING (2025-11-02) | Implement service accounts & delegation tokens (`act` chain), per-tenant quotas, audit stream of auth decisions, and revocation APIs. Dependencies: AUTH-TEN-47-001. | Authority Core & Security Guild (src/Authority/StellaOps.Authority/TASKS.md)
AUTH-POLICY-27-003 | DONE (2025-11-03) | Update Authority configuration/docs for Policy Studio roles, signing policies, approval workflows, and CLI integration; include compliance checklist. Dependencies: AUTH-POLICY-27-001, AUTH-POLICY-27-002. | Authority Core & Docs Guild (src/Authority/StellaOps.Authority/TASKS.md)
> 2025-11-03: Authority + policy docs refreshed for publish/promote metadata, DSSE signing workflow, CLI commands, and compliance checklist alignment.
AUTH-TEN-49-001 | DONE (2025-11-03) | Implement service accounts & delegation tokens (`act` chain), per-tenant quotas, audit stream of auth decisions, and revocation APIs. Dependencies: AUTH-TEN-47-001. | Authority Core & Security Guild (src/Authority/StellaOps.Authority/TASKS.md)
> 2025-11-02: Service account store + configuration wired, delegation quotas enforced, token persistence extended with `serviceAccountId`/`tokenKind`/`actorChain`, docs & samples refreshed, and new tests cover delegated issuance/persistence.
> 2025-11-02: Updated bootstrap test fixtures to use AuthorityDelegation seed types and verified `/internal/service-accounts` endpoints respond as expected via targeted Authority tests.
> 2025-11-02: Documented bootstrap admin API usage (`/internal/service-accounts/**`) and clarified that repeated seeding preserves Mongo `_id`/`createdAt` values to avoid immutable field errors.
> 2025-11-03: Patched Authority test harness to seed enabled service-account records deterministically and restored `StellaOps.Authority.Tests` to green (covers `/internal/service-accounts` listing + revocation paths).
> 2025-11-03: Completed service-account delegation coverage with new persistence/quota/audit assertions; `/internal/service-accounts` admin APIs verified via targeted tests (Authority & Issuer Directory suites green).
AUTH-VULN-29-001 | DONE (2025-11-03) | Define Vuln Explorer scopes/roles (`vuln:view`, `vuln:investigate`, `vuln:operate`, `vuln:audit`) with ABAC attributes (env, owner, business_tier) and update discovery metadata/offline kit defaults. Dependencies: AUTH-POLICY-27-001. | Authority Core & Security Guild (src/Authority/StellaOps.Authority/TASKS.md)
AUTH-VULN-29-002 | DONE (2025-11-03) | Enforce CSRF/anti-forgery tokens for workflow actions, sign attachment tokens, and record audit logs with ledger event hashes. Dependencies: AUTH-VULN-29-001, LEDGER-29-002. | Authority Core & Security Guild (src/Authority/StellaOps.Authority/TASKS.md)
AUTH-VULN-29-003 | DOING (2025-11-03) | Update security docs/config samples for Vuln Explorer roles, ABAC policies, attachment signing, and ledger verification guidance. Dependencies: AUTH-VULN-29-001..002. | Authority Core & Docs Guild (src/Authority/StellaOps.Authority/TASKS.md)
> 2025-11-03: Workflow anti-forgery and attachment token endpoints merged with audit trails; negative-path coverage added (`VulnWorkflowTokenEndpointTests`). Full Authority test suite still running; follow-up execution required after dependency build completes.
AUTH-VULN-29-003 | DONE (2025-11-03) | Update security docs/config samples for Vuln Explorer roles, ABAC policies, attachment signing, and ledger verification guidance. Dependencies: AUTH-VULN-29-001..002. | Authority Core & Docs Guild (src/Authority/StellaOps.Authority/TASKS.md)
> 2025-11-03: Docs, release notes, and samples updated for Vuln Explorer roles, ABAC filters, attachment signing tokens, and ledger verification guidance.
PLG4-6.CAPABILITIES | BLOCKED (2025-10-12) | Finalise capability metadata exposure, config validation, and developer guide updates; remaining action is Docs polish/diagram export. | BE-Auth Plugin, Docs Guild (src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard/TASKS.md)
PLG6.DIAGRAM | TODO | Export final sequence/component diagrams for the developer guide and add offline-friendly assets under `docs/assets/authority`. | Docs Guild (src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard/TASKS.md)
PLG7.RFC | REVIEW | Socialize LDAP plugin RFC (`docs/rfcs/authority-plugin-ldap.md`) and capture guild feedback. | BE-Auth Plugin, Security Guild (src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard/TASKS.md)
PLG6.DIAGRAM | DONE (2025-11-03) | Export final sequence/component diagrams for the developer guide and add offline-friendly assets under `docs/assets/authority`. | Docs Guild (src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard/TASKS.md)
> 2025-11-03: PLG6.DIAGRAM moved to DOING preparing final Authority plug-in diagrams and offline asset exports (Docs Guild).
> 2025-11-03: PLG6.DIAGRAM marked DONE component topology + bootstrap sequence diagrams exported (SVG + Mermaid) and developer guide updated for offline-ready assets (Docs Guild).
PLG7.RFC | DONE (2025-11-03) | Socialize LDAP plugin RFC (`docs/rfcs/authority-plugin-ldap.md`) and capture guild feedback. | BE-Auth Plugin, Security Guild (src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard/TASKS.md)
PLG7.IMPL-001 | DONE (2025-11-03) | Scaffold `StellaOps.Authority.Plugin.Ldap` + tests, bind configuration (client certificate, trust-store, insecure toggle) with validation and docs samples. | BE-Auth Plugin (src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard/TASKS.md)
> 2025-11-03: Initial `StellaOps.Authority.Plugin.Ldap` project/tests scaffolded with configuration options + registrar; sample manifest (`etc/authority.plugins/ldap.yaml`) updated to new schema (client certificate, trust store, insecure toggle).
PLG7.IMPL-002 | DOING (2025-11-03) | Implement LDAP credential store with TLS/mutual TLS enforcement, deterministic retry/backoff, and structured logging/metrics. | BE-Auth Plugin, Security Guild (src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard/TASKS.md)
> 2025-11-03: Review concluded; RFC accepted with audit/mTLS/mapping decisions recorded in `docs/notes/2025-11-03-authority-plugin-ldap-review.md`. Follow-up implementation tasks PLG7.IMPL-001..005 added to plugin board.
> 2025-11-04: Updated connection factory to negotiate StartTLS via `StartTransportLayerSecurity(null)` and normalized LDAP result-code handling (invalid credentials + transient codes) against `System.DirectoryServices.Protocols` 8.0. Plugin unit suite (`dotnet test src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/StellaOps.Authority.Plugin.Ldap.Tests.csproj`) now passes again after the retry/error-path fixes.
SEC2.PLG | BLOCKED (2025-10-21) | Emit audit events from password verification outcomes and persist via `IAuthorityLoginAttemptStore`. <br>⛔ Waiting on AUTH-DPOP-11-001 / AUTH-MTLS-11-002 / PLUGIN-DI-08-001 to stabilise Authority auth surfaces before final verification + publish. | Security Guild, Storage Guild (src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard/TASKS.md)
SEC3.PLG | BLOCKED (2025-10-21) | Ensure lockout responses and rate-limit metadata flow through plugin logs/events (include retry-after). <br>⛔ Pending AUTH-DPOP-11-001 / AUTH-MTLS-11-002 / PLUGIN-DI-08-001 so limiter telemetry contract matches final authority surface. | Security Guild, BE-Auth Plugin (src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard/TASKS.md)
SEC5.PLG | BLOCKED (2025-10-21) | Address plugin-specific mitigations (bootstrap user handling, password policy docs) in threat model backlog. <br>⛔ Final documentation depends on AUTH-DPOP-11-001 / AUTH-MTLS-11-002 / PLUGIN-DI-08-001 outcomes. | Security Guild (src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard/TASKS.md)
@@ -105,7 +117,8 @@ Task ID | State | Task description | Owners (Source)
--- | --- | --- | ---
ISSUER-30-001 | DONE (2025-11-01) | Implement issuer CRUD API with RBAC, audit logging, and tenant scoping; seed CSAF publisher metadata. | Issuer Directory Guild (src/IssuerDirectory/StellaOps.IssuerDirectory/TASKS.md)
ISSUER-30-002 | DONE (2025-11-01) | Implement key management endpoints (add/rotate/revoke keys), enforce expiry, validate formats (Ed25519, X.509, DSSE). Dependencies: ISSUER-30-001. | Issuer Directory Guild, Security Guild (src/IssuerDirectory/StellaOps.IssuerDirectory/TASKS.md)
ISSUER-30-003 | DOING | Provide trust weight APIs and tenant overrides with validation (+/- bounds) and audit trails. Dependencies: ISSUER-30-001. | Issuer Directory Guild, Policy Guild (src/IssuerDirectory/StellaOps.IssuerDirectory/TASKS.md)
ISSUER-30-003 | DONE (2025-11-03) | Provide trust weight APIs and tenant overrides with validation (+/- bounds) and audit trails. Dependencies: ISSUER-30-001. | Issuer Directory Guild, Policy Guild (src/IssuerDirectory/StellaOps.IssuerDirectory/TASKS.md)
> 2025-11-03: Trust override APIs, client reflection helpers, and audit trails finalized; additional client tests cover cache invalidation and failure paths (Issuer Directory Core suite passed).
ISSUER-30-004 | DONE (2025-11-01) | Integrate with VEX Lens and Excitor signature verification (client SDK, caching, retries). Dependencies: ISSUER-30-001..003. | Issuer Directory Guild, VEX Lens Guild (src/IssuerDirectory/StellaOps.IssuerDirectory/TASKS.md)
ISSUER-30-005 | DONE (2025-11-01) | Instrument metrics/logs (issuer changes, key rotation, verification failures) and dashboards/alerts. Dependencies: ISSUER-30-001..004. | Issuer Directory Guild, Observability Guild (src/IssuerDirectory/StellaOps.IssuerDirectory/TASKS.md)
ISSUER-30-006 | DONE (2025-11-02) | Provide deployment manifests, backup/restore, secure secret storage, and offline kit instructions. Dependencies: ISSUER-30-001..005. | Issuer Directory Guild, DevOps Guild (src/IssuerDirectory/StellaOps.IssuerDirectory/TASKS.md)
@@ -115,8 +128,10 @@ ISSUER-30-006 | DONE (2025-11-02) | Provide deployment manifests, backup/restore
Summary: Identity & Signing focus on Libraries.
Task ID | State | Task description | Owners (Source)
--- | --- | --- | ---
KMS-73-001 | TODO | Add cloud KMS driver (e.g., AWS KMS, GCP KMS) with signing and key metadata retrieval. Dependencies: KMS-72-001. | KMS Guild (src/__Libraries/StellaOps.Cryptography.Kms/TASKS.md)
KMS-73-002 | TODO | Implement PKCS#11/HSM driver plus FIDO2 signing support for high assurance workflows. Dependencies: KMS-73-001. | KMS Guild (src/__Libraries/StellaOps.Cryptography.Kms/TASKS.md)
KMS-73-001 | DONE (2025-11-03) | Add cloud KMS driver (e.g., AWS KMS, GCP KMS) with signing and key metadata retrieval. Dependencies: KMS-72-001. | KMS Guild (src/__Libraries/StellaOps.Cryptography.Kms/TASKS.md)
> 2025-11-03: AWS/GCP KMS clients now hash locally before signing, cache metadata/public key blobs, and expose non-exportable keys for JWKS via raw descriptors; Authority/ACK registries consume `kms.version` metadata, and tests cover sign/verify/export plus raw fallback flows.
KMS-73-002 | DONE (2025-11-03) | Implement PKCS#11/HSM driver plus FIDO2 signing support for high assurance workflows. Dependencies: KMS-73-001. | KMS Guild (src/__Libraries/StellaOps.Cryptography.Kms/TASKS.md)
> 2025-11-03: PKCS#11 facade + client layered, FIDO2 authenticator wiring landed, DI helpers added, signer docs updated for five keyful modes, and unit fakes cover sign/verify/export paths.
If all tasks are done - read next sprint section - SPRINT_110_ingestion_evidence.md

View File

@@ -1,5 +1,21 @@
# Sprint 110 - Ingestion & Evidence
## Status Snapshot (2025-11-03)
- **Advisory AI** 3 of 11 tasks are DONE (AIAI-31-001, AIAI-31-010, AIAI-31-011); orchestration core work (AIAI-31-002, AIAI-31-003, AIAI-31-004) remains DOING while downstream wiring, guardrails, and CLI deliverables (AIAI-31-004A/004B/004C and AIAI-31-005 through AIAI-31-009) stay TODO pending SBOM context integration and orchestrator plumbing.
- 2025-11-03: AIAI-31-002 landed the configurable HTTP client + DI defaults; retriever now resolves data via `/v1/sbom/context`, retaining a null fallback until SBOM service ships.
- 2025-11-03: Follow-up: SBOM guild to deliver base URL/API key and run an Advisory AI smoke retrieval once SBOM-AIAI-31-001 endpoints are live.
- **Concelier** CONCELIER-CORE-AOC-19-004 is the only in-flight Concelier item; air-gap, console, attestation, and Link-Not-Merge tasks remain TODO, and several connector upgrades still carry overdue October due dates.
- **Excititor** Excititor WebService, console, policy, and observability tracks are all TODO and hinge on Link-Not-Merge schema delivery plus trust-provenance connectors (SUSE/Ubuntu) progressing in section 110.C.
- **Mirror** Mirror Creator track (MIRROR-CRT-56-001 through MIRROR-CRT-58-002) has not started; DSSE signing, OCI bundle, and scheduling integrations depend on the deterministic bundle assembler landing first.
## Blockers & Overdue Follow-ups
- `CONCELIER-GRAPH-21-001`, `CONCELIER-GRAPH-21-002`, and `CONCELIER-GRAPH-21-005` remain BLOCKED awaiting `CONCELIER-POLICY-20-002` outputs and Cartographer schema (`CARTO-GRAPH-21-002`), keeping downstream Excititor graph consumers on hold.
- `EXCITITOR-GRAPH-21-001`, `EXCITITOR-GRAPH-21-002`, and `EXCITITOR-GRAPH-21-005` stay BLOCKED until the same Cartographer/Link-Not-Merge prerequisites are delivered.
- Connector provenance updates `FEEDCONN-ICSCISA-02-012` (due 2025-10-23) and `FEEDCONN-KISA-02-008` (due 2025-10-24) plus coordination items `FEEDMERGE-COORD-02-901`/`FEEDMERGE-COORD-02-902`/`FEEDMERGE-COORD-02-903` (due 2025-10-21 through 2025-10-24) are past due and need scheduling.
- Mirror evidence work remains blocked until `MIRROR-CRT-56-001` ships; align Export Center (`EXPORT-OBS-51-001`) and AirGap time anchor (`AIRGAP-TIME-57-001`) owners for kickoff.
[Ingestion & Evidence] 110.A) AdvisoryAI
Depends on: Sprint 100.A - Attestor
Summary: Ingestion & Evidence focus on AdvisoryAI.
@@ -9,11 +25,33 @@ AIAI-31-001 | DONE (2025-11-02) | Implement structured and vector retrievers for
AIAI-31-002 | DOING | Build SBOM context retriever (purl version timelines, dependency paths, env flags, blast radius estimator). Dependencies: SBOM-VULN-29-001. | Advisory AI Guild, SBOM Service Guild (src/AdvisoryAI/StellaOps.AdvisoryAI/TASKS.md)
AIAI-31-003 | DOING | Implement deterministic toolset (version comparators, range checks, dependency analysis, policy lookup) exposed via orchestrator. Dependencies: AIAI-31-001..002. | Advisory AI Guild (src/AdvisoryAI/StellaOps.AdvisoryAI/TASKS.md)
AIAI-31-004 | DOING | Build orchestration pipeline for Summary/Conflict/Remediation tasks (prompt templates, tool calls, token budgets, caching). Dependencies: AIAI-31-001..003, AUTH-VULN-29-001. | Advisory AI Guild (src/AdvisoryAI/StellaOps.AdvisoryAI/TASKS.md)
AIAI-31-004A | TODO | Wire orchestrator into WebService/Worker, expose API + queue contract, emit metrics, stub cache. Dependencies: AIAI-31-004, AIAI-31-002. | Advisory AI Guild, Platform Guild (src/AdvisoryAI/StellaOps.AdvisoryAI/TASKS.md)
AIAI-31-004B | TODO | Implement prompt assembler, guardrails, cache persistence, DSSE provenance, golden outputs. Dependencies: AIAI-31-004A, DOCS-AIAI-31-003, AUTH-AIAI-31-004. | Advisory AI Guild, Security Guild (src/AdvisoryAI/StellaOps.AdvisoryAI/TASKS.md)
AIAI-31-004A | DOING (2025-11-03) | Wire orchestrator into WebService/Worker, expose API + queue contract, emit metrics, stub cache. Dependencies: AIAI-31-004, AIAI-31-002. | Advisory AI Guild, Platform Guild (src/AdvisoryAI/StellaOps.AdvisoryAI/TASKS.md)
> 2025-11-03: WebService/Worker scaffolds created with in-memory cache/queue, minimal APIs (`/api/v1/advisory/plan`, `/api/v1/advisory/queue`), metrics counters, and plan cache instrumentation; worker processes queue using orchestrator.
AIAI-31-004B | DONE (2025-11-03) | Implement prompt assembler, guardrails, cache persistence, DSSE provenance, golden outputs. Dependencies: AIAI-31-004A, DOCS-AIAI-31-003, AUTH-AIAI-31-004. | Advisory AI Guild, Security Guild (src/AdvisoryAI/StellaOps.AdvisoryAI/TASKS.md)
> 2025-11-03: Prompt assembler emits deterministic JSON payloads with citations, guardrail pipeline wiring landed (no-op for now), outputs persist with DSSE-ready provenance and metrics, and golden prompt fixtures/tests added.
AIAI-31-004C | TODO | Deliver CLI `stella advise run` command, renderer, docs, CLI golden tests. Dependencies: AIAI-31-004B, CLI-AIAI-31-003. | Advisory AI Guild, CLI Guild (src/AdvisoryAI/StellaOps.AdvisoryAI/TASKS.md)
AIAI-31-005 | TODO | Implement guardrails (redaction, injection defense, output validation, citation enforcement) and fail-safe handling. Dependencies: AIAI-31-004. | Advisory AI Guild, Security Guild (src/AdvisoryAI/StellaOps.AdvisoryAI/TASKS.md)
AIAI-31-006 | TODO | Expose REST API endpoints (`/advisory/ai/*`) with RBAC, rate limits, OpenAPI schemas, and batching support. Dependencies: AIAI-31-004..005. | Advisory AI Guild (src/AdvisoryAI/StellaOps.AdvisoryAI/TASKS.md)
DOCS-AIAI-31-002 | DONE (2025-11-03) | Author `/docs/advisory-ai/architecture.md` detailing RAG pipeline, deterministic tooling, caching, model profiles. Dependencies: AIAI-31-004. | Docs Guild, Advisory AI Guild (docs/TASKS.md)
DOCS-AIAI-31-001 | DONE (2025-11-03) | Publish `/docs/advisory-ai/overview.md` covering capabilities, guardrails, RBAC personas, and offline posture. | Docs Guild, Advisory AI Guild (docs/TASKS.md)
DOCS-AIAI-31-003 | DONE (2025-11-03) | Write `/docs/advisory-ai/api.md` covering endpoints, schemas, errors, rate limits, and imposed-rule banner. Dependencies: DOCS-AIAI-31-002. | Docs Guild, Advisory AI Guild (docs/TASKS.md)
DOCS-AIAI-31-004 | BLOCKED (2025-11-03) | Create `/docs/advisory-ai/console.md` with screenshots, a11y notes, copy-as-ticket instructions. Dependencies: CONSOLE-VULN-29-001, CONSOLE-VEX-30-001, EXCITITOR-CONSOLE-23-001. | Docs Guild, Console Guild (docs/TASKS.md)
DOCS-AIAI-31-005 | BLOCKED (2025-11-03) | Publish `/docs/advisory-ai/cli.md` covering commands, exit codes, scripting patterns. Dependencies: CLI-VULN-29-001, CLI-VEX-30-001, AIAI-31-004C. | Docs Guild, DevEx/CLI Guild (docs/TASKS.md)
DOCS-AIAI-31-006 | BLOCKED (2025-11-03) | Update `/docs/policy/assistant-parameters.md` covering temperature, token limits, ranking weights, TTLs. Dependencies: POLICY-ENGINE-31-001. | Docs Guild, Policy Guild (docs/TASKS.md)
DOCS-AIAI-31-007 | BLOCKED (2025-11-03) | Write `/docs/security/assistant-guardrails.md` detailing redaction, injection defense, logging. Dependencies: AIAI-31-005. | Docs Guild, Security Guild (docs/TASKS.md)
DOCS-AIAI-31-008 | BLOCKED (2025-11-03) | Publish `/docs/sbom/remediation-heuristics.md` (feasibility scoring, blast radius). Dependencies: SBOM-AIAI-31-001. | Docs Guild, SBOM Service Guild (docs/TASKS.md)
DOCS-AIAI-31-009 | BLOCKED (2025-11-03) | Create `/docs/runbooks/assistant-ops.md` for warmup, cache priming, model outages, scaling. Dependencies: DEVOPS-AIAI-31-001. | Docs Guild, DevOps Guild (docs/TASKS.md)
> 2025-11-03: DOCS-AIAI-31-003 moved to DOING drafting Advisory AI API reference (endpoints, rate limits, error model) for sprint 110.
> 2025-11-03: DOCS-AIAI-31-003 marked DONE `docs/advisory-ai/api.md` published with scopes, request/response schemas, rate limits, and error catalogue (Docs Guild).
> 2025-11-03: DOCS-AIAI-31-001 marked DONE `docs/advisory-ai/overview.md` published with value, personas, guardrails, observability, and roadmap checklists (Docs Guild).
> 2025-11-03: DOCS-AIAI-31-002 marked DONE `docs/advisory-ai/architecture.md` published describing pipeline, deterministic tooling, caching, and profile governance (Docs Guild).
> 2025-11-03: DOCS-AIAI-31-004 marked BLOCKED Console widgets/endpoints (CONSOLE-VULN-29-001, CONSOLE-VEX-30-001, EXCITITOR-CONSOLE-23-001) still pending; cannot document UI flows yet.
> 2025-11-03: DOCS-AIAI-31-005 marked BLOCKED CLI implementation (`stella advise run`, CLI-VULN-29-001, CLI-VEX-30-001) plus AIAI-31-004C not shipped; doc blocked until commands exist.
> 2025-11-03: DOCS-AIAI-31-006 marked BLOCKED Advisory AI parameter knobs (POLICY-ENGINE-31-001) absent; doc deferred.
> 2025-11-03: DOCS-AIAI-31-007 marked BLOCKED Guardrail implementation (AIAI-31-005) incomplete.
> 2025-11-03: DOCS-AIAI-31-008 marked BLOCKED Waiting on SBOM heuristics delivery (SBOM-AIAI-31-001).
> 2025-11-03: DOCS-AIAI-31-009 marked BLOCKED DevOps runbook inputs (DEVOPS-AIAI-31-001) outstanding.
AIAI-31-005 | DOING (2025-11-03) | Implement guardrails (redaction, injection defense, output validation, citation enforcement) and fail-safe handling. Dependencies: AIAI-31-004. | Advisory AI Guild, Security Guild (src/AdvisoryAI/StellaOps.AdvisoryAI/TASKS.md)
AIAI-31-006 | DOING (2025-11-03) | Expose REST API endpoints (`/advisory/ai/*`) with RBAC, rate limits, OpenAPI schemas, and batching support. Dependencies: AIAI-31-004..005. | Advisory AI Guild (src/AdvisoryAI/StellaOps.AdvisoryAI/TASKS.md)
> 2025-11-03: Shipped `/api/v1/advisory/{task}` execution and `/api/v1/advisory/outputs/{cacheKey}` retrieval endpoints with guardrail integration, provenance hashes, and metrics (RBAC & rate limiting still pending Authority scope delivery).
AIAI-31-007 | TODO | Instrument metrics (`advisory_ai_latency`, `guardrail_blocks`, `validation_failures`, `citation_coverage`), logs, and traces; publish dashboards/alerts. Dependencies: AIAI-31-004..006. | Advisory AI Guild, Observability Guild (src/AdvisoryAI/StellaOps.AdvisoryAI/TASKS.md)
AIAI-31-008 | TODO | Package inference on-prem container, remote inference toggle, Helm/Compose manifests, scaling guidance, offline kit instructions. Dependencies: AIAI-31-006..007. | Advisory AI Guild, DevOps Guild (src/AdvisoryAI/StellaOps.AdvisoryAI/TASKS.md)
AIAI-31-010 | DONE (2025-11-02) | Implement Concelier advisory raw document provider mapping CSAF/OSV payloads into structured chunks for retrieval. Dependencies: CONCELIER-VULN-29-001, EXCITITOR-VULN-29-001. | Advisory AI Guild (src/AdvisoryAI/StellaOps.AdvisoryAI/TASKS.md)
@@ -150,8 +188,8 @@ CONCELIER-WEB-OBS-55-001 `Incident mode toggles` | TODO | Implement incident mod
FEEDCONN-CCCS-02-009 Version range provenance (Oct 2025) | BE-Conn-CCCS | **TODO (due 2025-10-21)** Map CCCS advisories into the new `advisory_observations.affected.versions[]` structure, preserving each upstream range with provenance anchors (`cccs:{serial}:{index}`) and normalized comparison keys. Update mapper tests/fixtures for the Link-Not-Merge schema and verify linkset builders consume the ranges without relying on legacy merge counters.<br>2025-10-29: `docs/dev/normalized-rule-recipes.md` now documents helper snippets for building observation version entries—use them instead of merge-specific builders and refresh fixtures with `UPDATE_CCCS_FIXTURES=1`. | CONCELIER-LNM-21-001 (src/Concelier/__Libraries/StellaOps.Concelier.Connector.Cccs/TASKS.md)
FEEDCONN-CERTBUND-02-010 Version range provenance | BE-Conn-CERTBUND | **TODO (due 2025-10-22)** Translate `product.Versions` phrases (e.g., `2023.1 bis 2024.2`, `alle`) into comparison helpers for `advisory_observations.affected.versions[]`, capturing provenance (`certbund:{advisoryId}:{vendor}`) and localisation notes. Update mapper/tests for the Link-Not-Merge schema and refresh documentation accordingly. | CONCELIER-LNM-21-001 (src/Concelier/__Libraries/StellaOps.Concelier.Connector.CertBund/TASKS.md)
FEEDCONN-CISCO-02-009 SemVer range provenance | BE-Conn-Cisco | **TODO (due 2025-10-21)** Emit Cisco SemVer ranges into `advisory_observations.affected.versions[]` with provenance identifiers (`cisco:{productId}`) and deterministic comparison keys. Update mapper/tests for the Link-Not-Merge schema and replace legacy merge counter checks with observation/linkset validation. | CONCELIER-LNM-21-001 (src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Cisco/TASKS.md)
FEEDCONN-ICSCISA-02-012 Version range provenance | BE-Conn-ICS-CISA | **TODO (due 2025-10-23)** Promote existing firmware/semver data into `advisory_observations.affected.versions[]` entries with deterministic comparison keys and provenance identifiers (`ics-cisa:{advisoryId}:{product}`). Add regression coverage for mixed firmware strings and raise a Models ticket only when observation schema needs a new comparison helper.<br>2025-10-29: Follow `docs/dev/normalized-rule-recipes.md` §2 to build observation version entries and log failures without invoking the retired merge helpers. | CONCELIER-LNM-21-001 (src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ics.Cisa/TASKS.md)
FEEDCONN-KISA-02-008 Firmware range provenance | BE-Conn-KISA, Models | **TODO (due 2025-10-24)** Define comparison helpers for Hangul-labelled firmware ranges (`XFU 1.0.1.0084 ~ 2.0.1.0034`) and map them into `advisory_observations.affected.versions[]` with provenance tags. Coordinate with Models only if a new comparison scheme is required, then update localisation notes and fixtures for the Link-Not-Merge schema. | CONCELIER-LNM-21-001 (src/Concelier/__Libraries/StellaOps.Concelier.Connector.Kisa/TASKS.md)
FEEDCONN-ICSCISA-02-012 Version range provenance | BE-Conn-ICS-CISA | **DONE (2025-11-03)** Promote existing firmware/semver data into `advisory_observations.affected.versions[]` entries with deterministic comparison keys and provenance identifiers (`ics-cisa:{advisoryId}:{product}`). Add regression coverage for mixed firmware strings and raise a Models ticket only when observation schema needs a new comparison helper.<br>2025-10-29: Follow `docs/dev/normalized-rule-recipes.md` §2 to build observation version entries and log failures without invoking the retired merge helpers.<br>2025-11-03: Completed connector now normalizes semver ranges with provenance notes, RSS fallback content clears the AOC guard, and end-to-end Fetch/Parse/Map integration tests pass. | CONCELIER-LNM-21-001 (src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ics.Cisa/TASKS.md)
FEEDCONN-KISA-02-008 Firmware range provenance | BE-Conn-KISA, Models | **DONE (2025-11-04)** Define comparison helpers for Hangul-labelled firmware ranges (`XFU 1.0.1.0084 ~ 2.0.1.0034`) and map them into `advisory_observations.affected.versions[]` with provenance tags. Coordinate with Models only if a new comparison scheme is required, then update localisation notes and fixtures for the Link-Not-Merge schema.<br>2025-11-03: Analysis in progress auditing existing mapper output/fixtures ahead of implementing firmware range normalization and provenance wiring.<br>2025-11-03: SemVer normalization helper wired through `KisaMapper` with provenance slugs + vendor extensions; integration tests updated and green, follow-up capture for additional Hangul exclusivity markers queued before completion.<br>2025-11-03: Extended connector tests to cover single-ended (`이상`, `초과`, `이하`, `미만`) and non-numeric phrases, verifying normalized rule types (`gt`, `gte`, `lt`, `lte`) and fallback behaviour; broader corpus review remains before transitioning to DONE.<br>2025-11-03: Captured the top 10 `detailDos.do?IDX=` pages into `seed-data/kisa/html/` via `scripts/kisa_capture_html.py`; JSON endpoint (`rssDetailData.do?IDX=…`) now returns error pages, so connector updates must parse the embedded HTML or secure authenticated API access before closing.<br>2025-11-04: Fetch + parse pipeline now consumes the HTML detail pages end to end (metadata persisted, DOM parser extracts vendor/product ranges); fixtures/tests operate on the HTML snapshots to guard normalized SemVer + vendor extension expectations and severity extraction. | CONCELIER-LNM-21-001 (src/Concelier/__Libraries/StellaOps.Concelier.Connector.Kisa/TASKS.md)
FEEDCONN-SHARED-STATE-003 Source state seeding helper | Tools Guild, BE-Conn-MSRC | **DOING (2025-10-19)** Provide a reusable CLI/utility to seed `pendingDocuments`/`pendingMappings` for connectors (MSRC backfills require scripted CVRF + detail injection). Coordinate with MSRC team for expected JSON schema and handoff once prototype lands. Prereqs confirmed none (2025-10-19). | Tools (src/Concelier/__Libraries/StellaOps.Concelier.Connector.Common/TASKS.md)
FEEDMERGE-COORD-02-901 Connector deadline check-ins | BE-Merge | **TODO (due 2025-10-21)** Confirm Cccs/Cisco version-provenance updates land, capture `LinksetVersionCoverage` dashboard snapshots (expect zero missing-range warnings), and update coordination docs with the results.<br>2025-10-29: Observation metrics now surface `version_entries_total`/`missing_version_entries_total`; include screenshots for both when closing this task. | FEEDMERGE-COORD-02-900 (src/Concelier/__Libraries/StellaOps.Concelier.Merge/TASKS.md)
FEEDMERGE-COORD-02-902 ICS-CISA version comparison support | BE-Merge, Models | **TODO (due 2025-10-23)** Review ICS-CISA sample advisories, validate reuse of existing comparison helpers, and pre-stage Models ticket template only if a new firmware comparator is required. Document the outcome and observation coverage logs in coordination docs + tracker files.<br>2025-10-29: `docs/dev/normalized-rule-recipes.md` (§2§3) now covers observation entries; attach decision summary + log sample when handing off to Models. Dependencies: FEEDMERGE-COORD-02-901. | FEEDMERGE-COORD-02-900 (src/Concelier/__Libraries/StellaOps.Concelier.Merge/TASKS.md)

View File

@@ -9,8 +9,8 @@ AIRGAP-POL-56-001 | DONE | Implement `StellaOps.AirGap.Policy` package exposing
AIRGAP-POL-56-002 | DONE | Create Roslyn analyzer/code fix warning on raw `HttpClient` usage outside approved wrappers; add CI integration. Dependencies: AIRGAP-POL-56-001. | AirGap Policy Guild, DevEx Guild (src/AirGap/StellaOps.AirGap.Policy/TASKS.md)
AIRGAP-POL-57-001 | DONE (2025-11-03) | Update core web services (Web, Exporter, Policy, Findings, Authority) to use `EgressPolicy`; ensure configuration wiring for sealed mode. Dependencies: AIRGAP-POL-56-002. | AirGap Policy Guild, BE-Base Platform Guild (src/AirGap/StellaOps.AirGap.Policy/TASKS.md)
AIRGAP-POL-57-002 | DONE (2025-11-03) | Implement Task Runner job plan validator rejecting network steps unless marked internal allow-list.<br>2025-11-03: Worker wiring pulls `IEgressPolicy`, filesystem dispatcher enforces sealed-mode egress, dispatcher test + grant normalization landed, package versions aligned to rc.2.<br>Next: ensure other dispatchers/executors reuse the injected policy before enabling sealed-mode runs in worker service. Dependencies: AIRGAP-POL-57-001. | AirGap Policy Guild, Task Runner Guild (src/AirGap/StellaOps.AirGap.Policy/TASKS.md)
AIRGAP-POL-58-001 | TODO | Ensure Observability exporters only target local endpoints in sealed mode; disable remote sinks with warning. Dependencies: AIRGAP-POL-57-002. | AirGap Policy Guild, Observability Guild (src/AirGap/StellaOps.AirGap.Policy/TASKS.md)
AIRGAP-POL-58-002 | TODO | Add CLI sealed-mode guard that refuses commands needing egress and surfaces remediation. Dependencies: AIRGAP-POL-58-001. | AirGap Policy Guild, CLI Guild (src/AirGap/StellaOps.AirGap.Policy/TASKS.md)
AIRGAP-POL-58-001 | DONE (2025-11-03) | Ensure Observability exporters only target local endpoints in sealed mode; disable remote sinks with warning.<br>2025-11-03: Introduced `StellaOps.Telemetry.Core` with OTLP exporter guard; Registry Token Service consumes new telemetry bootstrap; sealed-mode now skips non-loopback collectors and logs remediation guidance; docs refreshed for telemetry/air-gap playbooks. Dependencies: AIRGAP-POL-57-002. | AirGap Policy Guild, Observability Guild (src/AirGap/StellaOps.AirGap.Policy/TASKS.md)
AIRGAP-POL-58-002 | DONE (2025-11-03) | Add CLI sealed-mode guard that refuses commands needing egress and surfaces remediation.<br>2025-11-03: CLI now wires HTTP clients through `StellaOps.AirGap.Policy`, returns `AIRGAP_EGRESS_BLOCKED` with remediation when sealed, and docs updated. Dependencies: AIRGAP-POL-58-001. | AirGap Policy Guild, CLI Guild (src/AirGap/StellaOps.AirGap.Policy/TASKS.md)
[Policy & Reasoning] 120.B) Findings.I
@@ -18,10 +18,10 @@ Depends on: Sprint 110.A - AdvisoryAI
Summary: Policy & Reasoning focus on Findings (phase I).
Task ID | State | Task description | Owners (Source)
--- | --- | --- | ---
LEDGER-29-001 | TODO | Design ledger & projection schemas (tables/indexes), canonical JSON format, hashing strategy, and migrations. Publish schema doc + fixtures. | Findings Ledger Guild (src/Findings/StellaOps.Findings.Ledger/TASKS.md)
LEDGER-29-002 | TODO | Implement ledger write API (`POST /vuln/ledger/events`) with validation, idempotency, hash chaining, and Merkle root computation job. Dependencies: LEDGER-29-001. | Findings Ledger Guild (src/Findings/StellaOps.Findings.Ledger/TASKS.md)
LEDGER-29-003 | TODO | Build projector worker that derives `findings_projection` rows from ledger events + policy determinations; ensure idempotent replay keyed by `(tenant,finding_id,policy_version)`. Dependencies: LEDGER-29-002. | Findings Ledger Guild, Scheduler Guild (src/Findings/StellaOps.Findings.Ledger/TASKS.md)
LEDGER-29-004 | TODO | Integrate Policy Engine batch evaluation (baseline + simulate) with projector; cache rationale references. Dependencies: LEDGER-29-003. | Findings Ledger Guild, Policy Guild (src/Findings/StellaOps.Findings.Ledger/TASKS.md)
LEDGER-29-001 | DONE (2025-11-03) | Design ledger & projection schemas (tables/indexes), canonical JSON format, hashing strategy, and migrations. Publish schema doc + fixtures.<br>2025-11-03: Initial migration, canonical fixtures, and schema doc alignment delivered (LEDGER-29-001). | Findings Ledger Guild (src/Findings/StellaOps.Findings.Ledger/TASKS.md)
LEDGER-29-002 | DONE (2025-11-03) | Implement ledger write API (`POST /vuln/ledger/events`) with validation, idempotency, hash chaining, and Merkle root computation job.<br>2025-11-03: Web service + domain scaffolding landed with canonical hashing helpers, in-memory repository, Merkle scheduler stub, request/response contracts, and unit tests covering hashing & conflict flows. Dependencies: LEDGER-29-001. | Findings Ledger Guild (src/Findings/StellaOps.Findings.Ledger/TASKS.md)
LEDGER-29-003 | DONE (2025-11-03) | Build projector worker that derives `findings_projection` rows from ledger events + policy determinations; ensure idempotent replay keyed by `(tenant,finding_id,policy_version)`. <br>2025-11-03: Postgres projection services landed with replay checkpoints, fixtures, and unit coverage (LEDGER-29-003). Dependencies: LEDGER-29-002. | Findings Ledger Guild, Scheduler Guild (src/Findings/StellaOps.Findings.Ledger/TASKS.md)
LEDGER-29-004 | DOING (2025-11-03) | Integrate Policy Engine batch evaluation (baseline + simulate) with projector; cache rationale references.<br>2025-11-04: Reducer+worker now store `policy_rationale` via inline evaluation; Postgres schema/fixtures/tests updated, pending real Policy Engine client wiring. Dependencies: LEDGER-29-003. | Findings Ledger Guild, Policy Guild (src/Findings/StellaOps.Findings.Ledger/TASKS.md)
LEDGER-29-005 | TODO | Implement workflow mutation handlers (assign, comment, accept-risk, target-fix, verify-fix, reopen) producing ledger events with validation and attachments metadata. Dependencies: LEDGER-29-004. | Findings Ledger Guild (src/Findings/StellaOps.Findings.Ledger/TASKS.md)
LEDGER-29-006 | TODO | Integrate attachment encryption (KMS envelope), signed URL issuance, CSRF protection hooks for Console. Dependencies: LEDGER-29-005. | Findings Ledger Guild, Security Guild (src/Findings/StellaOps.Findings.Ledger/TASKS.md)
LEDGER-29-007 | TODO | Instrument metrics (`ledger_write_latency`, `projection_lag_seconds`, `ledger_events_total`), structured logs, and Merkle anchoring alerts; publish dashboards. Dependencies: LEDGER-29-006. | Findings Ledger Guild, Observability Guild (src/Findings/StellaOps.Findings.Ledger/TASKS.md)

View File

@@ -12,9 +12,9 @@ ENTRYTRACE-SURFACE-02 | DONE (2025-11-02) | Replace direct env/secret access wit
SCANNER-ENTRYTRACE-18-509 | DONE (2025-11-02) | Add regression coverage for EntryTrace surfaces (result store, WebService endpoint, CLI renderer) and NDJSON hashing. | EntryTrace Guild, QA Guild (src/Scanner/__Libraries/StellaOps.Scanner.EntryTrace/TASKS.md)
SCANNER-ENTRYTRACE-18-507 | DONE (2025-11-02) | Expand candidate discovery beyond ENTRYPOINT/CMD by scanning Docker history metadata and default service directories (`/etc/services/**`, `/s6/**`, `/etc/supervisor/*.conf`, `/usr/local/bin/*-entrypoint`) when explicit commands are absent. Dependencies: SCANNER-ENTRYTRACE-18-509. | EntryTrace Guild (src/Scanner/__Libraries/StellaOps.Scanner.EntryTrace/TASKS.md)
SCANNER-ENTRYTRACE-18-508 | DONE (2025-11-02) | Extend wrapper catalogue to collapse language/package launchers (`bundle`, `bundle exec`, `docker-php-entrypoint`, `npm`, `yarn node`, `pipenv`, `poetry run`) and vendor init scripts before terminal classification. Dependencies: SCANNER-ENTRYTRACE-18-507. | EntryTrace Guild (src/Scanner/__Libraries/StellaOps.Scanner.EntryTrace/TASKS.md)
LANG-SURFACE-01 | TODO | Invoke Surface.Validation checks (env/cache/secrets) before analyzer execution to ensure consistent prerequisites. | Language Analyzer Guild (src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang/TASKS.md)
LANG-SURFACE-02 | TODO | Consume Surface.FS APIs for layer/source caching (instead of bespoke caches) to improve determinism. Dependencies: LANG-SURFACE-01. | Language Analyzer Guild (src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang/TASKS.md)
LANG-SURFACE-03 | TODO | Replace direct secret/env reads with Surface.Secrets references when fetching package feeds or registry creds. Dependencies: LANG-SURFACE-02. | Language Analyzer Guild (src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang/TASKS.md)
LANG-SURFACE-01 | DONE (2025-11-03) | Invoke Surface.Validation checks (env/cache/secrets) before analyzer execution to ensure consistent prerequisites.<br>2025-11-03: CompositeScanAnalyzerDispatcher now enforces Surface.Validation prior to language analyzers and propagates actionable failure diagnostics. | Language Analyzer Guild (src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang/TASKS.md)
LANG-SURFACE-02 | DONE (2025-11-03) | Consume Surface.FS APIs for layer/source caching (instead of bespoke caches) to improve determinism. Dependencies: LANG-SURFACE-01.<br>2025-11-03: Language analyzer runs fingerprint the workspace and persist results via Surface.FS cache helper for deterministic reuse. | Language Analyzer Guild (src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang/TASKS.md)
LANG-SURFACE-03 | DONE (2025-11-03) | Replace direct secret/env reads with Surface.Secrets references when fetching package feeds or registry creds. Dependencies: LANG-SURFACE-02.<br>2025-11-03: LanguageAnalyzerContext exposes Surface.Secrets-backed helper for registry/feed credentials with unit coverage. | Language Analyzer Guild (src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang/TASKS.md)
SCANNER-ANALYZERS-DENO-26-001 | TODO | Build input normalizer & VFS for Deno projects: merge `deno.json(c)`, import maps, lockfiles, vendor dirs, `$DENO_DIR` caches, and container layers. Detect runtime/toolchain hints deterministically. | Deno Analyzer Guild (src/Scanner/StellaOps.Scanner.Analyzers.Lang.Deno/TASKS.md)
SCANNER-ANALYZERS-DENO-26-002 | TODO | Module graph builder: resolve static/dynamic imports using import map, `deno.lock`, vendor/, cache, npm bridge, node: builtins, WASM/JSON assertions. Annotate edges with resolution source and form. Dependencies: SCANNER-ANALYZERS-DENO-26-001. | Deno Analyzer Guild (src/Scanner/StellaOps.Scanner.Analyzers.Lang.Deno/TASKS.md)
SCANNER-ANALYZERS-DENO-26-003 | TODO | NPM/Node compat adapter: map `npm:` specifiers to cached packages or compat `node_modules`, evaluate package `exports`/conditions, record node: builtin usage. Dependencies: SCANNER-ANALYZERS-DENO-26-002. | Deno Analyzer Guild (src/Scanner/StellaOps.Scanner.Analyzers.Lang.Deno/TASKS.md)

View File

@@ -5,12 +5,13 @@ Depends on: Sprint 120.A - AirGap, Sprint 130.A - Scanner
Summary: Runtime & Signals focus on Graph).
Task ID | State | Task description | Owners (Source)
--- | --- | --- | ---
GRAPH-INDEX-28-001 | TODO | Define canonical node/edge schemas, attribute dictionaries, identity rules, and seed fixtures; publish schema doc. | Graph Indexer Guild (src/Graph/StellaOps.Graph.Indexer/TASKS.md)
GRAPH-INDEX-28-002 | TODO | Implement SBOM ingest consumer producing artifact/package/file nodes and edges with `valid_from/valid_to`, scope metadata, and provenance links. Dependencies: GRAPH-INDEX-28-001. | Graph Indexer Guild (src/Graph/StellaOps.Graph.Indexer/TASKS.md)
GRAPH-INDEX-28-003 | TODO | Project Concelier linksets into overlay tiles (`affected_by` edges, evidence refs) without mutating source observations; keep advisory aggregates in overlay store only. Dependencies: GRAPH-INDEX-28-002. | Graph Indexer Guild (src/Graph/StellaOps.Graph.Indexer/TASKS.md)
GRAPH-INDEX-28-004 | TODO | Integrate VEX statements (`vex_exempts` edges) with justification metadata and precedence markers for overlays. Dependencies: GRAPH-INDEX-28-003. | Graph Indexer Guild (src/Graph/StellaOps.Graph.Indexer/TASKS.md)
GRAPH-INDEX-28-005 | TODO | Hydrate policy overlays into graph (`governs_with` nodes/edges) referencing effective findings and explain hashes for sampled nodes. Dependencies: GRAPH-INDEX-28-004. | Graph Indexer Guild, Policy Guild (src/Graph/StellaOps.Graph.Indexer/TASKS.md)
GRAPH-INDEX-28-006 | TODO | Generate graph snapshots per SBOM with lineage (`derived_from`), adjacency manifests, and metadata for diff jobs. Dependencies: GRAPH-INDEX-28-005. | Graph Indexer Guild (src/Graph/StellaOps.Graph.Indexer/TASKS.md)
GRAPH-INDEX-28-001 | DONE (2025-11-03) | Define canonical node/edge schemas, attribute dictionaries, identity rules, and seed fixtures; publish schema doc.<br>2025-11-03: Published `docs/modules/graph/schema.md` v1, refreshed fixtures (`nodes.json`, `edges.json`), and aligned GraphIdentity determinism tests. | Graph Indexer Guild (src/Graph/StellaOps.Graph.Indexer/TASKS.md)
GRAPH-INDEX-28-002 | DONE (2025-11-03) | Implement SBOM ingest consumer producing artifact/package/file nodes and edges with `valid_from/valid_to`, scope metadata, and provenance links. Dependencies: GRAPH-INDEX-28-001.<br>2025-11-03: Snapshot models restored, provenance resolution tightened, ingest processor + metrics added, transformer/fixtures/tests expanded for license + base artifact determinism. | Graph Indexer Guild (src/Graph/StellaOps.Graph.Indexer/TASKS.md)
GRAPH-INDEX-28-003 | DONE (2025-11-03) | Project Concelier linksets into overlay tiles (`affected_by` edges, evidence refs) without mutating source observations; keep advisory aggregates in overlay store only. Dependencies: GRAPH-INDEX-28-002. | Graph Indexer Guild (src/Graph/StellaOps.Graph.Indexer/TASKS.md)<br>2025-11-03: Advisory linkset snapshot/transformer coded with AFFECTED_BY edges plus fixture-backed tests; overlay persistence wiring landed; graph overlay suite green.
GRAPH-INDEX-28-004 | DONE (2025-11-03) | Integrate VEX statements (`vex_exempts` edges) with justification metadata and precedence markers for overlays. Dependencies: GRAPH-INDEX-28-003. | Graph Indexer Guild (src/Graph/StellaOps.Graph.Indexer/TASKS.md)<br>2025-11-03: VEX snapshot + transformer emit deterministic VEX_EXEMPTS overlays with provenance hashes; fixtures/tests updated; full graph indexer tests pass.
GRAPH-INDEX-28-005 | DONE (2025-11-03) | Hydrate policy overlays into graph (`governs_with` nodes/edges) referencing effective findings and explain hashes for sampled nodes. Dependencies: GRAPH-INDEX-28-004. | Graph Indexer Guild, Policy Guild (src/Graph/StellaOps.Graph.Indexer/TASKS.md)<br>2025-11-03: Policy snapshot/transformer emit deterministic policy_version nodes and GOVERNS_WITH edges; fixtures/tests updated; targeted transformer tests pass (full Mongo-backed suite requires local mongod).<br>2025-11-03: Processor + OTEL metrics wired to Mongo writer with unit coverage for success/failure; Mongo2Go-backed writer tests now fall back to `STELLAOPS_TEST_MONGO_URI` or `mongodb://127.0.0.1:27017` when available, otherwise they skip with guidance.
GRAPH-INDEX-28-006 | DONE (2025-11-03) | Generate graph snapshots per SBOM with lineage (`derived_from`), adjacency manifests, and metadata for diff jobs. Dependencies: GRAPH-INDEX-28-005. | Graph Indexer Guild (src/Graph/StellaOps.Graph.Indexer/TASKS.md)<br>2025-11-03: Snapshot builder + adjacency manifest added with hashed metadata, tests covering lineage/edges landed, docs note required `STELLAOPS_TEST_MONGO_URI`.<br>2025-11-03: Snapshot exporter writes manifest/adjacency/nodes/edges to snapshot directory with deterministic ordering.
GRAPH-INDEX-28-011 | DONE (2025-11-04) | Wire SBOM ingest runtime to emit snapshot artifacts and align dev/CI Mongo availability. Dependencies: GRAPH-INDEX-28-006. | Graph Indexer Guild (src/Graph/StellaOps.Graph.Indexer/TASKS.md)<br>2025-11-04: Added `AddSbomIngestPipeline` DI wiring with configurable snapshot root (`STELLAOPS_GRAPH_SNAPSHOT_DIR`), updated docs for Mongo/snapshot env vars, and ran Graph Indexer tests (Mongo writer skipped when URI absent).
GRAPH-INDEX-28-007 | TODO | Implement clustering/centrality background jobs (Louvain/degree/betweenness approximations) with configurable schedules and store cluster ids on nodes. Dependencies: GRAPH-INDEX-28-006. | Graph Indexer Guild, Observability Guild (src/Graph/StellaOps.Graph.Indexer/TASKS.md)
GRAPH-INDEX-28-008 | TODO | Provide incremental update + backfill pipeline with change streams, retry/backoff, idempotent operations, and backlog metrics. Dependencies: GRAPH-INDEX-28-007. | Graph Indexer Guild (src/Graph/StellaOps.Graph.Indexer/TASKS.md)
GRAPH-INDEX-28-009 | TODO | Add unit/property/integration tests, synthetic large graph fixtures, chaos testing (missing overlays, cycles), and determinism checks across runs. Dependencies: GRAPH-INDEX-28-008. | Graph Indexer Guild, QA Guild (src/Graph/StellaOps.Graph.Indexer/TASKS.md)
@@ -19,7 +20,7 @@ GRAPH-INDEX-28-010 | TODO | Package deployment artifacts (Helm/Compose), offline
[Runtime & Signals] 140.B) SbomService
Depends on: Sprint 120.A - AirGap, Sprint 130.A - Scanner
Summary: Runtime & Signals focus on SbomService).
Summary: Runtime & Signals focus on SBOM Service — projections, APIs, and orchestrator integration.
Task ID | State | Task description | Owners (Source)
--- | --- | --- | ---
SBOM-AIAI-31-001 | TODO | Provide `GET /sbom/paths?purl=...` and version timeline endpoints optimized for Advisory AI (incl. env flags, blast radius metadata). | SBOM Service Guild (src/SbomService/StellaOps.SbomService/TASKS.md)
@@ -29,10 +30,10 @@ SBOM-CONSOLE-23-002 | TODO | Deliver component lookup endpoints powering global
SBOM-ORCH-32-001 | TODO | Register SBOM ingest/index sources with orchestrator, embed worker SDK, and emit artifact hashes + job metadata. | SBOM Service Guild (src/SbomService/StellaOps.SbomService/TASKS.md)
SBOM-ORCH-33-001 | TODO | Report backpressure metrics, honor orchestrator pause/throttle signals, and classify error outputs for sbom jobs. Dependencies: SBOM-ORCH-32-001. | SBOM Service Guild (src/SbomService/StellaOps.SbomService/TASKS.md)
SBOM-ORCH-34-001 | TODO | Implement orchestrator backfill + watermark reconciliation for SBOM ingest/index, ensuring idempotent artifact reuse. Dependencies: SBOM-ORCH-33-001. | SBOM Service Guild (src/SbomService/StellaOps.SbomService/TASKS.md)
SBOM-SERVICE-21-001 | BLOCKED (2025-10-27) | Publish normalized SBOM projection schema (components, relationships, scopes, entrypoints) and implement read API with pagination + tenant enforcement. | SBOM Service Guild, Cartographer Guild (src/SbomService/StellaOps.SbomService/TASKS.md)
SBOM-SERVICE-21-002 | BLOCKED (2025-10-27) | Emit change events (`sbom.version.created`) carrying digest/version metadata for Graph Indexer builds; add replay/backfill tooling. Dependencies: SBOM-SERVICE-21-001. | SBOM Service Guild, Scheduler Guild (src/SbomService/StellaOps.SbomService/TASKS.md)
SBOM-SERVICE-21-003 | BLOCKED (2025-10-27) | Provide entrypoint/service node management API (list/update overrides) feeding Cartographer path relevance with deterministic defaults. Dependencies: SBOM-SERVICE-21-002. | SBOM Service Guild (src/SbomService/StellaOps.SbomService/TASKS.md)
SBOM-SERVICE-21-004 | BLOCKED (2025-10-27) | Wire observability: metrics (`sbom_projection_seconds`, `sbom_projection_size`), traces, structured logs with tenant info; set alerts for backlog. Dependencies: SBOM-SERVICE-21-003. | SBOM Service Guild, Observability Guild (src/SbomService/StellaOps.SbomService/TASKS.md)
SBOM-SERVICE-21-001 | BLOCKED (2025-10-27) | Publish normalized SBOM projection schema (components, relationships, scopes, entrypoints) and implement read API with pagination + tenant enforcement.<br>2025-10-27: Awaiting projection schema from Concelier (`CONCELIER-GRAPH-21-001`) before finalizing API payloads and fixtures. | SBOM Service Guild, Cartographer Guild (src/SbomService/StellaOps.SbomService/TASKS.md)
SBOM-SERVICE-21-002 | BLOCKED (2025-10-27) | Emit change events (`sbom.version.created`) carrying digest/version metadata for Graph Indexer builds; add replay/backfill tooling. Dependencies: SBOM-SERVICE-21-001.<br>2025-10-27: Blocked until `SBOM-SERVICE-21-001` defines projection schema and endpoints. | SBOM Service Guild, Scheduler Guild (src/SbomService/StellaOps.SbomService/TASKS.md)
SBOM-SERVICE-21-003 | BLOCKED (2025-10-27) | Provide entrypoint/service node management API (list/update overrides) feeding Cartographer path relevance with deterministic defaults. Dependencies: SBOM-SERVICE-21-002.<br>2025-10-27: Depends on base projection schema (`SBOM-SERVICE-21-001`) which is blocked. | SBOM Service Guild (src/SbomService/StellaOps.SbomService/TASKS.md)
SBOM-SERVICE-21-004 | BLOCKED (2025-10-27) | Wire observability: metrics (`sbom_projection_seconds`, `sbom_projection_size`), traces, structured logs with tenant info; set alerts for backlog. Dependencies: SBOM-SERVICE-21-003.<br>2025-10-27: Projection pipeline not in place yet; will follow once `SBOM-SERVICE-21-001` unblocks. | SBOM Service Guild, Observability Guild (src/SbomService/StellaOps.SbomService/TASKS.md)
SBOM-SERVICE-23-001 | TODO | Extend projections to include asset metadata (criticality, owner, environment, exposure flags) required by policy rules; update schema docs. Dependencies: SBOM-SERVICE-21-004. | SBOM Service Guild, Policy Guild (src/SbomService/StellaOps.SbomService/TASKS.md)
SBOM-SERVICE-23-002 | TODO | Emit `sbom.asset.updated` events when metadata changes; ensure idempotent payloads and documentation. Dependencies: SBOM-SERVICE-23-001. | SBOM Service Guild, Platform Events Guild (src/SbomService/StellaOps.SbomService/TASKS.md)
SBOM-VULN-29-001 | TODO | Emit inventory evidence with `scope`, `runtime_flag`, dependency paths, and nearest safe version hints, streaming change events for resolver jobs. | SBOM Service Guild (src/SbomService/StellaOps.SbomService/TASKS.md)
@@ -41,24 +42,27 @@ SBOM-VULN-29-002 | TODO | Provide resolver feed (artifact, purl, version, paths)
[Runtime & Signals] 140.C) Signals
Depends on: Sprint 120.A - AirGap, Sprint 130.A - Scanner
Summary: Runtime & Signals focus on Signals).
Summary: Runtime & Signals focus on Signals — reachability ingestion and scoring.
Notes:
- 2025-10-29: Skeleton live with scope policies, stub endpoints, and integration tests; sample configuration committed under `etc/signals.yaml.sample`.
- 2025-10-29: JSON parsers for Java/Node.js/Python/Go implemented; artifacts stored on filesystem with SHA-256 and callgraphs upserted into Mongo.
Task ID | State | Task description | Owners (Source)
--- | --- | --- | ---
SIGNALS-24-003 | BLOCKED (2025-10-27) | Implement runtime facts ingestion endpoint and normalizer (process, sockets, container metadata) populating `context_facts` with AOC provenance. | Signals Guild, Runtime Guild (src/Signals/StellaOps.Signals/TASKS.md)
SIGNALS-24-004 | BLOCKED (2025-10-27) | Deliver reachability scoring engine producing states/scores and writing to `reachability_facts`; expose configuration for weights. Dependencies: SIGNALS-24-003. | Signals Guild, Data Science (src/Signals/StellaOps.Signals/TASKS.md)
SIGNALS-24-005 | BLOCKED (2025-10-27) | Implement Redis caches (`reachability_cache:*`), invalidation on new facts, and publish `signals.fact.updated` events. Dependencies: SIGNALS-24-004. | Signals Guild, Platform Events Guild (src/Signals/StellaOps.Signals/TASKS.md)
SIGNALS-24-003 | BLOCKED (2025-10-27) | Implement runtime facts ingestion endpoint and normalizer (process, sockets, container metadata) populating `context_facts` with AOC provenance.<br>2025-10-27: Depends on `SIGNALS-24-001` for base API host and authentication plumbing. | Signals Guild, Runtime Guild (src/Signals/StellaOps.Signals/TASKS.md)
SIGNALS-24-004 | BLOCKED (2025-10-27) | Deliver reachability scoring engine producing states/scores and writing to `reachability_facts`; expose configuration for weights. Dependencies: SIGNALS-24-003.<br>2025-10-27: Upstream ingestion pipelines (`SIGNALS-24-002/003`) blocked; scoring engine cannot proceed. | Signals Guild, Data Science (src/Signals/StellaOps.Signals/TASKS.md)
SIGNALS-24-005 | BLOCKED (2025-10-27) | Implement Redis caches (`reachability_cache:*`), invalidation on new facts, and publish `signals.fact.updated` events. Dependencies: SIGNALS-24-004.<br>2025-10-27: Awaiting scoring engine and ingestion layers before wiring cache/events. | Signals Guild, Platform Events Guild (src/Signals/StellaOps.Signals/TASKS.md)
[Runtime & Signals] 140.D) Zastava
Depends on: Sprint 120.A - AirGap, Sprint 130.A - Scanner
Summary: Runtime & Signals focus on Zastava).
Summary: Runtime & Signals focus on Zastava — observer and webhook Surface integration.
Task ID | State | Task description | Owners (Source)
--- | --- | --- | ---
ZASTAVA-ENV-01 | TODO | Adopt Surface.Env helpers for cache endpoints, secret refs, and feature toggles. | Zastava Observer Guild (src/Zastava/StellaOps.Zastava.Observer/TASKS.md)
ZASTAVA-ENV-02 | TODO | Switch to Surface.Env helpers for webhook configuration (cache endpoint, secret refs, feature toggles). Dependencies: ZASTAVA-ENV-01. | Zastava Webhook Guild (src/Zastava/StellaOps.Zastava.Webhook/TASKS.md)
ZASTAVA-SECRETS-01 | TODO | Retrieve CAS/attestation access via Surface.Secrets instead of inline secret stores. | Zastava Observer Guild, Security Guild (src/Zastava/StellaOps.Zastava.Observer/TASKS.md)
ZASTAVA-SECRETS-02 | TODO | Retrieve attestation verification secrets via Surface.Secrets. Dependencies: ZASTAVA-SECRETS-01. | Zastava Webhook Guild, Security Guild (src/Zastava/StellaOps.Zastava.Webhook/TASKS.md)
ZASTAVA-SURFACE-01 | TODO | Integrate Surface.FS client for runtime drift detection (lookup cached layer hashes/entry traces). | Zastava Observer Guild (src/Zastava/StellaOps.Zastava.Observer/TASKS.md)
ZASTAVA-SURFACE-01 | TODO | Integrate Surface.FS client for runtime drift detection (lookup cached layer hashes/entry traces).<br>2025-10-24: Observer unit tests pending; `dotnet restore` needs offline copies of `Google.Protobuf`, `Grpc.Net.Client`, and `Grpc.Tools` in `local-nuget` before verification. | Zastava Observer Guild (src/Zastava/StellaOps.Zastava.Observer/TASKS.md)
ZASTAVA-SURFACE-02 | TODO | Enforce Surface.FS availability during admission (deny when cache missing/stale) and embed pointer checks in webhook response. Dependencies: ZASTAVA-SURFACE-01. | Zastava Webhook Guild (src/Zastava/StellaOps.Zastava.Webhook/TASKS.md)

View File

@@ -80,9 +80,9 @@ Depends on: Sprint 120.A - AirGap, Sprint 130.A - Scanner, Sprint 140.A - Graph
Summary: Scheduling & Automation focus on Scheduler (phase I).
Task ID | State | Task description | Owners (Source)
--- | --- | --- | ---
SCHED-CONSOLE-23-001 | TODO | Extend runs APIs with live progress SSE endpoints (`/console/runs/{id}/stream`), queue lag summaries, diff metadata fetch, retry/cancel hooks with RBAC enforcement, and deterministic pagination for history views consumed by Console. | Scheduler WebService Guild, BE-Base Platform Guild (src/Scheduler/StellaOps.Scheduler.WebService/TASKS.md)
SCHED-CONSOLE-27-001 | TODO | Provide policy batch simulation orchestration endpoints (`/policies/simulations` POST/GET) exposing run creation, shard status, SSE progress, cancellation, and retries with RBAC enforcement. Dependencies: SCHED-CONSOLE-23-001. | Scheduler WebService Guild, Policy Registry Guild (src/Scheduler/StellaOps.Scheduler.WebService/TASKS.md)
SCHED-CONSOLE-27-002 | TODO | Emit telemetry endpoints/metrics (`policy_simulation_queue_depth`, `policy_simulation_latency`) and webhook callbacks for completion/failure consumed by Registry. Dependencies: SCHED-CONSOLE-27-001. | Scheduler WebService Guild, Observability Guild (src/Scheduler/StellaOps.Scheduler.WebService/TASKS.md)
SCHED-CONSOLE-23-001 | DONE (2025-11-03) | Extend runs APIs with live progress SSE endpoints (`/console/runs/{id}/stream`), queue lag summaries, diff metadata fetch, retry/cancel hooks with RBAC enforcement, and deterministic pagination for history views consumed by Console. | Scheduler WebService Guild, BE-Base Platform Guild (src/Scheduler/StellaOps.Scheduler.WebService/TASKS.md)
SCHED-CONSOLE-27-001 | DONE (2025-11-03) | Provide policy batch simulation orchestration endpoints (`/policies/simulations` POST/GET) exposing run creation, shard status, SSE progress, cancellation, and retries with RBAC enforcement. Dependencies: SCHED-CONSOLE-23-001. | Scheduler WebService Guild, Policy Registry Guild (src/Scheduler/StellaOps.Scheduler.WebService/TASKS.md)
SCHED-CONSOLE-27-002 | DOING (2025-11-03) | Emit telemetry endpoints/metrics (`policy_simulation_queue_depth`, `policy_simulation_latency`) and webhook callbacks for completion/failure consumed by Registry. Dependencies: SCHED-CONSOLE-27-001. | Scheduler WebService Guild, Observability Guild (src/Scheduler/StellaOps.Scheduler.WebService/TASKS.md)
SCHED-IMPACT-16-303 | TODO | Snapshot/compaction + invalidation for removed images; persistence to RocksDB/Redis per architecture. | Scheduler ImpactIndex Guild (src/Scheduler/__Libraries/StellaOps.Scheduler.ImpactIndex/TASKS.md)
SCHED-SURFACE-01 | TODO | Evaluate Surface.FS pointers when planning delta scans to avoid redundant work and prioritise drift-triggered assets. | Scheduler Worker Guild (src/Scheduler/__Libraries/StellaOps.Scheduler.Worker/TASKS.md)
SCHED-VULN-29-001 | TODO | Expose resolver job APIs (`POST /vuln/resolver/jobs`, `GET /vuln/resolver/jobs/{id}`) to trigger candidate recomputation per artifact/policy change with RBAC and rate limits. | Scheduler WebService Guild, Findings Ledger Guild (src/Scheduler/StellaOps.Scheduler.WebService/TASKS.md)

View File

@@ -5,13 +5,13 @@ Depends on: Sprint 110.A - AdvisoryAI, Sprint 120.A - AirGap, Sprint 130.A - Sca
Summary: Export & Evidence focus on EvidenceLocker).
Task ID | State | Task description | Owners (Source)
--- | --- | --- | ---
EVID-OBS-53-001 | TODO | Bootstrap `StellaOps.Evidence.Locker` service with Postgres schema for `evidence_bundles`, `evidence_artifacts`, `evidence_holds`, tenant RLS, and object-store abstraction (WORM optional). | Evidence Locker Guild (src/EvidenceLocker/StellaOps.EvidenceLocker/TASKS.md)
EVID-OBS-53-002 | TODO | Implement bundle builders for evaluation/job/export snapshots collecting inputs, outputs, env digests, run metadata. Generate Merkle tree + manifest skeletons and persist root hash. Dependencies: EVID-OBS-53-001. | Evidence Locker Guild, Orchestrator Guild (src/EvidenceLocker/StellaOps.EvidenceLocker/TASKS.md)
EVID-OBS-53-003 | TODO | Expose REST APIs (`POST /evidence/snapshot`, `GET /evidence/:id`, `POST /evidence/verify`, `POST /evidence/hold/:case_id`) with audit logging, tenant enforcement, and size quotas. Dependencies: EVID-OBS-53-002. | Evidence Locker Guild, Security Guild (src/EvidenceLocker/StellaOps.EvidenceLocker/TASKS.md)
EVID-OBS-54-001 | TODO | Attach DSSE signing and RFC3161 timestamping to bundle manifests; validate against Provenance verification library. Wire legal hold retention extension and chain-of-custody events for Timeline Indexer. Dependencies: EVID-OBS-53-003. | Evidence Locker Guild, Provenance Guild (src/EvidenceLocker/StellaOps.EvidenceLocker/TASKS.md)
EVID-OBS-54-002 | TODO | Provide bundle download/export packaging (tgz) with checksum manifest, offline verification instructions, and sample fixture for CLI tests. Dependencies: EVID-OBS-54-001. | Evidence Locker Guild, DevEx/CLI Guild (src/EvidenceLocker/StellaOps.EvidenceLocker/TASKS.md)
EVID-OBS-55-001 | TODO | Implement incident mode hooks increasing retention window, capturing additional debug artefacts, and emitting activation/deactivation events to Timeline Indexer + Notifier. Dependencies: EVID-OBS-54-002. | Evidence Locker Guild, DevOps Guild (src/EvidenceLocker/StellaOps.EvidenceLocker/TASKS.md)
EVID-OBS-60-001 | TODO | Deliver portable evidence export flow for sealed environments: generate sealed bundles with checksum manifest, redacted metadata, and offline verification script. Document air-gapped import/verify procedures. Dependencies: EVID-OBS-55-001. | Evidence Locker Guild (src/EvidenceLocker/StellaOps.EvidenceLocker/TASKS.md)
EVID-OBS-53-001 | DONE | Bootstrap `StellaOps.Evidence.Locker` service with Postgres schema for `evidence_bundles`, `evidence_artifacts`, `evidence_holds`, tenant RLS, and object-store abstraction (WORM optional). | Evidence Locker Guild (src/EvidenceLocker/StellaOps.EvidenceLocker/TASKS.md)
EVID-OBS-53-002 | DONE (2025-11-03) | Implement bundle builders for evaluation/job/export snapshots collecting inputs, outputs, env digests, run metadata. Generate Merkle tree + manifest skeletons and persist root hash. Dependencies: EVID-OBS-53-001. | Evidence Locker Guild, Orchestrator Guild (src/EvidenceLocker/StellaOps.EvidenceLocker/TASKS.md)
EVID-OBS-53-003 | DONE (2025-11-03) | Expose REST APIs (`POST /evidence/snapshot`, `GET /evidence/:id`, `POST /evidence/verify`, `POST /evidence/hold/:case_id`) with audit logging, tenant enforcement, and size quotas. Dependencies: EVID-OBS-53-002. | Evidence Locker Guild, Security Guild (src/EvidenceLocker/StellaOps.EvidenceLocker/TASKS.md)
EVID-OBS-54-001 | DONE (2025-11-04) | Attach DSSE signing and RFC3161 timestamping to bundle manifests; validate against Provenance verification library. Wire legal hold retention extension and chain-of-custody events for Timeline Indexer. Dependencies: EVID-OBS-53-003. | Evidence Locker Guild, Provenance Guild (src/EvidenceLocker/StellaOps.EvidenceLocker/TASKS.md)
EVID-OBS-54-002 | DONE (2025-11-04) | Provide bundle download/export packaging (tgz) with checksum manifest, offline verification instructions, and sample fixture for CLI tests. Dependencies: EVID-OBS-54-001. | Evidence Locker Guild, DevEx/CLI Guild (src/EvidenceLocker/StellaOps.EvidenceLocker/TASKS.md)
EVID-OBS-55-001 | DONE (2025-11-04) | Implement incident mode hooks increasing retention window, capturing additional debug artefacts, and emitting activation/deactivation events to Timeline Indexer + Notifier. Dependencies: EVID-OBS-54-002. | Evidence Locker Guild, DevOps Guild (src/EvidenceLocker/StellaOps.EvidenceLocker/TASKS.md)
EVID-OBS-60-001 | DONE (2025-11-04) | Deliver portable evidence export flow for sealed environments: generate sealed bundles with checksum manifest, redacted metadata, and offline verification script. Document air-gapped import/verify procedures. Dependencies: EVID-OBS-55-001. | Evidence Locker Guild (src/EvidenceLocker/StellaOps.EvidenceLocker/TASKS.md)
[Export & Evidence] 160.B) ExportCenter.I
@@ -19,7 +19,7 @@ Depends on: Sprint 110.A - AdvisoryAI, Sprint 120.A - AirGap, Sprint 130.A - Sca
Summary: Export & Evidence focus on ExportCenter (phase I).
Task ID | State | Task description | Owners (Source)
--- | --- | --- | ---
DVOFF-64-001 | TODO | Implement Export Center job `devportal --offline` bundling portal HTML, specs, SDK artifacts, changelogs, and verification manifest. | DevPortal Offline Guild, Exporter Guild (src/ExportCenter/StellaOps.ExportCenter.DevPortalOffline/TASKS.md)
DVOFF-64-001 | DOING (2025-11-04) | Implement Export Center job `devportal --offline` bundling portal HTML, specs, SDK artifacts, changelogs, and verification manifest. | DevPortal Offline Guild, Exporter Guild (src/ExportCenter/StellaOps.ExportCenter.DevPortalOffline/TASKS.md)
DVOFF-64-002 | TODO | Provide verification CLI (`stella devportal verify bundle.tgz`) ensuring integrity before import. Dependencies: DVOFF-64-001. | DevPortal Offline Guild, AirGap Controller Guild (src/ExportCenter/StellaOps.ExportCenter.DevPortalOffline/TASKS.md)
EXPORT-AIRGAP-56-001 | TODO | Extend Export Center to build Mirror Bundles as export profiles, including advisories/VEX/policy packs manifesting DSSE/TUF metadata. | Exporter Service Guild, Mirror Creator Guild (src/ExportCenter/StellaOps.ExportCenter/TASKS.md)
EXPORT-AIRGAP-56-002 | TODO | Package Bootstrap Pack (images + charts) into OCI archives with signed manifests for air-gapped deployment. Dependencies: EXPORT-AIRGAP-56-001. | Exporter Service Guild, DevOps Guild (src/ExportCenter/StellaOps.ExportCenter/TASKS.md)

View File

@@ -6,10 +6,10 @@ Summary: Notifications & Telemetry focus on Notifier (phase I).
Task ID | State | Task description | Owners (Source)
--- | --- | --- | ---
NOTIFY-DOC-70-001 | DONE | Record architecture decision to keep `src/Notify` (shared libraries) and `src/Notifier` (host runtime) separate; capture rationale in notifications docs. Notes added 2025-11-02. | Notifications Service Guild (src/Notifier/StellaOps.Notifier/TASKS.md)
NOTIFY-AIRGAP-56-001 | TODO | Disable external webhook targets in sealed mode, default to enclave-safe channels (SMTP relay, syslog, file sink), and surface remediation guidance. | Notifications Service Guild (src/Notifier/StellaOps.Notifier/TASKS.md)
NOTIFY-AIRGAP-56-002 | TODO | Provide local notifier configurations bundled within Bootstrap Pack with deterministic secrets handling. Dependencies: NOTIFY-AIRGAP-56-001. | Notifications Service Guild, DevOps Guild (src/Notifier/StellaOps.Notifier/TASKS.md)
NOTIFY-AIRGAP-57-001 | TODO | Send staleness drift and bundle import notifications with remediation steps. Dependencies: NOTIFY-AIRGAP-56-002. | Notifications Service Guild, AirGap Time Guild (src/Notifier/StellaOps.Notifier/TASKS.md)
NOTIFY-AIRGAP-58-001 | TODO | Add portable evidence export completion notifications including checksum + location metadata. Dependencies: NOTIFY-AIRGAP-57-001. | Notifications Service Guild, Evidence Locker Guild (src/Notifier/StellaOps.Notifier/TASKS.md)
NOTIFY-AIRGAP-56-001 | DONE | Disable external webhook targets in sealed mode, default to enclave-safe channels (SMTP relay, syslog, file sink), and surface remediation guidance. | Notifications Service Guild (src/Notifier/StellaOps.Notifier/TASKS.md)
NOTIFY-AIRGAP-56-002 | DONE | Provide local notifier configurations bundled within Bootstrap Pack with deterministic secrets handling. Dependencies: NOTIFY-AIRGAP-56-001. | Notifications Service Guild, DevOps Guild (src/Notifier/StellaOps.Notifier/TASKS.md)
NOTIFY-AIRGAP-57-001 | DONE | Send staleness drift and bundle import notifications with remediation steps. Dependencies: NOTIFY-AIRGAP-56-002. | Notifications Service Guild, AirGap Time Guild (src/Notifier/StellaOps.Notifier/TASKS.md)
NOTIFY-AIRGAP-58-001 | DONE | Add portable evidence export completion notifications including checksum + location metadata. Dependencies: NOTIFY-AIRGAP-57-001. | Notifications Service Guild, Evidence Locker Guild (src/Notifier/StellaOps.Notifier/TASKS.md)
NOTIFY-ATTEST-74-001 | TODO | Create notification templates for verification failures, expiring attestations, key revocations, and transparency anomalies. | Notifications Service Guild, Attestor Service Guild (src/Notifier/StellaOps.Notifier/TASKS.md)
NOTIFY-ATTEST-74-002 | TODO | Wire notifications to key rotation/revocation events and transparency witness failures. Dependencies: NOTIFY-ATTEST-74-001. | Notifications Service Guild, KMS Guild (src/Notifier/StellaOps.Notifier/TASKS.md)
NOTIFY-OAS-61-001 | TODO | Update notifier OAS with rules, templates, incidents, quiet hours endpoints using standard error envelope and examples. | Notifications Service Guild, API Contracts Guild (src/Notifier/StellaOps.Notifier/TASKS.md)

View File

@@ -0,0 +1,14 @@
# Sprint 185 - Replay Core Foundations
[Replay Core] 185.A) Shared Replay Primitives
Depends on: Sprint 160 Export & Evidence
Summary: Stand up a shared replay library, hashing/cononicalisation helpers, and baseline documentation for deterministic bundles.
Task ID | State | Task description | Owners (Source)
--- | --- | --- | ---
REPLAY-CORE-185-001 | TODO | Scaffold `StellaOps.Replay.Core` with manifest schema types, canonical JSON rules, Merkle utilities, and DSSE payload builders; add `AGENTS.md`/`TASKS.md` for the new library; cross-reference `docs/replay/DETERMINISTIC_REPLAY.md` section 3 when updating the library charter. | BE-Base Platform Guild (`src/__Libraries/StellaOps.Replay.Core/TASKS.md`)
REPLAY-CORE-185-002 | TODO | Implement deterministic bundle writer (tar.zst, CAS naming) and hashing abstractions, updating `docs/modules/platform/architecture-overview.md` with a “Replay CAS” subsection that documents layout/retention expectations. | Platform Guild (`src/__Libraries/StellaOps.Replay.Core/TASKS.md`, `docs/modules/platform/architecture-overview.md`)
REPLAY-CORE-185-003 | TODO | Define Mongo collections (`replay_runs`, `replay_bundles`, `replay_subjects`) and indices, then author `docs/data/replay_schema.md` detailing schema fields, constraints, and offline sync strategy. | Platform Data Guild (`docs/TASKS.md`)
REPLAY-CORE-185-004 | TODO | Expand `docs/replay/DEVS_GUIDE_REPLAY.md` with integration guidance for consuming services (Scanner, Evidence Locker, CLI) and add checklist derived from `docs/replay/DETERMINISTIC_REPLAY.md` Section 11. | Docs Guild (`docs/TASKS.md`)
> 2025-11-03: Replay CAS section published in `docs/modules/platform/architecture-overview.md` §5 — owners can move REPLAY-CORE-185-001/002 to **DOING** once library scaffolding begins.

View File

@@ -0,0 +1,14 @@
# Sprint 186 - Scanner Record Mode
[Scanner Replay] 186.A) Record & Deterministic Execution
Depends on: Sprint 185 Replay Core Foundations, Sprint 130 Scanner & Surface
Summary: Enable Scanner services to emit replay manifests/bundles, wire deterministic analyzer execution, and align signing flows.
Task ID | State | Task description | Owners (Source)
--- | --- | --- | ---
SCAN-REPLAY-186-001 | TODO | Implement `record` mode in `StellaOps.Scanner.WebService` (manifest assembly, policy/feed/tool hash capture, CAS uploads) and document the workflow in `docs/modules/scanner/architecture.md` with references to `docs/replay/DETERMINISTIC_REPLAY.md` Section 6. | Scanner Guild (`src/Scanner/StellaOps.Scanner.WebService/TASKS.md`, `docs/modules/scanner/architecture.md`)
SCAN-REPLAY-186-002 | TODO | Update `StellaOps.Scanner.Worker` analyzers to consume sealed input bundles, enforce deterministic ordering, and contribute Merkle metadata; extend `docs/modules/scanner/deterministic-execution.md` (new) summarising invariants drawn from `docs/replay/DETERMINISTIC_REPLAY.md` Section 4. | Scanner Guild (`src/Scanner/StellaOps.Scanner.Worker/TASKS.md`, `docs/modules/scanner/deterministic-execution.md`)
SIGN-REPLAY-186-003 | TODO | Extend Signer/Authority DSSE flows to cover replay manifest/bundle payload types with multi-profile support; refresh `docs/modules/signer/architecture.md` and `docs/modules/authority/architecture.md` to capture the new signing/verification path referencing `docs/replay/DETERMINISTIC_REPLAY.md` Section 5. | Signing Guild (`src/Signer/StellaOps.Signer/TASKS.md`, `src/Authority/StellaOps.Authority/TASKS.md`)
DOCS-REPLAY-186-004 | TODO | Author `docs/replay/TEST_STRATEGY.md` (golden replay, feed drift, tool upgrade) and link it from both replay docs and Scanner architecture pages. | Docs Guild (`docs/TASKS.md`)
> 2025-11-03: `docs/replay/TEST_STRATEGY.md` drafted — Scanner/Signer guilds should shift replay tasks to **DOING** when engineering picks up implementation.

View File

@@ -0,0 +1,14 @@
# Sprint 187 - Evidence & CLI Replay Enablement
[Replay Delivery] 187.A) Evidence Locker & CLI Integration
Depends on: Sprint 186 Scanner Record Mode, Sprint 160 Export & Evidence, Sprint 180 Experience & SDKs
Summary: Persist replay bundles in Evidence Locker, expose ledger-backed verification, and ship offline-ready CLI workflows.
Task ID | State | Task description | Owners (Source)
--- | --- | --- | ---
EVID-REPLAY-187-001 | TODO | Implement replay bundle ingestion/retention APIs in Evidence Locker (WebService + Worker) and document storage/retention rules in `docs/modules/evidence-locker/architecture.md`, referencing `docs/replay/DETERMINISTIC_REPLAY.md` Sections 2 & 8. | Evidence Locker Guild (`src/EvidenceLocker/StellaOps.EvidenceLocker/TASKS.md`, `docs/modules/evidence-locker/architecture.md`)
CLI-REPLAY-187-002 | TODO | Add `scan --record`, `verify`, `replay`, `diff` commands to the CLI with offline bundle resolution; update `docs/modules/cli/architecture.md` and add a replay commands appendix citing `docs/replay/DEVS_GUIDE_REPLAY.md`. | DevEx/CLI Guild (`src/Cli/StellaOps.Cli/TASKS.md`, `docs/modules/cli/architecture.md`)
ATTEST-REPLAY-187-003 | TODO | Wire Attestor/Rekor anchoring for replay manifests and capture verification APIs; extend `docs/modules/attestor/architecture.md` with a replay ledger flow referencing `docs/replay/DETERMINISTIC_REPLAY.md` Section 9. | Attestor Guild (`src/Attestor/StellaOps.Attestor/TASKS.md`, `docs/modules/attestor/architecture.md`)
RUNBOOK-REPLAY-187-004 | TODO | Publish `/docs/runbooks/replay_ops.md` covering retention enforcement, RootPack rotation, offline kits, and verification drills; cross-link from replay specification summary. | Docs Guild, Ops Guild (`docs/TASKS.md`)
> 2025-11-03: `/docs/runbooks/replay_ops.md` created — Evidence Locker, CLI, Attestor teams can transition replay delivery tasks to **DOING** alongside Ops runbook rehearsals.

View File

@@ -56,6 +56,24 @@
- Dependency paths (runtime vs build/test, deduped by coordinate chain).
- Tenant environment flags (prod/stage toggles) with optional blast radius summary.
- Service-side clamps: max 500 timeline entries, 200 dependency paths, with client-provided toggles for env/blast data.
- `AddSbomContextHttpClient(...)` registers the typed HTTP client that calls `/v1/sbom/context`, while `NullSbomContextClient` remains the safe default for environments that have not yet exposed the SBOM service.
**Sample configuration** (wire real SBOM base URL + API key):
```csharp
services.AddSbomContextHttpClient(options =>
{
options.BaseAddress = new Uri("https://sbom-service.internal");
options.Endpoint = "/v1/sbom/context";
options.ApiKey = configuration["SBOM_SERVICE_API_KEY"];
options.UserAgent = "stellaops-advisoryai/1.0";
options.Tenant = configuration["TENANT_ID"];
});
services.AddAdvisoryPipeline();
```
After configuration, issue a smoke request (e.g., `ISbomContextRetriever.RetrieveAsync`) during deployment validation to confirm end-to-end connectivity and credentials before enabling Advisory AI endpoints.
Retriever requests and results are trimmed/normalized before hashing; metadata (counts, provenance keys) is returned for downstream guardrails. Unit coverage ensures deterministic ordering and flag handling.
@@ -69,6 +87,7 @@ All context references include `content_hash` and `source_id` enabling verifiabl
- Citations follow `[n]` indexing referencing actual sources.
- Remediation suggestions only cite policy-approved sources (fixed versions, vendor hotfixes).
- Moderation/PII filters prevent leaking secrets; responses failing validation are rejected and logged.
- Pre-flight guardrails redact secrets (AWS keys, generic API tokens, PEM blobs), block "ignore previous instructions"-style prompt injection attempts, enforce citation presence, and cap prompt payload length (default 16kB). Guardrail outcomes and redaction counts surface via `advisory_guardrail_blocks` / `advisory_outputs_stored` metrics.
## 5) Deterministic tooling
@@ -95,10 +114,8 @@ All context references include `content_hash` and `source_id` enabling verifiabl
## 8) APIs
- `POST /v1/advisory-ai/summaries` — generate (or retrieve cached) summary for `{advisoryKey, artifactId, policyVersion}`.
- `POST /v1/advisory-ai/conflicts` — explain conflicting VEX statements with trust ranking.
- `POST /v1/advisory-ai/remediation` — fetch remediation plan with target fix versions, prerequisites, verification steps.
- `GET /v1/advisory-ai/outputs/{hash}` — retrieve cached artefact (used by CLI/Console/Export Center).
- `POST /api/v1/advisory/{task}` — executes Summary/Conflict/Remediation pipeline (`task` ∈ `summary|conflict|remediation`). Requests accept `{advisoryKey, artifactId?, policyVersion?, profile, preferredSections?, forceRefresh}` and return sanitized prompt payloads, citations, guardrail metadata, provenance hash, and cache hints.
- `GET /api/v1/advisory/outputs/{cacheKey}?taskType=SUMMARY&profile=default` — retrieves cached artefacts for downstream consumers (Console, CLI, Export Center). Guardrail state and provenance hash accompany results.
All endpoints accept `profile` parameter (default `fips-local`) and return `output_hash`, `input_digest`, and `citations` for verification.

View File

@@ -50,6 +50,7 @@ Wire the deterministic pipeline (Summary / Conflict / Remediation flows) into th
- **Scope:** Implement prompt assembler, connect to guardrails, persist cache entries w/ DSSE metadata.
- **Dependencies:** Prompt templates, cache storage decision, guardrail interface.
- **Exit:** Deterministic outputs stored; force-refresh honoured; tests cover prompt assembly + caching.
> 2025-11-03: Prompt assembler now emits deterministic JSON payloads, guardrail pipeline wiring is stubbed for upcoming security hardening, and outputs persist with DSSE-ready provenance metadata plus golden test coverage.
### AIAI-31-004C (CLI integration & docs)
@@ -57,6 +58,13 @@ Wire the deterministic pipeline (Summary / Conflict / Remediation flows) into th
- **Dependencies:** Service endpoints stable, caching semantics documented.
- **Exit:** CLI command produces deterministic output, docs updated, smoke tests recorded.
### AIAI-31-006 (Service API surface)
- **Scope:** Expose REST endpoints for summary/conflict/remediation execution plus cached output retrieval (`POST /api/v1/advisory/{task}`, `GET /api/v1/advisory/outputs/{cacheKey}`). Include guardrail execution, provenance hashing, metrics, and stubs for RBAC/rate limits.
- **Dependencies:** Guardrail enforcement (AIAI-31-005), Authority scope wiring (`advisory-ai:view` / `advisory-ai:operate`), Offline kit docs.
- **Exit:** Endpoints return sanitized prompts with citations, guardrail metadata, DSSE hash, and plan cache indicators; OpenAPI description updated; rate-limit hooks ready for Authority integration.
> 2025-11-03: Initial REST surface shipped direct execution runs through guardrail pipeline, outputs persist with DSSE-ready provenance, metrics `advisory_outputs_stored`/`advisory_guardrail_blocks` emit, and cache retrieval endpoint exposes stored artefacts (RBAC/header enforcement pending scope delivery).
### Supporting tasks (other guilds)
- **AUTH-AIAI-31-004** Update scopes and DSSE policy (Authority guild).

View File

@@ -0,0 +1,55 @@
Using database: attestor_ttl_validation
true
{ ok: 1 }
Created collection and resetting indexes...
dedupe_key_unique
dedupe_ttl
{
acknowledged: true,
insertedId: ObjectId("6909225d9ddb8e8caf11da28")
}
Inserted document scheduled to expire at 2025-11-03T21:45:21.054Z
Current indexes:
[
{
v: 2,
key: {
_id: 1
},
name: '_id_'
},
{
v: 2,
key: {
key: 1
},
name: 'dedupe_key_unique',
unique: true
},
{
v: 2,
key: {
ttlAt: 1
},
name: 'dedupe_ttl',
expireAfterSeconds: 0
}
]
Still present at 2025-11-03T21:45:06.275Z (waiting for TTL monitor)...
Still present at 2025-11-03T21:45:09.473Z (waiting for TTL monitor)...
Still present at 2025-11-03T21:45:14.492Z (waiting for TTL monitor)...
Still present at 2025-11-03T21:45:19.510Z (waiting for TTL monitor)...
Still present at 2025-11-03T21:45:24.532Z (waiting for TTL monitor)...
Still present at 2025-11-03T21:45:29.565Z (waiting for TTL monitor)...
Still present at 2025-11-03T21:45:34.590Z (waiting for TTL monitor)...
Still present at 2025-11-03T21:45:37.779Z (waiting for TTL monitor)...
Still present at 2025-11-03T21:45:42.799Z (waiting for TTL monitor)...
Still present at 2025-11-03T21:45:47.818Z (waiting for TTL monitor)...
Still present at 2025-11-03T21:45:52.838Z (waiting for TTL monitor)...
Still present at 2025-11-03T21:45:57.855Z (waiting for TTL monitor)...
Still present at 2025-11-03T21:46:02.875Z (waiting for TTL monitor)...
Still present at 2025-11-03T21:46:07.885Z (waiting for TTL monitor)...
Still present at 2025-11-03T21:46:11.070Z (waiting for TTL monitor)...
Still present at 2025-11-03T21:46:16.075Z (waiting for TTL monitor)...
Document expired and removed after 80.0 seconds.
Remaining documents: 0

View File

@@ -0,0 +1,13 @@
redis> OK
2025-11-03T21:49:38+00:00 ttl=45
2025-11-03T21:49:41+00:00 ttl=42
2025-11-03T21:49:46+00:00 ttl=37
2025-11-03T21:49:51+00:00 ttl=32
2025-11-03T21:49:56+00:00 ttl=27
2025-11-03T21:50:01+00:00 ttl=22
2025-11-03T21:50:06+00:00 ttl=17
2025-11-03T21:50:11+00:00 ttl=12
2025-11-03T21:50:14+00:00 ttl=8
2025-11-03T21:50:20+00:00 ttl=3
2025-11-03T21:50:25+00:00 ttl=-2
Key expired after 47s

View File

@@ -39,3 +39,9 @@ If the helper script cannot be used:
## Ownership
- Primary: Attestor Service Guild.
- Partner: QA Guild (observes TTL metrics, confirms evidence archiving).
## 2025-11-03 validation summary
- **Stack:** `mongod` 7.0.5 (tarball) + `mongosh` 2.0.2, `redis-server` 7.2.4 (source build) running on localhost without Docker.
- **Mongo results:** `dedupe` TTL index (`ttlAt`, `expireAfterSeconds: 0`) confirmed; document inserted with 20s TTL expired automatically after ~80s (expected allocator sweep). Evidence: `docs/modules/attestor/evidence/2025-11-03-mongo-ttl-validation.txt`.
- **Redis results:** Key `attestor:ttl:live:bundle:validation` set with 45s TTL reached `TTL=-2` after ~47s confirming expiry propagation. Evidence: `docs/modules/attestor/evidence/2025-11-03-redis-ttl-validation.txt`.
- **Notes:** Local binaries built/run to accommodate sandbox without Docker; services shut down after validation.

View File

@@ -97,6 +97,8 @@ plan? = <plan name> // optional hint for UIs; not used for e
* `GET /.well-known/openid-configuration` → endpoints, algs, jwks_uri
* `GET /jwks` → JSON Web Key Set (rotating, at least 2 active keys during transition)
> **KMS-backed keys.** When the signing provider is `kms`, Authority fetches only the public coordinates (`Qx`, `Qy`) and version identifiers from the backing KMS. Private scalars never leave the provider; JWKS entries are produced by re-exporting the public material via the `kms.version` metadata attached to each key. Retired keys keep the same `kms.version` metadata so audits can trace which cloud KMS version produced a token.
### 3.2 Token issuance
* `POST /token`

View File

@@ -129,6 +129,10 @@ src/
Both subcommands honour offline-first expectations (no network access) and normalise relative roots via `--root` when operators mirror the credential store.
### 2.11 Air-gap guard
- CLI outbound HTTP flows (Authority auth, backend APIs, advisory downloads) route through `StellaOps.AirGap.Policy`. When sealed mode is active the CLI refuses commands that would require external egress and surfaces the shared `AIRGAP_EGRESS_BLOCKED` remediation guidance instead of attempting the request.
---
## 3) AuthN: Authority + DPoP

View File

@@ -304,7 +304,20 @@ Additional notes:
---
*Last updated: 2025-11-02 (Sprint100).*
## 7·Policy lifecycle CLI quick start
- `stella policy submit --policy <id> --version <n> --attach <simulation.json> --reviewers group`
- `stella policy review --policy <id> --version <n> --request-changes|--approve`
- `stella policy approve --policy <id> --version <n> --note "<justification>"`
- `stella policy publish --policy <id> --version <n> --reason "<why>" --ticket SEC-2048 --sign`
- `stella policy promote --policy <id> --version <n> --environment stage --note "<context>"`
- `stella policy activate --policy <id> --version <n> --note "<deployment reason>"`
All publish/promote operations require interactive identities with `policy:publish`/`policy:promote` and inject attestation metadata headers (`policy_reason`, `policy_ticket`, `policy_digest`). See [Policy Lifecycle & Approvals](../../../policy/lifecycle.md) §34 for the full workflow and compliance checklist.
---
*Last updated: 2025-11-03 (Sprint100).*
## 13. Authority configuration quick reference

View File

@@ -0,0 +1,75 @@
# Evidence Locker Bundle Packaging
> Sprint 160 / Task EVID-OBS-54-002 — deterministic tarball packaging for download/export.
The Evidence Locker emits a **single `bundle.tgz` artifact** for every sealed bundle. The artifact is deterministic so that operators can re-run packaging and obtain identical bytes when the manifest and signature are unchanged.
## Layout
The tar stream is written with **POSIX/PAX entries** and wrapped in a gzip layer:
```
bundle.tgz
├── manifest.json # Re-emitted DSSE payload (pretty JSON, canonical ordering)
├── signature.json # DSSE signature + key metadata + RFC3161 timestamp (if present)
├── bundle.json # Locker metadata (ids, status, root hash, storage key, timestamps)
├── checksums.txt # SHA-256 root hash + per-entry hashes from the manifest
└── instructions.txt # Offline verification steps and retention guidance
```
### Determinism traits
- **Gzip header timestamp** is pinned to `2025-01-01T00:00:00Z` so CI fixtures remain stable.
- All tar entries use the same fixed mtime/atime/ctime, `0644` permissions, and UTF-8 encoding.
- JSON files are serialized with `JsonSerializerDefaults.Web` + indentation to stabilise ordering.
- `checksums.txt` sorts manifest entries by `canonicalPath` and prefixes the Merkle root (`root <hash>`).
- `instructions.txt` conditionally adds timestamp verification steps when an RFC3161 token exists.
## Download endpoint
`GET /evidence/{bundleId}/download`
- Requires scopes: `evidence:read`.
- Streams `application/gzip` content with `Content-Disposition: attachment; filename="bundle.tgz"`.
- Emits quota headers (`X-Stella-Quota-*`) and audit events mirroring snapshot fetches.
- Returns `404` when the bundle is not sealed or the package has not been materialised.
The endpoint reuses `EvidenceBundlePackagingService` and caches the packaged object in the configured object store (`tenants/{tenant}/bundles/{bundle}/bundle.tgz`). If the underlying storage key changes (for example, during migration from filesystem to S3), the repository is updated atomically.
## Verification guidance
1. Download `bundle.tgz` and read `instructions.txt`; the first section lists bundle id, root hash, and creation/timestamp information.
2. Verify `checksums.txt` against the transferred archive to detect transit corruption.
3. Use the StellaOps CLI (`stella evidence verify bundle.tgz`) or the provenance verifier library to validate `signature.json`.
4. When present, validate the RFC3161 timestamp token with the configured TSA endpoint.
These steps match the offline procedure described in `docs/forensics/evidence-locker.md` (Portable Evidence section). Update that guide whenever packaging fields change.
## Portable bundle (`portable-bundle-v1.tgz`)
When sealed or air-gapped environments need a redacted evidence artifact, request:
`GET /evidence/{bundleId}/portable`
The portable archive is deterministic and contains only non-sensitive metadata:
```
portable-bundle-v1.tgz
├── manifest.json # Canonical manifest (identical to sealed bundle)
├── signature.json # DSSE signature + optional RFC3161 token
├── bundle.json # Redacted metadata (no tenant/storage identifiers)
├── checksums.txt # SHA-256 root + entry checksums
├── instructions-portable.txt # Sealed-mode transfer + verification guidance
└── verify-offline.sh # Offline verification helper script (POSIX shell)
```
Portable packaging traits:
- `bundle.json` excludes tenant identifiers, storage keys, and free-form descriptions. It adds `portableGeneratedAt` along with entry counts and totals for audit purposes.
- `incidentMetadata` is preserved only when incident mode injects `incident.*` keys into the manifest metadata.
- `verify-offline.sh` extracts the bundle, validates checksums (using `sha256sum`/`shasum`), surfaces the Merkle root hash, and reminds operators to run `stella evidence verify --bundle <archive>`.
- `instructions-portable.txt` mirrors the sealed documentation but calls out the offline script and redaction constraints.
Portable bundles reuse the same DSSE payload and timestamp, so downstream verifiers can validate signatures without additional configuration. The Evidence Locker tracks the portable storage key separately to honour write-once semantics for both sealed and portable artifacts.
For step-by-step sealed-mode guidance see `docs/airgap/portable-evidence.md`.

View File

@@ -0,0 +1,13 @@
# Evidence Locker Compliance Checklist (Sprint 160)
- [x] Postgres schema created via deterministic SQL migrations (`evidence_locker.*` tables, schema version tracking).
- [x] Row-level security enforced per tenant via `app.current_tenant` guard function.
- [x] Evidence bundle storage keys are content-addressed (sha256) and unique per tenant/bundle.
- [x] Object-store abstraction provides local filesystem and Amazon S3 drivers with optional WORM enforcement.
- [x] Startup migrations wired via hosted service with opt-out flag (`ApplyMigrationsAtStartup`).
- [x] Integration tests cover schema bootstrap, RLS behaviour, and storage drivers (filesystem, S3 fake client).
- [x] Temporary artifacts cleaned deterministically; filesystem targets validated in tests.
- [x] Timeline publisher emits bundle sealed and hold events with DSSE metadata when enabled; offline deployments fall back to null publisher.
- [x] Bundle packaging outputs deterministic `bundle.tgz` (fixed gzip mtime, sorted checksums, timestamp-aware instructions) and `/evidence/{id}/download` streams the cached object with audit logging.
- [x] Incident mode extends bundle retention, captures incident request snapshots, and emits activation/deactivation events to Timeline Indexer and Notifier stubs with unit + web integration coverage.
- [x] Portable bundle flow (`/evidence/{id}/portable`) emits `portable-bundle-v1.tgz` with redacted metadata, deterministic offline script, and write-once storage tracking.

View File

@@ -0,0 +1,24 @@
# Evidence Locker Incident Mode
> Sprint 55 / Task EVID-OBS-55-001 retention & debug hooks
Incident mode is a service-wide switch that increases forensic fidelity when StellaOps enters a suspected compromise or SLO breach. The Evidence Locker reacts to the flag in four ways:
1. **Extended retention.** Every newly sealed bundle receives an `ExpiresAt` timestamp of `CreatedAt + Incident.RetentionExtensionDays` so downstream TTL jobs keep artefacts long enough for investigation.
2. **Debug artefacts.** Snapshot requests emit an `incident/request-*.json` payload into the object store. The payload captures the normalized request metadata/materials plus the incident stamp so offline replay tooling has everything it needs. The manifest surfaces the artefact under the `incident/` section and packaging streams it alongside the canonical bundle files.
3. **Manifest metadata.** Bundles carry `incident.mode`, `incident.changedAt`, and `incident.retentionExtensionDays` metadata so verifiers and auditors can see exactly when the mode toggled and how long retention was extended.
4. **Operational signals.** Activation/deactivation events are published to the Timeline Indexer (and, via the notifier stub, to the future Notify integration). The `IEvidenceTimelinePublisher` now emits `evidence.incident.mode` with `state` and retention attributes, giving Ops a canonical audit trail.
Configuration lives under `EvidenceLocker:Incident`:
```jsonc
"EvidenceLocker": {
"Incident": {
"Enabled": true,
"RetentionExtensionDays": 60,
"CaptureRequestSnapshot": true
}
}
```
`IncidentModeManager` watches the options and raises events whenever the state flips. Tests cover retention math, timeline/notifier fan-out, and the new debug artefact path.

View File

@@ -82,6 +82,9 @@ All endpoints require Authority-issued JWT + DPoP tokens with scopes `export:run
- Builds self-contained filesystem layout (`/manifests`, `/data/raw`, `/data/policy`, `/indexes`).
- Delta variant compares against base manifest (`base_export_id`) to write only changed artefacts; records `removed` entries for cleanup.
- Supports optional encryption of `/data` subtree (age/AES-GCM) with key wrapping stored in `provenance.json`.
- **DevPortal (`devportal:offline`).**
- Packages developer portal static assets, OpenAPI specs, SDK releases, and changelog content into a reproducible archive with manifest/checksum pairs.
- Emits `manifest.json`, `checksums.txt`, and helper scripts described in [DevPortal Offline Bundle Specification](devportal-offline.md); signing/DSSE wiring follows the shared Export Center signing service.
Adapters expose structured telemetry events (`adapter.start`, `adapter.chunk`, `adapter.complete`) with record counts and byte totals per chunk. Failures emit `adapter.error` with reason codes.

View File

@@ -0,0 +1,115 @@
# DevPortal Offline Bundle Specification
> Sprint 160 · Task DVOFF-64-001
> Owners: DevPortal Offline Guild · Exporter Service Guild
The DevPortal offline bundle packages developer portal assets, OpenAPI specifications, SDK binaries, and changelog content into a deterministic archive for air-gapped distribution. This document captures the first iteration of the profile produced by the new `devportal --offline` export job.
## 1. Archive layout
The bundle ships as a gzip-compressed tar archive (`devportal-offline-bundle.tgz`) with the following structure:
```
manifest.json # Bundle manifest (schema v1)
checksums.txt # SHA-256 root + per-entry checksums
instructions-portable.txt # Human-readable verification guidance
verify-offline.sh # POSIX helper that extracts + validates checksums
portal/** # Static site assets (HTML, CSS, JS, etc.)
specs/** # OpenAPI / additional specs
sdks/<name>/** # SDK artifacts grouped by logical name (dotnet, python, ...)
changelog/** # Changelog and release notes
```
Every file entry is written with fixed permissions (`0644`, `0755` for scripts) and a pinned timestamp (`2025-01-01T00:00:00Z`) so the archive is byte-for-byte reproducible.
## 2. Manifest (`manifest.json`)
The manifest is emitted with camel-cased JSON (`JsonSerializerDefaults.Web`) and the following schema:
```jsonc
{
"version": "devportal-offline/v1",
"bundleId": "14b094c9-f0b4-4f9e-b221-b7a77c3f3445",
"generatedAt": "2025-11-04T12:30:00Z",
"metadata": {
"releaseVersion": "2025.11.0"
},
"sources": {
"portalIncluded": true,
"specsIncluded": true,
"sdkNames": ["dotnet", "python"],
"changelogIncluded": true
},
"totals": {
"entryCount": 6,
"totalSizeBytes": 123456
},
"entries": [
{
"category": "portal",
"path": "portal/index.html",
"sha256": "850db3...",
"sizeBytes": 5120,
"contentType": "text/html"
},
{
"category": "sdk",
"path": "sdks/dotnet/stellaops.sdk.nupkg",
"sha256": "0e1f23...",
"sizeBytes": 20480,
"contentType": "application/zip"
}
]
}
```
- `metadata` is a free-form dictionary (release version, build tag, etc.).
- `sdkNames` is a sorted list of logical SDK identifiers (sanitised to lowercase alphanumeric / `-_.`).
- `entries` are ordered lexicographically by `path` and include per-file SHA-256 digests, size, and inferred media type.
## 3. Checksums and root hash
`checksums.txt` follows the evidence locker format:
```
# DevPortal offline bundle checksums (sha256)
root <sha256(manifest.json)>
<sha256> portal/index.html
<sha256> specs/openapi.yaml
...
```
The `root` value is the SHA-256 hash of the serialized manifest and is exposed separately in the result object for downstream signing.
## 4. Verification script
`verify-offline.sh` is a POSIX-compatible helper that:
1. Extracts the archive into a temporary directory.
2. Validates `checksums.txt` via `sha256sum` (or `shasum -a 256` fallback).
3. Prints the manifest root hash and reminds operators to run `stella devportal verify --bundle <archive>` once DSSE signing is wired.
Operators can override the archive name via the first argument (`./verify-offline.sh mybundle.tgz`).
## 5. Content categories
| Category | Target prefix | Notes |
|-----------|---------------|-------|
| `portal` | `portal/` | Static site assets (HTML, CSS, JS, images). |
| `specs` | `specs/` | OpenAPI/JSON/YAML specifications. |
| `sdk` | `sdks/<name>/`| Each SDK source defines `<name>`; files are copied recursively. |
| `changelog` | `changelog/`| Markdown, text, or PDF release notes. |
Paths are normalised to forward slashes and guarded against directory traversal.
## 6. Determinism and hashing rules
- Files are enumerated and emitted in ordinal path order.
- SHA-256 digests use lowercase hex encoding.
- Optional directories (specs, SDKs, changelog) are skipped when absent; at least one category must contain files or the builder fails fast.
## 7. Next steps
- Attach DSSE signing + timestamping (`signature.json`) once Export Center signing infrastructure is ready.
- Integrate the builder into the Export Center worker profile (`devportal --offline`) and plumb orchestration/persistence.
- Produce CLI validation tooling (`stella devportal verify`) per DVOFF-64-002 and document operator workflows under `docs/airgap/devportal-offline.md`.

View File

@@ -0,0 +1,274 @@
# Findings Ledger Schema (Sprint 120)
> **Owners:** Findings Ledger Guild • Vuln Explorer Guild
> **Status:** Draft schema delivered 2025-11-03 for LEDGER-29-001
## 1. Storage profile
| Concern | Decision | Notes |
|---------|----------|-------|
| Engine | PostgreSQL 14+ with UTF-8, `jsonb`, and partitioning support | Aligns with shared data plane; deterministic ordering enforced via primary keys. |
| Tenancy | Range/list partition on `tenant_id` for ledger + projection tables | Simplifies retention and cross-tenant anchoring. |
| Time zone | All timestamps stored as `timestamptz` UTC | Canonical JSON uses ISO-8601 (`yyyy-MM-ddTHH:mm:ss.fffZ`). |
| Hashing | SHA-256 (lower-case hex) over canonical JSON | Implemented client-side and verified by DB constraint. |
| Migrations | SQL files under `src/Findings/StellaOps.Findings.Ledger/migrations` | Applied via DatabaseMigrator (part of platform toolchain). |
## 2. Ledger event model
Events are immutable append-only records representing every workflow change. Records capture the original event payload, cryptographic hashes, and actor metadata.
### 2.1 `ledger_events`
| Column | Type | Description |
|--------|------|-------------|
| `tenant_id` | `text` | Tenant partition key. |
| `chain_id` | `uuid` | Logical chain grouping (per tenant/policy combination). |
| `sequence_no` | `bigint` | Monotonic sequence within a chain (gapless). |
| `event_id` | `uuid` | Globally unique event identifier. |
| `event_type` | `ledger_event_type` | Enumerated type (see §2.2). |
| `policy_version` | `text` | Policy digest (e.g., SHA-256). |
| `finding_id` | `text` | Stable finding identity `(artifactId + vulnId + policyVersion)`. |
| `artifact_id` | `text` | Asset identifier (image digest, SBOM id, etc.). |
| `source_run_id` | `uuid` | Policy run that produced the event (nullable). |
| `actor_id` | `text` | Operator/service initiating the mutation. |
| `actor_type` | `text` | `system`, `operator`, `integration`. |
| `occurred_at` | `timestamptz` | Domain timestamp supplied by source. |
| `recorded_at` | `timestamptz` | Ingestion timestamp (defaults to `now()`). |
| `event_body` | `jsonb` | Canonical payload (see §2.3). |
| `event_hash` | `char(64)` | SHA-256 over canonical payload envelope. |
| `previous_hash` | `char(64)` | Hash of prior event in chain (all zeroes for first). |
| `merkle_leaf_hash` | `char(64)` | Leaf hash used for Merkle anchoring (hash over `event_hash || sequence_no`). |
**Constraints & indexes**
```
PRIMARY KEY (tenant_id, chain_id, sequence_no);
UNIQUE (tenant_id, event_id);
UNIQUE (tenant_id, chain_id, event_hash);
CHECK (event_hash ~ '^[0-9a-f]{64}$');
CHECK (previous_hash ~ '^[0-9a-f]{64}$');
CREATE INDEX ix_ledger_events_finding ON ledger_events (tenant_id, finding_id, policy_version);
CREATE INDEX ix_ledger_events_type ON ledger_events (tenant_id, event_type, recorded_at DESC);
```
Partitions: top-level partitioned by `tenant_id` (list) with a default partition. Optional sub-partition by month on `recorded_at` for large tenants. PostgreSQL requires the partition key in unique constraints; global uniqueness for `event_id` is enforced as `(tenant_id, event_id)` with application-level guards maintaining cross-tenant uniqueness.
### 2.2 Event types
```
CREATE TYPE ledger_event_type AS ENUM (
'finding.created',
'finding.status_changed',
'finding.severity_changed',
'finding.tag_updated',
'finding.comment_added',
'finding.assignment_changed',
'finding.accepted_risk',
'finding.remediation_plan_added',
'finding.attachment_added',
'finding.closed'
);
```
Additional types can be appended via migrations; canonical JSON must include `event_type` key.
### 2.3 Canonical ledger JSON
Canonical payload envelope (before hashing):
```json
{
"event": {
"id": "3ac1f4ef-3c26-4b0d-91d4-6a6d3a5bde10",
"type": "finding.status_changed",
"tenant": "tenant-a",
"chainId": "5fa2b970-9da2-4ef4-9a63-463c5d98d3cc",
"sequence": 42,
"policyVersion": "sha256:5f38...",
"finding": {
"id": "artifact:sha256:abc|pkg:cpe:/o:vendor:product",
"artifactId": "sha256:abc",
"vulnId": "CVE-2025-1234"
},
"actor": {
"id": "user:alice@tenant",
"type": "operator"
},
"occurredAt": "2025-11-03T15:12:05.123Z",
"payload": {
"previousStatus": "affected",
"status": "triaged",
"justification": "Ticket SEC-1234 created",
"ticket": {
"id": "SEC-1234",
"url": "https://tracker/sec-1234"
}
}
}
}
```
Canonicalisation rules:
1. Serialize using UTF-8, no BOM.
2. Sort object keys lexicographically at every level.
3. Represent enums/flags as lower-case strings.
4. Timestamps formatted as `yyyy-MM-ddTHH:mm:ss.fffZ` (millisecond precision, UTC).
5. Numbers use decimal notation; omit trailing zeros.
6. Arrays maintain supplied order.
Hash pipeline:
```
canonical_json = CanonicalJsonSerializer.Serialize(envelope)
sha256_bytes = SHA256(canonical_json)
event_hash = HexLower(sha256_bytes)
```
`merkle_leaf_hash = HexLower(SHA256(event_hash || '-' || sequence_no)).`
## 3. Merkle anchoring
Anchoring batches events per tenant across fixed windows (default: 1,000 events or 15 minutes). Anchors are stored in `ledger_merkle_roots`.
| Column | Type | Description |
|--------|------|-------------|
| `tenant_id` | `text` | Tenant key. |
| `anchor_id` | `uuid` | Anchor identifier. |
| `window_start` | `timestamptz` | Inclusive start of batch. |
| `window_end` | `timestamptz` | Exclusive end. |
| `sequence_start` | `bigint` | First sequence included. |
| `sequence_end` | `bigint` | Last sequence included. |
| `root_hash` | `char(64)` | Merkle root (SHA-256). |
| `leaf_count` | `integer` | Number of events aggregated. |
| `anchored_at` | `timestamptz` | Timestamp root stored/signed. |
| `anchor_reference` | `text` | Optional reference to external ledger (e.g., Rekor UUID). |
Indexes: `PRIMARY KEY (tenant_id, anchor_id)`, `UNIQUE (tenant_id, root_hash)`, `INDEX ix_merkle_sequences ON ledger_merkle_roots (tenant_id, sequence_end DESC)`.
## 4. Projection tables
### 4.1 `findings_projection`
Stores the latest verdict/state per finding.
| Column | Type | Description |
|--------|------|-------------|
| `tenant_id` | `text` | Partition key. |
| `finding_id` | `text` | Matches ledger payload. |
| `policy_version` | `text` | Active policy digest. |
| `status` | `text` | e.g., `affected`, `triaged`, `accepted_risk`, `resolved`. |
| `severity` | `numeric(6,3)` | Normalised severity score (0-10). |
| `labels` | `jsonb` | Key-value metadata (tags, KEV flag, runtime signals). |
| `current_event_id` | `uuid` | Ledger event that produced this state. |
| `explain_ref` | `text` | Reference to explain bundle or object storage key. |
| `policy_rationale` | `jsonb` | Array of policy rationale references (explain bundle IDs, remediation notes). |
| `updated_at` | `timestamptz` | Last projection update. |
| `cycle_hash` | `char(64)` | Deterministic hash of projection record (used in export bundles). |
Primary key: `(tenant_id, finding_id, policy_version)`.
Indexes:
- `ix_projection_status` on `(tenant_id, status, severity DESC)`.
- `ix_projection_labels_gin` using `labels` GIN for KEV/runtime filters.
### 4.2 `finding_history`
Delta view derived from ledger events for quick UI queries.
| Column | Type | Description |
|--------|------|-------------|
| `tenant_id` | `text` | Partition key. |
| `finding_id` | `text` | Finding identity. |
| `policy_version` | `text` | Policy digest. |
| `event_id` | `uuid` | Ledger event ID. |
| `status` | `text` | Status after event. |
| `severity` | `numeric(6,3)` | Severity after event (nullable). |
| `actor_id` | `text` | Actor performing change. |
| `comment` | `text` | Optional summary/message. |
| `occurred_at` | `timestamptz` | Domain event timestamp. |
Materialized view or table updated by projector. Indexed by `(tenant_id, finding_id, occurred_at DESC)`.
### 4.3 `triage_actions`
Audit table for operator actions needing tailored queries.
| Column | Type | Description |
|--------|------|-------------|
| `tenant_id` | `text` | Partition key. |
| `action_id` | `uuid` | Primary key. |
| `event_id` | `uuid` | Source ledger event. |
| `finding_id` | `text` | Finding identity. |
| `action_type` | `ledger_action_type` | e.g., `assign`, `comment`, `attach_evidence`, `link_ticket`. |
| `payload` | `jsonb` | Structured action body (canonical stored separately). |
| `created_at` | `timestamptz` | Timestamp stored. |
| `created_by` | `text` | Actor ID. |
`ledger_action_type` enum mirrors CLI/UX operations.
```
CREATE TYPE ledger_action_type AS ENUM (
'assign',
'comment',
'attach_evidence',
'link_ticket',
'remediation_plan',
'status_change',
'accept_risk',
'reopen',
'close'
);
### 4.4 `ledger_projection_offsets`
Checkpoint store for the projection background worker. Ensures idempotent replays across restarts.
| Column | Type | Description |
|--------|------|-------------|
| `worker_id` | `text` | Logical worker identifier (defaults to `default`). |
| `last_recorded_at` | `timestamptz` | Timestamp of the last projected ledger event. |
| `last_event_id` | `uuid` | Event identifier paired with `last_recorded_at` for deterministic ordering. |
| `updated_at` | `timestamptz` | Last time the checkpoint was persisted. |
Seed row inserted on migration ensures catch-up from epoch (`1970-01-01T00:00:00Z` with empty GUID).
## 5. Hashing & verification
1. Canonical serialize the envelope (§2.3).
2. Compute `event_hash` and store along with `previous_hash`.
3. Build Merkle tree per anchoring window using leaf hash `SHA256(event_hash || '-' || sequence_no)`.
4. Persist root in `ledger_merkle_roots` and, when configured, submit to external transparency log (Rekor v2). Store receipt/UUID in `anchor_reference`.
5. Projection rows compute `cycle_hash = SHA256(canonical_projection_json)` where canonical projection includes fields `{tenant_id, finding_id, policy_version, status, severity, labels, current_event_id}` with sorted keys.
Verification flow for auditors:
- Fetch event, recompute canonical hash, validate `previous_hash` chain.
- Reconstruct Merkle path from stored leaf hash; verify matches recorded root.
- Cross-check projection `cycle_hash` matches ledger state derived from last event.
## 6. Fixtures & migrations
- Initial migration script: `src/Findings/StellaOps.Findings.Ledger/migrations/001_initial.sql`.
- Sample canonical event: `seed-data/findings-ledger/fixtures/ledger-event.sample.json` (includes pre-computed `eventHash`, `previousHash`, and `merkleLeafHash` values).
- Sample projection row: `seed-data/findings-ledger/fixtures/finding-projection.sample.json` (includes canonical `cycleHash` for replay validation).
Fixtures follow canonical key ordering and include precomputed hashes to validate tooling.
## 7. Projection worker
- `LedgerProjectionWorker` consumes ledger events via `PostgresLedgerEventStream`, applying deterministic reductions with `LedgerProjectionReducer`.
- Checkpoint state is stored in `ledger_projection_offsets`, allowing replay from any point in time.
- Batch processing is configurable via `findings:ledger:projection` (`batchSize`, `idleDelay`).
- Each event writes:
- `findings_projection` (upserted current state with `cycle_hash`).
- `finding_history` (timeline entry keyed by event ID).
- `triage_actions` when applicable (status change, comment, assignment, remediation, attachment, accept-risk, close).
## 8. Next steps
- Integrate Policy Engine batch evaluation with the projector (`LEDGER-29-004`).
- Align Vulnerability Explorer queries with the new projection state and timeline endpoints.
- Externalise Merkle anchor publishing to transparency log once anchoring cadence is finalised.
| | | Array of policy rationale references (explain bundle IDs, remediation notes). |

View File

@@ -7,6 +7,7 @@ Graph module (upcoming) will power graph-indexed queries for SBOM relationships,
- Provide APIs for dependency impact, provenance chains, and reachability analysis.
- Integrate with Scheduler/Policy for graph-driven re-evaluation.
- Expose tooling for offline explorers.
- Maintain [Graph Index Canonical Schema](schema.md) with deterministic identities, fixtures, and attribute dictionary.
### Domain highlights (Epic5)
- **Nodes:** artifacts/images, SBOM components, packages/versions, files/paths, licences, advisories, VEX statements, provenance attestations, policy versions.

View File

@@ -40,6 +40,7 @@
- Each snapshot packages `nodes.jsonl`, `edges.jsonl`, `overlays/` plus manifest with hash, counts, and provenance. Export Center consumes these artefacts for graph-specific bundles.
- Saved queries and overlays include deterministic IDs so Offline Kit consumers can import and replay results.
- Runtime hosts register the SBOM ingest pipeline via `services.AddSbomIngestPipeline(...)`. Snapshot exports default to `./artifacts/graph-snapshots` but can be redirected with `STELLAOPS_GRAPH_SNAPSHOT_DIR` or the `SbomIngestOptions.SnapshotRootDirectory` callback.
## 6) Observability
@@ -53,4 +54,8 @@
- Phase 2: add VEX overlays, policy overlays, diff tooling.
- Phase 3: expose runtime/Zastava edges and AI-assisted recommendations (future).
### Local testing note
Set `STELLAOPS_TEST_MONGO_URI` to a reachable MongoDB instance before running `tests/Graph/StellaOps.Graph.Indexer.Tests`. The test harness falls back to `mongodb://127.0.0.1:27017`, then Mongo2Go, but the CI workflow requires the environment variable to be present to ensure upsert coverage runs against a managed database. Use `STELLAOPS_GRAPH_SNAPSHOT_DIR` (or the `AddSbomIngestPipeline` options callback) to control where graph snapshot artefacts land during local runs.
Refer to the module README and implementation plan for immediate context, and update this document once component boundaries and data flows are finalised.

View File

@@ -0,0 +1,98 @@
# Graph Index Canonical Schema
> Ownership: Graph Indexer Guild • Version 2025-11-03 (Sprint 140)\
> Scope: Canonical node and edge schemas, attribute dictionary, identity rules, and fixture references for the Graph Indexer foundations (GRAPH-INDEX-28-001).
## 1. Purpose
- Provide a deterministic schema contract for graph indexing pipelines.
- Document the attribute dictionary consumed by SBOM, Advisory, VEX, Policy, and Runtime signal feeds.
- Define the identity rules that guarantee stable node and edge identifiers across rebuilds.
- Point implementers and QA to the seed fixtures used in unit/integration tests.
## 2. Node taxonomy
| Node kind | Identity tuple (ordered) | Required attributes | Primary sources |
|-----------|--------------------------|---------------------|-----------------|
| `artifact` | `tenant`, `artifact_digest`, `sbom_digest` | `display_name`, `artifact_digest`, `sbom_digest`, `environment`, `labels[]`, `origin_registry`, `supply_chain_stage` | Scanner WebService, SBOM Service |
| `component` | `tenant`, `purl`, `source_type` | `purl`, `version`, `ecosystem`, `scope`, `license_spdx`, `usage` | SBOM Service analyzers |
| `file` | `tenant`, `artifact_digest`, `normalized_path`, `content_sha256` | `normalized_path`, `content_sha256`, `language_hint`, `size_bytes`, `scope` | SBOM layer analyzers |
| `license` | `tenant`, `license_spdx`, `source_digest` | `license_spdx`, `name`, `classification`, `notice_uri` | SBOM Service, Concelier |
| `advisory` | `tenant`, `advisory_source`, `advisory_id`, `content_hash` | `advisory_source`, `advisory_id`, `severity`, `published_at`, `content_hash`, `linkset_digest` | Concelier |
| `vex_statement` | `tenant`, `vex_source`, `statement_id`, `content_hash` | `status`, `statement_id`, `justification`, `issued_at`, `expires_at`, `content_hash` | Excititor |
| `policy_version` | `tenant`, `policy_pack_digest`, `effective_from` | `policy_pack_digest`, `policy_name`, `effective_from`, `expires_at`, `explain_hash` | Policy Engine |
| `runtime_context` | `tenant`, `runtime_fingerprint`, `collector`, `observed_at` | `runtime_fingerprint`, `collector`, `observed_at`, `cluster`, `namespace`, `workload_kind`, `runtime_state` | Signals, Zastava |
## 3. Edge taxonomy
| Edge kind | Source → Target | Identity tuple (ordered) | Required attributes | Default validity |
|-----------|-----------------|--------------------------|---------------------|------------------|
| `CONTAINS` | `artifact``component` | `tenant`, `artifact_node_id`, `component_node_id`, `sbom_digest` | `detected_by`, `layer_digest`, `scope`, `evidence_digest` | `valid_from = sbom_collected_at`, `valid_to = null` |
| `DEPENDS_ON` | `component``component` | `tenant`, `component_node_id`, `dependency_purl`, `sbom_digest` | `dependency_purl`, `dependency_version`, `relationship`, `evidence_digest` | Derived from SBOM dependency graph |
| `DECLARED_IN` | `component``file` | `tenant`, `component_node_id`, `file_node_id`, `sbom_digest` | `detected_by`, `scope`, `evidence_digest` | Mirrors SBOM declaration |
| `BUILT_FROM` | `artifact``artifact` | `tenant`, `parent_artifact_node_id`, `child_artifact_digest` | `build_type`, `builder_id`, `attestation_digest` | Derived from provenance attestations |
| `AFFECTED_BY` | `component``advisory` | `tenant`, `component_node_id`, `advisory_node_id`, `linkset_digest` | `evidence_digest`, `matched_versions`, `cvss`, `confidence` | Concelier overlays |
| `VEX_EXEMPTS` | `component``vex_statement` | `tenant`, `component_node_id`, `vex_node_id`, `statement_hash` | `status`, `justification`, `impact_statement`, `evidence_digest` | Excititor overlays |
| `GOVERNS_WITH` | `policy_version``component` | `tenant`, `policy_node_id`, `component_node_id`, `finding_explain_hash` | `verdict`, `explain_hash`, `policy_rule_id`, `evaluation_timestamp` | Policy Engine overlays |
| `OBSERVED_RUNTIME` | `runtime_context``component` | `tenant`, `runtime_node_id`, `component_node_id`, `runtime_fingerprint` | `process_name`, `entrypoint_kind`, `runtime_evidence_digest`, `confidence` | Signals/Zastava ingestion |
## 4. Attribute dictionary
| Attribute | Type | Applies to | Description |
|-----------|------|------------|-------------|
| `tenant` | `string` | nodes, edges | Tenant identifier (enforced on storage and query). |
| `kind` | `string` | nodes, edges | One of the values listed in the taxonomy tables. |
| `canonical_key` | `object` | nodes | Ordered tuple persisted as a JSON object matching the identity tuple components. |
| `id` | `string` | nodes, edges | Deterministic identifier (`gn:` or `ge:` prefix + Base32-encoded SHA-256). |
| `hash` | `string` | nodes, edges | SHA-256 of the canonical JSON representation (normalized by sorted keys). |
| `attributes` | `object` | nodes, edges | Domain-specific attributes (all dictionary keys kebab-case). |
| `provenance` | `object` | nodes, edges | Includes `source`, `collected_at`, `sbom_digest`, `attestation_digest`, `event_offset`. |
| `valid_from` | `string (ISO-8601)` | nodes, edges | Inclusive timestamp describing when the record became effective. |
| `valid_to` | `string (ISO-8601 or null)` | nodes, edges | Exclusive timestamp; `null` means open-ended. |
| `scope` | `string` | nodes, edges | Scope label (e.g., `runtime`, `build`, `dev-dependency`). |
| `labels` | `array[string]` | nodes | Free-form but deterministic ordering (ASCII sort). |
| `confidence` | `number` | edges | 0-1 numeric confidence score for overlay-derived edges. |
| `evidence_digest` | `string` | edges | SHA-256 digest referencing the immutable evidence payload. |
| `linkset_digest` | `string` | nodes, edges | SHA-256 digest to Concelier linkset documents. |
| `explain_hash` | `string` | nodes, edges | Hash of Policy Engine explain trace payload. |
| `runtime_state` | `string` | `runtime_context` nodes | Aggregated runtime state (e.g., `Running`, `Terminated`). |
## 5. Identity rules
1. **Node IDs (`gn:` prefix).**
`id = "gn:" + tenant + ":" + kind + ":" + base32(sha256(identity_tuple))`\
`identity_tuple` concatenates tuple components with `|` (no escaping) and lower-cases both keys and values unless the component is a hash or digest.
2. **Edge IDs (`ge:` prefix).**
`id = "ge:" + tenant + ":" + kind + ":" + base32(sha256(identity_tuple))`\
Edge tuples must include the resolved node IDs rather than only the canonical keys to ensure immutability under re-key events.
3. **Hashes.**
`hash` is computed by serializing the canonical document with:
- UTF-8 JSON
- Object keys sorted lexicographically
- Arrays sorted where semantics allow (e.g., `labels`, `matched_versions`)
- Timestamps normalized to UTC ISO-8601 (`YYYY-MM-DDTHH:MM:SSZ`)
4. **Deterministic provenance.**
`provenance.source` is a dotted string (`scanner.sbom.v1`, `concelier.linkset.v1`) and `provenance.event_offset` is a monotonic integer for replay.
## 6. Validity window semantics
- `valid_from` equals the upstream event timestamp at ingestion time (SBOM collected timestamp, advisory published timestamp, policy evaluation timestamp, runtime observation timestamp).
- `valid_to` stays `null` until a newer version supersedes the record. Superseding records carry a `supersedes` reference in `attributes`.
- Snapshots freeze the set of nodes/edges with `valid_from <= snapshot_at < coalesce(valid_to, +∞)`.
## 7. Fixtures & verification
- Seed fixtures live under `tests/Graph/StellaOps.Graph.Indexer.Tests/Fixtures/v1/`.
- Fixture files:
- `nodes.json` — canonical node samples (per node kind).
- `edges.json` — canonical edge samples including overlay references.
- `schema-matrix.json` — lists attribute coverage per node/edge kind for regression tests.
- Unit tests assert:
- Identifier determinism (`GraphIdentityTests.NodeIds_are_stable`).
- Hash determinism under property ordering variations.
- Attribute coverage against `schema-matrix.json`.
- Fixtures follow the attribute dictionary above; new attributes require dictionary updates and fixture refresh.
## 8. Change control
- Increment schema version in fixture folder (`v1`, `v2`, …) when making breaking changes.
- Update this document and the JSON fixtures together; do not ship mismatched versions.
- Notify SBOM Service, Concelier, Excititor, Policy, Signals, and Zastava owners before promoting changes to DOING/DONE state.
## 9. References
- `docs/modules/graph/architecture.md` — high-level architecture.
- `docs/modules/platform/architecture-overview.md` — platform context.
- `src/Graph/StellaOps.Graph.Indexer/TASKS.md` — task tracking.
- `seed-data/` — additional sample payloads for offline kit packaging (future work).

View File

@@ -63,6 +63,11 @@ IssuerDirectory:
| `POST` | `/issuer-directory/issuers/{id}/keys` | `issuer-directory:write` | Add a signing key (validates format, deduplicates fingerprint, audits). |
| `POST` | `/issuer-directory/issuers/{id}/keys/{keyId}/rotate` | `issuer-directory:write` | Retire an active key and create a replacement atomically. |
| `DELETE` | `/issuer-directory/issuers/{id}/keys/{keyId}` | `issuer-directory:admin` | Revoke a key (status → revoked, audit logged). |
| `GET` | `/issuer-directory/issuers/{id}/trust` | `issuer-directory:read` | Retrieve tenant/global trust overrides with effective weight. |
| `PUT` | `/issuer-directory/issuers/{id}/trust` | `issuer-directory:write` | Set or update a tenant trust override; reason may be supplied in body/header. |
| `DELETE` | `/issuer-directory/issuers/{id}/trust` | `issuer-directory:admin` | Remove a tenant trust override (falls back to global/default weight). |
All write/delete operations accept an optional audit reason header (`X-StellaOps-Reason`) which is persisted alongside trust override changes.
Payloads follow the contract in `Contracts/IssuerDtos.cs` and align with domain types (`IssuerRecord`, `IssuerMetadata`, `IssuerEndpoint`).

View File

@@ -514,11 +514,31 @@ sequenceDiagram
* **Templates**: compile and cache per rule+channel+locale; version with rule `updatedAt` to invalidate.
* **Rules**: store raw YAML + parsed AST; validate with schema + static checks (e.g., nonsensical combos).
* **Secrets**: pluggable secret resolver (Authority Secret proxy, K8s, Vault).
* **Rate limiting**: `System.Threading.RateLimiting` + perconnector adapters.
* **Rate limiting**: `System.Threading.RateLimiting` + per-connector adapters.
---
## 19) Roadmap (postv1)
## 19) Air-gapped bootstrap configuration
Air-gapped deployments ship a deterministic Notifier profile inside the
Bootstrap Pack. The artefacts live under `bootstrap/notify/` after running the
Offline Kit builder and include:
- `notify.yaml` — configuration derived from `etc/notify.airgap.yaml`, pointing
to the sealed MongoDB/Authority endpoints and loading connectors from the
local plug-in directory.
- `notify-web.secret.example` — template for the Authority client secret,
intended to be renamed to `notify-web.secret` before deployment.
- `README.md` — operator guide (`docs/modules/notify/bootstrap-pack.md`).
These files are copied automatically by `ops/offline-kit/build_offline_kit.py`
via `copy_bootstrap_configs`. Operators mount the configuration and secret into
the `StellaOps.Notifier.WebService` container (Compose or Kubernetes) to keep
sealed-mode roll-outs reproducible.
---
## 20) Roadmap (post-v1)
* **PagerDuty/Opsgenie** connectors; **Jira** ticket creation.
* **User inbox** (inapp notifications) + mobile push via webhook relay.

View File

@@ -0,0 +1,59 @@
# Notifier Bootstrap Pack Guide
The Bootstrap Pack gives operators a deterministic set of configuration files
to stage the Notifier service in sealed or fully air-gapped environments. The
assets ship alongside the Offline Kit under `bootstrap/notify/` and can be
copied directly onto the hosts that run `StellaOps.Notifier.WebService`.
## Contents
| File | Purpose |
| ---- | ------- |
| `notify.yaml` | Sealed-mode configuration derived from `etc/notify.airgap.yaml`. It disables external resolution by pointing to in-cluster services and honours the shared `EgressPolicy`. |
| `notify-web.secret.example` | Deterministic template for the Authority client secret. Replace the value before running the service. |
| `rules/airgap-ops.rule.json` | Bootstrap rule subscribing to air-gap drift, bundle import, and portable export completion events. Update channel identifiers before import. |
| `templates/airgap-ops-email.template.json` | Email template used by the bootstrap rule with remediation guidance, checksum context, and download locations. |
| `README.md` | This guide, also embedded in the pack for quick operator reference. |
## Usage
1. **Populate secrets** copy `notify-web.secret.example` to
`notify-web.secret`, change `NOTIFY_WEB_CLIENT_SECRET` to the value issued by
Authority, and store it with restrictive permissions (for example
`chmod 600`).
2. **Drop configuration** place `notify.yaml` in the location expected by
the runtime (`/app/etc/notify.yaml` for the containers we ship). The file
assumes MongoDB is reachable at `mongodb://stellaops:airgap-password@mongo:27017`
and Authority at `https://authority.airgap.local` adjust if your
deployment uses different hostnames.
3. **Import rule/template** with the Notify CLI or REST API, import
`templates/airgap-ops-email.template.json` first, then
`rules/airgap-ops.rule.json`. Update the `channel` identifiers inside the
rule so they match your sealed SMTP relay (for example `email:airgap-ops`).
The rule now also delivers portable export completion notices; ensure your
downstream process watches for checksum and location details in the payload.
4. **Mount secrets/config** for Docker Compose use:
```yaml
volumes:
- ./bootstrap/notify/notify.yaml:/app/etc/notify.yaml:ro
env_file:
- ./bootstrap/notify/notify-web.secret
```
In Kubernetes, create a Secret from the two files and mount them into the
Notifier pod.
5. **Verify sealed mode** with the configuration in place the Notifier
resolves channels that point to local relays (SMTP, syslog, file sink). Any
attempt to contact an external webhook is denied by `StellaOps.AirGap.Policy`
with remediation guidance.
## How it is packaged
`ops/offline-kit/build_offline_kit.py` automatically copies the configuration
and secret template into `bootstrap/notify/` during Offline Kit creation. The
same staging directory is what we sign and publish as the Bootstrap Pack, so
the artefacts stay deterministic across releases.
Refer to `etc/notify.airgap.yaml` if you need to regenerate the pack or build a
site-specific overlay from source control.

View File

@@ -0,0 +1,29 @@
{
"eventId": "99b40f9c-4a34-4a5f-9e1a-0c1e5a97c0bb",
"kind": "airgap.bundle.import",
"version": "1",
"tenant": "tenant-01",
"ts": "2025-10-30T22:05:18+00:00",
"actor": "airgap-importer",
"payload": {
"bundleId": "mirror-2025-10-30",
"importedAt": "2025-10-30T22:02:03Z",
"links": {
"audit": "https://authority.airgap.local/authority/audit/airgap/entries/mirror-2025-10-30",
"docs": "https://docs.stella-ops.org/airgap/airgap-mode.html#import"
},
"remediation": "Review bundle warnings and plan the next mirror export to keep advisories within the allowed freshness budget.",
"severity": "medium",
"status": "completed",
"warnings": [
{
"code": "feeds.outdated",
"message": "OSV feed is 2 days old; schedule next mirror export sooner."
}
]
},
"attributes": {
"importer": "ops:olivia",
"category": "airgap"
}
}

View File

@@ -0,0 +1,40 @@
{
"eventId": "6a9f4e37-5053-4a40-9761-5c0a0a857ee2",
"kind": "airgap.portable.export.completed",
"version": "1",
"tenant": "tenant-01",
"ts": "2025-11-02T21:45:12+00:00",
"actor": "export-center",
"payload": {
"bundleId": "portable-2025-11-02",
"checksum": {
"sha256": "f4f56c7d9a68ee4d4c324e7d782f9e2a3c1c4b2fa83f39c7c4b5f9f047d3af11",
"sha512": "c2d1b5ec4784f8cfe317aa7c501c7fd736b119f1d0d1eaa99bf3d6f4f70a85b7e699f356e2f3d3d8c536a8a6f2a506d1c2f458f8829b6f8d9c4abe0ac7edb5a1"
},
"exportedAt": "2025-11-02T21:43:05Z",
"links": {
"docs": "https://docs.stella-ops.org/airgap/portable-evidence.html",
"manifest": "https://authority.airgap.local/export/bundles/portable-2025-11-02/export.json"
},
"locations": [
{
"availableUntil": "2025-11-09T00:00:00Z",
"path": "/data/offline-kit/bootstrap/exports/portable/portable-2025-11-02.tar.zst",
"type": "file"
},
{
"reference": "registry.airgap.local/offline/portable@sha256:f4f56c7d9a68ee4d4c324e7d782f9e2a3c1c4b2fa83f39c7c4b5f9f047d3af11",
"type": "oci"
}
],
"profile": "portable-evidence:mirror-full",
"remediation": "Distribute the portable evidence bundle to downstream enclaves before the freshness budget expires.",
"severity": "medium",
"sizeBytes": 73400320,
"status": "completed"
},
"attributes": {
"profile": "portable-evidence",
"category": "airgap"
}
}

View File

@@ -0,0 +1,26 @@
{
"eventId": "5cf2d3b2-9b90-4f7d-9a9a-54b8b5a5e3aa",
"kind": "airgap.time.drift",
"version": "1",
"tenant": "tenant-01",
"ts": "2025-10-31T06:15:00+00:00",
"actor": "airgap-time",
"payload": {
"anchorId": "anchor-2025-10-28",
"anchorIssuedAt": "2025-10-28T05:00:00Z",
"budgetSeconds": 259200,
"driftSeconds": 216000,
"links": {
"docs": "https://docs.stella-ops.org/airgap/staleness-and-time.html"
},
"nextAnchorDueBy": "2025-11-01T05:00:00Z",
"remainingSeconds": 43200,
"remediation": "Import the latest mirror bundle to refresh the time anchor or extend the budget via policy override before sealed mode blocks scheduled jobs.",
"severity": "high",
"status": "critical"
},
"attributes": {
"category": "airgap",
"anchorBudgetHours": "72"
}
}

View File

@@ -142,18 +142,36 @@ sequenceDiagram
---
## 5·References
## 5·Replay CAS & deterministic bundles
- **Replay CAS:** Content-addressed storage lives under `cas://replay/<sha256-prefix>/<digest>.tar.zst`. Writers must use [StellaOps.Replay.Core](../../src/__Libraries/StellaOps.Replay.Core/AGENTS.md) helpers to ensure lexicographic file ordering, POSIX mode normalisation (0644/0755), LF newlines, and zstd level19 compression. Bundle metadata (size, hash, created) feeds the platform-wide `replay_bundles` collection defined in `docs/data/replay_schema.md`.
- **Artifacts:** Each recorded scan stores three bundles:
1. `manifest.json` (canonical JSON, hashed and signed via DSSE).
2. `inputbundle.tar.zst` (feeds, policies, tools, environment snapshot).
3. `outputbundle.tar.zst` (SBOM, findings, VEX, logs, Merkle proofs).
Every artifact is signed with multi-profile keys (FIPS, GOST, SM, etc.) managed by Authority. See `docs/replay/DETERMINISTIC_REPLAY.md` §2§5 for the full schema.
- **Storage tiers:** Primary storage is Mongo (`replay_runs`, `replay_subjects`) plus the CAS bucket. Evidence Locker mirrors bundles for long-term retention and legal hold workflows (`docs/modules/evidence-locker/architecture.md`). Offline kits package bundles under `offline/replay/<scan-id>` with detached DSSE envelopes for air-gapped verification.
- **APIs & ownership:** Scanner WebService produces the bundles via `record` mode, Scanner Worker emits Merkle metadata, Signer/Authority provide DSSE signatures, Attestor anchors manifests to Rekor, CLI/Evidence Locker handle retrieval, and Docs Guild maintains runbooks. Responsibilities are tracked in `docs/implplan/SPRINT_185_replay_core.md` through `SPRINT_187_evidence_cli_replay.md`.
- **Operational policies:** Retention defaults to 180days for hot CAS storage and 2years for cold Evidence Locker copies. Rotation and pruning follow the checklist in `docs/runbooks/replay_ops.md`.
---
## 6·References
- [Aggregation-Only Contract reference](../../ingestion/aggregation-only-contract.md)
- [Concelier architecture](../concelier/architecture.md)
- [Excititor architecture](../excititor/architecture.md)
- [Policy Engine architecture](../policy/architecture.md)
- [Authority service](../authority/architecture.md)
- [Replay specification](../../replay/DETERMINISTIC_REPLAY.md)
- [Replay developer guide](../../replay/DEVS_GUIDE_REPLAY.md)
- [Replay schema](../../data/replay_schema.md) *(pending)*
- [Replay test strategy](../../replay/TEST_STRATEGY.md) *(draft)*
- [Observability standards (upcoming)](../../observability/policy.md) interim reference for telemetry naming.
---
## 6·Compliance checklist
## 7·Compliance checklist
- [ ] AOC guard enabled for all Concelier and Excititor write paths in production.
- [ ] Mongo schema validators deployed for `advisory_raw` and `vex_raw`; change streams scoped per tenant.
@@ -165,4 +183,4 @@ sequenceDiagram
---
*Last updated: 2025-10-26 (Sprint19).*
*Last updated: 2025-11-03 (Replay planning refresh).*

View File

@@ -269,6 +269,8 @@ At cron tick:
* `scheduler.run_latency_seconds{quantile}` // event → first verdict
* `scheduler.delta_images_total{severity}`
* `scheduler.rate_limited_total{reason}`
* `policy_simulation_queue_depth{status}` (WebService gauge)
* `policy_simulation_latency_seconds` (WebService histogram)
**Targets**
@@ -278,6 +280,12 @@ At cron tick:
**Tracing** (OTEL): spans `plan`, `resolve`, `enqueue`, `report_call`, `persist`, `emit`.
**Webhooks**
* Policy simulation webhooks fire on terminal states (`succeeded`, `failed`, `cancelled`).
* Configure under `Scheduler:Worker:Policy:Webhook` (see `SCHED-WEB-27-002-POLICY-SIMULATION-WEBHOOKS.md`).
* Requests include headers `X-StellaOps-Tenant` and `X-StellaOps-Run-Id` for idempotency.
---
## 10) Configuration (YAML)

View File

@@ -129,6 +129,24 @@ Response:
---
### KMS drivers (keyful mode)
Signer now ships five deterministic KMS adapters alongside the default keyless flow:
- `services.AddFileKms(...)` stores encrypted ECDSA material on disk for air-gapped or lab installs.
- `services.AddAwsKms(options => { options.Region = "us-east-1"; /* optional: options.Endpoint, UseFipsEndpoint */ });` delegates signing to AWS KMS, caches metadata/public keys offline, and never exports the private scalar. Rotation/revocation still run through AWS tooling (this library intentionally throws for those APIs so we do not paper over operator approvals).
- `services.AddGcpKms(options => { options.Endpoint = "kms.googleapis.com"; });` integrates with Google Cloud KMS asymmetric keys, auto-resolves the primary key version when callers omit a version, and verifies signatures locally with exported PEM material.
- `services.AddPkcs11Kms(options => { options.LibraryPath = "/opt/hsm/libpkcs11.so"; options.PrivateKeyLabel = "stella-attestor"; });` loads a PKCS#11 module, opens read-only sessions, signs digests via HSM mechanisms, and never hoists the private scalar into process memory.
- `services.AddFido2Kms(options => { options.CredentialId = "<base64url>"; options.PublicKeyPem = "-----BEGIN PUBLIC KEY-----..."; options.AuthenticatorFactory = sp => new WebAuthnAuthenticator(); });` routes signing to a WebAuthn/FIDO2 authenticator for dual-control or air-gap scenarios. The authenticator must supply the CTAP/WebAuthn plumbing; the library handles digesting, key material caching, and verification.
Cloud & hardware-backed drivers share a few invariants:
1. Hash payloads server-side (SHA-256) before invoking provider APIs signatures remain reproducible and digest inputs are observable in structured audit logs.
2. Cache metadata for the configurable window (default 5min) and subject-public-key-info blobs for 10min; tune these per sovereignty policy when running in sealed/offline environments.
3. Only expose public coordinates (`Qx`, `Qy`) to the host ― `KmsKeyMaterial.D` is blank for non-exportable keys so downstream code cannot accidentally persist secrets.
> **Security review checkpoint:** rotate/destroy remains an administrative action in the provider. Document those runbooks per tenant, and gate AWS/GCP traffic in sealed-mode via the existing egress allowlist. PKCS#11 loads native code, so keep library paths on the allowlist and validate HSM policies separately. FIDO2 authenticators expect an operator in the loop; plan for session timeouts and explicit audit fields when enabling interactive signing.
## 4) Validation pipeline (hot path)
```mermaid

View File

@@ -20,6 +20,7 @@
- **Redaction.** Attribute processors strip PII/secrets based on policy-managed allowed keys. Redaction profiles mirrored in Offline Kit.
- **Sampling.** Tail sampling by service/error; incident mode (triggered by Orchestrator) promotes services to 100% sampling, extends retention, and toggles Notify alerts.
- **Alerting.** Prometheus rules/Dashboards packaged with Export Center: service SLOs, queue depth, policy run latency, ingestion AOC violations.
- **Sealed-mode guard.** `StellaOps.Telemetry.Core` enforces `IEgressPolicy` on OTLP exporters; when air-gap mode is sealed any non-loopback collector endpoints are automatically disabled and a structured warning with remediation is emitted.
## 4) APIs & integration

View File

@@ -4,6 +4,8 @@
## 1) Ledger data model
- See [`../findings-ledger/schema.md`](../findings-ledger/schema.md) for the canonical SQL schema, hashing strategy, and fixtures underpinning these collections.
- **Collections / tables**
- `finding_records` canonical, policy-derived findings enriched with advisory, VEX, SBOM, runtime context. Includes `policyVersion`, `advisoryRawIds`, `vexRawIds`, `sbomComponentId`, and `explainBundleRef`.
- `finding_history` append-only state transitions (`new`, `triaged`, `accepted_risk`, `remediated`, `false_positive`, etc.) with timestamps, actor, and justification.
@@ -60,6 +62,8 @@ CLI mirrors these endpoints (`stella findings list|view|update|export`). Console
- **Attribute filters (ABAC)** Authority enforces per-service-account filters via the client-credential parameters `vuln_env`, `vuln_owner`, and `vuln_business_tier`. Service accounts define the allowed values in `authority.yaml` (`attributes` block). Tokens include the resolved filters as claims (`stellaops:vuln_env`, `stellaops:vuln_owner`, `stellaops:vuln_business_tier`), and tokens persisted to Mongo retain the same values for audit and revocation.
- **Audit trail** Every token issuance emits `authority.vuln_attr.*` audit properties that mirror the resolved filter set, along with `delegation.service_account` and ordered `delegation.actor[n]` entries so Vuln Explorer can correlate access decisions.
- **Permalinks** Signed permalinks inherit the callers ABAC filters; consuming services must enforce the embedded claims in addition to scope checks when resolving permalinks.
- **Attachment tokens** Authority mints short-lived tokens (`POST /vuln/attachments/tokens/issue`) to gate evidence downloads. Verification (`POST /vuln/attachments/tokens/verify`) enforces tenant, scope, and ABAC metadata, and emits `vuln.attachment.token.*` audit records.
- **Ledger verification** Offline workflows validate attachments by comparing the Authority-issued token, the Vuln Explorer ledger hash, and the downloaded artefact hash before distribution.
## 7) Offline bundle requirements

View File

@@ -0,0 +1,28 @@
# Authority Plugin LDAP Review — 2025-11-03
## Attendees
- Auth Guild core (Authority Host Crew)
- Security Guild (Identity Controls)
- DevEx Docs Guild
- Plugin Team 4 (Auth Libraries & Identity Providers)
## Agenda
- Confirm LDAP plugin charter and offline/sovereign requirements.
- Resolve outstanding decisions (audit mirror, mutual TLS, group mapping).
- Capture follow-up implementation tasks and documentation deliverables.
## Discussion Summary
1. **Audit mirror parity** — All provisioning flows must emit Mongo audit records even when LDAP is the write source. Records store actor, tenant, DN, operation, hashed secret reference, and correlation IDs matching Authority audit events.
2. **Mutual TLS requirements** — Regulated installations (FIPS/eIDAS/GOST) require client certificate bindings. Plugin must accept secret-backed PFX stores, optional chain send, and deterministic trust-store configuration (`system` vs bundled roots). Runtime must fail fast when TLS is misconfigured.
3. **Role mapping flexibility** — Deterministic regex mappings allow deriving canonical Authority roles from LDAP DNs without custom scripting. Regex capture groups map to `{role}` substitutions; evaluation order is deterministic (dictionary map → regex map) to preserve predictability.
4. **Offline cache expectations** — Mongo-backed cache must record TTL and emit metrics when falling back to cached entries. Cache invalidation respects `cache.ttlSeconds` configuration.
## Follow-up Tasks
- `PLG7.IMPL-001` — Scaffold plugin + tests, configuration binding (client cert, trust store, insecure toggle validation).
- `PLG7.IMPL-002` — Implement credential store + mutual TLS enforcement with deterministic retry/backoff and structured logging.
- `PLG7.IMPL-003` — Deliver claims enricher with regex mapping, cache layer, and associated tests/fixtures.
- `PLG7.IMPL-004` — Implement client provisioning store with LDAP write toggles, Mongo audit mirror, and bootstrap validation.
- `PLG7.IMPL-005` — Update developer guide, samples, and release notes with LDAP configuration guidance (mutual TLS, regex mapping, audit mirror).
## Next Checkpoint
- Status review scheduled 2025-11-10 to assess scaffolding progress and mutual TLS handshake tests.

View File

@@ -106,7 +106,23 @@ stateDiagram-v2
- Approver cannot be same identity as author (enforced by Authority config).
- Approver must attest to successful simulation diff review (`--attach diff.json`).
### 3.5 Activation & Runs
### 3.5 Signing & Publication
- **Who:** Operators with fresh-auth (`policy:publish`, `policy:promote`) and approval backing.
- **Tools:** Console Publish & Sign wizard, CLI `stella policy publish`, `stella policy promote`.
- **Actions:**
- Execute `stella policy publish <id> --version n --reason "<why>" --ticket SEC-123 --sign` to produce a DSSE attestation capturing IR digest + approval metadata.
- Provide required metadata headers (`policy_reason`, `policy_ticket`, `policy_digest`), enforced by Authority; CLI flags map to headers automatically.
- Promote the signed version to targeted environments (`stella policy promote <id> --version n --environment stage`).
- **Artefacts:**
- DSSE payload stored in `policy_attestations`, containing SHA-256 digest, signer, reason, ticket, promoted environment.
- Audit events `policy.published`, `policy.promoted` including metadata snapshot and attestation reference.
- **Guards:**
- Publish requires a fresh-auth window (<5 minutes) and interactive identity (client-credentials tokens are rejected).
- Metadata headers must be present; missing values return `policy_attestation_metadata_missing`.
- Signing key rotation enforced via Authority JWKS; CLI refuses to publish if attestation verification fails.
### 3.6 Activation & Runs
- **Who:** Operators (`policy:operate`, `policy:run`, `policy:activate`).
- **Tools:** Console Promote to active”, CLI `stella policy activate <id> --version n`, `stella policy run`.
@@ -122,7 +138,7 @@ stateDiagram-v2
- Activation blocked if previous full run <24h old failed or is pending.
- Selection of SBOM/advisory snapshots uses consistent cursors recorded for reproducibility.
### 3.6 Archival / Rollback
### 3.7 Archival / Rollback
- **Who:** Approvers or Operators with `policy:archive`.
- **Tools:** Console menu, CLI `stella policy archive <id> --version n --reason`.
@@ -172,7 +188,7 @@ All CLI commands emit structured JSON by default; use `--format table` for human
---
## 6 · Compliance Gates
## 6 · Compliance Gates
| Gate | Stage | Enforced by | Requirement |
|------|-------|-------------|-------------|
@@ -180,14 +196,15 @@ All CLI commands emit structured JSON by default; use `--format table` for human
| **Simulation evidence** | Submit | CLI/Console | Attach diff from `stella policy simulate` covering baseline SBOM set. |
| **Reviewer quorum** | Submit Approve | Authority | Minimum approver/reviewer count configurable per tenant. |
| **Determinism CI** | Approve | DevOps job | Twin run diff passes (`DEVOPS-POLICY-20-003`). |
| **Activation health** | Approve Activate | Policy Engine | Last run status succeeded; orchestrator queue healthy. |
| **Attestation metadata** | Approve Publish | Authority / CLI | `policy:publish` executed with reason & ticket metadata; DSSE attestation verified. |
| **Activation health** | Publish/Promote Activate | Policy Engine | Last run status succeeded; orchestrator queue healthy. |
| **Export validation** | Archive | Offline Kit | DSSE-signed policy pack generated for long-term retention. |
Failure of any gate emits a `policy.lifecycle.violation` event and blocks transition until resolved.
---
## 7 · Offline / Air-Gap Considerations
## 7 · Offline / Air-Gap Considerations
- Offline Kit bundles include:
- Approved policy packs (`.policy.bundle` + DSSE signatures).
@@ -200,7 +217,7 @@ Failure of any gate emits a `policy.lifecycle.violation` event and blocks transi
---
## 8 · Incident Response & Rollback
## 8 · Incident Response & Rollback
- Incident mode (triggered via `policy incident activate`) forces:
- Immediate incremental run to evaluate mitigation policies.
@@ -214,7 +231,7 @@ Failure of any gate emits a `policy.lifecycle.violation` event and blocks transi
---
## 9 · CI/CD Integration (Reference)
## 9 · CI/CD Integration (Reference)
- **Pre-merge:** run lint + simulation jobs against golden SBOM fixtures.
- **Post-merge (main):** compile, compute IR checksum, stage for Offline Kit.
@@ -223,16 +240,18 @@ Failure of any gate emits a `policy.lifecycle.violation` event and blocks transi
---
## 10 · Compliance Checklist
## 10 · Compliance Checklist
- [ ] **Role mapping validated:** Authority issuer config maps organisational roles to required `policy:*` scopes (per tenant).
- [ ] **Submission evidence attached:** Latest simulation diff and lint artefacts linked to submission.
- [ ] **Reviewer quorum met:** All required reviewers approved or acknowledged; no unresolved blocking comments.
- [ ] **Approval note logged:** Approver justification recorded in audit trail alongside IR checksum.
- [ ] **Publish attestation signed:** `stella policy publish` executed by interactive operator, metadata (`policy_reason`, `policy_ticket`, `policy_digest`) present, DSSE attestation stored.
- [ ] **Promotion recorded:** Target environment promoted via CLI/Console with audit event linking to attestation.
- [ ] **Activation guard passed:** Latest run status success, orchestrator queue healthy, determinism job green.
- [ ] **Archive bundles produced:** When archiving, DSSE-signed policy pack exported and stored for offline retention.
- [ ] **Offline parity proven:** For sealed deployments, `--sealed` simulations executed and logged before approval.
---
*Last updated: 2025-10-26 (Sprint 20).*
*Last updated: 2025-11-03 (Sprint 100).*

View File

@@ -43,7 +43,7 @@ All modes record their status in `policy_runs` with deterministic metadata:
}
```
> **Schemas & samples:** see `src/Scheduler/__Libraries/StellaOps.Scheduler.Models/docs/SCHED-MODELS-20-001-POLICY-RUNS.md` and the fixtures in `samples/api/scheduler/policy-*.json` for canonical payloads consumed by CLI/UI/worker integrations.
> **Schemas & samples:** see `src/Scheduler/__Libraries/StellaOps.Scheduler.Models/docs/SCHED-MODELS-20-001-POLICY-RUNS.md` and the fixtures in `samples/api/scheduler/policy-*.json` (including `policy-simulation-status.json`) for canonical payloads consumed by CLI/UI/worker integrations. Cloned simulations append `metadata.retry-of=<sourceRunId>` so operators can trace retries without losing provenance.
---
@@ -81,7 +81,7 @@ sequenceDiagram
- **Queue** Backed by Mongo + optional NATS for fan-out; supports leases and replay on crash.
- **Engine** Stateless worker executing the deterministic evaluator.
- **Store** Mongo collections: `policy_runs`, `effective_finding_{policyId}`, `policy_run_events` (append-only history), optional object storage for explain traces.
- **Observability** Prometheus metrics (`policy_run_seconds`), OTLP traces, structured logs.
- **Observability** Prometheus metrics (`policy_run_seconds`, `policy_simulation_queue_depth`, `policy_simulation_latency`), OTLP traces, structured logs.
---

View File

@@ -0,0 +1,57 @@
# Replay Test Strategy (Draft)
> **Ownership:** Docs Guild · Scanner Guild · Evidence Locker Guild · QA Guild
> **Related:** `docs/replay/DETERMINISTIC_REPLAY.md`, `docs/replay/DEVS_GUIDE_REPLAY.md`, `docs/modules/platform/architecture-overview.md`, `docs/implplan/SPRINT_186_scanner_record_mode.md`, `docs/implplan/SPRINT_187_evidence_cli_replay.md`
This playbook enumerates the deterministic replay validation suite. It guides the work tracked under Sprints186187 so every guild ships the same baseline before enabling `scan --record`.
---
## 1 · Test matrix
| ID | Scenario | Purpose | Modules | Required Artifacts |
|----|----------|---------|---------|--------------------|
| T-STRICT-001 | **Golden Replay** | Re-run a recorded scan and expect byte-identical outputs. | Scanner.WebService, Scanner.Worker, CLI | `manifest.json`, input/output bundles, DSSE signatures |
| T-FEED-002 | **Feed Drift What-If** | Re-run with updated feeds (`--what-if feeds`) to ensure only feed hashes change. | Scanner.Worker, Concelier, CLI | Feed snapshot bundles, policy bundle, diff report |
| T-TOOL-003 | **Toolchain Upgrade Guard** | Attempt replay with newer scanner binary; expect rejection with `ToolHashMismatch`. | Scanner.Worker, Replay.Core | Tool hash catalog, error log |
| T-POLICY-004 | **Policy Variation Diff** | Re-run with alternate lattice bundle; expect deterministic diff, not failure. | Policy Engine, CLI | Policy bundle(s), diff output |
| T-LEDGER-005 | **Ledger Verification** | Verify Rekor inclusion proof and DSSE signatures offline. | Attestor, Signer, Authority, CLI | DSSE envelopes, Rekor proof, RootPack |
| T-RETENTION-006 | **Retention Sweep** | Ensure Evidence Locker prunes hot CAS after SLA while preserving cold storage copies. | Evidence Locker, Ops | Replay retention config, audit logs |
| T-OFFLINE-007 | **Offline Kit Replay** | Execute `stella replay` using only Offline Kit artifacts. | CLI, Evidence Locker | Offline kit bundle, local RootPack |
| T-OPA-008 | **Runbook Drill** | Simulate replay-driven incident response per `docs/runbooks/replay_ops.md`. | Ops Guild, Scanner, Authority | Runbook checklist, incident notes |
---
## 2 · Execution guidelines
1. **Deterministic environment** — Freeze clock, locale, timezone, and random seed per manifest. See `docs/replay/DETERMINISTIC_REPLAY.md` §4.
2. **Canonical verification** — Use `StellaOps.Replay.Core` JSON serializer; reject non-canonical payloads before diffing.
3. **Data sources** — Replay always consumes `replay_runs` + CAS bundles, never live feeds/policies.
4. **CI integration**
- Scanner repo: add pipeline stage `ReplayStrict` running T-STRICT-001 on fixture images (x64 + arm64).
- CLI repo: smoke test `scan --record`, `verify`, `replay`, `diff` using generated fixtures.
- Evidence Locker repo: nightly retention test (T-RETENTION-006) with dry-run mode.
5. **Observability** — Emit metrics `replay_verify_total{result}`, `replay_diff_total{mode}`, `replay_bundle_size_bytes`. Structured logs require `replay.scan_id`, `subject.digest`, `manifest.hash`.
---
## 3 · Fixtures and tooling
- **Fixture catalog** lives under `tools/replay-fixtures/`. Include `README.md` describing update workflow and deterministic compression command.
- **Generation script** (`./tools/replay-fixtures/build.sh`) orchestrates recording, verifying, and packaging fixtures.
- **Checksum manifest** (`fixtures/checksums.json`) lists CAS digests and DSSE hashes for quick sanity checks.
- **CI secrets** must provide offline RootPack and replay signing keys; use sealed secrets in air-gapped pipelines.
---
## 4 · Acceptance checklist
- [ ] All test scenarios executed on x64 and arm64 runners.
- [ ] Replay verification metrics ingested into Telemetry Stack dashboards.
- [ ] Evidence Locker retention job validated against hot/cold tiers.
- [ ] CLI documentation updated with troubleshooting steps observed during tests.
- [ ] Runbook drill logged with timestamp and owners in `docs/runbooks/replay_ops.md`.
---
*Drafted: 2025-11-03. Update statuses in Sprint186/187 boards when this checklist is satisfied.*

View File

@@ -1,9 +1,20 @@
# RFC: StellaOps.Authority.Plugin.Ldap
**Status:** Draft for review by Auth Guild, Security Guild, DevEx (2025-10-10)
**Status:** Accepted Auth Guild, Security Guild, DevEx Docs sign-off (2025-11-03)
**Authors:** Plugin Team 4 (Auth Libraries & Identity Providers)
**Related initiatives:** PLG7 backlog, CORE5 event handlers, DOC4 developer guide
> Review log captured in `docs/notes/2025-11-03-authority-plugin-ldap-review.md`. Decisions below reflect consensus from Auth Guild, Security Guild, and DevEx Docs walkthroughs held on 2025-11-03.
## 0. Review Summary (2025-11-03)
- Confirmed plugin charter: deliver offline-friendly LDAP credential verification with deterministic caching and audit parity with the Standard plugin.
- Resolved open questions:
- **Client provisioning audit trail:** plugin always mirrors credential lifecycle metadata (actor, timestamp, hashed secret reference) into Authoritys Mongo store even when LDAP writes succeed; directory writes remain optional and secrets never persist locally.
- **Mutual TLS support:** LDAPS client certificates are required for regulated installations; configuration gains optional client certificate bindings with secret-provider integration and deterministic trust-store selection.
- **Group-to-role mapping:** mappings accept static DN dictionaries and deterministic `regex` matchers; regex captures project to canonical roles via substitution (documented contract for policy automation).
- Follow-up implementation issues filed in `StellaOps.Authority.Plugin.Standard/TASKS.md` (see Section 11) to track scaffolding, mutual TLS enablement, audit mirror, and mapping enhancements.
## 1. Problem Statement
Many on-prem StellaOps deployments rely on existing LDAP/Active Directory domains for workforce identity. The current Standard Mongo-backed plugin requires duplicating users and secrets, which increases operational overhead and violates corporate policy in some regulated environments. We need a sovereign, offline-friendly LDAP plugin that:
@@ -51,6 +62,13 @@ connection:
port: 636
useStartTls: false
validateCertificates: true
clientCertificate:
pfxPath: "file:/etc/stellaops/certs/ldap-client.pfx"
passwordSecret: "file:/etc/stellaops/secrets/ldap-client-pfx.txt"
sendChain: true
trustStore:
mode: "system" # system | bundle
bundlePath: "file:/etc/stellaops/trust/ldap-root.pem"
bindDn: "cn=stellaops-bind,ou=service,dc=example,dc=internal"
bindPasswordSecret: "file:/etc/stellaops/secrets/ldap-bind.txt"
searchBase: "dc=example,dc=internal"
@@ -58,6 +76,7 @@ connection:
userDnFormat: "uid={username},ou=people,dc=example,dc=internal" # optional template
security:
requireTls: true
allowInsecureWithEnvToggle: false # requires STELLAOPS_LDAP_ALLOW_INSECURE=true
allowedCipherSuites: [] # optional allow-list
referralChasing: false
lockout:
@@ -68,6 +87,9 @@ claims:
groupToRoleMap:
"cn=stellaops-admins,ou=groups,dc=example,dc=internal": "operators"
"cn=stellaops-read,ou=groups,dc=example,dc=internal": "auditors"
regexMappings:
- pattern: "^cn=stellaops-(?P<role>[a-z-]+),ou=groups,dc=example,dc=internal$"
roleFormat: "{role}" # yields operators/investigate/etc.
extraAttributes:
displayName: "displayName"
email: "mail"
@@ -75,6 +97,9 @@ clientProvisioning:
enabled: false
containerDn: "ou=service,dc=example,dc=internal"
secretAttribute: "userPassword"
auditMirror:
enabled: true
collectionName: "ldap_client_provisioning"
health:
probeIntervalSeconds: 60
timeoutSeconds: 5
@@ -83,43 +108,47 @@ health:
## 7. Capability Mapping
| Capability | Implementation Notes |
|------------|---------------------|
| `password` | Bind-as-user validation with Authority lockout integration. Mandatory. |
| `clientProvisioning` | Optional; when enabled, creates/updates LDAP entries for machine clients or stores metadata in Mongo if directory writes are disabled. |
| `bootstrap` | Exposed only when bootstrap manifest provides service account credentials AND directory write permissions are confirmed during startup. |
| `password` | Bind-as-user validation with Authority lockout integration. Mandatory. Requires TLS and optionally client certificate binding per regulated install posture. |
| `clientProvisioning` | Optional; when enabled, creates/updates LDAP entries for machine clients **and** mirrors lifecycle metadata into Mongo for audit parity. |
| `bootstrap` | Exposed only when bootstrap manifest provides service account credentials AND directory write permissions are confirmed during startup; always records audit mirror entries. |
| `mfa` | Not supported in MVP. Future iteration may integrate TOTP attributes or external MFA providers. |
## 8. Operational Considerations
- **Offline cache:** provide optional Mongo cache for group membership to keep `/ready` responsive if LDAP is temporarily unreachable. Cache entries must include TTL and invalidation hooks.
- **Secrets management:** accept `file:` and environment variable references; integrate with existing `StellaOps.Configuration` secret providers.
- **Mutual TLS & trust anchors:** support client certificate authentication with deterministic trust-store selection (`system` vs bundled file) to satisfy regulated deployments; surface validation outcomes via health endpoints.
- **Audit mirror:** write deterministic Mongo records capturing provisioning operations (actor, LDAP DN, operation type, hashed secret reference) to align with Authority audit policy even when LDAP is authoritative.
- **Observability:** emit structured logs with event IDs (`LDAP_BIND_START`, `LDAP_BIND_FAILURE`, `LDAP_GROUP_LOOKUP`), counters for success/failure, and latency histograms.
- **Throttling:** reuse Authority rate-limiting middleware; add per-connection throttles to avoid saturating directory servers during brute-force attacks.
## 9. Security & Compliance
- Enforce TLS (`ldaps://` or STARTTLS) by default. Provide explicit `allowInsecure` flag gated behind environment variable for lab/testing only.
- Support optional mutual TLS (client cert authentication) with secret-backed PFX loader and deterministic trust bundle selection.
- Support password hash migration by detecting directory lockout attributes and surfacing `RequiresPasswordReset` when policies demand changes.
- Log distinguished names only at `Debug` level to avoid leaking sensitive structure in default logs.
- Coordinate with Security Guild for penetration testing before GA; incorporate audit log entries for bind attempts and provisioning changes.
## 10. Testing Strategy
- **Unit tests:** mock LDAP connections to validate DN formatting, error mapping, and capability negotiation.
- **Integration tests:** run against an ephemeral OpenLDAP container (seeded via LDIF fixtures) within CI. Include offline cache regression (disconnect LDAP mid-test).
- **Integration tests:** run against an ephemeral OpenLDAP container (seeded via LDIF fixtures) within CI. Include mutual TLS handshake verification (valid/expired certs) and offline cache regression (disconnect LDAP mid-test).
- **Determinism tests:** feed identical LDIF snapshots and configuration to ensure output tokens/claims remain stable across runs.
- **Smoke tests:** `dotnet test` harness plus manual `dotnet run` scenario verifying `/token` password grants and `/internal/users` bootstrap with LDAP-backed store.
- **Smoke tests:** `dotnet test` harness plus manual `dotnet run` scenario verifying `/token` password grants, `/internal/users` bootstrap with LDAP-backed store, and Mongo audit mirror entries.
## 11. Implementation Plan
1. Scaffold `StellaOps.Authority.Plugin.Ldap` project + tests (net10.0, `<IsAuthorityPlugin>` true).
2. Implement configuration options + validation (mirroring Standard plugin guardrails).
3. Build connection factory + credential store with bind logic.
4. Implement claims enricher and optional cache layer.
5. Add client provisioning store (optional) with toggles for read-only deployments.
6. Wire bootstrapper to validate connectivity/permissions and record findings in startup logs.
7. Extend developer guide with LDAP specifics (post-RFC acceptance).
8. Update Docs and TODO trackers; produce release notes entry once merged.
1. Scaffold `StellaOps.Authority.Plugin.Ldap` project + companion test project (net10.0, `<IsAuthorityPlugin>` true).
2. Implement configuration binding/validation, including secret-backed client certificate + trust-store options and `allowInsecureWithEnvToggle`.
3. Build connection factory + credential store with bind logic, TLS enforcement, and deterministic retry policies.
4. Implement claims enricher with regex mapping support and optional Mongo-backed cache layer.
5. Add client provisioning store with LDAP write toggles and Mongo audit mirror (`ldap_client_provisioning` collection).
6. Wire health checks, telemetry, and structured audit events (bind attempts, provisioning, cache fallbacks).
7. Deliver bootstrap validation that inspects directory permissions and logs deterministic capability summary.
8. Extend developer guide and samples with LDAP configuration guidance; include mutual TLS and regex mapping examples.
9. Update docs/TASKS trackers and release notes entry; ensure CI coverage (unit, integration with OpenLDAP, determinism, smoke tests).
## 12. Open Questions
- Should client provisioning default to storing metadata in Mongo even when LDAP writes succeed (to preserve audit history)?
- Do we require LDAPS mutual TLS support (client certificates) for regulated environments? If yes, need to extend configuration schema.
- How will we map LDAP groups to Authority scopes/roles when names differ significantly? Consider supporting regex or mapping scripts.
## 12. Resolved Questions
- **Audit mirror:** Client provisioning always persists lifecycle metadata in Mongo for audit parity; LDAP remains the credential source of truth.
- **Mutual TLS:** Plugin must support optional client certificate authentication with secret-backed key material and deterministic trust-store selection.
- **Group mapping:** Provide deterministic regex mapping support to translate directory DNs into Authority roles/scopes without custom scripts.
## 13. Timeline (Tentative)
- **Week 1:** RFC review & sign-off.
@@ -128,9 +157,9 @@ health:
- **Week 5:** Security review, release candidate packaging.
## 14. Approval
- **Auth Guild Lead:** _TBD_
- **Security Guild Representative:** _TBD_
- **DevEx Docs:** _TBD_
- **Auth Guild Lead:** ✅ Approved 2025-11-03 (see review log).
- **Security Guild Representative:** ✅ Approved 2025-11-03 (see review log).
- **DevEx Docs:** ✅ Approved 2025-11-03 (see review log).
---
Please add comments inline or via PR review. Once approved, track execution under PLG7.

View File

@@ -0,0 +1,95 @@
# Runbook — Replay Operations
> **Audience:** Ops Guild · Evidence Locker Guild · Scanner Guild · Authority/Signer · Attestor
> **Prereqs:** `docs/replay/DETERMINISTIC_REPLAY.md`, `docs/replay/DEVS_GUIDE_REPLAY.md`, `docs/replay/TEST_STRATEGY.md`, `docs/modules/platform/architecture-overview.md` §5
This runbook governs day-to-day replay operations, retention, and incident handling across online and air-gapped environments. Keep it in sync with the tasks in `docs/implplan/SPRINT_187_evidence_cli_replay.md`.
---
## 1 · Terminology
- **Replay Manifest** — `manifest.json` describing scan inputs, outputs, signatures.
- **Input Bundle** — `inputbundle.tar.zst` containing feeds, policies, tools, env.
- **Output Bundle** — `outputbundle.tar.zst` with SBOM, findings, VEX, logs.
- **DSSE Envelope** — Signed metadata produced by Authority/Signer.
- **RootPack** — Trusted key bundle used to validate DSSE signatures offline.
---
## 2 · Normal operations
1. **Ingestion**
- Scanner WebService writes manifest metadata to `replay_runs`.
- Bundles uploaded to CAS (`cas://replay/...`) and mirrored into Evidence Locker (`evidence.replay_bundles`).
- Authority triggers DSSE signing; Attestor optionally anchors to Rekor.
2. **Verification**
- Nightly job runs `stella verify` on the latest N replay manifests per tenant.
- Metrics `replay_verify_total{result}`, `replay_bundle_size_bytes` recorded in Telemetry Stack (see `docs/modules/telemetry/architecture.md`).
- Failures alert `#ops-replay` via PagerDuty with runbook link.
3. **Retention**
- Hot CAS retention: 180days (configurable per tenant). Cron job `replay-retention` prunes expired digests and writes audit entries.
- Cold storage (Evidence Locker): 2years; legal holds extend via `/evidence/holds`. Ensure holds recorded in `timeline.events` with type `replay.hold.created`.
4. **Access control**
- Only service identities with `replay:read` scope may fetch bundles. CLI requires device or client credential flow with DPoP.
---
## 3 · Incident response (Replay Integrity)
| Step | Action | Owner | Notes |
|------|--------|-------|-------|
| 1 | Page Ops via `replay_verify_total{result="failed"}` alert | Observability | Include scan id, tenant, failure codes |
| 2 | Lock affected bundles (`POST /evidence/holds`) | Evidence Locker | Reference incident ticket |
| 3 | Re-run `stella verify` with `--explain` to gather diffs | Scanner Guild | Attach diff JSON to incident |
| 4 | Check Rekor inclusion proofs (`stella verify --ledger`) | Attestor | Flag if ledger mismatch or stale |
| 5 | If tool hash drift → coordinate Signer for rotation | Authority/Signer | Rotate DSSE profile, update RootPack |
| 6 | Update incident timeline (`docs/runbooks/replay_ops.md` -> Incident Log) | Ops Guild | Record timestamps and decisions |
| 7 | Close hold once resolved, publish postmortem | Ops + Docs | Postmortem must reference replay spec sections |
---
## 4 · Air-gapped workflow
1. Receive Offline Kit bundle containing:
- `offline/replay/<scan-id>/manifest.json`
- Bundles + DSSE signatures
- RootPack snapshot
2. Run `stella replay manifest.json --strict --offline` using local CLI.
3. Load feed/policy snapshots from kit; never hit external networks.
4. Store verification logs under `ops/offline/replay/<scan-id>/`.
5. Sync results back to Evidence Locker once connectivity restored.
---
## 5 · Maintenance checklist
- [ ] RootPack rotated quarterly; CLI/Evidence Locker updated with new fingerprints.
- [ ] CAS retention job executed successfully in the past 24hours.
- [ ] Replay verification metrics present in dashboards (x64 + arm64 lanes).
- [ ] Runbook incident log updated (see section 6) for the last drill.
- [ ] Offline kit instructions verified against current CLI version.
---
## 6 · Incident log
| Date (UTC) | Incident ID | Tenant | Summary | Follow-up |
|------------|-------------|--------|---------|-----------|
| _TBD_ | | | | |
---
## 7 · References
- `docs/replay/DETERMINISTIC_REPLAY.md`
- `docs/replay/DEVS_GUIDE_REPLAY.md`
- `docs/replay/TEST_STRATEGY.md`
- `docs/modules/platform/architecture-overview.md` §5
- `docs/modules/evidence-locker/architecture.md`
- `docs/modules/telemetry/architecture.md`
- `docs/implplan/SPRINT_187_evidence_cli_replay.md`
---
*Created: 2025-11-03 — Update alongside replay task status changes.*

View File

@@ -45,8 +45,8 @@ Authority issues short-lived tokens bound to tenants and scopes. Sprint19 int
| `policy:review` | Policy Studio review panes | Review drafts, leave comments, request changes. | Tenant required; pair with `policy:simulate` for diff previews. |
| `policy:approve` | Policy Studio approvals | Approve or reject policy drafts. | Tenant required; fresh-auth enforced by Console UI. |
| `policy:operate` | Policy Studio promotion controls | Trigger batch simulations, promotions, and canary runs. | Tenant required; combine with `policy:run`/`policy:activate`. |
| `policy:publish` | Policy Studio / CLI attestation flows | Publish approved policy versions and generate signing bundles. | Interactive only; tenant required; tokens must include `policy_reason`, `policy_ticket`, and policy digest (fresh-auth enforced). |
| `policy:promote` | Policy Studio / CLI attestation flows | Promote policy attestations between environments (e.g., staging → prod). | Interactive only; tenant required; requires `policy_reason`, `policy_ticket`, digest, and fresh-auth within 5 minutes. |
| `policy:publish` | Policy Studio / CLI attestation flows | Publish approved policy versions and generate signing bundles. | Interactive only; tenant required; tokens must include `policy_reason`, `policy_ticket`, and policy digest (fresh-auth enforced). `stella policy publish --sign` injects the headers. |
| `policy:promote` | Policy Studio / CLI attestation flows | Promote policy attestations between environments (e.g., staging → prod). | Interactive only; tenant required; requires `policy_reason`, `policy_ticket`, digest, and fresh-auth within 5 minutes. CLI: `stella policy promote --environment <env>`. |
| `policy:audit` | Policy audit exports | Access immutable policy history, comments, and signatures. | Tenant required; read-only access. |
| `policy:simulate` | Policy Studio / CLI simulations | Run simulations against tenant inventories. | Tenant required; available to authors, reviewers, operators. |
| `vuln:view` | Vuln Explorer API/UI | Read normalized vulnerability data, issue permalinks. | Tenant required; ABAC attributes (`env`, `owner`, `business_tier`) further constrain access. |
@@ -54,6 +54,7 @@ Authority issues short-lived tokens bound to tenants and scopes. Sprint19 int
| `vuln:operate` | Vuln Explorer state transitions | Change remediation state, accept risk, trigger remediation plans. | Tenant + ABAC attributes required; interactive flows should enforce fresh-auth on prod tenants. |
| `vuln:audit` | Vuln Explorer audit/report exports | Access immutable ledgers, reports, and offline bundles. | Tenant required; ABAC attributes restrict which assets may be exported. |
> **Legacy:** `vuln:read` remains available for backwards compatibility and is still emitted on Vuln Explorer permalinks. New clients should request the granular scopes above.
- Attachment tokens reuse the same scopes: issuance requires `vuln:investigate`, verification honours the callers ABAC attributes, and Authority records `vuln.attachment.token.*` audit events for every issue/verify flow.
| `export.viewer` | Export Center APIs | List export profiles/runs, fetch manifests and bundles. | Tenant required; read-only access. |
| `export.operator` | Export Center APIs | Trigger export runs, manage schedules, request verifications. | Tenant required; pair with `export.admin` for retention/encryption changes. |
| `export.admin` | Export Center administrative APIs | Configure retention policies, encryption keys, and scheduling defaults. | Tenant required; token requests must include `export_reason` + `export_ticket`; Authority audits denials. |

View File

@@ -0,0 +1,5 @@
# 2025-11-03 Vuln Explorer access controls refresh
- Expanded `docs/11_AUTHORITY.md` with attachment signing tokens, ledger verification workflow, and a Vuln Explorer security checklist.
- Added scope guidance for attachment tokens in `docs/security/authority-scopes.md` and updated the Vuln Explorer architecture dossier.
- Refreshed `etc/authority.yaml.sample` comments to highlight ABAC attributes and attachment token verification requirements.

View File

@@ -1,17 +1,63 @@
# Placeholder configuration for the LDAP identity provider plug-in.
# Replace values with your directory settings before enabling the plug-in.
# Example configuration for the LDAP identity provider plug-in.
# Adjust values to match your directory deployment before enabling the plugin.
connection:
host: "ldap.example.com"
host: "ldaps://ldap.example.internal"
port: 636
useTls: true
bindDn: "cn=service,dc=example,dc=com"
bindPassword: "CHANGE_ME"
useStartTls: false
validateCertificates: true
clientCertificate:
pfxPath: "file:/etc/stellaops/certs/ldap-client.pfx"
passwordSecret: "file:/etc/stellaops/secrets/ldap-client-pfx.txt"
sendChain: true
trustStore:
mode: system # system | bundle
bundlePath: "file:/etc/stellaops/trust/ldap-root.pem"
searchBase: "ou=people,dc=example,dc=internal"
usernameAttribute: "uid"
userDnFormat: "uid={username},ou=people,dc=example,dc=internal"
bindDn: "cn=stellaops-bind,ou=service,dc=example,dc=internal"
bindPasswordSecret: "file:/etc/stellaops/secrets/ldap-bind.txt"
security:
requireTls: true
allowInsecureWithEnvToggle: false # set STELLAOPS_LDAP_ALLOW_INSECURE=true to permit TLS downgrade
allowedCipherSuites:
- "TLS_AES_256_GCM_SHA384"
- "TLS_AES_128_GCM_SHA256"
referralChasing: false
lockout:
useAuthorityPolicies: true
directoryLockoutAttribute: "pwdAccountLockedTime"
claims:
groupAttribute: "memberOf"
groupToRoleMap:
"cn=stellaops-admins,ou=groups,dc=example,dc=internal": "operators"
"cn=stellaops-read,ou=groups,dc=example,dc=internal": "auditors"
regexMappings:
- pattern: "^cn=stellaops-(?P<role>[a-z-]+),ou=groups,dc=example,dc=internal$"
roleFormat: "{role}"
extraAttributes:
displayName: "displayName"
email: "mail"
queries:
userFilter: "(uid={username})"
groupFilter: "(member={distinguishedName})"
groupAttribute: "cn"
userFilter: "(&(objectClass=person)(uid={username}))"
attributes:
- "displayName"
- "mail"
- "memberOf"
capabilities:
supportsPassword: true
supportsMfa: false
clientProvisioning:
enabled: false
containerDn: "ou=service,dc=example,dc=internal"
secretAttribute: "userPassword"
auditMirror:
enabled: true
collectionName: "ldap_client_provisioning"
health:
probeIntervalSeconds: 60
timeoutSeconds: 5

View File

@@ -65,6 +65,24 @@ notifications:
scope: "notify.escalate"
requireAdminScope: true
vulnerabilityExplorer:
workflow:
antiForgery:
enabled: true
audience: "stellaops:vuln-workflow"
defaultLifetime: "00:10:00"
maxLifetime: "00:30:00"
maxContextEntries: 16
maxContextValueLength: 256
attachments:
enabled: true
payloadType: "application/vnd.stellaops.vuln-attachment-token+json"
defaultLifetime: "00:30:00"
maxLifetime: "04:00:00"
maxMetadataEntries: 16
maxMetadataValueLength: 512
# Authority signs attachment tokens; Policy/UI must call verify before honouring downloads.
delegation:
quotas:
# Maximum concurrent delegated (service account) tokens per tenant.
@@ -81,6 +99,7 @@ delegation:
authorizedClients:
- "export-center-worker"
attributes:
# Keys map to vulnerability ABAC parameters (vuln_env / vuln_owner / vuln_business_tier).
env: [ "prod", "stage" ]
owner: [ "secops" ]
business_tier: [ "tier-1" ]

View File

@@ -0,0 +1,50 @@
{
"schemaVersion": "notify.rule@1",
"ruleId": "rule-airgap-ops",
"tenantId": "bootstrap",
"name": "Air-gap operations alerts",
"description": "Send time-drift, bundle import, and portable export notifications with remediation steps.",
"enabled": true,
"match": {
"eventKinds": [
"airgap.time.drift",
"airgap.bundle.import",
"airgap.portable.export.completed"
],
"minSeverity": "medium",
"labels": [],
"namespaces": [],
"repositories": [],
"digests": [],
"componentPurls": [],
"verdicts": [],
"kevOnly": false,
"vex": {
"includeAcceptedJustifications": true,
"includeRejectedJustifications": true,
"includeUnknownJustifications": true,
"justificationKinds": []
}
},
"actions": [
{
"actionId": "email-airgap-ops",
"channel": "email:airgap-ops",
"template": "airgap-ops",
"enabled": true,
"metadata": {
"locale": "en-us"
}
}
],
"labels": {
"category": "airgap"
},
"metadata": {
"source": "bootstrap-pack"
},
"createdBy": "bootstrap-pack",
"createdAt": "2025-11-03T08:00:00Z",
"updatedBy": "bootstrap-pack",
"updatedAt": "2025-11-03T08:00:00Z"
}

View File

@@ -0,0 +1,16 @@
{
"schemaVersion": "notify.template@1",
"templateId": "tmpl-airgap-ops-email",
"tenantId": "bootstrap",
"channelType": "email",
"key": "airgap-ops",
"locale": "en-us",
"renderMode": "html",
"format": "email",
"description": "Air-gapped operations alert for time drift, bundle imports, and portable exports.",
"body": "<p><strong>Air-gap status:</strong> {{payload.status}} (severity {{payload.severity}})</p>\n{{#if payload.driftSeconds}}<p>Current drift: {{payload.driftSeconds}} seconds. Remaining budget: {{payload.remainingSeconds}} seconds (anchor issued {{payload.anchorIssuedAt}}).</p>{{/if}}\n{{#if payload.bundleId}}<p><strong>Portable bundle:</strong> <code>{{payload.bundleId}}</code> (profile {{payload.profile}}) exported at {{payload.exportedAt}}.</p>{{/if}}\n{{#if payload.sizeBytes}}<p>Bundle size: {{payload.sizeBytes}} bytes.</p>{{/if}}\n{{#if payload.checksum.sha256}}<p>Checksum (SHA-256): <code>{{payload.checksum.sha256}}</code></p>{{/if}}\n{{#if payload.checksum.sha512}}<p>Checksum (SHA-512): <code>{{payload.checksum.sha512}}</code></p>{{/if}}\n{{#if payload.locations}}<p><strong>Locations</strong></p><ul>{{#each payload.locations}}<li>{{#if path}}File: <code>{{path}}</code>{{/if}}{{#if reference}}OCI: <code>{{reference}}</code>{{/if}}{{#if availableUntil}} (available until {{availableUntil}}){{/if}}</li>{{/each}}</ul>{{/if}}\n{{#if payload.warnings}}<p><strong>Warnings</strong></p><ul>{{#each payload.warnings}}<li>{{message}}</li>{{/each}}</ul>{{/if}}\n<p>{{payload.remediation}}</p>\n{{#if payload.links.docs}}<p>{{link \"Review guidance\" payload.links.docs}}</p>{{/if}}\n{{#if payload.links.manifest}}<p>{{link \"View manifest\" payload.links.manifest}}</p>{{/if}}",
"metadata": {
"author": "bootstrap-pack",
"version": "2025-11-03"
}
}

5
etc/findings-ledger.yaml Normal file
View File

@@ -0,0 +1,5 @@
# Sample configuration for StellaOps Findings Ledger service
findings:
ledger:
database:
connectionString: Host=postgres

51
etc/notify.airgap.yaml Normal file
View File

@@ -0,0 +1,51 @@
# Notify WebService configuration — air-gapped bootstrap profile
#
# This template ships inside the Bootstrap Pack so operators can stage
# deterministic notifier settings without reaching external services. The
# values align with the docker-compose.airgap.yaml profile and the defaults
# produced by the Offline Kit builder. Update the connection string and
# Authority endpoints if your environment uses different hosts.
storage:
driver: mongo
connectionString: "mongodb://stellaops:airgap-password@mongo:27017"
database: "stellaops_notify_airgap"
commandTimeoutSeconds: 45
authority:
enabled: true
issuer: "https://authority.airgap.local"
metadataAddress: "https://authority.airgap.local/.well-known/openid-configuration"
requireHttpsMetadata: true
allowAnonymousFallback: false
backchannelTimeoutSeconds: 30
tokenClockSkewSeconds: 60
audiences:
- notify
viewerScope: notify.viewer
operatorScope: notify.operator
adminScope: notify.admin
api:
basePath: "/api/v1/notify"
internalBasePath: "/internal/notify"
tenantHeader: "X-StellaOps-Tenant"
plugins:
baseDirectory: "/opt/stellaops"
directory: "plugins/notify"
searchPatterns:
- "StellaOps.Notify.Connectors.*.dll"
orderedPlugins:
- StellaOps.Notify.Connectors.Email
- StellaOps.Notify.Connectors.Webhook
telemetry:
enableRequestLogging: true
minimumLogLevel: Information
# In sealed/air-gapped mode, outbound connectors are constrained by the
# shared EgressPolicy facade. Channels that point to loopback services (SMTP
# relay, syslog forwarder, file sink) are permitted; external webhooks are
# denied until the host is unsealed or allow-listed. Review
# docs/modules/notify/bootstrap-pack.md for the full bootstrap workflow.

View File

@@ -0,0 +1,9 @@
# Replace this file with the site-specific client secret for the notify-web
# Authority client when running in sealed / air-gapped environments.
#
# Keep the secret outside version control. When building the Bootstrap Pack or
# Offline Kit, copy the populated file alongside notify.yaml so the container
# can load it via environment injection (for example `env_file` or Kubernetes
# Secret mounts).
NOTIFY_WEB_CLIENT_SECRET=change-me-airgap

View File

@@ -186,6 +186,25 @@ def copy_plugins_and_assets(staging_dir: Path) -> None:
copy_if_exists(REPO_ROOT / "docs" / "ops" / "telemetry-storage.md", docs_dir / "telemetry-storage.md")
def copy_bootstrap_configs(staging_dir: Path) -> None:
notify_config = REPO_ROOT / "etc" / "notify.airgap.yaml"
notify_secret = REPO_ROOT / "etc" / "secrets" / "notify-web-airgap.secret.example"
notify_doc = REPO_ROOT / "docs" / "modules" / "notify" / "bootstrap-pack.md"
if not notify_config.exists():
raise FileNotFoundError(f"Missing notifier air-gap config: {notify_config}")
if not notify_secret.exists():
raise FileNotFoundError(f"Missing notifier air-gap secret template: {notify_secret}")
notify_bootstrap_dir = staging_dir / "bootstrap" / "notify"
notify_bootstrap_dir.mkdir(parents=True, exist_ok=True)
copy_if_exists(REPO_ROOT / "etc" / "bootstrap" / "notify", notify_bootstrap_dir)
copy_if_exists(notify_config, notify_bootstrap_dir / "notify.yaml")
copy_if_exists(notify_secret, notify_bootstrap_dir / "notify-web.secret.example")
copy_if_exists(notify_doc, notify_bootstrap_dir / "README.md")
def package_telemetry_bundle(staging_dir: Path) -> None:
script = TELEMETRY_TOOLS_DIR / "package_offline_bundle.py"
if not script.exists():
@@ -326,6 +345,7 @@ def build_offline_kit(args: argparse.Namespace) -> MutableMapping[str, Any]:
copy_component_artifacts(manifest_data, release_dir, staging_dir)
copy_collections(manifest_data, release_dir, staging_dir)
copy_plugins_and_assets(staging_dir)
copy_bootstrap_configs(staging_dir)
package_telemetry_bundle(staging_dir)
offline_manifest_path, offline_manifest_sha = write_offline_manifest(

View File

@@ -9,7 +9,9 @@ import sys
from collections import OrderedDict
from pathlib import Path
sys.path.append(str(Path(__file__).resolve().parent))
current_dir = Path(__file__).resolve().parent
sys.path.append(str(current_dir))
sys.path.append(str(current_dir.parent / "devops" / "release"))
from build_release import write_manifest # type: ignore import-not-found
@@ -236,6 +238,10 @@ class OfflineKitBuilderTests(unittest.TestCase):
offline_manifest = self.output_dir.parent / "staging" / "manifest" / "offline-manifest.json"
self.assertTrue(offline_manifest.exists())
bootstrap_notify = self.staging_dir / "bootstrap" / "notify"
self.assertTrue((bootstrap_notify / "notify.yaml").exists())
self.assertTrue((bootstrap_notify / "notify-web.secret.example").exists())
with offline_manifest.open("r", encoding="utf-8") as handle:
manifest_data = json.load(handle)
artifacts = manifest_data["artifacts"]
@@ -250,6 +256,8 @@ class OfflineKitBuilderTests(unittest.TestCase):
members = tar.getnames()
self.assertIn("manifest/release.yaml", members)
self.assertTrue(any(name.startswith("sboms/sample-") for name in members))
self.assertIn("bootstrap/notify/notify.yaml", members)
self.assertIn("bootstrap/notify/notify-web.secret.example", members)
if __name__ == "__main__":

View File

@@ -0,0 +1,13 @@
{
"generatedAt": "2025-11-03T21:56:23Z",
"artifacts": [
{
"buildId": "0000000000000000000000000000000000000000",
"platform": "linux/amd64",
"kind": "elf-debug",
"debugPath": "debug/dummy.debug",
"sha256": "eff2b4e47e7a104171a2be80d6d4a5bce2a13dc33f382e90781a531aa926599a",
"size": 26
}
]
}

View File

@@ -0,0 +1 @@
d924d25e7b028105a1c7d16cb1d82955edf103a48571a253b474d8ee30a1b577 debug-manifest.json

View File

@@ -0,0 +1 @@
portable-debug-placeholder

19
out/release/release.json Normal file
View File

@@ -0,0 +1,19 @@
{
"version": "2025.11.03-test",
"channel": "airgap",
"releaseDate": "2025-11-03",
"gitSha": "0000000000000000000000000000000000000000",
"components": [],
"charts": [],
"compose": [],
"debugStore": {
"manifest": "debug/debug-manifest.json",
"sha256": "d924d25e7b028105a1c7d16cb1d82955edf103a48571a253b474d8ee30a1b577",
"size": 340,
"generatedAt": "2025-11-03T21:56:23Z",
"artifactCount": 1
},
"checksums": {
"sha256": "72473433eb9cee20e848dd52212d10a2295158359d47c35b823d28de09858f59"
}
}

View File

@@ -0,0 +1 @@
3ee54a8f242b4a52a253e3badb4bf44d6e6ccc54c1c9028268860b8ea6628e3c release.json

18
out/release/release.yaml Normal file
View File

@@ -0,0 +1,18 @@
version: "2025.11.03-test"
channel: airgap
releaseDate: "2025-11-03"
gitSha: 0000000000000000000000000000000000000000
components:
[]
charts:
[]
compose:
[]
debugStore:
manifest: "debug/debug-manifest.json"
sha256: d924d25e7b028105a1c7d16cb1d82955edf103a48571a253b474d8ee30a1b577
size: 340
generatedAt: "2025-11-03T21:56:23Z"
artifactCount: 1
checksums:
sha256: 72473433eb9cee20e848dd52212d10a2295158359d47c35b823d28de09858f59

View File

@@ -0,0 +1 @@
985892ffd6cbebb6278fdaed346711073c533c7e26d4076f1c7f6273fe0678fa release.yaml

Binary file not shown.

View File

@@ -0,0 +1 @@
49d3ac3502bad1caaed4c1f7bceaa4ce40fdfce6210d4ae20c90386aeb84ca4e telemetry-offline-bundle.tar.gz

View File

@@ -0,0 +1,17 @@
{
"policy_simulation_queue_depth": {
"total": 3,
"by_status": {
"pending": 2,
"dispatching": 1
}
},
"policy_simulation_latency": {
"samples": 2,
"p50_seconds": 1.5,
"p90_seconds": 2.5,
"p95_seconds": 3.5,
"p99_seconds": 4.0,
"mean_seconds": 2.0
}
}

View File

@@ -0,0 +1,29 @@
{
"simulation": {
"schemaVersion": "scheduler.policy-run-status@1",
"runId": "run:P-7:20251103T153000Z:e4d1a9b2",
"tenantId": "tenant-alpha",
"policyId": "P-7",
"policyVersion": 4,
"mode": "simulate",
"status": "queued",
"priority": "normal",
"queuedAt": "2025-11-03T15:30:00Z",
"stats": {
"components": 0,
"rulesFired": 0,
"findingsWritten": 0,
"vexOverrides": 0
},
"inputs": {
"sbomSet": [
"sbom:S-318",
"sbom:S-42"
],
"captureExplain": true
},
"metadata": {
"source": "console.review"
}
}
}

View File

@@ -0,0 +1,32 @@
{
"tenantId": "tenant-alpha",
"simulation": {
"runId": "run:policy-risk:20251103T195901Z:deadbeef",
"tenantId": "tenant-alpha",
"policyId": "policy-risk",
"policyVersion": 7,
"mode": "simulate",
"status": "succeeded",
"priority": "normal",
"queuedAt": "2025-11-03T19:59:01Z",
"startedAt": "2025-11-03T19:59:05Z",
"finishedAt": "2025-11-03T19:59:16Z",
"attempts": 1,
"inputs": {
"sbomSet": [
"sbom://sha256-alpha",
"sbom://sha256-bravo"
],
"captureExplain": true
},
"metadata": {
"requestedby": "console-user",
"correlation-id": "policy-sim-4242"
},
"cancellationRequested": false,
"schemaVersion": "1.0.0"
},
"result": "succeeded",
"observedAt": "2025-11-03T19:59:16Z",
"latencySeconds": 15.0
}

Binary file not shown.

View File

@@ -0,0 +1,75 @@
#!/usr/bin/env python3
"""Download KISA/KNVD advisory HTML pages for offline analysis."""
from __future__ import annotations
import argparse
import datetime as dt
import sys
import xml.etree.ElementTree as ET
from pathlib import Path
from urllib.error import HTTPError, URLError
from urllib.parse import parse_qs, urlsplit
from urllib.request import Request, urlopen
FEED_URL = "https://knvd.krcert.or.kr/rss/securityInfo.do"
USER_AGENT = "Mozilla/5.0 (compatible; StellaOpsOffline/1.0)"
def fetch(url: str) -> bytes:
req = Request(url, headers={"User-Agent": USER_AGENT})
with urlopen(req, timeout=15) as resp:
return resp.read()
def iter_idxs(feed_xml: bytes) -> list[tuple[str, str]]:
root = ET.fromstring(feed_xml)
items = []
for item in root.findall(".//item"):
title = (item.findtext("title") or "").strip()
link = item.findtext("link") or ""
idx = parse_qs(urlsplit(link).query).get("IDX", [None])[0]
if idx:
items.append((idx, title))
return items
def capture(idx: str, title: str, out_dir: Path) -> Path:
url = f"https://knvd.krcert.or.kr/detailDos.do?IDX={idx}"
html = fetch(url)
target = out_dir / f"{idx}.html"
target.write_bytes(html)
print(f"saved {target} ({title})")
return target
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--out", type=Path, default=Path("seed-data/kisa/html"))
parser.add_argument("--limit", type=int, default=10, help="Maximum advisories to download")
args = parser.parse_args()
args.out.mkdir(parents=True, exist_ok=True)
print(f"[{dt.datetime.utcnow():%Y-%m-%d %H:%M:%S}Z] fetching RSS feed…")
try:
feed = fetch(FEED_URL)
except (URLError, HTTPError) as exc:
print("RSS fetch failed:", exc, file=sys.stderr)
return 1
items = iter_idxs(feed)[: args.limit]
if not items:
print("No advisories found in feed", file=sys.stderr)
return 1
for idx, title in items:
try:
capture(idx, title, args.out)
except (URLError, HTTPError) as exc:
print(f"failed {idx}: {exc}", file=sys.stderr)
return 0
if __name__ == "__main__":
raise SystemExit(main())

View File

@@ -0,0 +1,19 @@
{
"currentEventId": "3ac1f4ef-3c26-4b0d-91d4-6a6d3a5bde10",
"cycleHash": "1a61c14efc1aceaed7d2574d2054475b2683a3bfc81103585070ef560b15bd02",
"explainRef": "explain://tenant-a/findings/3ac1f4ef",
"findingId": "artifact:sha256:3f1e2d9c7b1a0f6534d1b6f998d7a5c3ef9e0ab92f4c1d2e3f5a6b7c8d9e0f1a|pkg:cpe:/o:vendor:product",
"labels": {
"kev": true,
"runtime": "exposed"
},
"policyVersion": "sha256:5f38c7887d4a4bb887ce89c393c7a2e23e6e708fda310f9f3ff2a2a0b4dffbdf",
"severity": 6.7,
"status": "triaged",
"tenantId": "tenant-a",
"updatedAt": "2025-11-03T15:12:05.456Z",
"policyRationale": [
"explain://tenant-a/findings/3ac1f4ef",
"policy://tenant-a/policy-v1/rationale/accepted"
]
}

View File

@@ -0,0 +1,42 @@
{
"event": {
"actor": {
"id": "user:alice@tenant",
"type": "operator"
},
"artifactId": "sha256:3f1e2d9c7b1a0f6534d1b6f998d7a5c3ef9e0ab92f4c1d2e3f5a6b7c8d9e0f1a",
"chainId": "5fa2b970-9da2-4ef4-9a63-463c5d98d3cc",
"eventHash": "05332adf4298733a243968c40c7aeb4215dae48c52af9a5316374eacc9b30d45",
"finding": {
"artifactId": "sha256:3f1e2d9c7b1a0f6534d1b6f998d7a5c3ef9e0ab92f4c1d2e3f5a6b7c8d9e0f1a",
"id": "artifact:sha256:3f1e2d9c7b1a0f6534d1b6f998d7a5c3ef9e0ab92f4c1d2e3f5a6b7c8d9e0f1a|pkg:cpe:/o:vendor:product",
"vulnId": "CVE-2025-1234"
},
"id": "3ac1f4ef-3c26-4b0d-91d4-6a6d3a5bde10",
"occurredAt": "2025-11-03T15:12:05.123Z",
"payload": {
"justification": "Ticket SEC-1234 created",
"previousStatus": "affected",
"status": "triaged",
"ticket": {
"id": "SEC-1234",
"url": "https://tracker.example/sec-1234"
},
"rationaleRefs": [
"explain://tenant-a/findings/3ac1f4ef"
]
},
"policyVersion": "sha256:5f38c7887d4a4bb887ce89c393c7a2e23e6e708fda310f9f3ff2a2a0b4dffbdf",
"previousHash": "0000000000000000000000000000000000000000000000000000000000000000",
"recordedAt": "2025-11-03T15:12:06.001Z",
"sequence": 42,
"sourceRunId": "8f89a703-94cd-4e9d-8a75-2f407c4bee7f",
"tenant": "tenant-a",
"type": "finding.status_changed"
},
"hashes": {
"eventHash": "05332adf4298733a243968c40c7aeb4215dae48c52af9a5316374eacc9b30d45",
"merkleLeafHash": "a2ad094e2e2064a29de8b93710d97645401d7690e920e866eef231790c5200be",
"previousHash": "0000000000000000000000000000000000000000000000000000000000000000"
}
}

34
seed-data/kisa/README.md Normal file
View File

@@ -0,0 +1,34 @@
# KISA Offline Detail Capture (2025-11-03)
This directory contains HTML snapshots of the KISA/KNVD advisory detail pages (`detailDos.do?IDX=...`).
## Capture notes
- Captured: 2025-11-03T22:53:00Z from `https://knvd.krcert.or.kr/rss/securityInfo.do`.
- Detail API `rssDetailData.do` now returns an HTML error page; the SPA embeds the full advisory content in `detailDos.do`.
- Each file under `html/` corresponds to the RSS item `IDX` and preserves the original Korean content and table layout.
- User agent: `Mozilla/5.0 (compatible; StellaOpsOffline/1.0)`.
- No authentication was required; cookies set during the HTML fetch are not needed for static page capture.
## Regeneration
```bash
python scripts/kisa_capture_html.py --out seed-data/kisa/html
```
(See `scripts/kisa_capture_html.py` for exact implementation; it parses the RSS feed, walks each `IDX`, and writes `IDX.html` alongside a sha256 manifest.)
## sha256 manifest
| IDX | sha256 |
| --- | --- |
| 5859 | 8a31a530b3e4d4ce356fc18d561028a41320b27ed398abdb8e7ec2b0b5c693fe |
| 5860 | 74013ef35a76cd0c44c2e17cac9ecf51095e64fd7f9a9436460d0e0b10526af3 |
| 5861 | 1d95c34b76dc9d5be5cbc0b8fdc9d423dd5cc77cb0fc214534887dc444ef9a45 |
| 5862 | 93ae557286b4ee80ae26486c13555e1fda068dcc13d440540757a7d53166457e |
| 5863 | ee3c81915e99065021b8bb1a601144e99af196140d92859049cea1c308547859 |
| 5864 | 6f84dc5f1bb4998d9af123f7ddc8912b47cdc1acf816d41ff0e1ad281d31fa2f |
| 5865 | d5e60ea3a80307f797721a988bed609c99587850e59bc125d287c8e8db85b0ec |
| 5866 | a6f332315324fb268adad214bba170e81c56db6afdb316bafdd18fb9defbe721 |
| 5867 | 4245dbf6c03a27d6bdf1d7b2651e9e7a05ad1bc027c2f928edb3bf3e58a62b20 |
| 5868 | 316c1476589a51e57914186373bfd0394e3d0a8ae64a2c9c16a1d8bdfe941fa9 |

View File

@@ -0,0 +1,35 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using StellaOps.AdvisoryAI.Orchestration;
namespace StellaOps.AdvisoryAI.WebService.Contracts;
public sealed class AdvisoryExecuteRequest
{
[Required]
[MinLength(1)]
public string AdvisoryKey { get; set; } = string.Empty;
public string? ArtifactId { get; set; }
public string? ArtifactPurl { get; set; }
public string? PolicyVersion { get; set; }
public string Profile { get; set; } = "default";
public IReadOnlyCollection<string>? PreferredSections { get; set; }
public bool ForceRefresh { get; set; }
public AdvisoryTaskRequest ToTaskRequest(AdvisoryTaskType taskType)
=> new(
taskType,
AdvisoryKey,
ArtifactId,
ArtifactPurl,
PolicyVersion,
Profile,
PreferredSections,
ForceRefresh);
}

View File

@@ -0,0 +1,27 @@
using System.Collections.Generic;
using StellaOps.AdvisoryAI.Guardrails;
using StellaOps.AdvisoryAI.Orchestration;
namespace StellaOps.AdvisoryAI.WebService.Contracts;
public sealed record AdvisoryOutputResponse(
string CacheKey,
AdvisoryTaskType TaskType,
string Profile,
string OutputHash,
bool GuardrailBlocked,
IReadOnlyCollection<AdvisoryGuardrailViolationResponse> GuardrailViolations,
IReadOnlyDictionary<string, string> GuardrailMetadata,
string Prompt,
IReadOnlyCollection<AdvisoryCitationResponse> Citations,
IReadOnlyDictionary<string, string> Metadata,
DateTimeOffset GeneratedAtUtc,
bool PlanFromCache);
public sealed record AdvisoryGuardrailViolationResponse(string Code, string Message)
{
public static AdvisoryGuardrailViolationResponse From(AdvisoryGuardrailViolation violation)
=> new(violation.Code, violation.Message);
}
public sealed record AdvisoryCitationResponse(int Index, string DocumentId, string ChunkId);

View File

@@ -0,0 +1,38 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using StellaOps.AdvisoryAI.Orchestration;
namespace StellaOps.AdvisoryAI.WebService.Contracts;
public sealed class AdvisoryPlanRequest
{
[Required]
public AdvisoryTaskType TaskType { get; set; }
[Required]
[MinLength(1)]
public string AdvisoryKey { get; set; } = string.Empty;
public string? ArtifactId { get; set; }
public string? ArtifactPurl { get; set; }
public string? PolicyVersion { get; set; }
public string Profile { get; set; } = "default";
public IReadOnlyCollection<string>? PreferredSections { get; set; }
public bool ForceRefresh { get; set; }
public AdvisoryTaskRequest ToTaskRequest()
=> new(
TaskType,
AdvisoryKey,
ArtifactId,
ArtifactPurl,
PolicyVersion,
Profile,
PreferredSections,
ForceRefresh);
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using StellaOps.AdvisoryAI.Orchestration;
namespace StellaOps.AdvisoryAI.WebService.Contracts;
public sealed record AdvisoryPlanResponse(
string CacheKey,
AdvisoryTaskType TaskType,
string AdvisoryKey,
string Profile,
int StructuredChunkCount,
int VectorMatchCount,
bool IncludesSbom,
IReadOnlyDictionary<string, string> Metadata,
DateTimeOffset CreatedAtUtc);

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