{"platform":"CAIN TRUST FABRIC","deployment":"studio","mode":"enforce","enforcement":{"fabric_master_switch":true,"stages":{"identity":{"enforcing":true,"note":"a revoked principal is always a denial"},"authorization":{"enforcing":true,"note":"entitlement, tier and agent budget are always enforced by the gateway, independently of the Fabric switch"},"policy":{"enforcing":true,"note":"OPA. Enforced by the gateway on the request path regardless of the Fabric switch."},"risk":{"enforcing":true,"patterns_loaded":18,"note":"adversarial-fuzzer blocklist, enforced by the gateway on the MCP tool-call path regardless of the Fabric switch. It matches fragments discovered by fuzzing campaigns against this deployment -- it is not a general prompt-injection classifier, and with patterns_loaded at 0 it blocks nothing."},"actionproof":{"enforcing":true,"note":"Z3 plan verification. Only blocks when the Fabric switch is also on and the tenant has an ActionProof profile."},"intent":{"enforcing":false,"note":"records why the caller says it is acting. Off by default: requiring it rejects any call that does not declare an intent, which breaks integrations written before the field existed. Undeclared intent is recorded as not_configured, never as allow."},"verification":{"enforcing":true,"note":"structural check that the submitted plan is well-formed and every step names a tool. Runs locally, so it cannot be unavailable. Distinct from actionproof, which proves a well-formed plan against a constraint profile."},"approval":{"enforcing":false,"note":"human-in-the-loop hold. Off by default, because a hold nobody is watching is an outage. With no rule configured this reports not_configured -- 'no human gate exists' and 'a human approved this' are different facts. This stage is what makes the REQUIRE_APPROVAL verdict reachable."},"consensus":{"enforcing":true,"configured":true,"cluster":"cain-mr-01 (4 PBFT replicas, 3 regions)","note":"orders each recorded decision through the live PBFT cluster; no quorum commit -> deny (fail closed), never 'unavailable'. The cluster receives only the decision id, a SHA-256 commitment and the preliminary verdict. Verify a decision's certificate at /api/v1/live-cluster/qc/{sequence}."},"egress":{"enforcing":true,"note":"action-tool allowlist over the network destinations an action names. Default deny: with any rule configured, an action naming a destination outside the tenant's allowlist is denied, and loopback, link-local, private and cloud-metadata endpoints are denied regardless of rules. A tenant with no rules runs in observe mode (recorded, not blocked) so existing integrations are not broken. Restriction-only: it can never turn a deny into an allow. Manage at /fabric/egress/rules."},"toolargs":{"enforcing":true,"registered_tools":1,"note":"tool-call argument validity: a registered tool's arguments must match its schema and any grounded value must be present in the supplied context; a hallucinated or malformed argument is denied. A tool with no registered schema is observe mode (recorded, not blocked). Schemas load from data/tool_schemas.json. Restriction-only."},"artifacts":{"enforcing":true,"note":"artifact supply-chain attestation and composition risk: verifies tools, skills, and plugins against pinned publisher-signed manifests (preventing rug-pulls and stealth privilege expansion) and evaluates path-aware composition risk across active capabilities. Unpinned artifacts run in observe mode. Manage at /fabric/artifacts/pins."},"mcpgate":{"enforcing":true,"deployment":"studio","note":"records which enforcement boundary the decision lands on, so 'a gateway acted on this' is checkable rather than assumed."},"execution":{"enforcing":true,"note":"records whether the call was permitted to proceed. It does NOT observe the upstream result -- the Fabric decides, it does not watch."},"evidence":{"enforcing":false,"retention_days":90,"note":"records that the decision was written, and names the record. A failed write is reported as unavailable on the decision itself rather than passing silently."}},"chain":["identity","intent","policy","authorization","risk","verification","actionproof","approval","consensus","egress","toolargs","artifacts","mcpgate","execution","evidence"],"decision_schema_version":3,"deployment_provenance":{"source_digest":"4374fd161e005d72a05e9ab67f6de5fc903af28bee91da5855f3351d21c920bc","source_files":1384,"git_commit":"659acb52fa1a627b120a3129dd27b2e5c1581a68","git_commit_meaning":"HEAD of the checkout at start; running code may include uncommitted files","recorded_at_startup":true,"provenance":"computed from the deployed Python sources when the gateway imported this module","not":"proof that the code is correct; independent verification; proof that the running code equals git_commit; a guarantee that the on-disk tree is still identical (the digest is frozen at start)"},"record_integrity":{"per_record_digest":true,"record_signature":true,"guarantee":"signed: every record's digest (all stages, including those after consensus, and the final verdict) is Ed25519-signed by a key kept outside the database, so a database-level edit is detectable even if the digest is recomputed","not":"protection against root on the gateway host (it holds the key and the database), or an append-only external log","public_key":"GET /fabric/decision-signing-key","verify":"GET /fabric/decisions/{id}/integrity"},"note":"The Fabric master switch is ON (the default since 2026-09-27): a denial blocks the call for every tenant that has not opted down to shadow mode (POST /fabric/settings). Stages marked enforcing above are enforced by the gateway's own request path, which predates the Fabric and is unaffected by that switch."},"dependencies":{"actionproof":{"reachable":true,"http_status":200},"agent-id":{"reachable":true,"http_status":200}},"decision_retention_days":90}