# SCHED-WEB-21-001 — Graph Job APIs > Status: 2025-10-26 — **Complete** (developer preview) Minimal API endpoints for Cartographer orchestration live under `/graphs`. Authentication now relies on Authority-issued bearer tokens carrying `graph:*` scopes. For development scenarios you can disable `Scheduler:Authority:Enabled` and continue using legacy headers: - `X-Tenant-Id`: tenant identifier (matches Scheduler Models `tenantId`). - `X-Scopes`: space-delimited scopes. `graph:write` is required for write operations, `graph:read` for queries. Example configuration (`appsettings.json` or environment overrides): ```jsonc { "Scheduler": { "Authority": { "Enabled": true, "Issuer": "https://authority.stella-ops.local", "Audiences": [ "api://scheduler" ], "RequiredScopes": [ "graph:read", "graph:write" ] }, "Events": { "GraphJobs": { "Enabled": true } }, "Cartographer": { "Webhook": { "Enabled": true, "Endpoint": "https://cartographer.stella-ops.local/hooks/graph/completed", "ApiKeyHeader": "X-StellaOps-Webhook-Key", "ApiKey": "change-me", "TimeoutSeconds": 10 } } } } ``` ## Endpoints ### `POST /graphs/build` Creates a `GraphBuildJob` in `pending` state. Request body: ```jsonc { "sbomId": "sbom_alpha", "sbomVersionId": "sbom_alpha_v1", "sbomDigest": "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", "trigger": "sbom-version", "metadata": { "sbomEventId": "sbom_evt_20251026" } } ``` Response: `201 Created` ```jsonc { "id": "gbj_018dc2f5902147e2b7f2ea05f5de1f3f", "tenantId": "tenant-alpha", "kind": "build", "status": "pending", "payload": { "schemaVersion": "scheduler.graph-build-job@1", "id": "gbj_018dc2f5902147e2b7f2ea05f5de1f3f", "tenantId": "tenant-alpha", "sbomId": "sbom_alpha", "sbomVersionId": "sbom_alpha_v1", "sbomDigest": "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", "status": "pending", "trigger": "sbom-version", "createdAt": "2025-10-26T12:00:00Z", "metadata": { "sbomeventid": "sbom_evt_20251026" } } } ``` ### `POST /graphs/overlays` Creates a `GraphOverlayJob` in `pending` state. Include optional `buildJobId` and `subjects` filters. ### `POST /graphs/hooks/completed` Webhook invoked by Scheduler Worker once Cartographer finishes a build/overlay job. Requires `graph:write`. ```jsonc { "jobId": "goj_018dc2f5929b4f5c88ad1e43d0ab3b90", "jobType": "Overlay", "status": "Completed", // Completed | Failed | Cancelled "occurredAt": "2025-10-26T12:02:45Z", "correlationId": "corr-123", "resultUri": "oras://cartographer/offline/tenant-alpha/graph_snap_20251026" } ``` The endpoint advances the job through `running → terminal` transitions via `GraphJobStateMachine`, captures the latest correlation identifier, and stores the optional `resultUri` in metadata for downstream exports. ### `GET /graphs/overlays/lag` Returns per-tenant overlay lag metrics (counts, min/max/average lag seconds, and last five completions with correlation IDs + result URIs). Requires `graph:read`. ### `GET /graphs/jobs` Returns a combined `GraphJobCollection`. Query parameters: | Parameter | Description | |-----------|-------------| | `type` | Optional filter (`build` or `overlay`). | | `status` | Optional filter using `GraphJobStatus`. | | `limit` | Maximum number of results (default 50, max 200). | Response example: ```jsonc { "jobs": [ { "id": "gbj_018dc2f5902147e2b7f2ea05f5de1f3f", "tenantId": "tenant-alpha", "kind": "build", "status": "pending", "payload": { /* graph build job */ } } ] } ``` ## Integration tests `StellaOps.Scheduler.WebService.Tests/GraphJobEndpointTests.cs` covers scope enforcement and the build-list happy path using the in-memory store. Future work should add overlay coverage once Cartographer adapters are available. ## Known gaps / TODO - Persist jobs to Scheduler storage and publish `scheduler.graph.job.completed@1` events + outbound webhook to Cartographer (see new `SCHED-WEB-21-004`). - Extend `GET /graphs/jobs` with pagination cursors shared with Cartographer/Console.