export type VaultReceipt = { id: string; title: string; desc: string; date: string; severity: "normal" | "weird" | "redacted"; }; export type VaultState = { version: 1; keys: string[]; receipts: VaultReceipt[]; flags: Record; }; /** Legacy single-vault bucket (pre–per-account). */ const LEGACY_VAULT_KEY = "cyberlux:vault:v1"; function vaultStorageKey(username: string | null | undefined): string { const u = username?.trim().toLowerCase(); if (!u) return LEGACY_VAULT_KEY; return `cyberlux:vault:v2:${u}`; } export function defaultVaultState(): VaultState { return { version: 1, keys: [], receipts: [], flags: {} }; } export function safeParseVaultState(raw: string | null): VaultState { if (!raw) return defaultVaultState(); try { const v = JSON.parse(raw) as Partial; const keys = Array.isArray(v.keys) ? v.keys.filter((k) => typeof k === "string") : []; const receipts: VaultReceipt[] = Array.isArray(v.receipts) ? (v.receipts as unknown[]).filter(Boolean).map((r) => { const x = r as Record; const sev = x.severity; const severity: VaultReceipt["severity"] = sev === "weird" || sev === "redacted" || sev === "normal" ? sev : "normal"; return { id: String(x.id ?? ""), title: String(x.title ?? "Receipt"), desc: String(x.desc ?? ""), date: String(x.date ?? ""), severity, }; }) : []; const flags = v.flags && typeof v.flags === "object" ? (v.flags as Record) : {}; return { version: 1, keys, receipts, flags }; } catch { return defaultVaultState(); } } /** Load vault for a signed-in handle, or the legacy anonymous bucket when username is omitted. */ export function loadVaultState(username?: string | null): VaultState { if (typeof window === "undefined") return defaultVaultState(); const u = username?.trim() ? username.trim().toLowerCase() : null; const key = vaultStorageKey(u); let raw = localStorage.getItem(key); if (u && raw == null) { const legacy = localStorage.getItem(LEGACY_VAULT_KEY); if (legacy) { localStorage.setItem(key, legacy); raw = legacy; } } return safeParseVaultState(raw); } export function saveVaultState(username: string | null | undefined, state: VaultState): void { if (typeof window === "undefined") return; const key = vaultStorageKey(username?.trim() ? username.trim().toLowerCase() : null); localStorage.setItem(key, JSON.stringify(state)); if (username?.trim() && localStorage.getItem(LEGACY_VAULT_KEY)) { localStorage.removeItem(LEGACY_VAULT_KEY); } } export function addKey(state: VaultState, key: string): VaultState { if (!key) return state; if (state.keys.includes(key)) return state; return { ...state, keys: [...state.keys, key] }; } export function addReceipt(state: VaultState, receipt: VaultReceipt): VaultState { if (!receipt?.id) return state; if (state.receipts.some((r) => r.id === receipt.id)) return state; return { ...state, receipts: [receipt, ...state.receipts].slice(0, 24) }; } export function setFlag(state: VaultState, flag: string, value: boolean): VaultState { if (!flag) return state; return { ...state, flags: { ...state.flags, [flag]: Boolean(value) } }; } export function hasFlag(state: VaultState, flag: string) { return Boolean(state.flags?.[flag]); }