The executable part
The identity test, and how to fail it
This is the check we run before any agentic system goes live, and it is three steps because it has to be runnable by somebody who did not build it.
# The rule every tool call is built to satisfy
#
# An agent may read nothing its caller could not read unaided.
#
# WRONG — the agent holds the rights. Works in the demo, fails the review:
# client = ErpClient(token=SERVICE_ACCOUNT_TOKEN) # broad, shared, unattributable
# rows = client.query(user_question) # whose permissions? ours.
#
# RIGHT — the call carries the caller, and the source system decides:
# caller = verify(request.headers["Authorization"]) # the user's own OIDC token
# client = ErpClient(on_behalf_of=caller) # exchanged, not substituted
# rows = client.query(user_question) # the ERP applies ITS rules
#
# The test that this is real, and the one to run before go-live:
# 1. Pick a document user A may read and user B may not.
# 2. Ask the agent for it as B, through the product, not through a test harness.
# 3. The answer must be a refusal, and the refusal must appear in the audit log
# with B's identity on it.
#
# If step 3 produces the document, you do not have an identity layer. You have a
# service account with a chat interface in front of it.
Token exchange rather than token substitution is the part that is easy to get subtly wrong: an exchanged token still represents the user, a substituted one represents the application and silently widens the blast radius.