Ctrl K
ComunidadGuías…

frontend/src/skins/vaultLogic.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
/**
 * Vault state shared by every skin's extension.
 *
 * Wraps the real device-local vault (lib/localStore/vault) — AES-GCM under a
 * key generated non-extractable, so the raw key can never be read out of the
 * browser. That is materially different from what the imported designs
 * simulate: all three ship a vault backed by plain localStorage and carry a
 * "protection is simulated, do not enter real passwords" notice. Wiring this in
 * is what lets those notices come off.
 *
 * It also means the designs' "protection level" chooser (device / PIN /
 * passphrase) has nothing to map onto. The real model is simpler and stronger:
 * the key is bound to this browser profile and cannot leave it. The surfaces
 * built here say that instead of inventing a chooser.
 */
import { vault } from "@/lib/localStore";

export interface VaultRow {
    id: string;
    label: string;
    createdAt: number;
    lastUsedAt: number;
    useCount: number;
}

export interface VaultState {
    entries: VaultRow[];
    /** id of the entry currently revealed, if any. */
    revealedId: string;
    revealedValue: string;
    label: string;
    password: string;
    busy: boolean;
    error: string;
    /** Entries that failed to decrypt — a key mismatch, not corruption we caused. */
    unreadable: number;
    confirmingClear: boolean;
}

export const initialVaultState: VaultState = {
    entries: [], revealedId: "", revealedValue: "", label: "", password: "",
    busy: false, error: "", unreadable: 0, confirmingClear: false,
};

export const vaultApi = {
    async load(): Promise<{ entries: VaultRow[]; unreadable: number }> {
        const [entries, unreadable] = await Promise.all([
            vault.listEntries(),
            vault.unreadableCount(),
        ]);
        return { entries: entries as VaultRow[], unreadable };
    },
    add: (label: string, password: string) => vault.addPassword(label, password),
    reveal: (id: string) => vault.revealPassword(id),
    remove: (id: string) => vault.deleteEntry(id),
    clear: () => vault.clearVault(),
};

/** Short, human description of an entry for a list row. */
export function describeEntry(row: VaultRow): string {
    const created = new Date(row.createdAt).toISOString().slice(0, 10);
    if (!row.useCount) return `Never used · added ${created}`;
    const used = new Date(row.lastUsedAt).toISOString().slice(0, 10);
    return `Used ${row.useCount}× · last ${used}`;
}