@tokenoftrust/storefront-runner 2.5.4 → 2.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,28 @@
1
+ import type { APIContext } from "astro";
2
+
3
+ const ROUTES = {
4
+ "pipeline-job": { path: /^\/api\/pipeline\/jobs\/([A-Za-z0-9._:-]{1,128})\/?$/, param: "jobId" },
5
+ "fulfillment-order": { path: /^\/api\/admin\/fulfillment\/orders\/([A-Za-z0-9._:-]{1,128})\/?$/, param: "id" },
6
+ "fulfillment-address": { path: /^\/api\/admin\/fulfillment\/orders\/([A-Za-z0-9._:-]{1,128})\/address\/?$/, param: "id" },
7
+ } as const;
8
+
9
+ export type RoutedApiKind = keyof typeof ROUTES;
10
+
11
+ /** Resolve an opaque resource inside the server-routed tenant, including rewritten endpoints. */
12
+ export function routedApiParam(context: APIContext, kind: RoutedApiKind): string | undefined {
13
+ if (!Object.hasOwn(ROUTES, kind)) return undefined;
14
+ const tenant = context.locals.tenant?.appDomain;
15
+ const prefix = context.locals.apiBasePath;
16
+ if (typeof tenant !== "string" || !/^[A-Za-z0-9][A-Za-z0-9.-]{0,252}$/.test(tenant)) return undefined;
17
+ if (typeof prefix !== "string" || (prefix !== "" && !/^\/[A-Za-z0-9][A-Za-z0-9.-]{0,252}$/.test(prefix))) return undefined;
18
+ let pathname: string;
19
+ try { pathname = new URL(context.request.url).pathname; } catch { return undefined; }
20
+ if (prefix && !pathname.startsWith(`${prefix}/`)) return undefined;
21
+ const relative = pathname.slice(prefix.length);
22
+ const route = ROUTES[kind];
23
+ const id = route.path.exec(relative)?.[1];
24
+ if (!id || id === "." || id === "..") return undefined;
25
+ const param = context.params[route.param];
26
+ if (param !== undefined && param !== "" && param !== id) return undefined;
27
+ return id;
28
+ }
@@ -1,3 +1,4 @@
1
+ import { routedApiParam } from "@/lib/publication/shared/routedApiParam";
1
2
  /**
2
3
  * Owner-only retrieval of a stored ship-to address.
3
4
  * The read runs only after the owner gate admits the caller.
@@ -24,8 +25,8 @@ export async function GET(context: APIContext): Promise<Response> {
24
25
  },
25
26
  });
26
27
  }
27
- const orderId = context.params.id ?? "";
28
- if (!isOpaqueId(orderId)) return fulfillmentResultResponse({ ok: false, code: "not-found" }, () => ({}));
28
+ const orderId = routedApiParam(context, "fulfillment-address");
29
+ if (!orderId || !isOpaqueId(orderId)) return fulfillmentResultResponse({ ok: false, code: "not-found" }, () => ({}));
29
30
  const opened = await openFulfillment(context);
30
31
  if (!opened.ok) return opened.response;
31
32
  return fulfillmentResultResponse(await opened.service.readAddress(opened.actor, orderId), (address) => address);
@@ -1,3 +1,4 @@
1
+ import { routedApiParam } from "@/lib/publication/shared/routedApiParam";
1
2
  /**
2
3
  * Authenticated owner API for one order's fulfillment commands.
3
4
  * The response is state codes and the fulfillment view. It never returns an address.
@@ -53,8 +54,8 @@ function fail(code: string): Response {
53
54
  export async function GET(context: APIContext): Promise<Response> {
54
55
  const refused = await requireOwner(context);
55
56
  if (refused) return refused;
56
- const orderId = context.params.id ?? "";
57
- if (!isOpaqueId(orderId)) return fail("not-found");
57
+ const orderId = routedApiParam(context, "fulfillment-order");
58
+ if (!orderId || !isOpaqueId(orderId)) return fail("not-found");
58
59
  const opened = await openFulfillment(context);
59
60
  if (!opened.ok) return opened.response;
60
61
  return fulfillmentResultResponse(await opened.service.get(opened.actor, orderId), (view) => view);
@@ -63,8 +64,8 @@ export async function GET(context: APIContext): Promise<Response> {
63
64
  export async function POST(context: APIContext): Promise<Response> {
64
65
  const refused = await requireOwner(context);
65
66
  if (refused) return refused;
66
- const orderId = context.params.id ?? "";
67
- if (!isOpaqueId(orderId)) return fail("not-found");
67
+ const orderId = routedApiParam(context, "fulfillment-order");
68
+ if (!orderId || !isOpaqueId(orderId)) return fail("not-found");
68
69
  const raw = await readJsonBody(context.request);
69
70
  if (!raw.ok) return fulfillmentResultResponse(raw, () => ({}));
70
71
  const parsed = parseFulfillmentBody(raw.value);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tokenoftrust/storefront-runner",
3
- "version": "2.5.4",
3
+ "version": "2.5.5",
4
4
  "license": "SEE LICENSE IN LICENSE",
5
5
  "description": "World-shareable storefront runner: multi-tenant renderer on Astro/Cloudflare. No control plane.",
6
6
  "packageManager": "pnpm@11.9.0",