create-flowdular 0.2.4 → 0.2.6

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 (271) hide show
  1. package/README.md +11 -0
  2. package/agent-template/.agents/skills/agent-tool-design/SKILL.md +203 -0
  3. package/agent-template/.agents/skills/auth-security-review/SKILL.md +90 -0
  4. package/agent-template/.agents/skills/auto-review/SKILL.md +103 -0
  5. package/agent-template/.agents/skills/bug-hunt/SKILL.md +104 -0
  6. package/agent-template/.agents/skills/business-agent-design/SKILL.md +182 -0
  7. package/agent-template/.agents/skills/cli-extension/SKILL.md +108 -0
  8. package/agent-template/.agents/skills/core-extend/SKILL.md +99 -0
  9. package/agent-template/.agents/skills/database-adapter/SKILL.md +198 -0
  10. package/agent-template/.agents/skills/database-adapter/references/first-run-and-matrix.md +105 -0
  11. package/agent-template/.agents/skills/migration-authoring/SKILL.md +161 -0
  12. package/agent-template/.agents/skills/module-new/SKILL.md +171 -0
  13. package/agent-template/.agents/skills/module-update/SKILL.md +91 -0
  14. package/agent-template/.agents/skills/perf-audit/SKILL.md +98 -0
  15. package/agent-template/.agents/skills/release-eject-pr/SKILL.md +107 -0
  16. package/agent-template/.agents/skills/spec-approval/SKILL.md +106 -0
  17. package/agent-template/.agents/skills/test-hardening/SKILL.md +79 -0
  18. package/agent-template/.agents/skills/translations-i18n/SKILL.md +78 -0
  19. package/agent-template/.agents/skills/ux-design/SKILL.md +92 -0
  20. package/agent-template/.agents/skills/variables/SKILL.md +156 -0
  21. package/agent-template/.agents/skills/workflow-development/SKILL.md +192 -0
  22. package/agent-template/.ai/README.md +62 -0
  23. package/agent-template/.ai/agents/README.md +27 -0
  24. package/agent-template/.ai/agents/module-executor.md +36 -0
  25. package/agent-template/.ai/agents/reviewer.md +23 -0
  26. package/agent-template/.ai/agents/sandbox/agentic-engineer.md +31 -0
  27. package/agent-template/.ai/agents/sandbox/backend-engineer.md +36 -0
  28. package/agent-template/.ai/agents/sandbox/business-manager.md +23 -0
  29. package/agent-template/.ai/agents/sandbox/frontend-engineer.md +27 -0
  30. package/agent-template/.ai/agents/sandbox/ux-designer.md +23 -0
  31. package/agent-template/.ai/agents/spec-author.md +29 -0
  32. package/agent-template/.ai/blueprints/add-migration/README.md +5 -0
  33. package/agent-template/.ai/blueprints/add-migration/allowed-paths.yaml +23 -0
  34. package/agent-template/.ai/blueprints/add-migration/blueprint.json +14 -0
  35. package/agent-template/.ai/blueprints/add-migration/examples/invalid/input-destructive.json +6 -0
  36. package/agent-template/.ai/blueprints/add-migration/examples/invalid/plan-unnumbered-file.json +9 -0
  37. package/agent-template/.ai/blueprints/add-migration/examples/valid/input.json +6 -0
  38. package/agent-template/.ai/blueprints/add-migration/examples/valid/plan.json +9 -0
  39. package/agent-template/.ai/blueprints/add-migration/gates.yaml +30 -0
  40. package/agent-template/.ai/blueprints/add-migration/input.schema.json +23 -0
  41. package/agent-template/.ai/blueprints/add-migration/plan.schema.json +54 -0
  42. package/agent-template/.ai/blueprints/add-migration/required-files.yaml +18 -0
  43. package/agent-template/.ai/blueprints/add-migration/spec-requirements.yaml +13 -0
  44. package/agent-template/.ai/blueprints/add-migration/steps.yaml +62 -0
  45. package/agent-template/.ai/blueprints/author-spec/README.md +5 -0
  46. package/agent-template/.ai/blueprints/author-spec/allowed-paths.yaml +7 -0
  47. package/agent-template/.ai/blueprints/author-spec/blueprint.json +14 -0
  48. package/agent-template/.ai/blueprints/author-spec/examples/invalid/input-missing-outcome.json +5 -0
  49. package/agent-template/.ai/blueprints/author-spec/examples/valid/input.json +6 -0
  50. package/agent-template/.ai/blueprints/author-spec/gates.yaml +13 -0
  51. package/agent-template/.ai/blueprints/author-spec/input.schema.json +20 -0
  52. package/agent-template/.ai/blueprints/author-spec/plan.schema.json +14 -0
  53. package/agent-template/.ai/blueprints/author-spec/required-files.yaml +6 -0
  54. package/agent-template/.ai/blueprints/author-spec/spec-requirements.yaml +35 -0
  55. package/agent-template/.ai/blueprints/author-spec/steps.yaml +28 -0
  56. package/agent-template/.ai/blueprints/author-spec/templates/module.yaml +45 -0
  57. package/agent-template/.ai/blueprints/bug-fix/README.md +5 -0
  58. package/agent-template/.ai/blueprints/bug-fix/allowed-paths.yaml +29 -0
  59. package/agent-template/.ai/blueprints/bug-fix/blueprint.json +14 -0
  60. package/agent-template/.ai/blueprints/bug-fix/examples/invalid/input-no-symptom.json +4 -0
  61. package/agent-template/.ai/blueprints/bug-fix/examples/invalid/plan-no-test.json +8 -0
  62. package/agent-template/.ai/blueprints/bug-fix/examples/valid/input.json +6 -0
  63. package/agent-template/.ai/blueprints/bug-fix/examples/valid/plan.json +8 -0
  64. package/agent-template/.ai/blueprints/bug-fix/gates.yaml +30 -0
  65. package/agent-template/.ai/blueprints/bug-fix/input.schema.json +25 -0
  66. package/agent-template/.ai/blueprints/bug-fix/plan.schema.json +53 -0
  67. package/agent-template/.ai/blueprints/bug-fix/required-files.yaml +7 -0
  68. package/agent-template/.ai/blueprints/bug-fix/spec-requirements.yaml +7 -0
  69. package/agent-template/.ai/blueprints/bug-fix/steps.yaml +51 -0
  70. package/agent-template/.ai/blueprints/core-extend/README.md +5 -0
  71. package/agent-template/.ai/blueprints/core-extend/allowed-paths.yaml +49 -0
  72. package/agent-template/.ai/blueprints/core-extend/blueprint.json +14 -0
  73. package/agent-template/.ai/blueprints/core-extend/examples/invalid/input-unknown-package.json +5 -0
  74. package/agent-template/.ai/blueprints/core-extend/examples/invalid/plan-missing-gates.json +7 -0
  75. package/agent-template/.ai/blueprints/core-extend/examples/valid/input.json +6 -0
  76. package/agent-template/.ai/blueprints/core-extend/examples/valid/plan.json +10 -0
  77. package/agent-template/.ai/blueprints/core-extend/gates.yaml +16 -0
  78. package/agent-template/.ai/blueprints/core-extend/input.schema.json +54 -0
  79. package/agent-template/.ai/blueprints/core-extend/plan.schema.json +39 -0
  80. package/agent-template/.ai/blueprints/core-extend/required-files.yaml +36 -0
  81. package/agent-template/.ai/blueprints/core-extend/spec-requirements.yaml +17 -0
  82. package/agent-template/.ai/blueprints/core-extend/steps.yaml +54 -0
  83. package/agent-template/.ai/blueprints/edit-module/README.md +9 -0
  84. package/agent-template/.ai/blueprints/edit-module/allowed-paths.yaml +27 -0
  85. package/agent-template/.ai/blueprints/edit-module/blueprint.json +20 -0
  86. package/agent-template/.ai/blueprints/edit-module/examples/invalid/input-unknown-change.json +5 -0
  87. package/agent-template/.ai/blueprints/edit-module/examples/invalid/plan-touches-platform.json +15 -0
  88. package/agent-template/.ai/blueprints/edit-module/examples/valid/input.json +5 -0
  89. package/agent-template/.ai/blueprints/edit-module/examples/valid/plan.json +25 -0
  90. package/agent-template/.ai/blueprints/edit-module/gates.yaml +30 -0
  91. package/agent-template/.ai/blueprints/edit-module/input.schema.json +31 -0
  92. package/agent-template/.ai/blueprints/edit-module/plan.schema.json +65 -0
  93. package/agent-template/.ai/blueprints/edit-module/required-files.yaml +80 -0
  94. package/agent-template/.ai/blueprints/edit-module/spec-requirements.yaml +15 -0
  95. package/agent-template/.ai/blueprints/edit-module/steps.yaml +115 -0
  96. package/agent-template/.ai/blueprints/new-module/README.md +7 -0
  97. package/agent-template/.ai/blueprints/new-module/allowed-paths.yaml +27 -0
  98. package/agent-template/.ai/blueprints/new-module/blueprint.json +20 -0
  99. package/agent-template/.ai/blueprints/new-module/examples/invalid/input-spec-outside-modules.json +4 -0
  100. package/agent-template/.ai/blueprints/new-module/examples/invalid/plan-unknown-gate.json +8 -0
  101. package/agent-template/.ai/blueprints/new-module/examples/valid/input.json +5 -0
  102. package/agent-template/.ai/blueprints/new-module/examples/valid/plan.json +22 -0
  103. package/agent-template/.ai/blueprints/new-module/gates.yaml +30 -0
  104. package/agent-template/.ai/blueprints/new-module/input.schema.json +21 -0
  105. package/agent-template/.ai/blueprints/new-module/plan.schema.json +58 -0
  106. package/agent-template/.ai/blueprints/new-module/required-files.yaml +73 -0
  107. package/agent-template/.ai/blueprints/new-module/spec-requirements.yaml +30 -0
  108. package/agent-template/.ai/blueprints/new-module/steps.yaml +138 -0
  109. package/agent-template/.ai/blueprints/release/README.md +5 -0
  110. package/agent-template/.ai/blueprints/release/allowed-paths.yaml +19 -0
  111. package/agent-template/.ai/blueprints/release/blueprint.json +14 -0
  112. package/agent-template/.ai/blueprints/release/examples/invalid/input-bad-version.json +4 -0
  113. package/agent-template/.ai/blueprints/release/examples/invalid/plan-bad-branch.json +7 -0
  114. package/agent-template/.ai/blueprints/release/examples/valid/input.json +5 -0
  115. package/agent-template/.ai/blueprints/release/examples/valid/plan.json +20 -0
  116. package/agent-template/.ai/blueprints/release/gates.yaml +20 -0
  117. package/agent-template/.ai/blueprints/release/input.schema.json +24 -0
  118. package/agent-template/.ai/blueprints/release/plan.schema.json +46 -0
  119. package/agent-template/.ai/blueprints/release/required-files.yaml +19 -0
  120. package/agent-template/.ai/blueprints/release/spec-requirements.yaml +8 -0
  121. package/agent-template/.ai/blueprints/release/steps.yaml +47 -0
  122. package/agent-template/.ai/blueprints/security-review/README.md +5 -0
  123. package/agent-template/.ai/blueprints/security-review/allowed-paths.yaml +6 -0
  124. package/agent-template/.ai/blueprints/security-review/blueprint.json +14 -0
  125. package/agent-template/.ai/blueprints/security-review/examples/invalid/input-unknown-kind.json +4 -0
  126. package/agent-template/.ai/blueprints/security-review/examples/invalid/plan-finding-without-scenario.json +14 -0
  127. package/agent-template/.ai/blueprints/security-review/examples/valid/input.json +4 -0
  128. package/agent-template/.ai/blueprints/security-review/examples/valid/plan.json +19 -0
  129. package/agent-template/.ai/blueprints/security-review/gates.yaml +22 -0
  130. package/agent-template/.ai/blueprints/security-review/input.schema.json +20 -0
  131. package/agent-template/.ai/blueprints/security-review/plan.schema.json +65 -0
  132. package/agent-template/.ai/blueprints/security-review/required-files.yaml +6 -0
  133. package/agent-template/.ai/blueprints/security-review/spec-requirements.yaml +9 -0
  134. package/agent-template/.ai/blueprints/security-review/steps.yaml +38 -0
  135. package/agent-template/.ai/examples/README.md +8 -0
  136. package/agent-template/.ai/examples/bad/client-imports-server/README.md +20 -0
  137. package/agent-template/.ai/examples/bad/client-imports-server/api.ts +12 -0
  138. package/agent-template/.ai/examples/bad/missing-acl/README.md +23 -0
  139. package/agent-template/.ai/examples/bad/missing-acl/endpoints.ts +12 -0
  140. package/agent-template/.ai/examples/bad/tenant-from-body/README.md +19 -0
  141. package/agent-template/.ai/examples/bad/tenant-from-body/endpoints.ts +33 -0
  142. package/agent-template/.ai/examples/client-contribution/CustomerListView.tsrx +34 -0
  143. package/agent-template/.ai/examples/client-contribution/README.md +11 -0
  144. package/agent-template/.ai/examples/client-contribution/contribution.tsrx +48 -0
  145. package/agent-template/.ai/examples/client-contribution/index.ts +20 -0
  146. package/agent-template/.ai/examples/client-contribution/permissions.ts +8 -0
  147. package/agent-template/.ai/examples/customer-cli-extension/README.md +14 -0
  148. package/agent-template/.ai/examples/customer-cli-extension/commands.json +17 -0
  149. package/agent-template/.ai/examples/customer-cli-extension/index.ts +36 -0
  150. package/agent-template/.ai/examples/module-create/task-packet.json +11 -0
  151. package/agent-template/.ai/guides/application-development.md +97 -0
  152. package/agent-template/.ai/policies/capabilities.yaml +164 -0
  153. package/agent-template/.ai/policies/model-routing.yaml +72 -0
  154. package/agent-template/.ai/policies/path-ownership.yaml +65 -0
  155. package/agent-template/.ai/policies/task-budgets.yaml +37 -0
  156. package/agent-template/.ai/references/catalog/LICENSE +21 -0
  157. package/agent-template/.ai/references/catalog/migrations/0001_catalog_core.down.sql +2 -0
  158. package/agent-template/.ai/references/catalog/migrations/0001_catalog_core.up.sql +21 -0
  159. package/agent-template/.ai/references/catalog/migrations/0002_catalog_history.down.sql +3 -0
  160. package/agent-template/.ai/references/catalog/migrations/0002_catalog_history.up.sql +20 -0
  161. package/agent-template/.ai/references/catalog/migrations/0003_catalog_history_service_actors.down.sql +3 -0
  162. package/agent-template/.ai/references/catalog/migrations/0003_catalog_history_service_actors.up.sql +36 -0
  163. package/agent-template/.ai/references/catalog/migrations/0004_catalog_idempotency_ledger.down.sql +3 -0
  164. package/agent-template/.ai/references/catalog/migrations/0004_catalog_idempotency_ledger.up.sql +19 -0
  165. package/agent-template/.ai/references/catalog/migrations/README.md +3 -0
  166. package/agent-template/.ai/references/catalog/module.json +27 -0
  167. package/agent-template/.ai/references/catalog/package.json +49 -0
  168. package/agent-template/.ai/references/catalog/spec/module.yaml +86 -0
  169. package/agent-template/.ai/references/catalog/src/acl/permissions.ts +6 -0
  170. package/agent-template/.ai/references/catalog/src/agent/tools.ts +164 -0
  171. package/agent-template/.ai/references/catalog/src/api/endpoints.ts +243 -0
  172. package/agent-template/.ai/references/catalog/src/client/CatalogHistoryDrawer.tsrx +123 -0
  173. package/agent-template/.ai/references/catalog/src/client/CatalogItemForm.tsrx +190 -0
  174. package/agent-template/.ai/references/catalog/src/client/CatalogView.tsrx +473 -0
  175. package/agent-template/.ai/references/catalog/src/client/api.ts +111 -0
  176. package/agent-template/.ai/references/catalog/src/client/contribution.tsrx +61 -0
  177. package/agent-template/.ai/references/catalog/src/client/index.ts +18 -0
  178. package/agent-template/.ai/references/catalog/src/client/navigation-copy.ts +9 -0
  179. package/agent-template/.ai/references/catalog/src/client/state.ts +24 -0
  180. package/agent-template/.ai/references/catalog/src/domain/types.ts +32 -0
  181. package/agent-template/.ai/references/catalog/src/domain/variables.ts +111 -0
  182. package/agent-template/.ai/references/catalog/src/index.ts +31 -0
  183. package/agent-template/.ai/references/catalog/src/platform.ts +35 -0
  184. package/agent-template/.ai/references/catalog/src/server/index.ts +4 -0
  185. package/agent-template/.ai/references/catalog/src/server/runtime.ts +86 -0
  186. package/agent-template/.ai/references/catalog/src/services/catalog-service.ts +306 -0
  187. package/agent-template/.ai/references/catalog/src/services/database-repository.ts +440 -0
  188. package/agent-template/.ai/references/catalog/src/services/index.ts +4 -0
  189. package/agent-template/.ai/references/catalog/src/services/migration.ts +171 -0
  190. package/agent-template/.ai/references/catalog/src/services/repository.ts +36 -0
  191. package/agent-template/.ai/references/catalog/src/services/target-idempotency.ts +59 -0
  192. package/agent-template/.ai/references/catalog/tests/agent-tools.test.ts +277 -0
  193. package/agent-template/.ai/references/catalog/tests/endpoints.test.ts +320 -0
  194. package/agent-template/.ai/references/catalog/tests/idempotency.test.ts +297 -0
  195. package/agent-template/.ai/references/catalog/tests/migrations.test.ts +149 -0
  196. package/agent-template/.ai/references/catalog/tests/module.test.ts +271 -0
  197. package/agent-template/.ai/references/catalog/tests/support/database.ts +76 -0
  198. package/agent-template/.ai/references/catalog/translations/en.json +101 -0
  199. package/agent-template/.ai/references/catalog/translations/pl.json +101 -0
  200. package/agent-template/.ai/references/catalog/tsconfig.json +15 -0
  201. package/agent-template/.ai/references/catalog/vitest.config.ts +16 -0
  202. package/agent-template/.ai/references/catalog.provenance.json +55 -0
  203. package/agent-template/.ai/rules/flowdular.md +86 -0
  204. package/agent-template/.ai/skills/README.md +36 -0
  205. package/agent-template/.ai/skills/agent-tool-design/SKILL.md +209 -0
  206. package/agent-template/.ai/skills/auth-security-review/SKILL.md +96 -0
  207. package/agent-template/.ai/skills/auto-review/SKILL.md +112 -0
  208. package/agent-template/.ai/skills/bug-hunt/SKILL.md +110 -0
  209. package/agent-template/.ai/skills/business-agent-design/SKILL.md +188 -0
  210. package/agent-template/.ai/skills/cli-extension/SKILL.md +114 -0
  211. package/agent-template/.ai/skills/core-extend/SKILL.md +104 -0
  212. package/agent-template/.ai/skills/database-adapter/SKILL.md +204 -0
  213. package/agent-template/.ai/skills/database-adapter/references/first-run-and-matrix.md +105 -0
  214. package/agent-template/.ai/skills/migration-authoring/SKILL.md +167 -0
  215. package/agent-template/.ai/skills/module-new/SKILL.md +180 -0
  216. package/agent-template/.ai/skills/module-update/SKILL.md +100 -0
  217. package/agent-template/.ai/skills/perf-audit/SKILL.md +105 -0
  218. package/agent-template/.ai/skills/release-eject-pr/SKILL.md +113 -0
  219. package/agent-template/.ai/skills/spec-approval/SKILL.md +112 -0
  220. package/agent-template/.ai/skills/test-hardening/SKILL.md +86 -0
  221. package/agent-template/.ai/skills/translations-i18n/SKILL.md +85 -0
  222. package/agent-template/.ai/skills/ux-design/SKILL.md +97 -0
  223. package/agent-template/.ai/skills/variables/SKILL.md +164 -0
  224. package/agent-template/.ai/skills/workflow-development/SKILL.md +199 -0
  225. package/agent-template/.claude/skills/agent-tool-design/SKILL.md +203 -0
  226. package/agent-template/.claude/skills/auth-security-review/SKILL.md +90 -0
  227. package/agent-template/.claude/skills/auto-review/SKILL.md +103 -0
  228. package/agent-template/.claude/skills/bug-hunt/SKILL.md +104 -0
  229. package/agent-template/.claude/skills/business-agent-design/SKILL.md +182 -0
  230. package/agent-template/.claude/skills/cli-extension/SKILL.md +108 -0
  231. package/agent-template/.claude/skills/core-extend/SKILL.md +99 -0
  232. package/agent-template/.claude/skills/database-adapter/SKILL.md +198 -0
  233. package/agent-template/.claude/skills/database-adapter/references/first-run-and-matrix.md +105 -0
  234. package/agent-template/.claude/skills/migration-authoring/SKILL.md +161 -0
  235. package/agent-template/.claude/skills/module-new/SKILL.md +171 -0
  236. package/agent-template/.claude/skills/module-update/SKILL.md +91 -0
  237. package/agent-template/.claude/skills/perf-audit/SKILL.md +98 -0
  238. package/agent-template/.claude/skills/release-eject-pr/SKILL.md +107 -0
  239. package/agent-template/.claude/skills/spec-approval/SKILL.md +106 -0
  240. package/agent-template/.claude/skills/test-hardening/SKILL.md +79 -0
  241. package/agent-template/.claude/skills/translations-i18n/SKILL.md +78 -0
  242. package/agent-template/.claude/skills/ux-design/SKILL.md +92 -0
  243. package/agent-template/.claude/skills/variables/SKILL.md +156 -0
  244. package/agent-template/.claude/skills/workflow-development/SKILL.md +192 -0
  245. package/agent-template/AGENTS.md +77 -0
  246. package/agent-template/CLAUDE.md +77 -0
  247. package/agent-template/docs/adr/0001-development-reload.md +16 -0
  248. package/agent-template/docs/adr/0002-durable-agent-execution.md +21 -0
  249. package/agent-template/docs/adr/0003-module-settings.md +22 -0
  250. package/agent-template/docs/adr/0004-enterprise-access-and-audit.md +36 -0
  251. package/agent-template/docs/adr/0005-sandbox-runtime-and-coding-agents.md +81 -0
  252. package/agent-template/docs/adr/0006-agentic-workflows.md +1702 -0
  253. package/agent-template/docs/adr/0007-module-owned-agents.md +429 -0
  254. package/agent-template/docs/adr/0008-database-adapter-contract.md +90 -0
  255. package/agent-template/docs/agent-contract.md +45 -0
  256. package/agent-template/docs/configuration.md +122 -0
  257. package/agent-template/docs/database-adapters.md +346 -0
  258. package/agent-template/docs/design-system.md +217 -0
  259. package/agent-template/docs/modules.md +146 -0
  260. package/agent-template/platform/scripts/build.mjs +38 -0
  261. package/agent-template/rulesync.jsonc +11 -0
  262. package/dist/bin.js +40 -2
  263. package/package.json +3 -2
  264. package/template/default/.prettierignore +9 -0
  265. package/template/default/README.md +12 -0
  266. package/template/default/flowdular.json +3 -3
  267. package/template/default/modules/example/package.json +2 -2
  268. package/template/default/package.json +6 -2
  269. package/template/default/platform/octane.config.ts +17 -6
  270. package/template/default/platform/package.json +3 -2
  271. package/template/default/pnpm-workspace.yaml +1 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Flowdular contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ DROP POLICY IF EXISTS catalog_items_tenant_policy ON catalog_items;
2
+ DROP TABLE IF EXISTS catalog_items;
@@ -0,0 +1,21 @@
1
+ CREATE TABLE IF NOT EXISTS catalog_items (
2
+ id TEXT PRIMARY KEY,
3
+ tenant_id TEXT NOT NULL,
4
+ sku TEXT NOT NULL,
5
+ sku_normalized TEXT NOT NULL,
6
+ name TEXT NOT NULL,
7
+ kind TEXT NOT NULL CHECK (kind IN ('product', 'service')),
8
+ unit TEXT NOT NULL,
9
+ base_price_minor BIGINT NOT NULL CHECK (base_price_minor >= 0),
10
+ currency TEXT NOT NULL,
11
+ status TEXT NOT NULL CHECK (status IN ('active', 'archived')),
12
+ created_at BIGINT NOT NULL,
13
+ UNIQUE (tenant_id, sku_normalized)
14
+ );
15
+ CREATE INDEX IF NOT EXISTS catalog_items_tenant_sku_idx
16
+ ON catalog_items (tenant_id, sku_normalized, id);
17
+ ALTER TABLE catalog_items ENABLE ROW LEVEL SECURITY;
18
+ ALTER TABLE catalog_items FORCE ROW LEVEL SECURITY;
19
+ CREATE POLICY catalog_items_tenant_policy ON catalog_items
20
+ USING (tenant_id = current_setting('coreloom.tenant_id', true))
21
+ WITH CHECK (tenant_id = current_setting('coreloom.tenant_id', true));
@@ -0,0 +1,3 @@
1
+ DROP POLICY IF EXISTS catalog_items_history_tenant_policy ON catalog_items_history;
2
+ DROP INDEX IF EXISTS catalog_items_history_tenant_record_version_idx;
3
+ DROP TABLE IF EXISTS catalog_items_history;
@@ -0,0 +1,20 @@
1
+ CREATE TABLE IF NOT EXISTS catalog_items_history (
2
+ id TEXT PRIMARY KEY,
3
+ tenant_id TEXT NOT NULL,
4
+ record_id TEXT NOT NULL,
5
+ version BIGINT NOT NULL CHECK (version >= 1),
6
+ action TEXT NOT NULL CHECK (length(action) BETWEEN 1 AND 32),
7
+ actor_kind TEXT NOT NULL CHECK (actor_kind IN ('user', 'agent')),
8
+ actor_id TEXT NOT NULL CHECK (length(actor_id) BETWEEN 1 AND 128),
9
+ actor_label TEXT NOT NULL CHECK (length(actor_label) BETWEEN 1 AND 160),
10
+ run_id TEXT CHECK (run_id IS NULL OR length(run_id) BETWEEN 1 AND 128),
11
+ changes_json TEXT NOT NULL,
12
+ occurred_at BIGINT NOT NULL
13
+ );
14
+ CREATE UNIQUE INDEX IF NOT EXISTS catalog_items_history_tenant_record_version_idx
15
+ ON catalog_items_history (tenant_id, record_id, version DESC);
16
+ ALTER TABLE catalog_items_history ENABLE ROW LEVEL SECURITY;
17
+ ALTER TABLE catalog_items_history FORCE ROW LEVEL SECURITY;
18
+ CREATE POLICY catalog_items_history_tenant_policy ON catalog_items_history
19
+ USING (tenant_id = current_setting('coreloom.tenant_id', true))
20
+ WITH CHECK (tenant_id = current_setting('coreloom.tenant_id', true));
@@ -0,0 +1,3 @@
1
+ DROP POLICY IF EXISTS catalog_items_history_v2_tenant_policy ON catalog_items_history_v2;
2
+ DROP INDEX IF EXISTS catalog_items_history_v2_tenant_record_version_idx;
3
+ DROP TABLE IF EXISTS catalog_items_history_v2;
@@ -0,0 +1,36 @@
1
+ CREATE TABLE IF NOT EXISTS catalog_items_history_v2 (
2
+ id TEXT PRIMARY KEY,
3
+ tenant_id TEXT NOT NULL,
4
+ record_id TEXT NOT NULL,
5
+ version BIGINT NOT NULL CHECK (version >= 1),
6
+ action TEXT NOT NULL CHECK (length(action) BETWEEN 1 AND 32),
7
+ actor_kind TEXT NOT NULL CHECK (actor_kind IN ('user', 'agent', 'service')),
8
+ actor_id TEXT NOT NULL CHECK (length(actor_id) BETWEEN 1 AND 128),
9
+ actor_label TEXT NOT NULL CHECK (length(actor_label) BETWEEN 1 AND 160),
10
+ run_id TEXT CHECK (run_id IS NULL OR length(run_id) BETWEEN 1 AND 128),
11
+ configured_by_json TEXT CHECK (configured_by_json IS NULL OR configured_by_json::jsonb IS NOT NULL),
12
+ changes_json TEXT NOT NULL,
13
+ occurred_at BIGINT NOT NULL,
14
+ CHECK (
15
+ (actor_kind = 'agent' AND run_id IS NOT NULL)
16
+ OR (actor_kind IN ('user', 'service') AND run_id IS NULL)
17
+ ),
18
+ CHECK (
19
+ (actor_kind = 'service' AND configured_by_json IS NOT NULL)
20
+ OR (actor_kind IN ('user', 'agent') AND configured_by_json IS NULL)
21
+ )
22
+ );
23
+ CREATE UNIQUE INDEX IF NOT EXISTS catalog_items_history_v2_tenant_record_version_idx
24
+ ON catalog_items_history_v2 (tenant_id, record_id, version DESC);
25
+ INSERT INTO catalog_items_history_v2
26
+ (id, tenant_id, record_id, version, action, actor_kind, actor_id,
27
+ actor_label, run_id, configured_by_json, changes_json, occurred_at)
28
+ SELECT id, tenant_id, record_id, version, action, actor_kind, actor_id,
29
+ actor_label, run_id, NULL, changes_json, occurred_at
30
+ FROM catalog_items_history
31
+ ON CONFLICT DO NOTHING;
32
+ ALTER TABLE catalog_items_history_v2 ENABLE ROW LEVEL SECURITY;
33
+ ALTER TABLE catalog_items_history_v2 FORCE ROW LEVEL SECURITY;
34
+ CREATE POLICY catalog_items_history_v2_tenant_policy ON catalog_items_history_v2
35
+ USING (tenant_id = current_setting('coreloom.tenant_id', true))
36
+ WITH CHECK (tenant_id = current_setting('coreloom.tenant_id', true));
@@ -0,0 +1,3 @@
1
+ DROP POLICY IF EXISTS catalog_idempotency_ledger_tenant_policy ON catalog_idempotency_ledger;
2
+ DROP INDEX IF EXISTS catalog_idempotency_ledger_tenant_operation_idx;
3
+ DROP TABLE IF EXISTS catalog_idempotency_ledger;
@@ -0,0 +1,19 @@
1
+ CREATE TABLE IF NOT EXISTS catalog_idempotency_ledger (
2
+ id TEXT PRIMARY KEY,
3
+ tenant_id TEXT NOT NULL,
4
+ idempotency_key TEXT NOT NULL CHECK (length(idempotency_key) BETWEEN 8 AND 128),
5
+ operation_id TEXT NOT NULL CHECK (length(operation_id) BETWEEN 3 AND 160),
6
+ input_digest TEXT NOT NULL CHECK (length(input_digest) = 71),
7
+ outcome TEXT NOT NULL CHECK (outcome = 'succeeded'),
8
+ result_json TEXT NOT NULL CHECK (result_json::jsonb IS NOT NULL),
9
+ result_digest TEXT NOT NULL CHECK (length(result_digest) = 71),
10
+ created_at BIGINT NOT NULL,
11
+ UNIQUE (tenant_id, idempotency_key)
12
+ );
13
+ CREATE INDEX IF NOT EXISTS catalog_idempotency_ledger_tenant_operation_idx
14
+ ON catalog_idempotency_ledger (tenant_id, operation_id, created_at, id);
15
+ ALTER TABLE catalog_idempotency_ledger ENABLE ROW LEVEL SECURITY;
16
+ ALTER TABLE catalog_idempotency_ledger FORCE ROW LEVEL SECURITY;
17
+ CREATE POLICY catalog_idempotency_ledger_tenant_policy ON catalog_idempotency_ledger
18
+ USING (tenant_id = current_setting('coreloom.tenant_id', true))
19
+ WITH CHECK (tenant_id = current_setting('coreloom.tenant_id', true));
@@ -0,0 +1,3 @@
1
+ # Migrations
2
+
3
+ Migrations in this directory are append-only after release.
@@ -0,0 +1,27 @@
1
+ {
2
+ "$schema": "../../packages/contracts/schemas/module.schema.json",
3
+ "schemaVersion": 1,
4
+ "id": "catalog.core",
5
+ "package": "@flowdular/module-catalog",
6
+ "version": "0.6.1",
7
+ "profile": "full",
8
+ "capabilities": ["api", "database", "client", "translations"],
9
+ "platform": {
10
+ "server": true,
11
+ "client": true
12
+ },
13
+ "dependencies": [
14
+ {
15
+ "id": "system.core",
16
+ "range": "0.5.0"
17
+ },
18
+ {
19
+ "id": "auth.core",
20
+ "range": "0.10.0"
21
+ }
22
+ ],
23
+ "tenancy": "required",
24
+ "locales": ["en", "pl"],
25
+ "stability": "experimental",
26
+ "platformApi": "0.1.0"
27
+ }
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@flowdular/module-catalog",
3
+ "version": "0.6.1",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": "./src/index.ts",
7
+ "./client": "./src/client/index.ts",
8
+ "./server": "./src/server/index.ts",
9
+ "./platform": "./src/platform.ts",
10
+ "./module.json": "./module.json"
11
+ },
12
+ "scripts": {
13
+ "typecheck": "tsrx-tsc --noEmit -p tsconfig.json",
14
+ "test": "vitest run"
15
+ },
16
+ "dependencies": {
17
+ "octane": "0.1.51",
18
+ "segment-state": "0.2.0",
19
+ "@flowdular/sdk": "0.1.0"
20
+ },
21
+ "devDependencies": {
22
+ "@tsrx/typescript-plugin": "0.3.120",
23
+ "@types/node": "24.13.3",
24
+ "typescript": "5.9.3",
25
+ "vitest": "4.1.10"
26
+ },
27
+ "license": "MIT",
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/Flowdular/official-modules.git",
34
+ "directory": "modules/catalog"
35
+ },
36
+ "files": [
37
+ "src",
38
+ "schemas",
39
+ "dist",
40
+ "bin",
41
+ "public",
42
+ "module.json",
43
+ "migrations",
44
+ "translations",
45
+ "spec",
46
+ "README.md",
47
+ "LICENSE"
48
+ ]
49
+ }
@@ -0,0 +1,86 @@
1
+ schemaVersion: 1
2
+ id: catalog.core
3
+ specVersion: 0.6.1
4
+ status: approved
5
+ name: Product Catalog Core
6
+ description: Provides tenant-scoped products and services with stable SKUs, units, prices, currencies, and lifecycle state.
7
+ profile: full
8
+ capabilities:
9
+ - api
10
+ - database
11
+ - client
12
+ - translations
13
+ dependencies:
14
+ - id: system.core
15
+ range: 0.5.0
16
+ - id: auth.core
17
+ range: 0.10.0
18
+ tenancy: required
19
+ locales:
20
+ - en
21
+ - pl
22
+ invariants:
23
+ - Persistence runs on the shared asynchronous database contract. The module receives a leased PostgreSQL handle from platform composition, never a driver or a connection string, and declares explicit PostgreSQL SQL for every statement and migration.
24
+ - PostgreSQL item, history, and idempotency ledger tables enable and force row-level security with USING and WITH CHECK policies bound to transaction-local coreloom.tenant_id, and the runtime role holds neither SUPERUSER nor BYPASSRLS. Migrations use a separate lease.
25
+ - Every catalog item is owned by exactly one tenant and every query uses the trusted tenant identifier.
26
+ - SKU is unique inside a tenant and is never used as tenancy authority.
27
+ - Monetary values are stored as integer minor units with an explicit ISO currency code.
28
+ - Item kind is product or service and status is active or archived.
29
+ - Background workflow actions preserve their service actor and the configuring user in record history.
30
+ - One tenant-scoped durable target ledger is shared by mutating agent tools and workflow actions; each entry binds an idempotency key to the exact tool identifier or versioned workflow action identifier, canonical input digest, and first persisted result in the same transaction as the catalog mutation.
31
+ - Replaying the same idempotency key for the same operation and canonical input returns the original result without another catalog item or history row, while reuse for another operation or input fails with a stable conflict.
32
+ - Idempotency ledger entries remain after a catalog item is deleted, and audit metadata records identifiers, input digests, and outcomes without raw tool input, credentials, secrets, or result payloads.
33
+ permissions:
34
+ - id: catalog.items.read
35
+ description: Read products and services in the active tenant.
36
+ - id: catalog.items.manage
37
+ description: Create and update products and services in the active tenant.
38
+ dataOwnership:
39
+ - catalog.core owns SKU, item identity, kind, unit, base price, currency, and lifecycle status.
40
+ - catalog.core owns the idempotency ledger for its mutating agent tools and workflow actions; callers supply the key but do not maintain a second target ledger.
41
+ - Sales and purchasing modules reference catalog item identifiers and snapshot commercial terms when required by their specs.
42
+ acceptanceScenarios:
43
+ - id: CATALOG-LIST
44
+ given: Tenant-scoped products and services exist.
45
+ when: An authorized principal lists catalog items.
46
+ then: Only items owned by the active tenant are returned in deterministic SKU order.
47
+ - id: CATALOG-CREATE
48
+ given: An authorized principal supplies a unique SKU and valid product or service data.
49
+ when: The catalog item is created.
50
+ then: A tenant-owned active item is persisted with integer minor-unit pricing.
51
+ - id: CATALOG-DUPLICATE
52
+ given: An item already uses a SKU in the active tenant.
53
+ when: Another item is created with the same normalized SKU.
54
+ then: The server returns a stable conflict error and leaves existing data unchanged.
55
+ - id: CATALOG-DENY
56
+ given: A principal is unauthenticated or lacks the required catalog permission.
57
+ when: The principal reads or mutates catalog data.
58
+ then: The server denies the operation before repository access.
59
+ - id: CATALOG-AGENT-TOOL
60
+ given: An agent run holds catalog.items.manage in its permission snapshot and the tool catalog.item.create in its grants.
61
+ when: The agent invokes the tool with a valid item, and a run without the manage scope invokes the same tool.
62
+ then: The scoped run creates a tenant-owned catalog item from the run tenant and the harness denies the unscoped run before any write.
63
+ - id: CATALOG-LIFECYCLE-HISTORY
64
+ given: A catalog item is active in the current tenant.
65
+ when: An authorized principal edits it, archives it, restores it, or deletes it after archiving.
66
+ then: Each accepted transition has an append-only tenant-scoped revision with the user or agent actor, and the item history endpoint returns only that tenant's revisions.
67
+ - id: CATALOG-WORKFLOW-ACTIONS
68
+ given: A workflow revision selects a versioned catalog read or create action and carries the matching permission snapshot.
69
+ when: The action capability validates and executes the node with an idempotency key and service actor.
70
+ then: The action exposes exact input and output schemas, refuses a missing permission before work, cooperates with cancellation, and attributes a created item to the service and its configuring user.
71
+ - id: CATALOG-IDEMPOTENCY-REPLAY
72
+ given: A mutating catalog tool or workflow action has committed a catalog mutation and its target-ledger result for an idempotency key.
73
+ when: The caller repeats the exact operation with the same canonical input and key, including after losing the first response.
74
+ then: The module returns the original persisted result and creates no second catalog item or history row.
75
+ - id: CATALOG-IDEMPOTENCY-CONFLICT
76
+ given: A tenant-scoped idempotency key is already bound to an exact catalog tool identifier or versioned workflow action identifier and canonical input digest.
77
+ when: A caller reuses the key for a different operation or canonical input.
78
+ then: The module returns a stable conflict before any catalog item, history, or ledger write.
79
+ - id: CATALOG-POSTGRESQL-TENANT-BOUNDARY
80
+ given: catalog.core runs on PostgreSQL and two tenants own catalog data.
81
+ when: A runtime transaction bound to one tenant reads or writes items, history, or ledger rows.
82
+ then: Only that tenant's rows are visible or mutable, a transaction without a tenant is refused, and the forced row-level security policy rejects a row carrying another tenant identifier.
83
+ - id: CATALOG-IDEMPOTENCY-RECOVERY
84
+ given: A catalog item has been committed atomically with its idempotency result, or the item is later deleted through its lifecycle operation.
85
+ when: Recovery replays the mutating tool or workflow action with the same key.
86
+ then: The retained ledger returns the original result without another mutation, and audit evidence contains no raw input, credentials, secrets, or result payload.
@@ -0,0 +1,6 @@
1
+ export const CATALOG_PERMISSIONS = {
2
+ read: 'catalog.items.read',
3
+ manage: 'catalog.items.manage',
4
+ } as const;
5
+
6
+ export const permissions = Object.freeze(Object.values(CATALOG_PERMISSIONS));
@@ -0,0 +1,164 @@
1
+ import { defineApiAgentTool } from '@flowdular/sdk/harness/tool-adapters';
2
+ import {
3
+ AgentHarnessError,
4
+ type AgentTool,
5
+ type AgentToolContext,
6
+ } from '@flowdular/sdk/harness/runtime';
7
+ import { agentActor, type Actor } from '@flowdular/sdk/kernel';
8
+ import { CATALOG_PERMISSIONS } from '../acl/permissions.ts';
9
+ import type { CatalogItemKind } from '../domain/types.ts';
10
+ import type { CatalogRuntime } from '../server/runtime.ts';
11
+ import { CatalogServiceError } from '../services/catalog-service.ts';
12
+
13
+ const MAX_TOOL_ROWS = 200;
14
+ const CREATE_OPERATION = 'catalog.item.create@1';
15
+
16
+ const CATALOG_ITEM_OUTPUT_SCHEMA = {
17
+ type: 'object',
18
+ additionalProperties: false,
19
+ required: [
20
+ 'id',
21
+ 'tenantId',
22
+ 'sku',
23
+ 'name',
24
+ 'kind',
25
+ 'unit',
26
+ 'basePriceMinor',
27
+ 'currency',
28
+ 'status',
29
+ 'createdAt',
30
+ ],
31
+ properties: {
32
+ id: { type: 'string' },
33
+ tenantId: { type: 'string' },
34
+ sku: { type: 'string' },
35
+ name: { type: 'string' },
36
+ kind: { type: 'string', enum: ['product', 'service'] },
37
+ unit: { type: 'string' },
38
+ basePriceMinor: { type: 'integer' },
39
+ currency: { type: 'string' },
40
+ status: { type: 'string', enum: ['active', 'archived'] },
41
+ createdAt: { type: 'integer' },
42
+ },
43
+ } as const;
44
+
45
+ function actionActor(context: AgentToolContext): Actor {
46
+ return context.actor ?? agentActor(context);
47
+ }
48
+
49
+ function normalized(value: unknown): string {
50
+ return typeof value === 'string'
51
+ ? value.trim().toLocaleLowerCase('en-US')
52
+ : '';
53
+ }
54
+
55
+ function idempotencyKey(context: AgentToolContext): string {
56
+ if (!context.idempotencyKey) {
57
+ throw new AgentHarnessError(
58
+ 'TOOL_IDEMPOTENCY_KEY_REQUIRED',
59
+ 'The catalog create tool requires a durable idempotency key.',
60
+ );
61
+ }
62
+ return context.idempotencyKey;
63
+ }
64
+
65
+ /* Tools call the catalog service and take the tenant and the actor from the
66
+ run context, never from input; the service revalidates so a tool cannot
67
+ bypass the endpoint's rules, every write is attributed to the run that made
68
+ it, and list output is capped so one call cannot flood the run window. */
69
+ export function catalogAgentTools(
70
+ runtime: CatalogRuntime,
71
+ ): readonly AgentTool[] {
72
+ return [
73
+ defineApiAgentTool({
74
+ id: 'catalog.item.list',
75
+ endpointId: 'catalog.items.list',
76
+ contractVersion: 1,
77
+ description:
78
+ 'List products and services of the active tenant, optionally filtered by a free-text query.',
79
+ requiredPermissions: [CATALOG_PERMISSIONS.read],
80
+ risk: 'read',
81
+ idempotency: 'required',
82
+ cancellation: 'cooperative',
83
+ inputSchema: {
84
+ type: 'object',
85
+ additionalProperties: false,
86
+ properties: { query: { type: 'string', maxLength: 120 } },
87
+ },
88
+ outputSchema: { type: 'array', items: CATALOG_ITEM_OUTPUT_SCHEMA },
89
+ execute: async (input, context) => {
90
+ context.signal.throwIfAborted();
91
+ const query = normalized(
92
+ (input as Record<string, unknown> | null)?.query,
93
+ );
94
+ return (await (await runtime.service()).list(context.tenantId))
95
+ .filter(
96
+ (item) =>
97
+ query === '' ||
98
+ item.id.toLocaleLowerCase('en-US') === query ||
99
+ item.sku.toLocaleLowerCase('en-US').includes(query) ||
100
+ item.name.toLocaleLowerCase('en-US').includes(query),
101
+ )
102
+ .slice(0, MAX_TOOL_ROWS);
103
+ },
104
+ }),
105
+ defineApiAgentTool({
106
+ id: 'catalog.item.create',
107
+ endpointId: 'catalog.items.create',
108
+ contractVersion: 1,
109
+ description: 'Create a product or service owned by the active tenant.',
110
+ requiredPermissions: [CATALOG_PERMISSIONS.manage],
111
+ risk: 'workspace-write',
112
+ idempotency: 'required',
113
+ idempotencyProtection: 'target-ledger',
114
+ cancellation: 'cooperative',
115
+ inputSchema: {
116
+ type: 'object',
117
+ additionalProperties: false,
118
+ required: ['sku', 'name', 'kind', 'unit', 'basePriceMinor', 'currency'],
119
+ properties: {
120
+ sku: { type: 'string', maxLength: 64 },
121
+ name: { type: 'string', maxLength: 160 },
122
+ kind: { type: 'string', enum: ['product', 'service'] },
123
+ unit: { type: 'string', maxLength: 24 },
124
+ basePriceMinor: { type: 'integer' },
125
+ currency: { type: 'string', maxLength: 3 },
126
+ },
127
+ },
128
+ outputSchema: CATALOG_ITEM_OUTPUT_SCHEMA,
129
+ execute: async (input, context) => {
130
+ context.signal.throwIfAborted();
131
+ const value = (input ?? {}) as Record<string, unknown>;
132
+ try {
133
+ return (await runtime.service()).createIdempotent(
134
+ context.tenantId,
135
+ {
136
+ sku: String(value.sku ?? ''),
137
+ name: String(value.name ?? ''),
138
+ kind: value.kind as CatalogItemKind,
139
+ unit: String(value.unit ?? ''),
140
+ basePriceMinor:
141
+ typeof value.basePriceMinor === 'number'
142
+ ? value.basePriceMinor
143
+ : Number.NaN,
144
+ currency: String(value.currency ?? ''),
145
+ },
146
+ actionActor(context),
147
+ {
148
+ key: idempotencyKey(context),
149
+ operationId: CREATE_OPERATION,
150
+ },
151
+ );
152
+ } catch (error) {
153
+ if (
154
+ error instanceof CatalogServiceError &&
155
+ error.code === 'CATALOG_IDEMPOTENCY_CONFLICT'
156
+ ) {
157
+ throw new AgentHarnessError(error.code, error.message);
158
+ }
159
+ throw error;
160
+ }
161
+ },
162
+ }),
163
+ ];
164
+ }