Skip to content

Promote test → main#565

Merged
sweetmantech merged 11 commits into
mainfrom
test
May 14, 2026
Merged

Promote test → main#565
sweetmantech merged 11 commits into
mainfrom
test

Conversation

@sweetmantech
Copy link
Copy Markdown
Contributor

@sweetmantech sweetmantech commented May 14, 2026

Routine promotion of test to main.

Notable items:

  • feat(api): add PATCH handler for updating session details #546 PATCH /api/sessions/{sessionId} — manually smoke-tested on preview (17 cases, see PR comment); two doc-divergences flagged (path on validation 400s, message vs error on bogus-Bearer 401)
  • selectSessions now returns null on DB error so callers can distinguish "DB down" from "no rows" (PATCH/GET handlers return 500)

This will be back-synced into test after merge.


Summary by cubic

Promotes test to main with a new PATCH session endpoint and stronger DB error handling across session APIs and sandbox workflows. Adds support to update session title, status, and optional line counters.

  • New Features

    • Added PATCH /api/sessions/{sessionId} to update title, status (running|completed|failed|archived), linesAdded, and linesRemoved; all optional.
    • Auth via Privy Bearer token or x-api-key. Returns 404 when missing, 403 when not owned, 400 on malformed/invalid body, and 200 with no-op when body has no updates.
  • Bug Fixes

    • selectSessions now returns null on DB errors; GET/PATCH handlers return 500 instead of treating as no rows.
    • Updated workflows and sandbox helpers to handle DB failures and log clearer reasons.
    • Expanded tests for GET/PATCH: DB error paths, malformed JSON, authorization, and happy cases.
    • Known response differences from docs: validation 400s include a path field; bad Bearer 401 uses error instead of message.

Written for commit 3cb13d6. Summary will update on new commits.

Summary by CodeRabbit

  • New Features

    • Added support for updating session details including title, status, and line metrics via API.
  • Bug Fixes

    • Improved error handling and reliability of session operations by adding defensive checks for database query failures and missing data.

Review Change Stack

ahmednahima0-beep and others added 11 commits May 11, 2026 02:05
- Implemented a new PATCH endpoint for updating a session's title or status, allowing optional fields to be modified.
- Authenticates requests using a Privy Bearer token or x-api-key header.
- Added comprehensive tests for the PATCH handler, covering scenarios such as unauthorized access, session not found, and successful updates.

This enhancement improves the API's functionality by enabling users to modify session details dynamically.
- Implemented tests for the GET and PATCH session API endpoints to handle scenarios where the database returns an error, ensuring a 500 status response with appropriate error messages.
- Updated the `selectSessions` function to return `null` on database errors, allowing for better error handling in the API responses.
- Enhanced existing tests to verify that the API correctly responds to internal server errors, improving overall robustness and reliability of the session management functionality.
- Updated the `selectSessions` function calls in `clearLifecycleRunIdIfOwned`, `computeLifecycleWakeDecision`, and `evaluateSandboxLifecycle` to handle potential database errors more gracefully.
- Added console error logging in `clearLifecycleRunIdIfOwned` for better debugging.
- Enhanced return values in `computeLifecycleWakeDecision` and `evaluateSandboxLifecycle` to provide clearer failure reasons when session queries fail.

These changes enhance the robustness of session management by ensuring that errors are properly logged and handled.
- Enhanced error handling in the `evaluateSandboxLifecycle` function by ensuring that an error is thrown with a clear message when session refresh fails during lifecycle extension checks. This change improves the robustness of session management by providing better feedback in case of failures.
…nal status values and line counters

- Updated the API documentation to reflect the new optional fields for line counters and expanded status options (running, completed, failed, archived).
- Modified the patchSessionByIdHandler to handle updates for linesAdded and linesRemoved, returning a 200 status when no updates are provided.
- Added tests to ensure correct handling of new status values and line counter mappings in the session update process.
* fix(stripe): fall back to Checkout for any card-level off-session error

Surfaced during open-agents preview UI testing of #559: an off-session
charge against an account that has a card on file but where Stripe
returned a non-authentication_required error (declined / fraud check /
expired / invalid request) bubbled out as a 500 instead of falling
through to Checkout.

Before: only StripeCardError with code === "authentication_required"
returned kind: "requires_action". Everything else rethrew → handler
returned 500 → UI showed "Couldn't create a checkout session".

After: any StripeCardError or StripeInvalidRequestError returns
kind: "requires_action" so the caller falls back to a Stripe Checkout
Session — the customer can update the card, complete 3DS, or pick a
different payment method interactively. Only genuinely unexpected
errors (network, our own bugs) still bubble as 500.

Tests: existing 9 cases plus a parameterized check across 4 common
card error codes plus an InvalidRequestError case.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(stripe): surface Stripe decline reason in the API response

Per real-world finding: when an off-session charge fails with
insufficient_funds / card_declined / expired_card / etc., the API was
silently falling through to Checkout with no signal of why. UI and
LLM-driven callers couldn't tell their human "your card has
insufficient funds" — they just saw a new Checkout URL.

Adds optional declineReason to the Checkout-fallback response shape:

  { id: "cs_…", url: "…",
    declineReason: {
      code: "card_declined",           // Stripe error code
      declineCode: "insufficient_funds", // Stripe decline_code on card errors
      message: "Your card has insufficient funds."
    } }

declineReason is omitted when fallback is from no_payment_method (no
prior off-session attempt was made), so fresh users still see the
clean { id, url } shape.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(stripe): narrow Stripe errors via instanceof, drop ad-hoc cast

DRY: reuse Stripe SDK's typed error classes (StripeCardError /
StripeInvalidRequestError) instead of defining our own structural type
to read `type`, `code`, `decline_code`, `message`. TypeScript narrows
each branch automatically; `decline_code` is only accessed on the
StripeCardError branch where the SDK guarantees it.

Tests updated to construct real Stripe error instances with the
StripeCardError / StripeInvalidRequestError constructors so the
`instanceof` path is what's exercised — the previous plain-object
fixtures relied on duck-typing that no longer matches the impl.

Addresses CodeRabbit nitpick on PR #561.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…d JSON body

- Added a new utility function to read and validate the JSON body of PATCH requests, returning an empty object for empty bodies and a 400 error for malformed JSON.
- Updated the test suite to include a case for handling malformed JSON, ensuring the API responds correctly with a 400 status and an appropriate error message.
- Adjusted the validation logic in `validatePatchSessionBody` to utilize the new JSON reading function, improving error handling for invalid input.
feat(api): add PATCH handler for updating session details
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 14, 2026

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

Project Deployment Actions Updated (UTC)
api Ready Ready Preview May 14, 2026 0:49am

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 14, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 37fb1446-d566-4295-99dd-e12c7442c2e0

📥 Commits

Reviewing files that changed from the base of the PR and between 83b201b and 3cb13d6.

⛔ Files ignored due to path filters (1)
  • app/api/sessions/[sessionId]/__tests__/route.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by app/**
📒 Files selected for processing (15)
  • app/api/sessions/[sessionId]/route.ts
  • app/workflows/clearLifecycleRunIdIfOwned.ts
  • app/workflows/computeLifecycleWakeDecision.ts
  • lib/sandbox/createSandboxHandler.ts
  • lib/sandbox/evaluateSandboxLifecycle.ts
  • lib/sandbox/getSandboxStatusHandler.ts
  • lib/sandbox/reclaimStaleLease.ts
  • lib/sandbox/runKick.ts
  • lib/sandbox/validateSandboxReconnectRequest.ts
  • lib/sandbox/wasLifecycleTimingExtended.ts
  • lib/sessions/getSessionByIdHandler.ts
  • lib/sessions/patchSessionByIdHandler.ts
  • lib/sessions/resolveSessionTitle.ts
  • lib/sessions/validatePatchSessionBody.ts
  • lib/supabase/sessions/selectSessions.ts

📝 Walkthrough

Walkthrough

The PR implements a new PATCH /api/sessions/{sessionId} endpoint to update session fields (title, status, line counters) and refactors selectSessions to return null on database errors, requiring defensive null-checks across session, sandbox, and workflow handlers to distinguish query failures from empty results.

Changes

Session PATCH & Error-Handling Contract Propagation

Layer / File(s) Summary
selectSessions return type and null-on-error contract
lib/supabase/sessions/selectSessions.ts
Updated selectSessions to return null when Supabase queries fail (error present or exception thrown), preserving empty-array behavior for successful but empty results. Exported signature changes from Promise<Tables<"sessions">[]> to Promise<Tables<"sessions">[] | null>, with updated JSDoc.
PATCH request validation and schema
lib/sessions/validatePatchSessionBody.ts
Introduced validatePatchSessionBody for PATCH /api/sessions/{sessionId} requests with a private body reader handling empty/whitespace bodies as {}, JSON parsing, and a Zod schema for optional fields (title, status, linesAdded, linesRemoved). Exports PatchSessionBody type and ValidatedPatchSessionRequest interface.
PATCH handler implementation and route wiring
lib/sessions/patchSessionByIdHandler.ts, app/api/sessions/[sessionId]/route.ts
Implemented patchSessionByIdHandler with request/body validation, ownership checks via account_id, 404 on missing session, optional no-op response when no fields provided, partial updates via updateSession, and standardized JSON responses with CORS headers. Route handler in [sessionId]/route.ts imports and delegates to patchSessionByIdHandler.
GET handler and direct consumer null-safety
lib/sessions/getSessionByIdHandler.ts, lib/sessions/resolveSessionTitle.ts
Updated getSessionByIdHandler to handle selectSessions returning null, responding with 500 "Internal server error". Updated resolveSessionTitle to default selectSessions result to empty array via nullish coalescing.
Sandbox and workflow defensive null-checks
app/workflows/clearLifecycleRunIdIfOwned.ts, app/workflows/computeLifecycleWakeDecision.ts, lib/sandbox/createSandboxHandler.ts, lib/sandbox/evaluateSandboxLifecycle.ts, lib/sandbox/getSandboxStatusHandler.ts, lib/sandbox/reclaimStaleLease.ts, lib/sandbox/runKick.ts, lib/sandbox/validateSandboxReconnectRequest.ts, lib/sandbox/wasLifecycleTimingExtended.ts
Propagated null-safe session lookup pattern: each function now defaults selectSessions result to empty array via ?? [], explicitly checks for null/falsy rows and returns early with error reason, or throws on missing re-fetched sessions to trigger catch-block error handling.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • recoupable/api#546: Closely matches this PR by adding the same PATCH /api/sessions/{sessionId} handler and propagating selectSessions null-on-error contract through session/workflow/sandbox code.
  • recoupable/api#514: Overlaps on extending app/api/sessions/[sessionId]/route.ts and updating lib/sessions/getSessionByIdHandler.ts with the same null-handling logic.
  • recoupable/api#535: Both PRs modify lib/sandbox/getSandboxStatusHandler.ts for safer session row fetching with the new selectSessions contract.

Poem

🔧 A PATCH arrives to mend the sessions well,
With null-safe guards where queries fall and quell,
From sandbox floors to workflow threads above,
Each handler now checks what it has—or thereof! 🎯

✨ 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 test

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.

@sweetmantech sweetmantech merged commit ffd627f into main May 14, 2026
6 of 7 checks passed
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.

2 participants