types.ts

6.3 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  // Content-script-bound message types — sent BY the background TO content193  // scripts. They never reach messages.ts's switch. Kept in this union so194  // existing call sites type-check; do not add cases for them in the195  // background handler.196  | "PING"            // background → content: liveness probe197  | "SUMMON_AUTOFILL" // background → content: open the in-page palette198  | "VAULT_LOCKED"    // background → content/popup: vault just locked199  | "VAULT_UNLOCKED"; // background → content/popup: vault just unlocked200201export const ACCENT_COLORS = [202  { name: "peach",    hex: "#E8956D" },203  { name: "rose",     hex: "#E8909A" },204  { name: "plum",     hex: "#C49AC8" },205  { name: "lavender", hex: "#9FA8D4" },206  { name: "sky",      hex: "#85BAD4" },207  { name: "mint",     hex: "#7EC8A4" },208  { name: "sage",     hex: "#9AB87A" },209  { name: "butter",   hex: "#D4B96A" },210  { name: "sand",     hex: "#C8A882" },211  { name: "clay",     hex: "#C4826A" },212  { name: "slate",    hex: "#8A9EAA" },213  { name: "stone",    hex: "#A89E92" },214] as const;215216export type AccentColorName = typeof ACCENT_COLORS[number]["name"];217218export interface PasswordPolicy {219  minLength?: number;220  maxLength?: number;221  requiresUppercase?: boolean;222  requiresLowercase?: boolean;223  requiresNumbers?: boolean;224  requiresSymbols?: boolean;225  forbidsSymbols?: boolean;226  allowedSymbols?: string;227}228229export interface Message {230  type: MessageType;231  payload?: unknown;232}233234export interface MessageResponse {235  ok: boolean;236  data?: unknown;237  error?: string;238}