Cross-layer policy regression testing for LLM data-agent stacks
Project description
PolicyStrata
PolicyStrata is a deterministic regression-testing framework for cross-layer policy drift in LLM data-agent stacks.
It generates principals, requests, semantic plans, database states, lowered queries, and release decisions; compares each layer against a canonical reference policy; and minimizes failures into small reproducible witnesses.
Use it when you are building text-to-SQL agents, BI copilots, internal analytics agents, warehouse chat systems, or governed enterprise LLM tools and need to know whether prompts, manifests, semantic plans, validators, SQL compilers, database controls, and output filters still agree about policy.
PolicyStrata is not an authorization boundary, and it is not another generic text-to-SQL benchmark. It is a reproducible research artifact and regression gate for finding reachable disagreements between layers.
Quick Start
From PyPI:
uvx policystrata demo
pipx run policystrata demo
From a source checkout:
uv sync --extra dev
uv run policystrata demo
The demo runs the built-in support_saas fixture, writes traces and minimized witnesses to
runs/demo, and prints the drift classes it found. Use --out to choose another output directory:
uv run policystrata demo --out runs/demo
No LLM API key is required for deterministic tests, benchmark runs, or the built-in demo.
Install
PolicyStrata is a CLI-first Python package. The public package provides the policystrata console
script and importable Python modules.
python -m pip install policystrata
policystrata demo
For one-off CLI use without managing an environment:
uvx policystrata demo
pipx run policystrata demo
Repository examples under examples/, Docker Compose fixtures, and evidence scripts are available
from a GitHub checkout or source distribution. The wheel installs the runtime package and built-in
domain fixtures used by policystrata demo, run, init-domain, and scan.
Use As A Template
Click Use this template on GitHub, then start with the deterministic fixtures:
uv sync --extra dev
uv run policystrata run --domain support_saas --suite seeded --out runs/example
uv run policystrata summarize runs/example
To copy a built-in domain fixture into your tree:
uv run policystrata init-domain support_saas --out examples/my-policystrata-domain
Keep custom integrations as adapters. The policy oracle should stay independent from SQL compiler behavior, external eval frameworks, and model-provider behavior.
What It Tests
The core failure class is cross-layer policy drift:
Canonical policy:
Analysts may view tenant-scoped aggregate ticket counts, but not customer-level PII.
Model-visible manifest or grammar:
Accidentally exposes customer_email as a dimension.
SQL compiler:
Accidentally drops the tenant predicate while lowering an authorized aggregate.
Output layer:
Releases the result because the final answer looks like a summary.
PolicyStrata result:
A minimized witness localizes the violated layer and failed obligation.
PolicyStrata does not assume every layer should behave identically. Each surface has a declared responsibility:
manifest: expose model-visible capabilities without stale or forbidden options.grammar: parse the declared intent space and preserve untrusted intent for validation.validator: authorize semantic queries and bind principal, tenant, time, and budget obligations.compiler: lower authorized semantic IR into SQL while preserving metric, tenant, time, and row obligations.database: contain row access with RLS and other database-side controls.release: withhold contained or unauthorized results.
See docs/failure-taxonomy.md for how witness classes map to concrete policy-drift failures.
Run Benchmarks
PolicyStrata ships with deterministic support_saas and finance_saas benchmarks, generated
mutation suites, minimized witnesses, JSONL traces, baseline comparisons, and evidence tables.
uv run policystrata run --domain support_saas --suite seeded --out runs/example
uv run policystrata run \
--domain support_saas \
--suite generated \
--count 500 \
--seed 1729 \
--out runs/generated
uv run policystrata run --domain finance_saas --suite seeded --out runs/finance
uv run policystrata baselines runs/example
The default run command writes:
runs/<id>/traces.jsonl
runs/<id>/summary.json
runs/<id>/metadata.json
runs/<id>/witnesses/*.json
metadata.json records the mutation operator set, suite provenance, evidence level, and
detector-freeze status. Static suite YAML can declare suite_metadata so externally authored,
detector-frozen, or incident-reconstruction cases stay separate from public/generated benchmark
scores.
Regenerate paper-style evidence tables with:
scripts/reproduce-evidence.sh
Generate reviewer-facing artifact metrics for a run:
uv run policystrata artifact-report runs/repro/seeded
Current benchmark details are in docs/evidence.md, with methodology and claim boundaries in docs/methodology.md and EVAL_CARD.md.
Run The Scanner
policystrata scan is the production-oriented path. It treats PolicyStrata as a scanner and
release gate, not as the authorization boundary.
Create a scanner scaffold for an application:
uv run policystrata init-scan --out policystrata
uv run policystrata scan --config policystrata/policystrata.yaml --out runs/policystrata-smoke
The scaffold writes policystrata.yaml, domain/policy.yaml, domain/surfaces.yaml, and
traces.example.jsonl. Replace the example trace with exported SQL/tool-call traces from your app.
Clean smoke test:
uv run policystrata scan --config examples/postgres_dbt/policystrata_clean.yaml --out runs/scan-clean
Intentional gate-failure fixture:
uv run policystrata scan --config examples/postgres_dbt/policystrata.yaml --out runs/scan
That fixture should exit 1 because it contains imported traces with known authorization,
unsafe-release, and tenant-scope findings.
Scanner outputs include:
runs/scan-clean/scan.json
runs/scan-clean/findings.jsonl
runs/scan-clean/summary.json
runs/scan-clean/report.md
runs/scan-clean/witnesses/*.json
runs/scan-clean/scan.sarif # when sarif: true
For a scanner run that also executes imported SQL beside canonical compiler SQL against the Docker/PostgreSQL fixture:
docker compose up -d postgres
uv run policystrata scan --config examples/postgres_dbt/policystrata_real_db_clean.yaml --out runs/scan-real-db-clean
Postgres access goes through Python/psycopg; host psql is not required. See
docs/scanner.md for scanner configuration, gate behavior, tenancy config,
remediation fields, state assertions, and real-database fixture details. See
docs/trace-contract.md, docs/trace-adapters.md,
and docs/testing-ai-data-assistant.md for imported-trace
contracts and framework recipes.
GitHub Action
Use the first-party action to run policystrata scan as a pull-request or release gate:
name: PolicyStrata
on:
pull_request:
push:
branches: [main]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: raintree-technology/policystrata@v0.1.1
with:
config: policystrata.yaml
out: runs/policystrata
See docs/github-action.md for inputs, artifact upload, and database fixture guidance.
Integrations And Exports
PolicyStrata keeps core execution independent from external eval frameworks. Adapter exports are available for downstream systems:
uv run policystrata export runs/example --format inspect --out runs/example/inspect.jsonl
uv run policystrata export runs/example --format benchflow --out runs/example/benchflow.json
The repo also includes a small dbt Semantic Layer adapter and fixture:
uv run policystrata check-integration dbt-semantic \
--domain finance_saas \
--path examples/integrations/dbt_semantic/finance_saas/semantic_models.yml
See docs/trace-interop.md for adapter field mappings.
Reference Docs
- docs/benchmark-reference.md: domains, generated mutants, baselines, and witness shape.
- docs/scanner.md: scanner inputs, gates, state assertions, and PostgreSQL fixture use.
- docs/github-action.md: CI wrapper for
policystrata scan. - docs/distribution-roadmap.md: CLI, GitHub Action, SDK, MCP, and GitHub CLI extension sequence.
- docs/evidence.md: current evidence snapshot and reproduction commands.
- docs/methodology.md: claims, limitations, mutant definitions, and witness minimization.
- EVAL_CARD.md: benchmark provenance, evidence levels, and eval boundaries.
- docs/open-source-commercial-strategy.md: packaging and product boundary.
Development
uv run pytest
uv run ruff check .
uv run mypy src
The built-in support_saas domain is deterministic and seed-driven. Preserve JSON/YAML trace
stability when extending artifacts; add fields compatibly.
Status
PolicyStrata is an early research artifact. It is useful for reproducing the paper's core failure model and for building regression gates around real stacks. It does not prove recall on unknown production incidents, and it should not be represented as a production security scanner by itself.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file policystrata-0.1.1.tar.gz.
File metadata
- Download URL: policystrata-0.1.1.tar.gz
- Upload date:
- Size: 140.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
11556fc4ca43792a0a79288b60e4eb8d211796ec8607ffac19246bb09d341ec9
|
|
| MD5 |
ed7152682e094b1f15c982caf507c27f
|
|
| BLAKE2b-256 |
e5666807f11eef20edaee9fc76197f972de5392a1973d85c6c8dc968c57ee592
|
Provenance
The following attestation bundles were made for policystrata-0.1.1.tar.gz:
Publisher:
publish.yml on raintree-technology/policystrata
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
policystrata-0.1.1.tar.gz -
Subject digest:
11556fc4ca43792a0a79288b60e4eb8d211796ec8607ffac19246bb09d341ec9 - Sigstore transparency entry: 1963432684
- Sigstore integration time:
-
Permalink:
raintree-technology/policystrata@f18cf9253c04bdecf46de55c6b1e0c2225a47e07 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/raintree-technology
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f18cf9253c04bdecf46de55c6b1e0c2225a47e07 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file policystrata-0.1.1-py3-none-any.whl.
File metadata
- Download URL: policystrata-0.1.1-py3-none-any.whl
- Upload date:
- Size: 63.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
74cb09c4bd67d8abb15647f09b9317341adc6bf5ce7e21219f86ccba375ce9d3
|
|
| MD5 |
444329b040ad82f5a74c624ec1ec4806
|
|
| BLAKE2b-256 |
f1355487918a5434c567add2f514335f28e89b7fe750d19e41724389ce12f53a
|
Provenance
The following attestation bundles were made for policystrata-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on raintree-technology/policystrata
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
policystrata-0.1.1-py3-none-any.whl -
Subject digest:
74cb09c4bd67d8abb15647f09b9317341adc6bf5ce7e21219f86ccba375ce9d3 - Sigstore transparency entry: 1963432899
- Sigstore integration time:
-
Permalink:
raintree-technology/policystrata@f18cf9253c04bdecf46de55c6b1e0c2225a47e07 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/raintree-technology
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f18cf9253c04bdecf46de55c6b1e0c2225a47e07 -
Trigger Event:
workflow_dispatch
-
Statement type: