@headless-lms/core 0.2.0 → 0.3.0

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 (225) hide show
  1. package/dist/assets/events.d.ts +39 -21
  2. package/dist/assets/events.js +1 -1
  3. package/dist/assets/events.js.map +1 -1
  4. package/dist/assets/file-urls.d.ts +20 -0
  5. package/dist/assets/file-urls.js +25 -0
  6. package/dist/assets/file-urls.js.map +1 -0
  7. package/dist/assets/index.d.ts +5 -4
  8. package/dist/assets/index.js +3 -2
  9. package/dist/assets/model.d.ts +2 -2
  10. package/dist/assets/ports.d.ts +45 -15
  11. package/dist/assets/service.d.ts +39 -7
  12. package/dist/assets/service.js +291 -38
  13. package/dist/assets/service.js.map +1 -1
  14. package/dist/automations/actions.d.ts +13 -24
  15. package/dist/automations/actions.js +168 -43
  16. package/dist/automations/actions.js.map +1 -1
  17. package/dist/automations/catalog.d.ts +2 -1
  18. package/dist/automations/catalog.js +229 -13
  19. package/dist/automations/catalog.js.map +1 -1
  20. package/dist/automations/community-derivations.d.ts +14 -0
  21. package/dist/automations/community-derivations.js +439 -0
  22. package/dist/automations/community-derivations.js.map +1 -0
  23. package/dist/automations/community-mail.d.ts +112 -0
  24. package/dist/automations/community-mail.js +90 -0
  25. package/dist/automations/community-mail.js.map +1 -0
  26. package/dist/automations/community-notifications.d.ts +16 -0
  27. package/dist/automations/community-notifications.js +84 -0
  28. package/dist/automations/community-notifications.js.map +1 -0
  29. package/dist/automations/events.d.ts +28 -0
  30. package/dist/automations/index.d.ts +4 -2
  31. package/dist/automations/index.js +3 -2
  32. package/dist/automations/model.d.ts +10 -3
  33. package/dist/automations/model.js +15 -2
  34. package/dist/automations/model.js.map +1 -1
  35. package/dist/automations/ports.d.ts +5 -1
  36. package/dist/automations/schedule.d.ts +6 -0
  37. package/dist/automations/schedule.js +41 -0
  38. package/dist/automations/schedule.js.map +1 -0
  39. package/dist/automations/seeds.d.ts +17 -0
  40. package/dist/automations/seeds.js +235 -0
  41. package/dist/automations/seeds.js.map +1 -0
  42. package/dist/automations/service.d.ts +22 -3
  43. package/dist/automations/service.js +306 -43
  44. package/dist/automations/service.js.map +1 -1
  45. package/dist/content/events.d.ts +631 -19
  46. package/dist/content/events.js +44 -1
  47. package/dist/content/events.js.map +1 -1
  48. package/dist/content/index.d.ts +4 -4
  49. package/dist/content/model.d.ts +2 -2
  50. package/dist/content/ports.d.ts +71 -18
  51. package/dist/content/service.d.ts +57 -18
  52. package/dist/content/service.js +502 -23
  53. package/dist/content/service.js.map +1 -1
  54. package/dist/content/types.d.ts +2 -2
  55. package/dist/discussion/authors.d.ts +10 -0
  56. package/dist/discussion/authors.js +23 -0
  57. package/dist/discussion/authors.js.map +1 -0
  58. package/dist/discussion/chats.d.ts +104 -0
  59. package/dist/discussion/chats.js +798 -0
  60. package/dist/discussion/chats.js.map +1 -0
  61. package/dist/discussion/events.d.ts +619 -56
  62. package/dist/discussion/events.js +106 -3
  63. package/dist/discussion/events.js.map +1 -1
  64. package/dist/discussion/index.d.ts +7 -3
  65. package/dist/discussion/index.js +4 -1
  66. package/dist/discussion/ports.d.ts +288 -27
  67. package/dist/discussion/ports.js +6 -1
  68. package/dist/discussion/ports.js.map +1 -0
  69. package/dist/discussion/posts.d.ts +103 -0
  70. package/dist/discussion/posts.js +723 -0
  71. package/dist/discussion/posts.js.map +1 -0
  72. package/dist/discussion/service.d.ts +32 -10
  73. package/dist/discussion/service.js +293 -78
  74. package/dist/discussion/service.js.map +1 -1
  75. package/dist/entitlements/events.d.ts +178 -11
  76. package/dist/entitlements/events.js +28 -1
  77. package/dist/entitlements/events.js.map +1 -1
  78. package/dist/entitlements/index.d.ts +5 -4
  79. package/dist/entitlements/index.js +2 -1
  80. package/dist/entitlements/model.d.ts +3 -2
  81. package/dist/entitlements/ports.d.ts +124 -11
  82. package/dist/entitlements/rules.d.ts +12 -0
  83. package/dist/entitlements/rules.js +17 -0
  84. package/dist/entitlements/rules.js.map +1 -0
  85. package/dist/entitlements/service.d.ts +54 -3
  86. package/dist/entitlements/service.js +472 -2
  87. package/dist/entitlements/service.js.map +1 -1
  88. package/dist/identity/access.d.ts +6 -0
  89. package/dist/identity/access.js +7 -0
  90. package/dist/identity/access.js.map +1 -0
  91. package/dist/identity/index.d.ts +6 -4
  92. package/dist/identity/index.js +3 -1
  93. package/dist/identity/model.d.ts +2 -1
  94. package/dist/identity/notifications.d.ts +27 -0
  95. package/dist/identity/notifications.js +101 -0
  96. package/dist/identity/notifications.js.map +1 -0
  97. package/dist/identity/ports.d.ts +73 -3
  98. package/dist/identity/service.d.ts +14 -3
  99. package/dist/identity/service.js +62 -5
  100. package/dist/identity/service.js.map +1 -1
  101. package/dist/integrations/model.js +1 -1
  102. package/dist/integrations/model.js.map +1 -1
  103. package/dist/integrations/service.js +2 -2
  104. package/dist/integrations/service.js.map +1 -1
  105. package/dist/organizations/access-scopes.d.ts +19 -0
  106. package/dist/organizations/access-scopes.js +89 -0
  107. package/dist/organizations/access-scopes.js.map +1 -0
  108. package/dist/organizations/events.d.ts +74 -32
  109. package/dist/organizations/events.js +6 -0
  110. package/dist/organizations/events.js.map +1 -1
  111. package/dist/organizations/index.d.ts +7 -6
  112. package/dist/organizations/index.js +4 -3
  113. package/dist/organizations/members.d.ts +8 -5
  114. package/dist/organizations/members.js.map +1 -1
  115. package/dist/organizations/ports.d.ts +14 -11
  116. package/dist/organizations/roles.d.ts +6 -10
  117. package/dist/organizations/roles.js +19 -7
  118. package/dist/organizations/roles.js.map +1 -1
  119. package/dist/organizations/service.d.ts +20 -11
  120. package/dist/organizations/service.js +157 -47
  121. package/dist/organizations/service.js.map +1 -1
  122. package/dist/organizations/types.d.ts +1 -10
  123. package/dist/progress/index.d.ts +2 -2
  124. package/dist/progress/ports.d.ts +6 -1
  125. package/dist/progress/service.d.ts +3 -1
  126. package/dist/progress/service.js +6 -2
  127. package/dist/progress/service.js.map +1 -1
  128. package/dist/reporting/admin/index.d.ts +4 -0
  129. package/dist/reporting/admin/index.js +2 -0
  130. package/dist/reporting/admin/model.d.ts +108 -0
  131. package/dist/reporting/admin/ports.d.ts +27 -0
  132. package/dist/reporting/admin/service.d.ts +22 -0
  133. package/dist/reporting/admin/service.js +38 -0
  134. package/dist/reporting/admin/service.js.map +1 -0
  135. package/dist/reporting/member/index.d.ts +5 -0
  136. package/dist/reporting/member/index.js +2 -0
  137. package/dist/reporting/member/model.d.ts +124 -0
  138. package/dist/reporting/member/ports.d.ts +45 -0
  139. package/dist/reporting/member/service.d.ts +73 -0
  140. package/dist/reporting/member/service.js +286 -0
  141. package/dist/reporting/member/service.js.map +1 -0
  142. package/dist/shared/actor.d.ts +9 -0
  143. package/dist/shared/errors.d.ts +7 -1
  144. package/dist/shared/errors.js +10 -1
  145. package/dist/shared/errors.js.map +1 -1
  146. package/dist/shared/id.d.ts +11 -0
  147. package/dist/shared/id.js +12 -1
  148. package/dist/shared/id.js.map +1 -1
  149. package/dist/shared/mailer.d.ts +4 -1
  150. package/dist/shared/mailer.js.map +1 -1
  151. package/dist/shared/network.d.ts +10 -0
  152. package/dist/shared/network.js +211 -0
  153. package/dist/shared/network.js.map +1 -0
  154. package/dist/types/assets.d.ts +2 -2
  155. package/dist/types/automations.d.ts +10 -2
  156. package/dist/types/content.d.ts +2 -2
  157. package/dist/types/discussion.d.ts +11 -3
  158. package/dist/types/email-templates.d.ts +121 -0
  159. package/dist/types/entitlements.d.ts +2 -2
  160. package/dist/types/identity.d.ts +48 -2
  161. package/dist/types/index.d.ts +9 -9
  162. package/dist/types/ports.d.ts +6 -0
  163. package/dist/types/schemas/assets.d.ts +65 -37
  164. package/dist/types/schemas/assets.js +17 -12
  165. package/dist/types/schemas/assets.js.map +1 -1
  166. package/dist/types/schemas/automations.d.ts +18 -1
  167. package/dist/types/schemas/automations.js +15 -6
  168. package/dist/types/schemas/automations.js.map +1 -1
  169. package/dist/types/schemas/content.d.ts +335 -3
  170. package/dist/types/schemas/content.js +139 -3
  171. package/dist/types/schemas/content.js.map +1 -1
  172. package/dist/types/schemas/discussion.d.ts +370 -3
  173. package/dist/types/schemas/discussion.js +199 -4
  174. package/dist/types/schemas/discussion.js.map +1 -1
  175. package/dist/types/schemas/entitlements.d.ts +36 -2
  176. package/dist/types/schemas/entitlements.js +23 -1
  177. package/dist/types/schemas/entitlements.js.map +1 -1
  178. package/dist/types/schemas/identity.d.ts +111 -1
  179. package/dist/types/schemas/identity.js +55 -2
  180. package/dist/types/schemas/identity.js.map +1 -1
  181. package/dist/types/schemas/index.d.ts +8 -8
  182. package/dist/types/schemas/index.js +8 -8
  183. package/dist/types/schemas/organizations.d.ts +8 -0
  184. package/dist/types/schemas/organizations.js +2 -0
  185. package/dist/types/schemas/organizations.js.map +1 -1
  186. package/dist/types/schemas/shared.d.ts +3 -1
  187. package/dist/types/schemas/shared.js +5 -1
  188. package/dist/types/schemas/shared.js.map +1 -1
  189. package/package.json +2 -2
  190. package/dist/reporting/courses/index.d.ts +0 -4
  191. package/dist/reporting/courses/index.js +0 -2
  192. package/dist/reporting/courses/model.d.ts +0 -24
  193. package/dist/reporting/courses/ports.d.ts +0 -13
  194. package/dist/reporting/courses/service.d.ts +0 -19
  195. package/dist/reporting/courses/service.js +0 -20
  196. package/dist/reporting/courses/service.js.map +0 -1
  197. package/dist/reporting/dashboard/index.d.ts +0 -4
  198. package/dist/reporting/dashboard/index.js +0 -2
  199. package/dist/reporting/dashboard/model.d.ts +0 -14
  200. package/dist/reporting/dashboard/ports.d.ts +0 -13
  201. package/dist/reporting/dashboard/service.d.ts +0 -19
  202. package/dist/reporting/dashboard/service.js +0 -20
  203. package/dist/reporting/dashboard/service.js.map +0 -1
  204. package/dist/reporting/learn/index.d.ts +0 -5
  205. package/dist/reporting/learn/index.js +0 -2
  206. package/dist/reporting/learn/model.d.ts +0 -23
  207. package/dist/reporting/learn/ports.d.ts +0 -43
  208. package/dist/reporting/learn/ports.js +0 -1
  209. package/dist/reporting/learn/service.d.ts +0 -49
  210. package/dist/reporting/learn/service.js +0 -116
  211. package/dist/reporting/learn/service.js.map +0 -1
  212. package/dist/reporting/students/index.d.ts +0 -4
  213. package/dist/reporting/students/index.js +0 -2
  214. package/dist/reporting/students/model.d.ts +0 -51
  215. package/dist/reporting/students/model.js +0 -1
  216. package/dist/reporting/students/ports.d.ts +0 -15
  217. package/dist/reporting/students/ports.js +0 -1
  218. package/dist/reporting/students/service.d.ts +0 -20
  219. package/dist/reporting/students/service.js +0 -23
  220. package/dist/reporting/students/service.js.map +0 -1
  221. /package/dist/reporting/{courses → admin}/model.js +0 -0
  222. /package/dist/reporting/{courses → admin}/ports.js +0 -0
  223. /package/dist/reporting/{dashboard → member}/model.js +0 -0
  224. /package/dist/reporting/{dashboard → member}/ports.js +0 -0
  225. /package/dist/{reporting/learn/model.js → shared/actor.js} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","names":[],"sources":["../../src/automations/service.ts"],"sourcesContent":["// automations context — service implementation (inbound port) and the\n// AutomationExecutor the engine drives.\n//\n// `handle` is subscribed to all events on the EventBus: it matches an event\n// against enabled automations for its trigger, opens one run per match, and\n// hands it to the injected AutomationEngine, which calls back into\n// `runAction`/`finalize`.\nimport { catalogActions, catalogTriggers, DELIVER_WEBHOOK_ACTION } from './catalog.js';\nimport { executeAction } from './actions.js';\nimport { generateWebhookSecret } from './webhook-signing.js';\nimport {\n AutomationKindMismatchError,\n InvalidTriggerError,\n ReservedActionError,\n type Automation,\n type AutomationAction,\n type AutomationActionResult,\n type AutomationRun,\n type CreatedWebhook,\n type DeliverWebhookInput,\n type Page,\n type Webhook,\n type WebhookSecret,\n} from './model.js';\nimport type {\n AutomationRunsQuery,\n AutomationsQuery,\n AvailableActions,\n AvailableTriggers,\n CreateAutomationInput,\n CreateWebhookInput,\n UpdateAutomationInput,\n UpdateWebhookInput,\n} from './types.js';\nimport type {\n AutomationDispatch,\n AutomationEngine,\n AutomationExecutor,\n AutomationRunsRepository,\n AutomationsRepository,\n AutomationsService,\n AutomationsUnitOfWork,\n WebhookSender,\n} from './ports.js';\nimport type { CredentialStore, DomainEvent, Logger } from '../shared/ports.js';\nimport type { JsonValue } from '../types/index.js';\nimport { deliverWebhookInputSchema } from '../types/schemas/index.js';\nimport { ConflictError, NotFoundError } from '../shared/errors.js';\nimport { noopLogger } from '../shared/logger.js';\nimport type { Mailer, MailerLookups } from '../shared/mailer.js';\nimport type { IntegrationsService } from '../integrations/index.js';\nimport { automationEvents } from './events.js';\n\n/** True only when `input` sets `enabled` and nothing else — emits automation.enabled|disabled instead of automation.updated. */\nfunction isEnabledOnlyUpdate<T extends { enabled?: boolean }>(\n input: T,\n): input is T & { enabled: boolean } {\n if (input.enabled === undefined) {\n return false;\n }\n const { enabled: _enabled, ...rest } = input;\n return Object.values(rest).every((v) => v === undefined);\n}\n\nfunction unique(values: string[]): string[] {\n return [...new Set(values)];\n}\n\nfunction assertAuthorableTriggers(triggers: string[]): void {\n for (const trigger of triggers) {\n if (trigger.startsWith('automation.')) {\n throw new InvalidTriggerError(trigger);\n }\n }\n}\n\nfunction assertAuthorableActions(actions: AutomationAction[]): void {\n for (const action of actions) {\n if (action.type === DELIVER_WEBHOOK_ACTION) {\n throw new ReservedActionError(action.type);\n }\n }\n}\n\nfunction webhookTarget(automation: Automation): DeliverWebhookInput {\n return deliverWebhookInputSchema.parse(automation.actions[0]?.input);\n}\n\nfunction toWebhook(automation: Automation): Webhook {\n return {\n orgId: automation.orgId,\n id: automation.id,\n url: webhookTarget(automation).url,\n events: automation.triggers,\n description: automation.description,\n enabled: automation.enabled,\n createdAt: automation.createdAt,\n updatedAt: automation.updatedAt,\n };\n}\n\nfunction updateEvent(orgId: string, input: { enabled?: boolean }, updated: Automation) {\n if (isEnabledOnlyUpdate(input)) {\n return input.enabled\n ? automationEvents.automationEnabled.make({ orgId, data: updated })\n : automationEvents.automationDisabled.make({ orgId, data: updated });\n }\n return automationEvents.automationUpdated.make({ orgId, data: updated });\n}\n\nexport type AutomationsServiceParams = {\n /** Read-only access (list/get/available) — runs outside any transaction. */\n repo: AutomationsRepository;\n runsRepo: AutomationRunsRepository;\n /** Atomic write scope: tx-bound repos + credential store + outbox appender. */\n uow: AutomationsUnitOfWork;\n engine: AutomationEngine;\n mailer: Pick<Mailer, 'send'>;\n lookups: MailerLookups;\n integrations: Pick<IntegrationsService, 'available'>;\n credentials: CredentialStore;\n webhooks: WebhookSender;\n logger?: Logger;\n};\n\nexport class AutomationsServiceImpl implements AutomationsService, AutomationExecutor {\n private readonly repo: AutomationsRepository;\n private readonly runsRepo: AutomationRunsRepository;\n private readonly uow: AutomationsUnitOfWork;\n private readonly engine: AutomationEngine;\n private readonly mailer: Pick<Mailer, 'send'>;\n private readonly lookups: MailerLookups;\n private readonly integrations: Pick<IntegrationsService, 'available'>;\n private readonly credentials: CredentialStore;\n private readonly webhooks: WebhookSender;\n private readonly logger: Logger;\n\n constructor(params: AutomationsServiceParams) {\n this.repo = params.repo;\n this.runsRepo = params.runsRepo;\n this.uow = params.uow;\n this.engine = params.engine;\n this.mailer = params.mailer;\n this.lookups = params.lookups;\n this.integrations = params.integrations;\n this.credentials = params.credentials;\n this.webhooks = params.webhooks;\n this.logger = params.logger ?? noopLogger;\n }\n\n async handle(event: DomainEvent): Promise<void> {\n // automation.* events are this service's own output — matching one as a trigger would self-loop.\n if (event.type.startsWith('automation.')) {\n return;\n }\n const automations = await this.safeListByTrigger(event);\n for (const automation of automations.filter((a) => a.enabled)) {\n await this.dispatchOne(automation, event);\n }\n }\n\n private async safeListByTrigger(event: DomainEvent): Promise<Automation[]> {\n try {\n return await this.repo.listByTrigger(event.orgId, event.type);\n } catch (err) {\n this.logger.error('automations: failed to load trigger matches', {\n orgId: event.orgId,\n trigger: event.type,\n error: err instanceof Error ? err.message : String(err),\n });\n return [];\n }\n }\n\n private async dispatchOne(automation: Automation, event: DomainEvent): Promise<void> {\n let run: AutomationRun | null = null;\n try {\n run = await this.openRun(automation, event);\n if (!run) {\n // At-least-once redelivery of a trigger event already run for this automation — no-op.\n return;\n }\n await this.engine.dispatch(this.dispatchFor(automation, run, event));\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n this.logger.error('automation run failed', {\n orgId: event.orgId,\n automationId: automation.id,\n runId: run?.id,\n error: message,\n });\n if (run) {\n await this.recordFailure(run, message);\n }\n }\n }\n\n private openRun(automation: Automation, event: DomainEvent): Promise<AutomationRun | null> {\n const now = new Date();\n return this.uow.run(async ({ runs, outbox }) => {\n const inserted = await runs.insert(event.orgId, {\n orgId: event.orgId,\n automationId: automation.id,\n trigger: event.type,\n event,\n status: 'running',\n actionResults: [],\n startedAt: now,\n finishedAt: null,\n createdAt: now,\n updatedAt: now,\n });\n if (!inserted) {\n return null;\n }\n await outbox.append([\n automationEvents.runStarted.make({\n orgId: event.orgId,\n data: inserted,\n }),\n ]);\n return inserted;\n });\n }\n\n private dispatchFor(\n automation: Automation,\n run: AutomationRun,\n event: DomainEvent,\n ): AutomationDispatch {\n return {\n runId: run.id,\n orgId: event.orgId,\n automationId: automation.id,\n actions: automation.actions,\n event,\n };\n }\n\n /** Best-effort: logs and never rethrows — `handle` must never throw. */\n private async recordFailure(run: AutomationRun, error: string): Promise<AutomationRun | null> {\n try {\n return await this.uow.run(async ({ runs, outbox }) => {\n const failed = await runs.recordOutcome(run.orgId, run.id, {\n status: 'failed',\n actionResults: run.actionResults,\n finishedAt: new Date(),\n });\n if (failed) {\n await outbox.append([\n automationEvents.runFailed.make({\n orgId: run.orgId,\n data: failed,\n }),\n ]);\n }\n return failed;\n });\n } catch (err) {\n this.logger.error('failed to record automation run failure', {\n orgId: run.orgId,\n runId: run.id,\n error: err instanceof Error ? err.message : String(err),\n originalError: error,\n });\n return null;\n }\n }\n\n async runAction(d: AutomationDispatch, index: number): Promise<AutomationActionResult> {\n const action = d.actions[index];\n if (!action) {\n throw new Error(`automation ${d.automationId} run ${d.runId}: no action at index ${index}`);\n }\n await executeAction(action, d.event, {\n mailer: this.mailer,\n lookups: this.lookups,\n credentials: this.credentials,\n webhooks: this.webhooks,\n });\n return { index, type: action.type, status: 'completed' };\n }\n\n async finalize(d: AutomationDispatch, results: AutomationActionResult[]): Promise<void> {\n const status: 'completed' | 'failed' =\n results.length === d.actions.length && results.every((r) => r.status === 'completed')\n ? 'completed'\n : 'failed';\n await this.uow.run(async ({ runs, outbox }) => {\n const run = await runs.recordOutcome(d.orgId, d.runId, {\n status,\n actionResults: results,\n finishedAt: new Date(),\n });\n if (!run) {\n return;\n }\n const runEvent =\n status === 'completed'\n ? automationEvents.runCompleted.make({ orgId: d.orgId, data: run })\n : automationEvents.runFailed.make({ orgId: d.orgId, data: run });\n const actionFailedEvents = results\n .filter((r) => r.status === 'failed')\n .map((result) => ({\n ...automationEvents.actionFailed.make({\n orgId: d.orgId,\n data: result,\n }),\n }));\n await outbox.append([runEvent, ...actionFailedEvents]);\n });\n }\n\n async create(orgId: string, input: CreateAutomationInput): Promise<Automation> {\n assertAuthorableTriggers(input.triggers);\n assertAuthorableActions(input.actions);\n const automation = await this.uow.run(async ({ automations, outbox }) => {\n const created = await automations.insert(orgId, {\n ...input,\n triggers: unique(input.triggers),\n kind: 'workflow',\n });\n await outbox.append([automationEvents.automationCreated.make({ orgId, data: created })]);\n return created;\n });\n this.logger.info('automation created', { orgId, automationId: automation.id });\n return automation;\n }\n\n async update(\n orgId: string,\n id: string,\n input: UpdateAutomationInput,\n ): Promise<Automation | null> {\n if (input.triggers !== undefined) {\n assertAuthorableTriggers(input.triggers);\n }\n if (input.actions !== undefined) {\n assertAuthorableActions(input.actions);\n }\n const existing = await this.repo.findById(orgId, id);\n if (!existing) {\n return null;\n }\n if (existing.kind !== 'workflow') {\n throw new AutomationKindMismatchError(id, existing.kind);\n }\n const patch =\n input.triggers === undefined ? input : { ...input, triggers: unique(input.triggers) };\n const automation = await this.uow.run(async ({ automations, outbox }) => {\n const updated = await automations.update(orgId, id, patch);\n if (!updated) {\n return null;\n }\n await outbox.append([updateEvent(orgId, input, updated)]);\n return updated;\n });\n if (automation) {\n this.logger.info('automation updated', { orgId, automationId: id });\n }\n return automation;\n }\n\n async delete(orgId: string, id: string): Promise<boolean> {\n const existing = await this.repo.findById(orgId, id);\n if (!existing) {\n return false;\n }\n if (existing.kind !== 'workflow') {\n throw new AutomationKindMismatchError(id, existing.kind);\n }\n const deleted = await this.uow.run(async ({ automations, outbox }) => {\n const removed = await automations.delete(orgId, id);\n if (!removed) {\n return null;\n }\n await outbox.append([automationEvents.automationDeleted.make({ orgId, data: removed })]);\n return removed;\n });\n if (deleted) {\n this.logger.info('automation deleted', { orgId, automationId: id });\n }\n return deleted !== null;\n }\n\n list(orgId: string, query?: AutomationsQuery): Promise<Automation[]> {\n return this.repo.listByOrg(orgId, query?.kind);\n }\n\n get(orgId: string, id: string): Promise<Automation | null> {\n return this.repo.findById(orgId, id);\n }\n\n listRuns(\n orgId: string,\n automationId: string,\n query: AutomationRunsQuery,\n ): Promise<Page<AutomationRun>> {\n return this.runsRepo.list(orgId, automationId, query);\n }\n\n async rerun(orgId: string, automationId: string, runId: string): Promise<AutomationRun> {\n const existing = await this.runsRepo.findById(orgId, runId);\n if (!existing || existing.automationId !== automationId) {\n throw new NotFoundError('Automation run', runId);\n }\n const automation = await this.repo.findById(orgId, automationId);\n if (!automation) {\n throw new NotFoundError('Automation', automationId);\n }\n const run = await this.uow.run(async ({ runs, outbox }) => {\n const restarted = await runs.restart(orgId, runId, new Date());\n if (!restarted) {\n return null;\n }\n await outbox.append([automationEvents.runStarted.make({ orgId, data: restarted })]);\n return restarted;\n });\n if (!run) {\n throw new ConflictError(`automation run ${runId} is still running`);\n }\n try {\n await this.engine.dispatch(this.dispatchFor(automation, run, run.event));\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n this.logger.error('automation rerun failed', {\n orgId,\n automationId,\n runId: run.id,\n error: message,\n });\n return (await this.recordFailure(run, message)) ?? run;\n }\n this.logger.info('automation rerun started', { orgId, automationId, runId: run.id });\n return run;\n }\n\n async listWebhooks(orgId: string): Promise<Webhook[]> {\n const automations = await this.repo.listByOrg(orgId, 'webhook');\n return automations.map(toWebhook);\n }\n\n async getWebhook(orgId: string, id: string): Promise<Webhook | null> {\n const automation = await this.findWebhook(orgId, id);\n return automation ? toWebhook(automation) : null;\n }\n\n async createWebhook(orgId: string, input: CreateWebhookInput): Promise<CreatedWebhook> {\n const events = unique(input.events);\n this.assertSubscribableEvents(events);\n const secret = generateWebhookSecret();\n const automation = await this.uow.run(async ({ automations, credentials, outbox }) => {\n const secretRef = await credentials.store(orgId, { secret });\n const created = await automations.insert(orgId, {\n kind: 'webhook',\n name: input.url,\n description: input.description,\n triggers: events,\n actions: [{ type: DELIVER_WEBHOOK_ACTION, input: { url: input.url, secretRef } }],\n });\n await outbox.append([automationEvents.automationCreated.make({ orgId, data: created })]);\n return created;\n });\n this.logger.info('webhook created', { orgId, automationId: automation.id });\n return { ...toWebhook(automation), secret };\n }\n\n async updateWebhook(\n orgId: string,\n id: string,\n input: UpdateWebhookInput,\n ): Promise<Webhook | null> {\n const existing = await this.findWebhook(orgId, id);\n if (!existing) {\n return null;\n }\n const events = input.events === undefined ? undefined : unique(input.events);\n if (events) {\n this.assertSubscribableEvents(events);\n }\n const { secretRef } = webhookTarget(existing);\n const patch: UpdateAutomationInput = {\n name: input.url,\n description: input.description,\n triggers: events,\n actions:\n input.url === undefined\n ? undefined\n : [{ type: DELIVER_WEBHOOK_ACTION, input: { url: input.url, secretRef } }],\n enabled: input.enabled,\n };\n const updated = await this.uow.run(async ({ automations, outbox }) => {\n const row = await automations.update(orgId, id, patch);\n if (!row) {\n return null;\n }\n await outbox.append([updateEvent(orgId, input, row)]);\n return row;\n });\n if (!updated) {\n return null;\n }\n this.logger.info('webhook updated', { orgId, automationId: id });\n return toWebhook(updated);\n }\n\n async deleteWebhook(orgId: string, id: string): Promise<boolean> {\n const existing = await this.findWebhook(orgId, id);\n if (!existing) {\n return false;\n }\n const { secretRef } = webhookTarget(existing);\n const deleted = await this.uow.run(async ({ automations, credentials, outbox }) => {\n const removed = await automations.delete(orgId, id);\n if (!removed) {\n return null;\n }\n await credentials.destroy(orgId, secretRef);\n await outbox.append([automationEvents.automationDeleted.make({ orgId, data: removed })]);\n return removed;\n });\n if (deleted) {\n this.logger.info('webhook deleted', { orgId, automationId: id });\n }\n return deleted !== null;\n }\n\n async revealWebhookSecret(orgId: string, id: string): Promise<WebhookSecret | null> {\n const existing = await this.findWebhook(orgId, id);\n if (!existing) {\n return null;\n }\n const secrets = await this.credentials.reveal(orgId, webhookTarget(existing).secretRef);\n const secret = secrets?.['secret'];\n if (typeof secret !== 'string') {\n throw new Error(`webhook ${id}: signing secret is missing`);\n }\n return { secret };\n }\n\n async rotateWebhookSecret(orgId: string, id: string): Promise<WebhookSecret | null> {\n const existing = await this.findWebhook(orgId, id);\n if (!existing) {\n return null;\n }\n const secret = generateWebhookSecret();\n await this.credentials.update(orgId, webhookTarget(existing).secretRef, { secret });\n this.logger.info('webhook secret rotated', { orgId, automationId: id });\n return { secret };\n }\n\n private async findWebhook(orgId: string, id: string): Promise<Automation | null> {\n const automation = await this.repo.findById(orgId, id);\n return automation?.kind === 'webhook' ? automation : null;\n }\n\n private assertSubscribableEvents(events: string[]): void {\n assertAuthorableTriggers(events);\n const known = new Set(catalogTriggers().map((t) => t.type));\n for (const event of events) {\n if (!known.has(event)) {\n throw new InvalidTriggerError(event, 'unknown');\n }\n }\n }\n\n availableActions(): AvailableActions {\n return [\n ...catalogActions(),\n ...this.integrations.available().flatMap((integration) =>\n integration.actions.map((action) => ({\n type: `${integration.id}.${action.id}`,\n description: action.description,\n inputSchema: action.inputSchema as Record<string, JsonValue>,\n source: integration.id,\n })),\n ),\n ];\n }\n\n availableTriggers(): AvailableTriggers {\n return { triggers: catalogTriggers() };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"service.js","names":[],"sources":["../../src/automations/service.ts"],"sourcesContent":["// automations context — service implementation (inbound port) and the\n// AutomationExecutor the engine drives.\n//\n// `handle` is subscribed to all events on the EventBus: it matches an event\n// against enabled automations for its trigger, opens one run per match, and\n// hands it to the injected AutomationEngine, which calls back into\n// `runAction`/`finalize`.\nimport {\n catalogActions,\n catalogTriggers,\n DELIVER_WEBHOOK_ACTION,\n publicDataSchema,\n} from './catalog.js';\nimport { executeAction, type ActionOutcome } from './actions.js';\nimport { generateWebhookSecret } from './webhook-signing.js';\nimport type { CommunityMailReads, GrantWriter, ScheduledWork } from './community-mail.js';\nimport type { NotificationDesk } from '../identity/index.js';\nimport { communitySeeds, orgSeeds, type SeedAutomation } from './seeds.js';\nimport { cronSupported } from './schedule.js';\nimport {\n ActionFailedError,\n AutomationKindMismatchError,\n InvalidTriggerError,\n ReservedActionError,\n type Automation,\n type AutomationAction,\n type AutomationActionResult,\n type AutomationRun,\n type CreatedWebhook,\n type DeliverWebhookInput,\n type Page,\n type Webhook,\n type WebhookSecret,\n} from './model.js';\nimport type {\n AutomationRunsQuery,\n AutomationsQuery,\n AvailableActions,\n AvailableTriggers,\n CreateAutomationInput,\n CreateWebhookInput,\n UpdateAutomationInput,\n UpdateWebhookInput,\n} from './types.js';\nimport type {\n AutomationDispatch,\n AutomationEngine,\n AutomationExecutor,\n AutomationRunsRepository,\n AutomationsRepository,\n AutomationsService,\n AutomationsUnitOfWork,\n WebhookSender,\n} from './ports.js';\nimport type { CredentialStore, DomainEvent, Logger } from '../shared/ports.js';\nimport type { JsonValue, ScheduledAutomation } from '../types/index.js';\nimport { deliverWebhookInputSchema } from '../types/schemas/index.js';\nimport { ConflictError, NotFoundError } from '../shared/errors.js';\nimport { noopLogger } from '../shared/logger.js';\nimport type { Mailer, MailerLookups } from '../shared/mailer.js';\nimport type { IntegrationsService } from '../integrations/index.js';\nimport { automationEvents } from './events.js';\n\n/** True only when `input` sets `enabled` and nothing else — emits automation.enabled|disabled instead of automation.updated. */\nfunction isEnabledOnlyUpdate<T extends { enabled?: boolean }>(\n input: T,\n): input is T & { enabled: boolean } {\n if (input.enabled === undefined) {\n return false;\n }\n const { enabled: _enabled, ...rest } = input;\n return Object.values(rest).every((v) => v === undefined);\n}\n\nfunction floorMinute(at: Date): number {\n const copy = new Date(at);\n copy.setUTCSeconds(0, 0);\n return copy.getTime();\n}\n\nfunction unique(values: string[]): string[] {\n return [...new Set(values)];\n}\n\nfunction recordString(value: unknown, key: string): string | null {\n if (typeof value !== 'object' || value === null || !(key in value)) {\n return null;\n }\n const found = (value as Record<string, unknown>)[key];\n return typeof found === 'string' ? found : null;\n}\n\nfunction filterMatches(filter: Record<string, JsonValue> | null, data: unknown): boolean {\n if (filter == null) {\n return true;\n }\n if (typeof data !== 'object' || data === null || Array.isArray(data)) {\n return false;\n }\n const record = data as Record<string, unknown>;\n return Object.entries(filter).every(([key, expected]) => {\n if (!Object.prototype.hasOwnProperty.call(record, key)) {\n return false;\n }\n return JSON.stringify(record[key]) === JSON.stringify(expected);\n });\n}\n\nfunction assertAuthorableTriggers(triggers: string[]): void {\n for (const trigger of triggers) {\n if (trigger.startsWith('automation.')) {\n throw new InvalidTriggerError(trigger);\n }\n if (trigger.startsWith('schedule:') && !cronSupported(trigger.slice('schedule:'.length))) {\n throw new InvalidTriggerError(trigger, 'schedule');\n }\n }\n}\n\nfunction assertCatalogTriggers(triggers: string[], schedules: boolean): void {\n assertAuthorableTriggers(triggers);\n const known = new Set(catalogTriggers().map((t) => t.type));\n for (const trigger of triggers) {\n if (!(schedules && trigger.startsWith('schedule:')) && !known.has(trigger)) {\n throw new InvalidTriggerError(trigger, 'unknown');\n }\n }\n}\n\nfunction assertAuthorableActions(actions: AutomationAction[]): void {\n for (const action of actions) {\n if (action.type === DELIVER_WEBHOOK_ACTION) {\n throw new ReservedActionError(action.type);\n }\n }\n}\n\nconst SCHEDULE_FIRED = 'automation.schedule.fired';\n\nfunction publicEventData(event: DomainEvent): JsonValue {\n const parsed =\n event.type === SCHEDULE_FIRED\n ? { success: true as const, data: event.data }\n : publicDataSchema(event.type)?.safeParse(event.data);\n return parsed?.success ? (JSON.parse(JSON.stringify(parsed.data)) as JsonValue) : null;\n}\n\n/** A run as callers see it: its event carries only what a webhook of that event would. */\nfunction toRunView(run: AutomationRun): AutomationRun {\n const { type, version, id, orgId, occurredAt } = run.event;\n return {\n ...run,\n event: { type, version, id, orgId, occurredAt, data: publicEventData(run.event) },\n };\n}\n\n/** An automation as callers see it: a webhook's credential reference stays internal. */\nfunction toAutomationView(automation: Automation): Automation {\n return {\n ...automation,\n actions: automation.actions.map((action) => {\n if (action.type !== DELIVER_WEBHOOK_ACTION) {\n return action;\n }\n const { secretRef: _secretRef, ...input } = action.input;\n return { ...action, input };\n }),\n };\n}\n\nfunction webhookTarget(automation: Automation): DeliverWebhookInput {\n return deliverWebhookInputSchema.parse(automation.actions[0]?.input);\n}\n\nfunction toWebhook(automation: Automation): Webhook {\n return {\n orgId: automation.orgId,\n id: automation.id,\n url: webhookTarget(automation).url,\n events: automation.triggers,\n description: automation.description,\n enabled: automation.enabled,\n createdAt: automation.createdAt,\n updatedAt: automation.updatedAt,\n };\n}\n\nfunction updateEvent(orgId: string, input: { enabled?: boolean }, updated: Automation) {\n if (isEnabledOnlyUpdate(input)) {\n return input.enabled\n ? automationEvents.automationEnabled.make({ orgId, data: updated })\n : automationEvents.automationDisabled.make({ orgId, data: updated });\n }\n return automationEvents.automationUpdated.make({ orgId, data: updated });\n}\n\nexport type AutomationsServiceParams = {\n /** Read-only access (list/get/available) — runs outside any transaction. */\n repo: AutomationsRepository;\n runsRepo: AutomationRunsRepository;\n /** Atomic write scope: tx-bound repos + credential store + outbox appender. */\n uow: AutomationsUnitOfWork;\n engine: AutomationEngine;\n mailer: Pick<Mailer, 'send'>;\n lookups: MailerLookups;\n integrations: Pick<IntegrationsService, 'available'>;\n credentials: CredentialStore;\n webhooks: WebhookSender;\n mail: Omit<CommunityMailReads, 'recentMessageRecipients'>;\n grants: GrantWriter;\n desk: NotificationDesk;\n scheduledWork: ScheduledWork;\n logger?: Logger;\n};\n\nexport class AutomationsServiceImpl implements AutomationsService, AutomationExecutor {\n private readonly repo: AutomationsRepository;\n private readonly runsRepo: AutomationRunsRepository;\n private readonly uow: AutomationsUnitOfWork;\n private readonly engine: AutomationEngine;\n private readonly mailer: Pick<Mailer, 'send'>;\n private readonly lookups: MailerLookups;\n private readonly integrations: Pick<IntegrationsService, 'available'>;\n private readonly credentials: CredentialStore;\n private readonly webhooks: WebhookSender;\n private readonly mail: CommunityMailReads;\n private readonly grants: GrantWriter;\n private readonly desk: NotificationDesk;\n private readonly scheduledWork: ScheduledWork;\n private readonly logger: Logger;\n\n constructor(params: AutomationsServiceParams) {\n this.repo = params.repo;\n this.runsRepo = params.runsRepo;\n this.uow = params.uow;\n this.engine = params.engine;\n this.mailer = params.mailer;\n this.lookups = params.lookups;\n this.integrations = params.integrations;\n this.credentials = params.credentials;\n this.webhooks = params.webhooks;\n this.mail = {\n ...params.mail,\n recentMessageRecipients: (orgId, automationId, chatId, since) =>\n this.runsRepo.recentRecipients(orgId, automationId, chatId, since),\n };\n this.grants = params.grants;\n this.desk = params.desk;\n this.scheduledWork = params.scheduledWork;\n this.logger = params.logger ?? noopLogger;\n }\n\n async handle(event: DomainEvent): Promise<void> {\n // automation.* events are this service's own output — matching one as a trigger would self-loop.\n if (event.type.startsWith('automation.')) {\n return;\n }\n await this.seedFor(event);\n const automations = await this.safeListByTrigger(event);\n for (const automation of automations) {\n const matches = filterMatches(automation.filter, event.data);\n if (!automation.enabled || !matches) {\n if (automation.enabled && !matches) {\n this.logger.debug('automation filter skipped', {\n orgId: event.orgId,\n automationId: automation.id,\n trigger: event.type,\n });\n }\n continue;\n }\n await this.dispatchOne(automation, event);\n }\n }\n\n private seedsFor(event: DomainEvent): SeedAutomation[] | null {\n if (event.type === 'organization.created') {\n return orgSeeds();\n }\n if (event.type !== 'content.community.created') {\n return null;\n }\n const communityId = recordString(event.data, 'id');\n if (!communityId) {\n this.logger.error('community seed missing id', { orgId: event.orgId, eventId: event.id });\n return null;\n }\n return communitySeeds(communityId);\n }\n\n private async seedFor(event: DomainEvent): Promise<void> {\n const rows = this.seedsFor(event);\n if (!rows) {\n return;\n }\n const seeded = await this.uow.run(async ({ automations, outbox }) => {\n const created = [];\n for (const row of rows) {\n const inserted = await automations.insertSeed(event.orgId, {\n name: row.name,\n description: row.description,\n triggers: row.triggers,\n actions: row.actions,\n filter: row.filter,\n kind: 'workflow',\n source: 'system',\n });\n if (inserted) {\n created.push(\n automationEvents.automationCreated.make({ orgId: event.orgId, data: inserted }),\n );\n }\n }\n if (created.length > 0) {\n await outbox.append(created);\n this.logger.info('system automations seeded', {\n orgId: event.orgId,\n trigger: event.type,\n count: created.length,\n });\n }\n return created.length;\n });\n if (seeded > 0) {\n await this.reconcileSchedules(event.orgId);\n }\n }\n\n private async reconcileSchedules(orgId: string): Promise<void> {\n try {\n await this.engine.syncSchedules?.();\n } catch (err) {\n this.logger.error('automation schedules not reconciled', { orgId, err });\n }\n }\n\n private async safeListByTrigger(event: DomainEvent): Promise<Automation[]> {\n try {\n return await this.repo.listByTrigger(event.orgId, event.type);\n } catch (err) {\n this.logger.error('automations: failed to load trigger matches', {\n orgId: event.orgId,\n trigger: event.type,\n err,\n });\n return [];\n }\n }\n\n private async dispatchOne(automation: Automation, event: DomainEvent): Promise<void> {\n let run: AutomationRun | null = null;\n try {\n run = await this.openRun(automation, event);\n if (!run) {\n // At-least-once redelivery of a trigger event already run for this automation — no-op.\n return;\n }\n await this.engine.dispatch(this.dispatchFor(automation, run, event));\n } catch (err) {\n this.logger.error('automation run failed', {\n orgId: event.orgId,\n automationId: automation.id,\n runId: run?.id,\n trigger: event.type,\n eventId: event.id,\n err,\n });\n if (run) {\n await this.recordFailure(run, err instanceof Error ? err.message : String(err));\n }\n }\n }\n\n private openRun(automation: Automation, event: DomainEvent): Promise<AutomationRun | null> {\n const now = new Date();\n return this.uow.run(async ({ runs, outbox }) => {\n const inserted = await runs.insert(event.orgId, {\n orgId: event.orgId,\n automationId: automation.id,\n trigger: event.type,\n event,\n status: 'running',\n actionResults: [],\n startedAt: now,\n finishedAt: null,\n createdAt: now,\n updatedAt: now,\n });\n if (!inserted) {\n return null;\n }\n await outbox.append([\n automationEvents.runStarted.make({\n orgId: event.orgId,\n data: inserted,\n }),\n ]);\n return inserted;\n });\n }\n\n private dispatchFor(\n automation: Automation,\n run: AutomationRun,\n event: DomainEvent,\n ): AutomationDispatch {\n return {\n runId: run.id,\n orgId: event.orgId,\n automationId: automation.id,\n actions: automation.actions,\n event,\n };\n }\n\n /** Best-effort: logs and never rethrows — `handle` must never throw. */\n private async recordFailure(run: AutomationRun, error: string): Promise<AutomationRun | null> {\n try {\n return await this.uow.run(async ({ runs, outbox }) => {\n const failed = await runs.recordOutcome(run.orgId, run.id, {\n status: 'failed',\n actionResults: run.actionResults,\n finishedAt: new Date(),\n });\n if (failed) {\n await outbox.append([\n automationEvents.runFailed.make({\n orgId: run.orgId,\n data: failed,\n }),\n ]);\n }\n return failed;\n });\n } catch (err) {\n this.logger.error('failed to record automation run failure', {\n orgId: run.orgId,\n automationId: run.automationId,\n runId: run.id,\n err,\n originalError: error,\n });\n return null;\n }\n }\n\n async runAction(d: AutomationDispatch, index: number): Promise<AutomationActionResult> {\n const action = d.actions[index];\n if (!action) {\n throw new Error(`automation ${d.automationId} run ${d.runId}: no action at index ${index}`);\n }\n let outcome: ActionOutcome;\n try {\n outcome = await executeAction(action, d.event, {\n mailer: this.mailer,\n lookups: this.lookups,\n credentials: this.credentials,\n webhooks: this.webhooks,\n mail: this.mail,\n grants: this.grants,\n desk: this.desk,\n scheduledWork: this.scheduledWork,\n automationId: d.automationId,\n actionInput: action.input,\n logger: this.logger,\n });\n } catch (err) {\n this.logger.error('automation action failed', {\n orgId: d.orgId,\n automationId: d.automationId,\n runId: d.runId,\n trigger: d.event.type,\n index,\n type: action.type,\n err,\n });\n throw err instanceof ActionFailedError ? err : new ActionFailedError();\n }\n const { recipients, failed } = outcome;\n this.logger.info('automation action completed', {\n orgId: d.orgId,\n automationId: d.automationId,\n runId: d.runId,\n type: action.type,\n recipients: recipients.length,\n failed: failed.length,\n });\n return {\n index,\n type: action.type,\n status: 'completed',\n ...(recipients.length > 0 ? { recipients } : {}),\n ...(failed.length > 0\n ? { error: `delivery failed for ${failed.length} recipients: ${failed.join(', ')}` }\n : {}),\n };\n }\n\n async listSchedules(): Promise<ScheduledAutomation[]> {\n return this.repo.listSchedules();\n }\n\n async fireSchedule(orgId: string, automationId: string, at: Date): Promise<void> {\n const firedAt = new Date(floorMinute(at));\n const automation = await this.repo.findById(orgId, automationId);\n if (!automation?.enabled || firedAt.getTime() < floorMinute(automation.createdAt)) {\n this.logger.debug('schedule skipped', { orgId, automationId });\n return;\n }\n if (!(await this.scheduleHasWork(orgId, automation, firedAt))) {\n this.logger.debug('schedule idle', { orgId, automationId });\n return;\n }\n const event: DomainEvent = {\n type: SCHEDULE_FIRED,\n id: `schedule_${automationId}_${firedAt.toISOString()}`,\n orgId,\n version: 1,\n occurredAt: firedAt.toISOString(),\n data: { automationId, firedAt: firedAt.toISOString() },\n };\n await this.dispatchOne(automation, event);\n }\n\n private async scheduleHasWork(\n orgId: string,\n automation: Automation,\n firedAt: Date,\n ): Promise<boolean> {\n const checks = automation.actions.map((action) => this.pendingWork(action.type));\n const known = checks.filter((check) => check !== null);\n if (checks.length === 0 || known.length < checks.length) {\n return true;\n }\n for (const check of known) {\n if (await check(orgId, firedAt)) {\n return true;\n }\n }\n return false;\n }\n\n private pendingWork(type: string): ((orgId: string, now: Date) => Promise<boolean>) | null {\n switch (type) {\n case 'publishDuePosts':\n return (orgId, now) => this.scheduledWork.hasDuePosts(orgId, now);\n case 'expireDueGrants':\n return (orgId, now) => this.scheduledWork.hasDueGrants(orgId, now);\n case 'removeUnattachedUploads':\n return (orgId, now) => this.scheduledWork.hasUnattachedUploads(orgId, now);\n default:\n return null;\n }\n }\n\n async finalize(d: AutomationDispatch, results: AutomationActionResult[]): Promise<void> {\n const status: 'completed' | 'failed' =\n results.length === d.actions.length && results.every((r) => r.status === 'completed')\n ? 'completed'\n : 'failed';\n await this.uow.run(async ({ runs, outbox }) => {\n const run = await runs.recordOutcome(d.orgId, d.runId, {\n status,\n actionResults: results,\n finishedAt: new Date(),\n });\n if (!run) {\n return;\n }\n const runEvent =\n status === 'completed'\n ? automationEvents.runCompleted.make({ orgId: d.orgId, data: run })\n : automationEvents.runFailed.make({ orgId: d.orgId, data: run });\n const actionFailedEvents = results\n .filter((r) => r.status === 'failed')\n .map((result) => ({\n ...automationEvents.actionFailed.make({\n orgId: d.orgId,\n data: result,\n }),\n }));\n await outbox.append([runEvent, ...actionFailedEvents]);\n });\n this.logOutcome(d, status, results);\n }\n\n private logOutcome(\n d: AutomationDispatch,\n status: 'completed' | 'failed',\n results: AutomationActionResult[],\n ): void {\n const run = {\n orgId: d.orgId,\n automationId: d.automationId,\n runId: d.runId,\n trigger: d.event.type,\n eventId: d.event.id,\n };\n if (status === 'failed') {\n const failed = results.find((r) => r.status === 'failed');\n const index = failed?.index ?? results.length;\n this.logger.error('automation run failed', {\n ...run,\n index,\n action: failed?.type ?? d.actions[index]?.type,\n error: failed?.error ?? 'not every action ran',\n });\n return;\n }\n const partial = results.filter((r) => r.error !== undefined);\n if (partial.length > 0) {\n this.logger.warn('automation run completed with failed deliveries', {\n ...run,\n actions: partial.map(({ index, type, error }) => ({ index, type, error })),\n });\n }\n }\n\n async create(orgId: string, input: CreateAutomationInput): Promise<Automation> {\n assertCatalogTriggers(input.triggers, true);\n assertAuthorableActions(input.actions);\n const automation = await this.uow.run(async ({ automations, outbox }) => {\n const created = await automations.insert(orgId, {\n ...input,\n triggers: unique(input.triggers),\n kind: 'workflow',\n });\n await outbox.append([automationEvents.automationCreated.make({ orgId, data: created })]);\n return created;\n });\n this.logger.info('automation created', { orgId, automationId: automation.id });\n await this.reconcileSchedules(orgId);\n return automation;\n }\n\n async update(\n orgId: string,\n id: string,\n input: UpdateAutomationInput,\n ): Promise<Automation | null> {\n if (input.triggers !== undefined) {\n assertCatalogTriggers(input.triggers, true);\n }\n if (input.actions !== undefined) {\n assertAuthorableActions(input.actions);\n }\n const existing = await this.repo.findById(orgId, id);\n if (!existing) {\n return null;\n }\n if (existing.kind !== 'workflow') {\n throw new AutomationKindMismatchError(id, existing.kind);\n }\n const patch =\n input.triggers === undefined ? input : { ...input, triggers: unique(input.triggers) };\n const automation = await this.uow.run(async ({ automations, outbox }) => {\n const updated = await automations.update(orgId, id, patch);\n if (!updated) {\n return null;\n }\n await outbox.append([updateEvent(orgId, input, updated)]);\n return updated;\n });\n if (automation) {\n this.logger.info('automation updated', { orgId, automationId: id });\n await this.reconcileSchedules(orgId);\n }\n return automation;\n }\n\n async delete(orgId: string, id: string): Promise<boolean> {\n const existing = await this.repo.findById(orgId, id);\n if (!existing) {\n return false;\n }\n if (existing.kind !== 'workflow') {\n throw new AutomationKindMismatchError(id, existing.kind);\n }\n if (existing.source === 'system') {\n throw new ConflictError('A system automation cannot be deleted');\n }\n const deleted = await this.uow.run(async ({ automations, outbox }) => {\n const removed = await automations.delete(orgId, id);\n if (!removed) {\n return null;\n }\n await outbox.append([automationEvents.automationDeleted.make({ orgId, data: removed })]);\n return removed;\n });\n if (deleted) {\n this.logger.info('automation deleted', { orgId, automationId: id });\n await this.reconcileSchedules(orgId);\n }\n return deleted !== null;\n }\n\n async list(orgId: string, query?: AutomationsQuery): Promise<Automation[]> {\n const automations = await this.repo.listByOrg(orgId, query?.kind);\n return automations.map(toAutomationView);\n }\n\n async get(orgId: string, id: string): Promise<Automation | null> {\n const automation = await this.repo.findById(orgId, id);\n return automation ? toAutomationView(automation) : null;\n }\n\n async listRuns(\n orgId: string,\n automationId: string,\n query: AutomationRunsQuery,\n ): Promise<Page<AutomationRun>> {\n const page = await this.runsRepo.list(orgId, automationId, query);\n return { ...page, rows: page.rows.map(toRunView) };\n }\n\n async rerun(orgId: string, automationId: string, runId: string): Promise<AutomationRun> {\n const existing = await this.runsRepo.findById(orgId, runId);\n if (!existing || existing.automationId !== automationId) {\n throw new NotFoundError('Automation run', runId);\n }\n const automation = await this.repo.findById(orgId, automationId);\n if (!automation) {\n throw new NotFoundError('Automation', automationId);\n }\n const run = await this.uow.run(async ({ runs, outbox }) => {\n const restarted = await runs.restart(orgId, runId, new Date());\n if (!restarted) {\n return null;\n }\n await outbox.append([automationEvents.runStarted.make({ orgId, data: restarted })]);\n return restarted;\n });\n if (!run) {\n throw new ConflictError(`automation run ${runId} is still running`);\n }\n try {\n await this.engine.dispatch(this.dispatchFor(automation, run, run.event));\n } catch (err) {\n this.logger.error('automation rerun failed', {\n orgId,\n automationId,\n runId: run.id,\n trigger: run.trigger,\n err,\n });\n const failed = await this.recordFailure(\n run,\n err instanceof Error ? err.message : String(err),\n );\n return toRunView(failed ?? run);\n }\n this.logger.info('automation rerun started', { orgId, automationId, runId: run.id });\n return toRunView(run);\n }\n\n async listWebhooks(orgId: string): Promise<Webhook[]> {\n const automations = await this.repo.listByOrg(orgId, 'webhook');\n return automations.map(toWebhook);\n }\n\n async getWebhook(orgId: string, id: string): Promise<Webhook | null> {\n const automation = await this.findWebhook(orgId, id);\n return automation ? toWebhook(automation) : null;\n }\n\n async createWebhook(orgId: string, input: CreateWebhookInput): Promise<CreatedWebhook> {\n const events = unique(input.events);\n assertCatalogTriggers(events, false);\n const secret = generateWebhookSecret();\n const automation = await this.uow.run(async ({ automations, credentials, outbox }) => {\n const secretRef = await credentials.store(orgId, { secret });\n const created = await automations.insert(orgId, {\n kind: 'webhook',\n name: input.url,\n description: input.description,\n triggers: events,\n actions: [{ type: DELIVER_WEBHOOK_ACTION, input: { url: input.url, secretRef } }],\n });\n await outbox.append([automationEvents.automationCreated.make({ orgId, data: created })]);\n return created;\n });\n this.logger.info('webhook created', { orgId, automationId: automation.id });\n return { ...toWebhook(automation), secret };\n }\n\n async updateWebhook(\n orgId: string,\n id: string,\n input: UpdateWebhookInput,\n ): Promise<Webhook | null> {\n const existing = await this.findWebhook(orgId, id);\n if (!existing) {\n return null;\n }\n const events = input.events === undefined ? undefined : unique(input.events);\n if (events) {\n assertCatalogTriggers(events, false);\n }\n const { secretRef } = webhookTarget(existing);\n const patch: UpdateAutomationInput = {\n name: input.url,\n description: input.description,\n triggers: events,\n actions:\n input.url === undefined\n ? undefined\n : [{ type: DELIVER_WEBHOOK_ACTION, input: { url: input.url, secretRef } }],\n enabled: input.enabled,\n };\n const updated = await this.uow.run(async ({ automations, outbox }) => {\n const row = await automations.update(orgId, id, patch);\n if (!row) {\n return null;\n }\n await outbox.append([updateEvent(orgId, input, row)]);\n return row;\n });\n if (!updated) {\n return null;\n }\n this.logger.info('webhook updated', { orgId, automationId: id });\n return toWebhook(updated);\n }\n\n async deleteWebhook(orgId: string, id: string): Promise<boolean> {\n const existing = await this.findWebhook(orgId, id);\n if (!existing) {\n return false;\n }\n const { secretRef } = webhookTarget(existing);\n const deleted = await this.uow.run(async ({ automations, credentials, outbox }) => {\n const removed = await automations.delete(orgId, id);\n if (!removed) {\n return null;\n }\n await credentials.destroy(orgId, secretRef);\n await outbox.append([automationEvents.automationDeleted.make({ orgId, data: removed })]);\n return removed;\n });\n if (deleted) {\n this.logger.info('webhook deleted', { orgId, automationId: id });\n }\n return deleted !== null;\n }\n\n async revealWebhookSecret(orgId: string, id: string): Promise<WebhookSecret | null> {\n const existing = await this.findWebhook(orgId, id);\n if (!existing) {\n return null;\n }\n const secrets = await this.credentials.reveal(orgId, webhookTarget(existing).secretRef);\n const secret = secrets?.['secret'];\n if (typeof secret !== 'string') {\n throw new Error(`webhook ${id}: signing secret is missing`);\n }\n return { secret };\n }\n\n async rotateWebhookSecret(orgId: string, id: string): Promise<WebhookSecret | null> {\n const existing = await this.findWebhook(orgId, id);\n if (!existing) {\n return null;\n }\n const secret = generateWebhookSecret();\n await this.credentials.update(orgId, webhookTarget(existing).secretRef, { secret });\n this.logger.info('webhook secret rotated', { orgId, automationId: id });\n return { secret };\n }\n\n private async findWebhook(orgId: string, id: string): Promise<Automation | null> {\n const automation = await this.repo.findById(orgId, id);\n return automation?.kind === 'webhook' ? automation : null;\n }\n\n availableActions(): AvailableActions {\n return [\n ...catalogActions(),\n ...this.integrations.available().flatMap((integration) =>\n integration.actions.map((action) => ({\n type: `${integration.id}.${action.id}`,\n description: action.description,\n inputSchema: action.inputSchema as Record<string, JsonValue>,\n source: integration.id,\n })),\n ),\n ];\n }\n\n availableTriggers(): AvailableTriggers {\n return { triggers: catalogTriggers() };\n }\n}\n"],"mappings":"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"}