Files
openhuman/app/src/utils/oauthAppVersionGate.ts
T
Mega MindandGitHub 5551e1e0aa Fix/365 enforce latest oauth gate from 351 (#421)
* 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
2026-04-08 04:26:19 +05:30

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');
}
}