feat: Implement vulnerability token signing and verification utilities
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled

- Added VulnTokenSigner for signing JWT tokens with specified algorithms and keys.
- Introduced VulnTokenUtilities for resolving tenant and subject claims, and sanitizing context dictionaries.
- Created VulnTokenVerificationUtilities for parsing tokens, verifying signatures, and deserializing payloads.
- Developed VulnWorkflowAntiForgeryTokenIssuer for issuing anti-forgery tokens with configurable options.
- Implemented VulnWorkflowAntiForgeryTokenVerifier for verifying anti-forgery tokens and validating payloads.
- Added AuthorityVulnerabilityExplorerOptions to manage configuration for vulnerability explorer features.
- Included tests for FilesystemPackRunDispatcher to ensure proper job handling under egress policy restrictions.
This commit is contained in:
master
2025-11-03 10:02:29 +02:00
parent bf2bf4b395
commit b1e78fe412
215 changed files with 19441 additions and 12185 deletions

View File

@@ -30,9 +30,6 @@
<package pattern="Microsoft.AspNetCore.Authentication.JwtBearer" /> <package pattern="Microsoft.AspNetCore.Authentication.JwtBearer" />
<package pattern="Google.Protobuf" /> <package pattern="Google.Protobuf" />
<package pattern="Grpc.*" /> <package pattern="Grpc.*" />
<package pattern="Microsoft.Bcl.AsyncInterfaces" />
<package pattern="System.Memory" />
<package pattern="System.Runtime.CompilerServices.Unsafe" />
</packageSource> </packageSource>
<packageSource key="dotnet-public"> <packageSource key="dotnet-public">
<package pattern="Microsoft.Extensions.*" /> <package pattern="Microsoft.Extensions.*" />

View File

@@ -10,6 +10,7 @@ AUTHORITY_PORT=8440
SIGNER_POE_INTROSPECT_URL=file:///offline/poe/introspect.json SIGNER_POE_INTROSPECT_URL=file:///offline/poe/introspect.json
SIGNER_PORT=8441 SIGNER_PORT=8441
ATTESTOR_PORT=8442 ATTESTOR_PORT=8442
# Secrets for Issuer Directory are provided via issuer-directory.mongo.env (see etc/secrets/issuer-directory.mongo.secret.example).
ISSUER_DIRECTORY_PORT=8447 ISSUER_DIRECTORY_PORT=8447
ISSUER_DIRECTORY_MONGO_CONNECTION_STRING=mongodb://${MONGO_INITDB_ROOT_USERNAME}:${MONGO_INITDB_ROOT_PASSWORD}@mongo:27017 ISSUER_DIRECTORY_MONGO_CONNECTION_STRING=mongodb://${MONGO_INITDB_ROOT_USERNAME}:${MONGO_INITDB_ROOT_PASSWORD}@mongo:27017
ISSUER_DIRECTORY_SEED_CSAF=true ISSUER_DIRECTORY_SEED_CSAF=true

View File

@@ -10,6 +10,7 @@ AUTHORITY_PORT=8440
SIGNER_POE_INTROSPECT_URL=https://licensing.svc.local/introspect SIGNER_POE_INTROSPECT_URL=https://licensing.svc.local/introspect
SIGNER_PORT=8441 SIGNER_PORT=8441
ATTESTOR_PORT=8442 ATTESTOR_PORT=8442
# Secrets for Issuer Directory are provided via issuer-directory.mongo.env (see etc/secrets/issuer-directory.mongo.secret.example).
ISSUER_DIRECTORY_PORT=8447 ISSUER_DIRECTORY_PORT=8447
ISSUER_DIRECTORY_MONGO_CONNECTION_STRING=mongodb://${MONGO_INITDB_ROOT_USERNAME}:${MONGO_INITDB_ROOT_PASSWORD}@mongo:27017 ISSUER_DIRECTORY_MONGO_CONNECTION_STRING=mongodb://${MONGO_INITDB_ROOT_USERNAME}:${MONGO_INITDB_ROOT_PASSWORD}@mongo:27017
ISSUER_DIRECTORY_SEED_CSAF=true ISSUER_DIRECTORY_SEED_CSAF=true

View File

@@ -12,6 +12,7 @@ AUTHORITY_PORT=8440
SIGNER_POE_INTROSPECT_URL=https://licensing.prod.stella-ops.org/introspect SIGNER_POE_INTROSPECT_URL=https://licensing.prod.stella-ops.org/introspect
SIGNER_PORT=8441 SIGNER_PORT=8441
ATTESTOR_PORT=8442 ATTESTOR_PORT=8442
# Secrets for Issuer Directory are provided via issuer-directory.mongo.env (see etc/secrets/issuer-directory.mongo.secret.example).
ISSUER_DIRECTORY_PORT=8447 ISSUER_DIRECTORY_PORT=8447
ISSUER_DIRECTORY_MONGO_CONNECTION_STRING=mongodb://${MONGO_INITDB_ROOT_USERNAME}:${MONGO_INITDB_ROOT_PASSWORD}@mongo:27017 ISSUER_DIRECTORY_MONGO_CONNECTION_STRING=mongodb://${MONGO_INITDB_ROOT_USERNAME}:${MONGO_INITDB_ROOT_PASSWORD}@mongo:27017
ISSUER_DIRECTORY_SEED_CSAF=true ISSUER_DIRECTORY_SEED_CSAF=true

View File

@@ -10,6 +10,7 @@ AUTHORITY_PORT=8440
SIGNER_POE_INTROSPECT_URL=https://licensing.stage.stella-ops.internal/introspect SIGNER_POE_INTROSPECT_URL=https://licensing.stage.stella-ops.internal/introspect
SIGNER_PORT=8441 SIGNER_PORT=8441
ATTESTOR_PORT=8442 ATTESTOR_PORT=8442
# Secrets for Issuer Directory are provided via issuer-directory.mongo.env (see etc/secrets/issuer-directory.mongo.secret.example).
ISSUER_DIRECTORY_PORT=8447 ISSUER_DIRECTORY_PORT=8447
ISSUER_DIRECTORY_MONGO_CONNECTION_STRING=mongodb://${MONGO_INITDB_ROOT_USERNAME}:${MONGO_INITDB_ROOT_PASSWORD}@mongo:27017 ISSUER_DIRECTORY_MONGO_CONNECTION_STRING=mongodb://${MONGO_INITDB_ROOT_USERNAME}:${MONGO_INITDB_ROOT_PASSWORD}@mongo:27017
ISSUER_DIRECTORY_SEED_CSAF=true ISSUER_DIRECTORY_SEED_CSAF=true

View File

@@ -45,7 +45,7 @@ Authority persists every issued token in MongoDB so operators can audit or revok
- **Client ID**: `console-web` - **Client ID**: `console-web`
- **Grants**: `authorization_code` (PKCE required), `refresh_token` - **Grants**: `authorization_code` (PKCE required), `refresh_token`
- **Audience**: `console` - **Audience**: `console`
- **Scopes**: `openid`, `profile`, `email`, `advisory:read`, `advisory-ai:view`, `vex:read`, `aoc:verify`, `findings:read`, `orch:read`, `vuln:read` - **Scopes**: `openid`, `profile`, `email`, `advisory:read`, `advisory-ai:view`, `vex:read`, `aoc:verify`, `findings:read`, `orch:read`, `vuln:view`, `vuln:investigate`, `vuln:operate`, `vuln:audit`
- **Redirect URIs** (defaults): `https://console.stella-ops.local/oidc/callback` - **Redirect URIs** (defaults): `https://console.stella-ops.local/oidc/callback`
- **Post-logout redirect**: `https://console.stella-ops.local/` - **Post-logout redirect**: `https://console.stella-ops.local/`
- **Tokens**: Access tokens inherit the global 2 minute lifetime; refresh tokens remain short-lived (30 days) and can be exchanged silently via `/token`. - **Tokens**: Access tokens inherit the global 2 minute lifetime; refresh tokens remain short-lived (30 days) and can be exchanged silently via `/token`.
@@ -111,7 +111,7 @@ Resource servers (Concelier WebService, Backend, Agent) **must not** assume in-m
| `export-center-admin` | Export Center administrative automation | `export.viewer`, `export.operator`, `export.admin` | `dpop` | `tenant-default` | | `export-center-admin` | Export Center administrative automation | `export.viewer`, `export.operator`, `export.admin` | `dpop` | `tenant-default` |
| `notify-service` | Notify WebService API | `notify.viewer`, `notify.operator` | `dpop` | `tenant-default` | | `notify-service` | Notify WebService API | `notify.viewer`, `notify.operator` | `dpop` | `tenant-default` |
| `notify-admin` | Notify administrative automation | `notify.viewer`, `notify.operator`, `notify.admin` | `dpop` | `tenant-default` | | `notify-admin` | Notify administrative automation | `notify.viewer`, `notify.operator`, `notify.admin` | `dpop` | `tenant-default` |
| `vuln-explorer-ui` | Vuln Explorer UI/API | `vuln:read` | `dpop` | `tenant-default` | | `vuln-explorer-ui` | Vuln Explorer UI/API | `vuln:view`, `vuln:investigate`, `vuln:operate`, `vuln:audit` | `dpop` | `tenant-default` |
| `signals-uploader` | Reachability sensor ingestion | `signals:write`, `signals:read`, `aoc:verify` | `dpop` | `tenant-default` | | `signals-uploader` | Reachability sensor ingestion | `signals:write`, `signals:read`, `aoc:verify` | `dpop` | `tenant-default` |
> **Secret hygiene (20251027):** The repository includes a convenience `etc/authority.yaml` for compose/helm smoke tests. Every entrys `secretFile` points to `etc/secrets/*.secret`, which ship with `*-change-me` placeholders—replace them with strong values (and wire them through your vault/secret manager) before issuing tokens in CI, staging, or production. > **Secret hygiene (20251027):** The repository includes a convenience `etc/authority.yaml` for compose/helm smoke tests. Every entrys `secretFile` points to `etc/secrets/*.secret`, which ship with `*-change-me` placeholders—replace them with strong values (and wire them through your vault/secret manager) before issuing tokens in CI, staging, or production.
@@ -153,11 +153,18 @@ Graph Explorer introduces dedicated scopes: `graph:write` for Cartographer build
- **Administrative controls** Changes to channel secrets, quiet hours, or escalation policies require `notify.admin`. Authority logs these operations and surfaces `authority.notify.scope_violation` when tokens omit the scope or tenant. - **Administrative controls** Changes to channel secrets, quiet hours, or escalation policies require `notify.admin`. Authority logs these operations and surfaces `authority.notify.scope_violation` when tokens omit the scope or tenant.
- **Least privilege** Assign `notify.admin` sparingly (platform operations, DR automation). Day-to-day rule editing should rely on `notify.operator` scoped per tenant. - **Least privilege** Assign `notify.admin` sparingly (platform operations, DR automation). Day-to-day rule editing should rely on `notify.operator` scoped per tenant.
#### Vuln Explorer permalinks #### Vuln Explorer scopes, ABAC, and permalinks
- **Scope** `vuln:read` authorises Vuln Explorer to fetch advisory/linkset evidence and issue shareable links. Assign it only to front-end/API clients that must render vulnerability details. - **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.
- **Signed links** `POST /permalinks/vuln` (requires `vuln:read`) accepts `{ "tenant": "tenant-a", "resourceKind": "vulnerability", "state": { ... }, "expiresInSeconds": 86400 }` and returns a JWT (`token`) plus `issuedAt`/`expiresAt`. The token embeds the tenant, requested state, and `vuln:read` scope and is signed with the same Authority signing keys published via `/jwks`. - **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.
- **Validation** Resource servers verify the permalink using cached JWKS: check signature, ensure the tenant matches the current request context, honour the expiry, and enforce the contained `vuln:read` scope. The payloads `resource.state` block is opaque JSON so UIs can round-trip filters/search terms without new schema changes. - **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.
- **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).
- `vuln_owner`: owning team/code; optional only when the service account allows a single value.
- `vuln_business_tier`: business criticality tier (`tier-1`, `tier-2`, etc.).
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.
## 4. Revocation Pipeline ## 4. Revocation Pipeline
Authority centralises revocation in `authority_revocations` with deterministic categories: Authority centralises revocation in `authority_revocations` with deterministic categories:
@@ -453,6 +460,20 @@ tenants:
* `serviceAccounts[].authorizedClients` restricts which OAuth clients may assume the delegate. Leave empty to allow any tenant client. * `serviceAccounts[].authorizedClients` restricts which OAuth clients may assume the delegate. Leave empty to allow any tenant client.
* `tenants[].delegation.maxActiveTokens` optionally overrides the quota for a specific tenant. * `tenants[].delegation.maxActiveTokens` optionally overrides the quota for a specific tenant.
**Bootstrap administration**
Bootstrap operators can inspect and rotate delegated identities via the internal API group:
```text
GET /internal/service-accounts?tenant={tenantId}
GET /internal/service-accounts/{accountId}/tokens
POST /internal/service-accounts/{accountId}/revocations
```
Requests must include the bootstrap API key header (`X-StellaOps-Bootstrap-Key`). Listing returns the seeded accounts with their configuration; the token listing call shows currently active delegation tokens (status, client, scopes, actor chain) and the revocation endpoint supports bulk or targeted token revocation with audit logging.
Bootstrap seeding reuses the existing Mongo `_id`/`createdAt` values. When Authority restarts with updated configuration it upserts documents without mutating immutable fields, avoiding duplicate or conflicting service-account records.
**Requesting a delegated token** **Requesting a delegated token**
```bash ```bash

View File

@@ -142,7 +142,7 @@ Samples live under `samples/api/scheduler/` (e.g., `schedule.json`, `run.json`,
"_id": "run_20251018_0001", "_id": "run_20251018_0001",
"tenantId": "tenant-alpha", "tenantId": "tenant-alpha",
"scheduleId": "sch_20251018a", "scheduleId": "sch_20251018a",
"trigger": "feedser", "trigger": "conselier",
"state": "running", "state": "running",
"stats": { "stats": {
"candidates": 1280, "candidates": 1280,
@@ -155,7 +155,7 @@ Samples live under `samples/api/scheduler/` (e.g., `schedule.json`, `run.json`,
"newMedium": 18, "newMedium": 18,
"newLow": 6 "newLow": 6
}, },
"reason": {"feedserExportId": "exp-20251018-03"}, "reason": {"conselierExportId": "exp-20251018-03"},
"createdAt": "2025-10-18T22:03:14Z", "createdAt": "2025-10-18T22:03:14Z",
"startedAt": "2025-10-18T22:03:20Z", "startedAt": "2025-10-18T22:03:20Z",
"finishedAt": null, "finishedAt": null,
@@ -244,7 +244,7 @@ Materialized view powering the Scheduler UI dashboards. Stores the latest roll-u
"updatedAt": "2025-10-18T22:10:10Z", "updatedAt": "2025-10-18T22:10:10Z",
"lastRun": { "lastRun": {
"runId": "run_20251018_0001", "runId": "run_20251018_0001",
"trigger": "feedser", "trigger": "conselier",
"state": "completed", "state": "completed",
"createdAt": "2025-10-18T22:03:14Z", "createdAt": "2025-10-18T22:03:14Z",
"startedAt": "2025-10-18T22:03:20Z", "startedAt": "2025-10-18T22:03:20Z",
@@ -265,7 +265,7 @@ Materialized view powering the Scheduler UI dashboards. Stores the latest roll-u
"recent": [ "recent": [
{ {
"runId": "run_20251018_0001", "runId": "run_20251018_0001",
"trigger": "feedser", "trigger": "conselier",
"state": "completed", "state": "completed",
"createdAt": "2025-10-18T22:03:14Z", "createdAt": "2025-10-18T22:03:14Z",
"startedAt": "2025-10-18T22:03:20Z", "startedAt": "2025-10-18T22:03:20Z",

View File

@@ -129,7 +129,8 @@
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | | ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|----|--------|----------|------------|-------------|---------------| |----|--------|----------|------------|-------------|---------------|
| DOCS-LNM-22-007 | TODO | Docs Guild, Observability Guild | CONCELIER-LNM-21-005, EXCITITOR-LNM-21-005, DEVOPS-LNM-22-002 | Publish `/docs/observability/aggregation.md` with metrics/traces/logs/SLOs. | Observability doc merged; dashboards referenced; checklist appended. | | DOCS-LNM-22-007 | TODO | Docs Guild, Observability Guild | CONCELIER-LNM-21-005, EXCITITOR-LNM-21-005, DEVOPS-LNM-22-002 | Publish `/docs/observability/aggregation.md` with metrics/traces/logs/SLOs. | Observability doc merged; dashboards referenced; checklist appended. |
| DOCS-LNM-22-008 | TODO | Docs Guild, DevOps Guild | MERGE-LNM-21-001, CONCELIER-LNM-21-102 | Write `/docs/migration/no-merge.md` describing migration plan, backfill steps, rollback, feature flags. | Migration doc approved by stakeholders; checklist appended. | | DOCS-LNM-22-008 | DONE (2025-11-03) | Docs Guild, DevOps Guild | MERGE-LNM-21-001, CONCELIER-LNM-21-102 | Write `/docs/migration/no-merge.md` describing migration plan, backfill steps, rollback, feature flags. | Migration doc approved by stakeholders; checklist appended. |
> 2025-11-03: Moved to DOING to align playbook structure, then published `docs/migration/no-merge.md` with rollout/backfill/rollback guidance plus readiness checklist; awaiting stakeholder approval note.
## Policy Engine + Editor v1 ## Policy Engine + Editor v1

View File

@@ -6,7 +6,7 @@
Air-Gapped Mode is the supported operating profile for deployments with **zero external egress**. All inputs arrive via signed mirror bundles, and every surface (CLI, Console, APIs, schedulers, scanners) operates under sealed-network constraints while preserving Aggregation-Only Contract invariants. Air-Gapped Mode is the supported operating profile for deployments with **zero external egress**. All inputs arrive via signed mirror bundles, and every surface (CLI, Console, APIs, schedulers, scanners) operates under sealed-network constraints while preserving Aggregation-Only Contract invariants.
- **Primary components:** Web Services API, Console, CLI, Orchestrator, Task Runner, Conseiller (Feedser), Excitator (VEXer), Policy Engine, Findings Ledger, Export Center, Authority & Tenancy, Notifications, Observability & Forensics. - **Primary components:** Web Services API, Console, CLI, Orchestrator, Task Runner, Conselier (formerly Feedser), Excitor (formerly Vexer), Policy Engine, Findings Ledger, Export Center, Authority & Tenancy, Notifications, Observability & Forensics.
- **Surfaces:** offline bootstrap, mirror ingestion, deterministic jobs, offline advisories/VEX/policy packs/notifications, evidence exports. - **Surfaces:** offline bootstrap, mirror ingestion, deterministic jobs, offline advisories/VEX/policy packs/notifications, evidence exports.
- **Dependencies:** Export Center, Containerized Distribution, Authority-backed scopes & tenancy, Observability & Forensics, Policy Studio. - **Dependencies:** Export Center, Containerized Distribution, Authority-backed scopes & tenancy, Observability & Forensics, Policy Studio.
@@ -15,7 +15,7 @@ Air-Gapped Mode is the supported operating profile for deployments with **zero e
1. **Zero egress:** all outbound network calls are disabled unless explicitly allowed. Any feature requiring online data must degrade gracefully with clear UX messaging. 1. **Zero egress:** all outbound network calls are disabled unless explicitly allowed. Any feature requiring online data must degrade gracefully with clear UX messaging.
2. **Deterministic inputs:** the platform accepts only signed Mirror Bundles (advisories, VEX, policy packs, vendor feeds, images, dashboards). Bundles carry provenance attestations and chain-of-custody manifests. 2. **Deterministic inputs:** the platform accepts only signed Mirror Bundles (advisories, VEX, policy packs, vendor feeds, images, dashboards). Bundles carry provenance attestations and chain-of-custody manifests.
3. **Auditable exchange:** every import/export records provenance, signatures, and operator identity. Evidence bundles and reports remain verifiable offline. 3. **Auditable exchange:** every import/export records provenance, signatures, and operator identity. Evidence bundles and reports remain verifiable offline.
4. **Aggregation-Only Contract compliance:** Conseiller and Excitator continue to aggregate without mutating source records, even when ingesting mirrored feeds. 4. **Aggregation-Only Contract compliance:** Conseiller and Excitor continue to aggregate without mutating source records, even when ingesting mirrored feeds.
5. **Operator ergonomics:** offline bootstrap, upgrade, and verification steps are reproducible and scripted. 5. **Operator ergonomics:** offline bootstrap, upgrade, and verification steps are reproducible and scripted.
## Lifecycle & modes ## Lifecycle & modes
@@ -44,7 +44,7 @@ Air-Gapped Mode is the supported operating profile for deployments with **zero e
| --- | --- | | --- | --- |
| Export Center | Produce full/delta mirror bundles, signed manifests, provenance attestations. | | Export Center | Produce full/delta mirror bundles, signed manifests, provenance attestations. |
| Authority & Tenancy | Provide offline scope enforcement, short-lived tokens, revocation via local CRLs. | | Authority & Tenancy | Provide offline scope enforcement, short-lived tokens, revocation via local CRLs. |
| Conseiller / Excitator | Ingest mirrored advisories/VEX, enforce AOC, versioned observations. | | Conseiller / Excitor | Ingest mirrored advisories/VEX, enforce AOC, versioned observations. |
| Policy Engine & Findings Ledger | Replay evaluations using offline feeds, emit explain traces, support sealed-mode hints. | | Policy Engine & Findings Ledger | Replay evaluations using offline feeds, emit explain traces, support sealed-mode hints. |
| Notifications | Deliver locally via approved channels (email relay, webhook proxies) or queue for manual export. | | Notifications | Deliver locally via approved channels (email relay, webhook proxies) or queue for manual export. |
| Observability | Collect metrics/logs/traces locally, generate forensic bundles for external analysis. | | Observability | Collect metrics/logs/traces locally, generate forensic bundles for external analysis. |
@@ -57,6 +57,8 @@ Air-Gapped Mode is the supported operating profile for deployments with **zero e
- **Key rotation:** plan for offline key ceremonies; Export Center and Authority document rotation playbooks. - **Key rotation:** plan for offline key ceremonies; Export Center and Authority document rotation playbooks.
- **Authority scopes:** enforce `airgap:status:read`, `airgap:import`, and `airgap:seal` via tenant-scoped roles; require operator reason/ticket metadata for sealing. - **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. - **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.
- **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 ## Testing & verification

View File

@@ -0,0 +1,18 @@
# Scanner API Docs — Windows/macOS Coverage (Draft)
This directory collects interim artefacts tracking customer demand and roadmap readiness for extending Scanner coverage to Windows and macOS.
## Files
- `windows-coverage.md` — narrative summary of customer signals and required artefacts.
- `windows-macos-summary.md` — dashboard-style snapshot (counts, cross-references) updated after each discovery cycle.
## Related resources
- `../../modules/scanner/design/README.md`
- `../../benchmarks/scanner/windows-macos-demand.md`
- `../../benchmarks/scanner/windows-macos-interview-template.md`
- `../../modules/scanner/design/macos-analyzer.md`
- `../../modules/scanner/design/windows-analyzer.md`
- `../../modules/policy/windows-package-readiness.md`
- `../../modules/policy/secret-leak-detection-readiness.md`
> Note: replace these working notes with formal API documentation once Windows/macOS analyzer endpoints are defined.

View File

@@ -0,0 +1,50 @@
# Scanner API — Windows/macOS Coverage Signals (Draft)
> Audience: Solutions engineers, product managers, guild leads coordinating Windows/macOS roadmap
> Status: Informational; update as interviews conclude
## Summary
| Region | Accounts referenced | Primary workloads | Demand strength (1-5) | Blocking? | Notes |
| --- | --- | --- | --- | --- | --- |
| North America | Northwind Health Services; FinSecure Corp | macOS CI runners; Windows Server 2019 workloads | 4-5 | macOS: evaluation; Windows: blocking | Demo 2025-11-10; Security decision due 2025-11-07. |
| EMEA | — | — | — | — | — |
| APAC | — | — | — | — | — |
| Gov / Regulated | — | — | — | — | — |
### Key drivers
- Customers with regulated Windows Server/desktop estates lack deterministic SBOM coverage and provenance.
- macOS development shops (Mobile, Gaming) require entitlements/notarization evidence for compliance.
- Offline/air-gapped environments need signed rule bundles and feed mirrors for Windows/macOS ecosystems.
### Competitive landscape
- Trivy/Grype/Snyk remain Linux-focused; Windows/macOS features are roadmap items or SaaS-only.
- Opportunity to differentiate via deterministic evidence, policy integration, and offline parity.
### Design references
- `../../modules/scanner/design/macos-analyzer.md`
- `../../modules/scanner/design/windows-analyzer.md`
### Action items
- Maintain region rows using interview summaries from `docs/benchmarks/scanner/windows-macos-demand.md` (last update 2025-11-03; capture via the interview template).
- Track readiness decisions by updating POLICY-READINESS-0001/0002 status and recording outcomes in the summary table.
- Align backlog references (`SCANNER-ENG-0020..0027`, `DOCS-SCANNER-BENCH-62-016`) with product prioritisation after each roadmap review.
### Open blockers
- FinSecure PCI audit pending POLICY-READINESS-0002 decision (due 2025-11-07); unblock Windows analyzer spike scheduling.
- Northwind macOS readiness workshop scheduled 2025-11-10; capture masking/telemetry decisions for POLICY-READINESS-0001.
## Interview log (selected)
| Date | Customer | Platform focus | Signal summary | Strength (1-5) | Follow-up |
| --- | --- | --- | --- | --- | --- |
| 2025-11-03 | Northwind Health Services | macOS | Needs notarization/entitlement visibility for CI runners | 4 | Demo 2025-11-10 with Product; feed findings into POLICY-READINESS-0001. |
| 2025-11-03 | FinSecure Corp | Windows | Requires MSI/WinSxS SBOM + signed driver attestations for PCI audit | 5 | Security guild to resolve Authenticode posture (POLICY-READINESS-0002) by 2025-11-07. |
## Required artefacts
- Maintain interview notes using `docs/benchmarks/scanner/windows-macos-interview-template.md`.
- Update demand tracker tables in `docs/benchmarks/scanner/windows-macos-demand.md`.
- Sync backlog entries in `docs/modules/scanner/TASKS.md` and `docs/scanner/design/*.md`.
## Next steps
1. Collect at least three qualified Windows and macOS requests; update summary table.
2. Present findings to Scanner Guild for prioritisation (target Sprint 133 design spike).
3. Coordinate policy readiness briefs (`docs/modules/policy/windows-package-readiness.md`) and design docs (`design/macos-analyzer.md`, `design/windows-analyzer.md`).

View File

@@ -0,0 +1,37 @@
# Scanner API — Windows/macOS Coverage Dashboard (Draft)
> Owners: Product Guild, Scanner Guild • Status: living document updated every sprint
## At-a-glance metrics (Sprint 132 intake)
- macOS demand entries logged: 1 (Northwind Health Services, 2025-11-03)
- Windows demand entries logged: 1 (FinSecure Corp, 2025-11-03)
- Qualified customers awaiting roadmap response: 1 (FinSecure PCI blocker)
- Open policy readiness items: POLICY-READINESS-0001, POLICY-READINESS-0002
## Cross-reference
| Resource | Purpose |
| --- | --- |
| docs/benchmarks/scanner/windows-macos-demand.md | Signal log & next actions |
| docs/benchmarks/scanner/windows-macos-interview-template.md | Interview capture template |
| docs/benchmarks/scanner/deep-dives/macos.md | macOS implementation roadmap |
| docs/benchmarks/scanner/deep-dives/windows.md | Windows implementation roadmap |
| docs/modules/scanner/design/macos-analyzer.md | Detailed macOS design |
| docs/modules/scanner/design/windows-analyzer.md | Detailed Windows design |
| docs/modules/policy/windows-package-readiness.md | Policy readiness for Windows packages |
| docs/modules/policy/secret-leak-detection-readiness.md | Policy readiness for secrets |
| docs/modules/scanner/TASKS.md | Engineering backlog (SCANNER-ENG-0020..0027) |
| docs/modules/policy/TASKS.md | Policy readiness tasks |
| docs/api/scanner/windows-coverage.md | Narrative summary |
## Maintenance cadence
- Update metrics and cross-links after each customer signal or roadmap checkpoint.
- Ensure DOCS-SCANNER-BENCH-62-002/016 status mirrors demand tracker progress.
## Upcoming milestones
- 2025-11-07: POLICY-READINESS-0002 Authenticode/feed decision for FinSecure (unblocks Windows analyzer spike).
- 2025-11-10: POLICY-READINESS-0001 workshop during Northwind demo to finalise masking/telemetry posture.
## Recent updates
- 2025-11-03: Logged Northwind Health Services (macOS) & FinSecure Corp (Windows); awaiting POLICY-READINESS-0001/0002 decisions before scheduling analyzer spikes.
Last updated: 2025-11-03 (initial demand entries logged).

View File

@@ -6,7 +6,7 @@
The SDK & OpenAPI program delivers canonical OpenAPI 3.1 contracts for every StellaOps surface, plus officially supported SDKs (TypeScript/Node, Python, Go, Java, C#). It ensures backwards-compatible evolution, documentation, and offline availability. The SDK & OpenAPI program delivers canonical OpenAPI 3.1 contracts for every StellaOps surface, plus officially supported SDKs (TypeScript/Node, Python, Go, Java, C#). It ensures backwards-compatible evolution, documentation, and offline availability.
- **Primary components:** API Gateway, Web Services, Policy Engine, Conseiller, Excitator, Orchestrator, Findings Ledger, Export Center, Authority & Tenancy, Console, CLI. - **Primary components:** API Gateway, Web Services, Policy Engine, Conseiller, Excitor, Orchestrator, Findings Ledger, Export Center, Authority & Tenancy, Console, CLI.
- **Surfaces:** OpenAPI specs, language SDKs, developer portal, examples, mock server, conformance tests, changelog feeds, deprecation notices. - **Surfaces:** OpenAPI specs, language SDKs, developer portal, examples, mock server, conformance tests, changelog feeds, deprecation notices.
- **Dependencies:** Authority scopes/tenancy, CLI parity, Export Center, Notifications, Air-Gapped Mode, Observability. - **Dependencies:** Authority scopes/tenancy, CLI parity, Export Center, Notifications, Air-Gapped Mode, Observability.

View File

@@ -0,0 +1,26 @@
# Scanner Benchmarks & Coverage Dossiers
This directory aggregates competitive analyses, deep dives, and demand signals that inform the Scanner roadmap.
## Structure
- `../../scanner-feature-comparison-*.md` — high-level feature comparisons versus Trivy, Grype, Snyk.
- `deep-dives/` — ecosystem-specific implementation deep dives (languages, OS packages, secrets, macOS, Windows, etc.).
- `scanning-gaps-stella-misses-from-competitors.md` — gap analysis with scorecards, implementation plans, and backlog references.
- `windows-macos-demand.md` — demand tracker and next actions for Windows/macOS coverage.
- `windows-macos-interview-template.md` — structured questionnaire for customer discovery.
## Quick links
- macOS: `deep-dives/macos.md`, `../../modules/scanner/design/macos-analyzer.md`.
- Windows: `deep-dives/windows.md`, `../../modules/scanner/design/windows-analyzer.md`.
- Policy readiness: `../../modules/policy/secret-leak-detection-readiness.md`, `../../modules/policy/windows-package-readiness.md`.
- API dashboards: `../../api/scanner/windows-coverage.md`, `../../api/scanner/windows-macos-summary.md`.
## Maintenance tips
- When new interview signals are logged, update `windows-macos-demand.md`, the API dashboards, and cross-link relevant design docs.
- Ensure gap scorecards reflect the latest findings and backlog IDs.
- Keep feature comparison docs aligned with deep dive updates.
## Backlog references
- Engineering: see `../../modules/scanner/TASKS.md` (SCANNER-ENG-0020..0027).
- Docs: `../../docs/TASKS.md` (DOCS-SCANNER-BENCH-62-016).
- Policy: `../../modules/policy/TASKS.md` (POLICY-READINESS-0001/0002).

View File

@@ -0,0 +1,48 @@
# macOS Package Ecosystem — Coverage Deep Dive
## Competitor snapshot
- **Trivy**: Official coverage tables list only Linux distributions (Alpine/Wolfi, Debian/Ubuntu, RHEL family, SUSE, Photon, Amazon, Bottlerocket). No analyzer exists for Homebrew, Mac App Store receipts, or `.app` bundles.
- **Grype**: Mirrors Syft catalogers that target Linux package managers; no matchers for Homebrew formulae, pkgutil receipts, or macOS frameworks.
- **Snyk CLI**: Container and open-source scans are routed through the SaaS backend; macOS host package analysis is not advertised or documented.
## Proposed StellaOps roadmap
See also: `../../modules/scanner/design/macos-analyzer.md` for the in-depth design brief.
1. **Homebrew cellar collector**
- Parse `/usr/local/Cellar` and `/opt/homebrew/Cellar` manifest files plus taps metadata to enumerate installed formulae/casks.
- Normalize tap origin, version, revision, and bottle source; map to `pkg:brew/{tap}/{name}@{version}` PURLs.
2. **System receipt inventory**
- Use `pkgutil --pkgs --pkg-info-plist` style parsing against `/var/db/receipts/*.bom` to capture Apple installer packages and third-party pkg receipts.
- Record CFBundleIdentifier, install timestamps, and BOM file hashes to feed deterministic provenance.
3. **Application bundle inspection**
- Scan `/Applications`, `/System/Applications`, and `/Users/*/Applications` for `.app` bundles.
- Extract Info.plist data (bundle id/version), embedded frameworks, entitlements, and code signing certificates.
4. **Policy alignment**
- Emit capability hints (network, TCC categories) for Policy Engine gating.
- Provide allow lists for signed Apple system components versus third-party apps.
5. **Offline parity**
- Mirror Homebrew tap metadata snapshots and entitlements schema inside Offline Kit.
- Package notarization certificate bundles and CRL/OCSP cache guidance for air-gapped verification.
## Detection technique comparison
| Technique | Artifacts | Merge strategy | Notes |
| --- | --- | --- | --- |
| Homebrew cellar parsing | Cellar manifests, `INSTALL_RECEIPT.json`, tap metadata | Produce per-formula component records keyed by tap + version; merge duplicates by canonical tap origin; attach bottle SHA256 for provenance. | Requires tap snapshot to ensure deterministic version resolution. |
| pkgutil receipt parsing | `/var/db/receipts/*.plist` + `.bom` files | Build component entries for Apple/third-party installer packages; merge with bundle evidence when matching CFBundleIdentifier. | Provides authoritative install-time metadata including install source. |
| `.app` bundle inspection | Info.plist, CodeResources, entitlements, embedded frameworks | Emit capability records (e.g., `tcc.camera`, `network.client`); merge with receipts when bundle id matches. | Must preserve signing chain and team identifier; store hash of CodeDirectory. |
| Launch daemon/service mapping | `/Library/LaunchDaemons`, `/Library/LaunchAgents`, `launchctl print` exports | (Planned) Attach runtime usage hints for Policy Engine and EntryTrace cross-module alignment. | Helps differentiate dormant apps from active services. |
| Competitor baseline | — | No competitor evidence to merge; Trivy/Grype/Snyk lack macOS analyzers. | Presents differentiation opportunity once demand justifies investment. |
## Backlog / coordination
- Keep demand capture in `docs/benchmarks/scanner/windows-macos-demand.md` up to date; once thresholds are met, open:
- `SCANNER-ENG-00xx` (macOS cellar/receipt analyzer design spike).
- `DOCS-SCANNER-BENCH-62-002` (this docs parent task) — exit criteria: demand summary + design scope recommendation.
- Policy task to define macOS capability predicates (entitlements, notarization state).
- Align with Offline Kit guild on notarization/CRL packaging and tap mirroring strategy.
## Open design questions
| Topic | Question | Owner |
| --- | --- | --- |
| Notarization verification | Should scanner verify Apple notarization tickets or delegate to Policy Engine? | Security Guild |
| Entitlement taxonomy | How granular should capability predicates be (per entitlement vs grouped categories)? | Policy Guild |
| User-space scope | Do we scan per-user Homebrew installs and sandboxed app containers? | Scanner Guild |
| Performance | Do we cache receipts/bundle metadata between scans given large `.app` trees? | Scanner + Surface Guilds |

View File

@@ -13,7 +13,8 @@
| Rust | Binary heuristics | StellaOps | Fingerprint coverage incomplete for niche toolchains. | Unmatched binaries ignored; no fallback crates. | No fallback for binaries lacking Cargo metadata; depends on Syft crate data. | No Rust/Cargo support in CLI plugins. | Execute Rust fingerprint plan (`scanning-gaps-stella-misses-from-competitors.md`) and update analyzer backlog. | [rust.md](rust.md) | | Rust | Binary heuristics | StellaOps | Fingerprint coverage incomplete for niche toolchains. | Unmatched binaries ignored; no fallback crates. | No fallback for binaries lacking Cargo metadata; depends on Syft crate data. | No Rust/Cargo support in CLI plugins. | Execute Rust fingerprint plan (`scanning-gaps-stella-misses-from-competitors.md`) and update analyzer backlog. | [rust.md](rust.md) |
| OS packages | Linux distro coverage & provenance | Tie (StellaOps / Grype) | Requires RustFS/object store deployment for full replay; Windows packaging still out of scope. | No per-layer fragment storage; provenance limited; Windows support likewise minimal. | No per-layer provenance; shares Syft catalog and Anchore DB only. | Snyk Container scanning depends on SaaS API; no per-layer provenance. | Document RustFS dependency & offline alternatives in ops backlog; evaluate Windows pkg roadmap. | [os-packages.md](os-packages.md) | | OS packages | Linux distro coverage & provenance | Tie (StellaOps / Grype) | Requires RustFS/object store deployment for full replay; Windows packaging still out of scope. | No per-layer fragment storage; provenance limited; Windows support likewise minimal. | No per-layer provenance; shares Syft catalog and Anchore DB only. | Snyk Container scanning depends on SaaS API; no per-layer provenance. | Document RustFS dependency & offline alternatives in ops backlog; evaluate Windows pkg roadmap. | [os-packages.md](os-packages.md) |
| OS packages | Linux flavor support (Alpine/Wolfi/Chainguard, Debian/Ubuntu, RHEL/Alma/Rocky, SUSE, Amazon/Bottlerocket) | Tie (Trivy / Snyk) | Windows/macOS package ecosystems still pending. | Coverage relies on package DB adapters; per-distro nuances (e.g., Chainguard signatures) not attested. | Supports major Linux feeds but no Windows/macOS package analyzers. | Supports documented distro list via Snyk Container but requires cloud connectivity. | Track demand for non-Linux package analyzers; document distro mapping in os-packages deep dive. | [os-packages.md](os-packages.md) | | OS packages | Linux flavor support (Alpine/Wolfi/Chainguard, Debian/Ubuntu, RHEL/Alma/Rocky, SUSE, Amazon/Bottlerocket) | Tie (Trivy / Snyk) | Windows/macOS package ecosystems still pending. | Coverage relies on package DB adapters; per-distro nuances (e.g., Chainguard signatures) not attested. | Supports major Linux feeds but no Windows/macOS package analyzers. | Supports documented distro list via Snyk Container but requires cloud connectivity. | Track demand for non-Linux package analyzers; document distro mapping in os-packages deep dive. | [os-packages.md](os-packages.md) |
| OS packages | Windows/macOS coverage | — | No Windows/macOS analyzer; backlog item for offline parity. | Coverage docs enumerate Linux distributions only; Windows/macOS packages unsupported. | Syft matchers focus on Linux ecosystems; Windows/macOS packages unsupported. | Coverage depends on Snyks SaaS service; no offline assurance for Windows/macOS packages. | Capture demand for Windows/macOS analyzers (see `docs/benchmarks/scanner/windows-macos-demand.md`) and scope feasibility. | [os-packages.md](os-packages.md) | | macOS packages | Coverage & provenance | StellaOps (future) | macOS analyzer not implemented yet; design captured in deep dive. | No macOS analyzers (Linux only). | No macOS analyzers (Linux only). | No macOS host scanning; SaaS container focus only. | Advance demand capture (`windows-macos-demand.md`); open macOS design spike once threshold met. | [macos.md](macos.md) |
| Windows packages | Coverage & provenance | StellaOps (future) | Windows analyzer family not yet implemented; design brief in progress. | No Windows coverage beyond containers. | Syft/Grype lack Windows collectors; Anchore feeds Linux-only. | SaaS host scanning only; no offline or deterministic evidence. | Capture demand signals; scope Windows analyzer spike when thresholds met. | [windows.md](windows.md) |
| Secrets | Handling posture | StellaOps | No leak scanning by design; Surface.Secrets manages retrieval/rotation with tenant scopes. | Leak detections lack governance hooks; operators must track rule updates. | No secret management abstraction; credentials configured manually. | Requires SaaS backend for secret scanning; no offline posture or secret storage guidance. | Document governance patterns for Surface.Secrets users and recommended companion tooling. | [secrets.md](secrets.md) | | Secrets | Handling posture | StellaOps | No leak scanning by design; Surface.Secrets manages retrieval/rotation with tenant scopes. | Leak detections lack governance hooks; operators must track rule updates. | No secret management abstraction; credentials configured manually. | Requires SaaS backend for secret scanning; no offline posture or secret storage guidance. | Document governance patterns for Surface.Secrets users and recommended companion tooling. | [secrets.md](secrets.md) |
| Secrets | Detection technique | Trivy | No content scanning; relies on Surface.Secrets integrations. | Regex/entropy detectors with configurable allow/deny lists across files/bytecode. | No detector available; Syft/Grype skip leak scanning entirely. | Snyk Code/Snyk secrets require uploading code to SaaS; offline detection unavailable. | Execute secrets leak detection plan (`scanning-gaps-stella-misses-from-competitors.md`) and plan policy templates. | [secrets.md](secrets.md) | | Secrets | Detection technique | Trivy | No content scanning; relies on Surface.Secrets integrations. | Regex/entropy detectors with configurable allow/deny lists across files/bytecode. | No detector available; Syft/Grype skip leak scanning entirely. | Snyk Code/Snyk secrets require uploading code to SaaS; offline detection unavailable. | Execute secrets leak detection plan (`scanning-gaps-stella-misses-from-competitors.md`) and plan policy templates. | [secrets.md](secrets.md) |
| EntryTrace | Runtime command resolution | StellaOps | Shell/language launcher coverage needs continuous tuning. | Not supported. | Not available. | Not available. | Maintain EntryTrace plan (`scanning-gaps-stella-misses-from-competitors.md`) and backlog cadence. | — | | EntryTrace | Runtime command resolution | StellaOps | Shell/language launcher coverage needs continuous tuning. | Not supported. | Not available. | Not available. | Maintain EntryTrace plan (`scanning-gaps-stella-misses-from-competitors.md`) and backlog cadence. | — |

View File

@@ -29,6 +29,14 @@
- **Metadata depth**: StellaOps records extensive vendor metadata and file evidence for replay; Trivy, Snyk, and Grype focus on match-relevant fields from their feeds. - **Metadata depth**: StellaOps records extensive vendor metadata and file evidence for replay; Trivy, Snyk, and Grype focus on match-relevant fields from their feeds.
- **Provenance**: StellaOps outputs integrate directly with attestation/diff pipelines, while Trivy, Snyk, and Grype assume downstream tools consume package lists without replay requirements. - **Provenance**: StellaOps outputs integrate directly with attestation/diff pipelines, while Trivy, Snyk, and Grype assume downstream tools consume package lists without replay requirements.
### Detection technique comparison
| Tool | Detection technique(s) | Merge / result handling | Notes |
| --- | --- | --- | --- |
| **StellaOps** | Deterministic DB parsing via `StellaOps.Scanner.Analyzers.OS.(Apk|Dpkg|Rpm)`; fragment mapping via `OsComponentMapper`; provenance persisted in Surface.FS. | Analyzer outputs become `LayerComponentFragment`s stored in `ScanAnalysisStore`; SBOM assembly composes inventory/usage views while preserving layer digests and metadata for diffs + attestations. | Supports offline replay, DSSE binding, and policy joins with Concelier advisories. |
| **Trivy** | Layer walkers + distro parsers in `pkg/fanal/analyzer/pkg/*`; optional manifest enrichment using vendor feeds. | Packages aggregated per artifact; provenance/layer context not persisted, leaving downstream tooling to interpret results. | Coverage matrix enumerated in `docs/docs/coverage/os/*.md`. |
| **Grype** | Syft catalogers + matchers in `grype/matcher/{apk,dpkg,rpm}` leveraging Anchore feeds. | Matchers run against Syft inventory and Anchore DB; no layer fragments retained. | Determinism depends on feed snapshots. |
| **Snyk** | Container scans upload image metadata to SaaS for analysis. | Results surfaced via SaaS dashboards/API; no local merge or provenance data. | Requires network connectivity; offline unsupported. |
### References ### References
- [t1] `/tmp/trivy-src/docs/docs/coverage/os/index.md` - [t1] `/tmp/trivy-src/docs/docs/coverage/os/index.md`
- [s1] `/tmp/snyk-cli/README.md` - [s1] `/tmp/snyk-cli/README.md`

View File

@@ -1,6 +1,7 @@
# Secret Handling # Secret Handling
## StellaOps approach ## StellaOps approach
- Detailed Policy/Security briefing: `../../modules/policy/secret-leak-detection-readiness.md`.
- Secrets treated as operational inputs delivered through Surface.Secrets (`src/Scanner/__Libraries/StellaOps.Scanner.Surface.Secrets` and documented in `docs/modules/scanner/design/surface-secrets.md`). - Secrets treated as operational inputs delivered through Surface.Secrets (`src/Scanner/__Libraries/StellaOps.Scanner.Surface.Secrets` and documented in `docs/modules/scanner/design/surface-secrets.md`).
- Providers support Kubernetes Secrets, file-based bundles, and inline definitions; configuration resolved via Surface.Env with validation gates from Surface.Validation. - Providers support Kubernetes Secrets, file-based bundles, and inline definitions; configuration resolved via Surface.Env with validation gates from Surface.Validation.
- Secret placeholders (`secret://type/name`) are resolved before analyzers execute, with results wrapped in secure handles and rotation metadata checked at startup. - Secret placeholders (`secret://type/name`) are resolved before analyzers execute, with results wrapped in secure handles and rotation metadata checked at startup.
@@ -26,6 +27,15 @@
- **Workflow**: StellaOps secret lifecycle is pre-scan configuration; Trivy and Snyk analyse content at scan time (Snyk requiring SaaS connectivity), and Grype requires external tooling for leak detection. - **Workflow**: StellaOps secret lifecycle is pre-scan configuration; Trivy and Snyk analyse content at scan time (Snyk requiring SaaS connectivity), and Grype requires external tooling for leak detection.
- **Determinism**: StellaOps avoids non-deterministic leak scans; Trivy and Snyks detectors may evolve with rule updates; Grype remains deterministic by not attempting secret discovery. - **Determinism**: StellaOps avoids non-deterministic leak scans; Trivy and Snyks detectors may evolve with rule updates; Grype remains deterministic by not attempting secret discovery.
### Detection technique comparison
| Tool | Detection technique(s) | Merge / result handling | Notes |
| --- | --- | --- | --- |
| **StellaOps (current)** | `Surface.Secrets` providers fetch credentials at runtime; no leak scanning today. | Secrets resolve to opaque handles stored in scan metadata; no SBOM entries emitted. | Deterministic and explainable; avoids exposing payloads. |
| **StellaOps (planned)** | `StellaOps.Scanner.Analyzers.Secrets` plug-in executing signed rule bundles. | Findings inserted into `ScanAnalysisStore` as `secret.leak` evidence; Policy Engine merges with component context and lattice scores. | Rules packaged offline; CLI/reporting masks payloads while surfacing rule IDs. |
| **Trivy** | Regex + entropy detectors under `pkg/fanal/secret` (configurable via `trivy-secret.yaml`). | Detectors aggregate per file; results exported alongside vulnerability findings without provenance binding. | Ships built-in rule sets; users can add allow/block lists. |
| **Snyk** | Snyk Code SaaS classifiers invoked by CLI plugin (`src/lib/plugins/sast`). | Source uploaded to SaaS; issues returned with severity + remediation; no offline merge with SBOM data. | Requires authenticated cloud access; rules evolve server-side. |
| **Grype** | None (focuses on vulnerability matching). | — | Operators must integrate separate tooling for leak detection. |
### References ### References
- [s1] `/tmp/snyk-cli/src/lib/plugins/sast` - [s1] `/tmp/snyk-cli/src/lib/plugins/sast`
- [s2] `/tmp/snyk-cli/README.md` - [s2] `/tmp/snyk-cli/README.md`

View File

@@ -0,0 +1,47 @@
# Windows Package Ecosystem — Coverage Deep Dive
## Competitor snapshot
- **Trivy**: No analyzers for Windows Installer (MSI), WinSxS manifests, or Chocolatey feeds. Official coverage tables enumerate Linux distributions only.
- **Grype**: Syft catalogers focus on Linux ecosystems; no Windows package collectors or matchers are available.
- **Snyk CLI**: Container/open-source scans rely on SaaS services; Windows host-level package scanning is not advertised. Snyk AppRisk references depend on SaaS integrations rather than offline collectors.
## Proposed StellaOps roadmap
In-depth design detail lives in `../../modules/scanner/design/windows-analyzer.md`.
1. **MSI/WinSxS collector**
- Traverse `Windows/WinSxS/Manifests` and `Windows/Installer` to harvest component manifests, linking to installed products via the installer database.
- Parse MSI tables (Product, Component, File) to emit authoritative component records with product codes, upgrade codes, and install context.
2. **Chocolatey/NuGet-based packages**
- Inspect `ProgramData/Chocolatey/lib` and `ProgramData/Chocolatey/packages.config` for package metadata, including embedded nuspec files and checksums.
- Resolve package sources and cache feed metadata to support offline replay.
3. **Registry-backed inventory**
- Query `HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall` and equivalent Wow6432Node path to capture legacy installers (EXE/PDB) with version/signature hints.
- Record install source, publisher, and install location for cross-reference with filesystem collectors.
4. **Capability signals**
- Detect installed services (`System32/config/SYSTEM` registry hive), scheduled tasks, and driver packages to feed Policy Engine capability predicates.
- Capture Authenticode signatures and catalog (.cat) references to support trust enforcement.
5. **Offline parity**
- Package MSI schema definitions, Chocolatey feed snapshots, and Windows update catalog indexes into Offline Kit bundles.
- Provide hashing guidance for large binaries to avoid excessive Offline Kit growth (use external CAS references where possible).
## Detection technique comparison
| Technique | Artifacts | Merge strategy | Notes |
| --- | --- | --- | --- |
| MSI database parsing | `Windows/Installer/*.msi` database tables (Product, Component, File) | Emit component records keyed by ProductCode/ComponentCode; merge with WinSxS manifests using file hashes. | Requires custom MSI reader (Jet/COM-free) compatible with offline bundles. |
| WinSxS manifest enumeration | `Windows/WinSxS/Manifests/*.manifest` | Map assemblies to catalog signatures and MSP patches; merge with MSI output for provenance. | Provides side-by-side assembly version info and language resources. |
| Chocolatey package inspection | `ProgramData/Chocolatey/lib/*/tools` & nuspec metadata | Produce package records with source feed URL, checksum, install scripts. | Feed metadata snapshot required to resolve dependencies offline. |
| Registry uninstall keys | `HKLM/HKCU ... /Uninstall/*` | Fill gaps for legacy installers (non-MSI); merge by install path and display name with file system evidence. | Use hive exports during scan to avoid registry API dependencies. |
| Service/driver mapping | `System32/config/SYSTEM` hive, `System32/DriverStore/FileRepository` | Generate capability overlays (services, drivers) for Policy Engine gating. | Helps differentiate drivers requiring elevated scrutiny (e.g., kernel-mode). |
| Competitor baseline | — | No competitor tool offers deterministic Windows package coverage with offline support. | Opportunity to differentiate once demand justifies scope. |
## Backlog / coordination
- Follow demand capture in `docs/benchmarks/scanner/windows-macos-demand.md`. Once Windows signals meet thresholds, open engineering backlog (see proposed IDs below).
- Coordinate with Offline Kit guild on distributing MSI schema, Chocolatey feed snapshots, and driver catalog signatures.
- Engage Policy guild on required predicates (Authenticode trust, driver risk classes, service start modes).
## Open design questions
| Topic | Question | Owner |
| --- | --- | --- |
| MSI parsing library | Build custom reader or embed open-source MSI parser? Must be AGPL-compatible and offline-ready. | Scanner Guild |
| Driver risk classification | Should Policy Engine treat kernel-mode drivers differently by default? | Policy Guild |
| Authenticodes & catalogs | Where do we verify signature/certificate revocation (scanner vs policy)? | Security Guild |
| Registry access | Will scanner access registry hives directly or require pre-extracted exports? | Scanner + Ops Guild |

View File

@@ -232,12 +232,108 @@
- **Policy considerations**: Policies would need repository allowlists, signing requirements, and OS-specific mitigations; defer concrete templates until design spike completes. - **Policy considerations**: Policies would need repository allowlists, signing requirements, and OS-specific mitigations; defer concrete templates until design spike completes.
- **Next actions**: Execute tasks DOCS-SCANNER-BENCH-62-002/003/004/005/006 as demand signals accrue; only open engineering backlog after demand review approves scope expansion. - **Next actions**: Execute tasks DOCS-SCANNER-BENCH-62-002/003/004/005/006 as demand signals accrue; only open engineering backlog after demand review approves scope expansion.
### Implementation details
- **StellaOps**:
- Linux analyzers live under `StellaOps.Scanner.Analyzers.OS.(Apk|Dpkg|Rpm)` and inherit from `OsPackageAnalyzerBase`, which normalises package metadata, file evidence, and vendor fields before persisting content-addressed fragments via Surface.FS.
- Analyzer results are converted to `LayerComponentFragment`s by `OsComponentMapper` and cached inside the worker `ScanAnalysisStore`; downstream SBOM assembly keeps layer digests and provenance so usage/inventory views can be replayed deterministically.
- Export Center binds OS fragments to DSSE attestations through Signer/Attestor so operators can prove provenance for every package list in offline bundles.
- **Trivy**:
- Package analyzers under `pkg/fanal/analyzer/pkg/(apk|dpkg|rpm)` walk layer file systems and emit `types.Package` results; the upstream coverage matrix in `docs/docs/coverage/os/*.md` drives which distro manifests and feeds ship with Trivy releases.
- Results are flattened per artifact, leaving layer attribution to Syft-style catalog walks; provenance and diffing are delegated to downstream tooling.
- **Grype**:
- Delegates cataloguing to Syft, then applies matchers in `grype/matcher/{apk,dpkg,rpm}` that resolve distro namespaces and fix statuses using Anchore feeds.
- Evidence is matched at scan time without long-lived fragments, so reproducibility depends on feed snapshots rather than packaged artifacts.
- **Snyk**:
- `snyk container test` uploads image metadata to Snyk SaaS; coverage is dictated by the hosted service and cannot run offline.
- No layer-aware evidence is returned; operators rely on SaaS reports for package presence and risk.
### Detection techniques ### Detection techniques
| Technique | Artifacts | Analyzer / Module | Merge strategy | | Technique | Artifacts | Analyzer / Module | Merge strategy |
|-----------|-----------|-------------------|----------------| |-----------|-----------|-------------------|----------------|
| Layer package DB parsing | apk, dpkg, rpm status/databases per layer | StellaOps.Scanner.Analyzers.OS.* with RustFS CAS | Produces per-layer fragments keyed by layer digest; composed into inventory/usage SBOM with provenance pointers. | | Layer package DB parsing | apk, dpkg, rpm status/databases per layer | `StellaOps.Scanner.Analyzers.OS.(Apk|Dpkg|Rpm)` + Surface.FS | Emits `OSPackageRecord` fragments tagged with layer digest; `OsComponentMapper` writes `LayerComponentFragment`s that SBOM assembly uses to build inventory/usage views with provenance. |
| Manifest + attestation binding | Distro manifest attestations, vendor signatures | Export Center + Signer/Attestor hand-off | Binds package fragments to DSSE attestations; policy consumes provenance metadata for trust weighting. | | Manifest + attestation binding | Distro manifest attestations, vendor signatures | Export Center + Signer/Attestor hand-off | Couples OS fragments with DSSE/Rekor proofs; Policy Engine verifies signatures before promotion gates. |
| External SBOM import (interim) | Third-party SBOMs for Windows/macOS | Scanner SBOM import API (planned) | Imports produce declared-only entries flagged for policy review until native analyzers exist. | | Linux distro enrichment | Vendor advisory feeds, package-to-CVE mapping | Concelier + Policy Engine | Concelier ingests advisory metadata; Policy joins advisories with package fragments to produce lattice-scored findings. |
| External SBOM import (interim) | Third-party SBOMs for Windows/macOS | Scanner SBOM import API (planned) | Declared-only entries are merged with runtime evidence; policy downgrades unmatched declarations until native analyzers exist. |
## macOS package coverage (Trivy, Grype, Snyk)
### Scorecard
| Dimension | Score (1-5) | Notes |
|-----------|-------------|-------|
| Customer demand | 2 | macOS coverage requests surface intermittently; demand capture ongoing via `windows-macos-demand.md`. |
| Competitive risk | 2 | Competitors lack macOS analyzers today, but roadmap announcements could erode differentiation quickly. |
| Engineering effort | 4 | Requires new collectors (Homebrew, pkgutil receipts, `.app` bundles) plus Offline Kit tap mirroring. |
| Policy/config impact | 4 | Policies must reason over entitlements, notarization, and signed bundle provenance. |
| Offline/air-gap impact | 4 | Tap metadata, notarization caches, and entitlement schemas must ship offline. |
- **Competitor capability**: None of Trivy, Grype, or Snyk provide macOS host/package coverage; their documentation lists Linux-only ecosystems.
- **StellaOps gap**: No macOS analyzers exist; design work is captured in `docs/benchmarks/scanner/deep-dives/macos.md` but implementation/backlog stories are not yet opened.
- **Proposed plan**:
1. Finalise demand assessment (DOCS-SCANNER-BENCH-62-002) using customer interviews, sales telemetry, and support tags.
2. Scope macOS analyzer design spike covering Homebrew cellar parsing, pkgutil receipt ingestion, and `.app` bundle inspection; include entitlements/notarization strategy.
3. Define Policy Engine predicates for entitlements, notarization status, bundle signing chain, and tenant allow lists.
4. Coordinate with Offline Kit guild on mirroring tap metadata, notarization caches, and CRL/OCSP content for air-gapped operation.
- **Milestones**: Northwind Health Services demo (2025-11-10) doubles as POLICY-READINESS-0001 workshop to finalise masking/telemetry defaults before spike approval.
- **Policy considerations**: Need predicates for `macos.entitlement`, `macos.notarized`, `macos.bundle.teamId`, and severity rules for unsigned or unnotarized software; waivers should bind to bundle hash + signer.
- **Next actions**: Keep `windows-macos-demand.md` updated, prepare design brief once threshold met, and log engineering backlog items (SCANNER-ENG-00xx) for macOS collectors and policy integration.
### Implementation details
- **Design references**: `docs/benchmarks/scanner/deep-dives/macos.md` captures proposed collectors (Homebrew, receipts, bundles) and open questions for Security/Policy guilds.
- **Collector outline**:
- Homebrew collector enumerates Cellar manifests under `/usr/local/Cellar` and `/opt/homebrew/Cellar`, mapping taps to PURLs and retaining bottle SHA256 for provenance.
- pkgutil collector parses `/var/db/receipts/*.plist` and `.bom` files to record installer package metadata with deterministic hashes.
- Bundle inspector walks `.app` directories, extracting Info.plist, entitlements, embedded frameworks, and code signing chains.
- **Merge strategy**: Collectors will emit component fragments keyed by bundle/tap identifiers; planned aggregator merges receipts and cellular data where identifiers match, tagging capabilities for Policy Engine.
- **Offline requirements**: Bundle signed rule packs (tap metadata snapshots, entitlements schema) with Offline Kit; ensure notarization cache instructions are documented.
### Detection techniques
| Technique | Artifacts | Analyzer / Module | Merge strategy |
|-----------|-----------|-------------------|----------------|
| Homebrew cellar parsing (planned) | Cellar manifests, `INSTALL_RECEIPT.json`, tap metadata | Planned `StellaOps.Scanner.Analyzers.OS.Mac.Homebrew` | Emits component records keyed by tap + version; merges duplicates and attaches bottle hashes for provenance. |
| pkgutil receipt parsing (planned) | `/var/db/receipts/*.plist` and `.bom` | Planned `StellaOps.Scanner.Analyzers.OS.Mac.Receipts` | Records installer packages with bundle identifiers; merges with bundle evidence when identifiers align. |
| `.app` bundle inspection (planned) | Info.plist, CodeResources, entitlements, signing certs | Planned `StellaOps.Scanner.Analyzers.OS.Mac.Bundles` | Produces capability evidence (entitlements, hardened runtime) and links to receipts/Homebrew entries via bundle id. |
| Launch agent/daemon analysis (planned) | `/Library/Launch*` manifests, `launchctl` exports | Planned runtime usage mapper | Augments EntryTrace usage hints to distinguish active services. |
| Competitor baseline | — | Trivy/Grype/Snyk | No macOS host analyzers; coverage limited to Linux/container contexts. |
## Windows package coverage (Trivy, Grype, Snyk)
### Scorecard
| Dimension | Score (1-5) | Notes |
|-----------|-------------|-------|
| Customer demand | 3 | Windows Server/container adopters continue to request evidence parity; demand captured via `windows-macos-demand.md`. |
| Competitive risk | 2 | Competitors lack Windows analyzers today but could narrow the gap with roadmap announcements. |
| Engineering effort | 5 | Requires MSI/WinSxS parsers, registry collectors, Chocolatey handling, and extensive Offline Kit work. |
| Policy/config impact | 4 | Policies must interpret Authenticode trust, driver/service posture, and legacy installer artefacts. |
| Offline/air-gap impact | 5 | Need to package MSI schemas, feed snapshots, and certificate bundles; storage overhead is significant. |
- **Competitor capability**: Trivy, Grype, and Snyk do not ship Windows host analyzers; tooling focuses on Linux ecosystems and SaaS flows.
- **StellaOps gap**: No Windows analyzers exist yet; design outline under `docs/benchmarks/scanner/deep-dives/windows.md`.
- **Proposed plan**:
1. Complete demand validation and prioritisation (DOCS-SCANNER-BENCH-62-002) alongside macOS signals.
2. Execute engineering spike covering MSI/WinSxS parsing, Chocolatey inventory, and registry-based fallbacks.
3. Define Policy Engine predicates for Authenticode, driver risk, service start mode, and Chocolatey provenance.
4. Coordinate Offline Kit packaging strategy for MSI schemas, feed snapshots, and certificate revocation caches.
- **Policy considerations**: Introduce predicates such as `windows.package.signed(teamId?)`, `windows.driver.kernelMode`, `windows.service.startType`, and waivers tied to product code + signature thumbprint.
- **Next actions**: Maintain demand tracker, execute DOCS-SCANNER-BENCH-62-016, refine `docs/modules/scanner/design/windows-analyzer.md`, and open SCANNER-ENG-0024..0027 backlog tickets for collector and policy work once demand threshold is confirmed.
- **Milestones**: POLICY-READINESS-0002 Authenticode/feed decision due 2025-11-07 (FinSecure PCI blocker) gates Windows analyzer spikes.
### Implementation details
- **Design references**: `docs/benchmarks/scanner/deep-dives/windows.md`, `docs/modules/scanner/design/windows-analyzer.md`, `docs/api/scanner/windows-coverage.md`.
- **Policy readiness**: see `docs/modules/policy/windows-package-readiness.md` for predicate requirements, waiver model, and offline guidance.
- **Collector outline**:
- MSI/WinSxS collector to parse installer databases/manifests and correlate via file hashes.
- Chocolatey collector to read nuspec metadata and install scripts, retaining feed provenance.
- Registry collector to harvest uninstall/service keys, linking to filesystem artefacts and signatures.
- **Merge strategy**: Planned `WindowsComponentMapper` merges MSI, WinSxS, Chocolatey, and registry evidence into unified fragments with provenance metadata; capability overlays capture services/drivers.
- **Offline requirements**: Bundle MSI schema definitions, Chocolatey feed snapshots, Windows Update catalog hashes, and certificate chains; document cache priming steps for air-gapped environments.
### Detection techniques
| Technique | Artifacts | Analyzer / Module | Merge strategy |
|-----------|-----------|-------------------|----------------|
| MSI database parsing (planned) | `Windows/Installer/*.msi` Product/Component/File tables | Planned `StellaOps.Scanner.Analyzers.OS.Windows.Msi` | Emits component records keyed by product/component codes; merges with WinSxS manifests via file hashes. |
| WinSxS manifest parsing (planned) | `Windows/WinSxS/Manifests/*.manifest`, catalog files | Planned `StellaOps.Scanner.Analyzers.OS.Windows.WinSxS` | Maps assemblies to catalogs and MSP patches; merges with MSI output for provenance. |
| Chocolatey package parsing (planned) | `ProgramData/Chocolatey/lib/*`, nuspec metadata | Planned `StellaOps.Scanner.Analyzers.OS.Windows.Choco` | Records package evidence with feed provenance; merges with registry uninstall data. |
| Registry fallback (planned) | Exported uninstall/service hives | Planned `StellaOps.Scanner.Analyzers.OS.Windows.Registry` | Fills gaps for legacy installers and services; merges evidence by install path/signature. |
| Service/driver capability mapping (planned) | SYSTEM hive, DriverStore manifest | Planned capability overlay | Emits runtime capability records (drivers/services) for Policy Engine gating. |
| Competitor baseline | — | Trivy/Grype/Snyk | No Windows host analyzers; operators depend on external tooling. |
## Secrets leak detection (Trivy, Snyk) ## Secrets leak detection (Trivy, Snyk)
### Scorecard ### Scorecard
@@ -258,14 +354,29 @@
4. Offer CLI verb (`stella secrets scan`) and integration into existing scan workflows behind an opt-in flag. 4. Offer CLI verb (`stella secrets scan`) and integration into existing scan workflows behind an opt-in flag.
5. Expose explain traces detailing rule IDs, masked snippets, and remediation guidance while upholding privacy constraints. 5. Expose explain traces detailing rule IDs, masked snippets, and remediation guidance while upholding privacy constraints.
- **Policy considerations**: Deliver policy templates for severity gating, rule packs per tenant, and privacy controls; lattice logic should discount low-confidence matches. - **Policy considerations**: Deliver policy templates for severity gating, rule packs per tenant, and privacy controls; lattice logic should discount low-confidence matches.
- **Next actions**: open analyzer/CLI backlog work, coordinate with Docs Guild on policy templates, and bundle signed rule packs for Offline Kit distribution. - **Next actions**: Track execution via SCANNER-ENG-0007 (design/implementation) and DOCS-SCANNER-BENCH-62-007 (policy/docs); bundle signed rule packs for Offline Kit distribution once analyzer stories land.
### Implementation details
- **StellaOps**:
- Operational secret retrieval flows through `Surface.Secrets` providers (Kubernetes, file bundle, inline) with validation policies enforced by `Surface.Validation`; handles remain opaque to analyzers.
- Planned `StellaOps.Scanner.Analyzers.Secrets` plug-in will execute deterministic rule bundles signed by the Export Center signing stack; findings land in `ScanAnalysisStore` alongside component fragments.
- Policy Engine will ingest `secret.leak` evidence with lattice hints (`confidence`, `rule.id`, `masking.applied`) so tenants can tune severities and approvals.
- **Trivy**:
- Secret detection is implemented in `pkg/fanal/secret` with detectors combining regex and entropy heuristics; rules merge into `Result` objects per file with severity weighting.
- Configuration is provided via `trivy-secret.yaml`, enabling per-rule enable/disable and allow lists.
- **Snyk**:
- CLI delegates to Snyk Code (`src/lib/plugins/sast`) which uploads source or image contents to SaaS for analysis; results stream back as issue JSON with remediation tips.
- Offline execution is unsupported; rule updates ship server-side.
- **Grype**:
- No leak detection analyzer; secrets are only used for registry authentication options.
### Detection techniques ### Detection techniques
| Technique | Artifacts | Analyzer / Module | Merge strategy | | Technique | Artifacts | Analyzer / Module | Merge strategy |
|-----------|-----------|-------------------|----------------| |-----------|-----------|-------------------|----------------|
| Operational secret retrieval | secret:// references resolved via Surface.Secrets providers | Surface.Secrets, Surface.Validation | Injects secrets at runtime; no SBOM entry created; policy ensures provenance of retrieved credentials. | | Operational secret retrieval | `secret://` references resolved via `Surface.Secrets` providers | Surface.Secrets, Surface.Validation | Injects handles at runtime only; provenance recorded in scan metadata, nothing added to SBOM inventory. |
| Deterministic leak detection (planned) | File content, archives, bytecode | StellaOps.Scanner.Analyzers.Secrets (planned) | Emits secret.leak evidence with masked snippets; Policy Engine merges with package evidence using VEX gating. | | Deterministic leak detection (planned) | File contents, archives, bytecode, container layers | `StellaOps.Scanner.Analyzers.Secrets` plug-in | Produces `secret.leak` records stored in `ScanAnalysisStore`; Policy Engine correlates with component metadata for context-aware enforcement. |
| Competitor leak scanning | Regex/entropy rulesets (Trivy pkg/fanal/secret), Snyk Code SaaS service | Trivy secret analyzer, Snyk Code API | Findings remain separate from SBOM data; StellaOps will map to policy evidence types once analyzer ships. | | Policy gating and reporting | Secret evidence + policy templates | Policy Engine, CLI/Export Center | Lattice scores combine confidence + severity; CLI/report output masks payloads while referencing rule IDs for explainability. |
| Competitor leak scanning | Regex/entropy rule sets, SaaS classifiers | Trivy `pkg/fanal/secret`; Snyk Code service | Trivy merges detectors per file; Snyk relies on SaaS analysis; neither binds results to SBOM evidence or deterministic attestations. |
## EntryTrace runtime command resolution (Trivy, Grype, Snyk) ## EntryTrace runtime command resolution (Trivy, Grype, Snyk)
### Scorecard ### Scorecard
@@ -314,12 +425,23 @@
- **Policy considerations**: Provide policy predicates for attestation presence, Rekor inclusion, and proof expiry to enforce promotion gates. - **Policy considerations**: Provide policy predicates for attestation presence, Rekor inclusion, and proof expiry to enforce promotion gates.
- **Next actions**: Track via DOCS-SCANNER-BENCH-62-015 and SCANNER-ENG-0015 for playbook plus tooling updates. - **Next actions**: Track via DOCS-SCANNER-BENCH-62-015 and SCANNER-ENG-0015 for playbook plus tooling updates.
### Implementation details
- **StellaOps**:
- `StellaOps.Signer` generates DSSE envelopes for SBOMs/reports using PoE-scoped keys and forwards them to `StellaOps.Attestor`, which handles Rekor v2 submissions with retries and proof caching.
- Export Center profiles bundle DSSE payloads, Rekor inclusion proofs, and any external attestations into offline-ready archives; CLI and Policy Engine verify proofs before release.
- Notify + Scanner.WebService emit attestation health telemetry so operators can quickly spot and remediate failed Rekor submissions.
- **Trivy / Grype / Snyk**:
- Trivy supports optional Cosign signing but leaves Rekor submission manual; proofs are not bundled with scanner outputs.
- Grype leans on Syft for SBOM export and does not sign outputs.
- Snyk Container/Snyk CLI rely on SaaS-managed signing and do not expose DSSE workflows or offline proof packaging.
### Detection techniques ### Detection techniques
| Technique | Artifacts | Analyzer / Module | Merge strategy | | Technique | Artifacts | Analyzer / Module | Merge strategy |
|-----------|-----------|-------------------|----------------| |-----------|-----------|-------------------|----------------|
| SBOM emission | CycloneDX/SPDX payloads per scan | Scanner emit pipelines | Generates inventory/usage BOMs stored with CAS hashes for attestation. | | SBOM emission | CycloneDX/SPDX payloads per scan | Scanner emit pipelines | Generates inventory/usage BOMs stored with CAS hashes for attestation. |
| DSSE signing | DSSE bundles, signing keys | StellaOps.Signer + StellaOps.Attestor | Signs SBOM/report metadata, forwards to Rekor v2, records proof identifiers. | | DSSE signing | DSSE bundles, signing keys | StellaOps.Signer + StellaOps.Attestor | Signs SBOM/report metadata, forwards to Rekor v2, records proof identifiers. |
| Rekor proof packaging | Rekor inclusion proofs, bundle metadata | Export Center attestation packager | Bundles proofs into Offline Kit/export artifacts; Policy verifies before release. | | Rekor proof packaging | Rekor inclusion proofs, bundle metadata | Export Center attestation packager | Bundles proofs into Offline Kit/export artifacts; Policy verifies before release. |
| Policy enforcement | Attestation & proof evidence | Policy Engine, Scheduler gates | Policies require successful DSSE/Rekor entries before promotion; Scheduler blocks exports lacking proofs. |
| Competitor approach | CLI or SaaS-managed signing | Trivy Cosign integration, Snyk SaaS, Grype none | Operators must integrate manually; no default policy enforcement. | | Competitor approach | CLI or SaaS-managed signing | Trivy Cosign integration, Snyk SaaS, Grype none | Operators must integrate manually; no default policy enforcement. |
## Ruby analyzer parity (Trivy, Grype, Snyk) ## Ruby analyzer parity (Trivy, Grype, Snyk)

View File

@@ -10,8 +10,24 @@
2. **Sales & SE feedback loop** capture any RFP items referencing Windows/macOS scanning and log them in the Scanner guild tracker (SCANNER-ANALYZERS-OS-*). 2. **Sales & SE feedback loop** capture any RFP items referencing Windows/macOS scanning and log them in the Scanner guild tracker (SCANNER-ANALYZERS-OS-*).
3. **Support telemetry** review ticket tags for “windows”, “macos”, “dotnet framework” to quantify inbound demand. 3. **Support telemetry** review ticket tags for “windows”, “macos”, “dotnet framework” to quantify inbound demand.
4. **Community landscape** monitor Trivy/Grype/Snyk release notes for Windows/macOS announcements; update this note and the feature matrix when competitors change posture. 4. **Community landscape** monitor Trivy/Grype/Snyk release notes for Windows/macOS announcements; update this note and the feature matrix when competitors change posture.
5. **Interview discipline** use the structured questionnaire in `windows-macos-interview-template.md` to ensure consistent scoring and capture follow-up actions.
## Signals log — macOS
| Date (YYYY-MM-DD) | Source / Account | Use case | Demand strength (1-5) | Notes / follow-up |
|-------------------|------------------|----------|------------------------|-------------------|
| 2025-11-03 | Northwind Health Services (NA) | macOS CI runners require notarization evidence for release sign-off | 4 | Demo deterministic bundle inspection w/ Product on 2025-11-10; capture entitlements policy requirements. |
## Signals log — Windows
| Date (YYYY-MM-DD) | Source / Account | Use case | Demand strength (1-5) | Notes / follow-up |
|-------------------|------------------|----------|------------------------|-------------------|
| 2025-11-03 | FinSecure Corp (NA) | Windows Server 2019 images need MSI/WinSxS SBOM + signed driver attestations for PCI audit | 5 | Blocking go-live; Security guild to confirm Authenticode posture (POLICY-READINESS-0002) by 2025-11-07. |
## Next actions ## Next actions
- Coordinate with Product Marketing to add Windows/macOS discovery prompts into upcoming customer advisory sessions (target: Sprint 132 intake). - Coordinate with Product Marketing to add Windows/macOS discovery prompts into upcoming customer advisory sessions (target: Sprint 132 intake).
- Instrument the scanner roadmap intake form with explicit checkboxes for Windows/macOS package ecosystems. - Instrument the scanner roadmap intake form with explicit checkboxes for Windows/macOS package ecosystems.
- If three or more qualified customers flag Windows/macOS coverage as a blocking requirement, open a design spike under the Scanner Analyzer Guild with scope/time estimates and Offline Kit considerations. - If three or more qualified customers flag Windows/macOS coverage as a blocking requirement, open a design spike under the Scanner Analyzer Guild with scope/time estimates and Offline Kit considerations.
- Keep the macOS deep dive (`docs/benchmarks/scanner/deep-dives/macos.md`) in sync with demand findings so engineering can move from design sketch to formal backlog when thresholds are met.
- Update the Windows deep dive (`docs/benchmarks/scanner/deep-dives/windows.md`) and associated design briefs (`docs/modules/scanner/design/windows-analyzer.md`) as new signals arrive.
- Refresh API dashboards (`docs/api/scanner/windows-macos-summary.md`, `docs/api/scanner/windows-coverage.md`) after each update to keep Product and Field teams aligned.
- Drive POLICY-READINESS-0002 Authenticode/feed decision by 2025-11-07 (FinSecure PCI blocker); log outcome in dashboards and design briefs.
- Prepare POLICY-READINESS-0001 workshop aligned with Northwind demo on 2025-11-10, updating policy briefs with masking/telemetry decisions.

View File

@@ -0,0 +1,50 @@
# Windows / macOS Analyzer Demand — Interview Template
Use this template during customer interviews, SE discovery calls, or product advisory meetings. Copy the table into your meeting notes and fill in the responses. Summaries should be pushed back into `windows-macos-demand.md`.
## Interview metadata
| Field | Notes |
| --- | --- |
| Date | `YYYY-MM-DD` |
| Interviewer(s) | |
| Customer / Account | |
| Participant roles | (e.g., platform lead, security architect) |
| Workload context | (container images, VMs, desktop fleets, CI pipelines, etc.) |
## Current state
1. **Operating systems in scope**
- Which Windows or macOS versions/images are mission critical?
- Container vs VM vs bare-metal distribution?
2. **Existing tooling**
- What scanners or inventory tools are used today (e.g., SCCM, Tanium, Trivy, Snyk, custom scripts)?
- Pain points / gaps they experience (offline support, provenance, coverage, explainability).
3. **Regulatory / compliance drivers**
- Any specific frameworks (PCI, FedRAMP, DISA, internal policies) mandating Windows/macOS SBOM or attestation?
## Desired capabilities (score 15 per feature)
| Capability | Score | Notes |
| --- | --- | --- |
| MSI / WinSxS package inventory | | |
| Chocolatey / third-party feed tracking | | |
| macOS Homebrew / pkgutil receipts | | |
| `.app` bundle inspection (signing, entitlements) | | |
| Driver / service posture | | |
| Authenticode / notarization verification | | |
| Offline/air-gap parity | | |
| Policy integration (e.g., block unsigned driver) | | |
## Operational requirements
- **Offline expectations**: Do they require artefact mirroring? Which feeds?
- **Performance**: Time budget for scans? Incremental vs full?
- **Evidence formats**: Preferred SBOM types, attestation needs, API endpoints.
- **Secrets / credentials**: Any constraints for registry/hive exports or feed mirrors?
## Success metrics
- How will the customer judge success? (e.g., number of workloads covered, audit findings reduced, ability to prove provenance).
- Timeline expectations for pilot vs GA?
## Follow-up actions
- What next steps were promised (POC, roadmap update, integration with other guilds)?
- Owners + due dates.
> After the interview: convert highlights into a concise row in `windows-macos-demand.md` and, if needed, create Jira/backlog items for SCANNER-ENG-0020..0027 or DOCS-SCANNER-BENCH-62-016 with the captured context.

View File

@@ -1,18 +1,18 @@
# Vexer Connector Packaging Guide # Excitor Connector Packaging Guide
> **Audience:** teams implementing new Vexer provider plugins (CSAF feeds, > **Audience:** teams implementing new Excitor provider plugins (CSAF feeds,
> OpenVEX attestations, etc.) > OpenVEX attestations, etc.)
> **Prerequisites:** read `docs/modules/vexer/architecture.md` and the module > **Prerequisites:** read `docs/modules/excitor/architecture.md` and the module
> `AGENTS.md` in `src/Excititor/__Libraries/StellaOps.Excititor.Connectors.Abstractions/`. > `AGENTS.md` in `src/Excititor/__Libraries/StellaOps.Excititor.Connectors.Abstractions/`.
The Vexer connector SDK gives you: The Excitor connector SDK gives you:
- `VexConnectorBase` deterministic logging, SHA256 helpers, time provider. - `VexConnectorBase` deterministic logging, SHA256 helpers, time provider.
- `VexConnectorOptionsBinder` strongly typed YAML/JSON configuration binding. - `VexConnectorOptionsBinder` strongly typed YAML/JSON configuration binding.
- `IVexConnectorOptionsValidator<T>` custom validation hooks (offline defaults, auth invariants). - `IVexConnectorOptionsValidator<T>` custom validation hooks (offline defaults, auth invariants).
- `VexConnectorDescriptor` & metadata helpers for consistent telemetry. - `VexConnectorDescriptor` & metadata helpers for consistent telemetry.
This guide explains how to package a connector so the Vexer Worker/WebService This guide explains how to package a connector so the Excitor Worker/WebService
can load it via the plugin host. can load it via the plugin host.
--- ---
@@ -20,12 +20,12 @@ can load it via the plugin host.
## 1. Project layout ## 1. Project layout
Start from the template under Start from the template under
`docs/dev/templates/vexer-connector/`. It contains: `docs/dev/templates/excitor-connector/`. It contains:
``` ```
Vexer.MyConnector/ Excitor.MyConnector/
├── src/ ├── src/
│ ├── Vexer.MyConnector.csproj │ ├── Excitor.MyConnector.csproj
│ ├── MyConnectorOptions.cs │ ├── MyConnectorOptions.cs
│ ├── MyConnector.cs │ ├── MyConnector.cs
│ └── MyConnectorPlugin.cs │ └── MyConnectorPlugin.cs
@@ -36,8 +36,8 @@ Vexer.MyConnector/
Key points: Key points:
- Target `net10.0`, enable `TreatWarningsAsErrors`, reference the - Target `net10.0`, enable `TreatWarningsAsErrors`, reference the
`StellaOps.Vexer.Connectors.Abstractions` project (or NuGet once published). `StellaOps.Excitor.Connectors.Abstractions` project (or NuGet once published).
- Keep project ID prefix `StellaOps.Vexer.Connectors.<Provider>` so the - Keep project ID prefix `StellaOps.Excitor.Connectors.<Provider>` so the
plugin loader can discover it with the default search pattern. plugin loader can discover it with the default search pattern.
### 1.1 csproj snippet ### 1.1 csproj snippet
@@ -51,7 +51,7 @@ Key points:
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\..\src\StellaOps.Vexer.Connectors.Abstractions\StellaOps.Vexer.Connectors.Abstractions.csproj" /> <ProjectReference Include="..\..\..\src\StellaOps.Excitor.Connectors.Abstractions\StellaOps.Excitor.Connectors.Abstractions.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>
``` ```
@@ -135,7 +135,7 @@ this contract today.
public sealed class MyConnectorPlugin : IConnectorPlugin public sealed class MyConnectorPlugin : IConnectorPlugin
{ {
private static readonly VexConnectorDescriptor Descriptor = private static readonly VexConnectorDescriptor Descriptor =
new("vexer:my-provider", VexProviderKind.Vendor, "My Provider VEX"); new("excitor:my-provider", VexProviderKind.Vendor, "My Provider VEX");
public string Name => Descriptor.DisplayName; public string Name => Descriptor.DisplayName;
@@ -150,8 +150,8 @@ public sealed class MyConnectorPlugin : IConnectorPlugin
} }
``` ```
> **Note:** the Vexer Worker currently instantiates connectors through the > **Note:** the Excitor Worker currently instantiates connectors through the
> shared `IConnectorPlugin` contract. Once a dedicated Vexer plugin interface > shared `IConnectorPlugin` contract. Once a dedicated Excitor plugin interface
> lands you simply swap the base interface; the descriptor/connector code > lands you simply swap the base interface; the descriptor/connector code
> remains unchanged. > remains unchanged.
@@ -159,18 +159,18 @@ Provide a manifest describing the assembly for operational tooling:
```yaml ```yaml
# manifest/connector.manifest.yaml # manifest/connector.manifest.yaml
id: vexer-my-provider id: excitor-my-provider
assembly: StellaOps.Vexer.Connectors.MyProvider.dll assembly: StellaOps.Excitor.Connectors.MyProvider.dll
entryPoint: StellaOps.Vexer.Connectors.MyProvider.MyConnectorPlugin entryPoint: StellaOps.Excitor.Connectors.MyProvider.MyConnectorPlugin
description: > description: >
Official VEX feed for ExampleCorp products (CSAF JSON, daily updates). Official VEX feed for ExampleCorp products (CSAF JSON, daily updates).
tags: tags:
- vexer - excitor
- csaf - csaf
- vendor - vendor
``` ```
Store manifests under `/opt/stella/vexer/plugins/<connector>/manifest/` in Store manifests under `/opt/stella/excitor/plugins/<connector>/manifest/` in
production so the deployment tooling can inventory and verify plugins. production so the deployment tooling can inventory and verify plugins.
--- ---
@@ -178,9 +178,9 @@ production so the deployment tooling can inventory and verify plugins.
## 4. Packaging workflow ## 4. Packaging workflow
1. `dotnet publish -c Release` → copy the published DLLs to 1. `dotnet publish -c Release` → copy the published DLLs to
`/opt/stella/vexer/plugins/<Provider>/`. `/opt/stella/excitor/plugins/<Provider>/`.
2. Place `connector.manifest.yaml` next to the binaries. 2. Place `connector.manifest.yaml` next to the binaries.
3. Restart the Vexer Worker or WebService (hot reload not supported yet). 3. Restart the Excitor Worker or WebService (hot reload not supported yet).
4. Verify logs: `VEX-ConnectorLoader` should list the connector descriptor. 4. Verify logs: `VEX-ConnectorLoader` should list the connector descriptor.
### 4.1 Offline kits ### 4.1 Offline kits
@@ -195,7 +195,7 @@ production so the deployment tooling can inventory and verify plugins.
## 5. Testing checklist ## 5. Testing checklist
- Unit tests around options binding & validators. - Unit tests around options binding & validators.
- Integration tests (future `StellaOps.Vexer.Connectors.Abstractions.Tests`) - Integration tests (future `StellaOps.Excitor.Connectors.Abstractions.Tests`)
verifying deterministic logging scopes: verifying deterministic logging scopes:
`logger.BeginScope` should produce `vex.connector.id`, `vex.connector.kind`, `logger.BeginScope` should produce `vex.connector.id`, `vex.connector.kind`,
and `vex.connector.operation`. and `vex.connector.operation`.
@@ -206,7 +206,7 @@ production so the deployment tooling can inventory and verify plugins.
## 6. Reference template ## 6. Reference template
See `docs/dev/templates/vexer-connector/` for the full quickstart including: See `docs/dev/templates/excitor-connector/` for the full quickstart including:
- Sample options class + validator. - Sample options class + validator.
- Connector implementation inheriting from `VexConnectorBase`. - Connector implementation inheriting from `VexConnectorBase`.

View File

@@ -0,0 +1,8 @@
id: excitor-my-provider
assembly: StellaOps.Excitor.Connectors.MyProvider.dll
entryPoint: StellaOps.Excitor.Connectors.MyProvider.MyConnectorPlugin
description: |
Example connector template. Replace metadata before shipping.
tags:
- excitor
- template

View File

@@ -7,6 +7,6 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<!-- Adjust the relative path when copying this template into a repo --> <!-- Adjust the relative path when copying this template into a repo -->
<ProjectReference Include="..\..\..\..\src\StellaOps.Vexer.Connectors.Abstractions\StellaOps.Vexer.Connectors.Abstractions.csproj" /> <ProjectReference Include="..\..\..\..\src\StellaOps.Excitor.Connectors.Abstractions\StellaOps.Excitor.Connectors.Abstractions.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -2,10 +2,10 @@ using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using StellaOps.Vexer.Connectors.Abstractions; using StellaOps.Excitor.Connectors.Abstractions;
using StellaOps.Vexer.Core; using StellaOps.Excitor.Core;
namespace StellaOps.Vexer.Connectors.MyProvider; namespace StellaOps.Excitor.Connectors.MyProvider;
public sealed class MyConnector : VexConnectorBase public sealed class MyConnector : VexConnectorBase
{ {

View File

@@ -1,6 +1,6 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
namespace StellaOps.Vexer.Connectors.MyProvider; namespace StellaOps.Excitor.Connectors.MyProvider;
public sealed class MyConnectorOptions public sealed class MyConnectorOptions
{ {

View File

@@ -1,7 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using StellaOps.Vexer.Connectors.Abstractions; using StellaOps.Excitor.Connectors.Abstractions;
namespace StellaOps.Vexer.Connectors.MyProvider; namespace StellaOps.Excitor.Connectors.MyProvider;
public sealed class MyConnectorOptionsValidator : IVexConnectorOptionsValidator<MyConnectorOptions> public sealed class MyConnectorOptionsValidator : IVexConnectorOptionsValidator<MyConnectorOptions>
{ {

View File

@@ -1,15 +1,15 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using StellaOps.Plugin; using StellaOps.Plugin;
using StellaOps.Vexer.Connectors.Abstractions; using StellaOps.Excitor.Connectors.Abstractions;
using StellaOps.Vexer.Core; using StellaOps.Excitor.Core;
namespace StellaOps.Vexer.Connectors.MyProvider; namespace StellaOps.Excitor.Connectors.MyProvider;
public sealed class MyConnectorPlugin : IConnectorPlugin public sealed class MyConnectorPlugin : IConnectorPlugin
{ {
private static readonly VexConnectorDescriptor Descriptor = new( private static readonly VexConnectorDescriptor Descriptor = new(
id: "vexer:my-provider", id: "excitor:my-provider",
kind: VexProviderKind.Vendor, kind: VexProviderKind.Vendor,
displayName: "My Provider VEX"); displayName: "My Provider VEX");

View File

@@ -1,8 +0,0 @@
id: vexer-my-provider
assembly: StellaOps.Vexer.Connectors.MyProvider.dll
entryPoint: StellaOps.Vexer.Connectors.MyProvider.MyConnectorPlugin
description: |
Example connector template. Replace metadata before shipping.
tags:
- vexer
- template

View File

@@ -14,6 +14,13 @@ Follow the sprint files below in order. Update task status in both `SPRINTS` and
- [Ops & Offline](./SPRINT_190_ops_offline.md) - [Ops & Offline](./SPRINT_190_ops_offline.md)
- [Documentation & Process](./SPRINT_200_documentation_process.md) - [Documentation & Process](./SPRINT_200_documentation_process.md)
> 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-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-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-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: 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. > 2025-11-01: ENTRYTRACE-SURFACE-01 moved to DOING (EntryTrace Guild) wiring Surface.Validation and Surface.FS reuse ahead of EntryTrace runs.

View File

@@ -24,7 +24,7 @@ This file describe implementation of Stella Ops (docs/README.md). Implementation
| Sprint 8 | Plugin Infrastructure | src/Authority/StellaOps.Authority/TASKS.md | DONE (2025-10-20) | Authority Core, Plugin Platform Guild | AUTH-PLUGIN-COORD-08-002 | Coordinate scoped-service adoption for Authority plug-in registrars<br>Workshop notes and follow-up backlog captured 2025-10-20 in `docs/dev/authority-plugin-di-coordination.md`. | | Sprint 8 | Plugin Infrastructure | src/Authority/StellaOps.Authority/TASKS.md | DONE (2025-10-20) | Authority Core, Plugin Platform Guild | AUTH-PLUGIN-COORD-08-002 | Coordinate scoped-service adoption for Authority plug-in registrars<br>Workshop notes and follow-up backlog captured 2025-10-20 in `docs/dev/authority-plugin-di-coordination.md`. |
| Sprint 9 | Scanner Core Foundations | src/Scanner/StellaOps.Scanner.WebService/TASKS.md | DONE (2025-10-19) | Team Scanner WebService | SCANNER-WEB-09-103 | Progress streaming (SSE/JSONL) with correlation IDs and ISO-8601 UTC timestamps, documented in API reference. | | Sprint 9 | Scanner Core Foundations | src/Scanner/StellaOps.Scanner.WebService/TASKS.md | DONE (2025-10-19) | Team Scanner WebService | SCANNER-WEB-09-103 | Progress streaming (SSE/JSONL) with correlation IDs and ISO-8601 UTC timestamps, documented in API reference. |
| Sprint 9 | Scanner Core Foundations | src/Scanner/StellaOps.Scanner.WebService/TASKS.md | DONE (2025-10-19) | Team Scanner WebService | SCANNER-POLICY-09-105 | Policy snapshot loader + schema + OpenAPI (YAML ignore rules, VEX include/exclude, vendor precedence). | | Sprint 9 | Scanner Core Foundations | src/Scanner/StellaOps.Scanner.WebService/TASKS.md | DONE (2025-10-19) | Team Scanner WebService | SCANNER-POLICY-09-105 | Policy snapshot loader + schema + OpenAPI (YAML ignore rules, VEX include/exclude, vendor precedence). |
| Sprint 9 | Scanner Core Foundations | src/Scanner/StellaOps.Scanner.WebService/TASKS.md | DONE (2025-10-19) | Team Scanner WebService | SCANNER-POLICY-09-106 | `/reports` verdict assembly (Feedser+Vexer+Policy) + signed response envelope. | | Sprint 9 | Scanner Core Foundations | src/Scanner/StellaOps.Scanner.WebService/TASKS.md | DONE (2025-10-19) | Team Scanner WebService | SCANNER-POLICY-09-106 | `/reports` verdict assembly (Conselier+Excitor+Policy) + signed response envelope. |
| Sprint 9 | Scanner Core Foundations | src/Scanner/StellaOps.Scanner.WebService/TASKS.md | DONE (2025-10-19) | Team Scanner WebService | SCANNER-POLICY-09-107 | Expose score inputs, config version, and quiet provenance in `/reports` JSON and signed payload. | | Sprint 9 | Scanner Core Foundations | src/Scanner/StellaOps.Scanner.WebService/TASKS.md | DONE (2025-10-19) | Team Scanner WebService | SCANNER-POLICY-09-107 | Expose score inputs, config version, and quiet provenance in `/reports` JSON and signed payload. |
| Sprint 9 | DevOps Foundations | ops/devops/TASKS.md | DONE (2025-10-21) | DevOps Guild, Scanner WebService Guild | DEVOPS-SCANNER-09-204 | Surface `SCANNER__EVENTS__*` env config across Compose/Helm and document overrides. | | Sprint 9 | DevOps Foundations | ops/devops/TASKS.md | DONE (2025-10-21) | DevOps Guild, Scanner WebService Guild | DEVOPS-SCANNER-09-204 | Surface `SCANNER__EVENTS__*` env config across Compose/Helm and document overrides. |
| Sprint 9 | DevOps Foundations | ops/devops/TASKS.md | DONE (2025-10-21) | DevOps Guild, Notify Guild | DEVOPS-SCANNER-09-205 | Notify smoke job validates Redis stream + Notify deliveries after staging deploys. | | Sprint 9 | DevOps Foundations | ops/devops/TASKS.md | DONE (2025-10-21) | DevOps Guild, Notify Guild | DEVOPS-SCANNER-09-205 | Notify smoke job validates Redis stream + Notify deliveries after staging deploys. |

View File

@@ -20,7 +20,7 @@ This file describe implementation of Stella Ops (docs/README.md). Implementation
| Sprint 12 | Runtime Guardrails | src/Zastava/StellaOps.Zastava.Webhook/TASKS.md | DONE (2025-10-24) | Zastava Webhook Guild | ZASTAVA-WEBHOOK-12-103 | Caching, fail-open/closed toggles, metrics/logging for admission decisions. | | Sprint 12 | Runtime Guardrails | src/Zastava/StellaOps.Zastava.Webhook/TASKS.md | DONE (2025-10-24) | Zastava Webhook Guild | ZASTAVA-WEBHOOK-12-103 | Caching, fail-open/closed toggles, metrics/logging for admission decisions. |
| Sprint 12 | Runtime Guardrails | src/Zastava/StellaOps.Zastava.Webhook/TASKS.md | DONE (2025-10-24) | Zastava Webhook Guild | ZASTAVA-WEBHOOK-12-104 | Wire `/admission` endpoint to runtime policy client and emit allow/deny envelopes. | | Sprint 12 | Runtime Guardrails | src/Zastava/StellaOps.Zastava.Webhook/TASKS.md | DONE (2025-10-24) | Zastava Webhook Guild | ZASTAVA-WEBHOOK-12-104 | Wire `/admission` endpoint to runtime policy client and emit allow/deny envelopes. |
| Sprint 12 | Runtime Guardrails | src/Scanner/StellaOps.Scanner.WebService/TASKS.md | DONE (2025-10-24) | Scanner WebService Guild | SCANNER-RUNTIME-12-302 | `/policy/runtime` endpoint joining SBOM baseline + policy verdict, returning admission guidance. | | Sprint 12 | Runtime Guardrails | src/Scanner/StellaOps.Scanner.WebService/TASKS.md | DONE (2025-10-24) | Scanner WebService Guild | SCANNER-RUNTIME-12-302 | `/policy/runtime` endpoint joining SBOM baseline + policy verdict, returning admission guidance. |
| Sprint 12 | Runtime Guardrails | src/Scanner/StellaOps.Scanner.WebService/TASKS.md | DONE (2025-10-24) | Scanner WebService Guild | SCANNER-RUNTIME-12-303 | Align `/policy/runtime` verdicts with canonical policy evaluation (Feedser/Vexer). | | Sprint 12 | Runtime Guardrails | src/Scanner/StellaOps.Scanner.WebService/TASKS.md | DONE (2025-10-24) | Scanner WebService Guild | SCANNER-RUNTIME-12-303 | Align `/policy/runtime` verdicts with canonical policy evaluation (Conselier/Excitor). |
| Sprint 12 | Runtime Guardrails | src/Scanner/StellaOps.Scanner.WebService/TASKS.md | DONE (2025-10-24) | Scanner WebService Guild | SCANNER-RUNTIME-12-304 | Integrate attestation verification into runtime policy metadata. | | Sprint 12 | Runtime Guardrails | src/Scanner/StellaOps.Scanner.WebService/TASKS.md | DONE (2025-10-24) | Scanner WebService Guild | SCANNER-RUNTIME-12-304 | Integrate attestation verification into runtime policy metadata. |
| Sprint 12 | Runtime Guardrails | src/Scanner/StellaOps.Scanner.WebService/TASKS.md | DONE (2025-10-24) | Scanner WebService Guild | SCANNER-RUNTIME-12-305 | Deliver shared fixtures + e2e validation with Zastava/CLI teams. | | Sprint 12 | Runtime Guardrails | src/Scanner/StellaOps.Scanner.WebService/TASKS.md | DONE (2025-10-24) | Scanner WebService Guild | SCANNER-RUNTIME-12-305 | Deliver shared fixtures + e2e validation with Zastava/CLI teams. |
| Sprint 13 | UX & CLI Experience | src/UI/StellaOps.UI/TASKS.md | DONE (2025-10-23) | UI Guild | UI-AUTH-13-001 | Integrate Authority OIDC + DPoP flows with session management. | | Sprint 13 | UX & CLI Experience | src/UI/StellaOps.UI/TASKS.md | DONE (2025-10-23) | UI Guild | UI-AUTH-13-001 | Integrate Authority OIDC + DPoP flows with session management. |

View File

@@ -19,7 +19,7 @@ This file describe implementation of Stella Ops (docs/README.md). Implementation
| Sprint 16 | Scheduler Intelligence | src/Scheduler/__Libraries/StellaOps.Scheduler.ImpactIndex/TASKS.md | DONE (2025-10-26) | Scheduler ImpactIndex Guild | SCHED-IMPACT-16-301 | Ingest BOM-Index into roaring bitmap store. | | Sprint 16 | Scheduler Intelligence | src/Scheduler/__Libraries/StellaOps.Scheduler.ImpactIndex/TASKS.md | DONE (2025-10-26) | Scheduler ImpactIndex Guild | SCHED-IMPACT-16-301 | Ingest BOM-Index into roaring bitmap store. |
| Sprint 16 | Scheduler Intelligence | src/Scheduler/StellaOps.Scheduler.WebService/TASKS.md | DONE (2025-10-26) | Scheduler WebService Guild | SCHED-WEB-16-102 | Schedules CRUD (cron validation, pause/resume, audit). | | Sprint 16 | Scheduler Intelligence | src/Scheduler/StellaOps.Scheduler.WebService/TASKS.md | DONE (2025-10-26) | Scheduler WebService Guild | SCHED-WEB-16-102 | Schedules CRUD (cron validation, pause/resume, audit). |
| Sprint 16 | Scheduler Intelligence | src/Scheduler/StellaOps.Scheduler.WebService/TASKS.md | DONE (2025-10-26) | Scheduler WebService Guild | SCHED-WEB-16-103 | Runs API (list/detail/cancel) + impact previews. | | Sprint 16 | Scheduler Intelligence | src/Scheduler/StellaOps.Scheduler.WebService/TASKS.md | DONE (2025-10-26) | Scheduler WebService Guild | SCHED-WEB-16-103 | Runs API (list/detail/cancel) + impact previews. |
| Sprint 16 | Scheduler Intelligence | src/Scheduler/StellaOps.Scheduler.WebService/TASKS.md | DONE (2025-10-27) | Scheduler WebService Guild | SCHED-WEB-16-104 | Feedser/Vexer webhook handlers with security enforcement. | | Sprint 16 | Scheduler Intelligence | src/Scheduler/StellaOps.Scheduler.WebService/TASKS.md | DONE (2025-10-27) | Scheduler WebService Guild | SCHED-WEB-16-104 | Conselier/Excitor webhook handlers with security enforcement. |
| Sprint 17 | Symbol Intelligence & Forensics | docs/TASKS.md | DONE (2025-10-26) | Docs Guild | DOCS-RUNTIME-17-004 | Document build-id workflows for SBOMs, runtime events, and debug-store usage. | | Sprint 17 | Symbol Intelligence & Forensics | docs/TASKS.md | DONE (2025-10-26) | Docs Guild | DOCS-RUNTIME-17-004 | Document build-id workflows for SBOMs, runtime events, and debug-store usage. |
| Sprint 17 | Symbol Intelligence & Forensics | ops/devops/TASKS.md | DONE (2025-10-26) | DevOps Guild | DEVOPS-REL-17-002 | Ship stripped debug artifacts organised by build-id within release/offline kits. | | Sprint 17 | Symbol Intelligence & Forensics | ops/devops/TASKS.md | DONE (2025-10-26) | DevOps Guild | DEVOPS-REL-17-002 | Ship stripped debug artifacts organised by build-id within release/offline kits. |
| Sprint 17 | Symbol Intelligence & Forensics | ops/offline-kit/TASKS.md | DONE (2025-10-26) | Offline Kit Guild, DevOps Guild | DEVOPS-OFFLINE-17-003 | Mirror release debug-store artefacts into Offline Kit packaging and document validation. | | Sprint 17 | Symbol Intelligence & Forensics | ops/offline-kit/TASKS.md | DONE (2025-10-26) | Offline Kit Guild, DevOps Guild | DEVOPS-OFFLINE-17-003 | Mirror release debug-store artefacts into Offline Kit packaging and document validation. |

View File

@@ -162,7 +162,7 @@ This file describe implementation of Stella Ops (docs/README.md). Implementation
| Sprint 23 | StellaOps Console | src/Web/StellaOps.Web/TASKS.md | TODO | BE-Base Platform Guild, Policy Guild | WEB-CONSOLE-23-003 | Expose `/console/exports` orchestration for evidence bundles, CSV/JSON streaming, manifest retrieval. | | Sprint 23 | StellaOps Console | src/Web/StellaOps.Web/TASKS.md | TODO | BE-Base Platform Guild, Policy Guild | WEB-CONSOLE-23-003 | Expose `/console/exports` orchestration for evidence bundles, CSV/JSON streaming, manifest retrieval. |
| Sprint 23 | StellaOps Console | src/Web/StellaOps.Web/TASKS.md | TODO | BE-Base Platform Guild | WEB-CONSOLE-23-004 | Implement `/console/search` fan-out router for CVE/GHSA/PURL/SBOM lookups with caching and RBAC. | | Sprint 23 | StellaOps Console | src/Web/StellaOps.Web/TASKS.md | TODO | BE-Base Platform Guild | WEB-CONSOLE-23-004 | Implement `/console/search` fan-out router for CVE/GHSA/PURL/SBOM lookups with caching and RBAC. |
| Sprint 23 | StellaOps Console | src/Web/StellaOps.Web/TASKS.md | TODO | BE-Base Platform Guild, DevOps Guild | WEB-CONSOLE-23-005 | Serve `/console/downloads` manifest with signed image metadata and offline guidance. | | Sprint 23 | StellaOps Console | src/Web/StellaOps.Web/TASKS.md | TODO | BE-Base Platform Guild, DevOps Guild | WEB-CONSOLE-23-005 | Serve `/console/downloads` manifest with signed image metadata and offline guidance. |
| Sprint 24 | Graph & Vuln Explorer v1 | src/Authority/StellaOps.Authority/TASKS.md | TODO | Authority Core Guild | AUTH-VULN-24-001 | Extend scopes (`vuln:read`) and signed permalinks. | | Sprint 24 | Graph & Vuln Explorer v1 | src/Authority/StellaOps.Authority/TASKS.md | TODO | Authority Core Guild | AUTH-VULN-24-001 | Extend scopes (`vuln:view`/`vuln:investigate`/`vuln:operate`/`vuln:audit`) and signed permalinks. |
> 2025-10-27: Scope enforcement spike paused; no production change landed. > 2025-10-27: Scope enforcement spike paused; no production change landed.
| Sprint 24 | Graph & Vuln Explorer v1 | src/Concelier/__Libraries/StellaOps.Concelier.Core/TASKS.md | TODO | Concelier Core Guild | CONCELIER-GRAPH-24-001 | Surface raw advisory observations/linksets for overlay services (no derived aggregation in ingestion). | | Sprint 24 | Graph & Vuln Explorer v1 | src/Concelier/__Libraries/StellaOps.Concelier.Core/TASKS.md | TODO | Concelier Core Guild | CONCELIER-GRAPH-24-001 | Surface raw advisory observations/linksets for overlay services (no derived aggregation in ingestion). |
> 2025-10-27: Prototype not merged (query layer + CLI consumer under review); resetting to TODO. > 2025-10-27: Prototype not merged (query layer + CLI consumer under review); resetting to TODO.
@@ -300,7 +300,7 @@ This file describe implementation of Stella Ops (docs/README.md). Implementation
| Sprint 28 | Graph Explorer | docs/TASKS.md | TODO | Docs & Graph API Guilds | DOCS-GRAPH-28-004 | Publish `/docs/sbom/graph-api.md` endpoints + streaming guidance. | | Sprint 28 | Graph Explorer | docs/TASKS.md | TODO | Docs & Graph API Guilds | DOCS-GRAPH-28-004 | Publish `/docs/sbom/graph-api.md` endpoints + streaming guidance. |
| Sprint 28 | Graph Explorer | docs/TASKS.md | TODO | Docs & CLI Guilds | DOCS-GRAPH-28-005 | Produce `/docs/sbom/graph-cli.md` command reference. | | Sprint 28 | Graph Explorer | docs/TASKS.md | TODO | Docs & CLI Guilds | DOCS-GRAPH-28-005 | Produce `/docs/sbom/graph-cli.md` command reference. |
| Sprint 28 | Graph Explorer | docs/TASKS.md | TODO | Docs & Policy Guilds | DOCS-GRAPH-28-006 | Publish `/docs/policy/graph-overlays.md`. | | Sprint 28 | Graph Explorer | docs/TASKS.md | TODO | Docs & Policy Guilds | DOCS-GRAPH-28-006 | Publish `/docs/policy/graph-overlays.md`. |
| Sprint 28 | Graph Explorer | docs/TASKS.md | TODO | Docs & Excitator Guilds | DOCS-GRAPH-28-007 | Document `/docs/vex/graph-integration.md`. | | Sprint 28 | Graph Explorer | docs/TASKS.md | TODO | Docs & Excitor Guilds | DOCS-GRAPH-28-007 | Document `/docs/vex/graph-integration.md`. |
| Sprint 28 | Graph Explorer | docs/TASKS.md | TODO | Docs & Concelier Guilds | DOCS-GRAPH-28-008 | Document `/docs/advisories/graph-integration.md`. | | Sprint 28 | Graph Explorer | docs/TASKS.md | TODO | Docs & Concelier Guilds | DOCS-GRAPH-28-008 | Document `/docs/advisories/graph-integration.md`. |
| Sprint 28 | Graph Explorer | docs/TASKS.md | TODO | Docs & Architecture Guilds | DOCS-GRAPH-28-009 | Author `/docs/architecture/graph-services.md`. | | Sprint 28 | Graph Explorer | docs/TASKS.md | TODO | Docs & Architecture Guilds | DOCS-GRAPH-28-009 | Author `/docs/architecture/graph-services.md`. |
| Sprint 28 | Graph Explorer | docs/TASKS.md | TODO | Docs & Observability Guilds | DOCS-GRAPH-28-010 | Publish `/docs/observability/graph-telemetry.md`. | | Sprint 28 | Graph Explorer | docs/TASKS.md | TODO | Docs & Observability Guilds | DOCS-GRAPH-28-010 | Publish `/docs/observability/graph-telemetry.md`. |
@@ -1058,7 +1058,8 @@ This file describe implementation of Stella Ops (docs/README.md). Implementation
| Sprint 72 | Attestor Console Phase 1 Foundations | src/Attestor/StellaOps.Attestor.Types/TASKS.md | DONE | Attestation Payloads Guild | ATTEST-TYPES-72-001 | Draft schemas for all attestation payload types. | | Sprint 72 | Attestor Console Phase 1 Foundations | src/Attestor/StellaOps.Attestor.Types/TASKS.md | DONE | Attestation Payloads Guild | ATTEST-TYPES-72-001 | Draft schemas for all attestation payload types. |
| Sprint 72 | Attestor Console Phase 1 Foundations | src/Attestor/StellaOps.Attestor.Types/TASKS.md | DONE | Attestation Payloads Guild | ATTEST-TYPES-72-002 | Generate models/validators from schemas. | | Sprint 72 | Attestor Console Phase 1 Foundations | src/Attestor/StellaOps.Attestor.Types/TASKS.md | DONE | Attestation Payloads Guild | ATTEST-TYPES-72-002 | Generate models/validators from schemas. |
| Sprint 72 | Attestor Console Phase 1 Foundations | src/Attestor/StellaOps.Attestor/TASKS.md | TODO | Attestor Service Guild | ATTESTOR-72-001 | Scaffold attestor service skeleton. | | Sprint 72 | Attestor Console Phase 1 Foundations | src/Attestor/StellaOps.Attestor/TASKS.md | TODO | Attestor Service Guild | ATTESTOR-72-001 | Scaffold attestor service skeleton. |
| Sprint 72 | Attestor Console Phase 1 Foundations | src/Attestor/StellaOps.Attestor/TASKS.md | TODO | Attestor Service Guild | ATTESTOR-72-002 | Implement attestation store + storage integration. | | Sprint 72 | Attestor Console Phase 1 Foundations | src/Attestor/StellaOps.Attestor/TASKS.md | TODO | Attestor Service Guild | ATTESTOR-72-002 | Implement attestation store + storage integration. |
| Sprint 72 | Attestor Console Phase 1 Foundations | src/__Libraries/StellaOps.Cryptography.Kms/TASKS.md | DONE | KMS Guild | KMS-72-001 | Implement KMS interface + file driver. |
| Sprint 73 | Attestor CLI Phase 2 Signing & Policies | src/Cli/StellaOps.Cli/TASKS.md | TODO | CLI Attestor Guild | CLI-ATTEST-73-001 | Implement `stella attest sign` (payload selection, subject digest, key reference, output format) using official SDK transport. | | Sprint 73 | Attestor CLI Phase 2 Signing & Policies | src/Cli/StellaOps.Cli/TASKS.md | TODO | CLI Attestor Guild | CLI-ATTEST-73-001 | Implement `stella attest sign` (payload selection, subject digest, key reference, output format) using official SDK transport. |
| Sprint 73 | Attestor CLI Phase 2 Signing & Policies | src/Cli/StellaOps.Cli/TASKS.md | TODO | CLI Attestor Guild | CLI-ATTEST-73-002 | Implement `stella attest verify` with policy selection, explainability output, and JSON/table formatting. | | Sprint 73 | Attestor CLI Phase 2 Signing & Policies | src/Cli/StellaOps.Cli/TASKS.md | TODO | CLI Attestor Guild | CLI-ATTEST-73-002 | Implement `stella attest verify` with policy selection, explainability output, and JSON/table formatting. |
| Sprint 73 | Attestor Console Phase 2 Signing & Policies | docs/TASKS.md | TODO | Docs Guild | DOCS-ATTEST-73-001 | Publish attestor overview. | | Sprint 73 | Attestor Console Phase 2 Signing & Policies | docs/TASKS.md | TODO | Docs Guild | DOCS-ATTEST-73-001 | Publish attestor overview. |

View File

@@ -84,9 +84,12 @@ AUTH-POLICY-27-002 | DONE (2025-11-02) | Provide attestation signing service bin
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-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-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)
> 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: 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.
AUTH-VULN-29-001 | TODO | 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) > 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.
AUTH-VULN-29-002 | TODO | 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) > 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.
AUTH-VULN-29-003 | TODO | 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) 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.
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) 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) 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) 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)
@@ -102,9 +105,9 @@ 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-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-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 | 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-004 | DONE (2025-11-01) | Integrate with VEX Lens and Excitator 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-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-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 | DOING (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) 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)
[Identity & Signing] 100.D) __Libraries [Identity & Signing] 100.D) __Libraries

View File

@@ -158,7 +158,7 @@ FEEDMERGE-COORD-02-902 ICS-CISA version comparison support | BE-Merge, Models |
FEEDMERGE-COORD-02-903 KISA firmware scheme review | BE-Merge, Models | **TODO (due 2025-10-24)** Pair with KISA team on proposed firmware comparison helper (`kisa.build` or variant), ensure observation mapper alignment, and open Models ticket only if a new comparator is required. Log the final helper signature and observation coverage metrics in coordination docs + tracker files. Dependencies: FEEDMERGE-COORD-02-902. | FEEDMERGE-COORD-02-900 (src/Concelier/__Libraries/StellaOps.Concelier.Merge/TASKS.md) FEEDMERGE-COORD-02-903 KISA firmware scheme review | BE-Merge, Models | **TODO (due 2025-10-24)** Pair with KISA team on proposed firmware comparison helper (`kisa.build` or variant), ensure observation mapper alignment, and open Models ticket only if a new comparator is required. Log the final helper signature and observation coverage metrics in coordination docs + tracker files. Dependencies: FEEDMERGE-COORD-02-902. | FEEDMERGE-COORD-02-900 (src/Concelier/__Libraries/StellaOps.Concelier.Merge/TASKS.md)
Fixture validation sweep | QA | **DOING (2025-10-19)** Prereqs confirmed none; continuing RHSA fixture regeneration and diff review alongside mapper provenance updates.<br>2025-10-29: Added `scripts/update-redhat-fixtures.sh` to regenerate golden snapshots with `UPDATE_GOLDENS=1`; run it before reviews to capture CSAF contract deltas. | None (src/Concelier/__Libraries/StellaOps.Concelier.Connector.Distro.RedHat/TASKS.md) Fixture validation sweep | QA | **DOING (2025-10-19)** Prereqs confirmed none; continuing RHSA fixture regeneration and diff review alongside mapper provenance updates.<br>2025-10-29: Added `scripts/update-redhat-fixtures.sh` to regenerate golden snapshots with `UPDATE_GOLDENS=1`; run it before reviews to capture CSAF contract deltas. | None (src/Concelier/__Libraries/StellaOps.Concelier.Connector.Distro.RedHat/TASKS.md)
Link-Not-Merge version provenance coordination | BE-Merge | **DOING** Coordinate remaining connectors (`Acsc`, `Cccs`, `CertBund`, `CertCc`, `Cve`, `Ghsa`, `Ics.Cisa`, `Kisa`, `Ru.Bdu`, `Ru.Nkcki`, `Vndr.Apple`, `Vndr.Cisco`, `Vndr.Msrc`) so they emit `advisory_observations.affected.versions[]` entries with provenance tags and deterministic comparison keys. Track rollout status in `docs/dev/normalized-rule-recipes.md` (now updated for Link-Not-Merge) and retire the legacy merge counters as coverage transitions to linkset validation metrics.<br>2025-10-29: Added new guidance in the doc for recording observation version metadata and logging gaps via `LinksetVersionCoverage` warnings to replace prior `concelier.merge.normalized_rules*` alerts. Dependencies: CONCELIER-LNM-21-203. | CONCELIER-LNM-21-001 (src/Concelier/__Libraries/StellaOps.Concelier.Merge/TASKS.md) Link-Not-Merge version provenance coordination | BE-Merge | **DOING** Coordinate remaining connectors (`Acsc`, `Cccs`, `CertBund`, `CertCc`, `Cve`, `Ghsa`, `Ics.Cisa`, `Kisa`, `Ru.Bdu`, `Ru.Nkcki`, `Vndr.Apple`, `Vndr.Cisco`, `Vndr.Msrc`) so they emit `advisory_observations.affected.versions[]` entries with provenance tags and deterministic comparison keys. Track rollout status in `docs/dev/normalized-rule-recipes.md` (now updated for Link-Not-Merge) and retire the legacy merge counters as coverage transitions to linkset validation metrics.<br>2025-10-29: Added new guidance in the doc for recording observation version metadata and logging gaps via `LinksetVersionCoverage` warnings to replace prior `concelier.merge.normalized_rules*` alerts. Dependencies: CONCELIER-LNM-21-203. | CONCELIER-LNM-21-001 (src/Concelier/__Libraries/StellaOps.Concelier.Merge/TASKS.md)
MERGE-LNM-21-001 Migration plan authoring | BE-Merge, Architecture Guild | Draft `no-merge` migration playbook, documenting backfill strategy, feature flag rollout, and rollback steps for legacy merge pipeline deprecation. | CONCELIER-LNM-21-101 (src/Concelier/__Libraries/StellaOps.Concelier.Merge/TASKS.md) MERGE-LNM-21-001 | DONE (2025-11-03) | Draft `no-merge` migration playbook, documenting backfill strategy, feature flag rollout, and rollback steps for legacy merge pipeline deprecation.<br>2025-11-03: Authored `docs/migration/no-merge.md` covering rollout phases, backfill/validation checklists, and rollback guidance; shared artefact owners. | BE-Merge, Architecture Guild (src/Concelier/__Libraries/StellaOps.Concelier.Merge/TASKS.md)
[Ingestion & Evidence] 110.B) Concelier.VII [Ingestion & Evidence] 110.B) Concelier.VII
@@ -166,7 +166,7 @@ Depends on: Sprint 110.B - Concelier.VI
Summary: Ingestion & Evidence focus on Concelier (phase VII). Summary: Ingestion & Evidence focus on Concelier (phase VII).
Task ID | State | Task description | Owners (Source) Task ID | State | Task description | Owners (Source)
--- | --- | --- | --- --- | --- | --- | ---
MERGE-LNM-21-002 Merge service deprecation | BE-Merge | Refactor or retire `AdvisoryMergeService` and related pipelines, ensuring callers transition to observation/linkset APIs; add compile-time analyzer preventing merge service usage. Dependencies: MERGE-LNM-21-001. | MERGE-LNM-21-001 (src/Concelier/__Libraries/StellaOps.Concelier.Merge/TASKS.md) MERGE-LNM-21-002 | DOING (2025-11-03) | Refactor or retire `AdvisoryMergeService` and related pipelines, ensuring callers transition to observation/linkset APIs; add compile-time analyzer preventing merge service usage.<br>2025-11-03: Began dependency audit and call-site inventory ahead of deprecation plan; cataloging service registrations/tests referencing merge APIs. | BE-Merge (src/Concelier/__Libraries/StellaOps.Concelier.Merge/TASKS.md)
MERGE-LNM-21-003 Determinism/test updates | QA Guild, BE-Merge | Replace merge determinism suites with observation/linkset regression tests verifying no data mutation and conflicts remain visible. Dependencies: MERGE-LNM-21-002. | MERGE-LNM-21-002 (src/Concelier/__Libraries/StellaOps.Concelier.Merge/TASKS.md) MERGE-LNM-21-003 Determinism/test updates | QA Guild, BE-Merge | Replace merge determinism suites with observation/linkset regression tests verifying no data mutation and conflicts remain visible. Dependencies: MERGE-LNM-21-002. | MERGE-LNM-21-002 (src/Concelier/__Libraries/StellaOps.Concelier.Merge/TASKS.md)

View File

@@ -5,10 +5,10 @@ Depends on: Sprint 110.A - AdvisoryAI
Summary: Policy & Reasoning focus on AirGap). Summary: Policy & Reasoning focus on AirGap).
Task ID | State | Task description | Owners (Source) Task ID | State | Task description | Owners (Source)
--- | --- | --- | --- --- | --- | --- | ---
AIRGAP-POL-56-001 | TODO | Implement `StellaOps.AirGap.Policy` package exposing `EgressPolicy` facade with sealed/unsealed branches and remediation-friendly errors. | AirGap Policy Guild (src/AirGap/StellaOps.AirGap.Policy/TASKS.md) AIRGAP-POL-56-001 | DONE | Implement `StellaOps.AirGap.Policy` package exposing `EgressPolicy` facade with sealed/unsealed branches and remediation-friendly errors. | AirGap Policy Guild (src/AirGap/StellaOps.AirGap.Policy/TASKS.md)
AIRGAP-POL-56-002 | TODO | 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-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 | TODO | 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-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 | TODO | Implement Task Runner job plan validator rejecting network steps unless marked internal allow-list. Dependencies: AIRGAP-POL-57-001. | AirGap Policy Guild, Task Runner 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-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-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)
@@ -226,7 +226,7 @@ Task ID | State | Task description | Owners (Source)
RISK-ENGINE-66-001 | TODO | Scaffold scoring service (job queue, worker loop, provider registry) with deterministic execution harness. | Risk Engine Guild (src/RiskEngine/StellaOps.RiskEngine/TASKS.md) RISK-ENGINE-66-001 | TODO | Scaffold scoring service (job queue, worker loop, provider registry) with deterministic execution harness. | Risk Engine Guild (src/RiskEngine/StellaOps.RiskEngine/TASKS.md)
RISK-ENGINE-66-002 | TODO | Implement default transforms (linear, minmax, logistic, piecewise), clamping, gating, and contribution calculator. Dependencies: RISK-ENGINE-66-001. | Risk Engine Guild (src/RiskEngine/StellaOps.RiskEngine/TASKS.md) RISK-ENGINE-66-002 | TODO | Implement default transforms (linear, minmax, logistic, piecewise), clamping, gating, and contribution calculator. Dependencies: RISK-ENGINE-66-001. | Risk Engine Guild (src/RiskEngine/StellaOps.RiskEngine/TASKS.md)
RISK-ENGINE-67-001 | TODO | Integrate CVSS and KEV providers pulling data from Conseiller; implement reducers (`max`, `any`, `consensus`). Dependencies: RISK-ENGINE-66-002. | Risk Engine Guild, Concelier Guild (src/RiskEngine/StellaOps.RiskEngine/TASKS.md) RISK-ENGINE-67-001 | TODO | Integrate CVSS and KEV providers pulling data from Conseiller; implement reducers (`max`, `any`, `consensus`). Dependencies: RISK-ENGINE-66-002. | Risk Engine Guild, Concelier Guild (src/RiskEngine/StellaOps.RiskEngine/TASKS.md)
RISK-ENGINE-67-002 | TODO | Integrate VEX gate provider and ensure gating short-circuits scoring as configured. Dependencies: RISK-ENGINE-67-001. | Risk Engine Guild, Excitator Guild (src/RiskEngine/StellaOps.RiskEngine/TASKS.md) RISK-ENGINE-67-002 | TODO | Integrate VEX gate provider and ensure gating short-circuits scoring as configured. Dependencies: RISK-ENGINE-67-001. | Risk Engine Guild, Excitor Guild (src/RiskEngine/StellaOps.RiskEngine/TASKS.md)
RISK-ENGINE-67-003 | TODO | Add fix availability, asset criticality, and internet exposure providers with caching + TTL enforcement. Dependencies: RISK-ENGINE-67-002. | Risk Engine Guild, Policy Engine Guild (src/RiskEngine/StellaOps.RiskEngine/TASKS.md) RISK-ENGINE-67-003 | TODO | Add fix availability, asset criticality, and internet exposure providers with caching + TTL enforcement. Dependencies: RISK-ENGINE-67-002. | Risk Engine Guild, Policy Engine Guild (src/RiskEngine/StellaOps.RiskEngine/TASKS.md)
RISK-ENGINE-68-001 | TODO | Persist scoring results + explanation pointers to Findings Ledger; handle incremental updates via input hash. Dependencies: RISK-ENGINE-67-003. | Risk Engine Guild, Findings Ledger Guild (src/RiskEngine/StellaOps.RiskEngine/TASKS.md) RISK-ENGINE-68-001 | TODO | Persist scoring results + explanation pointers to Findings Ledger; handle incremental updates via input hash. Dependencies: RISK-ENGINE-67-003. | Risk Engine Guild, Findings Ledger Guild (src/RiskEngine/StellaOps.RiskEngine/TASKS.md)
RISK-ENGINE-68-002 | TODO | Expose APIs (`/risk/jobs`, `/risk/results`, `/risk/results/{id}/explanation`); include pagination, filtering, error codes. Dependencies: RISK-ENGINE-68-001. | Risk Engine Guild, API Guild (src/RiskEngine/StellaOps.RiskEngine/TASKS.md) RISK-ENGINE-68-002 | TODO | Expose APIs (`/risk/jobs`, `/risk/results`, `/risk/results/{id}/explanation`); include pagination, filtering, error codes. Dependencies: RISK-ENGINE-68-001. | Risk Engine Guild, API Guild (src/RiskEngine/StellaOps.RiskEngine/TASKS.md)

View File

@@ -134,19 +134,27 @@ Summary: Scanner & Surface focus on Scanner (phase VII).
Task ID | State | Task description | Owners (Source) Task ID | State | Task description | Owners (Source)
--- | --- | --- | --- --- | --- | --- | ---
SCANNER-ENTRYTRACE-18-504 | TODO | Emit EntryTrace AOC NDJSON (`entrytrace.entry/node/edge/target/warning/capability`) and wire CLI/service streaming outputs. Dependencies: SCANNER-ENTRYTRACE-18-503. | EntryTrace Guild (src/Scanner/__Libraries/StellaOps.Scanner.EntryTrace/TASKS.md) SCANNER-ENTRYTRACE-18-504 | TODO | Emit EntryTrace AOC NDJSON (`entrytrace.entry/node/edge/target/warning/capability`) and wire CLI/service streaming outputs. Dependencies: SCANNER-ENTRYTRACE-18-503. | EntryTrace Guild (src/Scanner/__Libraries/StellaOps.Scanner.EntryTrace/TASKS.md)
SCANNER-ENV-01 | TODO | Replace ad-hoc environment reads with `StellaOps.Scanner.Surface.Env` helpers for cache roots and CAS endpoints. | Scanner Worker Guild (src/Scanner/StellaOps.Scanner.Worker/TASKS.md) SCANNER-ENV-01 | DOING (2025-11-02) | Replace ad-hoc environment reads with `StellaOps.Scanner.Surface.Env` helpers for cache roots and CAS endpoints.<br>2025-11-02: Env helper wiring drafted for Worker startup; initial tests validate cache root resolution. | Scanner Worker Guild (src/Scanner/StellaOps.Scanner.Worker/TASKS.md)
SCANNER-ENV-02 | TODO | Wire Surface.Env helpers into WebService hosting (cache roots, feature flags) and document configuration. Dependencies: SCANNER-ENV-01. | Scanner WebService Guild, Ops Guild (src/Scanner/StellaOps.Scanner.WebService/TASKS.md) SCANNER-ENV-02 | DOING (2025-11-02) | Wire Surface.Env helpers into WebService hosting (cache roots, feature flags) and document configuration. Dependencies: SCANNER-ENV-01.<br>2025-11-02: WebService bootstrap now consumes Surface.Env helpers for cache roots and feature flag toggles; configuration doc draft pending. | Scanner WebService Guild, Ops Guild (src/Scanner/StellaOps.Scanner.WebService/TASKS.md)
SCANNER-ENV-03 | TODO | Adopt Surface.Env helpers for plugin configuration (cache roots, CAS endpoints, feature toggles). Dependencies: SCANNER-ENV-02. | BuildX Plugin Guild (src/Scanner/StellaOps.Scanner.Sbomer.BuildXPlugin/TASKS.md) SCANNER-ENV-03 | TODO | Adopt Surface.Env helpers for plugin configuration (cache roots, CAS endpoints, feature toggles). Dependencies: SCANNER-ENV-02. | BuildX Plugin Guild (src/Scanner/StellaOps.Scanner.Sbomer.BuildXPlugin/TASKS.md)
SCANNER-EVENTS-16-301 | BLOCKED (2025-10-26) | Emit orchestrator-compatible envelopes (`scanner.event.*`) and update integration tests to verify Notifier ingestion (no Redis queue coupling). | Scanner WebService Guild (src/Scanner/StellaOps.Scanner.WebService/TASKS.md) SCANNER-EVENTS-16-301 | BLOCKED (2025-10-26) | Emit orchestrator-compatible envelopes (`scanner.event.*`) and update integration tests to verify Notifier ingestion (no Redis queue coupling). | Scanner WebService Guild (src/Scanner/StellaOps.Scanner.WebService/TASKS.md)
SCANNER-EVENTS-16-302 | DOING (2025-10-26) | Extend orchestrator event links (report/policy/attestation) once endpoints are finalised across gateway + console. Dependencies: SCANNER-EVENTS-16-301. | Scanner WebService Guild (src/Scanner/StellaOps.Scanner.WebService/TASKS.md) SCANNER-EVENTS-16-302 | DOING (2025-10-26) | Extend orchestrator event links (report/policy/attestation) once endpoints are finalised across gateway + console. Dependencies: SCANNER-EVENTS-16-301. | Scanner WebService Guild (src/Scanner/StellaOps.Scanner.WebService/TASKS.md)
SCANNER-GRAPH-21-001 | TODO | Provide webhook/REST endpoint for Cartographer to request policy overlays and runtime evidence for graph nodes, ensuring determinism and tenant scoping. | Scanner WebService Guild, Cartographer Guild (src/Scanner/StellaOps.Scanner.WebService/TASKS.md) SCANNER-GRAPH-21-001 | TODO | Provide webhook/REST endpoint for Cartographer to request policy overlays and runtime evidence for graph nodes, ensuring determinism and tenant scoping. | Scanner WebService Guild, Cartographer Guild (src/Scanner/StellaOps.Scanner.WebService/TASKS.md)
SCANNER-LNM-21-001 | TODO | Update `/reports` and `/policy/runtime` payloads to consume advisory/vex linksets, exposing source severity arrays and conflict summaries alongside effective verdicts. | Scanner WebService Guild, Policy Guild (src/Scanner/StellaOps.Scanner.WebService/TASKS.md) SCANNER-LNM-21-001 | TODO | Update `/reports` and `/policy/runtime` payloads to consume advisory/vex linksets, exposing source severity arrays and conflict summaries alongside effective verdicts. | Scanner WebService Guild, Policy Guild (src/Scanner/StellaOps.Scanner.WebService/TASKS.md)
SCANNER-LNM-21-002 | TODO | Add evidence endpoint for Console to fetch linkset summaries with policy overlay for a component/SBOM, including AOC references. Dependencies: SCANNER-LNM-21-001. | Scanner WebService Guild, UI Guild (src/Scanner/StellaOps.Scanner.WebService/TASKS.md) SCANNER-LNM-21-002 | TODO | Add evidence endpoint for Console to fetch linkset summaries with policy overlay for a component/SBOM, including AOC references. Dependencies: SCANNER-LNM-21-001. | Scanner WebService Guild, UI Guild (src/Scanner/StellaOps.Scanner.WebService/TASKS.md)
SCANNER-SECRETS-01 | TODO | Adopt `StellaOps.Scanner.Surface.Secrets` for registry/CAS credentials during scan execution. | Scanner Worker Guild, Security Guild (src/Scanner/StellaOps.Scanner.Worker/TASKS.md) SCANNER-SECRETS-01 | DOING (2025-11-02) | Adopt `StellaOps.Scanner.Surface.Secrets` for registry/CAS credentials during scan execution.<br>2025-11-02: Worker integration tests added for CAS token retrieval via Surface.Secrets abstraction; refactor under review. | Scanner Worker Guild, Security Guild (src/Scanner/StellaOps.Scanner.Worker/TASKS.md)
SCANNER-SECRETS-02 | TODO | Replace ad-hoc secret wiring with Surface.Secrets for report/export operations (registry and CAS tokens). Dependencies: SCANNER-SECRETS-01. | Scanner WebService Guild, Security Guild (src/Scanner/StellaOps.Scanner.WebService/TASKS.md) SCANNER-SECRETS-02 | DOING (2025-11-02) | Replace ad-hoc secret wiring with Surface.Secrets for report/export operations (registry and CAS tokens). Dependencies: SCANNER-SECRETS-01.<br>2025-11-02: WebService export path now resolves registry credentials via Surface.Secrets stub; CI pipeline hook in progress. | Scanner WebService Guild, Security Guild (src/Scanner/StellaOps.Scanner.WebService/TASKS.md)
SCANNER-SECRETS-03 | TODO | Use Surface.Secrets to retrieve registry credentials when interacting with CAS/referrers. Dependencies: SCANNER-SECRETS-02. | BuildX Plugin Guild, Security Guild (src/Scanner/StellaOps.Scanner.Sbomer.BuildXPlugin/TASKS.md) SCANNER-SECRETS-03 | TODO | Use Surface.Secrets to retrieve registry credentials when interacting with CAS/referrers. Dependencies: SCANNER-SECRETS-02. | BuildX Plugin Guild, Security Guild (src/Scanner/StellaOps.Scanner.Sbomer.BuildXPlugin/TASKS.md)
SCANNER-SURFACE-01 | TODO | Persist Surface.FS manifests after analyzer stages, including layer CAS metadata and EntryTrace fragments. | Scanner Worker Guild (src/Scanner/StellaOps.Scanner.Worker/TASKS.md) SCANNER-ENG-0020 | TODO | Implement Homebrew collector & fragment mapper per `design/macos-analyzer.md` §3.1. | Scanner Guild (docs/modules/scanner/TASKS.md)
SCANNER-SURFACE-02 | TODO | Publish Surface.FS pointers (CAS URIs, manifests) via scan/report APIs and update attestation metadata. Dependencies: SCANNER-SURFACE-01. | Scanner WebService Guild (src/Scanner/StellaOps.Scanner.WebService/TASKS.md) SCANNER-ENG-0021 | TODO | Implement pkgutil receipt collector per `design/macos-analyzer.md` §3.2. | Scanner Guild (docs/modules/scanner/TASKS.md)
SCANNER-ENG-0022 | TODO | Implement macOS bundle inspector & capability overlays per `design/macos-analyzer.md` §3.3. | Scanner Guild, Policy Guild (docs/modules/scanner/TASKS.md)
SCANNER-ENG-0023 | TODO | Deliver macOS policy/offline integration per `design/macos-analyzer.md` §56. | Scanner Guild, Offline Kit Guild, Policy Guild (docs/modules/scanner/TASKS.md)
SCANNER-ENG-0024 | TODO | Implement Windows MSI collector per `design/windows-analyzer.md` §3.1. | Scanner Guild (docs/modules/scanner/TASKS.md)
SCANNER-ENG-0025 | TODO | Implement WinSxS manifest collector per `design/windows-analyzer.md` §3.2. | Scanner Guild (docs/modules/scanner/TASKS.md)
SCANNER-ENG-0026 | TODO | Implement Windows Chocolatey & registry collectors per `design/windows-analyzer.md` §3.33.4. | Scanner Guild (docs/modules/scanner/TASKS.md)
SCANNER-ENG-0027 | TODO | Deliver Windows policy/offline integration per `design/windows-analyzer.md` §56. | Scanner Guild, Policy Guild, Offline Kit Guild (docs/modules/scanner/TASKS.md)
SCANNER-SURFACE-01 | DOING (2025-11-02) | Persist Surface.FS manifests after analyzer stages, including layer CAS metadata and EntryTrace fragments.<br>2025-11-02: Worker pipeline emitting draft Surface.FS manifests for sample scans; determinism checks running. | Scanner Worker Guild (src/Scanner/StellaOps.Scanner.Worker/TASKS.md)
SCANNER-SURFACE-02 | DOING (2025-11-02) | Publish Surface.FS pointers (CAS URIs, manifests) via scan/report APIs and update attestation metadata. Dependencies: SCANNER-SURFACE-01.<br>2025-11-02: WebService responses now include preview CAS URIs; attestation metadata updates staged for review. | Scanner WebService Guild (src/Scanner/StellaOps.Scanner.WebService/TASKS.md)
SCANNER-SURFACE-03 | TODO | Push layer manifests and entry fragments into Surface.FS during build-time SBOM generation. Dependencies: SCANNER-SURFACE-02. | BuildX Plugin Guild (src/Scanner/StellaOps.Scanner.Sbomer.BuildXPlugin/TASKS.md) SCANNER-SURFACE-03 | TODO | Push layer manifests and entry fragments into Surface.FS during build-time SBOM generation. Dependencies: SCANNER-SURFACE-02. | BuildX Plugin Guild (src/Scanner/StellaOps.Scanner.Sbomer.BuildXPlugin/TASKS.md)
[Scanner & Surface] 130.A) Scanner.VIII [Scanner & Surface] 130.A) Scanner.VIII

View File

@@ -5,6 +5,7 @@ Depends on: Sprint 150.A - Orchestrator
Summary: Notifications & Telemetry focus on Notifier (phase I). Summary: Notifications & Telemetry focus on Notifier (phase I).
Task ID | State | Task description | Owners (Source) 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-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-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-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)

View File

@@ -136,9 +136,9 @@ DEVOPS-VEX-30-001 | TODO | Provision CI, load tests, dashboards, alerts for VEX
DEVOPS-VULN-29-001 | TODO | Provision CI jobs for ledger projector (replay, determinism), set up backups, monitor Merkle anchoring, and automate verification. | DevOps Guild, Findings Ledger Guild (ops/devops/TASKS.md) DEVOPS-VULN-29-001 | TODO | Provision CI jobs for ledger projector (replay, determinism), set up backups, monitor Merkle anchoring, and automate verification. | DevOps Guild, Findings Ledger Guild (ops/devops/TASKS.md)
DEVOPS-VULN-29-002 | TODO | Configure load/perf tests (5M findings/tenant), query budget enforcement, API SLO dashboards, and alerts for `vuln_list_latency` and `projection_lag`. Dependencies: DEVOPS-VULN-29-001. | DevOps Guild, Vuln Explorer API Guild (ops/devops/TASKS.md) DEVOPS-VULN-29-002 | TODO | Configure load/perf tests (5M findings/tenant), query budget enforcement, API SLO dashboards, and alerts for `vuln_list_latency` and `projection_lag`. Dependencies: DEVOPS-VULN-29-001. | DevOps Guild, Vuln Explorer API Guild (ops/devops/TASKS.md)
DEVOPS-VULN-29-003 | TODO | Instrument analytics pipeline for Vuln Explorer (telemetry ingestion, query hashes), ensure compliance with privacy/PII guardrails, and update observability docs. Dependencies: DEVOPS-VULN-29-002. | DevOps Guild, Console Guild (ops/devops/TASKS.md) DEVOPS-VULN-29-003 | TODO | Instrument analytics pipeline for Vuln Explorer (telemetry ingestion, query hashes), ensure compliance with privacy/PII guardrails, and update observability docs. Dependencies: DEVOPS-VULN-29-002. | DevOps Guild, Console Guild (ops/devops/TASKS.md)
DOCKER-44-001 | TODO | Author multi-stage Dockerfiles for all core services (API, Console, Orchestrator, Task Runner, Conseiller, Excitator, Policy, Notify, Export, AI) with non-root users, read-only file systems, and health scripts. | DevOps Guild, Service Owners (ops/devops/TASKS.md) DOCKER-44-001 | TODO | Author multi-stage Dockerfiles for all core services (API, Console, Orchestrator, Task Runner, Conseiller, Excitor, Policy, Notify, Export, AI) with non-root users, read-only file systems, and health scripts. | DevOps Guild, Service Owners (ops/devops/TASKS.md)
DOCKER-44-002 | TODO | Generate SBOMs and cosign attestations for each image and integrate verification into CI. Dependencies: DOCKER-44-001. | DevOps Guild (ops/devops/TASKS.md) DOCKER-44-002 | TODO | Generate SBOMs and cosign attestations for each image and integrate verification into CI. Dependencies: DOCKER-44-001. | DevOps Guild (ops/devops/TASKS.md)
DOCKER-44-003 | TODO | Implement `/health/liveness`, `/health/readiness`, `/version`, `/metrics`, and ensure capability endpoint returns `merge=false` for Conseiller/Excitator. Dependencies: DOCKER-44-002. | DevOps Guild (ops/devops/TASKS.md) DOCKER-44-003 | TODO | Implement `/health/liveness`, `/health/readiness`, `/version`, `/metrics`, and ensure capability endpoint returns `merge=false` for Conseiller/Excitor. Dependencies: DOCKER-44-002. | DevOps Guild (ops/devops/TASKS.md)
OPS-ENV-01 | TODO | Update deployment manifests (Helm/Compose) and configuration docs to include Surface.Env variables for Scanner and Zastava services. | DevOps Guild, Scanner Guild (ops/devops/TASKS.md) OPS-ENV-01 | TODO | Update deployment manifests (Helm/Compose) and configuration docs to include Surface.Env variables for Scanner and Zastava services. | DevOps Guild, Scanner Guild (ops/devops/TASKS.md)
OPS-SECRETS-01 | TODO | Define secret provisioning workflow (Kubernetes, Compose, Offline Kit) for Surface.Secrets references and update runbooks. | DevOps Guild, Security Guild (ops/devops/TASKS.md) OPS-SECRETS-01 | TODO | Define secret provisioning workflow (Kubernetes, Compose, Offline Kit) for Surface.Secrets references and update runbooks. | DevOps Guild, Security Guild (ops/devops/TASKS.md)
OPS-SECRETS-02 | TODO | Embed Surface.Secrets material (encrypted bundles, manifests) into offline kit packaging scripts. Dependencies: OPS-SECRETS-01. | DevOps Guild, Offline Kit Guild (ops/devops/TASKS.md) OPS-SECRETS-02 | TODO | Embed Surface.Secrets material (encrypted bundles, manifests) into offline kit packaging scripts. Dependencies: OPS-SECRETS-01. | DevOps Guild, Offline Kit Guild (ops/devops/TASKS.md)

View File

@@ -103,7 +103,8 @@ DOCS-LNM-22-003 | BLOCKED (2025-10-27) | Update `/docs/api/advisories.md` and `/
DOCS-LNM-22-004 | TODO | Create `/docs/policy/effective-severity.md` detailing severity selection strategies from multiple sources. Dependencies: DOCS-LNM-22-003. | Docs Guild, Policy Guild (docs/TASKS.md) DOCS-LNM-22-004 | TODO | Create `/docs/policy/effective-severity.md` detailing severity selection strategies from multiple sources. Dependencies: DOCS-LNM-22-003. | Docs Guild, Policy Guild (docs/TASKS.md)
DOCS-LNM-22-005 | BLOCKED (2025-10-27) | Document `/docs/ui/evidence-panel.md` with screenshots, conflict badges, accessibility guidance. Dependencies: DOCS-LNM-22-004. | Docs Guild, UI Guild (docs/TASKS.md) DOCS-LNM-22-005 | BLOCKED (2025-10-27) | Document `/docs/ui/evidence-panel.md` with screenshots, conflict badges, accessibility guidance. Dependencies: DOCS-LNM-22-004. | Docs Guild, UI Guild (docs/TASKS.md)
DOCS-LNM-22-007 | TODO | Publish `/docs/observability/aggregation.md` with metrics/traces/logs/SLOs. Dependencies: DOCS-LNM-22-005. | Docs Guild, Observability Guild (docs/TASKS.md) DOCS-LNM-22-007 | TODO | Publish `/docs/observability/aggregation.md` with metrics/traces/logs/SLOs. Dependencies: DOCS-LNM-22-005. | Docs Guild, Observability Guild (docs/TASKS.md)
DOCS-LNM-22-008 | TODO | Write `/docs/migration/no-merge.md` describing migration plan, backfill steps, rollback, feature flags. Dependencies: DOCS-LNM-22-007. | Docs Guild, DevOps Guild (docs/TASKS.md) DOCS-LNM-22-008 | DONE (2025-11-03) | Write `/docs/migration/no-merge.md` describing migration plan, backfill steps, rollback, feature flags. Dependencies: DOCS-LNM-22-007. | Docs Guild, DevOps Guild (docs/TASKS.md)
> 2025-11-03: Drafted and published `docs/migration/no-merge.md` covering rollout phases, backfill/validation workflow, rollback plan, and readiness checklist.
DOCS-NOTIFY-40-001 | TODO | Publish `/docs/notifications/channels.md`, `/docs/notifications/escalations.md`, `/docs/notifications/api.md`, `/docs/operations/notifier-runbook.md`, `/docs/security/notifications-hardening.md`; each ends with imposed rule line. | Docs Guild, Security Guild (docs/TASKS.md) DOCS-NOTIFY-40-001 | TODO | Publish `/docs/notifications/channels.md`, `/docs/notifications/escalations.md`, `/docs/notifications/api.md`, `/docs/operations/notifier-runbook.md`, `/docs/security/notifications-hardening.md`; each ends with imposed rule line. | Docs Guild, Security Guild (docs/TASKS.md)
DOCS-OAS-61-001 | TODO | Publish `/docs/api/overview.md` covering auth, tenancy, pagination, idempotency, rate limits with banner. | Docs Guild, API Contracts Guild (docs/TASKS.md) DOCS-OAS-61-001 | TODO | Publish `/docs/api/overview.md` covering auth, tenancy, pagination, idempotency, rate limits with banner. | Docs Guild, API Contracts Guild (docs/TASKS.md)
DOCS-OAS-61-002 | TODO | Author `/docs/api/conventions.md` capturing naming, errors, filters, sorting, examples. Dependencies: DOCS-OAS-61-001. | Docs Guild, API Governance Guild (docs/TASKS.md) DOCS-OAS-61-002 | TODO | Author `/docs/api/conventions.md` capturing naming, errors, filters, sorting, examples. Dependencies: DOCS-OAS-61-001. | Docs Guild, API Governance Guild (docs/TASKS.md)

141
docs/migration/no-merge.md Normal file
View File

@@ -0,0 +1,141 @@
# No-Merge Migration Playbook
_Last updated: 2025-11-03_
This playbook guides the full retirement of the legacy Merge service (`AdvisoryMergeService`) in favour of Link-Not-Merge (LNM) observations plus linksets. It is written for the BE-Merge, Architecture, DevOps, and Docs guilds coordinating Sprint110 (Ingestion & Evidence) deliverables, and it feeds CONCELIER-LNM-21-101 / MERGE-LNM-21-001 and downstream DOCS-LNM-22-008.
## 0. Scope & objectives
- **Primary goal:** cut over all advisory pipelines to Link-Not-Merge with no residual dependencies on `AdvisoryMergeService`.
- **Secondary goals:** maintain deterministic evidence, zero data loss, and reversible deployment across online and offline tenants.
- **Success criteria:**
- All connectors emit observation `affected.versions[]` with provenance and pass LNM guardrails.
- Linkset dashboards show zero `missing_version_entries_total` and no `Normalized version rules missing…` warnings.
- Policy, Export Center, and CLI consumers operate solely on observations/linksets.
- Rollback playbook validated and rehearsed in staging.
## 1. Prerequisites checklist
| Item | Owner | Notes |
| --- | --- | --- |
| Normalized version ranges emitted for all Sprint110 connectors (`Acsc`, `Cccs`, `CertBund`, `CertCc`, `Cve`, `Ghsa`, `Ics.Cisa`, `Kisa`, `Ru.Bdu`, `Ru.Nkcki`, `Vndr.Apple`, `Vndr.Cisco`, `Vndr.Msrc`). | Connector guilds | Follow `docs/dev/normalized-rule-recipes.md`; update fixtures with `UPDATE_*_FIXTURES=1`. |
| Metrics dashboards (`LinksetVersionCoverage`, `Normalized version rules missing`) available in Grafana/CI snapshots. | Observability guild | Publish baseline before shadow rollout. |
| Concelier WebService exposes `linkset` and `observation` read APIs for policy/CLI consumers. | BE-Merge / Platform | Confirm contract parity with Merge outputs. |
| Export Center / Offline Kit aware of new manifests. | Export Center guild | Provide beta bundle for QA verification. |
| Docs guild aligned on public migration messaging. | Docs guild | Update `docs/dev`, `docs/modules/concelier`, and release notes once cutover date is locked. |
Do not proceed to Phase1 until all prerequisites are checked or explicitly waived by Architecture guild.
## 2. Feature flag & configuration plan
| Toggle | Default | Purpose | Notes |
| --- | --- | --- | --- |
| `concelier:features:noMergeEnabled` | `false` | Master switch to disable legacy Merge job scheduling/execution. | Applies to WebService + Worker; gate `AdvisoryMergeService` DI registration. |
| `concelier:features:lnmShadowWrites` | `true` | Enables dual-write of linksets while Merge remains active. | Keep enabled throughout Phase01 to validate parity. |
| `concelier:jobs:merge:allowlist` | `[]` | Explicit allowlist for Merge jobs when noMergeEnabled is `false`. | Set to empty during Phase2+ to prevent accidental restarts. |
| `policy:overlays:requireLinksetEvidence` | `false` | Policy engine safety net to require linkset-backed findings. | Flip to `true` only after cutover (Phase2). |
> **Configuration hygiene:** Document the toggle values per environment in `ops/devops/configuration/staging.md` and `ops/devops/configuration/production.md`. Air-gapped customers receive defaults through the Offline Kit release notes.
## 3. Rollout phases
| Phase | Goal | Duration | Key actions |
| --- | --- | --- | --- |
| **0 Preparation** | Ensure readiness | 23 days | Finalise prerequisites, snapshot Merge metrics, dry-run backfill scripts in dev. |
| **1 Shadow / Dual Write** | Validate parity | 57 days | Enable `lnmShadowWrites`, keep Merge primary. Compare linkset vs merged outputs using `stella concelier diff-merge --snapshot <date>`; fix discrepancies. |
| **2 Cutover** | Switch to LNM | 1 day (per env) | Enable `noMergeEnabled`, disable Merge job schedules, update Policy/Export configs, run post-cutover smoke tests. |
| **3 Harden** | Decommission Merge | 23 days | Remove Merge background services, delete `merge_event` retention jobs, clean dashboards, notify operators. |
### 3.1 Environment sequencing
1. **Dev/Test clusters:** Validate all automation. Run full regression suite (`dotnet test src/Concelier/...`).
2. **Staging:** Execute complete backfill (see §4) and collect 24h of telemetry before sign-off.
3. **Production:** Perform cutover during low-ingest window; communicate via Slack/email + status page two days in advance.
4. **Offline kit:** Package new Observer snapshots with LNM-only data; ensure instructions cover flag toggles for air-gapped deployments.
### 3.2 Smoke test matrix
- `stella concelier status --include linkset` returns healthy and shows zero Merge workers.
- `stella policy evaluate` against sample tenants produces identical findings pre/post cutover.
- Export Center bundle diff shows only expected metadata changes (manifest ID, timestamps).
- Grafana dashboards: `linkset_insert_duration_ms` steady, `merge.identity.conflicts` flatlined.
## 4. Backfill strategy
1. **Freeze Merge writes:** Pause Merge job scheduler (`MergeJobScheduler.PauseAsync`) to prevent new merge events while snapshots are taken.
2. **Generate linkset baseline:** Run `dotnet run --project src/Concelier/StellaOps.Concelier.WebService -- linkset backfill --from 2024-01-01` (or equivalent CLI job) to rebuild linksets from `advisory_raw`. Capture job output artefacts and attach to the sprint issue.
3. **Validate parity:** Use the internal diff tool (`tools/concelier/compare-linkset-merge.ps1`) to compare sample advisories. Any diffs must be triaged before production cutover.
4. **Publish evidence:** For air-gapped tenants, create a one-off Offline Kit slice (`export profile linkset-backfill`) and push to staging mirror.
5. **Tag snapshot:** Record Mongo `oplog` timestamp and S3/object storage manifests in `ops/devops/runbooks/concelier/no-merge.md` (new section) so rollback knows the safe point.
> **Determinism:** rerunning the backfill with identical inputs must produce byte-identical linkset documents. Use the `--verify-determinism` flag where available and archive the checksum report under `artifacts/lnm-backfill/<date>/`.
## 5. Validation gates
- **Metrics:** `linkset_insert_duration_ms`, `linkset_documents_total`, `normalized_version_rules_missing`, `merge.identity.conflicts`.
- Gate: `normalized_version_rules_missing == 0` for 48h before enabling `noMergeEnabled`.
- **Logs:** Ensure no occurrences of `Fallbacking to merge service` after cutover.
- **Change streams:** Policy and Scheduler should observe only `advisory.linkset.updated` events; monitor for stragglers referencing merge IDs.
- **QA:** Golden tests in `StellaOps.Concelier.Merge.Tests` updated to assert absence of merge outputs, plus integration tests verifying LNM-only exports.
Capture validation evidence in the sprint journal (attach Grafana screenshots + CLI output).
## 6. Rollback plan
1. **Toggle sequence:**
- Set `concelier:features:noMergeEnabled=false`.
- Re-enable Merge job schedules (`concelier:jobs:merge:allowlist=["merge:default"]`).
- Disable `policy:overlays:requireLinksetEvidence`.
2. **Data considerations:**
- Linkset writes continue, so no data is lost; ensure Policy consumers ignore linkset-only fields during rollback window.
- If Merge pipeline was fully removed (Phase3 complete), redeploy the Merge service container image from the `rollback` tag published before cutover.
3. **Verification:**
- Run `stella concelier status` to confirm Merge workers active.
- Monitor `merge.identity.conflicts` for spikes; if present, roll forward and re-open incident with Architecture guild.
4. **Communication:**
- Post incident note in #release-infra and customer status page.
- Log rollback reason, window, and configs in `ops/devops/incidents/<yyyy-mm-dd>-no-merge.md`.
Rollback window should not exceed 4hours; beyond that, plan to roll forward with a hotfix rather than reintroducing Merge.
## 7. Documentation & communications
- Update `docs/modules/concelier/architecture.md` appendix to mark Merge deprecated and link back to this playbook.
- Coordinate with Docs guild to publish operator-facing guidance (`docs/releases/2025-q4.md`) and update CLI help text.
- Notify product/CS teams with a short FAQ covering timelines, customer impact, and steps for self-hosted installations.
## 8. Responsibilities matrix
| Area | Lead guild(s) | Supporting |
| --- | --- | --- |
| Feature flags & config | BE-Merge | DevOps |
| Backfill scripting | BE-Merge | Tools |
| Observability dashboards | Observability | QA |
| Offline kit packaging | Export Center | AirGap |
| Customer comms | Docs | Product, Support |
## 9. Deliverables & artefacts
- Config diff per environment (stored in GitOps repo).
- Backfill checksum report (`artifacts/lnm-backfill/<date>/checksums.json`).
- Grafana export (PDF) showing validation metrics.
- QA test run attesting to LNM-only regressions passing.
- Updated runbook entry in `ops/devops/runbooks/concelier/`.
---
## 10. Migration readiness checklist
| Item | Primary owner | Status notes |
| --- | --- | --- |
| Capture Linkset coverage baselines (`version_entries_total`, `missing_version_entries_total`) and archive Grafana export. | Observability Guild | [ ] Pending |
| Stage and verify linkset backfill using `linkset backfill` job; store checksum report under `artifacts/lnm-backfill/<date>/`. | BE-Merge, DevOps Guild | [ ] Pending |
| Confirm feature flags per environment (`noMergeEnabled`, `lnmShadowWrites`, `policy:overlays:requireLinksetEvidence`) match Phase 03 plan. | DevOps Guild | [ ] Pending |
| Publish operator comms (status page, Slack/email) with cutover + rollback windows. | Docs Guild, Product | [ ] Pending |
| Execute rollback rehearsal in staging and log results in `ops/devops/incidents/<date>-no-merge.md`. | DevOps Guild, Architecture Guild | [ ] Pending |
> Update the checklist as each item completes; completion of every row is required before moving to Phase2 (Cutover).
---
With this playbook completed, proceed to MERGE-LNM-21-002 to remove the Merge service code paths and enforce compile-time analyzers that block new merge dependencies.

View File

@@ -146,6 +146,48 @@ plan? = <plan name> // optional hint for UIs; not used for e
--- ---
### 3.5 Vuln Explorer workflow safeguards
* **Anti-forgery flow** — Vuln Explorers mutation verbs call
* `POST /vuln/workflow/anti-forgery/issue`
* `POST /vuln/workflow/anti-forgery/verify`
Callers must hold `vuln:operate` scopes. Issued tokens embed the actor, tenant, whitelisted actions, ABAC selectors (environment/owner/business tier), and optional context key/value pairs. Tokens are EdDSA/ES256 signed via the primary Authority signing key and default to a 10minute TTL (cap: 30minutes). Verification enforces nonce reuse prevention, tenant match, and action membership before forwarding the request to Vuln Explorer.
* **Attachment access** — Evidence bundles and attachments reference a ledger hash. Vuln Explorer obtains a scoped download token through:
* `POST /vuln/attachments/tokens/issue`
* `POST /vuln/attachments/tokens/verify`
These tokens bind the ledger event hash, attachment identifier, optional finding/content metadata, and the actor. They default to a 30minute TTL (cap: 4hours) and require `vuln:investigate`.
* **Audit trail** — Both flows emit `vuln.workflow.csrf.*` and `vuln.attachment.token.*` audit records with tenant, actor, ledger hash, nonce, and filtered context metadata so Offline Kit operators can reconcile actions against ledger entries.
* **Configuration**
```yaml
authority:
vulnerabilityExplorer:
workflow:
antiForgery:
enabled: true
audience: "stellaops:vuln-workflow"
defaultLifetime: "00:10:00"
maxLifetime: "00:30:00"
maxContextEntries: 16
maxContextValueLength: 256
attachments:
enabled: true
defaultLifetime: "00:30:00"
maxLifetime: "04:00:00"
payloadType: "application/vnd.stellaops.vuln-attachment-token+json"
maxMetadataEntries: 16
maxMetadataValueLength: 512
```
Air-gapped bundles include the signing key material and policy snapshots required to validate these tokens offline.
---
## 4) Audiences, scopes & RBAC ## 4) Audiences, scopes & RBAC
### 4.1 Audiences ### 4.1 Audiences

View File

@@ -1,7 +1,7 @@
# Vexer agent guide # Excitor agent guide
## Mission ## Mission
Vexer computes deterministic consensus across VEX claims, preserving conflicts and producing attestable evidence for policy suppression. Excitor computes deterministic consensus across VEX claims, preserving conflicts and producing attestable evidence for policy suppression.
## Key docs ## Key docs
- [Module README](./README.md) - [Module README](./README.md)
@@ -21,9 +21,9 @@ Vexer computes deterministic consensus across VEX claims, preserving conflicts a
- Keep Offline Kit parity in mind—document air-gapped workflows for any new feature. - Keep Offline Kit parity in mind—document air-gapped workflows for any new feature.
- Update runbooks/observability assets when operational characteristics change. - Update runbooks/observability assets when operational characteristics change.
## Required Reading ## Required Reading
- `docs/modules/vexer/README.md` - `docs/modules/excitor/README.md`
- `docs/modules/vexer/architecture.md` - `docs/modules/excitor/architecture.md`
- `docs/modules/vexer/implementation_plan.md` - `docs/modules/excitor/implementation_plan.md`
- `docs/modules/platform/architecture-overview.md` - `docs/modules/platform/architecture-overview.md`
## Working Agreement ## Working Agreement

View File

@@ -1,6 +1,6 @@
# StellaOps Vexer # StellaOps Excitor
Vexer computes deterministic consensus across VEX claims, preserving conflicts and producing attestable evidence for policy suppression. Excitor computes deterministic consensus across VEX claims, preserving conflicts and producing attestable evidence for policy suppression.
## Responsibilities ## Responsibilities
- Ingest Excititor observations and compute per-product consensus snapshots. - Ingest Excititor observations and compute per-product consensus snapshots.
@@ -9,7 +9,7 @@ Vexer computes deterministic consensus across VEX claims, preserving conflicts a
- Keep provenance weights and disagreement metadata. - Keep provenance weights and disagreement metadata.
## Key components ## Key components
- Consensus engine and API host in `StellaOps.Vexer.*` (to-be-implemented). - Consensus engine and API host in `StellaOps.Excitor.*` (to-be-implemented).
- Storage schema for consensus graphs. - Storage schema for consensus graphs.
- Integration hooks for Policy Engine suppression logic. - Integration hooks for Policy Engine suppression logic.
@@ -27,7 +27,7 @@ Vexer computes deterministic consensus across VEX claims, preserving conflicts a
- ./scoring.md - ./scoring.md
## Backlog references ## Backlog references
- DOCS-VEXER backlog referenced in architecture doc. - DOCS-EXCITOR backlog referenced in architecture doc.
- CLI parity tracked in ../../TASKS.md (CLI-GRAPH/VEX stories). - CLI parity tracked in ../../TASKS.md (CLI-GRAPH/VEX stories).
## Epic alignment ## Epic alignment

View File

@@ -0,0 +1,9 @@
# Task board — Excitor
> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable.
| ID | Status | Owner(s) | Description | Notes |
|----|--------|----------|-------------|-------|
| EXCITOR-DOCS-0001 | DOING (2025-10-29) | Docs Guild | Validate that ./README.md aligns with the latest release notes. | See ./AGENTS.md |
| EXCITOR-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md |
| EXCITOR-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow |

View File

@@ -1,8 +1,8 @@
# component_architecture_vexer.md — **StellaOps Vexer** (2025Q4) # component_architecture_excitor.md — **StellaOps Excitor** (2025Q4)
> Built to satisfy Epic7 VEX Consensus Lens requirements. > Built to satisfy Epic7 VEX Consensus Lens requirements.
> **Scope.** This document specifies the **Vexer** service: its purpose, trust model, data structures, APIs, plugin contracts, storage schema, normalization/consensus algorithms, performance budgets, testing matrix, and how it integrates with Scanner, Policy, Feedser, and the attestation chain. It is implementationready. > **Scope.** This document specifies the **Excitor** service: its purpose, trust model, data structures, APIs, plugin contracts, storage schema, normalization/consensus algorithms, performance budgets, testing matrix, and how it integrates with Scanner, Policy, Conselier, and the attestation chain. It is implementationready.
--- ---
@@ -12,9 +12,9 @@
**Boundaries.** **Boundaries.**
* Vexer **does not** decide PASS/FAIL. It supplies **evidence** (statuses + justifications + provenance weights). * Excitor **does not** decide PASS/FAIL. It supplies **evidence** (statuses + justifications + provenance weights).
* Vexer preserves **conflicting claims** unchanged; consensus encodes how we would pick, but the raw set is always exportable. * Excitor preserves **conflicting claims** unchanged; consensus encodes how we would pick, but the raw set is always exportable.
* VEX consumption is **backendonly**: Scanner never applies VEX. The backends **Policy Engine** asks Vexer for status evidence and then decides what to show. * VEX consumption is **backendonly**: Scanner never applies VEX. The backends **Policy Engine** asks Excitor for status evidence and then decides what to show.
--- ---
@@ -54,7 +54,7 @@ VexClaim
* `rollupStatus` (after policy weights/justification gates), * `rollupStatus` (after policy weights/justification gates),
* `sources[]` (winning + losing claims with weights & reasons), * `sources[]` (winning + losing claims with weights & reasons),
* `policyRevisionId` (identifier of the Vexer policy used), * `policyRevisionId` (identifier of the Excitor policy used),
* `consensusDigest` (stable SHA256 over canonical JSON). * `consensusDigest` (stable SHA256 over canonical JSON).
* **Raw claims** export for auditing (unchanged, with provenance). * **Raw claims** export for auditing (unchanged, with provenance).
* **Provider snapshots** (per source, last N days) for operator debugging. * **Provider snapshots** (per source, last N days) for operator debugging.
@@ -69,7 +69,7 @@ All exports are **deterministic**, and (optionally) **attested** via DSSE and lo
### 2.1 Vuln identity ### 2.1 Vuln identity
* Accepts **CVE**, **GHSA**, vendor IDs (MSRC, RHSA…), distro IDs (DSA/USN/RHSA…) — normalized to `vulnId` with alias sets. * Accepts **CVE**, **GHSA**, vendor IDs (MSRC, RHSA…), distro IDs (DSA/USN/RHSA…) — normalized to `vulnId` with alias sets.
* **Alias graph** maintained (from Feedser) to map vendor/distro IDs → CVE (primary) and to **GHSA** where applicable. * **Alias graph** maintained (from Conselier) to map vendor/distro IDs → CVE (primary) and to **GHSA** where applicable.
### 2.2 Product identity (`productKey`) ### 2.2 Product identity (`productKey`)
@@ -78,13 +78,13 @@ All exports are **deterministic**, and (optionally) **attested** via DSSE and lo
* **Fallback:** `oci:<registry>/<repo>@<digest>` for imagelevel VEX. * **Fallback:** `oci:<registry>/<repo>@<digest>` for imagelevel VEX.
* **Special cases:** kernel modules, firmware, platforms → providerspecific mapping helpers (connector captures providers product taxonomy → canonical `productKey`). * **Special cases:** kernel modules, firmware, platforms → providerspecific mapping helpers (connector captures providers product taxonomy → canonical `productKey`).
> Vexer does not invent identities. If a provider cannot be mapped to purl/CPE/NVRA deterministically, we keep the native **product string** and mark the claim as **nonjoinable**; the backend will ignore it unless a policy explicitly whitelists that provider mapping. > Excitor does not invent identities. If a provider cannot be mapped to purl/CPE/NVRA deterministically, we keep the native **product string** and mark the claim as **nonjoinable**; the backend will ignore it unless a policy explicitly whitelists that provider mapping.
--- ---
## 3) Storage schema (MongoDB) ## 3) Storage schema (MongoDB)
Database: `vexer` Database: `excitor`
### 3.1 Collections ### 3.1 Collections
@@ -248,7 +248,7 @@ public interface IVexConnector
### 6.1 Inputs ### 6.1 Inputs
* Set **S** of `VexClaim` for the key. * Set **S** of `VexClaim` for the key.
* **Vexer policy snapshot**: * **Excitor policy snapshot**:
* **weights** per provider tier and per provider overrides. * **weights** per provider tier and per provider overrides.
* **justification gates** (e.g., require justification for `not_affected` to be acceptable). * **justification gates** (e.g., require justification for `not_affected` to be acceptable).
@@ -329,8 +329,8 @@ GET /providers/{id}/status → last fetch, doc counts, signature stats
## 9) Configuration (YAML) ## 9) Configuration (YAML)
```yaml ```yaml
vexer: excitor:
mongo: { uri: "mongodb://mongo/vexer" } mongo: { uri: "mongodb://mongo/excitor" }
s3: s3:
endpoint: http://minio:9000 endpoint: http://minio:9000
bucket: stellaops bucket: stellaops
@@ -429,7 +429,7 @@ vexer:
## 14) Integration points ## 14) Integration points
* **Backend Policy Engine** (in Scanner.WebService): calls `POST /excititor/resolve` (scope `vex.read`) with batched `(purl, vulnId)` pairs to fetch `rollupStatus + sources`. * **Backend Policy Engine** (in Scanner.WebService): calls `POST /excititor/resolve` (scope `vex.read`) with batched `(purl, vulnId)` pairs to fetch `rollupStatus + sources`.
* **Feedser**: provides alias graph (CVE↔vendor IDs) and may supply VEXadjacent metadata (e.g., KEV flag) for policy escalation. * **Conselier**: provides alias graph (CVE↔vendor IDs) and may supply VEXadjacent metadata (e.g., KEV flag) for policy escalation.
* **UI**: VEX explorer screens use `/claims/search` and `/consensus/search`; show conflicts & provenance. * **UI**: VEX explorer screens use `/claims/search` and `/consensus/search`; show conflicts & provenance.
* **CLI**: `stellaops vex export --consensus --since 7d --out vex.json` for audits. * **CLI**: `stellaops vex export --consensus --since 7d --out vex.json` for audits.

View File

@@ -1,4 +1,4 @@
# Implementation plan — Vexer # Implementation plan — Excitor
## Delivery phases ## Delivery phases
- **Phase 1 Connectors & normalization** - **Phase 1 Connectors & normalization**
@@ -31,7 +31,7 @@
- Console modules (list/detail, conflict diagnostics, provider health, simulation hooks). - Console modules (list/detail, conflict diagnostics, provider health, simulation hooks).
- **Integrations** - **Integrations**
- Policy Engine trust knobs, Vuln Explorer consensus badges, Advisory AI narrative generation, Notify alerts for conflicts. - Policy Engine trust knobs, Vuln Explorer consensus badges, Advisory AI narrative generation, Notify alerts for conflicts.
- Orchestrator jobs for recompute/backfill triggered by Excitator deltas. - Orchestrator jobs for recompute/backfill triggered by Excitor deltas.
- **Observability & Ops** - **Observability & Ops**
- Metrics (ingest latency, signature failure rate, conflict rate, consensus latency). - Metrics (ingest latency, signature failure rate, conflict rate, consensus latency).
- Logs/traces with tenant/issuer/provenance context. - Logs/traces with tenant/issuer/provenance context.
@@ -54,7 +54,7 @@
## Test strategy ## Test strategy
- **Unit:** connector parsers, normalization, mapping conversions, lattice operations. - **Unit:** connector parsers, normalization, mapping conversions, lattice operations.
- **Property:** randomised evidence ensuring commutative consensus and deterministic digests. - **Property:** randomised evidence ensuring commutative consensus and deterministic digests.
- **Integration:** end-to-end pipeline from Excitator to consensus export, policy simulation, conflict handling. - **Integration:** end-to-end pipeline from Excitor to consensus export, policy simulation, conflict handling.
- **Performance:** large feed ingestion, recompute stress, CLI export throughput. - **Performance:** large feed ingestion, recompute stress, CLI export throughput.
- **Security:** signature tampering, issuer revocation, RBAC. - **Security:** signature tampering, issuer revocation, RBAC.
- **Offline:** export/import verification, DSSE bundle validation. - **Offline:** export/import verification, DSSE bundle validation.

View File

@@ -1,6 +1,6 @@
## Status ## Status
This document tracks the future-looking risk scoring model for Vexer. The calculation below is not active yet; Sprint 7 work will add the required schema fields, policy controls, and services. Until that ships, Vexer emits consensus statuses without numeric scores. This document tracks the future-looking risk scoring model for Excitor. The calculation below is not active yet; Sprint 7 work will add the required schema fields, policy controls, and services. Until that ships, Excitor emits consensus statuses without numeric scores.
## Scoring model (target state) ## Scoring model (target state)
@@ -8,7 +8,7 @@ This document tracks the future-looking risk scoring model for Vexer. The calcul
* **Gate(VEX_status)**: `affected`/`under_investigation` → 1, `not_affected`/`fixed` → 0. A trusted “not affected” or “fixed” still zeroes the score. * **Gate(VEX_status)**: `affected`/`under_investigation` → 1, `not_affected`/`fixed` → 0. A trusted “not affected” or “fixed” still zeroes the score.
* **W_trust(source)**: normalized policy weight (baseline 01). Policies may opt into >1 boosts for signed vendor feeds once Phase 1 closes. * **W_trust(source)**: normalized policy weight (baseline 01). Policies may opt into >1 boosts for signed vendor feeds once Phase 1 closes.
* **Severity_base**: canonical numeric severity from Feedser (CVSS or org-defined scale). * **Severity_base**: canonical numeric severity from Conselier (CVSS or org-defined scale).
* **KEV flag**: 0/1 boost when CISA Known Exploited Vulnerabilities applies. * **KEV flag**: 0/1 boost when CISA Known Exploited Vulnerabilities applies.
* **EPSS**: probability [0,1]; bounded multiplier. * **EPSS**: probability [0,1]; bounded multiplier.
* **α, β**: configurable coefficients (default α=0.25, β=0.5) stored in policy. * **α, β**: configurable coefficients (default α=0.25, β=0.5) stored in policy.
@@ -19,9 +19,9 @@ Safeguards: freeze boosts when product identity is unknown, clamp outputs ≥0,
| Phase | Scope | Artifacts | | Phase | Scope | Artifacts |
| --- | --- | --- | | --- | --- | --- |
| **Phase 1 Schema foundations** | Extend Vexer consensus/claims and Feedser canonical advisories with severity, KEV, EPSS, and expose α/β + weight ceilings in policy. | Sprint 7 tasks `VEXER-CORE-02-001`, `VEXER-POLICY-02-001`, `VEXER-STORAGE-02-001`, `FEEDCORE-ENGINE-07-001`. | | **Phase 1 Schema foundations** | Extend Excitor consensus/claims and Conselier canonical advisories with severity, KEV, EPSS, and expose α/β + weight ceilings in policy. | Sprint 7 tasks `EXCITOR-CORE-02-001`, `EXCITOR-POLICY-02-001`, `EXCITOR-STORAGE-02-001`, `FEEDCORE-ENGINE-07-001`. |
| **Phase 2 Deterministic score engine** | Implement a scoring component that executes alongside consensus and persists score envelopes with hashes. | Planned task `VEXER-CORE-02-002` (backlog). | | **Phase 2 Deterministic score engine** | Implement a scoring component that executes alongside consensus and persists score envelopes with hashes. | Planned task `EXCITOR-CORE-02-002` (backlog). |
| **Phase 3 Surfacing & enforcement** | Expose scores via WebService/CLI, integrate with Feedser noise priors, and enforce policy-based suppressions. | To be scheduled after Phase 2. | | **Phase 3 Surfacing & enforcement** | Expose scores via WebService/CLI, integrate with Conselier noise priors, and enforce policy-based suppressions. | To be scheduled after Phase 2. |
## Data model (after Phase 1) ## Data model (after Phase 1)
@@ -60,7 +60,7 @@ Safeguards: freeze boosts when product identity is unknown, clamp outputs ≥0,
## Operational guidance ## Operational guidance
* **Inputs**: Feedser delivers severity/KEV/EPSS via the advisory event log; Vexer connectors load VEX statements. Policy owns trust tiers and coefficients. * **Inputs**: Conselier delivers severity/KEV/EPSS via the advisory event log; Excitor connectors load VEX statements. Policy owns trust tiers and coefficients.
* **Processing**: the scoring engine (Phase 2) runs next to consensus, storing results with deterministic hashes so exports and attestations can reference them. * **Processing**: the scoring engine (Phase 2) runs next to consensus, storing results with deterministic hashes so exports and attestations can reference them.
* **Consumption**: WebService/CLI will return consensus plus score; scanners may suppress findings only when policy-authorized VEX gating and signed score envelopes agree. * **Consumption**: WebService/CLI will return consensus plus score; scanners may suppress findings only when policy-authorized VEX gating and signed score envelopes agree.

View File

@@ -76,7 +76,7 @@ Sample (abridged):
"parameters": { "parameters": {
"tenant": "tenant-01", "tenant": "tenant-01",
"baseExportId": "run-20251020-01", "baseExportId": "run-20251020-01",
"selectors": { "sources": ["concelier","vexer"], "profiles": ["mirror"] } "selectors": { "sources": ["concelier","excitor"], "profiles": ["mirror"] }
} }
}, },
"materials": [ "materials": [

View File

@@ -88,6 +88,7 @@
- `curl -fsSL https://localhost:8447/health/live` - `curl -fsSL https://localhost:8447/health/live`
- Issue an access token and list issuers to confirm results. - Issue an access token and list issuers to confirm results.
- Check Mongo counts match expectations (`db.issuers.countDocuments()`, etc.). - Check Mongo counts match expectations (`db.issuers.countDocuments()`, etc.).
- Confirm Prometheus scrapes `issuer_directory_changes_total` and `issuer_directory_key_operations_total` for the tenants you restored.
## Disaster recovery notes ## Disaster recovery notes
- **Retention:** Maintain 30 daily + 12 monthly archives. Store copies in geographically separate, access-controlled vaults. - **Retention:** Maintain 30 daily + 12 monthly archives. Store copies in geographically separate, access-controlled vaults.
@@ -98,6 +99,6 @@
## Verification checklist ## Verification checklist
- [ ] `/health/live` returns `200 OK`. - [ ] `/health/live` returns `200 OK`.
- [ ] Mongo collections (`issuers`, `issuer_keys`, `issuer_trust_overrides`) have expected counts. - [ ] Mongo collections (`issuers`, `issuer_keys`, `issuer_trust_overrides`) have expected counts.
- [ ] `issuer_directory_changes_total` and `issuer_directory_key_operations_total` metrics resume within 1 minute. - [ ] `issuer_directory_changes_total`, `issuer_directory_key_operations_total`, and `issuer_directory_key_validation_failures_total` metrics resume within 1 minute.
- [ ] Audit entries exist for post-restore CRUD activity. - [ ] Audit entries exist for post-restore CRUD activity.
- [ ] Client integrations (VEX Lens, Excititor) resolve issuers successfully. - [ ] Client integrations (VEX Lens, Excititor) resolve issuers successfully.

View File

@@ -39,6 +39,13 @@
``` ```
Compose automatically mounts `../../etc/issuer-directory.yaml` into the container at `/etc/issuer-directory.yaml`, seeds CSAF publishers, and exposes the API on `https://localhost:8447`. Compose automatically mounts `../../etc/issuer-directory.yaml` into the container at `/etc/issuer-directory.yaml`, seeds CSAF publishers, and exposes the API on `https://localhost:8447`.
### Compose environment variables
| Variable | Purpose | Default |
| --- | --- | --- |
| `ISSUER_DIRECTORY_PORT` | Host port that maps to container port `8080`. | `8447` |
| `ISSUER_DIRECTORY_MONGO_CONNECTION_STRING` | Injected into `ISSUERDIRECTORY__MONGO__CONNECTIONSTRING`; should contain credentials. | `mongodb://${MONGO_INITDB_ROOT_USERNAME}:${MONGO_INITDB_ROOT_PASSWORD}@mongo:27017` |
| `ISSUER_DIRECTORY_SEED_CSAF` | Toggles CSAF bootstrap on startup. Set to `false` after the first production import if you manage issuers manually. | `true` |
4. **Smoke test** 4. **Smoke test**
```bash ```bash
curl -k https://localhost:8447/health/live curl -k https://localhost:8447/health/live

View File

@@ -12,6 +12,7 @@ Include the following artefacts in your Offline Update Kit staging tree:
| `config/issuer-directory/issuer-directory.yaml` | `etc/issuer-directory.yaml` (customised) | Replace Authority issuer, tenant header, and log level as required. | | `config/issuer-directory/issuer-directory.yaml` | `etc/issuer-directory.yaml` (customised) | Replace Authority issuer, tenant header, and log level as required. |
| `config/issuer-directory/csaf-publishers.json` | `src/IssuerDirectory/StellaOps.IssuerDirectory/data/csaf-publishers.json` or regional override | Operators can edit before import to add private publishers. | | `config/issuer-directory/csaf-publishers.json` | `src/IssuerDirectory/StellaOps.IssuerDirectory/data/csaf-publishers.json` or regional override | Operators can edit before import to add private publishers. |
| `secrets/issuer-directory/connection.env` | Secure secret store export (`ISSUER_DIRECTORY_MONGO_CONNECTION_STRING=`) | Encrypt at rest; Offline Kit importer places it in the Compose/Helm secret. | | `secrets/issuer-directory/connection.env` | Secure secret store export (`ISSUER_DIRECTORY_MONGO_CONNECTION_STRING=`) | Encrypt at rest; Offline Kit importer places it in the Compose/Helm secret. |
| `env/issuer-directory.env` (optional) | Curated `.env` snippet (for example `ISSUER_DIRECTORY_SEED_CSAF=false`) | Helps operators disable reseeding after their first import without editing the main profile. |
| `docs/issuer-directory/deployment.md` | `docs/modules/issuer-directory/operations/deployment.md` | Ship alongside kit documentation for operators. | | `docs/issuer-directory/deployment.md` | `docs/modules/issuer-directory/operations/deployment.md` | Ship alongside kit documentation for operators. |
> **Image digests:** Update `deploy/releases/2025.10-edge.yaml` (or the relevant manifest) with the exact digest before building the kit so `offline-manifest.json` can assert integrity. > **Image digests:** Update `deploy/releases/2025.10-edge.yaml` (or the relevant manifest) with the exact digest before building the kit so `offline-manifest.json` can assert integrity.
@@ -69,3 +70,4 @@ Include the following artefacts in your Offline Update Kit staging tree:
- [ ] `/issuer-directory/issuers` returns global seed issuers (requires token with `issuer-directory:read` scope). - [ ] `/issuer-directory/issuers` returns global seed issuers (requires token with `issuer-directory:read` scope).
- [ ] Audit collection receives entries when you create/update issuers offline. - [ ] Audit collection receives entries when you create/update issuers offline.
- [ ] Offline kit manifest (`offline-manifest.json`) lists `images/issuer-directory-web.tar` and `config/issuer-directory/issuer-directory.yaml` with SHA-256 values you recorded during packaging. - [ ] Offline kit manifest (`offline-manifest.json`) lists `images/issuer-directory-web.tar` and `config/issuer-directory/issuer-directory.yaml` with SHA-256 values you recorded during packaging.
- [ ] Prometheus in the offline environment reports `issuer_directory_changes_total` for the tenants imported from the kit.

View File

@@ -8,9 +8,10 @@
**Boundaries.** **Boundaries.**
* Notify **does not make policy decisions** and **does not rescan**; it **consumes** events from Scanner/Scheduler/Vexer/Feedser/Attestor/Zastava and routes them. * Notify **does not make policy decisions** and **does not rescan**; it **consumes** events from Scanner/Scheduler/Excitor/Conselier/Attestor/Zastava and routes them.
* Attachments are **links** (UI/attestation pages); Notify **does not** attach SBOMs or large blobs to messages. * Attachments are **links** (UI/attestation pages); Notify **does not** attach SBOMs or large blobs to messages.
* Secrets for channels (Slack tokens, SMTP creds) are **referenced**, not stored raw in Mongo. * Secrets for channels (Slack tokens, SMTP creds) are **referenced**, not stored raw in Mongo.
* **2025-11-02 module boundary.** Maintain `src/Notify/` as the reusable notification toolkit (engine, storage, queue, connectors) and `src/Notifier/` as the Notifications Studio host that composes those libraries. Do not merge directories without an approved packaging RFC that covers build impacts, offline kit parity, and cross-module governance.
--- ---
@@ -77,11 +78,11 @@ Notify subscribes to the **internal event bus** (produced by services, escaped J
* `scanner.scan.completed` — new SBOM(s) composed; artifacts ready * `scanner.scan.completed` — new SBOM(s) composed; artifacts ready
* `scanner.report.ready` — analysis verdict (policy+vex) available; carries deltas summary * `scanner.report.ready` — analysis verdict (policy+vex) available; carries deltas summary
* `scheduler.rescan.delta` — new findings after Feedser/Vexer deltas (already summarized) * `scheduler.rescan.delta` — new findings after Conselier/Excitor deltas (already summarized)
* `attestor.logged` — Rekor UUID returned (sbom/report/vex export) * `attestor.logged` — Rekor UUID returned (sbom/report/vex export)
* `zastava.admission` — admit/deny with reasons, namespace, image digests * `zastava.admission` — admit/deny with reasons, namespace, image digests
* `feedser.export.completed` — new export ready (rarely notified directly; usually drives Scheduler) * `conselier.export.completed` — new export ready (rarely notified directly; usually drives Scheduler)
* `vexer.export.completed` — new consensus snapshot (ditto) * `excitor.export.completed` — new consensus snapshot (ditto)
**Canonical envelope (bus → Notify.Engine):** **Canonical envelope (bus → Notify.Engine):**
@@ -467,7 +468,7 @@ notify:
## 17) Sequences (representative) ## 17) Sequences (representative)
**A) New criticals after Feedser delta (Slack immediate + Email hourly digest)** **A) New criticals after Conselier delta (Slack immediate + Email hourly digest)**
```mermaid ```mermaid
sequenceDiagram sequenceDiagram

View File

@@ -15,8 +15,8 @@
"scheduler.rescan.delta", "scheduler.rescan.delta",
"attestor.logged", "attestor.logged",
"zastava.admission", "zastava.admission",
"feedser.export.completed", "conselier.export.completed",
"vexer.export.completed" "excitor.export.completed"
] ]
}, },
"version": {"type": "string"}, "version": {"type": "string"},

View File

@@ -8,6 +8,8 @@ Policy Engine compiles and evaluates Stella DSL policies deterministically, prod
- [Architecture](./architecture.md) - [Architecture](./architecture.md)
- [Implementation plan](./implementation_plan.md) - [Implementation plan](./implementation_plan.md)
- [Task board](./TASKS.md) - [Task board](./TASKS.md)
- [Secret leak detection readiness](../policy/secret-leak-detection-readiness.md)
- [Windows package readiness](../policy/windows-package-readiness.md)
## How to get started ## How to get started
1. Open ../../implplan/SPRINTS.md and locate the stories referencing this module. 1. Open ../../implplan/SPRINTS.md and locate the stories referencing this module.

View File

@@ -21,6 +21,8 @@ Policy Engine compiles and evaluates Stella DSL policies deterministically, prod
- DSL grammar and lifecycle docs in ../../policy/. - DSL grammar and lifecycle docs in ../../policy/.
- Observability guidance in ../../observability/policy.md. - Observability guidance in ../../observability/policy.md.
- Governance and scope mapping in ../../security/policy-governance.md. - Governance and scope mapping in ../../security/policy-governance.md.
- Readiness briefs: ../policy/secret-leak-detection-readiness.md, ../policy/windows-package-readiness.md.
- Readiness briefs: ../scanner/design/macos-analyzer.md, ../scanner/design/windows-analyzer.md, ../policy/secret-leak-detection-readiness.md, ../policy/windows-package-readiness.md.
## Backlog references ## Backlog references
- DOCS-POLICY-20-001 … DOCS-POLICY-20-012 (completed baseline). - DOCS-POLICY-20-001 … DOCS-POLICY-20-012 (completed baseline).

View File

@@ -7,3 +7,5 @@
| POLICY ENGINE-DOCS-0001 | TODO | Docs Guild | Validate that ./README.md aligns with the latest release notes. | See ./AGENTS.md | | POLICY ENGINE-DOCS-0001 | TODO | Docs Guild | Validate that ./README.md aligns with the latest release notes. | See ./AGENTS.md |
| POLICY ENGINE-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md | | POLICY ENGINE-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md |
| POLICY ENGINE-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow | | POLICY ENGINE-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow |
| POLICY-READINESS-0001 | DOING (2025-11-03) | Policy Guild, Security Guild | Resolve open questions in `../policy/secret-leak-detection-readiness.md` ahead of SCANNER-ENG-0007. | Decision workshop 2025-11-10 (Northwind demo); cover masking depth, telemetry retention, bundle defaults, tenant overrides. |
| POLICY-READINESS-0002 | DOING (2025-11-03) | Policy Guild, Security Guild, Offline Kit Guild | Review `../policy/windows-package-readiness.md`, set signature verification locus, feed mirroring scopes, and legacy installer posture. | FinSecure PCI blocker; deliver Authenticode/feed decision by 2025-11-07 before analyzer spike kickoff. |

View File

@@ -0,0 +1,80 @@
# Secret Leak Detection Readiness — Policy & Security Brief
> Audience: Policy Guild, Security Guild
> Related backlog: SCANNER-ENG-0007 (deterministic leak detection pipeline), DOCS-SCANNER-BENCH-62-007 (rule bundle documentation), SCANNER-SECRETS-01..03 (Surface.Secrets alignment)
## 1. Goal & scope
- Provide a shared understanding of how the planned `StellaOps.Scanner.Analyzers.Secrets` plug-in will operate so Policy/Security can prepare governance controls in parallel with engineering delivery.
- Document evidence flow, policy predicates, and offline distribution requirements to minimise lead time once implementation lands.
- Capture open questions requiring Policy/Security sign-off (masking rules, tenancy constraints, waiver workflows).
## 2. Proposed evidence pipeline
1. **Source resolution**
- Surface.Secrets providers (Kubernetes, file bundle, inline) continue to resolve operational credentials. Handles remain opaque and never enter analyzer outputs.
2. **Deterministic scanning**
- New plug-in executes signed rule bundles (regex + entropy signatures) stored under `scanner/rules/secrets/`.
- Execution context restricted to read-only layer mount; analyzers emit `secret.leak` evidence with: `{rule.id, rule.version, confidence, severity, mask, file, line}`.
3. **Analysis store persistence**
- Findings are written into `ScanAnalysisStore` (`ScanAnalysisKeys.secretFindings`) so Policy Engine can ingest them alongside component fragments.
4. **Policy overlay**
- Policy predicates (see §3) evaluate evidence, lattice scores, and tenant-scoped allow/deny lists.
- CLI/export surfaces show masked snippets and remediation hints.
5. **Offline parity**
- Rule bundles, signature manifests, and validator hash lists ship with Offline Kit; rule updates must be signed and versioned to preserve determinism.
## 3. Policy Engine considerations
- **New predicates**
- `secret.hasFinding(ruleId?, severity?, confidence?)`
- `secret.bundle.version(requiredVersion)`
- `secret.mask.applied` (bool) — verify masking for high severity hits.
- `secret.path.allowlist` — tenant-configured allow list keyed by digest/path.
- **Lattice weight suggestions**
- High severity & high confidence → escalate to `block` unless waived.
- Low confidence → default to `warn` with optional escalation when multiple matches occur (`secret.match.count >= N`).
- **Waiver workflow**
- Reuse VEX-first lattice approach: require attach of remediation note, ticket reference, and expiration date.
- Ensure waivers attach rule version so upgraded rules re-evaluate automatically.
- **Masking / privacy**
- Minimum masking: first and last 2 characters retained; remainder replaced with `*`.
- Persist masked payload only; full value never leaves scanner context.
## 4. Security guardrails
- Rule bundle signing: Signer issues DSSE envelope for each ruleset; Policy must verify signature before enabling new bundle.
- Tenant isolation: bundle enablement scoped per tenant; defaults deny unknown bundles.
- Telemetry: emit `scanner.secret.finding_total{tenant, ruleId, severity}` with masking applied after count aggregation.
- Access control: restrict retrieval of raw finding payloads to roles with `scanner.secret.read` scope; audits log query + tenant + rule id.
## 5. Offline & update flow
1. Engineering publishes new bundle → Signer signs → Offline Kit includes bundle + manifest.
2. Operators import bundle via CLI (`stella secrets bundle install --path <bundle>`).
- CLI verifies signature, version monotonicity, and rule hash list.
3. Policy update: push config snippet enabling bundle, severity mapping, and waiver templates.
4. Run `stella secrets scan --dry-run` to verify deterministic output against golden fixtures before enabling in production.
## 6. Open questions / owners
| Topic | Question | Owner | Target decision |
| --- | --- | --- | --- |
| Masking depth | Do we mask file paths or only payloads? | Security Guild | Sprint 132 design review |
| Telemetry retention | Should secret finding metrics be sampled or full fidelity? | Policy + Observability Guild | Sprint 132 |
| Default bundles | Which rule families ship enabled-by-default (cloud creds, SSH keys, JWT)? | Security Guild | Sprint 133 |
| Tenant overrides | Format for per-tenant allow lists (path glob vs digest)? | Policy Guild | Sprint 133 |
### Decision tracker
| Decision | Owner(s) | Target date | Status |
| --- | --- | --- | --- |
| Masking depth (paths vs payloads) | Security Guild | 2025-11-10 | Pending — workshop aligned with Northwind demo |
| Telemetry retention granularity | Policy + Observability Guild | 2025-11-10 | Pending |
| Default rule bundles (cloud creds/SSH/JWT) | Security Guild | 2025-11-10 | Draft proposals under review |
| Tenant override format | Policy Guild | 2025-11-10 | Pending |
## 7. Next steps
1. Policy Guild drafts predicate specs + policy templates (map to DOCS-SCANNER-BENCH-62-007 exit criteria).
2. Security Guild reviews signing + masking requirements; align with Surface.Secrets roadmap.
3. Docs Guild (this task) continues maintaining `docs/benchmarks/scanner/deep-dives/secrets.md` with finalized rule taxonomy and references.
4. Engineering provides prototype fixture outputs for review once SCANNER-ENG-0007 spikes begin.
## Coordination
- Capture macOS customer requirements via `docs/benchmarks/scanner/windows-macos-demand.md` (Northwind Health Services).
- Update dashboard (`docs/api/scanner/windows-macos-summary.md`) after readiness decisions.
- Share outcomes from 2025-11-10 macOS demo before finalising POLICY-READINESS-0001.

View File

@@ -0,0 +1,92 @@
# Windows Package Coverage — Policy & Security Readiness Brief
> Audience: Policy Guild, Security Guild, Offline Kit Guild
> Related engineering backlog (proposed): SCANNER-ENG-0024..0027
> Docs linkage: DOCS-SCANNER-BENCH-62-016
## 1. Goal
- Prepare policy and security guidance ahead of Windows analyzer implementation (MSI, WinSxS, Chocolatey, registry).
- Define evidence handling, predicates, waiver expectations, and offline prerequisites so engineering can align during spike execution.
## 2. Evidence pipeline snapshot (from `design/windows-analyzer.md`)
1. **Collection**
- MSI database parsing → component records keyed by ProductCode/ComponentCode.
- WinSxS manifests → assembly identities, catalog signatures.
- Chocolatey packages → nuspec metadata, feed provenance, script hashes.
- Registry exports → uninstall/service entries, legacy installers.
- Driver/service mapper → capability overlays (kernel-mode, auto-start).
2. **Storage**
- Results persisted as `LayerComponentFragment`s plus capability overlays (`ScanAnalysisKeys.capability.windows`).
- Provenance metadata includes signature thumbprint, catalog hash, feed URL, install context.
3. **Downstream**
- Policy Engine consumes component + capability evidence; Export Center bundles MSI manifests, nuspec metadata, catalog hashes.
## 3. Policy predicate requirements
| Predicate | Description | Initial default |
| --- | --- | --- |
| `windows.package.signed(thumbprint?)` | True when Authenticode signature/cert matches allowlist. | Warn on missing signature, fail on mismatched thumbprint for kernel drivers. |
| `windows.package.sourceAllowed(sourceId)` | Validates Chocolatey/nuget feed against tenant allowlist. | Fail if feed not in tenant policy. |
| `windows.driver.kernelMode()` | Flags kernel-mode drivers for extra scrutiny. | Fail when unsigned; warn otherwise. |
| `windows.driver.signedBy(publisher)` | Checks driver publisher matches allowlist. | Warn on unknown publisher. |
| `windows.service.autoStart(name)` | Identifies auto-start services. | Warn if unsigned binary or service not in allowlist. |
| `windows.package.legacyInstaller()` | Legacy EXE-only installers detected via registry. | Warn by default; escalate if binary unsigned. |
Additional considerations:
- Map KB references (from WinSxS/MSP metadata) to vulnerability posture once Policy Engine supports patch layering.
- Provide predicates to waive specific ProductCodes or AssemblyIdentities with expiration.
## 4. Waiver & governance model
- Waiver key: `{productCode, version, signatureThumbprint}` or for drivers `{driverName, serviceName, signatureThumbprint}`.
- Required metadata: remediation ticket, justification, expiry date.
- Automated re-evaluation when version or signature changes.
- Tenants maintain allow lists for Chocolatey feeds and driver publishers via policy configuration.
## 5. Masking & privacy
- Findings should not include raw script contents; provide SHA256 hash and limited excerpt (first/last 8 chars).
- Registry values (install paths, command lines) must be truncated if they contain secrets; rely on Surface.Secrets to manage environment variables referenced during install scripts.
## 6. Offline kit guidance
- Bundle:
- MSI parser binary + schema definitions.
- Chocolatey feed snapshot(s) (nupkg files) with hash manifest.
- Microsoft root/intermediate certificate bundles; optional CRL/OCSP cache instructions.
- Operators must export registry hives (`SOFTWARE`, `SYSTEM`) during image extraction; document PowerShell script and required access.
- Provide checksum manifest to verify feed snapshot integrity.
## 7. Telemetry expectations
- Metrics:
- `scanner.windows.package_total{tenant,signed}` — count packages per signature state.
- `scanner.windows.driver_unsigned_total{tenant}`.
- `scanner.windows.choco_feed_total{tenant,feed}`.
- Logs:
- Include product code, version, signature thumbprint, feed ID (no file paths unless sanitized).
- Traces:
- Annotate collector spans (`collector.windows.msi`, `collector.windows.winsxs`, etc.) with component counts and parsing duration.
## 8. Open questions
| Topic | Question | Owner | Target decision |
| --- | --- | --- | --- |
| Signature verification locus | Scanner vs Policy: where to verify Authenticode signatures + revocation? | Security Guild | Sprint 133 |
| Feed mirroring scope | Default set of Chocolatey feeds to mirror (official/community). | Product + Security Guild | Sprint 133 |
| Legacy installers | Should we block unsigned EXE installers by default or allow warn-only posture? | Policy Guild | Sprint 134 |
| Driver taxonomy | Define high-risk driver categories (kernel-mode, filter drivers) for policy severity. | Policy Guild | Sprint 134 |
### Decision tracker
| Decision | Owner(s) | Target date | Status |
| --- | --- | --- | --- |
| Authenticode verification locus (Scanner vs Policy) | Security Guild | 2025-11-07 | Pending — blocker for FinSecure |
| Chocolatey feed mirroring scope | Product + Security Guild | 2025-11-07 | Draft proposal circulating |
| Legacy installer posture (warn vs fail) | Policy Guild | 2025-11-14 | Not started |
| Driver risk taxonomy | Policy Guild | 2025-11-14 | Not started |
## 9. Next steps
1. Policy Guild drafts predicate specs + policy templates; align with DOCS-SCANNER-BENCH-62-016.
2. Security Guild evaluates signature verification approach and revocation handling (online vs offline CRL cache).
3. Offline Kit Guild scopes snapshot size and update cadence for Chocolatey feeds and certificate bundles.
4. Docs Guild prepares policy/user guidance updates once predicates are finalised.
5. Security Guild to report decision for FinSecure Corp (POLICY-READINESS-0002) by 2025-11-07; feed outcome into dashboards.
## Coordination
- Sync demand signals via `docs/benchmarks/scanner/windows-macos-demand.md`.
- Log policy readiness status in `docs/api/scanner/windows-coverage.md`.
- Update Windows/macOS metrics dashboard when decisions change (`docs/api/scanner/windows-macos-summary.md`).

View File

@@ -8,6 +8,12 @@ Scanner analyses container images layer-by-layer, producing deterministic SBOM f
- [Architecture](./architecture.md) - [Architecture](./architecture.md)
- [Implementation plan](./implementation_plan.md) - [Implementation plan](./implementation_plan.md)
- [Task board](./TASKS.md) - [Task board](./TASKS.md)
- [macOS analyzer design](./design/macos-analyzer.md)
- [Windows analyzer design](./design/windows-analyzer.md)
- [Field engagement workflow](./operations/field-engagement.md)
- [Design dossiers](./design/README.md)
- [Benchmarks overview](../../benchmarks/scanner/README.md)
- [Benchmarks overview](../../benchmarks/scanner/README.md)
## How to get started ## How to get started
1. Open ../../implplan/SPRINTS.md and locate the stories referencing this module. 1. Open ../../implplan/SPRINTS.md and locate the stories referencing this module.

View File

@@ -28,6 +28,14 @@ Scanner analyses container images layer-by-layer, producing deterministic SBOM f
- ./operations/analyzers-grafana-dashboard.json - ./operations/analyzers-grafana-dashboard.json
- ./operations/rustfs-migration.md - ./operations/rustfs-migration.md
- ./operations/entrypoint.md - ./operations/entrypoint.md
- ./design/macos-analyzer.md
- ./design/windows-analyzer.md
- ../benchmarks/scanner/deep-dives/macos.md
- ../benchmarks/scanner/deep-dives/windows.md
- ../benchmarks/scanner/windows-macos-demand.md
- ../benchmarks/scanner/windows-macos-interview-template.md
- ./operations/field-engagement.md
- ./design/README.md
## Backlog references ## Backlog references
- DOCS-SCANNER updates tracked in ../../TASKS.md. - DOCS-SCANNER updates tracked in ../../TASKS.md.

View File

@@ -28,5 +28,13 @@
| SCANNER-ENG-0005 | TODO | Go Analyzer Guild | Enhance Go stripped-binary fallback inference per `docs/benchmarks/scanner/scanning-gaps-stella-misses-from-competitors.md`. | Include inferred module metadata & policy integration | | SCANNER-ENG-0005 | TODO | Go Analyzer Guild | Enhance Go stripped-binary fallback inference per `docs/benchmarks/scanner/scanning-gaps-stella-misses-from-competitors.md`. | Include inferred module metadata & policy integration |
| SCANNER-ENG-0006 | TODO | Rust Analyzer Guild | Expand Rust fingerprint coverage per `docs/benchmarks/scanner/scanning-gaps-stella-misses-from-competitors.md`. | Ship enriched fingerprint catalogue + policy controls | | SCANNER-ENG-0006 | TODO | Rust Analyzer Guild | Expand Rust fingerprint coverage per `docs/benchmarks/scanner/scanning-gaps-stella-misses-from-competitors.md`. | Ship enriched fingerprint catalogue + policy controls |
| SCANNER-ENG-0007 | TODO | Scanner Guild, Policy Guild | Design deterministic secret leak detection pipeline per `docs/benchmarks/scanner/scanning-gaps-stella-misses-from-competitors.md`. | Include rule packaging, Policy Engine integration, CLI workflow | | SCANNER-ENG-0007 | TODO | Scanner Guild, Policy Guild | Design deterministic secret leak detection pipeline per `docs/benchmarks/scanner/scanning-gaps-stella-misses-from-competitors.md`. | Include rule packaging, Policy Engine integration, CLI workflow |
| SCANNER-ENG-0020 | TODO | Scanner Guild (macOS Cellar Squad) | Implement Homebrew collector and fragment mapper per `design/macos-analyzer.md` §3.1. | Emit brew component fragments with tap provenance; integrate Surface.Validation/FS limits. |
| SCANNER-ENG-0021 | TODO | Scanner Guild (macOS Receipts Squad) | Implement pkgutil receipt collector per `design/macos-analyzer.md` §3.2. | Parse receipts/BOMs into deterministic component records with install metadata. |
| SCANNER-ENG-0022 | TODO | Scanner Guild, Policy Guild (macOS Bundles Squad) | Implement macOS bundle inspector & capability overlays per `design/macos-analyzer.md` §3.3. | Extract signing/entitlements, emit capability evidence, merge with receipts/Homebrew. |
| SCANNER-ENG-0023 | TODO | Scanner Guild, Offline Kit Guild, Policy Guild | Deliver macOS policy/offline integration per `design/macos-analyzer.md` §56. | Define policy predicates, CLI toggles, Offline Kit packaging, and documentation. |
| SCANNER-ENG-0024 | TODO | Scanner Guild (Windows MSI Squad) | Implement Windows MSI collector per `design/windows-analyzer.md` §3.1. | Parse MSI databases, emit component fragments with provenance metadata; blocked until POLICY-READINESS-0002 (decision due 2025-11-07). |
| SCANNER-ENG-0025 | TODO | Scanner Guild (Windows WinSxS Squad) | Implement WinSxS manifest collector per `design/windows-analyzer.md` §3.2. | Correlate assemblies with MSI components and catalog signatures; dependent on POLICY-READINESS-0002 outcome. |
| SCANNER-ENG-0026 | TODO | Scanner Guild (Windows Packages Squad) | Implement Chocolatey & registry collectors per `design/windows-analyzer.md` §3.33.4. | Harvest nuspec metadata and registry uninstall/service evidence; merge with filesystem artefacts; align with feed decisions from POLICY-READINESS-0002. |
| SCANNER-ENG-0027 | TODO | Scanner Guild, Policy Guild, Offline Kit Guild | Deliver Windows policy/offline integration per `design/windows-analyzer.md` §56. | Define predicates, CLI/Offline docs, and packaging for feeds/certs; start after POLICY-READINESS-0002 sign-off. |
| SCANNER-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md | | SCANNER-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md |
| SCANNER-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow | | SCANNER-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow |

View File

@@ -0,0 +1,35 @@
# Scanner Design Dossiers
This directory contains deep technical designs for current and upcoming analyzers and surface components.
## Language analyzers
- `ruby-analyzer.md` — lockfile, runtime graph, capability signals for Ruby.
## Surface & platform contracts
- `surface-fs.md`
- `surface-env.md`
- `surface-validation.md`
- `surface-secrets.md`
## OS ecosystem designs
- `macos-analyzer.md` — Homebrew, pkgutil, `.app` bundle plan.
- `windows-analyzer.md` — MSI, WinSxS, Chocolatey, registry collectors.
## Demand & dashboards
- `../../benchmarks/scanner/windows-macos-demand.md` — demand tracker.
- `../../benchmarks/scanner/windows-macos-interview-template.md` — interview template.
- `../../api/scanner/windows-coverage.md` — coverage summary dashboard.
- `../../api/scanner/windows-macos-summary.md` — metric snapshot.
## Utility & reference
- `../operations/field-engagement.md` — SE workflow guidance.
- `../operations/analyzers.md` — operational runbook.
- `../operations/rustfs-migration.md` — storage migration notes.
## Maintenance tips
- Keep demand tracker (`../../benchmarks/scanner/windows-macos-demand.md`) and API dashboards in sync when updating macOS/Windows designs.
- Cross-reference policy readiness briefs for associated predicates and waiver models.
## Policy readiness
- `../policy/secret-leak-detection-readiness.md` — secret leak pipeline decisions.
- `../policy/windows-package-readiness.md` — Windows analyzer policy decisions.

View File

@@ -0,0 +1,123 @@
# macOS Analyzer Design Brief (Draft)
> Owners: Scanner Guild, Policy Guild, Offline Kit Guild
> Related backlog (proposed): SCANNER-ENG-0020..0023, DOCS-SCANNER-BENCH-62-002
> Status: Draft pending demand validation (see `docs/benchmarks/scanner/windows-macos-demand.md`)
## 1. Scope & objectives
- Deliver deterministic inventory coverage for macOS container and VM images, focusing on Homebrew, Apple/pkgutil receipts, and `.app` bundles.
- Preserve StellaOps principles: per-layer provenance, offline parity, policy explainability, and signed evidence pipelines.
- Provide capability signals (entitlements, hardened runtime, launch agents) to enable Policy Engine gating.
Out of scope (Phase 1):
- Dynamic runtime tracing of macOS services (deferred to Zastava/EntryTrace).
- iOS/tvOS/visionOS package formats (will reuse bundle inspection where feasible).
- Direct notarization ticket validation (delegated to Policy Engine unless otherwise decided).
## 2. High-level architecture
```
Scanner.Worker (macOS profile)
├─ Surface.Validation (enforce allowlists, bundle size limits)
├─ Surface.FS (layer/materialized filesystem)
├─ HomebrewCollector (new) -> LayerComponentFragment (brew)
├─ PkgutilCollector (new) -> LayerComponentFragment (pkgutil)
├─ BundleInspector (new) -> Capability records + component fragments
├─ LaunchAgentMapper (optional) -> Usage hints
└─ MacOsAggregator (new) -> merges fragments, emits ComponentGraph & capability overlays
```
- Each collector runs deterministically against the mounted filesystem; results persist in `ScanAnalysisStore` under dedicated keys before being normalized by `MacOsComponentMapper`.
- Layer digests follow existing `LayerComponentFragment` semantics to maintain diff/replay parity.
## 3. Collectors & data sources
### 3.1 Homebrew collector
- Scan `/usr/local/Cellar/**` and `/opt/homebrew/Cellar/**` for `INSTALL_RECEIPT.json` and `*.rb` formula metadata.
- Output fields: `tap`, `formula`, `version`, `revision`, `poured_from_bottle`, `installed_with`: [].
- Store `bottle.sha256`, `source.url`, and `tapped_from` metadata for provenance.
- Map to PURL: `pkg:brew/<tap>/<formula>@<version>?revision=<revision>`.
- Guardrails: limit traversal depth, ignore caches (`/Caskroom` optional), enforce 200MB per formula cap (configurable).
### 3.2 pkgutil receipt collector
- Parse `/var/db/receipts/*.plist` for pkg identifiers, version, install time, volume, installer domain.
- Use `.bom` files to enumerate installed files; capture path hashes via `osx.BomParser`.
- Emit `ComponentRecord`s keyed by `pkgutil:<identifier>` with metadata: `bundleIdentifier`, `installTimeUtc`, `volume`.
- Provide dependency mapping between pkg receipts and Homebrew formulae when overlapping file hashes exist (optional Phase 2).
### 3.3 Bundle inspector
- Traverse `/Applications`, `/System/Applications`, `/Users/*/Applications`, `/Library/Application Support`.
- For each `.app`:
- Read `Info.plist` (bundle id, version, short version, minimum system).
- Extract code signing metadata via `codesign --display --xml` style parsing (Team ID, certificate chain, hardened runtime flag).
- Parse entitlements (`archived-entitlements.xcent`) and map to capability taxonomy (network, camera, automation, etc.).
- Hash `CodeResources` manifest to support provenance comparisons.
- Link `.app` bundles to receipts and Homebrew formulae using bundle id or install path heuristics.
- Emit capability overlays (e.g., `macos.entitlement("com.apple.security.network.server") == true`).
### 3.4 Launch agent mapper (optional Phase 1 extension)
- Inspect `/Library/Launch{Agents,Daemons}` and user equivalents.
- Parse `plist` for program arguments, run conditions, sockets, environment.
- Feed derived runtime hints into EntryTrace (`UsageHints`) to mark active binaries vs dormant installations.
## 4. Aggregation & output
- `MacOsComponentMapper` converts collector results into:
- `LayerComponentFragment` arrays keyed by synthetic digests (`sha256:stellaops-os-macbrew`, etc.).
- `ComponentMetadata` entries capturing tap origin, Team ID, entitlements, notarization flag (when available).
- Capability overlays stored under `ScanAnalysisKeys.capability.macOS`.
- Export Center enhancements:
- Include Homebrew metadata manifests and CodeResources hashes in attested bundles.
- Provide optional notarization proof attachments if Policy Engine later requires them.
## 5. Policy & governance integration
- Predicates to introduce:
- `macos.bundle.signed(teamId?, hardenedRuntime?)`
- `macos.entitlement(name)`
- `macos.pkg.receipt(identifier, version?)`
- `macos.notarized` (pending Security decision).
- Lattice guidance:
- Unsigned/unnotarized third-party apps default to `warn`.
- High-risk entitlements (camera, screen capture) escalate severity unless whitelisted.
- Waiver model similar to existing EntryTrace/Secrets: require bundle hash + Team ID to avoid broad exceptions.
## 6. Offline kit considerations
- Mirror required Homebrew taps (`homebrew/core`, `homebrew/cask`) and freeze metadata per release.
- Bundle notarization cache instructions (CRL/OCSP) so operators can prefetch without Apple connectivity.
- Package Apple certificate chain updates (WWDR) and provide verification script to ensure validity.
- Document disk space impacts (Homebrew cellar snapshots ~500MB per tap snapshot).
## 7. Testing strategy
- Unit tests with fixture directories:
- Sample Cellar tree with multiple formulas (bottled vs source builds).
- Synthetic pkg receipts + BOM files.
- `.app` bundles with varying signing states (signed/notarized/unsigned).
- Integration tests:
- Build macOS rootfs tarballs via CI job (runner requiring macOS) that mimic layered container conversion.
- Verify deterministic output by re-running collectors and diffing results (CI gating).
- Offline compliance tests:
- Ensure rule bundles and caches load without network by running integration suite in sealed environment.
## 8. Dependencies & open items
| Item | Description | Owner | Status |
| --- | --- | --- | --- |
| Demand threshold | Need ≥3 qualified customer asks to justify engineering investment | Product Guild | Active (DOCS-SCANNER-BENCH-62-002) |
| macOS rootfs fixtures | Require automation to produce macOS layer tarballs for tests | Scanner Guild | Pending design |
| Notarization validation | Decide whether scanner performs `spctl --assess` or defers | Security Guild | TBD |
| Entitlement taxonomy | Finalize capability grouping for Policy Engine | Policy Guild | TBD |
## 9. Proposed backlog entries
| ID (proposed) | Title | Summary |
| --- | --- | --- |
| SCANNER-ENG-0020 | Implement Homebrew collector and fragment mapper | Parse cellar manifests, emit brew component records, integrate with Surface.FS/Validation. |
| SCANNER-ENG-0021 | Implement pkgutil receipt collector | Parse receipts/BOM, output installer component records with provenance. |
| SCANNER-ENG-0022 | Implement macOS bundle inspector & capability overlays | Extract plist/signing/entitlements, produce capability evidence and merge with receipts. |
| SCANNER-ENG-0023 | Policy & Offline integration for macOS | Define predicates, CLI toggles, Offline Kit packaging, and documentation. |
## 10. References
- `docs/benchmarks/scanner/deep-dives/macos.md` — competitor snapshot and roadmap summary.
- `docs/benchmarks/scanner/windows-macos-demand.md` — demand capture log.
- `docs/modules/scanner/design/surface-secrets.md`, `surface-fs.md`, `surface-validation.md` — surface contracts leveraged by collectors.
Further reading: `../../api/scanner/windows-coverage.md` (summary) and `../../api/scanner/windows-macos-summary.md` (metrics dashboard).
Policy readiness alignment: see `../policy/secret-leak-detection-readiness.md` (POLICY-READINESS-0001).
Upcoming milestone: Northwind Health Services demo on 2025-11-10 to validate notarization/entitlement outputs before final policy sign-off.

View File

@@ -0,0 +1,135 @@
# Windows Analyzer Design Brief (Draft)
> Owners: Scanner Guild, Policy Guild, Offline Kit Guild, Security Guild
> Related backlog (proposed): SCANNER-ENG-0024..0027, DOCS-SCANNER-BENCH-62-002
> Status: Draft — contingent on Windows demand threshold (see `docs/benchmarks/scanner/windows-macos-demand.md`)
## 1. Objectives & boundaries
- Provide deterministic inventory for Windows Server/container images covering MSI/WinSxS assemblies, Chocolatey packages, and registry-derived installers.
- Preserve replayability (layer fragments, provenance metadata) and align outputs with existing SBOM/policy pipelines.
- Respect sovereignty constraints: offline-friendly, signed rule bundles, no reliance on Windows APIs unavailable in containerized scans.
Out of scope (Phase 1):
- Live registry queries on running Windows hosts (requires runtime agent; defer to Zastava/Runtime roadmap).
- Windows Update patch baseline comparison (tracked separately under Runtime/Posture).
- UWP/MSIX packages (flagged for follow-up once MSI parity is complete).
## 2. Architecture overview
```
Scanner.Worker (Windows profile)
├─ Surface.Validation (enforce layer size, path allowlists)
├─ Surface.FS (materialized NTFS image via 7z/guestmount)
├─ MsiCollector -> LayerComponentFragment (windows-msi)
├─ WinSxSCollector -> LayerComponentFragment (windows-winsxs)
├─ ChocolateyCollector -> LayerComponentFragment (windows-choco)
├─ RegistryCollector -> Evidence overlays (uninstall/services)
├─ DriverCapabilityMapper -> Capability overlays (kernel/user drivers)
└─ WindowsComponentMapper -> ComponentGraph + capability metadata
```
- Collectors operate on extracted filesystem snapshots; registry access performed on exported hive files produced during image extraction (document in ops runbooks).
- `WindowsComponentMapper` normalizes component identities (ProductCode, AssemblyIdentity, Chocolatey package ID) and merges overlapping evidence into deterministic fragments.
## 3. Collectors
### 3.1 MSI collector
- Input: `Windows/Installer/*.msi` database files (Jet OLE DB), registry hive exports for product mapping.
- Implementation approach:
- Use open-source MSI parser (custom or MIT-compatible) to avoid COM dependencies.
- Extract Product, Component, File, Feature, Media tables.
- Compute SHA256 for installed files via Component table, linking to WinSxS manifests.
- Output metadata: `productCode`, `upgradeCode`, `productVersion`, `manufacturer`, `language`, `installContext`, `packageCode`, `sourceList`.
- Evidence: file paths with digests, component IDs, CAB/patch references.
### 3.2 WinSxS collector
- Input: `Windows/WinSxS/Manifests/*.manifest`, `Windows/WinSxS/` payload directories, catalog (.cat) files.
- Parse XML assembly identities (name, version, processor architecture, public key token, language).
- Map to MSI components when file hashes match.
- Capture catalog signature thumbprint and optional patch KB references for policy gating.
### 3.3 Chocolatey collector
- Input: `ProgramData/Chocolatey/lib/**`, `ProgramData/Chocolatey/package.backup`, `chocolateyinstall.ps1`, `.nuspec`.
- Extract package ID, version, checksum, source feed, installed files and scripts.
- Note whether install used cache or remote feed; record script hash for determinism.
### 3.4 Registry collector
- Input: Exported `SOFTWARE` hive covering:
- `Microsoft\Windows\CurrentVersion\Uninstall`
- `Microsoft\Windows\CurrentVersion\Installer\UserData`
- `Microsoft\Windows\CurrentVersion\Run` (startup apps)
- Service/driver configuration from `SYSTEM` hive under `Services`.
- Emit fallback evidence for installers not captured by MSI/Chocolatey (legacy EXE installers).
- Record uninstall strings, install dates, publisher, estimated size, install location.
### 3.5 Driver & service mapper
- Parse `SYSTEM` hive `Services` entries to detect drivers (type=1 or 2) and critical services (start mode auto/boot).
- Output capability overlays (e.g., `windows.driver.kernelMode(true)`, `windows.service.autoStart("Spooler")`) for Policy Engine.
## 4. Component mapping & output
- `WindowsComponentMapper`:
- Generate `LayerComponentFragment`s with synthetic layer digests (e.g., `sha256:stellaops-windows-msi`).
- Build `ComponentIdentity` with PURL-like scheme: `pkg:msi/<productCode>` or `pkg:winsxs/<assemblyIdentity>`.
- Include metadata: signature thumbprint, catalog hash, KB references, install context, manufacturer.
- Capability overlays stored under `ScanAnalysisKeys.capability.windows` for policy consumption.
- Export Center bundling:
- Include MSI manifest extracts, WinSxS assembly manifests, Chocolatey nuspec snapshots, and service/driver capability CSV.
## 5. Policy integration
- Predicates to introduce:
- `windows.package.signed(expectedThumbprint?)`
- `windows.package.unsupportedInstallerType`
- `windows.driver.kernelMode`, `windows.driver.unsigned`
- `windows.service.autoStart(name)`
- `windows.choco.sourceAllowed(feed)`
- Lattice approach:
- Unsigned kernel drivers → default `fail`.
- Unknown installer sources → `warn` with escalation on critical services.
- Chocolatey packages from non-whitelisted feeds → configurable severity.
- Waiver semantics bind to product code + signature thumbprint; waivers expire when package version changes.
## 6. Offline kit & distribution
- Package:
- MSI schema definitions and parser binaries (signed).
- Chocolatey feed snapshot (nupkg archives + index) for allow-listed feeds.
- Windows catalog certificate chains + optional CRL/OCSP caches.
- Documentation:
- Provide instructions for exporting registry hives during image extraction (PowerShell script included).
- Note disk space expectations (Chocolatey snapshot size, WinSxS manifest volume).
## 7. Testing strategy
- Fixtures:
- Sample MSI packages (with/without transforms), WinSxS manifests, Chocolatey packages.
- Registry hive exports representing mixed installer types.
- Tests:
- Unit tests for each collector parsing edge cases (language-specific manifests, transforms, script hashing).
- Integration tests using synthetic Windows container image layers (generated via CI on Windows worker).
- Determinism checks ensuring repeated runs produce identical fragments.
- Security review:
- Validate script execution paths (collectors must never execute Chocolatey scripts; inspect only).
## 8. Dependencies & open questions
| Item | Description | Owner | Status |
| --- | --- | --- | --- |
| MSI parser choice | Select MIT/Apache-compatible parser or build internal reader | Scanner Guild | TBD |
| Registry export tooling | Determine standard script/utility for hive exports in container context | Ops Guild | TBD |
| Authenticodes verification locus | Decide scanner vs policy responsibility for signature verification | Security Guild | TBD |
| Feed mirroring policy | Which Chocolatey feeds to mirror by default | Product + Security Guilds | TBD |
## 9. Proposed backlog entries
| ID (proposed) | Title | Summary |
| --- | --- | --- |
| SCANNER-ENG-0024 | Implement Windows MSI collector | Parse MSI databases, emit component fragments with provenance metadata. |
| SCANNER-ENG-0025 | Implement WinSxS manifest collector | Correlate assemblies with MSI components and catalog signatures. |
| SCANNER-ENG-0026 | Implement Chocolatey & registry collectors | Harvest nuspec metadata and uninstall/service registry data. |
| SCANNER-ENG-0027 | Policy & Offline integration for Windows | Define predicates, CLI toggles, Offline Kit packaging, documentation. |
## 10. References
- `docs/benchmarks/scanner/deep-dives/windows.md`
- `docs/benchmarks/scanner/windows-macos-demand.md`
- `docs/modules/scanner/design/macos-analyzer.md` (structure/composition parallels)
- Surface design docs (`surface-fs.md`, `surface-validation.md`, `surface-secrets.md`) for interfacing expectations.
Further reading: `../../api/scanner/windows-coverage.md` (summary) and `../../api/scanner/windows-macos-summary.md` (metrics dashboard).
Policy readiness alignment: see `../policy/windows-package-readiness.md` (POLICY-READINESS-0002).
Upcoming milestone: FinSecure Corp PCI review requires Authenticode/feed decision by 2025-11-07 before Windows analyzer spike kickoff.

View File

@@ -0,0 +1,30 @@
# Field Engagement Playbook — Windows & macOS Coverage
> Audience: Field SEs, Product Specialists • Status: Draft
## Purpose
Provide quick-reference guidance when prospects or customers ask about Windows/macOS coverage.
## Key talking points
- **Current scope**: Scanner supports deterministic Linux coverage; Windows/macOS analyzers are in design.
- **Roadmap**: macOS design (brew/pkgutil/.app) at `../design/macos-analyzer.md`; Windows design (MSI/WinSxS/Chocolatey) at `../design/windows-analyzer.md`.
- **Demand tracking**: All signals captured in `../../benchmarks/scanner/windows-macos-demand.md` using the interview template.
- **Policy readiness**: Secret leak detection briefing (`../../policy/secret-leak-detection-readiness.md`) and Windows package readiness (`../../policy/windows-package-readiness.md`).
- **Backlog IDs**: MacOS (SCANNER-ENG-0020..0023), Windows (SCANNER-ENG-0024..0027), policy follow-ups (POLICY-READINESS-0001/0002).
## SE workflow
1. Use the interview template to capture customer needs.
2. Append structured summary to `windows-macos-demand.md` and update the API dashboards (`docs/api/scanner/windows-macos-summary.md`, `docs/api/scanner/windows-coverage.md`).
3. Notify Product/Scanner guild during weekly sync; flag blockers in Jira.
4. Add highlight to the “Recent updates” section in `docs/api/scanner/windows-macos-summary.md`.
5. Track upcoming milestones (FinSecure decision 2025-11-07, Northwind demo 2025-11-10) and ensure readiness tasks reflect outcomes.
## FAQ snippets
- *When will Windows/macOS analyzers be GA?* — Pending demand threshold; design complete, awaiting prioritisation.
- *Can we run scans offline?* — Offline parity is a requirement; Offline Kit packaging detailed in design briefs.
- *Do we cover Authenticode/notarization?* — Planned via Policy Engine predicates as part of readiness tasks.
## Contacts
- Product lead: TBD (record in demand log when assigned)
- Scanner guild rep: TBD
- Policy guild rep: TBD

View File

@@ -2,7 +2,7 @@
> Synthesises the scheduling requirements documented across the Policy, Vulnerability Explorer, and Orchestrator module guides and implementation plans. > Synthesises the scheduling requirements documented across the Policy, Vulnerability Explorer, and Orchestrator module guides and implementation plans.
> **Scope.** Implementationready architecture for **Scheduler**: a service that (1) **reevaluates** alreadycataloged images when intel changes (Feedser/Vexer/policy), (2) orchestrates **nightly** and **adhoc** runs, (3) targets only the **impacted** images using the BOMIndex, and (4) emits **reportready** events that downstream **Notify** fans out. Default mode is **analysisonly** (no image pull); optional **contentrefresh** can be enabled per schedule. > **Scope.** Implementationready architecture for **Scheduler**: a service that (1) **reevaluates** alreadycataloged images when intel changes (Conselier/Excitor/policy), (2) orchestrates **nightly** and **adhoc** runs, (3) targets only the **impacted** images using the BOMIndex, and (4) emits **reportready** events that downstream **Notify** fans out. Default mode is **analysisonly** (no image pull); optional **contentrefresh** can be enabled per schedule.
--- ---
@@ -12,7 +12,7 @@
**Boundaries.** **Boundaries.**
* Scheduler **does not** compute SBOMs and **does not** sign. It calls Scanner/WebServices **/reports (analysisonly)** endpoint and lets the backend (Policy + Vexer + Feedser) decide PASS/FAIL. * Scheduler **does not** compute SBOMs and **does not** sign. It calls Scanner/WebServices **/reports (analysisonly)** endpoint and lets the backend (Policy + Excitor + Conselier) decide PASS/FAIL.
* Scheduler **may** ask Scanner to **contentrefresh** selected targets (e.g., mutable tags) but the default is **no** image pull. * Scheduler **may** ask Scanner to **contentrefresh** selected targets (e.g., mutable tags) but the default is **no** image pull.
* Notifications are **not** sent directly; Scheduler emits events consumed by **Notify**. * Notifications are **not** sent directly; Scheduler emits events consumed by **Notify**.
@@ -36,14 +36,14 @@ src/
* **Scheduler.WebService** (stateless) * **Scheduler.WebService** (stateless)
* **Scheduler.Worker** (scaleout; planners + executors) * **Scheduler.Worker** (scaleout; planners + executors)
**Dependencies**: Authority (OpTok + DPoP/mTLS), Scanner.WebService, Feedser, Vexer, MongoDB, Redis/NATS, (optional) Notify. **Dependencies**: Authority (OpTok + DPoP/mTLS), Scanner.WebService, Conselier, Excitor, MongoDB, Redis/NATS, (optional) Notify.
--- ---
## 2) Core responsibilities ## 2) Core responsibilities
1. **Timebased** runs: cron windows per tenant/timezone (e.g., “02:00 Europe/Sofia”). 1. **Timebased** runs: cron windows per tenant/timezone (e.g., “02:00 Europe/Sofia”).
2. **Eventdriven** runs: react to **Feedser export** and **Vexer export** deltas (changed product keys / advisories / claims). 2. **Eventdriven** runs: react to **Conselier export** and **Excitor export** deltas (changed product keys / advisories / claims).
3. **Impact targeting**: map changes to **image sets** using a **global inverted index** built from Scanners perimage **BOMIndex** sidecars. 3. **Impact targeting**: map changes to **image sets** using a **global inverted index** built from Scanners perimage **BOMIndex** sidecars.
4. **Run planning**: shard, pace, and ratelimit jobs to avoid thundering herds. 4. **Run planning**: shard, pace, and ratelimit jobs to avoid thundering herds.
5. **Execution**: call Scanner **/reports (analysisonly)** or **/scans (contentrefresh)**; aggregate **delta** results. 5. **Execution**: call Scanner **/reports (analysisonly)** or **/scans (contentrefresh)**; aggregate **delta** results.
@@ -72,8 +72,8 @@ src/
* `runs` * `runs`
``` ```
{ _id, scheduleId?, tenantId, trigger: "cron|feedser|vexer|manual", { _id, scheduleId?, tenantId, trigger: "cron|conselier|excitor|manual",
reason?: { feedserExportId?, vexerExportId?, cursor? }, reason?: { conselierExportId?, excitorExportId?, cursor? },
state: "planning|queued|running|completed|error|cancelled", state: "planning|queued|running|completed|error|cancelled",
stats: { candidates: int, deduped: int, queued: int, completed: int, deltas: int, newCriticals: int }, stats: { candidates: int, deduped: int, queued: int, completed: int, deltas: int, newCriticals: int },
startedAt, finishedAt, error? } startedAt, finishedAt, error? }
@@ -82,7 +82,7 @@ src/
* `impact_cursors` * `impact_cursors`
``` ```
{ _id: tenantId, feedserLastExportId, vexerLastExportId, updatedAt } { _id: tenantId, conselierLastExportId, excitorLastExportId, updatedAt }
``` ```
* `locks` (singleton schedulers, run leases) * `locks` (singleton schedulers, run leases)
@@ -123,7 +123,7 @@ Goal: translate **change keys** → **image sets** in **milliseconds**.
```csharp ```csharp
IImpactIndex { IImpactIndex {
ImpactSet ResolveByPurls(IEnumerable<string> purls, bool usageOnly, Selector sel); ImpactSet ResolveByPurls(IEnumerable<string> purls, bool usageOnly, Selector sel);
ImpactSet ResolveByVulns(IEnumerable<string> vulnIds, bool usageOnly, Selector sel); // optional (vuln->purl precomputed by Feedser) ImpactSet ResolveByVulns(IEnumerable<string> vulnIds, bool usageOnly, Selector sel); // optional (vuln->purl precomputed by Conselier)
ImpactSet ResolveAll(Selector sel); // for nightly ImpactSet ResolveAll(Selector sel); // for nightly
} }
``` ```
@@ -159,14 +159,14 @@ Base path: `/api/v1/scheduler` (Authority OpToks; scopes: `scheduler.read`, `sch
* `POST /preview/impact` — returns **candidate count** and a small sample of impacted digests for given change keys or selection. * `POST /preview/impact` — returns **candidate count** and a small sample of impacted digests for given change keys or selection.
### 5.4 Event webhooks (optional push from Feedser/Vexer) ### 5.4 Event webhooks (optional push from Conselier/Excitor)
* `POST /events/feedser-export` * `POST /events/conselier-export`
```json ```json
{ "exportId":"...", "changedProductKeys":["pkg:rpm/openssl", ...], "kev": ["CVE-..."], "window": { "from":"...","to":"..." } } { "exportId":"...", "changedProductKeys":["pkg:rpm/openssl", ...], "kev": ["CVE-..."], "window": { "from":"...","to":"..." } }
``` ```
* `POST /events/vexer-export` * `POST /events/excitor-export`
```json ```json
{ "exportId":"...", "changedClaims":[ { "productKey":"pkg:deb/...", "vulnId":"CVE-...", "status":"not_affected→affected"} ], ... } { "exportId":"...", "changedClaims":[ { "productKey":"pkg:deb/...", "vulnId":"CVE-...", "status":"not_affected→affected"} ], ... }
@@ -181,7 +181,7 @@ Base path: `/api/v1/scheduler` (Authority OpToks; scopes: `scheduler.read`, `sch
### 6.1 Planning algorithm (eventdriven) ### 6.1 Planning algorithm (eventdriven)
``` ```
On Export Event (Feedser/Vexer): On Export Event (Conselier/Excitor):
keys = Normalize(change payload) # productKeys or vulnIds→productKeys keys = Normalize(change payload) # productKeys or vulnIds→productKeys
usageOnly = schedule/policy hint? # default true usageOnly = schedule/policy hint? # default true
sel = Selector for tenant/scope from schedules subscribed to events sel = Selector for tenant/scope from schedules subscribed to events
@@ -252,7 +252,7 @@ At cron tick:
* **AuthN/Z**: Authority OpToks with `aud=scheduler`; DPoP (preferred) or mTLS. * **AuthN/Z**: Authority OpToks with `aud=scheduler`; DPoP (preferred) or mTLS.
* **Multitenant**: every schedule, run, and event carries `tenantId`; ImpactIndex filters by tenantvisible images. * **Multitenant**: every schedule, run, and event carries `tenantId`; ImpactIndex filters by tenantvisible images.
* **Webhook** callers (Feedser/Vexer) present **mTLS** or **HMAC** and Authority token. * **Webhook** callers (Conselier/Excitor) present **mTLS** or **HMAC** and Authority token.
* **Input hardening**: size caps on changed key lists; reject >100k keys per event; compress (zstd/gzip) allowed with limits. * **Input hardening**: size caps on changed key lists; reject >100k keys per event; compress (zstd/gzip) allowed with limits.
* **No secrets** in logs; redact tokens and signatures. * **No secrets** in logs; redact tokens and signatures.
@@ -302,8 +302,8 @@ scheduler:
maxJobsPerRun: 50000 maxJobsPerRun: 50000
integrates: integrates:
scannerUrl: "https://scanner-web.internal" scannerUrl: "https://scanner-web.internal"
feedserWebhook: true conselierWebhook: true
vexerWebhook: true excitorWebhook: true
notifications: notifications:
emitBus: "internal" # deliver to Notify via internal bus emitBus: "internal" # deliver to Notify via internal bus
``` ```
@@ -314,7 +314,7 @@ scheduler:
* **Schedules** page: CRUD, enable/pause, next run, last run stats, mode (analysis/content), selector preview. * **Schedules** page: CRUD, enable/pause, next run, last run stats, mode (analysis/content), selector preview.
* **Runs** page: timeline; heatmap of deltas; drilldown to affected images. * **Runs** page: timeline; heatmap of deltas; drilldown to affected images.
* **Dryrun preview** modal: “This Feedser export touches ~3,214 images; projected deltas: ~420 (34 KEV).” * **Dryrun preview** modal: “This Conselier export touches ~3,214 images; projected deltas: ~420 (34 KEV).”
--- ---
@@ -323,7 +323,7 @@ scheduler:
| Condition | Behavior | | Condition | Behavior |
| ------------------------------------ | ---------------------------------------------------------------------------------------- | | ------------------------------------ | ---------------------------------------------------------------------------------------- |
| ImpactIndex cold / incomplete | Fall back to **All** selection for nightly; for events, cap to KEV+critical until warmed | | ImpactIndex cold / incomplete | Fall back to **All** selection for nightly; for events, cap to KEV+critical until warmed |
| Feedser/Vexer webhook storm | Coalesce by exportId; debounce 3060s; keep last | | Conselier/Excitor webhook storm | Coalesce by exportId; debounce 3060s; keep last |
| Scanner under load (429) | Backoff with jitter; respect pertenant/leaky bucket | | Scanner under load (429) | Backoff with jitter; respect pertenant/leaky bucket |
| Oversubscription (too many impacted) | Prioritize KEV/critical first; spillover to next window; UI banner shows backlog | | Oversubscription (too many impacted) | Prioritize KEV/critical first; spillover to next window; UI banner shows backlog |
| Notify down | Buffer outbound events in queue (TTL 24h) | | Notify down | Buffer outbound events in queue (TTL 24h) |
@@ -336,7 +336,7 @@ scheduler:
* **ImpactIndex**: correctness (purl→image sets), performance, persistence after restart, memory pressure with 1M purls. * **ImpactIndex**: correctness (purl→image sets), performance, persistence after restart, memory pressure with 1M purls.
* **Planner**: dedupe, shard, fairness, limit enforcement, KEV prioritization. * **Planner**: dedupe, shard, fairness, limit enforcement, KEV prioritization.
* **Runner**: parallel report calls, error backoff, partial failures, idempotency. * **Runner**: parallel report calls, error backoff, partial failures, idempotency.
* **Endtoend**: Feedser export → deltas visible in UI in ≤60s. * **Endtoend**: Conselier export → deltas visible in UI in ≤60s.
* **Security**: webhook auth (mTLS/HMAC), DPoP nonce dance, tenant isolation. * **Security**: webhook auth (mTLS/HMAC), DPoP nonce dance, tenant isolation.
* **Chaos**: drop scanner availability; simulate registry throttles (contentrefresh mode). * **Chaos**: drop scanner availability; simulate registry throttles (contentrefresh mode).
* **Nightly**: cron tick correctness across timezones and DST. * **Nightly**: cron tick correctness across timezones and DST.
@@ -356,18 +356,18 @@ scheduler:
## 15) Sequences (representative) ## 15) Sequences (representative)
**A) Eventdriven rescan (Feedser delta)** **A) Eventdriven rescan (Conselier delta)**
```mermaid ```mermaid
sequenceDiagram sequenceDiagram
autonumber autonumber
participant FE as Feedser participant FE as Conselier
participant SCH as Scheduler.Worker participant SCH as Scheduler.Worker
participant IDX as ImpactIndex participant IDX as ImpactIndex
participant SC as Scanner.WebService participant SC as Scanner.WebService
participant NO as Notify participant NO as Notify
FE->>SCH: POST /events/feedser-export {exportId, changedProductKeys} FE->>SCH: POST /events/conselier-export {exportId, changedProductKeys}
SCH->>IDX: ResolveByPurls(keys, usageOnly=true, sel) SCH->>IDX: ResolveByPurls(keys, usageOnly=true, sel)
IDX-->>SCH: bitmap(imageIds) → digests list IDX-->>SCH: bitmap(imageIds) → digests list
SCH->>SC: POST /reports {imageDigest} (batch/sequenced) SCH->>SC: POST /reports {imageDigest} (batch/sequenced)

View File

@@ -43,7 +43,7 @@ Capture screenshots once Grafana provisioning completes and store them under `do
Import `docs/modules/scheduler/operations/worker-prometheus-rules.yaml` into your Prometheus rule configuration. The bundle defines: Import `docs/modules/scheduler/operations/worker-prometheus-rules.yaml` into your Prometheus rule configuration. The bundle defines:
- **SchedulerPlannerFailuresHigh** 5%+ of planner runs failed for 10 minutes. Page SRE. - **SchedulerPlannerFailuresHigh** 5%+ of planner runs failed for 10 minutes. Page SRE.
- **SchedulerPlannerLatencyHigh** planner p95 latency remains above 45s for 10 minutes. Investigate ImpactIndex, Mongo, and Feedser/Vexer event queues. - **SchedulerPlannerLatencyHigh** planner p95 latency remains above 45s for 10 minutes. Investigate ImpactIndex, Mongo, and Conselier/Excitor event queues.
- **SchedulerRunnerBacklogGrowing** backlog exceeded 500 images for 15 minutes. Inspect runner workers, Scanner availability, and rate limiting. - **SchedulerRunnerBacklogGrowing** backlog exceeded 500 images for 15 minutes. Inspect runner workers, Scanner availability, and rate limiting.
- **SchedulerRunStuck** active run count stayed flat for 30 minutes while remaining non-zero. Check stuck segments, expired leases, and scanner retries. - **SchedulerRunStuck** active run count stayed flat for 30 minutes while remaining non-zero. Check stuck segments, expired leases, and scanner retries.
@@ -55,7 +55,7 @@ Hook these alerts into the existing Observability notification pathway (`observa
1. **Planner failure/latency:** 1. **Planner failure/latency:**
- Check Planner logs for ImpactIndex or Mongo exceptions. - Check Planner logs for ImpactIndex or Mongo exceptions.
- Verify Feedser/Vexer webhook health; requeue events if necessary. - Verify Conselier/Excitor webhook health; requeue events if necessary.
- If planner is overwhelmed, temporarily reduce schedule parallelism via `stella scheduler schedule update`. - If planner is overwhelmed, temporarily reduce schedule parallelism via `stella scheduler schedule update`.
2. **Runner backlog spike:** 2. **Runner backlog spike:**
- Confirm Scanner WebService health (`/healthz`). - Confirm Scanner WebService health (`/healthz`).

View File

@@ -10,7 +10,7 @@
- **Phase 4 Console & CLI experiences** - **Phase 4 Console & CLI experiences**
Ship Console module (lists, evidence table, quorum bar, conflicts, simulation drawer) and CLI commands (`stella vex consensus ...`) with export support. Ship Console module (lists, evidence table, quorum bar, conflicts, simulation drawer) and CLI commands (`stella vex consensus ...`) with export support.
- **Phase 5 Recompute & performance** - **Phase 5 Recompute & performance**
Implement recompute scheduling (policy activation, Excitator deltas), caching, load tests (10M records/tenant), observability dashboards, and Offline Kit exports. Implement recompute scheduling (policy activation, Excitor deltas), caching, load tests (10M records/tenant), observability dashboards, and Offline Kit exports.
## Work breakdown ## Work breakdown
- **VEX Lens service** - **VEX Lens service**
@@ -19,7 +19,7 @@
- Idempotent workers for consensus projection and history tracking. - Idempotent workers for consensus projection and history tracking.
- Conflict handling queue for manual review and notifications. - Conflict handling queue for manual review and notifications.
- **Integrations** - **Integrations**
- Excitator: enrich VEX events with issuer hints, signatures, product trees. - Excitor: enrich VEX events with issuer hints, signatures, product trees.
- Policy Engine: trust knobs, simulation endpoints, policy-driven recompute. - Policy Engine: trust knobs, simulation endpoints, policy-driven recompute.
- Vuln Explorer & Advisory AI: consensus badges, conflict surfacing. - Vuln Explorer & Advisory AI: consensus badges, conflict surfacing.
- **Issuer Directory** - **Issuer Directory**
@@ -39,7 +39,7 @@
- Signature verification influences trust weights; unverifiable evidence is down-weighted without pipeline failure. - Signature verification influences trust weights; unverifiable evidence is down-weighted without pipeline failure.
- Policy simulations show quorum shifts without persisting state; Vuln Explorer consumes consensus signals. - Policy simulations show quorum shifts without persisting state; Vuln Explorer consumes consensus signals.
- Issuer Directory enforces RBAC, audit logs, and key rotation; CLI & Console parity achieved. - Issuer Directory enforces RBAC, audit logs, and key rotation; CLI & Console parity achieved.
- Recompute pipeline handles Excitator deltas and policy activations with backpressure and incident surfacing. - Recompute pipeline handles Excitor deltas and policy activations with backpressure and incident surfacing.
- Observability dashboards/alerts cover ingestion lag, conflict spikes, signature failures, performance budgets (P95 < 500ms for 100-row pages at 10M records/tenant). - Observability dashboards/alerts cover ingestion lag, conflict spikes, signature failures, performance budgets (P95 < 500ms for 100-row pages at 10M records/tenant).
## Risks & mitigations ## Risks & mitigations
@@ -52,7 +52,7 @@
## Test strategy ## Test strategy
- **Unit:** normalisers, mapping, trust weights, consensus lattice, signature verification. - **Unit:** normalisers, mapping, trust weights, consensus lattice, signature verification.
- **Property:** randomised evidence sets verifying lattice commutativity and determinism. - **Property:** randomised evidence sets verifying lattice commutativity and determinism.
- **Integration:** Excitator Lens Policy/Vuln Explorer flow, issuer overrides, simulation. - **Integration:** Excitor Lens Policy/Vuln Explorer flow, issuer overrides, simulation.
- **Performance:** large tenant datasets, cache behaviour, concurrency tests. - **Performance:** large tenant datasets, cache behaviour, concurrency tests.
- **Security:** RBAC, tenant scoping, signature tampering, issuer revocation. - **Security:** RBAC, tenant scoping, signature tampering, issuer revocation.
- **Offline:** export/import verification, CLI parity. - **Offline:** export/import verification, CLI parity.

View File

@@ -1,9 +0,0 @@
# Task board — Vexer
> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable.
| ID | Status | Owner(s) | Description | Notes |
|----|--------|----------|-------------|-------|
| VEXER-DOCS-0001 | DOING (2025-10-29) | Docs Guild | Validate that ./README.md aligns with the latest release notes. | See ./AGENTS.md |
| VEXER-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md |
| VEXER-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow |

View File

@@ -54,7 +54,14 @@ CLI mirrors these endpoints (`stella findings list|view|update|export`). Console
- Audit exports: `audit_log.jsonl` appended whenever state changes; offline bundles include signed audit log and manifest. - Audit exports: `audit_log.jsonl` appended whenever state changes; offline bundles include signed audit log and manifest.
- Compliance: accepted risk requires dual approval and stores justification plus expiry reminders (raised through Notify). - Compliance: accepted risk requires dual approval and stores justification plus expiry reminders (raised through Notify).
## 6) Offline bundle requirements ## 6) Identity & access integration
- **Scopes** `vuln:view`, `vuln:investigate`, `vuln:operate`, `vuln:audit` map to read-only, triage, workflow, and audit experiences respectively. The deprecated `vuln:read` scope is still honoured for legacy tokens but is no longer advertised.
- **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.
## 7) Offline bundle requirements
- Bundle structure: - Bundle structure:
- `manifest.json` (hashes, counts, policy version, generation timestamp). - `manifest.json` (hashes, counts, policy version, generation timestamp).

View File

@@ -31,7 +31,7 @@
- Commands `stella vuln list|show|simulate|assign|accept-risk|verify-fix|export`. - Commands `stella vuln list|show|simulate|assign|accept-risk|verify-fix|export`.
- Stable schemas for automation; piping support; tests for exit codes. - Stable schemas for automation; piping support; tests for exit codes.
- **Integrations** - **Integrations**
- Conseiller/Excitator: normalized advisory keys, linksets, evidence retrieval. - Conseiller/Excitor: normalized advisory keys, linksets, evidence retrieval.
- SBOM Service: inventory deltas with scope/runtime flags, safe version hints. - SBOM Service: inventory deltas with scope/runtime flags, safe version hints.
- Notify: events for SLA breaches, accepted-risk expiries, remediation deadlines. - Notify: events for SLA breaches, accepted-risk expiries, remediation deadlines.
- Scheduler: trigger rescans when remediation plan milestones complete. - Scheduler: trigger rescans when remediation plan milestones complete.

View File

@@ -33,6 +33,7 @@ Tenant API│ REST + gRPC WIP │ │ rules/channels│
└─────────────┘ └──────────────────┘ └─────────────┘ └──────────────────┘
``` ```
- **2025-11-02 decision — module boundaries.** Keep `src/Notify/` as the shared notification toolkit (engine, storage, queue, connectors) that multiple hosts can consume. `src/Notifier/` remains the Notifications Studio runtime (WebService + Worker) composed from those libraries. Do not collapse the directories until a packaging RFC covers build impacts, offline kit parity, and imposed-rule propagation.
- **WebService** hosts REST endpoints (`/channels`, `/rules`, `/templates`, `/deliveries`, `/digests`, `/stats`) and handles schema normalisation, validation, and Authority enforcement. - **WebService** hosts REST endpoints (`/channels`, `/rules`, `/templates`, `/deliveries`, `/digests`, `/stats`) and handles schema normalisation, validation, and Authority enforcement.
- **Worker** subscribes to the platform event bus, evaluates rules per tenant, applies throttles/digests, renders payloads, writes ledger entries, and invokes connectors. - **Worker** subscribes to the platform event bus, evaluates rules per tenant, applies throttles/digests, renders payloads, writes ledger entries, and invokes connectors.
- **Plug-ins** live under `plugins/notify/` and are loaded deterministically at service start (`orderedPlugins` list). Each implements connector contracts and optional health/test-preview providers. - **Plug-ins** live under `plugins/notify/` and are loaded deterministically at service start (`orderedPlugins` list). Each implements connector contracts and optional health/test-preview providers.

View File

@@ -48,6 +48,7 @@ The Notify WebService fronts worker state with REST APIs used by the UI and CLI.
| **Scaling** | Workers scale horizontally; per-tenant rule snapshots are cached and refreshed from Mongo change streams. Redis (or equivalent) guards throttles and locks. | | **Scaling** | Workers scale horizontally; per-tenant rule snapshots are cached and refreshed from Mongo change streams. Redis (or equivalent) guards throttles and locks. |
| **Offline** | Offline Kits include plug-ins, default templates, and seed rules. Operators can edit YAML/JSON manifests before air-gapped deployment. | | **Offline** | Offline Kits include plug-ins, default templates, and seed rules. Operators can edit YAML/JSON manifests before air-gapped deployment. |
| **Security** | Channel secrets use indirection (`secretRef`), Authority-protected OAuth clients secure API access, and delivery payloads are redacted before storage where required. | | **Security** | Channel secrets use indirection (`secretRef`), Authority-protected OAuth clients secure API access, and delivery payloads are redacted before storage where required. |
| **Module boundaries** | 2025-11-02 decision: keep `src/Notify/` as the shared notification toolkit and `src/Notifier/` as the Notifications Studio runtime host until a packaging RFC covers the implications of merging. |
--- ---

View File

@@ -6,10 +6,10 @@
Risk Scoring Profiles define customizable formulas that convert raw evidence (CVSS, EPSS-like exploit likelihood, KEV exploited lists, VEX status, reachability, runtime evidence, fix availability, asset criticality, provenance trust) into normalized risk scores (0100) with severity buckets. Profiles are authored in Policy Studio, simulated, versioned, and executed by the scoring engine with full explainability. Risk Scoring Profiles define customizable formulas that convert raw evidence (CVSS, EPSS-like exploit likelihood, KEV exploited lists, VEX status, reachability, runtime evidence, fix availability, asset criticality, provenance trust) into normalized risk scores (0100) with severity buckets. Profiles are authored in Policy Studio, simulated, versioned, and executed by the scoring engine with full explainability.
- **Primary components:** Policy Engine, Findings Ledger, Conseiller, Excitator, Console, Policy Studio, CLI, Export Center, Authority & Tenancy, Observability. - **Primary components:** Policy Engine, Findings Ledger, Conseiller, Excitor, Console, Policy Studio, CLI, Export Center, Authority & Tenancy, Observability.
- **Surfaces:** policy documents, scoring engine, factor providers, explainability artefacts, APIs, CLI, UI. - **Surfaces:** policy documents, scoring engine, factor providers, explainability artefacts, APIs, CLI, UI.
Aggregation-Only Contract remains in force: Conseiller and Excitator never merge or mutate source records. Risk scoring consumes linked evidence and preserves provenance for explainability. Aggregation-Only Contract remains in force: Conseiller and Excitor never merge or mutate source records. Risk scoring consumes linked evidence and preserves provenance for explainability.
## Core workflow ## Core workflow
@@ -24,7 +24,7 @@ Aggregation-Only Contract remains in force: Conseiller and Excitator never merge
| Factor | Description | Typical signal source | | Factor | Description | Typical signal source |
| --- | --- | --- | | --- | --- | --- |
| Exploit likelihood | EPSS/KEV or internal intel | Conseiller enrichment | | Exploit likelihood | EPSS/KEV or internal intel | Conseiller enrichment |
| VEX status | not_affected / affected / fixed | Excitator (VEX Lens) | | VEX status | not_affected / affected / fixed | Excitor (VEX Lens) |
| Reachability | entrypoint closure, runtime observations | Scanner + Zastava | | Reachability | entrypoint closure, runtime observations | Scanner + Zastava |
| Fix availability | patch released, vendor guidance | Conseiller, Policy Engine | | Fix availability | patch released, vendor guidance | Conseiller, Policy Engine |
| Asset criticality | business context, tenant overrides | Policy Studio inputs | | Asset criticality | business context, tenant overrides | Policy Studio inputs |

View File

@@ -49,7 +49,11 @@ Authority issues short-lived tokens bound to tenants and scopes. Sprint19 int
| `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: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:audit` | Policy audit exports | Access immutable policy history, comments, and signatures. | Tenant required; read-only access. | | `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. | | `policy:simulate` | Policy Studio / CLI simulations | Run simulations against tenant inventories. | Tenant required; available to authors, reviewers, operators. |
| `vuln:read` | Vuln Explorer API/UI | Read normalized vulnerability data. | Tenant required. | | `vuln:view` | Vuln Explorer API/UI | Read normalized vulnerability data, issue permalinks. | Tenant required; ABAC attributes (`env`, `owner`, `business_tier`) further constrain access. |
| `vuln:investigate` | Vuln Explorer triage workflows | Assign findings, add comments, attach remediation notes. | Tenant + ABAC attributes required; typically paired with `vuln:view`. |
| `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.
| `export.viewer` | Export Center APIs | List export profiles/runs, fetch manifests and bundles. | Tenant required; read-only access. | | `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.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. | | `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. |
@@ -80,7 +84,7 @@ Authority issues short-lived tokens bound to tenants and scopes. Sprint19 int
- **`role/policy-engine`** → `effective:write`, `findings:read`. - **`role/policy-engine`** → `effective:write`, `findings:read`.
- **`role/cartographer-service`** → `graph:write`, `graph:read`. - **`role/cartographer-service`** → `graph:write`, `graph:read`.
- **`role/graph-gateway`** → `graph:read`, `graph:export`, `graph:simulate`. - **`role/graph-gateway`** → `graph:read`, `graph:export`, `graph:simulate`.
- **`role/console`** → `ui.read`, `advisory:read`, `vex:read`, `exceptions:read`, `aoc:verify`, `findings:read`, `airgap:status:read`, `orch:read`, `vuln:read`. - **`role/console`** → `ui.read`, `advisory:read`, `vex:read`, `exceptions:read`, `aoc:verify`, `findings:read`, `airgap:status:read`, `orch:read`, `vuln:view`, `vuln:investigate`.
- **`role/ui-console-admin`** → `ui.read`, `authority:tenants.read`, `authority:roles.read`, `authority:tokens.read`, `authority:clients.read` (paired with write scopes where required). - **`role/ui-console-admin`** → `ui.read`, `authority:tenants.read`, `authority:roles.read`, `authority:tokens.read`, `authority:clients.read` (paired with write scopes where required).
- **`role/orch-viewer`** *(Authority role: `Orch.Viewer`)*`orch:read`. - **`role/orch-viewer`** *(Authority role: `Orch.Viewer`)*`orch:read`.
- **`role/orch-operator`** *(Authority role: `Orch.Operator`)*`orch:read`, `orch:operate`. - **`role/orch-operator`** *(Authority role: `Orch.Operator`)*`orch:read`, `orch:operate`.
@@ -242,8 +246,14 @@ security:
description: Export graph artefacts description: Export graph artefacts
- name: graph:simulate - name: graph:simulate
description: Run graph what-if simulations description: Run graph what-if simulations
- name: vuln:read - name: vuln:view
description: Read Vuln Explorer data description: Read Vuln Explorer data, list findings, issue permalinks
- name: vuln:investigate
description: Perform triage actions (assign, comment, remediation notes)
- name: vuln:operate
description: Execute state changes and remediation workflows
- name: vuln:audit
description: Access Vuln Explorer audit ledgers and offline exports
claimTransforms: claimTransforms:
- match: { scope: "effective:write" } - match: { scope: "effective:write" }
require: require:
@@ -262,7 +272,7 @@ Update service clients:
- `Policy.Engine` → request `effective:write`, `findings:read`; set `properties.serviceIdentity=policy-engine`. - `Policy.Engine` → request `effective:write`, `findings:read`; set `properties.serviceIdentity=policy-engine`.
- `Cartographer.Service` → request `graph:write`, `graph:read`; set `properties.serviceIdentity=cartographer`. - `Cartographer.Service` → request `graph:write`, `graph:read`; set `properties.serviceIdentity=cartographer`.
- `Graph API Gateway` → request `graph:read`, `graph:export`, `graph:simulate`; tenant hint required. - `Graph API Gateway` → request `graph:read`, `graph:export`, `graph:simulate`; tenant hint required.
- `Console` → request `advisory:read`, `vex:read`, `aoc:verify`, `findings:read`, `vuln:read` plus existing UI scopes. - `Console` → request `advisory:read`, `vex:read`, `aoc:verify`, `findings:read`, `vuln:view`, `vuln:investigate`, `vuln:operate`, `vuln:audit` plus existing UI scopes.
- `CLI automation` → request `aoc:verify`, `advisory:read`, `vex:read` as needed. - `CLI automation` → request `aoc:verify`, `advisory:read`, `vex:read` as needed.
Client definition snippet: Client definition snippet:

View File

@@ -38,7 +38,7 @@ Each module directory bundles an ownership charter (`AGENTS.md`), current work (
| UI / Console | [architecture.md](../../modules/ui/architecture.md), [console-architecture.md](../../modules/ui/console-architecture.md) | [implementation_plan.md](../../modules/ui/implementation_plan.md) | — | | UI / Console | [architecture.md](../../modules/ui/architecture.md), [console-architecture.md](../../modules/ui/console-architecture.md) | [implementation_plan.md](../../modules/ui/implementation_plan.md) | — |
| Vuln Explorer | [architecture.md](../../modules/vuln-explorer/architecture.md) | [implementation_plan.md](../../modules/vuln-explorer/implementation_plan.md) | — | | Vuln Explorer | [architecture.md](../../modules/vuln-explorer/architecture.md) | [implementation_plan.md](../../modules/vuln-explorer/implementation_plan.md) | — |
| VEX Lens | [architecture.md](../../modules/vex-lens/architecture.md) | [implementation_plan.md](../../modules/vex-lens/implementation_plan.md) | — | | VEX Lens | [architecture.md](../../modules/vex-lens/architecture.md) | [implementation_plan.md](../../modules/vex-lens/implementation_plan.md) | — |
| Vexer | [architecture.md](../../modules/vexer/architecture.md) | [implementation_plan.md](../../modules/vexer/implementation_plan.md) | [scoring.md](../../modules/vexer/scoring.md) | | Excitor | [architecture.md](../../modules/excitor/architecture.md) | [implementation_plan.md](../../modules/excitor/implementation_plan.md) | [scoring.md](../../modules/excitor/scoring.md) |
| Zastava | [architecture.md](../../modules/zastava/architecture.md) | [implementation_plan.md](../../modules/zastava/implementation_plan.md) | — | | Zastava | [architecture.md](../../modules/zastava/architecture.md) | [implementation_plan.md](../../modules/zastava/implementation_plan.md) | — |
> **Tip:** Every module directory also exposes `README.md`, `AGENTS.md`, and `TASKS.md` for roles, current backlog, and ownership responsibilities. > **Tip:** Every module directory also exposes `README.md`, `AGENTS.md`, and `TASKS.md` for roles, current backlog, and ownership responsibilities.

View File

@@ -13,7 +13,7 @@ Resources for contributors building features, plug-ins, connectors, and tests.
- [../10_PLUGIN_SDK_GUIDE.md](../../10_PLUGIN_SDK_GUIDE.md) plug-in lifecycle, manifests, packaging. - [../10_PLUGIN_SDK_GUIDE.md](../../10_PLUGIN_SDK_GUIDE.md) plug-in lifecycle, manifests, packaging.
- [../10_CONCELIER_CLI_QUICKSTART.md](../../10_CONCELIER_CLI_QUICKSTART.md) local Concelier + CLI workflow for advisory ingestion. - [../10_CONCELIER_CLI_QUICKSTART.md](../../10_CONCELIER_CLI_QUICKSTART.md) local Concelier + CLI workflow for advisory ingestion.
- Developer guides under [../dev/](../../dev/): - Developer guides under [../dev/](../../dev/):
- Connector playbooks (`30_EXCITITOR_CONNECTOR_GUIDE.md`, `30_VEXER_CONNECTOR_GUIDE.md`, `concelier-connector-research-20251011.md`, `kisa_connector_notes.md`). - Connector playbooks (`30_EXCITITOR_CONNECTOR_GUIDE.md`, `30_EXCITOR_CONNECTOR_GUIDE.md`, `concelier-connector-research-20251011.md`, `kisa_connector_notes.md`).
- Authority and DPoP guidance (`31_AUTHORITY_PLUGIN_DEVELOPER_GUIDE.md`, `authority-dpop-mtls-plan.md`, `authority-plugin-di-coordination.md`, `authority-rate-limit-tuning-outline.md`, `32_AUTH_CLIENT_GUIDE.md`). - Authority and DPoP guidance (`31_AUTHORITY_PLUGIN_DEVELOPER_GUIDE.md`, `authority-dpop-mtls-plan.md`, `authority-plugin-di-coordination.md`, `authority-rate-limit-tuning-outline.md`, `32_AUTH_CLIENT_GUIDE.md`).
- Analyzer and cache configuration (`SCANNER_CACHE_CONFIGURATION.md`, `java-analyzer-observation-plan.md`, `EXCITITOR_STATEMENT_BACKFILL.md`). - Analyzer and cache configuration (`SCANNER_CACHE_CONFIGURATION.md`, `java-analyzer-observation-plan.md`, `EXCITITOR_STATEMENT_BACKFILL.md`).
- Normalisation & merge references (`aoc-normalization-removal-notes.md`, `merge_semver_playbook.md`, `normalized-rule-recipes.md`, `normalized_versions_rollout.md`). - Normalisation & merge references (`aoc-normalization-removal-notes.md`, `merge_semver_playbook.md`, `normalized-rule-recipes.md`, `normalized_versions_rollout.md`).

View File

@@ -43,7 +43,7 @@ The header integrates the status ticker to show ingestion deltas and planner hea
| Column | Description | | Column | Description |
|--------|-------------| |--------|-------------|
| **Run ID** | Deterministic identifier (`run:<tenant>:<timestamp>:<nonce>`). Clicking opens detail drawer. | | **Run ID** | Deterministic identifier (`run:<tenant>:<timestamp>:<nonce>`). Clicking opens detail drawer. |
| **Trigger** | `cron`, `manual`, `feedser`, `vexer`, `policy`, `content-refresh`. Tooltip lists schedule and initiator. | | **Trigger** | `cron`, `manual`, `conselier`, `excitor`, `policy`, `content-refresh`. Tooltip lists schedule and initiator. |
| **State** | Badges: `planning`, `queued`, `running`, `completed`, `cancelled`, `error`. Errors include error code (e.g., `ERR_RUN_005`). | | **State** | Badges: `planning`, `queued`, `running`, `completed`, `cancelled`, `error`. Errors include error code (e.g., `ERR_RUN_005`). |
| **Progress** | Percentage + processed/total candidates. SSE updates increment in real time. | | **Progress** | Percentage + processed/total candidates. SSE updates increment in real time. |
| **Duration** | Elapsed time (auto-updating). Completed runs show total duration; running runs show timer. | | **Duration** | Elapsed time (auto-updating). Completed runs show total duration; running runs show timer. |

View File

@@ -80,6 +80,10 @@ delegation:
- "findings:read" - "findings:read"
authorizedClients: authorizedClients:
- "export-center-worker" - "export-center-worker"
attributes:
env: [ "prod", "stage" ]
owner: [ "secops" ]
business_tier: [ "tier-1" ]
# - accountId: "svc-airgap-import" # - accountId: "svc-airgap-import"
# tenant: "tenant-default" # tenant: "tenant-default"
# displayName: "Airgap Import Service Account" # displayName: "Airgap Import Service Account"
@@ -242,7 +246,7 @@ clients:
displayName: "StellaOps Console" displayName: "StellaOps Console"
grantTypes: [ "authorization_code", "refresh_token" ] grantTypes: [ "authorization_code", "refresh_token" ]
audiences: [ "console" ] audiences: [ "console" ]
scopes: [ "openid", "profile", "email", "ui.read", "authority:tenants.read", "advisory:read", "vex:read", "exceptions:read", "exceptions:approve", "aoc:verify", "findings:read", "airgap:status:read", "obs:read", "obs:incident", "timeline:read", "evidence:read", "attest:read", "orch:read", "vuln:read" ] scopes: [ "openid", "profile", "email", "ui.read", "authority:tenants.read", "advisory:read", "vex:read", "exceptions:read", "exceptions:approve", "aoc:verify", "findings:read", "airgap:status:read", "obs:read", "obs:incident", "timeline:read", "evidence:read", "attest:read", "orch:read", "vuln:view", "vuln:investigate", "vuln:operate", "vuln:audit" ]
# exceptions:approve is elevated via fresh-auth and requires an MFA-capable identity provider. # exceptions:approve is elevated via fresh-auth and requires an MFA-capable identity provider.
tenant: "tenant-default" tenant: "tenant-default"
senderConstraint: "dpop" senderConstraint: "dpop"
@@ -391,7 +395,7 @@ clients:
displayName: "Vuln Explorer UI" displayName: "Vuln Explorer UI"
grantTypes: [ "client_credentials" ] grantTypes: [ "client_credentials" ]
audiences: [ "api://vuln-explorer" ] audiences: [ "api://vuln-explorer" ]
scopes: [ "vuln:read" ] scopes: [ "vuln:view", "vuln:investigate", "vuln:operate", "vuln:audit" ]
tenant: "tenant-default" tenant: "tenant-default"
senderConstraint: "dpop" senderConstraint: "dpop"
auth: auth:
@@ -473,6 +477,30 @@ tenants:
scopes: [ "advisory-ai:view", "advisory-ai:operate" ] scopes: [ "advisory-ai:view", "advisory-ai:operate" ]
advisory-ai-admin: advisory-ai-admin:
scopes: [ "advisory-ai:view", "advisory-ai:operate", "advisory-ai:admin" ] scopes: [ "advisory-ai:view", "advisory-ai:operate", "advisory-ai:admin" ]
vuln-viewer:
scopes: [ "vuln:view" ]
attributes:
env: [ "*" ]
owner: [ "*" ]
business_tier: [ "*" ]
vuln-investigator:
scopes: [ "vuln:view", "vuln:investigate" ]
attributes:
env: [ "*" ]
owner: [ "*" ]
business_tier: [ "*" ]
vuln-operator:
scopes: [ "vuln:view", "vuln:investigate", "vuln:operate" ]
attributes:
env: [ "*" ]
owner: [ "*" ]
business_tier: [ "*" ]
vuln-auditor:
scopes: [ "vuln:view", "vuln:audit" ]
attributes:
env: [ "*" ]
owner: [ "*" ]
business_tier: [ "*" ]
advisoryAi: advisoryAi:
remoteInference: remoteInference:
consentGranted: false consentGranted: false

View File

@@ -1,4 +1,6 @@
IssuerDirectory: IssuerDirectory:
# Override connection secrets via environment variables (ISSUERDIRECTORY__MONGO__*)
# rather than editing this file for production.
telemetry: telemetry:
minimumLogLevel: Information minimumLogLevel: Information
authority: authority:

View File

@@ -76,6 +76,8 @@
| DEVOPS-LNM-22-002 | BLOCKED (2025-10-27) | DevOps Guild, Excititor Guild | EXCITITOR-LNM-21-102 | Execute VEX observation/linkset backfill with monitoring; ensure NATS/Redis events integrated; document ops runbook. Blocked until Excititor storage migration lands. | | DEVOPS-LNM-22-002 | BLOCKED (2025-10-27) | DevOps Guild, Excititor Guild | EXCITITOR-LNM-21-102 | Execute VEX observation/linkset backfill with monitoring; ensure NATS/Redis events integrated; document ops runbook. Blocked until Excititor storage migration lands. |
| DEVOPS-LNM-22-003 | TODO | DevOps Guild, Observability Guild | CONCELIER-LNM-21-005, EXCITITOR-LNM-21-005 | Add CI/monitoring coverage for new metrics (`advisory_observations_total`, `linksets_total`, etc.) and alerts on ingest-to-API SLA breaches. | Metrics scraped into Grafana; alert thresholds set; CI job verifies metric emission. | | DEVOPS-LNM-22-003 | TODO | DevOps Guild, Observability Guild | CONCELIER-LNM-21-005, EXCITITOR-LNM-21-005 | Add CI/monitoring coverage for new metrics (`advisory_observations_total`, `linksets_total`, etc.) and alerts on ingest-to-API SLA breaches. | Metrics scraped into Grafana; alert thresholds set; CI job verifies metric emission. |
> 2025-11-03: Link-Not-Merge migration playbook (`docs/migration/no-merge.md`) published—use it to sequence DEVOPS-LNM-22-001 rehearsals and record Phase03 config toggles in runbooks.
## Graph & Vuln Explorer v1 ## Graph & Vuln Explorer v1
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | | ID | Status | Owner(s) | Depends on | Description | Exit Criteria |

View File

@@ -26,6 +26,6 @@ COPY --from=build /workspace/dist/stellaops-web/ /usr/share/nginx/html/
COPY ops/devops/release/docker/nginx-default.conf /etc/nginx/conf.d/default.conf COPY ops/devops/release/docker/nginx-default.conf /etc/nginx/conf.d/default.conf
LABEL org.opencontainers.image.version="${VERSION}" \ LABEL org.opencontainers.image.version="${VERSION}" \
org.opencontainers.image.revision="${GIT_SHA}" \ org.opencontainers.image.revision="${GIT_SHA}" \
org.opencontainers.image.source="https://git.stella-ops.org/stella-ops/feedser" \ org.opencontainers.image.source="https://git.stella-ops.org/stella-ops/conselier" \
org.stellaops.release.channel="${CHANNEL}" org.stellaops.release.channel="${CHANNEL}"
EXPOSE 8080 EXPOSE 8080

View File

@@ -47,6 +47,6 @@ RUN set -eu; \
EXPOSE 8080 EXPOSE 8080
LABEL org.opencontainers.image.version="${VERSION}" \ LABEL org.opencontainers.image.version="${VERSION}" \
org.opencontainers.image.revision="${GIT_SHA}" \ org.opencontainers.image.revision="${GIT_SHA}" \
org.opencontainers.image.source="https://git.stella-ops.org/stella-ops/feedser" \ org.opencontainers.image.source="https://git.stella-ops.org/stella-ops/conselier" \
org.stellaops.release.channel="${CHANNEL}" org.stellaops.release.channel="${CHANNEL}"
ENTRYPOINT ["/entrypoint.sh"] ENTRYPOINT ["/entrypoint.sh"]

View File

@@ -4,7 +4,7 @@
"updatedAt": "2025-10-18T22:10:10Z", "updatedAt": "2025-10-18T22:10:10Z",
"lastRun": { "lastRun": {
"runId": "run_20251018_0001", "runId": "run_20251018_0001",
"trigger": "feedser", "trigger": "conselier",
"state": "completed", "state": "completed",
"createdAt": "2025-10-18T22:03:14Z", "createdAt": "2025-10-18T22:03:14Z",
"startedAt": "2025-10-18T22:03:20Z", "startedAt": "2025-10-18T22:03:20Z",
@@ -25,7 +25,7 @@
"recent": [ "recent": [
{ {
"runId": "run_20251018_0001", "runId": "run_20251018_0001",
"trigger": "feedser", "trigger": "conselier",
"state": "completed", "state": "completed",
"createdAt": "2025-10-18T22:03:14Z", "createdAt": "2025-10-18T22:03:14Z",
"startedAt": "2025-10-18T22:03:20Z", "startedAt": "2025-10-18T22:03:20Z",

View File

@@ -3,7 +3,7 @@
"id": "run_20251018_0001", "id": "run_20251018_0001",
"tenantId": "tenant-alpha", "tenantId": "tenant-alpha",
"scheduleId": "sch_20251018a", "scheduleId": "sch_20251018a",
"trigger": "feedser", "trigger": "conselier",
"state": "running", "state": "running",
"stats": { "stats": {
"candidates": 1280, "candidates": 1280,
@@ -17,7 +17,7 @@
"newLow": 6 "newLow": 6
}, },
"reason": { "reason": {
"feedserExportId": "exp-20251018-03" "conselierExportId": "exp-20251018-03"
}, },
"createdAt": "2025-10-18T22:03:14+00:00", "createdAt": "2025-10-18T22:03:14+00:00",
"startedAt": "2025-10-18T22:03:20+00:00", "startedAt": "2025-10-18T22:03:20+00:00",

View File

@@ -6,7 +6,7 @@ Deliver the Advisory AI assistant service that synthesizes advisory/VEX evidence
## Scope ## Scope
- Service under `src/AdvisoryAI/StellaOps.AdvisoryAI` (retrievers, deterministics, orchestrator, guardrails, inference adapters, REST APIs). - Service under `src/AdvisoryAI/StellaOps.AdvisoryAI` (retrievers, deterministics, orchestrator, guardrails, inference adapters, REST APIs).
- Batch processing for CLI/automation, caching, observability, and integration with Console, CLI, and downstream systems. - Batch processing for CLI/automation, caching, observability, and integration with Console, CLI, and downstream systems.
- Coordination across Conseiller, Excitator, VEX Lens, SBOM Service, Policy Engine, Findings Ledger, Web Gateway, Authority, DevOps, and Docs. - Coordination across Conseiller, Excitor, VEX Lens, SBOM Service, Policy Engine, Findings Ledger, Web Gateway, Authority, DevOps, and Docs.
## Principles ## Principles
1. **Evidence preservation** Raw advisory/VEX documents remain untouched; AI outputs reference them with citations. 1. **Evidence preservation** Raw advisory/VEX documents remain untouched; AI outputs reference them with citations.

View File

@@ -7,7 +7,7 @@ Deliver offline bundle verification and ingestion tooling for sealed environment
- TUF metadata verification, DSSE signature checks, Merkle root validation. - TUF metadata verification, DSSE signature checks, Merkle root validation.
- Import pipelines writing bundle catalogs, object-store layouts, and audit entries. - Import pipelines writing bundle catalogs, object-store layouts, and audit entries.
- CLI + API surfaces for dry-run verification, import, and status queries. - CLI + API surfaces for dry-run verification, import, and status queries.
- Integration hooks for Conseiller, Excitator, Policy Engine, and Export Center. - Integration hooks for Conseiller, Excitor, Policy Engine, and Export Center.
- Negative-case handling (tampering, expired signatures, root rotation) with operator guidance. - Negative-case handling (tampering, expired signatures, root rotation) with operator guidance.
## Definition of Done ## Definition of Done

View File

@@ -0,0 +1,184 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Text;
using Xunit;
namespace StellaOps.AirGap.Policy.Analyzers.Tests;
public sealed class HttpClientUsageAnalyzerTests
{
[Fact]
public async Task ReportsDiagnostic_ForNewHttpClient()
{
const string source = """
using System.Net.Http;
namespace Sample.App;
public sealed class Demo
{
public void Run()
{
var client = new HttpClient();
}
}
""";
var diagnostics = await AnalyzeAsync(source, assemblyName: "Sample.App");
Assert.Contains(diagnostics, d => d.Id == HttpClientUsageAnalyzer.DiagnosticId);
}
[Fact]
public async Task DoesNotReportDiagnostic_InsidePolicyAssembly()
{
const string source = """
using System.Net.Http;
namespace StellaOps.AirGap.Policy.Internal;
internal static class Loopback
{
public static HttpClient Create() => new HttpClient();
}
""";
var diagnostics = await AnalyzeAsync(source, assemblyName: "StellaOps.AirGap.Policy");
Assert.DoesNotContain(diagnostics, d => d.Id == HttpClientUsageAnalyzer.DiagnosticId);
}
[Fact]
public async Task CodeFix_RewritesToFactoryCall()
{
const string source = """
using System.Net.Http;
namespace Sample.Service;
public sealed class Demo
{
public void Run()
{
var client = new HttpClient();
}
}
""";
const string expected = """
using System.Net.Http;
namespace Sample.Service;
public sealed class Demo
{
public void Run()
{
var client = global::StellaOps.AirGap.Policy.EgressHttpClientFactory.Create(egressPolicy: /* TODO: provide IEgressPolicy instance */, request: new global::StellaOps.AirGap.Policy.EgressRequest(component: "REPLACE_COMPONENT", destination: new global::System.Uri("https://replace-with-endpoint"), intent: "REPLACE_INTENT"));
}
}
""";
var updated = await ApplyCodeFixAsync(source, assemblyName: "Sample.Service");
Assert.Equal(expected.ReplaceLineEndings(), updated.ReplaceLineEndings());
}
private static async Task<ImmutableArray<Diagnostic>> AnalyzeAsync(string source, string assemblyName)
{
var compilation = CSharpCompilation.Create(
assemblyName,
new[]
{
CSharpSyntaxTree.ParseText(source),
CSharpSyntaxTree.ParseText(PolicyStubSource),
},
CreateMetadataReferences(),
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
var analyzer = new HttpClientUsageAnalyzer();
var compilationWithAnalyzers = compilation.WithAnalyzers(ImmutableArray.Create<DiagnosticAnalyzer>(analyzer));
return await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync();
}
private static async Task<string> ApplyCodeFixAsync(string source, string assemblyName)
{
using var workspace = new AdhocWorkspace();
var projectId = ProjectId.CreateNewId();
var documentId = DocumentId.CreateNewId(projectId);
var stubDocumentId = DocumentId.CreateNewId(projectId);
var solution = workspace.CurrentSolution
.AddProject(projectId, "TestProject", "TestProject", LanguageNames.CSharp)
.WithProjectCompilationOptions(projectId, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
.WithProjectAssemblyName(projectId, assemblyName)
.AddMetadataReferences(projectId, CreateMetadataReferences())
.AddDocument(documentId, "Test.cs", SourceText.From(source))
.AddDocument(stubDocumentId, "PolicyStubs.cs", SourceText.From(PolicyStubSource));
var project = solution.GetProject(projectId)!;
var document = solution.GetDocument(documentId)!;
var compilation = await project.GetCompilationAsync();
var analyzer = new HttpClientUsageAnalyzer();
var diagnostics = await compilation!.WithAnalyzers(ImmutableArray.Create<DiagnosticAnalyzer>(analyzer))
.GetAnalyzerDiagnosticsAsync();
var diagnostic = Assert.Single(diagnostics);
var codeFixProvider = new HttpClientUsageCodeFixProvider();
var actions = new List<CodeAction>();
var context = new CodeFixContext(
document,
diagnostic,
(action, _) => actions.Add(action),
CancellationToken.None);
await codeFixProvider.RegisterCodeFixesAsync(context);
var action = Assert.Single(actions);
var operations = await action.GetOperationsAsync(CancellationToken.None);
foreach (var operation in operations)
{
operation.Apply(workspace, CancellationToken.None);
}
var updatedDocument = workspace.CurrentSolution.GetDocument(documentId)!;
var updatedText = await updatedDocument.GetTextAsync();
return updatedText.ToString();
}
private static IEnumerable<MetadataReference> CreateMetadataReferences()
{
yield return MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location);
yield return MetadataReference.CreateFromFile(typeof(Uri).GetTypeInfo().Assembly.Location);
yield return MetadataReference.CreateFromFile(typeof(HttpClient).GetTypeInfo().Assembly.Location);
yield return MetadataReference.CreateFromFile(typeof(Enumerable).GetTypeInfo().Assembly.Location);
}
private const string PolicyStubSource = """
namespace StellaOps.AirGap.Policy
{
public interface IEgressPolicy
{
void EnsureAllowed(EgressRequest request);
}
public readonly record struct EgressRequest(string Component, System.Uri Destination, string Intent);
public static class EgressHttpClientFactory
{
public static System.Net.Http.HttpClient Create(IEgressPolicy egressPolicy, EgressRequest request)
=> throw new System.NotImplementedException();
}
}
""";
}

View File

@@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.4" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.11.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.11.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="3.11.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
</ItemGroup>
<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\StellaOps.AirGap.Policy.Analyzers\StellaOps.AirGap.Policy.Analyzers.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,5 @@
### New Rules
Rule ID | Title | Category | Severity | Notes
--------|-------|----------|----------|------
AIRGAP001 | Replace raw HttpClient with EgressPolicy-aware client | Usage | Warning | Flags direct HttpClient instantiation outside the EgressPolicy-aware wrappers.

View File

@@ -0,0 +1,98 @@
using System;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;
namespace StellaOps.AirGap.Policy.Analyzers;
/// <summary>
/// Flags direct <c>new HttpClient()</c> usage so services adopt the air-gap aware egress policy wrappers.
/// </summary>
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public sealed class HttpClientUsageAnalyzer : DiagnosticAnalyzer
{
/// <summary>
/// Diagnostic identifier emitted when disallowed HttpClient usage is detected.
/// </summary>
public const string DiagnosticId = "AIRGAP001";
private const string HttpClientMetadataName = "System.Net.Http.HttpClient";
private static readonly LocalizableString Title = "Replace raw HttpClient with EgressPolicy-aware client";
private static readonly LocalizableString MessageFormat = "Instantiate HttpClient via StellaOps.AirGap.Policy wrappers to enforce sealed-mode egress controls";
private static readonly LocalizableString Description = "Air-gapped environments must route outbound network calls through the EgressPolicy facade so requests are pre-authorised. Replace raw HttpClient usage with the shared factory helpers.";
private static readonly DiagnosticDescriptor Rule = new(
DiagnosticId,
Title,
MessageFormat,
"Usage",
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
description: Description);
/// <inheritdoc/>
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);
/// <inheritdoc/>
public override void Initialize(AnalysisContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();
context.RegisterOperationAction(AnalyzeObjectCreation, OperationKind.ObjectCreation);
}
private static void AnalyzeObjectCreation(OperationAnalysisContext context)
{
if (context.Operation is not IObjectCreationOperation creation)
{
return;
}
var createdType = creation.Type;
if (createdType is null || !string.Equals(createdType.ToDisplayString(), HttpClientMetadataName, StringComparison.Ordinal))
{
return;
}
if (IsWithinAllowedAssembly(context.ContainingSymbol))
{
return;
}
var diagnostic = Diagnostic.Create(Rule, creation.Syntax.GetLocation());
context.ReportDiagnostic(diagnostic);
}
private static bool IsWithinAllowedAssembly(ISymbol? symbol)
{
var containingAssembly = symbol?.ContainingAssembly;
if (containingAssembly is null)
{
return false;
}
var assemblyName = containingAssembly.Name;
if (string.IsNullOrEmpty(assemblyName))
{
return false;
}
if (string.Equals(assemblyName, "StellaOps.AirGap.Policy", StringComparison.Ordinal))
{
return true;
}
if (assemblyName.EndsWith(".Tests", StringComparison.OrdinalIgnoreCase))
{
return true;
}
return false;
}
}

View File

@@ -0,0 +1,79 @@
using System;
using System.Collections.Immutable;
using System.Composition;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace StellaOps.AirGap.Policy.Analyzers;
/// <summary>
/// Offers a remediation template that routes HttpClient creation through the shared EgressPolicy factory.
/// </summary>
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(HttpClientUsageCodeFixProvider))]
[Shared]
public sealed class HttpClientUsageCodeFixProvider : CodeFixProvider
{
private const string Title = "Use EgressHttpClientFactory.Create(...)";
/// <inheritdoc/>
public override ImmutableArray<string> FixableDiagnosticIds
=> ImmutableArray.Create(HttpClientUsageAnalyzer.DiagnosticId);
/// <inheritdoc/>
public override FixAllProvider GetFixAllProvider()
=> WellKnownFixAllProviders.BatchFixer;
/// <inheritdoc/>
public override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
if (context.Document is null)
{
return;
}
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
if (root is null)
{
return;
}
var diagnostic = context.Diagnostics[0];
var node = root.FindNode(diagnostic.Location.SourceSpan);
if (node is not ObjectCreationExpressionSyntax objectCreation)
{
return;
}
context.RegisterCodeFix(
CodeAction.Create(
Title,
cancellationToken => ReplaceWithFactoryCallAsync(context.Document, objectCreation, cancellationToken),
equivalenceKey: Title),
diagnostic);
}
private static async Task<Document> ReplaceWithFactoryCallAsync(Document document, ObjectCreationExpressionSyntax creation, CancellationToken cancellationToken)
{
var replacementExpression = SyntaxFactory.ParseExpression(
"global::StellaOps.AirGap.Policy.EgressHttpClientFactory.Create(" +
"egressPolicy: /* TODO: provide IEgressPolicy instance */, " +
"request: new global::StellaOps.AirGap.Policy.EgressRequest(" +
"component: \"REPLACE_COMPONENT\", " +
"destination: new global::System.Uri(\"https://replace-with-endpoint\"), " +
"intent: \"REPLACE_INTENT\"))");
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
if (root is null)
{
return document;
}
var updatedRoot = root.ReplaceNode(creation, replacementExpression.WithTriviaFrom(creation));
return document.WithSyntaxRoot(updatedRoot);
}
}

View File

@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<IncludeBuildOutput>false</IncludeBuildOutput>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.11.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.11.0" PrivateAssets="all" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,229 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using StellaOps.AirGap.Policy;
using Xunit;
namespace StellaOps.AirGap.Policy.Tests;
public sealed class EgressPolicyTests
{
[Fact]
public void Evaluate_UnsealedEnvironment_AllowsRequest()
{
var options = new EgressPolicyOptions
{
Mode = EgressPolicyMode.Unsealed,
};
var policy = new EgressPolicy(options);
var request = new EgressRequest("PolicyEngine", new Uri("https://example.com"), "advisory-sync");
var decision = policy.Evaluate(request);
Assert.True(decision.IsAllowed);
Assert.Null(decision.Reason);
}
[Fact]
public void EnsureAllowed_SealedEnvironmentWithMatchingRule_Allows()
{
var options = new EgressPolicyOptions
{
Mode = EgressPolicyMode.Sealed,
};
options.AddAllowRule("api.example.com", 443, EgressTransport.Https);
var policy = new EgressPolicy(options);
var request = new EgressRequest("PolicyEngine", new Uri("https://api.example.com/v1/status"), "advisory-sync");
policy.EnsureAllowed(request);
}
[Fact]
public void EnsureAllowed_SealedEnvironmentWithoutRule_ThrowsWithGuidance()
{
var options = new EgressPolicyOptions
{
Mode = EgressPolicyMode.Sealed,
RemediationDocumentationUrl = "https://docs.stella-ops.org/airgap/egress",
SupportContact = "airgap-oncall@example.org",
};
var policy = new EgressPolicy(options);
var request = new EgressRequest("PolicyEngine", new Uri("https://unauthorized.example.com"), "advisory-sync", operation: "fetch-advisories");
var exception = Assert.Throws<AirGapEgressBlockedException>(() => policy.EnsureAllowed(request));
Assert.Contains(AirGapEgressBlockedException.ErrorCode, exception.Message, StringComparison.Ordinal);
Assert.Contains("unauthorized.example.com", exception.Message, StringComparison.OrdinalIgnoreCase);
Assert.Contains("airgap.egressAllowlist", exception.Remediation, StringComparison.OrdinalIgnoreCase);
Assert.Equal(request, exception.Request);
Assert.Equal(options.RemediationDocumentationUrl, exception.DocumentationUrl);
Assert.Equal(options.SupportContact, exception.SupportContact);
}
[Fact]
public void EnsureAllowed_SealedEnvironment_AllowsLoopbackWhenConfigured()
{
var options = new EgressPolicyOptions
{
Mode = EgressPolicyMode.Sealed,
AllowLoopback = true,
};
var policy = new EgressPolicy(options);
var request = new EgressRequest("PolicyEngine", new Uri("http://127.0.0.1:9000/health"), "local-probe");
policy.EnsureAllowed(request);
}
[Fact]
public void EnsureAllowed_SealedEnvironment_AllowsPrivateNetworkWhenConfigured()
{
var options = new EgressPolicyOptions
{
Mode = EgressPolicyMode.Sealed,
AllowPrivateNetworks = true,
};
var policy = new EgressPolicy(options);
var request = new EgressRequest("PolicyEngine", new Uri("https://10.10.0.5:8443/status"), "mirror-sync");
policy.EnsureAllowed(request);
}
[Fact]
public void EnsureAllowed_SealedEnvironment_BlocksPrivateNetworkWhenNotConfigured()
{
var options = new EgressPolicyOptions
{
Mode = EgressPolicyMode.Sealed,
AllowPrivateNetworks = false,
};
var policy = new EgressPolicy(options);
var request = new EgressRequest("PolicyEngine", new Uri("https://10.10.0.5:8443/status"), "mirror-sync");
var exception = Assert.Throws<AirGapEgressBlockedException>(() => policy.EnsureAllowed(request));
Assert.Contains("10.10.0.5", exception.Message, StringComparison.OrdinalIgnoreCase);
}
[Theory]
[InlineData("https://api.example.com", true)]
[InlineData("https://sub.api.example.com", true)]
[InlineData("https://example.com", false)]
public void Evaluate_SealedEnvironmentWildcardHost_Matches(string url, bool expectedAllowed)
{
var options = new EgressPolicyOptions
{
Mode = EgressPolicyMode.Sealed,
};
options.AddAllowRule("*.example.com", transport: EgressTransport.Https);
var policy = new EgressPolicy(options);
var request = new EgressRequest("PolicyEngine", new Uri(url), "mirror-sync");
var decision = policy.Evaluate(request);
Assert.Equal(expectedAllowed, decision.IsAllowed);
}
[Fact]
public void ServiceCollection_AddAirGapEgressPolicy_RegistersService()
{
var services = new ServiceCollection();
services.AddAirGapEgressPolicy(options =>
{
options.Mode = EgressPolicyMode.Sealed;
options.AddAllowRule("mirror.internal", transport: EgressTransport.Https);
});
using var provider = services.BuildServiceProvider();
var policy = provider.GetRequiredService<IEgressPolicy>();
Assert.True(policy.IsSealed);
policy.EnsureAllowed(new EgressRequest("PolicyEngine", new Uri("https://mirror.internal"), "mirror-sync"));
}
[Fact]
public void ServiceCollection_AddAirGapEgressPolicy_BindsFromConfiguration()
{
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?>
{
["AirGap:Egress:Mode"] = "Sealed",
["AirGap:Egress:AllowLoopback"] = "false",
["AirGap:Egress:AllowPrivateNetworks"] = "true",
["AirGap:Egress:RemediationDocumentationUrl"] = "https://docs.example/airgap",
["AirGap:Egress:SupportContact"] = "airgap@example.org",
["AirGap:Egress:Allowlist:0:HostPattern"] = "mirror.internal",
["AirGap:Egress:Allowlist:0:Port"] = "443",
["AirGap:Egress:Allowlist:0:Transport"] = "https",
["AirGap:Egress:Allowlist:0:Description"] = "Primary mirror",
})
.Build();
var services = new ServiceCollection();
services.AddAirGapEgressPolicy(configuration);
using var provider = services.BuildServiceProvider();
var policy = provider.GetRequiredService<IEgressPolicy>();
Assert.True(policy.IsSealed);
var decision = policy.Evaluate(new EgressRequest("ExportCenter", new Uri("https://mirror.internal/feeds"), "mirror-sync"));
Assert.True(decision.IsAllowed);
var blocked = policy.Evaluate(new EgressRequest("ExportCenter", new Uri("https://external.example"), "mirror-sync"));
Assert.False(blocked.IsAllowed);
Assert.Contains("mirror.internal", blocked.Remediation, StringComparison.OrdinalIgnoreCase);
}
[Fact]
public void EgressHttpClientFactory_Create_EnforcesPolicyBeforeReturningClient()
{
var recordingPolicy = new RecordingPolicy();
var request = new EgressRequest("Component", new Uri("https://allowed.internal"), "mirror-sync");
using var client = EgressHttpClientFactory.Create(recordingPolicy, request);
Assert.True(recordingPolicy.EnsureAllowedCalled);
Assert.NotNull(client);
}
private sealed class RecordingPolicy : IEgressPolicy
{
public bool EnsureAllowedCalled { get; private set; }
public bool IsSealed => true;
public EgressPolicyMode Mode => EgressPolicyMode.Sealed;
public EgressDecision Evaluate(EgressRequest request)
{
EnsureAllowedCalled = true;
return EgressDecision.Allowed;
}
public ValueTask<EgressDecision> EvaluateAsync(EgressRequest request, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
return new ValueTask<EgressDecision>(Evaluate(request));
}
public void EnsureAllowed(EgressRequest request)
{
EnsureAllowedCalled = true;
}
public ValueTask EnsureAllowedAsync(EgressRequest request, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
EnsureAllowed(request);
return ValueTask.CompletedTask;
}
}
}

View File

@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.4" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
</ItemGroup>
<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\StellaOps.AirGap.Policy\StellaOps.AirGap.Policy.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,100 @@
using System;
using System.Text;
namespace StellaOps.AirGap.Policy;
/// <summary>
/// Exception raised when an egress operation is blocked while sealed mode is active.
/// </summary>
public sealed class AirGapEgressBlockedException : InvalidOperationException
{
/// <summary>
/// Error code surfaced to callers when egress is blocked.
/// </summary>
public const string ErrorCode = "AIRGAP_EGRESS_BLOCKED";
/// <summary>
/// Initializes a new instance of the <see cref="AirGapEgressBlockedException"/> class.
/// </summary>
/// <param name="request">Request details.</param>
/// <param name="reason">Reason returned by the policy.</param>
/// <param name="remediation">Remediation guidance.</param>
/// <param name="documentationUrl">Optional documentation URL.</param>
/// <param name="supportContact">Optional support contact.</param>
public AirGapEgressBlockedException(
EgressRequest request,
string reason,
string remediation,
string? documentationUrl,
string? supportContact)
: base(BuildMessage(request, reason, remediation, documentationUrl, supportContact))
{
Request = request;
Reason = reason;
Remediation = remediation;
DocumentationUrl = documentationUrl;
SupportContact = supportContact;
}
/// <summary>
/// Gets the blocked request.
/// </summary>
public EgressRequest Request { get; }
/// <summary>
/// Gets the reason supplied by the policy.
/// </summary>
public string Reason { get; }
/// <summary>
/// Gets the remediation guidance.
/// </summary>
public string Remediation { get; }
/// <summary>
/// Gets an optional documentation URL.
/// </summary>
public string? DocumentationUrl { get; }
/// <summary>
/// Gets an optional support contact (for example, an on-call alias).
/// </summary>
public string? SupportContact { get; }
private static string BuildMessage(EgressRequest request, string reason, string remediation, string? documentationUrl, string? supportContact)
{
var builder = new StringBuilder();
builder.Append(ErrorCode)
.Append(": component '")
.Append(request.Component)
.Append("' attempted to reach '")
.Append(request.Destination)
.Append("' (intent: ")
.Append(request.Intent);
if (!string.IsNullOrEmpty(request.Operation))
{
builder.Append(", operation: ")
.Append(request.Operation);
}
builder.Append("). Reason: ")
.Append(reason)
.Append(". Remediation: ")
.Append(remediation);
if (!string.IsNullOrWhiteSpace(documentationUrl))
{
builder.Append(" Documentation: ")
.Append(documentationUrl);
}
if (!string.IsNullOrWhiteSpace(supportContact))
{
builder.Append(" Contact: ")
.Append(supportContact);
}
return builder.ToString();
}
}

View File

@@ -0,0 +1,43 @@
namespace StellaOps.AirGap.Policy;
/// <summary>
/// Represents the outcome of evaluating an egress request.
/// </summary>
public sealed record EgressDecision
{
private EgressDecision(bool isAllowed, string? reason, string? remediation)
{
IsAllowed = isAllowed;
Reason = reason;
Remediation = remediation;
}
/// <summary>
/// Gets a singleton instance representing an allowed decision.
/// </summary>
public static EgressDecision Allowed { get; } = new(true, null, null);
/// <summary>
/// Creates a blocked decision for the supplied reason/remediation.
/// </summary>
/// <param name="reason">Explanation for the denial.</param>
/// <param name="remediation">Suggested remediation to resolve the denial.</param>
/// <returns>An <see cref="EgressDecision"/> that blocks the request.</returns>
public static EgressDecision Blocked(string reason, string remediation)
=> new(false, reason, remediation);
/// <summary>
/// Gets a value indicating whether the request is permitted.
/// </summary>
public bool IsAllowed { get; }
/// <summary>
/// Gets the reason returned by the policy when the request was blocked.
/// </summary>
public string? Reason { get; }
/// <summary>
/// Gets suggested remediation guidance that callers can surface to operators.
/// </summary>
public string? Remediation { get; }
}

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