@pikku/core 0.12.80 → 0.12.82

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 (231) hide show
  1. package/CHANGELOG.md +312 -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 -15
  14. package/dist/services/index.js +5 -5
  15. package/dist/services/scoped-credential-service.d.ts +21 -0
  16. package/dist/services/scoped-credential-service.js +53 -0
  17. package/dist/testing/service-tests/ai-storage-service-tests.js +76 -0
  18. package/dist/types/core.types.d.ts +0 -2
  19. package/dist/types/state.types.d.ts +13 -0
  20. package/dist/wirings/actor-flow/index.d.ts +1 -1
  21. package/dist/wirings/ai-agent/ai-agent-finalize.d.ts +58 -0
  22. package/dist/wirings/ai-agent/ai-agent-finalize.js +138 -0
  23. package/dist/wirings/ai-agent/ai-agent-interrupt.js +1 -0
  24. package/dist/wirings/ai-agent/ai-agent-memory.d.ts +2 -8
  25. package/dist/wirings/ai-agent/ai-agent-memory.js +34 -17
  26. package/dist/wirings/ai-agent/ai-agent-model-config.d.ts +7 -0
  27. package/dist/wirings/ai-agent/ai-agent-model-config.js +44 -1
  28. package/dist/wirings/ai-agent/ai-agent-prepare.js +2 -0
  29. package/dist/wirings/ai-agent/ai-agent-runner.js +61 -40
  30. package/dist/wirings/ai-agent/ai-agent-stream.js +89 -36
  31. package/dist/wirings/ai-agent/ai-agent-turn.d.ts +1 -0
  32. package/dist/wirings/ai-agent/ai-agent-turn.js +1 -0
  33. package/dist/wirings/ai-agent/ai-agent.types.d.ts +46 -1
  34. package/dist/wirings/ai-agent/index.d.ts +8 -7
  35. package/dist/wirings/ai-agent/index.js +5 -4
  36. package/dist/wirings/ai-scorer/ai-scorer-grade.d.ts +26 -0
  37. package/dist/wirings/ai-scorer/ai-scorer-grade.js +33 -0
  38. package/dist/wirings/ai-scorer/ai-scorer-judge.d.ts +17 -0
  39. package/dist/wirings/ai-scorer/ai-scorer-judge.js +92 -0
  40. package/dist/wirings/ai-scorer/ai-scorer-live.d.ts +15 -0
  41. package/dist/wirings/ai-scorer/ai-scorer-live.js +38 -0
  42. package/dist/wirings/ai-scorer/ai-scorer-registry.d.ts +18 -0
  43. package/dist/wirings/ai-scorer/ai-scorer-registry.js +46 -0
  44. package/dist/wirings/ai-scorer/ai-scorer-sampling.d.ts +8 -0
  45. package/dist/wirings/ai-scorer/ai-scorer-sampling.js +31 -0
  46. package/dist/wirings/ai-scorer/ai-scorer-snapshots.d.ts +10 -0
  47. package/dist/wirings/ai-scorer/ai-scorer-snapshots.js +40 -0
  48. package/dist/wirings/ai-scorer/ai-scorer-worker.d.ts +15 -0
  49. package/dist/wirings/ai-scorer/ai-scorer-worker.js +58 -0
  50. package/dist/wirings/ai-scorer/ai-scorer.d.ts +39 -0
  51. package/dist/wirings/ai-scorer/ai-scorer.js +40 -0
  52. package/dist/wirings/ai-scorer/ai-scorer.types.d.ts +90 -0
  53. package/dist/wirings/ai-scorer/ai-scorer.types.js +4 -0
  54. package/dist/wirings/ai-scorer/index.d.ts +6 -0
  55. package/dist/wirings/ai-scorer/index.js +5 -0
  56. package/dist/wirings/channel/index.d.ts +5 -6
  57. package/dist/wirings/channel/index.js +3 -4
  58. package/dist/wirings/channel/local/local-channel-runner.js +8 -1
  59. package/dist/wirings/cli/channel/cli-raw-channel-runner.js +9 -1
  60. package/dist/wirings/cli/channel/index.d.ts +1 -2
  61. package/dist/wirings/cli/channel/index.js +0 -1
  62. package/dist/wirings/cli/cli-runner.js +13 -1
  63. package/dist/wirings/credential/index.d.ts +1 -1
  64. package/dist/wirings/gateway/index.d.ts +1 -1
  65. package/dist/wirings/http/http-runner.js +8 -2
  66. package/dist/wirings/http/index.d.ts +1 -2
  67. package/dist/wirings/mcp/index.d.ts +1 -1
  68. package/dist/wirings/mcp/mcp-runner.d.ts +15 -0
  69. package/dist/wirings/mcp/mcp-runner.js +18 -5
  70. package/dist/wirings/persona/index.d.ts +3 -4
  71. package/dist/wirings/persona/index.js +2 -3
  72. package/dist/wirings/queue/index.d.ts +1 -3
  73. package/dist/wirings/queue/index.js +1 -3
  74. package/dist/wirings/rpc/addon-runner.d.ts +4 -0
  75. package/dist/wirings/rpc/addon-runner.js +19 -3
  76. package/dist/wirings/rpc/rpc-runner.js +2 -0
  77. package/dist/wirings/rpc/rpc-types.d.ts +4 -0
  78. package/dist/wirings/rpc/wire-addon.d.ts +13 -0
  79. package/dist/wirings/rpc/wire-addon.js +4 -0
  80. package/dist/wirings/scheduler/index.d.ts +1 -1
  81. package/dist/wirings/trigger/index.d.ts +1 -1
  82. package/dist/wirings/virtual-user/index.d.ts +5 -6
  83. package/dist/wirings/virtual-user/index.js +2 -4
  84. package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +85 -15
  85. package/dist/wirings/workflow/index.d.ts +6 -6
  86. package/dist/wirings/workflow/index.js +2 -2
  87. package/dist/wirings/workflow/pikku-scenario-service.d.ts +7 -7
  88. package/dist/wirings/workflow/pikku-scenario-service.js +39 -13
  89. package/dist/wirings/workflow/pikku-workflow-service.js +17 -3
  90. package/dist/wirings/workflow/scenario-step.types.d.ts +8 -0
  91. package/dist/wirings/workflow/workflow-approval-audit.d.ts +16 -0
  92. package/dist/wirings/workflow/workflow-approval-audit.js +40 -0
  93. package/dist/wirings/workflow/workflow-approval-policy.d.ts +20 -0
  94. package/dist/wirings/workflow/workflow-approval-policy.js +48 -0
  95. package/dist/wirings/workflow/workflow-approval.d.ts +29 -1
  96. package/dist/wirings/workflow/workflow-approval.js +65 -2
  97. package/dist/wirings/workflow/workflow-run-ownership.d.ts +2 -1
  98. package/dist/wirings/workflow/workflow-run-ownership.js +2 -1
  99. package/dist/wirings/workflow/workflow.types.d.ts +1 -1
  100. package/knowledge/decisions/internals/addon-pikku-meta-ships-at-the-package-root-or-under-dist.md +32 -0
  101. package/knowledge/decisions/internals/an-addon-scope-root-loses-to-a-root-the-host-already-declares.md +39 -0
  102. package/knowledge/decisions/internals/index.md +30 -3
  103. package/knowledge/decisions/internals/validate-runs-checks-by-precondition.md +115 -0
  104. package/knowledge/decisions/security/a-function-never-receives-the-secret-service.md +37 -0
  105. package/knowledge/decisions/security/a-workflow-run-is-read-and-approved-by-its-owner.md +30 -14
  106. package/knowledge/decisions/security/an-approval-answer-outlives-the-run-it-answered.md +59 -0
  107. package/knowledge/decisions/security/index.md +3 -1
  108. package/knowledge/questions/index.md +1 -1
  109. package/package.json +3 -1
  110. package/scripts/generate-api-report.mts +143 -18
  111. package/src/api-report.test.ts +2 -2
  112. package/src/errors/index.ts +1 -1
  113. package/src/function/function-runner.test.ts +52 -0
  114. package/src/function/function-runner.ts +5 -9
  115. package/src/function/index.ts +0 -2
  116. package/src/index.ts +0 -35
  117. package/src/pikku-state.ts +5 -0
  118. package/src/public-surface.json +70 -94
  119. package/src/services/ai-agent-runner-service.ts +12 -1
  120. package/src/services/ai-run-state-service.ts +11 -0
  121. package/src/services/in-memory-ai-run-state-service.ts +13 -0
  122. package/src/services/index.ts +3 -43
  123. package/src/services/scoped-credential-service.test.ts +86 -0
  124. package/src/services/scoped-credential-service.ts +63 -0
  125. package/src/testing/service-tests/ai-storage-service-tests.ts +93 -0
  126. package/src/types/core.types.ts +3 -6
  127. package/src/types/state.types.ts +16 -0
  128. package/src/wirings/actor-flow/index.ts +0 -3
  129. package/src/wirings/ai-agent/ai-agent-finalize.test.ts +186 -0
  130. package/src/wirings/ai-agent/ai-agent-finalize.ts +197 -0
  131. package/src/wirings/ai-agent/ai-agent-interrupt.ts +1 -0
  132. package/src/wirings/ai-agent/ai-agent-memory.ts +54 -38
  133. package/src/wirings/ai-agent/ai-agent-model-config.test.ts +72 -3
  134. package/src/wirings/ai-agent/ai-agent-model-config.ts +49 -1
  135. package/src/wirings/ai-agent/ai-agent-prepare.ts +2 -0
  136. package/src/wirings/ai-agent/ai-agent-runner.ts +71 -40
  137. package/src/wirings/ai-agent/ai-agent-stream-output-hooks.test.ts +353 -0
  138. package/src/wirings/ai-agent/ai-agent-stream.ts +116 -54
  139. package/src/wirings/ai-agent/ai-agent-turn.test.ts +67 -0
  140. package/src/wirings/ai-agent/ai-agent-turn.ts +1 -0
  141. package/src/wirings/ai-agent/ai-agent.types.ts +64 -4
  142. package/src/wirings/ai-agent/index.ts +2 -16
  143. package/src/wirings/ai-scorer/ai-scorer-grade.test.ts +106 -0
  144. package/src/wirings/ai-scorer/ai-scorer-grade.ts +55 -0
  145. package/src/wirings/ai-scorer/ai-scorer-judge.test.ts +143 -0
  146. package/src/wirings/ai-scorer/ai-scorer-judge.ts +120 -0
  147. package/src/wirings/ai-scorer/ai-scorer-live.test.ts +174 -0
  148. package/src/wirings/ai-scorer/ai-scorer-live.ts +56 -0
  149. package/src/wirings/ai-scorer/ai-scorer-registry.ts +63 -0
  150. package/src/wirings/ai-scorer/ai-scorer-sampling.test.ts +34 -0
  151. package/src/wirings/ai-scorer/ai-scorer-sampling.ts +36 -0
  152. package/src/wirings/ai-scorer/ai-scorer-snapshots.test.ts +49 -0
  153. package/src/wirings/ai-scorer/ai-scorer-snapshots.ts +46 -0
  154. package/src/wirings/ai-scorer/ai-scorer-worker.test.ts +122 -0
  155. package/src/wirings/ai-scorer/ai-scorer-worker.ts +69 -0
  156. package/src/wirings/ai-scorer/ai-scorer.ts +76 -0
  157. package/src/wirings/ai-scorer/ai-scorer.types.ts +107 -0
  158. package/src/wirings/ai-scorer/index.ts +24 -0
  159. package/src/wirings/channel/index.ts +1 -20
  160. package/src/wirings/channel/local/local-channel-runner.test.ts +68 -0
  161. package/src/wirings/channel/local/local-channel-runner.ts +8 -1
  162. package/src/wirings/cli/channel/cli-raw-channel-runner.test.ts +23 -0
  163. package/src/wirings/cli/channel/cli-raw-channel-runner.ts +12 -1
  164. package/src/wirings/cli/channel/index.ts +0 -7
  165. package/src/wirings/cli/cli-runner.test.ts +68 -0
  166. package/src/wirings/cli/cli-runner.ts +18 -1
  167. package/src/wirings/credential/index.ts +0 -1
  168. package/src/wirings/gateway/index.ts +0 -3
  169. package/src/wirings/http/http-runner.test.ts +66 -0
  170. package/src/wirings/http/http-runner.ts +10 -2
  171. package/src/wirings/http/index.ts +1 -1
  172. package/src/wirings/mcp/index.ts +0 -1
  173. package/src/wirings/mcp/mcp-runner.test.ts +181 -0
  174. package/src/wirings/mcp/mcp-runner.ts +35 -5
  175. package/src/wirings/persona/index.ts +0 -8
  176. package/src/wirings/queue/index.ts +0 -14
  177. package/src/wirings/rpc/addon-runner.ts +34 -3
  178. package/src/wirings/rpc/addon-secrets.test.ts +261 -0
  179. package/src/wirings/rpc/rpc-runner.test.ts +2 -0
  180. package/src/wirings/rpc/rpc-runner.ts +2 -0
  181. package/src/wirings/rpc/rpc-types.ts +4 -0
  182. package/src/wirings/rpc/wire-addon.ts +17 -0
  183. package/src/wirings/scheduler/index.ts +0 -1
  184. package/src/wirings/trigger/index.ts +0 -1
  185. package/src/wirings/virtual-user/index.ts +0 -16
  186. package/src/wirings/workflow/dsl/workflow-dsl.types.ts +96 -16
  187. package/src/wirings/workflow/graph/graph-runner.test.ts +72 -0
  188. package/src/wirings/workflow/index.ts +2 -20
  189. package/src/wirings/workflow/pikku-scenario-service.ts +60 -15
  190. package/src/wirings/workflow/pikku-workflow-service.test.ts +13 -12
  191. package/src/wirings/workflow/pikku-workflow-service.ts +28 -4
  192. package/src/wirings/workflow/scenario-expectations.test.ts +75 -0
  193. package/src/wirings/workflow/scenario-hooks.test.ts +3 -2
  194. package/src/wirings/workflow/scenario-step.types.ts +8 -0
  195. package/src/wirings/workflow/workflow-approval-audit.ts +47 -0
  196. package/src/wirings/workflow/workflow-approval-policy.test.ts +524 -0
  197. package/src/wirings/workflow/workflow-approval-policy.ts +68 -0
  198. package/src/wirings/workflow/workflow-approval.ts +113 -9
  199. package/src/wirings/workflow/workflow-run-authority.test.ts +12 -15
  200. package/src/wirings/workflow/workflow-run-ownership.ts +2 -1
  201. package/src/wirings/workflow/workflow.types.ts +0 -9
  202. package/src/wirings-stay-decoupled.test.ts +6 -2
  203. package/tsconfig.tsbuildinfo +1 -1
  204. package/dist/internal.d.ts +0 -3
  205. package/dist/internal.js +0 -2
  206. package/dist/middleware/timeout.d.ts +0 -9
  207. package/dist/middleware/timeout.js +0 -15
  208. package/dist/pikku-response.d.ts +0 -6
  209. package/dist/pikku-response.js +0 -6
  210. package/dist/services/gopass-secrets.d.ts +0 -15
  211. package/dist/services/gopass-secrets.js +0 -76
  212. package/dist/services/http-scenario-actors.d.ts +0 -75
  213. package/dist/services/http-scenario-actors.js +0 -195
  214. package/dist/services/http-user-flow-actors.d.ts +0 -67
  215. package/dist/services/http-user-flow-actors.js +0 -193
  216. package/dist/services/scenario-actors-service.d.ts +0 -127
  217. package/dist/services/scenario-actors-service.js +0 -40
  218. package/dist/services/user-flow-actors-service.d.ts +0 -39
  219. package/dist/services/user-flow-actors-service.js +0 -1
  220. package/dist/wirings/credential/wire-credential.d.ts +0 -48
  221. package/dist/wirings/credential/wire-credential.js +0 -47
  222. package/dist/wirings/oauth2/oauth2-client.d.ts +0 -47
  223. package/dist/wirings/oauth2/oauth2-client.js +0 -263
  224. package/dist/wirings/oauth2/oauth2-routes.d.ts +0 -35
  225. package/dist/wirings/oauth2/oauth2-routes.js +0 -146
  226. package/dist/wirings/scope/wire-scope.d.ts +0 -33
  227. package/dist/wirings/scope/wire-scope.js +0 -32
  228. package/dist/wirings/workflow/dsl/index.d.ts +0 -5
  229. package/dist/wirings/workflow/dsl/index.js +0 -4
  230. package/dist/wirings/workflow/graph/index.d.ts +0 -5
  231. package/dist/wirings/workflow/graph/index.js +0 -4
@@ -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