Event Envelope Schemas
Platform services publish strongly typed events; the JSON Schemas in this directory define those envelopes. File names follow <event-name>@<version>.json so producers and consumers can negotiate contracts explicitly.
Catalog
Orchestrator envelopes (ORCH-SVC-38-101)
- scanner.event.report.ready@1.json— orchestrator event emitted when a signed report is persisted. Supersedes the legacy- scanner.report.ready@1schema and adds versioning, idempotency keys, and trace context. Consumers: Orchestrator bus, Notifications Studio, UI timeline.
- scanner.event.scan.completed@1.json— orchestrator event emitted when a scan run finishes. Supersedes the legacy- scanner.scan.completed@1schema. Consumers: Orchestrator bus, Notifications Studio, Scheduler replay tooling.
Legacy envelopes (Redis-backed)
- scanner.report.ready@1.json— legacy Redis stream event emitted once a signed report is persisted (kept for transitional compatibility).
- scanner.scan.completed@1.json— legacy Redis stream event emitted alongside the signed report for automation.
- scheduler.rescan.delta@1.json— emitted by Scheduler when BOM-Index diffs require fresh scans. Consumers: Notify, Policy Engine.
- scheduler.graph.job.completed@1.json— emitted when a Cartographer graph build/overlay job finishes (- status = completed|failed|cancelled). Consumers: Scheduler WebService (lag metrics/API), Cartographer cache warmers, UI overlay freshness indicators.
- attestor.logged@1.json— emitted by Attestor after storing the Rekor inclusion proof. Consumers: UI attestation panel, Governance exports.
Additive payload changes (new optional fields) can stay within the same version. Any breaking change (removing a field, tightening validation, altering semantics) must increment the @<version> suffix and update downstream consumers. For full orchestrator guidance see orchestrator-scanner-events.md.
Envelope structure
Orchestrator envelope (version 1)
| Field | Type | Notes | 
|---|---|---|
| eventId | uuid | Globally unique per occurrence. | 
| kind | string | e.g., scanner.event.report.ready. | 
| version | integer | Schema version ( 1for the initial release). | 
| tenant | string | Multi‑tenant isolation key; mirror the value recorded in queue/Mongo metadata. | 
| occurredAt | date-time | RFC 3339 UTC timestamp describing when the state transition happened. | 
| recordedAt | date-time | RFC 3339 UTC timestamp for durable persistence (optional but recommended). | 
| source | string | Producer identifier ( scanner.webservice). | 
| idempotencyKey | string | Deterministic dedupe key (`scanner.event.*::<report | 
| correlationId | string | Ties the event to the originating scan/API request. | 
| traceId/spanId | string | W3C trace context propagated into downstream telemetry. | 
| scope | object | Optional block with at least repoanddigest. | 
| payload | object | Event-specific body; schemas embed the canonical report and DSSE envelope. | 
| attributes | object | Optional metadata bag ( stringkeys/values) for downstream correlation. | 
For Scanner orchestrator events, links include console and API deep links (ui, report, and policy) plus an optional attestation URL when a DSSE envelope is present. See orchestrator-scanner-events.md for details.
Legacy Redis envelope
| Field | Type | Notes | 
|---|---|---|
| eventId | uuid | Must be globally unique per occurrence; producers log duplicates as fatal. | 
| kind | string | Fixed per schema (e.g., scanner.report.ready). Downstream services reject unknown kinds or versions. | 
| tenant | string | Multi‑tenant isolation key; mirror the value recorded in queue/Mongo metadata. | 
| ts | date-time | RFC 3339 UTC timestamp. Use monotonic clocks or atomic offsets so ordering survives retries. | 
| scope | object | Optional block used when the event concerns a specific image or repository. See schema for required fields (e.g., repo,digest). | 
| payload | object | Event-specific body. Schemas allow additional properties so producers can add optional hints (e.g., reportId,quietedFindingCount) without breaking consumers. Seedocs/runtime/SCANNER_RUNTIME_READINESS.mdfor the runtime consumer checklist covering these hints. | 
| attributes | object | Optional metadata bag ( stringkeys/values) for downstream correlation (e.g., pipeline identifiers). Omit when unused to keep payloads concise. | 
When adding new optional fields, document the behaviour in the schema’s description block and update the consumer checklist in the next sprint sync.
Canonical samples & validation
Reference payloads live under docs/events/samples/, mirroring the schema version (<event-name>@<version>.sample.json). They illustrate common field combinations, including the optional attributes that downstream teams rely on for UI affordances and audit trails. Scanner samples reuse the exact DSSE envelope checked into samples/api/reports/report-sample.dsse.json, and unit tests (ReportSamplesTests, PlatformEventSchemaValidationTests) guard that payloads stay canonical and continue to satisfy the published schemas.
Run the following loop offline to validate both schemas and samples:
# Validate schemas (same check as CI)
for schema in docs/events/*.json; do
  npx ajv compile -c ajv-formats -s "$schema"
done
# Validate canonical samples against their schemas
for sample in docs/events/samples/*.sample.json; do
  schema="docs/events/$(basename "${sample%.sample.json}").json"
  npx ajv validate -c ajv-formats -s "$schema" -d "$sample"
done
Consumers can copy the samples into integration tests to guarantee backwards compatibility. When emitting new event versions, include a matching sample and update this README so air-gapped operators stay in sync.
CI validation
The Docs CI workflow (.gitea/workflows/docs.yml) installs ajv-cli and compiles every schema on pull requests. Run the same check locally before opening a PR:
for schema in docs/events/*.json; do
  npx ajv compile -c ajv-formats -s "$schema"
done
Tip: run npm install --no-save ajv ajv-cli ajv-formats once per clone so npx can resolve the tooling offline.
If a schema references additional files, include -r flags so CI and local runs stay consistent.
Working with schemas
- Producers should validate outbound payloads using the matching schema during unit tests.
- Consumers should pin to a specific version and log when encountering unknown versions to catch missing migrations early.
- Store real payload samples under docs/events/samples/(mirrors the schema version) and mirror them intosamples/events/when you need fixtures in integration repositories.
Contact the Platform Events group in Docs Guild if you need help shaping a new event or version strategy.