diff --git a/pkg/auth/servicetoken.go b/pkg/auth/servicetoken.go index dc2a8e2..ecce7d3 100644 --- a/pkg/auth/servicetoken.go +++ b/pkg/auth/servicetoken.go @@ -58,8 +58,18 @@ var ErrAppPasswordInsufficientScope = errors.New("app-password lacks scope to mi // isInsufficientScopeError reports whether a PDS error body signals that the // presented app-password session is scoped too narrowly to call getServiceAuth. -// The reference PDS and tranquil both return the atproto error name -// "InsufficientScope" (paired with 403) for read-only app passwords. +// +// The name and status come from one observed case: issue #26, a read-only app +// password on tranquil (pds.sqrl.systems). createSession succeeded, then +// getServiceAuth answered 403 InsufficientScope. Read-only app passwords appear +// to be tranquil-specific — its choices are Full Access, Read Only and Post +// only — and the reference PDS has no such thing, so this branch cannot be +// reproduced against one and is untested end to end. +// +// It is safe either way, because this only adds a branch. A PDS reporting the +// same condition under a different name falls through to the generic non-200 +// path and the 503 that shipped before, so a wrong guess costs the better +// message, not correctness. func isInsufficientScopeError(body []byte) bool { return atprotoErrorName(body) == "InsufficientScope" } diff --git a/test/e2e/batch09-token.sh b/test/e2e/batch09-token.sh new file mode 100755 index 0000000..3fc5344 --- /dev/null +++ b/test/e2e/batch09-token.sh @@ -0,0 +1,111 @@ +#!/usr/bin/env bash +# batch09-token.sh — the /auth/token surface that unit tests cannot reach. +# +# handler_test.go covers the request shapes in-process. What it cannot show is +# which form a real client actually picks, and whether the deliberate +# non-RFC 401 keeps those clients moving instead of looping. +# +# Covers: +# b25aee3 — serve the OAuth2 POST form; refresh_token refused 401, not 400 +# 08121f3 — indexed device auth is O(1) (the legacy scan is checked separately, +# see LEGACY BACKFILL below — it is destructive and opt-in) +# +# Findings this script encodes, so a re-run re-checks them: +# * Docker (29.7.2) and skopeo (1.22.2) use the GET form even when they hold a +# credential. containerd (2.3.3) is the only client here that POSTs, which +# is the client b25aee3 was written for — it ate a 405 before this commit. +# * There is no anonymous branch in the handler at batch 09. Anonymous GET is +# a 401 here; the anonymous path arrives with val/10-anonpull. +# +# Read-only app passwords (9d4ad84) are NOT covered: the reference PDS has no +# such thing, so the 403 InsufficientScope path is unreproducible here. See +# pkg/auth/servicetoken.go for what is and is not known about it. +# +# Usage: ./test/e2e/batch09-token.sh +# ATCR_E2E_DESTRUCTIVE=1 ./test/e2e/batch09-token.sh # + legacy scan +set -uo pipefail + +APPVIEW=${ATCR_APPVIEW_URL:-http://127.0.0.1:5000} # never localhost: that 307s +A="$APPVIEW/auth/token" +SERVICE=${ATCR_E2E_SERVICE:-127.0.0.1} +HANDLE=${ATCR_E2E_HANDLE:-evan.jarrett.net} +REPO=${ATCR_E2E_REPO:-$HANDLE/valtest} + +pass=0; fail=0 +check() { # check