|
| 1 | +# Predicate Authority |
| 2 | + |
| 3 | +**Deterministic Authority for AI Agents: Secure the "Confused Deputy" with your existing Identity stack.** |
| 4 | + |
| 5 | +[](LICENSE) |
| 6 | +[](https://pypi.org/project/predicate-authority/) |
| 7 | +[](https://pypi.org/project/predicate-contracts/) |
| 8 | + |
| 9 | +`predicate-authority` is a production-grade pre-execution authority layer that binds AI agent identity to deterministic state. It bridges standard IdPs (Entra ID, Okta, OIDC) with runtime verification so every sensitive action is authorized, bounded, and provable. |
| 10 | + |
| 11 | +## Why Predicate Authority? |
| 12 | + |
| 13 | +Most agent security fails because it relies on static API keys or broad permissions. Predicate introduces short-lived mandates that are cryptographically tied to: |
| 14 | + |
| 15 | +- `state_hash` (what state the agent is in), |
| 16 | +- `intent_hash` (what action it intends to perform), |
| 17 | +- policy constraints and required verification labels. |
| 18 | + |
| 19 | +This closes the confused-deputy gap where an agent can misuse delegated credentials. |
| 20 | + |
| 21 | +- **Bridge, don't replace**: leverage existing enterprise identity and governance. |
| 22 | +- **Fail-closed by design**: deny before execution when state/intent/policy checks fail. |
| 23 | +- **Deterministic binding**: authority is tied to runtime evidence, not only identity. |
| 24 | +- **Provable controls**: each decision can emit signed proof events for audit pipelines. |
| 25 | + |
| 26 | +### Why not just use IdP directly? |
| 27 | + |
| 28 | +You should still use Entra/Okta/OIDC for identity and token issuance. `predicate-authority` adds the runtime control layer those systems do not provide by default for AI agents: |
| 29 | + |
| 30 | +- pre-execution allow/deny checks right before each sensitive action, |
| 31 | +- binding authority to current `state_hash` and `intent_hash`, |
| 32 | +- optional required verification labels from runtime checks (currently web-agent only via [predicate-sdk](https://github.com/PredicateSystems/sdk-python) integration), |
| 33 | +- fail-closed local enforcement and per-decision proof events. |
| 34 | + |
| 35 | +In practice: IdP answers **who the principal is**, while `predicate-authority` answers **whether this exact action is allowed right now in this state**. |
| 36 | + |
| 37 | +## Repository Components |
| 38 | + |
| 39 | +| Package | Purpose | |
| 40 | +| --- | --- | |
| 41 | +| `predicate_contracts` | Shared typed contracts and protocols (`ActionRequest`, `PolicyRule`, evidence, decision/proof models). | |
| 42 | +| `predicate_authority` | Runtime authorization engine (`PolicyEngine`, `ActionGuard`, mandate signing, proof ledger, telemetry emitter). | |
| 43 | +| `examples/` | Browser/MCP/HTTP guard examples using the local Phase 1 runtime. | |
| 44 | + |
| 45 | +## Phase 1 Status |
| 46 | + |
| 47 | +Implemented in this repository: |
| 48 | + |
| 49 | +- local pre-execution `ActionGuard.authorize(...)` and `enforce(...)`, |
| 50 | +- signed local mandates with TTL (`LocalMandateSigner`), |
| 51 | +- policy evaluation with deny precedence and required verification labels, |
| 52 | +- typed [predicate-sdk](https://github.com/PredicateSystems/sdk-python) integration adapter (`predicate_authority.integrations`), |
| 53 | +- OpenTelemetry-compatible trace emitter (`OpenTelemetryTraceEmitter`), |
| 54 | +- pytest coverage for core authorization, mandate, integration, and telemetry flows. |
| 55 | + |
| 56 | +Planned in upcoming phases: |
| 57 | + |
| 58 | +- `predicate-authorityd` sidecar for token lifecycle and local kill-switch, |
| 59 | +- enterprise IdP bridge hardening (Entra/Okta/OIDC adapters), |
| 60 | +- hosted governance control plane. |
| 61 | + |
| 62 | +## Installation |
| 63 | + |
| 64 | +```bash |
| 65 | +pip install predicate-authority |
| 66 | +``` |
| 67 | + |
| 68 | +For shared contracts directly: |
| 69 | + |
| 70 | +```bash |
| 71 | +pip install predicate-contracts |
| 72 | +``` |
| 73 | + |
| 74 | +## Quick Start (Phase 1 API) |
| 75 | + |
| 76 | +```python |
| 77 | +from predicate_authority import ActionGuard, InMemoryProofLedger, LocalMandateSigner, PolicyEngine |
| 78 | +from predicate_contracts import ( |
| 79 | + ActionRequest, |
| 80 | + ActionSpec, |
| 81 | + PolicyEffect, |
| 82 | + PolicyRule, |
| 83 | + PrincipalRef, |
| 84 | + StateEvidence, |
| 85 | + VerificationEvidence, |
| 86 | +) |
| 87 | + |
| 88 | +guard = ActionGuard( |
| 89 | + policy_engine=PolicyEngine( |
| 90 | + rules=( |
| 91 | + PolicyRule( |
| 92 | + name="allow-payment-submit", |
| 93 | + effect=PolicyEffect.ALLOW, |
| 94 | + principals=("agent:payments",), |
| 95 | + actions=("http.post",), |
| 96 | + resources=("https://finance.example.com/transfers",), |
| 97 | + ), |
| 98 | + ) |
| 99 | + ), |
| 100 | + mandate_signer=LocalMandateSigner(secret_key="dev-secret"), |
| 101 | + proof_ledger=InMemoryProofLedger(), |
| 102 | +) |
| 103 | + |
| 104 | +request = ActionRequest( |
| 105 | + principal=PrincipalRef(principal_id="agent:payments"), |
| 106 | + action_spec=ActionSpec( |
| 107 | + action="http.post", |
| 108 | + resource="https://finance.example.com/transfers", |
| 109 | + intent="submit transfer request #1234", |
| 110 | + ), |
| 111 | + state_evidence=StateEvidence(source="backend", state_hash="state-hash-abc"), |
| 112 | + verification_evidence=VerificationEvidence(), |
| 113 | +) |
| 114 | + |
| 115 | +decision = guard.authorize(request) |
| 116 | +if not decision.allowed: |
| 117 | + raise RuntimeError(f"Authority denied: {decision.reason.value}") |
| 118 | +``` |
| 119 | + |
| 120 | +See runnable examples in: |
| 121 | + |
| 122 | +- `examples/browser_guard_example.py` |
| 123 | +- `examples/mcp_tool_guard_example.py` |
| 124 | +- `examples/outbound_http_guard_example.py` |
| 125 | + |
| 126 | +## Security: Local Kill-Switch Path |
| 127 | + |
| 128 | +The current Phase 1 runtime supports fail-closed checks and local proof emission. The sidecar model (`predicate-authorityd`) is planned to provide instant local revocation and managed token lifecycle for long-running production agents. |
| 129 | + |
| 130 | +## Release |
| 131 | + |
| 132 | +- CI workflow: `.github/workflows/phase1-ci-and-release.yml` |
| 133 | +- Release guide: `docs/pypi-release-guide.md` |
| 134 | + |
| 135 | +Publish order is always: |
| 136 | + |
| 137 | +1. `predicate-contracts` |
| 138 | +2. `predicate-authority` |
| 139 | + |
| 140 | +## License |
| 141 | + |
| 142 | +Dual-licensed under **MIT** and **Apache 2.0**: |
| 143 | + |
| 144 | +- `LICENSE-MIT` |
| 145 | +- `LICENSE-APACHE` |
| 146 | + |
| 147 | +--- |
| 148 | + |
| 149 | +Copyright (c) 2026 Predicate Systems Inc. |
0 commit comments