Files
git.stella-ops.org/docs/modules/policy/contracts/29-002-streaming-simulation.md
StellaOps Bot 029002ad05 work
2025-11-23 23:40:10 +02:00

5.1 KiB

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)

{
  "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:

{
  "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":

{ "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.