Skip to content

Commit 87d0c7c

Browse files
feat(governance): runnable assurance — Groth16 zk proof, TLA+ TLC, GC-IR cross-target harness, OPA tests
Upgrade Sentinel v2.4 governance artifacts from declarative to executable/verifiable: - ZK (cry-05): SRC-1 ConcentrationBound Circom circuit proving foundation-model decision-volume HHI <= board threshold in zero knowledge; full Groth16 flow (run_src1_proof.sh) with verified proof + soundness negative test. Emitted proof_statement.json validates against proof_statement_schema.json. - TLA+ (con-04/con-07): complete KillSwitchAbstract spec with Init/Next; TLC model-checks ASA one-way containment ratchet + human dual-control quorum for terminal actuation/de-escalation (13 states, no error). - GC-IR: gcir_harness.py enforces the 'all targets agree' claim by running shared fixtures through real Rego (opa eval) AND the SRC-fair-1 Circom circuit; any disagreement fails the build. - OPA: 12 passing tests for release_gate + high_impact_credit; migrated policies to Rego v1 syntax; updated validator token checks accordingly. - run_runnable_assurance.sh runs all five checks; CI workflow added. - RUNNABLE_ASSURANCE.md documents control->proof mapping and reproduction.
1 parent 65feeae commit 87d0c7c

35 files changed

Lines changed: 2562 additions & 3 deletions
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: Runnable Assurance (Sentinel v2.4)
2+
3+
# Executes the runnable proof obligations behind the governance artifacts:
4+
# OPA policy tests, TLA+ TLC model check, GC-IR cross-target harness, and the
5+
# SRC-1 Groth16 concentration-bound proof flow.
6+
7+
on:
8+
push:
9+
paths:
10+
- 'governance_artifacts/**'
11+
- '.github/workflows/runnable-assurance.yml'
12+
pull_request:
13+
paths:
14+
- 'governance_artifacts/**'
15+
workflow_dispatch:
16+
17+
jobs:
18+
runnable-assurance:
19+
runs-on: ubuntu-latest
20+
steps:
21+
- uses: actions/checkout@v4
22+
23+
- name: Set up Python
24+
uses: actions/setup-python@v5
25+
with:
26+
python-version: '3.12'
27+
28+
- name: Set up Node
29+
uses: actions/setup-node@v4
30+
with:
31+
node-version: '20'
32+
33+
- name: Set up Java (for TLA+ TLC)
34+
uses: actions/setup-java@v4
35+
with:
36+
distribution: temurin
37+
java-version: '17'
38+
39+
- name: Install Python deps
40+
run: pip install pyyaml jsonschema
41+
42+
- name: Install OPA
43+
run: |
44+
curl -sSL -o /usr/local/bin/opa https://openpolicyagent.org/downloads/v0.70.0/opa_linux_amd64_static
45+
chmod +x /usr/local/bin/opa
46+
opa version
47+
48+
- name: Install circom 2.1.9
49+
run: |
50+
mkdir -p "$HOME/.local/bin"
51+
curl -L -o "$HOME/.local/bin/circom" https://github.com/iden3/circom/releases/download/v2.1.9/circom-linux-amd64
52+
chmod +x "$HOME/.local/bin/circom"
53+
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
54+
55+
- name: Install snarkjs + circomlib
56+
working-directory: governance_artifacts/zk
57+
run: npm install
58+
59+
- name: Fetch TLA+ tools
60+
run: |
61+
mkdir -p governance_artifacts/tla/tools
62+
curl -L -o governance_artifacts/tla/tools/tla2tools.jar \
63+
https://github.com/tlaplus/tlaplus/releases/download/v1.7.4/tla2tools.jar
64+
65+
- name: Compile circuits
66+
working-directory: governance_artifacts/zk
67+
run: |
68+
circom circuits/src1_concentration_bound.circom --r1cs --wasm --sym --O0 -o circuits/
69+
circom circuits/src_fair1_reason_code_check.circom --r1cs --wasm --sym --O0 -o circuits/
70+
71+
- name: Run runnable assurance suite
72+
run: bash governance_artifacts/run_runnable_assurance.sh

governance_artifacts/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,16 @@
33
## Purpose
44
This directory provides machine-readable governance controls, policies, schemas, and fixtures for Sentinel v2.4 release gating.
55

6+
## Runnable assurance (proofs, not prose)
7+
For the executable proof obligations — OPA policy tests, TLA+ TLC model checking
8+
of the containment ratchet, the GC-IR cross-target conformance harness, and the
9+
SRC-1 Groth16 systemic-risk concentration proof — see
10+
[`RUNNABLE_ASSURANCE.md`](RUNNABLE_ASSURANCE.md) and run:
11+
12+
```bash
13+
bash run_runnable_assurance.sh
14+
```
15+
616
## Local validation
717
Run the deterministic validator directly:
818

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# Runnable Assurance — Sentinel v2.4 Governance Artifacts
2+
3+
This directory upgrades the Sentinel v2.4 governance artifacts from *declarative*
4+
(schemas, prose controls, policy sketches) to **executable and verifiable**. Where
5+
the master reference documents assert that a control "holds," the artifacts here
6+
*prove* it with industry-standard tooling.
7+
8+
> Scope note. These artifacts implement the standards-grounded core (OSCAL 1.1.2,
9+
> OPA/Rego, TLA+/TLC, Circom/Groth16, FIPS 203/204/205 references). AGI/ASI
10+
> *containment* is modelled as a control-and-invariant discipline; speculative
11+
> regime fixtures (ICGC/GACP, GAIRA) remain tagged `feasibility-tier` C/D in the
12+
> OSCAL catalog and are not claimed as settled practice.
13+
14+
## One command
15+
16+
```bash
17+
bash governance_artifacts/run_runnable_assurance.sh
18+
```
19+
20+
Runs all five checks below and fails fast on any error.
21+
22+
## What is proven, and against which control
23+
24+
| # | Check | Tool | Backs OSCAL control | Regime anchor |
25+
|---|-------|------|---------------------|---------------|
26+
| 1 | Deny-by-default release gate + high-impact credit gate | `opa test` (12 tests) | release-gate semantics; `con-07` quorum | SR 11-7, EU AI Act Art. 14, ECOA, GDPR Art. 22 |
27+
| 2 | Containment one-way ratchet & terminal-actuation quorum | TLA+ `tlc2.TLC` | `con-04`, `con-07` | EU AI Act Art. 14, DORA resilience testing |
28+
| 3 | GC-IR cross-target conformance (policy ⇔ circuit ⇔ expectation) | `opa eval` + Circom witness | obligation `ob-ecoa-adverse-reason-codes` | ECOA, GDPR Art. 22, EU AI Act Art. 13 |
29+
| 4 | Systemic-risk concentration bound (HHI) zk proof | Circom + Groth16 (snarkjs) | `cry-05` | Basel op-risk, systemic telemetry |
30+
| 5 | Governance artifact schema validation | Python validator | manifest/schema integrity | OSCAL, evidence logging (EU AI Act Art. 12) |
31+
32+
## 1. OPA policy tests — `rego/`
33+
34+
- `release_gate.rego` — high-impact release is **deny-by-default**; `allow` requires
35+
containment `ENFORCED`, dual-control quorum ≥ 2, signed bundle, and both the
36+
Omni-Sentinel safety control and the SR 11-7 validation control.
37+
- `high_impact_credit.rego` — adverse credit underwriting requires human review,
38+
≥ 3 reason codes, fairness within an equal-opportunity delta, verified lineage,
39+
no active incident.
40+
- `fairness_credit_decision.rego` — the Rego emission target of the GC-IR obligation.
41+
42+
```bash
43+
opa test governance_artifacts/rego/ -v # 12/12 PASS
44+
```
45+
46+
## 2. TLA+ containment ratchet — `tla/KillSwitchAbstract.tla`
47+
48+
Models containment levels L0 NORMAL → L4 TERMINATED. Autonomous Supervisory Agents
49+
(ASAs) may only *raise* level within L0–L2; lowering the level or actuating the
50+
terminal levels L3/L4 requires a human dual-control quorum. TLC exhaustively checks:
51+
52+
- `TypeOK`, `ASARatchet`, `TerminalNeedsQuorum` (invariants)
53+
- `ASANeverLowers`, `DeEscalationNeedsQuorum` (action properties)
54+
55+
```bash
56+
cd governance_artifacts/tla
57+
java -cp tools/tla2tools.jar tlc2.TLC -config KillSwitchAbstract.cfg KillSwitchAbstract.tla
58+
# -> "Model checking completed. No error has been found." (13 distinct states)
59+
```
60+
61+
## 3. GC-IR cross-target harness — `zk/gcir_harness.py`
62+
63+
The GC-IR design claims a single obligation compiles to multiple targets and that
64+
"any disagreement fails the build." This harness makes that real for
65+
`ob-ecoa-adverse-reason-codes`: it runs each shared fixture through the **Rego**
66+
rule (`opa eval`) and through the **Circom** circuit (real witness generation), then
67+
asserts `rego_allow == circuit_witness_producible == declared_expectation`.
68+
69+
```bash
70+
cd governance_artifacts/zk && python3 gcir_harness.py
71+
# fx-001 allow / fx-002 deny (too few codes) / fx-003 deny (unapproved code) — all agree
72+
```
73+
74+
## 4. SRC-1 systemic-risk concentration proof — `zk/`
75+
76+
`circuits/src1_concentration_bound.circom` proves, in zero knowledge, that the
77+
decision-volume **Herfindahl-Hirschman Index** across foundation-model providers
78+
does not exceed a board-ratified threshold (basis points), with `circuit_tag`
79+
binding the proof to circuit revision SRC-1. The flow runs a dev Powers-of-Tau
80+
ceremony, Groth16 setup, proves the compliant fixture, verifies it, and emits a
81+
`proof_statement.json` conforming to `proof_statement_schema.json`. The negative
82+
test shows an over-concentrated portfolio **cannot** produce a witness.
83+
84+
```bash
85+
cd governance_artifacts/zk && bash run_src1_proof.sh
86+
# -> snarkJS: OK! (proof verifies); violation fixture rejected (soundness)
87+
```
88+
89+
> The Powers-of-Tau ceremony here is a **development** ceremony and is **not**
90+
> production-secure. A production deployment requires a multi-party trusted setup
91+
> (or a transparent system such as PLONK/STARK as noted in the schema enum).
92+
93+
## Reproducing from a clean checkout
94+
95+
```bash
96+
# OPA
97+
curl -sSL -o /usr/local/bin/opa https://openpolicyagent.org/downloads/v0.70.0/opa_linux_amd64_static && chmod +x /usr/local/bin/opa
98+
# circom 2.1.9 + snarkjs/circomlib
99+
curl -L -o ~/.local/bin/circom https://github.com/iden3/circom/releases/download/v2.1.9/circom-linux-amd64 && chmod +x ~/.local/bin/circom
100+
( cd governance_artifacts/zk && npm install )
101+
# TLA+ tools
102+
curl -L -o governance_artifacts/tla/tools/tla2tools.jar https://github.com/tlaplus/tlaplus/releases/download/v1.7.4/tla2tools.jar
103+
# Python
104+
pip install pyyaml jsonschema
105+
# Run everything
106+
bash governance_artifacts/run_runnable_assurance.sh
107+
```
108+
109+
> Sandbox note: compile circuits with `--O0` if circom raises a `SystemTimeError`
110+
> during constraint simplification (a known clock-skew issue in some containers).
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package fairness.credit_decision
2+
3+
import rego.v1
4+
5+
# GC-IR obligation ob-ecoa-adverse-reason-codes (governance_artifacts/zk/gcir_obligation_example.yaml):
6+
# Adverse, fully-automated credit decisions MUST carry >=2 approved reason codes.
7+
# Regimes: ECOA, GDPR Art. 22, EU AI Act Art. 13.
8+
#
9+
# This is the `rego` emission target of the GC-IR obligation. The cross-target
10+
# harness (zk/gcir_harness.py) runs the SAME fixtures through this rule, through
11+
# the Circom witness (SRC-fair-1), and against the TLA+ AdverseGate fixture
12+
# expectations; any disagreement fails the build.
13+
14+
# Approved reason-code set (data.approved_reason_codes in GC-IR).
15+
approved_reason_codes := {"RC01", "RC02", "RC03", "RC04", "RC05", "RC06", "RC07"}
16+
17+
default allow := false
18+
19+
# allow == the decision is COMPLIANT with the obligation.
20+
# Non-adverse or non-fully-automated decisions are out of scope -> compliant by default.
21+
allow if {
22+
not in_scope
23+
}
24+
25+
allow if {
26+
in_scope
27+
count(input.decision.reason_codes) >= 2
28+
every rc in input.decision.reason_codes {
29+
approved_reason_codes[rc]
30+
}
31+
}
32+
33+
in_scope if {
34+
input.decision.outcome == "adverse"
35+
input.decision.automation_level == "full"
36+
}
37+
38+
deny contains "insufficient_reason_codes" if {
39+
in_scope
40+
count(input.decision.reason_codes) < 2
41+
}
42+
43+
deny contains "unapproved_reason_code" if {
44+
in_scope
45+
some rc in input.decision.reason_codes
46+
not approved_reason_codes[rc]
47+
}

governance_artifacts/rego/high_impact_credit.rego

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package gsifi.ai.credit
22

3-
default allow = false
3+
import rego.v1
4+
5+
default allow := false
46

57
allow if {
68
input.model.use_case == "credit_underwriting"
@@ -12,7 +14,7 @@ allow if {
1214
not input.incident_flags.active
1315
}
1416

15-
deny[msg] if {
17+
deny contains msg if {
1618
input.model.use_case == "credit_underwriting"
1719
not input.human_review.completed
1820
msg := "Human review required for high-impact credit decisions"
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package gsifi.ai.credit
2+
3+
import rego.v1
4+
5+
# Backs ECOA / GDPR Art. 22 / EU AI Act Art. 13 obligations: high-impact credit
6+
# underwriting requires human review, >=3 reason codes, fairness within
7+
# equal-opportunity delta, verified lineage, and no active incident.
8+
9+
base := {
10+
"model": {"use_case": "credit_underwriting"},
11+
"risk_tier": "high",
12+
"human_review": {"completed": true},
13+
"explainability": {"reason_codes_count": 3},
14+
"fairness": {"equal_opportunity_delta": 0.02},
15+
"data": {"lineage": {"verified": true}},
16+
"incident_flags": {"active": false},
17+
}
18+
19+
test_allow_when_all_conditions_met if {
20+
allow with input as base
21+
}
22+
23+
test_deny_message_when_no_human_review if {
24+
not allow with input as object.union(base, {"human_review": {"completed": false}})
25+
count(deny) > 0 with input as object.union(base, {"human_review": {"completed": false}})
26+
}
27+
28+
test_block_when_too_few_reason_codes if {
29+
not allow with input as object.union(base, {"explainability": {"reason_codes_count": 2}})
30+
}
31+
32+
test_block_when_fairness_delta_exceeded if {
33+
not allow with input as object.union(base, {"fairness": {"equal_opportunity_delta": 0.05}})
34+
}
35+
36+
test_block_when_lineage_unverified if {
37+
not allow with input as object.union(base, {"data": {"lineage": {"verified": false}}})
38+
}
39+
40+
test_block_when_incident_active if {
41+
not allow with input as object.union(base, {"incident_flags": {"active": true}})
42+
}

governance_artifacts/rego/release_gate.rego

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package sentinel.release
22

3+
import rego.v1
4+
35
default allow := false
46

57
allow if {
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package sentinel.release
2+
3+
import rego.v1
4+
5+
# Backs OSCAL release-gate semantics: deny-by-default on high-impact autonomous
6+
# release unless containment ENFORCED + dual-control quorum + signed bundle +
7+
# required controls (Omni-Sentinel safety + SR 11-7 validation) are satisfied.
8+
9+
compliant_input := {
10+
"model": {"risk_tier": "high"},
11+
"controls": {"SAF-OMNI-001": true, "MOD-SR11-7-VAL": true},
12+
"supervision": {"quorum": 2},
13+
"containment": {"mode": "ENFORCED"},
14+
"signatures": {"bundle_verified": true},
15+
}
16+
17+
test_allow_when_all_controls_met if {
18+
allow with input as compliant_input
19+
}
20+
21+
test_deny_when_quorum_insufficient if {
22+
not allow with input as object.union(compliant_input, {"supervision": {"quorum": 1}})
23+
count(deny) > 0 with input as object.union(compliant_input, {"supervision": {"quorum": 1}})
24+
}
25+
26+
test_deny_when_containment_not_enforced if {
27+
not allow with input as object.union(compliant_input, {"containment": {"mode": "MONITOR"}})
28+
}
29+
30+
test_deny_when_validation_control_false if {
31+
not allow with input as object.union(
32+
compliant_input,
33+
{"controls": {"SAF-OMNI-001": true, "MOD-SR11-7-VAL": false}},
34+
)
35+
}
36+
37+
test_deny_when_signatures_unverified if {
38+
not allow with input as object.union(compliant_input, {"signatures": {"bundle_verified": false}})
39+
}
40+
41+
test_default_deny_on_empty_input if {
42+
not allow with input as {}
43+
count(deny) > 0 with input as {}
44+
}

0 commit comments

Comments
 (0)