Make revoking an agent and locking a dashboard actually revoke and lock
An MCP access token is a stateless JWT good until it expires, so deleting the client row revoked nothing already handed out — on the MCP endpoint or on the REST API, which takes the same token directly. Both doors now look the client up by the `client_id` the token has always carried, so tokens already in circulation are held to it too. A dashboard's `locked` setting stopped the client drawing a control and nothing else; the server took a publish from a panel showing it anyway. It now bounds the panel's write scope, resolved live where a flow drives the flag, exactly as the client resolves it. Reads are untouched — read-only is not blind — and so is a querying chart's request, which is how that tile reads rather than something anyone touched. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CL9zvnnvcp1mvA8o7impxk
This commit is contained in:
@@ -43,10 +43,10 @@ function confirms(live: unknown, sent: unknown): boolean {
|
||||
* disabled — a dashboard that silently swallows a press looks broken rather
|
||||
* than locked.
|
||||
*
|
||||
* ponytail: this is a read-only surface, not an authorisation boundary. The
|
||||
* server still takes a publish from a panel credential whose dashboard says
|
||||
* locked, because the credential's own allowlist is what bounds it. Making it
|
||||
* a real lock means carrying the flag into `_panel_may`.
|
||||
* Not the boundary, though — the affordance. A panel credential is bounded by
|
||||
* the same flag on the server (`api/deps.py`, `_panel_writable`), which is
|
||||
* what refuses a publish from a screen that asks anyway; this is what keeps a
|
||||
* control from looking pressable when it is not.
|
||||
*
|
||||
* Its own module rather than `widgets.tsx`, which every widget file is
|
||||
* imported *by*: a control drawn in a file of its own can only reach this
|
||||
|
||||
Reference in New Issue
Block a user