Skip to content

feat(auth): pending-approval page + role-gated routes - #13

Merged
joaocarvoli merged 3 commits into
mainfrom
feat/pending-approval-page-and-audit-fixes
May 18, 2026
Merged

feat(auth): pending-approval page + role-gated routes#13
joaocarvoli merged 3 commits into
mainfrom
feat/pending-approval-page-and-audit-fixes

Conversation

@joaocarvoli

Copy link
Copy Markdown
Member

Summary

Closes the broken-chat experience for pending users. Today, after signup a user gets a session, lands on `/chat`, and only discovers they have no access when they try to send a message and the backend 403s. This PR adds:

  • New `/pending-approval` page: friendly explainer rendered through `AuthShell`, with a "Check approval status" button that re-pulls roles and a sign-out fallback.
  • `requireAppRole` gate on `ProtectedRoute` (default true): when the user has no app role and isn't a platform admin, redirect to `/pending-approval`. Opted out for `/profile` and `/settings` so pending users can still edit their display name / locale.
  • Auto-redirect once approved: `PendingApproval` watches for roles to appear and bounces to `/` the moment a role lands.
  • Focus-based role refresh in `bootstrapAuth`: when an admin approves a pending user, they see the change the next time they tab back into the app — no hard reload required.
  • Signup auto-refreshes roles: pairs with the backend auto-approve toggle so that, when the app has `auto_approve=true`, the user goes straight into the app instead of bouncing through `/pending-approval`.
  • i18n: strings added to en, pt-BR, es, fr.

Test plan

  • `npx tsc --noEmit` clean
  • `npm run lint` — no new warnings
  • `npm run build` succeeds
  • Manual, auto-approve OFF: sign up → log in → land on `/pending-approval` (not `/chat`). Approve via tripod-console. Tab back to the app → land on `/welcome`.
  • Manual, auto-approve ON: with tripod-console flipped on for translation-helper, sign up a fresh user → land on `/welcome` directly (no `/pending-approval` flash).
  • Manual: signed-in pending user can still open `/profile` and `/settings`.
  • Manual: platform admin's access is unchanged (they bypass the role gate).

Dependent PRs

🤖 Generated with Claude Code

joaocarvoli and others added 3 commits May 17, 2026 23:25
Standalone page rendered through AuthShell. Tells the user their access
is queued for admin review, offers a "Check approval status" button that
re-pulls their roles, and a sign-out fallback. Routes them straight to
"/" the moment a role lands so a freshly-approved user doesn't get stuck
on this screen.

Strings in en, pt-BR, es, fr. The page is not yet wired to anything —
the route gate that redirects pending users here lands in the next
commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Pending users used to land on /chat with a session, then hit a 403 the
moment they tried to send a message. Add a requireAppRole prop to
ProtectedRoute (default true) that, when the user has no roles for this
app and isn't a platform admin, redirects to /pending-approval.

Opted out for /profile and /settings so pending users can still update
their display name / locale; /admin/prompts continues to use
requirePlatformAdmin which already bypasses the role check.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Two small wins for the approval flow:

- signup() now calls refreshMyRoles() after queuing the access request.
  When the app has auto_approve on, the role is granted server-side
  during the request — fetching it back in here means the user goes
  straight into the app instead of bouncing through /pending-approval.

- bootstrapAuth() installs a one-time focus listener that re-pulls the
  user's roles whenever they tab back into the app. So when an admin
  approves a pending user, they see the change the next time they look
  at the tab — no hard reload required.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@joaocarvoli
joaocarvoli merged commit f481db0 into main May 18, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant