/** * POST /api/workspaces/[slug]/keys/[keyId]/reveal * * Returns the plaintext `vibn_sk_...` token for an active workspace key. * * Intentionally restricted to SESSION principals. An API-key principal * cannot reveal keys — this prevents a leaked agent token from being * used to exfiltrate sibling keys. We use POST (not GET) to keep the * secret out of server logs / the browser history / referrer headers. * * Returns 409 with { revealable: false } for legacy keys minted before * the key_encrypted column existed — those plaintexts were never stored * and can never be recovered. The caller should prompt the user to * rotate (revoke + mint new). */ import { NextResponse } from 'next/server'; import { requireWorkspacePrincipal, revealWorkspaceApiKey, } from '@/lib/auth/workspace-auth'; export async function POST( request: Request, { params }: { params: Promise<{ slug: string; keyId: string }> }, ) { const { slug, keyId } = await params; const principal = await requireWorkspacePrincipal(request, { targetSlug: slug }); if (principal instanceof NextResponse) return principal; if (principal.source !== 'session') { return NextResponse.json( { error: 'API keys can only be revealed from a signed-in session' }, { status: 403 }, ); } const revealed = await revealWorkspaceApiKey(principal.workspace.id, keyId); if (!revealed) { return NextResponse.json( { error: 'Key not found, already revoked, or was minted before reveal was enabled. ' + 'Rotate the key (revoke + create new) if you need the plaintext.', revealable: false, }, { status: 409 }, ); } return NextResponse.json({ id: revealed.id, name: revealed.name, prefix: revealed.prefix, token: revealed.token, }); }