mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-09-29 16:24:22 +10:00
* feat(deploy): support Vercel Hobby alongside Docker * fix(deploy): include PDFKit runtime font assets * docs(deploy): document Vercel and Docker setup * docs(deploy): record storage persistence checks * refactor(deploy): drop scheduled staging cleanup Staging uploads are deleted after finalization and expired ones are swept on each new upload, so the Vercel cron job, its route, and CRON_SECRET are no longer needed. The Deploy with Vercel wizard now asks for two secrets. * docs(deploy): restructure Vercel guides Split the Vercel page into a how-to with its environment reference, move the large RPC staging protocol to an API reference page, and move CI deployment checks to the contributing section. Point Deploy with Vercel buttons at main. * chore: remove agent planning records and fix web app description Delete superpowers plans/specs, ADRs, issue plans, execution briefs, domain context maps, and Europass research. Describe apps/web as a TanStack Router SPA served by apps/server. * refactor(deploy): simplify Vercel support code - Share one Redis client and key namespace through @reactive-resume/db/redis for API and auth instead of a second auth-only client. - Drop the auth seeding retry; the provider already treats concurrent inserts as no-ops and deployment preparation seeds before runtime. - Detect staging support from POST /api/storage/stage (404 on Docker) instead of a separate GET probe. - Read staged bodies directly; the signed upload already caps their size. - Close per-subscription Redis connections with disconnect() alone. - Check Blob health with one list call instead of write/read/delete. - Remove redundant tsdown onlyBundle list, dead namespace fallbacks, and the conditional spread in the health status. * fix(deploy): heal stopped runs with dead owners and keep auth up without Redis - Run owners refresh a Redis heartbeat until they release their claim. Stop requests reap the run immediately when the owner has stopped heartbeating, instead of leaving the thread blocked until the 15-minute TTL reaper. - Auth and oRPC rate limiters fall back to per-instance memory limits when Redis errors, instead of rejecting every login or failing requests. * ci: allow esbuild build for Vercel CLI and register deployment deps with knip pnpm 12 fails dlx installs with ignored build scripts, so allow esbuild explicitly. The server bundle keeps @vercel/blob, ioredis, and jose external, and api/index.mjs is the Vercel Function entry. * fix(web): send buffered RPC bodies instead of teed streams Reading a request clone turned the original body into a stream, which browsers send without inspectable request data and which needs duplex mode. Send the already buffered Blob for direct requests. * fix(web): send direct RPC bodies as bytes Blob request bodies are sent as data pipes, so browser tooling cannot inspect them. Buffer the original request as an ArrayBuffer and send those bytes; this restores the e2e save assertions that match on request data.
88 lines
3.5 KiB
Plaintext
88 lines
3.5 KiB
Plaintext
---
|
|
title: "Large RPC requests"
|
|
description: "Reference for the staged-body protocol that lets RPC requests larger than the hosting request-body limit reach Reactive Resume on Vercel."
|
|
---
|
|
|
|
Vercel limits Function request bodies to 4.5 MB. On Vercel installations, RPC requests larger than that are uploaded to private Blob staging first. The server then restores the original request and runs it with the normal authorization, validation, and quota checks.
|
|
|
|
The web app uses this protocol automatically for request bodies of 3 MiB or more. Docker installations do not need it.
|
|
|
|
## Scope
|
|
|
|
| Item | Value |
|
|
| --- | --- |
|
|
| Applies to | `POST /api/rpc/...` only |
|
|
| Does not apply to | REST (`/api/openapi`) and MCP. Their bodies stay subject to the 4.5 MB limit. |
|
|
| Maximum staged size | 160 MiB of serialized request bytes, including base64 and RPC framing |
|
|
| Reference lifetime | Upload URL: 5 minutes. Staging reference: 10 minutes. |
|
|
| Use count | One. A reference is consumed when a finalization request passes the user and path checks, whether the RPC call then succeeds or fails. |
|
|
| Rate limit | 30 staging requests per user per minute |
|
|
|
|
## Protocol
|
|
|
|
### 1. Prepare
|
|
|
|
```http
|
|
POST /api/storage/stage
|
|
Content-Type: application/json
|
|
x-api-key: YOUR_API_KEY
|
|
|
|
{ "path": "/api/rpc/storage/uploadFile", "contentType": "multipart/form-data; boundary=...", "size": 10485861 }
|
|
```
|
|
|
|
| Field | Type | Description |
|
|
| --- | --- | --- |
|
|
| `path` | string | Pathname and query string of the original RPC request. Must start with `/api/rpc`. |
|
|
| `contentType` | string | `Content-Type` header of the original request, including any multipart boundary. |
|
|
| `size` | integer | Exact byte length of the serialized original body. |
|
|
|
|
Authenticate with a session cookie, an `x-api-key` header, or an OAuth bearer token. Browsers must send an `Origin` header that matches the application origin.
|
|
|
|
Response `200`:
|
|
|
|
```json
|
|
{ "id": "3f2b9c1e-6a0d-4a57-9d0a-3c1f7b8e2d44", "url": "https://..." }
|
|
```
|
|
|
|
The endpoint returns `404` when the installation does not support staging, for example on Docker. Send the original request unchanged in that case.
|
|
|
|
### 2. Upload
|
|
|
|
```http
|
|
PUT <url from step 1>
|
|
Content-Type: application/octet-stream
|
|
|
|
<exact serialized body bytes>
|
|
```
|
|
|
|
Do not send application credentials to this URL. The body must be exactly `size` bytes.
|
|
|
|
### 3. Finalize
|
|
|
|
Send the original request with an empty body and the staging reference header:
|
|
|
|
```http
|
|
POST /api/rpc/storage/uploadFile
|
|
x-api-key: YOUR_API_KEY
|
|
x-resume-staged-body: 3f2b9c1e-6a0d-4a57-9d0a-3c1f7b8e2d44
|
|
```
|
|
|
|
Use the same `path` and the same user as in step 1. The server replaces the body with the staged bytes, sets `Content-Type` to the stored `contentType`, and returns the normal RPC response.
|
|
|
|
## Errors
|
|
|
|
| Status | Step | Cause |
|
|
| --- | --- | --- |
|
|
| `400` | Prepare | Invalid JSON, `path` outside `/api/rpc`, or `size` above the maximum. |
|
|
| `400` | Finalize | Malformed reference, non-`POST` request, or staged object missing. |
|
|
| `401` | Prepare, finalize | Not authenticated, or `Origin` does not match. |
|
|
| `403` | Finalize | Reference belongs to another user or another path. |
|
|
| `404` | Prepare | Staging not available on this installation. |
|
|
| `409` | Finalize | Reference used by a parallel request. |
|
|
| `410` | Finalize | Reference expired or already used. |
|
|
| `413` | Finalize | Uploaded byte count differs from `size`. |
|
|
| `429` | Prepare | Rate limit exceeded. |
|
|
| `503` | Prepare | Redis unavailable. |
|
|
|
|
A reference cannot be retried. If a finalization response is lost, check the result of the mutation before you stage and send it again.
|