35 lines
1.3 KiB
TypeScript
35 lines
1.3 KiB
TypeScript
import { timingSafeEqual } from 'node:crypto';
|
|
import type { NextRequest } from 'next/server';
|
|
|
|
export const LEARNING_ENGINE_TOKEN_ENV = 'LEARNING_ENGINE_TOKEN';
|
|
export const LEGACY_LEARNING_ENGINE_TOKEN_ENV = 'MAKELORE_RUNTIME_TOKEN';
|
|
|
|
/**
|
|
* Server-to-server credential for the private Learning Engine API.
|
|
*
|
|
* LEARNING_ENGINE_TOKEN is the canonical deployment name shared with Works
|
|
* Square. MAKELORE_RUNTIME_TOKEN remains a migration alias so existing private
|
|
* deployments can rotate without downtime.
|
|
*/
|
|
export function configuredLearningRuntimeToken(): string | undefined {
|
|
return (
|
|
process.env[LEARNING_ENGINE_TOKEN_ENV]?.trim() ||
|
|
process.env[LEGACY_LEARNING_ENGINE_TOKEN_ENV]?.trim() ||
|
|
undefined
|
|
);
|
|
}
|
|
|
|
export function authorizeLearningRuntime(request: NextRequest): boolean {
|
|
const expected = configuredLearningRuntimeToken();
|
|
const header = request.headers.get('authorization') || '';
|
|
const received = header.startsWith('Bearer ') ? header.slice(7).trim() : '';
|
|
if (!expected || !received) return false;
|
|
const expectedBytes = Buffer.from(expected);
|
|
const receivedBytes = Buffer.from(received);
|
|
return expectedBytes.length === receivedBytes.length && timingSafeEqual(expectedBytes, receivedBytes);
|
|
}
|
|
|
|
export function runtimeUnauthorized(): Response {
|
|
return Response.json({ error: 'unauthorized' }, { status: 401 });
|
|
}
|