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:

FieldTypeNotes
eventIduuidGlobally unique identifier generated per occurrence.
kindstringEvent identifier; Scanner emits scanner.event.report.ready and scanner.event.scan.completed.
versionintegerSchema version. Initial release uses 1.
tenantstringTenant that owns the scan/report. Mirrors Authority claims.
occurredAtdate-timeUTC instant when the underlying state transition happened (e.g., report persisted).
recordedAtdate-timeUTC instant when the event was durably written. Optional but recommended.
sourcestringProducer identifier (scanner.webservice).
idempotencyKeystringDeterministic key for duplicate suppression (see §4).
correlationIdstringMaps back to the API request or scan identifier.
traceId / spanIdstringW3C trace context propagated into downstream telemetry.
scopeobjectDescribes the affected artefact. Requires repo and digest; optional namespace, component, image.
attributesobjectFlat string map for frequently queried metadata (e.g., policy revision).
payloadobjectEvent-specific body (see §2).

Canonical schemas live under docs/modules/signals/events/scanner.event.*@1.json. Samples that round-trip through NotifyCanonicalJsonSerializer are stored in docs/modules/signals/events/samples/.

2. Event kinds and payloads

2.1 scanner.event.report.ready

Emitted once a signed report is persisted and attested. Payload highlights:

Schema: docs/modules/signals/events/scanner.event.report.ready@1.json Sample: docs/modules/signals/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:

Schema: docs/modules/signals/events/scanner.event.scan.completed@1.json Sample: docs/modules/signals/events/samples/scanner.event.scan.completed@1.sample.json

2.3 Relationship to legacy events

Legacy Redis eventReplacement orchestrator eventNotes
scanner.report.readyscanner.event.report.readyAdds versioning, idempotency, trace context. Payload is a superset of the legacy fields.
scanner.scan.completedscanner.event.scan.completedSame 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

4. Idempotency and correlation

Idempotency keys dedupe repeated publishes and align with the orchestrator’s outbox pattern:

Event kindIdempotency key template
scanner.event.report.readyscanner.event.report.ready:<tenant>:<reportId>
scanner.event.scan.completedscanner.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

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.reportpolicy.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


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.