@open-mercato/cli 0.6.5 → 0.6.6-canary.315.1.g6673635216

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 (176) hide show
  1. package/.turbo/turbo-build.log +57 -2
  2. package/build.mjs +80 -2
  3. package/dist/agentic/guides/core.auth.md +2 -100
  4. package/dist/agentic/guides/core.catalog.md +2 -78
  5. package/dist/agentic/guides/core.currencies.md +2 -42
  6. package/dist/agentic/guides/core.customer_accounts.md +2 -128
  7. package/dist/agentic/guides/core.customers.md +2 -137
  8. package/dist/agentic/guides/core.data_sync.md +2 -106
  9. package/dist/agentic/guides/core.integrations.md +2 -112
  10. package/dist/agentic/guides/core.md +7 -40
  11. package/dist/agentic/guides/core.sales.md +2 -103
  12. package/dist/agentic/guides/core.workflows.md +2 -151
  13. package/dist/agentic/guides/module-facts.json +5100 -0
  14. package/dist/agentic/guides/module-system.md +130 -0
  15. package/dist/agentic/guides/modules/ai_assistant.md +57 -0
  16. package/dist/agentic/guides/modules/api_docs.md +39 -0
  17. package/dist/agentic/guides/modules/api_keys.md +41 -0
  18. package/dist/agentic/guides/modules/attachments.md +46 -0
  19. package/dist/agentic/guides/modules/audit_logs.md +42 -0
  20. package/dist/agentic/guides/modules/auth.md +64 -0
  21. package/dist/agentic/guides/modules/business_rules.md +44 -0
  22. package/dist/agentic/guides/modules/catalog.md +70 -0
  23. package/dist/agentic/guides/modules/channel_gmail.md +39 -0
  24. package/dist/agentic/guides/modules/channel_imap.md +39 -0
  25. package/dist/agentic/guides/modules/checkout.md +60 -0
  26. package/dist/agentic/guides/modules/communication_channels.md +65 -0
  27. package/dist/agentic/guides/modules/configs.md +42 -0
  28. package/dist/agentic/guides/modules/content.md +39 -0
  29. package/dist/agentic/guides/modules/currencies.md +50 -0
  30. package/dist/agentic/guides/modules/customer_accounts.md +76 -0
  31. package/dist/agentic/guides/modules/customers.md +115 -0
  32. package/dist/agentic/guides/modules/dashboards.md +43 -0
  33. package/dist/agentic/guides/modules/data_sync.md +49 -0
  34. package/dist/agentic/guides/modules/dictionaries.md +46 -0
  35. package/dist/agentic/guides/modules/directory.md +49 -0
  36. package/dist/agentic/guides/modules/entities.md +46 -0
  37. package/dist/agentic/guides/modules/events.md +39 -0
  38. package/dist/agentic/guides/modules/feature_toggles.md +42 -0
  39. package/dist/agentic/guides/modules/gateway_stripe.md +39 -0
  40. package/dist/agentic/guides/modules/generators.md +39 -0
  41. package/dist/agentic/guides/modules/inbox_ops.md +59 -0
  42. package/dist/agentic/guides/modules/integrations.md +49 -0
  43. package/dist/agentic/guides/modules/messages.md +55 -0
  44. package/dist/agentic/guides/modules/notifications.md +41 -0
  45. package/dist/agentic/guides/modules/onboarding.md +41 -0
  46. package/dist/agentic/guides/modules/payment_gateways.md +52 -0
  47. package/dist/agentic/guides/modules/perspectives.md +42 -0
  48. package/dist/agentic/guides/modules/planner.md +49 -0
  49. package/dist/agentic/guides/modules/portal.md +39 -0
  50. package/dist/agentic/guides/modules/progress.md +48 -0
  51. package/dist/agentic/guides/modules/query_index.md +46 -0
  52. package/dist/agentic/guides/modules/record_locks.md +53 -0
  53. package/dist/agentic/guides/modules/resources.md +62 -0
  54. package/dist/agentic/guides/modules/sales.md +109 -0
  55. package/dist/agentic/guides/modules/scheduler.md +46 -0
  56. package/dist/agentic/guides/modules/search.md +39 -0
  57. package/dist/agentic/guides/modules/security.md +67 -0
  58. package/dist/agentic/guides/modules/shipping_carriers.md +51 -0
  59. package/dist/agentic/guides/modules/sso.md +59 -0
  60. package/dist/agentic/guides/modules/staff.md +88 -0
  61. package/dist/agentic/guides/modules/storage_s3.md +39 -0
  62. package/dist/agentic/guides/modules/sync_akeneo.md +39 -0
  63. package/dist/agentic/guides/modules/sync_excel.md +41 -0
  64. package/dist/agentic/guides/modules/system_status_overlays.md +39 -0
  65. package/dist/agentic/guides/modules/translations.md +44 -0
  66. package/dist/agentic/guides/modules/webhooks.md +54 -0
  67. package/dist/agentic/guides/modules/workflows.md +73 -0
  68. package/dist/agentic/shared/AGENTS.md.template +21 -23
  69. package/dist/agentic/shared/ai/agentic.config.json +61 -0
  70. package/dist/agentic/shared/ai/skills/om-auto-continue-pr/SKILL.md +16 -318
  71. package/dist/agentic/shared/ai/skills/om-auto-continue-pr-loop/SKILL.md +16 -581
  72. package/dist/agentic/shared/ai/skills/om-auto-create-pr/SKILL.md +16 -397
  73. package/dist/agentic/shared/ai/skills/om-auto-create-pr-loop/SKILL.md +16 -738
  74. package/dist/agentic/shared/ai/skills/om-auto-fix-issue/SKILL.md +27 -0
  75. package/dist/agentic/shared/ai/skills/om-auto-review-pr/SKILL.md +16 -565
  76. package/dist/agentic/shared/ai/skills/om-help/references/skills-catalog.md +1 -1
  77. package/dist/agentic/shared/ai/skills/om-implement-spec/SKILL.md +1 -1
  78. package/dist/agentic/shared/ai/skills/om-integration-builder/SKILL.md +1 -1
  79. package/dist/agentic/shared/ai/skills/om-integration-builder/STANDALONE.md +34 -0
  80. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/naming-conventions.md +4 -14
  81. package/dist/agentic/shared/ai/skills/om-troubleshooter/SKILL.md +10 -6
  82. package/dist/agentic/shared/ai/skills/tiers.json +47 -0
  83. package/dist/agentic/shared/ai/skills/tiers.schema.json +73 -0
  84. package/dist/agentic/shared/ai/trackers/github.md +376 -0
  85. package/dist/agentic/shared/scripts/install-skills.sh +483 -0
  86. package/dist/lib/__integration__/TC-INT-008.spec.js +29 -1
  87. package/dist/lib/__integration__/TC-INT-008.spec.js.map +2 -2
  88. package/dist/lib/agentic-setup.js +110 -40
  89. package/dist/lib/agentic-setup.js.map +2 -2
  90. package/dist/lib/auto-spawn-workers.js +8 -1
  91. package/dist/lib/auto-spawn-workers.js.map +2 -2
  92. package/dist/lib/deploy/railway/env.js +1 -1
  93. package/dist/lib/deploy/railway/env.js.map +2 -2
  94. package/dist/lib/events-single-delivery.js +27 -0
  95. package/dist/lib/events-single-delivery.js.map +7 -0
  96. package/dist/lib/generators/extensions/injection-widgets.js +144 -5
  97. package/dist/lib/generators/extensions/injection-widgets.js.map +2 -2
  98. package/dist/lib/generators/module-facts-discovery.js +46 -0
  99. package/dist/lib/generators/module-facts-discovery.js.map +7 -0
  100. package/dist/lib/generators/module-facts.js +740 -0
  101. package/dist/lib/generators/module-facts.js.map +7 -0
  102. package/dist/lib/generators/module-registry.js +263 -55
  103. package/dist/lib/generators/module-registry.js.map +3 -3
  104. package/dist/lib/init-secrets.js +11 -4
  105. package/dist/lib/init-secrets.js.map +2 -2
  106. package/dist/lib/module-install-args.js +9 -1
  107. package/dist/lib/module-install-args.js.map +2 -2
  108. package/dist/lib/module-install.js +22 -11
  109. package/dist/lib/module-install.js.map +2 -2
  110. package/dist/lib/module-package.js +2 -2
  111. package/dist/lib/module-package.js.map +2 -2
  112. package/dist/lib/queue-worker-supervisor.js +95 -0
  113. package/dist/lib/queue-worker-supervisor.js.map +2 -2
  114. package/dist/lib/testing/integration.js +302 -7
  115. package/dist/lib/testing/integration.js.map +3 -3
  116. package/dist/lib/utils.js +1 -1
  117. package/dist/lib/utils.js.map +2 -2
  118. package/dist/lib/worker-connection-budget.js +63 -0
  119. package/dist/lib/worker-connection-budget.js.map +7 -0
  120. package/dist/lib/worker-job-handler.js +13 -1
  121. package/dist/lib/worker-job-handler.js.map +2 -2
  122. package/dist/mercato.js +74 -16
  123. package/dist/mercato.js.map +2 -2
  124. package/jest.config.cjs +1 -1
  125. package/package.json +15 -13
  126. package/src/__tests__/mercato.test.ts +36 -0
  127. package/src/lib/__integration__/TC-INT-008.spec.ts +41 -1
  128. package/src/lib/__tests__/auto-spawn-workers.test.ts +19 -0
  129. package/src/lib/__tests__/events-single-delivery.test.ts +68 -0
  130. package/src/lib/__tests__/init-secrets.test.ts +37 -6
  131. package/src/lib/__tests__/module-install-args.test.ts +23 -0
  132. package/src/lib/__tests__/module-install.test.ts +66 -1
  133. package/src/lib/__tests__/module-package.test.ts +27 -0
  134. package/src/lib/__tests__/queue-worker-supervisor.test.ts +42 -0
  135. package/src/lib/__tests__/release-notes-retired.test.ts +33 -0
  136. package/src/lib/__tests__/worker-connection-budget.test.ts +115 -0
  137. package/src/lib/__tests__/worker-job-handler.test.ts +28 -0
  138. package/src/lib/agentic-setup.ts +162 -42
  139. package/src/lib/auto-spawn-workers.ts +8 -0
  140. package/src/lib/deploy/railway/env.ts +1 -1
  141. package/src/lib/events-single-delivery.ts +69 -0
  142. package/src/lib/generators/__tests__/module-facts.auth-source.test.ts +83 -0
  143. package/src/lib/generators/__tests__/module-facts.bc-guard.test.ts +69 -0
  144. package/src/lib/generators/__tests__/module-facts.customers.fixture.test.ts +69 -0
  145. package/src/lib/generators/__tests__/module-facts.discovery.test.ts +88 -0
  146. package/src/lib/generators/__tests__/module-facts.malformed.test.ts +76 -0
  147. package/src/lib/generators/__tests__/module-subset.test.ts +47 -46
  148. package/src/lib/generators/__tests__/output-snapshots.test.ts +2 -0
  149. package/src/lib/generators/__tests__/structural-contracts.test.ts +67 -5
  150. package/src/lib/generators/extensions/injection-widgets.ts +173 -4
  151. package/src/lib/generators/module-facts-discovery.ts +58 -0
  152. package/src/lib/generators/module-facts.ts +998 -0
  153. package/src/lib/generators/module-registry.ts +299 -47
  154. package/src/lib/init-secrets.ts +25 -6
  155. package/src/lib/module-install-args.ts +12 -1
  156. package/src/lib/module-install.ts +25 -9
  157. package/src/lib/module-package.ts +2 -2
  158. package/src/lib/queue-worker-supervisor.ts +105 -0
  159. package/src/lib/testing/__tests__/integration.test.ts +292 -6
  160. package/src/lib/testing/integration.ts +369 -4
  161. package/src/lib/utils.ts +1 -0
  162. package/src/lib/worker-connection-budget.ts +131 -0
  163. package/src/lib/worker-job-handler.ts +13 -1
  164. package/src/mercato.ts +118 -13
  165. package/dist/agentic/shared/ai/skills/om-auto-continue-pr/STANDALONE.md +0 -98
  166. package/dist/agentic/shared/ai/skills/om-auto-create-pr/STANDALONE.md +0 -98
  167. package/dist/agentic/shared/ai/skills/om-auto-fix-github/SKILL.md +0 -419
  168. package/dist/agentic/shared/ai/skills/om-auto-fix-github/STANDALONE.md +0 -98
  169. package/dist/agentic/shared/ai/skills/om-auto-review-pr/STANDALONE.md +0 -98
  170. package/dist/agentic/shared/ai/skills/om-code-review/SKILL.md +0 -144
  171. package/dist/agentic/shared/ai/skills/om-code-review/references/review-checklist.md +0 -83
  172. package/dist/agentic/shared/ai/skills/om-integration-tests/SKILL.md +0 -279
  173. package/dist/agentic/shared/ai/skills/om-prepare-issue/SKILL.md +0 -202
  174. package/dist/agentic/shared/ai/skills/om-spec-writing/SKILL.md +0 -85
  175. package/dist/agentic/shared/ai/skills/om-spec-writing/references/spec-checklist.md +0 -67
  176. package/dist/agentic/shared/ai/skills/om-spec-writing/references/spec-template.md +0 -86
@@ -1,4 +1,59 @@
1
- [build:cli] found 89 entry points
1
+ [build:cli] found 93 entry points
2
2
  Copied create-app/agentic/ → dist/agentic/
3
- Discovered 16 standalone guides → dist/agentic/guides/
3
+ Discovered 7 standalone guides → dist/agentic/guides/
4
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for ai_assistant
5
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for channel_gmail
6
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for channel_imap
7
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for checkout
8
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for content
9
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for api_docs
10
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for api_keys
11
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for attachments
12
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for audit_logs
13
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for auth
14
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for business_rules
15
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for catalog
16
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for communication_channels
17
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for configs
18
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for currencies
19
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for customer_accounts
20
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for customers
21
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for dashboards
22
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for data_sync
23
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for dictionaries
24
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for directory
25
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for entities
26
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for feature_toggles
27
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for inbox_ops
28
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for integrations
29
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for messages
30
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for notifications
31
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for payment_gateways
32
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for perspectives
33
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for planner
34
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for portal
35
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for progress
36
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for query_index
37
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for resources
38
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for sales
39
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for shipping_carriers
40
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for staff
41
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for sync_excel
42
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for translations
43
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for workflows
44
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for record_locks
45
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for security
46
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for sso
47
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for system_status_overlays
48
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for events
49
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for gateway_stripe
50
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for onboarding
51
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for scheduler
52
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for search
53
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for generators
54
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for storage_s3
55
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for sync_akeneo
56
+ [module-facts] module registry unavailable (registryPath not provided); API route auth omitted for webhooks
57
+ Generated 53 module fact-sheets → dist/agentic/guides/modules/
58
+ Wrote 9 legacy core.<module>.md redirect stubs → dist/agentic/guides/
4
59
  [build:cli] built successfully
package/build.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import { chmodSync, cpSync, existsSync, mkdirSync, readdirSync, readFileSync } from 'node:fs'
1
+ import { chmodSync, cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
2
2
  import { dirname, join } from 'node:path'
3
- import { fileURLToPath } from 'node:url'
3
+ import { fileURLToPath, pathToFileURL } from 'node:url'
4
4
  import { atomicWriteFileSync } from '../../scripts/lib/add-js-extension.mjs'
5
5
  import { buildPackage } from '../../scripts/build-package.mjs'
6
6
 
@@ -35,6 +35,18 @@ await buildPackage(packageDir, {
35
35
  const guidesDestDir = join(outdir, 'agentic', 'guides')
36
36
  mkdirSync(guidesDestDir, { recursive: true })
37
37
 
38
+ // Clean stale per-module artifacts before regenerating so an incremental dist never
39
+ // retains a removed module's full guide or fact-sheet — a removed `core.<module>.md`
40
+ // (two-dot, per-module) must come back as a redirect stub, not linger as a full guide.
41
+ // Mirrors packages/create-app/build.mjs; the conceptual `module-system.md` and the
42
+ // single-dot package guides are re-copied/re-discovered below.
43
+ rmSync(join(guidesDestDir, 'modules'), { recursive: true, force: true })
44
+ for (const entry of readdirSync(guidesDestDir)) {
45
+ if (/^core\..+\.md$/.test(entry)) {
46
+ rmSync(join(guidesDestDir, entry))
47
+ }
48
+ }
49
+
38
50
  let guidesFound = 0
39
51
  for (const pkg of readdirSync(packagesDir)) {
40
52
  const guideSource = join(packagesDir, pkg, 'agentic', 'standalone-guide.md')
@@ -58,5 +70,71 @@ await buildPackage(packageDir, {
58
70
  if (guidesFound > 0) {
59
71
  console.log(`Discovered ${guidesFound} standalone guides → dist/agentic/guides/`)
60
72
  }
73
+
74
+ // Generate per-module fact-sheets (Layer 2) for every package-provided module via
75
+ // the freshly built ts-morph extractor + resolver-routed discovery, so
76
+ // `mercato agentic:init` bundles the same guides as a create-mercato-app scaffold
77
+ // (packages/create-app/build.mjs). Discovery goes through the resolver, never a
78
+ // hardcoded packages/* path (.ai/lessons.md §161-169).
79
+ const { extractAllModuleFacts, renderModuleFactsJson, MODULE_FACTS_ALLOWLIST } = await import(
80
+ pathToFileURL(join(outdir, 'lib', 'generators', 'module-facts.js')).href
81
+ )
82
+ const { discoverPackageModuleSources } = await import(
83
+ pathToFileURL(join(outdir, 'lib', 'generators', 'module-facts-discovery.js')).href
84
+ )
85
+ const { createResolver } = await import(pathToFileURL(join(outdir, 'lib', 'resolver.js')).href)
86
+
87
+ const sources = discoverPackageModuleSources(createResolver(join(packagesDir, '..')))
88
+ if (sources.length > 0) {
89
+ const registryPath = join(packagesDir, '..', 'apps', 'mercato', '.mercato', 'generated', 'modules.runtime.generated.ts')
90
+ let coreVersion = null
91
+ try {
92
+ coreVersion = JSON.parse(readFileSync(join(packagesDir, 'core', 'package.json'), 'utf8')).version ?? null
93
+ } catch {
94
+ coreVersion = null
95
+ }
96
+
97
+ const { factsByModule, markdownByModule, warnings } = extractAllModuleFacts({
98
+ sources,
99
+ registryPath: existsSync(registryPath) ? registryPath : null,
100
+ coreVersion,
101
+ })
102
+
103
+ const modulesGuidesDir = join(guidesDestDir, 'modules')
104
+ mkdirSync(modulesGuidesDir, { recursive: true })
105
+ for (const [moduleId, markdown] of Object.entries(markdownByModule)) {
106
+ writeFileSync(join(modulesGuidesDir, `${moduleId}.md`), markdown)
107
+ }
108
+ writeFileSync(join(guidesDestDir, 'module-facts.json'), renderModuleFactsJson(factsByModule))
109
+
110
+ for (const warning of warnings) console.warn(warning)
111
+ console.log(`Generated ${Object.keys(markdownByModule).length} module fact-sheets → dist/agentic/guides/modules/`)
112
+
113
+ // BC bridge (spec §7 generated-file contract): the legacy hand-written guides
114
+ // existed only for the historical allowlisted modules, so redirect stubs are
115
+ // emitted for that set alone — never for auto-discovered modules that never had a
116
+ // `core.<module>.md`. Fresh scaffolds never link these names; they exist only for
117
+ // apps upgrading in place.
118
+ const bundled = new Set(Object.keys(markdownByModule))
119
+ let stubsWritten = 0
120
+ for (const moduleId of MODULE_FACTS_ALLOWLIST) {
121
+ if (!bundled.has(moduleId)) continue
122
+ const legacyGuidePath = join(guidesDestDir, `core.${moduleId}.md`)
123
+ if (!existsSync(legacyGuidePath)) {
124
+ writeFileSync(
125
+ legacyGuidePath,
126
+ `# core.${moduleId} — moved\n\n` +
127
+ `> This guide has moved. See [\`modules/${moduleId}.md\`](modules/${moduleId}.md) for the generated ` +
128
+ `\`${moduleId}\` fact-sheet, and [\`module-system.md\`](module-system.md) for conceptual module guidance.\n`,
129
+ )
130
+ stubsWritten++
131
+ }
132
+ }
133
+ if (stubsWritten > 0) {
134
+ console.log(`Wrote ${stubsWritten} legacy core.<module>.md redirect stubs → dist/agentic/guides/`)
135
+ }
136
+ } else {
137
+ console.warn('[module-facts] no package modules discovered; skipping fact-sheet generation')
138
+ }
61
139
  },
62
140
  })
@@ -1,101 +1,3 @@
1
- # Auth Module — Standalone App Guide
1
+ # core.auth — moved
2
2
 
3
- The auth module handles staff authentication, authorization, users, roles, and RBAC. For customer portal authentication, see the `customer_accounts` module guide.
4
-
5
- ## RBAC Implementation
6
-
7
- ### Two-Layer Model
8
-
9
- 1. **Role ACLs** — features assigned to roles (admin, employee, etc.)
10
- 2. **User ACLs** — per-user overrides (additional features or restrictions)
11
-
12
- Effective permissions = Role features + User-specific features.
13
-
14
- ### Declaring Features
15
-
16
- Every module MUST declare features in `acl.ts` and wire them in `setup.ts`:
17
-
18
- ```typescript
19
- // src/modules/<your_module>/acl.ts
20
- export const features = [
21
- 'your_module.view',
22
- 'your_module.create',
23
- 'your_module.update',
24
- 'your_module.delete',
25
- ]
26
-
27
- // src/modules/<your_module>/setup.ts
28
- import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'
29
-
30
- export const setup: ModuleSetupConfig = {
31
- defaultRoleFeatures: {
32
- superadmin: ['your_module.*'],
33
- admin: ['your_module.*'],
34
- user: ['your_module.view'],
35
- },
36
- }
37
- ```
38
-
39
- ### Feature Naming Convention
40
-
41
- Features follow the `<module>.<action>` pattern (e.g., `users.view`, `users.edit`).
42
-
43
- ### Declarative Guards
44
-
45
- Prefer declarative guards in page and API metadata:
46
-
47
- ```typescript
48
- export const metadata = {
49
- requireAuth: true,
50
- requireRoles: ['admin'],
51
- requireFeatures: ['users.manage'],
52
- }
53
- ```
54
-
55
- ### Server-Side Checks
56
-
57
- ```typescript
58
- const rbacService = container.resolve('rbacService')
59
- const hasAccess = await rbacService.userHasAllFeatures(
60
- userId,
61
- ['your_module.view'],
62
- { tenantId, organizationId }
63
- )
64
- ```
65
-
66
- ### Wildcards
67
-
68
- Wildcards are first-class ACL grants: `module.*` and `*` satisfy matching concrete features. When your code inspects raw granted feature arrays (instead of calling `rbacService`), use the shared wildcard-aware matchers (`matchFeature`, `hasFeature`, `hasAllFeatures`) — never use `includes(...)`.
69
-
70
- ### Special Flags
71
-
72
- - `isSuperAdmin` — bypasses all feature checks
73
- - Organization visibility list — restricts which organizations a user can access
74
-
75
- ## Security Rules
76
-
77
- - Hash passwords with `bcryptjs` (cost >= 10)
78
- - Never log credentials
79
- - Return minimal auth error messages — never reveal whether an email exists
80
- - Use `findWithDecryption` / `findOneWithDecryption` for user queries
81
-
82
- ## Authentication Flow
83
-
84
- 1. User submits credentials via `POST /api/auth/session`
85
- 2. Password verified with bcryptjs
86
- 3. JWT session token issued
87
- 4. Session attached to requests via middleware
88
-
89
- ## Subscribing to Auth Events
90
-
91
- ```typescript
92
- export const metadata = {
93
- event: 'auth.user.created',
94
- persistent: true,
95
- id: 'your-module-user-created',
96
- }
97
-
98
- export default async function handler(payload, ctx) {
99
- // React to new user registration
100
- }
101
- ```
3
+ > This guide has moved. See [`modules/auth.md`](modules/auth.md) for the generated `auth` fact-sheet, and [`module-system.md`](module-system.md) for conceptual module guidance.
@@ -1,79 +1,3 @@
1
- # Catalog Module — Standalone App Guide
1
+ # core.catalog — moved
2
2
 
3
- Use the catalog module for products, categories, pricing, variants, and offers.
4
-
5
- ## Pricing System
6
-
7
- Never reimplement pricing logic. Use the catalog pricing service via DI:
8
-
9
- ```typescript
10
- const pricingService = container.resolve('catalogPricingService')
11
- ```
12
-
13
- - `selectBestPrice` — finds the best price for a given context (customer, channel, quantity)
14
- - `resolvePriceVariantId` — resolves variant-level prices
15
- - Register custom pricing resolvers with priority (higher = checked first):
16
-
17
- ```typescript
18
- import { registerCatalogPricingResolver } from '@open-mercato/core/modules/catalog/lib/pricing'
19
- registerCatalogPricingResolver(myResolver, { priority: 10 })
20
- ```
21
-
22
- Price layers compose in order: base price → channel override → customer-specific → promotional.
23
-
24
- The pipeline emits `catalog.pricing.resolve.before` and `catalog.pricing.resolve.after` events that your module can subscribe to.
25
-
26
- ## Data Model
27
-
28
- | Entity | Purpose | Key Constraints |
29
- |--------|---------|----------------|
30
- | **Products** | Core items with media and descriptions | MUST have at least a name |
31
- | **Categories** | Hierarchical product grouping | No circular parent-child references |
32
- | **Variants** | Product variations (size, color) | MUST reference valid option schemas |
33
- | **Prices** | Multi-tier with channel scoping | Use `selectBestPrice` for resolution |
34
- | **Offers** | Time-limited promotions | MUST have valid date ranges |
35
- | **Option Schemas** | Variant option type definitions | Cannot delete while variants reference them |
36
-
37
- ## Subscribing to Catalog Events
38
-
39
- React to product lifecycle events in your module:
40
-
41
- ```typescript
42
- // src/modules/<your_module>/subscribers/product-updated.ts
43
- export const metadata = {
44
- event: 'catalog.product.updated',
45
- persistent: true,
46
- id: 'your-module-product-updated',
47
- }
48
-
49
- export default async function handler(payload, ctx) {
50
- // payload.resourceId = product ID
51
- }
52
- ```
53
-
54
- Key events:
55
- - `catalog.product.created` / `updated` / `deleted`
56
- - `catalog.pricing.resolve.before` / `after` (excluded from workflow triggers)
57
-
58
- ## Extending Catalog UI
59
-
60
- Use widget injection to add your module's UI into catalog pages:
61
-
62
- ```typescript
63
- // src/modules/<your_module>/widgets/injection-table.ts
64
- export const widgetInjections = {
65
- 'crud-form:catalog.catalog_product:fields': {
66
- widgetId: 'your-module-product-fields',
67
- priority: 100,
68
- },
69
- }
70
- ```
71
-
72
- Common injection spots:
73
- - `crud-form:catalog.catalog_product:fields` — product edit form
74
- - `data-table:catalog.products:columns` — product list columns
75
- - `data-table:catalog.products:row-actions` — product row actions
76
-
77
- ## Using Catalog in Sales
78
-
79
- When building sales-related features, use the catalog pricing service to resolve prices rather than reading price entities directly. This ensures channel scoping, customer-specific pricing, and promotional offers are applied correctly.
3
+ > This guide has moved. See [`modules/catalog.md`](modules/catalog.md) for the generated `catalog` fact-sheet, and [`module-system.md`](module-system.md) for conceptual module guidance.
@@ -1,43 +1,3 @@
1
- # Currencies Module — Standalone App Guide
1
+ # core.currencies — moved
2
2
 
3
- Use the currencies module for multi-currency support, exchange rates, and currency conversion.
4
-
5
- ## Key Rules
6
-
7
- 1. **Store amounts with 4 decimal precision** — never truncate to 2 decimals internally
8
- 2. **Use date-based exchange rates** — always resolve rates for the transaction date, not the "current" rate
9
- 3. **Record both currencies** — dual recording (transaction currency + base currency) is mandatory for reporting
10
- 4. **Calculate realized gains/losses** on payment: `(payment rate - invoice rate) × foreign amount`
11
- 5. **Never hard-delete exchange rates** — they are historical reference data
12
-
13
- ## Multi-Currency Transaction Pattern
14
-
15
- When processing multi-currency transactions (e.g., sales invoice in EUR with USD base):
16
-
17
- 1. Retrieve the exchange rate for the transaction date
18
- 2. Generate the document in the transaction currency
19
- 3. Calculate the base currency equivalent: `foreign amount × rate`
20
- 4. Store both amounts on the document
21
- 5. On payment: calculate realized gain/loss from rate difference
22
- 6. Report in both transaction and base currencies
23
-
24
- ## Data Model
25
-
26
- | Entity | Table | Purpose |
27
- |--------|-------|---------|
28
- | **Currency** | `currency` | Currency master data (code, name, symbol) |
29
- | **Exchange Rate** | `exchange_rate` | Daily exchange rates per currency pair |
30
-
31
- ## Adding a New Currency
32
-
33
- 1. Add the currency record via the admin UI or `seedDefaults` hook in your `setup.ts`
34
- 2. Ensure exchange rates exist for the currency pair at required dates
35
- 3. Verify all sales/pricing logic resolves the new currency correctly
36
-
37
- ## Using Currencies in Your Module
38
-
39
- When your module deals with monetary amounts:
40
- - Store the currency code alongside the amount
41
- - Reference the currencies module for exchange rate lookups
42
- - Use the transaction date for rate resolution, not the current date
43
- - Store both foreign and base amounts for reporting
3
+ > This guide has moved. See [`modules/currencies.md`](modules/currencies.md) for the generated `currencies` fact-sheet, and [`module-system.md`](module-system.md) for conceptual module guidance.
@@ -1,129 +1,3 @@
1
- # Customer Accounts Module — Standalone App Guide
1
+ # core.customer_accounts — moved
2
2
 
3
- Customer-facing identity and portal authentication. This module manages customer user accounts, sessions, roles, and the authentication flow for the customer portal. It is separate from the staff `auth` module.
4
-
5
- ## Portal Authentication
6
-
7
- ### Login Flow
8
- 1. Customer submits credentials via `POST /api/login`
9
- 2. Password verified with bcryptjs, lockout checked (5 attempts → 15 min lock)
10
- 3. JWT issued with customer claims (`type: 'customer'`, features, CRM links)
11
- 4. Two cookies set: `customer_auth_token` (JWT, 8h) + `customer_session_token` (raw, 30d)
12
-
13
- ### Other Auth Methods
14
- - **Signup**: `POST /api/signup` — self-registration with email verification
15
- - **Magic Link**: `POST /api/magic-link/request` + `/verify` — passwordless login (15 min TTL)
16
- - **Password Reset**: `POST /api/password/reset-request` + `/reset-confirm` (60 min TTL)
17
- - **Invitation**: Admin invites user → `POST /api/invitations/accept` (72h TTL)
18
-
19
- ## Customer RBAC
20
-
21
- ### Two-Layer Model (mirrors staff RBAC)
22
- 1. **Role ACLs** — features assigned to roles
23
- 2. **User ACLs** — per-user overrides (takes precedence if present)
24
-
25
- ### Default Roles (seeded on tenant creation)
26
- | Role | Features | Portal Admin |
27
- |------|----------|-------------|
28
- | Portal Admin | `portal.*` | Yes |
29
- | Buyer | Orders, quotes, catalog, account | No |
30
- | Viewer | Read-only orders, invoices, catalog | No |
31
-
32
- ### Feature Convention
33
- Portal features use `portal.<area>.<action>` naming (e.g., `portal.orders.view`, `portal.catalog.view`).
34
-
35
- ### Cross-Module Feature Merging
36
- Your module can declare `defaultCustomerRoleFeatures` in `setup.ts`. During tenant setup, these are merged into the corresponding customer role ACLs:
37
-
38
- ```typescript
39
- // src/modules/<your_module>/setup.ts
40
- export const setup: ModuleSetupConfig = {
41
- defaultCustomerRoleFeatures: {
42
- portal_admin: ['portal.your_feature.*'],
43
- buyer: ['portal.your_feature.view'],
44
- },
45
- }
46
- ```
47
-
48
- ## Using Customer Auth in Your Module
49
-
50
- ### Server Components (pages)
51
- ```typescript
52
- import { getCustomerAuthFromCookies } from '@open-mercato/core/modules/customer_accounts/lib/customerAuthServer'
53
-
54
- const auth = await getCustomerAuthFromCookies()
55
- if (!auth) redirect('/login')
56
- ```
57
-
58
- ### API Routes
59
- ```typescript
60
- import { requireCustomerAuth, requireCustomerFeature } from '@open-mercato/core/modules/customer_accounts/lib/customerAuth'
61
- import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
62
- import type { CustomerRbacService } from '@open-mercato/core/modules/customer_accounts/services/customerRbacService'
63
-
64
- // In your API handler:
65
- const auth = await requireCustomerAuth(request) // throws 401 if not authenticated
66
- const container = await createRequestContainer()
67
- const customerRbacService = container.resolve('customerRbacService') as CustomerRbacService
68
- // Re-resolves ACL on every request so role/feature revocation is immediate
69
- await requireCustomerFeature(auth, ['portal.orders.view'], customerRbacService) // throws 403 if missing
70
- ```
71
-
72
- ### RBAC Service
73
- ```typescript
74
- const rbacService = container.resolve('customerRbacService')
75
- const hasAccess = await rbacService.userHasAllFeatures(
76
- userId, ['portal.orders.view'], { tenantId, organizationId }
77
- )
78
- ```
79
-
80
- ## Portal Page Guards
81
-
82
- Use declarative metadata for portal pages:
83
-
84
- ```typescript
85
- export const metadata = {
86
- requireCustomerAuth: true,
87
- requireCustomerFeatures: ['portal.orders.view'],
88
- }
89
- ```
90
-
91
- ## Subscribing to Customer Events
92
-
93
- | Event | When |
94
- |-------|------|
95
- | `customer_accounts.user.created` | New customer signup |
96
- | `customer_accounts.user.updated` | Profile updated |
97
- | `customer_accounts.user.locked` | Account locked after failed logins |
98
- | `customer_accounts.login.success` | Successful login |
99
- | `customer_accounts.invitation.accepted` | Invitation accepted |
100
-
101
- ```typescript
102
- export const metadata = {
103
- event: 'customer_accounts.user.created',
104
- persistent: true,
105
- id: 'your-module-customer-signup',
106
- }
107
-
108
- export default async function handler(payload, ctx) {
109
- // React to customer signup — e.g., create default preferences
110
- }
111
- ```
112
-
113
- ## CRM Auto-Linking
114
-
115
- When a customer signs up, the module automatically searches for a matching CRM person by email and links them (`personEntityId`). The reverse also works — creating a CRM person auto-links to an existing customer user.
116
-
117
- ## Widget Injection Spots
118
-
119
- | Spot | Widget | Purpose |
120
- |------|--------|---------|
121
- | `crud-form:customers:customer_person_profile:fields` | Account status | Shows portal account status on CRM person detail |
122
- | `crud-form:customers:customer_company_profile:fields` | Company users | Shows portal users linked to a CRM company |
123
-
124
- ## Security Notes
125
-
126
- - All public endpoints are rate-limited (per-email + per-IP)
127
- - Tokens stored as SHA-256 hashes — raw tokens never persisted
128
- - Emails use deterministic hash for lookups (`hashForLookup`)
129
- - Error messages never confirm whether an email is registered
3
+ > This guide has moved. See [`modules/customer_accounts.md`](modules/customer_accounts.md) for the generated `customer_accounts` fact-sheet, and [`module-system.md`](module-system.md) for conceptual module guidance.
@@ -1,138 +1,3 @@
1
- # Customers Module — Reference CRUD Patterns
1
+ # core.customers — moved
2
2
 
3
- This is the **reference CRUD module**. When building new modules in your standalone app, follow these patterns.
4
-
5
- ## CRUD API Pattern
6
-
7
- Use `makeCrudRoute` with `indexer: { entityType }` for query index coverage:
8
-
9
- ```typescript
10
- // src/modules/<your_module>/api/get/<entities>.ts
11
- import { makeCrudRoute } from '@open-mercato/shared/lib/crud/make-crud-route'
12
- import { YourEntity } from '../../entities/YourEntity'
13
-
14
- const handler = makeCrudRoute({
15
- entity: YourEntity,
16
- entityId: 'your_module.your_entity',
17
- operations: ['list', 'detail'],
18
- indexer: { entityType: 'your_module.your_entity' },
19
- })
20
-
21
- export default handler
22
- export const openApi = { summary: 'List and retrieve entities', tags: ['Your Module'] }
23
- ```
24
-
25
- Key points:
26
- - Always set `indexer: { entityType }` — keeps custom entities indexed
27
- - Wire custom field helpers for create/update if your module supports custom fields
28
- - Export `openApi` on every API route file
29
-
30
- ## Undoable Commands Pattern
31
-
32
- All write operations should use the Command pattern with undo support:
33
-
34
- ```typescript
35
- import { registerCommand } from '@open-mercato/shared/lib/commands'
36
- import { extractUndoPayload } from '@open-mercato/shared/lib/commands/undo'
37
-
38
- registerCommand('your_module.entity.create', {
39
- async execute(payload, ctx) {
40
- // 1. Create entity
41
- // 2. Capture snapshot for undo: extractUndoPayload(entity)
42
- // 3. Side effects: emitCrudSideEffects({ indexer: { entityType, cacheAliases } })
43
- },
44
- async undo(payload, ctx) {
45
- // 1. Restore from snapshot
46
- // 2. Side effects: emitCrudUndoSideEffects({ indexer: { entityType, cacheAliases } })
47
- },
48
- })
49
- ```
50
-
51
- Key points:
52
- - Include `indexer: { entityType, cacheAliases }` in both `emitCrudSideEffects` and `emitCrudUndoSideEffects`
53
- - Capture custom field snapshots in `before`/`after` payloads (`snapshot.custom`)
54
- - Restore custom fields via `buildCustomFieldResetMap(before.custom, after.custom)` in undo
55
-
56
- ## Custom Field Integration
57
-
58
- ```typescript
59
- import { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'
60
- ```
61
-
62
- - Pass `{ transform }` to normalize values (e.g., `normalizeCustomFieldSubmitValue`)
63
- - Works for both `cf_` and `cf:` prefixed keys
64
- - Pass `entityIds` to form helpers so correct custom-field sets are loaded
65
- - If your module ships default custom fields, declare them in `ce.ts` via `entities[].fields`
66
-
67
- ## Search Configuration
68
-
69
- Declare in `search.ts` with all three strategies:
70
-
71
- ```typescript
72
- import type { SearchModuleConfig } from '@open-mercato/shared/modules/search'
73
-
74
- export const searchConfig: SearchModuleConfig = {
75
- entities: {
76
- 'your_module.your_entity': {
77
- fields: ['name', 'description'], // Fulltext indexing
78
- // fieldPolicy for sensitive field handling
79
- // buildSource for vector embeddings
80
- // formatResult for search result display
81
- },
82
- },
83
- }
84
- ```
85
-
86
- Key points:
87
- - Use `fieldPolicy.excluded` for sensitive fields (passwords, tokens)
88
- - Use `fieldPolicy.hashOnly` for PII needing exact-match only (email, phone)
89
- - Always define `formatResult` for human-friendly search results
90
-
91
- ## Backend Page Structure
92
-
93
- Follow this pattern for each page type:
94
-
95
- | Page | Pattern | Key Features |
96
- |------|---------|-------------|
97
- | **List** | `DataTable` | Filters, search, export, row actions, pagination |
98
- | **Create** | `CrudForm` mode=create | Fields, groups, custom fields, back link |
99
- | **Detail/Edit** | `CrudForm` mode=edit or tabbed layout | Entity data, related entities, activities |
100
-
101
- ## Module Files Checklist
102
-
103
- When scaffolding a new CRUD module, ensure all these files are present:
104
-
105
- | File | Purpose |
106
- |------|---------|
107
- | `index.ts` | Module metadata |
108
- | `acl.ts` | Feature-based permissions |
109
- | `setup.ts` | Tenant init, default role features |
110
- | `di.ts` | Awilix DI registrations |
111
- | `events.ts` | Typed event declarations |
112
- | `data/entities.ts` | MikroORM entity classes |
113
- | `data/validators.ts` | Zod validation schemas |
114
- | `search.ts` | Search indexing configuration |
115
- | `ce.ts` | Custom entities / custom field sets |
116
-
117
- Optional:
118
- - `translations.ts` — translatable fields per entity
119
- - `notifications.ts` — notification type definitions
120
- - `cli.ts` — module CLI commands
121
-
122
- ## Entity Update Safety
123
-
124
- When mutating entities across multiple phases that include queries:
125
-
126
- ```typescript
127
- import { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'
128
-
129
- await withAtomicFlush(em, [
130
- () => { record.name = 'New'; record.status = 'active' },
131
- () => syncEntityTags(em, record, tags),
132
- ], { transaction: true })
133
-
134
- // Side effects AFTER the atomic flush
135
- await emitCrudSideEffects({ ... })
136
- ```
137
-
138
- Never run `em.find`/`em.findOne` between scalar mutations and `em.flush()` without `withAtomicFlush` — changes will be silently lost. Cache invalidation must also stay outside `withAtomicFlush` and fire after commit, so the opt-in `OM_CACHE_SAFETY_ALWAYS_CONSISTENT` mode (default OFF) never serves stale or partially-committed reads.
3
+ > This guide has moved. See [`modules/customers.md`](modules/customers.md) for the generated `customers` fact-sheet, and [`module-system.md`](module-system.md) for conceptual module guidance.