Skip to content

Mint narrows a token and refreshes past the cache - #294

Merged
czpython merged 1 commit into
mainfrom
mint-scopes
Aug 21, 2026
Merged

Mint narrows a token and refreshes past the cache#294
czpython merged 1 commit into
mainfrom
mint-scopes

Conversation

@czpython

Copy link
Copy Markdown
Owner

Two mint gaps close:

token = await connection.mint_access_token(scopes=("profile.read",))   # narrower ceiling
token = await connection.mint_access_token(cached=False)               # full lifetime

A narrower token for untrusted compute

scopes asks the provider for a subset of the connection's grant on the
refresh (RFC 6749 §6) — a server-side ceiling for a token that leaves the
host, e.g. into a sandbox. The ask must be inside the connection's granted
scopes, or OauthRefreshError.

A down-scoped token must never serve a full-scope caller, or the reverse:
the token cache and the refresher election key on the scope set as well as
the connection id, so each (connection, scope set) elects its own single
refresher and keeps its own cache entry. A provider that echoes a scope
different from the ask fails loudly instead of caching a token the caller
must not hold.

A full-lifetime token

cached=False skips the cache read — a consumer provisioning a long-lived
context is never served a cache-tail token with minutes left. It still
takes the refresh lock, still commits a rotated refresh token, and refills
the cache for later callers.

Eviction and disconnect sweep the scope-variant keys with one prefix scan.
Consent is untouched: scopes there remain the grant ceiling from the
declared union. MCP's mint path is unchanged — it passes no scopes.

mint_access_token(scopes=...) asks the provider for a subset of the
connection's grant (RFC 6749 §6) — a server-side ceiling for a token
handed to untrusted compute. The ask must be inside the grant, the token
cache and the refresher election key on the scope set as well as the
connection, and a provider that echoes a different scope than the ask
fails loudly instead of caching a token the caller must not hold.
cached=False skips the cache read for a full-lifetime token while keeping
the single-refresher election and refilling the cache. Eviction sweeps the
scope-variant keys.
@czpython
czpython merged commit 036394e into main Aug 21, 2026
1 check passed
@czpython
czpython deleted the mint-scopes branch August 21, 2026 05:20
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