- 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.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,scanIdmirrorsreportIdso 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, orfailafter policy evaluation.summary— blocked/warned/ignored/quieted counters (all non-negative integers).delta— newly critical/high counts and optionalkevarray.quietedFindingCount— mirrorssummary.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 mirrorsreportIdas 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 withid,severity, optionalcve,purl, andreachability.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.