Restructure solution layout by module
This commit is contained in:
@@ -1,121 +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.
|
||||
# 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.
|
||||
|
||||
@@ -1,93 +1,93 @@
|
||||
{
|
||||
"eventId": "6d2d1b77-f3c3-4f70-8a9d-6f2d0c8801ab",
|
||||
"kind": "scanner.event.report.ready",
|
||||
"version": 1,
|
||||
"tenant": "tenant-alpha",
|
||||
"occurredAt": "2025-10-19T12:34:56Z",
|
||||
"recordedAt": "2025-10-19T12:34:57Z",
|
||||
"source": "scanner.webservice",
|
||||
"idempotencyKey": "scanner.event.report.ready:tenant-alpha:report-abc",
|
||||
"correlationId": "report-abc",
|
||||
"traceId": "0af7651916cd43dd8448eb211c80319c",
|
||||
"spanId": "b7ad6b7169203331",
|
||||
"scope": {
|
||||
"namespace": "acme/edge",
|
||||
"repo": "api",
|
||||
"digest": "sha256:feedface"
|
||||
},
|
||||
"attributes": {
|
||||
"reportId": "report-abc",
|
||||
"policyRevisionId": "rev-42",
|
||||
"policyDigest": "digest-123",
|
||||
"verdict": "blocked"
|
||||
},
|
||||
"payload": {
|
||||
"reportId": "report-abc",
|
||||
"scanId": "report-abc",
|
||||
"imageDigest": "sha256:feedface",
|
||||
"generatedAt": "2025-10-19T12:34:56Z",
|
||||
"verdict": "fail",
|
||||
"summary": {
|
||||
"total": 1,
|
||||
"blocked": 1,
|
||||
"warned": 0,
|
||||
"ignored": 0,
|
||||
"quieted": 0
|
||||
},
|
||||
"delta": {
|
||||
"newCritical": 1,
|
||||
"kev": [
|
||||
"CVE-2024-9999"
|
||||
]
|
||||
},
|
||||
"quietedFindingCount": 0,
|
||||
"policy": {
|
||||
"digest": "digest-123",
|
||||
"revisionId": "rev-42"
|
||||
},
|
||||
"links": {
|
||||
"ui": "https://scanner.example/ui/reports/report-abc",
|
||||
"report": "https://scanner.example/api/v1/reports/report-abc",
|
||||
"policy": "https://scanner.example/api/v1/policy/revisions/rev-42",
|
||||
"attestation": "https://scanner.example/ui/attestations/report-abc"
|
||||
},
|
||||
"dsse": {
|
||||
"payloadType": "application/vnd.stellaops.report+json",
|
||||
"payload": "eyJyZXBvcnRJZCI6InJlcG9ydC1hYmMiLCJpbWFnZURpZ2VzdCI6InNoYTI1NjpmZWVkZmFjZSIsImdlbmVyYXRlZEF0IjoiMjAyNS0xMC0xOVQxMjozNDo1NiswMDowMCIsInZlcmRpY3QiOiJibG9ja2VkIiwicG9saWN5Ijp7InJldmlzaW9uSWQiOiJyZXYtNDIiLCJkaWdlc3QiOiJkaWdlc3QtMTIzIn0sInN1bW1hcnkiOnsidG90YWwiOjEsImJsb2NrZWQiOjEsIndhcm5lZCI6MCwiaWdub3JlZCI6MCwicXVpZXRlZCI6MH0sInZlcmRpY3RzIjpbeyJmaW5kaW5nSWQiOiJmaW5kaW5nLTEiLCJzdGF0dXMiOiJCbG9ja2VkIiwic2NvcmUiOjQ3LjUsInNvdXJjZVRydXN0IjoiTlZEIiwicmVhY2hhYmlsaXR5IjoicnVudGltZSJ9XSwiaXNzdWVzIjpbXX0=",
|
||||
"signatures": [
|
||||
{
|
||||
"keyId": "test-key",
|
||||
"algorithm": "hs256",
|
||||
"signature": "signature-value"
|
||||
}
|
||||
]
|
||||
},
|
||||
"report": {
|
||||
"reportId": "report-abc",
|
||||
"generatedAt": "2025-10-19T12:34:56Z",
|
||||
"imageDigest": "sha256:feedface",
|
||||
"policy": {
|
||||
"digest": "digest-123",
|
||||
"revisionId": "rev-42"
|
||||
},
|
||||
"summary": {
|
||||
"total": 1,
|
||||
"blocked": 1,
|
||||
"warned": 0,
|
||||
"ignored": 0,
|
||||
"quieted": 0
|
||||
},
|
||||
"verdict": "blocked",
|
||||
"verdicts": [
|
||||
{
|
||||
"findingId": "finding-1",
|
||||
"status": "Blocked",
|
||||
"score": 47.5,
|
||||
"sourceTrust": "NVD",
|
||||
"reachability": "runtime"
|
||||
}
|
||||
],
|
||||
"issues": []
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
"eventId": "6d2d1b77-f3c3-4f70-8a9d-6f2d0c8801ab",
|
||||
"kind": "scanner.event.report.ready",
|
||||
"version": 1,
|
||||
"tenant": "tenant-alpha",
|
||||
"occurredAt": "2025-10-19T12:34:56Z",
|
||||
"recordedAt": "2025-10-19T12:34:57Z",
|
||||
"source": "scanner.webservice",
|
||||
"idempotencyKey": "scanner.event.report.ready:tenant-alpha:report-abc",
|
||||
"correlationId": "report-abc",
|
||||
"traceId": "0af7651916cd43dd8448eb211c80319c",
|
||||
"spanId": "b7ad6b7169203331",
|
||||
"scope": {
|
||||
"namespace": "acme/edge",
|
||||
"repo": "api",
|
||||
"digest": "sha256:feedface"
|
||||
},
|
||||
"attributes": {
|
||||
"reportId": "report-abc",
|
||||
"policyRevisionId": "rev-42",
|
||||
"policyDigest": "digest-123",
|
||||
"verdict": "blocked"
|
||||
},
|
||||
"payload": {
|
||||
"reportId": "report-abc",
|
||||
"scanId": "report-abc",
|
||||
"imageDigest": "sha256:feedface",
|
||||
"generatedAt": "2025-10-19T12:34:56Z",
|
||||
"verdict": "fail",
|
||||
"summary": {
|
||||
"total": 1,
|
||||
"blocked": 1,
|
||||
"warned": 0,
|
||||
"ignored": 0,
|
||||
"quieted": 0
|
||||
},
|
||||
"delta": {
|
||||
"newCritical": 1,
|
||||
"kev": [
|
||||
"CVE-2024-9999"
|
||||
]
|
||||
},
|
||||
"quietedFindingCount": 0,
|
||||
"policy": {
|
||||
"digest": "digest-123",
|
||||
"revisionId": "rev-42"
|
||||
},
|
||||
"links": {
|
||||
"ui": "https://scanner.example/ui/reports/report-abc",
|
||||
"report": "https://scanner.example/api/v1/reports/report-abc",
|
||||
"policy": "https://scanner.example/api/v1/policy/revisions/rev-42",
|
||||
"attestation": "https://scanner.example/ui/attestations/report-abc"
|
||||
},
|
||||
"dsse": {
|
||||
"payloadType": "application/vnd.stellaops.report+json",
|
||||
"payload": "eyJyZXBvcnRJZCI6InJlcG9ydC1hYmMiLCJpbWFnZURpZ2VzdCI6InNoYTI1NjpmZWVkZmFjZSIsImdlbmVyYXRlZEF0IjoiMjAyNS0xMC0xOVQxMjozNDo1NiswMDowMCIsInZlcmRpY3QiOiJibG9ja2VkIiwicG9saWN5Ijp7InJldmlzaW9uSWQiOiJyZXYtNDIiLCJkaWdlc3QiOiJkaWdlc3QtMTIzIn0sInN1bW1hcnkiOnsidG90YWwiOjEsImJsb2NrZWQiOjEsIndhcm5lZCI6MCwiaWdub3JlZCI6MCwicXVpZXRlZCI6MH0sInZlcmRpY3RzIjpbeyJmaW5kaW5nSWQiOiJmaW5kaW5nLTEiLCJzdGF0dXMiOiJCbG9ja2VkIiwic2NvcmUiOjQ3LjUsInNvdXJjZVRydXN0IjoiTlZEIiwicmVhY2hhYmlsaXR5IjoicnVudGltZSJ9XSwiaXNzdWVzIjpbXX0=",
|
||||
"signatures": [
|
||||
{
|
||||
"keyId": "test-key",
|
||||
"algorithm": "hs256",
|
||||
"signature": "signature-value"
|
||||
}
|
||||
]
|
||||
},
|
||||
"report": {
|
||||
"reportId": "report-abc",
|
||||
"generatedAt": "2025-10-19T12:34:56Z",
|
||||
"imageDigest": "sha256:feedface",
|
||||
"policy": {
|
||||
"digest": "digest-123",
|
||||
"revisionId": "rev-42"
|
||||
},
|
||||
"summary": {
|
||||
"total": 1,
|
||||
"blocked": 1,
|
||||
"warned": 0,
|
||||
"ignored": 0,
|
||||
"quieted": 0
|
||||
},
|
||||
"verdict": "blocked",
|
||||
"verdicts": [
|
||||
{
|
||||
"findingId": "finding-1",
|
||||
"status": "Blocked",
|
||||
"score": 47.5,
|
||||
"sourceTrust": "NVD",
|
||||
"reachability": "runtime"
|
||||
}
|
||||
],
|
||||
"issues": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,99 +1,99 @@
|
||||
{
|
||||
"eventId": "08a6de24-4a94-4d14-8432-9d14f36f6da3",
|
||||
"kind": "scanner.event.scan.completed",
|
||||
"version": 1,
|
||||
"tenant": "tenant-alpha",
|
||||
"occurredAt": "2025-10-19T12:34:56Z",
|
||||
"recordedAt": "2025-10-19T12:34:57Z",
|
||||
"source": "scanner.webservice",
|
||||
"idempotencyKey": "scanner.event.scan.completed:tenant-alpha:report-abc",
|
||||
"correlationId": "report-abc",
|
||||
"traceId": "4bf92f3577b34da6a3ce929d0e0e4736",
|
||||
"scope": {
|
||||
"namespace": "acme/edge",
|
||||
"repo": "api",
|
||||
"digest": "sha256:feedface"
|
||||
},
|
||||
"attributes": {
|
||||
"reportId": "report-abc",
|
||||
"policyRevisionId": "rev-42",
|
||||
"policyDigest": "digest-123",
|
||||
"verdict": "blocked"
|
||||
},
|
||||
"payload": {
|
||||
"reportId": "report-abc",
|
||||
"scanId": "report-abc",
|
||||
"imageDigest": "sha256:feedface",
|
||||
"verdict": "fail",
|
||||
"summary": {
|
||||
"total": 1,
|
||||
"blocked": 1,
|
||||
"warned": 0,
|
||||
"ignored": 0,
|
||||
"quieted": 0
|
||||
},
|
||||
"delta": {
|
||||
"newCritical": 1,
|
||||
"kev": [
|
||||
"CVE-2024-9999"
|
||||
]
|
||||
},
|
||||
"policy": {
|
||||
"digest": "digest-123",
|
||||
"revisionId": "rev-42"
|
||||
},
|
||||
"findings": [
|
||||
{
|
||||
"id": "finding-1",
|
||||
"severity": "Critical",
|
||||
"cve": "CVE-2024-9999",
|
||||
"purl": "pkg:docker/acme/edge-api@sha256-feedface",
|
||||
"reachability": "runtime"
|
||||
}
|
||||
],
|
||||
"links": {
|
||||
"ui": "https://scanner.example/ui/reports/report-abc",
|
||||
"report": "https://scanner.example/api/v1/reports/report-abc",
|
||||
"policy": "https://scanner.example/api/v1/policy/revisions/rev-42",
|
||||
"attestation": "https://scanner.example/ui/attestations/report-abc"
|
||||
},
|
||||
"dsse": {
|
||||
"payloadType": "application/vnd.stellaops.report+json",
|
||||
"payload": "eyJyZXBvcnRJZCI6InJlcG9ydC1hYmMiLCJpbWFnZURpZ2VzdCI6InNoYTI1NjpmZWVkZmFjZSIsImdlbmVyYXRlZEF0IjoiMjAyNS0xMC0xOVQxMjozNDo1NiswMDowMCIsInZlcmRpY3QiOiJibG9ja2VkIiwicG9saWN5Ijp7InJldmlzaW9uSWQiOiJyZXYtNDIiLCJkaWdlc3QiOiJkaWdlc3QtMTIzIn0sInN1bW1hcnkiOnsidG90YWwiOjEsImJsb2NrZWQiOjEsIndhcm5lZCI6MCwiaWdub3JlZCI6MCwicXVpZXRlZCI6MH0sInZlcmRpY3RzIjpbeyJmaW5kaW5nSWQiOiJmaW5kaW5nLTEiLCJzdGF0dXMiOiJCbG9ja2VkIiwic2NvcmUiOjQ3LjUsInNvdXJjZVRydXN0IjoiTlZEIiwicmVhY2hhYmlsaXR5IjoicnVudGltZSJ9XSwiaXNzdWVzIjpbXX0=",
|
||||
"signatures": [
|
||||
{
|
||||
"keyId": "test-key",
|
||||
"algorithm": "hs256",
|
||||
"signature": "signature-value"
|
||||
}
|
||||
]
|
||||
},
|
||||
"report": {
|
||||
"reportId": "report-abc",
|
||||
"generatedAt": "2025-10-19T12:34:56Z",
|
||||
"imageDigest": "sha256:feedface",
|
||||
"policy": {
|
||||
"digest": "digest-123",
|
||||
"revisionId": "rev-42"
|
||||
},
|
||||
"summary": {
|
||||
"total": 1,
|
||||
"blocked": 1,
|
||||
"warned": 0,
|
||||
"ignored": 0,
|
||||
"quieted": 0
|
||||
},
|
||||
"verdict": "blocked",
|
||||
"verdicts": [
|
||||
{
|
||||
"findingId": "finding-1",
|
||||
"status": "Blocked",
|
||||
"score": 47.5,
|
||||
"sourceTrust": "NVD",
|
||||
"reachability": "runtime"
|
||||
}
|
||||
],
|
||||
"issues": []
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
"eventId": "08a6de24-4a94-4d14-8432-9d14f36f6da3",
|
||||
"kind": "scanner.event.scan.completed",
|
||||
"version": 1,
|
||||
"tenant": "tenant-alpha",
|
||||
"occurredAt": "2025-10-19T12:34:56Z",
|
||||
"recordedAt": "2025-10-19T12:34:57Z",
|
||||
"source": "scanner.webservice",
|
||||
"idempotencyKey": "scanner.event.scan.completed:tenant-alpha:report-abc",
|
||||
"correlationId": "report-abc",
|
||||
"traceId": "4bf92f3577b34da6a3ce929d0e0e4736",
|
||||
"scope": {
|
||||
"namespace": "acme/edge",
|
||||
"repo": "api",
|
||||
"digest": "sha256:feedface"
|
||||
},
|
||||
"attributes": {
|
||||
"reportId": "report-abc",
|
||||
"policyRevisionId": "rev-42",
|
||||
"policyDigest": "digest-123",
|
||||
"verdict": "blocked"
|
||||
},
|
||||
"payload": {
|
||||
"reportId": "report-abc",
|
||||
"scanId": "report-abc",
|
||||
"imageDigest": "sha256:feedface",
|
||||
"verdict": "fail",
|
||||
"summary": {
|
||||
"total": 1,
|
||||
"blocked": 1,
|
||||
"warned": 0,
|
||||
"ignored": 0,
|
||||
"quieted": 0
|
||||
},
|
||||
"delta": {
|
||||
"newCritical": 1,
|
||||
"kev": [
|
||||
"CVE-2024-9999"
|
||||
]
|
||||
},
|
||||
"policy": {
|
||||
"digest": "digest-123",
|
||||
"revisionId": "rev-42"
|
||||
},
|
||||
"findings": [
|
||||
{
|
||||
"id": "finding-1",
|
||||
"severity": "Critical",
|
||||
"cve": "CVE-2024-9999",
|
||||
"purl": "pkg:docker/acme/edge-api@sha256-feedface",
|
||||
"reachability": "runtime"
|
||||
}
|
||||
],
|
||||
"links": {
|
||||
"ui": "https://scanner.example/ui/reports/report-abc",
|
||||
"report": "https://scanner.example/api/v1/reports/report-abc",
|
||||
"policy": "https://scanner.example/api/v1/policy/revisions/rev-42",
|
||||
"attestation": "https://scanner.example/ui/attestations/report-abc"
|
||||
},
|
||||
"dsse": {
|
||||
"payloadType": "application/vnd.stellaops.report+json",
|
||||
"payload": "eyJyZXBvcnRJZCI6InJlcG9ydC1hYmMiLCJpbWFnZURpZ2VzdCI6InNoYTI1NjpmZWVkZmFjZSIsImdlbmVyYXRlZEF0IjoiMjAyNS0xMC0xOVQxMjozNDo1NiswMDowMCIsInZlcmRpY3QiOiJibG9ja2VkIiwicG9saWN5Ijp7InJldmlzaW9uSWQiOiJyZXYtNDIiLCJkaWdlc3QiOiJkaWdlc3QtMTIzIn0sInN1bW1hcnkiOnsidG90YWwiOjEsImJsb2NrZWQiOjEsIndhcm5lZCI6MCwiaWdub3JlZCI6MCwicXVpZXRlZCI6MH0sInZlcmRpY3RzIjpbeyJmaW5kaW5nSWQiOiJmaW5kaW5nLTEiLCJzdGF0dXMiOiJCbG9ja2VkIiwic2NvcmUiOjQ3LjUsInNvdXJjZVRydXN0IjoiTlZEIiwicmVhY2hhYmlsaXR5IjoicnVudGltZSJ9XSwiaXNzdWVzIjpbXX0=",
|
||||
"signatures": [
|
||||
{
|
||||
"keyId": "test-key",
|
||||
"algorithm": "hs256",
|
||||
"signature": "signature-value"
|
||||
}
|
||||
]
|
||||
},
|
||||
"report": {
|
||||
"reportId": "report-abc",
|
||||
"generatedAt": "2025-10-19T12:34:56Z",
|
||||
"imageDigest": "sha256:feedface",
|
||||
"policy": {
|
||||
"digest": "digest-123",
|
||||
"revisionId": "rev-42"
|
||||
},
|
||||
"summary": {
|
||||
"total": 1,
|
||||
"blocked": 1,
|
||||
"warned": 0,
|
||||
"ignored": 0,
|
||||
"quieted": 0
|
||||
},
|
||||
"verdict": "blocked",
|
||||
"verdicts": [
|
||||
{
|
||||
"findingId": "finding-1",
|
||||
"status": "Blocked",
|
||||
"score": 47.5,
|
||||
"sourceTrust": "NVD",
|
||||
"reachability": "runtime"
|
||||
}
|
||||
],
|
||||
"issues": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
{
|
||||
"eventId": "4d33c19c-1c8a-44d1-9954-1d5e98b2af71",
|
||||
"kind": "scheduler.graph.job.completed",
|
||||
"tenant": "tenant-alpha",
|
||||
"ts": "2025-10-26T12:00:45Z",
|
||||
"payload": {
|
||||
"jobType": "build",
|
||||
"status": "completed",
|
||||
"occurredAt": "2025-10-26T12:00:45Z",
|
||||
"job": {
|
||||
"schemaVersion": "scheduler.graph-build-job@1",
|
||||
"id": "gbj_20251026a",
|
||||
"tenantId": "tenant-alpha",
|
||||
"sbomId": "sbom_20251026",
|
||||
"sbomVersionId": "sbom_ver_20251026",
|
||||
"sbomDigest": "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
||||
"graphSnapshotId": "graph_snap_20251026",
|
||||
"status": "completed",
|
||||
"trigger": "sbom-version",
|
||||
"attempts": 1,
|
||||
"cartographerJobId": "carto_job_42",
|
||||
"correlationId": "evt_svc_987",
|
||||
"createdAt": "2025-10-26T12:00:00+00:00",
|
||||
"startedAt": "2025-10-26T12:00:05+00:00",
|
||||
"completedAt": "2025-10-26T12:00:45+00:00",
|
||||
"metadata": {
|
||||
"sbomEventId": "sbom_evt_20251026"
|
||||
}
|
||||
},
|
||||
"resultUri": "oras://cartographer/offline/tenant-alpha/graph_snap_20251026"
|
||||
},
|
||||
"attributes": {
|
||||
"cartographerCluster": "offline-kit",
|
||||
"plannerShard": "graph-builders-01"
|
||||
}
|
||||
}
|
||||
{
|
||||
"eventId": "4d33c19c-1c8a-44d1-9954-1d5e98b2af71",
|
||||
"kind": "scheduler.graph.job.completed",
|
||||
"tenant": "tenant-alpha",
|
||||
"ts": "2025-10-26T12:00:45Z",
|
||||
"payload": {
|
||||
"jobType": "build",
|
||||
"status": "completed",
|
||||
"occurredAt": "2025-10-26T12:00:45Z",
|
||||
"job": {
|
||||
"schemaVersion": "scheduler.graph-build-job@1",
|
||||
"id": "gbj_20251026a",
|
||||
"tenantId": "tenant-alpha",
|
||||
"sbomId": "sbom_20251026",
|
||||
"sbomVersionId": "sbom_ver_20251026",
|
||||
"sbomDigest": "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
||||
"graphSnapshotId": "graph_snap_20251026",
|
||||
"status": "completed",
|
||||
"trigger": "sbom-version",
|
||||
"attempts": 1,
|
||||
"cartographerJobId": "carto_job_42",
|
||||
"correlationId": "evt_svc_987",
|
||||
"createdAt": "2025-10-26T12:00:00+00:00",
|
||||
"startedAt": "2025-10-26T12:00:05+00:00",
|
||||
"completedAt": "2025-10-26T12:00:45+00:00",
|
||||
"metadata": {
|
||||
"sbomEventId": "sbom_evt_20251026"
|
||||
}
|
||||
},
|
||||
"resultUri": "oras://cartographer/offline/tenant-alpha/graph_snap_20251026"
|
||||
},
|
||||
"attributes": {
|
||||
"cartographerCluster": "offline-kit",
|
||||
"plannerShard": "graph-builders-01"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,164 +1,164 @@
|
||||
{
|
||||
"$id": "https://stella-ops.org/schemas/events/scanner.event.report.ready@1.json",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "Scanner orchestrator event – report ready (v1)",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"eventId",
|
||||
"kind",
|
||||
"version",
|
||||
"tenant",
|
||||
"occurredAt",
|
||||
"source",
|
||||
"idempotencyKey",
|
||||
"payload"
|
||||
],
|
||||
"properties": {
|
||||
"eventId": {
|
||||
"type": "string",
|
||||
"format": "uuid",
|
||||
"description": "Globally unique identifier for this occurrence."
|
||||
},
|
||||
"kind": {
|
||||
"const": "scanner.event.report.ready",
|
||||
"description": "Event kind identifier consumed by orchestrator subscribers."
|
||||
},
|
||||
"version": {
|
||||
"const": 1,
|
||||
"description": "Schema version for orchestrator envelopes."
|
||||
},
|
||||
"tenant": {
|
||||
"type": "string",
|
||||
"description": "Tenant that owns the scan/report."
|
||||
},
|
||||
"occurredAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Timestamp (UTC) when the report transitioned to ready."
|
||||
},
|
||||
"recordedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Timestamp (UTC) when the event was persisted. Optional."
|
||||
},
|
||||
"source": {
|
||||
"type": "string",
|
||||
"description": "Producer identifier, e.g. `scanner.webservice`."
|
||||
},
|
||||
"idempotencyKey": {
|
||||
"type": "string",
|
||||
"minLength": 8,
|
||||
"description": "Deterministic key used to deduplicate events downstream."
|
||||
},
|
||||
"correlationId": {
|
||||
"type": "string",
|
||||
"description": "Correlation identifier that ties this event to a request or workflow."
|
||||
},
|
||||
"traceId": {
|
||||
"type": "string",
|
||||
"description": "W3C trace ID (32 hex chars) for distributed tracing."
|
||||
},
|
||||
"spanId": {
|
||||
"type": "string",
|
||||
"description": "Optional span identifier associated with traceId."
|
||||
},
|
||||
"scope": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["repo", "digest"],
|
||||
"properties": {
|
||||
"namespace": {"type": "string"},
|
||||
"repo": {"type": "string"},
|
||||
"digest": {"type": "string"},
|
||||
"component": {"type": "string"},
|
||||
"image": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"attributes": {
|
||||
"type": "object",
|
||||
"description": "String attributes for downstream correlation (policy revision, scan id, etc.).",
|
||||
"additionalProperties": {"type": "string"}
|
||||
},
|
||||
"payload": {
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"required": ["reportId", "verdict", "summary", "links", "report"],
|
||||
"properties": {
|
||||
"reportId": {"type": "string"},
|
||||
"scanId": {"type": "string"},
|
||||
"imageDigest": {"type": "string"},
|
||||
"generatedAt": {"type": "string", "format": "date-time"},
|
||||
"verdict": {"enum": ["pass", "warn", "fail"]},
|
||||
"summary": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["total", "blocked", "warned", "ignored", "quieted"],
|
||||
"properties": {
|
||||
"total": {"type": "integer", "minimum": 0},
|
||||
"blocked": {"type": "integer", "minimum": 0},
|
||||
"warned": {"type": "integer", "minimum": 0},
|
||||
"ignored": {"type": "integer", "minimum": 0},
|
||||
"quieted": {"type": "integer", "minimum": 0}
|
||||
}
|
||||
},
|
||||
"delta": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"newCritical": {"type": "integer", "minimum": 0},
|
||||
"newHigh": {"type": "integer", "minimum": 0},
|
||||
"kev": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"}
|
||||
}
|
||||
}
|
||||
},
|
||||
"quietedFindingCount": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"policy": {
|
||||
"type": "object",
|
||||
"description": "Policy revision metadata surfaced alongside the report."
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"ui": {"type": "string", "format": "uri"},
|
||||
"report": {"type": "string", "format": "uri"},
|
||||
"policy": {"type": "string", "format": "uri"},
|
||||
"attestation": {"type": "string", "format": "uri"}
|
||||
}
|
||||
},
|
||||
"dsse": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["payloadType", "payload", "signatures"],
|
||||
"properties": {
|
||||
"payloadType": {"type": "string"},
|
||||
"payload": {"type": "string"},
|
||||
"signatures": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["keyId", "algorithm", "signature"],
|
||||
"properties": {
|
||||
"keyId": {"type": "string"},
|
||||
"algorithm": {"type": "string"},
|
||||
"signature": {"type": "string"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"report": {
|
||||
"type": "object",
|
||||
"description": "Canonical scanner report document that aligns with the DSSE payload."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
"$id": "https://stella-ops.org/schemas/events/scanner.event.report.ready@1.json",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "Scanner orchestrator event – report ready (v1)",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"eventId",
|
||||
"kind",
|
||||
"version",
|
||||
"tenant",
|
||||
"occurredAt",
|
||||
"source",
|
||||
"idempotencyKey",
|
||||
"payload"
|
||||
],
|
||||
"properties": {
|
||||
"eventId": {
|
||||
"type": "string",
|
||||
"format": "uuid",
|
||||
"description": "Globally unique identifier for this occurrence."
|
||||
},
|
||||
"kind": {
|
||||
"const": "scanner.event.report.ready",
|
||||
"description": "Event kind identifier consumed by orchestrator subscribers."
|
||||
},
|
||||
"version": {
|
||||
"const": 1,
|
||||
"description": "Schema version for orchestrator envelopes."
|
||||
},
|
||||
"tenant": {
|
||||
"type": "string",
|
||||
"description": "Tenant that owns the scan/report."
|
||||
},
|
||||
"occurredAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Timestamp (UTC) when the report transitioned to ready."
|
||||
},
|
||||
"recordedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Timestamp (UTC) when the event was persisted. Optional."
|
||||
},
|
||||
"source": {
|
||||
"type": "string",
|
||||
"description": "Producer identifier, e.g. `scanner.webservice`."
|
||||
},
|
||||
"idempotencyKey": {
|
||||
"type": "string",
|
||||
"minLength": 8,
|
||||
"description": "Deterministic key used to deduplicate events downstream."
|
||||
},
|
||||
"correlationId": {
|
||||
"type": "string",
|
||||
"description": "Correlation identifier that ties this event to a request or workflow."
|
||||
},
|
||||
"traceId": {
|
||||
"type": "string",
|
||||
"description": "W3C trace ID (32 hex chars) for distributed tracing."
|
||||
},
|
||||
"spanId": {
|
||||
"type": "string",
|
||||
"description": "Optional span identifier associated with traceId."
|
||||
},
|
||||
"scope": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["repo", "digest"],
|
||||
"properties": {
|
||||
"namespace": {"type": "string"},
|
||||
"repo": {"type": "string"},
|
||||
"digest": {"type": "string"},
|
||||
"component": {"type": "string"},
|
||||
"image": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"attributes": {
|
||||
"type": "object",
|
||||
"description": "String attributes for downstream correlation (policy revision, scan id, etc.).",
|
||||
"additionalProperties": {"type": "string"}
|
||||
},
|
||||
"payload": {
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"required": ["reportId", "verdict", "summary", "links", "report"],
|
||||
"properties": {
|
||||
"reportId": {"type": "string"},
|
||||
"scanId": {"type": "string"},
|
||||
"imageDigest": {"type": "string"},
|
||||
"generatedAt": {"type": "string", "format": "date-time"},
|
||||
"verdict": {"enum": ["pass", "warn", "fail"]},
|
||||
"summary": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["total", "blocked", "warned", "ignored", "quieted"],
|
||||
"properties": {
|
||||
"total": {"type": "integer", "minimum": 0},
|
||||
"blocked": {"type": "integer", "minimum": 0},
|
||||
"warned": {"type": "integer", "minimum": 0},
|
||||
"ignored": {"type": "integer", "minimum": 0},
|
||||
"quieted": {"type": "integer", "minimum": 0}
|
||||
}
|
||||
},
|
||||
"delta": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"newCritical": {"type": "integer", "minimum": 0},
|
||||
"newHigh": {"type": "integer", "minimum": 0},
|
||||
"kev": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"}
|
||||
}
|
||||
}
|
||||
},
|
||||
"quietedFindingCount": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"policy": {
|
||||
"type": "object",
|
||||
"description": "Policy revision metadata surfaced alongside the report."
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"ui": {"type": "string", "format": "uri"},
|
||||
"report": {"type": "string", "format": "uri"},
|
||||
"policy": {"type": "string", "format": "uri"},
|
||||
"attestation": {"type": "string", "format": "uri"}
|
||||
}
|
||||
},
|
||||
"dsse": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["payloadType", "payload", "signatures"],
|
||||
"properties": {
|
||||
"payloadType": {"type": "string"},
|
||||
"payload": {"type": "string"},
|
||||
"signatures": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["keyId", "algorithm", "signature"],
|
||||
"properties": {
|
||||
"keyId": {"type": "string"},
|
||||
"algorithm": {"type": "string"},
|
||||
"signature": {"type": "string"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"report": {
|
||||
"type": "object",
|
||||
"description": "Canonical scanner report document that aligns with the DSSE payload."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,174 +1,174 @@
|
||||
{
|
||||
"$id": "https://stella-ops.org/schemas/events/scanner.event.scan.completed@1.json",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "Scanner orchestrator event – scan completed (v1)",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"eventId",
|
||||
"kind",
|
||||
"version",
|
||||
"tenant",
|
||||
"occurredAt",
|
||||
"source",
|
||||
"idempotencyKey",
|
||||
"payload"
|
||||
],
|
||||
"properties": {
|
||||
"eventId": {
|
||||
"type": "string",
|
||||
"format": "uuid",
|
||||
"description": "Globally unique identifier for this occurrence."
|
||||
},
|
||||
"kind": {
|
||||
"const": "scanner.event.scan.completed",
|
||||
"description": "Event kind identifier consumed by orchestrator subscribers."
|
||||
},
|
||||
"version": {
|
||||
"const": 1,
|
||||
"description": "Schema version for orchestrator envelopes."
|
||||
},
|
||||
"tenant": {
|
||||
"type": "string",
|
||||
"description": "Tenant that owns the scan."
|
||||
},
|
||||
"occurredAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Timestamp (UTC) when the scan completed."
|
||||
},
|
||||
"recordedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Timestamp (UTC) when the event was persisted. Optional."
|
||||
},
|
||||
"source": {
|
||||
"type": "string",
|
||||
"description": "Producer identifier, e.g. `scanner.webservice`."
|
||||
},
|
||||
"idempotencyKey": {
|
||||
"type": "string",
|
||||
"minLength": 8,
|
||||
"description": "Deterministic key used to deduplicate events downstream."
|
||||
},
|
||||
"correlationId": {
|
||||
"type": "string",
|
||||
"description": "Correlation identifier tying this event to a request or workflow."
|
||||
},
|
||||
"traceId": {
|
||||
"type": "string",
|
||||
"description": "W3C trace ID (32 hex chars) for distributed tracing."
|
||||
},
|
||||
"spanId": {
|
||||
"type": "string",
|
||||
"description": "Optional span identifier associated with traceId."
|
||||
},
|
||||
"scope": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["repo", "digest"],
|
||||
"properties": {
|
||||
"namespace": {"type": "string"},
|
||||
"repo": {"type": "string"},
|
||||
"digest": {"type": "string"},
|
||||
"component": {"type": "string"},
|
||||
"image": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"attributes": {
|
||||
"type": "object",
|
||||
"description": "String attributes for downstream correlation (policy revision, scan id, etc.).",
|
||||
"additionalProperties": {"type": "string"}
|
||||
},
|
||||
"payload": {
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"required": ["reportId", "scanId", "imageDigest", "verdict", "summary", "report"],
|
||||
"properties": {
|
||||
"reportId": {"type": "string"},
|
||||
"scanId": {"type": "string"},
|
||||
"imageDigest": {"type": "string"},
|
||||
"verdict": {"enum": ["pass", "warn", "fail"]},
|
||||
"summary": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["total", "blocked", "warned", "ignored", "quieted"],
|
||||
"properties": {
|
||||
"total": {"type": "integer", "minimum": 0},
|
||||
"blocked": {"type": "integer", "minimum": 0},
|
||||
"warned": {"type": "integer", "minimum": 0},
|
||||
"ignored": {"type": "integer", "minimum": 0},
|
||||
"quieted": {"type": "integer", "minimum": 0}
|
||||
}
|
||||
},
|
||||
"delta": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"newCritical": {"type": "integer", "minimum": 0},
|
||||
"newHigh": {"type": "integer", "minimum": 0},
|
||||
"kev": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"}
|
||||
}
|
||||
}
|
||||
},
|
||||
"policy": {
|
||||
"type": "object",
|
||||
"description": "Policy revision metadata surfaced alongside the report."
|
||||
},
|
||||
"findings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["id"],
|
||||
"properties": {
|
||||
"id": {"type": "string"},
|
||||
"severity": {"type": "string"},
|
||||
"cve": {"type": "string"},
|
||||
"purl": {"type": "string"},
|
||||
"reachability": {"type": "string"}
|
||||
}
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"ui": {"type": "string", "format": "uri"},
|
||||
"report": {"type": "string", "format": "uri"},
|
||||
"policy": {"type": "string", "format": "uri"},
|
||||
"attestation": {"type": "string", "format": "uri"}
|
||||
}
|
||||
},
|
||||
"dsse": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["payloadType", "payload", "signatures"],
|
||||
"properties": {
|
||||
"payloadType": {"type": "string"},
|
||||
"payload": {"type": "string"},
|
||||
"signatures": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["keyId", "algorithm", "signature"],
|
||||
"properties": {
|
||||
"keyId": {"type": "string"},
|
||||
"algorithm": {"type": "string"},
|
||||
"signature": {"type": "string"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"report": {
|
||||
"type": "object",
|
||||
"description": "Canonical scanner report document that aligns with the DSSE payload."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
"$id": "https://stella-ops.org/schemas/events/scanner.event.scan.completed@1.json",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "Scanner orchestrator event – scan completed (v1)",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"eventId",
|
||||
"kind",
|
||||
"version",
|
||||
"tenant",
|
||||
"occurredAt",
|
||||
"source",
|
||||
"idempotencyKey",
|
||||
"payload"
|
||||
],
|
||||
"properties": {
|
||||
"eventId": {
|
||||
"type": "string",
|
||||
"format": "uuid",
|
||||
"description": "Globally unique identifier for this occurrence."
|
||||
},
|
||||
"kind": {
|
||||
"const": "scanner.event.scan.completed",
|
||||
"description": "Event kind identifier consumed by orchestrator subscribers."
|
||||
},
|
||||
"version": {
|
||||
"const": 1,
|
||||
"description": "Schema version for orchestrator envelopes."
|
||||
},
|
||||
"tenant": {
|
||||
"type": "string",
|
||||
"description": "Tenant that owns the scan."
|
||||
},
|
||||
"occurredAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Timestamp (UTC) when the scan completed."
|
||||
},
|
||||
"recordedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Timestamp (UTC) when the event was persisted. Optional."
|
||||
},
|
||||
"source": {
|
||||
"type": "string",
|
||||
"description": "Producer identifier, e.g. `scanner.webservice`."
|
||||
},
|
||||
"idempotencyKey": {
|
||||
"type": "string",
|
||||
"minLength": 8,
|
||||
"description": "Deterministic key used to deduplicate events downstream."
|
||||
},
|
||||
"correlationId": {
|
||||
"type": "string",
|
||||
"description": "Correlation identifier tying this event to a request or workflow."
|
||||
},
|
||||
"traceId": {
|
||||
"type": "string",
|
||||
"description": "W3C trace ID (32 hex chars) for distributed tracing."
|
||||
},
|
||||
"spanId": {
|
||||
"type": "string",
|
||||
"description": "Optional span identifier associated with traceId."
|
||||
},
|
||||
"scope": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["repo", "digest"],
|
||||
"properties": {
|
||||
"namespace": {"type": "string"},
|
||||
"repo": {"type": "string"},
|
||||
"digest": {"type": "string"},
|
||||
"component": {"type": "string"},
|
||||
"image": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"attributes": {
|
||||
"type": "object",
|
||||
"description": "String attributes for downstream correlation (policy revision, scan id, etc.).",
|
||||
"additionalProperties": {"type": "string"}
|
||||
},
|
||||
"payload": {
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"required": ["reportId", "scanId", "imageDigest", "verdict", "summary", "report"],
|
||||
"properties": {
|
||||
"reportId": {"type": "string"},
|
||||
"scanId": {"type": "string"},
|
||||
"imageDigest": {"type": "string"},
|
||||
"verdict": {"enum": ["pass", "warn", "fail"]},
|
||||
"summary": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["total", "blocked", "warned", "ignored", "quieted"],
|
||||
"properties": {
|
||||
"total": {"type": "integer", "minimum": 0},
|
||||
"blocked": {"type": "integer", "minimum": 0},
|
||||
"warned": {"type": "integer", "minimum": 0},
|
||||
"ignored": {"type": "integer", "minimum": 0},
|
||||
"quieted": {"type": "integer", "minimum": 0}
|
||||
}
|
||||
},
|
||||
"delta": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"newCritical": {"type": "integer", "minimum": 0},
|
||||
"newHigh": {"type": "integer", "minimum": 0},
|
||||
"kev": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"}
|
||||
}
|
||||
}
|
||||
},
|
||||
"policy": {
|
||||
"type": "object",
|
||||
"description": "Policy revision metadata surfaced alongside the report."
|
||||
},
|
||||
"findings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["id"],
|
||||
"properties": {
|
||||
"id": {"type": "string"},
|
||||
"severity": {"type": "string"},
|
||||
"cve": {"type": "string"},
|
||||
"purl": {"type": "string"},
|
||||
"reachability": {"type": "string"}
|
||||
}
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"ui": {"type": "string", "format": "uri"},
|
||||
"report": {"type": "string", "format": "uri"},
|
||||
"policy": {"type": "string", "format": "uri"},
|
||||
"attestation": {"type": "string", "format": "uri"}
|
||||
}
|
||||
},
|
||||
"dsse": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["payloadType", "payload", "signatures"],
|
||||
"properties": {
|
||||
"payloadType": {"type": "string"},
|
||||
"payload": {"type": "string"},
|
||||
"signatures": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["keyId", "algorithm", "signature"],
|
||||
"properties": {
|
||||
"keyId": {"type": "string"},
|
||||
"algorithm": {"type": "string"},
|
||||
"signature": {"type": "string"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"report": {
|
||||
"type": "object",
|
||||
"description": "Canonical scanner report document that aligns with the DSSE payload."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,196 +1,196 @@
|
||||
{
|
||||
"$id": "https://stella-ops.org/schemas/events/scheduler.graph.job.completed@1.json",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "Scheduler Graph Job Completed Event",
|
||||
"description": "Legacy scheduler event emitted when a graph build or overlay job reaches a terminal state. Consumers validate downstream caches and surface overlay freshness.",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["eventId", "kind", "tenant", "ts", "payload"],
|
||||
"properties": {
|
||||
"eventId": {
|
||||
"type": "string",
|
||||
"format": "uuid",
|
||||
"description": "Globally unique identifier per event."
|
||||
},
|
||||
"kind": {
|
||||
"const": "scheduler.graph.job.completed"
|
||||
},
|
||||
"tenant": {
|
||||
"type": "string",
|
||||
"description": "Tenant identifier scoped to the originating job."
|
||||
},
|
||||
"ts": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "UTC timestamp when the job reached a terminal state."
|
||||
},
|
||||
"payload": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["jobType", "job", "status", "occurredAt"],
|
||||
"properties": {
|
||||
"jobType": {
|
||||
"type": "string",
|
||||
"enum": ["build", "overlay"],
|
||||
"description": "Job flavour, matches the CLR type of the serialized job payload."
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": ["completed", "failed", "cancelled"],
|
||||
"description": "Terminal status recorded for the job."
|
||||
},
|
||||
"occurredAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "UTC timestamp of the terminal transition, mirrors job.CompletedAt."
|
||||
},
|
||||
"job": {
|
||||
"oneOf": [
|
||||
{"$ref": "#/definitions/graphBuildJob"},
|
||||
{"$ref": "#/definitions/graphOverlayJob"}
|
||||
],
|
||||
"description": "Canonical serialized representation of the finished job."
|
||||
},
|
||||
"resultUri": {
|
||||
"type": "string",
|
||||
"description": "Optional URI pointing to Cartographer snapshot or overlay bundle (if available)."
|
||||
}
|
||||
}
|
||||
},
|
||||
"attributes": {
|
||||
"type": "object",
|
||||
"description": "Optional correlation bag for downstream consumers.",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"graphBuildJob": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"schemaVersion",
|
||||
"id",
|
||||
"tenantId",
|
||||
"sbomId",
|
||||
"sbomVersionId",
|
||||
"sbomDigest",
|
||||
"status",
|
||||
"trigger",
|
||||
"attempts",
|
||||
"createdAt"
|
||||
],
|
||||
"properties": {
|
||||
"schemaVersion": {
|
||||
"const": "scheduler.graph-build-job@1"
|
||||
},
|
||||
"id": {"type": "string"},
|
||||
"tenantId": {"type": "string"},
|
||||
"sbomId": {"type": "string"},
|
||||
"sbomVersionId": {"type": "string"},
|
||||
"sbomDigest": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$"
|
||||
},
|
||||
"graphSnapshotId": {"type": "string"},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": ["pending", "queued", "running", "completed", "failed", "cancelled"]
|
||||
},
|
||||
"trigger": {
|
||||
"type": "string",
|
||||
"enum": ["sbom-version", "backfill", "manual"]
|
||||
},
|
||||
"attempts": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"cartographerJobId": {"type": "string"},
|
||||
"correlationId": {"type": "string"},
|
||||
"createdAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"startedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"completedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"error": {"type": "string"},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"additionalProperties": {"type": "string"}
|
||||
}
|
||||
}
|
||||
},
|
||||
"graphOverlayJob": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"schemaVersion",
|
||||
"id",
|
||||
"tenantId",
|
||||
"graphSnapshotId",
|
||||
"overlayKind",
|
||||
"overlayKey",
|
||||
"status",
|
||||
"trigger",
|
||||
"attempts",
|
||||
"createdAt"
|
||||
],
|
||||
"properties": {
|
||||
"schemaVersion": {
|
||||
"const": "scheduler.graph-overlay-job@1"
|
||||
},
|
||||
"id": {"type": "string"},
|
||||
"tenantId": {"type": "string"},
|
||||
"graphSnapshotId": {"type": "string"},
|
||||
"buildJobId": {"type": "string"},
|
||||
"overlayKind": {
|
||||
"type": "string",
|
||||
"enum": ["policy", "advisory", "vex"]
|
||||
},
|
||||
"overlayKey": {"type": "string"},
|
||||
"subjects": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"uniqueItems": true
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": ["pending", "queued", "running", "completed", "failed", "cancelled"]
|
||||
},
|
||||
"trigger": {
|
||||
"type": "string",
|
||||
"enum": ["policy", "advisory", "vex", "sbom-version", "manual"]
|
||||
},
|
||||
"attempts": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"correlationId": {"type": "string"},
|
||||
"createdAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"startedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"completedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"error": {"type": "string"},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"additionalProperties": {"type": "string"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
"$id": "https://stella-ops.org/schemas/events/scheduler.graph.job.completed@1.json",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "Scheduler Graph Job Completed Event",
|
||||
"description": "Legacy scheduler event emitted when a graph build or overlay job reaches a terminal state. Consumers validate downstream caches and surface overlay freshness.",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["eventId", "kind", "tenant", "ts", "payload"],
|
||||
"properties": {
|
||||
"eventId": {
|
||||
"type": "string",
|
||||
"format": "uuid",
|
||||
"description": "Globally unique identifier per event."
|
||||
},
|
||||
"kind": {
|
||||
"const": "scheduler.graph.job.completed"
|
||||
},
|
||||
"tenant": {
|
||||
"type": "string",
|
||||
"description": "Tenant identifier scoped to the originating job."
|
||||
},
|
||||
"ts": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "UTC timestamp when the job reached a terminal state."
|
||||
},
|
||||
"payload": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["jobType", "job", "status", "occurredAt"],
|
||||
"properties": {
|
||||
"jobType": {
|
||||
"type": "string",
|
||||
"enum": ["build", "overlay"],
|
||||
"description": "Job flavour, matches the CLR type of the serialized job payload."
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": ["completed", "failed", "cancelled"],
|
||||
"description": "Terminal status recorded for the job."
|
||||
},
|
||||
"occurredAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "UTC timestamp of the terminal transition, mirrors job.CompletedAt."
|
||||
},
|
||||
"job": {
|
||||
"oneOf": [
|
||||
{"$ref": "#/definitions/graphBuildJob"},
|
||||
{"$ref": "#/definitions/graphOverlayJob"}
|
||||
],
|
||||
"description": "Canonical serialized representation of the finished job."
|
||||
},
|
||||
"resultUri": {
|
||||
"type": "string",
|
||||
"description": "Optional URI pointing to Cartographer snapshot or overlay bundle (if available)."
|
||||
}
|
||||
}
|
||||
},
|
||||
"attributes": {
|
||||
"type": "object",
|
||||
"description": "Optional correlation bag for downstream consumers.",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"graphBuildJob": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"schemaVersion",
|
||||
"id",
|
||||
"tenantId",
|
||||
"sbomId",
|
||||
"sbomVersionId",
|
||||
"sbomDigest",
|
||||
"status",
|
||||
"trigger",
|
||||
"attempts",
|
||||
"createdAt"
|
||||
],
|
||||
"properties": {
|
||||
"schemaVersion": {
|
||||
"const": "scheduler.graph-build-job@1"
|
||||
},
|
||||
"id": {"type": "string"},
|
||||
"tenantId": {"type": "string"},
|
||||
"sbomId": {"type": "string"},
|
||||
"sbomVersionId": {"type": "string"},
|
||||
"sbomDigest": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$"
|
||||
},
|
||||
"graphSnapshotId": {"type": "string"},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": ["pending", "queued", "running", "completed", "failed", "cancelled"]
|
||||
},
|
||||
"trigger": {
|
||||
"type": "string",
|
||||
"enum": ["sbom-version", "backfill", "manual"]
|
||||
},
|
||||
"attempts": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"cartographerJobId": {"type": "string"},
|
||||
"correlationId": {"type": "string"},
|
||||
"createdAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"startedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"completedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"error": {"type": "string"},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"additionalProperties": {"type": "string"}
|
||||
}
|
||||
}
|
||||
},
|
||||
"graphOverlayJob": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"schemaVersion",
|
||||
"id",
|
||||
"tenantId",
|
||||
"graphSnapshotId",
|
||||
"overlayKind",
|
||||
"overlayKey",
|
||||
"status",
|
||||
"trigger",
|
||||
"attempts",
|
||||
"createdAt"
|
||||
],
|
||||
"properties": {
|
||||
"schemaVersion": {
|
||||
"const": "scheduler.graph-overlay-job@1"
|
||||
},
|
||||
"id": {"type": "string"},
|
||||
"tenantId": {"type": "string"},
|
||||
"graphSnapshotId": {"type": "string"},
|
||||
"buildJobId": {"type": "string"},
|
||||
"overlayKind": {
|
||||
"type": "string",
|
||||
"enum": ["policy", "advisory", "vex"]
|
||||
},
|
||||
"overlayKey": {"type": "string"},
|
||||
"subjects": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"uniqueItems": true
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": ["pending", "queued", "running", "completed", "failed", "cancelled"]
|
||||
},
|
||||
"trigger": {
|
||||
"type": "string",
|
||||
"enum": ["policy", "advisory", "vex", "sbom-version", "manual"]
|
||||
},
|
||||
"attempts": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"correlationId": {"type": "string"},
|
||||
"createdAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"startedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"completedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"error": {"type": "string"},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"additionalProperties": {"type": "string"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user