feat(FN-1153): add cross-tab locks for AI planning sessions
- Bump SQLite schema to v19 with ai_sessions lock columns and lock index, and align migration coverage in core DB tests - Extend AiSessionStore with acquire/release/force lock APIs, stale lock cleanup, and lock metadata in ai_session update summaries - Enforce lock checks on planning, subtask, and mission interview mutation routes with 409 conflict responses while keeping stream reads unaffected - Add frontend tab identity + useSessionLock hook and wire Planning, Subtask, and Mission modals to pass tabId, show lock overlay, and support Take Control - Expand dashboard route/e2e and modal tests to validate lock enforcement, lock handoff, and lock-aware session reentry behavior
This commit is contained in:
25
packages/dashboard/app/utils/getSessionTabId.ts
Normal file
25
packages/dashboard/app/utils/getSessionTabId.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
const SESSION_TAB_ID_KEY = "fusion-tab-id";
|
||||
|
||||
function createTabId(): string {
|
||||
const cryptoApi = globalThis.crypto;
|
||||
if (cryptoApi && typeof cryptoApi.randomUUID === "function") {
|
||||
return cryptoApi.randomUUID();
|
||||
}
|
||||
|
||||
return `tab-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
||||
}
|
||||
|
||||
export function getSessionTabId(): string {
|
||||
if (typeof window === "undefined") {
|
||||
return "server-tab";
|
||||
}
|
||||
|
||||
const existing = window.sessionStorage.getItem(SESSION_TAB_ID_KEY);
|
||||
if (existing) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
const next = createTabId();
|
||||
window.sessionStorage.setItem(SESSION_TAB_ID_KEY, next);
|
||||
return next;
|
||||
}
|
||||
Reference in New Issue
Block a user