@flowdular/sdk 0.2.4 → 0.3.1

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 (930) hide show
  1. package/.ai/agents/sandbox/business-manager.md +5 -1
  2. package/.ai/blueprints/author-spec/README.md +1 -1
  3. package/.ai/blueprints/author-spec/spec-requirements.yaml +44 -0
  4. package/.ai/blueprints/author-spec/steps.yaml +5 -5
  5. package/.ai/blueprints/author-spec/templates/module.yaml +99 -3
  6. package/.ai/blueprints/edit-module/gates.yaml +4 -0
  7. package/.ai/blueprints/edit-module/required-files.yaml +9 -0
  8. package/.ai/blueprints/new-module/gates.yaml +4 -0
  9. package/.ai/blueprints/new-module/spec-requirements.yaml +2 -2
  10. package/.ai/blueprints/release/gates.yaml +4 -0
  11. package/.ai/platform-capabilities.md +128 -0
  12. package/.ai/policies/capabilities.yaml +130 -3
  13. package/.ai/policies/path-ownership.yaml +5 -2
  14. package/.ai/policies/task-budgets.yaml +5 -3
  15. package/.ai/references/catalog/module.json +4 -4
  16. package/.ai/references/catalog/package.json +2 -2
  17. package/.ai/references/catalog/spec/module.yaml +5 -3
  18. package/.ai/references/catalog/src/platform.ts +2 -0
  19. package/.ai/references/catalog/src/services/catalog-service.ts +89 -1
  20. package/.ai/references/catalog/src/services/data-classes.ts +47 -0
  21. package/.ai/references/catalog/src/services/database-repository.ts +98 -1
  22. package/.ai/references/catalog/src/services/repository.ts +22 -1
  23. package/.ai/references/catalog/tests/data-classes.test.ts +157 -0
  24. package/.ai/references/catalog.provenance.json +12 -10
  25. package/.ai/skills/README.md +10 -0
  26. package/.ai/skills/agent-tool-design/SKILL.md +1 -2
  27. package/.ai/skills/auth-security-review/SKILL.md +1 -1
  28. package/.ai/skills/business-agent-design/SKILL.md +0 -1
  29. package/.ai/skills/cli-extension/SKILL.md +1 -1
  30. package/.ai/skills/deploy-operate/SKILL.md +119 -0
  31. package/.ai/skills/module-new/SKILL.md +29 -3
  32. package/.ai/skills/module-update/SKILL.md +9 -3
  33. package/.ai/skills/perf-audit/SKILL.md +0 -1
  34. package/.ai/skills/release-eject-pr/SKILL.md +0 -1
  35. package/.ai/skills/spec-interview/SKILL.md +120 -0
  36. package/.ai/skills/test-hardening/SKILL.md +1 -0
  37. package/.ai/skills/ux-design/SKILL.md +34 -3
  38. package/.ai/skills/variables/SKILL.md +0 -2
  39. package/.ai/skills/workflow-development/SKILL.md +0 -1
  40. package/AGENTS.md +4 -0
  41. package/docs/agent-contract.md +2 -2
  42. package/docs/design-system.md +185 -31
  43. package/modules/access/migrations/0001_access_core.down.sql +1 -0
  44. package/modules/access/migrations/0001_access_core.up.sql +28 -0
  45. package/modules/access/migrations/README.md +3 -0
  46. package/modules/access/module.json +33 -0
  47. package/modules/access/package.json +43 -0
  48. package/modules/access/spec/module.yaml +225 -0
  49. package/modules/access/src/acl/permissions.ts +6 -0
  50. package/modules/access/src/api/endpoints.ts +244 -0
  51. package/modules/access/src/client/ActivityView.tsrx +245 -0
  52. package/modules/access/src/client/AttestationsView.tsrx +176 -0
  53. package/modules/access/src/client/ReviewView.tsrx +586 -0
  54. package/modules/access/src/client/api.ts +132 -0
  55. package/modules/access/src/client/contribution.tsrx +41 -0
  56. package/modules/access/src/client/index.ts +41 -0
  57. package/modules/access/src/client/navigation.ts +57 -0
  58. package/modules/access/src/client/presentation.ts +69 -0
  59. package/modules/access/src/client/state.ts +72 -0
  60. package/modules/access/src/domain/types.ts +189 -0
  61. package/modules/access/src/index.ts +38 -0
  62. package/modules/access/src/platform.ts +60 -0
  63. package/modules/access/src/server/index.ts +42 -0
  64. package/modules/access/src/server/runtime.ts +105 -0
  65. package/modules/access/src/services/access-service.ts +298 -0
  66. package/modules/access/src/services/audit-window.ts +78 -0
  67. package/modules/access/src/services/auth-directory.ts +72 -0
  68. package/modules/access/src/services/changes.ts +91 -0
  69. package/modules/access/src/services/data-classes.ts +28 -0
  70. package/modules/access/src/services/database-repository.ts +185 -0
  71. package/modules/access/src/services/directory.ts +102 -0
  72. package/modules/access/src/services/index.ts +33 -0
  73. package/modules/access/src/services/list-exports.ts +150 -0
  74. package/modules/access/src/services/migration.ts +54 -0
  75. package/modules/access/src/services/repository.ts +30 -0
  76. package/modules/access/src/services/review.ts +178 -0
  77. package/modules/access/translations/en.json +155 -0
  78. package/modules/access/translations/pl.json +155 -0
  79. package/modules/agents/migrations/0022_credential_rotation_inventory.down.sql +2 -0
  80. package/modules/agents/migrations/0022_credential_rotation_inventory.up.sql +7 -0
  81. package/modules/agents/migrations/0023_agents_retention_indexes.down.sql +2 -0
  82. package/modules/agents/migrations/0023_agents_retention_indexes.up.sql +9 -0
  83. package/modules/agents/migrations/0024_agent_meter_refusals.down.sql +3 -0
  84. package/modules/agents/migrations/0024_agent_meter_refusals.up.sql +22 -0
  85. package/modules/agents/migrations/0025_agent_list_indexes.down.sql +3 -0
  86. package/modules/agents/migrations/0025_agent_list_indexes.up.sql +11 -0
  87. package/modules/agents/module.json +30 -4
  88. package/modules/agents/package.json +2 -1
  89. package/modules/agents/spec/module.yaml +63 -5
  90. package/modules/agents/src/api/endpoints.ts +291 -33
  91. package/modules/agents/src/cli/commands.json +11 -0
  92. package/modules/agents/src/cli/index.ts +45 -0
  93. package/modules/agents/src/client/AgentDashboardWidget.tsrx +19 -11
  94. package/modules/agents/src/client/AgentDefinitionList.tsrx +53 -10
  95. package/modules/agents/src/client/AgentPlaygroundView.tsrx +4 -4
  96. package/modules/agents/src/client/AgentProceduresView.tsrx +2 -2
  97. package/modules/agents/src/client/AgentRunsView.tsrx +143 -40
  98. package/modules/agents/src/client/AgentsView.tsrx +109 -33
  99. package/modules/agents/src/client/api.ts +99 -21
  100. package/modules/agents/src/client/state.ts +97 -0
  101. package/modules/agents/src/domain/types.ts +44 -4
  102. package/modules/agents/src/platform.ts +42 -0
  103. package/modules/agents/src/server/action-execution.ts +201 -106
  104. package/modules/agents/src/server/runtime.ts +32 -0
  105. package/modules/agents/src/services/agent-service.ts +158 -30
  106. package/modules/agents/src/services/credential-rotation.ts +185 -0
  107. package/modules/agents/src/services/credential-vault.ts +71 -46
  108. package/modules/agents/src/services/data-classes.ts +176 -0
  109. package/modules/agents/src/services/database-repository.ts +393 -101
  110. package/modules/agents/src/services/metering.ts +111 -0
  111. package/modules/agents/src/services/migration.ts +109 -0
  112. package/modules/agents/src/services/module-agent-preflight.ts +17 -9
  113. package/modules/agents/src/services/notifications.ts +98 -0
  114. package/modules/agents/src/services/provider-repository.ts +9 -18
  115. package/modules/agents/src/services/provider-service.ts +1 -9
  116. package/modules/agents/src/services/reports.ts +107 -0
  117. package/modules/agents/src/services/repository.ts +86 -6
  118. package/modules/agents/src/services/usage-service.ts +2 -0
  119. package/modules/agents/src/services/worker.ts +114 -4
  120. package/modules/agents/src/settings.ts +14 -3
  121. package/modules/agents/translations/en.json +14 -4
  122. package/modules/agents/translations/pl.json +14 -4
  123. package/modules/approvals/migrations/0001_approvals_core.down.sql +3 -0
  124. package/modules/approvals/migrations/0001_approvals_core.up.sql +78 -0
  125. package/modules/approvals/migrations/0002_approvals_expiry_routing_role.down.sql +2 -0
  126. package/modules/approvals/migrations/0002_approvals_expiry_routing_role.up.sql +19 -0
  127. package/modules/approvals/migrations/0003_approvals_retention_indexes.down.sql +6 -0
  128. package/modules/approvals/migrations/0003_approvals_retention_indexes.up.sql +14 -0
  129. package/modules/approvals/migrations/0004_approvals_inbox_keyset_indexes.down.sql +5 -0
  130. package/modules/approvals/migrations/0004_approvals_inbox_keyset_indexes.up.sql +12 -0
  131. package/modules/approvals/migrations/0005_approvals_grant_audit.down.sql +4 -0
  132. package/modules/approvals/migrations/0005_approvals_grant_audit.up.sql +20 -0
  133. package/modules/approvals/migrations/README.md +3 -0
  134. package/modules/approvals/module.json +34 -0
  135. package/modules/approvals/package.json +43 -0
  136. package/modules/approvals/spec/module.yaml +327 -0
  137. package/modules/approvals/src/acl/permissions.ts +7 -0
  138. package/modules/approvals/src/api/endpoints.ts +457 -0
  139. package/modules/approvals/src/client/ApprovalRequestDrawer.tsrx +138 -0
  140. package/modules/approvals/src/client/ApprovalsView.tsrx +562 -0
  141. package/modules/approvals/src/client/PendingCountWidget.tsrx +52 -0
  142. package/modules/approvals/src/client/api.ts +203 -0
  143. package/modules/approvals/src/client/approvals.css +51 -0
  144. package/modules/approvals/src/client/contribution.tsrx +44 -0
  145. package/modules/approvals/src/client/index.ts +26 -0
  146. package/modules/approvals/src/client/navigation.ts +39 -0
  147. package/modules/approvals/src/client/pending-count.ts +26 -0
  148. package/modules/approvals/src/client/presentation.ts +52 -0
  149. package/modules/approvals/src/client/state.ts +141 -0
  150. package/modules/approvals/src/domain/capability.ts +107 -0
  151. package/modules/approvals/src/domain/grant.ts +69 -0
  152. package/modules/approvals/src/domain/types.ts +168 -0
  153. package/modules/approvals/src/index.ts +61 -0
  154. package/modules/approvals/src/platform.ts +136 -0
  155. package/modules/approvals/src/server/index.ts +42 -0
  156. package/modules/approvals/src/server/runtime.ts +185 -0
  157. package/modules/approvals/src/services/approvals-service.ts +637 -0
  158. package/modules/approvals/src/services/callbacks.ts +75 -0
  159. package/modules/approvals/src/services/data-classes.ts +167 -0
  160. package/modules/approvals/src/services/database-repository.ts +783 -0
  161. package/modules/approvals/src/services/eligibility.ts +121 -0
  162. package/modules/approvals/src/services/expiry-runner.ts +81 -0
  163. package/modules/approvals/src/services/index.ts +31 -0
  164. package/modules/approvals/src/services/migration.ts +256 -0
  165. package/modules/approvals/src/services/notifications.ts +95 -0
  166. package/modules/approvals/src/services/repository.ts +169 -0
  167. package/modules/approvals/src/services/service-error.ts +70 -0
  168. package/modules/approvals/src/settings.ts +102 -0
  169. package/modules/approvals/translations/en.json +104 -0
  170. package/modules/approvals/translations/pl.json +104 -0
  171. package/modules/audit/migrations/0001_audit_core.down.sql +8 -0
  172. package/modules/audit/migrations/0001_audit_core.up.sql +107 -0
  173. package/modules/audit/migrations/0002_audit_sweep_routing_role.down.sql +2 -0
  174. package/modules/audit/migrations/0002_audit_sweep_routing_role.up.sql +21 -0
  175. package/modules/audit/migrations/0003_audit_export_request.down.sql +12 -0
  176. package/modules/audit/migrations/0003_audit_export_request.up.sql +40 -0
  177. package/modules/audit/migrations/0004_audit_hold_seal_erasure.down.sql +17 -0
  178. package/modules/audit/migrations/0004_audit_hold_seal_erasure.up.sql +192 -0
  179. package/modules/audit/migrations/0005_audit_event_format.down.sql +17 -0
  180. package/modules/audit/migrations/0005_audit_event_format.up.sql +60 -0
  181. package/modules/audit/migrations/0006_audit_own_class_walks.down.sql +3 -0
  182. package/modules/audit/migrations/0006_audit_own_class_walks.up.sql +14 -0
  183. package/modules/audit/migrations/README.md +3 -0
  184. package/modules/audit/module.json +32 -0
  185. package/modules/audit/package.json +49 -0
  186. package/modules/audit/spec/module.yaml +809 -0
  187. package/modules/audit/src/acl/permissions.ts +7 -0
  188. package/modules/audit/src/api/endpoints.ts +315 -0
  189. package/modules/audit/src/cli/commands.json +95 -0
  190. package/modules/audit/src/cli/index.ts +658 -0
  191. package/modules/audit/src/client/DataClassesView.tsrx +420 -0
  192. package/modules/audit/src/client/ExportsView.tsrx +256 -0
  193. package/modules/audit/src/client/HoldsView.tsrx +604 -0
  194. package/modules/audit/src/client/SweepsView.tsrx +251 -0
  195. package/modules/audit/src/client/api.ts +185 -0
  196. package/modules/audit/src/client/contribution.tsrx +52 -0
  197. package/modules/audit/src/client/index.ts +23 -0
  198. package/modules/audit/src/client/navigation.ts +74 -0
  199. package/modules/audit/src/client/presentation.ts +105 -0
  200. package/modules/audit/src/client/state.ts +86 -0
  201. package/modules/audit/src/domain/data-classes.ts +16 -0
  202. package/modules/audit/src/domain/types.ts +339 -0
  203. package/modules/audit/src/index.ts +76 -0
  204. package/modules/audit/src/platform.ts +44 -0
  205. package/modules/audit/src/server/index.ts +177 -0
  206. package/modules/audit/src/server/runtime.ts +303 -0
  207. package/modules/audit/src/services/anchor-key.ts +143 -0
  208. package/modules/audit/src/services/anchor-rotation.ts +147 -0
  209. package/modules/audit/src/services/audit-runners.ts +278 -0
  210. package/modules/audit/src/services/backup-guard.ts +95 -0
  211. package/modules/audit/src/services/database-repository.ts +1946 -0
  212. package/modules/audit/src/services/declared-classes.ts +64 -0
  213. package/modules/audit/src/services/erasure-port.ts +126 -0
  214. package/modules/audit/src/services/erasure-service.ts +770 -0
  215. package/modules/audit/src/services/export-directory.ts +106 -0
  216. package/modules/audit/src/services/export-service.ts +714 -0
  217. package/modules/audit/src/services/hold-service.ts +295 -0
  218. package/modules/audit/src/services/index.ts +17 -0
  219. package/modules/audit/src/services/migration.ts +658 -0
  220. package/modules/audit/src/services/own-classes.ts +318 -0
  221. package/modules/audit/src/services/platform-version.ts +23 -0
  222. package/modules/audit/src/services/repository.ts +495 -0
  223. package/modules/audit/src/services/retention-service.ts +191 -0
  224. package/modules/audit/src/services/seal-service.ts +769 -0
  225. package/modules/audit/src/services/service-error.ts +61 -0
  226. package/modules/audit/src/services/subject-keys.ts +90 -0
  227. package/modules/audit/src/services/sweep-service.ts +298 -0
  228. package/modules/audit/src/services/zip.ts +217 -0
  229. package/modules/audit/src/settings.ts +69 -0
  230. package/modules/audit/translations/en.json +210 -0
  231. package/modules/audit/translations/pl.json +210 -0
  232. package/modules/auth/README.md +77 -29
  233. package/modules/auth/migrations/0016_external_identities.up.sql +16 -0
  234. package/modules/auth/migrations/0017_mfa_key_id.up.sql +8 -0
  235. package/modules/auth/migrations/0018_retire_bundled_module_scopes.up.sql +29 -0
  236. package/modules/auth/migrations/0019_notifications_member_scopes.up.sql +44 -0
  237. package/modules/auth/migrations/0020_identity_providers.up.sql +61 -0
  238. package/modules/auth/migrations/0021_membership_status.up.sql +19 -0
  239. package/modules/auth/migrations/0022_auth_provider_scopes.up.sql +45 -0
  240. package/modules/auth/migrations/0023_enterprise_module_scopes.down.sql +19 -0
  241. package/modules/auth/migrations/0023_enterprise_module_scopes.up.sql +71 -0
  242. package/modules/auth/migrations/0024_approvals_member_scopes.down.sql +22 -0
  243. package/modules/auth/migrations/0024_approvals_member_scopes.up.sql +48 -0
  244. package/modules/auth/migrations/0025_audit_holds_owner_scope.down.sql +21 -0
  245. package/modules/auth/migrations/0025_audit_holds_owner_scope.up.sql +47 -0
  246. package/modules/auth/migrations/0026_auth_export_keyset_indexes.down.sql +6 -0
  247. package/modules/auth/migrations/0026_auth_export_keyset_indexes.up.sql +15 -0
  248. package/modules/auth/migrations/0027_workflow_automation_profile_scopes.down.sql +34 -0
  249. package/modules/auth/migrations/0027_workflow_automation_profile_scopes.up.sql +72 -0
  250. package/modules/auth/migrations/0028_auth_member_search_prefix_indexes.down.sql +6 -0
  251. package/modules/auth/migrations/0028_auth_member_search_prefix_indexes.up.sql +21 -0
  252. package/modules/auth/migrations/0029_reports_exports_access_scopes.down.sql +22 -0
  253. package/modules/auth/migrations/0029_reports_exports_access_scopes.up.sql +56 -0
  254. package/modules/auth/migrations/0030_auth_membership_keyset_index.down.sql +4 -0
  255. package/modules/auth/migrations/0030_auth_membership_keyset_index.up.sql +10 -0
  256. package/modules/auth/migrations/0031_membership_scope_backfills_under_rls.down.sql +4 -0
  257. package/modules/auth/migrations/0031_membership_scope_backfills_under_rls.up.sql +31 -0
  258. package/modules/auth/migrations/0032_audit_actor_service.down.sql +9 -0
  259. package/modules/auth/migrations/0032_audit_actor_service.up.sql +10 -0
  260. package/modules/auth/migrations/0033_auth_account_keyset_indexes.down.sql +5 -0
  261. package/modules/auth/migrations/0033_auth_account_keyset_indexes.up.sql +23 -0
  262. package/modules/auth/module.json +3 -3
  263. package/modules/auth/package.json +2 -1
  264. package/modules/auth/spec/module.yaml +372 -3
  265. package/modules/auth/src/acl/scopes.ts +50 -6
  266. package/modules/auth/src/cli/commands.json +11 -0
  267. package/modules/auth/src/cli/greenfield.ts +2 -2
  268. package/modules/auth/src/cli/index.ts +14 -0
  269. package/modules/auth/src/cli/secrets.ts +114 -0
  270. package/modules/auth/src/client/AuthenticationCore.tsrx +61 -8
  271. package/modules/auth/src/client/api.ts +72 -6
  272. package/modules/auth/src/client/contribution.tsrx +23 -0
  273. package/modules/auth/src/client/index.ts +6 -0
  274. package/modules/auth/src/client/providers/IdentityProviderForm.tsrx +191 -0
  275. package/modules/auth/src/client/providers/IdentityProvidersView.tsrx +358 -0
  276. package/modules/auth/src/client/providers/api.ts +128 -0
  277. package/modules/auth/src/client/providers/provider-columns.tsrx +60 -0
  278. package/modules/auth/src/client/providers/state.ts +35 -0
  279. package/modules/auth/src/client/security/SecurityView.tsrx +9 -1
  280. package/modules/auth/src/client/state.ts +15 -1
  281. package/modules/auth/src/domain/types.ts +55 -0
  282. package/modules/auth/src/index.ts +11 -1
  283. package/modules/auth/src/middleware/authentication.ts +4 -0
  284. package/modules/auth/src/server/endpoints.ts +467 -171
  285. package/modules/auth/src/server/http.ts +3 -2
  286. package/modules/auth/src/server/index.ts +22 -1
  287. package/modules/auth/src/server/membership-endpoints.ts +62 -0
  288. package/modules/auth/src/server/mfa-enforcement.ts +156 -0
  289. package/modules/auth/src/server/oidc.ts +389 -0
  290. package/modules/auth/src/server/provider-endpoints.ts +246 -0
  291. package/modules/auth/src/server/provider-host.ts +77 -0
  292. package/modules/auth/src/server/runtime.ts +231 -55
  293. package/modules/auth/src/services/auth-service-error.ts +7 -2
  294. package/modules/auth/src/services/auth-service.ts +948 -51
  295. package/modules/auth/src/services/data-classes.ts +236 -0
  296. package/modules/auth/src/services/database-repository.ts +853 -71
  297. package/modules/auth/src/services/identity-provider-service.ts +571 -0
  298. package/modules/auth/src/services/mail-delivery.ts +16 -16
  299. package/modules/auth/src/services/mail-message.ts +54 -0
  300. package/modules/auth/src/services/mail-port.ts +24 -0
  301. package/modules/auth/src/services/mail-smtp.ts +85 -0
  302. package/modules/auth/src/services/mfa-rotation.ts +144 -0
  303. package/modules/auth/src/services/migration.ts +810 -0
  304. package/modules/auth/src/services/password.ts +14 -0
  305. package/modules/auth/src/services/provider-secret-rotation.ts +169 -0
  306. package/modules/auth/src/services/provider-secrets.ts +136 -0
  307. package/modules/auth/src/services/repository.ts +321 -5
  308. package/modules/auth/src/services/session-sweep-runner.ts +73 -0
  309. package/modules/auth/src/services/settings-store.ts +10 -83
  310. package/modules/auth/src/services/totp.ts +88 -62
  311. package/modules/auth/src/services/validation.ts +194 -7
  312. package/modules/auth/src/settings.ts +18 -0
  313. package/modules/auth/translations/en.json +84 -1
  314. package/modules/auth/translations/pl.json +84 -1
  315. package/modules/automations/migrations/0005_secret_rotation_inventory.down.sql +1 -0
  316. package/modules/automations/migrations/0005_secret_rotation_inventory.up.sql +6 -0
  317. package/modules/automations/migrations/0006_automations_list_sort_indexes.down.sql +4 -0
  318. package/modules/automations/migrations/0006_automations_list_sort_indexes.up.sql +11 -0
  319. package/modules/automations/module.json +24 -6
  320. package/modules/automations/package.json +4 -1
  321. package/modules/automations/spec/module.yaml +81 -7
  322. package/modules/automations/src/api/endpoints.ts +202 -28
  323. package/modules/automations/src/cli/commands.json +17 -0
  324. package/modules/automations/src/cli/index.ts +114 -0
  325. package/modules/automations/src/client/AutomationScheduleForm.tsrx +77 -19
  326. package/modules/automations/src/client/AutomationSchedulesView.tsrx +144 -40
  327. package/modules/automations/src/client/AutomationTriggersView.tsrx +131 -32
  328. package/modules/automations/src/client/api.ts +62 -19
  329. package/modules/automations/src/client/presentation.ts +20 -2
  330. package/modules/automations/src/client/state.ts +84 -0
  331. package/modules/automations/src/domain/cadence.ts +99 -3
  332. package/modules/automations/src/domain/cron.ts +366 -0
  333. package/modules/automations/src/domain/time-zone.ts +61 -0
  334. package/modules/automations/src/platform.ts +38 -4
  335. package/modules/automations/src/server/index.ts +11 -0
  336. package/modules/automations/src/server/runtime.ts +46 -22
  337. package/modules/{automations-workflows-integration/src/server/adapter.ts → automations/src/server/workflow-target.ts} +13 -14
  338. package/modules/{automations-workflows-integration/src/server/tools.ts → automations/src/server/workflow-tools.ts} +0 -0
  339. package/modules/automations/src/services/data-classes.ts +62 -0
  340. package/modules/automations/src/services/database-repository.ts +152 -38
  341. package/modules/automations/src/services/migration.ts +119 -9
  342. package/modules/automations/src/services/repository.ts +52 -1
  343. package/modules/automations/src/services/schedule-runner.ts +84 -0
  344. package/modules/automations/src/services/schedule-service.ts +152 -26
  345. package/modules/automations/src/services/secret-rotation.ts +176 -0
  346. package/modules/automations/src/services/secret-vault.ts +68 -41
  347. package/modules/automations/src/services/trigger-service.ts +13 -10
  348. package/modules/automations/translations/en.json +15 -2
  349. package/modules/automations/translations/pl.json +15 -2
  350. package/modules/connectors/migrations/0001_connectors_core.down.sql +3 -0
  351. package/modules/connectors/migrations/0001_connectors_core.up.sql +72 -0
  352. package/modules/connectors/migrations/0002_connectors_call_keys.down.sql +3 -0
  353. package/modules/connectors/migrations/0002_connectors_call_keys.up.sql +18 -0
  354. package/modules/connectors/migrations/0003_connectors_rotation_inventory.down.sql +2 -0
  355. package/modules/connectors/migrations/0003_connectors_rotation_inventory.up.sql +19 -0
  356. package/modules/connectors/migrations/README.md +3 -0
  357. package/modules/connectors/module.json +32 -0
  358. package/modules/{automations-workflows-integration → connectors}/package.json +28 -26
  359. package/modules/connectors/spec/module.yaml +448 -0
  360. package/modules/connectors/src/acl/permissions.ts +6 -0
  361. package/modules/connectors/src/agent/tools.ts +180 -0
  362. package/modules/connectors/src/api/endpoints.ts +572 -0
  363. package/modules/connectors/src/cli/commands.json +17 -0
  364. package/modules/connectors/src/cli/index.ts +126 -0
  365. package/modules/connectors/src/client/ConnectorCallsView.tsrx +358 -0
  366. package/modules/connectors/src/client/ConnectorForm.tsrx +424 -0
  367. package/modules/connectors/src/client/ConnectorsView.tsrx +711 -0
  368. package/modules/connectors/src/client/api.ts +281 -0
  369. package/modules/connectors/src/client/consent.ts +48 -0
  370. package/modules/connectors/src/client/contribution.tsrx +37 -0
  371. package/modules/connectors/src/client/index.ts +22 -0
  372. package/modules/connectors/src/client/navigation.ts +42 -0
  373. package/modules/connectors/src/client/presentation.ts +38 -0
  374. package/modules/connectors/src/client/state.ts +175 -0
  375. package/modules/connectors/src/domain/calls.ts +70 -0
  376. package/modules/connectors/src/domain/definitions.ts +190 -0
  377. package/modules/connectors/src/domain/http-json.ts +68 -0
  378. package/modules/connectors/src/domain/types.ts +185 -0
  379. package/modules/connectors/src/index.ts +64 -0
  380. package/modules/connectors/src/platform.ts +56 -0
  381. package/modules/connectors/src/server/index.ts +66 -0
  382. package/modules/connectors/src/server/runtime.ts +163 -0
  383. package/modules/connectors/src/services/call-service.ts +903 -0
  384. package/modules/connectors/src/services/connectors-service.ts +653 -0
  385. package/modules/connectors/src/services/credential-rotation.ts +221 -0
  386. package/modules/connectors/src/services/credential-vault.ts +194 -0
  387. package/modules/connectors/src/services/data-classes.ts +158 -0
  388. package/modules/connectors/src/services/database-repository.ts +897 -0
  389. package/modules/connectors/src/services/egress.ts +261 -0
  390. package/modules/connectors/src/services/index.ts +19 -0
  391. package/modules/connectors/src/services/migration.ts +202 -0
  392. package/modules/connectors/src/services/repository.ts +175 -0
  393. package/modules/connectors/src/services/service-error.ts +46 -0
  394. package/modules/connectors/src/settings.ts +69 -0
  395. package/modules/connectors/translations/en.json +191 -0
  396. package/modules/connectors/translations/pl.json +191 -0
  397. package/modules/directory/migrations/0001_directory_core.down.sql +5 -0
  398. package/modules/directory/migrations/0001_directory_core.up.sql +111 -0
  399. package/modules/directory/migrations/README.md +3 -0
  400. package/modules/directory/module.json +27 -0
  401. package/modules/directory/package.json +46 -0
  402. package/modules/directory/spec/module.yaml +351 -0
  403. package/modules/directory/src/acl/permissions.ts +7 -0
  404. package/modules/directory/src/api/endpoints.ts +478 -0
  405. package/modules/directory/src/api/scim-endpoints.ts +516 -0
  406. package/modules/directory/src/client/GroupMappingsView.tsrx +430 -0
  407. package/modules/directory/src/client/ProvisioningLogView.tsrx +248 -0
  408. package/modules/directory/src/client/ScimTokensView.tsrx +587 -0
  409. package/modules/directory/src/client/api.ts +222 -0
  410. package/modules/directory/src/client/contribution.tsrx +46 -0
  411. package/modules/directory/src/client/index.ts +22 -0
  412. package/modules/directory/src/client/navigation.ts +57 -0
  413. package/modules/directory/src/client/presentation.ts +143 -0
  414. package/modules/directory/src/client/state.ts +173 -0
  415. package/modules/directory/src/domain/scim.ts +346 -0
  416. package/modules/directory/src/domain/types.ts +166 -0
  417. package/modules/directory/src/index.ts +44 -0
  418. package/modules/directory/src/platform.ts +43 -0
  419. package/modules/directory/src/server/index.ts +17 -0
  420. package/modules/directory/src/server/runtime.ts +124 -0
  421. package/modules/directory/src/services/auth-port.ts +127 -0
  422. package/modules/directory/src/services/data-classes.ts +41 -0
  423. package/modules/directory/src/services/database-repository.ts +1067 -0
  424. package/modules/directory/src/services/directory-service.ts +311 -0
  425. package/modules/directory/src/services/index.ts +43 -0
  426. package/modules/directory/src/services/migration.ts +146 -0
  427. package/modules/directory/src/services/provisioning-service.ts +1420 -0
  428. package/modules/directory/src/services/rate-limiter.ts +103 -0
  429. package/modules/directory/src/services/repository.ts +208 -0
  430. package/modules/directory/src/services/service-error.ts +42 -0
  431. package/modules/directory/src/services/token-service.ts +215 -0
  432. package/modules/directory/src/settings.ts +86 -0
  433. package/modules/directory/translations/en.json +185 -0
  434. package/modules/directory/translations/pl.json +185 -0
  435. package/modules/documents/migrations/0001_documents_core.down.sql +1 -0
  436. package/modules/documents/migrations/0001_documents_core.up.sql +35 -0
  437. package/modules/documents/migrations/0002_documents_files_page.down.sql +1 -0
  438. package/modules/documents/migrations/0002_documents_files_page.up.sql +6 -0
  439. package/modules/documents/migrations/0003_documents_rotation_inventory.down.sql +2 -0
  440. package/modules/documents/migrations/0003_documents_rotation_inventory.up.sql +18 -0
  441. package/modules/documents/migrations/README.md +3 -0
  442. package/modules/documents/module.json +32 -0
  443. package/modules/documents/package.json +50 -0
  444. package/modules/documents/spec/module.yaml +248 -0
  445. package/modules/documents/src/acl/permissions.ts +6 -0
  446. package/modules/documents/src/api/endpoints.ts +401 -0
  447. package/modules/documents/src/cli/commands.json +17 -0
  448. package/modules/documents/src/cli/index.ts +145 -0
  449. package/modules/documents/src/client/DocumentUploader.tsrx +148 -0
  450. package/modules/documents/src/client/DocumentsView.tsrx +540 -0
  451. package/modules/documents/src/client/api.ts +209 -0
  452. package/modules/documents/src/client/contribution.tsrx +29 -0
  453. package/modules/documents/src/client/download.ts +70 -0
  454. package/modules/documents/src/client/index.ts +22 -0
  455. package/modules/documents/src/client/navigation.ts +25 -0
  456. package/modules/documents/src/client/presentation.ts +110 -0
  457. package/modules/documents/src/client/state.ts +117 -0
  458. package/modules/documents/src/domain/attachments.ts +84 -0
  459. package/modules/documents/src/domain/types.ts +80 -0
  460. package/modules/documents/src/index.ts +46 -0
  461. package/modules/documents/src/platform.ts +61 -0
  462. package/modules/documents/src/server/index.ts +30 -0
  463. package/modules/documents/src/server/runtime.ts +107 -0
  464. package/modules/documents/src/services/attachments.ts +39 -0
  465. package/modules/documents/src/services/data-classes.ts +25 -0
  466. package/modules/documents/src/services/database-repository.ts +270 -0
  467. package/modules/documents/src/services/documents-service.ts +590 -0
  468. package/modules/documents/src/services/index.ts +18 -0
  469. package/modules/documents/src/services/migration.ts +117 -0
  470. package/modules/documents/src/services/repository.ts +58 -0
  471. package/modules/documents/src/services/storage-rotation.ts +157 -0
  472. package/modules/documents/src/settings.ts +107 -0
  473. package/modules/documents/translations/en.json +111 -0
  474. package/modules/documents/translations/pl.json +111 -0
  475. package/modules/exports/migrations/0001_exports_core.down.sql +2 -0
  476. package/modules/exports/migrations/0001_exports_core.up.sql +28 -0
  477. package/modules/exports/migrations/0002_exports_job_routing_role.down.sql +4 -0
  478. package/modules/exports/migrations/0002_exports_job_routing_role.up.sql +21 -0
  479. package/modules/exports/migrations/0003_exports_rotation_inventory.down.sql +1 -0
  480. package/modules/exports/migrations/0003_exports_rotation_inventory.up.sql +9 -0
  481. package/modules/exports/migrations/README.md +3 -0
  482. package/modules/exports/module.json +32 -0
  483. package/modules/exports/package.json +45 -0
  484. package/modules/exports/spec/module.yaml +230 -0
  485. package/modules/exports/src/acl/permissions.ts +6 -0
  486. package/modules/exports/src/api/endpoints.ts +211 -0
  487. package/modules/exports/src/cli/commands.json +17 -0
  488. package/modules/exports/src/cli/index.ts +145 -0
  489. package/modules/exports/src/client/ExportsView.tsrx +327 -0
  490. package/modules/exports/src/client/api.ts +133 -0
  491. package/modules/exports/src/client/contribution.tsrx +31 -0
  492. package/modules/exports/src/client/index.ts +20 -0
  493. package/modules/exports/src/client/navigation.ts +25 -0
  494. package/modules/exports/src/client/presentation.ts +53 -0
  495. package/modules/exports/src/client/state.ts +56 -0
  496. package/modules/exports/src/domain/lists.ts +29 -0
  497. package/modules/exports/src/domain/types.ts +120 -0
  498. package/modules/exports/src/index.ts +41 -0
  499. package/modules/exports/src/platform.ts +80 -0
  500. package/modules/exports/src/server/index.ts +50 -0
  501. package/modules/exports/src/server/runtime.ts +160 -0
  502. package/modules/exports/src/services/data-classes.ts +59 -0
  503. package/modules/exports/src/services/database-repository.ts +403 -0
  504. package/modules/exports/src/services/export-runner.ts +123 -0
  505. package/modules/exports/src/services/export-service.ts +356 -0
  506. package/modules/exports/src/services/index.ts +6 -0
  507. package/modules/exports/src/services/list-registry.ts +105 -0
  508. package/modules/exports/src/services/migration.ts +116 -0
  509. package/modules/exports/src/services/repository.ts +96 -0
  510. package/modules/exports/src/services/storage-rotation.ts +138 -0
  511. package/modules/exports/src/settings.ts +70 -0
  512. package/modules/exports/translations/en.json +69 -0
  513. package/modules/exports/translations/pl.json +69 -0
  514. package/modules/import/migrations/0001_import_core.down.sql +6 -0
  515. package/modules/import/migrations/0001_import_core.up.sql +61 -0
  516. package/modules/import/migrations/0002_import_job_routing_role.down.sql +4 -0
  517. package/modules/import/migrations/0002_import_job_routing_role.up.sql +20 -0
  518. package/modules/import/migrations/0003_import_jobs_export_index.down.sql +1 -0
  519. package/modules/import/migrations/0003_import_jobs_export_index.up.sql +7 -0
  520. package/modules/import/migrations/0004_import_jobs_traceparent.down.sql +1 -0
  521. package/modules/import/migrations/0004_import_jobs_traceparent.up.sql +7 -0
  522. package/modules/import/migrations/README.md +3 -0
  523. package/modules/import/module.json +37 -0
  524. package/modules/import/package.json +50 -0
  525. package/modules/import/spec/module.yaml +335 -0
  526. package/modules/import/src/acl/permissions.ts +6 -0
  527. package/modules/import/src/api/endpoints.ts +400 -0
  528. package/modules/import/src/client/ImportJobDrawer.tsrx +229 -0
  529. package/modules/import/src/client/ImportsView.tsrx +455 -0
  530. package/modules/import/src/client/NewImportForm.tsrx +274 -0
  531. package/modules/import/src/client/api.ts +243 -0
  532. package/modules/import/src/client/contribution.tsrx +29 -0
  533. package/modules/import/src/client/index.ts +23 -0
  534. package/modules/import/src/client/navigation.ts +25 -0
  535. package/modules/import/src/client/presentation.ts +59 -0
  536. package/modules/import/src/client/state.ts +43 -0
  537. package/modules/import/src/domain/csv.ts +258 -0
  538. package/modules/import/src/domain/ports.ts +157 -0
  539. package/modules/import/src/domain/types.ts +179 -0
  540. package/modules/import/src/index.ts +58 -0
  541. package/modules/import/src/platform.ts +60 -0
  542. package/modules/import/src/server/index.ts +49 -0
  543. package/modules/import/src/server/runtime.ts +158 -0
  544. package/modules/import/src/services/csv-source.ts +121 -0
  545. package/modules/import/src/services/data-classes.ts +63 -0
  546. package/modules/import/src/services/database-repository.ts +780 -0
  547. package/modules/import/src/services/import-runner.ts +127 -0
  548. package/modules/import/src/services/import-service.ts +872 -0
  549. package/modules/import/src/services/index.ts +6 -0
  550. package/modules/import/src/services/migration.ts +156 -0
  551. package/modules/import/src/services/port-registry.ts +158 -0
  552. package/modules/import/src/services/repository.ts +147 -0
  553. package/modules/import/src/settings.ts +70 -0
  554. package/modules/import/translations/en.json +175 -0
  555. package/modules/import/translations/pl.json +175 -0
  556. package/modules/metering/migrations/0001_metering_core.down.sql +6 -0
  557. package/modules/metering/migrations/0001_metering_core.up.sql +119 -0
  558. package/modules/metering/migrations/0002_metering_bucket_export.down.sql +3 -0
  559. package/modules/metering/migrations/0002_metering_bucket_export.up.sql +5 -0
  560. package/modules/metering/migrations/README.md +3 -0
  561. package/modules/metering/module.json +46 -0
  562. package/modules/metering/package.json +50 -0
  563. package/modules/metering/spec/module.yaml +269 -0
  564. package/modules/metering/src/acl/permissions.ts +5 -0
  565. package/modules/metering/src/api/endpoints.ts +104 -0
  566. package/modules/metering/src/cli/commands.json +28 -0
  567. package/modules/metering/src/cli/index.ts +246 -0
  568. package/modules/metering/src/client/LimitsView.tsrx +170 -0
  569. package/modules/metering/src/client/UsageSummaryWidget.tsrx +63 -0
  570. package/modules/metering/src/client/UsageView.tsrx +205 -0
  571. package/modules/metering/src/client/api.ts +91 -0
  572. package/modules/metering/src/client/contribution.tsrx +42 -0
  573. package/modules/metering/src/client/index.ts +26 -0
  574. package/modules/metering/src/client/navigation.ts +54 -0
  575. package/modules/metering/src/client/presentation.ts +63 -0
  576. package/modules/metering/src/client/state.ts +31 -0
  577. package/modules/metering/src/domain/meters.ts +100 -0
  578. package/modules/metering/src/domain/types.ts +71 -0
  579. package/modules/metering/src/index.ts +51 -0
  580. package/modules/metering/src/platform.ts +84 -0
  581. package/modules/metering/src/server/index.ts +40 -0
  582. package/modules/metering/src/server/runtime.ts +165 -0
  583. package/modules/metering/src/services/data-classes.ts +34 -0
  584. package/modules/metering/src/services/database-repository.ts +574 -0
  585. package/modules/metering/src/services/index.ts +9 -0
  586. package/modules/metering/src/services/meter-registry.ts +145 -0
  587. package/modules/metering/src/services/metering-service.ts +441 -0
  588. package/modules/metering/src/services/migration.ts +183 -0
  589. package/modules/metering/src/services/notifications.ts +75 -0
  590. package/modules/metering/src/services/reports.ts +105 -0
  591. package/modules/metering/src/services/repository.ts +132 -0
  592. package/modules/metering/src/services/service-error.ts +46 -0
  593. package/modules/metering/src/settings.ts +47 -0
  594. package/modules/metering/translations/en.json +68 -0
  595. package/modules/metering/translations/pl.json +68 -0
  596. package/modules/notifications/migrations/0001_notifications_core.down.sql +1 -0
  597. package/modules/notifications/migrations/0001_notifications_core.up.sql +26 -0
  598. package/modules/notifications/migrations/0002_notifications_preferences.down.sql +1 -0
  599. package/modules/notifications/migrations/0002_notifications_preferences.up.sql +17 -0
  600. package/modules/notifications/migrations/0003_notifications_webhook_subscriptions.down.sql +1 -0
  601. package/modules/notifications/migrations/0003_notifications_webhook_subscriptions.up.sql +30 -0
  602. package/modules/notifications/migrations/0004_notifications_deliveries.down.sql +1 -0
  603. package/modules/notifications/migrations/0004_notifications_deliveries.up.sql +35 -0
  604. package/modules/notifications/migrations/0005_notifications_delivery_routing_role.down.sql +2 -0
  605. package/modules/notifications/migrations/0005_notifications_delivery_routing_role.up.sql +17 -0
  606. package/modules/notifications/migrations/0006_notifications_delivery_title.down.sql +1 -0
  607. package/modules/notifications/migrations/0006_notifications_delivery_title.up.sql +11 -0
  608. package/modules/notifications/migrations/0007_notifications_secret_rotation_inventory.down.sql +2 -0
  609. package/modules/notifications/migrations/0007_notifications_secret_rotation_inventory.up.sql +19 -0
  610. package/modules/notifications/migrations/0008_notifications_delivery_claim.down.sql +8 -0
  611. package/modules/notifications/migrations/0008_notifications_delivery_claim.up.sql +19 -0
  612. package/modules/notifications/migrations/0009_notifications_kind_approvals.down.sql +16 -0
  613. package/modules/notifications/migrations/0009_notifications_kind_approvals.up.sql +18 -0
  614. package/modules/notifications/migrations/0010_notifications_kind_meter_threshold.down.sql +16 -0
  615. package/modules/notifications/migrations/0010_notifications_kind_meter_threshold.up.sql +18 -0
  616. package/modules/notifications/migrations/0011_notifications_retention_keyset.down.sql +5 -0
  617. package/modules/notifications/migrations/0011_notifications_retention_keyset.up.sql +15 -0
  618. package/modules/notifications/migrations/0012_notifications_email_channel.down.sql +12 -0
  619. package/modules/notifications/migrations/0012_notifications_email_channel.up.sql +38 -0
  620. package/modules/notifications/migrations/0013_notifications_list_pages.down.sql +5 -0
  621. package/modules/notifications/migrations/0013_notifications_list_pages.up.sql +13 -0
  622. package/modules/notifications/migrations/README.md +3 -0
  623. package/modules/notifications/module.json +32 -0
  624. package/modules/notifications/package.json +49 -0
  625. package/modules/notifications/spec/module.yaml +718 -0
  626. package/modules/notifications/src/acl/permissions.ts +11 -0
  627. package/modules/notifications/src/api/endpoints.ts +814 -0
  628. package/modules/notifications/src/cli/commands.json +17 -0
  629. package/modules/notifications/src/cli/index.ts +126 -0
  630. package/modules/notifications/src/client/DeliveriesView.tsrx +483 -0
  631. package/modules/notifications/src/client/FactList.tsrx +24 -0
  632. package/modules/notifications/src/client/NotificationPreferencesView.tsrx +240 -0
  633. package/modules/notifications/src/client/NotificationsInboxView.tsrx +592 -0
  634. package/modules/notifications/src/client/UnreadCountWidget.tsrx +62 -0
  635. package/modules/notifications/src/client/WebhookForm.tsrx +297 -0
  636. package/modules/notifications/src/client/WebhooksView.tsrx +637 -0
  637. package/modules/notifications/src/client/api.ts +382 -0
  638. package/modules/notifications/src/client/contribution.tsrx +83 -0
  639. package/modules/notifications/src/client/inbox.ts +41 -0
  640. package/modules/notifications/src/client/index.ts +29 -0
  641. package/modules/notifications/src/client/navigation.ts +92 -0
  642. package/modules/notifications/src/client/notifications.css +70 -0
  643. package/modules/notifications/src/client/presentation.ts +81 -0
  644. package/modules/notifications/src/client/state.ts +246 -0
  645. package/modules/notifications/src/client/unread-count.ts +26 -0
  646. package/modules/notifications/src/domain/locale.ts +47 -0
  647. package/modules/notifications/src/domain/publish.ts +46 -0
  648. package/modules/notifications/src/domain/types.ts +186 -0
  649. package/modules/notifications/src/index.ts +62 -0
  650. package/modules/notifications/src/platform.ts +85 -0
  651. package/modules/notifications/src/server/index.ts +82 -0
  652. package/modules/notifications/src/server/runtime.ts +251 -0
  653. package/modules/notifications/src/services/data-classes.ts +139 -0
  654. package/modules/notifications/src/services/database-repository.ts +1334 -0
  655. package/modules/notifications/src/services/delivery-payload.ts +93 -0
  656. package/modules/notifications/src/services/delivery-runner.ts +170 -0
  657. package/modules/notifications/src/services/delivery-service.ts +811 -0
  658. package/modules/notifications/src/services/egress.ts +239 -0
  659. package/modules/notifications/src/services/email-channel.ts +93 -0
  660. package/modules/notifications/src/services/index.ts +23 -0
  661. package/modules/notifications/src/services/migration.ts +572 -0
  662. package/modules/notifications/src/services/notifications-service.ts +297 -0
  663. package/modules/notifications/src/services/paging.ts +60 -0
  664. package/modules/notifications/src/services/publish-service.ts +133 -0
  665. package/modules/notifications/src/services/repository.ts +342 -0
  666. package/modules/notifications/src/services/secret-rotation.ts +177 -0
  667. package/modules/notifications/src/services/secret-vault.ts +168 -0
  668. package/modules/notifications/src/services/service-error.ts +67 -0
  669. package/modules/notifications/src/services/signature.ts +81 -0
  670. package/modules/notifications/src/services/webhook-service.ts +307 -0
  671. package/modules/notifications/src/settings.ts +130 -0
  672. package/modules/notifications/translations/en.json +255 -0
  673. package/modules/notifications/translations/pl.json +255 -0
  674. package/modules/profile/module.json +3 -3
  675. package/modules/profile/package.json +1 -1
  676. package/modules/profile/spec/module.yaml +3 -3
  677. package/modules/profile/src/services/database-repository.ts +3 -13
  678. package/modules/reports/module.json +28 -0
  679. package/modules/reports/package.json +42 -0
  680. package/modules/reports/spec/module.yaml +231 -0
  681. package/modules/reports/src/acl/permissions.ts +5 -0
  682. package/modules/reports/src/api/endpoints.ts +72 -0
  683. package/modules/reports/src/client/ReportsSummaryWidget.tsrx +52 -0
  684. package/modules/reports/src/client/ReportsView.tsrx +246 -0
  685. package/modules/reports/src/client/api.ts +65 -0
  686. package/modules/reports/src/client/contribution.tsrx +36 -0
  687. package/modules/reports/src/client/index.ts +18 -0
  688. package/modules/reports/src/client/navigation.ts +39 -0
  689. package/modules/reports/src/client/presentation.ts +123 -0
  690. package/modules/reports/src/client/state.ts +28 -0
  691. package/modules/reports/src/domain/providers.ts +115 -0
  692. package/modules/reports/src/domain/types.ts +44 -0
  693. package/modules/reports/src/index.ts +47 -0
  694. package/modules/reports/src/platform.ts +37 -0
  695. package/modules/reports/src/server/index.ts +21 -0
  696. package/modules/reports/src/server/runtime.ts +40 -0
  697. package/modules/reports/src/services/index.ts +17 -0
  698. package/modules/reports/src/services/provider-registry.ts +144 -0
  699. package/modules/reports/src/services/range.ts +65 -0
  700. package/modules/reports/src/services/reports-service.ts +316 -0
  701. package/modules/reports/src/services/service-error.ts +26 -0
  702. package/modules/reports/src/settings.ts +49 -0
  703. package/modules/reports/translations/en.json +35 -0
  704. package/modules/reports/translations/pl.json +35 -0
  705. package/modules/sandbox/module.json +4 -4
  706. package/modules/sandbox/package.json +1 -1
  707. package/modules/sandbox/spec/module.yaml +3 -3
  708. package/modules/sandbox/src/services/database-repository.ts +14 -23
  709. package/modules/sandbox/src/services/directory.ts +16 -0
  710. package/modules/sandbox/src/services/sandbox-service.ts +13 -11
  711. package/modules/search/migrations/0001_search_core.down.sql +1 -0
  712. package/modules/search/migrations/0001_search_core.up.sql +22 -0
  713. package/modules/search/migrations/0002_search_recent_export.down.sql +3 -0
  714. package/modules/search/migrations/0002_search_recent_export.up.sql +5 -0
  715. package/modules/search/migrations/README.md +3 -0
  716. package/modules/search/module.json +28 -0
  717. package/modules/search/package.json +43 -0
  718. package/modules/search/spec/module.yaml +177 -0
  719. package/modules/search/src/acl/permissions.ts +5 -0
  720. package/modules/search/src/api/endpoints.ts +221 -0
  721. package/modules/search/src/client/SearchView.tsrx +346 -0
  722. package/modules/search/src/client/api.ts +157 -0
  723. package/modules/search/src/client/contribution.tsrx +31 -0
  724. package/modules/search/src/client/index.ts +17 -0
  725. package/modules/search/src/client/navigation.ts +97 -0
  726. package/modules/search/src/client/search.css +56 -0
  727. package/modules/search/src/client/state.ts +113 -0
  728. package/modules/search/src/domain/data-classes.ts +73 -0
  729. package/modules/search/src/domain/providers.ts +88 -0
  730. package/modules/search/src/domain/types.ts +56 -0
  731. package/modules/search/src/index.ts +46 -0
  732. package/modules/search/src/platform.ts +42 -0
  733. package/modules/search/src/server/index.ts +25 -0
  734. package/modules/search/src/server/runtime.ts +123 -0
  735. package/modules/search/src/services/database-repository.ts +163 -0
  736. package/modules/search/src/services/index.ts +21 -0
  737. package/modules/search/src/services/migration.ts +65 -0
  738. package/modules/search/src/services/provider-registry.ts +137 -0
  739. package/modules/search/src/services/repository.ts +43 -0
  740. package/modules/search/src/services/search-service.ts +442 -0
  741. package/modules/search/src/services/service-error.ts +35 -0
  742. package/modules/search/src/settings.ts +68 -0
  743. package/modules/search/translations/en.json +45 -0
  744. package/modules/search/translations/pl.json +45 -0
  745. package/modules/system/module.json +2 -2
  746. package/modules/system/package.json +1 -1
  747. package/modules/system/spec/module.yaml +30 -3
  748. package/modules/system/src/client/FlagsPanel.tsrx +127 -0
  749. package/modules/system/src/client/ModuleSettingRow.tsrx +17 -7
  750. package/modules/system/src/client/ModuleSettingsSection.tsrx +10 -71
  751. package/modules/system/src/client/ModulesView.tsrx +91 -65
  752. package/modules/system/src/client/flags.ts +35 -0
  753. package/modules/system/src/client/index.ts +8 -0
  754. package/modules/system/src/client/navigation.ts +8 -0
  755. package/modules/system/src/client/settings-state.ts +159 -0
  756. package/modules/system/src/client/state.ts +2 -0
  757. package/modules/system/src/domain/time-zone.ts +105 -0
  758. package/modules/system/src/index.ts +12 -0
  759. package/modules/system/src/platform.ts +5 -1
  760. package/modules/system/src/server/endpoints.ts +72 -21
  761. package/modules/system/src/settings.ts +28 -0
  762. package/modules/system/translations/en.json +17 -0
  763. package/modules/system/translations/pl.json +17 -0
  764. package/modules/users/module.json +30 -4
  765. package/modules/users/package.json +4 -1
  766. package/modules/users/spec/module.yaml +290 -7
  767. package/modules/users/src/api/endpoints.ts +228 -15
  768. package/modules/users/src/client/InviteMemberForm.tsrx +2 -2
  769. package/modules/users/src/client/MemberDrawer.tsrx +142 -26
  770. package/modules/users/src/client/UserAccountForm.tsrx +2 -2
  771. package/modules/users/src/client/UsersView.tsrx +432 -71
  772. package/modules/users/src/client/api.ts +106 -12
  773. package/modules/users/src/client/contribution.tsrx +5 -0
  774. package/modules/users/src/client/member-columns.tsrx +22 -9
  775. package/modules/users/src/client/state.ts +172 -7
  776. package/modules/users/src/domain/lists.ts +9 -0
  777. package/modules/users/src/index.ts +11 -0
  778. package/modules/users/src/platform.ts +50 -1
  779. package/modules/users/src/services/member-export.ts +51 -0
  780. package/modules/users/src/services/member-import.ts +249 -0
  781. package/modules/users/src/services/member-search.ts +145 -0
  782. package/modules/users/src/services/users-service.ts +117 -4
  783. package/modules/users/translations/en.json +57 -8
  784. package/modules/users/translations/pl.json +57 -8
  785. package/modules/workflows/migrations/0004_payload_rotation_inventory.up.sql +17 -0
  786. package/modules/workflows/migrations/0005_workflows_human_approval.up.sql +28 -0
  787. package/modules/workflows/migrations/0006_workflows_retention_indexes.up.sql +11 -0
  788. package/modules/workflows/migrations/0007_workflows_erasure_subject_indexes.up.sql +17 -0
  789. package/modules/workflows/migrations/0008_workflows_subject_account.up.sql +24 -0
  790. package/modules/workflows/migrations/0009_workflows_definition_list_indexes.up.sql +9 -0
  791. package/modules/workflows/module.json +34 -6
  792. package/modules/workflows/package.json +2 -1
  793. package/modules/workflows/spec/module.yaml +26 -9
  794. package/modules/workflows/src/api/endpoints.ts +131 -25
  795. package/modules/workflows/src/cli/commands.json +17 -0
  796. package/modules/workflows/src/cli/index.ts +114 -0
  797. package/modules/workflows/src/client/WorkflowExecutionHistory.tsrx +36 -27
  798. package/modules/workflows/src/client/WorkflowInspector.tsrx +116 -0
  799. package/modules/workflows/src/client/WorkflowNodePalette.tsrx +1 -0
  800. package/modules/workflows/src/client/WorkflowsView.tsrx +236 -99
  801. package/modules/workflows/src/client/api.ts +54 -34
  802. package/modules/workflows/src/client/canvas-model.ts +12 -0
  803. package/modules/workflows/src/client/state.ts +95 -0
  804. package/modules/workflows/src/domain/events.ts +25 -11
  805. package/modules/workflows/src/domain/graph.ts +135 -1
  806. package/modules/workflows/src/domain/types.ts +91 -4
  807. package/modules/workflows/src/platform.ts +12 -0
  808. package/modules/workflows/src/server/runtime.ts +78 -5
  809. package/modules/workflows/src/services/approvals.ts +62 -0
  810. package/modules/workflows/src/services/cursors.ts +37 -0
  811. package/modules/workflows/src/services/data-classes.ts +232 -0
  812. package/modules/workflows/src/services/database-repository.ts +660 -171
  813. package/modules/workflows/src/services/migration.ts +240 -0
  814. package/modules/workflows/src/services/notifications.ts +98 -0
  815. package/modules/workflows/src/services/payload-codec.ts +51 -28
  816. package/modules/workflows/src/services/payload-rotation.ts +171 -0
  817. package/modules/workflows/src/services/repository.ts +123 -8
  818. package/modules/workflows/src/services/simulation.ts +7 -0
  819. package/modules/workflows/src/services/worker.ts +446 -25
  820. package/modules/workflows/src/services/workflows-service.ts +264 -103
  821. package/modules/workflows/translations/en.json +12 -4
  822. package/modules/workflows/translations/pl.json +12 -4
  823. package/modules.json +48 -4
  824. package/package.json +64 -6
  825. package/packages/client/package.json +1 -0
  826. package/packages/client/src/ApplicationShell.tsrx +43 -0
  827. package/packages/client/src/contributions.ts +55 -0
  828. package/packages/client/src/i18n/locales/en.json +5 -0
  829. package/packages/client/src/i18n/locales/pl.json +5 -0
  830. package/packages/client/src/index.ts +13 -1
  831. package/packages/client/src/routing.ts +22 -0
  832. package/packages/client/src/shell/CommandPalette.tsrx +223 -11
  833. package/packages/client/src/shell/command-search.ts +126 -0
  834. package/packages/client/src/shell/command.ts +30 -0
  835. package/packages/client/src/shell/navigation.ts +12 -0
  836. package/packages/client/src/shell/palette-keys.ts +27 -0
  837. package/packages/client/src/shell/shell.css +7 -0
  838. package/packages/contracts/schemas/module-spec.schema.json +287 -1
  839. package/packages/contracts/schemas/module.schema.json +25 -0
  840. package/packages/contracts/src/index.ts +144 -1
  841. package/packages/database/src/backup.ts +180 -0
  842. package/packages/database/src/decoders.ts +25 -0
  843. package/packages/database/src/index.ts +17 -0
  844. package/packages/database/src/migrations.ts +7 -0
  845. package/packages/database/src/record-history.ts +5 -14
  846. package/packages/harness/src/index.ts +2 -0
  847. package/packages/harness/src/runtime.ts +378 -2
  848. package/packages/harness/src/tool-adapters.ts +20 -9
  849. package/packages/kernel/src/acl.ts +179 -0
  850. package/packages/kernel/src/approval-grant.ts +310 -0
  851. package/packages/kernel/src/capability-registry.ts +69 -2
  852. package/packages/kernel/src/data-class-registry.ts +354 -0
  853. package/packages/kernel/src/index.ts +85 -4
  854. package/packages/kernel/src/keyring.ts +208 -0
  855. package/packages/kernel/src/module-compatibility.ts +35 -4
  856. package/packages/kernel/src/module-registry.ts +49 -2
  857. package/packages/kernel/src/module-settings.ts +189 -27
  858. package/packages/server/package.json +2 -1
  859. package/packages/server/src/composition.ts +38 -0
  860. package/packages/server/src/endpoint.ts +104 -47
  861. package/packages/server/src/export/csv.ts +34 -0
  862. package/packages/server/src/export/definition.ts +346 -0
  863. package/packages/server/src/export/index.ts +61 -0
  864. package/packages/server/src/export/run.ts +116 -0
  865. package/packages/server/src/index.ts +155 -0
  866. package/packages/server/src/jobs/index.ts +93 -0
  867. package/packages/server/src/jobs/runner.ts +486 -0
  868. package/packages/server/src/log.ts +291 -0
  869. package/packages/server/src/mail/config.ts +184 -0
  870. package/packages/server/src/mail/contracts.ts +251 -0
  871. package/packages/server/src/mail/index.ts +31 -0
  872. package/packages/server/src/mail/port.ts +101 -0
  873. package/packages/server/src/mail/smtp.ts +191 -0
  874. package/packages/server/src/mail/template.ts +105 -0
  875. package/packages/server/src/metrics.ts +447 -0
  876. package/packages/server/src/pagination.ts +246 -0
  877. package/packages/server/src/trace/context.ts +103 -0
  878. package/packages/server/src/trace/egress.ts +66 -0
  879. package/packages/server/src/trace/error-sink.ts +296 -0
  880. package/packages/server/src/trace/exporter.ts +295 -0
  881. package/packages/server/src/trace/index.ts +60 -0
  882. package/packages/server/src/trace/job-sink.ts +172 -0
  883. package/packages/server/src/trace/tracer.ts +338 -0
  884. package/packages/server/src/web.ts +5 -1
  885. package/packages/storage/package.json +40 -0
  886. package/packages/storage/src/config.ts +189 -0
  887. package/packages/storage/src/content-type.ts +124 -0
  888. package/packages/storage/src/contracts.ts +112 -0
  889. package/packages/storage/src/envelope.ts +238 -0
  890. package/packages/storage/src/index.ts +49 -0
  891. package/packages/storage/src/local.ts +75 -0
  892. package/packages/storage/src/port.ts +262 -0
  893. package/packages/storage/src/read-token.ts +130 -0
  894. package/packages/storage/src/reseal.ts +128 -0
  895. package/packages/storage/src/s3.ts +144 -0
  896. package/packages/storage/src/scanner.ts +22 -0
  897. package/packages/storage/src/sigv4.ts +104 -0
  898. package/packages/storage/src/store.ts +13 -0
  899. package/packages/ui/package.json +1 -0
  900. package/packages/ui/src/components/Button.tsrx +3 -0
  901. package/packages/ui/src/components/ConfirmDialog.tsrx +13 -2
  902. package/packages/ui/src/components/DateField.tsrx +92 -0
  903. package/packages/ui/src/components/DatePicker.tsrx +525 -0
  904. package/packages/ui/src/components/DateRangeField.tsrx +93 -0
  905. package/packages/ui/src/components/Drawer.tsrx +10 -1
  906. package/packages/ui/src/components/FileUpload.tsrx +158 -0
  907. package/packages/ui/src/components/Pagination.tsrx +130 -0
  908. package/packages/ui/src/components/Select.tsrx +78 -0
  909. package/packages/ui/src/components/Table.tsrx +498 -81
  910. package/packages/ui/src/components/Tabs.tsrx +53 -0
  911. package/packages/ui/src/components/ToastHost.tsrx +48 -0
  912. package/packages/ui/src/components/calendar.ts +243 -0
  913. package/packages/ui/src/components/date-field.ts +62 -0
  914. package/packages/ui/src/components/file-upload.ts +49 -0
  915. package/packages/ui/src/components/focus-trap.ts +62 -0
  916. package/packages/ui/src/components/pagination.ts +68 -0
  917. package/packages/ui/src/components/table-sorting.ts +49 -0
  918. package/packages/ui/src/components/tabs.ts +61 -0
  919. package/packages/ui/src/components/toast-store.ts +116 -0
  920. package/packages/ui/src/icons/Icon.tsrx +5 -0
  921. package/packages/ui/src/index.ts +45 -0
  922. package/packages/ui/src/styles/components.css +598 -0
  923. package/modules/automations-workflows-integration/module.json +0 -27
  924. package/modules/automations-workflows-integration/spec/module.yaml +0 -93
  925. package/modules/automations-workflows-integration/src/index.ts +0 -14
  926. package/modules/automations-workflows-integration/src/platform.ts +0 -24
  927. package/modules/automations-workflows-integration/src/server/index.ts +0 -11
  928. package/modules/automations-workflows-integration/translations/en.json +0 -21
  929. package/modules/automations-workflows-integration/translations/pl.json +0 -21
  930. package/modules/workflows/src/services/cursor-codec.ts +0 -62
@@ -0,0 +1,872 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import {
3
+ currentTraceParent,
4
+ resumeJobTrace,
5
+ serverTracer,
6
+ type Tracer,
7
+ } from '@flowdular/sdk/server';
8
+ import type { AuthPrincipal } from '@flowdular/sdk/modules/auth';
9
+ import { readCsv, CsvError, type CsvDocument } from '../domain/csv.ts';
10
+ import {
11
+ IMPORT_MODES,
12
+ type ImportField,
13
+ type ImportFieldType,
14
+ type ImportMode,
15
+ type ImportRow,
16
+ type ImportValidation,
17
+ type ImportWriteOutcome,
18
+ } from '../domain/ports.ts';
19
+ import {
20
+ IMPORT_CSV_CONTENT_TYPE,
21
+ IMPORT_LIMITS,
22
+ IMPORT_MAX_CSV_BYTES,
23
+ IMPORT_UNEXPECTED_FAILURE,
24
+ type ClaimedImportJob,
25
+ type ImportJob,
26
+ type ImportJobRow,
27
+ type ImportJobStatus,
28
+ type ImportMapping,
29
+ type ImportRequester,
30
+ type ImportRowOutcome,
31
+ } from '../domain/types.ts';
32
+ import { ImportSourceError, type ImportCsvSource } from './csv-source.ts';
33
+ import type {
34
+ ImportPortRegistry,
35
+ RegisteredImportPort,
36
+ } from './port-registry.ts';
37
+ import type {
38
+ ImportJobPage,
39
+ ImportJobQuery,
40
+ ImportRepository,
41
+ ImportRowPage,
42
+ } from './repository.ts';
43
+
44
+ export class ImportServiceError extends Error {
45
+ constructor(
46
+ readonly code: string,
47
+ message: string,
48
+ readonly status = 400,
49
+ ) {
50
+ super(message);
51
+ this.name = 'ImportServiceError';
52
+ }
53
+ }
54
+
55
+ /** One target as a screen sees it, with whether this reader may use it. */
56
+ export interface ImportTargetView {
57
+ readonly target: string;
58
+ readonly moduleId: string;
59
+ readonly label: string;
60
+ readonly permission: string;
61
+ readonly permitted: boolean;
62
+ readonly fields: readonly ImportField[];
63
+ readonly naturalKey: readonly string[];
64
+ }
65
+
66
+ export interface StartImportInput {
67
+ readonly target: string;
68
+ readonly documentId: string;
69
+ readonly documentRef: string;
70
+ readonly mode: ImportMode;
71
+ readonly dryRun: boolean;
72
+ readonly columns: Readonly<Record<string, string>>;
73
+ }
74
+
75
+ export interface ImportServiceOptions {
76
+ readonly repository: ImportRepository;
77
+ readonly ports: ImportPortRegistry;
78
+ readonly source: ImportCsvSource;
79
+ readonly maxRows: () => number;
80
+ readonly batchSize: () => number;
81
+ readonly now?: () => number;
82
+ readonly newId?: () => string;
83
+ /** Defaults to the process tracer, which is the one `context.tracer` carries. */
84
+ readonly tracer?: Tracer;
85
+ }
86
+
87
+ /** One stage of one claimed job, in the trace that enqueued it. */
88
+ const IMPORT_PERFORM_SPAN = 'import.core perform';
89
+
90
+ const EMAIL = /^[^\s@]{1,64}@[^\s@.]{1,63}(\.[^\s@.]{1,63})+$/;
91
+ const INTEGER = /^-?\d{1,15}$/;
92
+ const DATE = /^\d{4}-\d{2}-\d{2}([T ][\d:.+\-Z]{1,24})?$/;
93
+ const BOOLEAN = new Set(['true', 'false', 'yes', 'no', '1', '0']);
94
+
95
+ function shapeOf(value: string, type: ImportFieldType): boolean {
96
+ switch (type) {
97
+ case 'integer':
98
+ return INTEGER.test(value) && Number.isSafeInteger(Number(value));
99
+ case 'boolean':
100
+ return BOOLEAN.has(value.toLowerCase());
101
+ case 'date':
102
+ return DATE.test(value) && Number.isFinite(Date.parse(value));
103
+ case 'email':
104
+ return value.length <= 254 && EMAIL.test(value);
105
+ default:
106
+ return true;
107
+ }
108
+ }
109
+
110
+ function requesterOf(principal: AuthPrincipal): ImportRequester {
111
+ const requester: ImportRequester = {
112
+ accountId: principal.accountId,
113
+ email: principal.email,
114
+ displayName: principal.displayName,
115
+ role: principal.role,
116
+ scopes: [...principal.scopes],
117
+ };
118
+ /* The job row bounds the snapshot at 8 KB. A principal carrying more than
119
+ that is refused here with a code the screen can read, rather than by the
120
+ column check once the job is half written. */
121
+ if (JSON.stringify(requester).length > IMPORT_LIMITS.json) {
122
+ throw new ImportServiceError(
123
+ 'REQUESTER_TOO_LARGE',
124
+ 'Your account carries more grants than an import job can record.',
125
+ );
126
+ }
127
+ return requester;
128
+ }
129
+
130
+ /**
131
+ * The principal the port sees in a background stage. It carries the identity
132
+ * and the grants the requester held when the job was started; the workspace is
133
+ * the job's own, and other workspace memberships are never part of an import.
134
+ */
135
+ function principalOf(job: ImportJob): AuthPrincipal {
136
+ return {
137
+ accountId: job.requester.accountId,
138
+ tenantId: job.tenantId,
139
+ email: job.requester.email,
140
+ displayName: job.requester.displayName,
141
+ role: job.requester.role,
142
+ scopes: job.requester.scopes,
143
+ tenants: [],
144
+ };
145
+ }
146
+
147
+ /* The comparison a port that folds nothing gets: the key fields exactly as the
148
+ file carries them, length prefixed so two fields cannot run into one another. */
149
+ function exactKey(key: readonly string[], values: ImportRow['values']): string {
150
+ let composed = '';
151
+ for (const field of key) {
152
+ const value = values[field] ?? '';
153
+ composed += `${value.length}:${value}`;
154
+ }
155
+ return composed;
156
+ }
157
+
158
+ function truncate(value: string | undefined, max: number): string | null {
159
+ if (value === undefined) return null;
160
+ const normalized = value.trim();
161
+ if (normalized === '') return null;
162
+ return normalized.length > max ? normalized.slice(0, max) : normalized;
163
+ }
164
+
165
+ export class ImportService {
166
+ readonly #repository: ImportRepository;
167
+ readonly #ports: ImportPortRegistry;
168
+ readonly #source: ImportCsvSource;
169
+ readonly #maxRows: () => number;
170
+ readonly #batchSize: () => number;
171
+ readonly #now: () => number;
172
+ readonly #newId: () => string;
173
+ readonly #tracer: Tracer;
174
+
175
+ constructor(options: ImportServiceOptions) {
176
+ this.#repository = options.repository;
177
+ this.#ports = options.ports;
178
+ this.#source = options.source;
179
+ this.#maxRows = options.maxRows;
180
+ this.#batchSize = options.batchSize;
181
+ this.#now = options.now ?? (() => Date.now());
182
+ this.#newId = options.newId ?? (() => randomUUID());
183
+ this.#tracer = options.tracer ?? serverTracer();
184
+ }
185
+
186
+ targets(principal: AuthPrincipal): readonly ImportTargetView[] {
187
+ return this.#ports.list().map((registered) => ({
188
+ target: registered.target,
189
+ moduleId: registered.moduleId,
190
+ label: registered.port.label,
191
+ permission: registered.port.permission,
192
+ permitted: principal.scopes.includes(registered.port.permission),
193
+ fields: registered.port.fields,
194
+ naturalKey: registered.port.naturalKey,
195
+ }));
196
+ }
197
+
198
+ async start(
199
+ principal: AuthPrincipal,
200
+ input: StartImportInput,
201
+ ): Promise<ImportJob> {
202
+ const registered = this.#require(input.target);
203
+ /* The target module's own permission, checked on the acting principal
204
+ before anything is recorded, so an import never widens what a member
205
+ may write. */
206
+ if (!principal.scopes.includes(registered.port.permission)) {
207
+ throw new ImportServiceError(
208
+ 'TARGET_FORBIDDEN',
209
+ 'You do not hold the permission this import target requires.',
210
+ 403,
211
+ );
212
+ }
213
+ if (!(IMPORT_MODES as readonly string[]).includes(input.mode)) {
214
+ throw new ImportServiceError(
215
+ 'MODE_UNKNOWN',
216
+ 'The import mode is unknown.',
217
+ );
218
+ }
219
+ this.#assertMapping(registered, input.columns);
220
+ const requester = requesterOf(principal);
221
+
222
+ /* Every bound the metadata can answer is answered here, so an oversized or
223
+ non-CSV document never becomes a job at all. */
224
+ const document = await this.#source.describe(
225
+ principal.tenantId,
226
+ input.documentRef,
227
+ input.documentId,
228
+ );
229
+ if (!document || document.status === 'deleted') {
230
+ throw new ImportServiceError(
231
+ 'SOURCE_NOT_FOUND',
232
+ 'The source document is not stored in this workspace.',
233
+ 404,
234
+ );
235
+ }
236
+ if (document.scan === 'infected') {
237
+ throw new ImportServiceError(
238
+ 'SOURCE_INFECTED',
239
+ 'The source document was refused by the malware scanner.',
240
+ );
241
+ }
242
+ if (document.contentType !== IMPORT_CSV_CONTENT_TYPE) {
243
+ throw new ImportServiceError(
244
+ 'SOURCE_NOT_CSV',
245
+ 'The source document is not a CSV file.',
246
+ );
247
+ }
248
+ if (document.bytes > IMPORT_MAX_CSV_BYTES) {
249
+ throw new ImportServiceError(
250
+ 'SOURCE_TOO_LARGE',
251
+ `The source document is larger than ${IMPORT_MAX_CSV_BYTES} bytes.`,
252
+ );
253
+ }
254
+
255
+ return this.#repository.createJob({
256
+ id: this.#newId(),
257
+ tenantId: principal.tenantId,
258
+ target: registered.target,
259
+ documentId: input.documentId,
260
+ documentRef: input.documentRef,
261
+ mode: input.mode,
262
+ dryRun: input.dryRun,
263
+ validOnly: false,
264
+ status: 'parsing',
265
+ totalRows: 0,
266
+ validRows: 0,
267
+ writtenRows: 0,
268
+ failedRows: 0,
269
+ requesterAccountId: principal.accountId,
270
+ requester,
271
+ columns: { ...input.columns },
272
+ failureCode: null,
273
+ claimedAt: null,
274
+ startedAt: this.#now(),
275
+ completedAt: null,
276
+ /* Captured here, where the request that asked for the import is still
277
+ the ambient trace; the poll that claims the job runs in none. */
278
+ traceparent: currentTraceParent(),
279
+ });
280
+ }
281
+
282
+ async continue(
283
+ principal: AuthPrincipal,
284
+ id: string,
285
+ validOnly: boolean,
286
+ ): Promise<ImportJob> {
287
+ const job = await this.#requireJob(principal.tenantId, id);
288
+ if (job.dryRun) {
289
+ throw new ImportServiceError(
290
+ 'JOB_DRY_RUN',
291
+ 'A dry run writes nothing; start a new job to write these rows.',
292
+ 409,
293
+ );
294
+ }
295
+ if (job.status !== 'validated') {
296
+ throw new ImportServiceError(
297
+ 'JOB_NOT_VALIDATED',
298
+ 'Only a validated job can be continued.',
299
+ 409,
300
+ );
301
+ }
302
+ /* The grant is re-checked on the live principal: a job validated before a
303
+ permission was revoked must not write afterwards. */
304
+ const registered = this.#require(job.target);
305
+ if (!principal.scopes.includes(registered.port.permission)) {
306
+ throw new ImportServiceError(
307
+ 'TARGET_FORBIDDEN',
308
+ 'You do not hold the permission this import target requires.',
309
+ 403,
310
+ );
311
+ }
312
+ if (!validOnly && job.validRows !== job.totalRows) {
313
+ throw new ImportServiceError(
314
+ 'VALIDATION_FAILED',
315
+ 'This job has invalid rows; continue with the valid rows only.',
316
+ 409,
317
+ );
318
+ }
319
+ const moved = await this.#repository.continueJob(
320
+ principal.tenantId,
321
+ id,
322
+ validOnly,
323
+ );
324
+ if (!moved) {
325
+ throw new ImportServiceError(
326
+ 'JOB_NOT_VALIDATED',
327
+ 'Only a validated job can be continued.',
328
+ 409,
329
+ );
330
+ }
331
+ return moved;
332
+ }
333
+
334
+ async cancel(principal: AuthPrincipal, id: string): Promise<ImportJob> {
335
+ const job = await this.#requireJob(principal.tenantId, id);
336
+ const cancelled = await this.#repository.advanceJob(
337
+ principal.tenantId,
338
+ id,
339
+ ['validated'],
340
+ {
341
+ status: 'cancelled',
342
+ totalRows: job.totalRows,
343
+ validRows: job.validRows,
344
+ writtenRows: job.writtenRows,
345
+ failedRows: job.failedRows,
346
+ failureCode: null,
347
+ completedAt: this.#now(),
348
+ },
349
+ );
350
+ if (!cancelled) {
351
+ throw new ImportServiceError(
352
+ 'JOB_NOT_VALIDATED',
353
+ 'Only a validated job can be cancelled.',
354
+ 409,
355
+ );
356
+ }
357
+ return cancelled;
358
+ }
359
+
360
+ async job(tenantId: string, id: string): Promise<ImportJob> {
361
+ return this.#requireJob(tenantId, id);
362
+ }
363
+
364
+ async jobs(tenantId: string, query: ImportJobQuery): Promise<ImportJobPage> {
365
+ return this.#repository.listJobs(tenantId, query);
366
+ }
367
+
368
+ async rows(
369
+ tenantId: string,
370
+ jobId: string,
371
+ limit: number,
372
+ after?: number,
373
+ ): Promise<ImportRowPage> {
374
+ await this.#requireJob(tenantId, jobId);
375
+ return this.#repository.listJobRows(tenantId, jobId, limit, after);
376
+ }
377
+
378
+ async mapping(
379
+ tenantId: string,
380
+ target: string,
381
+ ): Promise<ImportMapping | null> {
382
+ this.#require(target);
383
+ return this.#repository.findMapping(tenantId, target);
384
+ }
385
+
386
+ async saveMapping(
387
+ principal: AuthPrincipal,
388
+ target: string,
389
+ columns: Readonly<Record<string, string>>,
390
+ ): Promise<ImportMapping> {
391
+ const registered = this.#require(target);
392
+ if (!principal.scopes.includes(registered.port.permission)) {
393
+ throw new ImportServiceError(
394
+ 'TARGET_FORBIDDEN',
395
+ 'You do not hold the permission this import target requires.',
396
+ 403,
397
+ );
398
+ }
399
+ this.#assertMapping(registered, columns);
400
+ const existing = await this.#repository.findMapping(
401
+ principal.tenantId,
402
+ target,
403
+ );
404
+ return this.#repository.saveMapping({
405
+ id: existing?.id ?? this.#newId(),
406
+ tenantId: principal.tenantId,
407
+ target,
408
+ columns: { ...columns },
409
+ updatedAt: this.#now(),
410
+ });
411
+ }
412
+
413
+ /**
414
+ * One stage of one claimed job. It never throws: a failure is the job's
415
+ * recorded outcome, because the operator reads the job, not this process's
416
+ * log.
417
+ *
418
+ * The stage runs in the trace the request that enqueued the job was part
419
+ * of, from the `traceparent` that request stored on the row, so the spans
420
+ * and the log lines of the background work carry the trace id of the
421
+ * import that asked for it.
422
+ */
423
+ async perform(
424
+ job: ClaimedImportJob,
425
+ signal?: AbortSignal,
426
+ ): Promise<ImportJob> {
427
+ return resumeJobTrace(
428
+ this.#tracer,
429
+ job.traceparent,
430
+ IMPORT_PERFORM_SPAN,
431
+ () => this.#perform(job, signal),
432
+ );
433
+ }
434
+
435
+ async #perform(
436
+ job: ClaimedImportJob,
437
+ signal?: AbortSignal,
438
+ ): Promise<ImportJob> {
439
+ try {
440
+ return job.status === 'parsing'
441
+ ? await this.#parseAndValidate(job, signal)
442
+ : await this.#write(job, signal);
443
+ } catch (error) {
444
+ /* The lease lapsed and another loop reclaimed the job. It is that loop's
445
+ work now, so this stage records nothing at all: failing the job here
446
+ would settle work that is still running. */
447
+ if (error instanceof ImportServiceError && error.code === 'CLAIM_LOST') {
448
+ return (await this.#repository.findJob(job.tenantId, job.id)) ?? job;
449
+ }
450
+ const code =
451
+ error instanceof CsvError || error instanceof ImportSourceError
452
+ ? error.code
453
+ : error instanceof ImportServiceError
454
+ ? error.code
455
+ : IMPORT_UNEXPECTED_FAILURE;
456
+ return (
457
+ (await this.#repository.advanceJob(job.tenantId, job.id, [job.status], {
458
+ status: 'failed',
459
+ totalRows: job.totalRows,
460
+ validRows: job.validRows,
461
+ writtenRows: job.writtenRows,
462
+ failedRows: job.failedRows,
463
+ failureCode: code.slice(0, IMPORT_LIMITS.failureCode),
464
+ completedAt: this.#now(),
465
+ })) ?? job
466
+ );
467
+ }
468
+ }
469
+
470
+ async #parseAndValidate(
471
+ job: ClaimedImportJob,
472
+ signal: AbortSignal | undefined,
473
+ ): Promise<ImportJob> {
474
+ const registered = this.#require(job.target);
475
+ const document = await this.#read(job);
476
+ const { rows, invalid } = this.#map(registered, job, document);
477
+
478
+ const verdicts = new Map<number, ImportValidation>();
479
+ for (const entry of invalid) verdicts.set(entry.row, entry);
480
+ for (const entry of this.#duplicates(registered, rows)) {
481
+ verdicts.set(entry.row, entry);
482
+ }
483
+ /* A row already refused is never offered to the port: the port answers
484
+ refusals for rows it was given, and a duplicate is refused here. */
485
+ const pending = rows.filter((row) => !verdicts.has(row.row));
486
+
487
+ const batch = this.#batchSize();
488
+ const principal = principalOf(job);
489
+ for (let start = 0; start < pending.length; start += batch) {
490
+ const slice = pending.slice(start, start + batch);
491
+ for (const verdict of await this.#validate(registered, {
492
+ tenantId: job.tenantId,
493
+ principal,
494
+ rows: slice,
495
+ })) {
496
+ if (verdict.verdict === 'invalid') verdicts.set(verdict.row, verdict);
497
+ }
498
+ this.#checkpoint(signal);
499
+ }
500
+
501
+ const outcomes: ImportJobRow[] = [];
502
+ const total = document.rows.length;
503
+ let validRows = 0;
504
+ for (let row = 1; row <= total; row += 1) {
505
+ const verdict = verdicts.get(row);
506
+ if (!verdict) validRows += 1;
507
+ outcomes.push(
508
+ this.#outcomeRow(job, row, verdict ? 'invalid' : 'valid', {
509
+ field: verdict?.field,
510
+ reason: verdict?.reason,
511
+ }),
512
+ );
513
+ }
514
+ await this.#repository.replaceJobRows(job.tenantId, job.id, outcomes);
515
+
516
+ const failed = total - validRows;
517
+ const completed = job.dryRun;
518
+ return (
519
+ (await this.#repository.advanceJob(job.tenantId, job.id, ['parsing'], {
520
+ status: completed ? 'completed' : 'validated',
521
+ totalRows: total,
522
+ validRows,
523
+ writtenRows: 0,
524
+ failedRows: failed,
525
+ failureCode: null,
526
+ completedAt: completed ? this.#now() : null,
527
+ })) ?? job
528
+ );
529
+ }
530
+
531
+ async #write(
532
+ job: ClaimedImportJob,
533
+ signal: AbortSignal | undefined,
534
+ ): Promise<ImportJob> {
535
+ const registered = this.#require(job.target);
536
+ const document = await this.#read(job);
537
+ const { rows } = this.#map(registered, job, document);
538
+ const valid = new Set(
539
+ await this.#repository.listValidRowNumbers(job.tenantId, job.id),
540
+ );
541
+ const writable = rows.filter((row) => valid.has(row.row));
542
+
543
+ const batch = this.#batchSize();
544
+ const principal = principalOf(job);
545
+ for (let start = 0; start < writable.length; start += batch) {
546
+ const slice = writable.slice(start, start + batch);
547
+ const outcomes = await this.#writeBatch(registered, {
548
+ tenantId: job.tenantId,
549
+ principal,
550
+ rows: slice,
551
+ mode: job.mode,
552
+ });
553
+ const byRow = new Map(outcomes.map((entry) => [entry.row, entry]));
554
+ const recorded: ImportJobRow[] = [];
555
+ for (const row of slice) {
556
+ /* A row the port said nothing about is recorded as failed: a dropped
557
+ row has to be visible in the job rather than counted as written. */
558
+ const outcome = byRow.get(row.row) ?? {
559
+ row: row.row,
560
+ outcome: 'failed' as const,
561
+ reason: 'PORT_SILENT',
562
+ };
563
+ recorded.push(
564
+ this.#outcomeRow(job, row.row, outcome.outcome, {
565
+ reason: outcome.reason,
566
+ recordRef: outcome.recordRef,
567
+ }),
568
+ );
569
+ }
570
+ await this.#repository.recordJobRows(job.tenantId, recorded);
571
+ this.#checkpoint(signal);
572
+ }
573
+
574
+ /* The counts are read back from the outcomes rather than counted in this
575
+ pass: a job reclaimed after a crash writes only the rows the earlier
576
+ pass had not reached, and an in-memory counter would report those alone.
577
+ A skipped row is neither written nor failed: the natural key already
578
+ held it, so a skip-existing repeat reports zero written. */
579
+ const counts = await this.#repository.countRowOutcomes(
580
+ job.tenantId,
581
+ job.id,
582
+ );
583
+ return (
584
+ (await this.#repository.advanceJob(job.tenantId, job.id, ['writing'], {
585
+ status: 'completed',
586
+ totalRows: job.totalRows,
587
+ validRows: job.validRows,
588
+ writtenRows: counts.created + counts.updated,
589
+ failedRows: counts.invalid + counts.failed,
590
+ failureCode: null,
591
+ completedAt: this.#now(),
592
+ })) ?? job
593
+ );
594
+ }
595
+
596
+ /**
597
+ * The claim fence, read once per batch. The runner renews the claim on its
598
+ * own timer so a job longer than the lease is not taken up a second time, and
599
+ * aborts this signal when a renewal matches nothing: the lease lapsed and
600
+ * another loop reclaimed the job. The stage stops there rather than writing
601
+ * on behalf of a claim it no longer has.
602
+ */
603
+ #checkpoint(signal: AbortSignal | undefined): void {
604
+ if (!signal?.aborted) return;
605
+ throw new ImportServiceError(
606
+ 'CLAIM_LOST',
607
+ 'Another process took this import job over while it was running.',
608
+ 409,
609
+ );
610
+ }
611
+
612
+ /**
613
+ * Rows repeating an earlier row's natural key, refused before batching. A
614
+ * port carries no state between calls, so a repeat in a later batch would
615
+ * otherwise meet its own earlier row as an existing record and be written
616
+ * twice or refused as somebody else's. Which two values are one key is the
617
+ * port's own decision: it folds them in `naturalKeyOf`, and without one they
618
+ * are compared exactly.
619
+ */
620
+ #duplicates(
621
+ registered: RegisteredImportPort,
622
+ rows: readonly ImportRow[],
623
+ ): readonly ImportValidation[] {
624
+ const port = registered.port;
625
+ const key = port.naturalKey;
626
+ const first = key[0];
627
+ if (first === undefined) return [];
628
+ const seen = new Set<string>();
629
+ const duplicates: ImportValidation[] = [];
630
+ for (const row of rows) {
631
+ let composed: string;
632
+ try {
633
+ composed = port.naturalKeyOf?.(row.values) ?? exactKey(key, row.values);
634
+ } catch {
635
+ /* The fold is another module's code: a throwing one costs this file
636
+ the port's own comparison, never the duplicate check itself. */
637
+ composed = exactKey(key, row.values);
638
+ }
639
+ if (seen.has(composed)) {
640
+ duplicates.push({
641
+ row: row.row,
642
+ verdict: 'invalid',
643
+ field: first,
644
+ reason: 'NATURAL_KEY_DUPLICATE',
645
+ });
646
+ continue;
647
+ }
648
+ seen.add(composed);
649
+ }
650
+ return duplicates;
651
+ }
652
+
653
+ /* A port is another module's code. It is isolated so a throwing port fails
654
+ its own batch's rows and never the platform's loop; the rows it was given
655
+ are recorded as failed with a stable reason. */
656
+ async #validate(
657
+ registered: RegisteredImportPort,
658
+ input: Parameters<RegisteredImportPort['port']['validate']>[0],
659
+ ): Promise<readonly ImportValidation[]> {
660
+ try {
661
+ return await registered.port.validate(input);
662
+ } catch {
663
+ return input.rows.map((row) => ({
664
+ row: row.row,
665
+ verdict: 'invalid' as const,
666
+ reason: 'PORT_FAILED',
667
+ }));
668
+ }
669
+ }
670
+
671
+ async #writeBatch(
672
+ registered: RegisteredImportPort,
673
+ input: Parameters<RegisteredImportPort['port']['write']>[0],
674
+ ): Promise<readonly ImportWriteOutcome[]> {
675
+ try {
676
+ return await registered.port.write(input);
677
+ } catch {
678
+ return input.rows.map((row) => ({
679
+ row: row.row,
680
+ outcome: 'failed' as const,
681
+ reason: 'PORT_FAILED',
682
+ }));
683
+ }
684
+ }
685
+
686
+ async #read(job: ImportJob): Promise<CsvDocument> {
687
+ const body = await this.#source.open(
688
+ job.tenantId,
689
+ job.documentRef,
690
+ job.documentId,
691
+ );
692
+ return readCsv(body, {
693
+ maxBytes: IMPORT_MAX_CSV_BYTES,
694
+ maxRows: this.#maxRows(),
695
+ });
696
+ }
697
+
698
+ /**
699
+ * Maps CSV cells onto port fields. Header positions are resolved once, so
700
+ * mapping is O(rows x fields) and never searches the header per cell.
701
+ */
702
+ #map(
703
+ registered: RegisteredImportPort,
704
+ job: ImportJob,
705
+ document: CsvDocument,
706
+ ): { rows: readonly ImportRow[]; invalid: readonly ImportValidation[] } {
707
+ const position = new Map(
708
+ document.header.map((name, index) => [name, index]),
709
+ );
710
+ const columns: { field: ImportField; index: number }[] = [];
711
+ for (const field of registered.port.fields) {
712
+ const header = job.columns[field.id];
713
+ if (header === undefined) {
714
+ if (field.required) {
715
+ throw new ImportServiceError(
716
+ 'MAPPING_COLUMN_MISSING',
717
+ `The file has no column for ${field.id}.`,
718
+ );
719
+ }
720
+ continue;
721
+ }
722
+ /* A mapped column the file does not carry fails the job whether the
723
+ field is required or not: skipping it would import the file the
724
+ requester mapped as if that column had been left out on purpose. */
725
+ const index = position.get(header);
726
+ if (index === undefined) {
727
+ throw new ImportServiceError(
728
+ 'MAPPING_COLUMN_MISSING',
729
+ `The file has no column ${header} for ${field.id}.`,
730
+ );
731
+ }
732
+ columns.push({ field, index });
733
+ }
734
+
735
+ const rows: ImportRow[] = [];
736
+ const invalid: ImportValidation[] = [];
737
+ for (const record of document.rows) {
738
+ /* A row whose cell count differs from the header is reported rather
739
+ than padded or truncated: silently dropping a trailing cell writes a
740
+ record the file did not describe. */
741
+ if (record.cells.length !== document.header.length) {
742
+ invalid.push({
743
+ row: record.row,
744
+ verdict: 'invalid',
745
+ reason: 'ROW_RAGGED',
746
+ });
747
+ continue;
748
+ }
749
+ const values: Record<string, string> = {};
750
+ let refusal: ImportValidation | null = null;
751
+ for (const { field, index } of columns) {
752
+ const cell = record.cells[index] ?? '';
753
+ if (cell === '') {
754
+ if (field.required) {
755
+ refusal = {
756
+ row: record.row,
757
+ verdict: 'invalid',
758
+ field: field.id,
759
+ reason: 'FIELD_REQUIRED',
760
+ };
761
+ break;
762
+ }
763
+ continue;
764
+ }
765
+ if (!shapeOf(cell, field.type)) {
766
+ refusal = {
767
+ row: record.row,
768
+ verdict: 'invalid',
769
+ field: field.id,
770
+ reason: 'FIELD_TYPE',
771
+ };
772
+ break;
773
+ }
774
+ values[field.id] = cell;
775
+ }
776
+ if (refusal) invalid.push(refusal);
777
+ else rows.push({ row: record.row, values });
778
+ }
779
+ return { rows, invalid };
780
+ }
781
+
782
+ #outcomeRow(
783
+ job: ImportJob,
784
+ rowNumber: number,
785
+ outcome: ImportRowOutcome,
786
+ detail: {
787
+ readonly field?: string | undefined;
788
+ readonly reason?: string | undefined;
789
+ readonly recordRef?: string | undefined;
790
+ },
791
+ ): ImportJobRow {
792
+ return {
793
+ id: this.#newId(),
794
+ tenantId: job.tenantId,
795
+ jobId: job.id,
796
+ rowNumber,
797
+ outcome,
798
+ field: truncate(detail.field, IMPORT_LIMITS.field),
799
+ reason: truncate(detail.reason, IMPORT_LIMITS.reason),
800
+ recordRef: truncate(detail.recordRef, IMPORT_LIMITS.recordRef),
801
+ };
802
+ }
803
+
804
+ #assertMapping(
805
+ registered: RegisteredImportPort,
806
+ columns: Readonly<Record<string, string>>,
807
+ ): void {
808
+ /* The job row and the saved mapping each bound the serialized object at
809
+ 8 KB, and the endpoint's per-entry bounds still allow a mapping past it.
810
+ It is refused here with a code the screen can read, rather than by the
811
+ column check once the job is half written. */
812
+ if (JSON.stringify(columns).length > IMPORT_LIMITS.json) {
813
+ throw new ImportServiceError(
814
+ 'MAPPING_TOO_LARGE',
815
+ 'The column mapping is larger than an import job can record.',
816
+ );
817
+ }
818
+ const fields = new Map(
819
+ registered.port.fields.map((field) => [field.id, field]),
820
+ );
821
+ /* One header feeds one field. Two fields reading one column would write
822
+ the same cell under two meanings, which is a mapping mistake rather
823
+ than a choice the file can answer. */
824
+ const headers = new Map<string, string>();
825
+ for (const [id, header] of Object.entries(columns)) {
826
+ if (!fields.has(id)) {
827
+ throw new ImportServiceError(
828
+ 'MAPPING_UNKNOWN_FIELD',
829
+ `The target has no field ${id}.`,
830
+ );
831
+ }
832
+ const taken = headers.get(header);
833
+ if (taken !== undefined) {
834
+ throw new ImportServiceError(
835
+ 'MAPPING_COLUMN_REUSED',
836
+ `The column ${header} is mapped to ${taken} and ${id}.`,
837
+ );
838
+ }
839
+ headers.set(header, id);
840
+ }
841
+ for (const field of registered.port.fields) {
842
+ if (field.required && !columns[field.id]) {
843
+ throw new ImportServiceError(
844
+ 'MAPPING_INCOMPLETE',
845
+ `The required field ${field.id} has no column.`,
846
+ );
847
+ }
848
+ }
849
+ }
850
+
851
+ #require(target: string): RegisteredImportPort {
852
+ const registered = this.#ports.find(target);
853
+ if (!registered) {
854
+ throw new ImportServiceError(
855
+ 'TARGET_UNKNOWN',
856
+ 'No module offers that import target.',
857
+ 404,
858
+ );
859
+ }
860
+ return registered;
861
+ }
862
+
863
+ async #requireJob(tenantId: string, id: string): Promise<ImportJob> {
864
+ const job = await this.#repository.findJob(tenantId, id);
865
+ if (!job) {
866
+ throw new ImportServiceError('JOB_NOT_FOUND', 'No such import job.', 404);
867
+ }
868
+ return job;
869
+ }
870
+ }
871
+
872
+ export type { ImportJobStatus };