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

13 KiB
Raw Blame History

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:

{
  "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:

{
  "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

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:

{
  "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):

{
  "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:

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.