@pikku/core 0.12.106 → 0.12.111

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 (589) hide show
  1. package/CHANGELOG.md +358 -0
  2. package/dist/analytics/analytics.d.ts +6 -0
  3. package/dist/analytics/analytics.js +58 -0
  4. package/dist/analytics/analytics.types.d.ts +156 -0
  5. package/dist/analytics/analytics.types.js +1 -0
  6. package/dist/analytics/anonymous-analytics-identity.d.ts +23 -0
  7. package/dist/analytics/anonymous-analytics-identity.js +27 -0
  8. package/dist/analytics/compose-analytics-identity.d.ts +14 -0
  9. package/dist/analytics/compose-analytics-identity.js +33 -0
  10. package/dist/analytics/cookie-analytics-identity.d.ts +24 -0
  11. package/dist/analytics/cookie-analytics-identity.js +37 -0
  12. package/dist/analytics/define-analytics-events.d.ts +22 -0
  13. package/dist/analytics/define-analytics-events.js +9 -0
  14. package/dist/analytics/fan-out-analytics.d.ts +15 -0
  15. package/dist/analytics/fan-out-analytics.js +36 -0
  16. package/dist/analytics/index.d.ts +13 -0
  17. package/dist/analytics/index.js +8 -0
  18. package/dist/analytics/logger-analytics-service.d.ts +14 -0
  19. package/dist/analytics/logger-analytics-service.js +23 -0
  20. package/dist/analytics/mint-cookie.d.ts +44 -0
  21. package/dist/analytics/mint-cookie.js +55 -0
  22. package/dist/errors/errors.d.ts +7 -0
  23. package/dist/errors/errors.js +17 -0
  24. package/dist/function/function-meta.types.d.ts +2 -0
  25. package/dist/function/function-runner.js +29 -0
  26. package/dist/function/functions.types.d.ts +22 -3
  27. package/dist/middleware/auth-apikey.d.ts +1 -1
  28. package/dist/pikku-state.d.ts +1 -1
  29. package/dist/scopes.d.ts +11 -0
  30. package/dist/scopes.js +17 -0
  31. package/dist/services/credential-wire-service.d.ts +1 -1
  32. package/dist/services/feature-flag-service.d.ts +100 -0
  33. package/dist/services/feature-flag-service.js +1 -0
  34. package/dist/services/index.d.ts +1 -0
  35. package/dist/services/meta-service.d.ts +16 -0
  36. package/dist/services/meta-service.js +19 -0
  37. package/dist/services/webhook-service.d.ts +7 -2
  38. package/dist/services/webhook-service.js +11 -6
  39. package/dist/testing/service-tests/agent-run-service-tests.d.ts +2 -2
  40. package/dist/testing/service-tests/agent-storage-service-tests.d.ts +1 -1
  41. package/dist/testing/service-tests/channel-store-tests.d.ts +1 -1
  42. package/dist/testing/service-tests/credential-service-tests.d.ts +1 -1
  43. package/dist/testing/service-tests/deployment-service-tests.d.ts +1 -1
  44. package/dist/testing/service-tests/event-hub-store-tests.d.ts +1 -1
  45. package/dist/testing/service-tests/secret-service-tests.d.ts +1 -1
  46. package/dist/testing/service-tests/session-store-tests.d.ts +1 -1
  47. package/dist/testing/service-tests/workflow-run-service-tests.d.ts +1 -1
  48. package/dist/testing/service-tests/workflow-service-tests.d.ts +1 -1
  49. package/dist/types/core.types.d.ts +23 -0
  50. package/dist/wirings/agent/agent-rpc.d.ts +1 -1
  51. package/dist/wirings/agent/agent-turn.d.ts +1 -1
  52. package/dist/wirings/agent-scorer/agent-scorer-live.d.ts +1 -1
  53. package/dist/wirings/channel/channel-common.d.ts +1 -1
  54. package/dist/wirings/channel/channel-rpc-validators.d.ts +2 -2
  55. package/dist/wirings/channel/channel-runner.d.ts +1 -1
  56. package/dist/wirings/channel/local/local-channel-runner.d.ts +1 -1
  57. package/dist/wirings/channel/serverless/serverless-channel-runner.d.ts +1 -1
  58. package/dist/wirings/cli/channel/cli-approval.d.ts +2 -2
  59. package/dist/wirings/flag/assert-feature-available.d.ts +15 -0
  60. package/dist/wirings/flag/assert-feature-available.js +23 -0
  61. package/dist/wirings/flag/cached-flag-source.d.ts +73 -0
  62. package/dist/wirings/flag/cached-flag-source.js +96 -0
  63. package/dist/wirings/flag/define-feature-flags.d.ts +33 -0
  64. package/dist/wirings/flag/define-feature-flags.js +32 -0
  65. package/dist/wirings/flag/flag.types.d.ts +97 -0
  66. package/dist/wirings/flag/flag.types.js +1 -0
  67. package/dist/wirings/flag/index.d.ts +7 -0
  68. package/dist/wirings/flag/index.js +5 -0
  69. package/dist/wirings/flag/resolve-flag.d.ts +52 -0
  70. package/dist/wirings/flag/resolve-flag.js +90 -0
  71. package/dist/wirings/flag/validate-flag-definitions.d.ts +26 -0
  72. package/dist/wirings/flag/validate-flag-definitions.js +103 -0
  73. package/dist/wirings/rpc/rpc-runner.js +3 -0
  74. package/dist/wirings/virtual-user/virtual-user-scaffold.d.ts +8 -8
  75. package/dist/wirings/virtual-user/virtual-user-schedule.d.ts +1 -1
  76. package/dist/wirings/workflow/workflow-queue-routing.d.ts +1 -1
  77. package/package.json +11 -5
  78. package/run-tests.sh +17 -9
  79. package/src/public-surface.json +26 -0
  80. package/src/agent-naming.test.ts +0 -68
  81. package/src/api-report.test.ts +0 -138
  82. package/src/app-alias-surface.test.ts +0 -179
  83. package/src/app-leaf-surface.test.ts +0 -222
  84. package/src/bootstrap-compat/root.ts +0 -20
  85. package/src/classification/column-form.test.ts +0 -97
  86. package/src/classification/column-form.ts +0 -55
  87. package/src/classification/data-classification.ts +0 -73
  88. package/src/classification/index.ts +0 -40
  89. package/src/classification/key-ids.ts +0 -2
  90. package/src/classification/secret-value.test.ts +0 -204
  91. package/src/classification/secret-value.ts +0 -106
  92. package/src/crypto-utils.test.ts +0 -668
  93. package/src/crypto-utils.ts +0 -460
  94. package/src/dev/hot-reload.test.ts +0 -587
  95. package/src/dev/hot-reload.ts +0 -225
  96. package/src/dev/module-runner.test.ts +0 -235
  97. package/src/dev/module-runner.ts +0 -138
  98. package/src/dev/reload-meta.test.ts +0 -183
  99. package/src/dev/reload-meta.ts +0 -144
  100. package/src/ecosystem-tier-removed.test.ts +0 -72
  101. package/src/env.ts +0 -1
  102. package/src/errors/error-handler.ts +0 -77
  103. package/src/errors/error.test.ts +0 -229
  104. package/src/errors/errors.ts +0 -393
  105. package/src/errors/index.ts +0 -11
  106. package/src/errors/serialized-error.ts +0 -12
  107. package/src/factory-functions.test.ts +0 -111
  108. package/src/function/abort-scope.test.ts +0 -97
  109. package/src/function/abort-scope.ts +0 -80
  110. package/src/function/function-meta.types.ts +0 -151
  111. package/src/function/function-runner.test.ts +0 -1619
  112. package/src/function/function-runner.ts +0 -499
  113. package/src/function/functions.types.ts +0 -319
  114. package/src/function/index.ts +0 -40
  115. package/src/function/list.types.test.ts +0 -100
  116. package/src/function/list.types.ts +0 -69
  117. package/src/function/pikku-request.test.ts +0 -35
  118. package/src/function/pikku-request.ts +0 -17
  119. package/src/gopass-secrets-removed.test.ts +0 -51
  120. package/src/handle-error.test.ts +0 -532
  121. package/src/handle-error.ts +0 -64
  122. package/src/middleware/auth-apikey.test.ts +0 -362
  123. package/src/middleware/auth-apikey.ts +0 -39
  124. package/src/middleware/auth-bearer.test.ts +0 -566
  125. package/src/middleware/auth-bearer.ts +0 -83
  126. package/src/middleware/auth-cookie.test.ts +0 -572
  127. package/src/middleware/auth-cookie.ts +0 -107
  128. package/src/middleware/cors.test.ts +0 -579
  129. package/src/middleware/cors.ts +0 -103
  130. package/src/middleware/index.ts +0 -30
  131. package/src/middleware/middleware-factories.ts +0 -76
  132. package/src/middleware/middleware.types.ts +0 -61
  133. package/src/middleware/remote-auth.test.ts +0 -547
  134. package/src/middleware/remote-auth.ts +0 -95
  135. package/src/middleware/remote-jobs-secret.ts +0 -35
  136. package/src/middleware/require-origin.test.ts +0 -115
  137. package/src/middleware/require-origin.ts +0 -79
  138. package/src/middleware/telemetry.ts +0 -83
  139. package/src/middleware-runner.test.ts +0 -578
  140. package/src/middleware-runner.ts +0 -232
  141. package/src/no-any-casts.test.ts +0 -57
  142. package/src/no-root-barrel.test.ts +0 -122
  143. package/src/permissions.test.ts +0 -256
  144. package/src/permissions.ts +0 -217
  145. package/src/pikku-state.test.ts +0 -198
  146. package/src/pikku-state.ts +0 -206
  147. package/src/production-barrels-stay-lean.test.ts +0 -110
  148. package/src/public-surface.test.ts +0 -133
  149. package/src/remote.test.ts +0 -173
  150. package/src/remote.ts +0 -56
  151. package/src/removed-legacy-exports.test.ts +0 -66
  152. package/src/run-tests-script.test.ts +0 -67
  153. package/src/schema.test.ts +0 -430
  154. package/src/schema.ts +0 -204
  155. package/src/scopes.test.ts +0 -203
  156. package/src/scopes.ts +0 -67
  157. package/src/services/agent-run-state-service.ts +0 -37
  158. package/src/services/agent-runner-service.ts +0 -238
  159. package/src/services/agent-storage-service.ts +0 -39
  160. package/src/services/ai-embedding-service.ts +0 -9
  161. package/src/services/audit-service.test.ts +0 -44
  162. package/src/services/audit-service.ts +0 -280
  163. package/src/services/content-service.ts +0 -65
  164. package/src/services/credential-service.ts +0 -20
  165. package/src/services/credential-wire-service.test.ts +0 -235
  166. package/src/services/credential-wire-service.ts +0 -120
  167. package/src/services/deployment-service.ts +0 -32
  168. package/src/services/email-service.test.ts +0 -100
  169. package/src/services/email-service.ts +0 -60
  170. package/src/services/email-template.test.ts +0 -311
  171. package/src/services/email-template.ts +0 -254
  172. package/src/services/file-scenario-run-store.test.ts +0 -349
  173. package/src/services/file-scenario-run-store.ts +0 -282
  174. package/src/services/gateway-service.ts +0 -5
  175. package/src/services/http-personas-converse.test.ts +0 -274
  176. package/src/services/http-personas.test.ts +0 -379
  177. package/src/services/http-personas.ts +0 -508
  178. package/src/services/in-memory-agent-run-state-service.ts +0 -87
  179. package/src/services/in-memory-queue-service.test.ts +0 -162
  180. package/src/services/in-memory-queue-service.ts +0 -78
  181. package/src/services/in-memory-session-store.test.ts +0 -58
  182. package/src/services/in-memory-session-store.ts +0 -20
  183. package/src/services/in-memory-trigger-service.ts +0 -47
  184. package/src/services/in-memory-workflow-service.test.ts +0 -430
  185. package/src/services/in-memory-workflow-service.ts +0 -595
  186. package/src/services/index.ts +0 -192
  187. package/src/services/istanbul-coverage-service.test.ts +0 -66
  188. package/src/services/istanbul-coverage-service.ts +0 -59
  189. package/src/services/jwt-service.ts +0 -15
  190. package/src/services/local-content-request-handler.test.ts +0 -240
  191. package/src/services/local-content-request-handler.ts +0 -295
  192. package/src/services/local-content.test.ts +0 -186
  193. package/src/services/local-content.ts +0 -242
  194. package/src/services/local-credential-service.ts +0 -63
  195. package/src/services/local-email-service.test.ts +0 -182
  196. package/src/services/local-email-service.ts +0 -43
  197. package/src/services/local-gateway-service.ts +0 -51
  198. package/src/services/local-secrets.test.ts +0 -95
  199. package/src/services/local-secrets.ts +0 -71
  200. package/src/services/local-variables.test.ts +0 -61
  201. package/src/services/local-variables.ts +0 -45
  202. package/src/services/logger-console.test.ts +0 -117
  203. package/src/services/logger-console.ts +0 -174
  204. package/src/services/logger.ts +0 -48
  205. package/src/services/meta-service.test.ts +0 -75
  206. package/src/services/meta-service.ts +0 -767
  207. package/src/services/persona-actor-secret.test.ts +0 -68
  208. package/src/services/persona-actor-secret.ts +0 -70
  209. package/src/services/persona-sign-in.test.ts +0 -219
  210. package/src/services/persona-sign-in.ts +0 -238
  211. package/src/services/personas-service.ts +0 -191
  212. package/src/services/pikku-user-id.test.ts +0 -62
  213. package/src/services/pikku-user-id.ts +0 -13
  214. package/src/services/queue-webhook-service.test.ts +0 -409
  215. package/src/services/queue-webhook-service.ts +0 -150
  216. package/src/services/remote-jobs.test.ts +0 -106
  217. package/src/services/remote-jobs.ts +0 -92
  218. package/src/services/scheduler-service.ts +0 -37
  219. package/src/services/schema-service.ts +0 -10
  220. package/src/services/scope-service.ts +0 -91
  221. package/src/services/scoped-credential-service.test.ts +0 -86
  222. package/src/services/scoped-credential-service.ts +0 -63
  223. package/src/services/scoped-secret-service.test.ts +0 -93
  224. package/src/services/scoped-secret-service.ts +0 -40
  225. package/src/services/secret-host-binding.test.ts +0 -138
  226. package/src/services/secret-host-binding.ts +0 -51
  227. package/src/services/secret-service.ts +0 -25
  228. package/src/services/secretless.test.ts +0 -54
  229. package/src/services/secretless.ts +0 -29
  230. package/src/services/session-store.ts +0 -9
  231. package/src/services/stub-tracker.test.ts +0 -104
  232. package/src/services/stub-tracker.ts +0 -175
  233. package/src/services/system-role-guard.test.ts +0 -96
  234. package/src/services/system-role-guard.ts +0 -71
  235. package/src/services/temporary-file-service.ts +0 -76
  236. package/src/services/trigger-service.ts +0 -5
  237. package/src/services/typed-credential-service.ts +0 -83
  238. package/src/services/typed-secret-service.test.ts +0 -204
  239. package/src/services/typed-secret-service.ts +0 -132
  240. package/src/services/typed-variables-service.test.ts +0 -166
  241. package/src/services/typed-variables-service.ts +0 -166
  242. package/src/services/user-session-service.test.ts +0 -147
  243. package/src/services/user-session-service.ts +0 -85
  244. package/src/services/v8-coverage-service.test.ts +0 -69
  245. package/src/services/v8-coverage-service.ts +0 -163
  246. package/src/services/variables-service.ts +0 -13
  247. package/src/services/webhook-service.ts +0 -147
  248. package/src/services/workflow-service.ts +0 -120
  249. package/src/side-effects-are-declared.test.ts +0 -84
  250. package/src/source-files-stay-composable.test.ts +0 -41
  251. package/src/template-alias-surface.test.ts +0 -240
  252. package/src/test-utils.ts +0 -38
  253. package/src/testing/index.ts +0 -3
  254. package/src/testing/service-tests/agent-run-service-tests.ts +0 -98
  255. package/src/testing/service-tests/agent-storage-service-tests.ts +0 -379
  256. package/src/testing/service-tests/channel-store-tests.ts +0 -98
  257. package/src/testing/service-tests/credential-service-tests.ts +0 -143
  258. package/src/testing/service-tests/deployment-service-tests.ts +0 -33
  259. package/src/testing/service-tests/event-hub-store-tests.ts +0 -48
  260. package/src/testing/service-tests/secret-service-tests.ts +0 -105
  261. package/src/testing/service-tests/session-store-tests.ts +0 -62
  262. package/src/testing/service-tests/workflow-run-service-tests.ts +0 -59
  263. package/src/testing/service-tests/workflow-service-tests.ts +0 -308
  264. package/src/testing/service-tests.ts +0 -95
  265. package/src/time-utils.test.ts +0 -56
  266. package/src/time-utils.ts +0 -89
  267. package/src/types/core.types.ts +0 -446
  268. package/src/types/index.ts +0 -25
  269. package/src/types/state.types.ts +0 -226
  270. package/src/types/typed-credentials.test.ts +0 -72
  271. package/src/utils/hash.test.ts +0 -68
  272. package/src/utils/hash.ts +0 -26
  273. package/src/utils/hmac.ts +0 -21
  274. package/src/utils/node-host-resolver.ts +0 -20
  275. package/src/utils/safe-fetch.test.ts +0 -515
  276. package/src/utils/safe-fetch.ts +0 -347
  277. package/src/utils.test.ts +0 -359
  278. package/src/utils.ts +0 -165
  279. package/src/version.test.ts +0 -80
  280. package/src/version.ts +0 -25
  281. package/src/wirings/actor-flow/actor-flow.types.ts +0 -40
  282. package/src/wirings/actor-flow/index.ts +0 -10
  283. package/src/wirings/actor-flow/run-conversation.test.ts +0 -187
  284. package/src/wirings/actor-flow/run-conversation.ts +0 -280
  285. package/src/wirings/addon/addon-auth-tags.test.ts +0 -219
  286. package/src/wirings/addon/addon-runner.ts +0 -236
  287. package/src/wirings/addon/addon-scopes.test.ts +0 -225
  288. package/src/wirings/addon/addon-secrets.test.ts +0 -391
  289. package/src/wirings/addon/index.ts +0 -12
  290. package/src/wirings/addon/remote-addon-auth.ts +0 -65
  291. package/src/wirings/addon/wire-addon.test.ts +0 -102
  292. package/src/wirings/addon/wire-addon.ts +0 -202
  293. package/src/wirings/addon/wire-remote-addon.ts +0 -41
  294. package/src/wirings/agent/agent-agui.test.ts +0 -1213
  295. package/src/wirings/agent/agent-agui.ts +0 -405
  296. package/src/wirings/agent/agent-authorization.test.ts +0 -208
  297. package/src/wirings/agent/agent-finalize.test.ts +0 -187
  298. package/src/wirings/agent/agent-finalize.ts +0 -197
  299. package/src/wirings/agent/agent-helpers.test.ts +0 -215
  300. package/src/wirings/agent/agent-helpers.ts +0 -96
  301. package/src/wirings/agent/agent-interrupt.test.ts +0 -833
  302. package/src/wirings/agent/agent-interrupt.ts +0 -400
  303. package/src/wirings/agent/agent-memory.test.ts +0 -397
  304. package/src/wirings/agent/agent-memory.ts +0 -496
  305. package/src/wirings/agent/agent-middleware.types.test.ts +0 -41
  306. package/src/wirings/agent/agent-model-config.test.ts +0 -103
  307. package/src/wirings/agent/agent-model-config.ts +0 -59
  308. package/src/wirings/agent/agent-prepare.test.ts +0 -977
  309. package/src/wirings/agent/agent-prepare.ts +0 -1083
  310. package/src/wirings/agent/agent-registry.test.ts +0 -455
  311. package/src/wirings/agent/agent-registry.ts +0 -99
  312. package/src/wirings/agent/agent-resume-authorization.test.ts +0 -206
  313. package/src/wirings/agent/agent-rpc.ts +0 -116
  314. package/src/wirings/agent/agent-runner.test.ts +0 -1229
  315. package/src/wirings/agent/agent-runner.ts +0 -858
  316. package/src/wirings/agent/agent-stream-delegate.test.ts +0 -381
  317. package/src/wirings/agent/agent-stream-output-hooks.test.ts +0 -353
  318. package/src/wirings/agent/agent-stream.test.ts +0 -1800
  319. package/src/wirings/agent/agent-stream.ts +0 -1639
  320. package/src/wirings/agent/agent-thread-ownership.test.ts +0 -297
  321. package/src/wirings/agent/agent-turn.test.ts +0 -65
  322. package/src/wirings/agent/agent-turn.ts +0 -122
  323. package/src/wirings/agent/agent-utils.ts +0 -20
  324. package/src/wirings/agent/agent.types.ts +0 -676
  325. package/src/wirings/agent/index.ts +0 -58
  326. package/src/wirings/agent/voice-input.test.ts +0 -220
  327. package/src/wirings/agent/voice-input.ts +0 -180
  328. package/src/wirings/agent/voice-output.test.ts +0 -510
  329. package/src/wirings/agent/voice-output.ts +0 -311
  330. package/src/wirings/agent-scorer/agent-scorer-grade.test.ts +0 -106
  331. package/src/wirings/agent-scorer/agent-scorer-grade.ts +0 -55
  332. package/src/wirings/agent-scorer/agent-scorer-judge.test.ts +0 -285
  333. package/src/wirings/agent-scorer/agent-scorer-judge.ts +0 -180
  334. package/src/wirings/agent-scorer/agent-scorer-live.test.ts +0 -174
  335. package/src/wirings/agent-scorer/agent-scorer-live.ts +0 -56
  336. package/src/wirings/agent-scorer/agent-scorer-registry.ts +0 -66
  337. package/src/wirings/agent-scorer/agent-scorer-sampling.test.ts +0 -34
  338. package/src/wirings/agent-scorer/agent-scorer-sampling.ts +0 -36
  339. package/src/wirings/agent-scorer/agent-scorer-snapshots.test.ts +0 -49
  340. package/src/wirings/agent-scorer/agent-scorer-snapshots.ts +0 -46
  341. package/src/wirings/agent-scorer/agent-scorer-worker.test.ts +0 -122
  342. package/src/wirings/agent-scorer/agent-scorer-worker.ts +0 -71
  343. package/src/wirings/agent-scorer/agent-scorer.ts +0 -102
  344. package/src/wirings/agent-scorer/agent-scorer.types.ts +0 -128
  345. package/src/wirings/agent-scorer/index.ts +0 -23
  346. package/src/wirings/channel/channel-common.ts +0 -102
  347. package/src/wirings/channel/channel-handler-shapes.test.ts +0 -72
  348. package/src/wirings/channel/channel-handler.test.ts +0 -322
  349. package/src/wirings/channel/channel-handler.ts +0 -259
  350. package/src/wirings/channel/channel-host-rpc.test.ts +0 -150
  351. package/src/wirings/channel/channel-host-rpc.ts +0 -69
  352. package/src/wirings/channel/channel-middleware-runner.test.ts +0 -188
  353. package/src/wirings/channel/channel-middleware-runner.ts +0 -126
  354. package/src/wirings/channel/channel-rpc-registry.ts +0 -116
  355. package/src/wirings/channel/channel-rpc-responder.ts +0 -117
  356. package/src/wirings/channel/channel-rpc-service.ts +0 -132
  357. package/src/wirings/channel/channel-rpc-validators.ts +0 -65
  358. package/src/wirings/channel/channel-rpc.test.ts +0 -841
  359. package/src/wirings/channel/channel-rpc.ts +0 -5
  360. package/src/wirings/channel/channel-rpc.types.ts +0 -160
  361. package/src/wirings/channel/channel-runner.ts +0 -164
  362. package/src/wirings/channel/channel-store.ts +0 -35
  363. package/src/wirings/channel/channel.types.ts +0 -193
  364. package/src/wirings/channel/define-channel-routes.ts +0 -5
  365. package/src/wirings/channel/eventhub-service.ts +0 -16
  366. package/src/wirings/channel/eventhub-store.ts +0 -13
  367. package/src/wirings/channel/index.ts +0 -40
  368. package/src/wirings/channel/local/index.ts +0 -3
  369. package/src/wirings/channel/local/local-channel-handler.ts +0 -98
  370. package/src/wirings/channel/local/local-channel-runner.test.ts +0 -339
  371. package/src/wirings/channel/local/local-channel-runner.ts +0 -271
  372. package/src/wirings/channel/local/local-eventhub-service.test.ts +0 -77
  373. package/src/wirings/channel/local/local-eventhub-service.ts +0 -69
  374. package/src/wirings/channel/log-channels.ts +0 -16
  375. package/src/wirings/channel/pikku-abstract-channel-handler.test.ts +0 -135
  376. package/src/wirings/channel/pikku-abstract-channel-handler.ts +0 -60
  377. package/src/wirings/channel/serverless/index.ts +0 -6
  378. package/src/wirings/channel/serverless/serverless-channel-runner.ts +0 -328
  379. package/src/wirings/cli/channel/cli-approval.test.ts +0 -177
  380. package/src/wirings/cli/channel/cli-approval.ts +0 -135
  381. package/src/wirings/cli/channel/cli-channel-runner.ts +0 -118
  382. package/src/wirings/cli/channel/cli-raw-channel-runner.test.ts +0 -192
  383. package/src/wirings/cli/channel/cli-raw-channel-runner.ts +0 -148
  384. package/src/wirings/cli/channel/cli-raw-client-runner.test.ts +0 -480
  385. package/src/wirings/cli/channel/cli-raw-client-runner.ts +0 -188
  386. package/src/wirings/cli/channel/index.ts +0 -6
  387. package/src/wirings/cli/cli-runner.test.ts +0 -969
  388. package/src/wirings/cli/cli-runner.ts +0 -538
  389. package/src/wirings/cli/cli.types.ts +0 -388
  390. package/src/wirings/cli/command-parser.test.ts +0 -1120
  391. package/src/wirings/cli/command-parser.ts +0 -713
  392. package/src/wirings/cli/define-cli-commands.ts +0 -13
  393. package/src/wirings/cli/format-cli-error.test.ts +0 -91
  394. package/src/wirings/cli/format-cli-error.ts +0 -96
  395. package/src/wirings/cli/index.ts +0 -19
  396. package/src/wirings/credential/credential.types.ts +0 -37
  397. package/src/wirings/credential/define-credential.ts +0 -49
  398. package/src/wirings/credential/index.ts +0 -7
  399. package/src/wirings/credential/validate-credential-definitions.ts +0 -63
  400. package/src/wirings/gateway/gateway-authorization.test.ts +0 -575
  401. package/src/wirings/gateway/gateway-channel-meta.test.ts +0 -44
  402. package/src/wirings/gateway/gateway-runner.test.ts +0 -581
  403. package/src/wirings/gateway/gateway-runner.ts +0 -411
  404. package/src/wirings/gateway/gateway.types.ts +0 -137
  405. package/src/wirings/gateway/index.ts +0 -15
  406. package/src/wirings/http/http-routes.test.ts +0 -318
  407. package/src/wirings/http/http-routes.ts +0 -111
  408. package/src/wirings/http/http-runner-addon-ref.test.ts +0 -238
  409. package/src/wirings/http/http-runner.test.ts +0 -503
  410. package/src/wirings/http/http-runner.ts +0 -462
  411. package/src/wirings/http/http.types.ts +0 -307
  412. package/src/wirings/http/index.ts +0 -27
  413. package/src/wirings/http/log-http-routes.ts +0 -18
  414. package/src/wirings/http/pikku-fetch-http-request.test.ts +0 -318
  415. package/src/wirings/http/pikku-fetch-http-request.ts +0 -260
  416. package/src/wirings/http/pikku-fetch-http-response.test.ts +0 -123
  417. package/src/wirings/http/pikku-fetch-http-response.ts +0 -149
  418. package/src/wirings/http/routers/http-router.ts +0 -13
  419. package/src/wirings/http/routers/path-to-regex.test.ts +0 -306
  420. package/src/wirings/http/routers/path-to-regex.ts +0 -115
  421. package/src/wirings/http/web-request.test.ts +0 -382
  422. package/src/wirings/http/web-request.ts +0 -162
  423. package/src/wirings/mcp/index.ts +0 -26
  424. package/src/wirings/mcp/mcp-endpoint-registry.test.ts +0 -388
  425. package/src/wirings/mcp/mcp-endpoint-registry.ts +0 -159
  426. package/src/wirings/mcp/mcp-runner.test.ts +0 -588
  427. package/src/wirings/mcp/mcp-runner.ts +0 -330
  428. package/src/wirings/mcp/mcp.types.ts +0 -199
  429. package/src/wirings/node/index.ts +0 -2
  430. package/src/wirings/node/node.types.ts +0 -23
  431. package/src/wirings/oauth2/index.ts +0 -1
  432. package/src/wirings/oauth2/oauth2.types.ts +0 -12
  433. package/src/wirings/persona/define-personas.ts +0 -33
  434. package/src/wirings/persona/index.ts +0 -75
  435. package/src/wirings/persona/persona-app-scopes.test.ts +0 -47
  436. package/src/wirings/persona/persona-app-scopes.ts +0 -74
  437. package/src/wirings/persona/persona-email.ts +0 -87
  438. package/src/wirings/persona/persona-environments.test.ts +0 -194
  439. package/src/wirings/persona/persona-environments.ts +0 -138
  440. package/src/wirings/persona/persona-mailbox.ts +0 -156
  441. package/src/wirings/persona/persona.test.ts +0 -230
  442. package/src/wirings/persona/persona.types.ts +0 -156
  443. package/src/wirings/persona/validate-personas.ts +0 -137
  444. package/src/wirings/queue/index.ts +0 -29
  445. package/src/wirings/queue/queue-identity.test.ts +0 -454
  446. package/src/wirings/queue/queue-identity.ts +0 -176
  447. package/src/wirings/queue/queue-runner.test.ts +0 -705
  448. package/src/wirings/queue/queue-runner.ts +0 -181
  449. package/src/wirings/queue/queue.types.ts +0 -161
  450. package/src/wirings/queue/register-queue-helper.ts +0 -46
  451. package/src/wirings/queue/signed-queue-service.ts +0 -60
  452. package/src/wirings/queue/validate-worker-config.test.ts +0 -108
  453. package/src/wirings/queue/validate-worker-config.ts +0 -90
  454. package/src/wirings/role/define-system-role.ts +0 -33
  455. package/src/wirings/role/index.ts +0 -13
  456. package/src/wirings/role/role.test.ts +0 -104
  457. package/src/wirings/role/role.types.ts +0 -47
  458. package/src/wirings/role/validate-role-definitions.ts +0 -93
  459. package/src/wirings/rpc/index.ts +0 -8
  460. package/src/wirings/rpc/rpc-runner.test.ts +0 -1130
  461. package/src/wirings/rpc/rpc-runner.ts +0 -566
  462. package/src/wirings/rpc/rpc-types.ts +0 -87
  463. package/src/wirings/scheduler/index.ts +0 -11
  464. package/src/wirings/scheduler/log-schedulers.ts +0 -16
  465. package/src/wirings/scheduler/scheduler-runner.test.ts +0 -835
  466. package/src/wirings/scheduler/scheduler-runner.ts +0 -138
  467. package/src/wirings/scheduler/scheduler.types.ts +0 -42
  468. package/src/wirings/scope/define-scope.ts +0 -33
  469. package/src/wirings/scope/index.ts +0 -15
  470. package/src/wirings/scope/scope.test.ts +0 -159
  471. package/src/wirings/scope/scope.types.ts +0 -42
  472. package/src/wirings/scope/validate-scope-definitions.ts +0 -107
  473. package/src/wirings/secret/index.ts +0 -9
  474. package/src/wirings/secret/secret.types.ts +0 -70
  475. package/src/wirings/secret/validate-secret-definitions.test.ts +0 -232
  476. package/src/wirings/secret/validate-secret-definitions.ts +0 -88
  477. package/src/wirings/trigger/index.ts +0 -9
  478. package/src/wirings/trigger/pikku-trigger-service.ts +0 -107
  479. package/src/wirings/trigger/trigger-runner.test.ts +0 -78
  480. package/src/wirings/trigger/trigger-runner.ts +0 -113
  481. package/src/wirings/trigger/trigger.types.ts +0 -100
  482. package/src/wirings/variable/index.ts +0 -8
  483. package/src/wirings/variable/validate-variable-definitions.test.ts +0 -115
  484. package/src/wirings/variable/validate-variable-definitions.ts +0 -71
  485. package/src/wirings/variable/variable.types.ts +0 -40
  486. package/src/wirings/virtual-user/index.ts +0 -107
  487. package/src/wirings/virtual-user/prepare-virtual-user-run.test.ts +0 -115
  488. package/src/wirings/virtual-user/prepare-virtual-user-run.ts +0 -95
  489. package/src/wirings/virtual-user/run-virtual-user.test.ts +0 -774
  490. package/src/wirings/virtual-user/run-virtual-user.ts +0 -684
  491. package/src/wirings/virtual-user/virtual-user-agents.test.ts +0 -72
  492. package/src/wirings/virtual-user/virtual-user-agents.ts +0 -62
  493. package/src/wirings/virtual-user/virtual-user-catalogue.test.ts +0 -215
  494. package/src/wirings/virtual-user/virtual-user-catalogue.ts +0 -184
  495. package/src/wirings/virtual-user/virtual-user-derive.test.ts +0 -426
  496. package/src/wirings/virtual-user/virtual-user-derive.ts +0 -161
  497. package/src/wirings/virtual-user/virtual-user-dispositions.test.ts +0 -68
  498. package/src/wirings/virtual-user/virtual-user-dispositions.ts +0 -210
  499. package/src/wirings/virtual-user/virtual-user-intents.test.ts +0 -218
  500. package/src/wirings/virtual-user/virtual-user-intents.ts +0 -185
  501. package/src/wirings/virtual-user/virtual-user-rng.test.ts +0 -72
  502. package/src/wirings/virtual-user/virtual-user-rng.ts +0 -50
  503. package/src/wirings/virtual-user/virtual-user-run-store.ts +0 -131
  504. package/src/wirings/virtual-user/virtual-user-scaffold.test.ts +0 -854
  505. package/src/wirings/virtual-user/virtual-user-scaffold.ts +0 -664
  506. package/src/wirings/virtual-user/virtual-user-schedule-store.ts +0 -93
  507. package/src/wirings/virtual-user/virtual-user-schedule.test.ts +0 -280
  508. package/src/wirings/virtual-user/virtual-user-schedule.ts +0 -156
  509. package/src/wirings/virtual-user/virtual-user-target.ts +0 -47
  510. package/src/wirings/virtual-user/virtual-user.types.ts +0 -215
  511. package/src/wirings/workflow/dsl/workflow-dsl.types.ts +0 -709
  512. package/src/wirings/workflow/dsl/workflow-runner.ts +0 -25
  513. package/src/wirings/workflow/feature.test.ts +0 -131
  514. package/src/wirings/workflow/feature.ts +0 -59
  515. package/src/wirings/workflow/graph/graph-foreach-queued.test.ts +0 -569
  516. package/src/wirings/workflow/graph/graph-foreach.test.ts +0 -626
  517. package/src/wirings/workflow/graph/graph-node.ts +0 -115
  518. package/src/wirings/workflow/graph/graph-runner.test.ts +0 -1049
  519. package/src/wirings/workflow/graph/graph-runner.ts +0 -1376
  520. package/src/wirings/workflow/graph/graph-validation.test.ts +0 -27
  521. package/src/wirings/workflow/graph/graph-validation.ts +0 -41
  522. package/src/wirings/workflow/graph/template.test.ts +0 -49
  523. package/src/wirings/workflow/graph/template.ts +0 -42
  524. package/src/wirings/workflow/graph/wire-workflow-graph.ts +0 -39
  525. package/src/wirings/workflow/graph/workflow-graph.types.ts +0 -75
  526. package/src/wirings/workflow/index.ts +0 -107
  527. package/src/wirings/workflow/pikku-scenario-service.ts +0 -1013
  528. package/src/wirings/workflow/pikku-workflow-service.test.ts +0 -963
  529. package/src/wirings/workflow/pikku-workflow-service.ts +0 -1993
  530. package/src/wirings/workflow/run-timeline.test.ts +0 -199
  531. package/src/wirings/workflow/run-timeline.ts +0 -185
  532. package/src/wirings/workflow/scenario-cookie-jar.test.ts +0 -107
  533. package/src/wirings/workflow/scenario-cookie-jar.ts +0 -57
  534. package/src/wirings/workflow/scenario-expectations.test.ts +0 -238
  535. package/src/wirings/workflow/scenario-hooks.test.ts +0 -259
  536. package/src/wirings/workflow/scenario-poll.test.ts +0 -64
  537. package/src/wirings/workflow/scenario-poll.ts +0 -27
  538. package/src/wirings/workflow/scenario-prose.test.ts +0 -275
  539. package/src/wirings/workflow/scenario-prose.ts +0 -86
  540. package/src/wirings/workflow/scenario-run.types.ts +0 -193
  541. package/src/wirings/workflow/scenario-service.test.ts +0 -147
  542. package/src/wirings/workflow/scenario-step-guards.ts +0 -23
  543. package/src/wirings/workflow/scenario-step.test.ts +0 -800
  544. package/src/wirings/workflow/scenario-step.types.ts +0 -262
  545. package/src/wirings/workflow/scenario-surface.test.ts +0 -146
  546. package/src/wirings/workflow/scenario-surface.ts +0 -71
  547. package/src/wirings/workflow/scenario.types.ts +0 -63
  548. package/src/wirings/workflow/workflow-approval-audit.ts +0 -47
  549. package/src/wirings/workflow/workflow-approval-policy.test.ts +0 -594
  550. package/src/wirings/workflow/workflow-approval-policy.ts +0 -68
  551. package/src/wirings/workflow/workflow-approval.ts +0 -290
  552. package/src/wirings/workflow/workflow-child-run-session.test.ts +0 -168
  553. package/src/wirings/workflow/workflow-constants.ts +0 -66
  554. package/src/wirings/workflow/workflow-dispatch-durability.test.ts +0 -116
  555. package/src/wirings/workflow/workflow-dispatch-payload.test.ts +0 -55
  556. package/src/wirings/workflow/workflow-dispatch-relay.test.ts +0 -128
  557. package/src/wirings/workflow/workflow-errors.ts +0 -132
  558. package/src/wirings/workflow/workflow-inline-authority.test.ts +0 -175
  559. package/src/wirings/workflow/workflow-invocation-id.test.ts +0 -51
  560. package/src/wirings/workflow/workflow-invocation-id.ts +0 -28
  561. package/src/wirings/workflow/workflow-meta-resolver.ts +0 -45
  562. package/src/wirings/workflow/workflow-mirror.test.ts +0 -171
  563. package/src/wirings/workflow/workflow-missing-meta.test.ts +0 -92
  564. package/src/wirings/workflow/workflow-on-error.test.ts +0 -145
  565. package/src/wirings/workflow/workflow-queue-routing.ts +0 -129
  566. package/src/wirings/workflow/workflow-queue-wiring.ts +0 -149
  567. package/src/wirings/workflow/workflow-queue-workers.test.ts +0 -131
  568. package/src/wirings/workflow/workflow-queue-workers.ts +0 -66
  569. package/src/wirings/workflow/workflow-recovery.ts +0 -192
  570. package/src/wirings/workflow/workflow-replay-snapshot.test.ts +0 -140
  571. package/src/wirings/workflow/workflow-retry-policy.test.ts +0 -113
  572. package/src/wirings/workflow/workflow-run-authority.test.ts +0 -212
  573. package/src/wirings/workflow/workflow-run-context.test.ts +0 -172
  574. package/src/wirings/workflow/workflow-run-engine.types.ts +0 -92
  575. package/src/wirings/workflow/workflow-run-ownership.ts +0 -37
  576. package/src/wirings/workflow/workflow-run-polling.test.ts +0 -127
  577. package/src/wirings/workflow/workflow-stalled-recovery.test.ts +0 -152
  578. package/src/wirings/workflow/workflow-status-stream.test.ts +0 -354
  579. package/src/wirings/workflow/workflow-status-stream.ts +0 -144
  580. package/src/wirings/workflow/workflow-step-claim.ts +0 -46
  581. package/src/wirings/workflow/workflow-step-ordinal.test.ts +0 -94
  582. package/src/wirings/workflow/workflow-step-session.test.ts +0 -87
  583. package/src/wirings/workflow/workflow-suspend.ts +0 -61
  584. package/src/wirings/workflow/workflow-terminal-run-guard.test.ts +0 -105
  585. package/src/wirings/workflow/workflow.types.ts +0 -268
  586. package/src/wirings-stay-decoupled.test.ts +0 -130
  587. package/tsconfig.json +0 -14
  588. package/tsconfig.tsbuildinfo +0 -1
  589. package/tsconfig.type-tests.json +0 -15
@@ -1,47 +0,0 @@
1
- import assert from 'node:assert/strict'
2
- import { describe, test } from 'node:test'
3
- import {
4
- appScopeId,
5
- buildAppScopeDefinition,
6
- declaredApps,
7
- } from './persona-app-scopes.js'
8
-
9
- const persona = (id: string, app?: string) =>
10
- ({ id, name: id, roles: [], goals: [], tags: [], runnable: true, app }) as any
11
-
12
- describe('declaredApps', () => {
13
- test('deduplicates and sorts the apps the personas name', () => {
14
- assert.deepEqual(
15
- declaredApps([
16
- persona('a', 'staff'),
17
- persona('b', 'portal'),
18
- persona('c', 'staff'),
19
- ]),
20
- ['portal', 'staff']
21
- )
22
- })
23
-
24
- test('ignores personas that name no app', () => {
25
- assert.deepEqual(declaredApps([persona('a'), persona('b', '')]), [])
26
- })
27
- })
28
-
29
- describe('buildAppScopeDefinition', () => {
30
- test('renders one grantable child per app under the app root', () => {
31
- const definition = buildAppScopeDefinition([
32
- persona('a', 'staff'),
33
- persona('b', 'portal'),
34
- ])
35
-
36
- assert.equal(definition?.name, 'app')
37
- assert.deepEqual(Object.keys(definition?.scopes ?? {}).sort(), [
38
- 'portal',
39
- 'staff',
40
- ])
41
- assert.equal(appScopeId('staff'), 'app:staff')
42
- })
43
-
44
- test('is null for a single-frontend product', () => {
45
- assert.equal(buildAppScopeDefinition([persona('a')]), null)
46
- })
47
- })
@@ -1,74 +0,0 @@
1
- import type { ScopeDefinitionMeta, ScopeNodeMeta } from '../scope/scope.types.js'
2
- import type { PersonaMeta } from './persona.types.js'
3
-
4
- /**
5
- * The root every app grant hangs off. One segment, so a grant of `app` alone
6
- * means "may use all of them" under the same parent-grant rule the admin tree
7
- * relies on — which is what a support operator or an internal tool wants, and
8
- * what a per-app boolean column could never express.
9
- */
10
- export const APP_SCOPE_ROOT = 'app'
11
-
12
- /** `app:staff` for `staff`. */
13
- export const appScopeId = (app: string) => `${APP_SCOPE_ROOT}:${app}`
14
-
15
- /**
16
- * The apps named across the declared personas, sorted and deduplicated.
17
- *
18
- * The personas *are* the registry. There is no separate list of apps to keep in
19
- * step, because a frontend nobody signs into is not a thing the auth layer has
20
- * an opinion about — and the moment somebody does sign into it, they are a
21
- * persona and they name it.
22
- */
23
- export const declaredApps = (personas: PersonaMeta[]): string[] =>
24
- [
25
- ...new Set(
26
- personas
27
- .map((persona) => persona.app)
28
- .filter((app): app is string => typeof app === 'string' && app !== '')
29
- ),
30
- ].sort()
31
-
32
- /**
33
- * The `app` scope tree, synthesised from the personas that name an app.
34
- *
35
- * Which frontend a person may sign into is a different question from what they
36
- * may do once inside it, but it is the same *kind* of question — a grant that
37
- * an admin can make and revoke at runtime, that resolves at the session
38
- * boundary, and that a restricted API key can decline to inherit. So it is
39
- * carried as a scope rather than a `can_access_<app>` column: no migration per
40
- * app, one query for "which apps may this user reach", and no second
41
- * authorization mechanism to keep honest.
42
- *
43
- * Synthesised rather than written by hand because the declaration already
44
- * exists. Asking an app to also spell out `defineScope({ app: { staff: {} } })`
45
- * beside its personas invites the two to drift, and the failure that produces —
46
- * a persona provisioned with a grant the vocabulary no longer declares — is one
47
- * `pikku scopes prune` away from silently revoking sign-in.
48
- *
49
- * Null when no persona names an app, which is the single-frontend case: nothing
50
- * to declare, and no empty root cluttering the console's grant list.
51
- */
52
- export const buildAppScopeDefinition = (
53
- personas: PersonaMeta[]
54
- ): ScopeDefinitionMeta | null => {
55
- const apps = declaredApps(personas)
56
- if (apps.length === 0) {
57
- return null
58
- }
59
-
60
- const scopes: Record<string, ScopeNodeMeta> = {}
61
- for (const app of apps) {
62
- scopes[app] = {
63
- displayName: app,
64
- description: `May sign in to the ${app} app`,
65
- }
66
- }
67
-
68
- return {
69
- name: APP_SCOPE_ROOT,
70
- displayName: 'Apps',
71
- description: 'Which frontend a person may sign in to',
72
- scopes,
73
- }
74
- }
@@ -1,87 +0,0 @@
1
- /**
2
- * A persona's email address is computed, never declared.
3
- *
4
- * A persona that cannot read its own email cannot complete sign-up, magic
5
- * links, invites or password resets — which are most of the flows worth
6
- * exercising. So addresses are real and deliverable against a domain the stage
7
- * actually receives mail on, rather than a synthetic `.local` dead end.
8
- */
9
-
10
- const LABEL = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/
11
-
12
- /**
13
- * Lower-cases and strips a persona id down to something an address can carry.
14
- *
15
- * Personas are declared as object keys, so they are already identifier-shaped;
16
- * this exists for the ones that are not (`'susan.buyer'`, `'Susan_2'`) rather
17
- * than to permit arbitrary input.
18
- */
19
- export const personaEmailLabel = (personaId: string): string => {
20
- const label = personaId
21
- .toLowerCase()
22
- .replace(/[^a-z0-9]+/g, '-')
23
- .replace(/^-+|-+$/g, '')
24
- if (!LABEL.test(label)) {
25
- throw new Error(
26
- `Persona '${personaId}' has no usable email label. A persona id must contain at least one letter or digit.`
27
- )
28
- }
29
- return label
30
- }
31
-
32
- /**
33
- * The address a persona reads mail at during a run.
34
- *
35
- * The `runId` suffix is not decoration. Without it two concurrent runs share an
36
- * inbox *and* a user row, and run B reads run A's magic link. Sub-addressing
37
- * also buys isolation for free: a different address is a different account in
38
- * the app, so two runs cannot collide on sign-up either.
39
- *
40
- * Omitting `runId` gives the bare form, which is what a seeded fixture that has
41
- * to stay stable across runs wants.
42
- */
43
- export const personaEmail = (
44
- personaId: string,
45
- domain: string,
46
- runId?: string
47
- ): string => {
48
- const label = personaEmailLabel(personaId)
49
- const cleanDomain = domain.trim().toLowerCase().replace(/^@/, '')
50
- if (!cleanDomain || cleanDomain.includes('@') || !cleanDomain.includes('.')) {
51
- throw new Error(
52
- `Persona email domain '${domain}' is not a domain. Set it to a domain the stage actually receives mail on.`
53
- )
54
- }
55
- const suffix = runId ? `+${personaEmailLabel(runId)}` : ''
56
- return `${label}${suffix}@${cleanDomain}`
57
- }
58
-
59
- /**
60
- * Every address in a run, keyed by persona.
61
- *
62
- * All of a persona's logins share one address. That is not a simplification:
63
- * better-auth keeps `email` on the `user` and defaults `allowDifferentEmails`
64
- * to false, so giving a linked account its own address would have the library
65
- * under test refuse to link the very thing the persona declared as linked.
66
- */
67
- export const personaEmails = (
68
- personaIds: readonly string[],
69
- domain: string,
70
- runId?: string
71
- ): Record<string, string> => {
72
- const emails: Record<string, string> = {}
73
- const seen = new Map<string, string>()
74
- for (const id of personaIds) {
75
- const address = personaEmail(id, domain, runId)
76
- const collidesWith = seen.get(address)
77
- if (collidesWith !== undefined) {
78
- throw new Error(
79
- `Personas '${collidesWith}' and '${id}' both compute the address ${address}. ` +
80
- `They would share a user row and read each other's email.`
81
- )
82
- }
83
- seen.set(address, id)
84
- emails[id] = address
85
- }
86
- return emails
87
- }
@@ -1,194 +0,0 @@
1
- import assert from 'node:assert/strict'
2
- import { describe, test } from 'node:test'
3
- import {
4
- personaEnvironmentErrors,
5
- personaEnvironmentRefusal,
6
- resolvePersonaEnvironments,
7
- } from './persona-environments.js'
8
-
9
- const ENVIRONMENTS = {
10
- local: {},
11
- staging: {},
12
- prod: { production: true },
13
- 'eu-prod': { production: true },
14
- }
15
-
16
- describe('resolvePersonaEnvironments', () => {
17
- // The default that makes production opt-in: a persona nobody thought about
18
- // runs everywhere it is harmless and nowhere it is not.
19
- test('omitting environments means everywhere but production', () => {
20
- assert.deepEqual(resolvePersonaEnvironments({}, ENVIRONMENTS), [
21
- 'local',
22
- 'staging',
23
- ])
24
- })
25
-
26
- test('a declared list is taken verbatim, production included', () => {
27
- assert.deepEqual(
28
- resolvePersonaEnvironments(
29
- { disposition: 'accountable', environments: ['staging', 'prod'] },
30
- ENVIRONMENTS
31
- ),
32
- ['staging', 'prod']
33
- )
34
- })
35
-
36
- test('more than one environment can be production', () => {
37
- assert.deepEqual(
38
- resolvePersonaEnvironments({}, { a: {}, b: { production: true } }),
39
- ['a']
40
- )
41
- })
42
- })
43
-
44
- describe('personaEnvironmentErrors', () => {
45
- test('a persona that declares nothing cannot be wrong', () => {
46
- assert.deepEqual(
47
- personaEnvironmentErrors(
48
- 'shopper',
49
- { disposition: 'careless' },
50
- ENVIRONMENTS
51
- ),
52
- []
53
- )
54
- })
55
-
56
- test('an accountable persona may name production', () => {
57
- assert.deepEqual(
58
- personaEnvironmentErrors(
59
- 'robin',
60
- { disposition: 'accountable', environments: ['staging', 'prod'] },
61
- ENVIRONMENTS
62
- ),
63
- []
64
- )
65
- })
66
-
67
- test('a testing disposition naming production is an error', () => {
68
- const [error, ...rest] = personaEnvironmentErrors(
69
- 'shopper',
70
- { disposition: 'careless', environments: ['prod'] },
71
- ENVIRONMENTS
72
- )
73
- assert.deepEqual(rest, [])
74
- assert.match(error!, /names production environment 'prod'/)
75
- assert.match(error!, /'careless'/)
76
- assert.match(error!, /disposition 'accountable'/)
77
- })
78
-
79
- // The default disposition is `realistic`, which is still a testing one. A
80
- // persona that declares no disposition at all must not slip into production
81
- // on the strength of having said nothing.
82
- test('no disposition at all is reported as realistic, and refused', () => {
83
- const [error] = personaEnvironmentErrors(
84
- 'quiet',
85
- { environments: ['prod'] },
86
- ENVIRONMENTS
87
- )
88
- assert.match(error!, /'realistic'/)
89
- })
90
-
91
- test('every offending environment is reported, not just the first', () => {
92
- const errors = personaEnvironmentErrors(
93
- 'shopper',
94
- { disposition: 'careless', environments: ['prod', 'eu-prod'] },
95
- ENVIRONMENTS
96
- )
97
- assert.equal(errors.length, 2)
98
- })
99
-
100
- // A typo silently narrows the persona to nothing, which is the same class of
101
- // bug the rule exists to prevent — only quieter.
102
- test('an unknown environment names the ones that exist', () => {
103
- const [error] = personaEnvironmentErrors(
104
- 'shopper',
105
- { environments: ['stagng'] },
106
- ENVIRONMENTS
107
- )
108
- assert.match(error!, /'stagng', which is not configured/)
109
- assert.match(error!, /local, staging, prod, eu-prod/)
110
- })
111
-
112
- test('with nothing configured it says where environments go', () => {
113
- const [error] = personaEnvironmentErrors(
114
- 'shopper',
115
- { environments: ['x'] },
116
- {}
117
- )
118
- assert.match(
119
- error!,
120
- /Declare it under 'environments' in pikku\.config\.json/
121
- )
122
- })
123
- })
124
-
125
- describe('personaEnvironmentRefusal', () => {
126
- const accountable = {
127
- disposition: 'accountable' as const,
128
- environments: ['staging', 'prod'],
129
- }
130
-
131
- test('lets a declared environment through', () => {
132
- assert.equal(
133
- personaEnvironmentRefusal('robin', accountable, 'prod', ENVIRONMENTS),
134
- null
135
- )
136
- })
137
-
138
- // Fail closed. An unresolved PIKKU_ENV is precisely the case where the build
139
- // check was passed by a different artifact than the one now running, so
140
- // "I don't know where I am" must not read as permission.
141
- test('an unresolved environment refuses everybody', () => {
142
- const refusal = personaEnvironmentRefusal(
143
- 'robin',
144
- accountable,
145
- undefined,
146
- ENVIRONMENTS
147
- )
148
- assert.match(refusal!, /no environment is resolved/)
149
- assert.match(refusal!, /PIKKU_ENV/)
150
- })
151
-
152
- test('an unrecognised environment refuses rather than assuming staging', () => {
153
- const refusal = personaEnvironmentRefusal(
154
- 'robin',
155
- accountable,
156
- 'somewhere-else',
157
- ENVIRONMENTS
158
- )
159
- assert.match(refusal!, /is not configured/)
160
- })
161
-
162
- // The check the deployed artifact cannot have been trusted on: whatever the
163
- // file said, this persona is not allowed to act on real data.
164
- test('production refuses a testing disposition whatever it declared', () => {
165
- const refusal = personaEnvironmentRefusal(
166
- 'shopper',
167
- { disposition: 'adversarial', environments: ['prod'] },
168
- 'prod',
169
- ENVIRONMENTS
170
- )
171
- assert.match(refusal!, /only 'accountable' may act on real data/)
172
- })
173
-
174
- test('an environment outside the declared list is refused', () => {
175
- const refusal = personaEnvironmentRefusal(
176
- 'robin',
177
- accountable,
178
- 'local',
179
- ENVIRONMENTS
180
- )
181
- assert.match(refusal!, /it declares environments staging, prod/)
182
- })
183
-
184
- test('a persona declaring nothing still runs everywhere but production', () => {
185
- assert.equal(
186
- personaEnvironmentRefusal('shopper', {}, 'staging', ENVIRONMENTS),
187
- null
188
- )
189
- assert.match(
190
- personaEnvironmentRefusal('shopper', {}, 'prod', ENVIRONMENTS)!,
191
- /only 'accountable' may act on real data/
192
- )
193
- })
194
- })
@@ -1,138 +0,0 @@
1
- import {
2
- PRODUCTION_DISPOSITION,
3
- type VirtualUserDisposition,
4
- } from '../virtual-user/virtual-user.types.js'
5
-
6
- /**
7
- * Which environments a persona may run against, and the one rule on it.
8
- *
9
- * Two callers, deliberately sharing this file. The inspector checks the
10
- * declaration at build time; sign-in re-checks against the environment actually
11
- * resolved at run time. Neither is redundant — the build check trusts the file,
12
- * and the run check does not trust which artifact got deployed.
13
- */
14
-
15
- /** The part of an environment entry this rule cares about. */
16
- export interface PersonaEnvironment {
17
- production?: boolean
18
- }
19
-
20
- /** What a persona needs to expose for the rule to be applied to it. */
21
- export interface PersonaEnvironmentSubject {
22
- disposition?: VirtualUserDisposition
23
- environments?: string[]
24
- }
25
-
26
- /**
27
- * The environments a persona may target, resolved.
28
- *
29
- * An omitted `environments` means every configured environment **except** the
30
- * production ones: production is opt-in for everybody, so nothing reaches it by
31
- * being forgotten.
32
- */
33
- export const resolvePersonaEnvironments = (
34
- persona: PersonaEnvironmentSubject,
35
- environments: Readonly<Record<string, PersonaEnvironment>>
36
- ): string[] => {
37
- if (persona.environments) {
38
- return [...persona.environments]
39
- }
40
- return Object.entries(environments)
41
- .filter(([, env]) => !env.production)
42
- .map(([name]) => name)
43
- }
44
-
45
- /**
46
- * The declaration check, as a list of messages. Empty means the persona's
47
- * `environments` are coherent with the config and its disposition.
48
- *
49
- * An unknown environment name is an error rather than a shrug: a typo silently
50
- * narrowing a persona to nothing is the same class of bug as the one this whole
51
- * rule exists to prevent, only quieter.
52
- */
53
- export const personaEnvironmentErrors = (
54
- id: string,
55
- persona: PersonaEnvironmentSubject,
56
- environments: Readonly<Record<string, PersonaEnvironment>>
57
- ): string[] => {
58
- if (!persona.environments) {
59
- return []
60
- }
61
-
62
- const errors: string[] = []
63
- const known = Object.keys(environments)
64
-
65
- for (const name of persona.environments) {
66
- const env = environments[name]
67
- if (!env) {
68
- errors.push(
69
- `Persona '${id}' names environment '${name}', which is not configured. ` +
70
- (known.length
71
- ? `Configured environments: ${known.join(', ')}.`
72
- : `Declare it under 'environments' in pikku.config.json.`)
73
- )
74
- continue
75
- }
76
- if (env.production && persona.disposition !== PRODUCTION_DISPOSITION) {
77
- errors.push(
78
- `Persona '${id}' names production environment '${name}' with disposition ` +
79
- `'${persona.disposition ?? 'realistic'}'. ` +
80
- `Only '${PRODUCTION_DISPOSITION}' may run against production — every other ` +
81
- `disposition exists to find out what the product does wrong, which is not a ` +
82
- `thing to do to real data. Either give '${id}' disposition '${PRODUCTION_DISPOSITION}', ` +
83
- `or drop '${name}' from its environments.`
84
- )
85
- }
86
- }
87
-
88
- return errors
89
- }
90
-
91
- /**
92
- * The sign-in check: the message to refuse with, or `null` to let the run
93
- * start.
94
- *
95
- * Fails closed on an environment it cannot find. An unresolved `PIKKU_ENV` is
96
- * the case where the build check has already been passed by a *different*
97
- * artifact than the one running, so treating "I don't know where I am" as
98
- * permission is exactly backwards.
99
- */
100
- export const personaEnvironmentRefusal = (
101
- id: string,
102
- persona: PersonaEnvironmentSubject,
103
- environmentName: string | undefined,
104
- environments: Readonly<Record<string, PersonaEnvironment>>
105
- ): string | null => {
106
- if (!environmentName) {
107
- return (
108
- `Refusing to sign in persona '${id}': no environment is resolved. ` +
109
- `Set PIKKU_ENV to one of the configured environments (${Object.keys(environments).join(', ') || 'none are configured'}).`
110
- )
111
- }
112
-
113
- const env = environments[environmentName]
114
- if (!env) {
115
- return (
116
- `Refusing to sign in persona '${id}': environment '${environmentName}' is not configured. ` +
117
- `Configured environments: ${Object.keys(environments).join(', ') || 'none'}.`
118
- )
119
- }
120
-
121
- if (env.production && persona.disposition !== PRODUCTION_DISPOSITION) {
122
- return (
123
- `Refusing to sign in persona '${id}' against production environment '${environmentName}': ` +
124
- `its disposition is '${persona.disposition ?? 'realistic'}', and only ` +
125
- `'${PRODUCTION_DISPOSITION}' may act on real data.`
126
- )
127
- }
128
-
129
- const allowed = resolvePersonaEnvironments(persona, environments)
130
- if (!allowed.includes(environmentName)) {
131
- return (
132
- `Refusing to sign in persona '${id}' against '${environmentName}': ` +
133
- `it declares environments ${allowed.join(', ') || 'none'}.`
134
- )
135
- }
136
-
137
- return null
138
- }
@@ -1,156 +0,0 @@
1
- /** One email a persona received. */
2
- export interface ReceivedEmail {
3
- to: string
4
- from: string
5
- subject: string
6
- receivedAt: Date
7
- /**
8
- * Links found in the body, already extracted.
9
- *
10
- * Extracted rather than handed over as text on purpose — see
11
- * {@link PersonaMailbox}. A magic link is the only part of most emails a
12
- * virtual user needs, and it is checkable in a way prose is not.
13
- */
14
- links: string[]
15
- /**
16
- * Numeric codes found in the body: OTPs, verification codes.
17
- *
18
- * Separate from `links` because plenty of flows never send a URL at all, and
19
- * a run that can only follow links cannot complete them.
20
- */
21
- codes: string[]
22
- /**
23
- * The raw body, if the implementation kept it.
24
- *
25
- * Deliberately optional and deliberately awkward to reach. Nothing in the
26
- * engine puts this in a model's context: an email body is attacker-controlled
27
- * text arriving through the front door, and a virtual user holds a real
28
- * session.
29
- */
30
- body?: string
31
- }
32
-
33
- /**
34
- * Where a persona reads its mail.
35
- *
36
- * Capturing inbound mail is platform-specific — on Cloudflare an Email Worker
37
- * on the test domain, elsewhere whatever the stage can receive with — so pikku
38
- * declares the interface and ships no default.
39
- *
40
- * Implementations **must** apply {@link MailboxAllowlist} before returning
41
- * anything. That is the primary defence against prompt injection: a virtual
42
- * user's address is real and deliverable, so anyone who learns it can send it
43
- * instructions, and the run holds a live session against a real stage.
44
- */
45
- export interface PersonaMailbox {
46
- /**
47
- * Wait for a matching email, or reject on timeout.
48
- *
49
- * The flows this exists for — sign-up, magic link, invite, reset — all block
50
- * on one arriving, so waiting is the primary operation and polling is the
51
- * fallback rather than the other way round.
52
- */
53
- waitFor(
54
- address: string,
55
- opts?: {
56
- subject?: RegExp
57
- from?: string
58
- since?: Date
59
- timeoutMs?: number
60
- }
61
- ): Promise<ReceivedEmail>
62
-
63
- /** Everything currently held for an address. */
64
- list(address: string): Promise<ReceivedEmail[]>
65
-
66
- /**
67
- * Empties an address.
68
- *
69
- * Called between runs. Without it a run reads the previous run's magic link,
70
- * succeeds, and reports a passing sign-up flow that never ran.
71
- */
72
- clear(address: string): Promise<void>
73
- }
74
-
75
- /** Who a mailbox will accept mail from. */
76
- export interface MailboxAllowlist {
77
- /**
78
- * Sender addresses or domains the stage itself sends as, e.g.
79
- * `['noreply@example.com', 'example.com']`.
80
- */
81
- senders: readonly string[]
82
- /**
83
- * Origins a link may point at, e.g. `['https://staging.example.com']`.
84
- *
85
- * A link that survives sender checking can still point anywhere; following
86
- * one off-origin is how a session leaves the stage it was scoped to.
87
- */
88
- linkOrigins?: readonly string[]
89
- }
90
-
91
- const senderMatches = (from: string, entry: string): boolean => {
92
- const sender = from.trim().toLowerCase()
93
- const allowed = entry.trim().toLowerCase()
94
- if (allowed.includes('@')) {
95
- return sender === allowed
96
- }
97
- // A bare domain matches the domain part only — never a substring, or
98
- // 'example.com' would admit 'example.com.attacker.net'.
99
- const at = sender.lastIndexOf('@')
100
- return at !== -1 && sender.slice(at + 1) === allowed
101
- }
102
-
103
- /** Whether an email may be shown to a run at all. */
104
- export const isAllowedSender = (
105
- from: string,
106
- allowlist: MailboxAllowlist
107
- ): boolean => allowlist.senders.some((entry) => senderMatches(from, entry))
108
-
109
- /**
110
- * Drops links pointing outside the permitted origins.
111
- *
112
- * Returns the surviving links rather than rejecting the whole email: a
113
- * legitimate email from the stage may well carry an unsubscribe link to
114
- * somewhere else, and refusing the email over it would break the flow this
115
- * exists to test.
116
- */
117
- export const allowedLinks = (
118
- links: readonly string[],
119
- allowlist: MailboxAllowlist
120
- ): string[] => {
121
- const origins = allowlist.linkOrigins
122
- if (!origins?.length) {
123
- return [...links]
124
- }
125
- const permitted = new Set(
126
- origins.map((origin) => {
127
- try {
128
- return new URL(origin).origin
129
- } catch {
130
- return origin
131
- }
132
- })
133
- )
134
- return links.filter((link) => {
135
- try {
136
- return permitted.has(new URL(link).origin)
137
- } catch {
138
- return false
139
- }
140
- })
141
- }
142
-
143
- /**
144
- * Applies the allowlist to a batch of received mail.
145
- *
146
- * Implementations call this rather than filtering themselves — a mailbox that
147
- * forgets is not obviously broken, it just quietly becomes an injection
148
- * channel, and nothing in a passing run would say so.
149
- */
150
- export const applyMailboxAllowlist = (
151
- emails: readonly ReceivedEmail[],
152
- allowlist: MailboxAllowlist
153
- ): ReceivedEmail[] =>
154
- emails
155
- .filter((email) => isAllowedSender(email.from, allowlist))
156
- .map((email) => ({ ...email, links: allowedLinks(email.links, allowlist) }))