@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
package/CHANGELOG.md CHANGED
@@ -1,3 +1,796 @@
1
+ ## 0.12.74
2
+
3
+ ### Patch Changes
4
+
5
+ - 6a307f0: Fix four latent correctness bugs in the function, RPC and error runtimes, and
6
+ remove dead code from the workflow service surface.
7
+
8
+ `WorkflowService.getNodesWithoutSteps` is gone. It was declared on the abstract
9
+ service and implemented by all five storage backends, and nothing ever called
10
+ it — hence the non-core packages in this changeset, which only lose that method.
11
+
12
+ **An RPC could execute twice.** `RPCService.invoke`, its addon path, and
13
+ `rpcWithWire` each wrapped the _execution_ of a resolved function in a `try`
14
+ whose `catch` treated `RPCNotFoundError` as "not found locally" and re-dispatched
15
+ the call through `deploymentService`. A nested `rpc.invoke` to a missing name,
16
+ raised from inside an already-running function, therefore re-ran that function on
17
+ a remote instance after its local side effects had already committed. Resolution
18
+ is now separated from execution on all three paths, so only a genuinely
19
+ unresolvable name reaches the fallback. What escapes to callers is unchanged.
20
+
21
+ **`addonNamespace` leaked between sibling calls.** The function runner's
22
+ middleware path restored `rpc`, `functionId`, `audit` and `addonNamespace` after
23
+ an invocation; the non-middleware path restored the first three but not the
24
+ fourth. A call into an addon function with no middleware left the addon's
25
+ namespace on the wire, so subsequent sibling calls resolved the wrong
26
+ per-instance singletons and `credentialOverrides`.
27
+
28
+ **Errors registered on a subclass never resolved.** `misc.errors` was typed
29
+ `Map<PikkuError, ErrorDetails>` — instances — while `addError` stores
30
+ constructors, a mismatch hidden by its `error: any` parameter. The instance
31
+ lookup in `getErrorResponse` was consequently dead, and lookup fell through to a
32
+ scan comparing `constructor.name`, so a subclass of a registered error got no
33
+ status mapping at all. The map is now typed `Map<PikkuErrorConstructor, …>` and
34
+ lookup walks the prototype chain first. Name matching is retained, deliberately,
35
+ as the fallback that keeps error mapping working when two copies of
36
+ `@pikku/core` are installed.
37
+
38
+ **`createWeakUID` collided across instances.** The prefix was
39
+ `Date.now().toString(36)` evaluated at module load, so any two instances loading
40
+ the module in the same millisecond emitted identical `channelId` and `requestId`
41
+ sequences — reproducibly, not just in principle. It is now seeded lazily from
42
+ `crypto.randomUUID()`.
43
+
44
+ Also: `pikkuState` keys its global map with `Symbol.for` rather than `Symbol`, so
45
+ two copies of the package share registrations instead of silently getting
46
+ disjoint state; and the local channel upgrade path no longer keys its middleware
47
+ cache on the raw request path, which grew the cache without bound while the
48
+ cached value never varied by path.
49
+
50
+ - afef587: Close eleven security weaknesses found in a review of `@pikku/core`. Most are
51
+ breaking, and two invalidate data or credentials already in the wild — read the
52
+ migration notes before upgrading.
53
+
54
+ **Breaking: AI agent thread ownership now fails closed.** Reading, listing,
55
+ resuming or approving an existing thread or run requires a resolved session
56
+ principal (`userId`, or `orgId` for `sessionScope: 'org'`), regardless of the
57
+ agent's `auth` setting. Previously a request without a session had no ownership
58
+ model at all: the caller-supplied `resourceId` was accepted as the ownership
59
+ key, so any caller could read or resume another party's thread by naming its
60
+ `resourceId`. Worse, `threadOwnerConstraint` returned `undefined` for a
61
+ sessionless caller, and `undefined` means _no filter_ rather than _no rows_ —
62
+ so `getAgentThreads` returned every thread in the deployment. It now returns
63
+ `string[]`, empty for a sessionless caller, which every storage backend already
64
+ treats as matching nothing. Sessionless agents still run one-shot conversations,
65
+ each with a fresh unguessable owner; what they lose is cross-request continuity.
66
+ Wire a session to restore it.
67
+
68
+ **Breaking: stored secrets and credentials must be re-entered.** `deriveKey` ran
69
+ a single unsalted round of SHA-256 over the passphrase and used the digest
70
+ directly as the AES-GCM key — roughly one hash per brute-force guess, with one
71
+ rainbow table working against every deployment. It is now PBKDF2-HMAC-SHA256 at
72
+ 600,000 iterations over a random salt. There is no compatibility path: every
73
+ value held by the kysely, mongodb and redis secret services and the kysely
74
+ credential service becomes undecryptable. They fail loud, naming the key and
75
+ `key_version`, so the app hard-fails on first secret read until each is re-set.
76
+
77
+ The KEK salt is scoped to the key version and stored alongside it, rather than
78
+ per secret, so a bulk read costs one derivation instead of N — `getSecrets` over
79
+ 50 secrets went from ~2.3s to ~48ms, and rotation from ~4.6s to ~94ms. This adds
80
+ a salt table (kysely), hash field (redis) or collection (mongodb), created
81
+ automatically on first use.
82
+
83
+ **Breaking: `PIKKU_REMOTE_SECRET` must be at least 32 characters.** The
84
+ remote-RPC session envelope moved from PBKDF2 to HKDF, which expands
85
+ high-entropy key material rather than stretching a low-entropy passphrase. That
86
+ took a remote hop from ~269ms to ~0.4ms — PBKDF2 was running twice per request —
87
+ but HKDF supplies no brute-force resistance, so the secret must carry the
88
+ entropy itself. A shorter secret now throws `WeakKeyMaterialError` at both ends.
89
+ Generate one with `openssl rand -base64 32` and roll it out to every service in
90
+ the mesh together: existing bearer tokens are format-incompatible, so a partial
91
+ rollout produces 401s until every instance is updated. The Cloudflare, Lambda
92
+ and Azure deployment services each hand-rolled a copy of `buildRemoteHeaders`
93
+ and now call the shared one, which is what keeps the two sides in step.
94
+
95
+ **Breaking: previously signed content URLs stop verifying.** `LocalContent`
96
+ signed only `{signedAt, expiresAt, notBefore}`, so a signature proved when a URL
97
+ was issued but never what it was issued for — any valid token was a skeleton
98
+ key, and swapping the pathname from a public thumbnail to a private document
99
+ still verified. The signature now binds the request path. Separately, the
100
+ verifier returned "valid" when no JWT service was wired, which is how
101
+ `pikku serve` ran: a forged `?signedAt=0&expiresAt=99999999999999` was accepted.
102
+ It now rejects with 403, `LocalContent` requires a `JWTService`, and
103
+ `pikku serve`/`pikku dev` mint an ephemeral per-process signing key so local
104
+ development works without shipping a fail-open path. In-flight signed URLs must
105
+ be re-issued.
106
+
107
+ **Request body size limits now apply to every adapter.** The `maxBodySize` cap
108
+ existed only in `PikkuFetchHTTPRequest`. The real hole was uWebSockets, which
109
+ drove `res.onData` itself and concatenated every chunk with no bound and nothing
110
+ downstream able to intervene; it now drops chunks past the limit and replies 413
111
+ before routing. Fastify delegates to its native `bodyLimit` (set only when
112
+ `maxBodySize` is configured, so fastify's stricter 1 MB default is never
113
+ loosened), and `PikkuExpressServer` feeds the limit into its body parsers. Two
114
+ paths can only reject rather than prevent, and are documented as such:
115
+ `express-middleware` mounted on your own app receives an already-parsed body, so
116
+ that deployment must bound its own parser; Next server actions bottom out at
117
+ `experimental.serverActions.bodySizeLimit`.
118
+
119
+ **Breaking: the console addon's privileged functions are gated by default.**
120
+ `wireAddon` gains a `scopes` option that applies to every function in the
121
+ addon's namespace, and the console scaffold now generates
122
+ `wireAddon({ name: 'console', package: '@pikku/addon-console', scopes: ['admin'] })`.
123
+ Previously the console's entire privileged surface — around 54 functions
124
+ including `credentialGet`, which returns a resolved OAuth token for an arbitrary
125
+ `userId`, `updateFunctionBody`, and `installAddon`, which shells out to a
126
+ package install — was protected only by an optional host-registered
127
+ `addGlobalPermission`. `resolveGlobalPermissions` returns `[]` when none is
128
+ registered and permission checking then no-ops, so an app that never registered
129
+ one served those functions to anyone, and with the template's default
130
+ `scaffold.rpc: "no-auth"` that meant unauthenticated. All of them now return 403
131
+ `MissingScopeError` without an `admin`, `admin:*` or `*` scope. **Regenerating
132
+ is required** — an app holding an old `console.gen.ts` stays open.
133
+ `installAddon` and `installOpenapiAddon` additionally declare their own
134
+ `auth: true, scopes: ['admin']`, and `getAgentThreads` now scopes its listing to
135
+ the session's own threads unless the caller holds admin.
136
+
137
+ Addon scopes are enforced in `runPikkuFunc` rather than at the RPC boundary,
138
+ because a wiring can reference an addon function directly — the inspector
139
+ records the addon's `packageName` on HTTP, channel, schedule, queue, CLI,
140
+ trigger, gateway and MCP wirings — and those paths never call `resolveNamespace`.
141
+ Enforcing at the RPC seam would have covered only the `namespace:function` form
142
+ while reading as complete.
143
+
144
+ **Breaking: `wireAddon`'s `auth` and `tags` now apply on direct wirings too.**
145
+ Both were read only by `resolveAddonFunction`, so they had exactly the hole
146
+ scopes had: `wireAddon({ name: 'console', package: '@pikku/addon-console', auth:
147
+ true, tags: ['admin'] })` gated `rpc('console:credentialGet')` and gated nothing
148
+ at all on an HTTP route wired straight to `credentialGet`. A consumer who
149
+ reached for the documented way to lock an addon down got a control that was
150
+ silently inert on every wiring except one. Both now resolve in `runPikkuFunc`.
151
+ `auth` merges as an OR — `auth: false` from an addon is ignored on a direct
152
+ wiring, because an addon may require a session the wiring did not but must never
153
+ waive one it did. Addon tags resolve to concrete middleware against the **root**
154
+ tag groups before the call rather than being folded into the function's
155
+ inherited middleware: `addTagMiddleware('admin', …)` is written by the consuming
156
+ app and registers under the root package, whereas `combineMiddleware` would look
157
+ the tag up under the addon's own `packageName`, where it does not exist.
158
+
159
+ One consequence worth naming: an addon that wires `auth: true` and also runs its
160
+ own sessionless internal work — a scheduled task or queue worker inside the
161
+ addon calling a sibling function — is now gated where it previously was not,
162
+ because a bare `rpc('fn')` from inside the addon reaches `runPikkuFunc` with the
163
+ addon's `packageName` like any other call. This reverses a decision that
164
+ deliberately scoped the gate to the namespaced boundary; that reasoning held
165
+ only while the boundary was real, and a direct wiring can enter an addon without
166
+ crossing it, so "already inside" is not something the runtime can infer. Such an
167
+ addon should carry authorization on the function via
168
+ `pikkuFunc({ permissions })`, which has always been enforced on every path. A
169
+ follow-up will add execution provenance so an intra-addon call can be
170
+ distinguished from an external one and skip the addon-level check; that needs a
171
+ marker no caller outside the process can set, which is its own design problem
172
+ and does not belong in a security fix.
173
+
174
+ **Codegen now warns when an exposed function has no gate (PKU574).** The
175
+ generated `POST /rpc/:rpcName` dispatcher forwards to `rpc.exposed`, which
176
+ refuses anything without `expose: true` — but nothing checked whether the
177
+ target was gated, because a dispatcher cannot know what it dispatches to. The
178
+ console shipped ~54 privileged functions through that gap and the toolchain was
179
+ silent. The inspector now reports every function that is exposed, sessionless,
180
+ and carries no `auth`, `scopes` or `permissions` of its own and none from a
181
+ governing `wireAddon`. It is a `warn`, not a critical: `expose: true` on an
182
+ ungated sessionless function is correct for a genuinely public endpoint, so it
183
+ blocks a build only under `--fail-on-warn`.
184
+
185
+ Two pieces of metadata were missing for this to be answerable statically, and
186
+ both are now recorded. A `pikkuSessionlessFunc`'s own `auth: true` was read at
187
+ runtime but never written to function meta, so a self-gated function was
188
+ indistinguishable from an ungated one — `sessionless` carries the baseline, and
189
+ `auth` now carries the tightening. And `wireAddon`'s `scopes`, `auth` and `tags`
190
+ were not parsed at all: the inspector recorded the addon's `rpcEndpoint` and its
191
+ secret, variable and credential overrides, and dropped every one of its gates.
192
+ An addon whose gates are not statically knowable is treated as gated, because a
193
+ false positive on a correctly-secured addon costs more than the one case it
194
+ would catch.
195
+
196
+ **Breaking: an application's global permissions now apply inside addons.**
197
+ `resolveGlobalPermissions` read only the bucket matching the function's own
198
+ package, but the generated `addGlobalPermission` wrapper takes no package
199
+ argument and always registers under the root. An app-wide rule like "every
200
+ request needs a signed-in user" therefore stopped at the addon boundary, and the
201
+ bucket an addon's functions did read was one no host could write to — which is
202
+ why the console addon's recommended `addGlobalPermission([isAdmin],
203
+ '@pikku/addon-console')` was never a gate anybody could actually install. A
204
+ function now resolves the root bucket and its own package's, root first.
205
+ Unioning is safe in a way nothing else here would be: globals AND, so adding the
206
+ root ones can only tighten. Package buckets stay one-way — a package's globals
207
+ never reach root functions, or an installed addon could gate the whole
208
+ application. Apps with both a root global and addon-provided functions will see
209
+ those functions gated where they previously were not.
210
+
211
+ **Codegen now records whether each HTTP route requires a session, and warns
212
+ about inert addon tags (PKU575).** Four separate things can demand a session —
213
+ the function's `sessionless`, its own `auth`, the route's (or its group's)
214
+ `auth`, and the addon it belongs to — and answering "which routes are open?"
215
+ meant joining all four by hand and knowing which wins. Each route's meta now
216
+ carries the resolved `requiresSession` alongside the route's own `auth`. Scopes
217
+ count as requiring one, since they are matched against the session's and fail
218
+ closed. Anything not statically knowable resolves to `true`, matching PKU574:
219
+ a route that looks stricter than it is costs less than one that looks open and
220
+ isn't. Separately, `wireAddon({ tags: ['admin'] })` reads like a gate and is
221
+ applied like one right up until no `addTagMiddleware('admin', …)` exists, at
222
+ which point it resolves to an empty list and gates nothing; that now warns.
223
+ Only addon tags are reported — a tag on a function is as likely to be
224
+ organizational, and warning about those would bury the case that matters.
225
+
226
+ **Object-shorthand permissions were missing from meta.** The inspector visited
227
+ `ts.PropertyAssignment` but not `ts.ShorthandPropertyAssignment`, so
228
+ `permissions: { canAdminOrg }` — enforced identically to the longhand form at
229
+ runtime, since `verifyPermissions` has a non-array branch — was recorded as _no
230
+ permissions at all_. That is the most dangerous direction for meta to be wrong
231
+ in: an audit reading it sees an open door where one is shut. It cost this review
232
+ a false IDOR report across ~35 billing and org functions before the source
233
+ contradicted the metadata.
234
+
235
+ **Functions that authorize in their own body can say so.** A webhook receiver
236
+ verifying a signature, or a handler redeeming a signed invite, is genuinely
237
+ closed while carrying no session, scope or permission — indistinguishable in
238
+ meta from one nobody remembered to gate, and so warned about forever by PKU574.
239
+ `selfAuthenticated: true` on the function config records the claim and silences
240
+ the warning for that function. It is declarative only: nothing at runtime reads
241
+ it and it grants nothing. Detection was rejected deliberately — inferring it
242
+ from the body means a function that _looks_ like it checks something silences
243
+ the warning while checking nothing, and a warning that is usually wrong stops
244
+ being read.
245
+
246
+ **Breaking: `scaffold.<feature>` is now `boolean | { auth?, path? }`, and `true`
247
+ means authenticated.** The old `'auth' | 'no-auth' | false` read like a
248
+ starter-file preference while being a live authorization decision, set three
249
+ directories from the functions it governed — the shape the console incident
250
+ took. A surface now becomes public only by writing `{ auth: false }`, so
251
+ omitting a field can never open anything: the failure mode of a forgotten flag
252
+ is a locked door. `{ path }` additionally overrides where the file is
253
+ generated, which previously could only be set for all features at once via
254
+ `pikkuDir`.
255
+
256
+ The legacy strings are **refused, not coerced**. `resolveScaffoldFeature` throws
257
+ naming the key and its replacement (`"rpc": "no-auth"` → `"rpc": { "auth":
258
+ false }`), and it does so at config load, not downstream. An earlier design used
259
+ a bare `string` for the output path, under which `"no-auth"` would have parsed
260
+ as a file named `no-auth` and every unmigrated config would have silently
261
+ produced nonsense; the object form makes any string invalid, so the failure is
262
+ loud.
263
+
264
+ The collapse is deliberately not uniform in effect. For `rpc` the flag was a
265
+ blanket "no anonymous RPC in this app" set on a dispatcher that cannot know what
266
+ it dispatches to; for `userAdmin` it was redundant, since the generated
267
+ functions are already `pikkuFunc` with `scopes: ['admin:users:list']`. But for
268
+ `agent`, `workflow`, `events` and `scenarios` it is the only gate — those
269
+ generate real endpoints the app never authors — so `true` keeps them
270
+ authenticated rather than opening them as a side effect of a config cleanup.
271
+ `webhook` and `remoteRpc` have no auth dimension at all (`serialize-remote-rpc.ts`
272
+ hardcodes `auth: false`), so an `{ auth }` on them is ignored. The three
273
+ configs in this repo are migrated preserving their current behaviour exactly.
274
+
275
+ **Queue job identities are signed.** A job carried the producer's `pikkuUserId`
276
+ as a plain string and the worker resolved a session from it with no
277
+ verification, so write access to the queue backend was act-as-any-user. The
278
+ identity is now `pq1.<claim>.<hmac>`, HMAC-SHA256 over the claim and the
279
+ canonicalized job payload, keyed by HKDF expansion of a new
280
+ `PIKKU_QUEUE_IDENTITY_SECRET`. Producers opt in by wrapping their queue service
281
+ with `SignedQueueService`. This fails safe rather than closed: with no secret
282
+ configured the identity is dropped and jobs still process, warning once per
283
+ process, so no existing deployment breaks on upgrade — it simply loses queue
284
+ identity until the secret is set. The payload rather than the job id is bound
285
+ because SQS, Cloudflare Queues, Azure and the in-memory service all mint ids
286
+ after `add` returns.
287
+
288
+ **Workflow inline state is read from the run record.** `isInline` consulted a
289
+ process-local `Map`, while `WorkflowRun.inline` is durable. Any instance that
290
+ did not start a run disagreed with the record, so one instance could dispatch a
291
+ queued job for a workflow another was already executing in-process. It is now
292
+ async and resolves through the durable identity, cached only when a context
293
+ already exists so a passive reader allocates nothing. The same `Map` also leaked:
294
+ `nextStepKey` fabricated replay state on every step, and `releaseContext`
295
+ refused to free anything carrying it, so runs whose steps executed outside a
296
+ `beginReplay` bracket — the step-worker queue path — stranded their context and
297
+ step state for the process lifetime. Contexts are now released by an explicit
298
+ execution counter. Step ordinals reset per execution rather than accumulating
299
+ across step-worker invocations in one process, which makes step naming
300
+ independent of how work was distributed.
301
+
302
+ **Secret reads fail loud in every store.** `MongoDBSecretService.getSecrets`
303
+ skipped rows that failed to decrypt, and the redis equivalent dropped every
304
+ rejection via `Promise.allSettled`, including the "No KEK available for
305
+ key_version N" configuration error. Both now throw, naming the key and its key
306
+ version, matching the kysely behaviour. This matters most alongside the KEK
307
+ change above: without it, an upgrade surfaces as a partial secrets map and an
308
+ opaque downstream failure instead of an error naming the secret to re-enter.
309
+
310
+ **A second middleware registration for a pattern no longer erases the first.**
311
+ `addHTTPMiddleware`, `addTagMiddleware` and `addChannelMiddleware` groups are
312
+ keyed by pattern or tag and held one source file each, so a second file's call
313
+ overwrote the first's. Codegen emits its imports from what is stored, so the
314
+ losing file was never imported and its middleware never registered — the
315
+ runtime composes repeated registrations for a pattern happily, and only codegen
316
+ dropped one. Adding an unrelated `addHTTPMiddleware('*', …)` to an app was
317
+ enough to silently unregister the generated better-auth session bridge, which
318
+ fails open and gives no sign until a request arrives without a session. A group
319
+ now carries every registration made for it, and all of them are imported.
320
+
321
+ - 8075f6a: Confine `SecretService` to the places an app is wired.
322
+
323
+ `secrets` is now omitted from the services every function, AI agent, workflow,
324
+ permission and wire receives, and the function runner replaces it with a
325
+ throwing accessor so a cast cannot reach past the type. It stays available in
326
+ `pikkuServices`, `pikkuWireServices`, addon service factories and middleware —
327
+ read a secret there, give it to a service, and have the function ask that
328
+ service.
329
+
330
+ Alongside it:
331
+ - `wireSecret` gains `allowedHosts`, refusing a secret attached to a host it was
332
+ not declared for. Permissive by default; strict via
333
+ `config.secrets.requireAllowedHosts`.
334
+ - `pikku-graph`'s `httpRequest` resolves and attaches its credential inside a new
335
+ `httpRequester` service instead of holding the plaintext in the function.
336
+ - New inspector diagnostics: `PKU950` (a `SecretService` exposed under another
337
+ service name), `PKU951` (a secret read that no `wireSecret` declares) and
338
+ `PKU952` (a secret read with a non-literal key).
339
+
340
+ ## 0.12.73
341
+
342
+ ### Patch Changes
343
+
344
+ - c984df6: Give an agent's tools back the descriptions their authors wrote
345
+
346
+ A tool's description is what the model is told the tool does, and the main
347
+ thing it chooses between tools on. It was not reaching the model. `description`
348
+ is classed as a verbose field, so it is stripped from the metadata bundled into
349
+ the generated bootstrap — the copy `pikkuState('function', 'meta')` is built
350
+ from. `buildToolDefs` read the description from there, found it always
351
+ undefined, and fell through to the tool's own name. Every agent has been
352
+ choosing between bare identifiers. The same fallback was offering an addon's
353
+ MCP tools under their names, for the same reason.
354
+
355
+ Tool definitions now resolve descriptions through `metaService`, which reads
356
+ the verbose metadata and falls back to the minimal copy, so the authored text
357
+ is recovered wherever the generated `.pikku` directory is readable. Where it is
358
+ not — no `metaService`, or a deployment shipping only the stripped copy — a
359
+ tool falls back to its name, which is what it did before. Addon metadata is
360
+ likewise loaded verbose-first. `title` is no longer part of the chain: a title
361
+ labels a tool in a UI, it does not tell a model when to reach for it.
362
+
363
+ An addon has to ship the verbose file for any of this to reach it. `tsc` only
364
+ emits the JSON it sees imported and nothing imports the verbose meta, so the
365
+ bundled addons now copy it into `dist` explicitly.
366
+
367
+ `ref()` is resolved at build time. It used to be pushed through codegen as an
368
+ opaque string, so `ref('todos:doesNotExist')` generated cleanly and failed only
369
+ when the agent ran. The inspector now resolves each reference against the
370
+ project's functions, or — using the namespace-to-package mapping `wireAddon`
371
+ already provides — against the addon's own metadata, and reports an unwired
372
+ namespace (`PKU152`) or a missing function (`PKU153`) at codegen. An addon that
373
+ has not been built yet contributed no metadata and is skipped rather than
374
+ reported missing.
375
+
376
+ New `pikku --strict-meta` additionally fails the build on any agent tool with
377
+ no description (`PKU154`), including tools reached through an addon. It is off
378
+ by default, so nothing that builds today stops building; turn it on to hold a
379
+ project to the metadata its agents actually run on.
380
+
381
+ - 63ff32b: Run a CLI's commands on the server, over the connection the client opened
382
+
383
+ A CLI that talks to a service has to ship the service's command tree, so the
384
+ two versions drift: the binary someone installed months ago still believes in
385
+ flags and commands the server has since changed. This makes the command tree
386
+ the server's, and leaves the client holding only a socket.
387
+
388
+ `wireCLI` gains `auth`, and a program wired with a channel entrypoint now
389
+ generates a `__raw` route: the client forwards argv untouched, the server
390
+ parses it, runs the command, and streams the output back as it happens. The
391
+ terminating frame carries the exit code, so a failed remote command still exits
392
+ non-zero locally. Renderers stay on the client and are matched by the command
393
+ id the server reports; an unrecognised command falls back to JSON rather than
394
+ failing.
395
+
396
+ Every channel gains `channel.remote(...)`: calling a function on the peer at
397
+ the other end of the connection and waiting for its answer. A channel is
398
+ otherwise fire-and-forget in both directions, so this is what reaches a peer
399
+ that has no address of its own — a CLI on a laptop, a browser tab, a sandbox
400
+ behind NAT. It is on `channel` rather than `rpc` because it is bound to one
401
+ connection: which peer answers is the socket the call goes out on, not
402
+ something the RPC map could resolve. Any `wireChannel` gets it — a client
403
+ registers what it is willing to answer to, and a name outside that list is
404
+ refused.
405
+
406
+ Requests are correlated by id, time out, and fail fast when the socket closes
407
+ rather than waiting out the timeout. Replies are taken off the socket ahead of
408
+ routing, so a channel needs no route for them and an answer can never be
409
+ mistaken for a new message; the transport is created on first use and released
410
+ when the channel closes, which is also what fails anything the departing peer
411
+ still owed an answer to. Channels that only flow one way — SSE, an agent's
412
+ output stream, a locally-run CLI — refuse the call outright instead of waiting
413
+ for an answer that was never going to come.
414
+
415
+ What a peer answers with is its word, so it is checked before a caller sees it
416
+ — against the schema codegen already generated from the function's declared
417
+ return type, the same one an agent tool or an HTTP response is checked against.
418
+ A capability is declared with `pikkuRemoteChannelFunc`, which takes the usual
419
+ `title` / `description` / `input` / `output` but no `func` — this side owns the
420
+ contract, the peer owns the body. It registers under its name like any other
421
+ function, so `channel.remote` is typed off the same generated map as
422
+ `rpc.remote` and no caller has to cast, and a local call throws rather than
423
+ missing: reaching it locally means a command asked the server for something
424
+ only a client knows. A client on an older build fails the call it answered
425
+ rather than the caller failing later somewhere with no reason to expect a bad
426
+ shape; a name with no declared contract is left alone. Both frame guards
427
+ validate the whole envelope rather than the action tag alone, and a failure
428
+ payload with a non-string name or message falls back rather than being attached
429
+ to an `Error`.
430
+
431
+ The arguments going the other way are checked too, against the schema for the
432
+ capability's declared input, before anything is registered or sent. That is not
433
+ a boundary — the peer runs the code and has to check what it was handed, and a
434
+ caller that meant harm would send arguments that pass. It catches drift, where a
435
+ server built against a newer capability signature calls a client that predates
436
+ it, and fails it here rather than inside someone else's process.
437
+
438
+ A channel-driven CLI command uses this to ask its caller for machine-local
439
+ facts mid-run — a git sha, a working tree, a local file. The CLI wire's own
440
+ channel is synthetic (it exists so a command can stream progress without
441
+ knowing where that goes), so it delegates `remote` to the connection the
442
+ command actually arrived on.
443
+
444
+ Because that runs code on someone's machine at a remote caller's request, the
445
+ capability map says what _can_ run and approval says whether a particular call
446
+ _should_. A capability may be declared `{ execute, needsApproval }`, sharing
447
+ `ApprovalPolicy` — `needsApproval` and `approvalDescriptionFn` — with
448
+ `AIAgentToolDef`, which has carried both since before channels could call back:
449
+ both are an allowlist of named callables invoked by something other than the
450
+ code that wrote them. The runtime around them is deliberately not shared, since
451
+ an agent suspends its run and resumes it later while a reverse call is a live
452
+ await with a person at the other end.
453
+
454
+ A capability written as a bare function is unclassified, and unclassified means
455
+ approval is required — the annotation nobody got round to writing is the one
456
+ most likely to matter, so it fails closed. Declare
457
+ `{ execute, needsApproval: false }` for a capability that may run unattended.
458
+ Nothing infers this: core cannot tell a read-only capability from a destructive
459
+ one, so `needsApproval: false` is the author asserting it, and the assertion is
460
+ the only thing standing between a remote caller and the machine.
461
+
462
+ The default is the opposite of `AIAgentToolDef`'s, where absence means "do not
463
+ ask" — a tool is written by the same people who run the server it executes on,
464
+ and a capability is not.
465
+
466
+ `executeRawCLIViaChannel` reads `--auto-approve` and
467
+ `--dangerously-auto-approve` out of argv (or `PIKKU_AUTO_APPROVE` /
468
+ `PIKKU_DANGEROUSLY_AUTO_APPROVE`) and strips them before argv reaches the
469
+ server — what may run on this machine is this machine's decision, and a flag
470
+ the server can see is one the server could act on. `--auto-approve` permits the
471
+ classified-safe set and refuses the rest; `--dangerously-auto-approve` permits
472
+ everything and says so once on stderr. Interactively the user is asked per
473
+ call, with `y` / `n` / `a`, where `a` is remembered for that one capability for
474
+ the rest of the run and never written to disk — widening it to the session
475
+ would quietly turn an interactive run into `--dangerously-auto-approve`. A run
476
+ with no terminal and no flag refuses rather than assuming yes, because CI is
477
+ exactly where an unattended `git push` would otherwise happen. The tiers are
478
+ meaningful here in a way they would not be for an agent: the caller is a
479
+ deterministic program whose source can be read, so "these calls are always
480
+ fine" is a claim someone can actually justify.
481
+
482
+ A peer that is asking a human sends a pending frame first, which stops the
483
+ caller's timeout. Without it any approval slower than the timeout would fail
484
+ the call and then discard the decision when it finally arrived. The call is
485
+ still failed the moment the socket drops — what actually happens when a peer
486
+ dies mid-prompt — and a peer that sends the frame dishonestly can do nothing
487
+ but keep its own call waiting. A refusal is sent as an answer, so a denied call
488
+ fails its command immediately rather than hanging.
489
+
490
+ Fixes found on the way, each of which broke this path:
491
+ - A websocket upgrade wrote middleware headers (CORS, on every request)
492
+ straight onto the socket, so the first bytes a client saw were headers rather
493
+ than `ws`'s `101` status line and the handshake failed to parse. Header
494
+ writes are now buffered and flushed behind a status line only when the
495
+ upgrade is actually being rejected.
496
+ - An upgrade socket had no error listener while the channel opened, so a client
497
+ that gave up mid-handshake took the whole server process down with an
498
+ unhandled `ECONNRESET`.
499
+ - `onConnect` and `onDisconnect` never saw the session established during the
500
+ upgrade, so a channel could not tell who had just connected.
501
+ - Setting the routing key on a channel result mutated the value in place, which
502
+ throws for a primitive under ESM strict mode.
503
+
504
+ - ba6cc08: fix: stop leaking internal error detail and bound the request body size
505
+
506
+ HTTP error responses no longer forward an error's `payload` or its raw `message` for
507
+ registered 5xx errors — those responses carry the registered error message instead, so an
508
+ internal error that happens to hold a `payload` cannot leak it to the client. Errors
509
+ registered with a 4xx status keep their message and payload, and `exposeErrors` still
510
+ surfaces the full detail outside production.
511
+
512
+ `PikkuFetchHTTPRequest` now caps how much of a request body it buffers, rejecting the
513
+ declared `content-length` up front and measuring the stream as it arrives so a lying or
514
+ absent header cannot exhaust memory. Exceeding the limit throws `PayloadTooLargeError`
515
+ (413). The ceiling defaults to 10MB and is configurable via the new `maxBodySize` option on
516
+ the constructor and on `RunHTTPWiringOptions`.
517
+
518
+ - d007191: `cors()` takes an `exposeHeaders` option.
519
+
520
+ Without `Access-Control-Expose-Headers` a cross-origin caller can read only the
521
+ CORS-safelisted response headers, so any header the client is meant to act on was
522
+ invisible to it. The cross-site session relay in `@pikku/better-auth` is the case that
523
+ surfaced it: the client cannot read `x-pikku-cross-site-set-cookie` off a cross-origin
524
+ response without being told it may.
525
+
526
+ Defaults to none, so nothing new is exposed unless it is named.
527
+
528
+ - a7b26c5: rename the inspected declarations to `define*`: `wireScope` → `defineScope`, `wireSecret` → `defineSecret`, `wireVariable` → `defineVariable`, `wireCredential` → `defineCredential`
529
+
530
+ `wire*` meant two unrelated things. A transport wiring attaches a function to
531
+ something that can invoke it — `wireHTTP`, `wireChannel`, `wireScheduler`,
532
+ `wireQueueWorker` and the rest — and the thing it wires runs. These four wire
533
+ nothing: they are no-ops that exist only so the call typechecks, they are
534
+ tree-shaken out of the build, and their whole job is to be found by the
535
+ inspector's AST pass and turned into a type union. One word for both left the
536
+ declaration reading like a registration with a runtime.
537
+
538
+ So the vocabulary splits: **`wire*` is a transport, `define*` is an inspected
539
+ declaration.**
540
+
541
+ ```ts
542
+ import { defineScope } from '@pikku/core/scope'
543
+ import { defineSecret } from '@pikku/core/secret'
544
+ import { defineVariable } from '@pikku/core/variable'
545
+ import { defineCredential } from '@pikku/core/credential'
546
+
547
+ defineScope({ admin: { scopes: { invoices: { scopes: { create: {} } } } } })
548
+ ```
549
+
550
+ **Breaking:** no alias is kept. Rename the four call sites; the module subpaths
551
+ (`@pikku/core/scope`, `/secret`, `/variable`) are unchanged.
552
+
553
+ The inspector matches these by identifier text, so a stale `wire*` call is not a
554
+ type error — it is silently not extracted, and the generated union comes back
555
+ empty. That fails as "this scope isn't declared" on code that was fine a moment
556
+ ago, nowhere near the declaration. Grep for the old names rather than trusting a
557
+ clean build.
558
+
559
+ An addon published with `.pikku` output generated before this release re-exports
560
+ `wireSecret` from `@pikku/core/secret` and will not typecheck against this core
561
+ until it is rebuilt and republished.
562
+
563
+ - 457cb25: Add `definePersonas()`: the people a project's scenarios and virtual users run
564
+ as, declared in code.
565
+
566
+ There used to be three names for two-and-a-bit things — an _actor_ in
567
+ `scenarios.actors`, a _persona_ in `scenarios.personas`, and a _virtual user_
568
+ declared separately against an actor. In practice almost every actor was its own
569
+ kind, so the second set carried no information and the third was a third place
570
+ for a name to drift. There is now one declaration:
571
+
572
+ ```ts
573
+ definePersonas({
574
+ shopper: {
575
+ name: 'Sam Shopper',
576
+ jobTitle: 'Shopper',
577
+ personality: 'Buys in a hurry and leaves tabs open',
578
+ roles: ['customer'],
579
+ disposition: 'careless',
580
+ goals: ['Buy something without reading anything'],
581
+ account: {},
582
+ },
583
+ })
584
+ ```
585
+
586
+ A persona is a person: what they are like, what they want, the roles they hold,
587
+ and **one** account they sign in with — `account: {}` plus `linkedAccounts` for
588
+ the rare case of more, modelled on how better-auth does linking. A persona with a
589
+ `disposition` is a virtual user; `runnable: false` marks someone who only ever
590
+ exists to be acted upon — banned, shared with, reset — and is never handed a
591
+ session.
592
+
593
+ **A persona names roles, never scopes.** Scopes come from `defineSystemRole()`
594
+ expansion, so the build fails if a persona names a role nobody declared, and
595
+ fails again if a role confers a scope no `defineScope` declares. Running one only
596
+ ever has to check that its roles are still valid.
597
+
598
+ **Addresses are computed, never declared.** `personaEmail(id, domain, runId)`
599
+ derives `<id>[+runId]@<domain>` from `scenarios.emailDomain`, so a seed, a
600
+ scenario run and a virtual-user run cannot disagree about who they are signing in
601
+ as. `scenarios.actors` and `scenarios.personas` are gone from
602
+ `pikku.config.json` — only `emailDomain` remains.
603
+
604
+ `actor` survives in exactly one place: the name of a **slot in a scenario step**,
605
+ which is the role a persona is cast in for that step. `pikkuVirtualUser()`,
606
+ `kind`, `grants` and the `actor` field are removed; the `actors` service is now
607
+ `personas`, and the CLI's `virtual-user` commands are now `pikku persona list` /
608
+ `pikku persona run`. `budget` and `allowApprovalRequired` moved to run flags —
609
+ how much you will spend today is not a fact about a person.
610
+
611
+ `@pikku/cucumber` drops its `Actor` class and `ActorDispatchContext`: a
612
+ hand-rolled cookie jar that a persona's own typed session replaces outright.
613
+
614
+ - f7567ad: Add `defineSystemRole()`: roles that ship with the product, declared in code.
615
+
616
+ A system role is to a console-composed role what an AWS managed policy is to a
617
+ customer-managed one — the console may show and grant it, but not rename,
618
+ re-scope or delete it. The CLI extracts declarations by AST and generates a
619
+ `SystemRoleName` union, so naming a role that does not exist fails the build,
620
+ and a role granting a scope no `defineScope` declares fails it too.
621
+
622
+ Removal is additive on the same terms as `defineScope`: deleting a declaration
623
+ leaves an inert row rather than revoking everyone's grant mid-deploy.
624
+
625
+ `ScopeService` gains `syncSystemRoles`, `findStaleSystemRoles` and
626
+ `pruneSystemRoles`; `Role` gains `system` and `declared`. Implementations
627
+ enforce immutability through the shared `assertRoleIsMutable` /
628
+ `assertRoleNameAvailable` guards rather than each inventing the rule.
629
+
630
+ - ba6cc08: Security hardening: removed the gopass secret service and stopped MCP internal errors leaking stack traces.
631
+
632
+ **Breaking:** `GopassSecretService` and the `@pikku/core/services/gopass-secrets` subpath export are gone. The service shelled out to the `gopass` binary and its key validation accepted `../`, so a caller-supplied key could traverse out of the configured prefix namespace and read secrets outside it. Rather than harden a shell-out that few projects used, the service is removed. Anyone importing it should implement `SecretService` against their own secret backend. Pre-0.13 breaking changes still ship as a patch.
633
+
634
+ MCP internal errors (JSON-RPC `-32603`) previously always attached `data: { message, stack }`, handing any MCP client an internal stack trace. That payload is now gated on `exposeErrors`, which defaults to `!isProduction()` — the same convention `handleHTTPError` already uses. In production a client receives a bare `Internal error` with no `message` and no `stack`; `RunMCPEndpointParams` accepts an explicit `exposeErrors` to override the default.
635
+
636
+ - a2e21e5: Keep the persona runtime off the production barrels
637
+
638
+ `@pikku/core/services` exported `HttpPersona`, `createHttpPersonas` and
639
+ `readScenarioHttpResponse` as values, and `@pikku/core/workflow` exported
640
+ `readScenarioHttpResponse` and `postScenarioJson`. Both are barrels a production
641
+ server imports, and `http-personas` reaches the actor-flow conversation runner
642
+ and through it the agent runner — so signing-in-as-a-persona machinery sat in the
643
+ module graph of every app that imported services.
644
+
645
+ Tree-shaking only removes that if you bundle. An unbundled Node or Lambda deploy
646
+ loads whatever the graph names, which is the case this matters in.
647
+
648
+ The values now come from `@pikku/core/persona`, which is where the rest of the
649
+ persona API already lives. **Types stay exactly where they were** — `import type`
650
+ erases, so it costs a bundle nothing, and moving them would put core in a cycle
651
+ with the code that describes its own function types.
652
+
653
+ `serialize-personas` generates the new import, so a regenerated
654
+ `pikku-personas.gen.ts` picks it up with no edit. Anything importing these four
655
+ values from `@pikku/core/services` or `@pikku/core/workflow` changes the
656
+ specifier to `@pikku/core/persona`; the names and signatures are unchanged.
657
+
658
+ A test walks each barrel's value-import graph and fails if scenario runtime
659
+ reappears, so this cannot regress quietly.
660
+
661
+ - 457cb25: Let a persona do a real job in production, and say where it may act.
662
+
663
+ A persona was only ever a test subject: something you pointed at a stage to find
664
+ out what the product does wrong. But the same declaration — a name, a job, the
665
+ roles it holds and what it is trying to get done — describes a teammate doing
666
+ the work for real, and nothing about the engine cared which one it was.
667
+
668
+ Four changes make that difference explicit and enforced.
669
+
670
+ **`environments` moves to the top level of `pikku.config.json`**, out from under
671
+ `scenarios`. It was never a scenario's anything: `persona run` targets one, and
672
+ now so does `persona sync`. An environment may be flagged `production: true` —
673
+ a flag rather than a reserved name, because projects call it `prod`, `live` or
674
+ `eu-prod`, and more than one environment can be production.
675
+
676
+ **A persona may name its `environments`.** Omitting them means every configured
677
+ environment _except_ the production ones, so nothing reaches production by being
678
+ forgotten. Naming a production environment requires `disposition: 'accountable'`.
679
+ The rule is checked twice, on purpose: the inspector refuses to generate a
680
+ declaration that breaks it, and sign-in re-checks against the environment
681
+ actually resolved — the build check trusts the file, and the run check does not
682
+ trust which artifact got deployed. An unresolved environment fails closed.
683
+
684
+ **`disposition: 'accountable'`** is that production disposition. It sits opposite
685
+ `adversarial` on the intent axis rather than the care axis: what it changes stays
686
+ changed, every call is recorded against its name, and it stops to ask rather than
687
+ acting and reporting afterwards. Alongside it, **agents now appear in a persona's
688
+ computed catalogue**, gated by the same scopes as the RPCs — an agent is reached
689
+ rather than declared, so a persona finds the specialists its roles unlock and
690
+ chooses between calling the API itself and handing the work over. That also fixes
691
+ a latent gap: `talkTo` was wired at the target but never advertised in the
692
+ instructions, so it was never used.
693
+
694
+ **`pikku persona sync <environment>`** provisions them: it creates each account
695
+ and applies the roles it declares, additively, and never revokes. Seeding is test
696
+ data and `db seed` does not run in production; a teammate doing a real job still
697
+ needs an account and its grants. It needs both halves of an environment — its API
698
+ to sign the person in, its database to write the grants — and `--dry-run` reports
699
+ who would be provisioned, with what, and why anyone was skipped.
700
+
701
+ In the console, a virtual user now says where it may act — the environments it
702
+ named, or the rule when it named none — and its dossier carries the `sync`
703
+ command alongside the `run` one, because the account is not a by-product of a
704
+ run. `accountable` reads as a disposition like the rest.
705
+
706
+ - 86a50b9: scenario: replace `browser: true` + `func` with per-surface bindings on `pikkuScenarioStep`
707
+
708
+ A step now declares one implementation per surface it can be driven through:
709
+
710
+ ```ts
711
+ export const buysTheItem = pikkuScenarioStep<{ sku: string }, { orderId: string }>({
712
+ name: 'buysTheItem',
713
+ description: 'buys the item',
714
+ browser: async (services, data, { browser }) => { ... },
715
+ default: async (services, data, { rpc }) => { ... },
716
+ })
717
+ ```
718
+
719
+ `pikku scenario run --run browser|cli|default` picks which surface the run drives,
720
+ and the two phases resolve bindings differently:
721
+ - **Actions** (`given` / `when` / `step`) run exactly one binding — the run
722
+ surface if it has one, otherwise `default`. A step with neither now fails with
723
+ `ScenarioNoSurfaceBinding` instead of silently running server-side.
724
+ - **Assertions** (`then`) are witnesses, not alternatives: every declared binding
725
+ runs and they must agree. Two surfaces reporting different things fails the run
726
+ with `ScenarioWitnessDisagreement` rather than reporting a pass. An assertion
727
+ with no witness the run can execute at all fails with `ScenarioNoWitness` —
728
+ without it the step returns `undefined` and renders as a tick, reporting a pass
729
+ for something nobody checked.
730
+
731
+ A scenario written as a step ladder that never calls `then` is now a **PKU680**
732
+ critical. It proves only that nothing threw, so an assertion-free ladder of
733
+ browser-bound actions would score perfect coverage while checking nothing.
734
+
735
+ The report gains a surface-coverage line — `n/m steps ran on browser`, counted
736
+ over every step, so an action that fell back to the server lowers the ratio
737
+ rather than needing a footnote. That also makes surfaces comparable over one
738
+ denominator: a scenario is `4/4` on a default run and `3/4` on a browser one.
739
+ Assertions that fell back are named separately and gate `--strict`, since a
740
+ sentence claiming the actor saw something nobody looked at is a different problem
741
+ from an action taking a shortcut.
742
+
743
+ **Breaking:** `browser: true` and the third `B extends boolean` type argument are
744
+ gone. Rename `func` to `default` (or to `browser` where the step drove a browser)
745
+ and drop the type argument.
746
+
747
+ - 0e0f6eb: Add virtual users: LLM-driven synthetic users that work a real stage in
748
+ character.
749
+
750
+ A scenario proves a path somebody thought of. A virtual user works the same
751
+ ground without the script — it signs in as a declared persona over the app's own
752
+ auth, is handed the scenarios' BDD prose and the schema of every endpoint it may
753
+ reach, and decides for itself what to do. It asserts nothing; a run produces
754
+ findings, and their absence only ever means "not this time, not with this seed".
755
+
756
+ There is nothing extra to declare. A persona with a `disposition` is a virtual
757
+ user, and running it is what makes it one — see the `definePersonas` changeset
758
+ for the declaration itself. Listing, describing or running one never loads the
759
+ app: the inspector reads the literal declaration, the CLI writes
760
+ `scopes/pikku-personas-meta.gen.json`, and `MetaService.getPersonasMeta()`
761
+ serves it.
762
+
763
+ **Dispositions are engine dials, not prose.** Each carries its own intent weights
764
+ (continue / suspend / resume / abandon), temperature, re-read and repeat rates,
765
+ and switches: `careless` puts things down and picks them up in the wrong order,
766
+ `newcomer` starts with no memory, `auditor` is never offered a mutation,
767
+ `adversarial` is shown the catalogue its roles do not cover — being offered a
768
+ call it should not be able to make is the test — while those roles stay live as
769
+ the oracle, so a success outside them is authorization drift rather than a pass.
770
+
771
+ **Nothing is retrieved against.** The whole reachable catalogue goes into the
772
+ instructions (~8k tokens on a 430-RPC project, cached for the run), because a
773
+ ranking function would make the user only as adventurous as the ranking and lose
774
+ exactly the endpoints worth stumbling into. Schema first: an endpoint must be
775
+ described before it may be called.
776
+
777
+ **No money in core.** The engine counts steps, calls, mutations and tokens; what
778
+ they cost is the app's to decide through `stop(tally)`.
779
+
780
+ CLI: `pikku persona list` and `pikku persona run <environment> [name]`, with
781
+ flags overriding a declaration for reproduction (`--seed`, `--steps`,
782
+ `--disposition`). Spending is a run flag too — `--steps`, `--mutations` and
783
+ `--duration` bound a run, because how much you will spend today is not a fact
784
+ about a person. Console: a Virtual Users screen beside Scenarios, built out of
785
+ core's own derivation functions so it shows a run's actual inputs rather than a
786
+ second implementation of them.
787
+
788
+ `dev-ai-runner` now ships its own `@pikku/ai-vercel` and
789
+ `@ai-sdk/openai-compatible` instead of requiring them from the project. Behind a
790
+ proxy one openai-compatible provider answers for every prefix, so there was never
791
+ a per-vendor package worth making somebody install; the project's copies still
792
+ win when it has them, and both load from the same place or neither does.
793
+
1
794
  ## 0.12.72
2
795
 
3
796
  ### Patch Changes