Files
Shadowbroker/frontend/src/lib/privacyBrowserStorage.ts
T
anoracleofra-code 668ce16dc7 v0.9.6: InfoNet hashchain, Wormhole gate encryption, mesh reputation, 16 community contributors
Gate messages now propagate via the Infonet hashchain as encrypted blobs — every node syncs them
through normal chain sync while only Gate members with MLS keys can decrypt. Added mesh reputation
system, peer push workers, voluntary Wormhole opt-in for node participation, fork recovery,
killwormhole scripts, obfuscated terminology, and hardened the self-updater to protect encryption
keys and chain state during updates.

New features: Shodan search, train tracking, Sentinel Hub imagery, 8 new intelligence layers,
CCTV expansion to 11,000+ cameras across 6 countries, Mesh Terminal CLI, prediction markets,
desktop-shell scaffold, and comprehensive mesh test suite (215 frontend + backend tests passing).

Community contributors: @wa1id, @AlborzNazari, @adust09, @Xpirix, @imqdcr, @csysp, @suranyami,
@chr0n1x, @johan-martensson, @singularfailure, @smithbh, @OrfeoTerkuci, @deuza, @tm-const,
@Elhard1, @ttulttul
2026-03-26 05:58:04 -06:00

147 lines
4.2 KiB
TypeScript

const PRIVACY_STRICT_KEY = 'sb_privacy_strict';
const PRIVACY_PROFILE_KEY = 'sb_privacy_profile';
const SESSION_MODE_KEY = 'sb_mesh_session_mode';
type BrowserStorageMode = 'local' | 'session';
function browserAvailable(): boolean {
return typeof window !== 'undefined';
}
function safeGet(store: Storage, key: string): string | null {
try {
return store.getItem(key);
} catch {
return null;
}
}
function safeSet(store: Storage, key: string, value: string): void {
try {
store.setItem(key, value);
} catch {
/* ignore */
}
}
function safeRemove(store: Storage, key: string): void {
try {
store.removeItem(key);
} catch {
/* ignore */
}
}
function readPreference(key: string): string | null {
if (!browserAvailable()) return null;
const sessionValue = safeGet(sessionStorage, key);
if (sessionValue !== null) return sessionValue;
return safeGet(localStorage, key);
}
function writePreference(key: string, value: string, mode: BrowserStorageMode): void {
if (!browserAvailable()) return;
const preferred = mode === 'session' ? sessionStorage : localStorage;
const alternate = mode === 'session' ? localStorage : sessionStorage;
safeSet(preferred, key, value);
safeRemove(alternate, key);
}
export function getSessionModePreference(): boolean {
return readPreference(SESSION_MODE_KEY) !== 'false';
}
export function setSessionModePreference(enabled: boolean): void {
writePreference(SESSION_MODE_KEY, enabled ? 'true' : 'false', enabled ? 'session' : 'local');
}
export function getPrivacyStrictPreference(): boolean {
return readPreference(PRIVACY_STRICT_KEY) === 'true';
}
export function setPrivacyStrictPreference(
enabled: boolean,
opts?: { sessionMode?: boolean },
): void {
const sessionMode = opts?.sessionMode ?? getSessionModePreference();
writePreference(
PRIVACY_STRICT_KEY,
enabled ? 'true' : 'false',
enabled || sessionMode ? 'session' : 'local',
);
}
export function getPrivacyProfilePreference(): string {
return readPreference(PRIVACY_PROFILE_KEY) || 'default';
}
export function setPrivacyProfilePreference(
profile: string,
opts?: { sessionMode?: boolean },
): void {
const normalized = String(profile || 'default') || 'default';
const sessionMode = opts?.sessionMode ?? getSessionModePreference();
writePreference(
PRIVACY_PROFILE_KEY,
normalized,
normalized === 'high' || sessionMode ? 'session' : 'local',
);
}
export function getSensitiveBrowserStorageMode(): BrowserStorageMode {
if (!browserAvailable()) return 'session';
const strict = getPrivacyStrictPreference();
const sessionMode = getSessionModePreference();
return strict || sessionMode ? 'session' : 'local';
}
function preferredSensitiveStorage(): Storage | null {
if (!browserAvailable()) return null;
return getSensitiveBrowserStorageMode() === 'session' ? sessionStorage : localStorage;
}
function alternateStorage(preferred: Storage): Storage | null {
if (!browserAvailable()) return null;
return preferred === localStorage ? sessionStorage : localStorage;
}
export function getSensitiveBrowserItem(key: string): string | null {
const preferred = preferredSensitiveStorage();
if (!preferred) return null;
const alternate = alternateStorage(preferred);
const preferredValue = safeGet(preferred, key);
if (preferredValue !== null) return preferredValue;
if (!alternate) return null;
const alternateValue = safeGet(alternate, key);
if (alternateValue !== null) {
safeSet(preferred, key, alternateValue);
if (alternate !== preferred) {
safeRemove(alternate, key);
}
}
return alternateValue;
}
export function setSensitiveBrowserItem(key: string, value: string): void {
const preferred = preferredSensitiveStorage();
if (!preferred) return;
const alternate = alternateStorage(preferred);
safeSet(preferred, key, value);
if (alternate && alternate !== preferred) {
safeRemove(alternate, key);
}
}
export function removeSensitiveBrowserItem(key: string): void {
if (!browserAvailable()) return;
safeRemove(localStorage, key);
safeRemove(sessionStorage, key);
}
export function migrateSensitiveBrowserItems(keys: string[]): void {
if (!browserAvailable()) return;
keys.forEach((key) => {
void getSensitiveBrowserItem(key);
});
}