feat: AnswerAI internal provisioning endpoint for Alpha Agent cross-provisioning#975
feat: AnswerAI internal provisioning endpoint for Alpha Agent cross-provisioning#975bradtaylorsf wants to merge 2 commits into
Conversation
…ioning Add POST /api/v1/internal/provision-apikey endpoint that allows Alpha Agent to provision AnswerAI API keys for users via Auth0 M2M tokens. The endpoint reuses existing user/org/workspace creation pipeline via verifyAAIToken middleware and returns a plaintext API key for storage in the user's container. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
PR Review: feat: AnswerAI internal provisioning endpoint for Alpha Agent cross-provisioningSummary: This PR adds a Critical Issues1. UUID stored in a Location: The @PrimaryColumn({ type: 'varchar', length: 20 })
id: stringThe new endpoint assigns a full UUID (36 characters) to that field: newKey.id = uuidv4() // e.g. "550e8400-e29b-41d4-a716-446655440000" — 36 charsAt the database level this will either silently truncate the id to 20 characters (SQLite) or raise a column-length error (PostgreSQL strict mode). Truncation would produce identical ids for different keys that share the same first 20 characters, causing unique-constraint failures on subsequent calls and silently corrupting data. The existing Recommendation: Use the same 2. Endpoint is fully unauthenticated at the network/whitelist level — Location: Adding That is acceptable as long as
Recommendation: Add an explicit check for the const authPayload = (req as any).auth?.payload
if (!authPayload?.scope?.includes('provision:apikey')) {
return res.status(403).json({ error: 'Forbidden: missing provision:apikey scope' })
}Major Concerns3. Location: /* eslint-disable no-console */The file contains eight Recommendation: Use the project logger (if one exists) or at minimum scope the disable comment to individual lines rather than suppressing the rule for the entire file. 4. Error handling does not use Location: } catch (error: any) {
console.error('[internal/provision-apikey] Error:', error.message)
return res.status(500).json({ error: 'Internal Server Error' })
}The project standard (documented in
The Recommendation: Use 5. Location: const organizationId = user.activeOrganizationId || user.organizationIdIf 6. Deletion of existing keys is not atomic with creation Location: The endpoint deletes existing Recommendation: Wrap the delete and insert in a TypeORM Minor Issues and Suggestions7. Request body fields ( Location: The PR description states the body contains 8. The As noted in issue 1, the 9. No tests included The test plan in the PR description is entirely manual. For a security-sensitive endpoint that provisions API keys using M2M tokens, automated tests would significantly reduce regression risk. Consider adding:
Positive Observations
Next Steps
🤖 Reviewed with Claude Code |
M2M tokens from client_credentials grant don't carry email/org_id claims, so verifyAAIToken would 401. Switch to direct jwtCheck for signature-only validation, then read user details from the request body instead of JWT claims. Run the user/org/workspace creation pipeline inline. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PR Review: feat: AnswerAI internal provisioning endpoint for Alpha Agent cross-provisioningSummary: This PR adds a new Critical Issues1. No OAuth Scope Validation on a Privileged Endpoint Location: The Why this matters: An M2M token issued to a completely unrelated service (e.g., a monitoring Lambda, a data pipeline) that happens to use the same Auth0 audience would have the full ability to provision API keys. Suggestion: Add scope enforcement using import { auth, requiredScopes } from 'express-oauth2-jwt-bearer'
// Chain the scope check after jwtCheck in the route definition:
router.post(
'/provision-apikey',
(req, res, next) => { jwtCheck(req, res, (err?: any) => { if (err) return res.status(401).json({ error: 'Unauthorized' }); next() }) },
requiredScopes('provision:apikey'),
async (req: Request, res: Response) => { ... }
)2. No Rate Limiting on a Privileged User-Creation Endpoint Location: This endpoint creates users, organizations, workspaces, and API keys in a single call. There is no rate limiting applied. If an attacker obtains a valid M2M token (or if the scope gap above is exploited), they could hammer this endpoint to create arbitrary users and organizations at high volume. The project already has a Why this matters: Without rate limiting, a single compromised token enables account flooding, database exhaustion, and potential DoS of the provisioning pipeline. Suggestion: Apply the project's existing rate limiting infrastructure to this endpoint before mounting it. Even a conservative limit (e.g., 10 requests/minute per IP or per token 3. Plaintext API Key in Response Body — Risk of Log Capture Location: The response returns Why this matters: Plaintext API keys in logs are a common source of credential exposure. Suggestion: Add an explicit comment next to the response block warning that the response body must never be logged, and confirm no existing middleware captures response bodies for this route. Major Concerns4. Deviation from Project Error-Handling Standards Location: The project standard (documented in Why this matters: Bypassing Suggestion: Import and throw 5. Business Logic Collapsed into Route Handler — Bypasses 4-Layer Architecture Location: The server's documented architecture separates concerns into Routes, Controllers, Services, and Entities. All business logic (finding/creating users, orgs, workspaces, and API keys) is collapsed into a single route handler. The existing Why this matters: Bypassing the service layer duplicates logic that already exists, creates a maintenance burden, and makes it harder to apply cross-cutting concerns (audit logging, quota enforcement) consistently. Suggestion: Extract provisioning logic into a dedicated service (e.g., 6. No Automated Tests for the New Endpoint Location: No test files included in this PR. The test plan is manual-only. No automated tests exist for: valid M2M token provisions key successfully, invalid/missing token returns 401, The project has test infrastructure at Suggestion: Add integration tests in Minor Issues and Suggestions7. Potential Location: newKey.id = uuidv4()The Suggestion: Confirm the actual column definition in the database migration and reconcile with the entity definition. 8. Excessive Raw Location: The file disables the Suggestion: Not a blocker. Consider using a structured logger in the 9. Missing Startup Guard for Location: const allowedOrgs = process.env.AUTH0_ORGANIZATION_ID?.split(',') || []If Suggestion: Add a startup-time warning or assertion when Positive Observations
Next Steps
Review conducted by Claude Code PR Review Agent |
Summary
POST /api/v1/internal/provision-apikeyendpoint that allows Alpha Agent to provision AnswerAI API keys for users via Auth0 M2M tokensverifyAAITokenmiddleware for JWT validation and the full user/org/workspace creation pipelineconstants.tsso it bypasses the main auth middleware (handles its own auth)How it works
POST /api/v1/internal/provision-apikeywith{ auth0Id, email, name, orgId }andx-request-from: aaiheaderverifyAAITokenvalidates the JWT, creates/finds user + org + workspaces (all idempotent){ apiKey, userId, workspaceId }— the plaintext key (only time it's visible)Files changed
packages/server/src/aai/routes/internal-provision.tspackages/server/src/routes/index.tspackages/server/src/index.ts/api/v1/internalpackages/server/src/utils/constants.tsRelated PRs
last-rev-llc/alphaagent#feature/cross-provision-answerai— M2M token helper + provisioning calllast-rev-llc/alphaclaw#feature/cross-provision-answerai— Skill + integration manifestManual setup required (Auth0)
provision:apikeyscope for the AnswerAI API audienceorg_idis in theAUTH0_ORGANIZATION_IDallowlistTest plan
pnpm --filter flowise build🤖 Generated with Claude Code