Files
git.stella-ops.org/docs/api/policy.md
master 96d52884e8
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Add Policy DSL Validator, Schema Exporter, and Simulation Smoke tools
- Implemented PolicyDslValidator with command-line options for strict mode and JSON output.
- Created PolicySchemaExporter to generate JSON schemas for policy-related models.
- Developed PolicySimulationSmoke tool to validate policy simulations against expected outcomes.
- Added project files and necessary dependencies for each tool.
- Ensured proper error handling and usage instructions across tools.
2025-10-27 08:00:11 +02:00

403 lines
9.9 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.

# 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 Epic2 (Policy Engine v2). Use it alongside the [DSL](../policy/dsl.md), [Lifecycle](../policy/lifecycle.md), and [Runs](../policy/runs.md) guides for end-to-end implementations.
---
## 1·Authentication & Headers
- **Auth:** Bearer tokens (`Authorization: Bearer <token>`) with the following scopes as applicable:
- `policy:read`, `policy:write`, `policy:submit`, `policy:approve`, `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 obtain `effective:write`.
- **Tenant:** Supply tenant context via `X-Stella-Tenant`. Tokens without multi-tenant claims default to `default`.
- **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-8` unless otherwise noted.
---
## 2·Error Model
All errors use HTTP semantics plus a structured payload:
```json
{
"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`, `run` when 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:write
```
**Request**
```json
{
"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**
```json
{
"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:write
```
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:submit
```
**Request**
```json
{
"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**
```json
{
"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:
```json
{
"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:write
```
**Response 200**
```json
{
"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:write
```
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/StellaOps.Scheduler.Models/docs/SCHED-MODELS-20-001-POLICY-RUNS.md`) and JSON fixtures under `samples/api/scheduler/policy-*.json`.
### 6.1 Trigger Run
```
POST /api/policy/policies/{policyId}/runs
Scopes: policy:run
```
**Request**
```json
{
"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**
```json
{
"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**
```json
{
"baseVersion": 3,
"candidateVersion": 4,
"sbomSet": ["sbom:S-42","sbom:S-318"],
"env": {"sealed": false},
"explain": true
}
```
**Response 200**
```json
{
"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:
```json
{
"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:
```json
{
"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](../policy/lifecycle.md)).
- 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/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-Count` or `nextCursor`.
- [ ] **Idempotency described:** Mutating endpoints mandate `Idempotency-Key`.
- [ ] **Offline parity noted:** Simulate/run endpoints explain `--sealed` behaviour and bundle generation.
- [ ] **Cross-links added:** References to lifecycle, runs, DSL, and observability docs verified.
---
*Last updated: 2025-10-26 (Sprint 20).*