@rovela-ai/sdk 0.19.4 → 0.19.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.
Files changed (202) hide show
  1. package/docs/changelog/README.md +53 -0
  2. package/docs/changelog/epoch-01-chrome-consent.md +63 -0
  3. package/docs/changelog/epoch-02-platform-commerce.md +108 -0
  4. package/docs/changelog/epoch-03-i18n-files.md +72 -0
  5. package/docs/changelog/epoch-04-emails.md +65 -0
  6. package/docs/changelog/epoch-05-admin-experience.md +98 -0
  7. package/docs/changelog/epoch-06-mobile-integrity.md +72 -0
  8. package/docs/design/admin-ledger-visual-universe.html +1961 -0
  9. package/docs/design/admin-sidebar-and-band.html +542 -0
  10. package/package.json +3 -1
  11. package/templates/store-template/.claude/skills/add-section/SKILL.md +438 -0
  12. package/templates/store-template/.claude/skills/build-feature/SKILL.md +201 -0
  13. package/templates/store-template/.claude/skills/customize-theme/SKILL.md +167 -0
  14. package/templates/store-template/.claude/skills/debug-errors/SKILL.md +68 -0
  15. package/templates/store-template/.claude/skills/frontend-design/SKILL.md +176 -0
  16. package/templates/store-template/.claude/skills/generate-images/SKILL.md +115 -0
  17. package/templates/store-template/.claude/skills/manage-products/SKILL.md +187 -0
  18. package/templates/store-template/.claude/skills/override-sdk-component/SKILL.md +154 -0
  19. package/templates/store-template/.env.example +50 -0
  20. package/templates/store-template/.mcp.json +8 -0
  21. package/templates/store-template/.rovela/blueprint.example.json +190 -0
  22. package/templates/store-template/CLAUDE.md +14 -0
  23. package/templates/store-template/app/LayoutContent.tsx +106 -0
  24. package/templates/store-template/app/[...path]/page.tsx +79 -0
  25. package/templates/store-template/app/account/addresses/page.tsx +45 -0
  26. package/templates/store-template/app/account/layout.tsx +17 -0
  27. package/templates/store-template/app/account/orders/[id]/invoice/page.tsx +277 -0
  28. package/templates/store-template/app/account/orders/[id]/page.tsx +725 -0
  29. package/templates/store-template/app/account/orders/page.tsx +153 -0
  30. package/templates/store-template/app/account/page.tsx +184 -0
  31. package/templates/store-template/app/account/profile/page.tsx +434 -0
  32. package/templates/store-template/app/admin/(dashboard)/account/page.tsx +16 -0
  33. package/templates/store-template/app/admin/(dashboard)/analytics/events/page.tsx +14 -0
  34. package/templates/store-template/app/admin/(dashboard)/analytics/layout.tsx +48 -0
  35. package/templates/store-template/app/admin/(dashboard)/analytics/page.tsx +15 -0
  36. package/templates/store-template/app/admin/(dashboard)/analytics/visitors/page.tsx +14 -0
  37. package/templates/store-template/app/admin/(dashboard)/categories/[id]/page.tsx +38 -0
  38. package/templates/store-template/app/admin/(dashboard)/categories/new/page.tsx +35 -0
  39. package/templates/store-template/app/admin/(dashboard)/categories/page.tsx +223 -0
  40. package/templates/store-template/app/admin/(dashboard)/customers/[id]/page.tsx +26 -0
  41. package/templates/store-template/app/admin/(dashboard)/customers/page.tsx +33 -0
  42. package/templates/store-template/app/admin/(dashboard)/discounts/page.tsx +16 -0
  43. package/templates/store-template/app/admin/(dashboard)/emails/page.tsx +16 -0
  44. package/templates/store-template/app/admin/(dashboard)/files/page.tsx +16 -0
  45. package/templates/store-template/app/admin/(dashboard)/layout.tsx +44 -0
  46. package/templates/store-template/app/admin/(dashboard)/loading.tsx +88 -0
  47. package/templates/store-template/app/admin/(dashboard)/locations/page.tsx +16 -0
  48. package/templates/store-template/app/admin/(dashboard)/orders/[id]/page.tsx +66 -0
  49. package/templates/store-template/app/admin/(dashboard)/orders/page.tsx +26 -0
  50. package/templates/store-template/app/admin/(dashboard)/page.tsx +146 -0
  51. package/templates/store-template/app/admin/(dashboard)/payments/page.tsx +15 -0
  52. package/templates/store-template/app/admin/(dashboard)/products/[id]/page.tsx +38 -0
  53. package/templates/store-template/app/admin/(dashboard)/products/new/page.tsx +35 -0
  54. package/templates/store-template/app/admin/(dashboard)/products/page.tsx +31 -0
  55. package/templates/store-template/app/admin/(dashboard)/settings/page.tsx +46 -0
  56. package/templates/store-template/app/admin/(dashboard)/shipping/page.tsx +15 -0
  57. package/templates/store-template/app/admin/(dashboard)/tax/page.tsx +15 -0
  58. package/templates/store-template/app/admin/(dashboard)/users/[id]/page.tsx +114 -0
  59. package/templates/store-template/app/admin/(dashboard)/users/page.tsx +16 -0
  60. package/templates/store-template/app/admin/accept-invite/page.tsx +36 -0
  61. package/templates/store-template/app/admin/forgot-password/page.tsx +13 -0
  62. package/templates/store-template/app/admin/layout.tsx +47 -0
  63. package/templates/store-template/app/admin/login/page.tsx +528 -0
  64. package/templates/store-template/app/admin/reset-password/page.tsx +36 -0
  65. package/templates/store-template/app/api/account/addresses/[id]/route.ts +10 -0
  66. package/templates/store-template/app/api/account/addresses/route.ts +10 -0
  67. package/templates/store-template/app/api/account/change-password/route.ts +107 -0
  68. package/templates/store-template/app/api/account/orders/[id]/refund/route.ts +11 -0
  69. package/templates/store-template/app/api/account/orders/[id]/return/route.ts +14 -0
  70. package/templates/store-template/app/api/account/orders/[id]/route.ts +42 -0
  71. package/templates/store-template/app/api/account/orders/route.ts +29 -0
  72. package/templates/store-template/app/api/account/profile/route.ts +165 -0
  73. package/templates/store-template/app/api/admin/accept-invite/route.ts +11 -0
  74. package/templates/store-template/app/api/admin/analytics/events/route.ts +9 -0
  75. package/templates/store-template/app/api/admin/analytics/route.ts +10 -0
  76. package/templates/store-template/app/api/admin/analytics/visitors/route.ts +9 -0
  77. package/templates/store-template/app/api/admin/branding/favicon/route.ts +9 -0
  78. package/templates/store-template/app/api/admin/branding/logo/route.ts +9 -0
  79. package/templates/store-template/app/api/admin/categories/[id]/route.ts +9 -0
  80. package/templates/store-template/app/api/admin/categories/route.ts +9 -0
  81. package/templates/store-template/app/api/admin/check/route.ts +10 -0
  82. package/templates/store-template/app/api/admin/customer-groups/[id]/route.ts +10 -0
  83. package/templates/store-template/app/api/admin/customer-groups/route.ts +10 -0
  84. package/templates/store-template/app/api/admin/customers/[id]/addresses/[addressId]/route.ts +15 -0
  85. package/templates/store-template/app/api/admin/customers/[id]/addresses/route.ts +15 -0
  86. package/templates/store-template/app/api/admin/customers/[id]/route.ts +11 -0
  87. package/templates/store-template/app/api/admin/customers/bulk/route.ts +8 -0
  88. package/templates/store-template/app/api/admin/customers/route.ts +9 -0
  89. package/templates/store-template/app/api/admin/discounts/[id]/route.ts +11 -0
  90. package/templates/store-template/app/api/admin/discounts/route.ts +10 -0
  91. package/templates/store-template/app/api/admin/emails/preview/route.ts +4 -0
  92. package/templates/store-template/app/api/admin/emails/route.ts +5 -0
  93. package/templates/store-template/app/api/admin/emails/test/route.ts +4 -0
  94. package/templates/store-template/app/api/admin/files/route.ts +8 -0
  95. package/templates/store-template/app/api/admin/forgot-password/route.ts +7 -0
  96. package/templates/store-template/app/api/admin/linked-customer/route.ts +11 -0
  97. package/templates/store-template/app/api/admin/locations/[id]/route.ts +10 -0
  98. package/templates/store-template/app/api/admin/locations/route.ts +10 -0
  99. package/templates/store-template/app/api/admin/me/password/route.ts +13 -0
  100. package/templates/store-template/app/api/admin/me/route.ts +11 -0
  101. package/templates/store-template/app/api/admin/orders/[id]/refund/route.ts +7 -0
  102. package/templates/store-template/app/api/admin/orders/[id]/return/approve/route.ts +7 -0
  103. package/templates/store-template/app/api/admin/orders/[id]/return/reject/route.ts +7 -0
  104. package/templates/store-template/app/api/admin/orders/[id]/route.ts +9 -0
  105. package/templates/store-template/app/api/admin/orders/[id]/ship-with-shippo/route.ts +6 -0
  106. package/templates/store-template/app/api/admin/orders/[id]/shippo-rates/route.ts +6 -0
  107. package/templates/store-template/app/api/admin/orders/bulk/route.ts +8 -0
  108. package/templates/store-template/app/api/admin/orders/route.ts +9 -0
  109. package/templates/store-template/app/api/admin/payment-methods/[id]/route.ts +10 -0
  110. package/templates/store-template/app/api/admin/payment-methods/route.ts +10 -0
  111. package/templates/store-template/app/api/admin/products/[id]/route.ts +9 -0
  112. package/templates/store-template/app/api/admin/products/bulk/route.ts +9 -0
  113. package/templates/store-template/app/api/admin/products/route.ts +9 -0
  114. package/templates/store-template/app/api/admin/products/stats/route.ts +10 -0
  115. package/templates/store-template/app/api/admin/reset-password/route.ts +10 -0
  116. package/templates/store-template/app/api/admin/settings/route.ts +11 -0
  117. package/templates/store-template/app/api/admin/setup/route.ts +10 -0
  118. package/templates/store-template/app/api/admin/setup-guide/manual-mark/route.ts +13 -0
  119. package/templates/store-template/app/api/admin/setup-guide/route.ts +10 -0
  120. package/templates/store-template/app/api/admin/shipping/carriers/[id]/route.ts +9 -0
  121. package/templates/store-template/app/api/admin/shipping/carriers/route.ts +9 -0
  122. package/templates/store-template/app/api/admin/shipping/rates/[id]/route.ts +9 -0
  123. package/templates/store-template/app/api/admin/shipping/rates/route.ts +9 -0
  124. package/templates/store-template/app/api/admin/shipping/shippo/api-key/route.ts +1 -0
  125. package/templates/store-template/app/api/admin/shipping/shippo/validate/route.ts +1 -0
  126. package/templates/store-template/app/api/admin/shipping/zones/[id]/route.ts +9 -0
  127. package/templates/store-template/app/api/admin/shipping/zones/route.ts +9 -0
  128. package/templates/store-template/app/api/admin/stats/route.ts +9 -0
  129. package/templates/store-template/app/api/admin/stripe-status/route.ts +1 -0
  130. package/templates/store-template/app/api/admin/tax-zones/[id]/route.ts +7 -0
  131. package/templates/store-template/app/api/admin/tax-zones/route.ts +7 -0
  132. package/templates/store-template/app/api/admin/users/[id]/route.ts +14 -0
  133. package/templates/store-template/app/api/admin/users/route.ts +12 -0
  134. package/templates/store-template/app/api/admin-auth/[...nextauth]/route.ts +17 -0
  135. package/templates/store-template/app/api/analytics/track/route.ts +12 -0
  136. package/templates/store-template/app/api/auth/[...nextauth]/route.ts +19 -0
  137. package/templates/store-template/app/api/auth/forgot-password/route.ts +9 -0
  138. package/templates/store-template/app/api/auth/register/route.ts +9 -0
  139. package/templates/store-template/app/api/auth/resend-verification/route.ts +9 -0
  140. package/templates/store-template/app/api/auth/reset-password/route.ts +10 -0
  141. package/templates/store-template/app/api/auth/verify-email/route.ts +10 -0
  142. package/templates/store-template/app/api/categories/route.ts +10 -0
  143. package/templates/store-template/app/api/checkout/countries/route.ts +7 -0
  144. package/templates/store-template/app/api/checkout/discount/route.ts +9 -0
  145. package/templates/store-template/app/api/checkout/manual/route.ts +10 -0
  146. package/templates/store-template/app/api/checkout/payment-methods/route.ts +8 -0
  147. package/templates/store-template/app/api/checkout/pickup-locations/route.ts +8 -0
  148. package/templates/store-template/app/api/checkout/route.ts +10 -0
  149. package/templates/store-template/app/api/checkout/shipping/route.ts +21 -0
  150. package/templates/store-template/app/api/checkout/status/route.ts +10 -0
  151. package/templates/store-template/app/api/contact/route.ts +164 -0
  152. package/templates/store-template/app/api/media/presign/route.ts +7 -0
  153. package/templates/store-template/app/api/media/route.ts +7 -0
  154. package/templates/store-template/app/api/products/[slug]/route.ts +10 -0
  155. package/templates/store-template/app/api/products/route.ts +10 -0
  156. package/templates/store-template/app/api/store/settings/route.ts +12 -0
  157. package/templates/store-template/app/api/webhooks/stripe/route.ts +63 -0
  158. package/templates/store-template/app/auth/forgot-password/page.tsx +38 -0
  159. package/templates/store-template/app/auth/layout.tsx +17 -0
  160. package/templates/store-template/app/auth/reset-password/page.tsx +81 -0
  161. package/templates/store-template/app/auth/signin/page.tsx +62 -0
  162. package/templates/store-template/app/auth/signup/page.tsx +38 -0
  163. package/templates/store-template/app/auth/verify-email/page.tsx +185 -0
  164. package/templates/store-template/app/cart/page.tsx +137 -0
  165. package/templates/store-template/app/checkout/page.tsx +88 -0
  166. package/templates/store-template/app/checkout/success/page.tsx +50 -0
  167. package/templates/store-template/app/contact/layout.tsx +24 -0
  168. package/templates/store-template/app/contact/page.tsx +321 -0
  169. package/templates/store-template/app/faq/page.tsx +153 -0
  170. package/templates/store-template/app/globals.css +99 -0
  171. package/templates/store-template/app/layout.tsx +269 -0
  172. package/templates/store-template/app/not-found.tsx +35 -0
  173. package/templates/store-template/app/page.tsx +23 -0
  174. package/templates/store-template/app/privacy/page.tsx +281 -0
  175. package/templates/store-template/app/products/[slug]/ProductDetailClient.tsx +179 -0
  176. package/templates/store-template/app/products/[slug]/page.tsx +149 -0
  177. package/templates/store-template/app/products/layout.tsx +26 -0
  178. package/templates/store-template/app/products/page.tsx +102 -0
  179. package/templates/store-template/app/robots.ts +25 -0
  180. package/templates/store-template/app/sitemap.ts +76 -0
  181. package/templates/store-template/app/terms/page.tsx +313 -0
  182. package/templates/store-template/components/PathSyncBridge.tsx +61 -0
  183. package/templates/store-template/components/Providers.tsx +37 -0
  184. package/templates/store-template/components/layout/Footer.tsx +150 -0
  185. package/templates/store-template/components/layout/Header.tsx +162 -0
  186. package/templates/store-template/components/sections/.gitkeep +7 -0
  187. package/templates/store-template/components/sections/CTA.tsx +51 -0
  188. package/templates/store-template/components/sections/Features.tsx +91 -0
  189. package/templates/store-template/components/sections/Hero.tsx +85 -0
  190. package/templates/store-template/eslint.config.mjs +18 -0
  191. package/templates/store-template/lib/store-config.ts +77 -0
  192. package/templates/store-template/lib/store-policy.ts +68 -0
  193. package/templates/store-template/lib/utils.ts +21 -0
  194. package/templates/store-template/next-env.d.ts +6 -0
  195. package/templates/store-template/next.config.js +105 -0
  196. package/templates/store-template/package.json +32 -0
  197. package/templates/store-template/postcss.config.js +6 -0
  198. package/templates/store-template/proxy.ts +150 -0
  199. package/templates/store-template/public/rovela-logo.png +0 -0
  200. package/templates/store-template/tailwind.config.ts +74 -0
  201. package/templates/store-template/tsconfig.json +41 -0
  202. package/templates/store-template/types/next-auth.d.ts +32 -0
@@ -0,0 +1,53 @@
1
+ # Rovela SDK Changelog — written for agents
2
+
3
+ This directory is the knowledge base of the **store update system**. Its
4
+ readers are (1) Claude Code inside a store sandbox executing an SDK update,
5
+ and (2) the Rovela platform composing update prompts. It is NOT a
6
+ marketing changelog — every line exists to make an update decision correct.
7
+
8
+ ## How it is used
9
+
10
+ When a store updates from SDK vA to vB, the update prompt embeds every
11
+ epoch entry whose range overlaps (vA, vB]. Claude Code then:
12
+ 1. **Audits** the store: diffs its template-contract files against the
13
+ stock reference (`node_modules/@rovela-ai/sdk/templates/store-template/`)
14
+ and greps its custom code for each entry's hazards.
15
+ 2. **Plans** a store-specific migration (impact-classified).
16
+ 3. **Prepares** the store at the old SDK (both-version-compatible edits,
17
+ new files, DB pre-heals) — no build gate during this stage.
18
+ 4. **Bumps** the pin, installs, then drives `get_errors` + `npm run build`
19
+ to green and walks each entry's verification checklist.
20
+
21
+ ## Entry schema (every epoch/release file follows it)
22
+
23
+ ```
24
+ # EN <name> — <first version>..<last version>
25
+ ## What landed — one paragraph, merchant-meaningful
26
+ ## SDK-internal (free) — improvements a pin bump delivers with zero file changes
27
+ ## Template contract — files whose SHAPE moved; per file: the semantic
28
+ intent + what the stock shape provides. Apply by
29
+ INTENT, adapted to the store's customizations —
30
+ never by blind overwrite.
31
+ ## Behavior contracts — semantics that changed under existing APIs. THE
32
+ dangerous category for customized stores.
33
+ ## Custom-code hazards — concrete greps to run against the STORE'S OWN
34
+ code, with the fix for each hit.
35
+ ## DB — schema additions; whether each self-heals at
36
+ runtime (ensure*) or should be pre-applied.
37
+ ## New surfaces — admin routes/pages that exist in the stock
38
+ template but not in older stores; adopt them
39
+ through THIS store's structure (its dashboard
40
+ layout, its navItems), never by assuming stock.
41
+ ## Verify — the post-update checklist for this epoch.
42
+ ```
43
+
44
+ ## Authoring rules
45
+
46
+ - Dense, imperative, grep-anchored. No prose padding.
47
+ - Every hazard names the grep AND the fix.
48
+ - **Release ritual**: any SDK release that changes a template-contract file
49
+ or a behavior contract MUST add its entry here in the same change
50
+ (enforced by `scripts/check-prompts.sh` platform-side).
51
+ - Epoch files consolidate the pre-0.19.4 history; per-release files
52
+ (`v0.19.5.md`, …) accumulate going forward and get consolidated into a
53
+ new epoch when a range stabilizes.
@@ -0,0 +1,63 @@
1
+ # E1 Chrome & consent — 0.1.0..0.5.0
2
+
3
+ ## What landed
4
+ The store foundations: catalog/cart/checkout/admin baseline, zone-based tax,
5
+ returns/refunds, the 4-role admin user management with the two-cookie auth
6
+ split, cookie consent (EDPB), product videos, the reworked product list +
7
+ dashboard metrics + setup guide, and the (since-retired) storefront admin
8
+ bar.
9
+
10
+ ## SDK-internal (free via pin bump)
11
+ Everything the store thin-mounts: admin pages, checkout, cart, auth forms.
12
+ Later SDKs keep this entire era's imports working (AdminGuard, AdminLayout,
13
+ CartProvider, CartDrawer, StoreSettingsProvider, SignIn/SignUpForm…) with
14
+ ONE exception below.
15
+
16
+ ## Template contract
17
+ - `app/LayoutContent.tsx` — stores generated between SDK 0.3.13 and ~0.4.3
18
+ carry `import { AdminBarBanner } from '@rovela-ai/sdk/admin'` and mount
19
+ `<AdminBarBanner />` in the customer branch. **That export no longer
20
+ exists** (retired 2026-05-24). The store's provider tree may have been
21
+ customized — find the import + JSX wherever they live and REMOVE both
22
+ (the banner's job is covered by platform-side navigation now). This is
23
+ the ONLY hard compile break in the SDK's history.
24
+ - `app/layout.tsx` reads `findSettings()` for `cookieBannerEnabled`
25
+ (0.3.19+); stores older than that predate the cookie banner mount — the
26
+ changelog entries of LATER epochs describe the current LayoutContent
27
+ shape if you are adopting new providers.
28
+
29
+ ## Behavior contracts
30
+ - Two-cookie auth split (0.3.20): admin and customer sessions are separate
31
+ configs, separate cookies, separate endpoints (`/api/admin-auth/…` vs
32
+ `/api/auth/…`). Custom code assuming one unified session breaks — check
33
+ for direct NextAuth cookie reads.
34
+ - Discounts/tax in this era are the LEGACY Stripe-coupon surfaces. They
35
+ keep working after an update, but the native discounts engine (E2)
36
+ supersedes them as the merchant surface.
37
+
38
+ ## Custom-code hazards (greps)
39
+ - `grep -rn "AdminBarBanner" app/ components/` — remove import + JSX
40
+ wherever found (see Template contract). MUST be done for the build to
41
+ pass after the bump.
42
+ - `grep -rn "AdminHeader" app/ components/` — removed at 0.3.15; extremely
43
+ rare, replace with the current AdminLayout chrome if found.
44
+ - `grep -rn "next-auth" app/ components/ lib/ --include=*.tsx --include=*.ts | grep -v "@rovela"` —
45
+ custom direct NextAuth usage should go through the SDK's `useAuth` /
46
+ `useAdminSession`.
47
+
48
+ ## DB
49
+ `store_settings` (+ `cookie_banner_enabled`), admin user-management tables,
50
+ return/refund columns, tax zones — all present from this era or self-healed
51
+ by later SDKs' `ensure*` functions at their chokepoints. Nothing to
52
+ pre-apply manually.
53
+
54
+ ## New surfaces
55
+ This era already has: /admin products, customers, discounts (legacy
56
+ Stripe), tax, users, account, auth pages. Later epochs ADD analytics,
57
+ locations, files, emails — see their entries.
58
+
59
+ ## Verify
60
+ - Build passes with zero references to `AdminBarBanner`.
61
+ - Admin login works (two-cookie: signing into /admin does not affect a
62
+ customer session in the same browser).
63
+ - Storefront renders with the cookie banner if enabled in settings.
@@ -0,0 +1,108 @@
1
+ # E2 Storefront platform & commerce core — 0.5.2..0.9.2
2
+
3
+ ## What landed
4
+ First-party storefront analytics, path-bar sync, the storefront SEO/GEO
5
+ overhaul (canonical-host redirect, JSON-LD, per-store llms.txt), zone-native
6
+ free shipping — and the ENTIRE commerce core: server-priced checkout
7
+ (`buildQuote`), manual payment methods, the native discounts engine,
8
+ customer accounts/addresses/groups, click & collect, and group-gated
9
+ visibility.
10
+
11
+ ## SDK-internal (free via pin bump)
12
+ The analytics module (`AnalyticsProvider`, admin Dashboards/Events/Visitors
13
+ views), the whole checkout pricing core, payment-methods/discounts/groups/
14
+ locations managers, address book, `OrderTimeline`, bulk-selection
15
+ primitives. All mounted from the SDK — a pin bump delivers the machinery;
16
+ the NEW SURFACES below make it reachable.
17
+
18
+ ## Template contract
19
+ - `app/LayoutContent.tsx` — INTENT: the customer branch mounts
20
+ `<AnalyticsProvider>` (from `@rovela-ai/sdk/analytics`) INSIDE
21
+ `CookieConsentProvider` (consent-gated ingestion), wrapping
22
+ `<CartProvider>`. Also mounts `<PathSyncBridge />` (a small local client
23
+ component posting `rovela:navigation` to the platform iframe parent —
24
+ copy from the stock reference or create per its ~30-line contract).
25
+ - `proxy.ts` — CREATED in this epoch: canonical-host 308 redirect
26
+ (collapses `*.rovela.app`/`*.vercel.app` onto a verified custom domain;
27
+ inert without one). If the store has NO proxy.ts, add the stock one.
28
+ - `next.config.js` — adds a headers() rule serving `/llms.txt` as
29
+ markdown + noindex. Additive.
30
+ - `app/layout.tsx` — enriched Organization/WebSite JSON-LD. Additive;
31
+ adopt only if the store's layout is stock-shaped or the merchant wants
32
+ the SEO surfaces.
33
+
34
+ ## Behavior contracts
35
+ 1. **Checkout is server-priced (`buildQuote` is the ONLY money source).**
36
+ Client-submitted amounts/customerId/groupId are ignored or rejected
37
+ (`PricingError` → 4xx). Custom checkout code that POSTs its own totals
38
+ or passes `customerId` in the body must be reworked to let the server
39
+ price (catalog price + discounts + shipping + tax) and to rely on the
40
+ session for identity.
41
+ 2. **Native discounts replace Stripe coupons as the merchant surface.**
42
+ Legacy Stripe-coupon helpers still exist (feature-card usage) but the
43
+ admin Discounts manager + `/api/checkout/discount` are the system now.
44
+ 3. **`orders.payment_provider`** (default 'stripe') exists — custom order
45
+ readers must not assume every order is a Stripe order (manual methods
46
+ create `pending` orders with `manual_*` idempotency keys).
47
+ 4. **Free shipping is a PER-ZONE rate** (0.5.5). The global
48
+ `free_shipping_threshold` column is dormant/display-only — checkout no
49
+ longer injects a synthetic free-shipping line from it.
50
+ 5. Analytics ingestion is CONSENT-GATED — do not mount AnalyticsProvider
51
+ outside CookieConsentProvider.
52
+
53
+ ## Custom-code hazards (greps)
54
+ - `grep -rn "free_shipping_threshold\|freeShippingThreshold" app/ components/ lib/` —
55
+ any custom logic treating it as checkout-enforced must be re-pointed at
56
+ per-zone rates (a zero-price rate with min_order_amount).
57
+ - `grep -rn "customerId" app/checkout app/api/checkout components/checkout 2>/dev/null` —
58
+ custom checkout paths passing client identity must drop it (server
59
+ resolves via session).
60
+ - `grep -rn "createCheckoutSession\|/api/checkout" app/ components/ | grep -v node_modules` —
61
+ verify custom callers send items + selections only, never totals.
62
+ - `grep -rn "status === 'paid'\|paymentIntent" app/ components/ lib/` —
63
+ order readers should tolerate `payment_provider !== 'stripe'` and
64
+ `pending` manual orders.
65
+
66
+ ## DB (ALL self-heal — pre-applying the idempotent ALTERs is optional)
67
+ `analytics_events` (ensureAnalyticsTable) · `customer_addresses` +
68
+ `customers.phone/updated_at` (ensureCustomerAddressSchema) ·
69
+ `customer_groups` + `customers.group_id` (ensureCustomerGroupsSchema, wired
70
+ into every customer read incl. login) · `payment_methods` +
71
+ `orders.payment_provider/payment_method_*` (ensurePaymentMethodsSchema) ·
72
+ `discounts` + `discount_redemptions` (ensureDiscountsSchema) ·
73
+ `store_locations` + `orders.pickup_location_id` (ensureStoreLocationsSchema)
74
+ · `visible_to_groups` on payment_methods/shipping_rates/tax_zones
75
+ (ensureVisibilityColumns) · `store_settings.store_country`,
76
+ `orders.currency` snapshot.
77
+
78
+ ## New surfaces (thin mounts to ADD if absent, wired through THIS store's
79
+ dashboard layout + navItems — never assume stock structure)
80
+ - `/admin/analytics` (+ `/events`, `/visitors`, shared layout) and
81
+ `/api/admin/analytics/*` + `/api/analytics/track`
82
+ - `/admin/locations` + `/api/admin/locations/*` + `/api/checkout/pickup-locations`
83
+ - `/api/account/addresses*`, `/api/admin/customers/[id]/addresses*`
84
+ - `/api/admin/customer-groups*`, `/api/admin/payment-methods*`,
85
+ `/api/admin/discounts*`, `/api/checkout/{manual,payment-methods,discount}`
86
+ - `/api/admin/{customers,orders,products}/bulk`
87
+ (Each is a 1–15 line re-export of SDK handlers — see the stock reference.)
88
+
89
+ ## Existing components that gained dependencies (silent-degradation risk)
90
+ An SDK component the store ALREADY mounts now calls a NEW route — if that
91
+ route is missing the component renders but silently does nothing. These are
92
+ NOT "new surfaces" (the page already exists); they're new wiring under a page
93
+ you must not miss:
94
+ - `<PaymentSettings>` (admin payments page) now reads/writes
95
+ `/api/admin/payment-methods*` — without it the manual-methods manager loads
96
+ empty and saves fail.
97
+ - `<CheckoutFlow>` (storefront checkout) now calls
98
+ `/api/checkout/{manual,payment-methods,discount}` — without them the payment
99
+ step shows no manual methods and discount codes never validate.
100
+
101
+ ## Verify
102
+ - `/admin/analytics` renders its three tabs; a storefront visit with
103
+ consent accepted records an event.
104
+ - Checkout end-to-end: a cart prices server-side; a discount code
105
+ previews; the payment step shows Stripe (+ any manual methods).
106
+ - `/admin/locations` loads; storefront picks up pickup only when a
107
+ pickup-enabled location exists.
108
+ - Custom domain stores: apex/vercel hosts 308 to the canonical domain.
@@ -0,0 +1,72 @@
1
+ # E3 Languages & files — 0.10.0..0.13.1
2
+
3
+ ## What landed
4
+ Native multilingual storefronts (§61): path-prefix locale routing
5
+ (`/en/...`), key-symmetric UI catalogs, per-locale catalog content
6
+ overlays, hreflang alternates, the admin Languages toggle — plus the admin
7
+ files library (§60).
8
+
9
+ ## SDK-internal (free via pin bump)
10
+ The whole `core/i18n` module (`useT`/`getT`, `LocaleLink`/`useLocalePath`,
11
+ `LanguageSwitcher`, catalog overlay `localizeCatalogRow`), the
12
+ `@rovela-ai/sdk/locales` edge-safe subpath, `FilesManager` +
13
+ `MediaLibraryPicker`, the Settings → Languages control. A store that skips
14
+ the template migration stays single-language and loses nothing.
15
+
16
+ ## Template contract (the i18n adoption — the ONE structural migration)
17
+ Adopting multilingual requires reshaping three files BY INTENT:
18
+ - `proxy.ts` — parse a leading locale prefix (`/en|/fr…` from
19
+ `SUPPORTED_LOCALES` in `@rovela-ai/sdk/locales`), rewrite to the bare
20
+ path, and set `x-rovela-locale` / `x-rovela-geo-locale` /
21
+ `x-rovela-pathname` headers. `/api` and `/admin` are NEVER localized.
22
+ Keep the store's existing canonical-host logic intact.
23
+ - `app/layout.tsx` — resolve the request locale server-side
24
+ (`resolveStoreLocaleConfig`, `resolveRequestLocale`,
25
+ `resolveLocaleRedirect` from `@rovela-ai/sdk/core`; `localizedAlternates`
26
+ from `core/server`): 308 `permanentRedirect` for structural strips
27
+ (disabled/unknown/default-locale prefixes), temporary redirect for
28
+ preference hops; thread `locale`/`defaultLocale`/`enabledLocales` down.
29
+ - `app/LayoutContent.tsx` — accept those props and wrap the WHOLE tree in
30
+ `<RovelaLocaleProvider>` (OUTSIDE CookieConsentProvider). HYDRATION RULE
31
+ (load-bearing): locale config must come from these server-resolved props,
32
+ NEVER from a client fetch — a late fetch mis-resolves the default locale
33
+ at first paint and bounces hard loads of prefixed URLs.
34
+ If this store's layout/LayoutContent are heavily customized, graft the
35
+ locale resolution AROUND the customizations — the provider nesting order
36
+ and the server-threaded props are the contract; everything else is theirs.
37
+
38
+ ## Behavior contracts
39
+ - Internal links in multilingual stores go through `LocaleLink` /
40
+ `useLocalePath` — a bare `<Link href="/products">` drops the prefix.
41
+ - New user-visible strings on a multilingual store must exist in EVERY
42
+ enabled locale (store dictionary pattern — CLAUDE.md §5.5).
43
+ - Latent `formatPrice` hazard EXISTS IN THIS ERA'S SDK (integers > 100
44
+ treated as cents) — it is FIXED in E5; see E5's money contract for the
45
+ post-update behavior.
46
+ - Menu labels: a translated `section.name` now beats a hand-set
47
+ `meta.label`.
48
+
49
+ ## Custom-code hazards (greps)
50
+ - On stores adopting i18n: `grep -rn "href=\"/" app/ components/ | grep -v admin | grep -v api` —
51
+ storefront internal links should migrate to `LocaleLink` (mechanical but
52
+ wide; scope to nav/header/footer/product cards first).
53
+ - `grep -rn "useSearchParams\|usePathname" components/` — custom routing
54
+ logic may need the locale-stripped pathname (`x-rovela-pathname`).
55
+
56
+ ## DB (self-heal)
57
+ `products.translations` + `categories.translations`
58
+ (ensureCatalogTranslationsSchema) · `store_settings.default_locale` +
59
+ `enabled_locales` (settings ensure) · `orders.locale` / `customers.locale`.
60
+
61
+ ## New surfaces
62
+ - `/admin/files` + `/api/admin/files` (files library — thin mounts).
63
+ - Languages control lives INSIDE Settings (no new route).
64
+
65
+ ## Verify
66
+ - Single-language store post-update: storefront byte-identical behavior,
67
+ no locale prefixes anywhere.
68
+ - If multilingual was adopted: `/xx/products` renders translated UI, bare
69
+ paths serve the default locale, `/admin` and `/api` unaffected,
70
+ hreflang alternates emitted, hard-load of a prefixed checkout URL does
71
+ NOT bounce to the bare path.
72
+ - `/admin/files` lists the store's media.
@@ -0,0 +1,65 @@
1
+ # E4 Email editor — 0.14.0..0.15.2
2
+
3
+ ## What landed
4
+ The merchant email editor (§62): every transactional email brand-themed
5
+ from the store's blueprint, block-editable per language, testable, plus
6
+ merchant-created custom emails.
7
+
8
+ ## SDK-internal (free via pin bump)
9
+ The entire emails module rebuild: brand-derived shared theme (full Google
10
+ Fonts), block engine + registry, `prepareEmail` overrides at the send
11
+ boundary, FR localizer, `EmailsManager` admin UI. Existing email sends keep
12
+ working untouched — no `store_emails` row means byte-identical shipped
13
+ templates (fail-open by design).
14
+
15
+ ## Template contract
16
+ - `next.config.js` — MUST gain
17
+ `outputFileTracingIncludes: { '/**': ['./.rovela/blueprint.json'] }`.
18
+ WHY: the email theme reads the blueprint at runtime through a
19
+ bundler-invisible loader; without this line, Vercel functions that don't
20
+ statically import `core/config` ship WITHOUT the blueprint and merchant
21
+ emails silently render DEFAULT branding (fail-open, no crash — easy to
22
+ miss). Anchored insert into the existing config object; preserve
23
+ everything else in the store's next.config.
24
+ - New thin mounts: `app/admin/(dashboard)/emails/page.tsx` +
25
+ `app/api/admin/emails/{route,preview/route,test/route}.ts` — 1-line
26
+ re-exports; wire the nav entry through THIS store's `navItems`.
27
+
28
+ ## Behavior contracts
29
+ - The emails module graph must stay free of static node-builtin imports
30
+ (it is client-reachable via the auth barrel; a static `fs` import fails
31
+ `next build`). Relevant only if custom code imports from
32
+ `@rovela-ai/sdk/emails` into client components — don't.
33
+ - Email amounts are decimal STRINGS end-to-end; order numbers pass through
34
+ `bareOrderNumber()` (templates add their own `#`).
35
+
36
+ ## Custom-code hazards (greps)
37
+ - `grep -rn "from '@rovela-ai/sdk/emails" app/ components/ | grep -v "api/"` —
38
+ emails imports in client components are a build hazard; move to server.
39
+ - Stores with custom email senders: they keep working; the editor covers
40
+ registry emails only.
41
+
42
+ ## DB (self-heal)
43
+ `store_emails` table (ensureStoreEmailsSchema) ·
44
+ `store_settings.email_theme` (settings ensure).
45
+
46
+ ## New surfaces
47
+ `/admin/emails` (nav: Sales → Emails) + the three API mounts above.
48
+
49
+ ## Existing components that gained dependencies (silent-degradation risk)
50
+ - Every EXISTING transactional email sender (order confirmation, shipping,
51
+ admin invites…) now renders through the brand-derived theme, which reads
52
+ `.rovela/blueprint.json` at runtime. Without the `next.config.js`
53
+ `outputFileTracingIncludes` line (Template contract above), Vercel
54
+ functions that don't statically import `core/config` ship WITHOUT the
55
+ blueprint and emails silently fall back to DEFAULT branding — no error,
56
+ no crash, just unbranded emails. The store's email code needs zero
57
+ changes; the config line is the whole dependency.
58
+
59
+ ## Verify
60
+ - `/admin/emails` lists the registry; opening one renders a themed preview
61
+ (store colors/fonts, not default green).
62
+ - Send test delivers to the signed-in admin.
63
+ - AFTER PUBLISH (Vercel only): trigger any transactional email and confirm
64
+ it renders with the store's branding — this is the
65
+ outputFileTracingIncludes check; the sandbox can't prove it.
@@ -0,0 +1,98 @@
1
+ # E5 Admin experience — 0.15.3..0.18.7
2
+
3
+ ## What landed
4
+ The complete admin redesign ("LEDGER"): Shopify-style chrome (identity top
5
+ bar + nav-only sidebar), the branding architecture (R2-truth logo/favicon),
6
+ the save-bar and toast grammars, the auth-shell front door, the settings
7
+ correctness wave (timezone, store identity, currency, cookie-consent
8
+ configurator), and the consolidation kit (one modal, one empty state, one
9
+ search input, one pagination, one switch, one status badge).
10
+
11
+ ## SDK-internal (free via pin bump)
12
+ Everything above ships through SDK components stores already mount:
13
+ `AdminLayout`/`AdminNav`/`AdminTopBar` chrome, `AdminPageHeader`,
14
+ `AdminSaveBar`+`useDirtyState`, `adminToast`+`AdminToaster` (mounted by
15
+ AdminLayout), `AdminModal`/`DeleteConfirmDialog`/`DiscardChangesModal`,
16
+ `AdminEmptyState`/`AdminSearchInput`/`AdminPagination`/`AdminSwitch`/
17
+ `OrderStatusBadge`, `AdminAuthShell`, `BrandingAssetUpload` (logo+favicon),
18
+ `CookieBannerConfigurator`, the rebuilt Products/Orders/Customers tables,
19
+ dashboard metrics, `useAdminDates`. Old inline patterns keep compiling
20
+ (`AdminToast` component, `LogoUpload` remain exported for back-compat) —
21
+ they are DEPRECATED in favor of the kit but never break.
22
+
23
+ ## Template contract
24
+ - `app/admin/layout.tsx` — INTENT: the admin segment loads Plus Jakarta
25
+ Sans via `next/font` exposing `--admin-font-jakarta`, and declares
26
+ `export const viewport` (device-width) + `export const dynamic =
27
+ 'force-dynamic'` (admin is session-gated, never static; also silences a
28
+ benign per-page "Failed to read session" build-log block). Old stores
29
+ missing these exports still build — add them; they are additive.
30
+ - Admin auth pages (`app/admin/{login,forgot-password,reset-password,
31
+ accept-invite}/page.tsx`) — INTENT: thin mounts on the SDK's
32
+ `AdminAuthShell`-based forms. EXCEPTION: the login page's LoginForm/
33
+ SetupForm are deliberately INLINED in the template (platform postMessage
34
+ auto-login contract) — if this store's login page is the old inline
35
+ version it keeps working; update its JSX chrome only if adopting the new
36
+ look, and NEVER replace the inline forms with SDK imports.
37
+ - Branding: logo/favicon live at fixed R2 keys and mirror into
38
+ `store_settings.logo_url` / `favicon_url`; storefront + admin read
39
+ settings-first with env fallback.
40
+
41
+ ## Behavior contracts (READ CAREFULLY — the dangerous ones)
42
+ 1. **MONEY (0.18.1)**: `formatPrice` (emails + core) DROPPED the
43
+ integer-cents heuristic ("whole number > 100 means cents, divide by
44
+ 100"). Money is DECIMAL CURRENCY UNITS end-to-end (`29.99`), cents only
45
+ at the Stripe API boundary. A store whose custom code passes CENTS to
46
+ SDK formatters displayed correctly before and will display 100× after.
47
+ 2. **TIMEZONE (0.18.0)**: date rendering falls back to UTC (never
48
+ America/New_York); admin dates go through `useAdminDates` /
49
+ `formatDayLabel` in the STORE timezone; day-bucket queries use the store
50
+ timezone server-side.
51
+ 3. **Settings-first identity (0.17.0+)**: storeName/email/logo/favicon/
52
+ currency read LIVE from `store_settings` (`useStoreSettings` /
53
+ `findSettings`); `NEXT_PUBLIC_*` env is a build-time fallback only.
54
+ 4. **`orders.currency` snapshot**: order displays use the order's own
55
+ currency, not the store's current one.
56
+ 5. **Notification grammar**: events → `adminToast`; states → inline
57
+ `admin-alert`; document saves → the save bar morph (never a success
58
+ toast alongside it). Native `confirm()`/`alert()` are banned in admin.
59
+
60
+ ## Custom-code hazards (greps against THIS store's code)
61
+ - `grep -rn "formatPrice" app/ components/ lib/` — for each call site,
62
+ verify the value passed is decimal units. If the store stores/computes
63
+ cents anywhere outside a Stripe call, convert at the source (÷100 once,
64
+ where the cents enter) — do NOT reintroduce a display heuristic.
65
+ - `grep -rn "toLocaleString\|toLocaleDateString\|Intl.DateTimeFormat" app/admin components/` —
66
+ admin-facing dates hardcoding a locale/timezone should move to
67
+ `useAdminDates`.
68
+ - `grep -rn "NEXT_PUBLIC_STORE_LOGO_URL\|NEXT_PUBLIC_STORE_NAME" app/ components/` —
69
+ fine as fallbacks; if used as the ONLY source in custom components,
70
+ prefer `useStoreSettings()`.
71
+ - `grep -rn "<AdminToast\b" app/ components/` — old component still works;
72
+ when touching those files anyway, migrate outcomes to `adminToast`.
73
+ - Custom admin pages built by feature cards in this store: they keep
74
+ working, but any YOU touch during this update must follow CLAUDE.md §7.6
75
+ (kit components, admin tokens, no Loader2/Sparkles).
76
+
77
+ ## DB
78
+ `store_settings` gains `store_country`, `favicon_url`, `email_theme`,
79
+ `cookie_consent` (+ locale columns from E4). ALL self-heal via
80
+ `ensureStoreSettingsSchema` at the settings chokepoints — you MAY pre-run
81
+ `ALTER TABLE store_settings ADD COLUMN IF NOT EXISTS …` for each (idempotent)
82
+ so the first post-update request is clean, but it is not required.
83
+
84
+ ## New surfaces
85
+ None route-level in this epoch (chrome replaced in place). The auth pages'
86
+ new look ships via SDK; only adopt template-side JSX if the store's pages
87
+ are stock-shaped.
88
+
89
+ ## Verify
90
+ - Admin loads with the top bar + nav-only sidebar; store name and logo tile
91
+ render (skeletons while loading, never "Admin"/"A" placeholders).
92
+ - Open a product with a known price: displays the SAME amount as before
93
+ the update (the money-contract check — if it shows 100×, a custom call
94
+ site is passing cents).
95
+ - Order detail: dates in store timezone; totals in the order's currency.
96
+ - Settings page: edit a field → save bar rises; Save → morph; no double
97
+ toast.
98
+ - Login page still auto-logs-in from the platform (if you touched it).
@@ -0,0 +1,72 @@
1
+ # E6 Mobile + integrity — 0.19.0..0.19.4
2
+
3
+ ## What landed
4
+ The save-grammar completion across every admin manager, full mobile
5
+ responsiveness for the admin, the analytics views' migration onto admin
6
+ tokens, catalog schema self-heals that ended the fresh-store outage class,
7
+ and build-log hygiene.
8
+
9
+ ## SDK-internal (free via pin bump)
10
+ - Save bar everywhere it belongs (0.19.0): Discounts/Locations editors,
11
+ CustomerDetails edit, account profile, EmailsManager (per-locale drafts,
12
+ theme) — with `DiscardChangesModal` back-guards. ProductForm/CategoryForm
13
+ fixed: no phantom "Unsaved changes" on open (dirty baseline captured only
14
+ after the fetch), translations echoed so saves can't wipe them.
15
+ - Mobile (0.19.1): sidebar becomes an overlay drawer under 767px, modals
16
+ become bottom sheets under 640px, `admin-col-optional` columns hide under
17
+ 480px, `pointer: coarse` touch sizing, shared `scroll-lock`.
18
+ - Analytics views on admin tokens with stacked CompactTable rows (0.19.2);
19
+ Recent Orders is a stacked two-line list; Low Stock pairs 6 rows (0.19.3).
20
+ - Catalog ensures (0.19.2): `products.metafields` + `translations` and
21
+ `store_settings.public_metafield_keys` self-heal at read chokepoints —
22
+ older branches converge on first query.
23
+ - Session helpers rethrow Next's static-prerender bailout (0.19.4) instead
24
+ of logging it as a failure.
25
+
26
+ ## Template contract
27
+ - `app/admin/layout.tsx` — adds `export const dynamic = 'force-dynamic'`
28
+ (0.19.4) on top of E5's viewport/font. Additive; removes ~21 benign
29
+ "Failed to read session" blocks per build.
30
+ - `app/admin/(dashboard)/users/[id]/page.tsx` — the details grid became
31
+ `grid grid-cols-1 sm:grid-cols-2` (mobile). Apply the responsive prefix
32
+ if the store's copy is stock-shaped.
33
+ - `app/products/page.tsx` — one message per state: on `error`, render ONLY
34
+ the error banner and SKIP `<ProductGrid>` (its built-in empty state
35
+ doubled the message); when empty, pass the page's copy via the grid's
36
+ `emptyState` prop and delete the standalone empty block. This page is
37
+ often customized — apply the INTENT (mutually exclusive error/empty
38
+ branches), not the stock markup. If the store's version already branches
39
+ exclusively, leave it.
40
+
41
+ ## Behavior contracts
42
+ - A `<table>` never sits bare in a card: 2–4 column cards use stacked row
43
+ lists; dense tables get `overflow-x-auto` wrappers + `admin-col-optional`.
44
+ Applies to any custom admin page you touch.
45
+ - Custom admin pages must hold at 375px (CLAUDE.md §7.6 mobile rules).
46
+
47
+ ## Custom-code hazards
48
+ - `grep -rn "text-muted-foreground\|bg-card\|border-border" app/admin/` —
49
+ storefront tokens inside custom admin pages render against the merchant
50
+ theme and now visibly clash with the admin system; migrate hits you touch
51
+ to `hsl(var(--admin-*))` / `admin-*` classes.
52
+ - `grep -rn "body.style.overflow" app/ components/` — custom overlays must
53
+ not lock scroll directly; use the SDK's shared lock (AdminModal has it
54
+ built in).
55
+ - Custom pages with `<table>` in small cards: check them at 375px.
56
+
57
+ ## DB
58
+ Nothing new; 0.19.2's ensures ADD `metafields`/`translations`/
59
+ `public_metafield_keys` on older branches automatically. Pre-running the
60
+ idempotent ALTERs is optional.
61
+
62
+ ## New surfaces
63
+ None.
64
+
65
+ ## Verify
66
+ - Resize the admin to 375px: drawer opens from the hamburger, closes on
67
+ scrim/Escape; a delete dialog docks as a bottom sheet; Products table
68
+ scrolls itself (page never scrolls horizontally); Recent Orders shows
69
+ stacked rows.
70
+ - Storefront `/products`: exactly ONE message in the error state and ONE
71
+ when no products match.
72
+ - `npm run build` log: zero "Failed to read session" blocks.