# TASKS — Carrier Dispatch "Create Trip" wizard (`/cd-new-trip`)

Source: Nash's feedback, 2026-10-01, plus his answers to four questions the same day. Scope: the Carrier Dispatch new-trip page only (`src/app/cd-new-trip/`, its server action in `src/app/trips/new/actions.ts`, `next.config.ts`). No change to the broker new-trip page, public intake, trip documents or Buy More Permits.

## What exists (inspected 2026-10-01)

| Area | Where | Notes |
|---|---|---|
| Two-step wizard | `src/app/cd-new-trip/carrier-wizard.tsx` (467 lines) | Step 1 "Trip info": rate-con drop zone → `POST /api/extract/rate-con` fills **editable fields on step 1** (origin, destination, commodity, unit number, pickup, delivery) → permit choice (own / Synchron) + permit drop zone. Step 2 "People": invites. "Create trip" submits the server action `createCarrierTrip`. |
| Reader | `src/app/api/extract/rate-con/route.ts` → `extractRateConfirmation` (`src/lib/adapters/flask.ts:229`) | Returns origin, destination, commodity, carrier_name, broker_name, pickup/delivery dates, length/width/height (inches), weight (lbs). The wizard only used six of them. |
| Server action | `createCarrierTrip` (`actions.ts:118+`) | Zod schema has origin, destination, commodity, unit number, dates, permit path, invites. Per-file check 25 MB. Stores the rate con and permits on S3, re-runs the reader with trip context (backend side effects), queues permits, emails Synchron on the Synchron path, invites, Auto-Participants. |
| The 1 MB failure | framework default | Nothing in the app says 1 MB. `createCarrierTrip` is a Server Action and Next.js caps a Server Action request body at 1 MB by default (`serverActions.bodySizeLimit`); the dev log shows `Body exceeded 1 MB limit.` The cap is on the **whole submit** (rate con + every permit + fields), not per file. |
| Trip columns | `trips` | `origin, destination, commodity, carrier_name, unit_number, pickup_date, delivery_date, load_length_in, load_width_in, load_height_in, load_weight_lbs`. There is **no broker name column** on `trips`. |

## Decisions (Nash, 2026-10-01)

| # | Decision |
|---|---|
| W1 | **Step 1 = rate confirmation + permit choice (+ permit files when "I have my own permits").** Dropping the rate con starts the reader immediately, so it works while the dispatcher picks the permit path. |
| W2 | **Step 2 = trip information, pre-filled from the rate confirmation, then people, then Create trip.** Everything the reader returns is shown and editable: origin, destination, commodity, pickup and delivery dates, load length / width / height / weight, carrier name, broker name; plus the truck/unit number typed by the dispatcher. |
| W3 | **If the reader is still running when step 2 opens, step 2 shows a "Reading your rate confirmation…" banner with empty fields and fills them in when the reader finishes.** Typed values are never overwritten. Create trip waits for the reader unless the dispatcher chooses to continue without it. |
| W4 | **Per-file limit stays 1 MB** (asked twice, confirmed twice). The browser checks each file and says which file is over the limit before anything is sent; the server checks the same. The submit cap is raised so a rate con plus several permits of up to 1 MB each go through in one request. |

## Tasks

### Task 1 — Restructure the wizard (`carrier-wizard.tsx`)
- Progress pills: "1 · Rate confirmation & permits" → "2 · Trip info & people".
- Step 1: rate-con drop zone (unchanged look; reader starts on drop), permit choice cards, permit drop zone for the upload path. "Next: confirm trip info →" is enabled as soon as a rate con is attached.
- Step 2: Card "Trip information" with the W3 banner while reading; fields: Origin*, Destination*, Commodity*, Pickup date, Delivery date, Truck / unit number, Carrier, Broker (read-only, from the rate con — see Task 2), Length (in), Width (in), Height (in), Weight (lbs). Then the existing "Invite drivers and brokers" card. Buttons: "← Back", "Create trip" (disabled while reading; a "Continue without waiting" link enables it).
- Reader result fills every field the reader returned, only where the field is still empty.
- Client-side file check (W4): a file over 1 MB is refused with "`name` is `N` MB — files must be 1 MB or smaller." and is not added.

### Task 2 — Server action accepts the confirmed fields (`actions.ts`)
- Schema gains `carrier_name`, `load_length_in`, `load_width_in`, `load_height_in`, `load_weight_lbs` (optional numbers in inches / lbs). They are written on the trip insert; `carrier_name` falls back to the dispatcher's company as today.
- Broker name is **not** persisted: `trips` has no column for it and no migration is in scope. It is shown on step 2 for confirmation only.
- Per-file check becomes 1 MB (W4) for the rate con and each permit, with a clear error.

### Task 3 — Submit cap (`next.config.ts`)
- `experimental.serverActions.bodySizeLimit = '25mb'`: one rate con plus up to ~20 permits of ≤1 MB each, with multipart overhead. Documented in the config comment.

### Task 4 — Tests
- `tests/upload-limits.test.ts`: the per-file rule and its message (`src/lib/domain/upload-limits.ts`).

## Out of scope
- Raising the per-file limit (W4). Other upload paths. Storing the broker name on the trip.
