@pikku/core 0.12.72 → 0.12.74

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 (811) hide show
  1. package/CHANGELOG.md +793 -0
  2. package/dist/crypto-utils.d.ts +30 -5
  3. package/dist/crypto-utils.js +146 -41
  4. package/dist/dev/hot-reload.js +11 -30
  5. package/dist/dev/module-runner.d.ts +3 -7
  6. package/dist/dev/module-runner.js +4 -10
  7. package/dist/dev/reload-meta.d.ts +8 -20
  8. package/dist/dev/reload-meta.js +9 -29
  9. package/dist/errors/error-handler.d.ts +5 -30
  10. package/dist/errors/error-handler.js +16 -32
  11. package/dist/errors/errors.d.ts +32 -151
  12. package/dist/errors/errors.js +55 -157
  13. package/dist/function/abort-scope.d.ts +47 -0
  14. package/dist/function/abort-scope.js +63 -0
  15. package/dist/function/function-runner.js +37 -32
  16. package/dist/function/functions.types.d.ts +44 -136
  17. package/dist/function/functions.types.js +0 -58
  18. package/dist/function/list.types.d.ts +12 -62
  19. package/dist/function/list.types.js +4 -25
  20. package/dist/handle-error.d.ts +0 -13
  21. package/dist/handle-error.js +0 -18
  22. package/dist/index.d.ts +5 -2
  23. package/dist/index.js +4 -1
  24. package/dist/middleware/auth-apikey.d.ts +3 -18
  25. package/dist/middleware/auth-apikey.js +0 -17
  26. package/dist/middleware/auth-bearer.d.ts +6 -41
  27. package/dist/middleware/auth-bearer.js +3 -40
  28. package/dist/middleware/auth-cookie.d.ts +5 -27
  29. package/dist/middleware/auth-cookie.js +2 -26
  30. package/dist/middleware/cors.d.ts +7 -34
  31. package/dist/middleware/cors.js +7 -34
  32. package/dist/middleware/remote-auth.d.ts +3 -1
  33. package/dist/middleware/remote-auth.js +3 -2
  34. package/dist/middleware/telemetry.d.ts +8 -33
  35. package/dist/middleware/telemetry.js +2 -31
  36. package/dist/middleware-runner.d.ts +4 -55
  37. package/dist/middleware-runner.js +5 -74
  38. package/dist/permissions.d.ts +3 -44
  39. package/dist/permissions.js +19 -71
  40. package/dist/pikku-request.d.ts +0 -6
  41. package/dist/pikku-request.js +0 -6
  42. package/dist/pikku-state.d.ts +0 -26
  43. package/dist/pikku-state.js +2 -30
  44. package/dist/remote.d.ts +3 -5
  45. package/dist/remote.js +8 -7
  46. package/dist/schema.d.ts +5 -39
  47. package/dist/schema.js +5 -39
  48. package/dist/scopes.d.ts +4 -23
  49. package/dist/scopes.js +7 -48
  50. package/dist/services/ai-agent-runner-service.d.ts +20 -0
  51. package/dist/services/ai-embedding-service.d.ts +2 -25
  52. package/dist/services/audit-service.js +1 -2
  53. package/dist/services/content-service.d.ts +1 -46
  54. package/dist/services/credential-service.d.ts +3 -40
  55. package/dist/services/deployment-service.d.ts +3 -9
  56. package/dist/services/gateway-service.d.ts +0 -15
  57. package/dist/services/http-personas.d.ts +80 -0
  58. package/dist/services/http-personas.js +233 -0
  59. package/dist/services/in-memory-queue-service.d.ts +0 -14
  60. package/dist/services/in-memory-queue-service.js +1 -15
  61. package/dist/services/in-memory-trigger-service.d.ts +0 -18
  62. package/dist/services/in-memory-trigger-service.js +1 -18
  63. package/dist/services/in-memory-workflow-service.d.ts +0 -16
  64. package/dist/services/in-memory-workflow-service.js +4 -33
  65. package/dist/services/index.d.ts +5 -6
  66. package/dist/services/index.js +2 -5
  67. package/dist/services/istanbul-coverage-service.d.ts +1 -5
  68. package/dist/services/istanbul-coverage-service.js +2 -8
  69. package/dist/services/jwt-service.d.ts +1 -16
  70. package/dist/services/local-content.d.ts +13 -2
  71. package/dist/services/local-content.js +40 -13
  72. package/dist/services/local-gateway-service.d.ts +0 -16
  73. package/dist/services/local-gateway-service.js +2 -17
  74. package/dist/services/local-secrets.d.ts +0 -4
  75. package/dist/services/local-secrets.js +0 -4
  76. package/dist/services/logger-console.d.ts +3 -7
  77. package/dist/services/logger-console.js +3 -7
  78. package/dist/services/logger.d.ts +2 -37
  79. package/dist/services/meta-service.d.ts +23 -26
  80. package/dist/services/meta-service.js +22 -36
  81. package/dist/services/personas-service.d.ts +134 -0
  82. package/dist/services/personas-service.js +40 -0
  83. package/dist/services/pikku-user-id.js +0 -4
  84. package/dist/services/queue-webhook-service.d.ts +2 -36
  85. package/dist/services/queue-webhook-service.js +9 -41
  86. package/dist/services/scheduler-service.d.ts +1 -50
  87. package/dist/services/scheduler-service.js +0 -10
  88. package/dist/services/schema-service.d.ts +1 -24
  89. package/dist/services/scope-service.d.ts +49 -34
  90. package/dist/services/scoped-secret-service.d.ts +0 -4
  91. package/dist/services/scoped-secret-service.js +0 -4
  92. package/dist/services/secret-host-binding.d.ts +8 -0
  93. package/dist/services/secret-host-binding.js +36 -0
  94. package/dist/services/secret-service.d.ts +5 -33
  95. package/dist/services/secretless.d.ts +6 -0
  96. package/dist/services/secretless.js +21 -0
  97. package/dist/services/stub-tracker.d.ts +7 -18
  98. package/dist/services/stub-tracker.js +8 -18
  99. package/dist/services/system-role-guard.d.ts +33 -0
  100. package/dist/services/system-role-guard.js +38 -0
  101. package/dist/services/trigger-service.d.ts +0 -12
  102. package/dist/services/typed-secret-service.d.ts +0 -7
  103. package/dist/services/typed-secret-service.js +1 -7
  104. package/dist/services/v8-coverage-service.d.ts +2 -3
  105. package/dist/services/v8-coverage-service.js +1 -2
  106. package/dist/services/variables-service.d.ts +1 -8
  107. package/dist/services/webhook-service.d.ts +19 -63
  108. package/dist/services/webhook-service.js +6 -20
  109. package/dist/services/workflow-service.d.ts +3 -15
  110. package/dist/testing/service-tests.js +0 -17
  111. package/dist/time-utils.d.ts +0 -16
  112. package/dist/time-utils.js +1 -19
  113. package/dist/types/core.types.d.ts +99 -219
  114. package/dist/types/core.types.js +0 -42
  115. package/dist/types/state.types.d.ts +4 -9
  116. package/dist/utils/hmac.d.ts +4 -10
  117. package/dist/utils/hmac.js +4 -10
  118. package/dist/utils/safe-fetch.d.ts +7 -35
  119. package/dist/utils/safe-fetch.js +13 -53
  120. package/dist/utils.d.ts +1 -6
  121. package/dist/utils.js +6 -15
  122. package/dist/wirings/actor-flow/actor-flow.types.d.ts +1 -34
  123. package/dist/wirings/actor-flow/index.d.ts +0 -9
  124. package/dist/wirings/actor-flow/run-conversation.d.ts +5 -5
  125. package/dist/wirings/actor-flow/run-conversation.js +14 -7
  126. package/dist/wirings/ai-agent/ai-agent-agui.d.ts +0 -5
  127. package/dist/wirings/ai-agent/ai-agent-agui.js +34 -12
  128. package/dist/wirings/ai-agent/ai-agent-helpers.d.ts +7 -0
  129. package/dist/wirings/ai-agent/ai-agent-helpers.js +7 -0
  130. package/dist/wirings/ai-agent/ai-agent-interrupt.d.ts +153 -0
  131. package/dist/wirings/ai-agent/ai-agent-interrupt.js +256 -0
  132. package/dist/wirings/ai-agent/ai-agent-memory.js +0 -2
  133. package/dist/wirings/ai-agent/ai-agent-model-config.d.ts +0 -9
  134. package/dist/wirings/ai-agent/ai-agent-model-config.js +1 -9
  135. package/dist/wirings/ai-agent/ai-agent-prepare.d.ts +10 -99
  136. package/dist/wirings/ai-agent/ai-agent-prepare.js +58 -131
  137. package/dist/wirings/ai-agent/ai-agent-registry.d.ts +2 -1
  138. package/dist/wirings/ai-agent/ai-agent-registry.js +5 -1
  139. package/dist/wirings/ai-agent/ai-agent-runner.js +49 -20
  140. package/dist/wirings/ai-agent/ai-agent-stream.d.ts +25 -2
  141. package/dist/wirings/ai-agent/ai-agent-stream.js +153 -63
  142. package/dist/wirings/ai-agent/ai-agent.types.d.ts +84 -4
  143. package/dist/wirings/ai-agent/index.d.ts +6 -4
  144. package/dist/wirings/ai-agent/index.js +5 -4
  145. package/dist/wirings/ai-agent/voice-input.d.ts +39 -1
  146. package/dist/wirings/ai-agent/voice-input.js +46 -3
  147. package/dist/wirings/ai-agent/voice-output.d.ts +54 -1
  148. package/dist/wirings/ai-agent/voice-output.js +153 -50
  149. package/dist/wirings/channel/channel-common.d.ts +7 -20
  150. package/dist/wirings/channel/channel-common.js +7 -21
  151. package/dist/wirings/channel/channel-handler.js +25 -6
  152. package/dist/wirings/channel/channel-host-rpc.d.ts +25 -0
  153. package/dist/wirings/channel/channel-host-rpc.js +38 -0
  154. package/dist/wirings/channel/channel-middleware-runner.d.ts +0 -12
  155. package/dist/wirings/channel/channel-middleware-runner.js +0 -12
  156. package/dist/wirings/channel/channel-rpc-registry.d.ts +31 -0
  157. package/dist/wirings/channel/channel-rpc-registry.js +89 -0
  158. package/dist/wirings/channel/channel-rpc-responder.d.ts +15 -0
  159. package/dist/wirings/channel/channel-rpc-responder.js +71 -0
  160. package/dist/wirings/channel/channel-rpc-service.d.ts +40 -0
  161. package/dist/wirings/channel/channel-rpc-service.js +106 -0
  162. package/dist/wirings/channel/channel-rpc-validators.d.ts +14 -0
  163. package/dist/wirings/channel/channel-rpc-validators.js +30 -0
  164. package/dist/wirings/channel/channel-rpc.d.ts +5 -0
  165. package/dist/wirings/channel/channel-rpc.js +5 -0
  166. package/dist/wirings/channel/channel-rpc.types.d.ts +90 -0
  167. package/dist/wirings/channel/channel-rpc.types.js +50 -0
  168. package/dist/wirings/channel/channel-runner.d.ts +0 -4
  169. package/dist/wirings/channel/channel-runner.js +0 -14
  170. package/dist/wirings/channel/channel-store.d.ts +0 -10
  171. package/dist/wirings/channel/channel.types.d.ts +12 -1
  172. package/dist/wirings/channel/define-channel-routes.d.ts +0 -20
  173. package/dist/wirings/channel/define-channel-routes.js +0 -20
  174. package/dist/wirings/channel/eventhub-service.d.ts +0 -18
  175. package/dist/wirings/channel/index.d.ts +4 -1
  176. package/dist/wirings/channel/index.js +2 -0
  177. package/dist/wirings/channel/local/local-channel-runner.js +3 -1
  178. package/dist/wirings/channel/local/local-eventhub-service.d.ts +0 -33
  179. package/dist/wirings/channel/local/local-eventhub-service.js +2 -36
  180. package/dist/wirings/channel/log-channels.d.ts +0 -4
  181. package/dist/wirings/channel/log-channels.js +0 -4
  182. package/dist/wirings/channel/pikku-abstract-channel-handler.js +6 -0
  183. package/dist/wirings/channel/serverless/serverless-channel-runner.js +2 -5
  184. package/dist/wirings/cli/channel/cli-approval.d.ts +41 -0
  185. package/dist/wirings/cli/channel/cli-approval.js +81 -0
  186. package/dist/wirings/cli/channel/cli-channel-runner.d.ts +0 -4
  187. package/dist/wirings/cli/channel/cli-channel-runner.js +3 -25
  188. package/dist/wirings/cli/channel/cli-raw-channel-runner.d.ts +47 -9
  189. package/dist/wirings/cli/channel/cli-raw-channel-runner.js +24 -16
  190. package/dist/wirings/cli/channel/cli-raw-client-runner.d.ts +20 -0
  191. package/dist/wirings/cli/channel/cli-raw-client-runner.js +121 -0
  192. package/dist/wirings/cli/channel/index.d.ts +4 -0
  193. package/dist/wirings/cli/channel/index.js +2 -0
  194. package/dist/wirings/cli/cli-runner.d.ts +20 -20
  195. package/dist/wirings/cli/cli-runner.js +28 -89
  196. package/dist/wirings/cli/cli.types.d.ts +14 -3
  197. package/dist/wirings/cli/command-parser.d.ts +1 -10
  198. package/dist/wirings/cli/command-parser.js +10 -87
  199. package/dist/wirings/cli/define-cli-commands.d.ts +1 -17
  200. package/dist/wirings/cli/define-cli-commands.js +1 -17
  201. package/dist/wirings/credential/credential.types.d.ts +0 -12
  202. package/dist/wirings/credential/define-credential.d.ts +48 -0
  203. package/dist/wirings/credential/define-credential.js +47 -0
  204. package/dist/wirings/credential/index.d.ts +1 -1
  205. package/dist/wirings/credential/index.js +1 -1
  206. package/dist/wirings/credential/validate-credential-definitions.d.ts +2 -4
  207. package/dist/wirings/gateway/gateway-runner.d.ts +1 -20
  208. package/dist/wirings/gateway/gateway-runner.js +8 -105
  209. package/dist/wirings/gateway/gateway.types.d.ts +7 -80
  210. package/dist/wirings/http/http-routes.d.ts +0 -63
  211. package/dist/wirings/http/http-routes.js +0 -63
  212. package/dist/wirings/http/http-runner.d.ts +0 -99
  213. package/dist/wirings/http/http-runner.js +9 -165
  214. package/dist/wirings/http/http.types.d.ts +14 -55
  215. package/dist/wirings/http/log-http-routes.d.ts +0 -4
  216. package/dist/wirings/http/log-http-routes.js +0 -4
  217. package/dist/wirings/http/pikku-fetch-http-request.d.ts +0 -40
  218. package/dist/wirings/http/pikku-fetch-http-request.js +0 -58
  219. package/dist/wirings/http/pikku-fetch-http-response.js +0 -3
  220. package/dist/wirings/http/routers/path-to-regex.js +2 -13
  221. package/dist/wirings/http/web-request.d.ts +0 -8
  222. package/dist/wirings/http/web-request.js +25 -17
  223. package/dist/wirings/mcp/mcp-runner.d.ts +1 -4
  224. package/dist/wirings/mcp/mcp-runner.js +1 -14
  225. package/dist/wirings/mcp/mcp.types.d.ts +2 -35
  226. package/dist/wirings/oauth2/oauth2.types.d.ts +0 -28
  227. package/dist/wirings/oauth2/oauth2.types.js +0 -3
  228. package/dist/wirings/persona/define-personas.d.ts +28 -0
  229. package/dist/wirings/persona/define-personas.js +27 -0
  230. package/dist/wirings/persona/index.d.ts +21 -0
  231. package/dist/wirings/persona/index.js +17 -0
  232. package/dist/wirings/persona/persona-email.d.ts +37 -0
  233. package/dist/wirings/persona/persona-email.js +69 -0
  234. package/dist/wirings/persona/persona-environments.d.ts +45 -0
  235. package/dist/wirings/persona/persona-environments.js +81 -0
  236. package/dist/wirings/persona/persona-mailbox.d.ts +101 -0
  237. package/dist/wirings/persona/persona-mailbox.js +53 -0
  238. package/dist/wirings/persona/persona.types.d.ts +125 -0
  239. package/dist/wirings/persona/persona.types.js +1 -0
  240. package/dist/wirings/persona/validate-personas.d.ts +53 -0
  241. package/dist/wirings/persona/validate-personas.js +94 -0
  242. package/dist/wirings/queue/index.d.ts +3 -0
  243. package/dist/wirings/queue/index.js +2 -3
  244. package/dist/wirings/queue/queue-identity.d.ts +28 -0
  245. package/dist/wirings/queue/queue-identity.js +102 -0
  246. package/dist/wirings/queue/queue-runner.d.ts +0 -19
  247. package/dist/wirings/queue/queue-runner.js +9 -30
  248. package/dist/wirings/queue/queue.types.d.ts +18 -89
  249. package/dist/wirings/queue/register-queue-helper.d.ts +0 -12
  250. package/dist/wirings/queue/register-queue-helper.js +0 -11
  251. package/dist/wirings/queue/signed-queue-service.d.ts +16 -0
  252. package/dist/wirings/queue/signed-queue-service.js +42 -0
  253. package/dist/wirings/queue/validate-worker-config.d.ts +2 -23
  254. package/dist/wirings/queue/validate-worker-config.js +0 -14
  255. package/dist/wirings/role/define-system-role.d.ts +32 -0
  256. package/dist/wirings/role/define-system-role.js +31 -0
  257. package/dist/wirings/role/index.d.ts +3 -0
  258. package/dist/wirings/role/index.js +2 -0
  259. package/dist/wirings/role/role.types.d.ts +43 -0
  260. package/dist/wirings/role/role.types.js +1 -0
  261. package/dist/wirings/role/validate-role-definitions.d.ts +21 -0
  262. package/dist/wirings/role/validate-role-definitions.js +71 -0
  263. package/dist/wirings/rpc/addon-runner.d.ts +0 -19
  264. package/dist/wirings/rpc/addon-runner.js +0 -51
  265. package/dist/wirings/rpc/remote-addon-auth.d.ts +1 -12
  266. package/dist/wirings/rpc/remote-addon-auth.js +1 -9
  267. package/dist/wirings/rpc/rpc-runner.d.ts +11 -18
  268. package/dist/wirings/rpc/rpc-runner.js +88 -105
  269. package/dist/wirings/rpc/rpc-types.d.ts +7 -6
  270. package/dist/wirings/rpc/wire-addon.d.ts +25 -0
  271. package/dist/wirings/rpc/wire-addon.js +62 -0
  272. package/dist/wirings/rpc/wire-remote-addon.d.ts +3 -28
  273. package/dist/wirings/rpc/wire-remote-addon.js +0 -8
  274. package/dist/wirings/scheduler/log-schedulers.d.ts +0 -4
  275. package/dist/wirings/scheduler/log-schedulers.js +0 -4
  276. package/dist/wirings/scheduler/scheduler-runner.d.ts +0 -1
  277. package/dist/wirings/scheduler/scheduler-runner.js +0 -1
  278. package/dist/wirings/scheduler/scheduler.types.d.ts +1 -14
  279. package/dist/wirings/scope/define-scope.d.ts +32 -0
  280. package/dist/wirings/scope/define-scope.js +31 -0
  281. package/dist/wirings/scope/index.d.ts +1 -1
  282. package/dist/wirings/scope/index.js +1 -1
  283. package/dist/wirings/scope/scope.types.d.ts +7 -9
  284. package/dist/wirings/scope/validate-scope-definitions.d.ts +2 -21
  285. package/dist/wirings/scope/validate-scope-definitions.js +3 -21
  286. package/dist/wirings/secret/index.d.ts +1 -1
  287. package/dist/wirings/secret/index.js +1 -1
  288. package/dist/wirings/secret/secret.types.d.ts +19 -15
  289. package/dist/wirings/secret/secret.types.js +1 -1
  290. package/dist/wirings/secret/validate-secret-definitions.d.ts +2 -4
  291. package/dist/wirings/trigger/trigger-runner.d.ts +0 -27
  292. package/dist/wirings/trigger/trigger-runner.js +1 -24
  293. package/dist/wirings/trigger/trigger.types.d.ts +1 -82
  294. package/dist/wirings/trigger/trigger.types.js +0 -34
  295. package/dist/wirings/variable/index.d.ts +1 -1
  296. package/dist/wirings/variable/index.js +1 -1
  297. package/dist/wirings/variable/validate-variable-definitions.d.ts +2 -4
  298. package/dist/wirings/variable/variable.types.d.ts +1 -13
  299. package/dist/wirings/variable/variable.types.js +1 -1
  300. package/dist/wirings/virtual-user/index.d.ts +27 -0
  301. package/dist/wirings/virtual-user/index.js +8 -0
  302. package/dist/wirings/virtual-user/run-virtual-user.d.ts +92 -0
  303. package/dist/wirings/virtual-user/run-virtual-user.js +478 -0
  304. package/dist/wirings/virtual-user/virtual-user-agents.d.ts +38 -0
  305. package/dist/wirings/virtual-user/virtual-user-agents.js +24 -0
  306. package/dist/wirings/virtual-user/virtual-user-catalogue.d.ts +92 -0
  307. package/dist/wirings/virtual-user/virtual-user-catalogue.js +134 -0
  308. package/dist/wirings/virtual-user/virtual-user-derive.d.ts +26 -0
  309. package/dist/wirings/virtual-user/virtual-user-derive.js +137 -0
  310. package/dist/wirings/virtual-user/virtual-user-dispositions.d.ts +79 -0
  311. package/dist/wirings/virtual-user/virtual-user-dispositions.js +128 -0
  312. package/dist/wirings/virtual-user/virtual-user-intents.d.ts +78 -0
  313. package/dist/wirings/virtual-user/virtual-user-intents.js +142 -0
  314. package/dist/wirings/virtual-user/virtual-user-rng.d.ts +24 -0
  315. package/dist/wirings/virtual-user/virtual-user-rng.js +44 -0
  316. package/dist/wirings/virtual-user/virtual-user-target.d.ts +21 -0
  317. package/dist/wirings/virtual-user/virtual-user-target.js +34 -0
  318. package/dist/wirings/virtual-user/virtual-user.types.d.ts +199 -0
  319. package/dist/wirings/virtual-user/virtual-user.types.js +8 -0
  320. package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +5 -5
  321. package/dist/wirings/workflow/dsl/workflow-runner.d.ts +0 -4
  322. package/dist/wirings/workflow/dsl/workflow-runner.js +0 -4
  323. package/dist/wirings/workflow/feature.d.ts +0 -19
  324. package/dist/wirings/workflow/feature.js +0 -19
  325. package/dist/wirings/workflow/graph/graph-node.d.ts +0 -98
  326. package/dist/wirings/workflow/graph/graph-node.js +0 -34
  327. package/dist/wirings/workflow/graph/graph-runner.js +6 -41
  328. package/dist/wirings/workflow/graph/wire-workflow-graph.d.ts +0 -4
  329. package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +0 -58
  330. package/dist/wirings/workflow/graph/workflow-graph.types.js +0 -6
  331. package/dist/wirings/workflow/index.d.ts +5 -7
  332. package/dist/wirings/workflow/index.js +3 -17
  333. package/dist/wirings/workflow/pikku-scenario-service.d.ts +87 -5
  334. package/dist/wirings/workflow/pikku-scenario-service.js +204 -42
  335. package/dist/wirings/workflow/pikku-workflow-service.d.ts +7 -459
  336. package/dist/wirings/workflow/pikku-workflow-service.js +58 -551
  337. package/dist/wirings/workflow/run-timeline.d.ts +0 -47
  338. package/dist/wirings/workflow/run-timeline.js +0 -22
  339. package/dist/wirings/workflow/scenario-cookie-jar.d.ts +0 -23
  340. package/dist/wirings/workflow/scenario-cookie-jar.js +0 -16
  341. package/dist/wirings/workflow/scenario-poll.d.ts +0 -15
  342. package/dist/wirings/workflow/scenario-poll.js +0 -12
  343. package/dist/wirings/workflow/scenario-prose.d.ts +0 -28
  344. package/dist/wirings/workflow/scenario-prose.js +0 -18
  345. package/dist/wirings/workflow/scenario-step-guards.d.ts +0 -13
  346. package/dist/wirings/workflow/scenario-step-guards.js +1 -14
  347. package/dist/wirings/workflow/scenario-step.types.d.ts +72 -6
  348. package/dist/wirings/workflow/scenario-step.types.js +5 -1
  349. package/dist/wirings/workflow/scenario-surface.d.ts +16 -0
  350. package/dist/wirings/workflow/scenario-surface.js +56 -0
  351. package/dist/wirings/workflow/workflow-invocation-id.d.ts +0 -18
  352. package/dist/wirings/workflow/workflow-invocation-id.js +2 -22
  353. package/dist/wirings/workflow/workflow-queue-workers.d.ts +0 -20
  354. package/dist/wirings/workflow/workflow-queue-workers.js +0 -19
  355. package/dist/wirings/workflow/workflow.types.d.ts +0 -197
  356. package/knowledge/decisions/index.md +19 -0
  357. package/knowledge/decisions/internals/a-secret-that-fails-to-decrypt-fails-the-whole-read.md +49 -0
  358. package/knowledge/decisions/internals/actor-flow-conversations-seed-a-hidden-kickoff-message.md +23 -0
  359. package/knowledge/decisions/internals/actor-flow-drives-the-target-through-a-transport-seam.md +24 -0
  360. package/knowledge/decisions/internals/actor-flow-verdicts-are-llm-self-evaluations.md +25 -0
  361. package/knowledge/decisions/internals/addon-package-roots-resolve-by-walking-node-module-search-paths.md +26 -0
  362. package/knowledge/decisions/internals/addon-singleton-services-are-cached-per-namespace-not-per-package.md +33 -0
  363. package/knowledge/decisions/internals/addon-workflow-names-are-prefixed-with-the-consumer-namespace.md +28 -0
  364. package/knowledge/decisions/internals/ai-agent-agui-bridge-obeys-the-client-ordering-contract.md +29 -0
  365. package/knowledge/decisions/internals/ai-agent-audio-chunks-carry-the-format-the-provider-returned.md +20 -0
  366. package/knowledge/decisions/internals/ai-agent-credential-suspensions-hide-the-tool-result.md +26 -0
  367. package/knowledge/decisions/internals/ai-agent-delegate-and-supervise-hide-different-text.md +26 -0
  368. package/knowledge/decisions/internals/ai-agent-llm-tool-arguments-have-nulls-stripped.md +23 -0
  369. package/knowledge/decisions/internals/ai-agent-model-config-stays-a-single-resolution-seam.md +25 -0
  370. package/knowledge/decisions/internals/ai-agent-onerror-hooks-cannot-change-the-failure.md +22 -0
  371. package/knowledge/decisions/internals/ai-agent-runner-methods-must-keep-their-receiver.md +22 -0
  372. package/knowledge/decisions/internals/ai-agent-stream-persistence-is-best-effort.md +27 -0
  373. package/knowledge/decisions/internals/ai-agent-sub-agents-inherit-the-parent-context-block.md +26 -0
  374. package/knowledge/decisions/internals/ai-agent-tool-execute-failures-are-logged-unconditionally.md +25 -0
  375. package/knowledge/decisions/internals/ai-agent-voice-input-transcribes-audio-parts-in-place.md +22 -0
  376. package/knowledge/decisions/internals/ai-agent-working-memory-is-persisted-only-when-valid.md +25 -0
  377. package/knowledge/decisions/internals/channel-message-handlers-accept-three-config-shapes.md +30 -0
  378. package/knowledge/decisions/internals/channel-middleware-caches-only-statically-resolved-middleware.md +31 -0
  379. package/knowledge/decisions/internals/channel-state-is-per-socket-session-state-is-per-user.md +29 -0
  380. package/knowledge/decisions/internals/channel-user-id-is-persisted-after-onconnect-middleware-runs.md +28 -0
  381. package/knowledge/decisions/internals/cli-option-names-are-camelcase-in-state-and-kebab-on-the-command-line.md +27 -0
  382. package/knowledge/decisions/internals/cli-parse-errors-are-routed-by-message-prefix.md +28 -0
  383. package/knowledge/decisions/internals/cli-stdout-is-reserved-for-machine-readable-output.md +34 -0
  384. package/knowledge/decisions/internals/cli-unknown-long-options-warn-instead-of-failing.md +29 -0
  385. package/knowledge/decisions/internals/core-data-classification-brand-is-an-optional-property.md +34 -0
  386. package/knowledge/decisions/internals/core-function-runner-restores-the-wire-fields-it-overwrites.md +44 -0
  387. package/knowledge/decisions/internals/core-hot-reload-merges-generated-meta-never-replaces-it.md +39 -0
  388. package/knowledge/decisions/internals/core-hot-reload-owns-its-module-registry.md +42 -0
  389. package/knowledge/decisions/internals/core-middleware-order-is-scope-then-priority.md +39 -0
  390. package/knowledge/decisions/internals/core-schema-defaults-apply-on-every-transport.md +43 -0
  391. package/knowledge/decisions/internals/core-scopes-are-an-and-gate-separate-from-permissions.md +38 -0
  392. package/knowledge/decisions/internals/core-state-is-a-global-map-written-only-at-registration-time.md +44 -0
  393. package/knowledge/decisions/internals/email-meta-is-read-uncached-because-codegen-rewrites-it-mid-session.md +27 -0
  394. package/knowledge/decisions/internals/gateway-adapters-resolve-lazily-and-are-promise-cached.md +32 -0
  395. package/knowledge/decisions/internals/gateway-webhook-challenges-echo-bytes-not-json.md +28 -0
  396. package/knowledge/decisions/internals/gateway-wiring-is-a-meta-wiring-over-http-and-channels.md +31 -0
  397. package/knowledge/decisions/internals/generated-src-paths-in-pikku-meta-are-absolute.md +26 -0
  398. package/knowledge/decisions/internals/http-request-bodies-are-read-once-and-shared.md +32 -0
  399. package/knowledge/decisions/internals/http-route-groups-cascade-config-in-a-fixed-order.md +28 -0
  400. package/knowledge/decisions/internals/http-router-matches-normalized-paths-but-returns-registered-ones.md +30 -0
  401. package/knowledge/decisions/internals/http-runner-logs-through-a-trace-scoped-logger-functions-do-not.md +26 -0
  402. package/knowledge/decisions/internals/http-set-cookie-headers-are-appended-never-joined.md +28 -0
  403. package/knowledge/decisions/internals/http-sse-streams-flush-headers-only-after-middleware.md +32 -0
  404. package/knowledge/decisions/internals/http-wiring-without-metadata-is-skipped-not-fatal.md +26 -0
  405. package/knowledge/decisions/internals/in-a-scenario-a-4xx-is-data-not-an-exception.md +25 -0
  406. package/knowledge/decisions/internals/in-memory-workflow-history-aliases-the-live-step-object.md +26 -0
  407. package/knowledge/decisions/internals/index.md +113 -0
  408. package/knowledge/decisions/internals/istanbul-statement-counts-attach-to-the-start-line-only.md +25 -0
  409. package/knowledge/decisions/internals/local-trigger-and-gateway-services-assume-a-single-process.md +26 -0
  410. package/knowledge/decisions/internals/node-only-builtins-are-imported-dynamically.md +24 -0
  411. package/knowledge/decisions/internals/queue-group-concurrency-keeps-one-shared-queue-fair.md +28 -0
  412. package/knowledge/decisions/internals/queue-jobs-always-carry-an-explicit-attempts-count.md +27 -0
  413. package/knowledge/decisions/internals/remote-addons-dispatch-over-http-instead-of-local-meta.md +31 -0
  414. package/knowledge/decisions/internals/rpc-names-resolve-through-package-scope-before-root.md +32 -0
  415. package/knowledge/decisions/internals/scenario-agent-calls-sign-in-on-401-only.md +27 -0
  416. package/knowledge/decisions/internals/scenario-meta-lives-apart-from-app-meta-but-merges-when-read-off-disk.md +26 -0
  417. package/knowledge/decisions/internals/scenario-steps-return-drained-response-records.md +27 -0
  418. package/knowledge/decisions/internals/scope-roots-may-be-co-declared-by-an-addon-and-its-host-app.md +30 -0
  419. package/knowledge/decisions/internals/serverless-channel-disconnect-must-tolerate-a-missing-channel.md +28 -0
  420. package/knowledge/decisions/internals/the-dev-queue-copies-prod-timing-and-serialization-semantics.md +30 -0
  421. package/knowledge/decisions/internals/the-embedding-model-is-pinned-per-service-and-doc-query-embedding-is-split.md +29 -0
  422. package/knowledge/decisions/internals/the-in-memory-workflow-service-is-inline-only-and-single-process.md +27 -0
  423. package/knowledge/decisions/internals/the-kek-salt-is-scoped-to-the-key-version.md +40 -0
  424. package/knowledge/decisions/internals/the-schema-service-is-never-stubbed.md +26 -0
  425. package/knowledge/decisions/internals/trigger-declaration-is-split-from-trigger-source.md +33 -0
  426. package/knowledge/decisions/internals/typed-secret-service-caches-for-the-process-lifetime.md +26 -0
  427. package/knowledge/decisions/internals/webhook-delivery-history-records-every-attempt-best-effort.md +26 -0
  428. package/knowledge/decisions/internals/webhook-service-collaborators-are-constructor-args-not-locator-lookups.md +25 -0
  429. package/knowledge/decisions/internals/whether-a-run-is-inline-is-read-from-the-run-record.md +58 -0
  430. package/knowledge/decisions/internals/workflow-approval-expiry-is-decided-from-a-recorded-deadline.md +34 -0
  431. package/knowledge/decisions/internals/workflow-core-never-imports-a-browser-driver.md +42 -0
  432. package/knowledge/decisions/internals/workflow-dsl-meta-separates-runtime-expressions-from-literals.md +38 -0
  433. package/knowledge/decisions/internals/workflow-features-resolve-scenarios-by-object-identity.md +29 -0
  434. package/knowledge/decisions/internals/workflow-graph-inline-and-queued-runs-share-one-planner.md +42 -0
  435. package/knowledge/decisions/internals/workflow-graph-node-notes-are-excluded-from-the-graph-hash.md +25 -0
  436. package/knowledge/decisions/internals/workflow-inline-runs-report-their-run-id-before-they-can-fail.md +29 -0
  437. package/knowledge/decisions/internals/workflow-invocation-id-is-the-dedupe-key-not-step-id.md +43 -0
  438. package/knowledge/decisions/internals/workflow-queued-step-dispatch-requires-an-explicit-opt-in.md +29 -0
  439. package/knowledge/decisions/internals/workflow-queues-are-per-workflow-by-default.md +42 -0
  440. package/knowledge/decisions/internals/workflow-repeated-step-names-get-an-ordinal-suffix.md +33 -0
  441. package/knowledge/decisions/internals/workflow-replay-reads-its-steps-once-and-caches-only-the-immutable-half.md +32 -0
  442. package/knowledge/decisions/internals/workflow-retries-are-owned-by-the-workflow-not-the-queue.md +31 -0
  443. package/knowledge/decisions/internals/workflow-run-capabilities-are-extensions-not-subclasses.md +39 -0
  444. package/knowledge/decisions/internals/workflow-run-mirror-is-never-a-source-of-truth.md +29 -0
  445. package/knowledge/decisions/internals/workflow-run-polling-backs-off-to-the-callers-ceiling.md +33 -0
  446. package/knowledge/decisions/internals/workflow-run-timeline-is-a-pure-fold-over-durable-history.md +37 -0
  447. package/knowledge/decisions/internals/workflow-scenario-assertions-never-retry-and-record-one-step.md +50 -0
  448. package/knowledge/decisions/internals/workflow-scenario-hooks-are-a-scenario-only-affordance.md +43 -0
  449. package/knowledge/decisions/internals/workflow-scenario-prose-is-rendered-from-typed-calls-not-parsed-from-english.md +32 -0
  450. package/knowledge/decisions/internals/workflow-scenario-quarantine-reason-lives-in-code.md +18 -0
  451. package/knowledge/decisions/internals/workflow-scenario-step-targets-are-string-literals-for-the-inspector.md +34 -0
  452. package/knowledge/decisions/internals/workflow-step-compensation-runs-as-its-own-durable-step.md +26 -0
  453. package/knowledge/decisions/internals/workflow-step-dispatch-failure-is-transient-not-a-run-failure.md +33 -0
  454. package/knowledge/decisions/internals/workflow-step-lock-is-held-only-to-claim-the-step.md +27 -0
  455. package/knowledge/decisions/internals/workflow-step-rpc-name-is-provenance-only.md +34 -0
  456. package/knowledge/decisions/internals/workflow-suspend-and-approval-reasons-are-durable-step-identities.md +38 -0
  457. package/knowledge/decisions/internals/workflow-suspended-runs-keep-their-in-process-context.md +30 -0
  458. package/knowledge/decisions/security/a-dropped-audit-write-is-always-logged.md +26 -0
  459. package/knowledge/decisions/security/actor-flow-missing-approval-decisions-default-to-denied.md +22 -0
  460. package/knowledge/decisions/security/actor-sign-in-is-proven-by-set-cookie-not-a-non-empty-jar.md +27 -0
  461. package/knowledge/decisions/security/actor-sign-in-only-works-for-actor-flagged-users.md +27 -0
  462. package/knowledge/decisions/security/addon-auth-and-tags-only-tighten.md +43 -0
  463. package/knowledge/decisions/security/addon-config-gates-apply-only-at-the-namespaced-rpc-boundary.md +52 -0
  464. package/knowledge/decisions/security/addon-scopes-are-resolved-where-the-function-runs.md +46 -0
  465. package/knowledge/decisions/security/ai-agent-approval-forwarding-requires-a-symbol-brand.md +27 -0
  466. package/knowledge/decisions/security/ai-agent-credential-requests-are-symbol-branded.md +37 -0
  467. package/knowledge/decisions/security/ai-agent-gate-requires-a-session-only-when-auth-is-true.md +31 -0
  468. package/knowledge/decisions/security/ai-agent-ownership-failures-never-echo-the-resource.md +23 -0
  469. package/knowledge/decisions/security/ai-agent-resume-re-runs-the-authorization-gate.md +22 -0
  470. package/knowledge/decisions/security/ai-agent-sessionless-deployments-have-no-thread-ownership.md +39 -0
  471. package/knowledge/decisions/security/ai-agent-thread-ownership-composes-the-session-principal.md +30 -0
  472. package/knowledge/decisions/security/ai-agent-tool-filtering-reads-the-live-function-config.md +24 -0
  473. package/knowledge/decisions/security/an-empty-owners-constraint-matches-nothing.md +30 -0
  474. package/knowledge/decisions/security/an-exposed-ungated-function-is-a-codegen-warning.md +49 -0
  475. package/knowledge/decisions/security/console-addon-privileged-functions-gate-themselves.md +76 -0
  476. package/knowledge/decisions/security/core-safe-fetch-blocks-ssrf-by-host-literal-not-dns.md +39 -0
  477. package/knowledge/decisions/security/core-secrets-use-a-per-secret-dek-wrapped-by-a-kek.md +37 -0
  478. package/knowledge/decisions/security/gateway-handlers-run-through-the-function-runner-gate.md +31 -0
  479. package/knowledge/decisions/security/gateway-middleware-sessions-must-be-bridged-onto-the-wire.md +30 -0
  480. package/knowledge/decisions/security/global-permissions-and-function-permissions-are-independent-gates.md +40 -0
  481. package/knowledge/decisions/security/http-error-detail-is-withheld-from-clients-in-production.md +33 -0
  482. package/knowledge/decisions/security/http-request-bodies-are-bounded-before-they-are-buffered.md +46 -0
  483. package/knowledge/decisions/security/index.md +55 -0
  484. package/knowledge/decisions/security/mcp-internal-error-details-are-double-gated-on-production.md +27 -0
  485. package/knowledge/decisions/security/passphrases-are-stretched-key-material-is-expanded.md +40 -0
  486. package/knowledge/decisions/security/permission-auth-filtering-requires-live-permission-functions.md +31 -0
  487. package/knowledge/decisions/security/pikku-carries-actor-scopes-as-data-and-the-app-grants-them.md +26 -0
  488. package/knowledge/decisions/security/queue-job-identities-are-signed-at-enqueue.md +69 -0
  489. package/knowledge/decisions/security/queue-jobs-carry-the-producers-pikku-user-id.md +39 -0
  490. package/knowledge/decisions/security/remote-addon-tokens-are-client-credentials-not-mesh-trust.md +34 -0
  491. package/knowledge/decisions/security/scaffold-features-are-authenticated-unless-opted-out.md +49 -0
  492. package/knowledge/decisions/security/scenario-step-functions-are-never-externally-invocable.md +30 -0
  493. package/knowledge/decisions/security/scope-resolution-happens-at-the-session-boundary-and-sync-never-deletes.md +28 -0
  494. package/knowledge/decisions/security/self-authentication-is-declared-not-detected.md +34 -0
  495. package/knowledge/decisions/security/signed-content-urls-bind-the-request-path.md +37 -0
  496. package/knowledge/decisions/security/webhook-bodies-are-signed-before-they-are-enqueued.md +25 -0
  497. package/knowledge/decisions/security/workflow-actor-steps-always-use-the-real-transport.md +34 -0
  498. package/knowledge/decisions/security/workflow-approval-payloads-are-validated-on-replay-inside-the-workflow.md +40 -0
  499. package/knowledge/decisions/security/workflow-queued-steps-rehydrate-their-session-from-the-run-wire.md +32 -0
  500. package/knowledge/decisions/security/workflow-scenario-sessions-are-isolated-per-actor-and-per-scenario.md +32 -0
  501. package/knowledge/decisions/security/workflow-scenario-steps-are-never-network-invocable.md +31 -0
  502. package/knowledge/index.md +24 -0
  503. package/knowledge/questions/index.md +15 -0
  504. package/package.json +4 -1
  505. package/run-tests.sh +0 -0
  506. package/src/crypto-utils.test.ts +460 -19
  507. package/src/crypto-utils.ts +283 -55
  508. package/src/data-classification.ts +1 -7
  509. package/src/dev/hot-reload.test.ts +0 -4
  510. package/src/dev/hot-reload.ts +11 -30
  511. package/src/dev/module-runner.ts +7 -32
  512. package/src/dev/reload-meta.ts +9 -29
  513. package/src/errors/error-handler.ts +20 -35
  514. package/src/errors/error.test.ts +30 -1
  515. package/src/errors/errors.ts +73 -157
  516. package/src/function/abort-scope.test.ts +97 -0
  517. package/src/function/abort-scope.ts +80 -0
  518. package/src/function/function-runner.test.ts +0 -7
  519. package/src/function/function-runner.ts +62 -32
  520. package/src/function/functions.types.ts +56 -136
  521. package/src/function/list.types.test.ts +3 -25
  522. package/src/function/list.types.ts +12 -62
  523. package/src/handle-error.ts +0 -18
  524. package/src/index.ts +60 -1
  525. package/src/middleware/auth-apikey.test.ts +0 -1
  526. package/src/middleware/auth-apikey.ts +0 -17
  527. package/src/middleware/auth-bearer.test.ts +0 -3
  528. package/src/middleware/auth-bearer.ts +3 -40
  529. package/src/middleware/auth-cookie.test.ts +0 -6
  530. package/src/middleware/auth-cookie.ts +2 -26
  531. package/src/middleware/cors.test.ts +34 -0
  532. package/src/middleware/cors.ts +12 -33
  533. package/src/middleware/remote-auth.test.ts +24 -9
  534. package/src/middleware/remote-auth.ts +10 -2
  535. package/src/middleware/telemetry.ts +2 -31
  536. package/src/middleware-runner.test.ts +0 -2
  537. package/src/middleware-runner.ts +5 -74
  538. package/src/permissions.test.ts +30 -0
  539. package/src/permissions.ts +24 -74
  540. package/src/pikku-request.ts +0 -6
  541. package/src/pikku-state.ts +2 -30
  542. package/src/production-barrels-stay-lean.test.ts +110 -0
  543. package/src/remote.test.ts +172 -0
  544. package/src/remote.ts +17 -7
  545. package/src/schema.ts +5 -39
  546. package/src/scopes.ts +7 -48
  547. package/src/services/ai-agent-runner-service.ts +20 -0
  548. package/src/services/ai-embedding-service.ts +3 -25
  549. package/src/services/audit-service.ts +1 -2
  550. package/src/services/content-service.ts +1 -46
  551. package/src/services/credential-service.ts +3 -40
  552. package/src/services/credential-wire-service.test.ts +0 -2
  553. package/src/services/deployment-service.ts +3 -9
  554. package/src/services/gateway-service.ts +0 -15
  555. package/src/services/{http-scenario-actors-converse.test.ts → http-personas-converse.test.ts} +38 -9
  556. package/src/services/{http-scenario-actors.test.ts → http-personas.test.ts} +39 -22
  557. package/src/services/{http-scenario-actors.ts → http-personas.ts} +85 -45
  558. package/src/services/in-memory-queue-service.ts +1 -15
  559. package/src/services/in-memory-trigger-service.ts +1 -18
  560. package/src/services/in-memory-workflow-service.test.ts +0 -13
  561. package/src/services/in-memory-workflow-service.ts +4 -38
  562. package/src/services/index.ts +20 -15
  563. package/src/services/istanbul-coverage-service.ts +2 -8
  564. package/src/services/jwt-service.ts +1 -16
  565. package/src/services/local-content.test.ts +159 -27
  566. package/src/services/local-content.ts +55 -23
  567. package/src/services/local-gateway-service.ts +2 -17
  568. package/src/services/local-secrets.ts +0 -4
  569. package/src/services/logger-console.test.ts +0 -1
  570. package/src/services/logger-console.ts +3 -7
  571. package/src/services/logger.ts +2 -37
  572. package/src/services/meta-service.test.ts +1 -5
  573. package/src/services/meta-service.ts +41 -61
  574. package/src/services/{scenario-actors-service.ts → personas-service.ts} +48 -43
  575. package/src/services/pikku-user-id.ts +0 -4
  576. package/src/services/queue-webhook-service.ts +9 -41
  577. package/src/services/scheduler-service.ts +1 -50
  578. package/src/services/schema-service.ts +1 -24
  579. package/src/services/scope-service.ts +50 -34
  580. package/src/services/scoped-secret-service.ts +0 -4
  581. package/src/services/secret-host-binding.test.ts +138 -0
  582. package/src/services/secret-host-binding.ts +51 -0
  583. package/src/services/secret-service.ts +5 -33
  584. package/src/services/secretless.test.ts +54 -0
  585. package/src/services/secretless.ts +29 -0
  586. package/src/services/stub-tracker.ts +8 -18
  587. package/src/services/system-role-guard.test.ts +93 -0
  588. package/src/services/system-role-guard.ts +71 -0
  589. package/src/services/trigger-service.ts +0 -12
  590. package/src/services/typed-secret-service.ts +1 -7
  591. package/src/services/v8-coverage-service.ts +3 -6
  592. package/src/services/variables-service.ts +1 -8
  593. package/src/services/webhook-service.ts +19 -63
  594. package/src/services/workflow-service.ts +3 -20
  595. package/src/testing/service-tests.ts +0 -26
  596. package/src/time-utils.ts +1 -19
  597. package/src/types/core.types.ts +116 -229
  598. package/src/types/state.types.ts +7 -9
  599. package/src/utils/hmac.ts +4 -10
  600. package/src/utils/safe-fetch.ts +13 -54
  601. package/src/utils.test.ts +11 -2
  602. package/src/utils.ts +6 -15
  603. package/src/wirings/actor-flow/actor-flow.types.ts +1 -34
  604. package/src/wirings/actor-flow/index.ts +0 -9
  605. package/src/wirings/actor-flow/run-conversation.test.ts +11 -6
  606. package/src/wirings/actor-flow/run-conversation.ts +19 -12
  607. package/src/wirings/ai-agent/ai-agent-agui.test.ts +75 -10
  608. package/src/wirings/ai-agent/ai-agent-agui.ts +36 -17
  609. package/src/wirings/ai-agent/ai-agent-helpers.ts +20 -0
  610. package/src/wirings/ai-agent/ai-agent-interrupt.test.ts +842 -0
  611. package/src/wirings/ai-agent/ai-agent-interrupt.ts +399 -0
  612. package/src/wirings/ai-agent/ai-agent-memory.ts +0 -2
  613. package/src/wirings/ai-agent/ai-agent-model-config.ts +1 -9
  614. package/src/wirings/ai-agent/ai-agent-prepare.test.ts +202 -31
  615. package/src/wirings/ai-agent/ai-agent-prepare.ts +82 -138
  616. package/src/wirings/ai-agent/ai-agent-registry.test.ts +191 -6
  617. package/src/wirings/ai-agent/ai-agent-registry.ts +18 -1
  618. package/src/wirings/ai-agent/ai-agent-resume-authorization.test.ts +0 -2
  619. package/src/wirings/ai-agent/ai-agent-runner.test.ts +11 -9
  620. package/src/wirings/ai-agent/ai-agent-runner.ts +67 -33
  621. package/src/wirings/ai-agent/ai-agent-stream.test.ts +205 -103
  622. package/src/wirings/ai-agent/ai-agent-stream.ts +192 -75
  623. package/src/wirings/ai-agent/ai-agent-thread-ownership.test.ts +301 -0
  624. package/src/wirings/ai-agent/ai-agent.types.ts +85 -4
  625. package/src/wirings/ai-agent/index.ts +35 -3
  626. package/src/wirings/ai-agent/voice-input.test.ts +72 -7
  627. package/src/wirings/ai-agent/voice-input.ts +48 -3
  628. package/src/wirings/ai-agent/voice-output.test.ts +422 -0
  629. package/src/wirings/ai-agent/voice-output.ts +216 -56
  630. package/src/wirings/channel/channel-common.ts +15 -20
  631. package/src/wirings/channel/channel-handler.test.ts +50 -0
  632. package/src/wirings/channel/channel-handler.ts +32 -11
  633. package/src/wirings/channel/channel-host-rpc.test.ts +150 -0
  634. package/src/wirings/channel/channel-host-rpc.ts +69 -0
  635. package/src/wirings/channel/channel-middleware-runner.test.ts +0 -1
  636. package/src/wirings/channel/channel-middleware-runner.ts +0 -12
  637. package/src/wirings/channel/channel-rpc-registry.ts +116 -0
  638. package/src/wirings/channel/channel-rpc-responder.ts +117 -0
  639. package/src/wirings/channel/channel-rpc-service.ts +146 -0
  640. package/src/wirings/channel/channel-rpc-validators.ts +65 -0
  641. package/src/wirings/channel/channel-rpc.test.ts +820 -0
  642. package/src/wirings/channel/channel-rpc.ts +5 -0
  643. package/src/wirings/channel/channel-rpc.types.ts +150 -0
  644. package/src/wirings/channel/channel-runner.ts +0 -14
  645. package/src/wirings/channel/channel-store.ts +0 -10
  646. package/src/wirings/channel/channel.types.ts +19 -8
  647. package/src/wirings/channel/define-channel-routes.ts +0 -20
  648. package/src/wirings/channel/eventhub-service.ts +0 -18
  649. package/src/wirings/channel/index.ts +35 -0
  650. package/src/wirings/channel/local/local-channel-handler.ts +3 -1
  651. package/src/wirings/channel/local/local-channel-runner.test.ts +0 -10
  652. package/src/wirings/channel/local/local-channel-runner.ts +3 -1
  653. package/src/wirings/channel/local/local-eventhub-service.test.ts +0 -13
  654. package/src/wirings/channel/local/local-eventhub-service.ts +2 -37
  655. package/src/wirings/channel/log-channels.ts +0 -4
  656. package/src/wirings/channel/pikku-abstract-channel-handler.test.ts +83 -2
  657. package/src/wirings/channel/pikku-abstract-channel-handler.ts +7 -0
  658. package/src/wirings/channel/serverless/serverless-channel-runner.ts +2 -5
  659. package/src/wirings/cli/channel/cli-approval.test.ts +177 -0
  660. package/src/wirings/cli/channel/cli-approval.ts +135 -0
  661. package/src/wirings/cli/channel/cli-channel-runner.ts +4 -26
  662. package/src/wirings/cli/channel/cli-raw-channel-runner.test.ts +169 -0
  663. package/src/wirings/cli/channel/cli-raw-channel-runner.ts +59 -16
  664. package/src/wirings/cli/channel/cli-raw-client-runner.test.ts +480 -0
  665. package/src/wirings/cli/channel/cli-raw-client-runner.ts +155 -0
  666. package/src/wirings/cli/channel/index.ts +9 -0
  667. package/src/wirings/cli/cli-runner.test.ts +0 -1
  668. package/src/wirings/cli/cli-runner.ts +46 -88
  669. package/src/wirings/cli/cli.types.ts +14 -3
  670. package/src/wirings/cli/command-parser.test.ts +0 -4
  671. package/src/wirings/cli/command-parser.ts +11 -91
  672. package/src/wirings/cli/define-cli-commands.ts +1 -17
  673. package/src/wirings/credential/credential.types.ts +0 -12
  674. package/src/wirings/credential/{wire-credential.ts → define-credential.ts} +7 -7
  675. package/src/wirings/credential/index.ts +1 -1
  676. package/src/wirings/credential/validate-credential-definitions.ts +2 -4
  677. package/src/wirings/gateway/gateway-runner.test.ts +1 -21
  678. package/src/wirings/gateway/gateway-runner.ts +8 -110
  679. package/src/wirings/gateway/gateway.types.ts +7 -80
  680. package/src/wirings/http/http-routes.test.ts +0 -3
  681. package/src/wirings/http/http-routes.ts +0 -86
  682. package/src/wirings/http/http-runner.test.ts +0 -1
  683. package/src/wirings/http/http-runner.ts +8 -167
  684. package/src/wirings/http/http.types.ts +15 -62
  685. package/src/wirings/http/log-http-routes.ts +0 -4
  686. package/src/wirings/http/pikku-fetch-http-request.test.ts +2 -10
  687. package/src/wirings/http/pikku-fetch-http-request.ts +0 -58
  688. package/src/wirings/http/pikku-fetch-http-response.test.ts +1 -1
  689. package/src/wirings/http/pikku-fetch-http-response.ts +0 -3
  690. package/src/wirings/http/routers/path-to-regex.test.ts +4 -17
  691. package/src/wirings/http/routers/path-to-regex.ts +2 -13
  692. package/src/wirings/http/web-request.test.ts +33 -2
  693. package/src/wirings/http/web-request.ts +30 -17
  694. package/src/wirings/mcp/mcp-endpoint-registry.test.ts +0 -1
  695. package/src/wirings/mcp/mcp-runner.ts +2 -17
  696. package/src/wirings/mcp/mcp.types.ts +7 -42
  697. package/src/wirings/oauth2/oauth2.types.ts +0 -30
  698. package/src/wirings/persona/define-personas.ts +29 -0
  699. package/src/wirings/persona/index.ts +62 -0
  700. package/src/wirings/persona/persona-email.ts +87 -0
  701. package/src/wirings/persona/persona-environments.test.ts +183 -0
  702. package/src/wirings/persona/persona-environments.ts +138 -0
  703. package/src/wirings/persona/persona-mailbox.ts +156 -0
  704. package/src/wirings/persona/persona.test.ts +220 -0
  705. package/src/wirings/persona/persona.types.ts +131 -0
  706. package/src/wirings/persona/validate-personas.ts +133 -0
  707. package/src/wirings/queue/index.ts +13 -3
  708. package/src/wirings/queue/queue-identity.test.ts +453 -0
  709. package/src/wirings/queue/queue-identity.ts +173 -0
  710. package/src/wirings/queue/queue-runner.ts +12 -31
  711. package/src/wirings/queue/queue.types.ts +19 -89
  712. package/src/wirings/queue/register-queue-helper.ts +0 -14
  713. package/src/wirings/queue/signed-queue-service.ts +59 -0
  714. package/src/wirings/queue/validate-worker-config.ts +2 -28
  715. package/src/wirings/role/define-system-role.ts +33 -0
  716. package/src/wirings/role/index.ts +13 -0
  717. package/src/wirings/role/role.test.ts +104 -0
  718. package/src/wirings/role/role.types.ts +47 -0
  719. package/src/wirings/role/validate-role-definitions.ts +93 -0
  720. package/src/wirings/rpc/addon-auth-tags.test.ts +223 -0
  721. package/src/wirings/rpc/addon-runner.ts +0 -56
  722. package/src/wirings/rpc/addon-scopes.test.ts +225 -0
  723. package/src/wirings/rpc/remote-addon-auth.ts +1 -13
  724. package/src/wirings/rpc/rpc-runner.test.ts +186 -2
  725. package/src/wirings/rpc/rpc-runner.ts +145 -127
  726. package/src/wirings/rpc/rpc-types.ts +11 -6
  727. package/src/wirings/rpc/wire-addon.test.ts +43 -1
  728. package/src/wirings/rpc/wire-addon.ts +99 -0
  729. package/src/wirings/rpc/wire-remote-addon.ts +9 -29
  730. package/src/wirings/scheduler/log-schedulers.ts +0 -4
  731. package/src/wirings/scheduler/scheduler-runner.test.ts +1 -8
  732. package/src/wirings/scheduler/scheduler-runner.ts +0 -2
  733. package/src/wirings/scheduler/scheduler.types.ts +1 -14
  734. package/src/wirings/scope/{wire-scope.ts → define-scope.ts} +5 -6
  735. package/src/wirings/scope/index.ts +1 -1
  736. package/src/wirings/scope/scope.test.ts +1 -2
  737. package/src/wirings/scope/scope.types.ts +7 -9
  738. package/src/wirings/scope/validate-scope-definitions.ts +3 -21
  739. package/src/wirings/secret/index.ts +1 -1
  740. package/src/wirings/secret/secret.types.ts +19 -15
  741. package/src/wirings/secret/validate-secret-definitions.ts +2 -4
  742. package/src/wirings/trigger/trigger-runner.ts +1 -27
  743. package/src/wirings/trigger/trigger.types.ts +1 -82
  744. package/src/wirings/variable/index.ts +1 -1
  745. package/src/wirings/variable/validate-variable-definitions.ts +2 -4
  746. package/src/wirings/variable/variable.types.ts +1 -13
  747. package/src/wirings/virtual-user/index.ts +76 -0
  748. package/src/wirings/virtual-user/run-virtual-user.test.ts +765 -0
  749. package/src/wirings/virtual-user/run-virtual-user.ts +671 -0
  750. package/src/wirings/virtual-user/virtual-user-agents.test.ts +65 -0
  751. package/src/wirings/virtual-user/virtual-user-agents.ts +57 -0
  752. package/src/wirings/virtual-user/virtual-user-catalogue.test.ts +215 -0
  753. package/src/wirings/virtual-user/virtual-user-catalogue.ts +184 -0
  754. package/src/wirings/virtual-user/virtual-user-derive.test.ts +398 -0
  755. package/src/wirings/virtual-user/virtual-user-derive.ts +173 -0
  756. package/src/wirings/virtual-user/virtual-user-dispositions.test.ts +63 -0
  757. package/src/wirings/virtual-user/virtual-user-dispositions.ts +213 -0
  758. package/src/wirings/virtual-user/virtual-user-intents.test.ts +208 -0
  759. package/src/wirings/virtual-user/virtual-user-intents.ts +185 -0
  760. package/src/wirings/virtual-user/virtual-user-rng.test.ts +72 -0
  761. package/src/wirings/virtual-user/virtual-user-rng.ts +50 -0
  762. package/src/wirings/virtual-user/virtual-user-target.ts +47 -0
  763. package/src/wirings/virtual-user/virtual-user.types.ts +219 -0
  764. package/src/wirings/workflow/dsl/workflow-dsl.types.ts +5 -4
  765. package/src/wirings/workflow/dsl/workflow-runner.ts +0 -4
  766. package/src/wirings/workflow/feature.ts +0 -19
  767. package/src/wirings/workflow/graph/graph-node.ts +0 -136
  768. package/src/wirings/workflow/graph/graph-runner.test.ts +20 -19
  769. package/src/wirings/workflow/graph/graph-runner.ts +6 -41
  770. package/src/wirings/workflow/graph/wire-workflow-graph.ts +0 -4
  771. package/src/wirings/workflow/graph/workflow-graph.types.ts +0 -58
  772. package/src/wirings/workflow/index.ts +10 -44
  773. package/src/wirings/workflow/pikku-scenario-service.ts +235 -52
  774. package/src/wirings/workflow/pikku-workflow-service.test.ts +0 -39
  775. package/src/wirings/workflow/pikku-workflow-service.ts +77 -674
  776. package/src/wirings/workflow/run-timeline.test.ts +7 -19
  777. package/src/wirings/workflow/run-timeline.ts +0 -56
  778. package/src/wirings/workflow/scenario-cookie-jar.test.ts +0 -1
  779. package/src/wirings/workflow/scenario-cookie-jar.ts +0 -25
  780. package/src/wirings/workflow/scenario-expectations.test.ts +2 -7
  781. package/src/wirings/workflow/scenario-hooks.test.ts +2 -7
  782. package/src/wirings/workflow/scenario-poll.test.ts +0 -2
  783. package/src/wirings/workflow/scenario-poll.ts +0 -15
  784. package/src/wirings/workflow/scenario-prose.ts +0 -28
  785. package/src/wirings/workflow/scenario-service.test.ts +2 -9
  786. package/src/wirings/workflow/scenario-step-guards.ts +1 -14
  787. package/src/wirings/workflow/scenario-step.test.ts +159 -14
  788. package/src/wirings/workflow/scenario-step.types.ts +82 -6
  789. package/src/wirings/workflow/scenario-surface.test.ts +145 -0
  790. package/src/wirings/workflow/scenario-surface.ts +71 -0
  791. package/src/wirings/workflow/workflow-dispatch-durability.test.ts +14 -15
  792. package/src/wirings/workflow/workflow-dispatch-payload.test.ts +0 -4
  793. package/src/wirings/workflow/workflow-inline-authority.test.ts +169 -0
  794. package/src/wirings/workflow/workflow-invocation-id.test.ts +0 -2
  795. package/src/wirings/workflow/workflow-invocation-id.ts +2 -22
  796. package/src/wirings/workflow/workflow-mirror.test.ts +0 -7
  797. package/src/wirings/workflow/workflow-on-error.test.ts +0 -9
  798. package/src/wirings/workflow/workflow-queue-workers.ts +0 -21
  799. package/src/wirings/workflow/workflow-replay-snapshot.test.ts +8 -7
  800. package/src/wirings/workflow/workflow-retry-policy.test.ts +0 -5
  801. package/src/wirings/workflow/workflow-run-context.test.ts +5 -10
  802. package/src/wirings/workflow/workflow-run-polling.test.ts +0 -5
  803. package/src/wirings/workflow/workflow-step-ordinal.test.ts +19 -4
  804. package/src/wirings/workflow/workflow-step-session.test.ts +0 -7
  805. package/src/wirings/workflow/workflow.types.ts +0 -203
  806. package/tsconfig.tsbuildinfo +1 -1
  807. package/src/middleware/timeout.ts +0 -22
  808. package/src/pikku-response.ts +0 -5
  809. package/src/wirings/mcp/mcp-endpoint-registry.test.d.ts +0 -1
  810. package/src/wirings/workflow/dsl/index.ts +0 -36
  811. package/src/wirings/workflow/graph/index.ts +0 -15
@@ -5,8 +5,9 @@ import { createScenarioRunner } from './pikku-scenario-service.js'
5
5
  import type { InMemoryWorkflowService } from '../../services/in-memory-workflow-service.js'
6
6
  import { pikkuState, resetPikkuState } from '../../pikku-state.js'
7
7
  import { addFunction } from '../../function/function-runner.js'
8
- import type { ScenarioActor } from '../../services/scenario-actors-service.js'
8
+ import type { ScenarioPersona } from '../../services/personas-service.js'
9
9
  import type { PikkuWire } from '../../types/core.types.js'
10
+ import type { ScenarioSurface } from './scenario-step.types.js'
10
11
  import { requireActor, requireScenarioEnv } from './scenario-step-guards.js'
11
12
 
12
13
  const noopLogger = { error() {}, info() {}, warn() {}, debug() {} }
@@ -14,7 +15,7 @@ const noopLogger = { error() {}, info() {}, warn() {}, debug() {} }
14
15
  const fakeActor = (
15
16
  name: string,
16
17
  handler: (rpcName: string, data: unknown) => Promise<unknown>
17
- ): ScenarioActor & { calls: Array<{ rpcName: string; data: unknown }> } => {
18
+ ): ScenarioPersona & { calls: Array<{ rpcName: string; data: unknown }> } => {
18
19
  const calls: Array<{ rpcName: string; data: unknown }> = []
19
20
  return {
20
21
  name,
@@ -87,8 +88,6 @@ describe('scenario actor steps (workflow.do with `actor`)', () => {
87
88
  const first = await wire.do('step', 'someRpc', {}, { actor: yasser })
88
89
  assert.deepEqual(first, { n: 1 })
89
90
 
90
- // Simulate replay: reset per-run ordinals so the same logical step name
91
- // resolves to the same durable step key.
92
91
  await (ws as any).beginReplay(runId)
93
92
  const replayWire = ws.createWorkflowWire('scenarioTest', runId, {})
94
93
  const replayed = await replayWire.do(
@@ -113,7 +112,6 @@ describe('scenario actor steps (workflow.do with `actor`)', () => {
113
112
  },
114
113
  },
115
114
  })
116
- // Function meta says this RPC would normally dispatch via the queue.
117
115
  pikkuState(null, 'function', 'meta').queuedRpc = {
118
116
  pikkuFuncId: 'queuedRpc',
119
117
  workflowQueued: true,
@@ -146,13 +144,11 @@ const registerStep = (
146
144
  name: string,
147
145
  config: {
148
146
  description?: string
149
- browser?: boolean
147
+ surfaces?: ScenarioSurface[]
150
148
  func: (services: any, data: any, wire: PikkuWire) => Promise<unknown>
151
149
  }
152
150
  ) => {
153
151
  addFunction(name, config as any)
154
- // `pikkuScenarioStep` maps to PikkuFunctionSessionless, which is what the
155
- // inspector records — a step is driven by an actor, not by a wire session.
156
152
  pikkuState(null, 'function', 'meta')[name] = {
157
153
  pikkuFuncId: name,
158
154
  sessionless: true,
@@ -306,9 +302,10 @@ describe('pikkuScenarioStep (scenario.step/given/when/then)', () => {
306
302
 
307
303
  test('a browser step fails loudly when no provider is registered', async () => {
308
304
  const { workflowService: ws, scenarioService } = createScenarioRunner()
305
+ scenarioService.setRunSurface('browser')
309
306
  const shopper = fakeActor('shopper', async () => ({}))
310
307
  registerStep('visitsCheckout', {
311
- browser: true,
308
+ surfaces: ['browser'],
312
309
  func: async () => null,
313
310
  })
314
311
 
@@ -325,6 +322,7 @@ describe('pikkuScenarioStep (scenario.step/given/when/then)', () => {
325
322
 
326
323
  test('a registered provider hands the step a session keyed by the actor', async () => {
327
324
  const { workflowService: ws, scenarioService } = createScenarioRunner()
325
+ scenarioService.setRunSurface('browser')
328
326
  const shopper = fakeActor('shopper', async () => ({}))
329
327
  const requested: string[] = []
330
328
  const session = { actor: 'shopper' } as any
@@ -337,7 +335,7 @@ describe('pikkuScenarioStep (scenario.step/given/when/then)', () => {
337
335
 
338
336
  let handed: unknown
339
337
  registerStep('visitsCheckout', {
340
- browser: true,
338
+ surfaces: ['browser'],
341
339
  func: async (_services, _data, wire) => {
342
340
  handed = wire.browser
343
341
  return null
@@ -354,6 +352,157 @@ describe('pikkuScenarioStep (scenario.step/given/when/then)', () => {
354
352
  assert.equal(handed, session)
355
353
  })
356
354
 
355
+ test('an action step falls back to its default binding rather than failing', async () => {
356
+ const { workflowService: ws, scenarioService } = createScenarioRunner()
357
+ scenarioService.setRunSurface('browser')
358
+ const ran: ScenarioSurface[] = []
359
+ registerStep('seedsAnAccount', {
360
+ surfaces: ['default'],
361
+ func: async (_services, _data, wire) => {
362
+ ran.push(wire.scenarioStep!.surface)
363
+ return null
364
+ },
365
+ })
366
+
367
+ const runId = await setup(ws)
368
+ const wire = ws.createWorkflowWire('scenarioTest', runId, {})
369
+ await wire.given('an account exists', 'seedsAnAccount')
370
+
371
+ assert.deepEqual(ran, ['default'], 'setup does not need a UI to be honest')
372
+ })
373
+
374
+ test('an action step with no runnable binding fails rather than silently skipping', async () => {
375
+ const { workflowService: ws, scenarioService } = createScenarioRunner()
376
+ scenarioService.setRunSurface('cli')
377
+ registerStep('clicksBuy', {
378
+ surfaces: ['browser'],
379
+ func: async () => null,
380
+ })
381
+
382
+ const runId = await setup(ws)
383
+ const wire = ws.createWorkflowWire('scenarioTest', runId, {})
384
+
385
+ await assert.rejects(
386
+ wire.when('shopper buys it', 'clicksBuy'),
387
+ /declares no binding for 'cli'/
388
+ )
389
+ })
390
+
391
+ test('a then step runs every witness, surface first', async () => {
392
+ const { workflowService: ws, scenarioService } = createScenarioRunner()
393
+ scenarioService.setRunSurface('browser')
394
+ scenarioService.setScenarioBrowserProvider({
395
+ sessionFor: async () => ({ actor: 'shopper' }) as any,
396
+ } as any)
397
+ const shopper = fakeActor('shopper', async () => ({}))
398
+ const ran: ScenarioSurface[] = []
399
+ registerStep('seesTheOrderConfirmed', {
400
+ surfaces: ['browser', 'default'],
401
+ func: async (_services, _data, wire) => {
402
+ ran.push(wire.scenarioStep!.surface)
403
+ return { status: 'paid' }
404
+ },
405
+ })
406
+
407
+ const runId = await setup(ws)
408
+ const wire = ws.createWorkflowWire('scenarioTest', runId, {})
409
+ await wire.then(
410
+ 'shopper sees the order confirmed',
411
+ 'seesTheOrderConfirmed',
412
+ undefined,
413
+ { actor: shopper }
414
+ )
415
+
416
+ assert.deepEqual(ran, ['browser', 'default'])
417
+ })
418
+
419
+ test('the page saying something else than the database is a failure', async () => {
420
+ const { workflowService: ws, scenarioService } = createScenarioRunner()
421
+ scenarioService.setRunSurface('browser')
422
+ scenarioService.setScenarioBrowserProvider({
423
+ sessionFor: async () => ({ actor: 'shopper' }) as any,
424
+ } as any)
425
+ const shopper = fakeActor('shopper', async () => ({}))
426
+ registerStep('seesTheOrderConfirmed', {
427
+ surfaces: ['browser', 'default'],
428
+ func: async (_services, _data, wire) =>
429
+ wire.scenarioStep!.surface === 'browser'
430
+ ? { status: 'pending' }
431
+ : { status: 'paid' },
432
+ })
433
+
434
+ const runId = await setup(ws)
435
+ const wire = ws.createWorkflowWire('scenarioTest', runId, {})
436
+
437
+ await assert.rejects(
438
+ wire.then(
439
+ 'shopper sees the order confirmed',
440
+ 'seesTheOrderConfirmed',
441
+ undefined,
442
+ { actor: shopper }
443
+ ),
444
+ /observed different things on different surfaces/
445
+ )
446
+ })
447
+
448
+ test('a default run pays for only one witness', async () => {
449
+ const { workflowService: ws, scenarioService } = createScenarioRunner()
450
+ const ran: ScenarioSurface[] = []
451
+ registerStep('seesTheOrderConfirmed', {
452
+ surfaces: ['browser', 'default'],
453
+ func: async (_services, _data, wire) => {
454
+ ran.push(wire.scenarioStep!.surface)
455
+ return { status: 'paid' }
456
+ },
457
+ })
458
+
459
+ const runId = await setup(ws)
460
+ const wire = ws.createWorkflowWire('scenarioTest', runId, {})
461
+ await wire.then('shopper sees the order confirmed', 'seesTheOrderConfirmed')
462
+
463
+ assert.deepEqual(ran, ['default'])
464
+ })
465
+
466
+ test('an assertion with no witness for the run fails instead of passing having checked nothing', async () => {
467
+ const { workflowService: ws, scenarioService } = createScenarioRunner()
468
+ scenarioService.setRunSurface('cli')
469
+ let ran = 0
470
+ registerStep('seesTheBanner', {
471
+ surfaces: ['browser'],
472
+ func: async () => {
473
+ ran++
474
+ return { visible: true }
475
+ },
476
+ })
477
+
478
+ const runId = await setup(ws)
479
+ const wire = ws.createWorkflowWire('scenarioTest', runId, {})
480
+
481
+ await assert.rejects(
482
+ wire.then('shopper sees the banner', 'seesTheBanner'),
483
+ /has no witness to run on 'cli'/
484
+ )
485
+ assert.equal(ran, 0, 'nothing ran — which is exactly why it must not pass')
486
+ })
487
+
488
+ test('a browser-only assertion is not silently skipped by the fast suite', async () => {
489
+ // The fast path is where this is most dangerous: `--run default` prints no
490
+ // coverage line, so a skipped assertion would leave no trace at all.
491
+ const { workflowService: ws, scenarioService } = createScenarioRunner()
492
+ registerStep('seesTheBanner', {
493
+ surfaces: ['browser'],
494
+ func: async () => ({ visible: true }),
495
+ })
496
+
497
+ const runId = await setup(ws)
498
+ const wire = ws.createWorkflowWire('scenarioTest', runId, {})
499
+
500
+ await assert.rejects(
501
+ wire.then('shopper sees the banner', 'seesTheBanner'),
502
+ /has no witness to run on 'default'/
503
+ )
504
+ })
505
+
357
506
  test('a non-string step target is rejected instead of silently dispatching', async () => {
358
507
  const { workflowService: ws, scenarioService } = createScenarioRunner()
359
508
  const runId = await setup(ws)
@@ -446,8 +595,6 @@ describe('scenario step input is recorded on the run', () => {
446
595
  packageName: '@pikku/addon-todos',
447
596
  })
448
597
 
449
- // A reporter renders each step's prose from this, so two calls to one step
450
- // must be distinguishable by what they were asked to check.
451
598
  const steps = await ws.getRunSteps(runId)
452
599
  assert.deepEqual(
453
600
  steps.map((step) => step.data),
@@ -496,8 +643,6 @@ describe('scenario step names its function on the run', () => {
496
643
 
497
644
  const runId = await setup(ws)
498
645
  const wire = ws.createWorkflowWire('scenarioTest', runId, {})
499
- // What a loop produces: the durable name is the interpolated one, so it
500
- // matches no statically recorded step name.
501
646
  for (const packageName of ['console', 'todos']) {
502
647
  await wire.then(`sees ${packageName}`, 'seesAddon', { packageName })
503
648
  }
@@ -1,4 +1,4 @@
1
- import type { ScenarioActor } from '../../services/scenario-actors-service.js'
1
+ import type { ScenarioPersona } from '../../services/personas-service.js'
2
2
 
3
3
  /**
4
4
  * Scenario steps: named, typed units of scenario behaviour.
@@ -14,6 +14,77 @@ import type { ScenarioActor } from '../../services/scenario-actors-service.js'
14
14
  */
15
15
  export type ScenarioStepPhase = 'step' | 'given' | 'when' | 'then'
16
16
 
17
+ /**
18
+ * Who acts in a step.
19
+ *
20
+ * `persona` is a person driving the system through one of its surfaces — the
21
+ * ordinary `pikkuScenarioStep`. `platform` is the app acting on itself ("the
22
+ * platform has expired the trial"), and `addon` is a third-party system acting
23
+ * on it ("Stripe's webhook arrives"), contributed by the addon that wraps that
24
+ * service.
25
+ *
26
+ * The three are separate declarations rather than a field on one, so the
27
+ * inspector verifies a step's kind by which function was called rather than by
28
+ * trusting a string literal — and so an addon package exports only addon steps,
29
+ * which is checkable.
30
+ */
31
+ export type ScenarioStepKind = 'persona' | 'platform' | 'addon'
32
+
33
+ /**
34
+ * How an actor drives the system for one step.
35
+ *
36
+ * A step declares one implementation per surface it supports, and the runner
37
+ * picks between them — so the same ladder can run through a real browser, over
38
+ * the websocket, or entirely server-side.
39
+ *
40
+ * `default` is the floor: it is what every other surface falls back to, so it
41
+ * can never itself fall back.
42
+ */
43
+ export type ScenarioSurface = 'browser' | 'cli' | 'default'
44
+
45
+ export const SCENARIO_SURFACES: readonly ScenarioSurface[] = [
46
+ 'browser',
47
+ 'cli',
48
+ 'default',
49
+ ]
50
+
51
+ /**
52
+ * How a step's declared surfaces resolve for one run.
53
+ *
54
+ * `given`/`when`/`step` bindings are **alternatives** — clicking Buy and calling
55
+ * `createOrder` are two ways to cause one effect, so exactly one runs.
56
+ *
57
+ * `then` bindings are **witnesses** — "the order row says paid" and "the
58
+ * confirmation panel says paid" are different claims that share a name, and the
59
+ * gap between them is the bug nobody catches. So every declared witness runs and
60
+ * they must agree.
61
+ */
62
+ export type ScenarioSurfaceResolution =
63
+ | {
64
+ kind: 'action'
65
+ surface: ScenarioSurface
66
+ /** The run asked for a surface this step does not implement. */
67
+ fellBack: boolean
68
+ }
69
+ | {
70
+ kind: 'witness'
71
+ /**
72
+ * Every witness to run, surface first. Empty means the assertion has no
73
+ * binding this run can execute at all — nothing would check anything, so
74
+ * the step fails rather than reporting a pass it never earned.
75
+ */
76
+ surfaces: ScenarioSurface[]
77
+ /**
78
+ * Something checked the assertion, but not on the surface its prose
79
+ * claims — so nobody looked at the UI. Reported as its own state and
80
+ * counted against coverage: not being in the UI *is* the finding.
81
+ *
82
+ * Disjoint from an empty `surfaces`; an assertion that ran nowhere is a
83
+ * failure, not a coverage statistic.
84
+ */
85
+ unwitnessed: boolean
86
+ }
87
+
17
88
  /**
18
89
  * Options accepted by `scenario.step/given/when/then`.
19
90
  *
@@ -22,7 +93,7 @@ export type ScenarioStepPhase = 'step' | 'given' | 'when' | 'then'
22
93
  * default to no retries.
23
94
  */
24
95
  export interface ScenarioStepOptions {
25
- /** The actor this step runs as. Required for steps declaring `browser: true`. */
96
+ /** The actor this step runs as. Required for steps declaring a `browser` binding. */
26
97
  actor?: unknown
27
98
  /** Overrides the step's own `description` for this call site only. */
28
99
  description?: string
@@ -33,7 +104,7 @@ export interface ScenarioStepOptions {
33
104
 
34
105
  /**
35
106
  * The environment a scenario run targets, as declared in pikku.config.json
36
- * under `scenarios.environments`.
107
+ * under `environments`.
37
108
  */
38
109
  export interface ScenarioEnvironment {
39
110
  /** Base API URL of the target app, INCLUDING the HTTP prefix. */
@@ -46,16 +117,21 @@ export interface ScenarioEnvironment {
46
117
  * The `scenarioStep` wire, present on every scenario step invocation.
47
118
  *
48
119
  * `TActor` is the project's own actor type, so a step reaches only the RPCs its
49
- * actors can actually call. It defaults to the open `ScenarioActor` for a
120
+ * actors can actually call. It defaults to the open `ScenarioPersona` for a
50
121
  * project that declares no registry.
51
122
  */
52
- export interface PikkuScenarioStepWire<TActor = ScenarioActor> {
123
+ export interface PikkuScenarioStepWire<TActor = ScenarioPersona> {
53
124
  /** Registered step name (also its pikkuFuncId) */
54
125
  name: string
55
126
  /** Durable key within the run; may carry an `#ordinal` suffix when repeated */
56
127
  stepName: string
57
128
  runId: string
58
129
  phase: ScenarioStepPhase
130
+ /**
131
+ * Which of the step's bindings is currently executing. A `then` step runs once
132
+ * per witness, so its body sees this change between invocations.
133
+ */
134
+ surface: ScenarioSurface
59
135
  /**
60
136
  * The actor this step runs as, when one was given. Call RPCs through it
61
137
  * (`actor.invoke(...)`) so they run against the target environment as that
@@ -96,7 +172,7 @@ export interface TestIdSelector {
96
172
 
97
173
  /**
98
174
  * Structural browser handle, present only when the runner provisioned a
99
- * browser for this step (`browser: true` on the step config).
175
+ * browser for this step (a `browser` binding on the step config).
100
176
  *
101
177
  * `@pikku/core` deliberately never imports playwright — it must stay
102
178
  * dependency-free for edge runtimes. `@pikku/playwright` augments this
@@ -0,0 +1,145 @@
1
+ import { describe, test } from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+ import { resolveScenarioSurfaces, witnessesAgree } from './scenario-surface.js'
4
+ import type { ScenarioSurface } from './scenario-step.types.js'
5
+
6
+ const ALL: ScenarioSurface[] = ['browser', 'cli', 'default']
7
+
8
+ describe('action steps pick exactly one binding', () => {
9
+ test('runs the binding the run asked for', () => {
10
+ assert.deepEqual(resolveScenarioSurfaces('when', ALL, 'browser'), {
11
+ kind: 'action',
12
+ surface: 'browser',
13
+ fellBack: false,
14
+ })
15
+ })
16
+
17
+ test('falls back to default and says so when the surface is not implemented', () => {
18
+ assert.deepEqual(resolveScenarioSurfaces('when', ['default'], 'browser'), {
19
+ kind: 'action',
20
+ surface: 'default',
21
+ fellBack: true,
22
+ })
23
+ })
24
+
25
+ test('given and step resolve like when, not like then', () => {
26
+ for (const phase of ['given', 'step'] as const) {
27
+ const resolution = resolveScenarioSurfaces(phase, ALL, 'cli')
28
+ assert.equal(resolution.kind, 'action')
29
+ }
30
+ })
31
+
32
+ test('a default run never counts as a fallback', () => {
33
+ assert.deepEqual(resolveScenarioSurfaces('when', ['default'], 'default'), {
34
+ kind: 'action',
35
+ surface: 'default',
36
+ fellBack: false,
37
+ })
38
+ })
39
+ })
40
+
41
+ describe('then steps run every witness', () => {
42
+ test('a browser run checks the page AND the system of record', () => {
43
+ assert.deepEqual(
44
+ resolveScenarioSurfaces('then', ['browser', 'default'], 'browser'),
45
+ { kind: 'witness', surfaces: ['browser', 'default'], unwitnessed: false }
46
+ )
47
+ })
48
+
49
+ test('the surface witness comes first, so its failure is the one reported', () => {
50
+ const resolution = resolveScenarioSurfaces(
51
+ 'then',
52
+ ['default', 'browser'],
53
+ 'browser'
54
+ )
55
+ assert.equal(resolution.kind, 'witness')
56
+ assert.deepEqual(
57
+ resolution.kind === 'witness' ? resolution.surfaces[0] : null,
58
+ 'browser'
59
+ )
60
+ })
61
+
62
+ test('a default run is unchanged — one witness, no extra cost', () => {
63
+ assert.deepEqual(
64
+ resolveScenarioSurfaces('then', ['browser', 'default'], 'default'),
65
+ { kind: 'witness', surfaces: ['default'], unwitnessed: false }
66
+ )
67
+ })
68
+
69
+ test('no witness for the run surface is flagged rather than excused', () => {
70
+ assert.deepEqual(resolveScenarioSurfaces('then', ['default'], 'browser'), {
71
+ kind: 'witness',
72
+ surfaces: ['default'],
73
+ unwitnessed: true,
74
+ })
75
+ })
76
+
77
+ test('a browser-only assertion has nothing to run on a default run', () => {
78
+ // No witness at all is not a coverage statistic — nothing checked anything,
79
+ // so `unwitnessed` stays false and the caller is expected to fail the step.
80
+ assert.deepEqual(resolveScenarioSurfaces('then', ['browser'], 'default'), {
81
+ kind: 'witness',
82
+ surfaces: [],
83
+ unwitnessed: false,
84
+ })
85
+ })
86
+
87
+ test('an assertion that runs nowhere is not counted as merely unwitnessed', () => {
88
+ assert.deepEqual(resolveScenarioSurfaces('then', ['browser'], 'cli'), {
89
+ kind: 'witness',
90
+ surfaces: [],
91
+ unwitnessed: false,
92
+ })
93
+ })
94
+
95
+ test('unwitnessed means checked somewhere else, never checked nowhere', () => {
96
+ const ranElsewhere = resolveScenarioSurfaces('then', ['default'], 'cli')
97
+ assert.equal(ranElsewhere.kind, 'witness')
98
+ assert.ok(
99
+ ranElsewhere.kind === 'witness' && ranElsewhere.surfaces.length > 0,
100
+ 'the two states are disjoint: unwitnessed always has something that ran'
101
+ )
102
+ assert.equal(
103
+ ranElsewhere.kind === 'witness' && ranElsewhere.unwitnessed,
104
+ true
105
+ )
106
+ })
107
+ })
108
+
109
+ describe('witness agreement', () => {
110
+ test('key order does not make two observations disagree', () => {
111
+ assert.equal(
112
+ witnessesAgree(
113
+ { status: 'paid', total: 500 },
114
+ { total: 500, status: 'paid' }
115
+ ),
116
+ true
117
+ )
118
+ })
119
+
120
+ test('a page showing something else is a disagreement', () => {
121
+ assert.equal(
122
+ witnessesAgree({ status: 'paid' }, { status: 'pending' }),
123
+ false
124
+ )
125
+ })
126
+
127
+ test('a witness that asserted by throwing is not compared', () => {
128
+ assert.equal(witnessesAgree(undefined, { status: 'paid' }), true)
129
+ assert.equal(witnessesAgree({ status: 'paid' }, undefined), true)
130
+ })
131
+
132
+ test('nested observations compare structurally', () => {
133
+ assert.equal(
134
+ witnessesAgree(
135
+ { order: { items: [{ sku: 'a' }, { sku: 'b' }] } },
136
+ { order: { items: [{ sku: 'a' }, { sku: 'b' }] } }
137
+ ),
138
+ true
139
+ )
140
+ assert.equal(
141
+ witnessesAgree({ items: ['a', 'b'] }, { items: ['b', 'a'] }),
142
+ false
143
+ )
144
+ })
145
+ })
@@ -0,0 +1,71 @@
1
+ import type {
2
+ ScenarioStepPhase,
3
+ ScenarioSurface,
4
+ ScenarioSurfaceResolution,
5
+ } from './scenario-step.types.js'
6
+
7
+ /**
8
+ * Resolve which of a step's declared bindings run, for one step, in one run.
9
+ *
10
+ * The asymmetry between phases is the whole point — see
11
+ * {@link ScenarioSurfaceResolution}.
12
+ */
13
+ export const resolveScenarioSurfaces = (
14
+ phase: ScenarioStepPhase,
15
+ declared: readonly ScenarioSurface[],
16
+ runSurface: ScenarioSurface
17
+ ): ScenarioSurfaceResolution => {
18
+ const has = (surface: ScenarioSurface) => declared.includes(surface)
19
+
20
+ if (phase !== 'then') {
21
+ if (has(runSurface)) {
22
+ return { kind: 'action', surface: runSurface, fellBack: false }
23
+ }
24
+ return { kind: 'action', surface: 'default', fellBack: true }
25
+ }
26
+
27
+ const surfaces: ScenarioSurface[] = []
28
+ if (runSurface !== 'default' && has(runSurface)) {
29
+ surfaces.push(runSurface)
30
+ }
31
+ if (has('default')) {
32
+ surfaces.push('default')
33
+ }
34
+ return {
35
+ kind: 'witness',
36
+ surfaces,
37
+ // Only meaningful once something ran: an assertion checked server-side
38
+ // under `--run browser` is a coverage gap, but one checked nowhere at all
39
+ // is a step that did not happen, which the caller fails rather than counts.
40
+ unwitnessed:
41
+ surfaces.length > 0 && runSurface !== 'default' && !has(runSurface),
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Structural comparison of two witnesses' observations.
47
+ *
48
+ * A witness that returns `undefined` asserted by throwing rather than by
49
+ * reporting what it saw, so it is not compared — that keeps assertion-style
50
+ * steps working without forcing every one of them to return a value.
51
+ */
52
+ export const witnessesAgree = (a: unknown, b: unknown): boolean => {
53
+ if (a === undefined || b === undefined) {
54
+ return true
55
+ }
56
+ return stableStringify(a) === stableStringify(b)
57
+ }
58
+
59
+ const stableStringify = (value: unknown): string => {
60
+ if (value === null || typeof value !== 'object') {
61
+ return JSON.stringify(value) ?? 'undefined'
62
+ }
63
+ if (Array.isArray(value)) {
64
+ return `[${value.map(stableStringify).join(',')}]`
65
+ }
66
+ const entries = Object.entries(value as Record<string, unknown>)
67
+ .filter(([, v]) => v !== undefined)
68
+ .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
69
+ .map(([k, v]) => `${JSON.stringify(k)}:${stableStringify(v)}`)
70
+ return `{${entries.join(',')}}`
71
+ }
@@ -5,8 +5,6 @@ import { InMemoryWorkflowService } from '../../services/in-memory-workflow-servi
5
5
  import { pikkuState } from '../../pikku-state.js'
6
6
  import { WorkflowDispatchException } from './pikku-workflow-service.js'
7
7
 
8
- // Register a `workflowQueued: true` function so the workflow's `do()` routes
9
- // the step through the queue (dispatchStep) instead of running it inline.
10
8
  function registerDispatchedFn(rpcName: string): void {
11
9
  const funcId = `fn:${rpcName}`
12
10
  pikkuState(null, 'rpc', 'meta', { [rpcName]: funcId } as any)
@@ -31,18 +29,17 @@ describe('dispatch durability: a transient queue failure is recoverable', () =>
31
29
  } as any)
32
30
 
33
31
  const ws = new InMemoryWorkflowService()
34
- const runId = await ws.createRun('flow', {}, false, 'hash', { type: 'test' })
32
+ const runId = await ws.createRun('flow', {}, false, 'hash', {
33
+ type: 'test',
34
+ })
35
35
  await ws.insertStepState(runId, 'thing', 'doThing', {})
36
36
 
37
- // Queue is down → dispatch throws the TRANSIENT exception (not a step failure).
38
37
  await assert.rejects(
39
38
  (ws as any).rpcStep(runId, 'thing', 'doThing', {}, {}),
40
39
  (err: any) => err instanceof WorkflowDispatchException,
41
40
  'a queue outage surfaces as WorkflowDispatchException'
42
41
  )
43
42
 
44
- // The step must NOT be stranded in `scheduled` — otherwise replay would pause
45
- // forever on a job that was never enqueued.
46
43
  const afterFail = await ws.getStepState(runId, 'thing')
47
44
  assert.equal(
48
45
  afterFail.status,
@@ -50,14 +47,13 @@ describe('dispatch durability: a transient queue failure is recoverable', () =>
50
47
  'step stays pending after a failed dispatch'
51
48
  )
52
49
 
53
- // The run itself must stay alive (not failed) — it is the snapshot we replay.
54
50
  const runAfterFail = await ws.getRun(runId)
55
- assert.notEqual(runAfterFail?.status, 'failed', 'run is not failed by a queue blip')
51
+ assert.notEqual(
52
+ runAfterFail?.status,
53
+ 'failed',
54
+ 'run is not failed by a queue blip'
55
+ )
56
56
 
57
- // Queue recovers → replaying the step now dispatches (pauses via async exception)
58
- // and the step transitions to `scheduled`. A real replay runs through
59
- // runWorkflowJob which resets the ordinal counter; simulate that so the
60
- // second reach resolves to the same step key, not the next ordinal.
61
57
  await (ws as any).beginReplay(runId)
62
58
  queueUp = true
63
59
  await assert.rejects(
@@ -81,7 +77,6 @@ describe('orchestrateWorkflow treats a dispatch failure as non-terminal', () =>
81
77
  logger: silentLogger,
82
78
  } as any)
83
79
  const ws = new InMemoryWorkflowService()
84
- // Override the replay to throw whatever the test wants.
85
80
  ;(ws as any).runWorkflowJob = async () => throwIt()
86
81
  return ws
87
82
  }
@@ -90,7 +85,9 @@ describe('orchestrateWorkflow treats a dispatch failure as non-terminal', () =>
90
85
  const ws = makeService(() => {
91
86
  throw new WorkflowDispatchException('r', 's')
92
87
  })
93
- const runId = await ws.createRun('flow', {}, false, 'hash', { type: 'test' })
88
+ const runId = await ws.createRun('flow', {}, false, 'hash', {
89
+ type: 'test',
90
+ })
94
91
 
95
92
  await assert.rejects(
96
93
  ws.orchestrateWorkflow(runId, {}),
@@ -108,7 +105,9 @@ describe('orchestrateWorkflow treats a dispatch failure as non-terminal', () =>
108
105
  const ws = makeService(() => {
109
106
  throw new Error('business logic blew up')
110
107
  })
111
- const runId = await ws.createRun('flow', {}, false, 'hash', { type: 'test' })
108
+ const runId = await ws.createRun('flow', {}, false, 'hash', {
109
+ type: 'test',
110
+ })
112
111
 
113
112
  await assert.rejects(ws.orchestrateWorkflow(runId, {}))
114
113
  const run = await ws.getRun(runId)