Connect your AI governance platform
Connect a governance platform by giving it one configuration source and read access to the audit trail. The platform writes the rules it owns. Pistra records the decisions those rules make with their control IDs.
You need an identity provider that can issue the platform a token and an admin API listener it can reach.
1. Give the platform an identity
Section titled “1. Give the platform an identity”Give the platform a JWT from a trusted issuer. Map its subject to the
governance role:
issuers: - name: acme-governance url: https://governance.acme.example
admin: listen: ":9900" issuers: - issuer: acme-governance audience: pistra-admin roles: claim: sub map: "aigp:acme": [governance]A client-credentials grant against your own IdP works the same way, and the subject is then the client id. See Restrict what an admin caller can do for issuers, audiences and what a machine principal looks like in the trail.
2. Grant it one source, and reading
Section titled “2. Grant it one source, and reading”The source is a Cedar resource, and so is every object in it, so one line of policy says what the platform may write:
@id("governance-owns-its-source")permit( principal in Role::"governance", action in [Action::"putConfigSource", Action::"deleteConfigSource"], resource in Resource::"config/aigp-acme");
@id("governance-reads")permit(principal in Role::"governance", action in Action::"read", resource);That is the whole grant. The platform cannot mint a key, cannot touch
default, the file’s own source, and cannot write any other team’s
document. An attempt is refused and recorded as admin.authz naming
the platform’s subject.
3. Write the policy source
Section titled “3. Write the policy source”The platform writes a deployment document, the same shape a node file names, as YAML or JSON, with the precondition that says what it means: create, or replace at the revision it last read.
# aigp-acme.yaml (written by acme governance, contract 12)access_rules: - name: finance-no-frontier-models at: [llm] condition: 'key.metadata.team == "finance" && model == "gpt-4o"' action: deny message: finance may not use frontier models until the AI-07 review closes controls: [acme:AI-07, eu-ai-act:art-50] - name: no-file-writes-from-agents at: [mcp] condition: 'method == "tools/call" && name.startsWith("write_")' action: deny controls: [acme:AG-03, nist-ai-rmf:manage-2.4]Create the source with an If-None-Match precondition:
curl -sS -X PUT https://gw.example/admin/v1/config/sources/aigp-acme \ -H "Authorization: Bearer $PLATFORM_JWT" \ -H 'Content-Type: application/yaml' \ -H 'If-None-Match: *' \ --data-binary @aigp-acme.yamlcontrols is the field this integration turns on. It is a list of
identifiers the platform assigned, in whatever taxonomy it uses. The
gateway checks their shape, non-empty, no whitespace, no duplicates,
and never their meaning. Put the platform’s own control id first if it
has one, and the framework citations after it. The order is kept.
What the source may hold. Anything name-keyed composes beside the
other sources: access_rules, profiles, budgets. Two sources
defining the same rule name is refused, naming both. That is the
ownership model. Nothing inspects a document to check a writer stayed
in its lane. See
Manage the configuration through the API.
What it may not. Providers and credentials belong to the platform
team’s source, and the composition refuses a second definition. Node
keys, listen, cluster, admin, cannot travel in a source at all.
Guardrail rules are the exception. guardrails is one block with
one owner, because its rules and its detectors read each other through
the same tuning. A second source cannot add a rule to it. A guardrail
rule declares controls like an access rule does, so the
platform’s controls reach guardrail decisions either way, but the rule
itself is written by whoever owns the block. If the platform is to own
guardrail policy, it owns the whole block, detectors included, and the
security team’s document gives it up.
Replacing. Read first, write back at the revision you read:
etag=$(curl -sSI https://gw.example/admin/v1/config/sources/aigp-acme \ -H "Authorization: Bearer $PLATFORM_JWT" | grep -i '^etag:' | cut -d' ' -f2 | tr -d '\r')curl -sS -X PUT https://gw.example/admin/v1/config/sources/aigp-acme \ -H "Authorization: Bearer $PLATFORM_JWT" -H 'Content-Type: application/yaml' \ -H "If-Match: $etag" --data-binary @aigp-acme.yamlA 412 means somebody wrote in between, a second replica of the platform, usually. Re-read and apply again. There is no unconditional write.
4. Read decisions from the audit trail
Section titled “4. Read decisions from the audit trail”The trail is where the platform’s “runtime enforcement” becomes a
record rather than a claim. It arrives at your collector on the
pistra/audit scope, and three record kinds close the loop:
The write. A successful PUT produces a config.source.write
record: target is the source name, actor.subject is the platform’s
subject, and source_revision is the revision the write produced,
the same number the sources listing and the revision history report
for it. That is the join key: contract 12 became revision 41 at
14:02:07.
{"event":"config.source.write","outcome":"allowed","actor":{"kind":"oidc","name":"aigp:acme","issuer":"acme-governance","subject":"aigp:acme"},"target":"aigp-acme","reason":"put","revision":118,"source_revision":41}The decisions. Every refusal by an access rule is a request.auth
record, every guardrail verdict a guardrail.decision record, and each
names the rule and carries its controls in the rule’s order:
{"event":"request.auth","outcome":"denied","actor":{"kind":"virtual_key","name":"finance-app"},"target":"chat_completions","rule":"finance-no-frontier-models","controls":["acme:AI-07","eu-ai-act:art-50"],"reason":"policy_denied"}controls is also duplicated out of the body as a log attribute, so
the collector query the platform runs is every record where
controls contains acme:AI-07, not every record, then parse. The
record never carries content. The text that matched is not in the
trail, and neither is the prompt.
The proof. Each record is a link in a per-node signed chain. The platform, or an auditor it hands the export to, verifies what the collector stored against the heads the cluster witnessed:
curl -sS https://gw.example/admin/v1/audit/heads \ -H "Authorization: Bearer $PLATFORM_JWT" > heads.jsonpistra audit verify -heads heads.json export.jsonlverify reports, per chain, anything altered, removed, moved, forged,
or cut short of a witnessed head. It proves what the node’s key
signed. Nothing the platform stores can be edited into that. See
The audit trail for why a gap in it is
evidence and a gap in a log is noise.
What the platform can now say
Section titled “What the platform can now say”For contract 12, the platform can say which revision it became, and when. It can list every decision its rules made since, each mapped to a control by the rule that decided it, without joining against the configuration in force at the time. It can say that the set of decisions is complete and unaltered, checked against a key the platform does not hold. Those three statements are the runtime half of an evidence collection. The platform keeps the other half.
What is not here
Section titled “What is not here”- Discovery. The platform’s registry says what was declared. The
gateway knows what was used. Today that is the metrics,
pistra_tokens_totalby route, provider, model and token type, MCP calls by server and tool, with the key on the trace (pistra.key) and in the budget ledger, rather than an inventory endpoint shaped for a registry. - Framework content. No control library, no mapping, no interpretation of a control id. The platform owns the taxonomy, and pistra carries the reference.
- Guardrail rules from a second source. See step 3.
Related
Section titled “Related”- Manage the configuration through the API, sources, preconditions, history, the ownership model.
- Restrict what an admin caller can do, issuers, roles, Cedar.
- Test your rules before they ship, the platform can pin what its contract decides before writing it.
- The audit trail and Architecture.