types.ts

6.5 KB · raw

1/**2 * types.ts — cross-boundary types and the `MessageType` union.3 *4 * `MessageType` mixes background-bound and content-script-bound messages.5 * Background-bound types have a case in `src/background/messages.ts`.6 * Content-script-bound types (PING, SUMMON_AUTOFILL, VAULT_LOCKED,7 * RESTART_AUTO_LOCK, etc.) are sent *to* content scripts or the popup and8 * have no handler in messages.ts by design — that absence is not a missing9 * handler. Add new cross-boundary types here, not inline in call sites.10 */1112export interface ManualSummonRecord {13  firstSummonedAt: number;14  summonCount: number;15  lastSummonedAt: number;16}1718export interface Canary {19  webhookUrl: string;20  label?: string;21  lastPinged?: number;22  pingCount?: number;23}2425export type CardNetwork = "visa" | "mastercard" | "amex" | "discover" | "unknown";2627export interface VaultEntry {28  id: string; // crypto.randomUUID()29  type?: "login" | "note" | "passkey" | "card"; // defaults to "login" for existing entries30  title: string;31  username?: string; // only for login entries32  password?: string; // only for login entries33  url?: string; // only for login entries34  totp?: string; // base32 seed, stored encrypted — only for login entries35  notes?: string;36  breach?: number; // HIBP exposure count; 0 or undefined = clean — only for login entries37  canary?: Canary;38  createdAt: number; // Date.now()39  modifiedAt: number;40  deletedAt?: number;41  tags?: string[];42  rpId?: string;43  rpName?: string;44  credentialId?: string;45  publicKeyCose?: string;46  privateKeyJwk?: JsonWebKey;47  userHandle?: string;48  userName?: string;49  userDisplayName?: string;50  algorithm?: -7 | -8;51  signCount?: number;52  aaguid?: string;53  backupEligible?: boolean;54  backupState?: boolean;55  lastUsedAt?: number;56  // Card entry fields57  cardholderName?: string;58  cardNumber?: string;       // full PAN, stored encrypted in vault59  expMonth?: string;60  expYear?: string;61  cvc?: string;62  cardNickname?: string;63  network?: CardNetwork;64  last4?: string;65}6667export interface LegacyVaultEntry {68  id: string;69  title: string;70  username: string;71  password: string;72  url: string;73  totp?: string;74  notes?: string;75  breach?: number;76  created: number;77  updated: number;78  deletedAt?: number;79}8081export interface CardEntry extends VaultEntry {82  type: "card";83  cardholderName: string;84  cardNumber: string;85  expMonth: string;86  expYear: string;87  cvc: string;88}8990export interface PasskeyEntry extends VaultEntry {91  type: "passkey";92  rpId: string;93  rpName: string;94  credentialId: string;95  publicKeyCose: string;96  privateKeyJwk: JsonWebKey;97  userHandle: string;98  userName: string;99  userDisplayName: string;100  algorithm: -7 | -8;101  signCount: number;102  aaguid: string;103  backupEligible: boolean;104  backupState: boolean;105  lastUsedAt?: number;106}107108export interface PendingPasskeyRequest {109  requestId: number;110  type: "create" | "get";111  rpId: string;112  rpName: string;113  userName: string;114  userDisplayName?: string;115}116117export interface PasskeyProviderState {118  supported: boolean;119  enabled: boolean;120  attached: boolean;121  browserLabel: string;122  statusLabel: string;123  conflict?: string;124}125126export interface StoredVault {127  version: 1; // AAD for AES-GCM --- prevents downgrade128  salt: string; // hex --- 16 bytes, CSPRNG, stored not secret129  nonce: string; // hex --- 12 bytes, CSPRNG, fresh per write130  ciphertext: string; // hex --- AES-256-GCM output131  tag: string; // hex --- 16-byte GCM auth tag132}133134// Background-bound message types — sent from popup/content scripts,135// handled in src/background/messages.ts. Everything in this group must136// have a matching case in that file's switch statement.137export type MessageType =138  | "UNLOCK"139  | "LOCK"140  | "IS_UNLOCKED"141  | "HAS_VAULT"142  | "GET_ENTRIES"143  | "ADD_ENTRY"144  | "BATCH_ADD_ENTRIES"145  | "RESTORE_ENTRIES"146  | "CLEAR_VAULT_ENTRIES"147  | "UPDATE_ENTRY"148  | "DELETE_ENTRY"149  | "AUTOFILL_QUERY"150  | "COPY"151  | "CREATE_VAULT"152  | "GET_ENTRY_FOR_FILL"153  | "CHECK_BREACH"154  | "CHECK_ALL_BREACHES"155  | "GET_SETTINGS"156  | "UPDATE_SETTINGS"157  | "FIRE_CANARY_PING"158  | "ACTIVATE_LICENSE"159  | "GET_LICENSE"160  | "IS_DURESS_ENABLED"161  | "SETUP_DURESS"162  | "DISABLE_DURESS"163  | "VERIFY_MAIN_PASSWORD"164  | "CHANGE_PASSWORD"165  | "GET_SITE_PASSWORD_POLICY"166  | "GET_SYNC_STATE"167  | "TRIGGER_SYNC"168  | "START_PAIRING"169  | "CANCEL_PAIRING"170  | "ACCEPT_PAIRING"171  | "REMOVE_PAIRED_DEVICE"172  | "REMOVE_TRUSTED_NETWORK"173  | "MARK_NETWORK_TRUSTED"174  | "GET_PENDING_PASSKEY"175  | "APPROVE_PASSKEY"176  | "DENY_PASSKEY"177  | "DELETE_PASSKEY"178  | "GET_PASSKEYS"179  | "GET_PASSKEY_PROVIDER_STATE"180  | "SET_PASSKEY_PROVIDER_ENABLED"181  | "GET_DELETED_ENTRIES"182  | "RESTORE_ENTRY"183  | "PURGE_ENTRY"184  | "PURGE_EXPIRED_TRASH"185  | "LIST_VAULT_SNAPSHOTS"186  | "RESTORE_VAULT_SNAPSHOT"187  | "COUNT_DUPLICATES"188  | "DEDUPLICATE_ENTRIES"189  | "RECORD_MANUAL_SUMMON"190  | "DECLINE_CARD_SAVE"191  | "IS_CARD_DECLINED"192  | "GET_VAULT_STATUS"193  // Content-script-bound message types — sent BY the background TO content194  // scripts. They never reach messages.ts's switch. Kept in this union so195  // existing call sites type-check; do not add cases for them in the196  // background handler.197  | "PING"            // background → content: liveness probe198  | "SUMMON_AUTOFILL" // background → content: open the in-page palette199  | "VAULT_LOCKED"    // background → content/popup: vault just locked200  | "VAULT_UNLOCKED"; // background → content/popup: vault just unlocked201202export const ACCENT_COLORS = [203  { name: "peach",    hex: "#E8956D" },  // brand204  { name: "rose",     hex: "#F08296" },205  { name: "plum",     hex: "#C58BE6" },206  { name: "lavender", hex: "#9C9EF0" },207  { name: "sky",      hex: "#6EBCDE" },208  { name: "mint",     hex: "#6FD4AC" },209  { name: "sage",     hex: "#A8C870" },210  { name: "butter",   hex: "#F0CC60" },211  { name: "sand",     hex: "#DCB280" },212  { name: "clay",     hex: "#E0825E" },213  { name: "slate",    hex: "#88AEC8" },214  { name: "stone",    hex: "#B8A89C" },215] as const;216217export type AccentColorName = typeof ACCENT_COLORS[number]["name"];218219export interface PasswordPolicy {220  minLength?: number;221  maxLength?: number;222  requiresUppercase?: boolean;223  requiresLowercase?: boolean;224  requiresNumbers?: boolean;225  requiresSymbols?: boolean;226  forbidsSymbols?: boolean;227  allowedSymbols?: string;228  /** Characters the site explicitly disallows. Filtered from every pool before generation. */229  forbiddenChars?: string;230}231232export interface Message {233  type: MessageType;234  payload?: unknown;235}236237export interface MessageResponse {238  ok: boolean;239  data?: unknown;240  error?: string;241  unlocked?: boolean;242}