···178178 // Call com.atproto.server.getServiceAuth on the user's PDS
179179 // Request 5-minute expiry (PDS may grant less)
180180 // exp must be absolute Unix timestamp, not relative duration
181181+ // Note: OAuth scope includes #atcr_hold fragment, but service auth aud must be bare DID
181182 expiryTime := time.Now().Unix() + 300 // 5 minutes from now
182183 serviceAuthURL := fmt.Sprintf("%s%s?aud=%s&lxm=%s&exp=%d",
183184 pdsEndpoint,
+3-3
pkg/auth/oauth/client.go
···133133 // OCI artifact manifests (for cosign signatures, SBOMs, attestations)
134134 "blob:application/vnd.cncf.oras.artifact.manifest.v1+json",
135135 }
136136+137137+ scopes = append(scopes, "transition:generic")
136138137139 // In test mode: use transition:generic (local dev with test PDS)
138140 // In production: use rpc scope for service auth
139139- if testMode {
140140- scopes = append(scopes, "transition:generic")
141141- } else {
141141+ if !testMode {
142142 scopes = append(scopes, fmt.Sprintf("rpc:com.atproto.repo.getRecord?aud=%s#atcr_hold", did))
143143 }
144144