export interface Canary { webhookUrl: string; label?: string; lastPinged?: number; pingCount?: number; } export interface VaultEntry { id: string; // crypto.randomUUID() type?: "login" | "note" | "passkey"; // defaults to "login" for existing entries title: string; username?: string; // only for login entries password?: string; // only for login entries url?: string; // only for login entries totp?: string; // base32 seed, stored encrypted — only for login entries notes?: string; breach?: number; // HIBP exposure count; 0 or undefined = clean — only for login entries canary?: Canary; createdAt: number; // Date.now() modifiedAt: number; deletedAt?: number; tags?: string[]; rpId?: string; rpName?: string; credentialId?: string; publicKeyCose?: string; privateKeyJwk?: JsonWebKey; userHandle?: string; userName?: string; userDisplayName?: string; algorithm?: -7 | -8; signCount?: number; aaguid?: string; backupEligible?: boolean; backupState?: boolean; lastUsedAt?: number; } export interface LegacyVaultEntry { id: string; title: string; username: string; password: string; url: string; totp?: string; notes?: string; breach?: number; created: number; updated: number; deletedAt?: number; } export interface PasskeyEntry extends VaultEntry { type: "passkey"; rpId: string; rpName: string; credentialId: string; publicKeyCose: string; privateKeyJwk: JsonWebKey; userHandle: string; userName: string; userDisplayName: string; algorithm: -7 | -8; signCount: number; aaguid: string; backupEligible: boolean; backupState: boolean; lastUsedAt?: number; } export interface PendingPasskeyRequest { requestId: number; type: "create" | "get"; rpId: string; rpName: string; userName: string; userDisplayName?: string; } export interface PasskeyProviderState { supported: boolean; enabled: boolean; attached: boolean; browserLabel: string; statusLabel: string; conflict?: string; } export interface StoredVault { version: 1; // AAD for AES-GCM --- prevents downgrade salt: string; // hex --- 16 bytes, CSPRNG, stored not secret nonce: string; // hex --- 12 bytes, CSPRNG, fresh per write ciphertext: string; // hex --- AES-256-GCM output tag: string; // hex --- 16-byte GCM auth tag } // Background-bound message types — sent from popup/content scripts, // handled in src/background/messages.ts. Everything in this group must // have a matching case in that file's switch statement. export type MessageType = | "UNLOCK" | "LOCK" | "IS_UNLOCKED" | "HAS_VAULT" | "GET_ENTRIES" | "ADD_ENTRY" | "BATCH_ADD_ENTRIES" | "RESTORE_ENTRIES" | "CLEAR_VAULT_ENTRIES" | "UPDATE_ENTRY" | "DELETE_ENTRY" | "AUTOFILL_QUERY" | "COPY" | "CREATE_VAULT" | "GET_ENTRY_FOR_FILL" | "CHECK_BREACH" | "CHECK_ALL_BREACHES" | "GET_SETTINGS" | "UPDATE_SETTINGS" | "FIRE_CANARY_PING" | "ACTIVATE_LICENSE" | "GET_LICENSE" | "IS_DURESS_ENABLED" | "SETUP_DURESS" | "DISABLE_DURESS" | "VERIFY_MAIN_PASSWORD" | "CHANGE_PASSWORD" | "GET_SITE_PASSWORD_POLICY" | "GET_SYNC_STATE" | "TRIGGER_SYNC" | "START_PAIRING" | "CANCEL_PAIRING" | "ACCEPT_PAIRING" | "REMOVE_PAIRED_DEVICE" | "REMOVE_TRUSTED_NETWORK" | "MARK_NETWORK_TRUSTED" | "GET_PENDING_PASSKEY" | "APPROVE_PASSKEY" | "DENY_PASSKEY" | "DELETE_PASSKEY" | "GET_PASSKEYS" | "GET_PASSKEY_PROVIDER_STATE" | "SET_PASSKEY_PROVIDER_ENABLED" | "GET_DELETED_ENTRIES" | "RESTORE_ENTRY" | "PURGE_ENTRY" | "PURGE_EXPIRED_TRASH" | "LIST_VAULT_SNAPSHOTS" | "RESTORE_VAULT_SNAPSHOT" | "COUNT_DUPLICATES" | "DEDUPLICATE_ENTRIES" // Content-script-bound message types — sent BY the background TO content // scripts. They never reach messages.ts's switch. Kept in this union so // existing call sites type-check; do not add cases for them in the // background handler. | "PING" // background → content: liveness probe | "SUMMON_AUTOFILL" // background → content: open the in-page palette | "VAULT_LOCKED" // background → content/popup: vault just locked | "VAULT_UNLOCKED"; // background → content/popup: vault just unlocked export const ACCENT_COLORS = [ { name: "peach", hex: "#E8956D" }, { name: "rose", hex: "#E8909A" }, { name: "plum", hex: "#C49AC8" }, { name: "lavender", hex: "#9FA8D4" }, { name: "sky", hex: "#85BAD4" }, { name: "mint", hex: "#7EC8A4" }, { name: "sage", hex: "#9AB87A" }, { name: "butter", hex: "#D4B96A" }, { name: "sand", hex: "#C8A882" }, { name: "clay", hex: "#C4826A" }, { name: "slate", hex: "#8A9EAA" }, { name: "stone", hex: "#A89E92" }, ] as const; export type AccentColorName = typeof ACCENT_COLORS[number]["name"]; export interface PasswordPolicy { minLength?: number; maxLength?: number; requiresUppercase?: boolean; requiresLowercase?: boolean; requiresNumbers?: boolean; requiresSymbols?: boolean; forbidsSymbols?: boolean; allowedSymbols?: string; } export interface Message { type: MessageType; payload?: unknown; } export interface MessageResponse { ok: boolean; data?: unknown; error?: string; }