mirror of
https://github.com/nimbold/Firelink.git
synced 2026-07-27 04:19:19 +00:00
edeef0ac54
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).
55 lines
1.7 KiB
TypeScript
55 lines
1.7 KiB
TypeScript
export type KeychainStartupState = {
|
|
portable: boolean;
|
|
appVersion: string;
|
|
approvedVersion: string;
|
|
accessGranted: boolean;
|
|
promptDismissed: boolean;
|
|
};
|
|
|
|
export type KeychainStartupDecision = {
|
|
deferKeychainHydration: boolean;
|
|
showKeychainPrompt: boolean;
|
|
};
|
|
|
|
// The semantic app version can remain unchanged across release-candidate and
|
|
// 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}|${consentIdentity}`
|
|
: '';
|
|
};
|
|
|
|
export const getKeychainStartupDecision = ({
|
|
portable,
|
|
appVersion,
|
|
approvedVersion,
|
|
accessGranted,
|
|
promptDismissed
|
|
}: KeychainStartupState): KeychainStartupDecision => {
|
|
if (portable) {
|
|
return {
|
|
deferKeychainHydration: false,
|
|
showKeychainPrompt: false
|
|
};
|
|
}
|
|
|
|
const versionKnown = Boolean(appVersion.trim());
|
|
const versionChanged = versionKnown && approvedVersion !== appVersion;
|
|
const mustDeferAccess = !accessGranted || !versionKnown || versionChanged;
|
|
return {
|
|
deferKeychainHydration: mustDeferAccess,
|
|
showKeychainPrompt: versionChanged || (!accessGranted && !promptDismissed)
|
|
};
|
|
};
|