()
| 85 | const DEMO_TEST_KIT_KEY_PATTERN = /^demo-[a-z0-9]+(?:-[a-z0-9]+)*-v\d+$/; |
| 86 | |
| 87 | function buildBearerAuthenticator(): Authenticator | null { |
| 88 | if (!TRAINING_AGENT_TOKEN && !PUBLIC_TEST_AGENT_TOKEN && !workos) { |
| 89 | return null; // dev mode: open |
| 90 | } |
| 91 | const staticKeys: Record<string, AuthPrincipal> = {}; |
| 92 | if (TRAINING_AGENT_TOKEN) staticKeys[TRAINING_AGENT_TOKEN] = { principal: 'static:primary' }; |
| 93 | if (PUBLIC_TEST_AGENT_TOKEN) staticKeys[PUBLIC_TEST_AGENT_TOKEN] = { principal: 'static:public' }; |
| 94 | |
| 95 | const authenticators: Authenticator[] = []; |
| 96 | if (Object.keys(staticKeys).length > 0) { |
| 97 | authenticators.push(verifyApiKey({ keys: staticKeys })); |
| 98 | } |
| 99 | authenticators.push(verifyApiKey({ |
| 100 | verify: (token) => { |
| 101 | if (!DEMO_TEST_KIT_KEY_PATTERN.test(token)) return null; |
| 102 | return { principal: `static:demo:${token}` }; |
| 103 | }, |
| 104 | })); |
| 105 | if (workos) { |
| 106 | const workosClient = workos; // narrow for closure |
| 107 | authenticators.push(verifyApiKey({ |
| 108 | verify: async (token) => { |
| 109 | if (!isWorkOSApiKeyFormat(token)) return null; |
| 110 | const result = await workosClient.apiKeys.createValidation({ value: token }); |
| 111 | if (!result.apiKey) return null; |
| 112 | const orgId = result.apiKey.owner.id; |
| 113 | logger.info({ orgId }, 'Training agent: authenticated via AAO API key'); |
| 114 | return { principal: `workos:${orgId}` }; |
| 115 | }, |
| 116 | })); |
| 117 | } |
| 118 | if (authenticators.length === 0) return null; |
| 119 | return authenticators.length === 1 ? authenticators[0] : anyOf(...authenticators); |
| 120 | } |
| 121 | |
| 122 | // Per-route lazy signing authenticators. Each route MUST own its own |
| 123 | // `InMemoryReplayStore` — sharing one store lets a nonce consumed on |
no test coverage detected