10 KiB
		
	
	
	
	
	
	
	
			
		
		
	
	Policy Engine REST API
Audience: Backend integrators, platform operators, and CI engineers invoking Policy Engine services programmatically.
Base URL:/api/policy/*(internal gateway route) – requires OAuth 2.0 bearer token issued by Authority with scopes listed below.
This document is the canonical reference for the Policy Engine REST surface described in Epic 2 (Policy Engine v2). Use it alongside the DSL, Lifecycle, and Runs guides for end-to-end implementations.
1 · Authentication & Headers
- Auth: Bearer tokens (Authorization: Bearer <token>) with the following scopes as applicable:
- policy:read,- policy:author,- policy:review,- policy:approve,- policy:operate,- policy:run,- policy:activate,- policy:archive,- policy:simulate,- policy:runs- findings:read(for effective findings APIs)
- effective:write(service identity only; not exposed to clients)
 
- Service identity: Authority marks the Policy Engine client with properties.serviceIdentity: policy-engine. Tokens missing this marker cannot obtaineffective:write.
- Tenant: Supply tenant context via X-Stella-Tenant. Tokens without multi-tenant claims default todefault.
- Idempotency: For mutating endpoints, include Idempotency-Key(UUID). Retries with same key return original result.
- Content type: All request/response bodies are application/json; charset=utf-8unless otherwise noted.
2 · Error Model
All errors use HTTP semantics plus a structured payload:
{
  "code": "ERR_POL_001",
  "message": "Policy syntax error",
  "details": [
    {"path": "rules[0].when", "error": "Unknown function foo()"}
  ],
  "traceId": "01HDV1C4E9Z4T5G6H7J8",
  "timestamp": "2025-10-26T14:07:03Z"
}
| Code | Meaning | Notes | 
|---|---|---|
| ERR_POL_001 | Policy syntax/compile error | Returned by compile,submit,simulate,runwhen DSL invalid. | 
| ERR_POL_002 | Policy not approved | Attempted to run or activate unapproved version. | 
| ERR_POL_003 | Missing inputs | Downstream service unavailable (Concelier/Excititor/SBOM). | 
| ERR_POL_004 | Determinism violation | Illegal API usage (wall-clock, RNG). Triggers incident mode. | 
| ERR_POL_005 | Unauthorized materialisation | Identity lacks effective:write. | 
| ERR_POL_006 | Run canceled or timed out | Includes cancellation metadata. | 
3 · Policy Management
3.1 Create Draft
POST /api/policy/policies
Scopes: policy:author
Request
{
  "policyId": "P-7",
  "name": "Default Org Policy",
  "description": "Baseline severity + VEX precedence",
  "dsl": {
    "syntax": "stella-dsl@1",
    "source": "policy \"Default Org Policy\" syntax \"stella-dsl@1\" { ... }"
  },
  "tags": ["baseline","vex"]
}
Response 201
{
  "policyId": "P-7",
  "version": 1,
  "status": "draft",
  "digest": "sha256:7e1d…",
  "createdBy": "user:ali",
  "createdAt": "2025-10-26T13:40:00Z"
}
3.2 List Policies
GET /api/policy/policies?status=approved&tenant=default&page=1&pageSize=25
Scopes: policy:read
Returns paginated list with X-Total-Count header.
3.3 Fetch Version
GET /api/policy/policies/{policyId}/versions/{version}
Scopes: policy:read
Returns full DSL, metadata, provenance, simulation artefact references.
3.4 Update Draft Version
PUT /api/policy/policies/{policyId}/versions/{version}
Scopes: policy:author
Body identical to create. Only permitted while status=draft.
4 · Lifecycle Transitions
4.1 Submit for Review
POST /api/policy/policies/{policyId}/versions/{version}:submit
Scopes: policy:author
Request
{
  "reviewers": ["user:kay","group:sec-reviewers"],
  "notes": "Simulated on golden SBOM set (diff attached)",
  "simulationArtifacts": [
    "blob://policy/P-7/v3/simulations/2025-10-26.json"
  ]
}
Response 202 – submission recorded. Location header points to review resource.
4.2 Review Feedback
POST /api/policy/policies/{policyId}/versions/{version}/reviews
Scopes: policy:review
Request
{
  "decision": "approve",     // approve | request_changes | comment
  "note": "Looks good, ensure incident playbook covers reachability data.",
  "blocking": false
}
4.3 Approve
POST /api/policy/policies/{policyId}/versions/{version}:approve
Scopes: policy:approve
Body requires approval note and confirmation of compliance gates:
{
  "note": "All simulations and determinism checks passed.",
  "acknowledgeDeterminism": true,
  "acknowledgeSimulation": true
}
4.4 Activate
POST /api/policy/policies/{policyId}/versions/{version}:activate
Scopes: policy:activate, policy:run
Marks version as active for tenant; triggers optional immediate full run ("runNow": true).
4.5 Archive
POST /api/policy/policies/{policyId}/versions/{version}:archive
Scopes: policy:archive
Request includes reason and optional incidentId.
5 · Compilation & Validation
5.1 Compile
POST /api/policy/policies/{policyId}/versions/{version}:compile
Scopes: policy:author
Response 200
{
  "digest": "sha256:7e1d…",
  "warnings": [],
  "rules": {
    "count": 24,
    "actions": {
      "block": 5,
      "warn": 4,
      "ignore": 3,
      "requireVex": 2
    }
  }
}
5.2 Lint / Simulate Quick Check
POST /api/policy/policies/{policyId}/lint
Scopes: policy:author
Slim wrapper used by CLI; returns 204 on success or ERR_POL_001 payload.
6 · Run & Simulation APIs
Schema reference: canonical policy run request/status/diff payloads ship with the Scheduler Models guide (
src/Scheduler/__Libraries/StellaOps.Scheduler.Models/docs/SCHED-MODELS-20-001-POLICY-RUNS.md) and JSON fixtures undersamples/api/scheduler/policy-*.json.
6.1 Trigger Run
POST /api/policy/policies/{policyId}/runs
Scopes: policy:run
Request
{
  "mode": "incremental",           // full | incremental
  "runId": "run:P-7:2025-10-26:auto",   // optional idempotency key
  "sbomSet": ["sbom:S-42","sbom:S-318"],
  "env": {"exposure": "internet"},
  "priority": "normal"             // normal | high | emergency
}
Response 202
{
  "runId": "run:P-7:2025-10-26:auto",
  "status": "queued",
  "queuedAt": "2025-10-26T14:05:00Z"
}
6.2 Get Run Status
GET /api/policy/policies/{policyId}/runs/{runId}
Scopes: policy:runs
Includes status, stats, determinism hash, failure diagnostics.
6.3 List Runs
GET /api/policy/policies/{policyId}/runs?mode=incremental&status=failed&page=1&pageSize=20
Scopes: policy:runs
Supports filtering by mode, status, from/to timestamps, tenant.
6.4 Simulate
POST /api/policy/policies/{policyId}/simulate
Scopes: policy:simulate
Request
{
  "baseVersion": 3,
  "candidateVersion": 4,
  "sbomSet": ["sbom:S-42","sbom:S-318"],
  "env": {"sealed": false},
  "explain": true
}
Response 200
{
  "diff": {
    "added": 12,
    "removed": 8,
    "unchanged": 657,
    "bySeverity": {
      "Critical": {"up": 1, "down": 0},
      "High": {"up": 3, "down": 4}
    }
  },
  "explainUri": "blob://policy/P-7/simulations/2025-10-26-4-vs-3.json"
}
6.5 Replay Run
POST /api/policy/policies/{policyId}/runs/{runId}:replay
Scopes: policy:runs, policy:simulate
Produces sealed bundle for determinism verification; returns location of bundle.
7 · Effective Findings APIs
7.1 List Findings
GET /api/policy/findings/{policyId}?sbomId=S-42&status=affected&severity=High,Critical&page=1&pageSize=100
Scopes: findings:read
Response includes cursor-based pagination:
{
  "items": [
    {
      "findingId": "P-7:S-42:pkg:npm/lodash@4.17.21:CVE-2021-23337",
      "status": "affected",
      "severity": {"normalized": "High", "score": 7.5},
      "sbomId": "sbom:S-42",
      "advisoryIds": ["CVE-2021-23337"],
      "vex": {"winningStatementId": "VendorX-123"},
      "policyVersion": 4,
      "updatedAt": "2025-10-26T14:06:01Z"
    }
  ],
  "nextCursor": "eyJwYWdlIjoxfQ=="
}
7.2 Fetch Explain Trace
GET /api/policy/findings/{policyId}/{findingId}/explain?mode=verbose
Scopes: findings:read
Returns rule hit sequence:
{
  "findingId": "P-7:S-42:pkg:npm/lodash@4.17.21:CVE-2021-23337",
  "policyVersion": 4,
  "steps": [
    {"rule": "vex_precedence", "status": "not_affected", "inputs": {"statementId": "VendorX-123"}},
    {"rule": "severity_baseline", "severity": {"normalized": "Low", "score": 3.4}}
  ],
  "sealedHints": [{"message": "Using cached EPSS percentile from bundle 2025-10-20"}]
}
8 · Events & Webhooks
- policy.run.completed– emitted with- runId,- policyId,- mode,- stats,- determinismHash.
- policy.run.failed– includes error code, retry count, guidance.
- policy.lifecycle.*– mirrored from lifecycle APIs (see Lifecycle guide).
- Webhook registration occurs via /api/policy/webhooks(future work, reserved). For now, integrate with Notifier streams documented in/docs/notifications/*.
9 · Compliance Checklist
- Scopes enforced: Endpoint access requires correct Authority scope mapping (see /src/Authority/StellaOps.Authority/TASKS.md).
- Schemas current: JSON examples align with Scheduler Models (SCHED-MODELS-20-001) and Policy Engine DTOs; update when contracts change.
- Error codes mapped: ERR_POL_*table reflects implementation and CI tests cover edge cases.
- Pagination documented: List endpoints specify page/size and cursor semantics; responses include X-Total-CountornextCursor.
- Idempotency described: Mutating endpoints mandate Idempotency-Key.
- Offline parity noted: Simulate/run endpoints explain --sealedbehaviour and bundle generation.
- Cross-links added: References to lifecycle, runs, DSL, and observability docs verified.
Last updated: 2025-10-26 (Sprint 20).