fix(startup): enforce consent before download handoffs

Gate clipboard, extension, and deep-link inputs until startup consent is resolved, and serialize extension readiness transitions so native prompts cannot race the app explanation. Identify consent by the build revision so same-version updates re-enter the consent boundary.

Requested by [this X post](https://x.com/ixabolfazl/status/2077356127763804450?s=20).
This commit is contained in:
NimBold
2026-07-15 21:48:00 +03:30
parent 9f333618fc
commit edeef0ac54
4 changed files with 90 additions and 12 deletions
+3 -1
View File
@@ -3,7 +3,9 @@ import { getKeychainConsentVersion, getKeychainStartupDecision } from './keychai
describe('getKeychainStartupDecision', () => {
it('changes the consent identity when the credential-access policy changes', () => {
expect(getKeychainConsentVersion('1.1.0')).toBe('1.1.0|keychain-policy-2');
expect(getKeychainConsentVersion('1.1.0')).toMatch(
/^1\.1\.0\|(build-.+|keychain-policy-2)$/
);
expect(getKeychainConsentVersion('')).toBe('');
});
+10 -4
View File
@@ -12,15 +12,21 @@ export type KeychainStartupDecision = {
};
// The semantic app version can remain unchanged across release-candidate and
// packaging rebuilds. Bump this contract version whenever a build can require
// a fresh credential-store authorization, so an updated binary cannot skip
// Firelink's explanation and invoke the OS prompt directly.
// packaging rebuilds. Use the build identity so an updated binary cannot skip
// Firelink's explanation and invoke the OS prompt directly. The policy epoch
// remains only as a safe fallback for builds created outside the Git checkout.
const KEYCHAIN_CONSENT_POLICY_VERSION = '2';
const buildId = typeof import.meta.env.VITE_BUILD_ID === 'string'
? import.meta.env.VITE_BUILD_ID.trim()
: '';
export const getKeychainConsentVersion = (appVersion: string): string => {
const normalizedVersion = appVersion.trim();
const consentIdentity = buildId && buildId !== 'unknown'
? `build-${buildId}`
: `keychain-policy-${KEYCHAIN_CONSENT_POLICY_VERSION}`;
return normalizedVersion
? `${normalizedVersion}|keychain-policy-${KEYCHAIN_CONSENT_POLICY_VERSION}`
? `${normalizedVersion}|${consentIdentity}`
: '';
};