@pikku/core 0.12.80 → 0.12.83

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 (237) hide show
  1. package/CHANGELOG.md +345 -0
  2. package/dist/errors/index.d.ts +1 -1
  3. package/dist/errors/index.js +1 -1
  4. package/dist/function/function-runner.js +2 -5
  5. package/dist/function/index.d.ts +1 -1
  6. package/dist/index.d.ts +11 -11
  7. package/dist/index.js +3 -3
  8. package/dist/pikku-state.js +4 -0
  9. package/dist/services/ai-agent-runner-service.d.ts +7 -0
  10. package/dist/services/ai-run-state-service.d.ts +10 -0
  11. package/dist/services/in-memory-ai-run-state-service.d.ts +5 -1
  12. package/dist/services/in-memory-ai-run-state-service.js +9 -0
  13. package/dist/services/index.d.ts +15 -16
  14. package/dist/services/index.js +5 -5
  15. package/dist/services/meta-service.d.ts +2 -1
  16. package/dist/services/scoped-credential-service.d.ts +21 -0
  17. package/dist/services/scoped-credential-service.js +53 -0
  18. package/dist/testing/service-tests/ai-storage-service-tests.js +76 -0
  19. package/dist/types/core.types.d.ts +2 -3
  20. package/dist/types/state.types.d.ts +19 -1
  21. package/dist/wirings/actor-flow/index.d.ts +1 -1
  22. package/dist/wirings/ai-agent/ai-agent-finalize.d.ts +58 -0
  23. package/dist/wirings/ai-agent/ai-agent-finalize.js +138 -0
  24. package/dist/wirings/ai-agent/ai-agent-interrupt.js +1 -0
  25. package/dist/wirings/ai-agent/ai-agent-memory.d.ts +2 -8
  26. package/dist/wirings/ai-agent/ai-agent-memory.js +34 -17
  27. package/dist/wirings/ai-agent/ai-agent-model-config.d.ts +7 -0
  28. package/dist/wirings/ai-agent/ai-agent-model-config.js +44 -1
  29. package/dist/wirings/ai-agent/ai-agent-prepare.js +4 -0
  30. package/dist/wirings/ai-agent/ai-agent-runner.js +61 -40
  31. package/dist/wirings/ai-agent/ai-agent-stream.js +89 -36
  32. package/dist/wirings/ai-agent/ai-agent-turn.d.ts +1 -0
  33. package/dist/wirings/ai-agent/ai-agent-turn.js +1 -0
  34. package/dist/wirings/ai-agent/ai-agent.types.d.ts +46 -1
  35. package/dist/wirings/ai-agent/index.d.ts +8 -7
  36. package/dist/wirings/ai-agent/index.js +5 -4
  37. package/dist/wirings/ai-scorer/ai-scorer-grade.d.ts +26 -0
  38. package/dist/wirings/ai-scorer/ai-scorer-grade.js +33 -0
  39. package/dist/wirings/ai-scorer/ai-scorer-judge.d.ts +17 -0
  40. package/dist/wirings/ai-scorer/ai-scorer-judge.js +92 -0
  41. package/dist/wirings/ai-scorer/ai-scorer-live.d.ts +15 -0
  42. package/dist/wirings/ai-scorer/ai-scorer-live.js +38 -0
  43. package/dist/wirings/ai-scorer/ai-scorer-registry.d.ts +18 -0
  44. package/dist/wirings/ai-scorer/ai-scorer-registry.js +46 -0
  45. package/dist/wirings/ai-scorer/ai-scorer-sampling.d.ts +8 -0
  46. package/dist/wirings/ai-scorer/ai-scorer-sampling.js +31 -0
  47. package/dist/wirings/ai-scorer/ai-scorer-snapshots.d.ts +10 -0
  48. package/dist/wirings/ai-scorer/ai-scorer-snapshots.js +40 -0
  49. package/dist/wirings/ai-scorer/ai-scorer-worker.d.ts +15 -0
  50. package/dist/wirings/ai-scorer/ai-scorer-worker.js +58 -0
  51. package/dist/wirings/ai-scorer/ai-scorer.d.ts +39 -0
  52. package/dist/wirings/ai-scorer/ai-scorer.js +40 -0
  53. package/dist/wirings/ai-scorer/ai-scorer.types.d.ts +90 -0
  54. package/dist/wirings/ai-scorer/ai-scorer.types.js +4 -0
  55. package/dist/wirings/ai-scorer/index.d.ts +6 -0
  56. package/dist/wirings/ai-scorer/index.js +5 -0
  57. package/dist/wirings/channel/index.d.ts +5 -6
  58. package/dist/wirings/channel/index.js +3 -4
  59. package/dist/wirings/channel/local/local-channel-runner.js +8 -1
  60. package/dist/wirings/cli/channel/cli-raw-channel-runner.js +9 -1
  61. package/dist/wirings/cli/channel/index.d.ts +1 -2
  62. package/dist/wirings/cli/channel/index.js +0 -1
  63. package/dist/wirings/cli/cli-runner.js +13 -1
  64. package/dist/wirings/credential/index.d.ts +1 -1
  65. package/dist/wirings/gateway/index.d.ts +1 -1
  66. package/dist/wirings/http/http-runner.js +8 -2
  67. package/dist/wirings/http/index.d.ts +1 -2
  68. package/dist/wirings/mcp/index.d.ts +1 -1
  69. package/dist/wirings/mcp/mcp-runner.d.ts +15 -0
  70. package/dist/wirings/mcp/mcp-runner.js +18 -5
  71. package/dist/wirings/persona/index.d.ts +3 -4
  72. package/dist/wirings/persona/index.js +2 -3
  73. package/dist/wirings/queue/index.d.ts +1 -3
  74. package/dist/wirings/queue/index.js +1 -3
  75. package/dist/wirings/rpc/addon-runner.d.ts +8 -0
  76. package/dist/wirings/rpc/addon-runner.js +31 -3
  77. package/dist/wirings/rpc/rpc-runner.js +4 -0
  78. package/dist/wirings/rpc/rpc-types.d.ts +8 -0
  79. package/dist/wirings/rpc/wire-addon.d.ts +25 -0
  80. package/dist/wirings/rpc/wire-addon.js +8 -0
  81. package/dist/wirings/scheduler/index.d.ts +1 -1
  82. package/dist/wirings/trigger/index.d.ts +1 -1
  83. package/dist/wirings/virtual-user/index.d.ts +5 -6
  84. package/dist/wirings/virtual-user/index.js +2 -4
  85. package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +85 -15
  86. package/dist/wirings/workflow/feature.d.ts +2 -1
  87. package/dist/wirings/workflow/index.d.ts +5 -16
  88. package/dist/wirings/workflow/index.js +1 -9
  89. package/dist/wirings/workflow/pikku-scenario-service.d.ts +17 -7
  90. package/dist/wirings/workflow/pikku-scenario-service.js +48 -13
  91. package/dist/wirings/workflow/pikku-workflow-service.js +17 -3
  92. package/dist/wirings/workflow/scenario-step.types.d.ts +8 -0
  93. package/dist/wirings/workflow/scenario.types.d.ts +37 -0
  94. package/dist/wirings/workflow/workflow-approval-audit.d.ts +16 -0
  95. package/dist/wirings/workflow/workflow-approval-audit.js +40 -0
  96. package/dist/wirings/workflow/workflow-approval-policy.d.ts +20 -0
  97. package/dist/wirings/workflow/workflow-approval-policy.js +48 -0
  98. package/dist/wirings/workflow/workflow-approval.d.ts +29 -1
  99. package/dist/wirings/workflow/workflow-approval.js +65 -2
  100. package/dist/wirings/workflow/workflow-run-ownership.d.ts +2 -1
  101. package/dist/wirings/workflow/workflow-run-ownership.js +2 -1
  102. package/dist/wirings/workflow/workflow.types.d.ts +2 -37
  103. package/knowledge/decisions/internals/addon-pikku-meta-ships-at-the-package-root-or-under-dist.md +32 -0
  104. package/knowledge/decisions/internals/an-addon-scope-root-loses-to-a-root-the-host-already-declares.md +39 -0
  105. package/knowledge/decisions/internals/index.md +30 -3
  106. package/knowledge/decisions/internals/validate-runs-checks-by-precondition.md +115 -0
  107. package/knowledge/decisions/security/a-function-never-receives-the-secret-service.md +37 -0
  108. package/knowledge/decisions/security/a-workflow-run-is-read-and-approved-by-its-owner.md +30 -14
  109. package/knowledge/decisions/security/an-approval-answer-outlives-the-run-it-answered.md +59 -0
  110. package/knowledge/decisions/security/index.md +3 -1
  111. package/knowledge/questions/index.md +1 -1
  112. package/package.json +3 -2
  113. package/scripts/generate-api-report.mts +143 -18
  114. package/src/api-report.test.ts +2 -2
  115. package/src/errors/index.ts +1 -1
  116. package/src/function/function-runner.test.ts +52 -0
  117. package/src/function/function-runner.ts +5 -9
  118. package/src/function/index.ts +0 -2
  119. package/src/index.ts +0 -35
  120. package/src/pikku-state.ts +5 -0
  121. package/src/public-surface.json +81 -118
  122. package/src/services/ai-agent-runner-service.ts +12 -1
  123. package/src/services/ai-run-state-service.ts +11 -0
  124. package/src/services/in-memory-ai-run-state-service.ts +13 -0
  125. package/src/services/index.ts +7 -58
  126. package/src/services/meta-service.ts +2 -4
  127. package/src/services/scoped-credential-service.test.ts +86 -0
  128. package/src/services/scoped-credential-service.ts +63 -0
  129. package/src/testing/service-tests/ai-storage-service-tests.ts +93 -0
  130. package/src/types/core.types.ts +4 -7
  131. package/src/types/state.types.ts +21 -1
  132. package/src/wirings/actor-flow/index.ts +0 -3
  133. package/src/wirings/ai-agent/ai-agent-finalize.test.ts +186 -0
  134. package/src/wirings/ai-agent/ai-agent-finalize.ts +197 -0
  135. package/src/wirings/ai-agent/ai-agent-interrupt.ts +1 -0
  136. package/src/wirings/ai-agent/ai-agent-memory.ts +54 -38
  137. package/src/wirings/ai-agent/ai-agent-model-config.test.ts +72 -3
  138. package/src/wirings/ai-agent/ai-agent-model-config.ts +49 -1
  139. package/src/wirings/ai-agent/ai-agent-prepare.ts +4 -0
  140. package/src/wirings/ai-agent/ai-agent-runner.ts +71 -40
  141. package/src/wirings/ai-agent/ai-agent-stream-output-hooks.test.ts +353 -0
  142. package/src/wirings/ai-agent/ai-agent-stream.ts +116 -54
  143. package/src/wirings/ai-agent/ai-agent-turn.test.ts +67 -0
  144. package/src/wirings/ai-agent/ai-agent-turn.ts +1 -0
  145. package/src/wirings/ai-agent/ai-agent.types.ts +64 -4
  146. package/src/wirings/ai-agent/index.ts +2 -16
  147. package/src/wirings/ai-scorer/ai-scorer-grade.test.ts +106 -0
  148. package/src/wirings/ai-scorer/ai-scorer-grade.ts +55 -0
  149. package/src/wirings/ai-scorer/ai-scorer-judge.test.ts +143 -0
  150. package/src/wirings/ai-scorer/ai-scorer-judge.ts +120 -0
  151. package/src/wirings/ai-scorer/ai-scorer-live.test.ts +174 -0
  152. package/src/wirings/ai-scorer/ai-scorer-live.ts +56 -0
  153. package/src/wirings/ai-scorer/ai-scorer-registry.ts +63 -0
  154. package/src/wirings/ai-scorer/ai-scorer-sampling.test.ts +34 -0
  155. package/src/wirings/ai-scorer/ai-scorer-sampling.ts +36 -0
  156. package/src/wirings/ai-scorer/ai-scorer-snapshots.test.ts +49 -0
  157. package/src/wirings/ai-scorer/ai-scorer-snapshots.ts +46 -0
  158. package/src/wirings/ai-scorer/ai-scorer-worker.test.ts +122 -0
  159. package/src/wirings/ai-scorer/ai-scorer-worker.ts +69 -0
  160. package/src/wirings/ai-scorer/ai-scorer.ts +76 -0
  161. package/src/wirings/ai-scorer/ai-scorer.types.ts +107 -0
  162. package/src/wirings/ai-scorer/index.ts +24 -0
  163. package/src/wirings/channel/index.ts +1 -20
  164. package/src/wirings/channel/local/local-channel-runner.test.ts +68 -0
  165. package/src/wirings/channel/local/local-channel-runner.ts +8 -1
  166. package/src/wirings/cli/channel/cli-raw-channel-runner.test.ts +23 -0
  167. package/src/wirings/cli/channel/cli-raw-channel-runner.ts +12 -1
  168. package/src/wirings/cli/channel/index.ts +0 -7
  169. package/src/wirings/cli/cli-runner.test.ts +68 -0
  170. package/src/wirings/cli/cli-runner.ts +18 -1
  171. package/src/wirings/credential/index.ts +0 -1
  172. package/src/wirings/gateway/index.ts +0 -3
  173. package/src/wirings/http/http-runner.test.ts +66 -0
  174. package/src/wirings/http/http-runner.ts +10 -2
  175. package/src/wirings/http/index.ts +1 -1
  176. package/src/wirings/mcp/index.ts +0 -1
  177. package/src/wirings/mcp/mcp-runner.test.ts +181 -0
  178. package/src/wirings/mcp/mcp-runner.ts +35 -5
  179. package/src/wirings/persona/index.ts +0 -8
  180. package/src/wirings/queue/index.ts +0 -14
  181. package/src/wirings/rpc/addon-runner.ts +62 -3
  182. package/src/wirings/rpc/addon-secrets.test.ts +391 -0
  183. package/src/wirings/rpc/rpc-runner.test.ts +2 -0
  184. package/src/wirings/rpc/rpc-runner.ts +4 -0
  185. package/src/wirings/rpc/rpc-types.ts +8 -0
  186. package/src/wirings/rpc/wire-addon.ts +33 -0
  187. package/src/wirings/scheduler/index.ts +0 -1
  188. package/src/wirings/trigger/index.ts +0 -1
  189. package/src/wirings/virtual-user/index.ts +0 -16
  190. package/src/wirings/workflow/dsl/workflow-dsl.types.ts +96 -16
  191. package/src/wirings/workflow/feature.ts +2 -5
  192. package/src/wirings/workflow/graph/graph-runner.test.ts +72 -0
  193. package/src/wirings/workflow/index.ts +2 -68
  194. package/src/wirings/workflow/pikku-scenario-service.ts +81 -16
  195. package/src/wirings/workflow/pikku-workflow-service.test.ts +13 -12
  196. package/src/wirings/workflow/pikku-workflow-service.ts +28 -4
  197. package/src/wirings/workflow/scenario-expectations.test.ts +75 -0
  198. package/src/wirings/workflow/scenario-hooks.test.ts +3 -2
  199. package/src/wirings/workflow/scenario-step.types.ts +8 -0
  200. package/src/wirings/workflow/scenario.types.ts +63 -0
  201. package/src/wirings/workflow/workflow-approval-audit.ts +47 -0
  202. package/src/wirings/workflow/workflow-approval-policy.test.ts +524 -0
  203. package/src/wirings/workflow/workflow-approval-policy.ts +68 -0
  204. package/src/wirings/workflow/workflow-approval.ts +113 -9
  205. package/src/wirings/workflow/workflow-run-authority.test.ts +12 -15
  206. package/src/wirings/workflow/workflow-run-ownership.ts +2 -1
  207. package/src/wirings/workflow/workflow.types.ts +1 -63
  208. package/src/wirings-stay-decoupled.test.ts +6 -2
  209. package/tsconfig.tsbuildinfo +1 -1
  210. package/dist/internal.d.ts +0 -3
  211. package/dist/internal.js +0 -2
  212. package/dist/middleware/timeout.d.ts +0 -9
  213. package/dist/middleware/timeout.js +0 -15
  214. package/dist/pikku-response.d.ts +0 -6
  215. package/dist/pikku-response.js +0 -6
  216. package/dist/services/gopass-secrets.d.ts +0 -15
  217. package/dist/services/gopass-secrets.js +0 -76
  218. package/dist/services/http-scenario-actors.d.ts +0 -75
  219. package/dist/services/http-scenario-actors.js +0 -195
  220. package/dist/services/http-user-flow-actors.d.ts +0 -67
  221. package/dist/services/http-user-flow-actors.js +0 -193
  222. package/dist/services/scenario-actors-service.d.ts +0 -127
  223. package/dist/services/scenario-actors-service.js +0 -40
  224. package/dist/services/user-flow-actors-service.d.ts +0 -39
  225. package/dist/wirings/credential/wire-credential.d.ts +0 -48
  226. package/dist/wirings/credential/wire-credential.js +0 -47
  227. package/dist/wirings/oauth2/oauth2-client.d.ts +0 -47
  228. package/dist/wirings/oauth2/oauth2-client.js +0 -263
  229. package/dist/wirings/oauth2/oauth2-routes.d.ts +0 -35
  230. package/dist/wirings/oauth2/oauth2-routes.js +0 -146
  231. package/dist/wirings/scope/wire-scope.d.ts +0 -33
  232. package/dist/wirings/scope/wire-scope.js +0 -32
  233. package/dist/wirings/workflow/dsl/index.d.ts +0 -5
  234. package/dist/wirings/workflow/dsl/index.js +0 -4
  235. package/dist/wirings/workflow/graph/index.d.ts +0 -5
  236. package/dist/wirings/workflow/graph/index.js +0 -4
  237. /package/dist/{services/user-flow-actors-service.js → wirings/workflow/scenario.types.js} +0 -0
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  type: decision
3
- title: A workflow run is read and approved by its owner
4
- description: A run started through a session records that user and only that user may read it or answer its approval gates; a run with no recorded owner has no ownership to enforce
3
+ title: A workflow run is read by its owner, and answered by whoever its gate declares
4
+ description: A run started through a session records that user and only that user may read it; who may answer an approval gate is the gate's own declaration, and a run with no recorded owner has no ownership to enforce
5
5
  tags: workflow
6
6
  ---
7
7
 
8
- # A workflow run is read and approved by its owner
8
+ # A workflow run is read by its owner, and answered by whoever its gate declares
9
9
 
10
10
  `WorkflowRunWire.pikkuUserId` has always been recorded on every run started
11
11
  through a session — `RPCService.startWorkflow` copies it off the wire — and
@@ -14,9 +14,9 @@ routes (which stream `output` and `error`) and `approveStep`, which took no
14
14
  session at all and rejected only an already-resolved gate.
15
15
 
16
16
  `assertWorkflowRunOwner`
17
- (`packages/core/src/wirings/workflow/workflow-run-ownership.ts`) is the one check
18
- both paths share. `approveStep` takes the caller's session and asserts it, and
19
- the generated status routes assert it against the run they were already reading.
17
+ (`packages/core/src/wirings/workflow/workflow-run-ownership.ts`) is the check the
18
+ **read** paths share: the generated status routes assert it against the run they
19
+ were already reading.
20
20
 
21
21
  **A run with no recorded owner is not gated.** Triggers, schedulers and routes
22
22
  wired without auth start runs with no `pikkuUserId`; there is nobody to compare a
@@ -24,11 +24,27 @@ caller against, and inventing one would reject the framework's own callers rathe
24
24
  than secure anything. Gate those at the entrypoint with `auth` or `permissions`.
25
25
 
26
26
  This is ownership, not an approver model. It answers "is this your run", not "are
27
- you entitled to approve this particular gate" — `WorkflowApprovalOptions` still
28
- carries no approver, role or permission, and a second approver on someone else's
29
- run is still a matter for the route's own `permissions`.
30
-
31
- **What this rules out:** treating a run id as a capability, and adding a new run
32
- read path that does not take a session. It does not rule out a richer approver
33
- model on `WorkflowApprovalOptions` later; that would narrow this gate, never
34
- replace it.
27
+ you entitled to approve this particular gate".
28
+
29
+ ## Approving is a separate question, and the gate answers it
30
+
31
+ `approveStep` originally shared `assertWorkflowRunOwner`, which made "only the
32
+ initiator may answer" the one available rule. That is right for "confirm your own
33
+ action" and exactly wrong for four-eyes sign-off, where the initiator is the one
34
+ person who must not sign. Which applies is a property of the decision, so it is
35
+ declared on the gate — `approvers` (`'any' | 'owner' | 'not-initiator'`) and
36
+ `approverScope` on `WorkflowApprovalOptions`.
37
+
38
+ It is enforced wherever the policy is known. Reaching the gate publishes the
39
+ policy into the run state, so a decision submitted after that is judged by the
40
+ approve entrypoint and refused with a 403. A decision can legitimately be
41
+ recorded before the run has reached the gate, and that one has no policy to be
42
+ judged against yet — it is judged on replay instead, alongside payload
43
+ validation, and discarded if it fails.
44
+
45
+ The default is therefore `any`: a gate is a pause for a decision, not an
46
+ authorization boundary, and a route that needs one has `auth`/`permissions`.
47
+
48
+ **What this rules out:** treating a run id as a capability, adding a new run read
49
+ path that does not take a session, and re-deriving who may approve from who
50
+ started the run.
@@ -0,0 +1,59 @@
1
+ ---
2
+ type: decision
3
+ title: An approval answer outlives the run it answered
4
+ description: Run state holds a decision only while the gate is open, so the settled answer carries decidedBy/decidedAt into the step result and every attempt is written to the audit sink, which has no foreign key to the run
5
+ tags: workflow, audit
6
+ ---
7
+
8
+ # An approval answer outlives the run it answered
9
+
10
+ An approval gate is asked for so it can be answered for afterwards. "Who
11
+ released the funds" is the entire point of four-eyes sign-off, and until this
12
+ change none of it was kept.
13
+
14
+ Run state is where a decision *waits*, not where it is kept. The record under
15
+ `workflowRuns.state.__approval_<hex>` is overwritten by the next write to that
16
+ key, and cleared outright — `decidedBy: undefined` included — whenever a
17
+ decision is refused on replay. A trail that erases exactly the events worth
18
+ keeping is not a trail.
19
+
20
+ So the answer is recorded twice, in two places with different lifetimes.
21
+
22
+ ## The settled decision keeps its provenance
23
+
24
+ `ApprovalOutcome<T>` carries `decidedBy` and `decidedAt` alongside `data`, so
25
+ the answer reaches `workflowStep.result` and, through it,
26
+ `workflowStepHistory` — append-only, and already the per-step event log. Both
27
+ are spread in only when present, so a gate answered without a session keeps the
28
+ shape it had before there was anything to record.
29
+
30
+ ## The audit sink is what survives deletion
31
+
32
+ `deleteRun` cascades: `workflowStep` is `onDelete('cascade')` from
33
+ `workflowRuns`, and `workflowStepHistory` from `workflowStep`. Deleting a run
34
+ therefore deletes the sign-off with it — and a *refused* attempt never reaches a
35
+ step at all, so it was never in that trail to begin with.
36
+
37
+ Every answer — accepted, refused at submission, or cleared on replay — is
38
+ written to the `AuditService` as `workflow.approval.decided`, with
39
+ `outcome: 'success' | 'denied'`, the decider under `userIdentity.pikkuUserId`,
40
+ and the run, reason, scopes and refusal in `metadata`. The `audit` table holds
41
+ no foreign key to any workflow table, which is precisely why it is the right
42
+ home.
43
+
44
+ `auditApprovalDecision`
45
+ (`packages/core/src/wirings/workflow/workflow-approval-audit.ts`) is a module of
46
+ its own rather than a method on `PikkuWorkflowService`: the trail is a separate
47
+ concern from running the workflow, and the service is already at the 2000-line
48
+ limit `source-files-stay-composable.test.ts` enforces.
49
+
50
+ **A sink that fails is logged, never thrown.** The trail must not be the reason a
51
+ decision is lost. A project with no `audit` service wired records nothing and is
52
+ otherwise unaffected — the sink is opt-in, and `auditSchema` is deliberately not
53
+ in `pikkuSchemas`.
54
+
55
+ **What this rules out:** a dedicated `workflowApprovals` table. It would have to
56
+ be implemented in all seven backends and would still be deleted with the run
57
+ unless it deliberately broke the cascade — at which point it is the audit table
58
+ with extra steps. If approvals later need to be *queried* as a first-class
59
+ entity rather than read back from the trail, that is when to revisit.
@@ -10,11 +10,12 @@ A rule about who may do what, and which way it fails when it is unsure.
10
10
 
11
11
  <!-- pikku:knowledge-index -->
12
12
  - [A dropped audit write is always logged](a-dropped-audit-write-is-always-logged.md) — The no-op audit service falls back to the singleton logger when the wire carries none, so an unconfigured audit call is never silent
13
+ - [A function never receives the secret service](a-function-never-receives-the-secret-service.md) — Every function-, permission- and auth-facing services type is bounded by SecretlessServices, so reaching for `secrets` in a function body is a type error rather than a lint
13
14
  - [A graph run starts at an entry node the graph declared](a-graph-run-starts-at-an-entry-node-the-graph-declared.md) — startNode may only name a node in meta.entryNodeIds, and no generated route offers it, because otherwise a caller picks which half of the graph to skip
14
15
  - [A permission gets a wire it cannot reply on](a-permission-gets-a-wire-it-cannot-reply-on.md) — The permission wire is typed with Out = never so a permission cannot send on the channel; that narrowing is not a subtype, so the call site asserts
15
16
  - [A step runs the function the workflow dispatched it with](a-step-runs-the-function-the-workflow-dispatched-it-with.md) — StepState records the step's function name so the worker can reject a queue message naming a different one, because the step executes under the run owner's identity
16
17
  - [A virtual user is never offered a scenario, platform or addon step](a-virtual-user-is-never-offered-a-step-that-would-forge-its-own-oracle.md) — Being able to invoke "the webhook arrives" lets the user manufacture the outcome it exists to discover, which invalidates every finding downstream
17
- - [A workflow run is read and approved by its owner](a-workflow-run-is-read-and-approved-by-its-owner.md) — A run started through a session records that user and only that user may read it or answer its approval gates; a run with no recorded owner has no ownership to enforce
18
+ - [A workflow run is read by its owner, and answered by whoever its gate declares](a-workflow-run-is-read-and-approved-by-its-owner.md) — A run started through a session records that user and only that user may read it; who may answer an approval gate is the gate's own declaration, and a run with no recorded owner has no ownership to enforce
18
19
  - [An actor's missing approval decision defaults to denied](actor-flow-missing-approval-decisions-default-to-denied.md) — Every pending tool call gets an explicit decision; an id the persona LLM omitted is denied, so a dropped field can never read as consent
19
20
  - [Actor sign-in is proven by Set-Cookie, not a non-empty jar](actor-sign-in-is-proven-by-set-cookie-not-a-non-empty-jar.md) — HttpScenarioActor tracks its own signedIn flag and requires the sign-in response itself to set a cookie, because a populated jar proves nothing
20
21
  - [Actor sign-in only works for actor-flagged users](actor-sign-in-only-works-for-actor-flagged-users.md) — The scenario actor secret mints sessions for user rows flagged actor and nothing else, so holding it never impersonates a real user
@@ -30,6 +31,7 @@ A rule about who may do what, and which way it fails when it is unsure.
30
31
  - [An agent thread key is always prefixed with the trusted principal](ai-agent-thread-ownership-composes-the-session-principal.md) — Ownership keys are composed as principal:resourceId, so a client id can sub-divide its own boundary but never widen it
31
32
  - [Agent tool permission filtering reads the live function config, not the metadata](ai-agent-tool-filtering-reads-the-live-function-config.md) — The pikkuAuth brand survives only on live permission objects, so a metadata-driven check would silently admit every gated tool
32
33
  - [An agent approval is claimed before the tool runs](an-agent-approval-is-claimed-before-the-tool-runs.md) — resolveApproval is a compare-and-swap returning whether this caller won, because the read that precedes it is not a claim and ten concurrent approvals would otherwise mean ten refunds
34
+ - [An approval answer outlives the run it answered](an-approval-answer-outlives-the-run-it-answered.md) — Run state holds a decision only while the gate is open, so the settled answer carries decidedBy/decidedAt into the step result and every attempt is written to the audit sink, which has no foreign key to the run
33
35
  - [An empty owners constraint matches nothing](an-empty-owners-constraint-matches-nothing.md) — owners is an authorization boundary, so every storage backend must treat [] as no rows rather than no filter
34
36
  - [An exposed function with no gate is reported at codegen, not at boot](an-exposed-ungated-function-is-a-codegen-warning.md) — The check runs in the inspector where function meta and every wireAddon declaration are both in hand, because neither source alone can tell a gated function from an ungated one
35
37
  - [An upload is counted as it arrives, not buffered and then measured](an-upload-is-counted-as-it-arrives-not-buffered-then-measured.md) — Reading the whole body before checking its size hands an unauthenticated caller a way to spend the server's memory
@@ -12,5 +12,5 @@ gets recorded.
12
12
 
13
13
  <!-- pikku:knowledge-index -->
14
14
  - [A channel's middleware list accepts bare factories that nothing ever resolves](channel-middleware-accepts-bare-factories-that-nothing-resolves.md) — CoreChannel.channelMiddleware admits CorePikkuChannelMiddlewareFactory, but no runner calls one, so a bare factory would stall the chain
15
- - [An unauthorized channel reply is sent outside the channel's declared Out type](unauthorized-channel-replies-escape-the-declared-out-type.md) — processMessageHandlers sends a bare string on auth failure that no generated client type admits, and the alternatives were never worked through
15
+ - [An unauthorized channel reply is sent outside the channel's declared Out type](unauthorized-channel-replies-escape-the-declared-out-type.md) — processMessageHandlers sends a bare string on auth failure, which no generated client type admits nobody has decided what the typed shape should be
16
16
  <!-- /pikku:knowledge-index -->
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/core",
3
- "version": "0.12.80",
3
+ "version": "0.12.83",
4
4
  "description": "The Pikku runtime — functions, wirings, services, middleware and types",
5
5
  "author": "yasser.fadl@gmail.com",
6
6
  "license": "MIT",
@@ -22,6 +22,7 @@
22
22
  "./dist/errors/errors.js",
23
23
  "./dist/wirings/rpc/rpc-runner.js",
24
24
  "./dist/wirings/rpc/remote-addon-auth.js",
25
+ "./dist/wirings/workflow/workflow-approval-policy.js",
25
26
  "./dist/wirings/workflow/workflow-errors.js",
26
27
  "./dist/wirings/workflow/workflow-run-ownership.js",
27
28
  "./dist/wirings/workflow/pikku-scenario-service.js"
@@ -49,6 +50,7 @@
49
50
  "./node-host-resolver": "./dist/utils/node-host-resolver.js",
50
51
  "./mcp": "./dist/wirings/mcp/index.js",
51
52
  "./ai-agent": "./dist/wirings/ai-agent/index.js",
53
+ "./ai-scorer": "./dist/wirings/ai-scorer/index.js",
52
54
  "./gateway": "./dist/wirings/gateway/index.js",
53
55
  "./cli": "./dist/wirings/cli/index.js",
54
56
  "./cli/command-parser": "./dist/wirings/cli/command-parser.js",
@@ -72,7 +74,6 @@
72
74
  "./crypto-utils": "./dist/crypto-utils.js",
73
75
  "./hmac": "./dist/utils/hmac.js",
74
76
  "./ecosystem": "./dist/ecosystem.js",
75
- "./internal": "./dist/ecosystem.js",
76
77
  "./schema": "./dist/schema.js",
77
78
  "./testing": "./dist/testing/index.js",
78
79
  "./dev": "./dist/dev/hot-reload.js"
@@ -16,6 +16,10 @@
16
16
  * disagree — so a member-level change is a reviewable diff rather than a
17
17
  * surprise in someone else's CI.
18
18
  *
19
+ * A member per line, and no member bodies. Both are load-bearing rather than
20
+ * cosmetic: the report exists to be diffed, and a class emitted as one long
21
+ * line of its own source is neither reviewable nor mergeable.
22
+ *
19
23
  * Run: yarn api-report
20
24
  */
21
25
  import { readFileSync, writeFileSync } from 'node:fs'
@@ -50,7 +54,132 @@ const program = ts.createProgram(
50
54
  )
51
55
  const checker = program.getTypeChecker()
52
56
 
53
- /** One line per symbol: how it is declared, flattened and stripped of noise. */
57
+ /** Comments are noise in a report the diff is read for. */
58
+ const stripComments = (text: string): string =>
59
+ text.replace(/\/\*[\s\S]*?\*\//g, '').replace(/\/\/[^\n]*/g, '')
60
+
61
+ /**
62
+ * Punctuation that makes a line and its successor one thing.
63
+ *
64
+ * Read from both ends rather than one, because the closers are ambiguous from
65
+ * behind: `string[]`, `Promise<T>` and `= {}` all end in a closing bracket and
66
+ * none of them is a continuation. What the *next* line starts with is not.
67
+ */
68
+ const CONTINUES = /(=>|[,;{([<|&=])$/
69
+ const CLOSES = /^(=>|extends\b|[}\])>,;|&])/
70
+
71
+ /**
72
+ * A member's own text on one line — long, but never long enough to matter.
73
+ *
74
+ * Inside an object type the author's newline *was* the separator, so collapsing
75
+ * without restoring it produces `{ a: string b: number }`, which is not the
76
+ * type it describes and does not parse in the ```ts fence it is printed into.
77
+ */
78
+ const oneLine = (text: string): string => {
79
+ const lines = stripComments(text)
80
+ .split('\n')
81
+ .map((l) => l.trim())
82
+ .filter(Boolean)
83
+ let depth = 0
84
+ const joined = lines
85
+ .map((line, index) => {
86
+ const inObjectType = depth > 0
87
+ for (const character of line) {
88
+ if (character === '{') depth++
89
+ else if (character === '}') depth--
90
+ }
91
+ const next = lines[index + 1]
92
+ return inObjectType &&
93
+ next !== undefined &&
94
+ !CONTINUES.test(line) &&
95
+ !CLOSES.test(next)
96
+ ? `${line};`
97
+ : line
98
+ })
99
+ .join(' ')
100
+ return joined.replace(/\(\s+/g, '(').replace(/\s+\)/g, ')')
101
+ }
102
+
103
+ /**
104
+ * A class member as a consumer sees it: the signature, and nothing after it.
105
+ *
106
+ * The body is where every character of this report used to come from — a class
107
+ * arrived as its own source, so the report promised implementation details and
108
+ * a one-word change to a method rewrote the whole declaration. Truncating at
109
+ * the body leaves exactly the part a compatibility promise covers.
110
+ */
111
+ const memberSignature = (member: ts.ClassElement | ts.TypeElement): string => {
112
+ const source = member.getSourceFile().text
113
+ const start = member.getStart()
114
+
115
+ const body = (member as { body?: ts.Node }).body
116
+ if (body) {
117
+ const head = oneLine(source.slice(start, body.getStart())).replace(
118
+ /\s*$/,
119
+ ''
120
+ )
121
+ // An inferred return type is still a return type a consumer depends on, and
122
+ // truncating at the body is what threw the author's away.
123
+ if (ts.isMethodDeclaration(member) || ts.isGetAccessorDeclaration(member)) {
124
+ const signature = member.type
125
+ ? undefined
126
+ : checker.getSignatureFromDeclaration(member)
127
+ if (signature) {
128
+ const returns = checker.getReturnTypeOfSignature(signature)
129
+ return `${head}: ${checker.typeToString(returns, undefined, ts.TypeFormatFlags.NoTruncation)}`
130
+ }
131
+ }
132
+ return head
133
+ }
134
+
135
+ // A property's initializer is a body by another name. Its annotation stands in
136
+ // for it, and the checker supplies one when the author left it inferred.
137
+ if (ts.isPropertyDeclaration(member) && member.initializer) {
138
+ if (member.type) return oneLine(source.slice(start, member.type.end))
139
+ const type = checker.getTypeAtLocation(member)
140
+ return `${oneLine(source.slice(start, member.name.end))}: ${checker.typeToString(type, undefined, ts.TypeFormatFlags.NoTruncation)}`
141
+ }
142
+
143
+ return oneLine(member.getText())
144
+ }
145
+
146
+ /** Members a consumer can reach, so a private field is not a promise. */
147
+ const isPublic = (member: ts.ClassElement | ts.TypeElement): boolean =>
148
+ !(ts.getModifiers(member as ts.HasModifiers) ?? []).some(
149
+ (modifier) => modifier.kind === ts.SyntaxKind.PrivateKeyword
150
+ ) && !(member.name && ts.isPrivateIdentifier(member.name))
151
+
152
+ /**
153
+ * A declaration with members, one member per line.
154
+ *
155
+ * The line break is the point. Two branches that touch different methods of the
156
+ * same class are a textual conflict when the class is one line and an ordinary
157
+ * merge when it is not, which is a tax the whole repo was paying: every rebase
158
+ * over this file stopped to re-resolve a forty-thousand-character line by hand.
159
+ */
160
+ const membered = (
161
+ declaration:
162
+ | ts.ClassDeclaration
163
+ | ts.InterfaceDeclaration
164
+ | ts.EnumDeclaration,
165
+ members: ts.NodeArray<ts.ClassElement | ts.TypeElement | ts.EnumMember>
166
+ ): string => {
167
+ if (members.length === 0) return oneLine(declaration.getText())
168
+ const source = declaration.getSourceFile().text
169
+ // `members.pos` is the offset just past the `{`, so the header comes with its
170
+ // own brace and needs no reassembling.
171
+ const header = oneLine(source.slice(declaration.getStart(), members.pos))
172
+ const lines = ts.isEnumDeclaration(declaration)
173
+ ? (members as readonly ts.EnumMember[]).map(
174
+ (member) => `${oneLine(member.getText())},`
175
+ )
176
+ : (members as readonly (ts.ClassElement | ts.TypeElement)[])
177
+ .filter(isPublic)
178
+ .map(memberSignature)
179
+ return [header, ...lines.map((line) => ` ${line}`), '}'].join('\n')
180
+ }
181
+
182
+ /** How a symbol is declared, in as many lines as its members need. */
54
183
  const signature = (exported: ts.Symbol): string => {
55
184
  // A re-export is an alias; the declaration that matters is the target's, so
56
185
  // an interface re-exported through a barrel still reports its members.
@@ -62,20 +191,21 @@ const signature = (exported: ts.Symbol): string => {
62
191
  if (!declaration) return exported.getName()
63
192
 
64
193
  if (
65
- ts.isInterfaceDeclaration(declaration) ||
66
194
  ts.isClassDeclaration(declaration) ||
67
- ts.isTypeAliasDeclaration(declaration) ||
195
+ ts.isInterfaceDeclaration(declaration) ||
68
196
  ts.isEnumDeclaration(declaration)
69
197
  ) {
70
- // The declaration itself, so member changes show up in the diff.
71
- return declaration
72
- .getText()
73
- .replace(/\/\*\*[\s\S]*?\*\//g, '')
74
- .replace(/\/\/[^\n]*/g, '')
198
+ return membered(declaration, declaration.members)
199
+ }
200
+
201
+ if (ts.isTypeAliasDeclaration(declaration)) {
202
+ // No members to walk, so the author's own line breaks are the ones that
203
+ // keep a long union reviewable.
204
+ return stripComments(declaration.getText())
75
205
  .split('\n')
76
- .map((l) => l.trim())
77
- .filter(Boolean)
78
- .join(' ')
206
+ .map((l) => l.trimEnd())
207
+ .filter((l) => l.trim())
208
+ .join('\n')
79
209
  }
80
210
 
81
211
  const type = checker.getTypeOfSymbolAtLocation(symbol, declaration)
@@ -92,17 +222,12 @@ const ECOSYSTEM_SUBPATHS = new Set(['./ecosystem', './internal'])
92
222
 
93
223
  type Exported = { name: string; members: number; signature: string }
94
224
 
95
- /** Members a consumer can reach, so a private field is not a promise. */
225
+ /** The members the report lists, which is what the tally is counting. */
96
226
  const memberCount = (declaration: ts.Declaration): number => {
97
227
  if (ts.isInterfaceDeclaration(declaration)) return declaration.members.length
98
228
  if (ts.isEnumDeclaration(declaration)) return declaration.members.length
99
229
  if (!ts.isClassDeclaration(declaration)) return 0
100
- return declaration.members.filter(
101
- (member) =>
102
- !(ts.getModifiers(member) ?? []).some(
103
- (modifier) => modifier.kind === ts.SyntaxKind.PrivateKeyword
104
- ) && !(member.name && ts.isPrivateIdentifier(member.name))
105
- ).length
230
+ return declaration.members.filter(isPublic).length
106
231
  }
107
232
 
108
233
  const modules = new Map<string, Exported[]>()
@@ -1,7 +1,7 @@
1
1
  import { describe, test } from 'node:test'
2
2
  import assert from 'node:assert/strict'
3
3
  import { execFileSync } from 'node:child_process'
4
- import { readFileSync } from 'node:fs'
4
+ import { readFileSync, writeFileSync } from 'node:fs'
5
5
  import { fileURLToPath } from 'node:url'
6
6
  import { join, dirname } from 'node:path'
7
7
 
@@ -39,7 +39,7 @@ describe('the API report matches the code', () => {
39
39
  const firstDiff = regeneratedLines.findIndex(
40
40
  (line, i) => line !== committedLines[i]
41
41
  )
42
- require('node:fs').writeFileSync(reportPath, committed)
42
+ writeFileSync(reportPath, committed)
43
43
 
44
44
  assert.fail(
45
45
  'the public API changed but api-report.md was not regenerated.\n' +
@@ -1,2 +1,2 @@
1
1
  export * from './errors.js'
2
- export { PikkuError, addError, addErrors } from './error-handler.js'
2
+ export { PikkuError, addError } from './error-handler.js'
@@ -14,6 +14,7 @@ import type { CorePermissionGroup } from './functions.types.js'
14
14
  import { PikkuSessionService } from '../services/user-session-service.js'
15
15
  import { MissingScopeError, ReadonlySessionError } from '../errors/errors.js'
16
16
  import { createInvocationAudit } from '../services/audit-service.js'
17
+ import { SecretAccessDeniedError } from '../services/secretless.js'
17
18
 
18
19
  beforeEach(() => {
19
20
  resetPikkuState()
@@ -1563,3 +1564,54 @@ describe('runPikkuFunc - scopes', () => {
1563
1564
  })
1564
1565
  })
1565
1566
  })
1567
+
1568
+ describe('runPikkuFunc - secrets', () => {
1569
+ const singletonServicesWithSecrets = {
1570
+ ...mockSingletonServices,
1571
+ secrets: { getSecret: async () => 'super-secret' },
1572
+ } as any
1573
+
1574
+ const addSecretReadingFunction = (
1575
+ funcName: string,
1576
+ seen: { error?: unknown }
1577
+ ) => {
1578
+ addTestFunction(funcName, {
1579
+ func: async (services: any) => {
1580
+ try {
1581
+ return services.secrets
1582
+ } catch (error) {
1583
+ seen.error = error
1584
+ return 'denied'
1585
+ }
1586
+ },
1587
+ })
1588
+ }
1589
+
1590
+ const run = (funcName: string) =>
1591
+ runPikkuFunc('rpc', Math.random().toString(), funcName, {
1592
+ singletonServices: singletonServicesWithSecrets,
1593
+ getAllServices: () => singletonServicesWithSecrets,
1594
+ data: () => ({}),
1595
+ auth: false,
1596
+ wire: {},
1597
+ })
1598
+
1599
+ test('a function never receives the secrets service', async () => {
1600
+ const seen: { error?: unknown } = {}
1601
+ addSecretReadingFunction('readsSecrets', seen)
1602
+
1603
+ assert.equal(await run('readsSecrets'), 'denied')
1604
+ assert.ok(seen.error instanceof SecretAccessDeniedError)
1605
+ })
1606
+
1607
+ test('no metadata flag can restore the secrets service', async () => {
1608
+ const seen: { error?: unknown } = {}
1609
+ addSecretReadingFunction('claimsAnExemption', seen)
1610
+ Object.assign(pikkuState(null, 'function', 'meta')['claimsAnExemption']!, {
1611
+ secretBroker: true,
1612
+ })
1613
+
1614
+ assert.equal(await run('claimsAnExemption'), 'denied')
1615
+ assert.ok(seen.error instanceof SecretAccessDeniedError)
1616
+ })
1617
+ })
@@ -177,8 +177,6 @@ export const runPikkuFunc = async <In = any, Out = any>(
177
177
 
178
178
  const resolvedFunctionId = funcMeta.pikkuFuncId ?? funcName
179
179
 
180
- const keepsSecrets = funcMeta.secretBroker === true
181
-
182
180
  const resolvedSingletonServices = packageName
183
181
  ? await getOrCreatePackageSingletonServices(
184
182
  packageName,
@@ -363,12 +361,10 @@ export const runPikkuFunc = async <In = any, Out = any>(
363
361
 
364
362
  await runPermissions({
365
363
  funcPermissions: funcConfig.permissions,
366
- services: keepsSecrets
367
- ? resolvedSingletonServices
368
- : (withoutSecrets(
369
- resolvedSingletonServices,
370
- 'a permission'
371
- ) as CoreSingletonServices),
364
+ services: withoutSecrets(
365
+ resolvedSingletonServices,
366
+ 'a permission'
367
+ ) as CoreSingletonServices,
372
368
  // knowledge: decisions/security/a-permission-gets-a-wire-it-cannot-reply-on.md
373
369
  wire: invocationWire as PermissionWire,
374
370
  data: actualData,
@@ -420,7 +416,7 @@ export const runPikkuFunc = async <In = any, Out = any>(
420
416
  enumerable: true,
421
417
  })
422
418
  return await funcConfig.func(
423
- keepsSecrets ? services : withoutSecrets(services, 'a pikku function'),
419
+ withoutSecrets(services, 'a pikku function'),
424
420
  actualData,
425
421
  invocationWire
426
422
  )
@@ -18,6 +18,4 @@ export type {
18
18
  ListInput,
19
19
  ListOutput,
20
20
  Filter,
21
- LeafFilter,
22
- LeafValue,
23
21
  } from './list.types.js'
package/src/index.ts CHANGED
@@ -17,12 +17,10 @@ export type {
17
17
  CreateConfig,
18
18
  ServerLifecycle,
19
19
  FunctionMeta,
20
- FunctionRuntimeMeta,
21
20
  FunctionServicesMeta,
22
21
  FunctionWiresMeta,
23
22
  FunctionsMeta,
24
23
  FunctionsRuntimeMeta,
25
- JSONPrimitive,
26
24
  JSONValue,
27
25
  MakeRequired,
28
26
  MiddlewareMetadata,
@@ -43,7 +41,6 @@ export type {
43
41
  SecuritySeverity,
44
42
  SecurityUpdateLevel,
45
43
  SerializedError,
46
- WireServices,
47
44
  } from './types/core.types.js'
48
45
  export {
49
46
  pikkuAIMiddleware,
@@ -57,7 +54,6 @@ export type {
57
54
  CorePikkuAuthConfig,
58
55
  CorePikkuFunction,
59
56
  CorePikkuFunctionConfig,
60
- CorePikkuFunctionHook,
61
57
  CorePikkuPermission,
62
58
  CorePikkuPermissionConfig,
63
59
  CorePikkuPermissionFactory,
@@ -75,8 +71,6 @@ export type {
75
71
  ListInput,
76
72
  ListOutput,
77
73
  Filter,
78
- LeafFilter,
79
- LeafValue,
80
74
  } from './function/list.types.js'
81
75
  export { pikkuCLIRender } from './wirings/cli/cli-runner.js'
82
76
  export { PikkuRequest } from './pikku-request.js'
@@ -92,9 +86,6 @@ export {
92
86
  } from './version.js'
93
87
  export {
94
88
  AbandonedError,
95
- beginChanges,
96
- getAbortScope,
97
- runInAbortScope,
98
89
  type AbortScope,
99
90
  } from './function/abort-scope.js'
100
91
  export { fetch } from './wirings/http/http-runner.js'
@@ -152,7 +143,6 @@ export type { QueueService } from './wirings/queue/queue.types.js'
152
143
  export type { JWTService } from './services/jwt-service.js'
153
144
  export type {
154
145
  EmailService,
155
- EmailTemplateReference,
156
146
  SendEmailInput,
157
147
  SendEmailResult,
158
148
  SendHTMLEmailInput,
@@ -188,8 +178,6 @@ export type { SessionService } from './services/user-session-service.js'
188
178
  export {
189
179
  NoopAuditService,
190
180
  createInvocationAudit,
191
- resolveAuditConfig,
192
- resolveAuditUserIdentityFromWire,
193
181
  } from './services/audit-service.js'
194
182
  export type {
195
183
  AuditConfig,
@@ -198,31 +186,14 @@ export type {
198
186
  AuditEventBatch,
199
187
  AuditFacets,
200
188
  AuditLog,
201
- AuditLogWriteInput,
202
- AuditOutcome,
203
189
  AuditQuery,
204
190
  AuditQueryResult,
205
191
  AuditService,
206
- AuditSource,
207
192
  AuditUserIdentity,
208
193
  ResolvedAuditConfig,
209
194
  } from './services/audit-service.js'
210
195
  export type {
211
196
  AIAgentRunnerService,
212
- AIEmbedManyParams,
213
- AIEmbedManyResult,
214
- AIEmbedParams,
215
- AIEmbedResult,
216
- AIGenerateImageParams,
217
- AIGenerateImagePrompt,
218
- AIGenerateImageResult,
219
- AIGenerateSpeechParams,
220
- AIGenerateSpeechResult,
221
- AIProviderOptions,
222
- AIRerankParams,
223
- AIRerankResult,
224
- AITranscriptionParams,
225
- AITranscriptionResult,
226
197
  } from './services/ai-agent-runner-service.js'
227
198
  export type { AIEmbeddingService } from './services/ai-embedding-service.js'
228
199
  export type { AIRunStateService } from './services/ai-run-state-service.js'
@@ -230,8 +201,6 @@ export type { AIStorageService } from './services/ai-storage-service.js'
230
201
  export type {
231
202
  EmailsMeta,
232
203
  EmailTemplateMeta,
233
- EmailTemplateLocaleMeta,
234
- EmailTemplateAssets,
235
204
  MetaService,
236
205
  } from './services/meta-service.js'
237
206
  export type { HTTPMethod } from './wirings/http/http.types.js'
@@ -266,7 +235,6 @@ export type {
266
235
  Secret,
267
236
  Classification,
268
237
  AnonymizeStrategy,
269
- ColumnClassification,
270
238
  ClassificationManifest,
271
239
  ColumnForm,
272
240
  WrappedValue,
@@ -276,9 +244,6 @@ export type {
276
244
 
277
245
  export {
278
246
  hashToken,
279
- unsafeAsWrapped,
280
- unsafeAsSealed,
281
- unsafeAsHashed,
282
247
  } from './column-form.js'
283
248
 
284
249
  export type { SecretValue, Safe } from './secret-value.js'
@@ -10,6 +10,7 @@ import type {
10
10
  MCPPromptMeta,
11
11
  } from './wirings/mcp/mcp.types.js'
12
12
  import type { AIAgentMeta } from './wirings/ai-agent/ai-agent.types.js'
13
+ import type { ScorerMeta } from './wirings/ai-scorer/ai-scorer.types.js'
13
14
  import type { GatewaysMeta } from './wirings/gateway/gateway.types.js'
14
15
  import type { ScheduledTasksMeta } from './wirings/scheduler/scheduler.types.js'
15
16
  import type { TriggerMeta } from './wirings/trigger/trigger.types.js'
@@ -118,6 +119,9 @@ const createEmptyPackageState = (): PikkuPackageState => ({
118
119
  agent: {
119
120
  agents: new Map(),
120
121
  agentsMeta: {} as AIAgentMeta,
122
+ scorers: new Map(),
123
+ scorersMeta: {} as ScorerMeta,
124
+ modelAliases: {},
121
125
  },
122
126
  gateway: {
123
127
  gateways: new Map(),
@@ -151,6 +155,7 @@ const createEmptyPackageState = (): PikkuPackageState => ({
151
155
  authFactory: null,
152
156
  credentialsMeta: null,
153
157
  requiredParentServices: null,
158
+ declaredSecrets: null,
154
159
  },
155
160
  })
156
161