From cd4cb75b6003a26b5ed21d2238f3fee12011cdc2 Mon Sep 17 00:00:00 2001 From: Chandler Copeland Date: Sat, 21 Mar 2026 10:33:53 -0600 Subject: [PATCH] feat(07-01): add createAgentDownloadToken and verifyAgentDownloadToken - Appends two new exports to token.ts (existing exports untouched) - purpose: 'agent-download', 5-min TTL, no DB record - Mirrors existing createDownloadToken/verifyDownloadToken pattern --- teressa-copeland-homes/src/lib/signing/token.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/teressa-copeland-homes/src/lib/signing/token.ts b/teressa-copeland-homes/src/lib/signing/token.ts index 35cb104..fa719cf 100644 --- a/teressa-copeland-homes/src/lib/signing/token.ts +++ b/teressa-copeland-homes/src/lib/signing/token.ts @@ -46,3 +46,19 @@ export async function verifyDownloadToken(token: string): Promise<{ documentId: if (payload['purpose'] !== 'download') throw new Error('Not a download token'); return { documentId: payload['documentId'] as string }; } + +// Agent download token — purpose: 'agent-download', 5-min TTL, no DB record +// Generated server-side only (server component or API route). Never in a client component. +export async function createAgentDownloadToken(documentId: string): Promise { + return await new SignJWT({ documentId, purpose: 'agent-download' }) + .setProtectedHeader({ alg: 'HS256' }) + .setIssuedAt() + .setExpirationTime('5m') + .sign(getSecret()); +} + +export async function verifyAgentDownloadToken(token: string): Promise<{ documentId: string }> { + const { payload } = await jwtVerify(token, getSecret()); + if (payload['purpose'] !== 'agent-download') throw new Error('Not an agent download token'); + return { documentId: payload['documentId'] as string }; +}