Release scope
These are release candidates until the exact versions appear in Release Status. Package versions are independent.
Go
v0.4.1 and x402 0.4.1 have no new source changes in this release.
Do not infer TypeScript/Python enforce() behavior from their version numbers.
See the release validation report for package,
installed-artifact, Docker and production browser results and their limits.
Upgrade the service first
Defaultenforce() now reads GET /v1/revocations/status. Upgrade the
auth service and apply its startup migrations before upgrading clients.
The hosted service already serves these endpoints. Self-hosted installations
must not disable REVOCATION_FEED_ENABLED or exclude the client’s developer
with REVOCATION_FEED_DEVELOPER_IDS while relying on online/feed checks.
An unavailable status endpoint denies the call; it never falls back offline.
The status budget is 6,000 calls/minute per developer and per client address.
It is shared across instances; it is not 6,000 per agent or per SDK process.
For high-volume execution use feed with an operational feed connection and
staleness monitoring. Feed failures and stale state fail closed.
Bind each relying party
Configure the exact resource audience from the verified request/service configuration, not from an untrusted agent-provided value:aud but no configured expected audience is denied with
token_invalid / audience_unconfigured. A different or missing token
audience when one is expected is denied with audience_mismatch.
String and array audiences match exactly; URL prefixes and trailing-slash
normalization are not accepted. Tokens without aud and clients without an
expected audience retain their earlier semantics.
audienceCheck: 'off' / audience_check="off" is an explicit migration
opt-out, not a safe production posture. It cannot be combined with a
configured audience. Audience failures remain denied even in permissive mode.
Gateway route-level audience overrides the global setting. Adapters accept
audience in their configuration; both expose named audience errors.
Legacy claim compatibility
Legacy token-claim aliases remain enabled with deprecation warnings in TypeScript 0.8 and Python 0.7. This release does not flip that compatibility default. After migrating old grants, setlegacyClaims: false or
legacy_claims=False to require standard claims and typ: at+jwt.
See the claim migration guide.
Supply trusted amounts
For every call on a connector covered bycapped:N, supply a finite amount
in the cap’s agreed units. This includes read-only calls on that connector;
use a validated zero when the operation genuinely has no monetary amount.
Omitted amounts now deny with cap_exceeded / amount_missing.
Malformed caps and invalid amounts also fail closed.
wrapTool and enforceMiddleware accept
extractAmount; Python wrap_tool accepts extract_amount. Extractor
failures refuse execution. TypeScript extractors may be asynchronous.
See the executable wrapper examples and
Python examples.
capsMode: 'warn' / caps_mode="warn" records tolerated denials in
wouldDenyAll / would_deny_all; the existing singular field remains the
first denial. Warn/off settings intentionally reduce protection and must not
be represented as spend-limit enforcement. Python Strands and the FastAPI
helper do not extract monetary amounts; call enforce() directly with a
validated amount before executing capped operations.
Choose current-state enforcement deliberately
The default client is nowonline. A per-call mode can only tighten the
client setting: offline < feed < online. Trying to weaken it throws before
execution. An explicit offline client is the migration opt-out, but accepts
cryptographically valid revoked grants until expiry.
verifyGrantToken() / verify_grant_token() alone remain local
cryptographic verification. Gateway, adapters and Strands default verified
mode do not call enforce() and do not gain online revocation merely by
installing the newer SDK. Put current-state enforcement at the service
boundary; Strands online mode uses the configured client’s enforcement.
See Revocation.
MCP Auth 2 to 3
MCP Auth 3 requires a revocation configuration on resource guards and Express/Hono middleware: pass a checker withisTokenRevoked(jti) backed by
the authorization server’s storage. Omitting it refuses startup.
revocations: 'none' is an explicit warned opt-out, not revocation enforcement.
Use Postgres or Redis shared storage for multi-instance deployments. Memory
storage is evaluation-only. Run the package migrations, provision database
drivers, use HTTPS issuer/resource/redirect URLs and verify the consent/callback
flow before moving traffic. Codes and callback bindings are single-use.
The package includes a consent page, but it does not replace Grantex’s live
principal passkey ceremony. Follow the complete deployment guide.
Verification checklist
- Install exact versions in a clean environment and check package metadata.
- Verify an approved grant succeeds for the correct audience and amount.
- Reject a different audience, a missing amount, an excessive amount and a forged token before any side effect.
- Revoke the grant and confirm the next online call is denied.
- Confirm a status outage denies execution, and a per-call offline downgrade is refused.
- For MCP Auth, restart a replica between authorization and exchange, and verify replay and cross-client/tenant rejection.
- Confirm passkey enrollment, live approval/denial and portable evidence against the intended public RP origin.