Skip to content

feat(website): claim the pending company on a register confirm link - #36

Merged
kubiknyc merged 3 commits into
mainfrom
feat/welcome-claim-company
Sep 9, 2026
Merged

feat(website): claim the pending company on a register confirm link#36
kubiknyc merged 3 commits into
mainfrom
feat/welcome-claim-company

Conversation

@kubiknyc

@kubiknyc kubiknyc commented Sep 9, 2026

Copy link
Copy Markdown
Owner

Summary

WorkLog website half of jobsight-backend #34 (phase 1), matching kubiknyc/PunchLog#158. After the tap-driven confirm on a register link, /welcome calls the claim_pending_company RPC before showing the password form.

  • lib/welcomeLink.ts: readRegisterFlow(hash) — true only for flow=register, which worklog-register-company (jobsight-backend #39, deployed v6) now appends to its token_hash landing links. Invite and recovery links never carry it.
  • app/welcome/page.tsx: new claim phase between the confirm tap and set-password. Success → set-password. 401/403 → existing expired path. 429 → existing rate-limit copy. Any other failure keeps "Try again" (the one-time token is already spent, so never re-verify) plus "Skip for now and choose your password", because the confirm-time DB trigger still mints the company today. Nothing fires on mount or in an effect; no server text is rendered. Recovery copy still points at the app.

Order and dependencies

Backend side is already live: migration 20260909000001_claim_pending_company (#36) and worklog-register-company v6 (#39). Until this merges, the flag in WorkLog's mail is inert and tenants come from the trigger. The stale-register-mail residual phase 1 accepts, and the consent step that closes it, are kubiknyc/jobsight-backend#35.

Verification

  • website: npm run typecheck, npm test (34), npm run build — green
  • WorkLog CI runs nothing on website/**; those are the complete checks
  • santa loop: 2 rounds, Reviewer A ecc:code-reviewer (Opus; the repo's worklog-reviewer is not registered in this session) + Reviewer B Gemini, both PASS in round 2. Round-1 HIGH (no way past a failed claim) fixed. Two round-2 MEDIUMs (button class, stale error on skip) fixed in the third commit.

Not covered: no component test for the claim phase (no jsdom in website/); live round trip owed after deploy.

Self-serve registration parks a pending_company marker on the unconfirmed
user, and a shared database trigger mints the company at confirmation. The
trigger cannot tell a register link from an invite link, so it carries an
affiliation guard. The fix is for the website to ask for the company
explicitly once the reader is authenticated.

Register confirm links now arrive tagged `&flow=register`. When the confirm
tap spends a tagged link's token and gets an access token back, /welcome
calls the claim_pending_company RPC before asking for a password. Invite and
recovery links are untagged and take the old path unchanged.

A failed claim gets its own phase rather than an error: the one-time confirm
token is already spent, so the reader must never be sent back to the confirm
tap or to a fresh link. The claim phase holds the access token and retries
the RPC alone. The RPC is idempotent, so a retry after a timeout that
actually succeeded is harmless. 401/403 takes the existing expired path, 429
the existing rate-limit copy.

The page's existing invariants hold: nothing fires on mount or in an effect,
the flow tag is read once where the fragment is first read, the
double-submit ref guard still covers every call, and no server text is ever
rendered.
Give the failed-claim card an escape hatch (skip to password setup,
matching PunchLog's shipped shape), key its copy on formError instead
of saving so a failure doesn't repeat the in-flight message, and fix
the module comment: the claim step already shipped in PunchLog
(kubiknyc/PunchLog#158), and the recovery/legacy paths that never
claim are now documented as depending on the confirm-time trigger.
@coderabbitai

coderabbitai Bot commented Sep 9, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: cf68db80-5741-4def-b6b1-b4c8d72950f7


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@kubiknyc
kubiknyc merged commit 9b417ec into main Sep 9, 2026
4 of 5 checks passed
@kubiknyc
kubiknyc deleted the feat/welcome-claim-company branch September 9, 2026 07:56
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