Relationships
#3949 /o/<slug>/billing sends a signed-out visitor to the collective page, or a 404 when private, instead of through login and back like /billing
Opened by stack72 · 10/25/2026· Shipped 10/26/2026
Problem
/billing sends a signed-out visitor to /login?returnUrl=… and back, keeping the query string (routes/billing.tsx, pinned in tests/routes/billing_page_test.ts). /o/<slug>/billing does not:
- a public collective redirects the visitor to
/o/<slug>(canViewConfigis false with no session), so after signing in they are not on the billing page - a private collective returns 404, because
loadCollectivePageContextreturns null when the viewer cannot see it
The upcoming swamp subscription start --collective <slug> (swamp CLI) opens <serverUrl>/o/<slug>/billing, and prints that URL when no browser can be launched. Opening the printed URL in a browser that is not signed in, the usual case over SSH or on a headless box, lands on the wrong page or a 404.
Change
In routes/o/[slug]/billing.tsx, check the session first, before loading the collective page context. With no session user, answer 302 to /login?returnUrl=${encodeURIComponent(/o/${slug}/billing${ctx.url.search})}, the same shape routes/billing.tsx uses.
Redirect before any collective lookup, for every slug: a signed-out visitor gets the same answer whether the collective exists, is private, or is personal, so the redirect reveals nothing a 404 would hide. After sign-in the existing handling applies unchanged:
- a personal collective redirects to
/billing, query kept - a plain member redirects to
/o/<slug> - a collective the viewer cannot see is a 404
- owners, admins and site admins see the billing page
Tests (tests/routes/billing_page_test.ts or a sibling)
- Signed-out visitor on
/o/<slug>/billingof a public collective → 302 to login withreturnUrl=/o/<slug>/billing - Same for a private collective → 302 to login, not 404
- Same for a slug that does not exist → 302 to login
- Query string survives the redirect (e.g.
?license=taken) - Signed-in owner, plain member and personal-collective cases behave exactly as today
Out of scope
/billing itself, the plan picker, and the Personal License form post. The CLI change lands separately in the swamp repo; this issue has no dependency on it.
Shipped
Click a lifecycle step above to view its details.
system commented 10/25/2026, 11:45:48 PM
Classified automatically when this issue was filed.
- Source: Swamp Club
If you feel this classification is incorrect, add a ripple to tell us so.
Sign in to post a ripple.