chore: add one-command local-dev sign-in (pnpm dev:login)#1419
Merged
Conversation
Add a single-command local-dev sign-in that takes a fresh worktree to a signed-in browser without the signup -> OTP -> MFA -> TOTP UI loop. pnpm dev:login: - bootstraps the local DB (idempotent): journal backfill when needed, db:migrate, seeds persistent e2e users plus a dev user/org, pre-trusts 127.0.0.1 + ::1, marks the dev user twoFactorEnabled, binds the local kh CLI token, and upserts 8 workflow fixtures - mints a Better Auth session using the same signSessionCookieValue / hashSessionToken helpers the production OAuth-MFA finalize path uses (imported, not modified) - ensures a dev server is serving localhost:3000: reuses a running one or spawns pnpm dev detached and waits for readiness - seeds the cookie into a dedicated Playwright Chromium profile and launches it detached All scripts refuse to run unless DATABASE_URL host is local; dev:mint-cookie additionally requires KEEPERHUB_DEV_MINT=1. No production auth, API route, or runtime code is modified. The minted cookie file, Chromium profile, and server log are gitignored. Replaces the old curl + SQL create-local-dev command. Lower-level entry points remain: pnpm dev:bootstrap, pnpm dev:mint-cookie.
Address non-blocking findings from PR review: - dev-login.ts: close the dev-server log file descriptor after spawning the detached child, so the parent does not leak it for the rest of its lifetime. The child keeps its own dup'd descriptor. - dev-login.ts / dev-login-browser.ts: pass the signed session cookie to the detached browser via the KEEPERHUB_DEV_COOKIE env var instead of argv. Process argv is world-readable (ps, /proc/<pid>/cmdline); the environ is owner-only. URL and profile dir stay positional (not secret). - dev-mint-session.ts: order the active-org fallback query by member createdAt so a multi-org seeded user resolves to a deterministic org instead of an arbitrary first row.
Follow-up to the local-dev sign-in hardening: order the active-org fallback query in dev-mint-session by member createdAt so a multi-org seeded user resolves to a deterministic org instead of an arbitrary first row.
dev-bootstrap.ts imports seedPersistentTestUsers from tests/, which .dockerignore strips from the build context, so next build's type check failed to resolve the module. These scripts are dev:login-only and never run in production, so exclude them from the image entirely.
next build type-checks scripts/ via the **/*.ts include. dev-bootstrap.ts imports a helper from tests/, which is absent in the Docker image, so the build's type check could not resolve the module. These are tsx-run dev:login-only scripts; exclude them from type checking.
🧹 PR Environment Cleaned UpThe PR environment has been successfully deleted. Deleted Resources:
All resources have been cleaned up and will no longer incur costs. |
ℹ️ No PR Environment to Clean UpNo PR environment was found for this PR. This is expected if:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
pnpm dev:login: one command takes a fresh worktree to a signed-in browser, skipping the signup -> OTP -> MFA -> TOTP UI loop.signSessionCookieValue/hashSessionTokenhelpers the production OAuth-MFA finalize path uses (imported, not modified), ensures a dev server is servinglocalhost:3000(reuses a running one or spawnspnpm devdetached and waits for readiness), then launches a dedicated detached Chromium profile already signed in.pnpm dev:bootstrap(DB setup only) andKEEPERHUB_DEV_MINT=1 pnpm dev:mint-cookie <email>(cookie only, no browser).create-local-devcommand with thedev-logincommand +create-local-devskill.Safety boundaries
DATABASE_URLhost is local (localhost/127.0.0.1/::1/db/postgres);dev:mint-cookieadditionally requiresKEEPERHUB_DEV_MINT=1.lib/auth.tsandlib/auth-session-token-hash.tsare imported only..claude/.dev-session-cookie-LOCAL), Chromium profile (.claude/.dev-chrome-profile/), and server log (.claude/.dev-server-LOCAL.log) are gitignored.Test plan
pnpm dev:loginfrom a fresh worktree opens a signed-in Chromium atlocalhost:3000(verified end-to-end).dev:loginstartspnpm dev, waits for readiness, then opens the signed-in window (verified end-to-end).pnpm type-checkclean.pnpm checkclean for changed files./dev-loginslash command available after merge + pull (to verify next session).No unit tests added: this is developer tooling (a Playwright-launching orchestrator + DB seed); verification is the end-to-end run plus the lint/type-check gates.