@tokenoftrust/storefront-runner 2.0.10 → 2.0.11

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.
@@ -144,6 +144,39 @@ export function isPublicPath(pathname: string): boolean {
144
144
  return pathname === "/api/cli/policy";
145
145
  }
146
146
 
147
+ /**
148
+ * The CLI viewer-session mint (`/api/dev/cli-session`) — how an invited developer
149
+ * turns their own `tot login` MCP token into a storefront session so `tot accept`
150
+ * can reach the ship surface. Like the static-bundle upload it governs its OWN,
151
+ * stricter auth and must reach its handler rather than being masked behind the
152
+ * "Coming soon" holding page.
153
+ *
154
+ * Gate-exemption does NOT weaken it, on three independent grounds:
155
+ * - It authenticates ITSELF: no `Authorization: Bearer <token>` → 401
156
+ * `missing_bearer`. It reads no cookie, so it carries zero ambient authority.
157
+ * - It resolves WHO that opaque token is only by asking the MCP over the
158
+ * service-secret seam, fail-closed (unconfigured seam, transport fault, non-2xx,
159
+ * unparseable body, or absent email all → 401).
160
+ * - The session it mints is capability `member`, roles `[]` — byte-for-byte the
161
+ * one `/api/auth/magic-exchange` produces from the same `reissueSubjectToken` →
162
+ * verify → `createSession` path, and that route is ALREADY exempt via
163
+ * {@link isAuthPath}. So this exposes no reachable surface that is not.
164
+ *
165
+ * It also grants no admission: a developer holding no membership for this host gets
166
+ * a session that STILL fails `sessionAdmitsHost`, so the gate stays closed to them.
167
+ *
168
+ * Matched in BOTH addressing forms, like {@link isCandidatePreviewPath} — the gate
169
+ * sees the PRE-STRIP request path, so a tenant reached by path prefix arrives as
170
+ * `/<tenant>/api/dev/cli-session`. The CLI addresses tenants exactly that way (the
171
+ * shared storefront origin serves every tenant under a path prefix, which is the only
172
+ * form that works for a tenant whose apex has not cut over), so an exact-match-only
173
+ * exemption would never fire for the one caller this route exists to serve.
174
+ */
175
+ export function isDevCliSessionPath(pathname: string): boolean {
176
+ if (pathname === "/api/dev/cli-session") return true;
177
+ return /^\/[^/]+\/api\/dev\/cli-session$/.test(pathname);
178
+ }
179
+
147
180
  /**
148
181
  * The authenticated static-bundle staging upload (`/api/publish/stage-bundle`).
149
182
  * Like the candidate-preview control plane, it governs its OWN, stricter auth (a
@@ -266,6 +299,8 @@ export function evaluateLoginGate(input: LoginGateInput): LoginGateDecision {
266
299
  if (isCandidatePreviewPath(input.pathname)) return { action: "pass" };
267
300
  // The static-bundle staging upload carries its own private_key_jwt auth.
268
301
  if (isStaticBundleUploadPath(input.pathname)) return { action: "pass" };
302
+ // The CLI viewer-session mint carries its own bearer auth — see isDevCliSessionPath.
303
+ if (isDevCliSessionPath(input.pathname)) return { action: "pass" };
269
304
  // QA content-bypass: a request presenting the server-configured token passes for
270
305
  // public content only. NEVER for admin/cockpit/api — that guard lives here (not
271
306
  // just in middleware) so /admin stays gated even if the flag is set upstream.
@@ -65,6 +65,8 @@ export interface CatalogSyncState {
65
65
  source: SyncStateSourceMode;
66
66
  fidelity: SyncStateFidelity;
67
67
  lastSyncAt: string | null;
68
+ /** True when the most recent sync loaded with record errors; absent on a pre-hsby-B3 catalog. */
69
+ lastSyncHadErrors?: boolean;
68
70
  products: SyncStateEntity;
69
71
  collections: SyncStateEntity;
70
72
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tokenoftrust/storefront-runner",
3
- "version": "2.0.10",
3
+ "version": "2.0.11",
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",