@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
@@ -7,7 +7,11 @@ import {
7
7
  import { ServerRoute, type Context } from '@octanejs/app-core';
8
8
  import { readJsonObject } from '@flowdular/sdk/server';
9
9
  import { BUNDLED_MODULE_SCOPES, PLATFORM_SCOPES } from '../acl/scopes.ts';
10
- import type { SignInInput, SignUpInput } from '../domain/types.ts';
10
+ import type {
11
+ SignInInput,
12
+ SignInProviderOption,
13
+ SignUpInput,
14
+ } from '../domain/types.ts';
11
15
  import { AttemptLimiter } from '../api/attempt-limiter.ts';
12
16
  import { clientAddress } from '../api/client-address.ts';
13
17
  import {
@@ -18,8 +22,12 @@ import {
18
22
  import { assertSameOrigin } from '../api/origin.ts';
19
23
  import { sessionFromContext } from '../middleware/authentication.ts';
20
24
  import { AuthServiceError } from '../services/auth-service-error.ts';
25
+ import type { TenantProviderSignIn } from '../services/auth-service.ts';
26
+ import type { TenantSummary } from '../services/repository.ts';
21
27
  import { normalizeEmail } from '../services/validation.ts';
22
28
  import { createAuditRoutes } from './audit-endpoints.ts';
29
+ import { createMembershipRoutes } from './membership-endpoints.ts';
30
+ import { createIdentityProviderRoutes } from './provider-endpoints.ts';
23
31
  import {
24
32
  actorOf,
25
33
  errorResponse,
@@ -29,6 +37,8 @@ import {
29
37
  sessionPayload,
30
38
  stringField,
31
39
  } from './http.ts';
40
+ import { oidcFailure, readOidcJson, OIDC_REQUEST_TIMEOUT_MS } from './oidc.ts';
41
+ import { assertProviderHostAllowed } from './provider-host.ts';
32
42
  import { createRoleRoutes } from './roles-endpoints.ts';
33
43
  import type { AuthRuntime, OidcProvider } from './runtime.ts';
34
44
  import { sessionMutationDenial } from './session-security.ts';
@@ -41,17 +51,27 @@ import { createApiTokenRoutes } from './token-endpoints.ts';
41
51
  const emailAttempts = new AttemptLimiter();
42
52
  const addressAttempts = new AttemptLimiter(20, 5 * 60 * 1000);
43
53
  const availabilityAttempts = new AttemptLimiter(60, 60_000);
54
+ /* The sign-in screen resolves a workspace before it can offer its providers,
55
+ and it does so for anonymous callers, so the lookup is bounded per workspace
56
+ reference. One screen costs a handful of that workspace's allowance: the page
57
+ load, the typed workspace, and the authorization round trip of every provider
58
+ button that is pressed. */
59
+ const workspaceLookupAttempts = new AttemptLimiter(120, 60_000);
44
60
  const passwordResetEmailAttempts = new AttemptLimiter(3, 15 * 60 * 1000);
45
61
  const passwordResetAddressAttempts = new AttemptLimiter(20, 15 * 60 * 1000);
46
62
  const MFA_CHALLENGE_COOKIE = 'coreloom_mfa_challenge';
47
63
  const OIDC_STATE_COOKIE = 'coreloom_oidc_state';
48
- const OIDC_REQUEST_TIMEOUT_MS = 10_000;
49
- const OIDC_RESPONSE_MAX_BYTES = 64 * 1024;
50
64
 
51
65
  interface OidcState {
52
66
  readonly provider: string;
53
67
  readonly state: string;
54
68
  readonly verifier: string;
69
+ /* Bound into the same signed cookie as the state, so the ID token can only
70
+ be replayed into the browser transaction that asked for it. */
71
+ readonly nonce: string;
72
+ /* The workspace a tenant-owned provider signs into. A platform provider
73
+ names none, exactly as before. */
74
+ readonly workspace?: string;
55
75
  }
56
76
 
57
77
  function oidcStateCookie(value: string, secure: boolean, maxAge = 600): string {
@@ -103,7 +123,11 @@ function openOidcState(value: string, provider: OidcProvider): OidcState {
103
123
  typeof state.state !== 'string' ||
104
124
  !/^[A-Za-z0-9_-]{32}$/.test(state.state) ||
105
125
  typeof state.verifier !== 'string' ||
106
- !/^[A-Za-z0-9_-]{43}$/.test(state.verifier)
126
+ !/^[A-Za-z0-9_-]{43}$/.test(state.verifier) ||
127
+ typeof state.nonce !== 'string' ||
128
+ !/^[A-Za-z0-9_-]{32}$/.test(state.nonce) ||
129
+ (state.workspace !== undefined &&
130
+ (typeof state.workspace !== 'string' || state.workspace.length > 128))
107
131
  ) {
108
132
  throw new Error('invalid OIDC state');
109
133
  }
@@ -111,6 +135,8 @@ function openOidcState(value: string, provider: OidcProvider): OidcState {
111
135
  provider: state.provider,
112
136
  state: state.state,
113
137
  verifier: state.verifier,
138
+ nonce: state.nonce,
139
+ ...(state.workspace === undefined ? {} : { workspace: state.workspace }),
114
140
  };
115
141
  }
116
142
 
@@ -127,42 +153,6 @@ function responseWithCookies(
127
153
  });
128
154
  }
129
155
 
130
- function oidcFailure(): AuthServiceError {
131
- return new AuthServiceError(
132
- 'OIDC_AUTHENTICATION_FAILED',
133
- 'External sign-in could not be completed.',
134
- 401,
135
- );
136
- }
137
-
138
- async function readOidcJson(response: Response): Promise<unknown> {
139
- const declared = Number(response.headers.get('content-length') ?? 0);
140
- if (
141
- (Number.isFinite(declared) && declared > OIDC_RESPONSE_MAX_BYTES) ||
142
- !response.body
143
- )
144
- throw oidcFailure();
145
- const reader = response.body.getReader();
146
- const chunks: Uint8Array[] = [];
147
- let total = 0;
148
- try {
149
- for (;;) {
150
- const chunk = await reader.read();
151
- if (chunk.done) break;
152
- total += chunk.value.byteLength;
153
- if (total > OIDC_RESPONSE_MAX_BYTES) {
154
- await reader.cancel();
155
- throw oidcFailure();
156
- }
157
- chunks.push(chunk.value);
158
- }
159
- return JSON.parse(Buffer.concat(chunks, total).toString('utf8')) as unknown;
160
- } catch (error) {
161
- if (error instanceof AuthServiceError) throw error;
162
- throw oidcFailure();
163
- }
164
- }
165
-
166
156
  function mfaChallengeCookie(
167
157
  token: string,
168
158
  secure: boolean,
@@ -215,20 +205,138 @@ function safeEqual(left: string, right: string): boolean {
215
205
  }
216
206
 
217
207
  export function createAuthRoutes(runtime: AuthRuntime): readonly ServerRoute[] {
208
+ /* A workspace id or slug arrives from an anonymous browser, so the lookup is
209
+ bounded and throttled before it reaches the database. */
210
+ const workspaceOf = async (
211
+ context: Context,
212
+ reference: string,
213
+ ): Promise<TenantSummary | null> => {
214
+ if (reference.length === 0 || reference.length > 128) return null;
215
+ const address = clientAddress(context.request, runtime.trustProxy);
216
+ /* Without a trusted proxy there is no client address, and a user-agent is
217
+ whatever the caller sends, so keying on one would put every anonymous
218
+ visitor in the same bucket. The workspace being asked for is the thing
219
+ worth bounding: one reference can be enumerated only at this rate, and
220
+ asking for another workspace never spends its allowance. */
221
+ const bucket = reference.trim().toLowerCase();
222
+ if (
223
+ !workspaceLookupAttempts.consume(
224
+ address === null
225
+ ? `workspace:${bucket}`
226
+ : `workspace:${address}:${bucket}`,
227
+ )
228
+ ) {
229
+ throw new AuthServiceError('RATE_LIMITED', 'Try again later.', 429);
230
+ }
231
+ return (await runtime.service()).findTenant(reference);
232
+ };
233
+
234
+ /* Sign-in is routed by workspace, so the platform providers a deployment
235
+ offers everywhere and the workspace's own providers arrive as one list of
236
+ buttons, each carrying where it starts. */
237
+ const signInProviderOptions = async (
238
+ workspace: TenantSummary | null,
239
+ ): Promise<readonly SignInProviderOption[]> => {
240
+ const platform = runtime.settings.signInProviders
241
+ .filter((id) => runtime.oidcProviders.some((entry) => entry.id === id))
242
+ .map(
243
+ (id): SignInProviderOption => ({
244
+ key: id,
245
+ label: id,
246
+ scope: 'platform',
247
+ startPath: `/api/auth/oidc/${encodeURIComponent(id)}/start`,
248
+ }),
249
+ );
250
+ if (!workspace) return platform;
251
+ const owned = await (
252
+ await runtime.service()
253
+ ).identityProviders.listEnabled(workspace.tenantId);
254
+ return [
255
+ ...owned.map(
256
+ (provider): SignInProviderOption => ({
257
+ key: provider.key,
258
+ label: provider.label,
259
+ scope: 'tenant',
260
+ startPath: `/api/auth/oidc/${encodeURIComponent(workspace.slug)}/${encodeURIComponent(provider.key)}/start`,
261
+ }),
262
+ ),
263
+ ...platform,
264
+ ];
265
+ };
266
+
218
267
  const configuration = new ServerRoute({
219
268
  path: '/api/auth/config',
220
269
  methods: ['GET'],
221
- handler: () =>
222
- response({
223
- allowSignUp: runtime.settings.allowSignUp,
224
- emailConfirmation: runtime.settings.emailConfirmation,
225
- signInProviders: runtime.settings.signInProviders.filter((id) =>
226
- runtime.oidcProviders.some((provider) => provider.id === id),
227
- ),
228
- passwordMinLength: runtime.settings.passwordMinLength,
229
- }),
270
+ handler: async (context) => {
271
+ try {
272
+ const requested =
273
+ new URL(context.request.url).searchParams.get('workspace') ?? '';
274
+ /* An unknown workspace answers exactly as none at all: the password
275
+ form and the platform providers, and nothing that tells an
276
+ anonymous caller which workspace ids exist. */
277
+ const workspace = requested
278
+ ? await workspaceOf(context, requested)
279
+ : null;
280
+ return response({
281
+ allowSignUp: runtime.settings.allowSignUp,
282
+ emailConfirmation: runtime.settings.emailConfirmation,
283
+ signInProviders: runtime.settings.signInProviders.filter((id) =>
284
+ runtime.oidcProviders.some((provider) => provider.id === id),
285
+ ),
286
+ passwordMinLength: runtime.settings.passwordMinLength,
287
+ workspace: workspace
288
+ ? { slug: workspace.slug, name: workspace.name }
289
+ : null,
290
+ providers: await signInProviderOptions(workspace),
291
+ });
292
+ } catch (error) {
293
+ return errorResponse(error);
294
+ }
295
+ },
230
296
  });
231
297
 
298
+ const startAuthorization = (options: {
299
+ readonly provider: OidcProvider;
300
+ readonly callback: string;
301
+ readonly scopes: readonly string[];
302
+ readonly workspace?: string;
303
+ }): Response => {
304
+ const state = randomBytes(24).toString('base64url');
305
+ const nonce = randomBytes(24).toString('base64url');
306
+ const verifier = randomBytes(32).toString('base64url');
307
+ const challenge = createHash('sha256').update(verifier).digest('base64url');
308
+ const authorization = new URL(options.provider.authorizationEndpoint);
309
+ authorization.searchParams.set('response_type', 'code');
310
+ authorization.searchParams.set('client_id', options.provider.clientId);
311
+ authorization.searchParams.set('redirect_uri', options.callback);
312
+ authorization.searchParams.set('scope', options.scopes.join(' '));
313
+ authorization.searchParams.set('state', state);
314
+ authorization.searchParams.set('nonce', nonce);
315
+ authorization.searchParams.set('code_challenge', challenge);
316
+ authorization.searchParams.set('code_challenge_method', 'S256');
317
+ return new Response(null, {
318
+ status: 302,
319
+ headers: {
320
+ location: authorization.toString(),
321
+ 'set-cookie': oidcStateCookie(
322
+ sealOidcState(
323
+ {
324
+ provider: options.provider.id,
325
+ state,
326
+ verifier,
327
+ nonce,
328
+ ...(options.workspace === undefined
329
+ ? {}
330
+ : { workspace: options.workspace }),
331
+ },
332
+ options.provider,
333
+ ),
334
+ runtime.cookie.secure,
335
+ ),
336
+ },
337
+ });
338
+ };
339
+
232
340
  const oidcStart = new ServerRoute({
233
341
  path: '/api/auth/oidc/:provider/start',
234
342
  methods: ['GET'],
@@ -247,32 +355,10 @@ export function createAuthRoutes(runtime: AuthRuntime): readonly ServerRoute[] {
247
355
  'This sign-in provider is not configured.',
248
356
  404,
249
357
  );
250
- const state = randomBytes(24).toString('base64url');
251
- const verifier = randomBytes(32).toString('base64url');
252
- const challenge = createHash('sha256')
253
- .update(verifier)
254
- .digest('base64url');
255
- const callback = `${runtime.publicBaseUrl.replace(/\/$/, '')}/api/auth/oidc/${provider.id}/callback`;
256
- const authorization = new URL(provider.authorizationEndpoint);
257
- authorization.searchParams.set('response_type', 'code');
258
- authorization.searchParams.set('client_id', provider.clientId);
259
- authorization.searchParams.set('redirect_uri', callback);
260
- authorization.searchParams.set('scope', 'openid email profile');
261
- authorization.searchParams.set('state', state);
262
- authorization.searchParams.set('code_challenge', challenge);
263
- authorization.searchParams.set('code_challenge_method', 'S256');
264
- return new Response(null, {
265
- status: 302,
266
- headers: {
267
- location: authorization.toString(),
268
- 'set-cookie': oidcStateCookie(
269
- sealOidcState(
270
- { provider: provider.id, state, verifier },
271
- provider,
272
- ),
273
- runtime.cookie.secure,
274
- ),
275
- },
358
+ return startAuthorization({
359
+ provider,
360
+ callback: `${runtime.publicBaseUrl.replace(/\/$/, '')}/api/auth/oidc/${provider.id}/callback`,
361
+ scopes: ['openid', 'email', 'profile'],
276
362
  });
277
363
  } catch (error) {
278
364
  return errorResponse(error);
@@ -280,104 +366,259 @@ export function createAuthRoutes(runtime: AuthRuntime): readonly ServerRoute[] {
280
366
  },
281
367
  });
282
368
 
283
- const oidcCallback = new ServerRoute({
284
- path: '/api/auth/oidc/:provider/callback',
369
+ /**
370
+ * The workspace-routed authorization request. The key names a provider the
371
+ * workspace owns and offers; the signed state binds both, so a callback that
372
+ * arrives for another workspace or another provider is refused before
373
+ * anything is exchanged.
374
+ */
375
+ const workspaceOidcStart = new ServerRoute({
376
+ path: '/api/auth/oidc/:workspace/:key/start',
285
377
  methods: ['GET'],
286
378
  handler: async (context) => {
287
- const expiredState = oidcStateCookie('', runtime.cookie.secure, 0);
288
379
  try {
289
- const provider = runtime.oidcProviders.find(
290
- (entry) => entry.id === context.params.provider,
380
+ const workspace = await workspaceOf(
381
+ context,
382
+ context.params.workspace ?? '',
291
383
  );
292
- const callback = runtime.publicBaseUrl
293
- ? `${runtime.publicBaseUrl.replace(/\/$/, '')}/api/auth/oidc/${context.params.provider}/callback`
384
+ const resolved = workspace
385
+ ? await (
386
+ await runtime.service()
387
+ ).identityProviders.resolveSignIn(
388
+ workspace.tenantId,
389
+ context.params.key ?? '',
390
+ )
294
391
  : null;
295
- const url = new URL(context.request.url);
296
- const encoded = readCookie(context.request, OIDC_STATE_COOKIE);
297
- const code = url.searchParams.get('code');
298
- const submittedState = url.searchParams.get('state') ?? '';
299
- if (
300
- !provider ||
301
- !runtime.settings.signInProviders.includes(provider.id) ||
302
- !callback ||
303
- !encoded ||
304
- url.searchParams.get('error') ||
305
- !code ||
306
- code.length > 4_096 ||
307
- submittedState.length > 128
308
- )
309
- throw oidcFailure();
310
- let state: OidcState;
311
- try {
312
- state = openOidcState(encoded, provider);
313
- } catch {
314
- throw oidcFailure();
392
+ if (!resolved || !runtime.publicBaseUrl) {
393
+ throw new AuthServiceError(
394
+ 'OIDC_NOT_CONFIGURED',
395
+ 'This sign-in provider is not configured.',
396
+ 404,
397
+ );
315
398
  }
316
- if (!safeEqual(state.state, submittedState)) throw oidcFailure();
317
- const tokenResponse = await fetch(provider.tokenEndpoint, {
318
- method: 'POST',
319
- headers: {
320
- 'content-type': 'application/x-www-form-urlencoded',
321
- accept: 'application/json',
322
- },
323
- body: new URLSearchParams({
324
- grant_type: 'authorization_code',
325
- code,
326
- redirect_uri: callback,
327
- client_id: provider.clientId,
328
- client_secret: provider.clientSecret,
329
- code_verifier: state.verifier,
330
- }),
331
- signal: AbortSignal.timeout(OIDC_REQUEST_TIMEOUT_MS),
399
+ return startAuthorization({
400
+ provider: resolved.oidc,
401
+ callback: `${runtime.publicBaseUrl.replace(/\/$/, '')}/api/auth/oidc/${encodeURIComponent(context.params.workspace!)}/${encodeURIComponent(resolved.key)}/callback`,
402
+ scopes: resolved.scopes,
403
+ workspace: resolved.tenantId,
332
404
  });
333
- if (!tokenResponse.ok) throw oidcFailure();
334
- const tokenBody = (await readOidcJson(tokenResponse)) as {
335
- access_token?: unknown;
336
- };
337
- if (
338
- typeof tokenBody.access_token !== 'string' ||
339
- tokenBody.access_token.length > 8192
340
- )
341
- throw oidcFailure();
342
- const profileResponse = await fetch(provider.userInfoEndpoint, {
343
- headers: {
344
- authorization: `Bearer ${tokenBody.access_token}`,
345
- accept: 'application/json',
346
- },
347
- signal: AbortSignal.timeout(OIDC_REQUEST_TIMEOUT_MS),
348
- });
349
- if (!profileResponse.ok) throw oidcFailure();
350
- const profile = (await readOidcJson(profileResponse)) as {
351
- email?: unknown;
352
- email_verified?: unknown;
353
- };
354
- if (
355
- typeof profile.email !== 'string' ||
356
- profile.email.length > 254 ||
357
- profile.email_verified !== true
358
- )
405
+ } catch (error) {
406
+ return errorResponse(error);
407
+ }
408
+ },
409
+ });
410
+
411
+ /* Everything after the browser comes back: the state check, the exchange,
412
+ the verified token and the session. The platform route and the
413
+ workspace-routed one differ only in what they resolved beforehand. */
414
+ const completeAuthorization = async (
415
+ context: Context,
416
+ options: {
417
+ readonly provider: OidcProvider;
418
+ readonly callback: string | null;
419
+ /** The provider name the binding is stored under. */
420
+ readonly binding: string;
421
+ readonly workspace: TenantProviderSignIn | null;
422
+ },
423
+ ): Promise<Response> => {
424
+ const expiredState = oidcStateCookie('', runtime.cookie.secure, 0);
425
+ try {
426
+ const provider = options.provider;
427
+ const callback = options.callback;
428
+ const url = new URL(context.request.url);
429
+ const encoded = readCookie(context.request, OIDC_STATE_COOKIE);
430
+ const code = url.searchParams.get('code');
431
+ const submittedState = url.searchParams.get('state') ?? '';
432
+ if (
433
+ !callback ||
434
+ !encoded ||
435
+ url.searchParams.get('error') ||
436
+ !code ||
437
+ code.length > 4_096 ||
438
+ submittedState.length > 128
439
+ )
440
+ throw oidcFailure();
441
+ let state: OidcState;
442
+ try {
443
+ state = openOidcState(encoded, provider);
444
+ } catch {
445
+ throw oidcFailure();
446
+ }
447
+ if (!safeEqual(state.state, submittedState)) throw oidcFailure();
448
+ /* The transaction names the workspace it started in. A state from
449
+ another workspace ends here, before the code is exchanged. */
450
+ if ((state.workspace ?? null) !== (options.workspace?.tenantId ?? null))
451
+ throw oidcFailure();
452
+ /* The stored endpoints are guarded again here: a row written before the
453
+ guard existed, or a deployment provider configured by hand, must not
454
+ turn a sign-in into a request at the deployment's own network. An
455
+ anonymous caller learns nothing beyond the generic failure. */
456
+ try {
457
+ assertProviderHostAllowed(
458
+ provider.tokenEndpoint,
459
+ runtime.providerHosts,
460
+ 'tokenEndpoint',
461
+ );
462
+ assertProviderHostAllowed(
463
+ provider.userInfoEndpoint,
464
+ runtime.providerHosts,
465
+ 'userInfoEndpoint',
466
+ );
467
+ } catch {
468
+ throw oidcFailure();
469
+ }
470
+ const tokenResponse = await fetch(provider.tokenEndpoint, {
471
+ method: 'POST',
472
+ headers: {
473
+ 'content-type': 'application/x-www-form-urlencoded',
474
+ accept: 'application/json',
475
+ },
476
+ body: new URLSearchParams({
477
+ grant_type: 'authorization_code',
478
+ code,
479
+ redirect_uri: callback,
480
+ client_id: provider.clientId,
481
+ client_secret: provider.clientSecret,
482
+ code_verifier: state.verifier,
483
+ }),
484
+ signal: AbortSignal.timeout(OIDC_REQUEST_TIMEOUT_MS),
485
+ });
486
+ if (!tokenResponse.ok) throw oidcFailure();
487
+ const tokenBody = (await readOidcJson(tokenResponse)) as {
488
+ access_token?: unknown;
489
+ id_token?: unknown;
490
+ };
491
+ if (
492
+ typeof tokenBody.access_token !== 'string' ||
493
+ tokenBody.access_token.length > 8192 ||
494
+ typeof tokenBody.id_token !== 'string'
495
+ )
496
+ throw oidcFailure();
497
+ /* The ID token is what this server trusts. The access token only
498
+ fetches the profile, and the profile is accepted only for the
499
+ subject the signed token named. */
500
+ const identity = await runtime.oidcVerifier.verifyIdToken(
501
+ provider,
502
+ tokenBody.id_token,
503
+ state.nonce,
504
+ );
505
+ const profileResponse = await fetch(provider.userInfoEndpoint, {
506
+ headers: {
507
+ authorization: `Bearer ${tokenBody.access_token}`,
508
+ accept: 'application/json',
509
+ },
510
+ signal: AbortSignal.timeout(OIDC_REQUEST_TIMEOUT_MS),
511
+ });
512
+ if (!profileResponse.ok) throw oidcFailure();
513
+ const profile = (await readOidcJson(profileResponse)) as {
514
+ sub?: unknown;
515
+ email?: unknown;
516
+ email_verified?: unknown;
517
+ };
518
+ if (
519
+ typeof profile.email !== 'string' ||
520
+ profile.email.length > 254 ||
521
+ profile.email_verified !== true ||
522
+ (profile.sub !== undefined &&
523
+ (typeof profile.sub !== 'string' ||
524
+ !safeEqual(profile.sub, identity.subject)))
525
+ )
526
+ throw oidcFailure();
527
+ /* How the account lookup ended is not something an external caller
528
+ may tell apart from a token this server refused. */
529
+ const issued = await (
530
+ await runtime.service()
531
+ )
532
+ .signInExternalIdentity({
533
+ provider: options.binding,
534
+ subject: identity.subject,
535
+ email: profile.email,
536
+ ...(options.workspace ? { workspace: options.workspace } : {}),
537
+ })
538
+ .catch(() => {
359
539
  throw oidcFailure();
360
- const issued = await (
361
- await runtime.service()
362
- ).signInVerifiedExternalEmail(profile.email);
363
- if ('mfaRequired' in issued) {
364
- const headers = new Headers({ location: '/auth/mfa?mfa=oidc' });
365
- headers.append(
366
- 'set-cookie',
367
- mfaChallengeCookie(issued.token, runtime.cookie.secure),
368
- );
369
- headers.append('set-cookie', expiredState);
370
- return new Response(null, { status: 302, headers });
371
- }
372
- const headers = new Headers({
373
- location: runtime.applicationPath ?? '/app',
374
540
  });
541
+ if ('mfaRequired' in issued) {
542
+ const headers = new Headers({ location: '/auth/mfa?mfa=oidc' });
375
543
  headers.append(
376
544
  'set-cookie',
377
- sessionCookie(issued.token, runtime.cookie),
545
+ mfaChallengeCookie(issued.token, runtime.cookie.secure),
378
546
  );
379
547
  headers.append('set-cookie', expiredState);
380
548
  return new Response(null, { status: 302, headers });
549
+ }
550
+ const headers = new Headers({
551
+ location: runtime.applicationPath ?? '/app',
552
+ });
553
+ headers.append('set-cookie', sessionCookie(issued.token, runtime.cookie));
554
+ headers.append('set-cookie', expiredState);
555
+ return new Response(null, { status: 302, headers });
556
+ } catch (error) {
557
+ return responseWithCookies(
558
+ errorResponse(
559
+ error instanceof AuthServiceError ? error : oidcFailure(),
560
+ ),
561
+ expiredState,
562
+ );
563
+ }
564
+ };
565
+
566
+ const oidcCallback = new ServerRoute({
567
+ path: '/api/auth/oidc/:provider/callback',
568
+ methods: ['GET'],
569
+ handler: async (context) => {
570
+ const provider = runtime.oidcProviders.find(
571
+ (entry) => entry.id === context.params.provider,
572
+ );
573
+ if (
574
+ !provider ||
575
+ !runtime.settings.signInProviders.includes(provider.id) ||
576
+ !runtime.publicBaseUrl
577
+ ) {
578
+ return responseWithCookies(
579
+ errorResponse(oidcFailure()),
580
+ oidcStateCookie('', runtime.cookie.secure, 0),
581
+ );
582
+ }
583
+ return completeAuthorization(context, {
584
+ provider,
585
+ callback: `${runtime.publicBaseUrl.replace(/\/$/, '')}/api/auth/oidc/${context.params.provider}/callback`,
586
+ binding: provider.id,
587
+ workspace: null,
588
+ });
589
+ },
590
+ });
591
+
592
+ const workspaceOidcCallback = new ServerRoute({
593
+ path: '/api/auth/oidc/:workspace/:key/callback',
594
+ methods: ['GET'],
595
+ handler: async (context) => {
596
+ const expiredState = oidcStateCookie('', runtime.cookie.secure, 0);
597
+ try {
598
+ const workspace = await workspaceOf(
599
+ context,
600
+ context.params.workspace ?? '',
601
+ );
602
+ const resolved = workspace
603
+ ? await (
604
+ await runtime.service()
605
+ ).identityProviders.resolveSignIn(
606
+ workspace.tenantId,
607
+ context.params.key ?? '',
608
+ )
609
+ : null;
610
+ if (!resolved || !runtime.publicBaseUrl) throw oidcFailure();
611
+ return await completeAuthorization(context, {
612
+ provider: resolved.oidc,
613
+ callback: `${runtime.publicBaseUrl.replace(/\/$/, '')}/api/auth/oidc/${encodeURIComponent(context.params.workspace!)}/${encodeURIComponent(resolved.key)}/callback`,
614
+ binding: resolved.key,
615
+ workspace: {
616
+ tenantId: resolved.tenantId,
617
+ jitEnabled: resolved.jitEnabled,
618
+ allowedDomains: resolved.allowedDomains,
619
+ jitRole: resolved.jitRole,
620
+ },
621
+ });
381
622
  } catch (error) {
382
623
  return responseWithCookies(
383
624
  errorResponse(
@@ -424,10 +665,10 @@ export function createAuthRoutes(runtime: AuthRuntime): readonly ServerRoute[] {
424
665
  /* The shell polls this route. The authentication middleware already
425
666
  resolved the session for this request, so reading it again would be a
426
667
  second round trip for the same answer. */
427
- handler: (context) => {
668
+ handler: async (context) => {
428
669
  const current = sessionFromContext(context);
429
670
  return current
430
- ? response(sessionPayload(current, runtime))
671
+ ? response(await sessionPayload(current, runtime))
431
672
  : response(
432
673
  {
433
674
  error: { code: 'UNAUTHENTICATED', message: 'No active session.' },
@@ -461,7 +702,7 @@ export function createAuthRoutes(runtime: AuthRuntime): readonly ServerRoute[] {
461
702
  const attempt = throttle(context, runtime, input.email);
462
703
  const issued = await (await runtime.service()).signUp(input);
463
704
  attempt.clear();
464
- return response(sessionPayload(issued, runtime), 201, {
705
+ return response(await sessionPayload(issued, runtime), 201, {
465
706
  'set-cookie': sessionCookie(issued.token, runtime.cookie),
466
707
  });
467
708
  } catch (error) {
@@ -477,9 +718,16 @@ export function createAuthRoutes(runtime: AuthRuntime): readonly ServerRoute[] {
477
718
  try {
478
719
  assertSameOrigin(context);
479
720
  const body = await readJsonObject(context.request);
721
+ /* The screen sends the workspace it is on. An empty field is the
722
+ same request the screen made before workspaces were routed. */
723
+ const workspace =
724
+ body.workspace === undefined
725
+ ? ''
726
+ : stringField(body, 'workspace').trim();
480
727
  const input: SignInInput = {
481
728
  email: stringField(body, 'email'),
482
729
  password: stringField(body, 'password'),
730
+ ...(workspace === '' ? {} : { workspace }),
483
731
  };
484
732
  const attempt = throttle(context, runtime, input.email);
485
733
  const issued = await (
@@ -493,7 +741,7 @@ export function createAuthRoutes(runtime: AuthRuntime): readonly ServerRoute[] {
493
741
  expiresAt: issued.expiresAt,
494
742
  });
495
743
  }
496
- return response(sessionPayload(issued, runtime), 200, {
744
+ return response(await sessionPayload(issued, runtime), 200, {
497
745
  'set-cookie': sessionCookie(issued.token, runtime.cookie),
498
746
  });
499
747
  } catch (error) {
@@ -586,7 +834,7 @@ export function createAuthRoutes(runtime: AuthRuntime): readonly ServerRoute[] {
586
834
  'set-cookie',
587
835
  mfaChallengeCookie('', runtime.cookie.secure, 0),
588
836
  );
589
- return response(sessionPayload(issued, runtime), 200, headers);
837
+ return response(await sessionPayload(issued, runtime), 200, headers);
590
838
  } catch (error) {
591
839
  return responseWithCookies(
592
840
  errorResponse(error),
@@ -602,11 +850,11 @@ export function createAuthRoutes(runtime: AuthRuntime): readonly ServerRoute[] {
602
850
  handler: async (context) => {
603
851
  try {
604
852
  const session = requireSession(context);
605
- return response(
606
- await (
607
- await runtime.service()
608
- ).mfaStatus(session.principal.accountId),
609
- );
853
+ const [status, tenant] = await Promise.all([
854
+ (await runtime.service()).mfaStatus(session.principal.accountId),
855
+ runtime.tenantSettings(session.principal.tenantId),
856
+ ]);
857
+ return response({ ...status, required: tenant.requireMfa });
610
858
  } catch (error) {
611
859
  return errorResponse(error);
612
860
  }
@@ -663,6 +911,37 @@ export function createAuthRoutes(runtime: AuthRuntime): readonly ServerRoute[] {
663
911
  },
664
912
  });
665
913
 
914
+ /* Administrative clearing of a lost factor. It lives beside the enrolment
915
+ routes because the factor is auth.core's, and it answers to the member
916
+ management scope because that is who administers members. */
917
+ const mfaReset = new ServerRoute({
918
+ path: '/api/auth/mfa/reset',
919
+ methods: ['POST'],
920
+ handler: async (context) => {
921
+ const denial = sessionMutationDenial(context, runtime);
922
+ if (denial) return denial;
923
+ try {
924
+ const session = requireSession(context);
925
+ requireScope(session, BUNDLED_MODULE_SCOPES.usersManage);
926
+ const body = await readJsonObject(context.request);
927
+ const accountId = stringField(body, 'accountId');
928
+ if (accountId.length === 0 || accountId.length > 128) {
929
+ throw new AuthServiceError(
930
+ 'INVALID_INPUT',
931
+ 'accountId is invalid.',
932
+ 400,
933
+ );
934
+ }
935
+ await (
936
+ await runtime.service()
937
+ ).resetMemberMfa(actorOf(session), accountId);
938
+ return response({ reset: true });
939
+ } catch (error) {
940
+ return errorResponse(error);
941
+ }
942
+ },
943
+ });
944
+
666
945
  const createInvitation = new ServerRoute({
667
946
  path: '/api/auth/invitations',
668
947
  methods: ['POST'],
@@ -793,7 +1072,7 @@ export function createAuthRoutes(runtime: AuthRuntime): readonly ServerRoute[] {
793
1072
  );
794
1073
  }
795
1074
  const issued = await service.switchTenant(token, tenantId);
796
- return response(sessionPayload(issued, runtime), 200, {
1075
+ return response(await sessionPayload(issued, runtime), 200, {
797
1076
  'set-cookie': sessionCookie(issued.token, runtime.cookie),
798
1077
  });
799
1078
  } catch (error) {
@@ -867,10 +1146,12 @@ export function createAuthRoutes(runtime: AuthRuntime): readonly ServerRoute[] {
867
1146
  },
868
1147
  });
869
1148
 
870
- return [
1149
+ const routes = [
871
1150
  configuration,
872
1151
  oidcStart,
873
1152
  oidcCallback,
1153
+ workspaceOidcStart,
1154
+ workspaceOidcCallback,
874
1155
  changePassword,
875
1156
  workspaceAvailability,
876
1157
  session,
@@ -882,6 +1163,7 @@ export function createAuthRoutes(runtime: AuthRuntime): readonly ServerRoute[] {
882
1163
  mfaStatus,
883
1164
  mfaEnroll,
884
1165
  mfaConfirm,
1166
+ mfaReset,
885
1167
  createInvitation,
886
1168
  acceptInvitation,
887
1169
  switchTenant,
@@ -891,5 +1173,19 @@ export function createAuthRoutes(runtime: AuthRuntime): readonly ServerRoute[] {
891
1173
  ...createRoleRoutes(runtime),
892
1174
  ...createAuditRoutes(runtime),
893
1175
  ...createSessionRoutes(runtime),
1176
+ ...createIdentityProviderRoutes(runtime),
1177
+ ...createMembershipRoutes(runtime),
894
1178
  ];
1179
+ /* The served chain resolves the service, and with it the platform settings
1180
+ these handlers read, before any route runs. A handler invoked on its own,
1181
+ as another module's test harness does, resolves it here so it answers
1182
+ exactly as a served one. */
1183
+ for (const route of routes) {
1184
+ const handler = route.handler;
1185
+ route.handler = async (context) => {
1186
+ await runtime.service();
1187
+ return handler(context);
1188
+ };
1189
+ }
1190
+ return routes;
895
1191
  }