@pikku/core 0.12.63 → 0.12.66

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 (225) hide show
  1. package/CHANGELOG.md +368 -0
  2. package/dist/dev/hot-reload.js +13 -55
  3. package/dist/dev/module-runner.d.ts +14 -0
  4. package/dist/dev/module-runner.js +59 -0
  5. package/dist/dev/reload-meta.d.ts +13 -0
  6. package/dist/dev/reload-meta.js +22 -0
  7. package/dist/errors/errors.d.ts +12 -0
  8. package/dist/errors/errors.js +19 -0
  9. package/dist/function/function-runner.d.ts +5 -5
  10. package/dist/function/function-runner.js +39 -111
  11. package/dist/function/functions.types.d.ts +17 -7
  12. package/dist/index.d.ts +5 -1
  13. package/dist/index.js +3 -1
  14. package/dist/middleware/auth-apikey.d.ts +1 -0
  15. package/dist/middleware/auth-bearer.d.ts +1 -0
  16. package/dist/middleware/auth-cookie.d.ts +1 -0
  17. package/dist/middleware/cors.d.ts +1 -0
  18. package/dist/middleware/index.d.ts +1 -1
  19. package/dist/middleware/index.js +1 -1
  20. package/dist/middleware/remote-auth.d.ts +1 -0
  21. package/dist/middleware/telemetry.d.ts +2 -0
  22. package/dist/middleware/timeout.d.ts +1 -0
  23. package/dist/permissions.d.ts +42 -27
  24. package/dist/permissions.js +101 -203
  25. package/dist/pikku-state.js +0 -2
  26. package/dist/scopes.d.ts +17 -0
  27. package/dist/scopes.js +59 -0
  28. package/dist/services/ai-embedding-service.d.ts +31 -0
  29. package/dist/services/ai-embedding-service.js +1 -0
  30. package/dist/services/credential-wire-service.d.ts +3 -1
  31. package/dist/services/credential-wire-service.js +10 -4
  32. package/dist/services/index.d.ts +4 -0
  33. package/dist/services/index.js +2 -0
  34. package/dist/services/meta-service.d.ts +15 -2
  35. package/dist/services/meta-service.js +51 -1
  36. package/dist/services/queue-webhook-service.d.ts +55 -0
  37. package/dist/services/queue-webhook-service.js +136 -0
  38. package/dist/services/scope-service.d.ts +67 -0
  39. package/dist/services/scope-service.js +1 -0
  40. package/dist/services/typed-secret-service.d.ts +8 -0
  41. package/dist/services/typed-secret-service.js +39 -4
  42. package/dist/services/webhook-service.d.ts +140 -0
  43. package/dist/services/webhook-service.js +44 -0
  44. package/dist/services/workflow-service.d.ts +7 -0
  45. package/dist/testing/service-tests.js +37 -0
  46. package/dist/types/core.types.d.ts +34 -6
  47. package/dist/types/state.types.d.ts +20 -2
  48. package/dist/utils/hmac.d.ts +16 -0
  49. package/dist/utils/hmac.js +26 -0
  50. package/dist/utils/safe-fetch.d.ts +51 -0
  51. package/dist/utils/safe-fetch.js +192 -0
  52. package/dist/wirings/ai-agent/ai-agent-agui.d.ts +84 -0
  53. package/dist/wirings/ai-agent/ai-agent-agui.js +305 -0
  54. package/dist/wirings/ai-agent/ai-agent-prepare.d.ts +105 -1
  55. package/dist/wirings/ai-agent/ai-agent-prepare.js +249 -11
  56. package/dist/wirings/ai-agent/ai-agent-runner.js +10 -1
  57. package/dist/wirings/ai-agent/ai-agent-stream.js +88 -16
  58. package/dist/wirings/ai-agent/ai-agent.types.d.ts +56 -2
  59. package/dist/wirings/ai-agent/index.d.ts +2 -1
  60. package/dist/wirings/ai-agent/index.js +2 -1
  61. package/dist/wirings/ai-agent/voice-input.d.ts +1 -0
  62. package/dist/wirings/ai-agent/voice-input.js +5 -41
  63. package/dist/wirings/ai-agent/voice-output.d.ts +1 -0
  64. package/dist/wirings/channel/channel-common.js +0 -1
  65. package/dist/wirings/channel/channel-handler.js +1 -4
  66. package/dist/wirings/channel/channel-middleware-runner.d.ts +12 -0
  67. package/dist/wirings/channel/channel-middleware-runner.js +34 -19
  68. package/dist/wirings/channel/channel.types.d.ts +2 -6
  69. package/dist/wirings/cli/cli-runner.js +3 -2
  70. package/dist/wirings/cli/cli.types.d.ts +1 -2
  71. package/dist/wirings/cli/command-parser.d.ts +2 -0
  72. package/dist/wirings/cli/command-parser.js +59 -2
  73. package/dist/wirings/credential/credential.types.d.ts +14 -0
  74. package/dist/wirings/credential/validate-credential-definitions.js +1 -0
  75. package/dist/wirings/gateway/gateway-runner.js +100 -50
  76. package/dist/wirings/gateway/gateway.types.d.ts +8 -5
  77. package/dist/wirings/http/http-routes.js +0 -3
  78. package/dist/wirings/http/http-runner.d.ts +9 -29
  79. package/dist/wirings/http/http-runner.js +9 -34
  80. package/dist/wirings/http/http.types.d.ts +4 -12
  81. package/dist/wirings/mcp/mcp-runner.js +0 -2
  82. package/dist/wirings/mcp/mcp.types.d.ts +5 -11
  83. package/dist/wirings/oauth2/index.d.ts +0 -3
  84. package/dist/wirings/oauth2/index.js +1 -2
  85. package/dist/wirings/rpc/addon-runner.d.ts +28 -0
  86. package/dist/wirings/rpc/addon-runner.js +173 -0
  87. package/dist/wirings/rpc/index.d.ts +5 -1
  88. package/dist/wirings/rpc/index.js +3 -1
  89. package/dist/wirings/rpc/remote-addon-auth.d.ts +26 -0
  90. package/dist/wirings/rpc/remote-addon-auth.js +43 -0
  91. package/dist/wirings/rpc/rpc-runner.d.ts +19 -0
  92. package/dist/wirings/rpc/rpc-runner.js +109 -3
  93. package/dist/wirings/rpc/rpc-types.d.ts +15 -1
  94. package/dist/wirings/rpc/wire-addon.js +9 -0
  95. package/dist/wirings/rpc/wire-remote-addon.d.ts +47 -0
  96. package/dist/wirings/rpc/wire-remote-addon.js +19 -0
  97. package/dist/wirings/scope/index.d.ts +3 -0
  98. package/dist/wirings/scope/index.js +2 -0
  99. package/dist/wirings/scope/scope.types.d.ts +39 -0
  100. package/dist/wirings/scope/scope.types.js +1 -0
  101. package/dist/wirings/scope/validate-scope-definitions.d.ts +16 -0
  102. package/dist/wirings/scope/validate-scope-definitions.js +76 -0
  103. package/dist/wirings/scope/wire-scope.d.ts +33 -0
  104. package/dist/wirings/scope/wire-scope.js +32 -0
  105. package/dist/wirings/secret/secret.types.d.ts +14 -0
  106. package/dist/wirings/secret/validate-secret-definitions.js +2 -0
  107. package/dist/wirings/variable/validate-variable-definitions.js +2 -0
  108. package/dist/wirings/variable/variable.types.d.ts +14 -0
  109. package/dist/wirings/workflow/dsl/index.d.ts +1 -1
  110. package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +89 -7
  111. package/dist/wirings/workflow/graph/graph-node.d.ts +2 -0
  112. package/dist/wirings/workflow/graph/graph-runner.js +3 -0
  113. package/dist/wirings/workflow/graph/wire-workflow-graph.d.ts +6 -0
  114. package/dist/wirings/workflow/graph/wire-workflow-graph.js +1 -0
  115. package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +5 -0
  116. package/dist/wirings/workflow/index.d.ts +2 -2
  117. package/dist/wirings/workflow/index.js +1 -1
  118. package/dist/wirings/workflow/pikku-workflow-service.d.ts +59 -1
  119. package/dist/wirings/workflow/pikku-workflow-service.js +187 -0
  120. package/dist/wirings/workflow/workflow.types.d.ts +1 -3
  121. package/package.json +6 -1
  122. package/run-tests.sh +1 -0
  123. package/src/dev/hot-reload.ts +13 -68
  124. package/src/dev/module-runner.test.ts +169 -0
  125. package/src/dev/module-runner.ts +103 -0
  126. package/src/dev/reload-meta.test.ts +31 -2
  127. package/src/dev/reload-meta.ts +26 -0
  128. package/src/errors/errors.ts +24 -0
  129. package/src/function/function-runner.test.ts +276 -142
  130. package/src/function/function-runner.ts +52 -145
  131. package/src/function/functions.types.ts +28 -38
  132. package/src/index.ts +8 -6
  133. package/src/middleware/index.ts +1 -5
  134. package/src/permissions.test.ts +160 -373
  135. package/src/permissions.ts +137 -279
  136. package/src/pikku-state.ts +0 -2
  137. package/src/scopes.test.ts +167 -0
  138. package/src/scopes.ts +69 -0
  139. package/src/services/ai-embedding-service.ts +31 -0
  140. package/src/services/credential-wire-service.ts +10 -4
  141. package/src/services/index.ts +20 -0
  142. package/src/services/meta-service.ts +68 -3
  143. package/src/services/queue-webhook-service.test.ts +408 -0
  144. package/src/services/queue-webhook-service.ts +182 -0
  145. package/src/services/scope-service.ts +75 -0
  146. package/src/services/typed-secret-service.test.ts +35 -0
  147. package/src/services/typed-secret-service.ts +39 -4
  148. package/src/services/webhook-service.ts +180 -0
  149. package/src/services/workflow-service.ts +7 -0
  150. package/src/testing/service-tests.ts +49 -0
  151. package/src/types/core.types.ts +42 -14
  152. package/src/types/state.types.ts +23 -3
  153. package/src/utils/hmac.ts +27 -0
  154. package/src/utils/safe-fetch.test.ts +373 -0
  155. package/src/utils/safe-fetch.ts +213 -0
  156. package/src/wirings/ai-agent/ai-agent-agui.test.ts +1127 -0
  157. package/src/wirings/ai-agent/ai-agent-agui.ts +386 -0
  158. package/src/wirings/ai-agent/ai-agent-authorization.test.ts +204 -0
  159. package/src/wirings/ai-agent/ai-agent-prepare.test.ts +483 -0
  160. package/src/wirings/ai-agent/ai-agent-prepare.ts +324 -13
  161. package/src/wirings/ai-agent/ai-agent-resume-authorization.test.ts +207 -0
  162. package/src/wirings/ai-agent/ai-agent-runner.test.ts +48 -1
  163. package/src/wirings/ai-agent/ai-agent-runner.ts +28 -0
  164. package/src/wirings/ai-agent/ai-agent-stream.test.ts +301 -10
  165. package/src/wirings/ai-agent/ai-agent-stream.ts +122 -16
  166. package/src/wirings/ai-agent/ai-agent.types.ts +57 -0
  167. package/src/wirings/ai-agent/index.ts +5 -0
  168. package/src/wirings/ai-agent/voice-input.test.ts +90 -0
  169. package/src/wirings/ai-agent/voice-input.ts +9 -40
  170. package/src/wirings/channel/channel-common.ts +0 -1
  171. package/src/wirings/channel/channel-handler.ts +1 -9
  172. package/src/wirings/channel/channel-middleware-runner.test.ts +28 -2
  173. package/src/wirings/channel/channel-middleware-runner.ts +39 -27
  174. package/src/wirings/channel/channel.types.ts +0 -6
  175. package/src/wirings/cli/cli-runner.ts +4 -2
  176. package/src/wirings/cli/cli.types.ts +0 -2
  177. package/src/wirings/cli/command-parser.test.ts +130 -0
  178. package/src/wirings/cli/command-parser.ts +80 -2
  179. package/src/wirings/credential/credential.types.ts +14 -0
  180. package/src/wirings/credential/validate-credential-definitions.ts +1 -0
  181. package/src/wirings/gateway/gateway-authorization.test.ts +444 -0
  182. package/src/wirings/gateway/gateway-runner.ts +114 -68
  183. package/src/wirings/gateway/gateway.types.ts +7 -9
  184. package/src/wirings/http/http-routes.ts +0 -3
  185. package/src/wirings/http/http-runner.test.ts +1 -11
  186. package/src/wirings/http/http-runner.ts +16 -39
  187. package/src/wirings/http/http.types.ts +7 -14
  188. package/src/wirings/mcp/mcp-runner.ts +0 -2
  189. package/src/wirings/mcp/mcp.types.ts +3 -11
  190. package/src/wirings/oauth2/index.ts +0 -3
  191. package/src/wirings/rpc/addon-runner.ts +233 -0
  192. package/src/wirings/rpc/index.ts +17 -1
  193. package/src/wirings/rpc/remote-addon-auth.ts +69 -0
  194. package/src/wirings/rpc/rpc-runner.test.ts +319 -16
  195. package/src/wirings/rpc/rpc-runner.ts +155 -3
  196. package/src/wirings/rpc/rpc-types.ts +16 -5
  197. package/src/wirings/rpc/wire-addon.test.ts +6 -3
  198. package/src/wirings/rpc/wire-addon.ts +9 -0
  199. package/src/wirings/rpc/wire-remote-addon.ts +57 -0
  200. package/src/wirings/scope/index.ts +14 -0
  201. package/src/wirings/scope/scope.test.ts +135 -0
  202. package/src/wirings/scope/scope.types.ts +44 -0
  203. package/src/wirings/scope/validate-scope-definitions.ts +110 -0
  204. package/src/wirings/scope/wire-scope.ts +34 -0
  205. package/src/wirings/secret/secret.types.ts +14 -0
  206. package/src/wirings/secret/validate-secret-definitions.ts +2 -0
  207. package/src/wirings/variable/validate-variable-definitions.ts +2 -0
  208. package/src/wirings/variable/variable.types.ts +14 -0
  209. package/src/wirings/workflow/dsl/index.ts +4 -0
  210. package/src/wirings/workflow/dsl/workflow-dsl.types.ts +97 -6
  211. package/src/wirings/workflow/graph/graph-node.ts +2 -0
  212. package/src/wirings/workflow/graph/graph-runner.test.ts +58 -0
  213. package/src/wirings/workflow/graph/graph-runner.ts +3 -0
  214. package/src/wirings/workflow/graph/wire-workflow-graph.ts +7 -0
  215. package/src/wirings/workflow/graph/workflow-graph.types.ts +5 -0
  216. package/src/wirings/workflow/index.ts +5 -0
  217. package/src/wirings/workflow/pikku-workflow-service.test.ts +341 -0
  218. package/src/wirings/workflow/pikku-workflow-service.ts +272 -0
  219. package/src/wirings/workflow/workflow-on-error.test.ts +154 -0
  220. package/src/wirings/workflow/workflow-step-session.test.ts +21 -5
  221. package/src/wirings/workflow/workflow.types.ts +4 -2
  222. package/tsconfig.tsbuildinfo +1 -1
  223. package/src/wirings/oauth2/oauth2-client.test.ts +0 -930
  224. package/src/wirings/oauth2/oauth2-client.ts +0 -331
  225. package/src/wirings/oauth2/oauth2-routes.ts +0 -234
@@ -4,11 +4,7 @@ import type {
4
4
  CorePikkuMiddlewareGroup,
5
5
  CoreSingletonServices,
6
6
  } from '../../types/core.types.js'
7
- import type {
8
- CorePikkuFunctionConfig,
9
- CorePermissionGroup,
10
- CorePikkuPermission,
11
- } from '../../function/functions.types.js'
7
+ import type { CorePikkuFunctionConfig } from '../../function/functions.types.js'
12
8
  import type { PikkuHTTPRequest } from '../http/http.types.js'
13
9
 
14
10
  /**
@@ -124,7 +120,6 @@ export type GatewayTransportType = 'webhook' | 'websocket' | 'listener'
124
120
  */
125
121
  export type CoreGateway<
126
122
  PikkuFunctionConfig = CorePikkuFunctionConfig<any, any>,
127
- PikkuPermission extends CorePikkuPermission = CorePikkuPermission,
128
123
  PikkuMiddleware extends CorePikkuMiddleware = CorePikkuMiddleware,
129
124
  > = Partial<
130
125
  Pick<CommonWireMeta, 'title' | 'summary' | 'description' | 'errors'>
@@ -143,11 +138,14 @@ export type CoreGateway<
143
138
  func: PikkuFunctionConfig
144
139
  /** Optional middleware chain (e.g., auth) */
145
140
  middleware?: CorePikkuMiddlewareGroup<any, any>
146
- /** Optional permissions */
147
- permissions?: CorePermissionGroup | PikkuPermission[]
148
141
  /** Optional tags for categorization */
149
142
  tags?: string[]
150
- /** Whether authentication is required (default: true) */
143
+ /**
144
+ * Whether the handler requires a session. Left unset, the handler's own
145
+ * `auth` governs, and a gateway handler is sessionless by default — inbound
146
+ * gateway traffic is platform-authenticated by the adapter, not
147
+ * session-bearing. Set `true` to require a session for every message.
148
+ */
151
149
  auth?: boolean
152
150
  }
153
151
 
@@ -128,7 +128,6 @@ function processRouteMap(
128
128
  * - tags: Merges (parent + child)
129
129
  * - middleware: Merges (parent runs first)
130
130
  * - auth: Inner overrides outer
131
- * - permissions: Inner overrides outer
132
131
  */
133
132
  function mergeGroupConfig(
134
133
  parent: HTTPRoutesGroupConfig,
@@ -139,7 +138,6 @@ function mergeGroupConfig(
139
138
  tags: [...(parent.tags || []), ...(child.tags || [])],
140
139
  middleware: [...(parent.middleware || []), ...(child.middleware || [])],
141
140
  auth: child.auth ?? parent.auth,
142
- permissions: child.permissions ?? parent.permissions,
143
141
  }
144
142
  }
145
143
 
@@ -162,7 +160,6 @@ function registerRoute(
162
160
  ...(groupConfig.middleware || []),
163
161
  ...(route.middleware || []),
164
162
  ],
165
- permissions: route.permissions ?? groupConfig.permissions,
166
163
  contentType: route.contentType,
167
164
  timeout: route.timeout,
168
165
  headers: route.headers,
@@ -4,7 +4,6 @@ import { NotFoundError } from '../../errors/errors.js'
4
4
  import type { JSONValue, CorePikkuMiddleware } from '../../types/core.types.js'
5
5
  import {
6
6
  addHTTPMiddleware,
7
- addHTTPPermission,
8
7
  createHTTPWire,
9
8
  fetch,
10
9
  fetchData,
@@ -253,23 +252,14 @@ describe('http-runner helpers', () => {
253
252
  } as any)
254
253
  })
255
254
 
256
- test('addHTTPMiddleware and addHTTPPermission register route groups', () => {
255
+ test('addHTTPMiddleware registers a route middleware group', () => {
257
256
  const middleware = [sessionMiddleware]
258
- const permissions = [async () => true]
259
257
 
260
258
  assert.strictEqual(addHTTPMiddleware('/api/*', middleware), middleware)
261
- assert.strictEqual(
262
- addHTTPPermission('/api/*', permissions as any),
263
- permissions
264
- )
265
259
  assert.strictEqual(
266
260
  pikkuState(null, 'middleware', 'httpGroup')['/api/*'],
267
261
  middleware
268
262
  )
269
- assert.strictEqual(
270
- pikkuState(null, 'permissions', 'httpGroup')['/api/*'],
271
- permissions
272
- )
273
263
  })
274
264
 
275
265
  test('addHTTPMiddleware composes repeated registrations for the same pattern', () => {
@@ -11,7 +11,6 @@ import type {
11
11
  CorePikkuFunction,
12
12
  CorePikkuFunctionSessionless,
13
13
  CorePikkuPermission,
14
- CorePermissionGroup,
15
14
  } from '../../function/functions.types.js'
16
15
  import type {
17
16
  CoreUserSession,
@@ -106,42 +105,23 @@ export const addHTTPMiddleware = <PikkuMiddleware extends CorePikkuMiddleware>(
106
105
  }
107
106
 
108
107
  /**
109
- * Registers HTTP permissions for a specific route pattern.
110
- *
111
- * This function registers permissions at runtime that will be applied to
112
- * HTTP routes matching the specified pattern.
113
- *
114
- * For tree-shaking benefits, wrap in a factory function:
115
- * `export const x = () => addHTTPPermission('pattern', [...])`
116
- *
117
- * @template PikkuPermission The permission type.
118
- * @param {string} pattern - Route pattern (e.g., '*' for all routes, '/api/*' for specific routes).
119
- * @param {CorePermissionGroup | CorePikkuPermission[]} permissions - Permissions for this route pattern.
120
- *
121
- * @returns {CorePermissionGroup | CorePikkuPermission[]} The permissions (for chaining/wrapping).
122
- *
123
- * @example
124
- * ```typescript
125
- * // Recommended: tree-shakeable
126
- * export const httpGlobalPermissions = () => addHTTPPermission('*', [
127
- * authenticatedPermission,
128
- * rateLimitPermission
129
- * ])
130
- *
131
- * // Also works: no tree-shaking
132
- * export const apiPermissions = addHTTPPermission('/api/*', [
133
- * adminPermission
134
- * ])
135
- * ```
108
+ * @deprecated HTTP-route-level permissions were removed in #972 — permissions
109
+ * are now function-scoped only (declare them on the function via
110
+ * `pikkuFunc({ permissions })`). This throwing stub exists solely so the pinned
111
+ * bootstrap CLI (which still generates an `addHTTPPermission` wrapper) can
112
+ * resolve the import at build time; it is never called. Delete once
113
+ * `PIKKU_CLI_VERSION` in the CLI build is bumped past the release that removes
114
+ * HTTP-route permissions.
136
115
  */
137
- export const addHTTPPermission = <PikkuPermission extends CorePikkuPermission>(
138
- pattern: string,
139
- permissions: CorePermissionGroup | CorePikkuPermission[],
140
- packageName: string | null = null
141
- ): CorePermissionGroup | CorePikkuPermission[] => {
142
- const httpGroups = pikkuState(packageName, 'permissions', 'httpGroup')
143
- httpGroups[pattern] = permissions
144
- return permissions
116
+ export const addHTTPPermission = (
117
+ _pattern: string,
118
+ _permissions:
119
+ | Record<string, CorePikkuPermission | CorePikkuPermission[]>
120
+ | CorePikkuPermission[]
121
+ ): never => {
122
+ throw new Error(
123
+ 'addHTTPPermission was removed in #972 — HTTP-route-level permissions no longer exist. Declare permissions on the function definition instead: pikkuFunc({ permissions }).'
124
+ )
145
125
  }
146
126
 
147
127
  /**
@@ -233,7 +213,6 @@ const getMatchingRoute = (requestType: string, requestPath: string) => {
233
213
  matchedPath,
234
214
  params: matchedPath.params,
235
215
  route,
236
- permissions: route.permissions,
237
216
  meta: meta!,
238
217
  }
239
218
  }
@@ -432,8 +411,6 @@ const executeRoute = async (
432
411
  data,
433
412
  inheritedMiddleware: meta.middleware,
434
413
  wireMiddleware: route.middleware,
435
- inheritedPermissions: meta.permissions,
436
- wirePermissions: route.permissions,
437
414
  coerceDataFromSchema: options.coerceDataFromSchema,
438
415
  tags: route.tags,
439
416
  wire,
@@ -8,7 +8,6 @@ import type {
8
8
  CorePikkuFunction,
9
9
  CorePikkuFunctionSessionless,
10
10
  CorePikkuPermission,
11
- CorePermissionGroup,
12
11
  CorePikkuFunctionConfig,
13
12
  } from '../../function/functions.types.js'
14
13
 
@@ -127,8 +126,10 @@ export type CoreHTTPFunctionWiring<
127
126
  > = CorePikkuFunctionSessionless<In, Out>,
128
127
  PikkuPermission extends CorePikkuPermission<In, any, any> =
129
128
  CorePikkuPermission<In, any, any>,
130
- PikkuMiddleware extends CorePikkuMiddleware<any, any> =
131
- CorePikkuMiddleware<any>,
129
+ PikkuMiddleware extends CorePikkuMiddleware<any, any> = CorePikkuMiddleware<
130
+ any,
131
+ any
132
+ >,
132
133
  > =
133
134
  | (CoreHTTPFunction & {
134
135
  route: R
@@ -138,7 +139,6 @@ export type CoreHTTPFunctionWiring<
138
139
  PikkuPermission,
139
140
  PikkuMiddleware
140
141
  >
141
- permissions?: CorePermissionGroup<PikkuPermission>
142
142
  auth?: true
143
143
  middleware?: PikkuMiddleware[]
144
144
  sse?: undefined
@@ -151,7 +151,6 @@ export type CoreHTTPFunctionWiring<
151
151
  PikkuPermission,
152
152
  PikkuMiddleware
153
153
  >
154
- permissions?: undefined
155
154
  auth?: false
156
155
  middleware?: PikkuMiddleware[]
157
156
  sse?: undefined
@@ -164,7 +163,6 @@ export type CoreHTTPFunctionWiring<
164
163
  PikkuPermission,
165
164
  PikkuMiddleware
166
165
  >
167
- permissions?: CorePermissionGroup<PikkuPermission>
168
166
  auth?: true
169
167
  middleware?: PikkuMiddleware[]
170
168
  sse?: boolean
@@ -177,7 +175,6 @@ export type CoreHTTPFunctionWiring<
177
175
  PikkuPermission,
178
176
  PikkuMiddleware
179
177
  >
180
- permissions?: undefined
181
178
  auth?: false
182
179
  middleware?: PikkuMiddleware[]
183
180
  sse?: boolean
@@ -190,7 +187,6 @@ export type CoreHTTPFunctionWiring<
190
187
  PikkuPermission,
191
188
  PikkuMiddleware
192
189
  >
193
- permissions?: CorePermissionGroup<PikkuPermission>
194
190
  auth?: true
195
191
  middleware?: PikkuMiddleware[]
196
192
  query?: Array<keyof In>
@@ -204,7 +200,6 @@ export type CoreHTTPFunctionWiring<
204
200
  PikkuPermission,
205
201
  PikkuMiddleware
206
202
  >
207
- permissions?: undefined
208
203
  auth?: false
209
204
  middleware?: PikkuMiddleware[]
210
205
  query?: Array<keyof In>
@@ -294,7 +289,7 @@ export type HTTPRouteConfig<
294
289
  | CorePikkuFunction<any, any, any, any, any>
295
290
  | CorePikkuFunctionSessionless<any, any, any, any, any>,
296
291
  PikkuPermission extends CorePikkuPermission<any, any, any> =
297
- CorePikkuPermission<any>,
292
+ CorePikkuPermission<any, any, any>,
298
293
  PikkuMiddleware extends CorePikkuMiddleware<any, any> = CorePikkuMiddleware<
299
294
  any,
300
295
  any
@@ -305,9 +300,8 @@ export type HTTPRouteConfig<
305
300
  route: string
306
301
  func: CorePikkuFunctionConfig<PikkuFunction, PikkuPermission, PikkuMiddleware>
307
302
 
308
- // Auth & permissions
303
+ // Auth
309
304
  auth?: boolean
310
- permissions?: CorePermissionGroup<PikkuPermission>
311
305
 
312
306
  // Middleware
313
307
  middleware?: PikkuMiddleware[]
@@ -321,7 +315,7 @@ export type HTTPRouteConfig<
321
315
  */
322
316
  export type HTTPRoutesGroupConfig<
323
317
  PikkuPermission extends CorePikkuPermission<any, any, any> =
324
- CorePikkuPermission<any>,
318
+ CorePikkuPermission<any, any, any>,
325
319
  PikkuMiddleware extends CorePikkuMiddleware<any, any> = CorePikkuMiddleware<
326
320
  any,
327
321
  any
@@ -331,7 +325,6 @@ export type HTTPRoutesGroupConfig<
331
325
  tags?: string[]
332
326
  auth?: boolean
333
327
  middleware?: PikkuMiddleware[]
334
- permissions?: CorePermissionGroup<PikkuPermission>
335
328
  }
336
329
 
337
330
  /**
@@ -252,8 +252,6 @@ async function runMCPPikkuFunc(
252
252
  data: () => request.params,
253
253
  inheritedMiddleware: meta?.middleware,
254
254
  wireMiddleware: mcp?.middleware,
255
- inheritedPermissions: meta?.permissions,
256
- wirePermissions: mcp?.permissions,
257
255
  tags: mcp?.tags,
258
256
  wire,
259
257
  sessionService: mcpSessionService,
@@ -1,5 +1,4 @@
1
1
  import type {
2
- CorePermissionGroup,
3
2
  CorePikkuFunctionConfig,
4
3
  CorePikkuFunctionSessionless,
5
4
  CorePikkuPermission,
@@ -7,7 +6,6 @@ import type {
7
6
  import type {
8
7
  CorePikkuMiddleware,
9
8
  MiddlewareMetadata,
10
- PermissionMetadata,
11
9
  } from '../../types/core.types.js'
12
10
 
13
11
  /**
@@ -49,12 +47,11 @@ export type PikkuMCP<Tools extends string = any> = {
49
47
  */
50
48
  export type MCPResourceMeta = Record<
51
49
  string,
52
- Omit<CoreMCPResource, 'func' | 'middleware' | 'permissions'> & {
50
+ Omit<CoreMCPResource, 'func' | 'middleware'> & {
53
51
  pikkuFuncId: string
54
52
  inputSchema: string | null
55
53
  outputSchema: string | null
56
54
  middleware?: MiddlewareMetadata[] // Pre-resolved middleware chain (tag + explicit)
57
- permissions?: PermissionMetadata[] // Pre-resolved permission chain (tag + explicit)
58
55
  }
59
56
  >
60
57
 
@@ -63,12 +60,11 @@ export type MCPResourceMeta = Record<
63
60
  */
64
61
  export type MCPToolMeta = Record<
65
62
  string,
66
- Omit<CoreMCPTool, 'func' | 'middleware' | 'permissions'> & {
63
+ Omit<CoreMCPTool, 'func' | 'middleware'> & {
67
64
  pikkuFuncId: string
68
65
  inputSchema: string | null
69
66
  outputSchema: string | null
70
67
  middleware?: MiddlewareMetadata[] // Pre-resolved middleware chain (tag + explicit)
71
- permissions?: PermissionMetadata[] // Pre-resolved permission chain (tag + explicit)
72
68
  }
73
69
  >
74
70
 
@@ -77,7 +73,7 @@ export type MCPToolMeta = Record<
77
73
  */
78
74
  export type MCPPromptMeta = Record<
79
75
  string,
80
- Omit<CoreMCPPrompt, 'func' | 'middleware' | 'permissions'> & {
76
+ Omit<CoreMCPPrompt, 'func' | 'middleware'> & {
81
77
  pikkuFuncId: string
82
78
  inputSchema: string | null
83
79
  outputSchema: string | null
@@ -87,7 +83,6 @@ export type MCPPromptMeta = Record<
87
83
  required: boolean
88
84
  }>
89
85
  middleware?: MiddlewareMetadata[] // Pre-resolved middleware chain (tag + explicit)
90
- permissions?: PermissionMetadata[] // Pre-resolved permission chain (tag + explicit)
91
86
  }
92
87
  >
93
88
 
@@ -112,7 +107,6 @@ export type CoreMCPResource<
112
107
  func: PikkuFunctionConfig
113
108
  tags?: string[]
114
109
  middleware?: PikkuMiddleware[]
115
- permissions?: CorePermissionGroup<PikkuPermission>
116
110
  }
117
111
 
118
112
  /**
@@ -134,7 +128,6 @@ export type CoreMCPTool<
134
128
  tags?: string[]
135
129
  streaming?: boolean
136
130
  middleware?: PikkuMiddleware[]
137
- permissions?: CorePermissionGroup<PikkuPermission>
138
131
  }
139
132
 
140
133
  /**
@@ -154,7 +147,6 @@ export type CoreMCPPrompt<
154
147
  func: PikkuFunctionConfig
155
148
  tags?: string[]
156
149
  middleware?: PikkuMiddleware[]
157
- permissions?: CorePermissionGroup<PikkuPermission>
158
150
  }
159
151
 
160
152
  export type JsonRpcRequest = {
@@ -1,4 +1 @@
1
- export { OAuth2Client } from './oauth2-client.js'
2
- export { createOAuth2Handler } from './oauth2-routes.js'
3
- export type { CreateOAuth2HandlerOptions } from './oauth2-routes.js'
4
1
  export type { OAuth2AppCredential, OAuth2Token } from './oauth2.types.js'
@@ -0,0 +1,233 @@
1
+ import { pikkuState } from '../../pikku-state.js'
2
+ import type {
3
+ CoreConfig,
4
+ CoreSingletonServices,
5
+ } from '../../types/core.types.js'
6
+ import type { SecretService } from '../../services/secret-service.js'
7
+ import type { VariablesService } from '../../services/variables-service.js'
8
+
9
+ /**
10
+ * A single wired addon instance: a namespace (wireAddon `name`) plus the
11
+ * per-instance name-aliases that remap the logical names the addon reads to
12
+ * the actual project secret/variable/credential names.
13
+ */
14
+ export type AddonInstance = {
15
+ namespace: string
16
+ secretOverrides?: Record<string, string>
17
+ variableOverrides?: Record<string, string>
18
+ credentialOverrides?: Record<string, string>
19
+ }
20
+
21
+ /**
22
+ * Wrap a SecretService so that the logical secret names an addon reads are
23
+ * remapped to the actual project secret names via the instance's overrides.
24
+ */
25
+ const aliasSecretService = (
26
+ secrets: SecretService,
27
+ overrides: Record<string, string>
28
+ ): SecretService => {
29
+ const map = (key: string) => overrides[key] ?? key
30
+ return {
31
+ getSecret: <T = string>(key: string) => secrets.getSecret<T>(map(key)),
32
+ hasSecret: (key: string) => secrets.hasSecret(map(key)),
33
+ setSecret: (key: string, value: unknown) =>
34
+ secrets.setSecret(map(key), value),
35
+ deleteSecret: (key: string) => secrets.deleteSecret(map(key)),
36
+ getSecrets: async (keys) => {
37
+ const result = await secrets.getSecrets(keys.map(map))
38
+ const out: Record<string, unknown> = {}
39
+ for (const logical of keys) {
40
+ const real = map(logical)
41
+ if (real in result)
42
+ out[logical] = (result as Record<string, unknown>)[real]
43
+ }
44
+ return out as never
45
+ },
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Wrap a VariablesService so that the logical variable names an addon reads
51
+ * are remapped to the actual project variable names via the instance's overrides.
52
+ */
53
+ const aliasVariablesService = (
54
+ variables: VariablesService,
55
+ overrides: Record<string, string>
56
+ ): VariablesService => {
57
+ const map = (name: string) => overrides[name] ?? name
58
+ return {
59
+ get: <T = string>(name: string) => variables.get<T>(map(name)),
60
+ getVariables: (names) => {
61
+ const result = variables.getVariables(names.map(map) as never)
62
+ const remap = (r: Record<string, unknown>) => {
63
+ const out: Record<string, unknown> = {}
64
+ for (const logical of names) {
65
+ const real = map(logical)
66
+ if (real in r) out[logical] = r[real]
67
+ }
68
+ return out
69
+ }
70
+ return result instanceof Promise
71
+ ? (result.then(remap) as never)
72
+ : (remap(result as Record<string, unknown>) as never)
73
+ },
74
+ getAll: () => variables.getAll(),
75
+ set: (name: string, value: unknown) => variables.set(map(name), value),
76
+ has: (name: string) => variables.has(map(name)),
77
+ delete: (name: string) => variables.delete(map(name)),
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Find the consumer-defined namespace (from wireAddon) for a given addon package.
83
+ * Returns null if the package isn't registered as an addon.
84
+ */
85
+ const findAddonNamespaceForPackage = (packageName: string): string | null => {
86
+ const addons = pikkuState(null, 'addons', 'packages')
87
+ if (!addons) return null
88
+ for (const [namespace, cfg] of addons.entries()) {
89
+ if (cfg?.package === packageName) return namespace
90
+ }
91
+ return null
92
+ }
93
+
94
+ /**
95
+ * Wrap a workflow service so that bare workflow names passed from inside an
96
+ * addon function are auto-prefixed with the addon's consumer-facing namespace.
97
+ * Without this, `runToCompletion('myWorkflow')` from inside an addon misses
98
+ * the workflow registered under the addon's package scope and throws
99
+ * WorkflowNotFoundError — forcing addons to hardcode their consumer-defined
100
+ * namespace, which couples the addon to its caller.
101
+ *
102
+ * Explicit `'ns:name'` and bare names that already exist in root meta are
103
+ * unaffected; only bare names that would otherwise miss resolution get
104
+ * prefixed.
105
+ */
106
+ const wrapWorkflowServiceForPackage = <T extends object>(
107
+ service: T,
108
+ packageName: string,
109
+ namespace: string | null
110
+ ): T => {
111
+ return new Proxy(service, {
112
+ get(target, prop, receiver) {
113
+ if (prop === 'startWorkflow' || prop === 'runToCompletion') {
114
+ const original = Reflect.get(target, prop, receiver) as Function
115
+ return function (this: any, name: string, ...rest: any[]) {
116
+ if (typeof name === 'string' && !name.includes(':')) {
117
+ // Prefer the known instance namespace; fall back to the
118
+ // package's sole namespace when invoked without an instance.
119
+ const ns = namespace ?? findAddonNamespaceForPackage(packageName)
120
+ if (ns) {
121
+ name = `${ns}:${name}`
122
+ }
123
+ }
124
+ return original.call(this, name, ...rest)
125
+ }
126
+ }
127
+ return Reflect.get(target, prop, receiver)
128
+ },
129
+ })
130
+ }
131
+
132
+ /**
133
+ * Get or create singleton services for an addon instance.
134
+ * Services are cached in pikkuState to avoid recreation on each call.
135
+ *
136
+ * @param packageName - The addon package name
137
+ * @param parentServices - The parent/caller's singleton services (used as base)
138
+ * @param addonInstance - The wired instance whose overrides shape the services
139
+ * @returns The instance's singleton services
140
+ */
141
+ export const getOrCreatePackageSingletonServices = async (
142
+ packageName: string,
143
+ parentServices: CoreSingletonServices,
144
+ addonInstance?: AddonInstance
145
+ ): Promise<CoreSingletonServices> => {
146
+ // Cache per instance (namespace), not per package, so two instances of one
147
+ // package get separate services built with their own overrides. A bare
148
+ // package-scoped call (no instance) falls back to per-package caching.
149
+ const cacheKey = addonInstance?.namespace ?? packageName
150
+
151
+ const cachedServices = pikkuState(cacheKey, 'package', 'singletonServices')
152
+ if (cachedServices) {
153
+ return cachedServices
154
+ }
155
+
156
+ const factories = pikkuState(packageName, 'package', 'factories')
157
+ if (!factories || !factories.createSingletonServices) {
158
+ // No factories registered, use parent services
159
+ return parentServices
160
+ }
161
+
162
+ // Apply this instance's secret/variable overrides by aliasing the resolver
163
+ // services the addon reads from, so its createSingletonServices resolves
164
+ // instance-specific secrets/variables.
165
+ let existingServices = parentServices
166
+ if (addonInstance?.secretOverrides && parentServices.secrets) {
167
+ existingServices = {
168
+ ...existingServices,
169
+ secrets: aliasSecretService(
170
+ parentServices.secrets,
171
+ addonInstance.secretOverrides
172
+ ),
173
+ }
174
+ }
175
+ if (addonInstance?.variableOverrides && parentServices.variables) {
176
+ existingServices = {
177
+ ...existingServices,
178
+ variables: aliasVariablesService(
179
+ parentServices.variables,
180
+ addonInstance.variableOverrides
181
+ ),
182
+ }
183
+ }
184
+
185
+ // Create config for the package (use parent config if no factory)
186
+ let config: CoreConfig = existingServices.config
187
+ if (factories.createConfig) {
188
+ config = await factories.createConfig(existingServices.variables)
189
+ }
190
+
191
+ // Create singleton services for the package, passing parent services as existing
192
+ const packageServices = await factories.createSingletonServices(
193
+ config,
194
+ existingServices
195
+ )
196
+
197
+ // Wrap workflowService so that bare names used inside the addon's functions
198
+ // resolve to workflows registered under the addon's package scope.
199
+ if (
200
+ packageServices.workflowService &&
201
+ typeof packageServices.workflowService === 'object'
202
+ ) {
203
+ packageServices.workflowService = wrapWorkflowServiceForPackage(
204
+ packageServices.workflowService as object,
205
+ packageName,
206
+ addonInstance?.namespace ?? null
207
+ ) as typeof packageServices.workflowService
208
+ }
209
+
210
+ pikkuState(cacheKey, 'package', 'singletonServices', packageServices)
211
+
212
+ return packageServices
213
+ }
214
+
215
+ /**
216
+ * Build the addon instance descriptor (namespace + per-instance overrides) for
217
+ * a bare intra-addon call, using the namespace currently executing on the wire.
218
+ * Returns undefined unless that namespace maps to the resolved package.
219
+ */
220
+ export const addonInstanceForNamespace = (
221
+ namespace: string | undefined,
222
+ expectedPackage: string
223
+ ): AddonInstance | undefined => {
224
+ if (!namespace) return undefined
225
+ const cfg = pikkuState(null, 'addons', 'packages').get(namespace)
226
+ if (!cfg || cfg.package !== expectedPackage) return undefined
227
+ return {
228
+ namespace,
229
+ secretOverrides: cfg.secretOverrides,
230
+ variableOverrides: cfg.variableOverrides,
231
+ credentialOverrides: cfg.credentialOverrides,
232
+ }
233
+ }
@@ -1,4 +1,20 @@
1
- export { PikkuRPCService, rpcService, RPCNotFoundError } from './rpc-runner.js'
1
+ export {
2
+ PikkuRPCService,
3
+ rpcService,
4
+ RPCNotFoundError,
5
+ RemoteAddonConfigError,
6
+ RemoteAddonRequestError,
7
+ } from './rpc-runner.js'
8
+ export {
9
+ resolveRemoteAddonToken,
10
+ RemoteAddonAuthError,
11
+ } from './remote-addon-auth.js'
12
+ export type { RemoteAddonAuthBinding } from './remote-addon-auth.js'
2
13
  export type { PikkuRPC, RPCMeta } from './rpc-types.js'
3
14
  export { wireAddon } from './wire-addon.js'
4
15
  export type { WireAddonConfig } from './wire-addon.js'
16
+ export { wireRemoteAddon } from './wire-remote-addon.js'
17
+ export type {
18
+ WireRemoteAddonConfig,
19
+ RemoteAddonAuth,
20
+ } from './wire-remote-addon.js'