Skip to content

feat(backend): add clerk.policy.check - #9550

Draft
wyattjoh wants to merge 1 commit into
clerk-agent-approvals/sdk-policy-check/typesfrom
clerk-agent-approvals/sdk-policy-check/check
Draft

feat(backend): add clerk.policy.check#9550
wyattjoh wants to merge 1 commit into
clerk-agent-approvals/sdk-policy-check/typesfrom
clerk-agent-approvals/sdk-policy-check/check

Conversation

@wyattjoh

@wyattjoh wyattjoh commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Description

Chunk 2 of four building clerk.policy in @clerk/backend, on top of #9542. That PR landed the resource types with no consumer; this one registers PolicyAPI and ships check(), which asks whether policy allows an agent's proposed operation and returns the AgentAction recording the answer.

Three things the diff doesn't explain:

  • It returns errors instead of throwing, alone among the package's endpoint classes. A policy decision and a transport failure are different questions and a caller branches on both. The { data, errors } union is restored by unwrapping the legacy wrapper inside the class — buildRequest is untouched.
  • actorId is always caller-supplied, never derived. An inbound token's client id is ambiguous between the party that exchanged it and the party the human authorized, and only the application knows which. The oauth_token arm derives subjectId and authorizedClientId, which its token verifiably names, and accepts neither. There is no session arm.
  • parameters keys reach the API byte-for-byte. The spelling passed to check() is the spelling the field registry and every policy leaf must use; a mismatch is a rule that never matches and never errors.

Reads and waitForApproval follow in the two PRs above.

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

@vercel

vercel Bot commented Aug 25, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview Aug 25, 2026 9:19pm
swingset Ready Ready Preview Aug 25, 2026 9:19pm

Request Review

@changeset-bot

changeset-bot Bot commented Aug 25, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 85a1a3a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 10 packages
Name Type
@clerk/backend Minor
@clerk/astro Patch
@clerk/express Patch
@clerk/fastify Patch
@clerk/hono Patch
@clerk/nextjs Patch
@clerk/nuxt Patch
@clerk/react-router Patch
@clerk/tanstack-react-start Patch
@clerk/testing Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Aug 25, 2026

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@9550

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@9550

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@9550

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@9550

@clerk/electron

npm i https://pkg.pr.new/@clerk/electron@9550

@clerk/electron-passkeys

npm i https://pkg.pr.new/@clerk/electron-passkeys@9550

@clerk/eslint-plugin

npm i https://pkg.pr.new/@clerk/eslint-plugin@9550

@clerk/expo

npm i https://pkg.pr.new/@clerk/expo@9550

@clerk/expo-google-signin

npm i https://pkg.pr.new/@clerk/expo-google-signin@9550

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@9550

@clerk/express

npm i https://pkg.pr.new/@clerk/express@9550

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@9550

@clerk/hono

npm i https://pkg.pr.new/@clerk/hono@9550

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@9550

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@9550

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@9550

@clerk/react

npm i https://pkg.pr.new/@clerk/react@9550

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@9550

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@9550

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@9550

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@9550

@clerk/ui

npm i https://pkg.pr.new/@clerk/ui@9550

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@9550

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@9550

commit: 85a1a3a

Register `policy: new PolicyAPI(request)` on the backend client and ship its
first method. `check` posts an operation to `POST /v1/agent_actions` and returns
the resulting `AgentAction`, never blocking and never throwing on an API
outcome.

`PolicyAPI` returns the native `{ data, errors }` union rather than throwing,
which it obtains by unwrapping the legacy request wrapper locally. The
conversion is total: `requestFn` never throws, the wrapper throws exactly
`ClerkAPIResponseError`, and every field of the errors arm survives that
construction. Anything else reaching the `catch` is rethrown.

`CheckParams` is split into per-`tokenType` arms so the contract's obligations
are compile-time facts. `actorId` is required everywhere and derived nowhere:
an inbound token's client id is ambiguous between the exchanging party and the
authorized client, and only the resource server knows which topology it is in.
The `oauth_token` arm derives `subjectId` and `authorizedClientId`, which its
token verifiably names, and accepts neither. There is no session arm.

`deepSnakecaseBodyParamKeys` stays unset so `parameters` keys reach the API
byte-for-byte — the spelling `check()` uses is the spelling the field registry
and every policy leaf must use.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant