Skip to content

feat: add PATCH /api/sandboxes/snapshot endpoint - #198

Merged
sweetmantech merged 2 commits into
testfrom
sweetmantech/myc-4130-api-filetree-patch-apisandboxessnapshot
Feb 3, 2026
Merged

feat: add PATCH /api/sandboxes/snapshot endpoint#198
sweetmantech merged 2 commits into
testfrom
sweetmantech/myc-4130-api-filetree-patch-apisandboxessnapshot

Conversation

@sweetmantech

@sweetmantechsweetmantech commented Feb 3, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Implements PATCH /api/sandboxes/snapshot endpoint following TDD red-green-refactor
  • Allows authenticated users to update their account's snapshot ID, which is used as the base environment when creating new sandboxes
  • Includes full test coverage (13 tests) for validator, handler, and Supabase function

Test plan

  • All 13 tests pass (pnpm test)
  • Lint passes on new files
  • Manual test: Send PATCH request with valid x-api-key and snapshotId body
  • Manual test: Verify 401 response without authentication
  • Manual test: Verify 400 response with missing/empty snapshotId

Summary by CodeRabbit

  • New Features
    • Added a new API endpoint for updating sandbox snapshots. The endpoint includes request validation and manages snapshot expiration with automatic lifecycle handling.

Implements TDD red-green-refactor for the snapshot update endpoint:
- validateSnapshotPatchBody: validates snapshotId in request body
- upsertAccountSnapshot: upserts snapshot record in account_snapshots table
- updateSnapshotPatchHandler: handles the PATCH request
- route.ts: exposes PATCH and OPTIONS at /api/sandboxes/snapshot
@vercel

vercelBot commented Feb 3, 2026

Copy link
Copy Markdown
Contributor

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

ProjectDeploymentActionsUpdated (UTC)
recoup-apiReadyReadyPreviewFeb 3, 2026 10:48pm

@coderabbitai

coderabbitaiBot commented Feb 3, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@sweetmantech has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 15 minutes and 2 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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.

📝 Walkthrough

Walkthrough

This pull request introduces a new PATCH endpoint for updating sandbox snapshots. The implementation includes request routing with CORS support, authentication and body validation, and database persistence of snapshot identifiers with expiration timestamps.

Changes

Cohort / File(s)Summary
API Route Handler
app/api/sandboxes/snapshot/route.ts
Implements OPTIONS (CORS preflight) and PATCH handlers; PATCH delegates to updateSnapshotPatchHandler for request processing.
Request Validation
lib/sandbox/validateSnapshotPatchBody.ts
Adds Zod schema for snapshot ID validation and async validator that checks authentication context and parses/validates request body; returns merged auth + validated data or error response.
Request Handler
lib/sandbox/updateSnapshotPatchHandler.ts
Processes validated PATCH requests; calls upsertAccountSnapshot and returns appropriate success or error responses with CORS headers.
Database Upsert
lib/supabase/account_snapshots/upsertAccountSnapshot.ts
Upserts snapshot record to account_snapshots table using account_id as conflict key; sets expiration timestamp one year in the future.

Sequence Diagram

sequenceDiagram
actor Client
participant Route as API Route<br/>(route.ts)
participant Validator as Validator<br/>(validateSnapshotPatchBody)
participant Handler as Handler<br/>(updateSnapshotPatchHandler)
participant DB as Database<br/>(Supabase)
Client->>Route: PATCH /api/sandboxes/snapshot
Route->>Validator: validateSnapshotPatchBody(request)
Validator->>Validator: Extract auth context
Validator->>Validator: Parse & validate body
alt Validation Success
Validator-->>Handler: Return validated data + auth
Handler->>DB: upsertAccountSnapshot
DB-->>Handler: Return snapshot record
Handler-->>Route: 200 { success: true, snapshotId }
Route-->>Client: 200 + CORS headers
else Validation Error
Validator-->>Route: 400 error response
Route-->>Client: 400 + CORS headers
end
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly Related PRs

Poem

🎁 Snapshots now flourish in digital repose,
Where sandboxes rest and their moments compose,
Through validation's gate and CORS so refined,
The database upserts leave time intertwined! ✨

🚥 Pre-merge checks | ✅ 1
✅ Passed checks (1 passed)
Check nameStatusExplanation
Solid & Clean Code✅ PassedCode demonstrates strong SOLID adherence with clear separation of concerns across modules, appropriate handler delegation, centralized utilities, reasonable function sizes (42-50 lines), explicit error handling, and TypeScript type safety.

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

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch sweetmantech/myc-4130-api-filetree-patch-apisandboxessnapshot

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.

@github-actions

github-actionsBot commented Feb 3, 2026

Copy link
Copy Markdown

Braintrust eval report

Catalog Opportunity Analysis Evaluation (HEAD-1770158832)

ScoreAverageImprovementsRegressions
Catalog_availability0% (+0pp)--
Llm_calls0 (+0)--
Tool_calls0 (+0)--
Errors0 (+0)--
Llm_errors0 (+0)--
Tool_errors0 (+0)--
Prompt_tokens0tok (+0tok)--
Prompt_cached_tokens0tok (+0tok)--
Prompt_cache_creation_tokens0tok (+0tok)--
Completion_tokens0tok (+0tok)--
Completion_reasoning_tokens0tok (+0tok)--
Total_tokens0tok (+0tok)--
Duration1.3s (+0.11s)1 🟢4 🔴

Catalog Songs Count Evaluation (HEAD-1770158832)

ScoreAverageImprovementsRegressions
AnswerCorrectness17.6% (+0pp)--
Factuality66.7% (+0pp)--
Llm_calls4 (+0)--
Tool_calls0 (+0)--
Errors0 (+0)--
Llm_errors0 (+0)--
Tool_errors0 (+0)--
Prompt_tokens0tok (+0tok)--
Prompt_cached_tokens0tok (+0tok)--
Prompt_cache_creation_tokens0tok (+0tok)--
Completion_tokens0tok (+0tok)--
Completion_reasoning_tokens0tok (+0tok)--
Completion_accepted_prediction_tokens0tok (+0tok)--
Completion_rejected_prediction_tokens0tok (+0tok)--
Completion_audio_tokens0tok (+0tok)--
Total_tokens0tok (+0tok)--
Duration1.22s (+0.05s)1 🟢2 🔴

First Week Album Sales Evaluation (HEAD-1770158832)

ScoreAverageImprovementsRegressions
Factuality50% (+0pp)--
Llm_calls1 (+0)--
Tool_calls0 (+0)--
Errors0 (+0)--
Llm_errors0 (+0)--
Tool_errors0 (+0)--
Prompt_tokens0tok (+0tok)--
Prompt_cached_tokens0tok (+0tok)--
Prompt_cache_creation_tokens0tok (+0tok)--
Completion_tokens0tok (+0tok)--
Completion_reasoning_tokens0tok (+0tok)--
Completion_accepted_prediction_tokens0tok (+0tok)--
Completion_rejected_prediction_tokens0tok (+0tok)--
Completion_audio_tokens0tok (+0tok)--
Total_tokens0tok (+0tok)--
Duration1.23s (+0.17s)1 🟢3 🔴

Memory & Storage Tools Evaluation (HEAD-1770158832)

ScoreAverageImprovementsRegressions
Tools_called0% (+0pp)--
Llm_calls0 (+0)--
Tool_calls0 (+0)--
Errors0 (+0)--
Llm_errors0 (+0)--
Tool_errors0 (+0)--
Prompt_tokens0tok (+0tok)--
Prompt_cached_tokens0tok (+0tok)--
Prompt_cache_creation_tokens0tok (+0tok)--
Completion_tokens0tok (+0tok)--
Completion_reasoning_tokens0tok (+0tok)--
Total_tokens0tok (+0tok)--
Duration1.08s (-0.46s)1 🟢-

Monthly Listeners Tracking Evaluation (HEAD-1770158832)

ScoreAverageImprovementsRegressions
AnswerSimilarity70% (+0pp)--
Llm_calls2 (+0)--
Tool_calls0 (+0)--
Errors0 (+0)--
Llm_errors0 (+0)--
Tool_errors0 (+0)--
Prompt_tokens0tok (+0tok)--
Prompt_cached_tokens0tok (+0tok)--
Prompt_cache_creation_tokens0tok (+0tok)--
Completion_tokens0tok (+0tok)--
Completion_reasoning_tokens0tok (+0tok)--
Total_tokens0tok (+0tok)--
Duration1.29s (+0.16s)1 🟢4 🔴

Search Web Tool Evaluation (HEAD-1770158832)

ScoreAverageImprovementsRegressions
AnswerCorrectness17.2% (+0pp)--
Llm_calls3 (+0)--
Tool_calls0 (+0)--
Errors0 (+0)--
Llm_errors0 (+0)--
Tool_errors0 (+0)--
Prompt_tokens0tok (+0tok)--
Prompt_cached_tokens0tok (+0tok)--
Prompt_cache_creation_tokens0tok (+0tok)--
Completion_tokens0tok (+0tok)--
Completion_reasoning_tokens0tok (+0tok)--
Completion_accepted_prediction_tokens0tok (+0tok)--
Completion_rejected_prediction_tokens0tok (+0tok)--
Completion_audio_tokens0tok (+0tok)--
Total_tokens0tok (+0tok)--
Duration1.23s (+0.09s)3 🟢8 🔴

Social Scraping Evaluation (HEAD-1770158832)

ScoreAverageImprovementsRegressions
Tools_called0% (+0pp)--
Llm_calls0 (+0)--
Tool_calls0 (+0)--
Errors0 (+0)--
Llm_errors0 (+0)--
Tool_errors0 (+0)--
Prompt_tokens0tok (+0tok)--
Prompt_cached_tokens0tok (+0tok)--
Prompt_cache_creation_tokens0tok (+0tok)--
Completion_tokens0tok (+0tok)--
Completion_reasoning_tokens0tok (+0tok)--
Total_tokens0tok (+0tok)--
Duration1.14s (-0.18s)4 🟢2 🔴

Spotify Followers Evaluation (HEAD-1770158832)

ScoreAverageImprovementsRegressions
Llm_calls3 (+0)--
Tool_calls0 (+0)--
Errors2 (+0)--
Llm_errors1 (+0)--
Tool_errors0 (+0)--
Prompt_tokens0tok (+0tok)--
Prompt_cached_tokens0tok (+0tok)--
Prompt_cache_creation_tokens0tok (+0tok)--
Completion_tokens0tok (+0tok)--
Completion_reasoning_tokens0tok (+0tok)--
Total_tokens0tok (+0tok)--
Duration1.02s (-0.16s)5 🟢-

Spotify Tools Evaluation (HEAD-1770158832)

ScoreAverageImprovementsRegressions
Tools_called0% (+0pp)--
Llm_calls0 (+0)--
Tool_calls0 (+0)--
Errors0 (+0)--
Llm_errors0 (+0)--
Tool_errors0 (+0)--
Prompt_tokens0tok (+0tok)--
Prompt_cached_tokens0tok (+0tok)--
Prompt_cache_creation_tokens0tok (+0tok)--
Completion_tokens0tok (+0tok)--
Completion_reasoning_tokens0tok (+0tok)--
Total_tokens0tok (+0tok)--
Duration1.29s (+0.36s)-2 🔴

TikTok Analytics Questions Evaluation (HEAD-1770158832)

ScoreAverageImprovementsRegressions
Question_answered0% (+0pp)--
Llm_calls0 (+0)--
Tool_calls0 (+0)--
Errors0 (+0)--
Llm_errors0 (+0)--
Tool_errors0 (+0)--
Prompt_tokens0tok (+0tok)--
Prompt_cached_tokens0tok (+0tok)--
Prompt_cache_creation_tokens0tok (+0tok)--
Completion_tokens0tok (+0tok)--
Completion_reasoning_tokens0tok (+0tok)--
Total_tokens0tok (+0tok)--
Duration1.33s (+0.02s)1 🟢1 🔴

Moves the PATCH handler from /api/sandboxes/snapshot to /api/sandboxes
to match the API specification. The endpoint is now:
- PATCH /api/sandboxes (not /api/sandboxes/snapshot)
@sweetmantech
sweetmantech merged commit 9afe50a into testFeb 3, 2026
5 checks passed
@sweetmantech
sweetmantech deleted the sweetmantech/myc-4130-api-filetree-patch-apisandboxessnapshot branch February 3, 2026 22:53
Sign up for freeto 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

@sweetmantech