Files
git.stella-ops.org/docs/api/console/workspaces.md
StellaOps Bot 4042fc2184
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
release-manifest-verify / verify (push) Has been cancelled
Add unit tests for PackRunAttestation and SealedInstallEnforcer
- Implement comprehensive tests for PackRunAttestationService, covering attestation generation, verification, and event emission.
- Add tests for SealedInstallEnforcer to validate sealed install requirements and enforcement logic.
- Introduce a MonacoLoaderService stub for testing purposes to prevent Monaco workers/styles from loading during Karma runs.
2025-12-06 22:25:30 +02:00

352 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Console Workspaces API
_Tracking: CONSOLE-VULN-29-001, CONSOLE-VEX-30-001, DOCS-AIAI-31-004_
## 1. Goals & Scope
The console workspaces provide read-only aggregates for Advisory AI operators:
- `/console/vuln/*` surfaces tenant-scoped findings annotated with policy verdicts, VEX justifications, Scheduler reachability signals, and Advisory AI rationale.
- `/console/vex/*` streams the underlying VEX statements, conflicts, and justification summaries (with SSE support for live updates).
All endpoints MUST:
1. Remain deterministic offline (stable sort keys, ISO-8601 UTC timestamps, hashed assets).
2. Operate with Authority-issued DPoP or mTLS client credentials that include `console:read` and either `vuln:read` or `vex:read`.
3. Respect tenant isolation every request carries `X-StellaOps-Tenant`.
## 2. Shared Request/Response Conventions
| Requirement | Description |
| --- | --- |
| Headers | `Authorization: DPoP <token>`, `DPoP: <proof>`, `X-StellaOps-Tenant: <tenantId>`, `Accept: application/json` (or `text/event-stream` for SSE). |
| Pagination | Cursor-based via `pageToken`; defaults to 50 items, max 200. Cursors are opaque, base64url, signed. |
| Sorting | Findings sorted by `(severity desc, exploitScore desc, findingId asc)`. Statements sorted by `(lastUpdated desc, statementId asc)`. |
| Dates | RFC 3339 / ISO-8601 UTC (e.g., `2025-11-08T12:02:11Z`). |
| Determinism | All arrays must be pre-sorted; no server-generated uuids in responses. |
## 3. Vulnerability Workspace (`/console/vuln/*`)
### 3.1 `GET /console/vuln/findings`
Query parameters:
| Parameter | Type | Notes |
| --- | --- | --- |
| `pageToken` | string | Optional cursor from previous response. |
| `pageSize` | int | 1-200, default 50. |
| `severity` | string[] | Accepts `critical`, `high`, `medium`, `low`, `info`. |
| `product` | string[] | SBOM `purl` or image digest anchors. |
| `policyBadge` | string[] | `pass`, `warn`, `fail`, `waived`. |
| `vexState` | string[] | `not_affected`, `fixed`, `under_investigation`, etc. |
| `reachability` | string[] | `reachable`, `unreachable`, `unknown`. |
| `search` | string | Substring match on CVE/GHSA/KEV ID (case-insensitive). |
Response body:
```jsonc
{
"items": [
{
"findingId": "tenant-default:advisory-ai:sha256:5d1a",
"coordinates": {
"advisoryId": "CVE-2024-12345",
"package": "pkg:npm/jsonwebtoken@9.0.2",
"component": "jwt-auth-service",
"image": "registry.local/ops/auth:2025.10.0"
},
"summary": "jsonwebtoken <10.0.0 allows algorithm downgrade.",
"severity": "high",
"cvss": 8.1,
"kev": true,
"policyBadge": "fail",
"vex": {
"statementId": "vex:tenant-default:jwt-auth:5d1a",
"state": "under_investigation",
"justification": "Advisory AI flagged reachable path via Scheduler run 42."
},
"reachability": {
"status": "reachable",
"lastObserved": "2025-11-07T23:11:04Z",
"signalsVersion": "signals-2025.310.1"
},
"evidence": {
"sbomDigest": "sha256:6c81…",
"policyRunId": "policy-run::2025-11-07::ca9f",
"attestationId": "dsse://authority/attest/84a2"
},
"timestamps": {
"firstSeen": "2025-10-31T04:22:18Z",
"lastSeen": "2025-11-07T23:16:51Z"
}
}
],
"facets": {
"severity": [
{ "value": "critical", "count": 2 },
{ "value": "high", "count": 7 }
],
"policyBadge": [
{ "value": "fail", "count": 6 },
{ "value": "warn", "count": 3 },
{ "value": "waived", "count": 1 }
],
"reachability": [
{ "value": "reachable", "count": 5 },
{ "value": "unreachable", "count": 2 },
{ "value": "unknown", "count": 1 }
]
},
"nextPageToken": "eyJjdXJzb3IiOiJmZjg0NiJ9"
}
```
### 3.2 `GET /console/vuln/facets`
Returns the full facet catalog (counts by severity, product, policy badge, VEX state, reachability, KEV flag). Designed for sidebar filters without paging; identical parameter surface as `/findings`.
### 3.3 `GET /console/vuln/{findingId}`
Returns the full finding document, including evidence timeline, policy overlays, and export-ready metadata:
```jsonc
{
"findingId": "tenant-default:advisory-ai:sha256:5d1a",
"details": {
"description": "jsonwebtoken <10.0.0 allows algorithm downgrade.",
"references": [
"https://nvd.nist.gov/vuln/detail/CVE-2024-12345",
"https://github.com/auth0/node-jsonwebtoken/security/advisories/GHSA-45mw-4jw3-g2wg"
],
"exploitAvailability": "known_exploit"
},
"policyBadges": [
{
"policyId": "policy://tenant-default/runtime-hardening",
"verdict": "fail",
"explainUrl": "https://console.local/policy/runs/policy-run::2025-11-07::ca9f"
}
],
"vex": {
"statementId": "vex:tenant-default:jwt-auth:5d1a",
"state": "under_investigation",
"justification": "Runtime telemetry confirmed exploitation path.",
"impactStatement": "Token exchange service remains exposed until patch 2025.11.2.",
"remediations": [
{
"type": "patch",
"description": "Upgrade jwt-auth-service to 2025.11.2.",
"deadline": "2025-11-12T00:00:00Z"
}
]
},
"reachability": {
"status": "reachable",
"callPathSamples": [
"api-gateway -> jwt-auth-service -> jsonwebtoken.verify"
],
"lastUpdated": "2025-11-07T23:11:04Z"
},
"evidence": {
"sbom": {
"digest": "sha256:6c81…",
"componentPath": [
"/src/jwt-auth/package.json",
"/src/jwt-auth/node_modules/jsonwebtoken"
]
},
"attestations": [
{
"type": "scan-report",
"attestationId": "dsse://authority/attest/84a2",
"signer": "attestor@stella-ops.org",
"bundleDigest": "sha256:e2bb…"
}
]
},
"timestamps": {
"firstSeen": "2025-10-31T04:22:18Z",
"lastSeen": "2025-11-07T23:16:51Z",
"vexLastUpdated": "2025-11-07T23:10:09Z"
}
}
```
### 3.4 `POST /console/vuln/tickets`
```jsonc
POST /console/vuln/tickets
{
"tenant": "tenant-default",
"selection": [
"tenant-default:advisory-ai:sha256:5d1a",
"tenant-default:advisory-ai:sha256:9bf4"
],
"targetSystem": "servicenow",
"metadata": {
"assignmentGroup": "runtime-security",
"priority": "P1"
}
}
```
Response:
```jsonc
{
"ticketId": "console-ticket::tenant-default::2025-11-08::00018",
"payload": {
"version": "2025-11-01",
"tenant": "tenant-default",
"findings": [
{ "findingId": "tenant-default:advisory-ai:sha256:5d1a", "severity": "high" },
{ "findingId": "tenant-default:advisory-ai:sha256:9bf4", "severity": "critical" }
],
"policyBadge": "fail",
"vexSummary": "2 reachable findings pending patch.",
"attachments": [
{
"type": "json",
"name": "console-ticket-20251108.json",
"digest": "sha256:1fdd…",
"contentType": "application/json",
"expiresAt": "2025-11-15T00:00:00Z"
}
]
},
"auditEventId": "console.ticket.export::2025-11-08::00018"
}
```
Requests emit `console.ticket.export` audit events (tenant, user, selection counts, target system).
## 4. VEX Workspace (`/console/vex/*`)
### 4.1 `GET /console/vex/statements`
Parameters mirror `/console/vuln/findings` plus:
| Parameter | Type | Notes |
| --- | --- | --- |
| `advisoryId` | string[] | CVE/GHSA/OVAL identifiers. |
| `justification` | string[] | `exploit_observed`, `component_not_present`, etc. |
| `statementType` | string[] | `vex`, `openvex`, `custom`, `advisory_ai`. |
| `prefer` | string | `prefer=stream` enables chunked streaming (NDJSON). |
Response (paged JSON):
```jsonc
{
"items": [
{
"statementId": "vex:tenant-default:jwt-auth:5d1a",
"advisoryId": "CVE-2024-12345",
"product": "registry.local/ops/auth:2025.10.0",
"status": "under_investigation",
"justification": "exploit_observed",
"lastUpdated": "2025-11-07T23:10:09Z",
"source": {
"type": "advisory_ai",
"modelBuild": "aiai-console-2025-10-28",
"confidence": 0.74
},
"links": [
{
"rel": "finding",
"href": "/console/vuln/findings/tenant-default:advisory-ai:sha256:5d1a"
}
]
}
],
"nextPageToken": null
}
```
When `Accept: text/event-stream`, the endpoint emits events (see §4.3) instead of paged JSON.
### 4.2 `GET /console/vex/statements/{statementId}`
Returns the canonical statement plus provenance extracts. SSE clients can call this endpoint when they need full bodies after receiving a summary event.
### 4.3 `GET /console/vex/events` (SSE)
Streams live updates for VEX statements affecting the tenant:
- Event types: `statement.created`, `statement.updated`, `statement.deleted`, `statement.conflict`.
- Fields: `id`, `advisoryId`, `product`, `vexState`, `severityHint`, `policyBadge`, `conflictSummary`, `sequence`.
- Replay: Clients include `Last-Event-ID`; server resumes from sequence.
- Heartbeats every 15 seconds (`event: keepalive`, `data: {}`).
Example event payload:
```jsonc
event: statement.updated
data: {
"statementId": "vex:tenant-default:jwt-auth:5d1a",
"advisoryId": "CVE-2024-12345",
"product": "registry.local/ops/auth:2025.10.0",
"state": "fixed",
"justification": "solution_available",
"sequence": 4182,
"updatedAt": "2025-11-08T11:44:32Z"
}
```
## 5. Signals & Scheduler Integration
- Reachability data is materialized by Scheduler delta jobs (`SCHED-CONSOLE-23-001`). `/console/vuln/findings` should cache the most recent job ID and expose `signalsVersion`.
- VEX justification fields reference Excititor statement IDs; ensure the gateway checks Excititor availability and degrades gracefully (returns `state: unavailable` plus telemetry).
- Scheduler must publish `console.vuln.refresh` events whenever advisory/VEX deltas warrant workspace refresh; console SSE endpoint may piggyback on the same Redis/NATS channel.
## 6. Determinism & Offline Notes
1. All responses are compressible JSON; no CDN fonts/assets referenced.
2. SSE endpoints must tolerate sealed mode by operating on loopback addresses only.
3. `authority-sealed-ci.json` (see DEVOPS-AIRGAP-57-002) is the evidence Authority consumes before enabling these APIs for sealed tenants; configure `airGap.sealedMode` and set `requiresAirgapSealConfirmation: true` on the Console client so `/token` refuses requests until the sealed harness uploads a fresh, passing artefact. Console responses echo `sealed: true/false` flags for UI badges once Authority has confirmed the evidence.
## 7. Sample Payloads for Docs
- `docs/api/console/samples/vuln-findings-sample.json` exported via `scripts/generate-console-samples.ts` (placeholder script to be added when backend lands).
- `docs/api/console/samples/vex-statement-sse.ndjson` contains 5 chronological SSE events for screenshot reproduction.
> Until backend implementations ship, use the examples above to unblock DOCS-AIAI-31-004; replace them with live captures once the gateway endpoints are available in staging.
## Exports (draft contract)
Routes
- `POST /console/exports` — start an evidence bundle export job.
- `GET /console/exports/{exportId}` — fetch job status and download locations.
- `GET /console/exports/{exportId}/events` — SSE stream of job progress (optional).
Headers
- `Authorization: Bearer <token>`
- `X-StellaOps-Tenant: <tenantId>`
- `Idempotency-Key: <uuid>` (recommended for POST)
- `Accept: application/json` (status) or `text/event-stream` (events)
Request body (POST /console/exports)
- `scope`: `{ tenantId, projectId? }`
- `sources`: array of `{ type: "advisory"|"vex"|"policy"|"scan", ids: string[] }`
- `formats`: array of `"json"|"csv"|"ndjson"|"pdf"`
- `attestations`: `{ include: boolean, sigstoreBundle?: boolean }`
- `notify`: `{ webhooks?: string[], email?: string[] }`
- `priority`: `"low"|"normal"|"high"`
Responses
- `202 Accepted` with `exportId`, `status: queued|running|succeeded|failed|expired`, `estimateSeconds`, `retryAfter`.
- Status payload includes presigned download URLs, checksum manifest, and error list when failed.
- SSE events emit `started`, `progress` (percent, item counts), `asset_ready` (uri, sha256), `completed`, `failed` (code, message).
Proposed limits
- Max request body 256 KiB; max sources 50; max outputs 1000 assets/export.
- Default job timeout 30 minutes; idle SSE timeout 60s; backoff header `Retry-After`.
Samples (draft)
- Request: `docs/api/console/samples/console-export-request.json`
- Status: `docs/api/console/samples/console-export-status.json`
- Manifest: `docs/api/console/samples/console-export-manifest.json`
- Events: `docs/api/console/samples/console-export-events.ndjson`
Open items (needs owner sign-off)
- Final schema (fields, limits, error codes), checksum manifest format, attestation options.
- Caching/tie-break rules for downstream `/console/search` and `/console/downloads`.