Skip to content

fix: resolve all 610 ESLint errors across the codebase#380

Open
sweetmantech wants to merge 1 commit intotestfrom
fix/lint-errors
Open

fix: resolve all 610 ESLint errors across the codebase#380
sweetmantech wants to merge 1 commit intotestfrom
fix/lint-errors

Conversation

@sweetmantech
Copy link
Copy Markdown
Contributor

@sweetmantech sweetmantech commented Mar 31, 2026

Summary

  • Replace 233 no-explicit-any with proper types (unknown, specific interfaces, typed casts)
  • Add meaningful JSDoc descriptions, @param, and @returns to 370+ functions (not empty stubs)
  • Remove 20 unused variables/imports
  • Fix param name mismatches, member ordering, import order, and tag-lines
  • 182 files changed, 926 insertions, 411 deletions

Error breakdown (all resolved)

Rule Count
@typescript-eslint/no-explicit-any 233
jsdoc/require-returns 101
jsdoc/require-param 91
jsdoc/require-param-description 81
jsdoc/require-jsdoc 29
jsdoc/check-param-names 25
jsdoc/require-description 20
@typescript-eslint/no-unused-vars 20
jsdoc/tag-lines 4
import/first 3
jsdoc/require-hyphen-before-param-description 2
@typescript-eslint/member-ordering 1

Test plan

  • pnpm lint:check passes with 0 errors
  • All 1624 tests pass (238 test files)
  • Lint CI workflow passes on PR

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation

    • Enhanced inline documentation across API endpoints, handlers, and utility functions for improved developer clarity.
  • Bug Fixes

    • Improved error handling in artist account creation and workspace initialization.
    • Updated data filtering logic for enhanced response consistency.
  • New Features

    • Added CORS preflight support to admin endpoints.
    • Introduced content template validation utility.

- Replace 233 `no-explicit-any` with proper types (unknown, specific interfaces)
- Add meaningful JSDoc descriptions, @param, and @returns to 370+ functions
- Remove 20 unused variables/imports
- Fix param name mismatches, member ordering, import order, and tag-lines
- All 1624 tests still pass

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Mar 31, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
recoup-api Error Error Mar 31, 2026 1:58am

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 31, 2026

📝 Walkthrough

Walkthrough

A comprehensive documentation update across 123 files adding and refining JSDoc comments for API routes, utility functions, and handlers. Includes targeted functional changes: removing orgId from chat operations, improving type safety by replacing unsafe as any casts, adding an OPTIONS route handler to the Privy endpoint, and introducing a new isSupportedContentTemplate utility function.

Changes

Cohort / File(s) Summary
API Route Handlers
app/api/accounts/[id]/route.ts, app/api/admins/coding/pr/route.ts, app/api/admins/coding/slack/route.ts, app/api/admins/content/slack/route.ts, app/api/songs/analyze/presets/route.ts, app/api/transcribe/route.ts, app/api/connectors/route.ts, app/api/coding-agent/callback/route.ts, app/api/coding-agent/github/route.ts
Updated JSDoc documentation for request/response semantics and CORS handling. Added OPTIONS handler to app/api/admins/privy/route.ts returning CORS headers.
Chat Request Handling
lib/chats/compactChatsHandler.ts, lib/chats/validateUpdateChatBody.ts, lib/chats/processCompactChatRequest.ts
Removed orgId destructuring from request handling; handlers now use only accountId, chatId, and prompt. Updated JSDoc to reflect parameter changes.
Privy Admin Functions
lib/admins/privy/countNewAccounts.ts, lib/admins/privy/fetchPrivyLogins.ts, lib/admins/privy/getCutoffMs.ts, lib/admins/privy/getLatestVerifiedAt.ts, lib/admins/privy/toMs.ts
Added comprehensive JSDoc for Privy user filtering and timestamp calculations, documenting period parameters and return semantics.
Slack Admin & Content Functions
lib/admins/slack/createSlackTagsHandler.ts, lib/admins/slack/extractGithubPrUrls.ts, lib/admins/slack/fetchThreadPullRequests.ts, lib/admins/slack/getCutoffTs.ts, lib/admins/content/extractVideoLinks.ts, lib/admins/content/fetchThreadVideoLinks.ts, lib/admins/pr/getPrStatusHandler.ts
Updated JSDoc documentation describing request parameter structure, deduplication behavior, and return shapes (URLs, timestamps, status mappings).
Coding Agent Route & Utilities
lib/coding-agent/buildMergeTestToMainCard.ts, lib/coding-agent/buildPRCard.ts, lib/coding-agent/buildTaskCard.ts, lib/coding-agent/encodeGitHubThreadId.ts, lib/coding-agent/extractPRComment.ts, lib/coding-agent/handleGitHubWebhook.ts, lib/coding-agent/handleMergeSuccess.ts, lib/coding-agent/handlePRCreated.ts, lib/coding-agent/handlers/*, lib/coding-agent/mergeGithubBranch.ts, lib/coding-agent/mergeGithubPR.ts, lib/coding-agent/parseMergeActionId.ts, lib/coding-agent/parseMergeTestToMainActionId.ts, lib/coding-agent/prState/*, lib/coding-agent/verifyGitHubWebhook.ts, lib/coding-agent/whatsApp/isWhatsAppConfigured.ts
Comprehensive JSDoc additions documenting Card components, webhook verification, GitHub branch/PR operations, and PR state management (storage keys, encoding).
Content Management Functions
lib/content/contentTemplates.ts, lib/content/createContentHandler.ts, lib/content/getArtistContentReadiness.ts, lib/content/getArtistFileTree.ts, lib/content/getArtistRootPrefix.ts, lib/content/getContentEstimateHandler.ts, lib/content/getContentTemplatesHandler.ts, lib/content/getContentValidateHandler.ts, lib/content/isCompletedRun.ts, lib/content/persistCreateContentRunVideo.ts, lib/content/validateCreateContentBody.ts, lib/content/validateGetContentEstimateQuery.ts, lib/content/validateGetContentValidateQuery.ts
Added new isSupportedContentTemplate function. Updated getContentValidateHandler to construct publicReadiness explicitly. Added/refined JSDoc for handlers and validators describing request parameters, readiness checks, and response shapes.
Catalog Functions
lib/catalog/formatCatalogSongsAsCSV.ts, lib/catalog/getCatalogDataAsCSV.ts, lib/catalog/getCatalogSongs.ts, lib/catalog/getCatalogs.ts
Updated JSDoc describing pagination, CSV formatting, and Recoup API integration. Replaced generic comments with explicit parameter/return documentation.
Chat Toolchain & System Prompt
lib/chat/toolChains/create_release_report/getReleaseReportReferenceMessage.ts, lib/chat/toolChains/getPrepareStepResult.ts, lib/prompts/getSystemPrompt.ts
Exported PrepareStepOptions type. Enhanced JSDoc for message templates and system prompt assembly, clarifying context injection semantics (account, organization, artist, conversation IDs).
AI & Model Functions
lib/ai/getAvailableModels.ts, lib/ai/getModel.ts, lib/ai/isEmbedModel.ts
Added JSDoc documenting model retrieval, embedding detection, and error handling (empty array fallback).
Composio Integration
lib/composio/client.ts, lib/composio/connectors/isAllowedArtistConnector.ts, lib/composio/getCallbackUrl.ts, lib/composio/getFrontendBaseUrl.ts, lib/composio/toolRouter/createToolRouterSession.ts, lib/mcp/tools/flamingo/registerAnalyzeMusicTool.ts
Updated getCallbackUrl function signature to destructure { destination, roomId } instead of accepting whole options object. Changed result-shaping logic from object destructuring to Object.entries filtering. Added JSDoc for client initialization and session configuration.
Database & File Storage
lib/supabase/account_artist_ids/getAccountArtistIds.ts, lib/supabase/account_workspace_ids/getAccountWorkspaceIds.ts, lib/supabase/files/createFileRecord.ts, lib/supabase/files/selectFileByStorageKey.ts, lib/supabase/song_artists/insertSongArtists.ts, lib/supabase/storage/createSignedFileUrlByKey.ts, lib/supabase/storage/uploadFileByKey.ts
Updated getAccountArtistIds to use destructured parameters in function signature. Added/refined JSDoc for file operations (creation, retrieval, signed URLs) and storage metadata documentation.
Transcription & Audio Processing
lib/transcribe/processAudioTranscription.ts, lib/transcribe/saveAudioToFiles.ts, lib/transcribe/saveTranscriptToFiles.ts, lib/transcribe/types.ts
Added new helper getExtensionFromContentType for MIME-to-file-extension mapping. Added comprehensive JSDoc for transcription workflows, file uploads, and error formatting.
Credit & Token Management
lib/credits/getCreditUsage.ts, lib/credits/handleChatCredits.ts
Replaced unsafe as any casts with Record<string, unknown> bracket-access approach. Updated JSDoc parameter descriptions from individual parameters to destructured object form.
Account & Workspace Creation
lib/accounts/validateOverrideAccountId.ts, lib/artists/createArtistInDb.ts, lib/workspaces/createWorkspaceInDb.ts
Removed error binding from catch clauses in error handlers. Updated JSDoc to clarify parameter destructuring and override semantics.
GitHub & MCP Functions
lib/github/expandSubmoduleEntries.ts, lib/github/getRepoGitModules.ts, lib/github/resolveSubmodulePath.ts, lib/mcp/resolveAccountId.ts, lib/mcp/tools/transcribe/registerTranscribeAudioTool.ts
Updated JSDoc parameter documentation to reflect options-object destructuring (e.g., root0.owner, root0.repo). Added documentation for MCP tool registration and submodule resolution.
Flamingo & Misc Handlers
lib/flamingo/getFlamingoPresetsHandler.ts, lib/flamingo/postFlamingoGenerateHandler.ts
Updated JSDoc for presets handler. Changed result-filtering logic in POST handler from object destructuring to Object.entries(...).filter(...) approach.
Slack Integration & Utilities
lib/slack/getBotChannels.ts, lib/slack/getBotUserId.ts, lib/slack/getSlackUserInfo.ts, lib/spotify/getSpotifyFollowers.ts, lib/trigger/fetchTriggerRuns.ts, lib/trigger/triggerCreateContent.ts, lib/coding-agent/resolvePRState.ts
Added JSDoc for Slack/Spotify API calls documenting token parameters, response shapes, and follower counts. Reordered TriggerRun interface property. Updated import structure for coding-agent PR state.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

📚✨ A thousand comments bloomed,
Where silence once had ruled the code.
@param and @returns now groom
Each function down the digital road.
Type safety tightened, org IDs sighed goodbye—
Clean prose meets cleaner sky. 🌟

🚥 Pre-merge checks | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Solid & Clean Code ⚠️ Warning PR violates SOLID principles: unguarded JSON.parse() calls in merge functions violate return contract, bare catch blocks suppress errors without logging, manual validation breaks architectural consistency, connector endpoints accept account_id from client input violating security principle, and getCutoffTs documentation is inaccurate. Wrap JSON.parse() in try-catch blocks, replace bare catch blocks with proper error handling, refactor validators to use Zod schemas, remove account_id parameters from connectors, and correct getCutoffTs documentation to match implementation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/lint-errors

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
lib/catalog/formatCatalogSongsAsCSV.ts (1)

10-13: ⚠️ Potential issue | 🟠 Major

Escape embedded quotes to avoid invalid CSV rows.

Quoted CSV fields must escape inner " characters. Current output breaks parsing when names/albums contain quotes.

Proposed fix
 export function formatCatalogSongsAsCSV(songs: CatalogSong[]): string {
+  const escapeCsv = (value: string): string => value.replace(/"/g, '""');
+
   const csvLines = songs.map(song => {
-    const artistNames = song.artists.map(artist => artist.name).join(", ");
-    return `${song.isrc},"${song.name}","${song.album}","${artistNames}"`;
+    const artistNames = song.artists.map(artist => artist.name).join(", ");
+    return `${song.isrc},"${escapeCsv(song.name)}","${escapeCsv(song.album)}","${escapeCsv(artistNames)}"`;
   });
 
   return csvLines.join("\n");
 }
As per coding guidelines "lib/**/*.ts: For domain functions, ensure ... Proper error handling ... Use TypeScript for type safety".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/catalog/formatCatalogSongsAsCSV.ts` around lines 10 - 13, The CSV builder
in formatCatalogSongsAsCSV.ts doesn't escape embedded double quotes, breaking
CSV parsing; implement an escape helper (e.g., escapeCsv(value: string)) that
replaces all " with "" and use it when building csvLines for song.name,
song.album and each artist.name (and any other quoted field), then wrap the
escaped values in quotes when interpolating into the template (keep ISRC
formatting consistent). Update the songs.map usage to apply escapeCsv to artist
names joined, song.name and song.album so all quoted fields are safe.
lib/ai/getAvailableModels.ts (1)

15-16: 🛠️ Refactor suggestion | 🟠 Major

Add error logging in the catch block.

The empty catch block silently swallows all errors, making debugging difficult when the gateway API fails. Consider logging the error before returning the empty array to aid troubleshooting.

🔍 Proposed fix to add error logging
-  } catch {
+  } catch (error) {
+    console.error("Failed to fetch available models from gateway:", error);
     return [];
   }

Based on coding guidelines: "For domain functions, ensure: Proper error handling"

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/ai/getAvailableModels.ts` around lines 15 - 16, The catch block in
getAvailableModels (lib/ai/getAvailableModels.ts) currently swallows errors and
returns [] — change it to capture the thrown error (e.g., catch (err)) and log
the error with context before returning the empty array; use the project's
logger (processLogger.error) if available, otherwise console.error, and include
a message like "getAvailableModels: gateway API failed" plus the error details
to aid debugging.
🧹 Nitpick comments (18)
lib/composio/getCallbackUrl.ts (1)

20-25: Use a named argument to avoid root0 JSDoc leakage

The generated root0.* docs are hard to read. Prefer a named parameter (options) and destructure inside the function for clearer API docs.

Proposed refactor
-/**
- * Build callback URL for OAuth redirects.
- *
- * `@param` root0 - The callback options
- * `@param` root0.destination - Where to redirect: "chat" or "connectors"
- * `@param` root0.roomId - For chat destination, the room ID to return to
- * `@returns` Full callback URL with success indicator
- */
-export function getCallbackUrl({ destination, roomId }: CallbackOptions): string {
+/**
+ * Build callback URL for OAuth redirects.
+ *
+ * `@param` options - The callback options
+ * `@param` options.destination - Where to redirect: "chat" or "connectors"
+ * `@param` options.roomId - For chat destination, the room ID to return to
+ * `@returns` Full callback URL with success indicator
+ */
+export function getCallbackUrl(options: CallbackOptions): string {
+  const { destination, roomId } = options;
   const baseUrl = getFrontendBaseUrl();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/composio/getCallbackUrl.ts` around lines 20 - 25, Replace the anonymous
destructured parameter in getCallbackUrl with a named parameter to avoid `root0`
in JSDoc: change the function signature to accept a single `options` object
(e.g., getCallbackUrl(options: CallbackOptions)) and then destructure inside the
function (const { destination, roomId } = options). Update the JSDoc param names
to `options`, `options.destination`, and `options.roomId` so generated docs are
clear, and keep the rest of the function logic unchanged.
lib/catalog/getCatalogSongs.ts (1)

34-44: Add input guards for pagination arguments.

Please validate page and pageSize before building query params to fail fast on invalid input.

Proposed guard
 export async function getCatalogSongs(
   catalogId: string,
   pageSize: number = 100,
   page: number = 1,
   artistName?: string,
 ): Promise<CatalogSongsResponse> {
+  if (!catalogId.trim()) {
+    throw new Error("catalogId is required");
+  }
+  if (!Number.isInteger(pageSize) || pageSize <= 0) {
+    throw new Error("pageSize must be a positive integer");
+  }
+  if (!Number.isInteger(page) || page <= 0) {
+    throw new Error("page must be a positive integer");
+  }
+
   try {
As per coding guidelines "lib/**/*.ts: For domain functions, ensure ... Proper error handling ... KISS: Prefer simple, readable implementations".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/catalog/getCatalogSongs.ts` around lines 34 - 44, In getCatalogSongs, add
input guards for the pagination args (page and pageSize) before constructing
URLSearchParams: verify Number.isInteger(page) and Number.isInteger(pageSize)
and that both are > 0 (optionally enforce a sensible max for pageSize), and
throw a clear synchronous error (e.g., TypeError or RangeError) if validation
fails; do this at the top of the getCatalogSongs function (before building
params) so invalid inputs fail fast and avoid sending bad query params.
lib/spotify/getSpotifyFollowers.ts (1)

44-66: Consider refining error handling and documenting the first-result behavior.

Two optional improvements to enhance maintainability:

  1. Error handling pattern (lines 63-64): Logging and then re-throwing can lead to duplicate log entries if the caller also logs. Consider either:

    • Letting the error propagate without logging (caller handles logging), OR
    • Wrapping in a domain-specific error type
  2. First-result assumption (line 61): The function returns the follower count of the first search result without documenting this behavior. Consider adding a note to the JSDoc that clarifies this, e.g., "Returns the follower count of the first matching artist from Spotify search results."

♻️ Optional refactor: Remove redundant error logging
   return data.artists.items[0].followers.total;
 } catch (error) {
-  console.error(`Error fetching Spotify followers for "${artistName}":`, error);
   throw error;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/spotify/getSpotifyFollowers.ts` around lines 44 - 66, Update
getSpotifyFollowers to avoid duplicate logging and to document first-result
behavior: remove the console.error from the catch block so errors simply
propagate (or alternatively wrap and throw a domain-specific error type such as
SpotifyFetchError from the catch), and add/extend the JSDoc for
getSpotifyFollowers to state that it returns the follower count of the first
matching artist returned by the Spotify search (i.e., first item in
data.artists.items). Ensure references to getSpotifyFollowers and the catch
block are updated accordingly.
lib/artists/createArtistInDb.ts (1)

54-55: Preserve exception context in the catch path

At Line 54, using a bare catch drops root-cause details, and this function already returns null for non-exception branches. Please capture/log the error (or return a typed error result) so operational failures are debuggable.

As per coding guidelines, for lib/**/*.ts domain functions, ensure “Proper error handling”.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/artists/createArtistInDb.ts` around lines 54 - 55, The catch block in
createArtistInDb currently swallows exceptions (bare `catch`) and returns null;
change it to `catch (err)` so the error is captured, then either log the error
(using the module's logger or console.error) with context (e.g.,
"createArtistInDb failed") and return null, or return a typed error/result
instead of null; update the `createArtistInDb` function to preserve and surface
the caught exception rather than dropping it.
lib/workspaces/createWorkspaceInDb.ts (1)

52-53: Avoid silent failure in catch

At Line 52, bare catch removes exception visibility while returning null, which is also used for expected early exits. Capture/log the error (or return a discriminated result) so callers and logs can distinguish operational failures from validation-style nulls.

As per coding guidelines, for lib/**/*.ts domain functions, ensure “Proper error handling”.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/workspaces/createWorkspaceInDb.ts` around lines 52 - 53, The bare catch
in createWorkspaceInDb swallows exceptions and returns null (which overlaps with
expected null exits); change the catch to catch (err) and do not silently return
null — instead log the error with the project's logger (e.g.,
processLogger.error or the module logger) including a descriptive message like
"Failed to create workspace in DB" and the error object, then rethrow the error
(or return a discriminated result object such as { success: false, error: err }
if the caller expects a non-throwing API) so operational failures are
distinguishable from validation-style nulls.
lib/supabase/storage/createSignedFileUrlByKey.ts (2)

23-25: Consider including the key in the error message for better debugging.

While the error handling is solid, including the key parameter in the error message would make debugging easier, especially when processing multiple files.

🔍 Suggested enhancement
   if (error || !data?.signedUrl) {
-    throw new Error(`Failed to create signed URL: ${error?.message ?? "unknown error"}`);
+    throw new Error(`Failed to create signed URL for key "${key}": ${error?.message ?? "unknown error"}`);
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/supabase/storage/createSignedFileUrlByKey.ts` around lines 23 - 25, The
error throw in createSignedFileUrlByKey should include the input key to aid
debugging; update the error construction in the block that checks (error ||
!data?.signedUrl) to append the value of the key parameter (e.g., `key`) to the
message so the thrown Error contains both the original error message and the key
being processed (keep existing fallback for unknown error and preserve current
nullish checks).

14-14: Consider extracting the time calculation to a named constant.

The inline calculation 60 * 60 * 24 * 7 works but could be more readable as a named constant, especially if this duration is used elsewhere in the codebase. This would improve maintainability per the DRY principle in the coding guidelines.

♻️ Suggested refactor

At the top of the file:

 import supabase from "@/lib/supabase/serverClient";
 import { SUPABASE_STORAGE_BUCKET } from "@/lib/const";
+
+const SEVEN_DAYS_IN_SECONDS = 60 * 60 * 24 * 7;

Then use it:

 export async function createSignedFileUrlByKey({
   key,
-  expiresInSeconds = 60 * 60 * 24 * 7,
+  expiresInSeconds = SEVEN_DAYS_IN_SECONDS,
 }: {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/supabase/storage/createSignedFileUrlByKey.ts` at line 14, Extract the
inline default expiry calculation from the createSignedFileUrlByKey parameter
(expiresInSeconds = 60 * 60 * 24 * 7) into a named top-level constant (e.g.,
DEFAULT_ONE_WEEK_SECONDS or DEFAULT_SIGNED_URL_TTL_SECONDS) and replace the
inline expression with that constant; update any other places that use the same
duration to reference the new constant to follow DRY and improve readability.
lib/mcp/tools/transcribe/registerTranscribeAudioTool.ts (1)

32-40: Consider using resolveAccountId() for authentication (outside current PR scope).

The tool directly uses args.account_id and args.artist_account_id from the input schema. For consistency with MCP authentication patterns, consider using resolveAccountId() to validate and resolve account access.

This is outside the scope of the current ESLint-fix PR but would align with the established MCP tool authentication pattern.

Based on learnings: "MCP tools should never manually extract accountId from extra.authInfo; always use resolveAccountId() for validation and access control".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/mcp/tools/transcribe/registerTranscribeAudioTool.ts` around lines 32 -
40, The code in the TranscribeAudio tool is directly using args.account_id and
args.artist_account_id when calling processAudioTranscription; replace that
manual extraction with the MCP auth helper by calling resolveAccountId() to
validate/resolve the caller's account and any target artist account before
calling processAudioTranscription. Concretely, in the TranscribeAudio handler
(the async (args: TranscribeAudioArgs) => { ... }), call resolveAccountId() to
obtain the resolved ownerAccountId and, if needed, resolve the artist account
similarly, then pass those resolved IDs to processAudioTranscription instead of
args.account_id and args.artist_account_id to follow MCP auth patterns.
app/api/transcribe/route.ts (1)

14-30: Consider authentication and validation improvements (outside current PR scope).

While the JSDoc changes look good, I noticed the existing implementation could benefit from future refactoring:

  1. The route accepts account_id directly from the request body rather than deriving it from authentication via validateAuthContext()
  2. Manual validation could be replaced with Zod schema validation

These are architectural concerns outside the scope of this ESLint-fix PR, but worth noting for a follow-up.

As per coding guidelines: "Never use account_id in request bodies or tool schemas; always derive the account ID from authentication" and "All API endpoints should use a validate function for input parsing using Zod for schema validation".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/api/transcribe/route.ts` around lines 14 - 30, The endpoint POST
currently trusts account_id from the request body and performs manual field
checks; update it to derive account_id from the authentication context and
switch input validation to a Zod schema. Specifically, call
validateAuthContext() (or the project's auth helper) at the start of POST to
obtain the account ID instead of reading body.account_id, define a Zod schema
for { audio_url, artist_account_id, title?, include_timestamps? } and run it
through the shared validate/parse helper used across the API, then remove the
manual if-checks for audio_url/artist_account_id and return schema-driven
errors. Ensure you still reject requests lacking audio_url or artist_account_id
per the schema and use the authenticated account_id for downstream logic.
lib/transcribe/processAudioTranscription.ts (1)

70-81: JSDoc is accurate; consider extending format coverage.

The JSDoc clearly documents the helper's purpose. The implementation handles the most common audio formats well.

A few observations for potential future enhancement:

  • Missing formats like ogg, flac, aac which OpenAI Whisper supports
  • The substring matching is loose (e.g., contentType.includes("wav") would match both audio/wav and audio/x-wav, which is likely intentional)

Since saveAudioToFiles uses the contentType parameter for the actual MIME type (not the extension), this is primarily cosmetic for filenames and works correctly.

🔧 Optional: Extended format coverage
 function getExtensionFromContentType(contentType: string): string {
   if (contentType.includes("wav")) return "wav";
   if (contentType.includes("m4a") || contentType.includes("mp4")) return "m4a";
   if (contentType.includes("webm")) return "webm";
+  if (contentType.includes("ogg")) return "ogg";
+  if (contentType.includes("flac")) return "flac";
+  if (contentType.includes("aac")) return "aac";
   return "mp3";
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/transcribe/processAudioTranscription.ts` around lines 70 - 81, The helper
getExtensionFromContentType currently maps a few audio MIME types but omits
formats Whisper supports (ogg, flac, aac) and uses loose substring checks;
update getExtensionFromContentType to explicitly handle "ogg", "flac", and "aac"
(returning "ogg", "flac", and "aac" respectively) and tighten matching (e.g.,
match MIME subtype tokens rather than arbitrary substrings) so predictable file
extensions are returned for MIME strings passed into saveAudioToFiles; reference
the function name getExtensionFromContentType to locate and modify the logic.
lib/supabase/storage/uploadFileByKey.ts (1)

4-12: Consider adding @returns and @throws tags for comprehensive documentation.

While the current JSDoc is clear and covers all parameters, adding @returns and @throws tags would provide a complete picture of the function's behavior for future maintainers.

📝 Suggested enhancement
 /**
  * Upload file to Supabase storage by key.
  *
  * `@param` key - The storage key (path) where the file will be stored
  * `@param` file - The file or blob data to upload
  * `@param` options - Optional upload configuration
  * `@param` options.contentType - MIME type of the file (defaults to application/octet-stream)
  * `@param` options.upsert - Whether to overwrite an existing file at the same key (defaults to false)
+ * `@returns` Resolves when the file upload completes successfully
+ * `@throws` {Error} When the upload operation fails
  */
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/supabase/storage/uploadFileByKey.ts` around lines 4 - 12, The JSDoc for
uploadFileByKey is missing `@returns` and `@throws` tags; update the comment above
the uploadFileByKey function to include a clear `@returns` describing the Promise
return type and what it resolves to (e.g., success result or response object)
and an `@throws` that lists the kinds of errors that can be raised (validation
errors, network/Supabase upload errors) — make sure the descriptions match the
function's actual behavior and return shape so maintainers know what to expect.
lib/content/getArtistRootPrefix.ts (1)

9-21: Consider adding input validation for improved robustness.

While the function logic is clean and follows KISS principles, adding defensive input validation would improve reliability, especially since this is a utility function that may be called from various contexts:

  • Validate that paths is a non-empty array
  • Validate that artistSlug is a non-empty string
  • Consider sanitizing artistSlug to prevent path traversal sequences (e.g., ../) or invalid characters

These checks would prevent runtime errors and ensure predictable behavior with edge-case inputs.

🛡️ Example validation approach
 export function getArtistRootPrefix(paths: string[], artistSlug: string): string {
+  if (!paths || paths.length === 0) {
+    throw new Error('paths array cannot be empty');
+  }
+  if (!artistSlug || artistSlug.trim().length === 0) {
+    throw new Error('artistSlug cannot be empty');
+  }
+  // Optional: sanitize artistSlug to prevent path traversal
+  const sanitizedSlug = artistSlug.replace(/\.\./g, '').replace(/^\/+|\/+$/g, '');
+  
-  const preferredPrefix = `artists/${artistSlug}/`;
+  const preferredPrefix = `artists/${sanitizedSlug}/`;
   if (paths.some(path => path.startsWith(preferredPrefix))) {
     return preferredPrefix;
   }

-  const directPrefix = `${artistSlug}/`;
+  const directPrefix = `${sanitizedSlug}/`;
   if (paths.some(path => path.startsWith(directPrefix))) {
     return directPrefix;
   }

   return preferredPrefix;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/content/getArtistRootPrefix.ts` around lines 9 - 21, The function
getArtistRootPrefix lacks input validation; add checks at the top of
getArtistRootPrefix to ensure paths is a non-empty array of strings and
artistSlug is a non-empty string, and either sanitize or reject artistSlug
values that contain path traversal or invalid characters (e.g., '..' or '/'),
throwing a clear TypeError for invalid inputs; after validation, preserve the
existing logic that computes preferredPrefix and directPrefix and returns the
matching prefix (preferredPrefix by default).
lib/prompts/getSystemPrompt.ts (1)

20-133: Consider extracting section builders to reduce function length.

The function body (~91 lines) exceeds the 50-line guideline. The three conditional sections (user context, artist instruction, knowledge base) follow a similar pattern and could be extracted into smaller helper functions.

This would improve:

  • Compliance with the Single Responsibility Principle
  • Code maintainability and testability
  • Adherence to coding guidelines for domain functions

Since this PR focuses on ESLint fixes, this refactoring can be deferred to a future PR.

♻️ Example refactoring approach

Extract helper functions for each section:

function buildUserContextSection(
  accountWithDetails: AccountWithDetails,
  email?: string
): string {
  let section = `\n\n-----CURRENT USER CONTEXT-----\n...`;
  // ... existing logic from lines 68-107
  return section;
}

function buildArtistInstructionSection(instruction: string): string {
  return `\n\n-----SELECTED ARTIST/WORKSPACE CONTEXT-----\n...`;
}

function buildKnowledgeBaseSection(text: string): string {
  return `\n\n-----ARTIST/WORKSPACE KNOWLEDGE BASE-----\n...`;
}

// Main function becomes much simpler:
export function getSystemPrompt({...}: {...}): string {
  let systemPrompt = `${SYSTEM_PROMPT}\n\n**IMPORTANT CONTEXT VALUES...**`;
  
  if (accountWithDetails) {
    systemPrompt += buildUserContextSection(accountWithDetails, email);
  }
  if (artistInstruction) {
    systemPrompt += buildArtistInstructionSection(artistInstruction);
  }
  if (knowledgeBaseText) {
    systemPrompt += buildKnowledgeBaseSection(knowledgeBaseText);
  }
  
  return systemPrompt;
}

This would create a file structure following the "one exported function per file" principle by keeping the helpers private or in separate utility files.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/prompts/getSystemPrompt.ts` around lines 20 - 133, The getSystemPrompt
function is over-long and should have its conditional sections extracted into
helpers; refactor the user, artist, and knowledge-base blocks into small private
functions (e.g., buildUserContextSection(accountWithDetails, email),
buildArtistInstructionSection(artistInstruction),
buildKnowledgeBaseSection(knowledgeBaseText)) and replace the inline
string-building in getSystemPrompt with calls to these helpers so
getSystemPrompt remains concise and each helper encapsulates the logic that
currently lives in the blocks that reference accountWithDetails,
artistInstruction, and knowledgeBaseText.
lib/credits/getCreditUsage.ts (1)

28-31: Falsy check treats zero tokens as missing.

The condition !inputTokens || !outputTokens evaluates to true when tokens are 0, logging "No tokens found in usage" even though zero is a valid token count. While the functional result (returning 0) is the same, the error message is misleading. Consider using nullish checks for semantic correctness.

♻️ Proposed fix for precise null checking
-    if (!inputTokens || !outputTokens) {
+    if (inputTokens == null || outputTokens == null) {
       console.error("No tokens found in usage");
       return 0;
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/credits/getCreditUsage.ts` around lines 28 - 31, The current falsy check
in getCreditUsage incorrectly treats 0 as missing; change the condition that
uses inputTokens and outputTokens (in getCreditUsage) to a nullish/undefined
check (e.g., check inputTokens == null || outputTokens == null) so only null or
undefined trigger the console.error("No tokens found in usage") and the early
return 0; update the conditional to use those nullish checks and keep the same
logging/return behavior when tokens are actually missing.
lib/admins/content/extractVideoLinks.ts (1)

14-53: Consider extracting helper functions for readability.

The function at 53 lines slightly exceeds the 50-line guideline. As per coding guidelines, lib functions should be kept under 50 lines. Similar to extractGithubPrUrls, consider extracting the three extraction surfaces into focused helper functions:

function extractUrlsFromText(text: string): string[]
function extractUrlsFromAttachments(attachments?: SlackAttachment[]): string[]
function extractUrlsFromBlocks(blocks?: SlackBlock[]): string[]

This would improve maintainability and make each extraction logic easier to test independently.

Based on coding guidelines: "Keep functions under 50 lines" for lib/**/*.ts files.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/admins/content/extractVideoLinks.ts` around lines 14 - 53, The
extractVideoLinks function exceeds the 50-line guideline; split its three
extraction responsibilities into small helpers to improve readability and
testability: create extractUrlsFromText(text: string): string[] to run
VIDEO_URL_PATTERN on text, extractUrlsFromAttachments(attachments?:
SlackAttachment[]): string[] to iterate attachment.actions and collect
action.url, and extractUrlsFromBlocks(blocks?: SlackBlock[]): string[] to walk
block.elements and nested element.elements for element.url; then refactor
extractVideoLinks to call these helpers, merge results, deduplicate with new
Set, and return the final array.
lib/admins/slack/extractGithubPrUrls.ts (1)

33-72: Consider splitting into smaller extraction functions.

The function at 72 lines exceeds the 50-line guideline. As per coding guidelines, lib functions should be kept under 50 lines. Consider extracting the three extraction surfaces (text, attachments, blocks) into separate helper functions:

function extractFromText(text: string): string[]
function extractFromAttachments(attachments?: SlackAttachment[]): string[]
function extractFromBlocks(blocks?: SlackBlock[]): string[]

This would improve testability and maintainability while adhering to the SRP principle.

Based on coding guidelines: "Keep functions under 50 lines" for lib/**/*.ts files.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/admins/slack/extractGithubPrUrls.ts` around lines 33 - 72, The
extractGithubPrUrls function is over the 50-line limit; split its three
extraction responsibilities into separate helpers to follow SRP and improve
testability: implement extractFromText(text: string): string[] to run
PR_URL_PATTERN on the message text, extractFromAttachments(attachments?:
SlackAttachment[]): string[] to scan attachment.actions and validate with
PR_URL_EXACT, and extractFromBlocks(blocks?: SlackBlock[]): string[] to traverse
block.elements and nested element.elements validating with PR_URL_EXACT; then
refactor extractGithubPrUrls to call these three helpers, concatenate results,
deduplicate (new Set) and return.
app/api/accounts/[id]/route.ts (1)

26-28: Prefer a named route context over root1 in docs/signature.

root1 is hard to read in API docs. Consider naming the second arg context and documenting context.params instead.

♻️ Optional readability refactor
-/**
- * `@param` request - The request object
- * `@param` root1 - Destructured route context
- * `@param` root1.params - Promise resolving to route params containing the account ID
- */
-export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
-  return getAccountHandler(request, params);
+/**
+ * `@param` request - The request object
+ * `@param` context - Route context
+ * `@param` context.params - Promise resolving to route params containing the account ID
+ */
+export async function GET(
+  request: NextRequest,
+  context: { params: Promise<{ id: string }> },
+) {
+  return getAccountHandler(request, context.params);
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/api/accounts/`[id]/route.ts around lines 26 - 28, The JSDoc and function
signature use the unclear name root1 for the route context; rename it to context
everywhere (both in the GET handler signature and the JSDoc) and update the
param docs to reference context.params instead of root1.params so
docs/readability improve — change occurrences in the GET function declaration
and the related JSDoc `@param` entries to use context and context.params.
lib/content/getArtistFileTree.ts (1)

7-10: JSDoc return description doesn't fully capture the fallback behavior.

The @returns states "or null if not found," but line 37 returns mainTree unconditionally after exhausting the org repos search. This means if the artist isn't found in any repo, the function returns the main repo's file tree (if it exists) rather than null. The only way to get null is if getRepoFileTree(githubRepo) returns null.

Consider clarifying the return contract:

📝 Suggested JSDoc refinement
 * `@param` githubRepo - The GitHub repository URL to search first.
 * `@param` artistSlug - The artist's directory slug to locate within the repo.
-* `@returns` The file tree entries for the repo that contains the artist, or null if not found.
+* `@returns` The file tree for the repo containing the artist, or the main repo's tree as a fallback, or null if the main repo tree couldn't be fetched.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/content/getArtistFileTree.ts` around lines 7 - 10, Update the JSDoc for
getArtistFileTree to accurately describe its fallback behavior: explain that it
returns the file tree for the repo that contains artistSlug if found, otherwise
it returns the main repo's file tree obtained from getRepoFileTree(githubRepo)
(which itself may be null) — i.e., the function only returns null when
getRepoFileTree(githubRepo) returns null; mention the mainTree fallback and
reference artistSlug, githubRepo, getRepoFileTree, and mainTree in the
description.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/api/connectors/route.ts`:
- Line 30: Remove all client-supplied account_id handling in the connectors
endpoints: stop reading account_id from query or request bodies and derive the
account ID exclusively from validateAuthContext() for the GET /api/connectors
handler, the POST /api/connectors/authorize handler, and the DELETE
/api/connectors handler. Update the handlers (functions/methods that parse
request.query.account_id, request.body.account_id or similar) to use the
accountId returned by validateAuthContext(), remove any conditional access
checks based on an optional account_id input, and adjust related TypeScript
types and JSDoc comments (the param lines in the file) to reflect that
account_id is not accepted from the client. Ensure all authorization/enforcement
still runs but now uses the accountId from validateAuthContext() only.

In `@lib/admins/slack/getCutoffTs.ts`:
- Around line 8-10: The JSDoc `@returns` for getCutoffTs is misleading — the
function returns "current time minus the period length" (a rolling cutoff), not
the calendar start of the period; update the comment in getCutoffTs to say:
"Unix timestamp in seconds representing current time minus the period length
(rolling cutoff), or null for 'all'." Ensure the updated wording appears where
the `@returns` is declared to match the getCutoffTs implementation.

In `@lib/coding-agent/mergeGithubBranch.ts`:
- Line 19: mergeGithubBranch and mergeGithubPR currently call
JSON.parse(errorBody) on error paths which can throw and break the documented
return contract; update both functions so the JSON.parse(errorBody) is wrapped
in a try-catch and never allowed to throw — on parse success extract a
meaningful message, on failure fall back to using the raw errorBody or a generic
message, then return { ok: false, message } so the function always returns the
documented union; locate the JSON.parse usage in mergeGithubBranch and
mergeGithubPR and implement this guarded parsing behavior.

In `@lib/content/validateGetContentValidateQuery.ts`:
- Around line 16-19: Replace the manual parsing of artist_account_id in the
validateGetContentValidateQuery module with a Zod-backed validator: define a Zod
schema (e.g., GetContentQuerySchema) that validates the incoming query shape
(including artist_account_id as the required string/UUID pattern you expect),
use schema.parse or schema.safeParse inside validateGetContentValidateQuery to
validate and extract values, export the inferred type (e.g., type
GetContentQuery = z.infer<typeof GetContentQuerySchema>), and update the
function to return the typed validated data (account ID, artist_account_id,
resolved artist slug) or a NextResponse error on failure; reference the existing
validateGetContentValidateQuery function and export names when making these
changes.

---

Outside diff comments:
In `@lib/ai/getAvailableModels.ts`:
- Around line 15-16: The catch block in getAvailableModels
(lib/ai/getAvailableModels.ts) currently swallows errors and returns [] — change
it to capture the thrown error (e.g., catch (err)) and log the error with
context before returning the empty array; use the project's logger
(processLogger.error) if available, otherwise console.error, and include a
message like "getAvailableModels: gateway API failed" plus the error details to
aid debugging.

In `@lib/catalog/formatCatalogSongsAsCSV.ts`:
- Around line 10-13: The CSV builder in formatCatalogSongsAsCSV.ts doesn't
escape embedded double quotes, breaking CSV parsing; implement an escape helper
(e.g., escapeCsv(value: string)) that replaces all " with "" and use it when
building csvLines for song.name, song.album and each artist.name (and any other
quoted field), then wrap the escaped values in quotes when interpolating into
the template (keep ISRC formatting consistent). Update the songs.map usage to
apply escapeCsv to artist names joined, song.name and song.album so all quoted
fields are safe.

---

Nitpick comments:
In `@app/api/accounts/`[id]/route.ts:
- Around line 26-28: The JSDoc and function signature use the unclear name root1
for the route context; rename it to context everywhere (both in the GET handler
signature and the JSDoc) and update the param docs to reference context.params
instead of root1.params so docs/readability improve — change occurrences in the
GET function declaration and the related JSDoc `@param` entries to use context and
context.params.

In `@app/api/transcribe/route.ts`:
- Around line 14-30: The endpoint POST currently trusts account_id from the
request body and performs manual field checks; update it to derive account_id
from the authentication context and switch input validation to a Zod schema.
Specifically, call validateAuthContext() (or the project's auth helper) at the
start of POST to obtain the account ID instead of reading body.account_id,
define a Zod schema for { audio_url, artist_account_id, title?,
include_timestamps? } and run it through the shared validate/parse helper used
across the API, then remove the manual if-checks for audio_url/artist_account_id
and return schema-driven errors. Ensure you still reject requests lacking
audio_url or artist_account_id per the schema and use the authenticated
account_id for downstream logic.

In `@lib/admins/content/extractVideoLinks.ts`:
- Around line 14-53: The extractVideoLinks function exceeds the 50-line
guideline; split its three extraction responsibilities into small helpers to
improve readability and testability: create extractUrlsFromText(text: string):
string[] to run VIDEO_URL_PATTERN on text,
extractUrlsFromAttachments(attachments?: SlackAttachment[]): string[] to iterate
attachment.actions and collect action.url, and extractUrlsFromBlocks(blocks?:
SlackBlock[]): string[] to walk block.elements and nested element.elements for
element.url; then refactor extractVideoLinks to call these helpers, merge
results, deduplicate with new Set, and return the final array.

In `@lib/admins/slack/extractGithubPrUrls.ts`:
- Around line 33-72: The extractGithubPrUrls function is over the 50-line limit;
split its three extraction responsibilities into separate helpers to follow SRP
and improve testability: implement extractFromText(text: string): string[] to
run PR_URL_PATTERN on the message text, extractFromAttachments(attachments?:
SlackAttachment[]): string[] to scan attachment.actions and validate with
PR_URL_EXACT, and extractFromBlocks(blocks?: SlackBlock[]): string[] to traverse
block.elements and nested element.elements validating with PR_URL_EXACT; then
refactor extractGithubPrUrls to call these three helpers, concatenate results,
deduplicate (new Set) and return.

In `@lib/artists/createArtistInDb.ts`:
- Around line 54-55: The catch block in createArtistInDb currently swallows
exceptions (bare `catch`) and returns null; change it to `catch (err)` so the
error is captured, then either log the error (using the module's logger or
console.error) with context (e.g., "createArtistInDb failed") and return null,
or return a typed error/result instead of null; update the `createArtistInDb`
function to preserve and surface the caught exception rather than dropping it.

In `@lib/catalog/getCatalogSongs.ts`:
- Around line 34-44: In getCatalogSongs, add input guards for the pagination
args (page and pageSize) before constructing URLSearchParams: verify
Number.isInteger(page) and Number.isInteger(pageSize) and that both are > 0
(optionally enforce a sensible max for pageSize), and throw a clear synchronous
error (e.g., TypeError or RangeError) if validation fails; do this at the top of
the getCatalogSongs function (before building params) so invalid inputs fail
fast and avoid sending bad query params.

In `@lib/composio/getCallbackUrl.ts`:
- Around line 20-25: Replace the anonymous destructured parameter in
getCallbackUrl with a named parameter to avoid `root0` in JSDoc: change the
function signature to accept a single `options` object (e.g.,
getCallbackUrl(options: CallbackOptions)) and then destructure inside the
function (const { destination, roomId } = options). Update the JSDoc param names
to `options`, `options.destination`, and `options.roomId` so generated docs are
clear, and keep the rest of the function logic unchanged.

In `@lib/content/getArtistFileTree.ts`:
- Around line 7-10: Update the JSDoc for getArtistFileTree to accurately
describe its fallback behavior: explain that it returns the file tree for the
repo that contains artistSlug if found, otherwise it returns the main repo's
file tree obtained from getRepoFileTree(githubRepo) (which itself may be null) —
i.e., the function only returns null when getRepoFileTree(githubRepo) returns
null; mention the mainTree fallback and reference artistSlug, githubRepo,
getRepoFileTree, and mainTree in the description.

In `@lib/content/getArtistRootPrefix.ts`:
- Around line 9-21: The function getArtistRootPrefix lacks input validation; add
checks at the top of getArtistRootPrefix to ensure paths is a non-empty array of
strings and artistSlug is a non-empty string, and either sanitize or reject
artistSlug values that contain path traversal or invalid characters (e.g., '..'
or '/'), throwing a clear TypeError for invalid inputs; after validation,
preserve the existing logic that computes preferredPrefix and directPrefix and
returns the matching prefix (preferredPrefix by default).

In `@lib/credits/getCreditUsage.ts`:
- Around line 28-31: The current falsy check in getCreditUsage incorrectly
treats 0 as missing; change the condition that uses inputTokens and outputTokens
(in getCreditUsage) to a nullish/undefined check (e.g., check inputTokens ==
null || outputTokens == null) so only null or undefined trigger the
console.error("No tokens found in usage") and the early return 0; update the
conditional to use those nullish checks and keep the same logging/return
behavior when tokens are actually missing.

In `@lib/mcp/tools/transcribe/registerTranscribeAudioTool.ts`:
- Around line 32-40: The code in the TranscribeAudio tool is directly using
args.account_id and args.artist_account_id when calling
processAudioTranscription; replace that manual extraction with the MCP auth
helper by calling resolveAccountId() to validate/resolve the caller's account
and any target artist account before calling processAudioTranscription.
Concretely, in the TranscribeAudio handler (the async (args:
TranscribeAudioArgs) => { ... }), call resolveAccountId() to obtain the resolved
ownerAccountId and, if needed, resolve the artist account similarly, then pass
those resolved IDs to processAudioTranscription instead of args.account_id and
args.artist_account_id to follow MCP auth patterns.

In `@lib/prompts/getSystemPrompt.ts`:
- Around line 20-133: The getSystemPrompt function is over-long and should have
its conditional sections extracted into helpers; refactor the user, artist, and
knowledge-base blocks into small private functions (e.g.,
buildUserContextSection(accountWithDetails, email),
buildArtistInstructionSection(artistInstruction),
buildKnowledgeBaseSection(knowledgeBaseText)) and replace the inline
string-building in getSystemPrompt with calls to these helpers so
getSystemPrompt remains concise and each helper encapsulates the logic that
currently lives in the blocks that reference accountWithDetails,
artistInstruction, and knowledgeBaseText.

In `@lib/spotify/getSpotifyFollowers.ts`:
- Around line 44-66: Update getSpotifyFollowers to avoid duplicate logging and
to document first-result behavior: remove the console.error from the catch block
so errors simply propagate (or alternatively wrap and throw a domain-specific
error type such as SpotifyFetchError from the catch), and add/extend the JSDoc
for getSpotifyFollowers to state that it returns the follower count of the first
matching artist returned by the Spotify search (i.e., first item in
data.artists.items). Ensure references to getSpotifyFollowers and the catch
block are updated accordingly.

In `@lib/supabase/storage/createSignedFileUrlByKey.ts`:
- Around line 23-25: The error throw in createSignedFileUrlByKey should include
the input key to aid debugging; update the error construction in the block that
checks (error || !data?.signedUrl) to append the value of the key parameter
(e.g., `key`) to the message so the thrown Error contains both the original
error message and the key being processed (keep existing fallback for unknown
error and preserve current nullish checks).
- Line 14: Extract the inline default expiry calculation from the
createSignedFileUrlByKey parameter (expiresInSeconds = 60 * 60 * 24 * 7) into a
named top-level constant (e.g., DEFAULT_ONE_WEEK_SECONDS or
DEFAULT_SIGNED_URL_TTL_SECONDS) and replace the inline expression with that
constant; update any other places that use the same duration to reference the
new constant to follow DRY and improve readability.

In `@lib/supabase/storage/uploadFileByKey.ts`:
- Around line 4-12: The JSDoc for uploadFileByKey is missing `@returns` and
`@throws` tags; update the comment above the uploadFileByKey function to include a
clear `@returns` describing the Promise return type and what it resolves to (e.g.,
success result or response object) and an `@throws` that lists the kinds of errors
that can be raised (validation errors, network/Supabase upload errors) — make
sure the descriptions match the function's actual behavior and return shape so
maintainers know what to expect.

In `@lib/transcribe/processAudioTranscription.ts`:
- Around line 70-81: The helper getExtensionFromContentType currently maps a few
audio MIME types but omits formats Whisper supports (ogg, flac, aac) and uses
loose substring checks; update getExtensionFromContentType to explicitly handle
"ogg", "flac", and "aac" (returning "ogg", "flac", and "aac" respectively) and
tighten matching (e.g., match MIME subtype tokens rather than arbitrary
substrings) so predictable file extensions are returned for MIME strings passed
into saveAudioToFiles; reference the function name getExtensionFromContentType
to locate and modify the logic.

In `@lib/workspaces/createWorkspaceInDb.ts`:
- Around line 52-53: The bare catch in createWorkspaceInDb swallows exceptions
and returns null (which overlaps with expected null exits); change the catch to
catch (err) and do not silently return null — instead log the error with the
project's logger (e.g., processLogger.error or the module logger) including a
descriptive message like "Failed to create workspace in DB" and the error
object, then rethrow the error (or return a discriminated result object such as
{ success: false, error: err } if the caller expects a non-throwing API) so
operational failures are distinguishable from validation-style nulls.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bad7ff9c-69b3-4310-ad24-eb4dd193bdd4

📥 Commits

Reviewing files that changed from the base of the PR and between d5c383b and ad61d55.

⛔ Files ignored due to path filters (74)
  • lib/admins/content/__tests__/getContentSlackTagsHandler.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/admins/emails/__tests__/validateGetAdminEmailsQuery.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/admins/pr/__tests__/getPrMergedStatusHandler.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/admins/privy/__tests__/getPrivyLoginsHandler.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/admins/privy/__tests__/validateGetPrivyLoginsQuery.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/admins/slack/__tests__/createSlackTagsHandler.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/admins/slack/__tests__/getSlackTagsHandler.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/admins/slack/__tests__/validateGetSlackTagsQuery.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/agents/generalAgent/__tests__/getGeneralAgent.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/ai/__tests__/getAvailableModels.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/ai/__tests__/getModel.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/artist/__tests__/updateArtistSocials.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/artists/__tests__/createArtistPostHandler.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/artists/__tests__/validateCreateArtistBody.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/auth/__tests__/validateAuthContext.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/chat/__tests__/handleChatCompletion.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/chat/__tests__/handleChatGenerate.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/chat/__tests__/handleChatStream.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/chat/__tests__/integration/chatEndToEnd.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/chat/__tests__/saveChatCompletion.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/chat/__tests__/setupChatRequest.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/chat/__tests__/validateChatRequest.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/chat/toolChains/__tests__/getExecutedToolTimeline.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/chat/toolChains/__tests__/getPrepareStepResult.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/chat/toolChains/__tests__/toolChains.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/chats/__tests__/createChatHandler.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/chats/__tests__/generateChatTitle.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/chats/__tests__/getChatsHandler.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/chats/__tests__/validateCreateChatBody.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/chats/__tests__/validateGetChatsRequest.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/coding-agent/__tests__/handleCodingAgentCallback.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/coding-agent/__tests__/handleGitHubWebhook.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/coding-agent/__tests__/handlers.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/coding-agent/__tests__/mergeGithubBranch.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/coding-agent/__tests__/mergeGithubPR.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/coding-agent/__tests__/onMergeAction.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/coding-agent/__tests__/onMergeTestToMainAction.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/coding-agent/__tests__/onSubscribedMessage.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/coding-agent/__tests__/resolvePRState.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/content/__tests__/validateCreateContentBody.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/credits/__tests__/getCreditUsage.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/emails/inbound/__tests__/validateNewEmailMemory.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/evals/callChatFunctions.ts is excluded by !**/evals/** and included by lib/**
  • lib/evals/callChatFunctionsWithResult.ts is excluded by !**/evals/** and included by lib/**
  • lib/evals/createToolsCalledScorer.ts is excluded by !**/evals/** and included by lib/**
  • lib/evals/extractTextFromResult.ts is excluded by !**/evals/** and included by lib/**
  • lib/evals/extractTextResultFromSteps.ts is excluded by !**/evals/** and included by lib/**
  • lib/evals/getCatalogSongsCountExpected.ts is excluded by !**/evals/** and included by lib/**
  • lib/evals/getSpotifyFollowersExpected.ts is excluded by !**/evals/** and included by lib/**
  • lib/evals/scorers/CatalogAvailability.ts is excluded by !**/evals/** and included by lib/**
  • lib/evals/scorers/QuestionAnswered.ts is excluded by !**/evals/** and included by lib/**
  • lib/evals/scorers/ToolsCalled.ts is excluded by !**/evals/** and included by lib/**
  • lib/flamingo/__tests__/getFlamingoPresetsHandler.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/github/__tests__/createOrUpdateFileContent.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/github/__tests__/expandSubmoduleEntries.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/mcp/__tests__/getMcpTools.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/mcp/tools/artists/__tests__/registerCreateNewArtistTool.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/mcp/tools/pulse/__tests__/registerGetPulsesTool.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/mcp/tools/pulse/__tests__/registerUpdatePulseTool.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/mcp/tools/sandbox/__tests__/registerPromptSandboxTool.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/mcp/tools/tasks/__tests__/registerGetTaskRunStatusTool.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/messages/__tests__/convertToUiMessages.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/messages/__tests__/getTextContent.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/notifications/__tests__/createNotificationHandler.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/notifications/__tests__/validateCreateNotificationBody.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/prompts/__tests__/getSystemPrompt.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/sandbox/__tests__/deleteSandboxHandler.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/sandbox/__tests__/postSandboxesFilesHandler.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/sandbox/__tests__/validateDeleteSandboxBody.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/supabase/account_sandboxes/__tests__/selectAccountSandboxes.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/tasks/__tests__/enrichTaskWithTriggerInfo.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/tasks/__tests__/getTaskRunHandler.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/tasks/__tests__/validateGetTaskRunQuery.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/tasks/__tests__/validateGetTasksQuery.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
📒 Files selected for processing (108)
  • app/api/accounts/[id]/route.ts
  • app/api/admins/coding/pr/route.ts
  • app/api/admins/coding/slack/route.ts
  • app/api/admins/content/slack/route.ts
  • app/api/admins/privy/route.ts
  • app/api/coding-agent/callback/route.ts
  • app/api/coding-agent/github/route.ts
  • app/api/connectors/route.ts
  • app/api/songs/analyze/presets/route.ts
  • app/api/transcribe/route.ts
  • lib/accounts/validateOverrideAccountId.ts
  • lib/admins/content/extractVideoLinks.ts
  • lib/admins/content/fetchThreadVideoLinks.ts
  • lib/admins/pr/getPrStatusHandler.ts
  • lib/admins/privy/countNewAccounts.ts
  • lib/admins/privy/fetchPrivyLogins.ts
  • lib/admins/privy/getCutoffMs.ts
  • lib/admins/privy/getLatestVerifiedAt.ts
  • lib/admins/privy/toMs.ts
  • lib/admins/slack/createSlackTagsHandler.ts
  • lib/admins/slack/extractGithubPrUrls.ts
  • lib/admins/slack/fetchThreadPullRequests.ts
  • lib/admins/slack/getCutoffTs.ts
  • lib/ai/getAvailableModels.ts
  • lib/ai/getModel.ts
  • lib/ai/isEmbedModel.ts
  • lib/artists/createArtistInDb.ts
  • lib/catalog/formatCatalogSongsAsCSV.ts
  • lib/catalog/getCatalogDataAsCSV.ts
  • lib/catalog/getCatalogSongs.ts
  • lib/catalog/getCatalogs.ts
  • lib/chat/toolChains/create_release_report/getReleaseReportReferenceMessage.ts
  • lib/chat/toolChains/getPrepareStepResult.ts
  • lib/chats/compactChatsHandler.ts
  • lib/chats/processCompactChatRequest.ts
  • lib/chats/validateUpdateChatBody.ts
  • lib/coding-agent/buildMergeTestToMainCard.ts
  • lib/coding-agent/buildPRCard.ts
  • lib/coding-agent/buildTaskCard.ts
  • lib/coding-agent/encodeGitHubThreadId.ts
  • lib/coding-agent/extractPRComment.ts
  • lib/coding-agent/handleGitHubWebhook.ts
  • lib/coding-agent/handleMergeSuccess.ts
  • lib/coding-agent/handlePRCreated.ts
  • lib/coding-agent/handlers/handleFeedback.ts
  • lib/coding-agent/handlers/onMergeAction.ts
  • lib/coding-agent/handlers/onMergeTestToMainAction.ts
  • lib/coding-agent/handlers/onNewMention.ts
  • lib/coding-agent/handlers/onSubscribedMessage.ts
  • lib/coding-agent/mergeGithubBranch.ts
  • lib/coding-agent/mergeGithubPR.ts
  • lib/coding-agent/parseMergeActionId.ts
  • lib/coding-agent/parseMergeTestToMainActionId.ts
  • lib/coding-agent/prState/buildPRStateKey.ts
  • lib/coding-agent/prState/deleteCodingAgentPRState.ts
  • lib/coding-agent/prState/getCodingAgentPRState.ts
  • lib/coding-agent/prState/setCodingAgentPRState.ts
  • lib/coding-agent/resolvePRState.ts
  • lib/coding-agent/verifyGitHubWebhook.ts
  • lib/coding-agent/whatsApp/isWhatsAppConfigured.ts
  • lib/composio/client.ts
  • lib/composio/connectors/isAllowedArtistConnector.ts
  • lib/composio/getCallbackUrl.ts
  • lib/composio/getFrontendBaseUrl.ts
  • lib/composio/toolRouter/createToolRouterSession.ts
  • lib/content/contentTemplates.ts
  • lib/content/createContentHandler.ts
  • lib/content/getArtistContentReadiness.ts
  • lib/content/getArtistFileTree.ts
  • lib/content/getArtistRootPrefix.ts
  • lib/content/getContentEstimateHandler.ts
  • lib/content/getContentTemplatesHandler.ts
  • lib/content/getContentValidateHandler.ts
  • lib/content/isCompletedRun.ts
  • lib/content/persistCreateContentRunVideo.ts
  • lib/content/validateCreateContentBody.ts
  • lib/content/validateGetContentEstimateQuery.ts
  • lib/content/validateGetContentValidateQuery.ts
  • lib/credits/getCreditUsage.ts
  • lib/credits/handleChatCredits.ts
  • lib/emails/processAndSendEmail.ts
  • lib/flamingo/getFlamingoPresetsHandler.ts
  • lib/flamingo/postFlamingoGenerateHandler.ts
  • lib/github/expandSubmoduleEntries.ts
  • lib/github/getRepoGitModules.ts
  • lib/github/resolveSubmodulePath.ts
  • lib/mcp/resolveAccountId.ts
  • lib/mcp/tools/flamingo/registerAnalyzeMusicTool.ts
  • lib/mcp/tools/transcribe/registerTranscribeAudioTool.ts
  • lib/prompts/getSystemPrompt.ts
  • lib/slack/getBotChannels.ts
  • lib/slack/getBotUserId.ts
  • lib/slack/getSlackUserInfo.ts
  • lib/spotify/getSpotifyFollowers.ts
  • lib/supabase/account_artist_ids/getAccountArtistIds.ts
  • lib/supabase/account_workspace_ids/getAccountWorkspaceIds.ts
  • lib/supabase/files/createFileRecord.ts
  • lib/supabase/files/selectFileByStorageKey.ts
  • lib/supabase/song_artists/insertSongArtists.ts
  • lib/supabase/storage/createSignedFileUrlByKey.ts
  • lib/supabase/storage/uploadFileByKey.ts
  • lib/transcribe/processAudioTranscription.ts
  • lib/transcribe/saveAudioToFiles.ts
  • lib/transcribe/saveTranscriptToFiles.ts
  • lib/transcribe/types.ts
  • lib/trigger/fetchTriggerRuns.ts
  • lib/trigger/triggerCreateContent.ts
  • lib/workspaces/createWorkspaceInDb.ts

* Authentication: x-api-key OR Authorization Bearer token required.
*
* @param request
* @param request - The incoming request with optional account_id query param
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Locate connector handlers:"
fd -i 'getConnectorsHandler.ts|authorizeConnectorHandler.ts|disconnectConnectorHandler.ts' lib

echo
echo "Check for account_id parsing/usages and auth context validation in those handlers:"
rg -n -C3 --type=ts '\baccount_id\b|searchParams\.get\("account_id"\)|validateAuthContext\(' lib/composio/connectors

Repository: recoupable/api

Length of output: 47897


Remove account_id parameter support across all connector endpoints (GET, POST, DELETE).

The current API design accepts optional account_id in query params (GET) and request bodies (POST, DELETE), which violates the authentication model. Per coding guidelines, account identity must derive solely from authentication context—never from client input. This applies to:

  • GET /api/connectors: account_id query param (documented in line 30)
  • POST /api/connectors/authorize: account_id body field (documented in line 49)
  • DELETE /api/connectors: account_id body field (documented in line 67–68)

The handlers currently accept account_id as optional with access checks, but the entire pattern conflicts with the guideline. Refactor to derive the account ID from validateAuthContext() alone. If multi-tenant access is needed, implement it through a separate, explicit authorization mechanism—not through optional client parameters.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/api/connectors/route.ts` at line 30, Remove all client-supplied
account_id handling in the connectors endpoints: stop reading account_id from
query or request bodies and derive the account ID exclusively from
validateAuthContext() for the GET /api/connectors handler, the POST
/api/connectors/authorize handler, and the DELETE /api/connectors handler.
Update the handlers (functions/methods that parse request.query.account_id,
request.body.account_id or similar) to use the accountId returned by
validateAuthContext(), remove any conditional access checks based on an optional
account_id input, and adjust related TypeScript types and JSDoc comments (the
param lines in the file) to reflect that account_id is not accepted from the
client. Ensure all authorization/enforcement still runs but now uses the
accountId from validateAuthContext() only.

Comment on lines +8 to 10
* @param period - The time window ("daily", "weekly", "monthly", or "all") to compute a cutoff for.
* @returns Unix timestamp in seconds representing the start of the period, or null for "all".
*/
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

@returns wording does not match current cutoff semantics.

At Line 14, the value is “current time minus period length,” not strictly the calendar “start of the period.” Please adjust wording (or change implementation) to avoid ambiguity.

📝 Suggested doc fix
- * `@returns` Unix timestamp in seconds representing the start of the period, or null for "all".
+ * `@returns` Unix timestamp in seconds computed as now minus the selected period, or null for "all".
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
* @param period - The time window ("daily", "weekly", "monthly", or "all") to compute a cutoff for.
* @returns Unix timestamp in seconds representing the start of the period, or null for "all".
*/
* `@param` period - The time window ("daily", "weekly", "monthly", or "all") to compute a cutoff for.
* `@returns` Unix timestamp in seconds computed as now minus the selected period, or null for "all".
*/
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/admins/slack/getCutoffTs.ts` around lines 8 - 10, The JSDoc `@returns` for
getCutoffTs is misleading — the function returns "current time minus the period
length" (a rolling cutoff), not the calendar start of the period; update the
comment in getCutoffTs to say: "Unix timestamp in seconds representing current
time minus the period length (rolling cutoff), or null for 'all'." Ensure the
updated wording appears where the `@returns` is declared to match the getCutoffTs
implementation.

* @param head - Branch to merge from (e.g. "test")
* @param base - Branch to merge into (e.g. "main")
* @param token - GitHub API token
* @returns An object with ok: true on success, or ok: false with a message on failure
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify unguarded JSON.parse usage in coding-agent merge helpers.
rg -n -C2 'JSON\.parse\(errorBody\)' --type=ts

Repository: recoupable/api

Length of output: 837


🏁 Script executed:

#!/bin/bash
# Check function signatures and return types for both merge functions
echo "=== mergeGithubBranch.ts ===" 
sed -n '1,30p' lib/coding-agent/mergeGithubBranch.ts | head -25

echo -e "\n=== mergeGithubPR.ts ===" 
sed -n '1,30p' lib/coding-agent/mergeGithubPR.ts | head -25

Repository: recoupable/api

Length of output: 1467


Unguarded JSON.parse in error paths violates return type contract.

Both mergeGithubBranch and mergeGithubPR document a deterministic return: { ok: true } | { ok: false, message: string }. However, JSON.parse(errorBody) at lines 51 (mergeGithubBranch.ts) and 47 (mergeGithubPR.ts) can throw if GitHub or an intermediary returns non-JSON, causing rejection instead of the promised failure object. This breaks the contract and violates the error handling requirement.

Wrap parsing in try-catch with a fallback message:

Proposed fix
  const errorBody = await response.text();
  console.error(
    `[coding-agent] ... ${response.status} ${errorBody}`,
  );
- const error = JSON.parse(errorBody);
- return { ok: false, message: error.message };
+ let message = `GitHub merge failed with status ${response.status}`;
+ try {
+   const error = JSON.parse(errorBody) as { message?: string };
+   if (error.message) message = error.message;
+ } catch {
+   if (errorBody.trim()) message = errorBody.trim();
+ }
+ return { ok: false, message };

Apply the same fix to both files.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/coding-agent/mergeGithubBranch.ts` at line 19, mergeGithubBranch and
mergeGithubPR currently call JSON.parse(errorBody) on error paths which can
throw and break the documented return contract; update both functions so the
JSON.parse(errorBody) is wrapped in a try-catch and never allowed to throw — on
parse success extract a meaningful message, on failure fall back to using the
raw errorBody or a generic message, then return { ok: false, message } so the
function always returns the documented union; locate the JSON.parse usage in
mergeGithubBranch and mergeGithubPR and implement this guarded parsing behavior.

Comment on lines +16 to +19
*
* @param request - The incoming Next.js request with the artist_account_id query param.
* @returns A NextResponse with an error if auth or validation fails,
* otherwise the validated account ID, artist account ID, and resolved artist slug.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Use a Zod-backed validator in this validate*.ts module.

The docs are improved, but the implementation still manually parses artist_account_id instead of validating through a Zod schema with inferred types. Please migrate this validator to the same schema-driven pattern used in other validate*.ts files.

As per coding guidelines lib/**/validate*.ts: “Use Zod for schema validation” and “Export inferred types for validated data”.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/content/validateGetContentValidateQuery.ts` around lines 16 - 19, Replace
the manual parsing of artist_account_id in the validateGetContentValidateQuery
module with a Zod-backed validator: define a Zod schema (e.g.,
GetContentQuerySchema) that validates the incoming query shape (including
artist_account_id as the required string/UUID pattern you expect), use
schema.parse or schema.safeParse inside validateGetContentValidateQuery to
validate and extract values, export the inferred type (e.g., type
GetContentQuery = z.infer<typeof GetContentQuerySchema>), and update the
function to return the typed validated data (account ID, artist_account_id,
resolved artist slug) or a NextResponse error on failure; reference the existing
validateGetContentValidateQuery function and export names when making these
changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant