deepline 0.3.88 → 0.3.90

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 (280) hide show
  1. package/contracts/install-commands.json +29 -0
  2. package/dist/bundling-sources/sdk/src/client.ts +652 -39
  3. package/dist/bundling-sources/sdk/src/config.ts +77 -0
  4. package/dist/bundling-sources/sdk/src/http.ts +76 -30
  5. package/dist/bundling-sources/sdk/src/index.ts +10 -0
  6. package/dist/bundling-sources/sdk/src/monitor-fleet-contract.ts +1 -1
  7. package/dist/bundling-sources/sdk/src/pagination.ts +25 -0
  8. package/dist/bundling-sources/sdk/src/play.ts +15 -1
  9. package/dist/bundling-sources/sdk/src/plays/bundle-play-file.ts +3 -3
  10. package/dist/bundling-sources/sdk/src/release.ts +16 -9
  11. package/dist/bundling-sources/sdk/src/types.ts +106 -4
  12. package/dist/bundling-sources/shared_libs/integration-contracts/AGENTS.md +9 -0
  13. package/dist/bundling-sources/shared_libs/integration-contracts/README.md +3 -0
  14. package/dist/bundling-sources/shared_libs/integration-contracts/index.ts +2 -0
  15. package/dist/bundling-sources/shared_libs/monitors/analytics-install-guides.ts +77 -0
  16. package/dist/bundling-sources/shared_libs/monitors/analytics-public.ts +10 -0
  17. package/dist/bundling-sources/shared_libs/monitors/billing/charges.ts +125 -0
  18. package/dist/bundling-sources/shared_libs/monitors/billing/policy-builders.ts +686 -0
  19. package/dist/bundling-sources/shared_libs/monitors/billing/pricing.ts +54 -0
  20. package/dist/bundling-sources/shared_libs/monitors/billing/public-pricing.ts +72 -0
  21. package/dist/bundling-sources/shared_libs/monitors/billing/session.ts +45 -0
  22. package/dist/bundling-sources/shared_libs/monitors/billing/state.ts +454 -0
  23. package/dist/bundling-sources/shared_libs/monitors/billing/tamradar.ts +260 -0
  24. package/dist/bundling-sources/shared_libs/monitors/billing/types.ts +215 -0
  25. package/dist/bundling-sources/shared_libs/monitors/callback-security.ts +333 -0
  26. package/dist/bundling-sources/shared_libs/monitors/cursor-page.ts +42 -0
  27. package/dist/bundling-sources/shared_libs/monitors/deactivation-reasons.ts +16 -0
  28. package/dist/bundling-sources/shared_libs/monitors/framework-managed-payload-fields.ts +71 -0
  29. package/dist/bundling-sources/shared_libs/monitors/generated/provider-monitor-callback-admission-targets.ts +16 -0
  30. package/dist/bundling-sources/shared_libs/monitors/http-error-response.ts +270 -0
  31. package/dist/bundling-sources/shared_libs/monitors/inbound-publish-key.ts +39 -0
  32. package/dist/bundling-sources/shared_libs/monitors/inbound-queue.ts +82 -0
  33. package/dist/bundling-sources/shared_libs/monitors/inventory-reconciliation.ts +59 -0
  34. package/dist/bundling-sources/shared_libs/monitors/lifecycle-notifications.ts +471 -0
  35. package/dist/bundling-sources/shared_libs/monitors/org-monitor-limits.ts +1 -1
  36. package/dist/bundling-sources/shared_libs/monitors/package.json +36 -0
  37. package/dist/bundling-sources/shared_libs/monitors/provider-callback-verification.ts +1125 -0
  38. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-batch-operation.ts +305 -0
  39. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-capability.ts +964 -0
  40. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-consumer-health.ts +56 -0
  41. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-errors.ts +131 -0
  42. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-identity-claims.ts +535 -0
  43. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-legacy-aliases.ts +16 -0
  44. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-priority-execution.ts +56 -0
  45. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-public-aliases.ts +28 -0
  46. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-runtime-read-eligibility.ts +38 -0
  47. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-state.ts +122 -0
  48. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-status.ts +10 -0
  49. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-upstream-identity.ts +112 -0
  50. package/dist/bundling-sources/shared_libs/monitors/provider-webhook-monitor-runtime.ts +300 -0
  51. package/dist/bundling-sources/shared_libs/monitors/quickstart-prompts.ts +22 -0
  52. package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-dead-letter.ts +245 -0
  53. package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-message.ts +38 -0
  54. package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-queue-ack-probe.ts +94 -0
  55. package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-queue-delivery.ts +60 -0
  56. package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-queue.ts +60 -0
  57. package/dist/bundling-sources/shared_libs/monitors/snitcher-install-validation.ts +93 -0
  58. package/dist/bundling-sources/shared_libs/monitors/snitcher-ip2company.ts +332 -0
  59. package/dist/bundling-sources/shared_libs/monitors/snitcher-radar.ts +221 -0
  60. package/dist/bundling-sources/shared_libs/monitors/starter-templates.ts +105 -0
  61. package/dist/bundling-sources/shared_libs/monitors/tracking-provider-guidance.ts +73 -0
  62. package/dist/bundling-sources/shared_libs/monitors/tracking-provider-integrations.ts +81 -0
  63. package/dist/bundling-sources/shared_libs/monitors/tsconfig.json +10 -0
  64. package/dist/bundling-sources/shared_libs/observability/build-context.ts +13 -0
  65. package/dist/bundling-sources/shared_libs/observability/log-metadata.ts +160 -0
  66. package/dist/bundling-sources/shared_libs/observability/request-context.ts +68 -0
  67. package/dist/bundling-sources/shared_libs/observability/scheduled-jobs.json +654 -0
  68. package/dist/bundling-sources/shared_libs/observability/scheduled-work-manual.ts +35 -0
  69. package/dist/bundling-sources/shared_libs/observability/scheduled-work.ts +5 -0
  70. package/dist/bundling-sources/shared_libs/play-data-plane/neon-constants.ts +9 -0
  71. package/dist/bundling-sources/shared_libs/play-data-plane/r2.ts +272 -0
  72. package/dist/bundling-sources/shared_libs/play-runtime/activity-observation.ts +6 -11
  73. package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +135 -12
  74. package/dist/bundling-sources/shared_libs/play-runtime/async-operation.ts +66 -1
  75. package/dist/bundling-sources/shared_libs/play-runtime/async-play-invocation.ts +77 -0
  76. package/dist/bundling-sources/shared_libs/play-runtime/bounceban-batching.ts +137 -0
  77. package/dist/bundling-sources/shared_libs/play-runtime/checkpoint-boundaries.ts +70 -0
  78. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +1159 -166
  79. package/dist/bundling-sources/shared_libs/play-runtime/coordinator-headers.ts +1 -32
  80. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +103 -0
  81. package/dist/bundling-sources/shared_libs/play-runtime/daytona-payload-contract.ts +68 -0
  82. package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-janitor.ts +103 -0
  83. package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-reaper.ts +725 -0
  84. package/dist/bundling-sources/shared_libs/play-runtime/default-batch-strategies.ts +20 -1
  85. package/dist/bundling-sources/shared_libs/play-runtime/durable-call-cache.ts +29 -0
  86. package/dist/bundling-sources/shared_libs/play-runtime/execution-capabilities.ts +29 -0
  87. package/dist/bundling-sources/shared_libs/play-runtime/execution-gateway-invocation-fence.ts +442 -0
  88. package/dist/bundling-sources/shared_libs/play-runtime/execution-protocol.ts +7 -1
  89. package/dist/bundling-sources/shared_libs/play-runtime/fixture-behavior.ts +18 -0
  90. package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-rate-state-backend.ts +9 -0
  91. package/dist/bundling-sources/shared_libs/play-runtime/governor/policy.ts +1 -1
  92. package/dist/bundling-sources/shared_libs/play-runtime/governor/rate-state-backend.ts +1 -1
  93. package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/contracts.ts +66 -0
  94. package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/job.ts +145 -0
  95. package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/ports.ts +21 -0
  96. package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/postgres-store.ts +170 -0
  97. package/dist/bundling-sources/shared_libs/play-runtime/internal-bootstrap-token.ts +1322 -0
  98. package/dist/bundling-sources/shared_libs/play-runtime/internal-step-ids.ts +2 -2
  99. package/dist/bundling-sources/shared_libs/play-runtime/lane-retirement-gate.ts +189 -0
  100. package/dist/bundling-sources/shared_libs/play-runtime/launch-source-policy.ts +112 -0
  101. package/dist/bundling-sources/shared_libs/play-runtime/map-execution-frame.ts +8 -0
  102. package/dist/bundling-sources/shared_libs/play-runtime/perf-trace.ts +127 -0
  103. package/dist/bundling-sources/shared_libs/play-runtime/play-artifact-runtime-contract.ts +5 -0
  104. package/dist/bundling-sources/shared_libs/play-runtime/play-run-recovery-policy.ts +24 -1
  105. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/contracts.ts +56 -0
  106. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/index.ts +13 -0
  107. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/job.ts +41 -0
  108. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/ports.ts +17 -0
  109. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/postgres-adapter.ts +54 -0
  110. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/contracts.ts +114 -0
  111. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/engine-suspension.ts +108 -0
  112. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/index.ts +36 -0
  113. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/job.ts +97 -0
  114. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/ports.ts +104 -0
  115. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/postgres-fence-adapter.ts +263 -0
  116. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/worker-terminal-projection.ts +64 -0
  117. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/contracts.ts +29 -0
  118. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/gateway-adapter.ts +56 -0
  119. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/index.ts +15 -0
  120. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/job.ts +65 -0
  121. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/ports.ts +17 -0
  122. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/contracts.ts +42 -0
  123. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/index.ts +17 -0
  124. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/job.ts +142 -0
  125. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/ports.ts +42 -0
  126. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/postgres-adapter.ts +102 -0
  127. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/contracts.ts +60 -0
  128. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/index.ts +16 -0
  129. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/job.ts +78 -0
  130. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/ports.ts +54 -0
  131. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/postgres-adapter.ts +71 -0
  132. package/dist/bundling-sources/shared_libs/play-runtime/play-runtime-batching-registry.ts +4 -0
  133. package/dist/bundling-sources/shared_libs/play-runtime/play-runtime-semantics.ts +28 -0
  134. package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +4 -0
  135. package/dist/bundling-sources/shared_libs/play-runtime/receipt-status.ts +5 -8
  136. package/dist/bundling-sources/shared_libs/play-runtime/run-failure.ts +23 -2
  137. package/dist/bundling-sources/shared_libs/play-runtime/run-identity.ts +168 -0
  138. package/dist/bundling-sources/shared_libs/play-runtime/run-snapshot-stream.ts +1 -1
  139. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +90 -13
  140. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +6 -12
  141. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-start-admission.ts +68 -0
  142. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +21 -0
  143. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/bundle.ts +0 -1
  144. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/runtime-sandbox-reconciliation.ts +14 -43
  145. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +67 -213
  146. package/dist/bundling-sources/shared_libs/play-runtime/runtime-authority.ts +201 -0
  147. package/dist/bundling-sources/shared_libs/play-runtime/runtime-capacity-policy.ts +20 -0
  148. package/dist/bundling-sources/shared_libs/play-runtime/runtime-contract.ts +6 -0
  149. package/dist/bundling-sources/shared_libs/play-runtime/runtime-env.ts +12 -0
  150. package/dist/bundling-sources/shared_libs/play-runtime/runtime-operation-contract.ts +67 -0
  151. package/dist/bundling-sources/shared_libs/play-runtime/runtime-release-environment.ts +2 -0
  152. package/dist/bundling-sources/shared_libs/play-runtime/runtime-sandbox-contract.ts +68 -0
  153. package/dist/bundling-sources/shared_libs/play-runtime/runtime-scheduler-topology.ts +38 -2
  154. package/dist/bundling-sources/shared_libs/play-runtime/runtime-telemetry.ts +108 -0
  155. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/contract.ts +4 -0
  156. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/runner-backend-adapter.ts +3 -0
  157. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +37 -1
  158. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-deadline-reconciliation.ts +88 -0
  159. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-play-deploy-task.ts +124 -0
  160. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-play-run-task.ts +68 -0
  161. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-pool.ts +193 -0
  162. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-queue-lifecycle.ts +269 -0
  163. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-queue-suffix.ts +73 -0
  164. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +6642 -0
  165. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-shared.ts +897 -0
  166. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-worker-metrics.ts +120 -0
  167. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-worker-required-env.ts +76 -0
  168. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd.ts +476 -0
  169. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/gateway-heavy-request-admission.ts +47 -0
  170. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/gateway-progress-registry.ts +147 -0
  171. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/index.ts +27 -0
  172. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/lazy.ts +50 -0
  173. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/play-run-recovery.ts +98 -0
  174. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-budget-state.ts +260 -0
  175. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-pool.ts +1416 -0
  176. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-progress.ts +1255 -0
  177. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-rate-state.ts +942 -0
  178. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +14636 -0
  179. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/receipt-gateway.ts +888 -0
  180. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +355 -0
  181. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-terminal-transition.ts +46 -0
  182. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runner-push.ts +60 -0
  183. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-api-origin.ts +33 -0
  184. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-receipt-gateway-health.ts +64 -0
  185. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-capacity.ts +835 -0
  186. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-ledger-reconciliation.ts +1218 -0
  187. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-operation.ts +207 -0
  188. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-scheduler-schema.ts +10 -0
  189. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/scheduler-capacity.ts +123 -0
  190. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/scheduler-launch-read-observability.ts +78 -0
  191. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/submit-admission.ts +169 -0
  192. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/terminal-contract.ts +20 -0
  193. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/worker-queue-metrics.ts +34 -0
  194. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/worker-resource-metrics.ts +249 -0
  195. package/dist/bundling-sources/shared_libs/play-runtime/sheet-attempt-sql.ts +7 -0
  196. package/dist/bundling-sources/shared_libs/play-runtime/step-progress.ts +296 -0
  197. package/dist/bundling-sources/shared_libs/play-runtime/tool-call/native-batch.ts +3 -3
  198. package/dist/bundling-sources/shared_libs/play-runtime/tool-call/runtime-step-receipts-adapter.ts +20 -1
  199. package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +60 -15
  200. package/dist/bundling-sources/shared_libs/play-runtime/tool-execution-outcome.ts +20 -0
  201. package/dist/bundling-sources/shared_libs/play-runtime/tool-http-errors.ts +1 -1
  202. package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +1 -1
  203. package/dist/bundling-sources/shared_libs/play-runtime/transient-service-error.ts +12 -0
  204. package/dist/bundling-sources/shared_libs/play-runtime/vercel-protection.ts +14 -1
  205. package/dist/bundling-sources/shared_libs/play-runtime/work-receipt-storage-contract.ts +165 -0
  206. package/dist/bundling-sources/shared_libs/play-runtime/work-receipts.ts +15 -23
  207. package/dist/bundling-sources/shared_libs/play-runtime/workflow-executor-auth.ts +169 -0
  208. package/dist/bundling-sources/shared_libs/play-runtime/zerobounce-batching.ts +122 -0
  209. package/dist/bundling-sources/shared_libs/plays/artifact-types.ts +8 -3
  210. package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +454 -17
  211. package/dist/bundling-sources/shared_libs/plays/bundling/index.ts +19 -4
  212. package/dist/bundling-sources/shared_libs/plays/contracts.ts +8 -14
  213. package/dist/bundling-sources/shared_libs/plays/core.ts +11 -6
  214. package/dist/bundling-sources/shared_libs/plays/deployment-status.ts +1 -1
  215. package/dist/bundling-sources/shared_libs/plays/docflow-binding-owner.ts +16 -11
  216. package/dist/bundling-sources/shared_libs/plays/docflow.ts +1 -1
  217. package/dist/bundling-sources/shared_libs/plays/email-status.ts +1 -1
  218. package/dist/bundling-sources/shared_libs/plays/play-grep-search.ts +39 -0
  219. package/dist/bundling-sources/shared_libs/plays/resolve-static-pipeline.ts +1 -1
  220. package/dist/bundling-sources/shared_libs/plays/share/copy.ts +271 -0
  221. package/dist/bundling-sources/shared_libs/plays/share/metrics.ts +140 -0
  222. package/dist/bundling-sources/shared_libs/plays/share/public-read-model.ts +86 -0
  223. package/dist/bundling-sources/shared_libs/plays/share/seo-quality.ts +181 -0
  224. package/dist/bundling-sources/shared_libs/plays/share/static-pipeline-summary.ts +658 -0
  225. package/dist/bundling-sources/shared_libs/plays/share/types.ts +197 -0
  226. package/dist/bundling-sources/shared_libs/plays/slack-hitl-timeout-error.ts +37 -0
  227. package/dist/bundling-sources/shared_libs/plays/slug.ts +115 -0
  228. package/dist/bundling-sources/shared_libs/plays/static-pipeline.ts +50 -15
  229. package/dist/bundling-sources/shared_libs/plays/tool-category-descriptions.ts +2 -2
  230. package/dist/bundling-sources/shared_libs/plays/tool-result-types.ts +1 -1
  231. package/dist/bundling-sources/shared_libs/product-notifications/catalog.ts +877 -0
  232. package/dist/bundling-sources/shared_libs/product-notifications/configuration-draft.ts +456 -0
  233. package/dist/bundling-sources/shared_libs/product-notifications/configuration.ts +566 -0
  234. package/dist/bundling-sources/shared_libs/product-notifications/content.ts +28 -0
  235. package/dist/bundling-sources/shared_libs/product-notifications/default-policy.ts +60 -0
  236. package/dist/bundling-sources/shared_libs/product-notifications/email.ts +246 -0
  237. package/dist/bundling-sources/shared_libs/product-notifications/evaluation.ts +280 -0
  238. package/dist/bundling-sources/shared_libs/product-notifications/events.ts +433 -0
  239. package/dist/bundling-sources/shared_libs/product-notifications/legacy-slack.ts +80 -0
  240. package/dist/bundling-sources/shared_libs/product-notifications/overflow.ts +18 -0
  241. package/dist/bundling-sources/shared_libs/product-notifications/rolling-limit.ts +24 -0
  242. package/dist/bundling-sources/shared_libs/product-notifications/slack-delivery.ts +624 -0
  243. package/dist/bundling-sources/shared_libs/product-notifications/slack-payload.ts +140 -0
  244. package/dist/bundling-sources/shared_libs/product-notifications/slack-transport.ts +75 -0
  245. package/dist/bundling-sources/shared_libs/product-notifications/workspace.ts +38 -0
  246. package/dist/bundling-sources/shared_libs/runtime-env.ts +12 -0
  247. package/dist/bundling-sources/shared_libs/security/email-blacklist.ts +42 -0
  248. package/dist/bundling-sources/shared_libs/security/header-safe-env.ts +35 -0
  249. package/dist/bundling-sources/shared_libs/security/internal-actor.ts +50 -0
  250. package/dist/bundling-sources/shared_libs/security/secret-redaction.ts +267 -0
  251. package/dist/bundling-sources/shared_libs/security/slack-sanitize.ts +133 -0
  252. package/dist/cli/getting-started.d.mts +52 -0
  253. package/dist/cli/getting-started.d.ts +52 -0
  254. package/dist/cli/getting-started.js +65 -0
  255. package/dist/cli/getting-started.mjs +36 -0
  256. package/dist/cli/index.d.mts +9 -0
  257. package/dist/cli/index.d.ts +9 -0
  258. package/dist/cli/index.js +1611 -453
  259. package/dist/cli/index.mjs +1596 -447
  260. package/dist/{compiler-manifest-Dbov16F7.d.mts → compiler-manifest-BaJfE-5H.d.mts} +136 -10
  261. package/dist/{compiler-manifest-Dbov16F7.d.ts → compiler-manifest-BaJfE-5H.d.ts} +136 -10
  262. package/dist/index.d.mts +910 -155
  263. package/dist/index.d.ts +910 -155
  264. package/dist/index.js +550 -64
  265. package/dist/index.mjs +550 -64
  266. package/dist/install-integrity.json +193 -4
  267. package/dist/monitor-fleet-contract.d.mts +138 -0
  268. package/dist/monitor-fleet-contract.d.ts +138 -0
  269. package/dist/monitor-fleet-contract.js +404 -0
  270. package/dist/monitor-fleet-contract.mjs +367 -0
  271. package/dist/plays/bundle-play-file.d.mts +8 -3
  272. package/dist/plays/bundle-play-file.d.ts +8 -3
  273. package/dist/plays/bundle-play-file.mjs +100 -20
  274. package/dist/release.d.mts +255 -0
  275. package/dist/release.d.ts +255 -0
  276. package/dist/release.js +215 -0
  277. package/dist/release.mjs +188 -0
  278. package/package.json +23 -4
  279. /package/dist/bundling-sources/shared_libs/{integrations/bettercontact-execution-policy.ts → integration-contracts/bettercontact/execution-policy.ts} +0 -0
  280. /package/dist/bundling-sources/shared_libs/{integrations/theirstack-execution-policy.ts → integration-contracts/theirstack/execution-policy.ts} +0 -0
@@ -0,0 +1,566 @@
1
+ export type ProductNotificationFactValue = string | number | boolean;
2
+ export type ProductNotificationFacts = Record<
3
+ string,
4
+ ProductNotificationFactValue
5
+ >;
6
+
7
+ const PRODUCT_NOTIFICATION_EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
8
+
9
+ /** Normalize an email destination consistently across API, CLI, and delivery. */
10
+ export function normalizeProductNotificationEmail(
11
+ value: unknown,
12
+ ): string | null {
13
+ const email = typeof value === 'string' ? value.trim().toLowerCase() : '';
14
+ return email &&
15
+ email.length <= 320 &&
16
+ PRODUCT_NOTIFICATION_EMAIL_PATTERN.test(email)
17
+ ? email
18
+ : null;
19
+ }
20
+
21
+ export function normalizeProductNotificationEmailList(
22
+ values: readonly string[] | undefined,
23
+ label: string,
24
+ maximum = 50,
25
+ ) {
26
+ const normalized = (values ?? []).map((value) => {
27
+ const email = normalizeProductNotificationEmail(value);
28
+ if (!email) throw new Error(`${label} contains an invalid email address.`);
29
+ return email;
30
+ });
31
+ if (new Set(normalized).size !== normalized.length) {
32
+ throw new Error(`${label} contains a duplicate email address.`);
33
+ }
34
+ if (normalized.length > maximum) {
35
+ throw new Error(`${label} exceeds ${maximum} recipients.`);
36
+ }
37
+ return normalized;
38
+ }
39
+
40
+ export type ProductNotificationDestinationSettings =
41
+ | {
42
+ kind: 'slack';
43
+ targetKind: 'channel' | 'member';
44
+ targetId: string;
45
+ targetName: string;
46
+ oauthConnectionId: string;
47
+ }
48
+ | {
49
+ kind: 'email_addresses';
50
+ to: string[];
51
+ cc?: string[];
52
+ bcc?: string[];
53
+ }
54
+ | { kind: 'email_roles'; roles: string[] };
55
+
56
+ export type ProductNotificationTrigger =
57
+ | { kind: 'each_match' }
58
+ | { kind: 'state_transition'; targetState: string; reasonCode?: string }
59
+ | {
60
+ kind: 'threshold_crossing';
61
+ direction: 'above' | 'below' | 'at_or_above';
62
+ threshold: number;
63
+ unit?: string;
64
+ }
65
+ | {
66
+ kind: 'consecutive_outcomes';
67
+ count: number;
68
+ outcome: string;
69
+ maxLookback: number;
70
+ };
71
+
72
+ export type ProductNotificationDeliveryTiming =
73
+ | { mode: 'immediate' }
74
+ | {
75
+ mode: 'immediate_first' | 'digest_only' | 'rolling_limit';
76
+ windowMs: number;
77
+ };
78
+
79
+ export const DEFAULT_PRODUCT_NOTIFICATION_DELIVERY_TIMING: ProductNotificationDeliveryTiming =
80
+ {
81
+ mode: 'rolling_limit',
82
+ windowMs: 3_600_000,
83
+ };
84
+
85
+ export type ProductNotificationRepeatMode = 'on_enter' | 'every_match';
86
+
87
+ export type ProductNotificationDefaultPolicy = {
88
+ version: number;
89
+ groups: ProductNotificationDefaultGroup[];
90
+ destinations: ProductNotificationDefaultDestination[];
91
+ rules: ProductNotificationDefaultRule[];
92
+ };
93
+
94
+ export type ProductNotificationDefaultGroup = {
95
+ groupKey: string;
96
+ name: string;
97
+ enabled: boolean;
98
+ /** Omitted only by stored compatibility rows; effective groups are normalized. */
99
+ deliveryTiming?: ProductNotificationDeliveryTiming;
100
+ };
101
+
102
+ export type ProductNotificationDefaultDestination = {
103
+ destinationKey: string;
104
+ groupKey: string;
105
+ name: string;
106
+ enabled: boolean;
107
+ settings: ProductNotificationDestinationSettings;
108
+ };
109
+
110
+ export type ProductNotificationDefaultRule = {
111
+ ruleKey: string;
112
+ groupKey: string;
113
+ enabled: boolean;
114
+ notificationType: string;
115
+ eventName: string;
116
+ eventFilter: ProductNotificationFacts;
117
+ trigger: ProductNotificationTrigger;
118
+ /** Omitted only by stored compatibility rows; effective rules are normalized. */
119
+ repeatMode?: ProductNotificationRepeatMode;
120
+ /** Omitted only by stored compatibility rows; effective rules are normalized. */
121
+ conditionGeneration?: number;
122
+ };
123
+
124
+ export type ProductNotificationConfigMode =
125
+ | 'custom'
126
+ | 'replace_default'
127
+ | 'disable_default';
128
+
129
+ type WorkspaceOverride = {
130
+ configMode: ProductNotificationConfigMode;
131
+ defaultKey?: string;
132
+ };
133
+
134
+ export type ProductNotificationWorkspaceGroup =
135
+ ProductNotificationDefaultGroup & WorkspaceOverride & { version: number };
136
+
137
+ export type ProductNotificationWorkspaceDestination =
138
+ ProductNotificationDefaultDestination &
139
+ WorkspaceOverride & {
140
+ version: number;
141
+ status: string;
142
+ };
143
+
144
+ export type ProductNotificationWorkspaceRule = ProductNotificationDefaultRule &
145
+ WorkspaceOverride & { version: number };
146
+
147
+ /** The provider-neutral state edited by UI and CLI clients for one group. */
148
+ export type ProductNotificationGroupDraft = {
149
+ group: EffectiveProductNotificationGroup;
150
+ destinations: EffectiveProductNotificationDestination[];
151
+ rules: EffectiveProductNotificationRule[];
152
+ };
153
+
154
+ /** Public configuration intent. Convex alone derives sparse override writes. */
155
+ export type ProductNotificationConfigurationChange =
156
+ | { kind: 'save_group'; draft: ProductNotificationGroupDraft }
157
+ | { kind: 'delete_group'; groupKey: string };
158
+
159
+ export type EffectiveProductNotificationGroup = Omit<
160
+ ProductNotificationDefaultGroup,
161
+ 'deliveryTiming'
162
+ > & {
163
+ deliveryTiming: ProductNotificationDeliveryTiming;
164
+ source: 'default' | 'workspace';
165
+ configMode: 'default' | ProductNotificationConfigMode;
166
+ defaultKey?: string;
167
+ version: number;
168
+ };
169
+
170
+ export type EffectiveProductNotificationDestination =
171
+ ProductNotificationDefaultDestination & {
172
+ source: 'default' | 'workspace';
173
+ configMode: 'default' | ProductNotificationConfigMode;
174
+ defaultKey?: string;
175
+ version: number;
176
+ status: string;
177
+ };
178
+
179
+ export type EffectiveProductNotificationRule = Omit<
180
+ ProductNotificationDefaultRule,
181
+ 'repeatMode' | 'conditionGeneration'
182
+ > & {
183
+ repeatMode: ProductNotificationRepeatMode;
184
+ conditionGeneration: number;
185
+ source: 'default' | 'workspace';
186
+ configMode: 'default' | ProductNotificationConfigMode;
187
+ defaultKey?: string;
188
+ version: number;
189
+ };
190
+
191
+ export function normalizeProductNotificationRepeatMode(
192
+ value: ProductNotificationRepeatMode | undefined,
193
+ ): ProductNotificationRepeatMode {
194
+ return value ?? 'on_enter';
195
+ }
196
+
197
+ export function normalizeProductNotificationDeliveryTiming(
198
+ value: ProductNotificationDeliveryTiming | undefined,
199
+ ): ProductNotificationDeliveryTiming {
200
+ return value ?? { mode: 'immediate' };
201
+ }
202
+
203
+ export function validateProductNotificationDeliveryTiming(
204
+ timing: ProductNotificationDeliveryTiming,
205
+ ) {
206
+ if (timing.mode === 'immediate') return timing;
207
+ if (
208
+ !Number.isInteger(timing.windowMs) ||
209
+ timing.windowMs < 1_000 ||
210
+ timing.windowMs > 86_400_000
211
+ ) {
212
+ throw new Error('Notification digest window is outside its bounds.');
213
+ }
214
+ return timing;
215
+ }
216
+
217
+ export function normalizeProductNotificationConditionGeneration(
218
+ value: number | undefined,
219
+ ): number {
220
+ return value ?? 1;
221
+ }
222
+
223
+ function withoutLegacyRuleEmission(value: ProductNotificationDefaultRule) {
224
+ const { emission: _legacyEmission, ...rule } =
225
+ value as ProductNotificationDefaultRule & { emission?: unknown };
226
+ return rule;
227
+ }
228
+
229
+ export type EffectiveProductNotificationConfiguration = {
230
+ /** Exact policy used to materialize this effective configuration. */
231
+ defaultPolicy: ProductNotificationDefaultPolicy | null;
232
+ workspaceVersion: number;
233
+ groups: EffectiveProductNotificationGroup[];
234
+ destinations: EffectiveProductNotificationDestination[];
235
+ rules: EffectiveProductNotificationRule[];
236
+ };
237
+
238
+ type KeyedDefault = { [key: string]: unknown };
239
+ type KeyedOverride = WorkspaceOverride & { [key: string]: unknown };
240
+
241
+ export function productNotificationValuesEqual(
242
+ left: unknown,
243
+ right: unknown,
244
+ ): boolean {
245
+ if (Object.is(left, right)) return true;
246
+ if (Array.isArray(left) || Array.isArray(right)) {
247
+ return (
248
+ Array.isArray(left) &&
249
+ Array.isArray(right) &&
250
+ left.length === right.length &&
251
+ left.every((value, index) =>
252
+ productNotificationValuesEqual(value, right[index]),
253
+ )
254
+ );
255
+ }
256
+ if (
257
+ typeof left !== 'object' ||
258
+ left === null ||
259
+ typeof right !== 'object' ||
260
+ right === null
261
+ ) {
262
+ return false;
263
+ }
264
+ const leftRecord = left as Record<string, unknown>;
265
+ const rightRecord = right as Record<string, unknown>;
266
+ const leftKeys = Object.keys(leftRecord).filter(
267
+ (key) => leftRecord[key] !== undefined,
268
+ );
269
+ const rightKeys = Object.keys(rightRecord).filter(
270
+ (key) => rightRecord[key] !== undefined,
271
+ );
272
+ return (
273
+ leftKeys.length === rightKeys.length &&
274
+ leftKeys.every(
275
+ (key) =>
276
+ Object.prototype.hasOwnProperty.call(rightRecord, key) &&
277
+ productNotificationValuesEqual(leftRecord[key], rightRecord[key]),
278
+ )
279
+ );
280
+ }
281
+
282
+ function assertUniqueKeys<T extends KeyedDefault>(
283
+ values: readonly T[],
284
+ keyName: keyof T & string,
285
+ label: string,
286
+ ) {
287
+ const seen = new Set<string>();
288
+ for (const value of values) {
289
+ const key = value[keyName];
290
+ if (typeof key !== 'string' || key.length === 0) {
291
+ throw new Error(`${label} has an empty ${keyName}.`);
292
+ }
293
+ if (seen.has(key)) throw new Error(`Duplicate ${label} key: ${key}.`);
294
+ seen.add(key);
295
+ }
296
+ }
297
+
298
+ function overlayDefaults<
299
+ TDefault extends KeyedDefault,
300
+ TOverride extends KeyedOverride,
301
+ TEffective,
302
+ >(input: {
303
+ defaults: readonly TDefault[];
304
+ overrides: readonly TOverride[];
305
+ keyName: keyof TDefault & keyof TOverride & string;
306
+ label: string;
307
+ defaultVersion: number;
308
+ fromDefault: (value: TDefault, version: number) => TEffective;
309
+ fromWorkspace: (value: TOverride) => TEffective;
310
+ }) {
311
+ assertUniqueKeys(input.defaults, input.keyName, `default ${input.label}`);
312
+ assertUniqueKeys(input.overrides, input.keyName, `workspace ${input.label}`);
313
+
314
+ const defaultKeys = new Set(
315
+ input.defaults.map((value) => value[input.keyName] as string),
316
+ );
317
+ const effective = new Map<string, TEffective>();
318
+ for (const value of input.defaults) {
319
+ effective.set(
320
+ value[input.keyName] as string,
321
+ input.fromDefault(value, input.defaultVersion),
322
+ );
323
+ }
324
+
325
+ for (const value of input.overrides) {
326
+ const key = value[input.keyName] as string;
327
+ if (value.configMode === 'custom') {
328
+ if (value.defaultKey !== undefined) {
329
+ throw new Error(`Custom ${input.label} ${key} cannot name a default.`);
330
+ }
331
+ if (defaultKeys.has(key)) {
332
+ throw new Error(
333
+ `Custom ${input.label} ${key} conflicts with a default key.`,
334
+ );
335
+ }
336
+ effective.set(key, input.fromWorkspace(value));
337
+ continue;
338
+ }
339
+
340
+ if (!value.defaultKey || value.defaultKey !== key) {
341
+ throw new Error(
342
+ `${input.label} ${key} must use its own key as defaultKey.`,
343
+ );
344
+ }
345
+ if (value.configMode === 'disable_default') {
346
+ effective.delete(key);
347
+ } else {
348
+ effective.set(key, input.fromWorkspace(value));
349
+ }
350
+ }
351
+
352
+ return [...effective.values()];
353
+ }
354
+
355
+ /**
356
+ * Materialize the one effective configuration shared by settings surfaces and
357
+ * asynchronous event processing. The function is deliberately pure so copy-
358
+ * on-write behavior can be tested without starting notification delivery.
359
+ */
360
+ export function resolveEffectiveProductNotificationConfiguration(input: {
361
+ policy: ProductNotificationDefaultPolicy;
362
+ workspaceVersion?: number;
363
+ groups: readonly ProductNotificationWorkspaceGroup[];
364
+ destinations: readonly ProductNotificationWorkspaceDestination[];
365
+ rules: readonly ProductNotificationWorkspaceRule[];
366
+ }): EffectiveProductNotificationConfiguration {
367
+ const workspaceVersion = input.workspaceVersion ?? 0;
368
+ const defaultGroupKeys = new Set(
369
+ input.policy.groups.map((group) => group.groupKey),
370
+ );
371
+ const defaultDestinationGroups = new Map(
372
+ input.policy.destinations.map((destination) => [
373
+ destination.destinationKey,
374
+ destination.groupKey,
375
+ ]),
376
+ );
377
+ const destinationOverrides = new Map(
378
+ input.destinations.map((destination) => [
379
+ destination.destinationKey,
380
+ destination,
381
+ ]),
382
+ );
383
+ const defaultRuleGroups = new Map(
384
+ input.policy.rules.map((rule) => [rule.ruleKey, rule.groupKey]),
385
+ );
386
+ const ruleOverrides = new Map(
387
+ input.rules.map((rule) => [rule.ruleKey, rule]),
388
+ );
389
+ const replacedDefaultGroupKeys = new Set(
390
+ input.groups
391
+ .filter((group) => group.configMode === 'replace_default')
392
+ .map((group) => group.groupKey),
393
+ );
394
+ for (const destination of input.policy.destinations) {
395
+ if (!defaultGroupKeys.has(destination.groupKey)) {
396
+ throw new Error(
397
+ `Default destination ${destination.destinationKey} references missing group ${destination.groupKey}.`,
398
+ );
399
+ }
400
+ }
401
+ for (const rule of input.policy.rules) {
402
+ if (!defaultGroupKeys.has(rule.groupKey)) {
403
+ throw new Error(
404
+ `Default rule ${rule.ruleKey} references missing group ${rule.groupKey}.`,
405
+ );
406
+ }
407
+ }
408
+
409
+ const groups = overlayDefaults<
410
+ ProductNotificationDefaultGroup,
411
+ ProductNotificationWorkspaceGroup,
412
+ EffectiveProductNotificationGroup
413
+ >({
414
+ defaults: input.policy.groups,
415
+ overrides: input.groups,
416
+ keyName: 'groupKey',
417
+ label: 'group',
418
+ defaultVersion: input.policy.version,
419
+ fromDefault: (value, version) => ({
420
+ ...value,
421
+ deliveryTiming: normalizeProductNotificationDeliveryTiming(
422
+ value.deliveryTiming,
423
+ ),
424
+ source: 'default' as const,
425
+ configMode: 'default' as const,
426
+ version,
427
+ }),
428
+ fromWorkspace: (value) => ({
429
+ groupKey: value.groupKey,
430
+ name: value.name,
431
+ enabled: value.enabled,
432
+ deliveryTiming: normalizeProductNotificationDeliveryTiming(
433
+ value.deliveryTiming,
434
+ ),
435
+ source: 'workspace' as const,
436
+ configMode: value.configMode,
437
+ defaultKey: value.defaultKey,
438
+ version: value.version,
439
+ }),
440
+ });
441
+ const groupKeys = new Set(groups.map((group) => group.groupKey));
442
+
443
+ const destinations = overlayDefaults<
444
+ ProductNotificationDefaultDestination,
445
+ ProductNotificationWorkspaceDestination,
446
+ EffectiveProductNotificationDestination
447
+ >({
448
+ defaults: input.policy.destinations.filter(
449
+ (destination) =>
450
+ !replacedDefaultGroupKeys.has(destination.groupKey) ||
451
+ destinationOverrides.has(destination.destinationKey),
452
+ ),
453
+ overrides: input.destinations,
454
+ keyName: 'destinationKey',
455
+ label: 'destination',
456
+ defaultVersion: input.policy.version,
457
+ fromDefault: (value, version) => ({
458
+ ...value,
459
+ source: 'default' as const,
460
+ configMode: 'default' as const,
461
+ version,
462
+ status: 'active',
463
+ }),
464
+ fromWorkspace: (value) => ({
465
+ destinationKey: value.destinationKey,
466
+ groupKey: value.groupKey,
467
+ name: value.name,
468
+ enabled: value.enabled,
469
+ settings: value.settings,
470
+ status: value.status,
471
+ source: 'workspace' as const,
472
+ configMode: value.configMode,
473
+ defaultKey: value.defaultKey,
474
+ version: value.version,
475
+ }),
476
+ }).filter((destination) => {
477
+ if (groupKeys.has(destination.groupKey)) return true;
478
+ const override = destinationOverrides.get(destination.destinationKey);
479
+ const isInheritedChild =
480
+ destination.source === 'default' ||
481
+ (override?.configMode === 'replace_default' &&
482
+ defaultDestinationGroups.get(destination.destinationKey) ===
483
+ destination.groupKey);
484
+ if (isInheritedChild && defaultGroupKeys.has(destination.groupKey)) {
485
+ return false;
486
+ }
487
+ throw new Error(
488
+ `${destination.source === 'default' ? 'Default' : 'Workspace'} destination ${destination.destinationKey} references missing group ${destination.groupKey}.`,
489
+ );
490
+ });
491
+
492
+ const rules = overlayDefaults<
493
+ ProductNotificationDefaultRule,
494
+ ProductNotificationWorkspaceRule,
495
+ EffectiveProductNotificationRule
496
+ >({
497
+ defaults: input.policy.rules.filter(
498
+ (rule) =>
499
+ !replacedDefaultGroupKeys.has(rule.groupKey) ||
500
+ ruleOverrides.has(rule.ruleKey),
501
+ ),
502
+ overrides: input.rules,
503
+ keyName: 'ruleKey',
504
+ label: 'rule',
505
+ defaultVersion: input.policy.version,
506
+ fromDefault: (value, version) => ({
507
+ ...withoutLegacyRuleEmission(value),
508
+ repeatMode: normalizeProductNotificationRepeatMode(value.repeatMode),
509
+ conditionGeneration: normalizeProductNotificationConditionGeneration(
510
+ value.conditionGeneration,
511
+ ),
512
+ source: 'default' as const,
513
+ configMode: 'default' as const,
514
+ version,
515
+ }),
516
+ fromWorkspace: (value) => ({
517
+ ruleKey: value.ruleKey,
518
+ groupKey: value.groupKey,
519
+ enabled: value.enabled,
520
+ notificationType: value.notificationType,
521
+ eventName: value.eventName,
522
+ eventFilter: value.eventFilter,
523
+ trigger: value.trigger,
524
+ repeatMode: normalizeProductNotificationRepeatMode(value.repeatMode),
525
+ conditionGeneration: normalizeProductNotificationConditionGeneration(
526
+ value.conditionGeneration,
527
+ ),
528
+ source: 'workspace' as const,
529
+ configMode: value.configMode,
530
+ defaultKey: value.defaultKey,
531
+ version: value.version,
532
+ }),
533
+ }).filter((rule) => {
534
+ if (groupKeys.has(rule.groupKey)) return true;
535
+ const override = ruleOverrides.get(rule.ruleKey);
536
+ const isInheritedChild =
537
+ rule.source === 'default' ||
538
+ (override?.configMode === 'replace_default' &&
539
+ defaultRuleGroups.get(rule.ruleKey) === rule.groupKey);
540
+ if (isInheritedChild && defaultGroupKeys.has(rule.groupKey)) {
541
+ return false;
542
+ }
543
+ throw new Error(
544
+ `${rule.source === 'default' ? 'Default' : 'Workspace'} rule ${rule.ruleKey} references missing group ${rule.groupKey}.`,
545
+ );
546
+ });
547
+
548
+ return {
549
+ defaultPolicy: {
550
+ version: input.policy.version,
551
+ groups: input.policy.groups,
552
+ destinations: input.policy.destinations,
553
+ rules: input.policy.rules.map((rule) => ({
554
+ ...rule,
555
+ repeatMode: normalizeProductNotificationRepeatMode(rule.repeatMode),
556
+ conditionGeneration: normalizeProductNotificationConditionGeneration(
557
+ rule.conditionGeneration,
558
+ ),
559
+ })),
560
+ },
561
+ workspaceVersion,
562
+ groups,
563
+ destinations,
564
+ rules,
565
+ };
566
+ }
@@ -0,0 +1,28 @@
1
+ /** Type-owned content, independent of email markup and persisted audit strings. */
2
+ export type NotificationText =
3
+ | string
4
+ | readonly (string | { strong: string } | { workspace: true })[];
5
+
6
+ export function notificationText(
7
+ content: NotificationText,
8
+ workspaceName?: string,
9
+ ): string {
10
+ if (typeof content === 'string') return content;
11
+ return content
12
+ .map((part) => {
13
+ if (typeof part === 'string') return part;
14
+ if ('strong' in part) return part.strong;
15
+ return workspaceName ? `workspace ${workspaceName}` : 'workspace';
16
+ })
17
+ .join('');
18
+ }
19
+
20
+ export function joinNotificationText(
21
+ contents: NotificationText[],
22
+ separator: string,
23
+ ): NotificationText {
24
+ return contents.flatMap((content, index) => [
25
+ ...(index ? [separator] : []),
26
+ ...(typeof content === 'string' ? [content] : content),
27
+ ]);
28
+ }
@@ -0,0 +1,60 @@
1
+ import {
2
+ PRODUCT_NOTIFICATION_DEFAULT_RULES,
3
+ validateProductNotificationRuleDefinition,
4
+ } from './catalog';
5
+ import {
6
+ DEFAULT_PRODUCT_NOTIFICATION_DELIVERY_TIMING,
7
+ resolveEffectiveProductNotificationConfiguration,
8
+ validateProductNotificationDeliveryTiming,
9
+ type ProductNotificationDefaultPolicy,
10
+ } from './configuration';
11
+
12
+ /**
13
+ * Product defaults stay in code. Workspaces see these rows synthetically until
14
+ * they create sparse copy-on-write overrides.
15
+ */
16
+ export const CURRENT_PRODUCT_NOTIFICATION_DEFAULT_POLICY = {
17
+ version: 5,
18
+ groups: [
19
+ {
20
+ groupKey: 'default',
21
+ name: 'Default Notifications',
22
+ enabled: true,
23
+ deliveryTiming: DEFAULT_PRODUCT_NOTIFICATION_DELIVERY_TIMING,
24
+ },
25
+ ],
26
+ destinations: [
27
+ {
28
+ destinationKey: 'default.roles',
29
+ groupKey: 'default',
30
+ name: 'Workspace owners',
31
+ enabled: true,
32
+ settings: { kind: 'email_roles', roles: ['owner'] },
33
+ },
34
+ ],
35
+ rules: PRODUCT_NOTIFICATION_DEFAULT_RULES,
36
+ } satisfies ProductNotificationDefaultPolicy;
37
+
38
+ /** Validate the complete code-owned policy. */
39
+ export function validateProductNotificationDefaultPolicy(
40
+ policy: ProductNotificationDefaultPolicy,
41
+ ) {
42
+ if (!Number.isInteger(policy.version) || policy.version < 1) {
43
+ throw new Error('Notification default policy version must be positive.');
44
+ }
45
+ resolveEffectiveProductNotificationConfiguration({
46
+ policy,
47
+ groups: [],
48
+ destinations: [],
49
+ rules: [],
50
+ });
51
+ for (const rule of policy.rules) {
52
+ validateProductNotificationRuleDefinition(rule);
53
+ }
54
+ for (const group of policy.groups) {
55
+ validateProductNotificationDeliveryTiming(
56
+ group.deliveryTiming ?? { mode: 'immediate' },
57
+ );
58
+ }
59
+ return policy;
60
+ }