mirror of
https://github.com/koala73/worldmonitor.git
synced 2026-04-25 17:14:57 +02:00
* feat: API key gating for desktop cloud fallback + registration system Gate desktop cloud fallback behind WORLDMONITOR_API_KEY — desktop users need a valid key for cloud access, otherwise operate local-only (sidecar). Add email registration system via Convex DB for future key distribution. Client-side: installRuntimeFetchPatch() checks key presence before allowing cloud fallback, with secretsReady promise + 2s timeout. Server-side: origin-aware validation in sebuf gateway — desktop origins require key, web origins pass through. - Add WORLDMONITOR_API_KEY to 3-place secret system (Rust, TS, sidecar) - New "World Monitor" settings tab with key input + registration form - New api/_api-key.js server-side validation (origin-aware) - New api/register-interest.js edge function with rate limiting - Convex DB schema + mutation for email registration storage - CORS headers updated for X-WorldMonitor-Key + Authorization - E2E tests for key gate (blocked without key, allowed with key) - Deployment docs (API_KEY_DEPLOYMENT.md) + updated desktop config docs * fix: harden worldmonitor key + registration input handling * fix: show invalid WorldMonitor API key status * fix: simplify key validation, trim registration checks, add env example vars - Inline getValidKeys() in _api-key.js - Remove redundant type checks in register-interest.js - Simplify WorldMonitorTab status to present/missing - Add WORLDMONITOR_VALID_KEYS and CONVEX_URL to .env.example * feat(sidecar): integrate proto gateway bundle into desktop build The sidecar's buildRouteTable() only discovers .js files, so the proto gateway at api/[domain]/v1/[rpc].ts was invisible — all 45 sebuf RPCs returned 404 in the desktop app. Wire the existing build script into Tauri's build commands and add esbuild as an explicit devDependency.
31 lines
1.1 KiB
JavaScript
31 lines
1.1 KiB
JavaScript
const DESKTOP_ORIGIN_PATTERNS = [
|
|
/^https?:\/\/tauri\.localhost(:\d+)?$/,
|
|
/^https?:\/\/[a-z0-9-]+\.tauri\.localhost(:\d+)?$/i,
|
|
/^tauri:\/\/localhost$/,
|
|
/^asset:\/\/localhost$/,
|
|
];
|
|
|
|
function isDesktopOrigin(origin) {
|
|
return Boolean(origin) && DESKTOP_ORIGIN_PATTERNS.some(p => p.test(origin));
|
|
}
|
|
|
|
export function validateApiKey(req) {
|
|
const key = req.headers.get('X-WorldMonitor-Key');
|
|
const origin = req.headers.get('Origin') || '';
|
|
|
|
if (isDesktopOrigin(origin)) {
|
|
if (!key) return { valid: false, required: true, error: 'API key required for desktop access' };
|
|
const validKeys = (process.env.WORLDMONITOR_VALID_KEYS || '').split(',').filter(Boolean);
|
|
if (!validKeys.includes(key)) return { valid: false, required: true, error: 'Invalid API key' };
|
|
return { valid: true, required: true };
|
|
}
|
|
|
|
if (key) {
|
|
const validKeys = (process.env.WORLDMONITOR_VALID_KEYS || '').split(',').filter(Boolean);
|
|
if (!validKeys.includes(key)) return { valid: false, required: true, error: 'Invalid API key' };
|
|
return { valid: true, required: true };
|
|
}
|
|
|
|
return { valid: false, required: false };
|
|
}
|