fix(ext): get_totp handles Totp items, not just Login
Critical bug caught in T8 code review: the SW's get_totp handler gated on core.type === 'login' and referenced core.totp, so the standalone Totp item type (which lands in T8 with core.type === 'totp' and core.config) had its detail-view ticker silently rejected with 'no_totp' every second. Ticker swallowed the error; rotating code display stayed at placeholder forever. Fix: extend the handler to resolve TotpConfig from either carrier: - Login items: item.core.totp (optional subfield) - Totp items: item.core.config (required) Also: - Add 3 router tests covering both paths + the empty case - Remove stale '……' placeholder check in types/totp.ts's \`t\` keyboard shortcut (dead code — the placeholder is '·····' or '······', never horizontal ellipses) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
/// via sender.url === popup.html (or setup.html for save_setup).
|
||||
|
||||
import type { PopupMessage, Response } from '../../shared/messages';
|
||||
import type { Item, ItemId, Manifest, VaultConfig, SetupState, DeviceSettings } from '../../shared/types';
|
||||
import type { Item, ItemId, Manifest, VaultConfig, SetupState, DeviceSettings, TotpConfig } from '../../shared/types';
|
||||
import { DEFAULT_DEVICE_SETTINGS } from '../../shared/types';
|
||||
import type { GitHost } from '../git-host';
|
||||
import { createGitHost, base64ToUint8Array } from '../git-host';
|
||||
@@ -107,11 +107,18 @@ export async function handle(
|
||||
const handle = session.getCurrent();
|
||||
if (!handle || !state.gitHost) return { ok: false, error: 'vault_locked' };
|
||||
const item = await vault.fetchAndDecryptItem(state.gitHost, handle, msg.id);
|
||||
if (item.core.type !== 'login' || !item.core.totp) {
|
||||
return { ok: false, error: 'no_totp' };
|
||||
// Resolve the TotpConfig from whichever carrier the item type uses.
|
||||
// Login items hold TOTP as an optional subfield on LoginCore; the standalone
|
||||
// Totp item type carries it as TotpCore.config (required).
|
||||
let cfg: TotpConfig | null = null;
|
||||
if (item.core.type === 'login' && item.core.totp) {
|
||||
cfg = item.core.totp;
|
||||
} else if (item.core.type === 'totp') {
|
||||
cfg = item.core.config;
|
||||
}
|
||||
if (!cfg) return { ok: false, error: 'no_totp' };
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
const code = state.wasm.totp_compute(JSON.stringify(item.core.totp), BigInt(now));
|
||||
const code = state.wasm.totp_compute(JSON.stringify(cfg), BigInt(now));
|
||||
return { ok: true, data: { code: code.code, expires_at: code.expires_at } };
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user