5.3 KiB
5.3 KiB
Phase 24: Public Access & Infrastructure - Context
Gathered: 2026-04-09 Status: Ready for planning
## Phase BoundaryRemove the login wall from read-only routes so anyone can browse the global item catalog, public setups, and user profiles without logging in. Add rate limiting to all public endpoints. Auth only required for write operations and personal data access.
## Implementation DecisionsAuth Boundary Redesign
- D-01: Keep
requireAuthas default middleware on/api/*. Expand the existing allowlist of public GET routes that skip auth (current pattern: regex checks insrc/server/index.ts). - D-02: Categories stay auth-gated — they are user-scoped organizational data. Public browsing uses tags (already public via GET
/api/tags). - D-03: Public setup views include the owner's category names as read-only display context (data already returned by GET
/api/setups/:id/public).
Client-Side Routing for Anonymous Users
- D-04: Expand the
isPublicRoutecheck in__root.tsxto include catalog routes (/global-items/*), public setup views, and the root/. Keep login redirect only for truly private routes (/collection,/settings,/threads). - D-05: No changes needed for TotalsBar — it's already only shown in collection views, not in the global header.
- D-06: When an anonymous user attempts a write action (add to collection, create thread, etc.), show an inline popup/modal saying "To manage your own collection, sign in or sign up" with links to both. Do NOT hard-redirect to
/login— this is hostile to new users who haven't signed up yet.
Rate Limiting Strategy
- D-07: Apply rate limiting to all public GET endpoints. Current rate limiter (
src/server/middleware/rateLimit.ts) needs new tiers — the existing 5 req/15 min is only appropriate for OAuth. - D-08: Same rate limits for authenticated and anonymous users — no exemptions. Tune limits based on real usage data over time.
Claude's Discretion
- Rate limit numbers: Claude picks appropriate limits per endpoint type (browse, search, detail). Start with reasonable defaults, expect tuning later.
Loading Experience for Visitors
- D-09: Fire-and-forget auth check — render the page immediately, check
/api/auth/mein the background. Anonymous users see content right away with no spinner or redirect. When auth resolves, UI updates silently (FAB appears, write actions enable). - D-10: Show a "Sign in" button in the top-right corner on all public pages for anonymous visitors. When authenticated, replace with the existing user menu.
<canonical_refs>
Canonical References
Downstream agents MUST read these before planning or implementing.
Auth & Middleware
src/server/middleware/auth.ts— CurrentrequireAuthimplementation (API key, OAuth bearer, OIDC session)src/server/middleware/rateLimit.ts— Current rate limiter (in-memory Map, needs new tiers for public endpoints)src/server/index.ts— Route registration and auth middleware skip logic (lines 121-140)
Client Routing & Layout
src/client/routes/__root.tsx— Root layout withisPublicRoutecheck, auth loading spinner, login redirect logicsrc/client/hooks/useAuth.ts— Auth state hook (useAuth) used throughout client
Requirements
.planning/REQUIREMENTS.md— PUBL-01 through PUBL-05, INFR-01
</canonical_refs>
<code_context>
Existing Code Insights
Reusable Assets
requireAuthmiddleware — well-structured, supports API key + OAuth + OIDC. No changes to its internals needed — just control when it's applied.rateLimitmiddleware — functional but needs configurable tiers (currently hardcoded 5/15min). Structure is reusable.useAuthhook — returns{ user, authenticated }. Already used throughout client for conditional rendering.UserMenucomponent — exists for authenticated users. Anonymous "Sign in" button will be its counterpart.
Established Patterns
- Auth skip in
index.tsuses regex path matching — extend this list for new public routes. - Client
isPublicRouteis a simple pathname check — extend with additional prefixes. - Public data endpoints already exist: GET
/api/global-items, GET/api/tags, GET/api/users/:id/profile, GET/api/setups/:id/public.
Integration Points
__root.tsxline 121-145: Auth loading/redirect logic — needs rework to render immediately instead of spinner-then-redirect.FabMenuvisibility already gated onisAuthenticated— will naturally hide for anonymous visitors.- Write action buttons across components need to check auth state and show the signup/signin popup instead of the normal action.
</code_context>
## Specific Ideas- The auth-required popup should be welcoming to new users — "sign in or sign up" language, not just "log in". The user emphasized that new user experience matters more than returning user convenience, since returning users will be re-authenticated quickly anyway.
- Tags are the public taxonomy, categories are the private taxonomy. This distinction should be clear in any public-facing UI.
None — discussion stayed within phase scope
Phase: 24-public-access-infrastructure Context gathered: 2026-04-09