Skip to content

Fix tower invitations and add email invites - #52

Merged
turnercore merged 9 commits into
mainfrom
fix/tower-invitations
Sep 19, 2026
Merged

turnercore merged 9 commits into
mainfrom
fix/tower-invitations

Conversation

@turnercore

@turnercore turnercore commented Sep 19, 2026

Copy link
Copy Markdown
Owner

What this fixes

  • replaces fragile Server Action invitation calls with a stable API route
  • returns useful duplicate/self-invite errors
  • accepts either username or email in the invite field
  • adds existing users immediately by username or email
  • sends a Supabase invite email when the email does not belong to an existing account
  • signs invited users in from the Supabase invite link and routes them directly to the tower
  • repairs membership during invite acceptance if the recipient clicks before the original membership write finishes
  • uses a signed, recipient-bound, expiring invitation token for that acceptance repair
  • fixes first-load profile creation for newly invited users
  • uses deterministic, bounded initial usernames instead of insecure randomness
  • keeps tower membership updates atomic and enforces owner/admin invitation permissions in PostgreSQL
  • fixes the duplicate Realtime presence subscription crash in the share UI
  • restores API validation/CSRF regression coverage and adds auth-only email invitation SQL coverage

Database

These migrations have already been applied to Supabase project estelamtbxdegwijmyha:

  • repair_tower_invitations
  • email_tower_invitations
  • repair_email_invitation_acceptance

The normal public invitation RPCs are SECURITY INVOKER functions backed by narrowly scoped helpers in the non-exposed clocktower_private schema. The email acceptance-repair RPC is callable only by service_role; anon and authenticated have no execute permission.

Deployment

The database changes are backwards-compatible with the previous app code.

The hosted Supabase Invite email template itself is unchanged. Supabase's default invite email works with this flow. Custom wording such as "You're invited to this tower. Click to join." can be configured in Authentication → Email Templates → Invite.

Verification

Final verification on the PR branch:

  • Next.js 16 production build: passed
  • TypeScript production typecheck: passed
  • Jest: 10 suites, 78 tests passed
  • PostgreSQL invitation regression suite: 35 assertions passed
  • CodeQL: no new alerts in PR code
  • Vercel preview deployment: passed
  • live Supabase acceptance RPC grants/search_path verified
  • Supabase security advisor shows no new findings from these invitation migrations

No test invitation emails were sent to real users during verification.

Copilot AI lite review requested due to automatic review settings September 19, 2026 10:42
@vercel

vercel Bot commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
clocktower Ready Ready Preview Sep 19, 2026 11:05am UTC

Comment thread clocktower/tools/actions/fetchSupabaseProfileSA.ts Fixed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Unresolved moderate issues remain in invitation ordering, identifier handling, UI refresh, username length, SQL coverage, and route-test coverage.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 4 Medium severity

Open (4)
What changed in this PR

This PR modernizes tower invitations with API/RPC-backed username and email invites, Supabase invite emails, invite-link routing, and profile initialization fixes.

Changes:

  • Adds secure invitation lookup and membership helpers.
  • Supports existing-user and email invitation flows.
  • Updates sharing UI, authentication handling, API contracts, and tests.
File Summary and review notes
clocktower/​types/​supabase.ts Adds invitation RPC types.
clocktower/​tools/​actions/​fetchSupabaseProfileSA.ts Returns newly created profiles. Moderate (2 votes): generated usernames can exceed the 30-character contract.
clocktower/​supabase/​migrations/​20260919114000_email_tower_invitations.sql Adds secure email lookup and membership helpers. Moderate (2 votes): new auth-only paths lack SQL regression coverage.
clocktower/​lib/​towers/​inviteUserToTower.ts Implements username/email invitations. Moderate (3 votes): usernames containing @ are misclassified. Moderate (2 votes): email delivery precedes membership creation.
clocktower/​lib/​towers/​inviteUserToTower.test.ts Tests invitation service behavior.
clocktower/​lib/​towers/​invite-user-request.ts Updates the invitation request contract.
clocktower/​lib/​towers/​invite-user-request.test.ts Tests invitation requests.
clocktower/​lib/​supabase/​admin.ts Adds the server-side admin client.
clocktower/​components/​layout/​ShareTowerPopover.tsx Updates the sharing UI. Moderate (1 vote): email invites do not refresh the displayed membership state.
clocktower/​components/​layout/​actions/​inviteUserToTowerSA.test.ts Updates legacy action tests.
clocktower/​components/​auth/​InviteAuthRedirect.tsx Handles invite-link sessions and routing.
clocktower/​app/​page.tsx Mounts invite-link handling.
clocktower/​app/​api/​towers/​[id]/​invitations/​route.ts Provides the stable invitation endpoint.
clocktower/​app/​api/​towers/​[id]/​invitations/​route.test.ts Tests endpoint behavior. Moderate (1 vote): prior CSRF, validation, ignored-field, and failure-path coverage was removed.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread clocktower/lib/towers/inviteUserToTower.ts Outdated
Comment thread clocktower/lib/towers/inviteUserToTower.ts Outdated
Comment thread clocktower/tools/actions/fetchSupabaseProfileSA.ts Outdated
@turnercore
turnercore merged commit 99295b1 into main Sep 19, 2026
6 checks passed
@turnercore
turnercore deleted the fix/tower-invitations branch September 19, 2026 13:09
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.

3 participants