mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-09-27 20:54:20 +00:00
A PDS that grants fewer scopes than requested produced a session that worked until the first write it wasn't allowed, which the PDS answered with a 403. We classified that 403 as a revoked session, deleted it, and returned a 500 "unknown error"; Docker's retries then failed with "no session found". Logging in again got the same partial grant, so the user looped (#30, an older tranquil PDS that left a scope off its consent screen). - Login refuses a partial grant. The callback checks the granted scopes cover what was requested and, if not, deletes the new session and shows a page listing what's missing. It runs before the old-session cleanup, so a refused login leaves a working session alone. "Try again" goes back through the login page so return_to (e.g. the device page) holds. - MissingScopes compares scopes by what they grant, not by spelling: an include: expanded or echoed back, collections split or reordered, wildcards, transition:generic. Extra grants are fine. It replaces the exact-match ScopesMatch at login, on resume, and in the boot sweep, which now evicts only sessions missing something. - A 403 never deletes a session. InsufficientScope comes out of isAuthError and IsSessionInvalidError, and isOAuthError no longer treats every 403 as dead. PDSes spell this differently (tranquil: InsufficientScope, the reference PDS: ScopeMissingError), so nothing keys on the name. - A PDS 403 on a manifest or tag write reaches Docker as DENIED with the PDS's own reason. The UI write handlers (star, tag and manifest delete, repo avatar and description) answer 403 with the reason too. - The OAuth error, missing-permissions and success pages render in the site layout via an injected PageRenderer; pkg/auth/oauth keeps its inline templates as a fallback. Verified live against a reference PDS with a forced partial grant: login refused, an existing session kept, a push denied twice on the same session with the PDS's message, the boot sweep evicting the partial session, and a full login pushing normally. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>