import { packageStorage } from 'kody:runtime' export const LAUNCHER_TOKEN_HASH_KEY = 'launcherTokenSha256' export const LAUNCHER_TOKEN_HINT_KEY = 'launcherTokenHint' export async function sha256Hex(value: string): Promise { const bytes = new TextEncoder().encode(value) const digest = await crypto.subtle.digest('SHA-256', bytes) return [...new Uint8Array(digest)] .map((b) => b.toString(16).padStart(2, '0')) .join('') } export async function storeLauncherToken(token: string) { const trimmed = token.trim() if (trimmed.length < 24) { throw new Error('Launcher token must be at least 24 characters.') } const hash = await sha256Hex(trimmed) const storage = packageStorage() await storage.set(LAUNCHER_TOKEN_HASH_KEY, hash) await storage.set(LAUNCHER_TOKEN_HINT_KEY, trimmed.slice(-4)) return { hash, hint: trimmed.slice(-4) } } export async function verifyLauncherToken(token: string | null): Promise { if (!token) return false const expected = await packageStorage().get(LAUNCHER_TOKEN_HASH_KEY) if (typeof expected !== 'string' || !expected) return false const actual = await sha256Hex(token.trim()) return actual === expected } export function bearerFromRequest(request: Request): string | null { const header = request.headers.get('authorization') || '' const match = header.match(/^Bearer\s+(.+)$/i) return match?.[1]?.trim() || null }