BIGF v2.4 Lab: Enforcing Deterministic AI Agent Boundaries with OPA, Rego & RFC 8785
Welcome to the **VITI Labs* hands-on guide.* System prompts are not security boundaries. If an autonomous AI agent is allowed to delegate tasks to sub-agents (Agent-to-Agent / A2A) or execute financial and infrastructur
Welcome to the **VITI Labs* hands-on guide.*
System prompts are not security boundaries. If an autonomous AI agent is allowed to delegate tasks to sub-agents (Agent-to-Agent / A2A) or execute financial and infrastructure mutations, governance must happen outside the LLM at a deterministic runtime gate.
In this lab, you will build and test a complete Business Impact Governance Framework (BIGF v2.4) policy gate using Open Policy Agent (OPA), Rego, and RFC 8785 JSON Canonicalization (JCS).
Architecture: How the Gate Works
Every A2A delegation or actuation request passes through three deterministic stages before execution:
-
Ingress Sanitization (
BIGF-DCS): Raw JSON floats (IEEE 754) are rejected immediately (422 Unprocessable). All currency and threshold values must be encoded as 10-4 fixed-point strings ("2450.5000"). -
Cryptographic Lineage (
RFC 8785JCS +SHA-256): The child contract must carry the exact SHA-256 hash of its canonicalized parent contract (parent_jcs_sha256) to prevent privilege injection or chain tampering. -
Monotonic Narrowing (
B Γ S Γ T): A child agent can never expand its parent's authority:-
B-Axis (Business Impact):
child.max_exposure_fp4 <= parent.max_exposure_fp4and currencies must match. -
S-Axis (Situational State / BIII):
child.min_biii_fp4 >= parent.min_biii_fp4(integrity requirements can only tighten), and live telemetryBIIImust meet the threshold. -
T-Axis (Time & Telemetry):
child.max_ttl_sec <= parent.max_ttl_sec, and the contract must fall strictly within the parent's[iat, exp]window.
-
B-Axis (Business Impact):
Step 1: Project Structure
Create a directory bigf-opa-lab with four files:
bigf-opa-lab/
βββ jcs_hash.py # RFC 8785 canonicalizer & SHA-256 lineage generator
βββ bigf_gate.rego # Deterministic BIGF v2.4 OPA policy
βββ bigf_gate_test.rego# Runnable OPA unit test suite (200 OK, 403 Halt, 422 Reject)
βββ input_valid.json # Sample A2A parent-to-child delegation payload
Step 2: RFC 8785 Canonicalizer (jcs_hash.py)
Before OPA evaluates a delegation chain, the orchestrator or ingress proxy canonicalizes the parent contract per RFC 8785 (sorted keys, zero insignificant whitespace, UTF-8) and verifies parent_jcs_sha256.
import hashlib
import json
def canonicalize_jcs(obj: dict) -> bytes:
"""RFC 8785 deterministic JSON canonicalization (UTF-8)."""
return json.dumps(
obj,
sort_keys=True,
separators=(",", ":"),
ensure_ascii=False
).encode("utf-8")
def compute_jcs_sha256(obj: dict) -> str:
"""Computes the deterministic SHA-256 lineage hash."""
return hashlib.sha256(canonicalize_jcs(obj)).hexdigest()
if __name__ == "__main__":
parent_contract = {
"bigf_version": "2.4.0",
"contract_id": "a2a-parent-9f8e7d6c",
"delegation_depth": 1,
"exp": 1794509100,
"iat": 1794508800,
"invariants": {
"b_axis": {
"currency": "EUR",
"max_exposure_fp4": "10000.0000",
"regulatory_anchor": ["DORA", "NIS2"]
},
"s_axis": {
"allowed_transitions": ["INVOICE_VERIFY", "SETTLEMENT_EXECUTE"],
"min_biii_fp4": "0.8000"
},
"t_axis": {
"max_ttl_sec": 300
}
},
"iss": "ed25519:3b6a27bcceb6a42d62a3a8d02a6f0d73653215771de243a63ac048a18b59da29",
"parent_jcs_sha256": None,
"sub": "agent:procurement-eu-01"
}
print("parent_jcs_sha256:", compute_jcs_sha256(parent_contract))
Step 3: The Deterministic Rego Gate (bigf_gate.rego)
Save this policy as bigf_gate.rego. Notice how Rego enforces fail-closed physics: if any violation fires, allow defaults to false and the gate emits a structured 403 HARD HALT or 422 REJECTED decision record.
package bigf.v2_4.gate
import rego.v1
# Fail-closed default
default allow := false
# 1. BIGF-DCS Ingress Guard: Reject any raw JSON floating-point numbers
dcs_float_violations contains msg if {
some path, val in walk(input)
is_number(val)
# In JSON/Rego, non-integers (e.g., 2450.5) fail exact integer division check
round(val) != val
msg := sprintf("422 BIGF-DCS Type Violation: IEEE 754 float detected at %v", [path])
}
# Fixed-point string parser (10^-4 scaling via to_number on validated strings)
parse_fp4(str) := num if {
is_string(str)
regex.match(`^\d+\.\d{4}$`, str)
num := to_number(str)
}
# 2. Cryptographic Lineage & Depth Checks
violations contains "CRYPTO_AXIS: parent_jcs_sha256 mismatch" if {
input.child.parent_jcs_sha256 != input.computed_parent_jcs_sha256
}
violations contains "CRYPTO_AXIS: Invalid delegation depth increment" if {
input.child.delegation_depth != input.parent.delegation_depth + 1
}
# 3. B-Axis (Business Impact Monotonic Narrowing)
violations contains "B_AXIS: Currency mismatch between parent and child" if {
input.child.invariants.b_axis.currency != input.parent.invariants.b_axis.currency
}
violations contains "B_AXIS: Child exposure exceeds parent ceiling" if {
child_exp := parse_fp4(input.child.invariants.b_axis.max_exposure_fp4)
parent_exp := parse_fp4(input.parent.invariants.b_axis.max_exposure_fp4)
child_exp > parent_exp
}
violations contains "B_AXIS: Requested action amount exceeds child ceiling" if {
req_amt := parse_fp4(input.request.amount_fp4)
child_exp := parse_fp4(input.child.invariants.b_axis.max_exposure_fp4)
req_amt > child_exp
}
# 4. S-Axis (Situational Integrity & Transition Subset)
violations contains "S_AXIS: Child weakened min_biii_fp4 requirement" if {
child_biii := parse_fp4(input.child.invariants.s_axis.min_biii_fp4)
parent_biii := parse_fp4(input.parent.invariants.s_axis.min_biii_fp4)
child_biii < parent_biii
}
violations contains "S_AXIS: Live telemetry BIII below required threshold" if {
live_biii := parse_fp4(input.telemetry.live_biii_fp4)
req_biii := parse_fp4(input.child.invariants.s_axis.min_biii_fp4)
live_biii < req_biii
}
violations contains "S_AXIS: Requested transition not permitted by child contract" if {
not input.request.transition in input.child.invariants.s_axis.allowed_transitions
}
violations contains "S_AXIS: Child transitions exceed parent scope" if {
some t in input.child.invariants.s_axis.allowed_transitions
not t in input.parent.invariants.s_axis.allowed_transitions
}
# 5. T-Axis (Time Window & TTL Bounds)
violations contains "T_AXIS: Child TTL exceeds parent max_ttl_sec" if {
input.child.invariants.t_axis.max_ttl_sec > input.parent.invariants.t_axis.max_ttl_sec
}
violations contains "T_AXIS: Child validity window escapes parent [iat, exp]" if {
input.child.iat < input.parent.iat
}
violations contains "T_AXIS: Child expiration exceeds parent expiration" if {
input.child.exp > input.parent.exp
}
violations contains "T_AXIS: Contract expired at evaluation timestamp" if {
input.telemetry.now_utc > input.child.exp
}
# Final Deterministic Gate Decision
allow if {
count(dcs_float_violations) == 0
count(violations) == 0
}
# Canonical Decision Record (CDR) Output
decision := {
"status": "422 UNPROCESSABLE",
"state": "INGRESS_SCHEMA_VIOLATION",
"privileges_propagated": 0,
"violations": dcs_float_violations,
} if {
count(dcs_float_violations) > 0
} else := {
"status": "403 HARD HALT",
"state": "UNVERIFIED_CRITICAL_STATE",
"privileges_propagated": 0,
"violations": violations,
} if {
count(violations) > 0
} else := {
"status": "200 OK",
"state": "VERIFIED_EXECUTION",
"approved_amount_fp4": input.request.amount_fp4,
"biii_fp4": input.telemetry.live_biii_fp4,
"lineage_sha256": input.child.parent_jcs_sha256,
}
Step 4: Runnable OPA Unit Tests (bigf_gate_test.rego)
Save this test suite alongside bigf_gate.rego to verify all three enforcement outcomes (200 OK, 403 HARD HALT, and 422 UNPROCESSABLE):
package bigf.v2_4.gate_test
import data.bigf.v2_4.gate
import rego.v1
base_input := {
"computed_parent_jcs_sha256": "7d1a54127b222502f5b79b5fb0803061152a44f92b37e23c6527baf665d4da9a",
"parent": {
"delegation_depth": 1,
"iat": 1794508800,
"exp": 1794509100,
"invariants": {
"b_axis": {"currency": "EUR", "max_exposure_fp4": "10000.0000"},
"s_axis": {
"allowed_transitions": ["INVOICE_VERIFY", "SETTLEMENT_EXECUTE"],
"min_biii_fp4": "0.8000"
},
"t_axis": {"max_ttl_sec": 300}
}
},
"child": {
"delegation_depth": 2,
"iat": 1794508810,
"exp": 1794508920,
"parent_jcs_sha256": "7d1a54127b222502f5b79b5fb0803061152a44f92b37e23c6527baf665d4da9a",
"invariants": {
"b_axis": {"currency": "EUR", "max_exposure_fp4": "2450.5000"},
"s_axis": {
"allowed_transitions": ["SETTLEMENT_EXECUTE"],
"min_biii_fp4": "0.8500"
},
"t_axis": {"max_ttl_sec": 110}
}
},
"request": {
"transition": "SETTLEMENT_EXECUTE",
"amount_fp4": "2450.5000"
},
"telemetry": {
"live_biii_fp4": "0.9100",
"now_utc": 1794508850
}
}
# Test 1: Valid attenuated delegation -> 200 OK
test_valid_monotonic_delegation if {
gate.allow with input as base_input
gate.decision.status == "200 OK" with input as base_input
}
# Test 2: Privilege escalation (child tries to raise exposure above parent) -> 403 HARD HALT
test_reject_exposure_escalation if {
bad := json.patch(base_input, [{"op": "replace", "path": "/child/invariants/b_axis/max_exposure_fp4", "value": "15000.0000"}])
not gate.allow with input as bad
gate.decision.status == "403 HARD HALT" with input as bad
}
# Test 3: Telemetry degradation (live BIII drops below 0.8500) -> 403 HARD HALT
test_reject_low_biii if {
degraded := json.patch(base_input, [{"op": "replace", "path": "/telemetry/live_biii_fp4", "value": "0.7900"}])
not gate.allow with input as degraded
gate.decision.status == "403 HARD HALT" with input as degraded
}
# Test 4: IEEE 754 float injected into payload -> 422 UNPROCESSABLE
test_reject_ieee754_float if {
float_payload := json.patch(base_input, [{"op": "replace", "path": "/request/amount_fp4", "value": 2450.5}])
not gate.allow with input as float_payload
gate.decision.status == "422 UNPROCESSABLE" with input as float_payload
}
Step 5: Run It in 10 Seconds
Install the OPA binary (or run via Docker) and execute the test suite:
opa test . -v
Expected output:
bigf_gate_test.rego:
data.bigf.v2_4.gate_test.test_valid_monotonic_delegation: PASS (1.2ms)
data.bigf.v2_4.gate_test.test_reject_exposure_escalation: PASS (0.8ms)
data.bigf.v2_4.gate_test.test_reject_low_biii: PASS (0.7ms)
data.bigf.v2_4.gate_test.test_reject_ieee754_float: PASS (0.9ms)
--------------------------------------------------------------------------------
PASS: 4/4
Four deterministic checks executed in under 4 millisecondsβzero CAB meetings, zero floating-point drift, and cryptographic lineage enforced before a single byte hits production.
Explore the full BIGF v2.4 specification & open-access whitepapers:
Just google it: BIG framework Erkki Laine (available on Zenodo & ORCID under CC BY-NC 4.0) βοΈ
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.