Skip to content

feat(auth): per-tab auth sessions (sessionStorage source of truth) behind NEXT_PUBLIC_IBL_PER_TAB_AUTH - #467

Open
sonegillis1 wants to merge 5 commits into
mainfrom
feat/per-tab-auth
Open

feat(auth): per-tab auth sessions (sessionStorage source of truth) behind NEXT_PUBLIC_IBL_PER_TAB_AUTH#467
sonegillis1 wants to merge 5 commits into
mainfrom
feat/per-tab-auth

Conversation

@sonegillis1

@sonegillis1 sonegillis1 commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

What

Wires mentorai onto the SDK's per-tab authStorage policy (released in @iblai/iblai-js@2.7.3), gated by NEXT_PUBLIC_IBL_PER_TAB_AUTH (default off = byte-identical to today).

Under the flag, sessionStorage becomes each tab's auth source of truth and localStorage keeps only the most-recent login as a seed, so different tabs can stay signed into different tenants — ending the recurring tenant-switch clobber. Off, every path is the current localStorage behavior.

Changes

  • lib/utils.tsLocalStorageService, hasNonExpiredAuthToken, isLoggedIn, handleLogout (tab-local clearPerTabSession), saveUserObjectToLocalStorage → authStorage.
  • hooks/use-local-storage.ts — routes every token hook (dm/axd/edx/tenant/userData/…) through getAuthItem/setAuthItem/removeAuthItem.
  • features/utils.ts (API auth headers), lib/handlers.ts (iframe AUTH_UPDATE install), coding-mode-button.tsx, use-opencode-402.ts, use-speech.ts, use-user.tsgetAuthItem.
  • src-tauri/src/{main,lib}.rs — offline snapshot reads sessionStorage[k] ?? localStorage[k], restore writes both.
  • .env.example — documents NEXT_PUBLIC_IBL_PER_TAB_AUTH.
  • Bumps @iblai/iblai-js → 2.7.3.

Tests

  • Typecheck clean.
  • Full unit suite green (11.3k). Shared flag-OFF __iblAuthStorageMock passthrough added to vitest.setup.ts and spread into the web-utils mocks that exercise the new imports.

Rollout

Land off (no behavior change) → enable NEXT_PUBLIC_IBL_PER_TAB_AUTH=true in staging → run the multi-tab verification matrix → production. Paired with the skillsai PR.

sonegillis1 and others added 2 commits August 28, 2026 18:28
…lai-js 2.7.3

Routes token/tenant reads+writes through @iblai/iblai-js/web-utils authStorage:
useLocalStorage (covers all token hooks), LocalStorageService (data-layer),
hasNonExpiredAuthToken/isLoggedIn/handleLogout(per-tab)/saveUserObjectToLocalStorage,
API auth headers, lib/handlers install loop, Code/Cowork/speech reads, and the
Tauri offline snapshot (session-first read, restore to both). Flag off = today.
Typecheck clean. NEXT_PUBLIC_IBL_PER_TAB_AUTH in .env.example.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
mentorai now imports getAuthItem/setAuthItem/etc. from the SDK, so the
hand-listed vi.mock('@iblai/iblai-js/web-utils') factories that exercise those
paths threw "No <fn> export is defined on the mock". Add a shared flag-OFF
localStorage passthrough (globalThis.__iblAuthStorageMock in vitest.setup.ts)
and spread it into the affected factories. use-user.test gains a web-utils mock
too: getAuthItem is now a value import that would otherwise pull the full SDK
runtime (redux-toolkit query -> react-redux batch) into a test that only
partially mocks react-redux.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sonegillis1
sonegillis1 requested a review from mamigot as a code owner August 30, 2026 21:08
sonegillis1 and others added 2 commits August 30, 2026 23:17
The restore guard checked sessionStorage||localStorage together, so when the
localStorage seed already matched it skipped the sessionStorage write — exactly
the case per-tab restore must cover (populate this tab's session source-of-truth
offline). Check each store on its own. Mirrors the same fix in skillsai; applied
to both the desktop (main.rs) and mobile (lib.rs) hand-synced copies. Flag-ON
path; flag ships off.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Mirrors the skillsai fix in both hand-synced copies (main.rs desktop, lib.rs
mobile): restore each store only when empty, so a fresh offline launch hydrates
but a running tab's live per-tab session is never overwritten by a stale
snapshot.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

PR E2E - FAILED

Full report, traces and screenshots

result FAILED
central run 33342080037
commit 4629ac52
suite mentor - mode full - env stg1
tested against prod release 1.167.0 (env was synced to it first)
failed 2
new failures 1

…dule

Same RSC-safety fix as skillsai. Importing getAuthItem/etc. from the
@iblai/iblai-js/web-utils barrel pulls a top-level React.createContext (via
@iblai/web-utils 2.2.2) into the server bundle; lib/utils.ts's cn() is used by
RSC components, so the server bundle would crash with 'createContext is not a
function'. Add lib/auth-storage.ts (a dependency-free mirror of the SDK's
flag-OFF/flag-ON policy) and repoint lib/utils, lib/handlers, the
use-local-storage hook, use-user, use-speech, use-opencode-402, features/utils
and coding-mode-button to it. Only the Tenant type still comes from the barrel.
Production build passes; typecheck clean; auth-storage covered.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

PR E2E - OK

Full report, traces and screenshots

result OK
central run 33416340219
commit 77b20cd7
suite mentor - mode full - env stg1
tested against prod release 1.178.0 (env was synced to it first)
failed 1
new failures 0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run-tests Trigger PR validation pipeline

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants