Summary
The current `welcome-page-guard` (in `packages/pds-core/src/welcome-page-guard.ts`) decides when to bounce by mirroring upstream @atproto/oauth-provider's internal render-decision logic:
- Zero-binding short-circuit (rows 1–4).
- Stored PAR `prompt === 'login'` short-circuit (row 5).
- Mirrored `matchesHint` filter + `provider.checkLoginRequired(b)` over the candidate set (rows 6/9).
This works, but it is brittle by construction: any upstream change to the render-decision logic (new triggers, changed precedence, additional UIs) will silently bypass the guard until we notice and update our mirror. Surfaced in PR #129 review.
Proposed approach
Replace the pre-emptive logic with response-rewrite detection, the same pattern already in use elsewhere in pds-core:
- `createChooserEnrichmentMiddleware` (`packages/pds-core/src/chooser-enrichment.ts`)
- `createUpstreamFaviconMiddleware` (`packages/pds-core/src/upstream-favicon.ts`)
- `installCssInjectionMiddleware` (`packages/pds-core/src/lib/client-css-injection.ts`)
Wrap the response on `/oauth/authorize` and `/account*`. Inspect the rendered HTML for unreachable-UI markers (welcome-page React hydration payload, sign-in-view password `<input type="password">`, page title, etc.). On match, swallow the response body and emit a 303 redirect to auth-service with stale device cookies cleared.
That detection looks at the page upstream actually decided to render, instead of trying to predict it.
Why not in PR #129
PR #129 extends the existing pre-emptive guard to cover three additional rows. Rewriting it as response-rewrite is a separate piece of work that would also replace the existing welcome-page check (rows 1–4). Worth doing as a unified refactor, not bundled into the row-5/6/9 fix.
Definition of done
- The guard no longer reads `provider.requestManager.store.readRequest` or calls `provider.checkLoginRequired` to make its bounce decision.
- All nine taxonomy rows in `features/session-reuse-bugs.feature` still pass.
- The unit test file `welcome-page-guard.test.ts` is rewritten / replaced to drive the new middleware.
Summary
The current `welcome-page-guard` (in `packages/pds-core/src/welcome-page-guard.ts`) decides when to bounce by mirroring upstream @atproto/oauth-provider's internal render-decision logic:
This works, but it is brittle by construction: any upstream change to the render-decision logic (new triggers, changed precedence, additional UIs) will silently bypass the guard until we notice and update our mirror. Surfaced in PR #129 review.
Proposed approach
Replace the pre-emptive logic with response-rewrite detection, the same pattern already in use elsewhere in pds-core:
Wrap the response on `/oauth/authorize` and `/account*`. Inspect the rendered HTML for unreachable-UI markers (welcome-page React hydration payload, sign-in-view password `<input type="password">`, page title, etc.). On match, swallow the response body and emit a 303 redirect to auth-service with stale device cookies cleared.
That detection looks at the page upstream actually decided to render, instead of trying to predict it.
Why not in PR #129
PR #129 extends the existing pre-emptive guard to cover three additional rows. Rewriting it as response-rewrite is a separate piece of work that would also replace the existing welcome-page check (rows 1–4). Worth doing as a unified refactor, not bundled into the row-5/6/9 fix.
Definition of done