# POLICY-ENGINE-29-002 — Streaming Simulation (Path/Scope) Contract Status: Final · 2025-11-23 Owners: Policy Guild · SBOM Service Guild · Findings Ledger Guild Working directory: `src/Policy/StellaOps.Policy.Engine` ## Purpose Define the canonical request/response contract for streaming comparisons between two policy versions with path/scope awareness. Output is explainable per-finding deltas without writes, suitable for Console simulation, Ledger projections, and Advisory AI consumers. ## Request Schema (JSON) ```json { "schemaVersion": "1.0.0", "tenant": "acme", // required "basePolicyRef": "policy://acme/main@sha256:abcd", // required "candidatePolicyRef": "policy://acme/feature@sha256:ef01", // required "subject": { "purl": "pkg:npm/lodash@4.17.21", // or cpe; at least one "packagePath": "lib/isEqual.js", // optional, POSIX "osImage": "ghcr.io/acme/app@sha256:..." // optional }, "targets": [ { "filePath": "src/lib/isEqual.js", // required, POSIX "digest": "c1ab...", // optional hex sha256 "treeDigest": "7ff0...", // optional Merkle root "pathMatch": "prefix", // exact|prefix|glob "pattern": "src/lib/", // required with pathMatch "confidence": 0.92, // 0..1 "depthLimit": 3, // optional int "evidenceHash": "4f9b...", // optional hex (stable over sorted JSON) "ingestedAt": "2025-11-20T00:00:00Z", // optional ISO-8601 UTC "connectorId": "excititor-ghsa" // optional string } ], "options": { "sort": "path,finding,verdict", // required enum; default shown "maxFindings": 1000, // optional int "includeTrace": true, // include rule trace fragments "deterministic": true // must be true; rejects false } } ``` - `schemaVersion` pinned to semantic version; breaking changes require bump. - All string comparisons are case-sensitive except `policy://` refs, which normalise to lowercase host/path. - At least one `target` required. Each target binds evidence to scope (derived from PREP docs `2025-11-20-policy-engine-29-002-prep.md`). ### Derived Scope Normalisation For each target: - `pathMatch` resolution order: `exact` > `prefix` > `glob`; tie-breaker by higher `confidence`, then lexical `filePath`. - `evidenceHash` = SHA-256 of canonical JSON object with properties sorted ASCII and nulls removed. ## Response Schema (streamed NDJSON) Each line is a JSON object with stable ordering: ```json { "tenant": "acme", "subject": { "purl": "pkg:npm/lodash@4.17.21", "packagePath": "lib/isEqual.js" }, "target": { "filePath": "src/lib/isEqual.js", "pattern": "src/lib/", "pathMatch": "prefix", "confidence": 0.92, "evidenceHash": "4f9b..." }, "finding": { "id": "GHSA-35jh-r3h4-6jhm", "ruleId": "policy.rules.javascript.unsafe-merge", "severity": "high", "verdict": { "base": "deny", // allow|deny|warn|info|not-applicable "candidate": "warn", "delta": "softened" // added|removed|hardened|softened|unchanged }, "evidence": { "locator": { "filePath": "src/lib/isEqual.js", "digest": "c1ab..." }, "provenance": { "ingestedAt": "2025-11-20T00:00:00Z", "connectorId": "excititor-ghsa" } } }, "trace": [ { "step": "match", "rule": "unsafe-merge", "path": "src/lib/isEqual.js" }, { "step": "decision", "effect": "warn" } ], "metrics": { "evalTicks": 128, // deterministic instruction counter "rulesEvaluated": 12, "bindings": 3 } } ``` - Lines are sorted by `target.filePath`, then `finding.id`, then `finding.ruleId`. No other ordering allowed. - Absent optional fields must be omitted (not null). ## Error Envelope Errors surface as NDJSON line with `type: "error"`: ```json { "type": "error", "code": "POLICY_29_002_SCHEMA", "message": "target[0].pattern required" } ``` Codes: `POLICY_29_002_SCHEMA`, `POLICY_29_002_UNSUPPORTED_VERSION`, `POLICY_29_002_SCOPE_MISMATCH`, `POLICY_29_002_TOO_MANY_FINDINGS`. ## Determinism Rules - No wall-clock, RNG, or network access during evaluation. - All hashes use SHA-256 over canonical JSON (sorted properties, UTF-8, no insignificant whitespace). - Stable ordering: request-specified sort or default `path,finding,verdict` defined above. - Trace fragments trimmed to deterministic steps only (no timestamps or hostnames). ## Validation & Conformance - JSON Schema published at `schemas/policy/29-002-streaming-simulation.schema.json` (to be mirrored in Offline Kit); engines must validate requests before execution. - CI fixtures: `tests/policy/fixtures/29-002-sample-request.json` and `...-response.ndjson` (to be added when engine implements). ## Compatibility Notes - Extends PREP docs `2025-11-20-policy-engine-29-002-prep.md` and `2025-11-21-policy-path-scope-29-002-prep.md`; supersedes their draft status. - Downstream tasks 29-003..40-002 must consume `target` shape above; any change requires bumping `schemaVersion` and updating sprint risks.