Skip to content

feat(auth): invite-gated signup UI#4212

Merged
PierreBrisorgueil merged 5 commits into
masterfrom
feat/invite-only-signup-gate
May 28, 2026
Merged

feat(auth): invite-gated signup UI#4212
PierreBrisorgueil merged 5 commits into
masterfrom
feat/invite-only-signup-gate

Conversation

@PierreBrisorgueil
Copy link
Copy Markdown
Collaborator

@PierreBrisorgueil PierreBrisorgueil commented May 28, 2026

Summary

  • What changed: Pinia auth store signup now relays an inviteToken as a URL query param (backend reads req.query) + new verifyInvite(token) action. signup.view.vue reads ?inviteToken, verifies it on mount, reveals the credentials form + prefills the invited email when public signup is disabled, and passes the token through to signup.
  • Why: Cross-stack feature — when the Node backend is configured with signupMode: invite-only, the UI must gate the signup form behind a valid invite token fetched from ?inviteToken.
  • Related issues: Closes feat(auth): invite-gated signup UI #4211

Scope

  • Modules impacted: modules/auth/ (store, view)
  • Cross-module impact: none
  • Risk level: low

Validation

  • npm run lint
  • npm run test:unit
  • npm run build
  • Manual checks done (if applicable)

Guardrails check

  • No secrets or credentials introduced (.env*, secrets/**, keys, tokens)
  • No risky rename/move of core stack paths
  • Changes remain merge-friendly for downstream projects
  • Tests added or updated when behavior changed

Optional: Infra/Stack alignment details

Before vs After (key changes only)

Area Before After Notes
auth.store.js signup() No invite token relay Appends ?inviteToken=<token> to signup URL query Backend reads via req.query
auth.store.js No verifyInvite action verifyInvite(token) calls GET /api/auth/invitations/verify/:token Returns { email }
signup.view.vue Always shows form Reads ?inviteToken on mount, verifies token, reveals form + prefills email No-op when inviteToken absent (public signup mode unchanged)
  • Upstream parity target / source: pierreb-devkit/Node — same branch feat/invite-only-signup-gate adds invitation endpoints + signup gate that this UI drives
  • Automation or policy impact: none
  • Rollback plan: revert commits on both stacks; Node gate defaults to signupMode: open so no data loss

Notes for reviewers

  • Security considerations: inviteToken is a short-lived JWT issued by the backend; the UI only relays it — no client-side validation of the token's claims.
  • Mergeability considerations: cross-stack pair with pierreb-devkit/Node feat/invite-only-signup-gate — Node PR should merge first (or simultaneously) so the verify endpoint exists.
  • Follow-up tasks: downstream propagation to trawl_vue, pierreb_vue, comes_vue, montaine_vue via /update-project after both stacks merge.

Cross-stack pair

Node counterpart PR: pierreb-devkit/Node branch feat/invite-only-signup-gate — adds invitation model, service, endpoints + signup gate.

Test plan

  • npm run lint — passes
  • npm run test:unit — 1918 tests, all green; auth.store coverage 99/92/100/100
  • npm run build — passes (note: src/config/index.js is generated/gitignored; CI regenerates via scripts/generateConfig.js)

Doc-sync ack

  • No deleted files vs master
  • No stale i18n/TODO/FIXME comments (Phase 0.5 clean)

… token

When signup is disabled and ?inviteToken is present, verifyInvite() is called
in created(); on valid invite the credentials form is shown and email prefilled.
The token is passed through to authStore.signup() (omitted when null to keep
existing tests exact-match on { email, password }).
Add missing verifyInvite error-path test (catch → {valid:false,email:null})
and invite-invalid view branch test to reach 100% line coverage on auth.store.js.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 28, 2026

Warning

Review limit reached

@PierreBrisorgueil, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 16 minutes and 22 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3e2b9bec-04cb-44cf-a5fe-f00da62cf576

📥 Commits

Reviewing files that changed from the base of the PR and between a92952c and e252c16.

📒 Files selected for processing (4)
  • src/modules/auth/stores/auth.store.js
  • src/modules/auth/tests/auth.signup.view.unit.tests.js
  • src/modules/auth/tests/auth.store.unit.tests.js
  • src/modules/auth/views/signup.view.vue
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/invite-only-signup-gate

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 and usage tips.

@PierreBrisorgueil PierreBrisorgueil marked this pull request as ready for review May 28, 2026 17:16
Copilot AI review requested due to automatic review settings May 28, 2026 17:16
@codecov
Copy link
Copy Markdown

codecov Bot commented May 28, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.56%. Comparing base (a3207c6) to head (e252c16).
⚠️ Report is 9 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #4212   +/-   ##
=======================================
  Coverage   99.56%   99.56%           
=======================================
  Files          31       31           
  Lines        1151     1159    +8     
  Branches      329      330    +1     
=======================================
+ Hits         1146     1154    +8     
  Misses          5        5           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds invite-gated signup support to the auth module by verifying an inviteToken from the signup page URL and relaying that token to the backend during signup, enabling “invite-only” signup mode compatibility.

Changes:

  • Update signup view to read ?inviteToken, verify it on creation, prefill invited email, and allow the credentials form when the invite is valid even if public signup is disabled.
  • Update auth store signup() to relay inviteToken via URL query (and omit it from the POST body).
  • Add a new verifyInvite(token) store action plus unit tests covering invite relay and invite-gated rendering.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
src/modules/auth/views/signup.view.vue Adds invite verification flow and gates form visibility based on inviteToken validity.
src/modules/auth/stores/auth.store.js Relays inviteToken via query param on signup and introduces verifyInvite() action.
src/modules/auth/tests/auth.store.unit.tests.js Adds tests for inviteToken relay on signup and verifyInvite behavior.
src/modules/auth/tests/auth.signup.view.unit.tests.js Adds tests for invite-only signup gating, email prefill, and passing inviteToken to signup().

Comment thread src/modules/auth/views/signup.view.vue Outdated
Comment thread src/modules/auth/views/signup.view.vue Outdated
Comment thread src/modules/auth/stores/auth.store.js Outdated
Comment thread src/modules/auth/stores/auth.store.js
@PierreBrisorgueil
Copy link
Copy Markdown
Collaborator Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 28, 2026

✅ Actions performed

Full review triggered.

…h during invite verify

- inviteToken: normalize string | string[] | undefined to single string or null
- inviteChecking flag: true when token present, cleared after verifyInvite resolves
- Suppresses disabled-alert flash while invite is being checked
- Tests: 6 new cases (array/string/null normalization, inviteChecking lifecycle, no-flash)
@PierreBrisorgueil PierreBrisorgueil merged commit d17a841 into master May 28, 2026
7 checks passed
@PierreBrisorgueil PierreBrisorgueil deleted the feat/invite-only-signup-gate branch May 28, 2026 20:20
PierreBrisorgueil pushed a commit that referenced this pull request Jun 1, 2026
# [2.1.0](v2.0.0...v2.1.0) (2026-06-01)

### Bug Fixes

* **billing:** 4 pricing page bugs (signed-in features, hero bg, truncation, guest CTA) ([#4123](#4123)) ([bd399bd](bd399bd))
* **billing:** add aria-expanded + touch support to BillingComputeGauge components ([#4181](#4181)) ([7e7fa97](7e7fa97))
* **billing:** billing UX hardening — 5 reliability fixes ([#4079](#4079)) ([dd62b3d](dd62b3d)), closes [#4078](#4078)
* **billing:** canonical FA6 icons + meterError lifecycle + reject URL credentials ([#4082](#4082)) ([be16045](be16045)), closes [#4081](#4081)
* **billing:** clear intentId on Stripe cancel-redirect ([#4085](#4085)) ([11be9ab](11be9ab))
* **billing:** drop empty overage aria-live div + add fr overDetail key ([#4142](#4142)) ([10e5d81](10e5d81))
* **billing:** i18n migration + Intl.NumberFormat USD (audit Codex P1) ([#4069](#4069)) ([3d3a4f6](3d3a4f6))
* **billing:** mega vue hardening v3 — UX + design + a11y + V4 ([#4063](#4063)) ([802cbc4](802cbc4))
* **billing:** send {} body on portal POST to satisfy Zod PortalRequest schema ([#4137](#4137)) ([bf6b9c8](bf6b9c8))
* **billing:** send intentId UUID to close extras double-charge window ([#4084](#4084)) ([3e27c4c](3e27c4c))
* **billing:** subscription state safety + webhook lag polling (audit Codex P1) ([#4068](#4068)) ([328700b](328700b))
* **billing:** surface meterError + remove dead 409 dialog from subscriptions ([#4081](#4081)) ([61f5d53](61f5d53))
* **billing:** V5 polish — F5 polling recovery + visibility refetch + i18n residual + locale null-guard ([#4070](#4070)) ([4908adb](4908adb))
* **billing:** V6 polish — sessionStorage guard + locale BCP47 + i18n plural + NaN guard ([#4076](#4076)) ([2ad018c](2ad018c))
* **build:** drop ARG defaults for analytics_* + filter empty env vars ([#4112](#4112)) ([afd336e](afd336e)), closes [Vue#4110](https://github.com/Vue/issues/4110) [#4110](#4110)
* **build:** restore Layer 5 empty-string env override (revert [#4112](#4112) part 2) ([c9aa9e6](c9aa9e6)), closes [Vue#4110](https://github.com/Vue/issues/4110) [comes-io/trawl_vue#880](https://github.com/comes-io/trawl_vue/issues/880) [Vue#4110](https://github.com/Vue/issues/4110)
* **core:** pin CorePageHeader to content size in flex-column contexts ([#4210](#4210)) ([e182512](e182512)), closes [#4202](#4202)
* **layout:** route /pricing outside app shell — no drawer offset on signed-in ([#4124](#4124)) ([d862fbb](d862fbb))
* **legal:** cookie banner UA-detection + appName fallback to app.title ([#4113](#4113)) ([04cc70a](04cc70a)), closes [trawl_vue#876](https://github.com/trawl_vue/issues/876) [#4109](#4109)
* **legal:** cookie consent + footer polish (5 QA bugs) ([#4098](#4098)) ([a9bf0a3](a9bf0a3))
* **legal:** gate cookie banner on isMounted to prevent prerender hydration double-render ([#4109](#4109)) ([3198e48](3198e48)), closes [#app](https://github.com/pierreb-devkit/Vue/issues/app)
* **router:** redirect authenticated users to config.sign.route instead of hardcoded '/' ([#4088](#4088)) ([ca9094e](ca9094e)), closes [#4083](#4083)
* **tasks:** propagate store errors so views gate navigation on success ([#4221](#4221)) ([b029d39](b029d39)), closes [#4218](#4218)
* **ui:** chrome convergence — restore section title + surface backgrounds + homogeneous gutter ([#4188](#4188)) ([1e5fdf1](1e5fdf1))
* **users:** re-apply route tab when serverConfig.billing arrives async ([#4138](#4138)) ([87cc7b2](87cc7b2))
* **users:** refetch billing subscription on auth state change ([#4125](#4125)) ([5a3425a](5a3425a))

### Features

* **admin:** invitations management tab ([#4217](#4217)) ([61ad86c](61ad86c)), closes [invitedBy/#actions](https://github.com/pierreb-devkit/Vue/issues/actions)
* **analytics:** add identify and reset helpers, wire auth store ([#4104](#4104)) ([c4d8b87](c4d8b87))
* **auth:** invite-gated signup UI ([#4212](#4212)) ([d17a841](d17a841))
* **billing:** add 'Manage subscription' footer link in meterDrawer ([#4056](#4056)) ([#4057](#4057)) ([7d494af](7d494af))
* **billing:** align packs.component on BillingCardComponent (V4 unified schema) ([#4147](#4147)) ([7f5dd41](7f5dd41))
* **billing:** combined pool gauge + linear breakdown bars + alerts cleanup ([f5034b1](f5034b1))
* **billing:** config-driven static-content resolver (no file replace) ([e95d944](e95d944))
* **billing:** expose netRemainingRaw + overage in useMeter for negative quota display ([#4061](#4061)) ([111e64b](111e64b)), closes [#4060](#4060)
* **billing:** meter gauges display % primary, compute units in overflow tooltip ([#4139](#4139)) ([50498ba](50498ba))
* **billing:** meter UX refonte — drop drawer + subscriptions tab ([#4059](#4059)) ([891b5ae](891b5ae)), closes [#subscriptions](https://github.com/pierreb-devkit/Vue/issues/subscriptions) [#1](#1) [#2](#2) [#3](#3) [#4](#4)
* **billing:** post-grant upgrade prompt variant for depleted signupGrant ([#4128](#4128)) ([0ae8558](0ae8558))
* **billing:** pricing page redesign — multi-mode + auto-savings + sectioned features + FAQ ([#4102](#4102)) ([2c83ab6](2c83ab6))
* **billing:** pricingCard Free CTA — 'Sign up' for guests, route to /signup ([#4106](#4106)) ([cc92ac8](cc92ac8))
* **billing:** redesign Subscriptions view to match user-tabs aesthetic ([#4127](#4127)) ([15fd466](15fd466))
* **billing:** relocate billing under Organization settings ([#4175](#4175)) ([1f36137](1f36137))
* **billing:** sidenav compute gauge above sign-out row (meter mode) ([#4126](#4126)) ([fe1497f](fe1497f))
* **billing:** sidenav compute gauge redesign — button-shape above sign-out row ([#4140](#4140)) ([9d3a090](9d3a090))
* **billing:** sidenav compute gauge revamp — v-progress-circular + v-tooltip ([#4144](#4144)) ([5d60f1b](5d60f1b)), closes [#prepend](https://github.com/pierreb-devkit/Vue/issues/prepend)
* **billing:** subscriptions view 2-col layout — drop dup bar, CTA to /pricing#units ([#4141](#4141)) ([b7ef516](b7ef516)), closes [pricing#units](https://github.com/pricing/issues/units)
* **billing:** unified BillingCardComponent + annual toggle disabled state ([#4146](#4146)) ([474bb11](474bb11))
* **billing:** unified BillingCardComponent + annual toggle disabled state ([#4149](#4149)) ([d1403ff](d1403ff))
* **billing:** v4 hardening + Phase 3 polish — equivalences chips + UX gaps + a11y ([#4066](#4066)) ([dd40b2a](dd40b2a))
* **billing:** wire netRemainingRaw + overage into devkit components ([#4062](#4062)) ([61d6897](61d6897)), closes [#4061](#4061)
* **core:** reusable PageTabs component + Account view refactor ([#4183](#4183)) ([dc2504a](dc2504a))
* **core:** unified logo+title lockup in header and sidenav ([#4086](#4086)) ([ec457db](ec457db)), closes [#4083](#4083)
* **feature:** read ERRORS.md in Phase 0 before coding ([#4089](#4089)) ([ddf8f60](ddf8f60))
* **legal:** Add legal module + cookie consent (RGPD) ([#4097](#4097)) ([595e6c4](595e6c4)), closes [#3204116570](https://github.com/pierreb-devkit/Vue/issues/3204116570) [#3204116650](https://github.com/pierreb-devkit/Vue/issues/3204116650) [#1](#1) [#19](#19) [#18](#18) [#13](#13) [#11](#11) [#18](#18) [#3](#3) [#10](#10) [#12](#12) [#14](#14) [#15](#15) [#17](#17) [#20](#20) [#4](#4) [#5](#5) [#6](#6) [#7](#7) [#8](#8) [#9](#9) [#16](#16) [#3](#3) [#16](#16) [#22](#22)
* **legal:** liquid glass cookie banner — Vuetify-only with friendlier copy ([#4115](#4115)) ([3d74789](3d74789)), closes [#4114](#4114)
* **monitoring:** single-source PostHog Error Tracking (drop Sentry) ([#4118](#4118)) ([82dfca6](82dfca6))
* **organizations:** add Organization tab + rename General route to tab-addressable ([#4184](#4184)) ([fdfbf0b](fdfbf0b))
* **organizations:** soft suggestedJoin onboarding banner + recovery-screen copy ([#4176](#4176)) ([25a3ceb](25a3ceb))
* **seo:** enrich seoInjectPlugin — multi-schemas + rich SoftwareApplication + themeColor ([#4092](#4092)) ([#4111](#4111)) ([7f8bd09](7f8bd09))
* **skill/feature:** add Phase 0.0 issue claim-on-start ([#4117](#4117)) ([a582430](a582430)), closes [pierreb-projects/infra#28](https://github.com/pierreb-projects/infra/issues/28)
* **skills/update-stack:** block on undeclared drift vs upstream ([#4228](#4228)) ([ab8ee68](ab8ee68)), closes [#4227](#4227)
* **users:** subs full-width + delete account danger zone + halo full-bleed fix ([#4143](#4143)) ([981f073](981f073))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(auth): invite-gated signup UI

2 participants