@tokenoftrust/storefront-runner 2.5.5 → 3.0.0

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.
Files changed (80) hide show
  1. package/agency-kit/tools/lib/public-binaries.mjs +95 -0
  2. package/apps/storefront/astro.config.mjs +7 -0
  3. package/apps/storefront/env.d.ts +3 -0
  4. package/apps/storefront/src/components/catalog/storefront/ProductCard.astro +5 -4
  5. package/apps/storefront/src/components/catalog/storefront/commerce/PriceDisplay.astro +2 -1
  6. package/apps/storefront/src/components/catalog/storefront/islands/ImageGallery.tsx +20 -3
  7. package/apps/storefront/src/components/catalog/storefront/islands/SearchTypeahead.tsx +17 -20
  8. package/apps/storefront/src/components/catalog/storefront/islands/VariantSelector.tsx +13 -21
  9. package/apps/storefront/src/components/catalog/storefront/plp/Pagination.astro +9 -5
  10. package/apps/storefront/src/components/checkout/storefront/commerce/CheckoutLoader.astro +18 -6
  11. package/apps/storefront/src/components/compliance/storefront/islands/CheckoutComplianceGate.tsx +19 -4
  12. package/apps/storefront/src/components/content/storefront/Badge.astro +1 -0
  13. package/apps/storefront/src/components/content/storefront/blog/BlogIndexView.astro +10 -1
  14. package/apps/storefront/src/components/publication/storefront/islands/CatalogQueryView.tsx +321 -0
  15. package/apps/storefront/src/config/declaredTenantConfig.ts +59 -27
  16. package/apps/storefront/src/config/devTenantSeed.ts +2 -1
  17. package/apps/storefront/src/layouts/Layout.astro +1 -1
  18. package/apps/storefront/src/lib/access/auth/gatePage.ts +29 -14
  19. package/apps/storefront/src/lib/access/shared/publicAccess.ts +95 -0
  20. package/apps/storefront/src/lib/access/shared/tenantRouting.ts +19 -0
  21. package/apps/storefront/src/lib/catalog/shared/catalogIndex.ts +109 -0
  22. package/apps/storefront/src/lib/catalog/shared/catalogQueryView.ts +60 -0
  23. package/apps/storefront/src/lib/catalog/shared/collectionPaging.ts +78 -0
  24. package/apps/storefront/src/lib/catalog/shared/stockStatus.ts +23 -0
  25. package/apps/storefront/src/lib/catalog/tot/query.ts +8 -0
  26. package/apps/storefront/src/lib/checkout/browser/checkoutRequirementsForm.ts +54 -0
  27. package/apps/storefront/src/lib/checkout/commerce/checkoutHandoffRoute.ts +103 -35
  28. package/apps/storefront/src/lib/checkout/commerce/checkoutRequirements.ts +88 -0
  29. package/apps/storefront/src/lib/checkout/commerce/finalCartAuthorization.ts +2 -0
  30. package/apps/storefront/src/lib/checkout/commerce/sharedStoreAdmission.ts +95 -0
  31. package/apps/storefront/src/lib/checkout/shared/lazyCheckoutLoader.ts +191 -0
  32. package/apps/storefront/src/lib/compliance/browser/checkoutVerificationFlow.ts +9 -0
  33. package/apps/storefront/src/lib/compliance/enforcement.ts +7 -5
  34. package/apps/storefront/src/lib/content/seo/structuredData.ts +12 -3
  35. package/apps/storefront/src/lib/content/storyblok/provider.ts +14 -7
  36. package/apps/storefront/src/lib/observability/shared/serverTiming.ts +110 -0
  37. package/apps/storefront/src/lib/publication/shared/edgeCache.ts +3 -4
  38. package/apps/storefront/src/lib/publication/shared/staticQuery.ts +64 -0
  39. package/apps/storefront/src/middleware/controlPlane.ts +14 -11
  40. package/apps/storefront/src/middleware/index.ts +33 -12
  41. package/apps/storefront/src/middleware/renderChain.ts +52 -26
  42. package/apps/storefront/src/pages/[...slug].astro +3 -0
  43. package/apps/storefront/src/pages/api/commerce/final-cart-authorization.ts +112 -42
  44. package/apps/storefront/src/pages/api/compliance/preflight.ts +61 -13
  45. package/apps/storefront/src/pages/blog/author/[author].astro +1 -1
  46. package/apps/storefront/src/pages/blog/category/[category].astro +1 -1
  47. package/apps/storefront/src/pages/blog/tag/[tag].astro +1 -1
  48. package/apps/storefront/src/pages/catalog-index.json.ts +20 -0
  49. package/apps/storefront/src/pages/collections/[handle]/page/[n].astro +28 -0
  50. package/apps/storefront/src/pages/collections/[handle].astro +13 -198
  51. package/apps/storefront/src/pages/collections/_CollectionView.astro +251 -0
  52. package/apps/storefront/src/pages/collections/index.astro +1 -1
  53. package/apps/storefront/src/pages/products/[handle].astro +18 -8
  54. package/apps/storefront/src/pages/search.astro +33 -33
  55. package/apps/storefront/src/pages/sitemap.xml.ts +7 -1
  56. package/apps/storefront/vitest.config.cts +3 -0
  57. package/package.json +1 -1
  58. package/packages/cli/src/declared-config.mjs +318 -32
  59. package/packages/cli/src/publication-spaces.mjs +1 -1
  60. package/packages/public-runtime/package.json +1 -0
  61. package/packages/public-runtime/schemas/publication-space/v1/manifest.schema.json +1 -1
  62. package/packages/public-runtime/schemas/publication-space/v1/normalized-mount.schema.json +1 -1
  63. package/packages/public-runtime/src/activity/catalog.ts +8 -1
  64. package/packages/public-runtime/src/candidate-index.ts +5 -0
  65. package/packages/public-runtime/src/capabilities.ts +12 -9
  66. package/packages/public-runtime/src/capture-rewrites.ts +687 -0
  67. package/packages/public-runtime/src/checkout-orders.ts +6 -7
  68. package/packages/public-runtime/src/checkout.ts +190 -6
  69. package/packages/public-runtime/src/compliance/evaluate.ts +7 -3
  70. package/packages/public-runtime/src/compliance/profile.ts +90 -14
  71. package/packages/public-runtime/src/compliance-coherence.d.mts +10 -1
  72. package/packages/public-runtime/src/compliance-coherence.mjs +129 -29
  73. package/packages/public-runtime/src/customization-runtime.ts +64 -2
  74. package/packages/public-runtime/src/declared-tenant-config.d.mts +13 -2
  75. package/packages/public-runtime/src/declared-tenant-config.mjs +83 -1
  76. package/packages/public-runtime/src/image-preview-rewrite-overlay.ts +13 -37
  77. package/packages/public-runtime/src/membership.ts +3 -0
  78. package/packages/public-runtime/src/publication-space.ts +1 -0
  79. package/packages/public-runtime/src/tenant.ts +28 -4
  80. package/scripts/tenant/validate.mjs +17 -8
@@ -33,7 +33,7 @@ export const PLATFORM_PATHS = Object.freeze([
33
33
  "/apps", "/assets", "/auth", "/brand", "/capabilities", "/cockpit", "/dashboard", "/dev",
34
34
  "/favicon.svg", "/health", "/js", "/feed.json", "/llms.txt", "/publication-discovery",
35
35
  "/search-index.json", "/sitemap.xml", "/platform", "/preview", "/products", "/collections",
36
- "/search", "/saved", "/robots.txt", "/shared", "/style-guide", "/tenants",
36
+ "/search", "/catalog-index.json", "/saved", "/robots.txt", "/shared", "/style-guide", "/tenants",
37
37
  ]);
38
38
 
39
39
  const SPACE_ID = /^[a-z0-9](?:[a-z0-9._-]{0,126}[a-z0-9])?$/;
@@ -15,6 +15,7 @@
15
15
  "./image-finding-dependencies": "./src/image-finding-dependencies.ts",
16
16
  "./image-finding-acceptance": "./src/image-finding-acceptance.ts",
17
17
  "./image-preview-rewrite-overlay": "./src/image-preview-rewrite-overlay.ts",
18
+ "./capture-rewrites": "./src/capture-rewrites.ts",
18
19
  "./hosted-image-media-types": "./src/hosted-image-media-types.ts",
19
20
  "./durable-assets": "./src/durable-assets.ts",
20
21
  "./catalog-files": "./src/catalog-files.ts",
@@ -207,7 +207,7 @@
207
207
  "mountPath": {
208
208
  "allOf": [
209
209
  { "$ref": "#/$defs/path" },
210
- { "type": "string", "pattern": "^/(?!(?:\\.[wW][eE][lL][lL]-[kK][nN][oO][wW][nN]|__[eE][vV][iI][dD][eE][nN][cC][eE]|__[pP][rR][eE][vV][iI][eE][wW]|_[aA]|_[aA][sS][tT][rR][oO]|_[sS][tT][yY][lL][eE]-[gG][uU][iI][dD][eE]|[aA][dD][mM][iI][nN]|[aA][pP][iI]|[aA][pP][pP][sS]|[aA][sS][sS][eE][tT][sS]|[aA][uU][tT][hH]|[bB][rR][aA][nN][dD]|[cC][aA][pP][aA][bB][iI][lL][iI][tT][iI][eE][sS]|[cC][oO][cC][kK][pP][iI][tT]|[cC][oO][lL][lL][eE][cC][tT][iI][oO][nN][sS]|[dD][aA][sS][hH][bB][oO][aA][rR][dD]|[dD][eE][vV]|[fF][aA][vV][iI][cC][oO][nN]\\.[sS][vV][gG]|[fF][eE][eE][dD]\\.[jJ][sS][oO][nN]|[hH][eE][aA][lL][tT][hH]|[jJ][sS]|[lL][lL][mM][sS]\\.[tT][xX][tT]|[pP][lL][aA][tT][fF][oO][rR][mM]|[pP][rR][eE][vV][iI][eE][wW]|[pP][rR][oO][dD][uU][cC][tT][sS]|[pP][uU][bB][lL][iI][cC][aA][tT][iI][oO][nN]-[dD][iI][sS][cC][oO][vV][eE][rR][yY]|[rR][oO][bB][oO][tT][sS]\\.[tT][xX][tT]|[sS][aA][vV][eE][dD]|[sS][eE][aA][rR][cC][hH]|[sS][eE][aA][rR][cC][hH]-[iI][nN][dD][eE][xX]\\.[jJ][sS][oO][nN]|[sS][hH][aA][rR][eE][dD]|[sS][iI][tT][eE][mM][aA][pP]\\.[xX][mM][lL]|[sS][tT][yY][lL][eE]-[gG][uU][iI][dD][eE]|[tT][eE][nN][aA][nN][tT][sS])(?:/|$))" }
210
+ { "type": "string", "pattern": "^/(?!(?:\\.[wW][eE][lL][lL]-[kK][nN][oO][wW][nN]|__[eE][vV][iI][dD][eE][nN][cC][eE]|__[pP][rR][eE][vV][iI][eE][wW]|_[aA]|_[aA][sS][tT][rR][oO]|_[sS][tT][yY][lL][eE]-[gG][uU][iI][dD][eE]|[aA][dD][mM][iI][nN]|[aA][pP][iI]|[aA][pP][pP][sS]|[aA][sS][sS][eE][tT][sS]|[aA][uU][tT][hH]|[bB][rR][aA][nN][dD]|[cC][aA][pP][aA][bB][iI][lL][iI][tT][iI][eE][sS]|[cC][aA][tT][aA][lL][oO][gG]-[iI][nN][dD][eE][xX]\\.[jJ][sS][oO][nN]|[cC][oO][cC][kK][pP][iI][tT]|[cC][oO][lL][lL][eE][cC][tT][iI][oO][nN][sS]|[dD][aA][sS][hH][bB][oO][aA][rR][dD]|[dD][eE][vV]|[fF][aA][vV][iI][cC][oO][nN]\\.[sS][vV][gG]|[fF][eE][eE][dD]\\.[jJ][sS][oO][nN]|[hH][eE][aA][lL][tT][hH]|[jJ][sS]|[lL][lL][mM][sS]\\.[tT][xX][tT]|[pP][lL][aA][tT][fF][oO][rR][mM]|[pP][rR][eE][vV][iI][eE][wW]|[pP][rR][oO][dD][uU][cC][tT][sS]|[pP][uU][bB][lL][iI][cC][aA][tT][iI][oO][nN]-[dD][iI][sS][cC][oO][vV][eE][rR][yY]|[rR][oO][bB][oO][tT][sS]\\.[tT][xX][tT]|[sS][aA][vV][eE][dD]|[sS][eE][aA][rR][cC][hH]|[sS][eE][aA][rR][cC][hH]-[iI][nN][dD][eE][xX]\\.[jJ][sS][oO][nN]|[sS][hH][aA][rR][eE][dD]|[sS][iI][tT][eE][mM][aA][pP]\\.[xX][mM][lL]|[sS][tT][yY][lL][eE]-[gG][uU][iI][dD][eE]|[tT][eE][nN][aA][nN][tT][sS])(?:/|$))" }
211
211
  ]
212
212
  },
213
213
  "aliasPath": {
@@ -67,7 +67,7 @@
67
67
  "mountPath": {
68
68
  "allOf": [
69
69
  { "$ref": "#/$defs/normalizedPath" },
70
- { "type": "string", "pattern": "^/(?!(?:\\.[wW][eE][lL][lL]-[kK][nN][oO][wW][nN]|__[eE][vV][iI][dD][eE][nN][cC][eE]|__[pP][rR][eE][vV][iI][eE][wW]|_[aA]|_[aA][sS][tT][rR][oO]|_[sS][tT][yY][lL][eE]-[gG][uU][iI][dD][eE]|[aA][dD][mM][iI][nN]|[aA][pP][iI]|[aA][pP][pP][sS]|[aA][sS][sS][eE][tT][sS]|[aA][uU][tT][hH]|[bB][rR][aA][nN][dD]|[cC][aA][pP][aA][bB][iI][lL][iI][tT][iI][eE][sS]|[cC][oO][cC][kK][pP][iI][tT]|[cC][oO][lL][lL][eE][cC][tT][iI][oO][nN][sS]|[dD][aA][sS][hH][bB][oO][aA][rR][dD]|[dD][eE][vV]|[fF][aA][vV][iI][cC][oO][nN]\\.[sS][vV][gG]|[fF][eE][eE][dD]\\.[jJ][sS][oO][nN]|[hH][eE][aA][lL][tT][hH]|[jJ][sS]|[lL][lL][mM][sS]\\.[tT][xX][tT]|[pP][lL][aA][tT][fF][oO][rR][mM]|[pP][rR][eE][vV][iI][eE][wW]|[pP][rR][oO][dD][uU][cC][tT][sS]|[pP][uU][bB][lL][iI][cC][aA][tT][iI][oO][nN]-[dD][iI][sS][cC][oO][vV][eE][rR][yY]|[rR][oO][bB][oO][tT][sS]\\.[tT][xX][tT]|[sS][aA][vV][eE][dD]|[sS][eE][aA][rR][cC][hH]|[sS][eE][aA][rR][cC][hH]-[iI][nN][dD][eE][xX]\\.[jJ][sS][oO][nN]|[sS][hH][aA][rR][eE][dD]|[sS][iI][tT][eE][mM][aA][pP]\\.[xX][mM][lL]|[sS][tT][yY][lL][eE]-[gG][uU][iI][dD][eE]|[tT][eE][nN][aA][nN][tT][sS])(?:/|$))" }
70
+ { "type": "string", "pattern": "^/(?!(?:\\.[wW][eE][lL][lL]-[kK][nN][oO][wW][nN]|__[eE][vV][iI][dD][eE][nN][cC][eE]|__[pP][rR][eE][vV][iI][eE][wW]|_[aA]|_[aA][sS][tT][rR][oO]|_[sS][tT][yY][lL][eE]-[gG][uU][iI][dD][eE]|[aA][dD][mM][iI][nN]|[aA][pP][iI]|[aA][pP][pP][sS]|[aA][sS][sS][eE][tT][sS]|[aA][uU][tT][hH]|[bB][rR][aA][nN][dD]|[cC][aA][pP][aA][bB][iI][lL][iI][tT][iI][eE][sS]|[cC][aA][tT][aA][lL][oO][gG]-[iI][nN][dD][eE][xX]\\.[jJ][sS][oO][nN]|[cC][oO][cC][kK][pP][iI][tT]|[cC][oO][lL][lL][eE][cC][tT][iI][oO][nN][sS]|[dD][aA][sS][hH][bB][oO][aA][rR][dD]|[dD][eE][vV]|[fF][aA][vV][iI][cC][oO][nN]\\.[sS][vV][gG]|[fF][eE][eE][dD]\\.[jJ][sS][oO][nN]|[hH][eE][aA][lL][tT][hH]|[jJ][sS]|[lL][lL][mM][sS]\\.[tT][xX][tT]|[pP][lL][aA][tT][fF][oO][rR][mM]|[pP][rR][eE][vV][iI][eE][wW]|[pP][rR][oO][dD][uU][cC][tT][sS]|[pP][uU][bB][lL][iI][cC][aA][tT][iI][oO][nN]-[dD][iI][sS][cC][oO][vV][eE][rR][yY]|[rR][oO][bB][oO][tT][sS]\\.[tT][xX][tT]|[sS][aA][vV][eE][dD]|[sS][eE][aA][rR][cC][hH]|[sS][eE][aA][rR][cC][hH]-[iI][nN][dD][eE][xX]\\.[jJ][sS][oO][nN]|[sS][hH][aA][rR][eE][dD]|[sS][iI][tT][eE][mM][aA][pP]\\.[xX][mM][lL]|[sS][tT][yY][lL][eE]-[gG][uU][iI][dD][eE]|[tT][eE][nN][aA][nN][tT][sS])(?:/|$))" }
71
71
  ]
72
72
  },
73
73
  "aliasPath": {
@@ -176,7 +176,7 @@ export const ACTION_CATALOG = {
176
176
  // A reconcile reached a terminal state (reconciled|blocked|failed). Low
177
177
  // volume, high value → timelined for the ops UI.
178
178
  actors: ["system"], source: "server", sinks: LIFECYCLE,
179
- argsAllow: ["changeId", "result", "evidenceStatus", "evidencePushError", "prNumber", "forgeOpenVerified", "terminalSource"], renderedAllow: [],
179
+ argsAllow: ["changeId", "result", "evidenceStatus", "evidencePushError", "prNumber", "forgeOpenVerified", "terminalSource", "cause", "traceId"], renderedAllow: [],
180
180
  desc: "A candidate reconcile reached a terminal state.",
181
181
  },
182
182
  "candidate.closed": {
@@ -323,6 +323,13 @@ export const ACTION_CATALOG = {
323
323
  argsAllow: ["versionId", "scope"], renderedAllow: [],
324
324
  desc: "A tenant's checkout styling was saved to a version.",
325
325
  },
326
+ "content.checkout_requirements.saved": {
327
+ // A store's shared-test-store checkout requirements (Settings → Checkout requirements)
328
+ // were saved to a versioned test artifact. Same actors and spine as checkout styling.
329
+ actors: ["merchant", "admin"], source: "server", sinks: LIFECYCLE,
330
+ argsAllow: ["versionId", "scope"], renderedAllow: [],
331
+ desc: "A store's checkout requirements were saved to a version.",
332
+ },
326
333
  "change.go_live": {
327
334
  // Renamed from the orphaned, un-namespaced `go_live` (the ONE key that broke the
328
335
  // domain-prefix rule). The snake_case suffix is kept (the `deploy.version_observed`
@@ -78,6 +78,11 @@ export interface CandidateReconcileLifecycle {
78
78
  | "ready"
79
79
  | "blocked";
80
80
  correlationId: string;
81
+ /**
82
+ * The forge's `X-Gitea-Delivery` id MCP forwarded with this reconcile — the key that joins this
83
+ * record to MCP's delivery record (`preview_status.delivery`) and to Gitea's own delivery log.
84
+ */
85
+ deliveryId?: string | null;
81
86
  startedAt: string;
82
87
  lastUpdatedAt: string;
83
88
  elapsedMs: number;
@@ -23,6 +23,7 @@
23
23
  * ArtifactPath)` overrides the build-time `TenantConfig.capabilities` default.
24
24
  */
25
25
  import type { TenantConfig } from "./tenant.js";
26
+ import { resolveObligationIds } from "./compliance-obligations.js";
26
27
 
27
28
  export interface CapabilityState {
28
29
  enabled: boolean;
@@ -70,24 +71,26 @@ export function capabilitiesArtifactPath(tenantId: string): string {
70
71
  /**
71
72
  * Resolve the non-negotiable compliance floor for a tenant. This is intentionally
72
73
  * narrower than feature defaults: it says only what MUST remain on for the site
73
- * to be publishable.
74
+ * to be publishable. Each capability is required exactly when the obligation
75
+ * registry (`resolveObligationIds`) applies the duty it serves.
74
76
  */
75
77
  export function resolveComplianceObligations(
76
78
  tenant: Pick<TenantConfig, "compliance" | "siteType">,
77
79
  ): CapabilityObligations {
80
+ const owed = new Set(resolveObligationIds(tenant));
78
81
  return {
79
82
  cartCheckout: { required: false },
80
- ageVerification: tenant.compliance?.minAge
83
+ ageVerification: owed.has("age_gate")
81
84
  ? {
82
85
  required: true,
83
- reason: `Tenant requires age/identity verification for ${tenant.compliance.minAge}+ access.`,
86
+ reason: `Tenant requires age/identity verification for ${tenant.compliance?.minAge}+ access.`,
84
87
  }
85
88
  : { required: false },
86
- exciseTax: tenant.compliance?.nicotineWarning
89
+ exciseTax: owed.has("excise")
87
90
  ? {
88
91
  required: true,
89
92
  reason:
90
- "Tenant sells nicotine/vape products and must keep excise-tax collection enabled at checkout.",
93
+ "Tenant sells excise-taxed products (`compliance.nicotineWarning` or `compliance.exciseTax`) and must keep excise-tax collection enabled at checkout.",
91
94
  }
92
95
  : { required: false },
93
96
  };
@@ -130,18 +133,18 @@ export function resolveCapabilities(
130
133
  override?: Partial<CapabilityConfig> | null,
131
134
  ): CapabilityConfig {
132
135
  const c = tenant.capabilities;
136
+ const owed = new Set(resolveObligationIds(tenant));
133
137
  const base: CapabilityConfig = {
134
138
  // Commerce tenants get a cart by default; marketing tenants don't.
135
139
  cartCheckout: {
136
140
  enabled: c?.cartCheckout?.enabled ?? tenant.siteType !== "marketing",
137
141
  },
138
- // Regulated tenants (an age minimum) verify by default.
142
+ // A tenant that owes a duty has the capability serving it on by default.
139
143
  ageVerification: {
140
- enabled: c?.ageVerification?.enabled ?? !!tenant.compliance?.minAge,
144
+ enabled: c?.ageVerification?.enabled ?? owed.has("age_gate"),
141
145
  },
142
- // Nicotine/vape tenants collect excise by default.
143
146
  exciseTax: {
144
- enabled: c?.exciseTax?.enabled ?? !!tenant.compliance?.nicotineWarning,
147
+ enabled: c?.exciseTax?.enabled ?? owed.has("excise"),
145
148
  },
146
149
  };
147
150
  const requested = override