Add Policy DSL Validator, Schema Exporter, and Simulation Smoke tools
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
- Implemented PolicyDslValidator with command-line options for strict mode and JSON output. - Created PolicySchemaExporter to generate JSON schemas for policy-related models. - Developed PolicySimulationSmoke tool to validate policy simulations against expected outcomes. - Added project files and necessary dependencies for each tool. - Ensured proper error handling and usage instructions across tools.
This commit is contained in:
121
docs/events/orchestrator-scanner-events.md
Normal file
121
docs/events/orchestrator-scanner-events.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# Scanner Orchestrator Events (ORCH-SVC-38-101)
|
||||
|
||||
Last updated: 2025-10-26
|
||||
|
||||
The Notifications Studio initiative (NOTIFY-SVC-38-001) and orchestrator backlog (ORCH-SVC-38-101) standardise how platform services emit lifecycle events. This document describes the Scanner WebService contract for the new **orchestrator envelopes** (`scanner.event.*`) and how they supersede the legacy Redis-backed `scanner.report.ready` / `scanner.scan.completed` events.
|
||||
|
||||
## 1. Envelope overview
|
||||
|
||||
Orchestrator events share a deterministic JSON envelope:
|
||||
|
||||
| Field | Type | Notes |
|
||||
|-------|------|-------|
|
||||
| `eventId` | `uuid` | Globally unique identifier generated per occurrence. |
|
||||
| `kind` | `string` | Event identifier; Scanner emits `scanner.event.report.ready` and `scanner.event.scan.completed`. |
|
||||
| `version` | `integer` | Schema version. Initial release uses `1`. |
|
||||
| `tenant` | `string` | Tenant that owns the scan/report. Mirrors Authority claims. |
|
||||
| `occurredAt` | `date-time` | UTC instant when the underlying state transition happened (e.g., report persisted). |
|
||||
| `recordedAt` | `date-time` | UTC instant when the event was durably written. Optional but recommended. |
|
||||
| `source` | `string` | Producer identifier (`scanner.webservice`). |
|
||||
| `idempotencyKey` | `string` | Deterministic key for duplicate suppression (see §4). |
|
||||
| `correlationId` | `string` | Maps back to the API request or scan identifier. |
|
||||
| `traceId` / `spanId` | `string` | W3C trace context propagated into downstream telemetry. |
|
||||
| `scope` | `object` | Describes the affected artefact. Requires `repo` and `digest`; optional `namespace`, `component`, `image`. |
|
||||
| `attributes` | `object` | Flat string map for frequently queried metadata (e.g., policy revision). |
|
||||
| `payload` | `object` | Event-specific body (see §2). |
|
||||
|
||||
Canonical schemas live under `docs/events/scanner.event.*@1.json`. Samples that round-trip through `NotifyCanonicalJsonSerializer` are stored in `docs/events/samples/`.
|
||||
|
||||
## 2. Event kinds and payloads
|
||||
|
||||
### 2.1 `scanner.event.report.ready`
|
||||
|
||||
Emitted once a signed report is persisted and attested. Payload highlights:
|
||||
|
||||
- `reportId` / `scanId` — identifiers for the persisted report and originating scan. Until Scan IDs are surfaced by the API, `scanId` mirrors `reportId` so downstream correlators can stabilise on a single key.
|
||||
- **Attributes:** `reportId`, `policyRevisionId`, `policyDigest`, `verdict` — pre-sorted for deterministic routing.
|
||||
- **Links:**
|
||||
- `ui` → `/ui/reports/{reportId}` on the current host.
|
||||
- `report` → `{apiBasePath}/{reportsSegment}/{reportId}` (defaults to `/api/v1/reports/{reportId}`).
|
||||
- `policy` → `{apiBasePath}/{policySegment}/revisions/{revisionId}` when a revision is present.
|
||||
- `attestation` → `/ui/attestations/{reportId}` when a DSSE envelope is included.
|
||||
- `imageDigest` — OCI image digest associated with the analysis.
|
||||
- `generatedAt` — report generation timestamp (ISO-8601 UTC).
|
||||
- `verdict` — `pass`, `warn`, or `fail` after policy evaluation.
|
||||
- `summary` — blocked/warned/ignored/quieted counters (all non-negative integers).
|
||||
- `delta` — newly critical/high counts and optional `kev` array.
|
||||
- `quietedFindingCount` — mirrors `summary.quieted`.
|
||||
- `policy` — revision metadata (`digest`, `revisionId`) surfaced for routing.
|
||||
- `links` — UI/report/policy URLs suitable for operators.
|
||||
- `dsse` — embedded DSSE envelope (payload, type, signature list).
|
||||
- `report` — canonical report document; identical to the DSSE payload.
|
||||
|
||||
Schema: `docs/events/scanner.event.report.ready@1.json`
|
||||
Sample: `docs/events/samples/scanner.event.report.ready@1.sample.json`
|
||||
|
||||
### 2.2 `scanner.event.scan.completed`
|
||||
|
||||
Emitted after scan execution finishes (success or policy failure). Payload highlights:
|
||||
|
||||
- `reportId` / `scanId` / `imageDigest` — identifiers mirroring the report-ready event. As with the report-ready payload, `scanId` currently mirrors `reportId` as a temporary shim.
|
||||
- **Attributes:** `reportId`, `policyRevisionId`, `policyDigest`, `verdict`.
|
||||
- **Links:** same as above (`ui`, `report`, `policy`) with `attestation` populated when DSSE metadata exists.
|
||||
- `verdict`, `summary`, `delta`, `policy` — same semantics as above.
|
||||
- `findings` — array of surfaced findings with `id`, `severity`, optional `cve`, `purl`, and `reachability`.
|
||||
- `links`, `dsse`, `report` — same structure as §2.1 (allows Notifier to reuse signatures).
|
||||
|
||||
Schema: `docs/events/scanner.event.scan.completed@1.json`
|
||||
Sample: `docs/events/samples/scanner.event.scan.completed@1.sample.json`
|
||||
|
||||
### 2.3 Relationship to legacy events
|
||||
|
||||
| Legacy Redis event | Replacement orchestrator event | Notes |
|
||||
|--------------------|-------------------------------|-------|
|
||||
| `scanner.report.ready` | `scanner.event.report.ready` | Adds versioning, idempotency, trace context. Payload is a superset of the legacy fields. |
|
||||
| `scanner.scan.completed` | `scanner.event.scan.completed` | Same data plus explicit scan identifiers and orchestrator metadata. |
|
||||
|
||||
Legacy schemas remain for backwards-compatibility during migration, but new integrations **must** target the orchestrator variants.
|
||||
|
||||
## 3. Deterministic serialization
|
||||
|
||||
- Producers must serialise events using `NotifyCanonicalJsonSerializer` to guarantee consistent key ordering and whitespace.
|
||||
- Timestamps (`occurredAt`, `recordedAt`, `payload.generatedAt`) use `DateTimeOffset.UtcDateTime.ToString("O")`.
|
||||
- Payload arrays (`delta.kev`, `findings`) should be pre-sorted (e.g., alphabetical CVE order) so hash-based consumers remain stable.
|
||||
- Optional fields are omitted rather than emitted as `null`.
|
||||
|
||||
## 4. Idempotency and correlation
|
||||
|
||||
Idempotency keys dedupe repeated publishes and align with the orchestrator’s outbox pattern:
|
||||
|
||||
| Event kind | Idempotency key template |
|
||||
|------------|-------------------------|
|
||||
| `scanner.event.report.ready` | `scanner.event.report.ready:<tenant>:<reportId>` |
|
||||
| `scanner.event.scan.completed` | `scanner.event.scan.completed:<tenant>:<scanId>` |
|
||||
|
||||
Keys are ASCII lowercase; components should be trimmed and validated before concatenation. Retries must reuse the same key.
|
||||
|
||||
`correlationId` should match the scan identifier that appears in REST responses (`scanId`). Re-using the same value across the pair of events allows Notifier and orchestrator analytics to stitch lifecycle data together.
|
||||
|
||||
## 5. Versioning and evolution
|
||||
|
||||
- Increment the `version` field and the `@<version>` suffix for **breaking** changes (field removals, type changes, semantic shifts).
|
||||
- Additive optional fields may remain within version 1; update the JSON schema and samples accordingly.
|
||||
- When introducing `@2`, keep the `@1` schema/docs in place until orchestrator subscribers confirm migration.
|
||||
|
||||
## 6. Consumer checklist
|
||||
|
||||
1. Validate incoming payloads against the schema for the targeted version.
|
||||
2. Use `idempotencyKey` for dedupe, not `eventId`.
|
||||
3. Map `traceId`/`spanId` into telemetry spans to preserve causality.
|
||||
4. Prefer `payload.report` → `policy.revisionId` when populating templates; the top-level `attributes` are convenience duplicates for quick routing.
|
||||
5. Reserve the legacy Redis events for transitional compatibility only; downstream systems should subscribe to the orchestrator bus exposed by ORCH-SVC-38-101.
|
||||
|
||||
## 7. Implementation status and next actions
|
||||
|
||||
- **Scanner WebService** — `SCANNER-EVENTS-16-301` (blocked) and `SCANNER-EVENTS-16-302` (doing) track the production of these envelopes. The remaining blocker is the .NET 10 preview OpenAPI/Auth dependency drift that currently breaks `dotnet test`. Once Gateway and Notifier owners land the replacement packages, rerun the full test suite and capture fresh fixtures under `docs/events/samples/`.
|
||||
- **Gateway/Notifier consumers** — subscribe to the orchestrator stream documented in ORCH-SVC-38-101. When the Scanner tasks unblock, regenerate notifier contract tests against the sample events included here.
|
||||
- **Docs cadence** — update this file and the matching JSON schemas whenever payload fields change. Use the rehearsal checklist in `docs/ops/launch-cutover.md` to confirm downstream validation before the production cutover. Record gaps or newly required fields in `docs/ops/launch-readiness.md` so they land in the launch checklist.
|
||||
|
||||
---
|
||||
|
||||
**Imposed rule reminder:** work of this type or tasks of this type on this component must also be applied everywhere else it should be applied.
|
||||
Reference in New Issue
Block a user