Skip to content

feat(organizations): always-create workspace + suggestedJoin hint (drop onboarding limbo)#3680

Merged
PierreBrisorgueil merged 9 commits into
masterfrom
feat/signup-always-create-suggested-join
May 19, 2026
Merged

feat(organizations): always-create workspace + suggestedJoin hint (drop onboarding limbo)#3680
PierreBrisorgueil merged 9 commits into
masterfrom
feat/signup-always-create-suggested-join

Conversation

@PierreBrisorgueil
Copy link
Copy Markdown
Contributor

@PierreBrisorgueil PierreBrisorgueil commented May 19, 2026

What

PR (a) of the Devkit onboarding/billing/UI-decoupling effort (PR(b) #4170 + PR(c) #4175 already merged on Vue). Removes corporate-domain onboarding limbo on the Node side.

  • Delete the autoCreate footgunconfig.organizations.autoCreate is now a documented deprecated no-op; every signup always provisions an active workspace regardless of config/domain. organizationSetupRequired/pendingJoin are never returned by the signup path.
  • Name-only suggestedJoin hint — corporate non-public domain matching an existing org → returns { orgId, orgName } (sanitized, no membership/size/domain leak) alongside the user's own always-created workspace. Soft signal, never a gate.
  • Canonical domain normalization — new organizations.domain.js (normalizeEmailDomain + isPublicDomain); single source of truth; exact-match (no subdomain recursion: user@eu.acme.comacme.com).
  • Idempotent retry-safe provisioning — single-node Mongo (no transactions): a pre-flight active-membership guard converges a retried signup to the existing single workspace (no duplicate org, no double signupGrant).
  • suggestedJoin serialized in the signup HTTP response (auth.controller.js) — the PR(a)↔PR(d) contract for the onboarding banner. Deprecated suggestedOrganization kept one release with a removal comment.
  • signupGrant (feat(billing): credit signupGrant on org creation post-signup #3663) preserved — credited exactly once per real new signup inside createOrganizationForUser, never on the idempotent converge path.

Verification

  • npm run lint: 0 errors. Full suite: 99 suites / 1459 tests, 0 failures.
  • Per-task two-stage review (spec + code-quality) with fix loops — caught dead imports (CI-lint), a mock-isolation leak, an abilities-mock gap, byte-identical-return verification across 3 sites.

⚠️ Known race (accepted)

feat-billing-plan-signup-grant and fix-checkout-502 carry identical changes that remove BillingSignupGrantService/the grant call from createOrganizationForUser (grant relocation). Neither has an open PR. Conflict is textual + semantic (grant relocation, not data-model). Decision: PR(a) merges first; whoever rebases those branches must re-verify the signupGrant "exactly-once" invariant against the relocated grant. Documented for the rebaser.

8 commits (6f7f0f8d7132647f).

Summary by CodeRabbit

Release Notes

  • New Features

    • Added suggestedJoin hint during signup to recommend existing organizations matching user's email domain.
  • Bug Fixes

    • Signup now always provisions a workspace for users.
    • Domain-matching behavior refined: users no longer receive pending join requests; each signup creates an independent active workspace.
  • Deprecations

    • suggestedOrganization field is deprecated in signup responses.

Review Change Stack

…op autoCreate footgun

Spec D5 — every signup provisions an active workspace. autoCreate config flag is a
deprecated no-op; no path returns organizationSetupRequired or pendingJoin.

- handleSignupOrganization: delete autoCreate:false footgun branch entirely; all enabled
  paths call createOrganizationForUser returning {organization, membership}.
- Domain-match branch: drop createJoinRequest+pendingJoin; return suggestedJoin:
  {orgId,orgName} name-only hint alongside the newly created workspace.
- Use A1 isPublicDomain for the public-domain gate (hardcoded list + config overrides).
- Naming: domainMatching+corporate domain → domain-based name; all other cases
  (domainMatching off, public domain) → "{firstName}'s organization".
- signupGrant: credited inside createOrganizationForUser, once per real new org,
  never double-credited. Preserved exactly from pre-A2.
- Auth controller: no change needed — uses ||false/||null fallbacks on removed keys.
- Test updates (required 0-failure): emailVerification, domainJoin E2E, auth signup
  integration + auth E2E updated to assert new always-create contract.
- New unit test: organizations.service.signup.unit.tests.js — all config combos,
  suggestedJoin shape (name-only), signupGrant credited once, createJoinRequest never.
…lation

- I1: remove unused MembershipService import and dead sanitizeOrg helper (both
  orphaned by A2); file is now lint-clean (no-unused-vars: 0)
- I2: replace clearAllMocks() with resetAllMocks() + explicit defaults in top-level
  beforeEach; prevents mockReturnValue leaking across describe blocks
- m1: hoist triple `orgConfig.domainMatching && !domainIsPublic` into const
  isCorporateDomain; used at all 3 call sites, behavior identical
- m2: reword misleading e2e comment on suggestedOrganization:null to state actual
  controller contract and reference A2b for wiring
…canonical normalizeEmailDomain

replace extractDomain(user.email) with normalizeEmailDomain (A1) at the two signup
sites in handleSignupOrganization: the repository list query (read) and the domain
passed to createOrganizationForUser (write). both now use the single canonical
lowercased/trimmed/null-safe path from organizations.domain.js.

guard isCorporateDomain against null domain (malformed email → normalizeEmailDomain
returns null → treated as non-corporate, falls through to personal workspace).

extractDomain kept as exported public API for non-signup callers; not modified.

tests (A3): mixed-case write normalization, case-insensitive match, subdomain
non-match (eu.acme.com ≠ acme.com), public-domain gate with mixed-case email.
…main guard

Remove extractDomain (def + JSDoc + export entry) — fully superseded by
normalizeEmailDomain since A3; 0 callers in repo. Drop stale "kept for
non-signup callers" comment (was factually wrong). Simplify domainIsPublic
to `isPublicDomain(domain) || publicDomains.includes(domain ?? '')` —
normalizeEmailDomain guarantees a lowercased string or null, so the
redundant ?. chain is gone. Fix stale RED label in A3 test to describe
the canonical-normalization contract it actually asserts.
…1 / A4)

Add convergence guard in handleSignupOrganization: if the user already holds
an active membership (partial-failure retry scenario), return the existing
org+membership without calling createOrganizationForUser — preventing duplicate
workspaces and double-crediting signupGrant on retried signups.

Uses MembershipRepository.findOne({ userId, status: ACTIVE }) — same canonical
read as autoSetCurrentOrganization. Guard fires after the email-verification
early-return and before Case 1/Case 2 always-create paths. signupGrant stays
once-only because it lives inside createOrganizationForUser, which is skipped.
Controller now serializes `suggestedJoin: { orgId, orgName } | null`
from orgResult into the signup response body alongside the existing keys.
`suggestedOrganization` kept as always-null with deprecation comment
(additive — breaking removal deferred to next release).
TDD: two integration tests (shape assert + null path), auth 1579 / orgs 1469 green.
Copilot AI review requested due to automatic review settings May 19, 2026 19:38
@codecov
Copy link
Copy Markdown

codecov Bot commented May 19, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.60%. Comparing base (cf6ea66) to head (4b970e6).
⚠️ Report is 11 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3680      +/-   ##
==========================================
+ Coverage   89.54%   89.60%   +0.06%     
==========================================
  Files         138      139       +1     
  Lines        4733     4734       +1     
  Branches     1472     1481       +9     
==========================================
+ Hits         4238     4242       +4     
+ Misses        388      385       -3     
  Partials      107      107              
Flag Coverage Δ
integration 59.63% <94.44%> (-0.21%) ⬇️
unit 65.82% <100.00%> (+0.85%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 77acdad...4b970e6. Read the comment docs.

🚀 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.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

Warning

Rate limit exceeded

@PierreBrisorgueil has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 49 minutes and 11 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, 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 have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 702dc1c0-9323-4ab5-ae88-0cdc2a16468f

📥 Commits

Reviewing files that changed from the base of the PR and between 7132647 and 4b970e6.

📒 Files selected for processing (5)
  • modules/organizations/services/organizations.domain.js
  • modules/organizations/services/organizations.service.js
  • modules/organizations/tests/organizations.domain.unit.tests.js
  • modules/organizations/tests/organizations.domainJoin.e2e.tests.js
  • modules/organizations/tests/organizations.service.signup.unit.tests.js

Walkthrough

This PR refactors signup organization provisioning to implement "Spec D5 — always-create." Every successful signup now provisions a workspace for the user, regardless of autoCreate setting. Domain matching suggests joins (via suggestedJoin hints) rather than creating them. Tests across auth, organizations, and integration suites are updated to validate the new behavior.

Changes

Always-Create Signup Organization Provisioning

Layer / File(s) Summary
Domain Normalization Utilities
modules/organizations/services/organizations.domain.js, modules/organizations/tests/organizations.domain.unit.tests.js
New normalizeEmailDomain and isPublicDomain functions extract and validate email domains; PUBLIC_DOMAINS set enumerates common public providers. Tests verify lowercase normalization, null handling for malformed inputs, and public provider detection.
Always-Create Service Implementation
modules/organizations/services/organizations.service.js, modules/organizations/tests/organizations.service.signup.unit.tests.js
handleSignupOrganization refactored to provision a workspace for every signup with an idempotent guard for existing active memberships. Domain matching derives name-only suggestedJoin hints for corporate domains without creating join requests. Organization naming is conditional on domain type. Module exports updated to remove extractDomain. Comprehensive unit tests validate always-create behavior, billing crediting exactly once, and idempotent convergence.
Response Contract Updates
modules/auth/controllers/auth.controller.js, modules/auth/tests/auth.e2e.tests.js, modules/auth/tests/auth.signup.organization.integration.tests.js, modules/organizations/tests/organizations.emailVerification.unit.tests.js
Signup responses remove organizationSetupRequired and pendingJoin fields; suggestedOrganization receives deprecation comment; suggestedJoin is validated as name-only or null. All signup paths now provision an organization with active membership regardless of autoCreate configuration. Integration and E2E tests updated to assert distinct organizations, no pending requests, and proper name/domain handling.
E2E Domain-Join Flow Validation
modules/organizations/tests/organizations.domainJoin.e2e.tests.js
E2E tests verify that second-user signup provisions its own active workspace with owner role, removes pending join request expectations, and confirms the pending requests list is empty on the first organization.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant AuthController
  participant HandleSignup
  participant OrgRepository
  participant MembershipRepository
  participant BillingService
  User->>AuthController: POST /signup
  AuthController->>HandleSignup: handleSignupOrganization(user)
  HandleSignup->>MembershipRepository: findOne(userId, ACTIVE)
  alt Existing Active Membership
    MembershipRepository-->>HandleSignup: membership found
    HandleSignup-->>AuthController: return existing org+membership
  else New Signup
    MembershipRepository-->>HandleSignup: no membership
    HandleSignup->>HandleSignup: normalizeEmailDomain(email)
    HandleSignup->>HandleSignup: isPublicDomain(domain)
    HandleSignup->>OrgRepository: findByDomain(domain)
    alt Corporate domain + org exists
      OrgRepository-->>HandleSignup: org found
      HandleSignup->>HandleSignup: return suggestedJoin hint
    else Create new org
      HandleSignup->>OrgRepository: create organization
      HandleSignup->>MembershipRepository: create membership
      HandleSignup->>BillingService: grantOnSignup
    end
    HandleSignup-->>AuthController: return org+membership+suggestedJoin
  end
  AuthController-->>User: signup response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • pierreb-devkit/Node#3403: Updates creator owner-role membership reference in organizations.service.js from string 'owner' to constant MEMBERSHIP_ROLES.OWNER, aligning with the main PR's signup organization provisioning logic.
  • pierreb-devkit/Node#3234: Adds email-verification early-return gate to handleSignupOrganization that prevents domain-based org features when mailer is configured and email unverified, complementing the main PR's always-create flow logic.

Poem

🐰 A signup that always creates workspace cheer,
No pending joins, just orgs crystal clear!
Domain hints suggest without delay,
Idempotent paths light the way—
Spec D5 hops in, here to stay!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The PR title directly summarizes the main change: always-create workspace + suggestedJoin hint to drop onboarding limbo, which aligns with the core feature across all modified files.
Description check ✅ Passed The PR description comprehensively covers the 'What' (changes made), 'Why' (onboarding limbo removal), verification (lint/tests passed), and critical caveats (known race condition); however, it does not follow the provided template structure with clear sections for Summary, Scope, Validation, Guardrails, and Notes for reviewers.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/signup-always-create-suggested-join

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.

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 updates the organizations/signup flow to eliminate the “onboarding limbo” path by always provisioning a workspace on signup, adds a sanitized suggestedJoin hint for corporate-domain matches, and centralizes email-domain normalization/public-domain detection.

Changes:

  • Make handleSignupOrganization always create an active organization + membership (with an idempotent convergence guard for retries) and return an optional suggestedJoin hint.
  • Add organizations.domain.js as the canonical domain normalization + public-domain source of truth.
  • Update auth controller + integration/E2E/unit tests to reflect the new always-create + suggestedJoin contract.

Reviewed changes

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

Show a summary per file
File Description
modules/organizations/tests/organizations.service.signup.unit.tests.js Adds unit coverage for always-create behavior, suggestedJoin shape, normalization, and idempotent convergence.
modules/organizations/tests/organizations.emailVerification.unit.tests.js Updates expectations to reflect removal of organizationSetupRequired/pendingJoin keys from service return.
modules/organizations/tests/organizations.domainJoin.e2e.tests.js Updates E2E expectations: no pending join requests; member gets their own workspace.
modules/organizations/tests/organizations.domain.unit.tests.js Adds unit tests for normalizeEmailDomain and isPublicDomain.
modules/organizations/services/organizations.service.js Implements always-create signup provisioning, suggestedJoin hinting, domain normalization usage, and retry-safe convergence guard.
modules/organizations/services/organizations.domain.js Introduces domain parsing/normalization + public-domain detection helpers.
modules/auth/tests/auth.signup.organization.integration.tests.js Updates integration expectations for always-create + suggestedJoin, and deprecates autoCreate:false behavior.
modules/auth/tests/auth.e2e.tests.js Updates auth E2E to validate no pending join requests and active membership on new org.
modules/auth/controllers/auth.controller.js Serializes suggestedJoin into the signup HTTP response (keeps deprecated suggestedOrganization).

Comment thread modules/organizations/services/organizations.service.js Outdated
Comment thread modules/organizations/services/organizations.service.js
Comment thread modules/organizations/services/organizations.service.js
Comment thread modules/organizations/tests/organizations.service.signup.unit.tests.js Outdated
Comment thread modules/organizations/tests/organizations.domainJoin.e2e.tests.js Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
modules/auth/controllers/auth.controller.js (2)

135-152: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use the project response envelope helper instead of raw res.status().json().

The signup controller still constructs a raw JSON response directly. This breaks the repo’s standardized API envelope convention and should be routed through responses.success(...).

Based on learnings: "Enforce project-wide API envelope: all backend endpoints should wrap responses in the { type, message, data } envelope via responses.success(res, message)(data). Do not flag or accept raw res.status(200).json(...) responses in modules/auth/controllers/auth.controller.js, as they break consistency."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@modules/auth/controllers/auth.controller.js` around lines 135 - 152, Replace
the raw res.status(200).cookie(...).json(...) return with the project's response
envelope helper: set the cookie first via res.cookie('TOKEN', token,
tokenCookieOptions) and then call responses.success(res, 'Sign up')(...) passing
the exact payload object (user, tokenExpiresIn, organization, joined,
pendingJoin, abilities, organizationSetupRequired, emailVerificationRequired,
suggestedOrganization, suggestedJoin, type: 'success', message: 'Sign up') so
the endpoint uses the standardized {type,message,data} envelope; locate this
change around the return in the signup handler in
modules/auth/controllers/auth.controller.js where token, tokenCookieOptions and
orgResult are used.

141-146: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Drop legacy pendingJoin / organizationSetupRequired from signup payload.

At Line 143 and Line 145, the response still emits deprecated fields that D5 says should no longer be returned. Keeping them prolongs mixed contracts and client ambiguity.

💡 Suggested fix
       .json({
         user,
         tokenExpiresIn: Date.now() + config.jwt.expiresIn * 1000,
         organization: orgResult.organization || null,
         joined: orgResult.joined || false,
-        pendingJoin: orgResult.pendingJoin || false,
         abilities: orgResult.abilities || [],
-        organizationSetupRequired: orgResult.organizationSetupRequired || false,
         emailVerificationRequired: orgResult.emailVerificationRequired || false,
         // deprecated: always null since always-create (A2); superseded by suggestedJoin — remove next release
         suggestedOrganization: orgResult.suggestedOrganization || null,
         suggestedJoin: orgResult.suggestedJoin || null,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@modules/auth/controllers/auth.controller.js` around lines 141 - 146, Remove
the deprecated fields pendingJoin and organizationSetupRequired from the
signup/response payload in auth.controller.js — locate the object that builds
the response (the block that sets organization: orgResult.organization, joined:
orgResult.joined, pendingJoin: orgResult.pendingJoin, abilities:
orgResult.abilities, organizationSetupRequired:
orgResult.organizationSetupRequired, emailVerificationRequired:
orgResult.emailVerificationRequired) and delete the pendingJoin and
organizationSetupRequired properties so only current fields (e.g., organization,
joined, abilities, emailVerificationRequired) are returned; run/update any tests
or client expectations that referenced pendingJoin or organizationSetupRequired.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@modules/organizations/services/organizations.domain.js`:
- Around line 20-23: The domain-extraction logic currently uses indexOf('@')
which accepts malformed emails with multiple '@' (e.g., "a@b@acme.com"); update
the normalization to first verify there's exactly one '@' (e.g., ensure
email.indexOf('@') === email.lastIndexOf('@') and index !== -1) before slicing,
then trim/lowercase and validate domain as before (use the existing variables
email, at, domain) so multiple-`@` inputs return null.

In `@modules/organizations/services/organizations.service.js`:
- Around line 158-162: The helper function buildResult is missing a JSDoc
header; add a JSDoc block above the const buildResult declaration documenting
the parameters and return value: include `@param` {Object} organization, `@param`
{Object} membership, and mention that the function uses the outer-scope user and
returns a Promise resolving to an object with organization, membership, and
abilities (the result of serializeAbilities(await policy.defineAbilityFor(user,
membership))) — reference buildResult, policy.defineAbilityFor,
serializeAbilities and user in the description.

In `@modules/organizations/tests/organizations.domainJoin.e2e.tests.js`:
- Around line 142-144: The test currently uses permissive falsy assertions for
removed response fields; replace the toBeFalsy() checks with explicit undefined
assertions so the contract failure is caught — i.e., change
expect(result.body.pendingJoin).toBeFalsy() and
expect(result.body.joined).toBeFalsy() to
expect(result.body.pendingJoin).toBeUndefined() and
expect(result.body.joined).toBeUndefined(), referencing the result.body object
and the pendingJoin / joined properties in the domain join e2e test.
- Around line 155-159: Add explicit assertions for the new suggestedJoin
payload: after the existing
expect(result.body.suggestedOrganization).toBeNull(); add checks that
result.body.suggestedJoin is defined and has the expected "name-only" hint
pointing to the owner's org (e.g.
expect(result.body.suggestedJoin).toBeDefined();
expect(result.body.suggestedJoin.type).toBe('name-only');
expect(result.body.suggestedJoin.name).toBe(ownerOrg.name) or compare against
the expected owner name used in this test). Ensure you reference
result.body.suggestedJoin and the test's owner/org fixture (ownerOrg or
expectedOwnerName) so the assertion verifies both presence and correct value.

---

Outside diff comments:
In `@modules/auth/controllers/auth.controller.js`:
- Around line 135-152: Replace the raw res.status(200).cookie(...).json(...)
return with the project's response envelope helper: set the cookie first via
res.cookie('TOKEN', token, tokenCookieOptions) and then call
responses.success(res, 'Sign up')(...) passing the exact payload object (user,
tokenExpiresIn, organization, joined, pendingJoin, abilities,
organizationSetupRequired, emailVerificationRequired, suggestedOrganization,
suggestedJoin, type: 'success', message: 'Sign up') so the endpoint uses the
standardized {type,message,data} envelope; locate this change around the return
in the signup handler in modules/auth/controllers/auth.controller.js where
token, tokenCookieOptions and orgResult are used.
- Around line 141-146: Remove the deprecated fields pendingJoin and
organizationSetupRequired from the signup/response payload in auth.controller.js
— locate the object that builds the response (the block that sets organization:
orgResult.organization, joined: orgResult.joined, pendingJoin:
orgResult.pendingJoin, abilities: orgResult.abilities,
organizationSetupRequired: orgResult.organizationSetupRequired,
emailVerificationRequired: orgResult.emailVerificationRequired) and delete the
pendingJoin and organizationSetupRequired properties so only current fields
(e.g., organization, joined, abilities, emailVerificationRequired) are returned;
run/update any tests or client expectations that referenced pendingJoin or
organizationSetupRequired.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: f5925ef7-8b87-4b20-90ae-1cc22a064ed7

📥 Commits

Reviewing files that changed from the base of the PR and between 77acdad and 7132647.

📒 Files selected for processing (9)
  • modules/auth/controllers/auth.controller.js
  • modules/auth/tests/auth.e2e.tests.js
  • modules/auth/tests/auth.signup.organization.integration.tests.js
  • modules/organizations/services/organizations.domain.js
  • modules/organizations/services/organizations.service.js
  • modules/organizations/tests/organizations.domain.unit.tests.js
  • modules/organizations/tests/organizations.domainJoin.e2e.tests.js
  • modules/organizations/tests/organizations.emailVerification.unit.tests.js
  • modules/organizations/tests/organizations.service.signup.unit.tests.js

Comment thread modules/organizations/services/organizations.domain.js
Comment thread modules/organizations/services/organizations.service.js
Comment thread modules/organizations/tests/organizations.domainJoin.e2e.tests.js
Comment thread modules/organizations/tests/organizations.domainJoin.e2e.tests.js Outdated
- domain: reject multiple-@ malformed emails in normalizeEmailDomain
- service: JSDoc for buildResult @param/@returns (CR+Copilot)
- service: update @returns to reflect null org/membership on mailer path
- e2e: add explicit suggestedJoin assertion on domain-match signup path
- e2e: fix stale A2b comment (now shipped in this PR)
- unit: remove stale "RED" test-driven header comment
- unit: cover multiple-@ rejection in domain tests
@PierreBrisorgueil PierreBrisorgueil merged commit 5e166d7 into master May 19, 2026
8 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.

2 participants