Files
git.stella-ops.org/docs/modules/policy/contracts/policy-console-23-001-console-api.md
StellaOps Bot 37cba83708
Some checks failed
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
Docs CI / lint-and-preview (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
devportal-offline / build-offline (push) Has been cancelled
up
2025-12-03 00:10:19 +02:00

139 lines
6.1 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.

# Contract: POLICY-CONSOLE-23-001 — Console findings/export & simulation surfaces
**Status:** Draft → Proposed (2025-12-02)
**Scope**
- Provide deterministic, tenant-scoped APIs from Policy Engine to StellaOps Console for findings browse/export and simulation/explain experiences.
- Replace legacy ad-hoc Console queries with cursor-based, RBAC-aware endpoints that expose provenance and aggregation hints.
- Keep all responses deterministic (stable ordering, explicit timestamps, no wall-clock/default time windows).
## Versioning & Compatibility
- `schemaVersion`: `console-policy-23-001` (bumped on breaking changes).
- Media type: `application/vnd.stellaops.console-policy-23-001+json` (clients MUST send `Accept` and SHOULD send `Content-Type`).
- Backward-compatible additions follow additive fields; ordering and cursor format remain stable.
## Authentication & RBAC
- Required scopes: `policy:read`, `effective:read`, `explain:read` (all tenant-scoped).
- Optional `findings:export` to enable NDJSON bulk export.
- All endpoints require `X-Tenant-Id`; server enforces tenant filter and rejects cross-tenant cursor reuse.
## Determinism Rules
- Ordering: `policyVersion DESC`, `artifactDigest ASC`, `purl ASC`, `ruleId ASC`, `findingId ASC`.
- Cursor: opaque, URL-safe base64 of the last tuple above; contains `policyVersion|artifactDigest|purl|ruleId|findingId` plus `schemaVersion`. No server clocks in cursors.
- Timestamps: clients MUST provide `evaluationTimestamp` or `timeWindowStart/End`; server never injects `DateTime.UtcNow` defaults.
- Randomness/network access disallowed; sampling ratios must be provided by the client or policy config.
## Endpoints
### 1) List findings (paged)
- **GET** `/policy/console/findings`
- **Query params**
- `cursor` (string, optional)
- `limit` (int, 1500, default 100)
- `severityBand[]` (enum: critical|high|medium|low|unknown)
- `ruleId[]`, `policyId`, `policyVersion`
- `artifactDigest[]`, `purl[]`, `namespace[]`
- `advisoryId[]`, `vexStatement[]`
- `state[]` (open|waived|fixed|not_applicable)
- `timeWindowStart`, `timeWindowEnd` (ISO-8601, optional)
- `sort` (one of `default`, `severity_desc`, `artifact`, `rule`); default respects deterministic tuple above.
- **Response**
```json
{
"schemaVersion": "console-policy-23-001",
"items": [
{
"findingId": "ulid",
"policyVersion": "2025.11.24",
"artifactDigest": "sha256:...",
"purl": "pkg:maven/org.example/foo@1.2.3",
"ruleId": "RULE-1234",
"severity": "high",
"state": "open",
"explainSummary": {
"hitRules": ["RULE-1234"],
"traceSampleId": "ulid",
"rationale": ["package matches advisory CVE-2025-1234"]
},
"provenance": {
"evaluationTimestamp": "2025-11-28T00:00:00Z",
"effectiveFindingHash": "be...",
"source": "materialized"
}
}
],
"cursor": { "next": "b64...", "prev": "b64..." },
"aggregates": {
"countsBySeverity": {"critical": 1, "high": 5, "medium": 12, "low": 3, "unknown": 0},
"countsByRule": [{"ruleId": "RULE-1234", "count": 4}],
"countsByPolicyVersion": [{"policyVersion": "2025.11.24", "count": 25}]
}
}
```
### 2) Finding explain trace (summary)
- **GET** `/policy/console/findings/{findingId}/explain`
- Returns deterministic trace summary for UI drawer (no full trace fan-out): hit rules, key facts, sampled trace token, policyVersion, evaluationTimestamp, hashes.
- Optional `format` (`json` default, `markdown` for UI preview); output ordering stable.
### 3) Simulation/export diff (used by POLICY-CONSOLE-23-002)
- **POST** `/policy/console/simulations/diff`
- **Body**
```json
{
"baselinePolicyVersion": "2025.11.24",
"candidatePolicyVersion": "2025.12.02",
"artifactScope": [{"artifactDigest": "sha256:..."}],
"budget": {"maxFindings": 2000, "maxExplainSamples": 50},
"filters": {"severityBand": ["high","critical"]}
}
```
- **Response**
```json
{
"schemaVersion": "console-policy-23-001",
"summary": {
"before": {"total": 120, "severity": {"critical":4,"high":30,"medium":60,"low":26}},
"after": {"total": 98, "severity": {"critical":3,"high":22,"medium":55,"low":18}},
"delta": {"added":12,"removed":34,"regressed":2}
},
"ruleImpact": [
{"ruleId":"RULE-1234","added":3,"removed":10,"severityShift":{"high→medium":6}},
{"ruleId":"RULE-2000","added":1,"removed":0}
],
"samples": {
"explain": ["trace-token-1","trace-token-2"],
"findings": ["finding-ulid-1","finding-ulid-2"]
},
"provenance": {
"baselinePolicyVersion": "2025.11.24",
"candidatePolicyVersion": "2025.12.02",
"evaluationTimestamp": "2025-12-02T00:00:00Z"
}
}
```
- Ordering of ruleImpact array: `ruleId ASC`; samples ordered by hash.
### 4) Bulk export (NDJSON)
- **POST** `/policy/console/findings/export`
- Body accepts same filters as list endpoint plus `format` (`ndjson` only) and `maxRows` (hard cap 50k).
- Response streams NDJSON of finding records in deterministic ordering with content hashes.
## Error Model
- 400 with machine-readable code (`invalid_filter`, `unsupported_schemaVersion`, `budget_exceeded`).
- 401/403 for auth/scope failures; 409 when `schemaVersion` mismatch.
- 429 when budget limits tripped; include `retryAfterSeconds` but never implicit sleep in server.
## Non-Goals
- No mutable state or approvals exposed here; status transitions remain in Console backend via existing endpoints.
- No live wall-clock filtering; clients must pass explicit windows.
## Testing Hooks
- Provide `X-Dry-Run: true` to validate filters and budgets without executing evaluation.
- `X-Debug-Sampling: <0..1>` allowed in non-production tenants only; otherwise rejected.
## Implementation Notes
- Reuse batch evaluation pipeline for simulation diff; reuse materialized `effective_finding_*` collections for listing/export.
- Enforce deterministic `evaluationTimestamp` supplied by caller; reject missing timestamp when `baselinePolicyVersion != candidatePolicyVersion`.
- All aggregates computed in-memory over deterministically ordered result sets; no sampling unless explicitly requested.