@open-mercato/cli 0.6.7-develop.6677.1.beabb7ca12 → 0.6.7-develop.6686.1.bdda5ed397

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 (211) hide show
  1. package/.turbo/turbo-build.log +0 -1
  2. package/build.mjs +21 -5
  3. package/dist/agentic/claude-code/hooks/entity-migration-check.ts +32 -88
  4. package/dist/agentic/codex/enforcement-rules.md +2 -16
  5. package/dist/agentic/cursor/hooks/entity-migration-check.mjs +19 -50
  6. package/dist/agentic/cursor/rules/entity-guard.mdc +9 -21
  7. package/dist/agentic/cursor/rules/generated-guard.mdc +3 -5
  8. package/dist/agentic/cursor/rules/open-mercato.mdc +3 -29
  9. package/dist/agentic/guides/ai-workflows.md +76 -0
  10. package/dist/agentic/guides/architecture.md +107 -0
  11. package/dist/agentic/guides/backend-ui.md +80 -0
  12. package/dist/agentic/guides/contracts.md +92 -0
  13. package/dist/agentic/guides/extensions.md +104 -0
  14. package/dist/agentic/guides/integrations.md +81 -0
  15. package/dist/agentic/guides/module-facts.json +217 -81
  16. package/dist/agentic/guides/module-system.md +12 -127
  17. package/dist/agentic/guides/modules/ai_assistant.md +1 -1
  18. package/dist/agentic/guides/modules/api_docs.md +1 -1
  19. package/dist/agentic/guides/modules/api_keys.md +1 -1
  20. package/dist/agentic/guides/modules/attachments.md +2 -2
  21. package/dist/agentic/guides/modules/audit_logs.md +2 -2
  22. package/dist/agentic/guides/modules/auth.md +1 -1
  23. package/dist/agentic/guides/modules/business_rules.md +1 -1
  24. package/dist/agentic/guides/modules/catalog.md +5 -5
  25. package/dist/agentic/guides/modules/channel_gmail.md +1 -1
  26. package/dist/agentic/guides/modules/channel_imap.md +1 -1
  27. package/dist/agentic/guides/modules/checkout.md +1 -1
  28. package/dist/agentic/guides/modules/communication_channels.md +1 -1
  29. package/dist/agentic/guides/modules/configs.md +1 -1
  30. package/dist/agentic/guides/modules/content.md +1 -1
  31. package/dist/agentic/guides/modules/currencies.md +1 -1
  32. package/dist/agentic/guides/modules/customer_accounts.md +1 -1
  33. package/dist/agentic/guides/modules/customers.md +2 -2
  34. package/dist/agentic/guides/modules/dashboards.md +1 -1
  35. package/dist/agentic/guides/modules/data_sync.md +1 -1
  36. package/dist/agentic/guides/modules/dictionaries.md +1 -1
  37. package/dist/agentic/guides/modules/directory.md +1 -1
  38. package/dist/agentic/guides/modules/entities.md +2 -2
  39. package/dist/agentic/guides/modules/events.md +1 -1
  40. package/dist/agentic/guides/modules/feature_toggles.md +1 -1
  41. package/dist/agentic/guides/modules/gateway_stripe.md +1 -1
  42. package/dist/agentic/guides/modules/generators.md +1 -1
  43. package/dist/agentic/guides/modules/inbox_ops.md +1 -1
  44. package/dist/agentic/guides/modules/integrations.md +1 -1
  45. package/dist/agentic/guides/modules/messages.md +1 -1
  46. package/dist/agentic/guides/modules/notifications.md +1 -1
  47. package/dist/agentic/guides/modules/onboarding.md +1 -1
  48. package/dist/agentic/guides/modules/payment_gateways.md +1 -1
  49. package/dist/agentic/guides/modules/perspectives.md +1 -1
  50. package/dist/agentic/guides/modules/planner.md +1 -1
  51. package/dist/agentic/guides/modules/portal.md +1 -1
  52. package/dist/agentic/guides/modules/progress.md +1 -1
  53. package/dist/agentic/guides/modules/query_index.md +2 -2
  54. package/dist/agentic/guides/modules/record_locks.md +1 -1
  55. package/dist/agentic/guides/modules/resources.md +1 -1
  56. package/dist/agentic/guides/modules/sales.md +17 -17
  57. package/dist/agentic/guides/modules/scheduler.md +1 -1
  58. package/dist/agentic/guides/modules/search.md +1 -1
  59. package/dist/agentic/guides/modules/security.md +1 -1
  60. package/dist/agentic/guides/modules/shipping_carriers.md +1 -1
  61. package/dist/agentic/guides/modules/sso.md +1 -1
  62. package/dist/agentic/guides/modules/staff.md +2 -2
  63. package/dist/agentic/guides/modules/storage_s3.md +1 -1
  64. package/dist/agentic/guides/modules/sync_akeneo.md +1 -1
  65. package/dist/agentic/guides/modules/sync_excel.md +1 -1
  66. package/dist/agentic/guides/modules/system_status_overlays.md +1 -1
  67. package/dist/agentic/guides/modules/translations.md +1 -1
  68. package/dist/agentic/guides/modules/webhooks.md +2 -2
  69. package/dist/agentic/guides/modules/wms.md +2 -2
  70. package/dist/agentic/guides/modules/workflows.md +1 -1
  71. package/dist/agentic/guides/testing-debugging.md +74 -0
  72. package/dist/agentic/guides/upstream/AGENTS.md +297 -0
  73. package/dist/agentic/guides/upstream/BACKWARD_COMPATIBILITY.md +303 -0
  74. package/dist/agentic/guides/upstream/manifest.json +8 -0
  75. package/dist/agentic/shared/AGENTS.md.template +123 -311
  76. package/dist/agentic/shared/ai/agentic.config.json +1 -0
  77. package/dist/agentic/shared/ai/harness/README.md +48 -0
  78. package/dist/agentic/shared/ai/harness/RELEASE.md +57 -0
  79. package/dist/agentic/shared/ai/harness/cases.json +13487 -0
  80. package/dist/agentic/shared/ai/harness/cases.schema.json +132 -0
  81. package/dist/agentic/shared/ai/harness/fixtures/index.json +49 -0
  82. package/dist/agentic/shared/ai/harness/fixtures/seeds.json +162 -0
  83. package/dist/agentic/shared/ai/harness/generated-code-review-policy.md +20 -0
  84. package/dist/agentic/shared/ai/harness/generated-code-review-response.schema.json +43 -0
  85. package/dist/agentic/shared/ai/harness/generated-code-review-result.schema.json +110 -0
  86. package/dist/agentic/shared/ai/harness/release-matrix.json +133 -0
  87. package/dist/agentic/shared/ai/harness/release-result.schema.json +219 -0
  88. package/dist/agentic/shared/ai/harness/result.schema.json +76 -0
  89. package/dist/agentic/shared/ai/harness/routing-response.schema.json +12 -0
  90. package/dist/agentic/shared/ai/harness/target-validation-result.schema.json +73 -0
  91. package/dist/agentic/shared/ai/harness/validators.json +78 -0
  92. package/dist/agentic/shared/ai/harness/writable-ast-oracles.mjs +1768 -0
  93. package/dist/agentic/shared/ai/harness/writable-behavior-oracles.mjs +1096 -0
  94. package/dist/agentic/shared/ai/review-checklist.md +36 -0
  95. package/dist/agentic/shared/ai/skills/om-auto-review-pr/SKILL.md +4 -0
  96. package/dist/agentic/shared/ai/skills/om-backend-ui-design/SKILL.md +20 -241
  97. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/crud-surfaces.md +16 -0
  98. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/frontend-and-design-system.md +53 -0
  99. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/page-and-navigation.md +13 -0
  100. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/quality-states.md +11 -0
  101. package/dist/agentic/shared/ai/skills/om-build-workflow/SKILL.md +30 -0
  102. package/dist/agentic/shared/ai/skills/om-build-workflow/references/activity-contracts.md +12 -0
  103. package/dist/agentic/shared/ai/skills/om-build-workflow/references/durability-and-progress.md +13 -0
  104. package/dist/agentic/shared/ai/skills/om-build-workflow/references/workflow-design.md +14 -0
  105. package/dist/agentic/shared/ai/skills/om-create-ai-agent/SKILL.md +28 -0
  106. package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/attachments-and-overrides.md +12 -0
  107. package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/module-agents-and-tools.md +22 -0
  108. package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/orchestrator-agents.md +12 -0
  109. package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/surface-selector.md +19 -0
  110. package/dist/agentic/shared/ai/skills/om-data-model-design/SKILL.md +16 -601
  111. package/dist/agentic/shared/ai/skills/om-data-model-design/references/integrity-and-concurrency.md +19 -0
  112. package/dist/agentic/shared/ai/skills/om-data-model-design/references/migration-workflow.md +13 -0
  113. package/dist/agentic/shared/ai/skills/om-data-model-design/references/schema-design.md +14 -0
  114. package/dist/agentic/shared/ai/skills/om-data-model-design/references/sensitive-data.md +10 -0
  115. package/dist/agentic/shared/ai/skills/om-eject-and-customize/SKILL.md +14 -310
  116. package/dist/agentic/shared/ai/skills/om-eject-and-customize/references/decision-and-procedure.md +17 -0
  117. package/dist/agentic/shared/ai/skills/om-evolve-harness/SKILL.md +28 -0
  118. package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-template.md +89 -0
  119. package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-workflow.md +16 -0
  120. package/dist/agentic/shared/ai/skills/om-evolve-harness/references/owner-selection.md +17 -0
  121. package/dist/agentic/shared/ai/skills/om-framework-context/SKILL.md +25 -0
  122. package/dist/agentic/shared/ai/skills/om-framework-context/references/resolver-procedure.md +11 -0
  123. package/dist/agentic/shared/ai/skills/om-framework-context/references/skew-and-escalation.md +13 -0
  124. package/dist/agentic/shared/ai/skills/om-help/SKILL.md +15 -97
  125. package/dist/agentic/shared/ai/skills/om-help/references/delivery-workflows.md +17 -0
  126. package/dist/agentic/shared/ai/skills/om-help/references/task-families.md +20 -0
  127. package/dist/agentic/shared/ai/skills/om-implement-spec/SKILL.md +15 -156
  128. package/dist/agentic/shared/ai/skills/om-implement-spec/references/phases-and-gates.md +12 -0
  129. package/dist/agentic/shared/ai/skills/om-integration-builder/SKILL.md +24 -708
  130. package/dist/agentic/shared/ai/skills/om-integration-builder/references/package-and-activation.md +16 -0
  131. package/dist/agentic/shared/ai/skills/om-integration-builder/references/provider-families.md +14 -0
  132. package/dist/agentic/shared/ai/skills/om-integration-builder/references/security-and-reliability.md +15 -0
  133. package/dist/agentic/shared/ai/skills/om-integration-builder/references/sync-and-files.md +12 -0
  134. package/dist/agentic/shared/ai/skills/om-module-scaffold/SKILL.md +20 -820
  135. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/api-and-domain.md +19 -0
  136. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/business-one-shot-blueprints.md +107 -0
  137. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/data-and-migrations.md +12 -0
  138. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/discovery-surface-catalog.md +83 -0
  139. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/module-surfaces.md +21 -0
  140. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/planning.md +11 -0
  141. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/runtime-cache-and-queues.md +22 -0
  142. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/verification.md +13 -0
  143. package/dist/agentic/shared/ai/skills/om-system-extension/SKILL.md +19 -843
  144. package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-branches.md +18 -0
  145. package/dist/agentic/shared/ai/skills/om-system-extension/references/mechanism-selector.md +25 -0
  146. package/dist/agentic/shared/ai/skills/om-system-extension/references/read-write-roundtrip.md +13 -0
  147. package/dist/agentic/shared/ai/skills/om-system-extension/references/unified-overrides.md +38 -0
  148. package/dist/agentic/shared/ai/skills/om-system-extension/references/verification.md +11 -0
  149. package/dist/agentic/shared/ai/skills/om-trim-unused-modules/SKILL.md +15 -63
  150. package/dist/agentic/shared/ai/skills/om-trim-unused-modules/references/dependency-and-redirect.md +15 -0
  151. package/dist/agentic/shared/ai/skills/om-troubleshooter/SKILL.md +16 -467
  152. package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnosis-map.md +16 -0
  153. package/dist/agentic/shared/ai/skills/om-troubleshooter/references/regression-oracles.md +14 -0
  154. package/dist/agentic/shared/ai/skills/tiers.json +137 -20
  155. package/dist/agentic/shared/ai/skills/tiers.schema.json +52 -40
  156. package/dist/agentic/shared/scripts/agent-harness-tool-server.mjs +174 -0
  157. package/dist/agentic/shared/scripts/evaluate-agent-harness.mjs +2783 -0
  158. package/dist/agentic/shared/scripts/execution-sandbox.mjs +329 -0
  159. package/dist/agentic/shared/scripts/framework-context.mjs +894 -0
  160. package/dist/agentic/shared/scripts/install-skills.mjs +1029 -0
  161. package/dist/agentic/shared/scripts/install-skills.sh +4 -694
  162. package/dist/agentic/shared/scripts/prepare-agent-harness-fixture.mjs +222 -0
  163. package/dist/agentic/shared/scripts/run-agent-harness-release.mjs +1761 -0
  164. package/dist/lib/__integration__/TC-INT-008.spec.js +87 -8
  165. package/dist/lib/__integration__/TC-INT-008.spec.js.map +2 -2
  166. package/dist/lib/agentic-init.js +13 -3
  167. package/dist/lib/agentic-init.js.map +2 -2
  168. package/dist/lib/agentic-setup.js +418 -186
  169. package/dist/lib/agentic-setup.js.map +2 -2
  170. package/dist/lib/generators/module-facts-discovery.js +41 -7
  171. package/dist/lib/generators/module-facts-discovery.js.map +2 -2
  172. package/dist/lib/generators/module-facts.js +65 -17
  173. package/dist/lib/generators/module-facts.js.map +2 -2
  174. package/dist/lib/generators/module-registry.js +5 -4
  175. package/dist/lib/generators/module-registry.js.map +2 -2
  176. package/dist/lib/resolver.js +2 -0
  177. package/dist/lib/resolver.js.map +2 -2
  178. package/package.json +5 -5
  179. package/src/lib/__integration__/TC-INT-008.spec.ts +103 -8
  180. package/src/lib/__tests__/agentic-init.test.ts +41 -5
  181. package/src/lib/__tests__/agentic-setup.ownership.test.ts +380 -0
  182. package/src/lib/agentic-init.ts +15 -3
  183. package/src/lib/agentic-setup.ts +526 -224
  184. package/src/lib/generators/__tests__/module-facts.bc-guard.test.ts +6 -0
  185. package/src/lib/generators/__tests__/module-facts.customers.fixture.test.ts +1 -0
  186. package/src/lib/generators/__tests__/module-facts.discovery.test.ts +54 -10
  187. package/src/lib/generators/__tests__/module-facts.extension-hosts.test.ts +108 -0
  188. package/src/lib/generators/__tests__/module-subset.test.ts +18 -0
  189. package/src/lib/generators/module-facts-discovery.ts +58 -7
  190. package/src/lib/generators/module-facts.ts +84 -20
  191. package/src/lib/generators/module-registry.ts +8 -4
  192. package/src/lib/resolver.ts +3 -0
  193. package/dist/agentic/guides/cache.md +0 -45
  194. package/dist/agentic/guides/core.md +0 -453
  195. package/dist/agentic/guides/events.md +0 -117
  196. package/dist/agentic/guides/queue.md +0 -53
  197. package/dist/agentic/guides/search.md +0 -115
  198. package/dist/agentic/guides/shared.md +0 -108
  199. package/dist/agentic/guides/ui.md +0 -347
  200. package/dist/agentic/shared/ai/skills/om-auto-continue-pr-loop/SKILL.md +0 -27
  201. package/dist/agentic/shared/ai/skills/om-auto-create-pr-loop/SKILL.md +0 -27
  202. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/ui-components.md +0 -260
  203. package/dist/agentic/shared/ai/skills/om-data-model-design/references/mikro-orm-cheatsheet.md +0 -146
  204. package/dist/agentic/shared/ai/skills/om-help/references/skills-catalog.md +0 -84
  205. package/dist/agentic/shared/ai/skills/om-help/references/workflow-sequences.md +0 -193
  206. package/dist/agentic/shared/ai/skills/om-integration-builder/STANDALONE.md +0 -34
  207. package/dist/agentic/shared/ai/skills/om-integration-builder/references/adapter-contracts.md +0 -762
  208. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/naming-conventions.md +0 -50
  209. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/navigation-patterns.md +0 -97
  210. package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-contracts.md +0 -271
  211. package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnostic-commands.md +0 -101
@@ -0,0 +1,80 @@
1
+ # Pages, CRUD UI, Navigation, and i18n
2
+
3
+ Use shared backend/page primitives and keep UI behavior aligned with API scope, locking, and extension hosts.
4
+
5
+ ## When This Guide Applies
6
+
7
+ `backend-ui` is additive and rarely the only route: select it with the route owning the code — `umes` for an installed module's surface, `module-data` when the app owns it — whenever the task authors, restyles, or permission-gates a rendered surface this app owns or injected. Not for hiding, toggling, disabling, or rewiring a surface an installed module owns, and not for payload text, pagination, or table IDs.
8
+
9
+ ## Page Selection
10
+
11
+ Every app page is module-owned and auto-discovered: author it under `src/modules/<id>/{backend,frontend}/**/page.tsx` and run `yarn generate` so it registers into the route registry served by the app's `(backend)`/`(frontend)` catch-all. Never place a `page.tsx`/`page.meta.ts` directly under `src/app/(backend)/**` or `src/app/(frontend)/**` — a page added to the Next.js route group instead of the module renders unregistered, skipping nav injection, ACL feature-gating, and breadcrumbs. The paths below are all relative to the owning `src/modules/<id>/`.
12
+
13
+ | Page | Location and rules |
14
+ |---|---|
15
+ | Backend list/detail/create/edit | `src/modules/<id>/backend/**/page.tsx` plus sibling `page.meta.ts`; require staff auth/features. |
16
+ | Settings | Backend metadata with `pageContext: 'settings' as const` and `navHidden: true`. |
17
+ | Profile | Backend metadata with `pageContext: 'profile' as const`. |
18
+ | Public frontend | `src/modules/<id>/frontend/**/page.tsx`; explicitly declare auth posture in metadata. |
19
+ | Customer portal | `src/modules/<id>/frontend/[orgSlug]/portal/**/page.tsx`; public login/signup/verify/landing pages are `navHidden` without customer auth, authenticated pages require customer auth/features, and only sidebar destinations add `nav`. |
20
+
21
+ List destinations need stable `pageGroup`, `pageGroupKey`, and order. Prefer a registered string icon name in `page.meta.ts` so generated metadata stays serializable; use `lucide-react` components in page-body UI. Hide create/edit/detail destinations from navigation when they are reached from a list.
22
+
23
+ ## Default CRUD Completeness
24
+
25
+ For a new editable entity or module, unless the brief explicitly excludes an operation, deliver list, create, view/edit, and delete as one connected slice. The `DataTable` list owns server filter/search controls, a localized add action linking to create, and a stable linked row action to view/edit. `CrudForm` owns create/update/delete, custom-field save/reload/clear, `updatedAt` conflicts, and return navigation. Do not leave a new backend entity reachable only by typing a URL.
26
+
27
+ ## DataTable
28
+
29
+ - Use `DataTable` with stable colon-form `entityId`, `apiPath`, and `extensionTableId`. These are host contracts, not cosmetic props.
30
+ - Use shared column helpers, `RowActions` with stable action IDs, built-in filter/search/export/column controls, and DataTable bulk-action surfaces.
31
+ - When owning pagination, wire page, page size, total count, and change handlers together. Do not slice a server page again in the client.
32
+ - Use the table's empty state and shared loading/error components. A successful empty result is not an error.
33
+ - Route selected-row and long-running operations through guarded mutations and progress contracts; do not loop direct API writes without cancellation/error reporting.
34
+
35
+ ## CrudForm
36
+
37
+ - Use `CrudForm`, typed fields/groups, and `createCrud`/`updateCrud`/`deleteCrud`; use the shared server-error adapter.
38
+ - Pass detail data including `updatedAt` as `initialValues`, allowing the form to protect update and delete automatically.
39
+ - Keep field IDs aligned through request validators, commands, response transforms, custom-field widgets, and translations.
40
+ - Support explicit `null` clearing where the field is clearable; avoid truthy fallbacks that resurrect the old value.
41
+ - Use `crud-form:<entityId>:fields` for injected fields and ensure the read/enricher and save/interceptor paths round-trip the same value.
42
+ - Use shared conflict surfacing for non-`CrudForm` writes.
43
+
44
+ ## Data Access and States
45
+
46
+ - Use `apiCall`/`apiCallOrThrow`; use scoped API headers for versions or other request context. Never call raw `fetch` from app backend UI.
47
+ - Use `LoadingMessage`, `ErrorMessage`, `EmptyState`, `Alert`, flash messages, and the standard page/form scaffolding.
48
+ - Preserve the user's input after validation/server errors. Disable duplicate submissions and expose retry only when the operation is safe.
49
+ - Every dialog supports Cmd/Ctrl+Enter submit and Escape cancel. Every icon-only control has an accessible label.
50
+ - Keep server/client locale, timezone, and environment-derived initial render deterministic to prevent hydration mismatches.
51
+
52
+ ## Navigation and Overrides
53
+
54
+ - Prefer page metadata for app-owned destinations and menu injection for adding/reordering items owned by another module.
55
+ - Use stable menu item IDs and translation keys. Gate injected items with wildcard-aware ACL checks.
56
+ - Hide or replace installed pages through `src/modules.ts` page overrides; do not delete package code or add a competing route accidentally.
57
+ - If disabling the dashboards module, update the backend landing page to redirect to the first accessible enabled destination, falling back to profile only when necessary.
58
+
59
+ ## Design-System Contract
60
+
61
+ - For public/portal or visually substantial app work, use `om-backend-ui-design` → `references/frontend-and-design-system.md` for route-shell, product hierarchy, responsive, accessibility, and UX-state coverage.
62
+ - Reuse existing page, section, form, detail, schedule, messages, notification, chart, KPI, and banner component families before building a local variant.
63
+ - Use semantic design tokens and `StatusBadge` for status. Do not hard-code Tailwind status colors or arbitrary text sizes.
64
+ - Use `FormField` for standalone forms; `CrudForm` owns field layout and must not be wrapped in it. Use `SectionHeader`, `CollapsibleSection`, standard buttons/dialogs, and Lucide icons.
65
+ - Portal record lists use `DataTable`. Never use raw buttons/checkboxes, a button-styled raw `Link`, or `window.confirm`; use the exported primitives and `useConfirmDialog`.
66
+ - Keep responsive behavior, keyboard navigation, focus order, contrast, and reduced-motion behavior intact.
67
+
68
+ ## Translation Contract
69
+
70
+ - Use `useT()` in client components and `resolveTranslations()` on the server.
71
+ - Put app translations in module/app locale files using stable namespaced keys. Translate titles, actions, placeholders, validation, empty/error states, notifications, and navigation.
72
+ - Declare `translations.ts` only for entity fields that use the Translation Manager and run `yarn generate` after changing it.
73
+ - Do not place translated output in stable machine identifiers, API enums, logs, or provider protocol values.
74
+
75
+ ## Verification
76
+
77
+ 1. Exercise permitted and forbidden roles, including wildcard grants.
78
+ 2. Exercise loading, empty, validation error, server error, conflict, success, and delete flows.
79
+ 3. Save, reload, edit, clear nullable fields, and verify the API payload and rendered state agree.
80
+ 4. Check keyboard and narrow-width behavior; run affected integration tests through real API fixtures.
@@ -0,0 +1,92 @@
1
+ # Module and Data Contracts
2
+
3
+ Use this guide for entities, APIs, commands, scoping, compatibility, migrations, events, workers, search, and cache. Use `customers` as the CRUD reference after resolving its installed source.
4
+
5
+ ## Entity and Scope Contract
6
+
7
+ - Define entity classes together in `src/modules/<id>/data/entities.ts`; import decorators from `@mikro-orm/decorators/legacy` and ORM types from the installed MikroORM package.
8
+ - Give organization-owned business rows `tenant_id` and `organization_id` columns plus a composite index suitable for their common filters. Derive scope from authenticated context, never request payloads. Preserve an installed tenant-wide/system contract only when it explicitly authorizes nullable organization scope; such code must not widen into organization-owned data.
9
+ - Give new user-editable rows `updated_at` with create/update behavior. Return it as `updatedAt` from list/detail APIs.
10
+ - Use UUID primary keys, explicit scalar FK IDs, and module-prefixed plural table names. Do not create cross-module ORM relations.
11
+ - Store sensitive/PII fields through `encryption.ts` `defaultEncryptionMaps`; use the framework decryption find helpers with both scope IDs. Add a deterministic hash sibling only when equality lookup requires it.
12
+ - Model nullable/optional/clearable fields consistently through validator, command, entity, response, and form. Test create, edit, reload, and clearing to `null`.
13
+
14
+ ## Migration Workflow
15
+
16
+ 1. Change `data/entities.ts` and any validator/command/response contracts.
17
+ 2. Run `yarn generate` if discovery or entity registration changed.
18
+ 3. Run `yarn db:generate` as a schema-diff probe.
19
+ 4. Review every emitted statement; retain only the intended module change and update that module's `.snapshot-open-mercato.json` to the post-change schema.
20
+ 5. Never edit a shipped migration. Add a corrective migration.
21
+ 6. Ask before `yarn db:migrate`; normal delivery includes migration plus snapshot without mutating the user's database.
22
+
23
+ ## CRUD Route Contract
24
+
25
+ Create handlers under `api/<resource>/route.ts` and build them with the installed `makeCrudRoute` contract:
26
+
27
+ - import `makeCrudRoute` from `@open-mercato/shared/lib/crud/factory`;
28
+
29
+ - `metadata`: per-method `requireAuth` and `requireFeatures`;
30
+ - `orm`: entity, id field, tenant/org fields, and explicit soft-delete field (including `null` when absent);
31
+ - `list`: Zod query schema, stable colon-form `entityId`, fields including `updated_at`, scoped filters, stable response transform, and custom-field decoration when needed;
32
+ - `actions.create`, `actions.update`, `actions.delete`: command IDs, raw schemas, scoped input mapping, responses, and statuses;
33
+ - `indexer: { entityType }`: query-index coverage;
34
+ - `enrichers: { entityId }`: only when this route intentionally exposes the enricher host.
35
+
36
+ Export the factory's handlers and a matching `openApi` document as a separate route export. `openApi` is not a `makeCrudRoute` option. Build it with `createCrudOpenApiFactory` and `createPagedListResponseSchema` from `@open-mercato/shared/lib/openapi/crud`, or provide a typed `OpenApiRouteDoc` from `@open-mercato/shared/lib/openapi`. Do not use the stale flat `create`/`update`/`del` factory shape, a top-level `requireAuth`, or an API file organized by HTTP-method directory.
37
+
38
+ Reject malformed ID lists and filters explicitly. Preserve existing response keys; normalize custom fields deliberately and test compatibility when changing prefixed keys.
39
+
40
+ ## Commands and Custom Writes
41
+
42
+ - Put domain mutations in commands so audit, undo, events, cache invalidation, and indexing share one path. Routes validate and dispatch; they do not reproduce writes.
43
+ - For custom write/action routes, run registered mutation guards before mutation, merge guarded payload changes, and run post-success callbacks after commit while logging callback failures.
44
+ - Enforce command-level optimistic locking for action/sub-resource endpoints. Guard the aggregate parent when lines share a parent version.
45
+ - Wrap multi-phase scalar/relation work with `withAtomicFlush(..., { transaction: true })`. Keep CRUD side effects and cache invalidation after the transaction commits.
46
+ - Emit both forward and undo side effects with the same index/cache aliases when undo exists.
47
+ - Make retries and idempotency explicit. Do not advance external cursors, one-time keys, or recovery state until the durable unit of work commits.
48
+
49
+ ## Runtime Logging
50
+
51
+ - Use `createLogger('<module>')` from `@open-mercato/shared/lib/logger` in runtime/server/module code; use `.child({ component, ...context })` for stable local context.
52
+ - Keep messages stable and put dynamic values in structured metadata; pass caught errors under `err`. Omit or redact credentials, tokens, secrets, PII, and payload bodies.
53
+ - Do not add raw `console.*` calls to runtime/server/module code. Intentional terminal output in CLI/build scripts and test-local console spies remain valid when that runtime requires them.
54
+
55
+ ## Optimistic-Lock UI Contract
56
+
57
+ - `CrudForm` derives the update/delete header from `initialValues.updatedAt`; ensure the detail payload supplies it.
58
+ - A custom client mutation wraps the call with the framework's scoped request-header helper and `buildOptimisticLockHeader(record.updatedAt)`.
59
+ - Surface 409s through the shared record-conflict UI. Do not silently retry over newer data.
60
+ - If a parent form mutates children, override the header per child with that child's version; do not reuse the parent version.
61
+
62
+ ## ACL and Setup
63
+
64
+ - Declare stable `<module>.<capability>` features in `acl.ts` and their dependency relationships when applicable.
65
+ - Gate API methods and pages declaratively with `requireFeatures`; never gate by mutable role names.
66
+ - Grant new features in `setup.ts` `defaultRoleFeatures` for the intended default roles, then run `yarn mercato auth sync-role-acls` for existing tenants.
67
+ - Use the wildcard-aware matcher wherever raw feature arrays are evaluated; `module.*` and `*` must satisfy concrete grants.
68
+ - Make `onTenantCreated`, `seedDefaults`, and provider setup idempotent. Keep examples in `seedExamples`.
69
+
70
+ ## Cross-Module Mechanism
71
+
72
+ | Need | Use |
73
+ |---|---|
74
+ | Side effect after another module changes | Typed event + subscriber owned by the optional consumer. |
75
+ | Display/read another module's data | Widget injection plus response enricher. |
76
+ | Durable historical reference | Scalar ID plus snapshot; resolve live data only when available. |
77
+ | Add app-owned data linked to installed entity | Separate extension entity in `data/extensions.ts`. |
78
+ | Optional service call | Guarded/soft DI resolve in the consumer and a defined degraded result. |
79
+
80
+ ## Events, Notifications, Workers, Search, and Cache
81
+
82
+ - Declare typed events in `events.ts` with `createModuleEvents(... as const)` before emitting them. Keep IDs past-tense and stable.
83
+ - Use persistent idempotent subscribers for retried side effects; use ephemeral subscribers for local reactive work. Verify the host module can be absent when optional.
84
+ - Declare notification types/renderers/handlers through their registries; keep notification IDs stable and ACL-aware.
85
+ - Give every worker discovered metadata, an idempotent handler, bounded concurrency/retry behavior, scoped serializable payloads, and commands for domain writes. Use `ProgressJob` for user-visible bulk/long work. Exact cache/queue imports, tenant context, worker shape, retry semantics, and operator commands live in `om-module-scaffold` → `references/runtime-cache-and-queues.md`.
86
+ - Configure `search.ts`; use deterministic convergence polling or reindex assertions rather than arbitrary sleeps.
87
+ - Resolve cache through DI and mirror the host scope in keys/tags: tenant+organization for organization-owned data, or an explicitly authorized tenant-wide key for tenant-wide state. Invalidate every successful write/undo/sub-resource path after commit; non-request runtimes establish the tenant cache context explicitly.
88
+ - Add module CLI commands through the discovery contract and test the compiled package path, not only TypeScript source.
89
+
90
+ ## Frozen Surfaces
91
+
92
+ Treat API routes, public imports/signatures, DB schema, event/entity/ACL/DI/widget/notification/AI IDs, CLI commands/flags, and generated bootstrap exports as compatibility surfaces. Prefer additive fields and aliases. A rename/removal needs an explicit deprecation bridge and migration plan.
@@ -0,0 +1,104 @@
1
+ # Unified Module Extensions and Overrides
2
+
3
+ Use the smallest extension mechanism that preserves installed-module ownership. Resolve host IDs from generated facts or exact installed source; never invent spot, route, or entity IDs.
4
+
5
+ ## Route Selection
6
+
7
+ Your file lives in `src/modules/<id>/` either way, so what you change decides the route, not where it lives. Creating your own entity/route/command/page is `module-data`/`backend-ui` alone, even when it calls installed APIs and reads installed facts. Changing an installed module — its records or data derived from them, commands, events, pages, agents, tools, or the invariants applied to them — selects `umes` as well. Reading its facts is not `umes`; changing its behavior is.
8
+
9
+ Add every other match too: `backend-ui` + `om-backend-ui-design` when authoring, restyling, or ACL-gating a surface this app owns or injected; `module-data` + contracts for app-owned entities/links/routes/commands/ACL; `ai-workflow` for a durable process, activity, or user task; plus the facts of each module involved. Stay `umes`-only when nothing of yours is rendered — hiding, toggling, disabling, rewiring, or auditing a surface an installed module owns.
10
+
11
+ ## Mechanism Selector
12
+
13
+ | Goal | Mechanism | App module file |
14
+ |---|---|---|
15
+ | Add computed/read data | Response enricher | `data/enrichers.ts` |
16
+ | Rewrite/validate request or augment response | API interceptor | `api/interceptors.ts` |
17
+ | Add pre/post command behavior without replacing the command | Command interceptor | `commands/interceptors.ts` |
18
+ | Block/rewrite a mutation with post-success work | Mutation guard contract | `data/guards.ts`; add widget injection only for a UI surface |
19
+ | Enrich query-engine reads | Query enricher | `data/enrichers.ts` with `queryEngine.enabled` |
20
+ | Add form fields/table columns/actions/filters/toolbar | Headless widget injection | `widgets/injection/**`, `widgets/injection-table.ts` |
21
+ | Add/reorder menu items | Headless menu widget | same widget files, `menu:*` host |
22
+ | Render a card/tab/section in another page | UI widget injection | same widget files |
23
+ | Add app data linked to installed entity | Entity extension | `data/extensions.ts` |
24
+ | React after lifecycle change | Typed subscriber | `subscribers/*.ts`; `metadata.sync`/`priority` for in-pipeline lifecycle work |
25
+ | React to query lifecycle | Sync query subscriber | `subscribers/*.ts` for `*.querying`/`*.queried` |
26
+ | React in the browser | Notification handler or DOM bridge | `notifications.handlers.ts`, or `events.ts` with `clientBroadcast` plus UI hooks |
27
+ | Replace/wrap/transform component props | Component override | `widgets/components.ts` |
28
+ | Disable/replace route, page, event, worker, widget, agent/tool, setup, ACL, DI, or encryption contract | Unified module entry override | `src/modules.ts` `entry.overrides` |
29
+ | Own unsupported installed internals | Eject, only after decision gate | `om-eject-and-customize` |
30
+
31
+ ## Response Enrichers
32
+
33
+ - Target the exact host entity token and namespace additive output under the app module.
34
+ - Implement `enrichMany` for lists to avoid N+1 queries; filter all reads by tenant and organization.
35
+ - Declare feature gates, timeout, fallback, priority, and criticality. Fail closed for security decisions; keep decorative enrichment non-critical.
36
+ - Opt into cache-on-list-hit only when output is record-pure and invalidated with the host record.
37
+ - The host route must enable enrichers for the same entity ID. Run `yarn generate` after adding the file.
38
+
39
+ ## API Interceptors
40
+
41
+ - Target exact route ID/methods and preserve host auth/scope. A before hook returns schema-compatible body/query; the host validates again.
42
+ - Narrow ID lists by intersecting with existing filters. Reject malformed IDs; never convert a bad restriction into unrestricted results.
43
+ - Preserve required response keys; make additive changes by default. Time-bound external work and define fallback behavior.
44
+ - Custom routes require their explicit interceptor bridge; do not assume all handlers execute generic hooks.
45
+
46
+ ## Command Interceptors
47
+
48
+ - Export `interceptors: CommandInterceptor[]` from `commands/interceptors.ts`. Give each entry a stable `id` and an exact stable `targetCommand`; use module/global wildcards only when the cross-command scope is intentional.
49
+ - `beforeExecute` may block with `{ ok: false }` or return a validated shallow `modifiedInput`; `afterExecute` may return additive `modifiedResult` or perform bounded post-success work. `beforeUndo` may block unsafe undo and `afterUndo` performs idempotent cleanup. Preserve metadata only through the documented hook context.
50
+ - Feature gates are wildcard-aware. Re-derive tenant/organization ownership from authenticated context or scoped records; an interceptor never grants authority, bypasses the command, suppresses locking/audit/undo, or turns invalid input into a valid-looking unrestricted request.
51
+ - Test execute and undo paths, authorized/denied/wildcard callers, safe block/rewrite, hook order, and failure posture. Post hooks must not pretend a committed command failed.
52
+
53
+ ## Mutation Guards
54
+
55
+ - Map the host operation to create/update/delete (state-changing actions usually update).
56
+ - Receive authenticated scope and wildcard-aware feature context. Return an explicit block or a validated modified payload.
57
+ - Run post-success callbacks only after commit; callback failure must be logged without pretending the committed write failed.
58
+ - Preserve optimistic locking and command side effects. A guard cannot authorize a caller denied by the host.
59
+
60
+ ## Widget Injection
61
+
62
+ - Map stable widget IDs to exact host spots with `InjectionPosition` for deterministic order.
63
+ - Use headless payloads for fields, columns, row/bulk actions, filters, toolbar items, and menus; do not mount React solely to return declarations.
64
+ - Preserve host `entityId`/`extensionTableId`; injected actions use guarded/scoped API calls and shared states.
65
+ - For editable injected fields, implement all three paths: render/input, read/enricher, and save/interceptor or command. Test save/reload/clear.
66
+ - Gate display and execution separately. UI hiding never substitutes for backend authorization.
67
+ - Scope client handlers with `eventHandlers.filter.operations`; use `clientBroadcast`, `useAppEvent`, and `useOperationProgress` for typed real-time behavior instead of polling by default.
68
+
69
+ Common host families include `crud-form:<entityId>:fields`, `data-table:<tableId>:columns`, `:row-actions`, `:bulk-actions`, `:filters`, `:toolbar`, `:search-trailing`, and `menu:sidebar:*`/`menu:topbar:*`. Resolve the concrete IDs; do not derive them by guess.
70
+
71
+ ## Extensions and Optional Coupling
72
+
73
+ - Keep extension data in a separate app-owned entity with scalar host ID and full tenant/org scope.
74
+ - Use a unique scoped key where one extension row per host is expected. Define deletion/orphan and absent-host behavior.
75
+ - Use ID plus snapshot when historical rendering must survive host removal/change.
76
+ - The optional consumer owns event/enricher/widget glue and guarded DI resolution. The host never imports the optional consumer.
77
+
78
+ ## Component and Module Overrides
79
+
80
+ - Prefer props transform, then wrapper, then full replacement. Preserve the component's public props and accessibility behavior.
81
+ - Use handle-based component targets and stable override keys from facts/source.
82
+ - In `src/modules.ts`, `null` disables a supported contract and a value replaces it. Keep override IDs aligned with the replaced value.
83
+ - Add a route/page replacement only once; verify generated registries select it and that disabling leaves no stale nav/cache entry.
84
+ - Use AI extensions for small prompt/tool/suggestion changes; use full AI overrides only for replacement/disable.
85
+ - The complete wired override catalog spans AI agents/tools/extensions, API/page routes, subscribers, workers, injection/component/dashboard widgets, notification types/handlers, API/command interceptors, enrichers, page guards, CLI, setup, ACL, DI, and encryption. Use `om-system-extension` → `references/unified-overrides.md`; never guess a domain/key.
86
+
87
+ ## Specialized Extension Families
88
+
89
+ - Integration onboarding/status/detail contributions use the typed integration registry, `InjectionWizard`, `StatusBadgeRenderer`, and provider detail `widgetSpotId`; route to the integration skill as well as UI/UMES.
90
+ - Search/vector work includes `search.ts`, `vector.ts`, query enrichers, and query lifecycle subscribers; route to module/data work and inspect exact installed search contracts.
91
+ - Embedded AI uses `<AiChat agent="module.agent_id">`; provider/currency/workflow registrations belong to their owning integration or workflow contracts.
92
+ - Reactive notification handlers use `notifications.handlers.ts`/`useNotificationEffect`; message/inbox definitions remain stable typed surfaces.
93
+
94
+ ## Feature Toggles
95
+
96
+ - Define one server-resolved toggle and use it consistently in backend behavior, page/menu/widget visibility, workers/subscribers, and APIs.
97
+ - When disabled, choose and test an explicit outcome: hidden, 404/403, no-op, or degraded read. Never leave UI-only gating around a live mutation.
98
+
99
+ ## Verification
100
+
101
+ 1. Test host present and optional host absent.
102
+ 2. Test authorized, unauthorized, and wildcard-feature callers.
103
+ 3. Test list and detail, create/update/delete/action, cache hit/miss, and failure fallback where applicable.
104
+ 4. Run `yarn generate`, inspect host registration, and verify no installed file changed.
@@ -0,0 +1,81 @@
1
+ # Integration and Provider Engineering
2
+
3
+ Build provider-owned modules around generic integration, data-sync, webhook, queue, and progress contracts. Never place provider-specific behavior inside a generic host module.
4
+
5
+ ## Provider Family Selector
6
+
7
+ | Family | Primary contract |
8
+ |---|---|
9
+ | Transactional email | `IntegrationDefinition`, tenant credentials, DI sender + health services, retry/redaction, and app activation. There is no installed generic transactional-email adapter contract. |
10
+ | Mailbox/email channel | Installed `communication_channels` hub plus its `ChannelAdapter`, per-user credentials, inbound/outbound conversion, polling/push, health, DI/setup registration. Follow the Gmail/IMAP precedent. |
11
+ | Shipping/carrier | Provider package, service/quote/label/tracking adapter, webhook mapping, idempotent fulfillment updates. |
12
+ | Payment gateway | Installed `GatewayAdapter`; `registerGatewayAdapter`, `registerWebhookHandler`, and `registerPaymentGatewayDescriptor`; idempotency keys, signed webhooks, concurrency-safe state machine. |
13
+ | Commerce/ERP sync | `DataSyncAdapter`, mappings/presets, external IDs, cursors, reconciliation, progress. |
14
+ | Generic webhook | Standard signing/verification, replay protection, delivery queue/log/status, scoped configuration. |
15
+ | File import/export | Streaming parser/writer, format adapter, progress, cleanup, row errors, formula neutralization. |
16
+ | Storage/media | Provider adapter, scoped object keys, signed access, metadata, cleanup and lifecycle. |
17
+
18
+ ## Package and Activation
19
+
20
+ - In this standalone repository, put an app-specific provider under `src/modules/<provider>/` and activate it through `src/modules.ts`. Do not invent a `packages/*` workspace: the scaffold has no workspace topology.
21
+ - When the user explicitly needs reuse across applications, build a separately published provider package/repository with compatible peer/runtime dependencies, public exports, build/prepack output, and module discovery files; install its packed artifact as an app dependency.
22
+ - Ask before changing repository topology or adding the production dependency. Keep packed-consumer validation on the reusable-package branch only.
23
+ - Register provider services through DI and use an `integration.ts` definition for credentials, health, versions, bundle membership, and detail-page extension spot.
24
+ - A provider implementation is not complete when only a transport/client exists. The production path includes `index.ts`, `integration.ts`, `di.ts`, the typed host adapter where one exists, `setup.ts`/`acl.ts` when bootstrap or features are needed, and `src/modules.ts` activation.
25
+ - Enable the local module or installed package in `src/modules.ts`. For the reusable branch, test the published/packed artifact, not only package source.
26
+ - Keep provider env names prefixed and stable. Apply optional deployment presets from provider-owned `setup.ts` through normal services, with an idempotent rerun CLI when practical.
27
+ - Do not preconfigure a provider from core/app bootstrap unless the provider package owns that code.
28
+
29
+ ## Credentials and Security
30
+
31
+ - Store credentials through the integrations credential service/encryption maps; never log raw values or return secrets to list/detail APIs.
32
+ - Declare the host credential/mapping scope. Thread `userId` on every per-user read/write. Tenant-wide credentials or scheduled jobs may use the installed contract's explicit tenant scope (including `organizationId: null`), but must never read or mutate organization-owned rows without deriving and checking an organization for that item.
33
+ - Validate external base URLs against SSRF rules, including redirects and DNS/private ranges. Permit private endpoints only through an explicit development setting.
34
+ - Redact authorization headers, tokens, signed URLs, provider payload secrets, and sensitive response bodies from errors and logs.
35
+ - Use `createLogger` from `@open-mercato/shared/lib/logger` with structured fields; never use raw `console.*` or place credentials/provider payload bodies in log fields.
36
+ - Verify inbound signatures against the raw body, enforce timestamp/replay bounds, and atomically claim each inbox delivery before side effects so duplicate callbacks have one winner (`atomic-inbox-claim`).
37
+
38
+ ## Reliability Contract
39
+
40
+ - Define timeouts, bounded retries with jitter, provider rate-limit handling, circuit/health behavior, and structured logs with correlation IDs.
41
+ - Give every remote mutation a durable idempotency key tied to the local operation. Preserve it across transaction rollback/retry.
42
+ - Separate transport success from domain reconciliation. Persist external IDs and snapshots only after the relevant durable local/remote boundary succeeds.
43
+ - Treat provider variants (site/store/currency/price scope, API version, feature availability) as explicit capability/config branches; do not infer one global shape.
44
+ - Keep webhook, poll, manual retry, and scheduled sync paths convergent and safe when they race.
45
+
46
+ ## Data Sync and Cursor Safety
47
+
48
+ - Implement/register a `DataSyncAdapter` with direction, supported entities, streaming import/export, connection validation, mappings, and cursor support.
49
+ - Run sync through queue workers and `ProgressJob`; prevent overlapping runs for the same scoped provider/entity/direction unless explicitly supported.
50
+ - Isolate item errors and continue safe batches; report row/item outcomes. A batch transport failure must not advance its cursor.
51
+ - Persist a cursor only after the page/batch and its external-ID mappings commit. Retry resumes from the last successful cursor.
52
+ - Make reruns idempotent and add reconciliation for provider-side totals/status that may differ from event payloads.
53
+ - Preserve nested snapshots/variants required for later mapping; avoid stale payload assumptions by validating versioned contracts.
54
+
55
+ ## Import and Export
56
+
57
+ - Stream large inputs/outputs; bound memory and file sizes. Validate content type, extension, encoding, column mapping, and row schemas.
58
+ - Neutralize spreadsheet formulas in exported untrusted values. Avoid zip/path traversal and clean temporary/artifact files in `finally`/retention jobs.
59
+ - Use deterministic locale/timezone/decimal/date handling and return row-level errors without exposing secrets.
60
+ - Support cancellation and progress; perform domain writes through commands.
61
+
62
+ ## Provider UI and UMES
63
+
64
+ - Use integrations/settings pages and provider detail widget spots rather than cloning the marketplace UI.
65
+ - Gate credential, health, mapping, sync, and log actions with their own features. Use shared guarded mutations and states.
66
+ - Add external IDs/status to domain pages through enrichers/widgets, keeping host modules unaware of the provider.
67
+ - Use typed events and notifications for completion/failure; use DOM Event Bridge/progress for live status instead of aggressive polling.
68
+
69
+ ## Email Routing
70
+
71
+ - First decide whether the request is **transactional delivery** or a **connected mailbox**. SMTP used only for application-generated mail is a transactional provider: register its `IntegrationDefinition`, encrypted credentials, DI sender/health services, and app module, but do not claim it implements a mailbox contract that the installed framework does not expose.
72
+ - Gmail, IMAP/SMTP mailboxes, inbox sync, threading, history, or per-user send/receive belong to the installed `communication_channels` module. Implement `ChannelAdapter` from `@open-mercato/core/modules/communication_channels/lib/adapter`, set `integration.hub: 'communication_channels'`, register the adapter and exact `healthCheck.service` in `di.ts`, ensure idempotent adapter registration/default grants in `setup.ts`, and activate both the hub and provider in `src/modules.ts`.
73
+ - Use the installed `channel_gmail` and `channel_imap` facts/source as precedent. Thread `userId` on every mailbox credential read/write; tenant-wide transactional credentials must not read per-user rows.
74
+
75
+ ## Testing
76
+
77
+ 1. Use a contract server/mock for normal, timeout, rate-limit, malformed, partial, retry, duplicate, signature, and pagination responses.
78
+ 2. Verify credential redaction, SSRF rejection, scope isolation, per-user separation, and webhook replay behavior.
79
+ 3. Verify a rerun produces no duplicate remote/local records and concurrent callbacks converge.
80
+ 4. Inject a page/batch failure and prove the cursor did not advance or lose data.
81
+ 5. Pack/build the provider and run generation/typecheck/tests from a standalone consumer.