Skip to content

fix(auth): set username at signup + bump owletto (new-user org routing)#1160

Merged
buremba merged 4 commits into
mainfrom
feat/fix-new-user-org-routing
May 29, 2026
Merged

fix(auth): set username at signup + bump owletto (new-user org routing)#1160
buremba merged 4 commits into
mainfrom
feat/fix-new-user-org-routing

Conversation

@buremba
Copy link
Copy Markdown
Member

@buremba buremba commented May 29, 2026

Problem

New users couldn't reach their workspace after login — they landed on /account/settings and the sidebar showed "Pick an organization to continue." despite having a valid personal org.

Root cause (two layers)

  1. Frontend race (fixed in owletto#251): the home route redirected to Settings before /api/organizations settled, and replace:true unmounted the route so it never recovered.
  2. Backend gap (this PR): the frontend resolves a user's home org synchronously from session.user.username (personalOrgSlug). That field was never set at signup, so currentOwner depended entirely on the org fetch — exposing the race for every new user. Only ~6 legacy users (with a username from an older path) were immune.

Fix

ensurePersonalOrganization now mirrors the personal-org slug onto user.username when it's null:

  • Set-when-null (idempotent) — won't overwrite a chosen handle.
  • NOT EXISTS guard — can't steal another user's username.
  • Non-fatal — a failure logs and doesn't roll back org creation.
  • Runs for both freshly created and pre-existing personal orgs, so legacy users self-heal on next login.

Submodule pointer bumped to the owletto fix.

Tests

  • src/__tests__/integration/auth/personal-org-username.test.ts (DB-backed): set-when-null + owner membership, idempotent (no overwrite), collision guard leaves username null. 3/3 green.
  • Server tsc --noEmit clean.

E2E / reproducer

The user-facing bug is the routing race; its red→green reproducer lives in owletto#251 (src/app/index.test.tsx). Prod data for the ~12 accounts created during the broken window was backfilled out-of-band (personal orgs + usernames).

Related: lobu-ai/owletto#251


View with Codesmith Autofix with Codesmith
Need help on this PR? Tag @codesmith with what you need. Autofix is disabled.

Summary by CodeRabbit

  • Bug Fixes
    • Users without a username are now automatically assigned one derived from their personal organization, improving account completeness.
    • Automatic username assignment avoids overwriting existing usernames (idempotent) and prevents collisions with other users’ identifiers.
    • Ensures created personal organizations properly establish ownership so users gain expected access immediately.

Review Change Stack

The frontend resolves a user's home org synchronously from
session.user.username (personalOrgSlug). It was never being set at signup, so
currentOwner depended entirely on the /api/organizations fetch — exposing the
home-route race for every new user (only ~6 legacy users with a username were
immune).

ensurePersonalOrganization now mirrors the personal-org slug onto username
when it's null: set-when-null (idempotent), guarded by NOT EXISTS so it can't
steal another user's username, non-fatal on error. Runs for both freshly
created and pre-existing personal orgs, so legacy users self-heal on next
login. Pairs with the owletto orgsReady gate (pointer bumped here).

Tests: src/__tests__/integration/auth/personal-org-username.test.ts
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

Warning

Review limit reached

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

More reviews will be available in 7 minutes and 52 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 29411af4-5955-448d-8a84-fc10bf3ea1b4

📥 Commits

Reviewing files that changed from the base of the PR and between b1d1f4f and 79d8076.

📒 Files selected for processing (1)
  • packages/owletto
📝 Walkthrough

Walkthrough

ensurePersonalOrganization now backfills a null user.username from the derived personal org slug (guarded against collisions). Adds exported findExistingPersonalOrg and integration tests for initialization, idempotency, and collision handling. Separately updates the Owletto submodule pointer.

Changes

Personal Org Username Backfill

Layer / File(s) Summary
Slug logic refactor and types
packages/server/src/auth/personal-org-provisioning.ts
UserLike formatting and slug/advisory-lock helper formatting were refactored without semantic changes.
Username backfill implementation and helper
packages/server/src/auth/personal-org-provisioning.ts
Adds exported findExistingPersonalOrg. ensurePersonalOrganization backfills user.username from the personal org slug when username is NULL, prevents collisions with a NOT EXISTS check, and treats the username update as non-fatal (wrapped in try/catch). Transactional org/member creation and conditional provisioning remain.
Integration tests for username backfill
packages/server/src/__tests__/integration/auth/personal-org-username.test.ts
New Vitest integration tests with seeding helpers and three cases: username initialization from org slug, idempotency (existing username unchanged), and collision behavior (slug taken leaves username null).

Dependency Submodule Update

Layer / File(s) Summary
Owletto submodule pointer update
packages/owletto
Submodule reference advanced to a different commit hash.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • lobu-ai/lobu#1074: Also updates the packages/owletto submodule pointer to a new commit.
  • lobu-ai/lobu#926: Related submodule pointer changes; this PR additionally adds username backfill logic and tests.

Poem

🐰 I seeded users in the test bed bright,
A slug becomes a name by moonlit light,
Collisions checked with careful tact,
Tests confirm the username is back,
Owletto hops to a newer night.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main backend change (set username at signup) and the submodule bump, which align with the core problem and fix described in the PR.
Description check ✅ Passed The description includes all required template sections: Summary (root cause and fix), Test plan items checked (DB test, TypeScript clean), and Notes (related issues, E2E context). The content is detailed and substantive.
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/fix-new-user-org-routing

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.

@codecov-commenter
Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

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: 1

🤖 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 `@packages/owletto`:
- Line 1: The packages/owletto submodule is pinned to an unreachable commit
(65ca050d...) from the owletto/main branch, which breaks the Submodule Drift
check and FluxCD deploy; to fix, merge the owletto#251 branch into owletto/main
(creating a reachable merge commit) and then update the packages/owletto
submodule reference to that merge commit SHA (or any SHA on owletto/main),
commit the updated submodule pointer (and .gitmodules if necessary), and push so
CI/Submodule Drift and FluxCD can resolve the submodule.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a57e1f1c-0c0e-4b4e-be50-1cf396f88a7d

📥 Commits

Reviewing files that changed from the base of the PR and between f1fceef and c83506c.

📒 Files selected for processing (3)
  • packages/owletto
  • packages/server/src/__tests__/integration/auth/personal-org-username.test.ts
  • packages/server/src/auth/personal-org-provisioning.ts

Comment thread packages/owletto Outdated
@@ -1 +1 @@
Subproject commit b579520a8767fd4daeea51a3a48d13465e501e57
Subproject commit 65ca050d50babd0f8765a11c0419d413812b08e9
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy lift

Pinned owletto SHA is not on owletto/main — blocks CI and breaks FluxCD deploy.

The submodule now points to 65ca050d..., which appears to be a commit from the unmerged owletto#251 branch. The Submodule Drift / check-drift job hard-fails because this SHA is not reachable from owletto/main, and per the guardrail in .github/workflows/submodule-drift.yml, FluxCD reads charts from owletto/main, so an off-main pin breaks deploy.

Merge owletto#251 into owletto/main first, then re-pin packages/owletto to a SHA that is reachable from owletto/main (e.g. the resulting merge commit).

🧰 Tools
🪛 GitHub Actions: Submodule Drift / check-drift

[error] 1-999: CI hard rule failed: Pinned SHA ($PINNED) is not reachable from owletto/main. Error: "Pinned SHA is not reachable from owletto/main." (check performed with: git -C packages/owletto merge-base --is-ancestor "$PINNED" origin/main).

🤖 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 `@packages/owletto` at line 1, The packages/owletto submodule is pinned to an
unreachable commit (65ca050d...) from the owletto/main branch, which breaks the
Submodule Drift check and FluxCD deploy; to fix, merge the owletto#251 branch
into owletto/main (creating a reachable merge commit) and then update the
packages/owletto submodule reference to that merge commit SHA (or any SHA on
owletto/main), commit the updated submodule pointer (and .gitmodules if
necessary), and push so CI/Submodule Drift and FluxCD can resolve the submodule.

@buremba buremba merged commit fc6a6d4 into main May 29, 2026
17 of 18 checks passed
@buremba buremba deleted the feat/fix-new-user-org-routing branch May 29, 2026 17:33
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