Files
git.stella-ops.org/docs/api/graph.md
StellaOps Bot 4831c7fcb0
Some checks failed
api-governance / spectral-lint (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
oas-ci / oas-validate (push) Has been cancelled
up
2025-11-26 09:28:16 +02:00

3.0 KiB

Graph API

Status: Draft (2025-11-26) — aligns with Sprint 0207 Graph API implementation (in-memory seed; RBAC + budgets enforced).

Base URL: <gateway>/api/graph (examples use relative paths).

Common headers

  • X-Stella-Tenant (required)
  • Authorization: Bearer <token> (required)
  • X-Stella-Scopes: space/comma/semicolon separated scopes
    • /graph/search: graph:read or graph:query
    • /graph/query|paths|diff: graph:query
    • /graph/export: graph:export Content-Type for requests: application/json Streaming responses: application/x-ndjson

POST /graph/search

Returns NDJSON stream of tiles (node, optional cursor).

Body:

{
  "kinds": ["component", "artifact"],
  "query": "pkg:npm/",
  "filters": { "ecosystem": "npm" },
  "limit": 50,
  "cursor": "opaque"
}

Errors:

  • 400 GRAPH_VALIDATION_FAILED (missing kinds/query/filters)
  • 401 missing auth; 403 missing scopes

POST /graph/query

Streams nodes, edges (optional), stats, cursor with cost metadata.

Body:

{
  "kinds": ["component"],
  "query": "widget",
  "filters": { "tenant": "acme" },
  "includeEdges": true,
  "includeStats": true,
  "includeOverlays": true,
  "limit": 100,
  "cursor": "opaque",
  "budget": { "tiles": 6000, "nodes": 5000, "edges": 10000 }
}

Error tile if edge budget exceeded: { "type":"error","data":{"error":"GRAPH_BUDGET_EXCEEDED",...}}

POST /graph/paths

Finds paths up to depth 6 between sources/targets.

Body:

{
  "sources": ["gn:acme:component:one"],
  "targets": ["gn:acme:component:two"],
  "kinds": ["depends_on"],
  "maxDepth": 4,
  "includeOverlays": false,
  "budget": { "tiles": 2000, "nodes": 1500, "edges": 3000 }
}

Response: NDJSON tiles (node, edge, stats, cursor).

POST /graph/diff

Diff two snapshots.

Body:

{
  "snapshotA": "snapA",
  "snapshotB": "snapB",
  "includeEdges": true,
  "includeStats": true,
  "budget": { "tiles": 2000 }
}

Response tiles: node/edge with change types, stats, optional cursor.

POST /graph/export

Kicks off an in-memory export job and returns manifest.

Body:

{
  "format": "ndjson",       // ndjson|csv|graphml|png|svg
  "includeEdges": true,
  "snapshotId": "snapA",    // optional
  "kinds": ["component"],   // optional
  "query": "pkg:",          // optional
  "filters": { "ecosystem": "npm" }
}

Response:

{
  "jobId": "job-123",
  "status": "completed",
  "format": "ndjson",
  "sha256": "...",
  "size": 1234,
  "downloadUrl": "/graph/export/job-123",
  "completedAt": "2025-11-26T00:00:00Z"
}

Download: GET /graph/export/{jobId} (returns file, headers include X-Content-SHA256).

Health

GET /healthz → 200 when service is ready; no auth/scopes required.

Error envelope

{ "error": "GRAPH_VALIDATION_FAILED", "message": "details", "requestId": "optional" }

Notes

  • All timestamps UTC ISO-8601.
  • Ordering is deterministic; cursors are opaque base64 offsets.
  • Overlays use policy.overlay.v1 and openvex.v1 payloads. Budgeted tiles reserve room for cursors when hasMore is true.