feat(artists): account_id override for DELETE /api/artists/{id}

Merged
SW
4mo ago
+78-2

Implements the first flagged endpoint in the admin account-override work: DELETE /api/artists/{id} now accepts an optional account_id override.

What changed

lib/artists/validateDeleteArtistRequest.ts:

  • Parses an optional account_id (UUID) from the request body via safeParseJson + a Zod schema.
  • Threads it into validateAuthContext(request, { accountId }) — the single chokepoint that authorizes the override (validateAccountIdOverride → canAccessAccount, which already grants Recoup org members universal access).
  • Uses the resolved account for the existing checkAccountArtistAccess check.
  • Returns 400 for a malformed account_id.

Mirrors the override pattern already shipped on POST /api/artists. No special admin header — auth (who you are) stays separate from authorization (what you can access).

TDD

  • Added two failing tests first (override threaded to validateAuthContext + resolved-account access; 400 for invalid UUID) and updated the existing auth-error assertion to the new call signature — confirmed RED, then GREEN.
  • Full lib/artists suite: 95 passed. Lint clean on changed files.
  • (Pre-existing, unrelated tsc errors live in lib/tasks / lib/trigger test files — not touched here.)

Done when

  • Admin calls DELETE /api/artists/{id} with { "account_id": "<target>" } → artist removed.
  • Non-admin passing an inaccessible account_id → still 403.

(Verified against the preview deployment in a follow-up comment.)

Merge order

Docs contract lands first: recoupable/docs#247 → then this PR to test.

Tracking issue: recoupable/chat#1811


Summary by cubic

Adds an optional account_id override to DELETE /api/artists/{id} so admins and org members can delete an artist in another account’s context. Supports the admin account-override work in chat#1811 and keeps unauthorized deletes blocked.

  • New Features
    • Parse optional account_id (UUID) from JSON body; return 400 if invalid.
    • Pass override to validateAuthContext(request, { accountId }) and use the resolved account for checkAccountArtistAccess.
    • Non-admins using an inaccessible account_id still get 403; mirrors POST /api/artists.