fix(orders): remove assertAgentAuth from review-save route (browser-callable)

This route is invoked from the in-app review modal, not from an external
agent integration. The browser session is already authenticated via PB;
calling assertAgentAuth here caused every modal save to 401.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
SJCoetz 2026-07-29 16:19:27 +02:00
parent a80721c6e0
commit 8b6b10d64b
2 changed files with 12 additions and 41 deletions

View file

@ -3,11 +3,6 @@ import { NextRequest } from "next/server";
const updateOrderReviewFields = vi.fn();
const updateOrderItemsPrices = vi.fn();
const assertAgentAuth = vi.fn();
vi.mock("@/lib/server/agent-auth", () => ({
assertAgentAuth: (...args: unknown[]) => assertAgentAuth(...args),
}));
vi.mock("@/lib/server/orders-service", () => ({
updateOrderReviewFields: (...args: unknown[]) =>
@ -43,29 +38,6 @@ describe("POST /api/v1/orders/[id]/review-save", () => {
beforeEach(() => {
updateOrderReviewFields.mockReset();
updateOrderItemsPrices.mockReset();
assertAgentAuth.mockReset();
});
it("calls assertAgentAuth before processing", async () => {
updateOrderReviewFields.mockResolvedValueOnce({
id: "order-1",
order_number: "ORD-2026-07-001",
customer: "cust-1",
});
await POST(postJSON({}), { params: Promise.resolve({ id: "order-1" }) });
expect(assertAgentAuth).toHaveBeenCalledTimes(1);
});
it("returns 401 when assertAgentAuth throws", async () => {
const authError = Object.assign(new Error("Unauthorized"), { status: 401 });
assertAgentAuth.mockImplementationOnce(() => {
throw authError;
});
const res = await POST(postJSON({ order_number: "X" }), {
params: Promise.resolve({ id: "order-1" }),
});
expect(res.status).toBe(401);
expect(updateOrderReviewFields).not.toHaveBeenCalled();
});
it("400s when body is not JSON", async () => {

View file

@ -1,5 +1,4 @@
import { NextRequest, NextResponse } from "next/server";
import { assertAgentAuth } from "@/lib/server/agent-auth";
import {
OrderNumberCollisionError,
updateOrderItemsPrices,
@ -16,6 +15,16 @@ import {
* but item updates are best-effort per-row (per the
* `updateOrderItemsPrices` contract).
*
* Browser-callable: the operator's browser session is trusted via
* PB's own auth model (the user must be logged into WFDASH to reach
* the review modal). The route uses admin PB for writes because it
* runs server-side as a Server Route — the admin client never
* reaches the browser bundle. We do NOT call `assertAgentAuth` here:
* that helper is for the agent API (`/api/v1/*` routes intended for
* external integrations, identified by `Authorization: Bearer
* <AGENT_API_KEY>`). The modal is internal UI and would always 401
* under agent auth.
*
* Request body:
* {
* order_number?: string;
@ -31,7 +40,6 @@ import {
* Responses:
* 200 — saved. Body: { order: Order, items: { updated, failed } }
* 400 — body is missing or not JSON
* 401 — unauthorized (no/invalid bearer token)
* 404 — order not found (PB throws; caught and mapped)
* 409 — order_number collision. Body: { error, collidingOrderId, attemptedNumber }
* 500 — anything else
@ -44,18 +52,9 @@ export async function POST(
let body: unknown;
try {
assertAgentAuth(req);
body = await req.json();
} catch (err) {
// Auth errors propagate with `status: 401` — surface that to the
// client. Anything else from `req.json()` is a malformed body.
const status =
(err as Error & { status?: number }).status === 401 ? 401 : 400;
const message =
status === 401
? (err instanceof Error ? err.message : "Unauthorized")
: "Body must be JSON";
return NextResponse.json({ error: message }, { status });
} catch {
return NextResponse.json({ error: "Body must be JSON" }, { status: 400 });
}
if (body === null || typeof body !== "object") {
return NextResponse.json({ error: "Body must be an object" }, { status: 400 });