···11+# authViewAll aud-enforcement inconsistency — Bluesky OAuth repro
22+33+Minimal reproduction of a Bluesky authorization-server bug where scope
44+enforcement for RPCs in the `app.bsky.authViewAll` permission set is
55+inconsistent: some RPCs are authorized against the service-fragmented aud
66+(`did:web:api.bsky.app#bsky_appview`), others against the bare aud
77+(`did:web:api.bsky.app`). The client has no way to satisfy both from one
88+`include:` scope.
99+1010+## Setup
1111+1212+```bash
1313+pnpm install
1414+pnpm dev
1515+```
1616+1717+Visit http://127.0.0.1:3000/, enter your atproto handle, approve the
1818+consent screen, and you'll land on `/test`. The page calls six RPCs with
1919+an identical agent and identical scope and reports which ones succeed.
2020+2121+## Observed
2222+2323+```
2424+atproto include:app.bsky.authViewAll?aud=did:web:api.bsky.app%23bsky_appview
2525+```
2626+2727+produces:
2828+2929+| Lexicon | Status | Detail |
3030+|---|---|---|
3131+| `app.bsky.actor.getProfile` | OK | |
3232+| `app.bsky.feed.getTimeline` | OK | |
3333+| `app.bsky.feed.getAuthorFeed` | OK | |
3434+| `app.bsky.graph.getLists` | FAIL | `Missing required scope "rpc:app.bsky.graph.getLists?aud=did:web:api.bsky.app"` |
3535+| `app.bsky.notification.listNotifications` | FAIL | `Missing required scope "rpc:app.bsky.notification.listNotifications?aud=did:web:api.bsky.app"` |
3636+| `app.bsky.feed.getFeedGenerator` | FAIL | `Missing required scope "rpc:app.bsky.feed.getFeedGenerator?aud=did:web:api.bsky.app"` |
3737+3838+Every RPC in the list above is declared in the
3939+[`app.bsky.authViewAll` permission set](https://lexicon.garden/lexicon/did:plc:4v4y5r3lwsbtmsxhile2ljac/app.bsky.authViewAll/llms.txt),
4040+which uses `inheritAud: true` — so all of them should be granted at the
4141+aud we passed to `include:`. The agent also sends
4242+`atproto-proxy: did:web:api.bsky.app#bsky_appview` on every call, so the
4343+service endpoint is unambiguously specified.
4444+4545+## Why we can't work around it with rpc scopes
4646+4747+Explicit per-RPC `rpc:` scopes would satisfy enforcement but display to
4848+users as broad permission requests on the consent screen, which is poor
4949+UX for an otherwise-narrow read-only app.
5050+5151+## Files
5252+5353+- `src/server.ts` — the entire OAuth client + test harness: in-memory
5454+ stores, ephemeral ES256 keypair per run, routes `/`, `/login`,
5555+ `/callback`, `/test`, `/jwks.json`, `/client-metadata.json`.