@tokenoftrust/storefront-runner 1.4.1 → 1.4.2-rc.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 (166) hide show
  1. package/apps/storefront/astro.config.mjs +17 -1
  2. package/apps/storefront/integrations/materialize-guard.mjs +56 -0
  3. package/apps/storefront/migrations-apps/0002_good_switch.sql +26 -0
  4. package/apps/storefront/migrations-apps/0003_mute_marauders.sql +12 -0
  5. package/apps/storefront/migrations-apps/meta/0002_snapshot.json +1160 -0
  6. package/apps/storefront/migrations-apps/meta/0003_snapshot.json +1235 -0
  7. package/apps/storefront/migrations-apps/meta/_journal.json +14 -0
  8. package/apps/storefront/public/js/dashboard-team.js +38 -2
  9. package/apps/storefront/src/components/Seo.astro +65 -1
  10. package/apps/storefront/src/components/admin/AdminBlogDetailRail.astro +878 -0
  11. package/apps/storefront/src/components/admin/AdminBlogTab.astro +1432 -0
  12. package/apps/storefront/src/components/admin/AdminCustomersTab.astro +3 -7
  13. package/apps/storefront/src/components/admin/AdminPublishTab.astro +1105 -2334
  14. package/apps/storefront/src/components/admin/AdminSubscriptionsTab.astro +1 -3
  15. package/apps/storefront/src/components/blog/BlogPaywall.astro +87 -0
  16. package/apps/storefront/src/components/blog/PostAccessBadge.astro +43 -0
  17. package/apps/storefront/src/components/blog/PostGrid.astro +57 -0
  18. package/apps/storefront/src/components/blog/ReactionBar.astro +214 -0
  19. package/apps/storefront/src/layouts/Layout.astro +48 -3
  20. package/apps/storefront/src/lib/activity/alerts.ts +17 -19
  21. package/apps/storefront/src/lib/activity/changeActorAttribution.ts +3 -3
  22. package/apps/storefront/src/lib/activity/deployVersion.ts +19 -26
  23. package/apps/storefront/src/lib/activity/ingest.ts +8 -8
  24. package/apps/storefront/src/lib/activity/ingestAuth.ts +1 -1
  25. package/apps/storefront/src/lib/activity/killSwitch.ts +6 -6
  26. package/apps/storefront/src/lib/activity/query.ts +9 -9
  27. package/apps/storefront/src/lib/activity/recordActivity.ts +11 -15
  28. package/apps/storefront/src/lib/activity/store.ts +4 -6
  29. package/apps/storefront/src/lib/activity/uiActor.ts +12 -12
  30. package/apps/storefront/src/lib/activity/workerCommit.ts +6 -6
  31. package/apps/storefront/src/lib/admin/adminShell.ts +290 -0
  32. package/apps/storefront/src/lib/admin/ai/approvalMode.ts +2 -3
  33. package/apps/storefront/src/lib/admin/ai/audit.ts +3 -5
  34. package/apps/storefront/src/lib/admin/checkoutStyleInput.ts +7 -7
  35. package/apps/storefront/src/lib/admin/checkoutStyleTarget.ts +3 -3
  36. package/apps/storefront/src/lib/admin/orderClient.ts +3 -5
  37. package/apps/storefront/src/lib/admin/services/orders.ts +17 -19
  38. package/apps/storefront/src/lib/admin/viewmodels/aiWorkflows.ts +4 -6
  39. package/apps/storefront/src/lib/admin/viewmodels/settings.ts +1 -1
  40. package/apps/storefront/src/lib/apps/adminService.ts +4 -4
  41. package/apps/storefront/src/lib/apps/adminSession.ts +53 -44
  42. package/apps/storefront/src/lib/apps/apiAuth.ts +2 -2
  43. package/apps/storefront/src/lib/apps/apiRoute.ts +2 -2
  44. package/apps/storefront/src/lib/apps/catalogMapper.ts +1 -1
  45. package/apps/storefront/src/lib/apps/credentials.ts +2 -2
  46. package/apps/storefront/src/lib/apps/gatewayKeys.ts +4 -4
  47. package/apps/storefront/src/lib/apps/healthAggregate.ts +5 -5
  48. package/apps/storefront/src/lib/apps/orders/attributionService.ts +2 -2
  49. package/apps/storefront/src/lib/apps/orders/customerHash.ts +1 -1
  50. package/apps/storefront/src/lib/apps/orders/foxyOrderClient.ts +12 -12
  51. package/apps/storefront/src/lib/apps/orders/idempotency.ts +7 -7
  52. package/apps/storefront/src/lib/apps/orders/orderForwardReceiver.ts +1 -1
  53. package/apps/storefront/src/lib/apps/orders/orderMapper.ts +2 -2
  54. package/apps/storefront/src/lib/apps/orders/ordersStore.ts +6 -6
  55. package/apps/storefront/src/lib/apps/registryService.ts +6 -6
  56. package/apps/storefront/src/lib/apps/scopes.ts +2 -2
  57. package/apps/storefront/src/lib/apps/tokenIssuer.ts +4 -4
  58. package/apps/storefront/src/lib/apps/tokenVerifier.ts +6 -6
  59. package/apps/storefront/src/lib/apps/widgets/eligibility.ts +2 -2
  60. package/apps/storefront/src/lib/apps/widgets/frameProps.ts +3 -3
  61. package/apps/storefront/src/lib/apps/widgets/launchToken.ts +4 -4
  62. package/apps/storefront/src/lib/apps/widgets/placements.ts +2 -2
  63. package/apps/storefront/src/lib/apps/widgets/renderSlot.ts +1 -1
  64. package/apps/storefront/src/lib/auth/adminEntry.ts +9 -9
  65. package/apps/storefront/src/lib/auth/identityToken.ts +6 -14
  66. package/apps/storefront/src/lib/auth/loginGate.ts +75 -13
  67. package/apps/storefront/src/lib/auth/mcpClientAssertion.ts +2 -4
  68. package/apps/storefront/src/lib/auth/operatorSession.ts +113 -0
  69. package/apps/storefront/src/lib/auth/session.ts +7 -8
  70. package/apps/storefront/src/lib/auth/totAccessClient.ts +8 -18
  71. package/apps/storefront/src/lib/basePath.ts +9 -2
  72. package/apps/storefront/src/lib/blog/access.ts +29 -0
  73. package/apps/storefront/src/lib/blog/collection.ts +313 -0
  74. package/apps/storefront/src/lib/blog/markdown.ts +174 -0
  75. package/apps/storefront/src/lib/blog/provider.ts +5 -0
  76. package/apps/storefront/src/lib/blog/reactions.ts +87 -0
  77. package/apps/storefront/src/lib/blog/rss.ts +92 -0
  78. package/apps/storefront/src/lib/blog/teaser.ts +83 -0
  79. package/apps/storefront/src/lib/blog/types.ts +34 -0
  80. package/apps/storefront/src/lib/blog/viewCounts.ts +243 -0
  81. package/apps/storefront/src/lib/d1/catalog.ts +2 -2
  82. package/apps/storefront/src/lib/d1/schema-apps.ts +96 -17
  83. package/apps/storefront/src/lib/dev/activityIngestToken.ts +2 -4
  84. package/apps/storefront/src/lib/dev/activityStore.ts +3 -5
  85. package/apps/storefront/src/lib/dev/apiBase.ts +1 -4
  86. package/apps/storefront/src/lib/dev/cockpitStore.ts +1 -9
  87. package/apps/storefront/src/lib/dev/devDraft.ts +1 -1
  88. package/apps/storefront/src/lib/dev/previewStatus.ts +9 -21
  89. package/apps/storefront/src/lib/dev/rendezvousBroker.ts +9 -24
  90. package/apps/storefront/src/lib/edgeCache.ts +17 -0
  91. package/apps/storefront/src/lib/http/fetchTransport.ts +63 -0
  92. package/apps/storefront/src/lib/i18n.ts +25 -0
  93. package/apps/storefront/src/lib/jsonld.ts +118 -0
  94. package/apps/storefront/src/lib/monitoring/manifest.ts +11 -11
  95. package/apps/storefront/src/lib/newsletter/confirmationEmail.ts +30 -0
  96. package/apps/storefront/src/lib/newsletter/consent.ts +23 -0
  97. package/apps/storefront/src/lib/newsletter/digest.ts +117 -0
  98. package/apps/storefront/src/lib/newsletter/resendClient.ts +79 -0
  99. package/apps/storefront/src/lib/newsletter/send.ts +265 -0
  100. package/apps/storefront/src/lib/newsletter/subscribers.ts +156 -0
  101. package/apps/storefront/src/lib/publish/adminPublishTab.ts +3519 -0
  102. package/apps/storefront/src/lib/publish/apex-readiness.ts +41 -18
  103. package/apps/storefront/src/lib/publish/dispatchHealth.ts +5 -7
  104. package/apps/storefront/src/lib/publish/domainState.ts +22 -13
  105. package/apps/storefront/src/lib/publish/panelPolling.ts +78 -0
  106. package/apps/storefront/src/lib/publish/shipWorkspace.ts +100 -49
  107. package/apps/storefront/src/lib/publish/stageBundleUpload.ts +215 -0
  108. package/apps/storefront/src/lib/rate/kvWindow.ts +53 -0
  109. package/apps/storefront/src/lib/search/index.ts +2 -2
  110. package/apps/storefront/src/lib/seo/alternates.ts +42 -0
  111. package/apps/storefront/src/lib/seo/meta.ts +65 -0
  112. package/apps/storefront/src/lib/social/golive.ts +212 -0
  113. package/apps/storefront/src/lib/social/notify.ts +32 -0
  114. package/apps/storefront/src/lib/social/tokenStore.ts +171 -0
  115. package/apps/storefront/src/lib/the-build/provider.ts +27 -0
  116. package/apps/storefront/src/lib/the-build/readingTime.ts +35 -0
  117. package/apps/storefront/src/lib/the-build/toc.ts +95 -0
  118. package/apps/storefront/src/lib/tot/ToTClient.ts +1 -1
  119. package/apps/storefront/src/lib/tot/d1Client.ts +2 -2
  120. package/apps/storefront/src/lib/tot/totClientInterface.ts +3 -4
  121. package/apps/storefront/src/lib/webhooks/deliveryStore.ts +16 -17
  122. package/apps/storefront/src/middleware/index.ts +113 -2
  123. package/apps/storefront/src/pages/admin.astro +10 -1312
  124. package/apps/storefront/src/pages/api/blog/[collection]/[slug]/react.ts +104 -0
  125. package/apps/storefront/src/pages/api/newsletter/[collection]/subscribe.ts +146 -0
  126. package/apps/storefront/src/pages/api/newsletter/confirm.ts +75 -0
  127. package/apps/storefront/src/pages/api/newsletter/unsubscribe.ts +90 -0
  128. package/apps/storefront/src/pages/api/publish/stage-bundle.ts +70 -0
  129. package/apps/storefront/src/pages/api/rum/vitals.ts +21 -2
  130. package/apps/storefront/src/pages/blog/[slug].astro +96 -16
  131. package/apps/storefront/src/pages/blog/author/[author].astro +140 -0
  132. package/apps/storefront/src/pages/blog/category/[category].astro +67 -0
  133. package/apps/storefront/src/pages/blog/index.astro +2 -0
  134. package/apps/storefront/src/pages/blog/tag/[tag].astro +65 -0
  135. package/apps/storefront/src/pages/cockpit.astro +37 -12
  136. package/apps/storefront/src/pages/dashboard/[appDomain]/team.astro +15 -11
  137. package/apps/storefront/src/pages/search.astro +1 -1
  138. package/apps/storefront/src/pages/sitemap.xml.ts +20 -0
  139. package/apps/storefront/src/pages/the-build/[slug].astro +129 -0
  140. package/apps/storefront/src/pages/the-build/index.astro +146 -0
  141. package/apps/storefront/src/pages/the-build/rss.xml.ts +33 -0
  142. package/apps/storefront/src/styles/admin.css +1080 -0
  143. package/apps/storefront/tsconfig.json +5 -0
  144. package/package.json +1 -1
  145. package/packages/public-runtime/package.json +1 -0
  146. package/packages/public-runtime/src/activity/catalog.ts +52 -0
  147. package/packages/public-runtime/src/catalog-d1.ts +1 -1
  148. package/packages/public-runtime/src/customization-preview.ts +25 -2
  149. package/packages/public-runtime/src/customization-runtime.ts +125 -3
  150. package/packages/public-runtime/src/customization-versioning.ts +10 -0
  151. package/packages/public-runtime/src/index.ts +1 -0
  152. package/packages/public-runtime/src/static-bundle.ts +357 -0
  153. package/packages/public-runtime/src/tenant.ts +36 -8
  154. package/scripts/build/copy-tenant-assets.mjs +14 -4
  155. package/scripts/dev/ai-edit.mjs +1 -1
  156. package/scripts/dev/checkout-watch.mjs +2 -2
  157. package/scripts/dev/file-browser.mjs +2 -4
  158. package/scripts/dev/file-writer.mjs +1 -1
  159. package/scripts/dev/git-status.mjs +2 -2
  160. package/scripts/dev/locate-handler.mjs +3 -3
  161. package/scripts/dev/port-check.mjs +3 -3
  162. package/scripts/dev/publish.mjs +5 -9
  163. package/scripts/dev/shot.mjs +1 -1
  164. package/scripts/dev/unified-diff.mjs +8 -3
  165. package/scripts/tot-dev.mjs +6 -9
  166. package/apps/storefront/src/lib/dev/vcBinding.ts +0 -80
@@ -15,6 +15,20 @@
15
15
  "when": 1787074116807,
16
16
  "tag": "0001_woozy_lyja",
17
17
  "breakpoints": true
18
+ },
19
+ {
20
+ "idx": 2,
21
+ "version": "6",
22
+ "when": 1787400126075,
23
+ "tag": "0002_good_switch",
24
+ "breakpoints": true
25
+ },
26
+ {
27
+ "idx": 3,
28
+ "version": "6",
29
+ "when": 1787403061681,
30
+ "tag": "0003_mute_marauders",
31
+ "breakpoints": true
18
32
  }
19
33
  ]
20
34
  }
@@ -42,11 +42,45 @@
42
42
  btn.title = "Re-send the sign-in email to " + m.developer;
43
43
  btn.addEventListener("click", () => resend(m.developer, btn));
44
44
  act.appendChild(btn);
45
+ if (m.inviteId) {
46
+ const revokeBtn = document.createElement("button");
47
+ revokeBtn.type = "button";
48
+ revokeBtn.className = "rowbtn";
49
+ revokeBtn.textContent = "Revoke";
50
+ revokeBtn.title = "Revoke " + m.developer + "'s access to this vendor";
51
+ revokeBtn.style.marginLeft = ".4rem";
52
+ revokeBtn.addEventListener("click", () => revoke(m.developer, m.inviteId, revokeBtn));
53
+ act.appendChild(revokeBtn);
54
+ }
45
55
  tr.appendChild(dev); tr.appendChild(roles); tr.appendChild(act);
46
56
  membersBody.appendChild(tr);
47
57
  }
48
58
  }
49
59
 
60
+ async function revoke(email, inviteId, btn) {
61
+ if (!confirm("Revoke " + email + "'s access to this vendor?")) return;
62
+ if (btn) btn.disabled = true;
63
+ showMsg("", "Revoking " + email + "'s access…");
64
+ try {
65
+ const res = await fetch("/api/grants/team-revoke", {
66
+ method: "POST",
67
+ headers: { "content-type": "application/json", accept: "application/json" },
68
+ body: JSON.stringify({ tenant, inviteId, email }),
69
+ });
70
+ const body = await res.json().catch(() => ({}));
71
+ if (res.ok) {
72
+ showMsg("ok", "Revoked " + email + "'s access.");
73
+ loadMembers();
74
+ } else {
75
+ showMsg("err", body.error || ("Couldn't revoke (HTTP " + res.status + ")."));
76
+ if (btn) btn.disabled = false;
77
+ }
78
+ } catch (e) {
79
+ showMsg("err", "Couldn't revoke: " + (e && e.message ? e.message : e));
80
+ if (btn) btn.disabled = false;
81
+ }
82
+ }
83
+
50
84
  async function resend(email, btn) {
51
85
  if (btn) btn.disabled = true;
52
86
  showMsg("", "Re-sending the sign-in email to " + email + "…");
@@ -104,8 +138,10 @@
104
138
  btn.disabled = true;
105
139
  showMsg("", "Sending…");
106
140
  try {
107
- // The role selector is present only for ToT staff (#8453); members are
108
- // developer-only. tot20 ignores a non-staff role, so sending it is harmless.
141
+ // The role selector always shows Developer + Contributor (a plain member may
142
+ // self-request Contributor tot20 honors it, handoff
143
+ // 2026-08-22-tot20-contributor-role); Admin/Owner render only for ToT staff
144
+ // (#8453) — tot20 ignores those two from a plain member and pins to developer.
109
145
  const roleEl = $("role");
110
146
  const role = roleEl && roleEl.value ? roleEl.value : undefined;
111
147
  const noteEl = $("note");
@@ -3,6 +3,9 @@
3
3
  * <Seo> — per-page title/meta, Open Graph, Twitter card, canonical, JSON-LD.
4
4
  * (brief §8). Tenant-aware: OG image + site name come from the resolved tenant.
5
5
  */
6
+ import { articleSeoMetaTags, type ArticleMeta } from "@/lib/seo/meta.js";
7
+ import { withXDefault, type Alternate } from "@/lib/seo/alternates.js";
8
+
6
9
  interface JsonLd {
7
10
  [key: string]: unknown;
8
11
  }
@@ -17,6 +20,25 @@ interface Props {
17
20
  noindex?: boolean;
18
21
  /** One or more JSON-LD graphs (Product, BreadcrumbList, Organization…). */
19
22
  jsonLd?: JsonLd | JsonLd[];
23
+ /** Alternate RSS/Atom feeds this page advertises (e.g. a collection's feed). */
24
+ feeds?: { title: string; href: string }[];
25
+ // --- B1.6 article SEO hardening (all additive/optional) ---
26
+ /** Open Graph `article:*` meta; emitted only when `ogType === "article"`. */
27
+ article?: ArticleMeta;
28
+ /** og:image:alt — accessible description of the OG image. */
29
+ imageAlt?: string;
30
+ imageWidth?: number;
31
+ imageHeight?: number;
32
+ twitterSite?: string;
33
+ twitterCreator?: string;
34
+ /** Syndication: when set, REPLACES the derived self-canonical (rel=canonical
35
+ * + og:url) so search engines point at the original. */
36
+ canonicalOverride?: string;
37
+ /** I2 — per-variant `hreflang` alternates for a translated article (self +
38
+ * siblings). When present and non-empty, emits one `<link rel="alternate">`
39
+ * per entry PLUS an `x-default`. Absent/empty ⇒ no alternate links (a
40
+ * singleton post is unchanged). */
41
+ alternates?: Alternate[];
20
42
  }
21
43
 
22
44
  const {
@@ -27,10 +49,29 @@ const {
27
49
  ogImage,
28
50
  noindex = false,
29
51
  jsonLd,
52
+ feeds = [],
53
+ article,
54
+ imageAlt,
55
+ imageWidth,
56
+ imageHeight,
57
+ twitterSite,
58
+ twitterCreator,
59
+ canonicalOverride,
60
+ alternates = [],
30
61
  } = Astro.props;
31
62
 
32
63
  const { tenant, canonicalBase } = Astro.locals;
33
- const canonical = new URL(path, canonicalBase + "/").toString();
64
+ const canonical =
65
+ canonicalOverride ?? new URL(path, canonicalBase + "/").toString();
66
+ const articleMeta = articleSeoMetaTags({
67
+ ogType,
68
+ article,
69
+ imageAlt,
70
+ imageWidth,
71
+ imageHeight,
72
+ twitterSite,
73
+ twitterCreator,
74
+ });
34
75
  // Don't double-append the brand: merchant SEO titles (title_tag) often already
35
76
  // end with the store name.
36
77
  const fullTitle = title.includes(tenant.displayName)
@@ -41,6 +82,7 @@ const image = ogImage
41
82
  : new URL(tenant.theme_tokens?.brand?.ogImage ?? "/brand/northwind-og.svg", canonicalBase + "/").toString();
42
83
 
43
84
  const graphs = jsonLd ? (Array.isArray(jsonLd) ? jsonLd : [jsonLd]) : [];
85
+ const alternateLinks = withXDefault(alternates);
44
86
  ---
45
87
 
46
88
  <title>{fullTitle}</title>
@@ -48,6 +90,18 @@ const graphs = jsonLd ? (Array.isArray(jsonLd) ? jsonLd : [jsonLd]) : [];
48
90
  <link rel="canonical" href={canonical} />
49
91
  {noindex && <meta name="robots" content="noindex,nofollow" />}
50
92
 
93
+ {
94
+ feeds.map((f) => (
95
+ <link rel="alternate" type="application/rss+xml" title={f.title} href={f.href} />
96
+ ))
97
+ }
98
+
99
+ {
100
+ alternateLinks.map((a) => (
101
+ <link rel="alternate" hreflang={a.hreflang} href={a.href} />
102
+ ))
103
+ }
104
+
51
105
  <meta property="og:type" content={ogType} />
52
106
  <meta property="og:site_name" content={tenant.displayName} />
53
107
  <meta property="og:title" content={fullTitle} />
@@ -60,6 +114,16 @@ const graphs = jsonLd ? (Array.isArray(jsonLd) ? jsonLd : [jsonLd]) : [];
60
114
  {description && <meta name="twitter:description" content={description} />}
61
115
  <meta name="twitter:image" content={image} />
62
116
 
117
+ {
118
+ articleMeta.map((t) =>
119
+ t.property ? (
120
+ <meta property={t.property} content={t.content} />
121
+ ) : (
122
+ <meta name={t.name} content={t.content} />
123
+ ),
124
+ )
125
+ }
126
+
63
127
  {
64
128
  graphs.map((g) => (
65
129
  <script