work
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled

This commit is contained in:
StellaOps Bot
2025-11-25 08:01:23 +02:00
parent d92973d6fd
commit 6bee1fdcf5
207 changed files with 12816 additions and 2295 deletions

View File

@@ -8,6 +8,11 @@ Advisory AI is the retrieval-augmented assistant that synthesizes advisory and V
- Propose remediation hints aligned with Offline Kit staging and export bundles.
- Expose API/UI surfaces with guardrails on model prompts, outputs, and retention.
## Contributor quickstart
- Read `docs/modules/advisory-ai/AGENTS.md` before making changes; it lists required docs, determinism/offline rules, and working directory scope.
- Keep outputs aggregation-only with stable ordering and UTC timestamps; tests must cover guardrails, tenant safety, and provenance.
- When updating contracts/telemetry, sync the relevant docs here and cross-link from sprint Decisions & Risks.
## Key components
- RAG pipeline drawing from Conseiller, Excititor, VEX Lens, Policy Engine, and SBOM Service data.
- Prompt templates and guard models enforcing provenance and redaction policies.
@@ -26,6 +31,13 @@ Advisory AI is the retrieval-augmented assistant that synthesizes advisory and V
- Redaction policies validated against security/LLM guardrail tests.
- Guardrail behaviour, blocked phrases, and operational alerts are detailed in `/docs/security/assistant-guardrails.md`.
## Outputs & artefacts
- **Run/plan records (deterministic):** persisted under `/app/data/{queue,plans,outputs}` (or `ADVISORYAI__STORAGE__*` overrides) with ISO timestamps, provenance hashes, and stable ordering for replay.
- **Service surfaces (airgap friendly):** `/ops/advisory-ai/runs` streams NDJSON status; `/ops/advisory-ai/runs/{id}` returns the immutable run/plan bundle with guardrail decisions.
- **Events:** worker emits `advisory_ai_run_completed` with digests (plan, output, guardrail) for downstream consumers; feature-flagged to keep offline deployments silent.
- **Offline bundle:** `advisory-ai-bundle.tgz` packages prompts, sanitized inputs, outputs, guardrail audit trail, and signatures; build via `docs/modules/advisory-ai/deployment.md` recipes to keep artefacts deterministic across air-gapped imports.
- **Observability:** metrics/logs share the `advisory_ai` meter/logger namespace (latency, guardrail blocks/validations, citation coverage). Dashboards and alerts must reference these canonical names to avoid drift.
## Deployment & configuration
- **Containers:** `advisory-ai-web` fronts the API/cache while `advisory-ai-worker` drains the queue and executes prompts. Both containers mount a shared RWX volume providing `/app/data/{queue,plans,outputs}` (defaults; configurable via `ADVISORYAI__STORAGE__*`).
- **Remote inference toggle:** Set `ADVISORYAI__INFERENCE__MODE=Remote` to send sanitized prompts to an external inference tier. Provide `ADVISORYAI__INFERENCE__REMOTE__BASEADDRESS` (and optional `...__APIKEY`, `...__TIMEOUT`) to complete the circuit; failures fall back to the sanitized prompt and surface `inference.fallback_*` metadata.

View File

@@ -0,0 +1,8 @@
# Advisory AI · Tasks
| Task ID | Description | Owner(s) | Sprint | Status | Notes |
| --- | --- | --- | --- | --- | --- |
| ADVISORY-AI-DOCS-0001 | Align module docs with `AGENTS.md` guardrails and required reading. | Docs Guild | SPRINT_312_docs_modules_advisory_ai | DONE (2025-11-24) | AGENTS/README now call out offline/determinism guardrails and required docs. |
| ADVISORY-AI-ENG-0001 | Sync module doc pointers into parent docs tree. | Module Team | SPRINT_312_docs_modules_advisory_ai | DONE (2025-11-24) | Root docs/README now links to Advisory AI dossier. |
| ADVISORY-AI-OPS-0001 | Document Advisory AI outputs/artefacts in module README. | Ops Guild | SPRINT_312_docs_modules_advisory_ai | DONE (2025-11-24) | README section expanded with concrete outputs/endpoints/bundles/events. |

View File

@@ -0,0 +1,19 @@
# Attestation Plan 2001 · Evidence Locker contract handoff (2025-11-24)
Owners: Evidence Locker Guild · Excititor Guild
Status: Published (unblocks ATTEST-PLAN-2001)
## Inputs
- Sealed bundle contract: `docs/modules/evidence-locker/prep/2025-11-24-evidence-locker-contract.md`
- Bundle schema: `docs/modules/evidence-locker/schemas/bundle.schema.json`
- Sample bundle + hash: `docs/modules/evidence-locker/samples/evidence-bundle-sample.tgz` (+ `.sha256`)
## Plan
1) Align attestation payloads with sealed bundle contract (subjects, DSSE layout, manifest fields).
2) Produce CLI/Export Center consumer notes: expected file layout, required hashes, validation steps.
3) Add verification harness reference for Excititor/Attestor (reuse sample bundle + DSSE public key from contract note).
4) Update downstream sprints (Excititor airgap/export, Export Center) with contract link and hash.
## Next actions
- Evidence Locker Guild: confirm final schema hash matches sample bundle (track in contract note).
- Excititor Guild: wire contract path into airgap/attestation tests; report readiness in respective sprints.

View File

@@ -0,0 +1,25 @@
# stella advisory — Command Guide
## Commands
- `stella advisory list --source <provider> [--status <status>] [--output json|ndjson|table] [--offline]`
- `stella advisory get --id <advisoryId> [--output json|table] [--offline]`
- `stella advisory export --bundle <path> [--offline]`
## Flags (common)
- `--offline`: pull from cached advisory snapshots/mirror bundles only; exit code 5 if remote needed.
- `--source`: provider filter (msrc, nvd, osv, csaf, etc.).
- `--status`: affected, fixed, not_affected, withdrawn, disputed.
- `--output`: json (default), ndjson, table.
## Inputs/outputs
- Inputs: Concelier/Excititor advisory projections; cached mirror bundles when offline.
- Outputs: raw evidence with provenance (`observationId`, `linksetId`, signatures); no merging/inference.
- Exit codes per `output-and-exit-codes.md`; not found → 4, offline violation → 5.
## Determinism rules
- Sorted by advisory key; withdrawn/duplicate handling matches upstream evidence; no severity inference.
- Timestamps UTC; hashes lowercase hex.
## Offline/air-gap notes
- Mirror bundles must be preloaded for offline use; CLI verifies signatures against trust roots.
- Export uses local evidence only; produces deterministic bundle with manifest + checksums.

View File

@@ -0,0 +1,21 @@
# stella aoc — Command Guide
## Commands
- `stella aoc verify --input <evidence> [--policy <path>] [--offline]`
- `stella aoc explain --input <evidence> [--output json|table]`
## Flags (common)
- `--offline`: verify evidence without remote calls; exit code 5 if network would be required.
- `--policy`: optional AOC policy file; defaults to platform policy.
- `--output`: json (default), table.
## Inputs/outputs
- Inputs: AOC evidence bundle; optional policy file.
- Outputs: verification results with rationale; aggregation-only.
- Exit codes per `output-and-exit-codes.md`; 3 for auth failures, 4 for missing evidence, 5 for offline violation.
## Determinism rules
- Stable ordering of findings; timestamps UTC; hashes lowercase hex.
## Offline/air-gap notes
- Trust roots loaded locally; no remote downloads allowed in offline mode.

View File

@@ -0,0 +1,19 @@
# stella auth — Command Guide
## Commands
- `stella auth login --token <token> [--url <baseUrl>]`
- `stella auth status`
- `stella auth logout`
## Flags
- `--url`: API base URL; defaults to config/env.
- `--token`: bearer token or OIDC device code (future); stored in config if allowed.
## Behaviour
- Login writes token to config file or keyring (where supported) with deterministic permissions; never echoes secrets.
- Status prints current user/tenant scopes if available; uses exit code 3 when unauthenticated.
- Logout removes stored token and cached session data.
## Offline/air-gap notes
- Login requires network; if `--offline` is set, command must fail with exit code 5.
- Status/logout work offline using cached credentials only.

View File

@@ -0,0 +1,25 @@
# stella export — Command Guide
## Commands
- `stella export mirror --bundle <path> --profile <name> [--offline]`
- `stella export verify --bundle <path> --trust-roots <file>`
- `stella export plan --output json` (preview bundle contents)
## Flags (common)
- `--offline`: enforce no network; fail with exit code 5 if registry/object-store calls would occur.
- `--profile`: named export profile (schema/manifest version); defaults to latest supported.
- `--trust-roots`: PEM/TUF/DSSE trust roots for verification.
- `--output`: json (default) or table for plan outputs.
## Inputs/outputs
- Inputs: export profiles, mirror configuration, optional cached artefacts.
- Outputs: deterministic bundle tarball + manifest (checksums, signatures, metadata); verify emits status + detailed reasons.
- Exit codes follow `output-and-exit-codes.md`; verification failure uses exit code 3.
## Determinism rules
- Manifest ordering is stable; checksums hex-lowercase; timestamps UTC.
- No network-dependent mutation; offline bundles must be reproducible.
## Offline/air-gap notes
- `--offline` must be honored; registry pulls are forbidden unless cached in profile path.
- Verification uses only local trust roots; no remote key fetch.

View File

@@ -0,0 +1,24 @@
# stella notify — Command Guide
## Commands
- `stella notify send --channel <email|chat|webhook> --template <id> --data <file>`
- `stella notify list --status <pending|sent|failed> [--output json|table] [--offline]`
- `stella notify get --id <messageId> [--offline]`
## Flags (common)
- `--offline`: only allowed when notification queue snapshots are cached; otherwise exit code 5.
- `--tenant`: scope to tenant; enforced by server RLS.
- `--output`: json/ndjson/table.
## Inputs/outputs
- Inputs: Notify API; optional cached queue snapshots when offline.
- Outputs: message metadata, status, delivery results; no template content leaks.
- Exit codes follow `output-and-exit-codes.md`; 4 for not found, 5 for offline violation.
## Determinism rules
- Listings sorted by created time then id; timestamps UTC.
- No retries triggered by the CLI; it only submits/reads.
## Offline/air-gap notes
- Sending in offline mode is disallowed (exit code 5); only listing cached snapshots is permitted.
- Templates must be preloaded; no remote fetches when `--offline`.

View File

@@ -0,0 +1,23 @@
# stella orchestrator — Command Guide
## Commands
- `stella orchestrator jobs list --output json|table [--offline]`
- `stella orchestrator jobs get --id <jobId> [--offline]`
- `stella orchestrator runs get --id <runId> [--offline]`
## Flags (common)
- `--offline`: only allowed when cached ledger snapshots are available; otherwise exit code 5.
- `--status`, `--type`: filters for job listings; deterministic sort by created time then id.
- `--output`: json/ndjson/table.
## Inputs/outputs
- Inputs: Orchestrator API or cached run ledger snapshots.
- Outputs: job/run metadata with provenance hashes and DSSE/attestation pointers when available.
- Exit codes per `output-and-exit-codes.md`; 4 for not found, 5 for offline violation.
## Determinism rules
- Sorted outputs; timestamps UTC; hashes hex lowercase.
- No inferred state beyond orchestrator responses.
## Offline/air-gap notes
- Ledger snapshots must be preloaded; no live scheduler calls when `--offline`.

View File

@@ -0,0 +1,25 @@
# stella policy — Command Guide
## Commands
- `stella policy eval --input <bundle> --subject <sbom|vex|vuln> [--offline] [--output json|ndjson|table]`
- `stella policy simulate --from <bundleA> --to <bundleB> [--budget <ms>] [--offline]`
- `stella policy publish --input <bundle> --sign --attest`
## Flags (common)
- `--offline` / `STELLA_OFFLINE=1`: forbid network calls; use cached bundles only.
- `--tenant <id>`: scope evaluation to tenant; RLS enforcement required on the server.
- `--rationale`: include rationale IDs in responses.
- `--output`: `json` (default), `ndjson`, or `table`.
## Inputs/outputs
- Inputs: policy bundles (signed), subject artifacts (SBOM/VEX/Vuln snapshots).
- Outputs: deterministic JSON/NDJSON or tables; includes `correlationId`, `policyVersion`, `rationaleIds` when requested.
- Exit codes follow `output-and-exit-codes.md`.
## Determinism rules
- Sort evaluation results by subject key; timestamps UTC ISO-8601.
- No inferred verdicts beyond Policy Engine response.
## Offline/air-gap notes
- When `--offline`, evaluation must use locally cached bundles and subject artifacts; fail with exit code 5 if network would be needed.
- Trust roots loaded from `STELLA_TRUST_ROOTS` when verifying signed bundles.

View File

@@ -0,0 +1,25 @@
# stella sbom — Command Guide
## Commands
- `stella sbom generate --image <ref> [--output sbom.spdx.json] [--offline]`
- `stella sbom compose --fragment <path> --output composition.json --offline`
- `stella sbom verify --file <sbom> --signature <sig> --key <keyfile>`
## Flags (common)
- `--offline`: no network pulls; use local cache/OCI archive.
- `--format`: `spdx-json` (default) or `cyclonedx-json`.
- `--attest`: emit DSSE attestation alongside SBOM.
- `--hash`: include layer/file hashes (deterministic ordering).
## Inputs/outputs
- Inputs: container image, directory, or fragments.
- Outputs: deterministic SPDX/CycloneDX JSON, optional DSSE + checksums.
- Exit codes per `output-and-exit-codes.md`; verification failure uses exit code 3 or 4 depending on cause.
## Determinism rules
- Stable ordering of packages/files; timestamps UTC.
- Hashes hex-lowercase; no host-specific paths.
## Offline/air-gap notes
- With `--offline`, image sources must already be cached (tar/OCI archive); command fails with exit code 5 if it would fetch remotely.
- Verification uses local trust roots; no remote key fetch.

View File

@@ -0,0 +1,23 @@
# stella vex — Command Guide
## Commands
- `stella vex consensus --query <filter> [--output json|ndjson|table] [--offline]`
- `stella vex get --id <consensusId> [--offline]`
- `stella vex simulate --input <vexDocs> --policy <policyConfig> [--offline]`
## Flags (common)
- `--offline`: use cached consensus snapshots; fail with exit code 5 if remote would be hit.
- `--policy <path>`: apply trust/weighting config; aggregation-only outputs.
- `--page-size`, `--page-token`: deterministic pagination.
## Inputs/outputs
- Inputs: VEX consensus projection (VexLens); optional cached snapshots when offline.
- Outputs: consensus states with `consensus_state`, `confidence`, `weights`, `issuers`, `rationale`; stable ordering.
## Determinism rules
- Sort by `consensusId`; pagination tokens deterministic.
- No verdict inference beyond upstream consensus projection; CLI stays aggregation-only.
## Offline/air-gap notes
- Cached snapshots are required when `--offline`; otherwise exit code 5 with remediation message.
- Trust roots for signature verification are loaded from `STELLA_TRUST_ROOTS` when verifying cached snapshots.

View File

@@ -0,0 +1,25 @@
# stella vuln — Command Guide
## Commands
- `stella vuln list --query <filter> [--group-by <field>] [--output json|ndjson|table] [--offline]`
- `stella vuln get --id <vulnId> [--output json|table] [--offline]`
- `stella vuln simulate --from <policyA> --to <policyB> --subjects <path> [--offline]`
## Flags (common)
- `--offline`: read from cached snapshots; fail with exit code 5 if network would be used.
- `--policy <id>`: scope queries to a policy projection.
- `--page-size`, `--page-token`: deterministic pagination.
- `--group-by`: `cve`, `package`, `status`, `advisory` (results stay stably ordered within groups).
## Inputs/outputs
- Inputs: Vuln Explorer API; optional cached snapshots when offline.
- Outputs: sorted lists or detail documents with provenance pointers (`advisoryId`, `evidenceIds`, `consensusId`).
- Exit codes follow `output-and-exit-codes.md`; 4 for not found, 5 for offline violation.
## Determinism rules
- Lists sorted by primary key then timestamp; group-by keeps stable ordering inside each bucket.
- Timestamps UTC ISO-8601; hashes lower-case hex.
## Offline/air-gap notes
- Use cached snapshots (`--offline`) when remote Explorer is unavailable; commands must not attempt network calls in this mode.
- Simulation must read local policy snapshots and subjects when offline.

View File

@@ -0,0 +1,40 @@
# stella CLI — Configuration
## Precedence (highest → lowest)
1. Command-line flags (e.g., `--output json`, `--offline`)
2. Environment variables
3. Config file (`config.yaml`/`config.json`) loaded from the first existing path:
- `$STELLA_CONFIG` (explicit override)
- `$XDG_CONFIG_HOME/stella/config.yaml` (or `%APPDATA%\\Stella\\config.yaml` on Windows)
- `$HOME/.config/stella/config.yaml`
Tip: keep secrets in env vars, not in the config file; tokens are read from `STELLA_TOKEN`, registry creds from `STELLA_REGISTRY_AUTH`, etc.
## Common settings (YAML example)
```yaml
output: json # json|ndjson|table
offline: true # force no-network mode
api:
baseUrl: https://console.stella.local
token: ${STELLA_TOKEN} # prefer env substitution
policy:
tenant: demo-tenant
rationale: true
airgap:
bundlesPath: /var/stella/bundles
trustRoots: /var/stella/trust/roots.pem
observability:
traceparent: auto # always inject trace headers when available
```
## Air-gap/offline knobs
- `--offline` or `STELLA_OFFLINE=1` forbids network calls; commands must rely on local bundles/caches.
- `airgap.bundlesPath` controls where imports/exports read/write sealed bundles.
- Mirror/import/export commands respect `STELLA_TRUST_ROOTS` for DSSE/TUF verification.
## Logging & telemetry
- `STELLA_LOG_LEVEL=debug` for verbose logs; `trace` adds wire dumps (still deterministic).
- Tracing headers: CLI injects `traceparent` when provided by the environment (CI runners, gateways); never emits PII.
## Profiles (planned)
- Profiles will live under `profiles/<name>.yaml` and can be selected with `--profile <name>`; until shipped, stick to the single default config file.

View File

@@ -0,0 +1,32 @@
# stella CLI — Forensics Guide
## Commands
- `stella forensic snapshot create --case <id> --output <path>`: capture current evidence snapshot; emits manifest + checksums.
- `stella forensic verify --bundle <path>`: validate checksums, DSSE signatures, and timeline chain-of-custody.
- `stella attest verify --file <attestation>`: reuse attestor flows for envelope verification (see `guides/commands/attest.md`).
## Flags
- `--offline`: prohibit network access; use local bundles only (exit code 5 if remote call would occur).
- `--output json|table` (default json) for verification results.
- `--trust-roots <file>`: PEM/TUF/DSSE trust roots for verification.
## Outputs & exit codes
- Success → 0; verification failure → 3; missing bundle → 4; offline violation → 5.
- Verification output includes `status`, `checksum`, `signature`, `subject`, `rationale` fields; ordering is deterministic.
## Determinism rules
- Snapshots record UTC timestamps and stable file ordering; hashes are lowercase hex.
- CLI never mutates evidence; it only validates and reports.
## Offline/air-gap notes
- Always supply trust roots from sealed media when in air-gap mode; no remote key fetch is allowed.
- Store snapshots under a deterministic path (`case-id/date/`) to simplify audits.
## Examples
```bash
# Create a snapshot for case ACME-123
stella forensic snapshot create --case ACME-123 --output out/forensics/acme-123.tgz
# Verify a snapshot with pinned trust roots
stella forensic verify --bundle out/forensics/acme-123.tgz --trust-roots trust/roots.pem --output table
```

View File

@@ -0,0 +1,32 @@
# stella CLI — Observability Guide
## Commands
- `stella obs top` (planned): stream service health (SLO/burn-rate, queue depth, error rates) with table/JSON output.
- `stella obs trace <trace_id>`: fetch correlated trace if server supports it; prints correlation/trace IDs.
- `stella obs logs --from <ts> --to <ts> [--service <name>]`: pull logs for a window with pagination tokens.
## Flags
- `--output json|ndjson|table` (default: json).
- `--offline`: when set, commands must operate on cached logs/trace bundles only; if remote access would be used, exit code 5.
- `--page-size`, `--page-token`: deterministic pagination.
## Output & exit codes
- Exit codes follow `guides/output-and-exit-codes.md` (not found → 4; offline violation → 5).
- Correlation IDs and trace IDs are echoed on stderr in verbose mode for scripting/debugging.
## Determinism & privacy
- Logs/trace exports are ordered by timestamp then id; timestamps are UTC ISO-8601.
- CLI never redacts server-side; it only forwards what the API returns. Avoid printing secrets—use `--output json` with `jq` to filter locally.
## Offline/air-gap
- With `--offline`, `stella obs *` must read only cached bundles; no network calls are allowed.
- For sealed environments, pass `--trust-roots <pem>` when verifying cached trace/log bundles.
## Examples
```bash
# Fetch logs for the last hour in NDJSON
stella obs logs --from "2025-11-25T01:00:00Z" --to "2025-11-25T02:00:00Z" --output ndjson
# Retrieve a trace and pretty print spans
stella obs trace 4f2c8d1c-3b1e-4a7f-9e4a-1f4c56 --output json | jq '.spans[0]'
```

View File

@@ -0,0 +1,34 @@
# stella CLI — Output & Exit Codes
## Output formats
- `--output json` (default): deterministic JSON objects per record.
- `--output ndjson`: one JSON object per line for streaming/large results.
- `--output table`: aligned columns for humans; preserves stable column order.
- Use `--quiet` to suppress informational logs; errors still print to stderr.
## Exit codes (contract)
- `0` — Success.
- `1` — Generic error (unexpected exception).
- `2` — Validation or user input error.
- `3` — AuthN/AuthZ failure (expired token, missing scope).
- `4` — Not found / resource missing.
- `5` — Network disabled/offline violation when a command requires connectivity.
- `10` — Retryable/transient error (service unavailable, backoff suggested).
Clients and scripts should treat `25` as non-retryable unless input changes; only `10` should trigger automated retry with backoff.
## Determinism & ordering
- Lists are sorted (stable) by primary key or timestamp per command documentation.
- Timestamps are UTC ISO-8601; hashes use hex lowercase.
- Randomness is seeded; avoid machine-specific paths in emitted artefacts.
## Examples
```bash
stella vuln list --output json | jq '.items[0]'
stella export mirror --offline --output ndjson > mirror.ndjson
stella task-runner simulate --output table
```
## Observability signals
- When tracing headers are present (`traceparent`), CLI propagates them; otherwise it emits new span IDs only in verbose logs.
- Metrics are not emitted by the CLI itself; servers capture request telemetry and can be correlated via the returned correlation/trace IDs printed on errors in verbose mode.

View File

@@ -0,0 +1,32 @@
# stella CLI — Overview
## What it does
- Single entrypoint for scans, exports, policy management, VEX/Vuln queries, air-gapped kit operations, and task-runner interactions.
- Evidence-preserving: the CLI never mutates upstream evidence; it emits signed manifests and deterministic JSON/NDJSON where possible.
- Offline-ready: every command must run with cached feeds/bundles when `STELLA_OFFLINE=1` or `--offline` is set.
## Core verbs (at a glance)
- `stella scan ...` — container/dir scans; emits SBOM + findings bundles.
- `stella policy ...` — push/eval/simulate policy bundles; attach evidence; request rationale.
- `stella vex ...` / `stella vuln ...` — query VEX consensus and vulnerability projections with pagination/budgets.
- `stella export ...` — mirror/export bundles; verify signatures; produce checksums/attestations.
- `stella airgap ...` — import/export sealed bundles; validate trust roots; run without network.
- `stella task-runner ...` — submit/inspect pack runs; stream logs; collect artefacts.
## Imposed rules (apply to every command)
- Determinism first: stable ordering, UTC ISO-8601 timestamps, no host-specific paths in outputs.
- Aggregation-only: if a command shows advisory/VEX data, it must not infer verdicts beyond published evidence.
- Offline/air-gap parity: every feature documents its offline flag(s) and expected cache locations.
## Quick start
```bash
stella --help # top-level verbs
stella scan image ghcr.io/acme/app:1.2.3 --output json --offline
stella policy eval --input policy.bundle.json --subject sbom.spdx.jsonl --explain
stella export mirror --bundle out/mirror.tgz --verify
```
## Where to read next
- Configuration precedence and file locations: `configuration.md`
- Output formats and exit codes: `output-and-exit-codes.md`
- Command-specific guides: see `cli-reference.md` and verb-specific guides under `guides/`.

View File

@@ -0,0 +1,19 @@
# stella CLI — Parity Matrix
Use this matrix to verify that CLI surfaces match the corresponding service APIs, schemas, and offline behaviours. Every row must stay deterministic and aggregation-only.
| Area | Server/API | CLI command(s) | Output contract | Offline support | Notes |
| --- | --- | --- | --- | --- | --- |
| Policy eval/simulate | Policy Engine `/policy/eval` `/policy/simulate` | `stella policy eval`, `stella policy simulate` | Stable JSON/NDJSON; includes `correlationId`, `policyVersion`, `rationaleIds` | Must run with cached bundles when `--offline` | No verdict inference beyond engine response. |
| VEX consensus | VexLens `/vex/consensus` | `stella vex consensus` | Deterministic pagination; weights/issuers/rationale echoed | Cached consensus snapshots permitted | Uses aggregation-only contract. |
| Vulnerability list/detail | Vuln Explorer `/vuln` | `stella vuln list`, `stella vuln get` | Sorted by `vulnId`; includes provenance pointers; no missing fields inferred | Must respect `--offline` using cached snapshots | |
| Export/mirror bundles | Export Service `/export/*` | `stella export mirror`, `stella export verify` | Emits manifest + checksums; verification errors are deterministic | Yes (air-gap bundles) | All paths must be relative and normalized. |
| Air-gap import/export | AirGap `/airgap/*` | `stella airgap import`, `stella airgap export` | Returns sealed bundle IDs, provenance hashes | Yes; network calls forbidden when `--offline` or sealed mode | |
| Task Runner | TaskRunner `/runs` | `stella task-runner run`, `stella task-runner logs` | Monotonic log stream; stable ordering by `sequence` | Local/log-only when offline; remote requires connectivity | |
| Attestations | Attestor `/attest/*` | `stella attest verify`, `stella attest list` | Verification results include DSSE status, signature details; no risk scoring | Yes, using cached trust roots/bundles | |
| SBOM | Scanner `/sbom/*` | `stella sbom generate`, `stella sbom compose` | Emits SPDX/CycloneDX + hashes; preserves ordering | Yes; reads local images/files when offline | |
Validation checklist:
- Commands echo correlation/trace IDs on errors (verbose mode) to match server logs.
- Exit codes follow the contract in `output-and-exit-codes.md`.
- When a server feature is unavailable offline, the CLI must fail with exit code 5 and an actionable message.

View File

@@ -0,0 +1,73 @@
# Concelier Evidence Batch API (draft v1)
Path: `POST /v1/evidence/batch`
Auth: same as other advisory read endpoints; requires tenant header `X-Stella-Tenant`.
Purpose: allow graph/UI/export clients to fetch observations and linksets for a set of components (purls/aliases) in one round-trip, without derived judgments.
## Request
```json
{
"items": [
{
"componentId": "component-a",
"purls": ["pkg:maven/org.example/app@1.0.0"],
"aliases": ["CVE-2025-0001"]
}
],
"observationLimit": 50,
"linksetLimit": 50
}
```
Field rules:
- `items` is required and must be non-empty.
- Each item must supply at least one identifier (`purls` or `aliases`).
- `observationLimit` and `linksetLimit` default to 50, max 200; values ≤0 are ignored.
## Response
```json
{
"items": [
{
"componentId": "component-a",
"observations": [
{
"id": "obs:123",
"tenant": "demo",
"aliases": ["CVE-2025-0001"],
"purls": ["pkg:maven/org.example/app@1.0.0"],
"source": "nvd",
"asOf": "2025-11-25T12:00:00Z"
}
],
"linksets": [
{
"advisoryId": "CVE-2025-0001",
"source": "nvd",
"normalized": {
"purls": ["pkg:maven/org.example/app@1.0.0"]
},
"createdAt": "2025-11-25T12:00:00Z"
}
],
"hasMore": false,
"retrievedAt": "2025-11-25T12:00:01Z"
}
]
}
```
Determinism:
- Results ordered by provider ordering returned from storage; clients must not assume stable sort keys beyond the documented arrays.
- `retrievedAt` is server UTC ISO-8601.
- `hasMore` is true if either observations or linksets were truncated by the supplied limits.
Notes:
- No derived severity/weights are added; payloads mirror stored observations/linksets.
- For empty matches, the endpoint returns empty `observations` and `linksets` with `hasMore=false`.
Fixtures:
- Sample request/response above; further fixtures can be generated from `docs/samples/lnm/` data once LNM v1 fixtures are refreshed.
Changelog:
- 2025-11-25: initial draft and implementation aligned with `/v1/evidence/batch` endpoint.

View File

@@ -56,12 +56,18 @@
- **Unit**: guard rejection paths, provenance enforcement, idempotent insertions, linkset determinism.
- **Property**: fuzz upstream payloads to guarantee no forbidden fields emerge.
- **Integration**: batch ingest (50k advisories, mixed VEX fixtures), verifying zero guard violations and consistent supersedes.
- **Contract**: Policy Engine consumers verify raw-only reads; Export Center consumes canonical datasets.
- **End-to-end**: ingest/verify flow with CLI + Console actions to confirm observability and guard reporting.
## Definition of done
- Validators deployed and verified in staging/offline environments.
- Runtime guards, CLI/Console workflows, and CI linting all active.
- Observability dashboards and runbooks updated; metrics visible.
- Documentation updates merged; Offline Kit instructions published.
- ./TASKS.md reflects status transitions; cross-module dependencies acknowledged in ../../TASKS.md.
- **Contract**: Policy Engine consumers verify raw-only reads; Export Center consumes canonical datasets.
- **End-to-end**: ingest/verify flow with CLI + Console actions to confirm observability and guard reporting.
## Definition of done
- Validators deployed and verified in staging/offline environments.
- Runtime guards, CLI/Console workflows, and CI linting all active.
- Observability dashboards and runbooks updated; metrics visible.
- Documentation updates merged; Offline Kit instructions published.
- ./TASKS.md reflects status transitions; cross-module dependencies acknowledged in ../../TASKS.md.
## Readiness checkpoints (2025-11-25)
- Sprint 110 attestation chain validated: `/internal/attestations/verify` endpoint and evidence bundle tests green (`TestResults/concelier-attestation/web.trx`, `core.trx`).
- Link-Not-Merge cache + console consumption docs frozen (see `operations/lnm-cache-plan.md`, `operations/console-lnm-consumption.md`); cache headers remain deterministic.
- Observation events transport reviewed; backlog guardrails and NATS/air-gap guidance updated in `operations/observation-events.md`.
- Next gating dependency: TaskRunner contract drop (sprint 0157 blockers) before wiring approvals/pack ingest flows into Concelier.

View File

@@ -29,3 +29,9 @@ Defaults: disabled, transport `mongo`; subject/stream as above.
## Testing
- Without NATS: leave `enabled=false`; app continues writing outbox only.
- With NATS: run a local `nats-server -js` and set `enabled=true transport=nats`. Verify published messages on subject via `nats sub concelier.advisory.observation.updated.v1`.
## 2025-11-25 demo review notes
- Verified attestation demo emits `StellaOps.Concelier.Advisory.Observations` meter with counters `events_published_total` and gauges `outbox_backlog`. Ensure these metrics are scraped with tenant labels.
- Backlog guard: alert if `outbox_backlog > 500` for 10m while `transport=nats`; recommended SLO is P95 publish latency < 2s.
- When transport disabled for air-gap runs, confirm background worker remains paused (`enabled=false`) to avoid noisy retries; resume only after mirror bundles restored.
- TRX from `/internal/attestations/verify` suite lives at `TestResults/concelier-attestation/web.trx` for current demo build; keep alongside dashboards for reproducibility.

View File

@@ -0,0 +1,23 @@
# Evidence Locker sealed bundle contract · 2025-11-24
Owners: Evidence Locker Guild · Security Guild
Status: Published 2025-11-24 (source for ELOCKER-CONTRACT-2001)
## Deliverables
- Bundle schema: `bundle.schema.json` (sealed DSSE envelope + manifest) — stored under `docs/modules/evidence-locker/schemas/bundle.schema.json`.
- DSSE layout: subject digests, payload (`evidence_bundle.json`), and signatures recorded; transparency optional; canonical hash: `SHA256:6f51d7a5c9d0c5db8a1f6e9d4a0af13e3e7eb5bcb4fa8457de99d8b1c2b3b8ff`.
- Sample bundle: `docs/modules/evidence-locker/samples/evidence-bundle-sample.tgz` with accompanying `.sha256` file.
## Scope and guarantees
- Sealed, offline-friendly; deterministic ordering of files in the tarball; UTC timestamps fixed to `1970-01-01T00:00:00Z` for reproducibility.
- Payload includes: `manifest.json`, `evidence_bundle.json`, `signatures/` (DSSE), `checksums.txt`.
- No network dependencies; validation and hashing performed locally.
## Validation
- `docs/modules/evidence-locker/schemas/bundle.schema.json` validated via `ajv` offline run (see `prep/validate.sh`).
- DSSE signature verifies with sample keypair; transparency step skipped (optional).
## Next steps
- Publish NuGet contract (if needed) referencing the schema path.
- Provide CLI/Export Center consumers with manifest path and hash above.
- Unblock ATTEST-PLAN-2001; keep downstream sprints updated.

View File

@@ -85,6 +85,26 @@ This note defines the deterministic, aggregation-only contract that Excititor ex
- When mirror bundles are configured, `provenance.canonicalUri` points to the local bundle path; otherwise it is omitted.
- All payloads are side-effect free; no remote fetches occur while streaming.
## Airgap import (sealed mode) — EXCITITOR-AIRGAP-56/57/58
- Endpoint: `POST /airgap/v1/vex/import` (thin bundle envelope). Deterministic fields: `bundleId`, `mirrorGeneration`, `signedAt`, `publisher`, `payloadHash`, optional `payloadUrl`, `signature` (base64), optional `transparencyLog`, optional `tenantId`.
- Sealed-mode toggle: set `EXCITITOR_SEALED=1` or `Excititor:Airgap:SealedMode=true`. When enabled:
- External payload URLs are rejected with **AIRGAP_EGRESS_BLOCKED** (HTTP 403).
- Optional allowlist `Excititor:Airgap:TrustedPublishers` gates mirror publishers; failures return **AIRGAP_SOURCE_UNTRUSTED** (HTTP 403).
- Error catalog (all 4xx):
- **AIRGAP_SIGNATURE_MISSING** / **AIRGAP_SIGNATURE_INVALID**
- **AIRGAP_PAYLOAD_STALE** (±5s clock skew guard)
- **AIRGAP_SOURCE_UNTRUSTED** (unknown/blocked publisher or signer set)
- **AIRGAP_PAYLOAD_MISMATCH** (bundle hash not in signer manifest)
- **AIRGAP_EGRESS_BLOCKED** (sealed mode forbids HTTP/HTTPS payloadUrl)
- **AIRGAP_IMPORT_DUPLICATE** (idempotent on `(bundleId,mirrorGeneration)`)
- Portable manifest outputs (EXCITITOR-AIRGAP-58-001):
- Response echoes `manifest`, `manifestSha256`, `evidence` paths derived from the bundle ID/generation; also persisted on the import record.
- Evidence Locker linkage: `evidence/{bundleId}/{generation}/bundle.ndjson` path recorded for downstream replay/export.
- Timeline events (deterministic order, ISO timestamps):
- `airgap.import.started`, `airgap.import.completed`, `airgap.import.failed`
- Attributes: `{tenantId,bundleId,generation,stalenessSeconds?,errorCode?}`
- Emitted for every import attempt; stored on the import record and logged for audit.
## Samples
- NDJSON sample: `docs/samples/excititor/chunks-sample.ndjson` (hashes in `.sha256`) aligned to the schema above.

View File

@@ -0,0 +1,7 @@
# Vuln Explorer API draft v1 (2025-11-25)
- OpenAPI: `docs/modules/vuln-explorer/openapi/vuln-explorer.v1.yaml`
- Scope: read-only vulnerability listing/detail for Console/CLI; deterministic ordering (score desc, id asc) with opaque page tokens.
- Required headers: `x-stella-tenant`; optional `policyVersion`.
- Filters: CVE, PURL, severity band, exploitability flag, fixAvailable.
- Responses include policyVersion + rationaleId for explainability; provenance anchors back to Findings Ledger/evidence bundles.

View File

@@ -0,0 +1,188 @@
# Vuln Explorer API · v1 (draft 2025-11-25)
openapi: 3.0.3
info:
title: StellaOps Vuln Explorer API
version: "1.0.0-draft.2025-11-25"
description: >
Read-only vulnerability exploration surface. All responses are deterministic
under identical inputs and include policy version + rationale identifiers.
servers:
- url: https://{host}
variables:
host:
default: vuln-explorer.local
tags:
- name: Vulns
paths:
/vulns:
get:
summary: List vulnerabilities
tags: [Vulns]
parameters:
- $ref: '#/components/parameters/Tenant'
- $ref: '#/components/parameters/PolicyVersion'
- $ref: '#/components/parameters/PageSize'
- $ref: '#/components/parameters/PageToken'
- $ref: '#/components/parameters/Cve'
- $ref: '#/components/parameters/Purl'
- $ref: '#/components/parameters/Severity'
- $ref: '#/components/parameters/Exploitability'
- $ref: '#/components/parameters/FixAvailable'
responses:
'200':
description: Paged vulnerabilities ordered by (score desc, id asc).
content:
application/json:
schema:
$ref: '#/components/schemas/VulnListResponse'
/vulns/{id}:
get:
summary: Get vulnerability by stable ID
tags: [Vulns]
parameters:
- $ref: '#/components/parameters/Tenant'
- name: id
in: path
required: true
schema:
type: string
description: Stable vulnerability id (hash over source ids+purls).
responses:
'200':
description: Vulnerability detail with evidence/provenance.
content:
application/json:
schema:
$ref: '#/components/schemas/Vuln'
'404':
description: Not found for tenant/policy scope.
components:
parameters:
Tenant:
name: x-stella-tenant
in: header
required: true
schema: { type: string }
description: Tenant identifier; required for all endpoints.
PolicyVersion:
name: policyVersion
in: query
schema: { type: string }
description: Policy version/rationale to contextualise scores.
PageSize:
name: pageSize
in: query
schema:
type: integer
minimum: 1
maximum: 200
default: 50
description: Max items per page.
PageToken:
name: pageToken
in: query
schema: { type: string }
description: Opaque token encoding last (score,id) tuple.
Cve:
name: cve
in: query
schema: { type: array, items: { type: string }, minItems: 1 }
style: form
explode: true
description: Filter by CVE ids.
Purl:
name: purl
in: query
schema: { type: array, items: { type: string }, minItems: 1 }
style: form
explode: true
description: Filter by PURL(s); matches affected packages.
Severity:
name: severity
in: query
schema:
type: array
items:
type: string
enum: [CRITICAL, HIGH, MEDIUM, LOW, NONE]
style: form
explode: true
description: Filter by normalized severity band.
Exploitability:
name: exploitability
in: query
schema:
type: string
enum: [known, likely, unknown, none]
description: Derived exploitability flag (from KEV + VEX + telemetry).
FixAvailable:
name: fixAvailable
in: query
schema: { type: boolean }
description: Whether at least one fix is available.
schemas:
VulnListResponse:
type: object
properties:
items:
type: array
items: { $ref: '#/components/schemas/Vuln' }
nextPageToken:
type: string
description: Opaque token encoding last (score,id) tuple.
required: [items]
Vuln:
type: object
properties:
id: { type: string, description: Stable hash id }
source:
type: object
properties:
feed: { type: string, description: Original source/feed name }
advisoryId: { type: string }
cveIds:
type: array
items: { type: string }
ghsaIds:
type: array
items: { type: string }
purls:
type: array
items: { type: string }
severity: { type: string, enum: [CRITICAL, HIGH, MEDIUM, LOW, NONE] }
score: { type: number, format: double, minimum: 0, maximum: 10 }
kev: { type: boolean }
exploitability: { type: string, enum: [known, likely, unknown, none] }
fixAvailable: { type: boolean }
summary: { type: string }
affectedPackages:
type: array
items:
type: object
properties:
purl: { type: string }
versions: { type: array, items: { type: string } }
firstSeen: { type: string, format: date-time }
lastSeen: { type: string, format: date-time }
advisoryRefs:
type: array
items:
type: object
properties:
url: { type: string, format: uri }
title: { type: string }
policyVersion: { type: string }
rationaleId: { type: string }
provenance:
type: object
properties:
ledgerEntryId: { type: string }
evidenceBundleId: { type: string }
required:
- id
- severity
- score
- policyVersion
- rationaleId