feat(ext/shared): centralize error-message copy in ERROR_COPY map
Replaces the popup's regex-chain humanizeError with a total lookup over every error code returned by extension/src/service-worker/router/. A generated test discovers codes via grep so the registry can't drift. The popup keeps its small set of regex translators for Rust/serde error phrasing that doesn't go through the router's error vocabulary. Subsumes B2 — fullscreen consumer lands in the next commit.
This commit is contained in:
102
extension/src/shared/error-copy.ts
Normal file
102
extension/src/shared/error-copy.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
export interface ErrorCta {
|
||||
label: string;
|
||||
action?: 'unlock' | 'reload_extension' | 'open_setup';
|
||||
}
|
||||
|
||||
export interface ErrorCopy {
|
||||
title: string;
|
||||
body: string;
|
||||
cta?: ErrorCta;
|
||||
}
|
||||
|
||||
const UNLOCK_CTA: ErrorCta = { label: 'Unlock vault', action: 'unlock' };
|
||||
|
||||
export const ERROR_COPY: Record<string, ErrorCopy> = {
|
||||
vault_locked: {
|
||||
title: 'Vault locked',
|
||||
body: 'Unlock your vault to continue.',
|
||||
cta: UNLOCK_CTA,
|
||||
},
|
||||
unauthorized_sender: {
|
||||
title: 'Action not allowed',
|
||||
body: 'This action is not allowed from here.',
|
||||
},
|
||||
unknown_message_type: {
|
||||
title: 'Internal error',
|
||||
body: 'The extension received an unknown request — try reloading.',
|
||||
cta: { label: 'Reload extension', action: 'reload_extension' },
|
||||
},
|
||||
origin_mismatch: {
|
||||
title: 'Wrong site',
|
||||
body: 'This login belongs to a different site — refusing to leak credentials cross-origin.',
|
||||
},
|
||||
not_a_login: {
|
||||
title: 'Not a login',
|
||||
body: 'That item does not have a username and password to fill.',
|
||||
},
|
||||
no_totp: {
|
||||
title: 'No 2FA on this item',
|
||||
body: 'This item does not have a TOTP secret configured.',
|
||||
},
|
||||
invalid_sender_url: {
|
||||
title: 'Cannot read tab URL',
|
||||
body: 'The current tab has no recognizable URL — try reloading the page.',
|
||||
},
|
||||
tab_navigated: {
|
||||
title: 'Tab changed',
|
||||
body: 'The browser tab changed before the action could complete — try again.',
|
||||
},
|
||||
captured_tab_gone: {
|
||||
title: 'Tab is gone',
|
||||
body: 'The browser tab closed before the action could complete — try again.',
|
||||
},
|
||||
item_not_found: {
|
||||
title: 'Item not found',
|
||||
body: 'That item is no longer in the vault — it may have been deleted from another device.',
|
||||
},
|
||||
attachment_not_found: {
|
||||
title: 'Attachment missing',
|
||||
body: 'The attachment is referenced in the item but is not present in the vault.',
|
||||
},
|
||||
upload_failed: {
|
||||
title: 'Upload failed',
|
||||
body: 'Could not upload the attachment — check your connection and try again.',
|
||||
},
|
||||
download_failed: {
|
||||
title: 'Download failed',
|
||||
body: 'Could not download the attachment — check your connection and try again.',
|
||||
},
|
||||
'invalid base32 secret': {
|
||||
title: 'Invalid secret',
|
||||
body: 'The TOTP secret must be valid Base32 (letters A-Z and digits 2-7 only).',
|
||||
},
|
||||
'no items to import': {
|
||||
title: 'Nothing to import',
|
||||
body: 'The CSV did not contain any importable items.',
|
||||
},
|
||||
'no reference image stored locally': {
|
||||
title: 'No reference image',
|
||||
body: 'This device has no reference image saved locally — re-attach the device or restore from backup.',
|
||||
},
|
||||
'remote already contains a Relicario vault': {
|
||||
title: 'Vault already exists',
|
||||
body: 'The selected repository already contains a vault — use Attach existing instead of Create new.',
|
||||
},
|
||||
'Extension not configured. Run setup first.': {
|
||||
title: 'Extension not configured',
|
||||
body: 'Run setup before using this action.',
|
||||
cta: { label: 'Open setup', action: 'open_setup' },
|
||||
},
|
||||
'Reference image not set. Run setup first.': {
|
||||
title: 'Reference image missing',
|
||||
body: 'Run setup to save your reference image.',
|
||||
cta: { label: 'Open setup', action: 'open_setup' },
|
||||
},
|
||||
};
|
||||
|
||||
export function lookupErrorCopy(code: string): ErrorCopy {
|
||||
return ERROR_COPY[code] ?? {
|
||||
title: 'Something went wrong',
|
||||
body: code,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user