Seventh commit in the session-expiration-policy series. Wires the
backend taxonomy from commit 2 through to the frontend so users see
the right page (calm banner vs plain logout) when the refresh path
fails for different reasons.
- types/auth.ts: Token gains idle_expires_at + absolute_expires_at
(Optional ISO 8601 strings). The next commit adds the
useAuthSessionExpiry hook that reads these.
- api/auth.ts: OAuthCallbackResponse mirrors the same two fields.
- api/client.ts: refresh-failure handler now branches on the response
detail. session_expired_idle and session_expired_absolute both
redirect to /login?reason=session_expired (commit 8 adds the
banner that reads the query param); any other detail (most
commonly invalid_refresh_token) goes to plain /login. The bare
redirect is guarded against re-firing when the user is already on
/login. The refresh-success path now forwards the two new fields
into setTokens so the store stays current as the session ages.
- pages/OAuthCallbackPage.tsx: setTokens({...}) spreads
idle_expires_at + absolute_expires_at from the OAuth response.
No new tests — authStore.test still 2/2, tsc clean. The
useAuthSessionExpiry hook and the SessionExpiryToast that consume
the new fields land in commit 8 alongside the AccountSecurity page.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- flowpilot_engine: pass account_id at all 5 AISessionStep instantiation
sites (_create_step_from_parsed x3, briefing step, status update step).
Phase 4 RLS blocked every INSERT with NULL account_id — this broke all
new FlowPilot sessions since the Phase 4 migration was applied.
- integrations: list_boards returns [] on PSAError instead of 502, stopping
the spurious 'Server error' toast on dashboard load (boards are optional).
- client.ts: 5xx global toast now shows backend detail when available.
- useFlowPilotSession: startSession extracts backend detail for error state;
suppresses duplicate toast for 5xx (global interceptor already handles it).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: prevent race conditions in token operations and auth flows
Backend:
- Refresh token rotation: use atomic UPDATE...WHERE revoked_at IS NULL
to prevent concurrent refresh requests from both succeeding
- Account invite codes: SELECT FOR UPDATE to prevent double-spend
- Platform invite codes: SELECT FOR UPDATE to prevent double-spend
- Password reset tokens: SELECT FOR UPDATE to prevent double-use
- Email verification tokens: SELECT FOR UPDATE to prevent double-use
Frontend:
- Token refresh subscriber arrays: swap before iterating so a throwing
callback doesn't leave the queue in a dirty state
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: atomic counters, plan limit re-check, and double-submit guard
Backend:
- Tree usage_count: use SQL-level UPDATE (Tree.usage_count + 1) instead
of Python-level increment to prevent lost updates under concurrency
- Tag usage_count: same SQL-level atomic increment/decrement in both
create_tree and update_tree (delete_tree already used this pattern)
- Plan tree limit: re-check count after db.flush() to close the TOCTOU
window where two concurrent creates could both pass the pre-check
Frontend:
- TreeEditorPage: add isSaving early-return guard inside handleSaveDraft
and handlePublish callbacks so Ctrl+S can't bypass the button disabled
prop and fire duplicate save requests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: prevent stale API responses from overwriting newer data
- SessionHistoryPage: move loadSessions into effect with cancelled flag
so rapid filter/tab changes discard outdated responses
- TreeLibraryPage: add request ID ref to loadTrees so stale responses
from previous filter selections are discarded
- QuickStartPage: add request ID ref to debounced search so out-of-order
responses don't overwrite newer search results
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add flexible intake design — deferred variables + prepared sessions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- AI flow builder: scaffold → branch detail → assemble → review flow
- Generate All one-click branch generation with stop/cancel
- Regenerate scaffold suggestions button
- 3-action review screen: Start Flow, Open in Editor, Build Another
- Fix Publish button gated behind !isDirty
- Fix visibility column enforcement in tree access filter
- Add ?visibility filter and author_name to GET /trees
- Dashboard tabbed flows: My Flows / My Team / Public / All
- Create button in My Flows tab, window focus reload (stale data fix)
- Fork UI with optional reason modal
- Fix account_id nullability in User type and schema
- Keep is_public and visibility in sync on updates
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: tree editor authoring blockers - scroll trap, form density, branching hint
- Replace fixed viewport height with flex layout in NodeEditorPanel
- Make footer sticky so Save/Cancel always reachable
- Compact root node banner to single-line with InfoTip tooltip
- Reduce resolution note from callout box to inline text
- Add answer-first branching hint below options label
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: broken functionality - auth errors, toast logic, role update, routing, step library
- Extract backend error detail in auth store login/register
- Fix inverted 4xx toast logic and add 429 rate limit handling
- Send account_role field to match backend schema in role update
- Use type-aware routing for Repeat Last Session button
- Add step library placeholder page and route, remove dot badge
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: navigation correctness - back buttons, exit dialog, dedup nav, redirects
- Standardize all procedural back/exit paths to /trees (not /my-trees)
- Add exit button with ConfirmDialog to procedural session top bar
- Consolidate duplicate account links in sidebar and topbar
- Auto-redirect non-owners to personal analytics
- Add toast feedback before silent permission redirects in tree editor
- Delete orphaned AdminCategoriesPage
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: shared components, ConfirmDialog migration, pinned flow fixes
- Create shared Spinner component with sm/md/lg sizes
- Migrate 13 page-level spinners to shared Spinner
- Promote EmptyState to shared component, adopt in MyShares and SessionHistory
- Replace window.confirm with ConfirmDialog in 3 files
- Fix PinnedFlow.tree_type to include maintenance, update emoji display
- Verify sidebar unpin handler already correct (no-op)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: visual consistency - toasts, typography, focus rings, container padding
- Remove richColors from Sonner toasts, limit stacking to 3
- Add font-heading to all page H1s (7 files)
- Add font-label (Outfit) to TagBadges component
- Fix focus ring tokens on analytics pages
- Replace deprecated glass-stat with design system tokens
- Standardize container padding on analytics pages
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: backend alignment - remove drafts toggle, clean dead code, truncation indicator
- Remove non-functional drafts toggle and clean TreeFilters type
- Fix AccountInvite type to match backend schema
- Remove dead API methods: pinnedFlows.pin/reorder, trees.getSharedTree
- Remove unused types: SessionListResponse, RatingCreate.is_verified_use
- Add session list truncation indicator with size=51 lookahead
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: remove bg-black from PageLoader and RouteError, fix PageLoader height
PageLoader used h-screen inside a grid cell, causing it to overflow.
Changed to h-full so it fits within the main-content area. Removed
bg-black from both PageLoader and RouteError in favor of theme-aware
bg-background to prevent black flash during lazy loading.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: guard against Pydantic validation error objects in toast/error messages
FastAPI returns `detail` as an array of objects for 422 validation errors,
not a string. Passing these objects to toast.error() or rendering them in
JSX crashes React with Error #31 ("Objects are not valid as a React child").
Now checks typeof detail === 'string' before using it.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: toast styling, node editor first-click, action node placeholder pattern
1. Toast fixes: Add theme="dark" to Sonner, use !important CSS overrides
instead of zero-specificity :where() selectors, suppress noisy 4xx
global toasts (pages handle their own errors)
2. Node editor first-click: Add node.type to draft initialization
useEffect deps so draft resets when answer stub converts to real type
3. Action node redesign: Remove NodePicker dropdown, auto-create answer
placeholder on save (matching decision node pattern). Users click the
placeholder on canvas to choose type and fill in details.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: auto-seed test users when release command fails on PR envs
The background seeder now creates users directly via DB if login fails,
instead of silently aborting. This handles Railway PR environments where
the releaseCommand may not execute properly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: remove categories/tags from sidebar to prevent footer clipping
Categories and Tags sections were pushing Feedback, Account, and
Collapse off-screen when All Flows expanded its children. These
filters already exist on the TreeLibraryPage, so the sidebar
duplicates were removed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Fix broken JWT token refresh that caused "Failed to load trees" after
idle timeout. The refresh endpoint expected token as query param but
frontend sent it as Authorization header. Added proper dependency
(get_refresh_token_payload) and refresh queue to handle concurrent 401s.
Also fix seed trees not being visible to non-admin users by updating
the seed script to set is_public/is_default on existing trees.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>