- 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.
		
			
				
	
	
	
		
			8.2 KiB
		
	
	
	
	
	
	
	
			
		
		
	
	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.readyandscanner.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 repoanddigest; optionalnamespace,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,- scanIdmirrors- reportIdso 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- failafter policy evaluation.
- summary— blocked/warned/ignored/quieted counters (all non-negative integers).
- delta— newly critical/high counts and optional- kevarray.
- 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,- scanIdcurrently mirrors- reportIdas a temporary shim.
- Attributes: reportId,policyRevisionId,policyDigest,verdict.
- Links: same as above (ui,report,policy) withattestationpopulated 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 NotifyCanonicalJsonSerializerto guarantee consistent key ordering and whitespace.
- Timestamps (occurredAt,recordedAt,payload.generatedAt) useDateTimeOffset.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 versionfield 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@1schema/docs in place until orchestrator subscribers confirm migration.
6. Consumer checklist
- Validate incoming payloads against the schema for the targeted version.
- Use idempotencyKeyfor dedupe, noteventId.
- Map traceId/spanIdinto telemetry spans to preserve causality.
- Prefer payload.report→policy.revisionIdwhen populating templates; the top-levelattributesare convenience duplicates for quick routing.
- 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) andSCANNER-EVENTS-16-302(doing) track the production of these envelopes. The remaining blocker is the .NET 10 preview OpenAPI/Auth dependency drift that currently breaksdotnet test. Once Gateway and Notifier owners land the replacement packages, rerun the full test suite and capture fresh fixtures underdocs/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.mdto confirm downstream validation before the production cutover. Record gaps or newly required fields indocs/ops/launch-readiness.mdso 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.