fix(payments): authenticate order detail and deposit checkout
masterplan-lock / check (push) Successful in 4s
masterplan-lock / check (pull_request) Successful in 4s
Security Scan (SIAX Cloud) / security (push) Successful in 17s
CI (SIAX Cloud) / security (pull_request) Successful in 17s
CI (SIAX Cloud) / quality (pull_request) Successful in 36s
CI (SIAX Cloud) / security (push) Successful in 1m14s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 1m12s
CI (SIAX Cloud) / quality (push) Successful in 1m22s
CI (SIAX Cloud) / integration (push) Failing after 1m22s
CI (SIAX Cloud) / integration (pull_request) Failing after 1m22s

This commit is contained in:
2026-09-15 19:09:53 +02:00
parent c7f8b3f651
commit cecc2bc637
6 changed files with 104 additions and 17 deletions
+16
View File
@@ -15,7 +15,9 @@
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { NextRequest } from 'next/server';
import { GET as ordersGET } from '@/app/api/orders/route';
import { GET as orderGET } from '@/app/api/orders/[id]/route';
import { GET as adminMetricsGET } from '@/app/api/admin/metrics/route';
import { POST as depositPOST } from '@/app/api/payments/[order_id]/deposit/route';
function req(url: string, headers: Record<string, string> = {}): NextRequest {
return new NextRequest(new URL(url, 'http://localhost'), { headers });
@@ -49,6 +51,20 @@ describe('anonymous-access regression: /api/orders (GET) and /api/admin/metrics
expect(res.status).toBe(401);
});
it('GET /api/orders/{id} rejects anonymous and spoofed-tenant reads before loading an order', async () => {
const params = { params: Promise.resolve({ id: 'order-unknown' }) };
expect((await orderGET(req('/api/orders/order-unknown'), params)).status).toBe(401);
expect((await orderGET(req('/api/orders/order-unknown', {
'x-0pt-verified-tenant': 'tenant_attacker',
}), params)).status).toBe(401);
});
it('deposit checkout rejects anonymous callers before checking Stripe credentials or order id', async () => {
const request = req('/api/payments/order-unknown/deposit');
const result = await depositPOST(request, { params: Promise.resolve({ order_id: 'order-unknown' }) });
expect(result.status).toBe(401);
});
it('REGRESSION: GET /api/admin/metrics 401s with no Authorization header (was: 200 + financial aggregates)', async () => {
const res = await adminMetricsGET(req('/api/admin/metrics'));
expect(res.status).toBe(401);
@@ -4,6 +4,9 @@ import { NextRequest } from "next/server";
vi.mock("@/lib/orders-store", () => ({
getOrder: vi.fn().mockResolvedValue({ order_id: "order-1", deposit_ore: 5000 }),
}));
vi.mock("@/src/auth/require-route-auth", () => ({
requireRouteAuth: vi.fn().mockResolvedValue({ ctx: { tenantId: "tenant-test" } }),
}));
import { POST } from "@/app/api/payments/[order_id]/deposit/route";