Skip to content

release: to prod#1421

Merged
eskp merged 11 commits into
prodfrom
staging
Jun 1, 2026
Merged

release: to prod#1421
eskp merged 11 commits into
prodfrom
staging

Conversation

@joelorzet

Copy link
Copy Markdown

No description provided.

eskp and others added 10 commits May 30, 2026 17:14
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.
chore: add one-command local-dev sign-in (pnpm dev:login)
Playwright's launchPersistentContext defaults to a fixed 1280x720
viewport that does not track window resizing, so the dev:login UI
rendered letterboxed when maximized or fullscreened. Set viewport: null
so the page follows the real OS window size and pass --start-maximized
so it opens filling the screen.
The new-network IP gate pinned trust to a byte-exact IPv4 address while
IPv6 was already bucketed to /64. When a user's egress IP rotates within
a provider block (CGNAT, dual-WAN, mobile pools), the host differs in the
same /24 between the page load that mints the pending_ip_verify cookie
and the OTP-send POST, so the re-check returned ip_mismatch before ever
sending the email. The modal renders but the code never arrives and the
prompt spins on "Sending...".

- Bucket IPv4 to its /24 in normalizeIpForTrust, mirroring the IPv6 /64
  rule; render the normalized key as CIDR in formatIpForDisplay.
- Move the IP-binding check off the OTP-send path onto the
  session-minting branch only, so requesting the code is never gated on a
  rotating address.
- Add an AbortSignal timeout to the SendGrid call so a stalled send fails
  closed instead of hanging the awaiting request.
- Add [ip-verify] tracing with the raw pre-normalization IP at the proxy
  gate, trust assessment, and verify-IP early returns.
fix(security): bucket IPv4 trust to /24 and decouple verify-IP OTP send
@joelorzet joelorzet requested review from a team, OleksandrUA, eskp and suisuss and removed request for a team May 31, 2026 01:06
chore: fill window in dev:login Chromium
@eskp eskp merged commit 481410d into prod Jun 1, 2026
33 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