import type { VercelRequest, VercelResponse } from "@vercel/node"; import crypto from "crypto"; const SESSION_TTL_SECONDS = 10 * 60; // 10 minutes const FORGE_SESSION_SECRET = process.env.FORGE_SESSION_SECRET!; function signSession(payload: any): string { const body = Buffer.from(JSON.stringify(payload)).toString("base64url"); const sig = crypto .createHmac("sha256", FORGE_SESSION_SECRET) .update(body) .digest("base64url"); return `${body}.${sig}`; } export default async function handler(req: VercelRequest, res: VercelResponse) { if (req.method !== "POST") return res.status(405).end(); try { const authResult = req.body; // For now we trust authResult structure (replace with actual Pi verification): const pi_uid = authResult.user?.uid; const username = authResult.user?.username; if (!pi_uid || !username) { return res.status(400).json({ error: "Missing user info from Pi." }); } // Mint short-lived Forge Session Token const now = Math.floor(Date.now() / 1000); const payload = { pi_uid, username, iat: now, exp: now + SESSION_TTL_SECONDS, scope: "agent-session" }; const session_token = signSession(payload); return res.status(200).json({ status: "ok", session_token }); } catch (e: any) { console.error(e); return res.status(500).json({ error: "pi_auth_failed", message: e.message }); } }