Restructure solution layout by module
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
# SCHED-MODELS-20-001 — Policy Engine Run DTOs
|
||||
|
||||
> Status: 2025-10-26 — **Complete**
|
||||
|
||||
Defines the scheduler contracts that Policy Engine (Epic 2) relies on for orchestration, simulation, and explainability. DTOs serialize with `CanonicalJsonSerializer` to guarantee deterministic ordering, enabling replay and signed artefacts.
|
||||
|
||||
## PolicyRunRequest — `scheduler.policy-run-request@1`
|
||||
|
||||
Posted by CLI/UI or the orchestrator to enqueue a run. Canonical sample lives at `samples/api/scheduler/policy-run-request.json`.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"schemaVersion": "scheduler.policy-run-request@1",
|
||||
"tenantId": "default",
|
||||
"policyId": "P-7",
|
||||
"policyVersion": 4,
|
||||
"mode": "incremental", // full | incremental | simulate
|
||||
"priority": "normal", // normal | high | emergency
|
||||
"runId": "run:P-7:2025-10-26:auto", // optional idempotency key
|
||||
"queuedAt": "2025-10-26T14:05:00+00:00",
|
||||
"requestedBy": "user:cli",
|
||||
"correlationId": "req-...",
|
||||
"metadata": {"source": "stella policy run", "trigger": "cli"},
|
||||
"inputs": {
|
||||
"sbomSet": ["sbom:S-318", "sbom:S-42"], // sorted uniques
|
||||
"advisoryCursor": "2025-10-26T13:59:00+00:00",
|
||||
"vexCursor": "2025-10-26T13:58:30+00:00",
|
||||
"environment": {"exposure": "internet", "sealed": false},
|
||||
"captureExplain": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* Environment values accept any JSON primitive/object; keys normalise to lowercase for deterministic hashing.
|
||||
* `metadata` is optional contextual breadcrumbs (lowercased keys). Use it for orchestrator provenance or offline bundle identifiers.
|
||||
|
||||
## PolicyRunStatus — `scheduler.policy-run-status@1`
|
||||
|
||||
Captured in `policy_runs` collection and returned by run status APIs. Sample: `samples/api/scheduler/policy-run-status.json`.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"schemaVersion": "scheduler.policy-run-status@1",
|
||||
"runId": "run:P-7:2025-10-26:auto",
|
||||
"tenantId": "default",
|
||||
"policyId": "P-7",
|
||||
"policyVersion": 4,
|
||||
"mode": "incremental",
|
||||
"status": "succeeded", // queued|running|succeeded|failed|canceled|replay_pending
|
||||
"priority": "normal",
|
||||
"queuedAt": "2025-10-26T14:05:00+00:00",
|
||||
"startedAt": "2025-10-26T14:05:11+00:00",
|
||||
"finishedAt": "2025-10-26T14:06:01+00:00",
|
||||
"determinismHash": "sha256:...", // optional until run completes
|
||||
"traceId": "01HE0BJX5S4T9YCN6ZT0",
|
||||
"metadata": {"orchestrator": "scheduler", "sbombatchhash": "sha256:..."},
|
||||
"stats": {
|
||||
"components": 1742,
|
||||
"rulesFired": 68023,
|
||||
"findingsWritten": 4321,
|
||||
"vexOverrides": 210,
|
||||
"quieted": 12,
|
||||
"durationSeconds": 50.8
|
||||
},
|
||||
"inputs": { ... } // same schema as request
|
||||
}
|
||||
```
|
||||
|
||||
* `determinismHash` must be a `sha256:` digest combining ordered input digests + policy digest.
|
||||
* `attempts` (not shown) increases per retry.
|
||||
* Error responses populate `errorCode` (`ERR_POL_00x`) and `error` message; omitted when successful.
|
||||
|
||||
## PolicyDiffSummary — `scheduler.policy-diff-summary@1`
|
||||
|
||||
Returned by simulation APIs; referenced by CLI/UI diff visualisations. Sample: `samples/api/scheduler/policy-diff-summary.json`.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"schemaVersion": "scheduler.policy-diff-summary@1",
|
||||
"added": 12,
|
||||
"removed": 8,
|
||||
"unchanged": 657,
|
||||
"bySeverity": {
|
||||
"critical": {"up": 1},
|
||||
"high": {"up": 3, "down": 4},
|
||||
"medium": {"up": 2, "down": 1}
|
||||
},
|
||||
"ruleHits": [
|
||||
{"ruleId": "rule-block-critical", "ruleName": "Block Critical Findings", "up": 1},
|
||||
{"ruleId": "rule-quiet-low", "ruleName": "Quiet Low Risk", "down": 2}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
* Severity bucket keys normalise to camelCase for JSON determinism across CLI/UI consumers.
|
||||
* Zero-valued counts (`down`/`up`) are omitted to keep payloads compact.
|
||||
* `ruleHits` sorts by `ruleId` to keep diff heatmaps deterministic.
|
||||
|
||||
## PolicyExplainTrace — `scheduler.policy-explain-trace@1`
|
||||
|
||||
Canonical explain tree embedded in findings explainers and exported bundles. Sample: `samples/api/scheduler/policy-explain-trace.json`.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"schemaVersion": "scheduler.policy-explain-trace@1",
|
||||
"findingId": "finding:sbom:S-42/pkg:npm/lodash@4.17.21",
|
||||
"policyId": "P-7",
|
||||
"policyVersion": 4,
|
||||
"tenantId": "default",
|
||||
"runId": "run:P-7:2025-10-26:auto",
|
||||
"evaluatedAt": "2025-10-26T14:06:01+00:00",
|
||||
"verdict": {"status": "blocked", "severity": "critical", "score": 19.5},
|
||||
"ruleChain": [
|
||||
{"ruleId": "rule-allow-known", "action": "allow", "decision": "skipped"},
|
||||
{"ruleId": "rule-block-critical", "action": "block", "decision": "matched", "score": 19.5}
|
||||
],
|
||||
"evidence": [
|
||||
{"type": "advisory", "reference": "CVE-2025-12345", "source": "nvd", "status": "affected", "weight": 1, "metadata": {}},
|
||||
{"type": "vex", "reference": "vex:ghsa-2025-0001", "source": "vendor", "status": "not_affected", "weight": 0.5}
|
||||
],
|
||||
"vexImpacts": [
|
||||
{"statementId": "vex:ghsa-2025-0001", "provider": "vendor", "status": "not_affected", "accepted": true}
|
||||
],
|
||||
"history": [
|
||||
{"status": "blocked", "occurredAt": "2025-10-26T14:06:01+00:00", "actor": "policy-engine"}
|
||||
],
|
||||
"metadata": {"componentpurl": "pkg:npm/lodash@4.17.21", "sbomid": "sbom:S-42", "traceid": "01HE0BJX5S4T9YCN6ZT0"}
|
||||
}
|
||||
```
|
||||
|
||||
* Rule chain preserves execution order; evidence & VEX arrays sort for deterministic outputs.
|
||||
* Evidence metadata is always emitted (empty object when no attributes) so clients can merge annotations deterministically.
|
||||
* Metadata keys lower-case for consistent lookups (`componentpurl`, `traceid`, etc.).
|
||||
* `verdict.status` uses `passed|warned|blocked|quieted|ignored` reflecting final policy decision.
|
||||
|
||||
## Compliance Checklist
|
||||
|
||||
| Item | Owner | Status | Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| Canonical samples committed (`policy-run-request|status|diff-summary|explain-trace`) | Scheduler Models Guild | ☑ 2025-10-26 | Round-trip tests enforce schema stability. |
|
||||
| DTOs documented here and linked from `/docs/policy/runs.md` checklist | Scheduler Models Guild | ☑ 2025-10-26 | Added Run DTO schema section. |
|
||||
| Serializer ensures deterministic ordering for new types | Scheduler Models Guild | ☑ 2025-10-26 | `CanonicalJsonSerializer` updated with property order + converters. |
|
||||
| Tests cover DTO validation and sample fixtures | Scheduler Models Guild | ☑ 2025-10-26 | `PolicyRunModelsTests` + extended `SamplePayloadTests`. |
|
||||
| Scheduler guilds notified (Models, Worker, WebService) | Scheduler Models Guild | ☑ 2025-10-26 | Posted in `#scheduler-guild` with sample links. |
|
||||
|
||||
---
|
||||
|
||||
*Last updated: 2025-10-26.*
|
||||
Reference in New Issue
Block a user