@pikku/core 0.12.84 → 0.12.86

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 (564) hide show
  1. package/CHANGELOG.md +424 -0
  2. package/dist/bootstrap-compat/root.d.ts +20 -0
  3. package/dist/classification/column-form.d.ts +32 -0
  4. package/dist/classification/column-form.js +42 -0
  5. package/dist/classification/data-classification.d.ts +64 -0
  6. package/dist/classification/index.d.ts +13 -0
  7. package/dist/classification/index.js +2 -0
  8. package/dist/classification/secret-value.d.ts +56 -0
  9. package/dist/classification/secret-value.js +46 -0
  10. package/dist/crypto-utils.d.ts +1 -1
  11. package/dist/ecosystem/agent-scorer.d.ts +1 -1
  12. package/dist/ecosystem/agent.d.ts +4 -1
  13. package/dist/ecosystem/channel/local.d.ts +2 -0
  14. package/dist/ecosystem/channel/local.js +2 -0
  15. package/dist/ecosystem/channel/serverless.d.ts +9 -0
  16. package/dist/ecosystem/channel/serverless.js +1 -0
  17. package/dist/ecosystem/channel.d.ts +3 -0
  18. package/dist/ecosystem/channel.js +1 -0
  19. package/dist/ecosystem/cli.d.ts +1 -1
  20. package/dist/ecosystem/cli.js +1 -1
  21. package/dist/ecosystem/credential.d.ts +1 -0
  22. package/dist/ecosystem/crypto-utils.d.ts +8 -0
  23. package/dist/ecosystem/crypto-utils.js +1 -0
  24. package/dist/ecosystem/dev.d.ts +1 -0
  25. package/dist/ecosystem/dev.js +1 -0
  26. package/{src/ecosystem/testing.ts → dist/ecosystem/errors.d.ts} +3 -3
  27. package/dist/ecosystem/errors.js +2 -0
  28. package/dist/ecosystem/function.d.ts +1 -1
  29. package/dist/ecosystem/function.js +1 -1
  30. package/dist/ecosystem/http.d.ts +3 -1
  31. package/dist/ecosystem/http.js +3 -1
  32. package/dist/ecosystem/mcp.d.ts +1 -1
  33. package/dist/ecosystem/mcp.js +1 -1
  34. package/dist/ecosystem/middleware.d.ts +2 -1
  35. package/dist/ecosystem/middleware.js +2 -1
  36. package/dist/ecosystem/persona.d.ts +4 -2
  37. package/dist/ecosystem/persona.js +2 -1
  38. package/dist/ecosystem/queue.d.ts +4 -2
  39. package/dist/ecosystem/queue.js +3 -1
  40. package/dist/ecosystem/role.d.ts +1 -0
  41. package/dist/ecosystem/rpc.d.ts +2 -0
  42. package/dist/ecosystem/rpc.js +1 -0
  43. package/dist/ecosystem/scenario.d.ts +8 -2
  44. package/dist/ecosystem/scenario.js +5 -1
  45. package/dist/ecosystem/scheduler.d.ts +2 -1
  46. package/dist/ecosystem/scheduler.js +2 -1
  47. package/dist/ecosystem/schema.d.ts +2 -1
  48. package/dist/ecosystem/schema.js +1 -1
  49. package/dist/ecosystem/scope.d.ts +2 -0
  50. package/dist/ecosystem/scope.js +1 -0
  51. package/dist/ecosystem/secret.d.ts +2 -0
  52. package/dist/ecosystem/secret.js +1 -0
  53. package/dist/ecosystem/services/local-content.d.ts +2 -1
  54. package/dist/ecosystem/services/local-content.js +1 -1
  55. package/dist/ecosystem/services/local-meta.d.ts +1 -0
  56. package/dist/ecosystem/services/local-meta.js +1 -0
  57. package/dist/ecosystem/services.d.ts +11 -3
  58. package/dist/ecosystem/services.js +7 -1
  59. package/dist/ecosystem/trigger.d.ts +1 -0
  60. package/dist/ecosystem/trigger.js +1 -1
  61. package/dist/ecosystem/types.d.ts +6 -3
  62. package/dist/ecosystem/types.js +3 -2
  63. package/dist/ecosystem/variable.d.ts +1 -0
  64. package/dist/ecosystem/virtual-user.d.ts +3 -0
  65. package/dist/ecosystem/virtual-user.js +3 -0
  66. package/dist/ecosystem/workflow.d.ts +2 -0
  67. package/dist/ecosystem/workflow.js +2 -0
  68. package/dist/errors/index.d.ts +8 -0
  69. package/dist/errors/index.js +1 -0
  70. package/dist/errors/serialized-error.d.ts +7 -0
  71. package/dist/function/function-meta.types.d.ts +139 -0
  72. package/dist/function/function-runner.d.ts +3 -2
  73. package/dist/function/function-runner.js +31 -11
  74. package/dist/function/functions.types.d.ts +10 -2
  75. package/dist/function/index.d.ts +8 -2
  76. package/dist/function/index.js +4 -1
  77. package/dist/function/pikku-request.d.ts +8 -0
  78. package/dist/function/pikku-request.js +15 -0
  79. package/dist/middleware/auth-apikey.d.ts +2 -10
  80. package/dist/middleware/auth-apikey.js +1 -1
  81. package/dist/middleware/auth-bearer.d.ts +2 -10
  82. package/dist/middleware/auth-bearer.js +1 -1
  83. package/dist/middleware/auth-cookie.d.ts +2 -10
  84. package/dist/middleware/auth-cookie.js +1 -1
  85. package/dist/middleware/cors.d.ts +5 -11
  86. package/dist/middleware/cors.js +13 -6
  87. package/dist/middleware/index.d.ts +3 -0
  88. package/dist/middleware/index.js +1 -0
  89. package/dist/middleware/middleware-factories.d.ts +9 -0
  90. package/dist/middleware/middleware-factories.js +19 -0
  91. package/dist/middleware/middleware.types.d.ts +27 -0
  92. package/dist/middleware/middleware.types.js +1 -0
  93. package/dist/middleware/remote-auth.d.ts +2 -2
  94. package/dist/middleware/remote-auth.js +1 -1
  95. package/dist/middleware/telemetry.d.ts +4 -20
  96. package/dist/middleware/telemetry.js +1 -1
  97. package/dist/middleware-runner.d.ts +2 -1
  98. package/dist/pikku-state.d.ts +2 -1
  99. package/dist/services/audit-service.d.ts +1 -1
  100. package/dist/services/credential-wire-service.js +1 -1
  101. package/dist/services/email-service.d.ts +1 -1
  102. package/dist/services/file-scenario-run-store.d.ts +58 -0
  103. package/dist/services/file-scenario-run-store.js +214 -0
  104. package/dist/services/in-memory-workflow-service.d.ts +1 -1
  105. package/dist/services/index.d.ts +5 -1
  106. package/dist/services/index.js +3 -0
  107. package/dist/services/local-secrets.d.ts +1 -1
  108. package/dist/services/local-secrets.js +1 -1
  109. package/dist/services/logger.d.ts +7 -7
  110. package/dist/services/meta-service.d.ts +2 -1
  111. package/dist/services/scoped-secret-service.d.ts +1 -1
  112. package/dist/services/secret-service.d.ts +1 -1
  113. package/dist/services/typed-secret-service.d.ts +16 -2
  114. package/dist/services/typed-secret-service.js +5 -0
  115. package/dist/services/webhook-service.d.ts +1 -1
  116. package/dist/services/workflow-service.d.ts +2 -1
  117. package/dist/testing/index.d.ts +1 -0
  118. package/dist/testing/index.js +1 -0
  119. package/dist/types/core.types.d.ts +30 -180
  120. package/dist/types/core.types.js +1 -19
  121. package/dist/types/index.d.ts +2 -0
  122. package/dist/types/index.js +1 -0
  123. package/dist/types/state.types.d.ts +3 -1
  124. package/dist/utils.d.ts +13 -0
  125. package/dist/utils.js +2 -0
  126. package/dist/wirings/addon/addon-runner.d.ts +17 -0
  127. package/dist/wirings/addon/addon-runner.js +150 -0
  128. package/dist/wirings/addon/index.d.ts +6 -0
  129. package/dist/wirings/addon/index.js +3 -0
  130. package/dist/wirings/addon/remote-addon-auth.d.ts +16 -0
  131. package/dist/wirings/addon/remote-addon-auth.js +39 -0
  132. package/dist/wirings/addon/wire-addon.d.ts +80 -0
  133. package/dist/wirings/addon/wire-addon.js +120 -0
  134. package/dist/wirings/addon/wire-remote-addon.d.ts +22 -0
  135. package/dist/wirings/addon/wire-remote-addon.js +11 -0
  136. package/dist/wirings/agent/agent-prepare.d.ts +3 -3
  137. package/dist/wirings/agent/agent-prepare.js +1 -1
  138. package/dist/wirings/agent/agent-runner.js +2 -3
  139. package/dist/wirings/agent/agent-stream.js +2 -2
  140. package/dist/wirings/agent/agent-utils.d.ts +13 -0
  141. package/dist/wirings/agent/agent-utils.js +16 -0
  142. package/dist/wirings/agent/agent.types.d.ts +3 -2
  143. package/dist/wirings/agent/index.d.ts +1 -1
  144. package/dist/wirings/agent/voice-input.js +1 -1
  145. package/dist/wirings/agent/voice-output.js +1 -1
  146. package/dist/wirings/agent-scorer/agent-scorer-judge.d.ts +13 -0
  147. package/dist/wirings/agent-scorer/agent-scorer-judge.js +52 -0
  148. package/dist/wirings/agent-scorer/agent-scorer.d.ts +7 -1
  149. package/dist/wirings/agent-scorer/agent-scorer.js +1 -0
  150. package/dist/wirings/agent-scorer/agent-scorer.types.d.ts +20 -0
  151. package/dist/wirings/agent-scorer/index.d.ts +1 -1
  152. package/dist/wirings/channel/channel-common.d.ts +2 -1
  153. package/dist/wirings/channel/channel-middleware-runner.d.ts +2 -1
  154. package/dist/wirings/channel/channel.types.d.ts +1 -1
  155. package/dist/wirings/channel/serverless/index.d.ts +1 -0
  156. package/dist/wirings/cli/channel/index.d.ts +1 -1
  157. package/dist/wirings/cli/cli-runner.d.ts +2 -1
  158. package/dist/wirings/cli/cli-runner.js +4 -1
  159. package/dist/wirings/cli/cli.types.d.ts +21 -2
  160. package/dist/wirings/cli/command-parser.js +157 -23
  161. package/dist/wirings/gateway/gateway.types.d.ts +2 -1
  162. package/dist/wirings/http/http-runner.d.ts +1 -1
  163. package/dist/wirings/http/http-runner.js +1 -1
  164. package/dist/wirings/http/http.types.d.ts +2 -2
  165. package/dist/wirings/http/index.d.ts +1 -0
  166. package/dist/wirings/http/index.js +1 -0
  167. package/dist/wirings/http/pikku-fetch-http-request.js +1 -1
  168. package/dist/wirings/http/pikku-fetch-http-response.js +2 -2
  169. package/dist/wirings/mcp/mcp.types.d.ts +1 -1
  170. package/dist/wirings/persona/index.d.ts +1 -1
  171. package/dist/wirings/persona/index.js +1 -1
  172. package/dist/wirings/persona/persona.types.d.ts +14 -0
  173. package/dist/wirings/queue/queue.types.d.ts +1 -1
  174. package/dist/wirings/queue/signed-queue-service.d.ts +1 -1
  175. package/dist/wirings/rpc/index.d.ts +0 -6
  176. package/dist/wirings/rpc/index.js +0 -3
  177. package/dist/wirings/rpc/remote-addon-auth.d.ts +1 -1
  178. package/dist/wirings/rpc/remote-addon-auth.js +1 -1
  179. package/dist/wirings/rpc/rpc-runner.js +2 -2
  180. package/dist/wirings/rpc/wire-addon.d.ts +1 -1
  181. package/dist/wirings/scheduler/scheduler.types.d.ts +2 -1
  182. package/dist/wirings/scope/index.d.ts +1 -0
  183. package/dist/wirings/scope/index.js +1 -0
  184. package/dist/wirings/secret/secret.types.d.ts +10 -0
  185. package/dist/wirings/secret/validate-secret-definitions.js +2 -0
  186. package/dist/wirings/variable/validate-variable-definitions.js +2 -0
  187. package/dist/wirings/variable/variable.types.d.ts +9 -0
  188. package/dist/wirings/virtual-user/index.d.ts +1 -1
  189. package/dist/wirings/virtual-user/index.js +1 -1
  190. package/dist/wirings/virtual-user/prepare-virtual-user-run.d.ts +1 -1
  191. package/dist/wirings/virtual-user/virtual-user-derive.d.ts +1 -1
  192. package/dist/wirings/workflow/graph/graph-node.d.ts +9 -2
  193. package/dist/wirings/workflow/graph/graph-node.js +2 -0
  194. package/dist/wirings/workflow/graph/graph-runner.d.ts +1 -0
  195. package/dist/wirings/workflow/graph/graph-runner.js +283 -31
  196. package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +16 -1
  197. package/dist/wirings/workflow/index.d.ts +2 -0
  198. package/dist/wirings/workflow/index.js +1 -0
  199. package/dist/wirings/workflow/pikku-scenario-service.d.ts +14 -4
  200. package/dist/wirings/workflow/pikku-scenario-service.js +44 -16
  201. package/dist/wirings/workflow/pikku-workflow-service.d.ts +2 -1
  202. package/dist/wirings/workflow/pikku-workflow-service.js +3 -4
  203. package/dist/wirings/workflow/run-timeline.d.ts +1 -1
  204. package/dist/wirings/workflow/scenario-run.types.d.ts +171 -0
  205. package/dist/wirings/workflow/scenario-run.types.js +1 -0
  206. package/dist/wirings/workflow/scenario-step-guards.d.ts +1 -2
  207. package/dist/wirings/workflow/scenario-step-guards.js +0 -8
  208. package/dist/wirings/workflow/scenario-step.types.d.ts +27 -12
  209. package/dist/wirings/workflow/workflow-approval.js +2 -1
  210. package/dist/wirings/workflow/workflow-run-engine.types.d.ts +2 -1
  211. package/dist/wirings/workflow/workflow.types.d.ts +2 -1
  212. package/knowledge/decisions/index.md +2 -0
  213. package/knowledge/decisions/internals/a-scenario-step-template-is-offered-unfilled.md +1 -1
  214. package/knowledge/decisions/internals/a-secret-that-fails-to-decrypt-fails-the-whole-read.md +1 -1
  215. package/knowledge/decisions/internals/a-virtual-user-run-is-not-a-workflow-and-not-a-queued-job.md +2 -2
  216. package/knowledge/decisions/internals/a-wall-clock-threshold-is-a-load-test-in-disguise.md +6 -6
  217. package/knowledge/decisions/internals/a-workflow-wire-is-built-from-the-run-not-from-the-rpc-service.md +1 -1
  218. package/knowledge/decisions/internals/addon-singleton-services-are-cached-per-namespace-not-per-package.md +1 -1
  219. package/knowledge/decisions/internals/addon-workflow-names-are-prefixed-with-the-consumer-namespace.md +1 -1
  220. package/knowledge/decisions/internals/an-addon-scope-root-loses-to-a-root-the-host-already-declares.md +1 -1
  221. package/knowledge/decisions/internals/channel-message-handlers-accept-three-config-shapes.md +1 -1
  222. package/knowledge/decisions/internals/channel-middleware-caches-only-statically-resolved-middleware.md +1 -1
  223. package/knowledge/decisions/internals/channel-user-id-is-persisted-after-onconnect-middleware-runs.md +1 -1
  224. package/knowledge/decisions/internals/cli-option-names-are-camelcase-in-state-and-kebab-on-the-command-line.md +1 -1
  225. package/knowledge/decisions/internals/cli-parse-errors-are-routed-by-message-prefix.md +1 -1
  226. package/knowledge/decisions/internals/cli-unknown-long-options-warn-instead-of-failing.md +1 -1
  227. package/knowledge/decisions/internals/core-column-form-is-an-axis-of-its-own.md +4 -4
  228. package/knowledge/decisions/internals/core-data-classification-brand-is-an-optional-property.md +1 -1
  229. package/knowledge/decisions/internals/core-function-runner-restores-the-wire-fields-it-overwrites.md +3 -3
  230. package/knowledge/decisions/internals/core-hot-reload-merges-generated-meta-never-replaces-it.md +2 -2
  231. package/knowledge/decisions/internals/core-hot-reload-owns-its-module-registry.md +2 -2
  232. package/knowledge/decisions/internals/core-middleware-order-is-scope-then-priority.md +1 -1
  233. package/knowledge/decisions/internals/core-schema-defaults-apply-on-every-transport.md +1 -1
  234. package/knowledge/decisions/internals/core-scopes-are-an-and-gate-separate-from-permissions.md +3 -3
  235. package/knowledge/decisions/internals/gateway-adapters-resolve-lazily-and-are-promise-cached.md +1 -1
  236. package/knowledge/decisions/internals/gateway-listener-middleware-runs-without-an-rpc-on-the-wire.md +4 -4
  237. package/knowledge/decisions/internals/gateway-wiring-is-a-meta-wiring-over-http-and-channels.md +1 -1
  238. package/knowledge/decisions/internals/http-router-matches-normalized-paths-but-returns-registered-ones.md +1 -1
  239. package/knowledge/decisions/internals/in-a-scenario-a-4xx-is-data-not-an-exception.md +1 -1
  240. package/knowledge/decisions/internals/in-memory-workflow-history-aliases-the-live-step-object.md +1 -1
  241. package/knowledge/decisions/internals/index.md +4 -2
  242. package/knowledge/decisions/internals/istanbul-statement-counts-attach-to-the-start-line-only.md +1 -1
  243. package/knowledge/decisions/internals/one-project-shape-check-two-validators.md +1 -1
  244. package/knowledge/decisions/internals/queue-jobs-always-carry-an-explicit-attempts-count.md +1 -1
  245. package/knowledge/decisions/internals/remote-addons-dispatch-over-http-instead-of-local-meta.md +1 -1
  246. package/knowledge/decisions/internals/rpc-names-resolve-through-package-scope-before-root.md +1 -1
  247. package/knowledge/decisions/internals/scenario-given-and-when-are-sugar-but-then-is-not.md +2 -2
  248. package/knowledge/decisions/internals/scenarios-live-in-files-named-for-them.md +5 -5
  249. package/knowledge/decisions/internals/the-actor-prompt-says-json-because-of-json-object-mode.md +1 -1
  250. package/knowledge/decisions/internals/the-api-report-pins-members-not-just-names.md +1 -1
  251. package/knowledge/decisions/internals/the-ecosystem-entry-point-carries-the-adapter-surface.md +43 -19
  252. package/knowledge/decisions/internals/the-persona-runtime-is-exported-from-the-persona-entry-point.md +1 -1
  253. package/knowledge/decisions/internals/the-worker-disposition-is-the-one-that-is-not-testing.md +1 -1
  254. package/knowledge/decisions/internals/validate-runs-checks-by-precondition.md +3 -3
  255. package/knowledge/decisions/internals/virtual-user-step-order-comes-from-insertion-order.md +1 -1
  256. package/knowledge/decisions/internals/webhook-delivery-history-records-every-attempt-best-effort.md +1 -1
  257. package/knowledge/decisions/internals/wiring-registries-erase-the-generics-their-wire-functions-capture.md +1 -1
  258. package/knowledge/decisions/internals/workflow-approval-expiry-is-decided-from-a-recorded-deadline.md +1 -1
  259. package/knowledge/decisions/internals/workflow-core-never-imports-a-browser-driver.md +1 -1
  260. package/knowledge/decisions/internals/workflow-inline-runs-report-their-run-id-before-they-can-fail.md +1 -1
  261. package/knowledge/decisions/internals/workflow-invocation-id-is-the-dedupe-key-not-step-id.md +1 -1
  262. package/knowledge/decisions/internals/workflow-run-capabilities-are-extensions-not-subclasses.md +1 -1
  263. package/knowledge/decisions/internals/workflow-run-timeline-is-a-pure-fold-over-durable-history.md +1 -1
  264. package/knowledge/decisions/internals/workflow-scenario-assertions-never-retry-and-record-one-step.md +9 -5
  265. package/knowledge/decisions/internals/workflow-scenario-hooks-are-a-scenario-only-affordance.md +1 -1
  266. package/knowledge/decisions/internals/workflow-step-rpc-name-is-provenance-only.md +2 -2
  267. package/knowledge/decisions/internals/workflow-suspend-and-approval-reasons-are-durable-step-identities.md +1 -1
  268. package/knowledge/decisions/security/a-function-never-receives-the-secret-service.md +1 -1
  269. package/knowledge/decisions/security/a-step-runs-the-function-the-workflow-dispatched-it-with.md +1 -1
  270. package/knowledge/decisions/security/a-virtual-user-is-never-offered-a-step-that-would-forge-its-own-oracle.md +2 -3
  271. package/knowledge/decisions/security/actor-sign-in-is-proven-by-set-cookie-not-a-non-empty-jar.md +1 -1
  272. package/knowledge/decisions/security/addon-auth-and-tags-only-tighten.md +1 -1
  273. package/knowledge/decisions/security/agent-gate-requires-a-session-only-when-auth-is-true.md +1 -1
  274. package/knowledge/decisions/security/an-approval-answer-outlives-the-run-it-answered.md +3 -3
  275. package/knowledge/decisions/security/console-addon-privileged-functions-gate-themselves.md +4 -3
  276. package/knowledge/decisions/security/core-safe-fetch-blocks-ssrf-by-host-literal-not-dns.md +1 -1
  277. package/knowledge/decisions/security/gateway-middleware-sessions-must-be-bridged-onto-the-wire.md +2 -2
  278. package/knowledge/decisions/security/global-permissions-and-function-permissions-are-independent-gates.md +1 -1
  279. package/knowledge/decisions/security/http-request-bodies-are-bounded-before-they-are-buffered.md +2 -2
  280. package/knowledge/decisions/security/index.md +2 -0
  281. package/knowledge/decisions/security/mcp-internal-error-details-are-double-gated-on-production.md +1 -1
  282. package/knowledge/decisions/security/queue-jobs-carry-the-producers-pikku-user-id.md +3 -3
  283. package/knowledge/decisions/security/remote-addon-tokens-are-client-credentials-not-mesh-trust.md +1 -1
  284. package/knowledge/decisions/security/scaffold-features-are-authenticated-unless-opted-out.md +2 -2
  285. package/knowledge/decisions/security/self-authentication-is-declared-not-detected.md +1 -1
  286. package/knowledge/decisions/security/signed-content-urls-bind-the-request-path.md +2 -2
  287. package/knowledge/index.md +3 -1
  288. package/knowledge/questions/channel-middleware-accepts-bare-factories-that-nothing-resolves.md +1 -1
  289. package/knowledge/questions/index.md +2 -0
  290. package/package.json +14 -13
  291. package/run-tests.sh +0 -0
  292. package/scripts/generate-api-report.d.mts +1 -1
  293. package/scripts/generate-api-report.mjs +67 -60
  294. package/scripts/generate-api-report.mts +11 -45
  295. package/src/api-report.test.ts +70 -1
  296. package/src/app-alias-surface.test.ts +179 -0
  297. package/src/app-leaf-surface.test.ts +217 -0
  298. package/src/bootstrap-compat/root.ts +20 -0
  299. package/src/{column-form.test.ts → classification/column-form.test.ts} +2 -2
  300. package/src/{data-classification.ts → classification/data-classification.ts} +1 -5
  301. package/src/classification/index.ts +38 -0
  302. package/src/{secret-value.test.ts → classification/secret-value.test.ts} +2 -2
  303. package/src/{secret-value.ts → classification/secret-value.ts} +1 -6
  304. package/src/crypto-utils.ts +1 -1
  305. package/src/dev/reload-meta.test.ts +1 -1
  306. package/src/errors/index.ts +9 -0
  307. package/src/errors/serialized-error.ts +9 -0
  308. package/src/factory-functions.test.ts +4 -2
  309. package/src/function/function-meta.types.ts +151 -0
  310. package/src/function/function-runner.test.ts +4 -2
  311. package/src/function/function-runner.ts +47 -14
  312. package/src/function/functions.types.ts +11 -7
  313. package/src/function/index.ts +24 -5
  314. package/src/function/list.types.ts +1 -3
  315. package/src/middleware/auth-apikey.ts +4 -2
  316. package/src/middleware/auth-bearer.test.ts +1 -1
  317. package/src/middleware/auth-bearer.ts +4 -2
  318. package/src/middleware/auth-cookie.ts +4 -1
  319. package/src/middleware/cors.test.ts +126 -5
  320. package/src/middleware/cors.ts +19 -8
  321. package/src/middleware/index.ts +16 -0
  322. package/src/middleware/middleware-factories.ts +62 -0
  323. package/src/middleware/middleware.types.ts +61 -0
  324. package/src/middleware/remote-auth.test.ts +1 -1
  325. package/src/middleware/remote-auth.ts +1 -1
  326. package/src/middleware/telemetry.ts +4 -2
  327. package/src/middleware-runner.test.ts +2 -3
  328. package/src/middleware-runner.ts +2 -2
  329. package/src/no-root-barrel.test.ts +114 -0
  330. package/src/permissions.ts +2 -4
  331. package/src/pikku-state.ts +3 -1
  332. package/src/public-surface.json +56 -241
  333. package/src/public-surface.json.README +3 -3
  334. package/src/public-surface.test.ts +5 -5
  335. package/src/remote.test.ts +1 -1
  336. package/src/removed-legacy-exports.test.ts +5 -1
  337. package/src/services/audit-service.ts +1 -1
  338. package/src/services/credential-wire-service.ts +1 -1
  339. package/src/services/email-service.ts +2 -4
  340. package/src/services/file-scenario-run-store.test.ts +349 -0
  341. package/src/services/file-scenario-run-store.ts +282 -0
  342. package/src/services/in-memory-workflow-service.ts +1 -1
  343. package/src/services/index.ts +13 -1
  344. package/src/services/local-content-request-handler.ts +1 -2
  345. package/src/services/local-secrets.ts +1 -1
  346. package/src/services/logger.ts +7 -7
  347. package/src/services/meta-service.ts +2 -2
  348. package/src/services/queue-webhook-service.test.ts +1 -1
  349. package/src/services/scoped-secret-service.ts +1 -1
  350. package/src/services/secret-service.ts +1 -1
  351. package/src/services/typed-secret-service.test.ts +52 -0
  352. package/src/services/typed-secret-service.ts +26 -2
  353. package/src/services/webhook-service.ts +1 -1
  354. package/src/services/workflow-service.ts +2 -1
  355. package/src/template-alias-surface.test.ts +240 -0
  356. package/src/testing/index.ts +1 -0
  357. package/src/types/core.types.ts +33 -285
  358. package/src/types/index.ts +2 -0
  359. package/src/types/state.types.ts +6 -5
  360. package/src/types/typed-credentials.test.ts +72 -0
  361. package/src/utils.ts +34 -0
  362. package/src/wirings/{rpc → addon}/addon-scopes.test.ts +1 -1
  363. package/src/wirings/addon/index.ts +12 -0
  364. package/src/wirings/{rpc → addon}/remote-addon-auth.ts +4 -1
  365. package/src/wirings/{rpc → addon}/wire-addon.ts +37 -2
  366. package/src/wirings/agent/agent-prepare.ts +8 -5
  367. package/src/wirings/agent/agent-runner.ts +2 -3
  368. package/src/wirings/agent/agent-stream.ts +2 -3
  369. package/src/wirings/agent/agent-utils.ts +19 -0
  370. package/src/wirings/agent/agent.types.ts +3 -3
  371. package/src/wirings/agent/index.ts +1 -0
  372. package/src/wirings/agent/voice-input.ts +1 -1
  373. package/src/wirings/agent/voice-output.test.ts +2 -4
  374. package/src/wirings/agent/voice-output.ts +1 -1
  375. package/src/wirings/agent-scorer/agent-scorer-judge.test.ts +145 -0
  376. package/src/wirings/agent-scorer/agent-scorer-judge.ts +60 -0
  377. package/src/wirings/agent-scorer/agent-scorer.ts +8 -0
  378. package/src/wirings/agent-scorer/agent-scorer.types.ts +21 -0
  379. package/src/wirings/agent-scorer/index.ts +1 -0
  380. package/src/wirings/channel/channel-common.ts +4 -2
  381. package/src/wirings/channel/channel-handler.ts +2 -5
  382. package/src/wirings/channel/channel-middleware-runner.ts +1 -1
  383. package/src/wirings/channel/channel-rpc.types.ts +1 -5
  384. package/src/wirings/channel/channel.types.ts +1 -2
  385. package/src/wirings/channel/local/local-channel-runner.test.ts +1 -2
  386. package/src/wirings/channel/serverless/index.ts +1 -0
  387. package/src/wirings/cli/channel/cli-raw-channel-runner.ts +2 -2
  388. package/src/wirings/cli/channel/index.ts +1 -3
  389. package/src/wirings/cli/cli-runner.test.ts +1 -1
  390. package/src/wirings/cli/cli-runner.ts +11 -7
  391. package/src/wirings/cli/cli.types.ts +24 -3
  392. package/src/wirings/cli/command-parser.test.ts +388 -1
  393. package/src/wirings/cli/command-parser.ts +189 -29
  394. package/src/wirings/gateway/gateway-runner.test.ts +1 -2
  395. package/src/wirings/gateway/gateway-runner.ts +3 -6
  396. package/src/wirings/gateway/gateway.types.ts +5 -4
  397. package/src/wirings/http/http-routes.test.ts +1 -2
  398. package/src/wirings/http/http-runner-addon-ref.test.ts +238 -0
  399. package/src/wirings/http/http-runner.test.ts +3 -8
  400. package/src/wirings/http/http-runner.ts +9 -3
  401. package/src/wirings/http/http.types.ts +3 -12
  402. package/src/wirings/http/index.ts +1 -0
  403. package/src/wirings/http/pikku-fetch-http-request.ts +1 -1
  404. package/src/wirings/http/pikku-fetch-http-response.ts +3 -2
  405. package/src/wirings/mcp/mcp-runner.test.ts +1 -1
  406. package/src/wirings/mcp/mcp.types.ts +1 -2
  407. package/src/wirings/persona/index.ts +1 -4
  408. package/src/wirings/persona/persona.types.ts +14 -0
  409. package/src/wirings/queue/queue-identity.test.ts +1 -1
  410. package/src/wirings/queue/queue.types.ts +2 -6
  411. package/src/wirings/queue/signed-queue-service.ts +1 -1
  412. package/src/wirings/rpc/index.ts +0 -12
  413. package/src/wirings/rpc/rpc-runner.test.ts +4 -4
  414. package/src/wirings/rpc/rpc-runner.ts +3 -3
  415. package/src/wirings/scheduler/scheduler.types.ts +2 -5
  416. package/src/wirings/scope/index.ts +1 -0
  417. package/src/wirings/secret/secret.types.ts +10 -0
  418. package/src/wirings/secret/validate-secret-definitions.test.ts +23 -0
  419. package/src/wirings/secret/validate-secret-definitions.ts +2 -0
  420. package/src/wirings/variable/validate-variable-definitions.test.ts +23 -0
  421. package/src/wirings/variable/validate-variable-definitions.ts +2 -0
  422. package/src/wirings/variable/variable.types.ts +9 -0
  423. package/src/wirings/virtual-user/index.ts +1 -4
  424. package/src/wirings/virtual-user/prepare-virtual-user-run.ts +1 -1
  425. package/src/wirings/virtual-user/virtual-user-derive.test.ts +1 -1
  426. package/src/wirings/virtual-user/virtual-user-derive.ts +1 -1
  427. package/src/wirings/virtual-user/virtual-user.types.ts +1 -5
  428. package/src/wirings/workflow/graph/graph-foreach-queued.test.ts +569 -0
  429. package/src/wirings/workflow/graph/graph-foreach.test.ts +626 -0
  430. package/src/wirings/workflow/graph/graph-node.ts +16 -1
  431. package/src/wirings/workflow/graph/graph-runner.ts +387 -61
  432. package/src/wirings/workflow/graph/workflow-graph.types.ts +28 -3
  433. package/src/wirings/workflow/index.ts +8 -0
  434. package/src/wirings/workflow/pikku-scenario-service.ts +59 -19
  435. package/src/wirings/workflow/pikku-workflow-service.ts +6 -8
  436. package/src/wirings/workflow/run-timeline.ts +1 -1
  437. package/src/wirings/workflow/scenario-expectations.test.ts +28 -13
  438. package/src/wirings/workflow/scenario-run.types.ts +186 -0
  439. package/src/wirings/workflow/scenario-step-guards.ts +1 -14
  440. package/src/wirings/workflow/scenario-step.test.ts +32 -7
  441. package/src/wirings/workflow/scenario-step.types.ts +27 -12
  442. package/src/wirings/workflow/workflow-approval-policy.test.ts +117 -47
  443. package/src/wirings/workflow/workflow-approval.ts +2 -1
  444. package/src/wirings/workflow/workflow-run-engine.types.ts +2 -1
  445. package/src/wirings/workflow/workflow.types.ts +4 -12
  446. package/src/wirings-stay-decoupled.test.ts +6 -3
  447. package/tsconfig.tsbuildinfo +1 -1
  448. package/tsconfig.type-tests.json +3 -2
  449. package/dist/ecosystem/ai-agent.d.ts +0 -18
  450. package/dist/ecosystem/ai-agent.js +0 -6
  451. package/dist/ecosystem/ai-scorer.d.ts +0 -12
  452. package/dist/ecosystem/ai-scorer.js +0 -5
  453. package/dist/services/ai-agent-runner-service.d.ts +0 -220
  454. package/dist/services/ai-run-state-service.d.ts +0 -29
  455. package/dist/services/ai-storage-service.d.ts +0 -18
  456. package/dist/services/in-memory-ai-run-state-service.d.ts +0 -19
  457. package/dist/services/in-memory-ai-run-state-service.js +0 -54
  458. package/dist/testing/service-tests/ai-storage-service-tests.d.ts +0 -3
  459. package/dist/testing/service-tests/ai-storage-service-tests.js +0 -302
  460. package/dist/wirings/ai-agent/agent-rpc.d.ts +0 -15
  461. package/dist/wirings/ai-agent/agent-rpc.js +0 -53
  462. package/dist/wirings/ai-agent/ai-agent-agui.d.ts +0 -79
  463. package/dist/wirings/ai-agent/ai-agent-agui.js +0 -327
  464. package/dist/wirings/ai-agent/ai-agent-finalize.d.ts +0 -58
  465. package/dist/wirings/ai-agent/ai-agent-finalize.js +0 -138
  466. package/dist/wirings/ai-agent/ai-agent-helpers.d.ts +0 -35
  467. package/dist/wirings/ai-agent/ai-agent-helpers.js +0 -47
  468. package/dist/wirings/ai-agent/ai-agent-interrupt.d.ts +0 -153
  469. package/dist/wirings/ai-agent/ai-agent-interrupt.js +0 -257
  470. package/dist/wirings/ai-agent/ai-agent-memory.d.ts +0 -42
  471. package/dist/wirings/ai-agent/ai-agent-memory.js +0 -333
  472. package/dist/wirings/ai-agent/ai-agent-model-config.d.ts +0 -16
  473. package/dist/wirings/ai-agent/ai-agent-model-config.js +0 -51
  474. package/dist/wirings/ai-agent/ai-agent-prepare.d.ts +0 -117
  475. package/dist/wirings/ai-agent/ai-agent-prepare.js +0 -728
  476. package/dist/wirings/ai-agent/ai-agent-registry.d.ts +0 -16
  477. package/dist/wirings/ai-agent/ai-agent-registry.js +0 -51
  478. package/dist/wirings/ai-agent/ai-agent-runner.d.ts +0 -7
  479. package/dist/wirings/ai-agent/ai-agent-runner.js +0 -580
  480. package/dist/wirings/ai-agent/ai-agent-stream.d.ts +0 -41
  481. package/dist/wirings/ai-agent/ai-agent-stream.js +0 -1029
  482. package/dist/wirings/ai-agent/ai-agent-turn.d.ts +0 -57
  483. package/dist/wirings/ai-agent/ai-agent-turn.js +0 -82
  484. package/dist/wirings/ai-agent/ai-agent-utils.d.ts +0 -1
  485. package/dist/wirings/ai-agent/ai-agent-utils.js +0 -1
  486. package/dist/wirings/ai-agent/ai-agent.types.d.ts +0 -625
  487. package/dist/wirings/ai-agent/index.d.ts +0 -12
  488. package/dist/wirings/ai-agent/index.js +0 -10
  489. package/dist/wirings/ai-agent/voice-input.d.ts +0 -69
  490. package/dist/wirings/ai-agent/voice-input.js +0 -150
  491. package/dist/wirings/ai-agent/voice-output.d.ts +0 -85
  492. package/dist/wirings/ai-agent/voice-output.js +0 -196
  493. package/dist/wirings/ai-scorer/ai-scorer-grade.d.ts +0 -26
  494. package/dist/wirings/ai-scorer/ai-scorer-grade.js +0 -33
  495. package/dist/wirings/ai-scorer/ai-scorer-judge.d.ts +0 -17
  496. package/dist/wirings/ai-scorer/ai-scorer-judge.js +0 -92
  497. package/dist/wirings/ai-scorer/ai-scorer-live.d.ts +0 -15
  498. package/dist/wirings/ai-scorer/ai-scorer-live.js +0 -38
  499. package/dist/wirings/ai-scorer/ai-scorer-registry.d.ts +0 -18
  500. package/dist/wirings/ai-scorer/ai-scorer-registry.js +0 -46
  501. package/dist/wirings/ai-scorer/ai-scorer-sampling.d.ts +0 -8
  502. package/dist/wirings/ai-scorer/ai-scorer-sampling.js +0 -31
  503. package/dist/wirings/ai-scorer/ai-scorer-snapshots.d.ts +0 -10
  504. package/dist/wirings/ai-scorer/ai-scorer-snapshots.js +0 -40
  505. package/dist/wirings/ai-scorer/ai-scorer-worker.d.ts +0 -15
  506. package/dist/wirings/ai-scorer/ai-scorer-worker.js +0 -58
  507. package/dist/wirings/ai-scorer/ai-scorer.d.ts +0 -39
  508. package/dist/wirings/ai-scorer/ai-scorer.js +0 -40
  509. package/dist/wirings/ai-scorer/ai-scorer.types.d.ts +0 -90
  510. package/dist/wirings/ai-scorer/ai-scorer.types.js +0 -4
  511. package/dist/wirings/ai-scorer/index.d.ts +0 -6
  512. package/dist/wirings/ai-scorer/index.js +0 -5
  513. package/src/ecosystem/agent-scorer.ts +0 -24
  514. package/src/ecosystem/agent.ts +0 -42
  515. package/src/ecosystem/channel/local.ts +0 -1
  516. package/src/ecosystem/channel.ts +0 -22
  517. package/src/ecosystem/cli/channel.ts +0 -25
  518. package/src/ecosystem/cli.ts +0 -21
  519. package/src/ecosystem/credential.ts +0 -10
  520. package/src/ecosystem/dev.ts +0 -12
  521. package/src/ecosystem/function.ts +0 -28
  522. package/src/ecosystem/gateway.ts +0 -4
  523. package/src/ecosystem/hmac.ts +0 -1
  524. package/src/ecosystem/http.ts +0 -22
  525. package/src/ecosystem/mcp.ts +0 -17
  526. package/src/ecosystem/middleware.ts +0 -27
  527. package/src/ecosystem/node-host-resolver.ts +0 -1
  528. package/src/ecosystem/node.ts +0 -5
  529. package/src/ecosystem/oauth2.ts +0 -4
  530. package/src/ecosystem/persona.ts +0 -30
  531. package/src/ecosystem/queue.ts +0 -23
  532. package/src/ecosystem/remote.ts +0 -9
  533. package/src/ecosystem/role.ts +0 -13
  534. package/src/ecosystem/rpc.ts +0 -7
  535. package/src/ecosystem/safe-fetch.ts +0 -8
  536. package/src/ecosystem/scenario.ts +0 -32
  537. package/src/ecosystem/scheduler.ts +0 -5
  538. package/src/ecosystem/schema.ts +0 -1
  539. package/src/ecosystem/scope.ts +0 -14
  540. package/src/ecosystem/secret.ts +0 -15
  541. package/src/ecosystem/services/istanbul-coverage.ts +0 -1
  542. package/src/ecosystem/services/local-content-request-handler.ts +0 -16
  543. package/src/ecosystem/services/local-content.ts +0 -1
  544. package/src/ecosystem/services/v8-coverage.ts +0 -1
  545. package/src/ecosystem/services.ts +0 -82
  546. package/src/ecosystem/trigger.ts +0 -7
  547. package/src/ecosystem/types.ts +0 -34
  548. package/src/ecosystem/variable.ts +0 -14
  549. package/src/ecosystem/virtual-user.ts +0 -48
  550. package/src/ecosystem/workflow.ts +0 -68
  551. package/src/ecosystem.ts +0 -40
  552. package/src/index.ts +0 -244
  553. /package/dist/{services/ai-agent-runner-service.js → bootstrap-compat/root.js} +0 -0
  554. /package/dist/{services/ai-run-state-service.js → classification/data-classification.js} +0 -0
  555. /package/dist/{services/ai-storage-service.js → errors/serialized-error.js} +0 -0
  556. /package/dist/{wirings/ai-agent/ai-agent.types.js → function/function-meta.types.js} +0 -0
  557. /package/src/{column-form.ts → classification/column-form.ts} +0 -0
  558. /package/src/{pikku-request.test.ts → function/pikku-request.test.ts} +0 -0
  559. /package/src/{pikku-request.ts → function/pikku-request.ts} +0 -0
  560. /package/src/wirings/{rpc → addon}/addon-auth-tags.test.ts +0 -0
  561. /package/src/wirings/{rpc → addon}/addon-runner.ts +0 -0
  562. /package/src/wirings/{rpc → addon}/addon-secrets.test.ts +0 -0
  563. /package/src/wirings/{rpc → addon}/wire-addon.test.ts +0 -0
  564. /package/src/wirings/{rpc → addon}/wire-remote-addon.ts +0 -0
@@ -0,0 +1,179 @@
1
+ import { test, describe } from 'node:test'
2
+ import * as assert from 'assert'
3
+ import ts from 'typescript'
4
+ import { readFileSync, readdirSync, statSync } from 'node:fs'
5
+ import { dirname, join, relative } from 'node:path'
6
+ import { fileURLToPath } from 'node:url'
7
+
8
+ /**
9
+ * The generated `#pikku` alias is the app developer's public API. An app
10
+ * reaching past it into `@pikku/core` is the smell this file measures: the
11
+ * alias is typed against that app's own functions, so a name pulled from core
12
+ * directly is one the app is holding untyped and one the CLI cannot evolve.
13
+ *
14
+ * The trees below are apps rather than packages, so they have no `src`
15
+ * convention to walk — bootstrap and test files sit wherever the runtime wants
16
+ * them. Walking each tree root means skipping what an app accumulates:
17
+ * installed dependencies, build output, and its own generated `.pikku`.
18
+ */
19
+ const repoRoot = join(dirname(fileURLToPath(import.meta.url)), '../../..')
20
+ const appTrees = ['templates', 'e2e', 'verifiers']
21
+ const skipped = new Set(['node_modules', 'dist', '.next', 'build'])
22
+
23
+ /**
24
+ * `outDir` is a project's own setting, so the generated tree is not always
25
+ * `.pikku` — the treeshake verifier writes one output tree per scenario under
26
+ * `.pikku-shake`. Matching the prefix keeps a leaf's generated `index.ts`, which
27
+ * carries no `.gen.` in its name, from reading as hand-written app code.
28
+ */
29
+ const isGeneratedTree = (entry: string) => entry.startsWith('.pikku')
30
+
31
+ const walkApp = (dir: string, out: string[] = []): string[] => {
32
+ for (const entry of readdirSync(dir)) {
33
+ if (skipped.has(entry) || isGeneratedTree(entry)) continue
34
+ const path = join(dir, entry)
35
+ if (statSync(path).isDirectory()) walkApp(path, out)
36
+ else if (path.endsWith('.ts') || path.endsWith('.tsx')) out.push(path)
37
+ }
38
+ return out
39
+ }
40
+
41
+ /**
42
+ * `.gen.*` and `.d.ts` files are CLI output, not hand-written source: what they
43
+ * import is decided by the codegen templates, which are the thing that writes
44
+ * the alias in the first place.
45
+ */
46
+ const isGenerated = (path: string) =>
47
+ path.includes('.gen.') || path.endsWith('.d.ts')
48
+
49
+ const appSourceFiles = () =>
50
+ appTrees
51
+ .flatMap((tree) => walkApp(join(repoRoot, tree)))
52
+ .filter((file) => !isGenerated(file))
53
+
54
+ /**
55
+ * Parsed rather than grepped: a step body held as a template literal is fixture
56
+ * text describing a user's file, not an import the app itself makes.
57
+ */
58
+ const coreImports = (file: string) => {
59
+ const source = ts.createSourceFile(
60
+ file,
61
+ readFileSync(file, 'utf8'),
62
+ ts.ScriptTarget.Latest,
63
+ true
64
+ )
65
+ const found: { specifier: string; line: number; names: string[] }[] = []
66
+ for (const statement of source.statements) {
67
+ if (
68
+ !ts.isImportDeclaration(statement) &&
69
+ !ts.isExportDeclaration(statement)
70
+ ) {
71
+ continue
72
+ }
73
+ const moduleSpecifier = statement.moduleSpecifier
74
+ if (!moduleSpecifier || !ts.isStringLiteral(moduleSpecifier)) continue
75
+ const specifier = moduleSpecifier.text
76
+ if (specifier !== '@pikku/core' && !specifier.startsWith('@pikku/core/')) {
77
+ continue
78
+ }
79
+ const { line } = source.getLineAndCharacterOfPosition(
80
+ statement.getStart(source)
81
+ )
82
+ const clause = ts.isImportDeclaration(statement)
83
+ ? statement.importClause?.namedBindings
84
+ : statement.exportClause
85
+ const names =
86
+ clause && (ts.isNamedImports(clause) || ts.isNamedExports(clause))
87
+ ? clause.elements.map((element) => element.name.text)
88
+ : []
89
+ found.push({ specifier, line: line + 1, names })
90
+ }
91
+ return found
92
+ }
93
+
94
+ /**
95
+ * The scenario and persona surfaces are test-only names — actors, cookie jars,
96
+ * polling helpers, the typed personas an app declares. They are app code, but a
97
+ * distinct surface from wiring, so they reach the app through their own
98
+ * sub-entry rather than crowding the main hub.
99
+ */
100
+ const scenarioSubpaths = new Set(['@pikku/core/scenario', '@pikku/core/persona'])
101
+
102
+ /**
103
+ * A relative path into the generated scenario barrel reaches the same file the
104
+ * alias does, so it compiles — and then hard-codes how far the app file sits
105
+ * from `outDir`. Moving either end breaks it, and the CLI has no way to see
106
+ * that it is depended upon.
107
+ */
108
+ const relativeIntoScenarioBarrel = (file: string) => {
109
+ const source = ts.createSourceFile(
110
+ file,
111
+ readFileSync(file, 'utf8'),
112
+ ts.ScriptTarget.Latest,
113
+ true
114
+ )
115
+ const found: { specifier: string; line: number }[] = []
116
+ for (const statement of source.statements) {
117
+ if (
118
+ !ts.isImportDeclaration(statement) &&
119
+ !ts.isExportDeclaration(statement)
120
+ ) {
121
+ continue
122
+ }
123
+ const moduleSpecifier = statement.moduleSpecifier
124
+ if (!moduleSpecifier || !ts.isStringLiteral(moduleSpecifier)) continue
125
+ if (!moduleSpecifier.text.startsWith('.')) continue
126
+ if (!/\/pikku-scenario-types\.gen\.js$/.test(moduleSpecifier.text)) continue
127
+ const { line } = source.getLineAndCharacterOfPosition(
128
+ statement.getStart(source)
129
+ )
130
+ found.push({ specifier: moduleSpecifier.text, line: line + 1 })
131
+ }
132
+ return found
133
+ }
134
+
135
+ describe('the #pikku alias is the app surface', () => {
136
+ test('scenario code reaches the test surface through #pikku/scenario', () => {
137
+ const offenders: string[] = []
138
+
139
+ for (const file of appSourceFiles()) {
140
+ for (const { specifier, line, names } of coreImports(file)) {
141
+ if (!scenarioSubpaths.has(specifier)) continue
142
+ offenders.push(
143
+ `${relative(repoRoot, file)}:${line} ${names.join(', ')} from '${specifier}'`
144
+ )
145
+ }
146
+ }
147
+
148
+ assert.deepStrictEqual(
149
+ offenders,
150
+ [],
151
+ `Scenario and persona names come from the generated ` +
152
+ `'#pikku/scenario' entry, which is typed against this app's own ` +
153
+ `personas and steps.\n` +
154
+ `Reaching '@pikku/core/scenario' or '@pikku/core/persona' directly ` +
155
+ `gets the untyped shape, from a subpath scheduled for deletion.\n\n` +
156
+ offenders.join('\n')
157
+ )
158
+ })
159
+
160
+ test('the scenario barrel is reached through the alias, not a relative path', () => {
161
+ const offenders: string[] = []
162
+
163
+ for (const file of appSourceFiles()) {
164
+ for (const { specifier, line } of relativeIntoScenarioBarrel(file)) {
165
+ offenders.push(`${relative(repoRoot, file)}:${line} '${specifier}'`)
166
+ }
167
+ }
168
+
169
+ assert.deepStrictEqual(
170
+ offenders,
171
+ [],
172
+ `The generated scenario barrel is reached through '#pikku/scenario', ` +
173
+ `which the app's own 'imports' map points at.\n` +
174
+ `A relative path hard-codes the distance from the file to 'outDir', ` +
175
+ `so moving either end breaks it silently.\n\n` +
176
+ offenders.join('\n')
177
+ )
178
+ })
179
+ })
@@ -0,0 +1,217 @@
1
+ import { test, describe } from 'node:test'
2
+ import * as assert from 'assert'
3
+ import ts from 'typescript'
4
+ import { readFileSync, readdirSync, statSync, existsSync } from 'node:fs'
5
+ import { dirname, join, relative } from 'node:path'
6
+ import { fileURLToPath } from 'node:url'
7
+
8
+ /**
9
+ * `#pikku` is the app tier's only door onto Pikku, and it is a namespace rather
10
+ * than a module: `#pikku/http`, `#pikku/workflow`, one subpath per wiring.
11
+ *
12
+ * The bare specifier used to resolve to `.pikku/pikku-types.gen.ts`, which
13
+ * re-exported all twelve wiring leaves with `export *` — undoing the split the
14
+ * leaves exist for, each of which still says so in its own header ("HTTP-specific
15
+ * type definitions for tree-shaking optimization"). Reaching that barrel put 33
16
+ * distinct `@pikku/core` subpaths into the module graph, and neither of the two
17
+ * consumers could drop them again: bundlers keep `export *` chains because the
18
+ * app declares no `sideEffects`, and Node and tsx do not tree-shake at all, so
19
+ * an app with no queues still executed `@pikku/core/queue` at boot.
20
+ *
21
+ * Deleting the barrel also turns the addon boundary from advice into a rule. An
22
+ * addon's leaves are never generated, so `#pikku/http` fails to resolve at the
23
+ * specifier rather than yielding "no exported member" from a hub that quietly
24
+ * dropped the re-export.
25
+ */
26
+ const repoRoot = join(dirname(fileURLToPath(import.meta.url)), '../../..')
27
+
28
+ /**
29
+ * Membership is discovered, not listed: every directory holding a
30
+ * `pikku.config.json` is a Pikku project, so a project added later arrives
31
+ * guarded rather than invisible. Listing them by hand is how the ecosystem
32
+ * guard reported green on four packages it had never scanned.
33
+ */
34
+ const skipped = new Set([
35
+ 'node_modules',
36
+ 'dist',
37
+ '.pikku',
38
+ '.next',
39
+ 'build',
40
+ '.git',
41
+ 'coverage',
42
+ ])
43
+
44
+ const findProjects = (dir: string, out: string[] = []): string[] => {
45
+ for (const entry of readdirSync(dir)) {
46
+ if (skipped.has(entry)) continue
47
+ const path = join(dir, entry)
48
+ if (!statSync(path).isDirectory()) continue
49
+ if (existsSync(join(path, 'pikku.config.json'))) out.push(path)
50
+ findProjects(path, out)
51
+ }
52
+ return out
53
+ }
54
+
55
+ const walk = (dir: string, out: string[] = []): string[] => {
56
+ for (const entry of readdirSync(dir)) {
57
+ if (skipped.has(entry)) continue
58
+ const path = join(dir, entry)
59
+ if (statSync(path).isDirectory()) walk(path, out)
60
+ else if (path.endsWith('.ts') || path.endsWith('.tsx')) out.push(path)
61
+ }
62
+ return out
63
+ }
64
+
65
+ /**
66
+ * `.gen.*` and `.d.ts` are the generator's own output — what they import is
67
+ * decided by the codegen templates, and `.pikku` is skipped outright.
68
+ */
69
+ const isGenerated = (path: string) =>
70
+ path.includes('.gen.') || path.endsWith('.d.ts')
71
+
72
+ const projectSourceFiles = (project: string) => {
73
+ const files: string[] = []
74
+ for (const entry of readdirSync(project)) {
75
+ if (skipped.has(entry)) continue
76
+ const path = join(project, entry)
77
+ if (!statSync(path).isDirectory()) continue
78
+ if (existsSync(join(path, 'pikku.config.json'))) continue
79
+ walk(path, files)
80
+ }
81
+ return files.filter((file) => !isGenerated(file))
82
+ }
83
+
84
+ /**
85
+ * Parsed rather than grepped: the CLI's serializers hold the specifiers they
86
+ * emit inside template literals, and those are output text rather than imports
87
+ * the CLI itself makes.
88
+ */
89
+ const barrelSpecifiers = (file: string) => {
90
+ const source = ts.createSourceFile(
91
+ file,
92
+ readFileSync(file, 'utf8'),
93
+ ts.ScriptTarget.Latest,
94
+ true
95
+ )
96
+ const found: { specifier: string; line: number }[] = []
97
+ for (const statement of source.statements) {
98
+ if (
99
+ !ts.isImportDeclaration(statement) &&
100
+ !ts.isExportDeclaration(statement)
101
+ ) {
102
+ continue
103
+ }
104
+ const moduleSpecifier = statement.moduleSpecifier
105
+ if (!moduleSpecifier || !ts.isStringLiteral(moduleSpecifier)) continue
106
+ const specifier = moduleSpecifier.text
107
+ const isBarrel =
108
+ specifier === '#pikku' ||
109
+ /^#pikku\/pikku-types\.gen(\.js)?$/.test(specifier)
110
+ if (!isBarrel) continue
111
+ const { line } = source.getLineAndCharacterOfPosition(
112
+ statement.getStart(source)
113
+ )
114
+ found.push({ specifier, line: line + 1 })
115
+ }
116
+ return found
117
+ }
118
+
119
+ /**
120
+ * Names a leaf carries, mapped to the leaf that carries them. An app reaching
121
+ * `@pikku/core` for one of these is the smell that says the generator is not
122
+ * emitting something it should — the definer is already generated into the
123
+ * project's own `.pikku`, so naming core instead couples the app to a package
124
+ * it otherwise never imports.
125
+ */
126
+ const namesOwnedByALeaf = new Map<string, string>([
127
+ ['defineCredential', '#pikku/credentials'],
128
+ ['defineSecret', '#pikku/secrets'],
129
+ ['defineVariable', '#pikku/variables'],
130
+ ['defineScope', '#pikku/scopes'],
131
+ ['defineSystemRole', '#pikku/scopes'],
132
+ ['cors', '#pikku/http'],
133
+ ['InvalidOriginError', '#pikku/error'],
134
+ ])
135
+
136
+ const coreNamesThatHaveALeaf = (file: string) => {
137
+ const source = ts.createSourceFile(
138
+ file,
139
+ readFileSync(file, 'utf8'),
140
+ ts.ScriptTarget.Latest,
141
+ true
142
+ )
143
+ const found: { name: string; leaf: string; line: number }[] = []
144
+ for (const statement of source.statements) {
145
+ if (!ts.isImportDeclaration(statement)) continue
146
+ const moduleSpecifier = statement.moduleSpecifier
147
+ if (!ts.isStringLiteral(moduleSpecifier)) continue
148
+ if (!/^@pikku\/core(\/|$)/.test(moduleSpecifier.text)) continue
149
+
150
+ const bindings = statement.importClause?.namedBindings
151
+ if (!bindings || !ts.isNamedImports(bindings)) continue
152
+ for (const element of bindings.elements) {
153
+ const name = (element.propertyName ?? element.name).text
154
+ const leaf = namesOwnedByALeaf.get(name)
155
+ if (!leaf) continue
156
+ const { line } = source.getLineAndCharacterOfPosition(
157
+ element.getStart(source)
158
+ )
159
+ found.push({ name, leaf, line: line + 1 })
160
+ }
161
+ }
162
+ return found
163
+ }
164
+
165
+ describe('app leaf surface', () => {
166
+ test('no Pikku project reaches past a leaf for a name the leaf carries', () => {
167
+ const projects = findProjects(repoRoot)
168
+ assert.ok(projects.length > 0, 'expected to discover Pikku projects')
169
+
170
+ // A project nested inside another (an addon under `e2e/packages`) is
171
+ // discovered on its own account and again as its parent's source, so the
172
+ // same offence is reached twice.
173
+ const offenders = new Set<string>()
174
+ for (const project of projects) {
175
+ for (const file of projectSourceFiles(project)) {
176
+ for (const { name, leaf, line } of coreNamesThatHaveALeaf(file)) {
177
+ offenders.add(
178
+ `${relative(repoRoot, file)}:${line} ${name} — import it from '${leaf}'`
179
+ )
180
+ }
181
+ }
182
+ }
183
+
184
+ assert.deepStrictEqual(
185
+ [...offenders].sort(),
186
+ [],
187
+ `An app developer imports from '#pikku/<leaf>'. Reaching past it to ` +
188
+ `'@pikku/core' for a name the leaf already carries is the smell that ` +
189
+ `says the generator is not emitting something it should.\n\n` +
190
+ [...offenders].sort().join('\n')
191
+ )
192
+ })
193
+
194
+ test('no Pikku project reaches the app tier through a barrel', () => {
195
+ const projects = findProjects(repoRoot)
196
+ assert.ok(projects.length > 0, 'expected to discover Pikku projects')
197
+
198
+ const offenders: string[] = []
199
+ for (const project of projects) {
200
+ for (const file of projectSourceFiles(project)) {
201
+ for (const { specifier, line } of barrelSpecifiers(file)) {
202
+ offenders.push(`${relative(repoRoot, file)}:${line} ${specifier}`)
203
+ }
204
+ }
205
+ }
206
+
207
+ assert.deepStrictEqual(
208
+ offenders,
209
+ [],
210
+ `The app tier reaches Pikku through one subpath per wiring — ` +
211
+ `'#pikku/http', '#pikku/workflow', '#pikku/function'.\n` +
212
+ `A barrel import pulls every wiring's core dependencies into the ` +
213
+ `module graph, and nothing downstream can drop them again.\n\n` +
214
+ offenders.join('\n')
215
+ )
216
+ })
217
+ })
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Bootstrap compatibility, not a public entry point.
3
+ *
4
+ * The package root carried a 206-name barrel; it is gone, and every name now
5
+ * lives on the subpath that owns it. What is left here is the handful of types
6
+ * the CLI pinned in `packages/cli/build.sh` still writes into the files it
7
+ * generates for the CLI itself — an unresolved type there is a silent `any` in
8
+ * the CLI's own generated surface, not a build failure, which is why this
9
+ * exists rather than letting it break loudly.
10
+ *
11
+ * `bootstrap-compat.test.ts` fails if the pinned CLI's output drifts from this
12
+ * list. Delete this file and its `exports` entry once the pin moves to a CLI
13
+ * released from this branch.
14
+ */
15
+ export type { PikkuWire, SecretlessServices } from '../types/core.types.js'
16
+ export type { CorePikkuMiddleware } from '../middleware/middleware.types.js'
17
+ export type { PickRequired } from '../utils.js'
18
+ export type { CorePermissionGroup } from '../function/functions.types.js'
19
+ export type { ListInput, ListOutput } from '../function/list.types.js'
20
+ export type { SecretService } from '../services/secret-service.js'
@@ -11,7 +11,7 @@ import type {
11
11
  SealedValue,
12
12
  WrappedValue,
13
13
  } from './data-classification.js'
14
- import { deriveKEK, envelopeEncrypt, envelopeRewrap } from './crypto-utils.js'
14
+ import { deriveKEK, envelopeEncrypt, envelopeRewrap } from '../crypto-utils.js'
15
15
 
16
16
  const KEY_MATERIAL = 'x'.repeat(32)
17
17
 
@@ -87,7 +87,7 @@ describe('the envelope primitives produce the brand', () => {
87
87
  test('decrypting accepts a bare string, so reading a row back needs no cast', async () => {
88
88
  const kek = await deriveKEK(KEY_MATERIAL, 'c2FsdA')
89
89
  const { ciphertext, wrappedDEK } = await envelopeEncrypt(kek, 'value')
90
- const { envelopeDecrypt } = await import('./crypto-utils.js')
90
+ const { envelopeDecrypt } = await import('../crypto-utils.js')
91
91
  const fromRow: string = ciphertext
92
92
  assert.equal(
93
93
  await envelopeDecrypt<string>(kek, fromRow, wrappedDEK),
@@ -5,11 +5,7 @@ export type Secret<T> = T & { readonly __classification__?: 'secret' }
5
5
 
6
6
  export type Classification = 'public' | 'private' | 'pii' | 'secret'
7
7
  export type AnonymizeStrategy =
8
- | 'fake:email'
9
- | 'fake:name'
10
- | 'hash'
11
- | 'keep'
12
- | null
8
+ 'fake:email' | 'fake:name' | 'hash' | 'keep' | null
13
9
 
14
10
  // knowledge: decisions/internals/core-column-form-is-an-axis-of-its-own.md
15
11
 
@@ -0,0 +1,38 @@
1
+ /**
2
+ * What a value is, and how it must be handled: the classification brands a
3
+ * column carries, the stored forms those brands map to, and the wrapper that
4
+ * keeps a secret out of a log.
5
+ *
6
+ * These arrived as three entry points — one for the types, one for the
7
+ * runtime helpers, one for `SecretValue` — which is the same subject behind
8
+ * three doors, split by whether a name happens to be a type or a value.
9
+ */
10
+ export type {
11
+ Private,
12
+ Pii,
13
+ Secret,
14
+ Classification,
15
+ AnonymizeStrategy,
16
+ ColumnForm,
17
+ WrappedValue,
18
+ SealedValue,
19
+ HashedValue,
20
+ ColumnClassification,
21
+ ClassificationManifest,
22
+ } from './data-classification.js'
23
+
24
+ export {
25
+ hashToken,
26
+ unsafeAsWrapped,
27
+ unsafeAsSealed,
28
+ unsafeAsHashed,
29
+ } from './column-form.js'
30
+
31
+ export {
32
+ REDACTED,
33
+ SecretCoercionError,
34
+ SecretValue,
35
+ createSecretValue,
36
+ isSecretValue,
37
+ } from './secret-value.js'
38
+ export type { Safe } from './secret-value.js'
@@ -8,8 +8,8 @@ import {
8
8
  type Safe,
9
9
  type SecretValue,
10
10
  } from './secret-value.js'
11
- import type { Logger } from './services/logger.js'
12
- import type { AuditLog } from './services/audit-service.js'
11
+ import type { Logger } from '../services/logger.js'
12
+ import type { AuditLog } from '../services/audit-service.js'
13
13
 
14
14
  const VALUE = 'sk-live-DEADBEEF'
15
15
 
@@ -70,12 +70,7 @@ export const isSecretValue = (value: unknown): value is SecretValue<unknown> =>
70
70
  type IsAny<T> = 0 extends 1 & T ? true : false
71
71
 
72
72
  type Passthrough =
73
- | Function
74
- | Date
75
- | RegExp
76
- | Error
77
- | ArrayBuffer
78
- | ArrayBufferView
73
+ Function | Date | RegExp | Error | ArrayBuffer | ArrayBufferView
79
74
 
80
75
  /**
81
76
  * Rejects a `SecretValue` anywhere in `T`, however deeply nested, by collapsing
@@ -1,4 +1,4 @@
1
- import type { WrappedValue } from './data-classification.js'
1
+ import type { WrappedValue } from './classification/data-classification.js'
2
2
  import { WeakKeyMaterialError } from './errors/errors.js'
3
3
 
4
4
  const encoder = new TextEncoder()
@@ -6,7 +6,7 @@ import { tmpdir } from 'node:os'
6
6
 
7
7
  import { pikkuState, resetPikkuState } from '../pikku-state.js'
8
8
  import { getSchema } from '../schema.js'
9
- import { wireAddon } from '../wirings/rpc/wire-addon.js'
9
+ import { wireAddon } from '../wirings/addon/wire-addon.js'
10
10
  import { reloadGeneratedMeta, reconcileAddonRegistry } from './reload-meta.js'
11
11
 
12
12
  const createMockLogger = () => {
@@ -1,2 +1,11 @@
1
1
  export * from './errors.js'
2
2
  export { PikkuError, addError } from './error-handler.js'
3
+
4
+ /**
5
+ * Types the exports above mention but do not themselves export. Without
6
+ * them a consumer's declaration emit has no name for the type it infers,
7
+ * and fails with TS2883 rather than reaching for the original entry point.
8
+ */
9
+ export type { ErrorDetails } from './error-handler.js'
10
+ export { isExpectedError } from './error-handler.js'
11
+ export type { SerializedError } from './serialized-error.js'
@@ -0,0 +1,9 @@
1
+ export interface SerializedError {
2
+ message: string
3
+ stack?: string
4
+ code?: string
5
+ // Set for a deliberate PikkuError; survives step-boundary rehydration so
6
+ // the workflow runner logs the message alone rather than a stack trace.
7
+ expected?: boolean
8
+ [key: string]: any
9
+ }
@@ -3,10 +3,12 @@ import assert from 'node:assert'
3
3
  import {
4
4
  pikkuAuth,
5
5
  pikkuPermission,
6
- pikkuMiddleware,
7
6
  pikkuPermissionFactory,
7
+ } from './function/functions.types.js'
8
+ import {
9
+ pikkuMiddleware,
8
10
  pikkuMiddlewareFactory,
9
- } from './index.js'
11
+ } from './middleware/middleware-factories.js'
10
12
 
11
13
  test('pikkuPermission returns the same function', async () => {
12
14
  const originalFn = async () => true