mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-29 22:23:01 +00:00
* feat: display app version in settings panel * fix(onboarding): auto-refresh accessibility state after grant (#351) * style(onboarding): apply formatter for issue #351 fix * fix(onboarding): ESLint + typed mock for ScreenPermissionsStep; clear flag in handler Consolidate tauriCommands imports and drop redundant mock cast. Handle granted accessibility in focus/visibility callback instead of a follow-up effect. Made-with: Cursor * fix(release): gate OAuth deep links on minimum app version (#365) - Add semver helpers and VITE_MINIMUM_SUPPORTED_APP_VERSION / download URL in app config - Block openhuman://oauth/success when desktop build is below minimum; enqueue error, open latest-release URL, dispatch oauth:stale-app - Pass new Vite env vars through release.yml and build-windows.yml Build frontend - Document policy in docs/RELEASE_POLICY.md; note vars in app/.env.example Closes #365 Made-with: Cursor * fix: import React in SkillSetupWizard component * fix: address CodeRabbit review (OAuth gate, semver, logging) - Anchor semver regex to full string; arrow-style exports; tests for bad inputs - Never throw from evaluateOAuthAppVersionGate; try/catch in deep link + omit raw URL from error logs - Document build-time vs runtime policy in config JSDoc and RELEASE_POLICY - Remove unused React import in SkillSetupWizard (tsc) Made-with: Cursor * fix: CodeRabbit — fail-closed OAuth gate, tauri-action Vite env, runbook - Block OAuth when minimum is set but getVersion fails or version is unparseable - Pass VITE_MINIMUM_* through tauri-action env (release + Windows) so bundles match yarn build - Expand RELEASE_POLICY: artifact retirement, dual workflow env note - Friendlier copy when current version is unknown Made-with: Cursor
65 lines
2.2 KiB
TypeScript
65 lines
2.2 KiB
TypeScript
import { getVersion } from '@tauri-apps/api/app';
|
|
import { isTauri } from '@tauri-apps/api/core';
|
|
|
|
import { LATEST_APP_DOWNLOAD_URL, MINIMUM_SUPPORTED_APP_VERSION } from './config';
|
|
import { isVersionAtLeast, parseSemverParts } from './semver';
|
|
|
|
export type OAuthAppVersionGateResult =
|
|
| { ok: true }
|
|
| { ok: false; current: string; minimum: string; downloadUrl: string };
|
|
|
|
function block(minimum: string, current: string): OAuthAppVersionGateResult {
|
|
return { ok: false, current, minimum, downloadUrl: LATEST_APP_DOWNLOAD_URL };
|
|
}
|
|
|
|
/**
|
|
* When `VITE_MINIMUM_SUPPORTED_APP_VERSION` is set (CI/production), block OAuth
|
|
* `openhuman://oauth/success` handling if the running desktop build is older.
|
|
* Prevents completing Gmail (and other) OAuth on deprecated app binaries.
|
|
*
|
|
* When a minimum is configured, fails **closed** if the app version cannot be
|
|
* determined or parsed (never silently allows OAuth on unknown versions).
|
|
*/
|
|
export async function evaluateOAuthAppVersionGate(): Promise<OAuthAppVersionGateResult> {
|
|
const minimum = MINIMUM_SUPPORTED_APP_VERSION.trim();
|
|
try {
|
|
if (!minimum) {
|
|
return { ok: true };
|
|
}
|
|
if (!parseSemverParts(minimum)) {
|
|
console.warn('[oauth-app-version] invalid MINIMUM_SUPPORTED_APP_VERSION; gate disabled');
|
|
return { ok: true };
|
|
}
|
|
if (!isTauri()) {
|
|
return { ok: true };
|
|
}
|
|
|
|
let current: string;
|
|
try {
|
|
current = await getVersion();
|
|
} catch (e) {
|
|
console.warn('[oauth-app-version] getVersion failed; blocking OAuth', e);
|
|
return block(minimum, 'unknown');
|
|
}
|
|
|
|
if (!parseSemverParts(current)) {
|
|
console.warn('[oauth-app-version] unparseable app version; blocking OAuth', current);
|
|
return block(minimum, current);
|
|
}
|
|
|
|
if (isVersionAtLeast(current, minimum)) {
|
|
return { ok: true };
|
|
}
|
|
|
|
console.warn('[oauth-app-version] blocked OAuth success deep link', { current, minimum });
|
|
return block(minimum, current);
|
|
} catch (e) {
|
|
// Never throw: outer deep-link handler must not receive errors that could log the raw URL.
|
|
console.warn('[oauth-app-version] unexpected error', e);
|
|
if (!minimum) {
|
|
return { ok: true };
|
|
}
|
|
return block(minimum, 'unknown');
|
|
}
|
|
}
|