Restructure solution layout by module
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user