/** 店铺中心敏感字段掩码与短时揭示(任务 86):店铺密钥令牌等凭证明文默认以掩码展示, * 用户主动点击后才在内存中短时揭示;不写入全局状态、持久化存储、地址栏或日志。纯逻辑,可注入时间便于测试。 */ /** 掩码占位符(默认固定长度,与旧页面 ****** 一致)。 */ export const SECRET_PLACEHOLDER = '******' /** 未指定时长时的默认揭示窗口(毫秒)。 */ export const DEFAULT_REVEAL_MS = 5_000 export interface SecretRevealState { /** 当前被揭示的记录行 id;无揭示时为 null。 */ keyId: number | null /** 揭示中的明文,仅存内存、离开即清空。 */ token?: string /** 揭示过期时间点(毫秒)。 */ expiresAt?: number } /** 空揭示状态(首屏/页面卸载默认)。 */ export function createSecretRevealState(): SecretRevealState { return { keyId: null, token: undefined, expiresAt: undefined } } export function secretPlaceholder(): string { return SECRET_PLACEHOLDER } /** 任何秘密展示一律落为掩码占位符;真正明文只经揭示会话在内存中出现。 */ export function maskSensitive(_value: unknown): string { return SECRET_PLACEHOLDER } /** 开始揭示指定行的秘密:记录明文与过期点(默认短时窗口);返回新状态,不改入参。 */ export function revealSecret( state: SecretRevealState, keyId: number, token: string, now: number, expiresAt?: number, ): SecretRevealState { return { keyId, token: typeof token === 'string' ? token : '', expiresAt: expiresAt === undefined ? now + DEFAULT_REVEAL_MS : expiresAt, } } /** 到达过期点即清空揭示明文,返回新状态;未过期原样返回。 */ export function expireReveal(state: SecretRevealState, now: number): SecretRevealState { if (state.expiresAt !== undefined && state.expiresAt !== null && now >= state.expiresAt) { return createSecretRevealState() } return state }