Give the new tab a session, instead of one that bounces to login

Fixkamo-internal
Shipped
August 28, 2026 at 2:59 AM UTC
Author
Kamo
Commit
ce4d901

"Open in new tab" was `window.open(location.href, '_blank', 'noopener,noreferrer')`. The session id is not in a cookie — it lives in sessionStorage, per tab, because organizations without a domain of their own share one host and a per-origin cookie would be a single slot any tab could overwrite. `window.open` legacy-clones the storage shed only while the opener relationship survives, and `noopener` (implied by `noreferrer` too) severs exactly that. The new tab therefore started with an empty store, found no session, and bounced to the login page. It looked like it worked because it was being rescued: the tab landed on login.*, where auto-login read the host-only *** cookie and forwarded it back into the org. Removing that forward is what exposed this, so the button is fixed rather than the redirect restored — it had never carried a session of its own. It now uses the same one-time-key handshake as every other cross-tab entry: open about:blank synchronously inside the click (an await first loses transient activation and WebKit blocks the popup), mint an OTK, then navigate to /validate with the current page in `next`. The OTK resolves to the SAME session, so the new tab is genuinely another instance of the same org, on the page it was opened from. `newtab` is registered as a document-load OTK purpose. An unlisted purpose is not rejected — it silently falls back to a 10s TTL, which /api/validate cannot rely on surviving, since it reads the key back from a Redis REPLICA and retries through replication lag before the app even boots. Three things the second-window notes warned about and this avoids: the key goes on /validate with the destination in `next`, because the edge rewrites any `?otk=` request to /validate and discards the original path; the target is an absolute URL held in a variable, because a literal assigned to `.location.href` fails check-client-navigation and the Docker build with it; and /validate is a pre-session path, so it will not sign the fresh tab out while it is unauthenticated.

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing