Skip to content

docs: agent identity & permissions, plus SDK version/import fixes - #80

Merged
lakhansamani merged 7 commits into
mainfrom
docs/sdk-version-and-import-path-audit
Aug 6, 2026
Merged

docs: agent identity & permissions, plus SDK version/import fixes#80
lakhansamani merged 7 commits into
mainfrom
docs/sdk-version-and-import-path-audit

Conversation

@lakhansamani

@lakhansamani lakhansamani commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Docs for 2.4.0, alongside authorizerdev/authorizer#742.

New: Agent Identity & Permissions

enterprise/agent-identity covers what Authorizer does with the agent identity a
delegated token carries — which nothing documented before:

  • perms(agent) ∩ perms(user), and why an intersection rather than either half
    alone (Confused Deputy on one side, a fictional "on behalf of" on the other)
  • The opt-in is declaring type agent in the model, with no flag, because
    checking agent:<id> against a model lacking the type errors rather than
    returning false — a flag would turn an unprepared model into a full outage
  • One user, many agents; multi-hop uses the immediate actor only
  • Calling Authorizer's own API (exchange for Authorizer's URL as the resource)
  • Why an explicit user cannot shed the agent half
  • A revocation matrix separating what stops a token here from what stops it at
    a downstream resource server
  • Audit attribution, and the not_enforced metric to alert on

Corrections

enterprise/token-exchange claimed delegated tokens are stateless with the TTL as
the only bound. True at the resource server; no longer true at Authorizer's own API,
which now checks the originating session. Left uncorrected, that reads as a
revocation guarantee nobody has.

core/authorization gains the agent subject alongside user: and
service_account:.

Also

Stale SDK versions and the Go import path across getting-started, migration, and the
Go/Python/Flutter SDK pages (the original scope of this branch).

Verified: npm run build clean, no broken links or anchors.

- authorizer-go example imported the pre-/v2 path while the same page
  documents `go get .../v2`; Go silently resolves it to an untagged
  pseudo-version of the old module, so the example runs against a
  different SDK than the one installed
- admin.md claimed the generated proto types live under `internal/` and
  are unimportable externally; they moved to the public
  authorizer-proto-go module in authorizer-go#23
- getting-started and the v1-to-v2 guide still pinned
  authorizer-js@^3.0.0-rc.1 / authorizer-react@^2.0.0-rc.1; js is at
  3.3.0 and react v2 has been stable since 2.0.0
- introduction listed authorizer-react v2.1.0, which was never published
- `pip install authorizer-py` resolves to 0.2.0, which predates server
  2.4.0: no skip_mfa_setup, and paginated admin queries still send the
  renamed PaginatedRequest type. Use --pre until 0.3.0 is stable
- Flutter docs pointed readers at a placeholder repo for "usage
  instructions"; introduction linked a community fork that 404s
@netlify

netlify Bot commented Aug 4, 2026

Copy link
Copy Markdown

Deploy Preview for authorizerdev-docs ready!

Name Link
🔨 Latest commit 96e01aa
🔍 Latest deploy log https://app.netlify.com/projects/authorizerdev-docs/deploys/6a745117e962340008673767
😎 Deploy Preview https://deploy-preview-80--authorizerdev-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

Token exchange documented how a delegated token is minted but not what
Authorizer does with the agent identity it carries. Covers the
perms(agent) ∩ perms(user) intersection, the model-declares-agent opt-in
and why it is not a flag, one-user-many-agents, multi-hop (immediate actor
only), calling Authorizer's own API, the revocation matrix, audit
attribution, and the metric to alert on when enforcement is off.

Also corrects token-exchange's "stateless, TTL is the only bound" — true
at the resource server, no longer true at Authorizer's own API.
The page pointed at with-agent-delegation, which demonstrates scope
attenuation and the act chain — not the permission intersection this page
is about. with-agent-permissions covers every claim made here.
@lakhansamani lakhansamani changed the title docs(sdks): fix stale SDK versions and Go import path docs: agent identity & permissions, plus SDK version/import fixes Aug 6, 2026
Both pages still described at-rest crypto as keyed by --jwt-secret, and
the flag that now keys it appeared nowhere in the docs. An RS*/ES*
deployment upgrading to 2.4.0 refuses to start, with no page saying why.

Adds the advisory for 2.2.1..2.4.0-rc.13, where the fallback produced a
constant compiled into the open-source binary for asymmetric
deployments: a database copy yields TOTP seeds and every outstanding OTP
digest, password-reset codes included. Remediation is rotation plus
forced re-enrolment — there is no re-encryption path — so it needs to be
read before upgrading, not after.

Also corrects the quoted decrypt-failure error, which named a flag the
server no longer mentions.
The delegated series shipped with no operator documentation, so the one
label that distinguishes 'grant the agent a tuple' from 'the user
genuinely lacks access' was undiscoverable — and not_enforced, which
means agent traffic is arriving unconstrained, appeared nowhere at all.
It is silent by construction: the request succeeds and the response says
nothing, so a metric nobody knows about is the only signal.
All four were on pages this branch added or touched, so they are ours.

- The revocation matrix implied symmetry between deactivating the SUBJECT
  and deactivating the AGENT. Only the subject is checked for liveness
  (delegated_access_token.go delegationSubjectIsLive); nothing checks the
  actor. Disabling an agent blocks the next exchange but not the token it
  minted a moment ago — a reader would have treated that as immediate
  containment. Deleting its tuples is the lever that works now.
- token-exchange said a resource server may validate delegated tokens via
  /oauth/introspect. It cannot: introspection gates on aud == the
  authenticated caller's client_id, and a delegated token's aud is the
  RFC 8707 resource URI, so it always answers {"active": false}. Anyone
  building on that line would reject every valid token.
- The delegated metric's outcome table implied all four outcomes occur on
  both operations. list_permissions intersects object sets rather than
  folding a per-check decision, so it only ever emits not_enforced.
- "costs no per-request read" was wrong: the model-id lookup runs on
  every delegated request; only the type enumeration is cached.
The intersection decides which resources an agent may reach; scope
decides which operations it may call. The second gate shipped with no
documentation, so the two new scopes were undiscoverable and the
fail-closed default would have read as a bug.

Includes why first-party tokens are deliberately not gated — the
asymmetry is the whole reason the delegated claim is a boundary.
@lakhansamani
lakhansamani merged commit 22a3375 into main Aug 6, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant