Add persistent onion key backup and restore, improve startup resilience, and flesh out the major site verticals with richer navigation, search coverage, and operator documentation. Made-with: Cursor
84 lines
2.8 KiB
TypeScript
84 lines
2.8 KiB
TypeScript
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<string, boolean>;
|
|
};
|
|
|
|
const STORAGE_KEY = "cyberlux:vault:v1";
|
|
|
|
export function defaultVaultState(): VaultState {
|
|
return {
|
|
version: 1,
|
|
keys: [],
|
|
receipts: [
|
|
{ id: "8821", title: "Receipt #8821", desc: "For 1x Used Password", date: "2026-03-12", severity: "normal" },
|
|
{ id: "9044", title: "Receipt #9044", desc: "For 3x Liquid Motivation", date: "2026-03-15", severity: "normal" },
|
|
{ id: "X-0000", title: "Mystery File", desc: "Unknown executable. DO NOT OPEN.", date: "1970-01-01", severity: "redacted" },
|
|
],
|
|
flags: {},
|
|
};
|
|
}
|
|
|
|
export function safeParseVaultState(raw: string | null): VaultState {
|
|
if (!raw) return defaultVaultState();
|
|
try {
|
|
const v = JSON.parse(raw) as Partial<VaultState>;
|
|
const base = defaultVaultState();
|
|
const keys = Array.isArray(v.keys) ? v.keys.filter((k) => typeof k === "string") : base.keys;
|
|
const receipts = Array.isArray(v.receipts)
|
|
? (v.receipts as any[]).filter(Boolean).map((r) => ({
|
|
id: String(r.id ?? ""),
|
|
title: String(r.title ?? "Receipt"),
|
|
desc: String(r.desc ?? ""),
|
|
date: String(r.date ?? ""),
|
|
severity: (r.severity === "weird" || r.severity === "redacted" || r.severity === "normal") ? r.severity : "normal",
|
|
}))
|
|
: base.receipts;
|
|
const flags = v.flags && typeof v.flags === "object" ? (v.flags as Record<string, boolean>) : base.flags;
|
|
return { version: 1, keys, receipts, flags };
|
|
} catch {
|
|
return defaultVaultState();
|
|
}
|
|
}
|
|
|
|
export function loadVaultState(): VaultState {
|
|
if (typeof window === "undefined") return defaultVaultState();
|
|
return safeParseVaultState(window.localStorage.getItem(STORAGE_KEY));
|
|
}
|
|
|
|
export function saveVaultState(state: VaultState) {
|
|
if (typeof window === "undefined") return;
|
|
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
|
|
}
|
|
|
|
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]: value } };
|
|
}
|
|
|
|
export function hasFlag(state: VaultState, flag: string) {
|
|
return Boolean(state.flags?.[flag]);
|
|
}
|
|
|