feat: POST /api/artists/{id}/segments (manual segment creation)#444
feat: POST /api/artists/{id}/segments (manual segment creation)#444arpitgupta1214 wants to merge 4 commits into
Conversation
…ation
Adds a dedicated REST endpoint for manual segment generation that reuses
the existing MCP-backed `createSegments` handler with no duplication of
generation or insert logic.
- Route: `app/api/artists/[id]/segments/route.ts` (POST, OPTIONS)
- Thin delegation to `lib/artists/segments/postArtistSegmentsHandler.ts`
- Body validator in `lib/artists/segments/validatePostSegmentsBody.ts`
accepting `{ prompt: string }` (non-empty)
- Auth via `validateAuthContext()`; per-artist access enforced via
`checkAccountArtistAccess`, matching existing `DELETE /api/artists/{id}`
- Error envelope mapping: 400 (validation), 401 (auth), 403 (access),
404 (artist not found), 409 (no socials/no fans — preserves `feedback`
from `createSegments`), 500 (other)
- Success envelope: `{ status, segments_created, message }`
- 11 handler tests cover success, 400, 401, 403, 404, 409 (both no-socials
and no-fans paths with feedback), 500 (error envelope and thrown)
Part of the Segments Surface Migration plan (Create → api PR).
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 47 minutes and 49 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (3)
📝 WalkthroughWalkthroughNew API endpoint for creating artist segments with comprehensive multi-layer validation, authentication checks, and access control. Includes route handlers with CORS support, request validation pipeline, and business logic orchestration with normalized error handling. Changes
Sequence DiagramsequenceDiagram
participant Client
participant RouteHandler as Route Handler<br/>/segments
participant Validator as Validation<br/>Pipeline
participant AuthCheck as Auth & Access
participant Database as Database
participant Service as Segment<br/>Service
Client->>RouteHandler: POST /api/artists/{id}/segments
RouteHandler->>Validator: validatePostArtistSegmentsRequest(request, id)
Validator->>Validator: validateAccountParams(id)
Validator->>Validator: parseJSON & validatePostSegmentsBody()
Validator->>AuthCheck: validateAuthContext()
AuthCheck-->>Validator: accountId
Validator->>Database: selectAccounts(artistId)
Database-->>Validator: artist record
alt Artist not found
Validator-->>RouteHandler: NextResponse 404
else Artist exists
Validator->>AuthCheck: checkAccountArtistAccess()
alt Access denied
AuthCheck-->>RouteHandler: NextResponse 403
else Access granted
Validator-->>RouteHandler: PostArtistSegmentsRequest
RouteHandler->>Service: createSegments(artist_account_id, prompt)
Service->>Database: Insert segments
alt Success
Service-->>RouteHandler: {success: true, count}
RouteHandler-->>Client: 200 JSON {status, segments_created}
else Failure
Service-->>RouteHandler: {success: false, error, feedback?}
RouteHandler->>RouteHandler: Normalize status (409 or 500)
RouteHandler-->>Client: Error JSON + status
end
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 1✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
3 issues found across 4 files
Confidence score: 4/5
- This PR is likely safe to merge, with mostly moderate concerns and no clear functionality-breaking defect called out.
- The most impactful issue is in
lib/artists/segments/postArtistSegmentsHandler.ts:validateAuthContextruns after body parsing/validation, which can return validation feedback before rejecting unauthenticated requests. lib/artists/segments/postArtistSegmentsHandler.tsalso has maintainability and API-semantics gaps (oversized handler and200 OKinstead of201 Createdfor creation), which raise cleanup priority more than immediate merge risk.- Pay close attention to
lib/artists/segments/postArtistSegmentsHandler.ts- auth-check ordering and response semantics should be tightened to avoid unintended behavior.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="lib/artists/segments/postArtistSegmentsHandler.ts">
<violation number="1" location="lib/artists/segments/postArtistSegmentsHandler.ts:26">
P2: Custom agent: **Enforce Clear Code Style and Maintainability Practices**
At 128 lines this handler is well over the 100-line limit and more than double every other handler in `lib/artists/` (~50 lines each). Extract the `createSegments` result-to-response mapping (lines 84–114, including the `NO_RESOURCE_ERROR_MESSAGES` set) into a small helper (e.g., `mapCreateSegmentsResult`) to bring the file under the limit and keep a single level of responsibility.</violation>
<violation number="2" location="lib/artists/segments/postArtistSegmentsHandler.ts:38">
P2: Auth check (`validateAuthContext`) runs after body validation. Move it before `safeParseJson` / `validatePostSegmentsBody` so unauthenticated requests are rejected immediately without exposing validation errors.</violation>
<violation number="3" location="lib/artists/segments/postArtistSegmentsHandler.ts:93">
P2: This POST endpoint creates new segments but returns `200 OK`. Use `201 Created` to follow HTTP semantics for resource creation.</violation>
</file>
Architecture diagram
sequenceDiagram
participant Client
participant Route as API Route
participant Handler as postArtistSegmentsHandler
participant Auth as Auth & Access Logic
participant DB as Supabase / DB
participant Logic as createSegments (Shared)
Note over Client,Logic: NEW: Manual Segment Creation Flow
Client->>Route: POST /api/artists/{id}/segments
Route->>Handler: NEW: Handle manual creation
Handler->>Handler: NEW: validatePostSegmentsBody()
alt Invalid prompt or ID shape
Handler-->>Client: 400 Bad Request
end
Handler->>Auth: validateAuthContext(request)
alt Missing/Invalid API Key or Bearer
Auth-->>Client: 401 Unauthorized
end
Auth-->>Handler: requesterAccountId
Handler->>DB: selectAccounts(artistId)
alt Artist not found
DB-->>Handler: empty
Handler-->>Client: 404 Not Found
end
Handler->>Auth: checkAccountArtistAccess(requester, artist)
alt Caller cannot manage this artist
Auth-->>Client: 403 Forbidden
end
Handler->>Logic: NEW: createSegments({ artist_account_id, prompt })
Note over Logic: Reuses logic from MCP tool flow
alt Segments Generated
Logic-->>Handler: { success: true, count }
Handler-->>Client: 200 Success { segments_created }
else Missing Socials or Fans
Logic-->>Handler: { success: false, feedback, message }
Handler-->>Client: 409 Conflict (with remediation feedback)
else Generation Failure
Logic-->>Handler: { success: false, error }
Handler-->>Client: 500 Internal Server Error
end
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.
| @@ -0,0 +1,128 @@ | |||
| import { NextRequest, NextResponse } from "next/server"; | |||
There was a problem hiding this comment.
P2: Custom agent: Enforce Clear Code Style and Maintainability Practices
At 128 lines this handler is well over the 100-line limit and more than double every other handler in lib/artists/ (~50 lines each). Extract the createSegments result-to-response mapping (lines 84–114, including the NO_RESOURCE_ERROR_MESSAGES set) into a small helper (e.g., mapCreateSegmentsResult) to bring the file under the limit and keep a single level of responsibility.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At lib/artists/segments/postArtistSegmentsHandler.ts, line 26:
<comment>At 128 lines this handler is well over the 100-line limit and more than double every other handler in `lib/artists/` (~50 lines each). Extract the `createSegments` result-to-response mapping (lines 84–114, including the `NO_RESOURCE_ERROR_MESSAGES` set) into a small helper (e.g., `mapCreateSegmentsResult`) to bring the file under the limit and keep a single level of responsibility.</comment>
<file context>
@@ -0,0 +1,128 @@
+ * @param params - The route params containing the artist account ID.
+ * @returns A NextResponse with the segment generation result envelope.
+ */
+export async function postArtistSegmentsHandler(
+ request: NextRequest,
+ params: Promise<{ id: string }>,
</file context>
…stSegmentsRequest Matches the project validate<Verb><Resource>Request pattern (see validateDeleteArtistRequest). Handler now calls one validator that covers path id, body, auth, artist existence, and per-artist access.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
🧹 Nitpick comments (3)
lib/artists/segments/validatePostArtistSegmentsRequest.ts (2)
28-84: Validation orchestrator is well-structured but lengthy; consider extraction.The function spans ~57 lines, exceeding the 20-line guideline. However, the sequential validation pipeline with early returns is clear and maintainable. For improved testability and adherence to length guidelines, consider extracting the artist existence check (lines 51-63) and access check (lines 65-77) into dedicated helper functions.
♻️ Optional: Extract existence and access checks
+async function ensureArtistExists(artistId: string): Promise<NextResponse | null> { + const existingArtist = await selectAccounts(artistId); + if (!existingArtist.length) { + return NextResponse.json( + { status: "error", error: "Artist not found" }, + { status: 404, headers: getCorsHeaders() }, + ); + } + return null; +} + +async function ensureArtistAccess( + requesterAccountId: string, + artistId: string, +): Promise<NextResponse | null> { + const hasAccess = await checkAccountArtistAccess(requesterAccountId, artistId); + if (!hasAccess) { + return NextResponse.json( + { status: "error", error: "Unauthorized segment creation attempt" }, + { status: 403, headers: getCorsHeaders() }, + ); + } + return null; +}As per coding guidelines: "Flag functions longer than 20 lines."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/artists/segments/validatePostArtistSegmentsRequest.ts` around lines 28 - 84, The validatePostArtistSegmentsRequest function is >20 lines; extract the artist existence check and the access check into two helpers (e.g., ensureArtistExists(artistId) and ensureRequesterHasAccess(requesterAccountId, artistId)) that encapsulate the selectAccounts(...) and checkAccountArtistAccess(...) logic and return either void (on success) or the NextResponse error used now; replace the inline blocks in validatePostArtistSegmentsRequest with calls to these helpers and return any NextResponse they produce so behavior and early-return semantics remain identical.
37-46: Consider validating authentication before parsing body.Currently, body parsing (line 37-41) occurs before authentication (line 43-46). While this provides better error messages for malformed requests, it means unauthenticated requests with invalid bodies receive a 400 instead of 401. If rate-limiting or audit logging depends on authentication, you may want to swap the order.
This is a minor design consideration—the current approach is valid if you prefer granular error reporting over strict auth-first semantics.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/artists/segments/validatePostArtistSegmentsRequest.ts` around lines 37 - 46, Swap authentication validation to run before body parsing so unauthenticated requests return 401 instead of 400: call validateAuthContext(request) and handle a NextResponse result before invoking safeParseJson(request) and validatePostSegmentsBody(rawBody). Update the order in validatePostArtistSegmentsRequest to invoke validateAuthContext first (and return if it is a NextResponse), then proceed to safeParseJson and validatePostSegmentsBody, preserving existing NextResponse checks for each function.lib/artists/segments/postArtistSegmentsHandler.ts (1)
21-81: Consider extracting response builders to reduce handler length.The handler function spans ~60 lines, exceeding the 20-line guideline. While the orchestration logic is sound, you could extract the success/error response construction into small helper functions to improve readability and testability.
♻️ Optional refactor to extract response builders
+function buildSuccessResponse(count: number): NextResponse { + return NextResponse.json( + { + status: "success", + segments_created: count, + message: "Segments generated successfully.", + }, + { status: 200, headers: getCorsHeaders() }, + ); +} + +function buildErrorResponse(message: string, feedback?: string): NextResponse { + const isNoResourceError = NO_RESOURCE_ERROR_MESSAGES.has(message); + return NextResponse.json( + { + status: "error", + error: message, + ...(feedback ? { feedback } : {}), + }, + { status: isNoResourceError ? 409 : 500, headers: getCorsHeaders() }, + ); +}As per coding guidelines: "Flag functions longer than 20 lines."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/artists/segments/postArtistSegmentsHandler.ts` around lines 21 - 81, The handler postArtistSegmentsHandler is over the 20-line guideline due to inline response construction; extract small helper builders (e.g., buildSuccessResponse(resultCount, corsHeaders), buildFailureResponse(message, feedback, statusCode, corsHeaders), buildExceptionResponse(error, corsHeaders)) and replace the three NextResponse.json blocks (success branch after createSegments, error branch using NO_RESOURCE_ERROR_MESSAGES, and the catch block) with calls to these helpers; keep validatePostArtistSegmentsRequest, createSegments and getCorsHeaders usage the same and ensure helpers return NextResponse objects and live in the same module or a nearby utils file for easy testing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@lib/artists/segments/postArtistSegmentsHandler.ts`:
- Around line 21-81: The handler postArtistSegmentsHandler is over the 20-line
guideline due to inline response construction; extract small helper builders
(e.g., buildSuccessResponse(resultCount, corsHeaders),
buildFailureResponse(message, feedback, statusCode, corsHeaders),
buildExceptionResponse(error, corsHeaders)) and replace the three
NextResponse.json blocks (success branch after createSegments, error branch
using NO_RESOURCE_ERROR_MESSAGES, and the catch block) with calls to these
helpers; keep validatePostArtistSegmentsRequest, createSegments and
getCorsHeaders usage the same and ensure helpers return NextResponse objects and
live in the same module or a nearby utils file for easy testing.
In `@lib/artists/segments/validatePostArtistSegmentsRequest.ts`:
- Around line 28-84: The validatePostArtistSegmentsRequest function is >20
lines; extract the artist existence check and the access check into two helpers
(e.g., ensureArtistExists(artistId) and
ensureRequesterHasAccess(requesterAccountId, artistId)) that encapsulate the
selectAccounts(...) and checkAccountArtistAccess(...) logic and return either
void (on success) or the NextResponse error used now; replace the inline blocks
in validatePostArtistSegmentsRequest with calls to these helpers and return any
NextResponse they produce so behavior and early-return semantics remain
identical.
- Around line 37-46: Swap authentication validation to run before body parsing
so unauthenticated requests return 401 instead of 400: call
validateAuthContext(request) and handle a NextResponse result before invoking
safeParseJson(request) and validatePostSegmentsBody(rawBody). Update the order
in validatePostArtistSegmentsRequest to invoke validateAuthContext first (and
return if it is a NextResponse), then proceed to safeParseJson and
validatePostSegmentsBody, preserving existing NextResponse checks for each
function.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 1518ee7b-92ad-424e-925a-ff7d275c3512
⛔ Files ignored due to path filters (1)
lib/artists/segments/__tests__/postArtistSegmentsHandler.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**
📒 Files selected for processing (4)
app/api/artists/[id]/segments/route.tslib/artists/segments/postArtistSegmentsHandler.tslib/artists/segments/validatePostArtistSegmentsRequest.tslib/artists/segments/validatePostSegmentsBody.ts
Preview smoke testRun against Error envelope paths
Handler delegation (409 path)POST against a real artist with no {
"status": "error",
"error": "No fans found for this artist",
"feedback": "No social_fans records found for <artist>. Before creating segments, you need social_fans data. Follow these steps:\n1. Call 'scrape_instagram_profile' ...\n2. Call 'scrape_instagram_comments' ...\n3. Wait for the scraping jobs to complete ...\n4. Call 'create_segments' again once social_fans records are populated\nNote: Scraping jobs may take several minutes to complete."
}This confirms the thin route → 201 success path not exercised (would require an artist with populated |
Summary
Adds the dedicated REST endpoint
POST /api/artists/{id}/segmentsfor manual segment creation.lib/segments/createSegmentshandler with no duplication of generation or insert logic — same handler that powers thecreate_segmentsMCP tool{ prompt }; artist target is path-encoded (id) and mapped toartist_account_idat the handler layer, so the shared handler signature is unchangedpostArtistSegmentsHandler→createSegments; Zod validator inlib/artists/segments/validatePostSegmentsBody.tsvalidateAuthContext()(supportsx-api-keyandAuthorization: Bearer); per-artist access enforced viacheckAccountArtistAccess, mirroringDELETE /api/artists/{id}Error envelope mapping
{ status, missing_fields, error }validateAuthContext{ status: "error", error: "Unauthorized segment creation attempt" }createSegmentsreturned "No social account found for this artist" or "No fans found for this artist"feedbackfield from the shared handler so the REST caller sees the same remediation guidance the MCP tool doescreateSegmentsfailure or thrown errorSuccess envelope
{ "status": "success", "segments_created": 5, "message": "Segments generated successfully." }Files
app/api/artists/[id]/segments/route.ts(new; POST, OPTIONS)lib/artists/segments/postArtistSegmentsHandler.ts(new)lib/artists/segments/validatePostSegmentsBody.ts(new)lib/artists/segments/__tests__/postArtistSegmentsHandler.test.ts(new; 11 tests)Test plan
pnpm test lib/artists/segments— 11/11 greenpnpm test— 1905/1905 green (full suite)pnpm lint:check— 0 errors (no ESLint config relaxations; see PR chore(lint): restore green lint via scoped rules + meaningful JSDoc #435)pnpm buildparses the new route; build exit is due to unrelated missing env vars (APIFY, PRIVY, SPOTIFY, REDIS, ARWEAVE, FAL) not this routenpx tsc --noEmitreports no TypeScript errors in the new filespnpm devE2E is not used)Notes
hooks/useCreateSegments.ts) will cut over in the follow-up chat PR in the Create stack; the localchat/app/api/segments/create/route.tsis removed there.Summary by cubic
Adds
POST /api/artists/{id}/segmentsto let clients manually create segments for an artist, reusing the sharedcreateSegmentsflow. Returns201 Createdon success and consolidates validation intovalidatePostArtistSegmentsRequest.New Features
POST /api/artists/{id}/segmentswithOPTIONSfor CORS.postArtistSegmentsHandlerdelegates tocreateSegments; body{ prompt }; pathidmaps toartist_account_id.validateAuthContext; per-artist access viacheckAccountArtistAccess; 404 when artist is missing.{ status, segments_created, message }; errors 400/401/403/404/409 (no socials or fans; includesfeedback)/500. 11 tests cover success and all error paths.Refactors
validatePostArtistSegmentsRequest; validator return types prefixed withValidated*.Written for commit eeff513. Summary will update on new commits.
Summary by CodeRabbit