Policy Contracts: SARAC and Payload Shapes
Blueprint · ← Foundation overview · Policy contracts · Token & session →
The PEP does not send natural language to the PDP. It maps session claims and tool proposals into a fixed four-field contract so every verdict is replayable.
THE CLAIM
SARAC (subject · action · resource · context) is the only shape the PDP evaluates. If your PEP sends prose, you do not have PGAR.
The four fields
| Field | Source | Carries |
|---|---|---|
| subject | IdP claims in agentic app session | identity, roles, emts, limits |
| action | Tool proposal name | lookup_beneficiary, retrieve_documents |
| resource | Proposal target | beneficiary id, corpus, account |
| context | Runtime state + proposal args | amount, sanctions_status, approval |
Example: wire initiation
{
"subject": {
"sub": "officer-123",
"roles": ["corporate_banking_officer", "payments_initiator"],
"emts": {
"payments.wire.initiate": true
},
"limits": {
"wire.auto_approved": 25000
}
},
"action": "initiate_wire",
"resource": {
"type": "wire_payment",
"beneficiary_id": "bene-acme-441",
"source_account": "acct-operating-4412"
},
"context": {
"amount": 47500,
"sanctions_status": "clear",
"approval": null
}
}
After step-up, the same request returns with context.approval set and the PDP re-evaluates.
Example: RAG retrieval
{
"subject": {
"sub": "officer-123",
"doc_entitlements": ["policy-engine:read"]
},
"action": "retrieve_documents",
"resource": {
"type": "corpus",
"id": "policy-engine"
},
"context": {
"query": "wire limits EU corporate",
"classification_ceiling": "internal"
}
}
See RAG retrieval.
Mapping rules (PEP responsibility)
- Never infer subject from model text. Subject comes from validated token claims only.
- Action = tool name from manifest, not paraphrased intent.
- Resource = normalized target (ids, not display names the model invented).
- Context = proposal args + prior tool results the PDP needs (sanctions, approval, amount).
Failure classes
- Schema drift: PEP sends fields PDP no longer accepts
- Subject substitution: claims from wrong session attached
- Resource ambiguity: model string passed through without resolution
- Context leakage: PII in context field not redacted in audit
Automated checks
assert pdp_request.has_fields(["subject", "action", "resource", "context"])
assert subject.sub == session.claims.sub
assert action in tool_manifest.names
assert audit.redacted_context == redact(context)
Trace fields
pep_request_id, subject.sub, action, resource.type, resource.id, context_hash, pdp_policy_version
See: PEP Enforcement · Policy-Governed Agent Runtime § contracts