Per-Request Policy Evaluation, Short-Lived Token Re-Attestation, and the Deny-by-Default Authorization Service
A fleet spends real effort proving who a workload is. SPIFFE gives it a name, SPIRE mints it a one-hour certificate, mTLS checks the name at the handshake. The 05-20 lesson built that whole chain. Then the 07-08 lesson made the credential short, so a stolen key dies on its own before it can be replayed for long.
Both lessons stop one step early. They authenticate. They answer who is calling. Neither answers the question that decides whether the call is allowed to do what it asks: may this caller, holding this identity, perform this action on this resource, right now. That question is authorization, and in a multi-agent fleet it cannot be answered once at login and cached for the session. It has to be answered on every request, because the thing being authorized changes on every request even when the caller does not.
This lesson is the consuming layer. The identity is the input; the decision is the output; the discipline that connects them is re-verify on the interval, not once, the same pattern this morning's synthesis read off the markets, where a driver's charge decays inside a single session and the correct read at the open is the wrong read at the close. A grant is a reading. It holds only for the window its premise survives.
Name the two operations before reasoning about them together.
Authentication establishes identity. It answers who are you and produces a verified principal: a SPIFFE ID from an mTLS handshake, a validated token subject, a service-account name. Authentication is expensive to do and cheap to cache, because identity is stable across a session.
Authorization establishes permission. It answers may you do this specific thing and produces a decision: permit or deny. Authorization is cheap to do and dangerous to cache, because permission depends on the action, the resource, and the current state of policy, none of which are stable across a session.
The failure that follows every conflation of the two has a name in the literature. Sam Newman calls it the confused deputy: a component with legitimate authority is tricked into using that authority on behalf of a caller who lacks it (Newman, Building Microservices 2e, Ch 11, pp. 471–472). A gateway authenticates a user at the edge, then makes downstream calls under its own powerful identity, and a downstream service sees only the gateway's authority, not the user's. The gateway proved who the user was and then forgot to carry what the user was allowed to do. Authentication succeeded. Authorization was skipped, and the deputy acted on a permission no one ever checked.
The deeper root is what Newman calls implicit trust (p. 455): the assumption that a request arriving from inside the perimeter is a request that has already been vetted. Inside a multi-agent fleet there is no inside. Agent A calls agent B calls tool C calls agent D, and each hop is a fresh request that inherits the identity of the link above without inheriting a decision about the link above. If B trusts A's call because it came from B's own cluster, B has cached a grant that was never made.
The move is to pull the decision out of every service and into one component that does nothing else, then call it on every request. Coin it plainly: the policy decision point, one authority that, given a principal, an action, a resource, and the live context, returns permit or deny and a reason. Every service becomes a policy enforcement point: it does not decide, it asks, and it obeys.
Three properties make this continuous rather than a login-time gate.
The decision point returns deny unless a rule explicitly permits. A new action, a new resource, a rule that failed to load all resolve to deny. The fleet fails closed; whoever adds a capability adds its grant in the open.
The enforcement point calls on each request, not once per session. The token proves the caller is still who they were; the policy call proves the caller may still do what they ask. Different questions, different lifetimes.
The identity is not permanent either. The SPIRE cert expires in an hour, the 07-08 lease in minutes, so a revoked principal stops authenticating at the next renewal. Auth runs on the credential's clock; authz on the request's clock.
Read the three together. Deny-by-default sets the floor. Per-request evaluation sets the cadence. Re-attestation bounds how long any single proof survives. A grant becomes an act only when all three agree in the same instant.
Take a live shape from the fleet. A research agent (Jupi-class, QuantOps) drafts a directional thesis and calls a broker tool to size a paper position. The broker tool, in turn, calls the capital-ledger service to record intent. Three hops, three seams.
Under implicit trust, the broker tool authenticates the research agent once, then calls the ledger under the broker's own service identity. The ledger sees a request from the broker, a trusted internal component, and writes. The research agent has just moved the ledger through a deputy that never checked whether a research agent may touch capital state. Under the Capital-Zero invariant, it may not; only a Sovereign-fired grant may. The deny that should have fired never got the chance, because no one asked.
Now wire the decision point in. Each hop carries the original principal forward as a scoped token, not the hop's own identity. At the ledger, the enforcement point calls:
decision = pdp.evaluate(
principal = "spiffe://hedronite/quantops/jupi",
action = "capital.ledger.write",
resource = "paper-account/jupi",
context = { mode: "paper", sovereign_grant: none, ts: now }
)
Policy says: capital.ledger.write on any account requires mode == paper OR a present sovereign_grant; and the principal's role must include capital-writer. Jupi is in paper mode, so the write to the paper account permits. The same call against a live account, with sovereign_grant: none, denies, not because Jupi is the wrong identity, but because the action-on-resource-in-context is not permitted, and deny-by-default holds the line the deputy would have crossed. The reason string names the failed clause, and the audit log records who asked, what they asked, and why the answer was no.
The 05-20 workload-identity lesson produced the principal this lesson consumes, the SPIFFE ID that arrives verified at the enforcement point. The 07-08 rotation lesson produced the short lease that makes re-attestation real, so revocation actually takes effect at the next renewal rather than waiting out a long-lived token. The 06-24 RBAC-and-audit lesson produced two things this lesson leans on: the role model the policy evaluates against, and the telemetry pipeline that records every permit and deny. Continuous authorization is what those three arcs were building toward. Identity without authorization is a name with no gate; a lease with no per-request check is a fresh key opening a door no one is watching.
Today's Dev lesson takes this decision to the browser and makes the type system enforce it: TypeScript models an unauthorized call as a value that cannot be constructed, so the deny-by-default floor becomes a compile error rather than a runtime check. Today's Cert lesson takes it into Kubernetes: the bound ServiceAccount token and the TokenRequest API are how a pod re-attests its identity on the platform's clock, and RBAC plus the authorization webhook are the cluster's own policy decision point evaluating every call to the API server. One discipline, three seats: prove who you are on the credential's clock, prove you may act on the request's clock, deny unless told otherwise.
Authentication is a photograph; authorization is a turnstile. A photograph taken at the door is worthless at the vault if no turnstile stands between them. Build the decision point that does nothing but answer permit-or-deny, call it on every request, deny by default, and let the identity re-attest on its own short clock. The grant you re-check on the interval is the grant that is still true when the action fires. The grant you cached at login is a reading whose charge has already decayed.
Examine the seams in your own fleet. At each one, name what is being granted, and name what asks may this happen before it happens. Where nothing asks, a deputy is waiting to be confused.