@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.
- package/CHANGELOG.md +368 -0
- package/dist/dev/hot-reload.js +13 -55
- package/dist/dev/module-runner.d.ts +14 -0
- package/dist/dev/module-runner.js +59 -0
- package/dist/dev/reload-meta.d.ts +13 -0
- package/dist/dev/reload-meta.js +22 -0
- package/dist/errors/errors.d.ts +12 -0
- package/dist/errors/errors.js +19 -0
- package/dist/function/function-runner.d.ts +5 -5
- package/dist/function/function-runner.js +39 -111
- package/dist/function/functions.types.d.ts +17 -7
- package/dist/index.d.ts +5 -1
- package/dist/index.js +3 -1
- package/dist/middleware/auth-apikey.d.ts +1 -0
- package/dist/middleware/auth-bearer.d.ts +1 -0
- package/dist/middleware/auth-cookie.d.ts +1 -0
- package/dist/middleware/cors.d.ts +1 -0
- package/dist/middleware/index.d.ts +1 -1
- package/dist/middleware/index.js +1 -1
- package/dist/middleware/remote-auth.d.ts +1 -0
- package/dist/middleware/telemetry.d.ts +2 -0
- package/dist/middleware/timeout.d.ts +1 -0
- package/dist/permissions.d.ts +42 -27
- package/dist/permissions.js +101 -203
- package/dist/pikku-state.js +0 -2
- package/dist/scopes.d.ts +17 -0
- package/dist/scopes.js +59 -0
- package/dist/services/ai-embedding-service.d.ts +31 -0
- package/dist/services/ai-embedding-service.js +1 -0
- package/dist/services/credential-wire-service.d.ts +3 -1
- package/dist/services/credential-wire-service.js +10 -4
- package/dist/services/index.d.ts +4 -0
- package/dist/services/index.js +2 -0
- package/dist/services/meta-service.d.ts +15 -2
- package/dist/services/meta-service.js +51 -1
- package/dist/services/queue-webhook-service.d.ts +55 -0
- package/dist/services/queue-webhook-service.js +136 -0
- package/dist/services/scope-service.d.ts +67 -0
- package/dist/services/scope-service.js +1 -0
- package/dist/services/typed-secret-service.d.ts +8 -0
- package/dist/services/typed-secret-service.js +39 -4
- package/dist/services/webhook-service.d.ts +140 -0
- package/dist/services/webhook-service.js +44 -0
- package/dist/services/workflow-service.d.ts +7 -0
- package/dist/testing/service-tests.js +37 -0
- package/dist/types/core.types.d.ts +34 -6
- package/dist/types/state.types.d.ts +20 -2
- package/dist/utils/hmac.d.ts +16 -0
- package/dist/utils/hmac.js +26 -0
- package/dist/utils/safe-fetch.d.ts +51 -0
- package/dist/utils/safe-fetch.js +192 -0
- package/dist/wirings/ai-agent/ai-agent-agui.d.ts +84 -0
- package/dist/wirings/ai-agent/ai-agent-agui.js +305 -0
- package/dist/wirings/ai-agent/ai-agent-prepare.d.ts +105 -1
- package/dist/wirings/ai-agent/ai-agent-prepare.js +249 -11
- package/dist/wirings/ai-agent/ai-agent-runner.js +10 -1
- package/dist/wirings/ai-agent/ai-agent-stream.js +88 -16
- package/dist/wirings/ai-agent/ai-agent.types.d.ts +56 -2
- package/dist/wirings/ai-agent/index.d.ts +2 -1
- package/dist/wirings/ai-agent/index.js +2 -1
- package/dist/wirings/ai-agent/voice-input.d.ts +1 -0
- package/dist/wirings/ai-agent/voice-input.js +5 -41
- package/dist/wirings/ai-agent/voice-output.d.ts +1 -0
- package/dist/wirings/channel/channel-common.js +0 -1
- package/dist/wirings/channel/channel-handler.js +1 -4
- package/dist/wirings/channel/channel-middleware-runner.d.ts +12 -0
- package/dist/wirings/channel/channel-middleware-runner.js +34 -19
- package/dist/wirings/channel/channel.types.d.ts +2 -6
- package/dist/wirings/cli/cli-runner.js +3 -2
- package/dist/wirings/cli/cli.types.d.ts +1 -2
- package/dist/wirings/cli/command-parser.d.ts +2 -0
- package/dist/wirings/cli/command-parser.js +59 -2
- package/dist/wirings/credential/credential.types.d.ts +14 -0
- package/dist/wirings/credential/validate-credential-definitions.js +1 -0
- package/dist/wirings/gateway/gateway-runner.js +100 -50
- package/dist/wirings/gateway/gateway.types.d.ts +8 -5
- package/dist/wirings/http/http-routes.js +0 -3
- package/dist/wirings/http/http-runner.d.ts +9 -29
- package/dist/wirings/http/http-runner.js +9 -34
- package/dist/wirings/http/http.types.d.ts +4 -12
- package/dist/wirings/mcp/mcp-runner.js +0 -2
- package/dist/wirings/mcp/mcp.types.d.ts +5 -11
- package/dist/wirings/oauth2/index.d.ts +0 -3
- package/dist/wirings/oauth2/index.js +1 -2
- package/dist/wirings/rpc/addon-runner.d.ts +28 -0
- package/dist/wirings/rpc/addon-runner.js +173 -0
- package/dist/wirings/rpc/index.d.ts +5 -1
- package/dist/wirings/rpc/index.js +3 -1
- package/dist/wirings/rpc/remote-addon-auth.d.ts +26 -0
- package/dist/wirings/rpc/remote-addon-auth.js +43 -0
- package/dist/wirings/rpc/rpc-runner.d.ts +19 -0
- package/dist/wirings/rpc/rpc-runner.js +109 -3
- package/dist/wirings/rpc/rpc-types.d.ts +15 -1
- package/dist/wirings/rpc/wire-addon.js +9 -0
- package/dist/wirings/rpc/wire-remote-addon.d.ts +47 -0
- package/dist/wirings/rpc/wire-remote-addon.js +19 -0
- package/dist/wirings/scope/index.d.ts +3 -0
- package/dist/wirings/scope/index.js +2 -0
- package/dist/wirings/scope/scope.types.d.ts +39 -0
- package/dist/wirings/scope/scope.types.js +1 -0
- package/dist/wirings/scope/validate-scope-definitions.d.ts +16 -0
- package/dist/wirings/scope/validate-scope-definitions.js +76 -0
- package/dist/wirings/scope/wire-scope.d.ts +33 -0
- package/dist/wirings/scope/wire-scope.js +32 -0
- package/dist/wirings/secret/secret.types.d.ts +14 -0
- package/dist/wirings/secret/validate-secret-definitions.js +2 -0
- package/dist/wirings/variable/validate-variable-definitions.js +2 -0
- package/dist/wirings/variable/variable.types.d.ts +14 -0
- package/dist/wirings/workflow/dsl/index.d.ts +1 -1
- package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +89 -7
- package/dist/wirings/workflow/graph/graph-node.d.ts +2 -0
- package/dist/wirings/workflow/graph/graph-runner.js +3 -0
- package/dist/wirings/workflow/graph/wire-workflow-graph.d.ts +6 -0
- package/dist/wirings/workflow/graph/wire-workflow-graph.js +1 -0
- package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +5 -0
- package/dist/wirings/workflow/index.d.ts +2 -2
- package/dist/wirings/workflow/index.js +1 -1
- package/dist/wirings/workflow/pikku-workflow-service.d.ts +59 -1
- package/dist/wirings/workflow/pikku-workflow-service.js +187 -0
- package/dist/wirings/workflow/workflow.types.d.ts +1 -3
- package/package.json +6 -1
- package/run-tests.sh +1 -0
- package/src/dev/hot-reload.ts +13 -68
- package/src/dev/module-runner.test.ts +169 -0
- package/src/dev/module-runner.ts +103 -0
- package/src/dev/reload-meta.test.ts +31 -2
- package/src/dev/reload-meta.ts +26 -0
- package/src/errors/errors.ts +24 -0
- package/src/function/function-runner.test.ts +276 -142
- package/src/function/function-runner.ts +52 -145
- package/src/function/functions.types.ts +28 -38
- package/src/index.ts +8 -6
- package/src/middleware/index.ts +1 -5
- package/src/permissions.test.ts +160 -373
- package/src/permissions.ts +137 -279
- package/src/pikku-state.ts +0 -2
- package/src/scopes.test.ts +167 -0
- package/src/scopes.ts +69 -0
- package/src/services/ai-embedding-service.ts +31 -0
- package/src/services/credential-wire-service.ts +10 -4
- package/src/services/index.ts +20 -0
- package/src/services/meta-service.ts +68 -3
- package/src/services/queue-webhook-service.test.ts +408 -0
- package/src/services/queue-webhook-service.ts +182 -0
- package/src/services/scope-service.ts +75 -0
- package/src/services/typed-secret-service.test.ts +35 -0
- package/src/services/typed-secret-service.ts +39 -4
- package/src/services/webhook-service.ts +180 -0
- package/src/services/workflow-service.ts +7 -0
- package/src/testing/service-tests.ts +49 -0
- package/src/types/core.types.ts +42 -14
- package/src/types/state.types.ts +23 -3
- package/src/utils/hmac.ts +27 -0
- package/src/utils/safe-fetch.test.ts +373 -0
- package/src/utils/safe-fetch.ts +213 -0
- package/src/wirings/ai-agent/ai-agent-agui.test.ts +1127 -0
- package/src/wirings/ai-agent/ai-agent-agui.ts +386 -0
- package/src/wirings/ai-agent/ai-agent-authorization.test.ts +204 -0
- package/src/wirings/ai-agent/ai-agent-prepare.test.ts +483 -0
- package/src/wirings/ai-agent/ai-agent-prepare.ts +324 -13
- package/src/wirings/ai-agent/ai-agent-resume-authorization.test.ts +207 -0
- package/src/wirings/ai-agent/ai-agent-runner.test.ts +48 -1
- package/src/wirings/ai-agent/ai-agent-runner.ts +28 -0
- package/src/wirings/ai-agent/ai-agent-stream.test.ts +301 -10
- package/src/wirings/ai-agent/ai-agent-stream.ts +122 -16
- package/src/wirings/ai-agent/ai-agent.types.ts +57 -0
- package/src/wirings/ai-agent/index.ts +5 -0
- package/src/wirings/ai-agent/voice-input.test.ts +90 -0
- package/src/wirings/ai-agent/voice-input.ts +9 -40
- package/src/wirings/channel/channel-common.ts +0 -1
- package/src/wirings/channel/channel-handler.ts +1 -9
- package/src/wirings/channel/channel-middleware-runner.test.ts +28 -2
- package/src/wirings/channel/channel-middleware-runner.ts +39 -27
- package/src/wirings/channel/channel.types.ts +0 -6
- package/src/wirings/cli/cli-runner.ts +4 -2
- package/src/wirings/cli/cli.types.ts +0 -2
- package/src/wirings/cli/command-parser.test.ts +130 -0
- package/src/wirings/cli/command-parser.ts +80 -2
- package/src/wirings/credential/credential.types.ts +14 -0
- package/src/wirings/credential/validate-credential-definitions.ts +1 -0
- package/src/wirings/gateway/gateway-authorization.test.ts +444 -0
- package/src/wirings/gateway/gateway-runner.ts +114 -68
- package/src/wirings/gateway/gateway.types.ts +7 -9
- package/src/wirings/http/http-routes.ts +0 -3
- package/src/wirings/http/http-runner.test.ts +1 -11
- package/src/wirings/http/http-runner.ts +16 -39
- package/src/wirings/http/http.types.ts +7 -14
- package/src/wirings/mcp/mcp-runner.ts +0 -2
- package/src/wirings/mcp/mcp.types.ts +3 -11
- package/src/wirings/oauth2/index.ts +0 -3
- package/src/wirings/rpc/addon-runner.ts +233 -0
- package/src/wirings/rpc/index.ts +17 -1
- package/src/wirings/rpc/remote-addon-auth.ts +69 -0
- package/src/wirings/rpc/rpc-runner.test.ts +319 -16
- package/src/wirings/rpc/rpc-runner.ts +155 -3
- package/src/wirings/rpc/rpc-types.ts +16 -5
- package/src/wirings/rpc/wire-addon.test.ts +6 -3
- package/src/wirings/rpc/wire-addon.ts +9 -0
- package/src/wirings/rpc/wire-remote-addon.ts +57 -0
- package/src/wirings/scope/index.ts +14 -0
- package/src/wirings/scope/scope.test.ts +135 -0
- package/src/wirings/scope/scope.types.ts +44 -0
- package/src/wirings/scope/validate-scope-definitions.ts +110 -0
- package/src/wirings/scope/wire-scope.ts +34 -0
- package/src/wirings/secret/secret.types.ts +14 -0
- package/src/wirings/secret/validate-secret-definitions.ts +2 -0
- package/src/wirings/variable/validate-variable-definitions.ts +2 -0
- package/src/wirings/variable/variable.types.ts +14 -0
- package/src/wirings/workflow/dsl/index.ts +4 -0
- package/src/wirings/workflow/dsl/workflow-dsl.types.ts +97 -6
- package/src/wirings/workflow/graph/graph-node.ts +2 -0
- package/src/wirings/workflow/graph/graph-runner.test.ts +58 -0
- package/src/wirings/workflow/graph/graph-runner.ts +3 -0
- package/src/wirings/workflow/graph/wire-workflow-graph.ts +7 -0
- package/src/wirings/workflow/graph/workflow-graph.types.ts +5 -0
- package/src/wirings/workflow/index.ts +5 -0
- package/src/wirings/workflow/pikku-workflow-service.test.ts +341 -0
- package/src/wirings/workflow/pikku-workflow-service.ts +272 -0
- package/src/wirings/workflow/workflow-on-error.test.ts +154 -0
- package/src/wirings/workflow/workflow-step-session.test.ts +21 -5
- package/src/wirings/workflow/workflow.types.ts +4 -2
- package/tsconfig.tsbuildinfo +1 -1
- package/src/wirings/oauth2/oauth2-client.test.ts +0 -930
- package/src/wirings/oauth2/oauth2-client.ts +0 -331
- package/src/wirings/oauth2/oauth2-routes.ts +0 -234
package/dist/permissions.js
CHANGED
|
@@ -1,18 +1,26 @@
|
|
|
1
1
|
import { pikkuState } from './pikku-state.js';
|
|
2
2
|
import { ForbiddenError } from './errors/errors.js';
|
|
3
|
-
import { freezeDedupe, getTagGroups } from './utils.js';
|
|
4
3
|
/**
|
|
5
|
-
*
|
|
4
|
+
* Evaluates a single permission group. A group ORs its branches together and
|
|
5
|
+
* ANDs the entries within a branch: the group passes if at least one branch
|
|
6
|
+
* (an array of permission functions, all of which must return true — or a lone
|
|
7
|
+
* function) is satisfied.
|
|
8
|
+
*
|
|
9
|
+
* This is the only place OR lives in authorization. Everything cross-cutting —
|
|
10
|
+
* global permissions, scopes, and auth — ANDs together; a function's own
|
|
11
|
+
* `permissions` group is the sole place where "owner OR admin"-style
|
|
12
|
+
* alternatives are expressed.
|
|
13
|
+
*
|
|
14
|
+
* @param permissions - The permission group to evaluate.
|
|
6
15
|
* @param services - The core services required for permission validation.
|
|
7
|
-
* @param data - The data to
|
|
16
|
+
* @param data - The request data passed to each permission function.
|
|
8
17
|
* @param wire - The wire object containing request/response context and session.
|
|
9
|
-
* @returns A promise
|
|
18
|
+
* @returns A promise resolving to true if the group is satisfied.
|
|
10
19
|
*/
|
|
11
20
|
const verifyPermissions = async (permissions, services, data, wire) => {
|
|
12
21
|
if (!permissions) {
|
|
13
22
|
return true;
|
|
14
23
|
}
|
|
15
|
-
let valid = false;
|
|
16
24
|
const permissionGroups = Object.values(permissions);
|
|
17
25
|
if (permissionGroups.length === 0) {
|
|
18
26
|
return true;
|
|
@@ -21,61 +29,33 @@ const verifyPermissions = async (permissions, services, data, wire) => {
|
|
|
21
29
|
if (funcs instanceof Array) {
|
|
22
30
|
const permissioned = await Promise.all(funcs.map((func) => func(services, data, wire)));
|
|
23
31
|
if (permissioned.every((result) => result)) {
|
|
24
|
-
|
|
32
|
+
return true;
|
|
25
33
|
}
|
|
26
34
|
}
|
|
27
35
|
else {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return true;
|
|
36
|
+
if (await funcs(services, data, wire)) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
32
39
|
}
|
|
33
40
|
}
|
|
34
41
|
return false;
|
|
35
42
|
};
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
* It's used internally by the framework to resolve permission references in metadata.
|
|
41
|
-
*
|
|
42
|
-
* @param {string} name - The unique name (pikkuFuncId) of the permission function.
|
|
43
|
-
* @returns {CorePikkuPermission | undefined} The permission function, or undefined if not found.
|
|
44
|
-
*
|
|
45
|
-
* @internal
|
|
46
|
-
*/
|
|
47
|
-
const getPermissionByName = (name) => {
|
|
48
|
-
const permissionStore = pikkuState(null, 'misc', 'permissions');
|
|
49
|
-
const permission = permissionStore[name];
|
|
50
|
-
if (Array.isArray(permission) && permission.length === 1) {
|
|
51
|
-
return permission[0];
|
|
52
|
-
}
|
|
53
|
-
return undefined;
|
|
54
|
-
};
|
|
55
|
-
/**
|
|
56
|
-
* Registers tag-scoped permissions. Applies to any wiring that carries the
|
|
57
|
-
* matching tag.
|
|
58
|
-
*
|
|
59
|
-
* For tree-shaking, wrap in a factory:
|
|
60
|
-
* `export const x = () => addTagPermission('tag', [...])`
|
|
61
|
-
*
|
|
62
|
-
* @example
|
|
63
|
-
* export const adminPermissions = () => addTagPermission('admin', [adminPermission])
|
|
64
|
-
*/
|
|
65
|
-
export const addTagPermission = (tag, permissions, packageName = null) => {
|
|
66
|
-
const tagGroups = pikkuState(packageName, 'permissions', 'tagGroup');
|
|
67
|
-
if (tagGroups[tag]) {
|
|
68
|
-
throw new Error(`Permissions for tag '${tag}' already exist. Use a different tag or remove the existing permissions first.`);
|
|
43
|
+
const globalPermissionsCache = {};
|
|
44
|
+
export const clearPermissionsCache = () => {
|
|
45
|
+
for (const key of Object.keys(globalPermissionsCache)) {
|
|
46
|
+
delete globalPermissionsCache[key];
|
|
69
47
|
}
|
|
70
|
-
tagGroups[tag] = permissions;
|
|
71
|
-
return permissions;
|
|
72
48
|
};
|
|
73
49
|
/**
|
|
74
|
-
* Registers wire-agnostic global permissions.
|
|
75
|
-
*
|
|
76
|
-
*
|
|
50
|
+
* Registers wire-agnostic global permissions. Global permissions are an AND
|
|
51
|
+
* gate: every registered requirement must pass on every function invocation,
|
|
52
|
+
* regardless of transport. A requirement may be a single permission function
|
|
53
|
+
* or a permission group (in which case that group ORs internally, but the
|
|
54
|
+
* group as a whole must still pass).
|
|
77
55
|
*
|
|
78
|
-
*
|
|
56
|
+
* Global permissions never satisfy a function's own `permissions` — the two
|
|
57
|
+
* are independent gates that both have to pass, so a broad global can only
|
|
58
|
+
* ever narrow access.
|
|
79
59
|
*
|
|
80
60
|
* @example
|
|
81
61
|
* addGlobalPermission([signedInUser])
|
|
@@ -88,188 +68,101 @@ export const addGlobalPermission = (permissions, packageName = null) => {
|
|
|
88
68
|
else {
|
|
89
69
|
state.push(permissions);
|
|
90
70
|
}
|
|
71
|
+
clearPermissionsCache();
|
|
91
72
|
return permissions;
|
|
92
73
|
};
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
workflow: {},
|
|
104
|
-
gateway: {},
|
|
74
|
+
/**
|
|
75
|
+
* @deprecated Tag-level permissions were removed in #972 — permissions are now
|
|
76
|
+
* function-scoped only (declare them on the function via `pikkuFunc({ permissions })`).
|
|
77
|
+
* This throwing stub exists solely so the pinned bootstrap CLI (which still
|
|
78
|
+
* generates an `addTagPermission` wrapper) can resolve the import at build time;
|
|
79
|
+
* it is never called. Delete once `PIKKU_CLI_VERSION` in the CLI build is bumped
|
|
80
|
+
* past the release that removes tag permissions.
|
|
81
|
+
*/
|
|
82
|
+
export const addTagPermission = (_tag, _permissions, _packageName = null) => {
|
|
83
|
+
throw new Error('addTagPermission was removed in #972 — tag-level permissions no longer exist. Declare permissions on the function definition instead: pikkuFunc({ permissions }).');
|
|
105
84
|
};
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
85
|
+
/**
|
|
86
|
+
* Resolves the registered global permission requirements for a package,
|
|
87
|
+
* caching the resolved array per package. The cache is keyed by package name
|
|
88
|
+
* (an empty string for the root package) so packages never collide, and it is
|
|
89
|
+
* cleared whenever globals are registered or on hot reload.
|
|
90
|
+
*/
|
|
91
|
+
const resolveGlobalPermissions = (packageName) => {
|
|
92
|
+
const key = packageName ?? '';
|
|
93
|
+
const cached = globalPermissionsCache[key];
|
|
94
|
+
if (cached) {
|
|
95
|
+
return cached;
|
|
109
96
|
}
|
|
97
|
+
const globals = pikkuState(packageName, 'permissions', 'global');
|
|
98
|
+
const resolved = globals && globals.length > 0 ? [...globals] : [];
|
|
99
|
+
globalPermissionsCache[key] = resolved;
|
|
100
|
+
return resolved;
|
|
110
101
|
};
|
|
102
|
+
const asGroup = (entry) => typeof entry === 'function' ? { permission: entry } : entry;
|
|
111
103
|
/**
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
* This function resolves permission metadata into actual permission functions and combines them.
|
|
115
|
-
* It filters out wire permissions without tags from inheritedPermissions to avoid duplication
|
|
116
|
-
* (those are passed separately as wirePermissions).
|
|
104
|
+
* Runs authorization for a function invocation. Two independent gates, both of
|
|
105
|
+
* which must pass:
|
|
117
106
|
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
* @param {PermissionMetadata[] | undefined} options.funcInheritedPermissions - Function permissions metadata (only tags).
|
|
122
|
-
* @param {CorePermissionGroup | CorePikkuPermission[] | undefined} options.funcPermissions - Inline function permissions.
|
|
123
|
-
* @returns {(CorePermissionGroup | CorePikkuPermission)[]} Combined array of resolved permissions.
|
|
107
|
+
* 1. Global permissions — AND. Every registered global requirement must pass.
|
|
108
|
+
* 2. Function permissions — OR. The function's own `permissions` group must be
|
|
109
|
+
* satisfied (see {@link verifyPermissions}).
|
|
124
110
|
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
* const combined = combinePermissions(wireType, wireId, {
|
|
128
|
-
* wireInheritedPermissions: meta.permissions,
|
|
129
|
-
* wirePermissions: inlinePermissions,
|
|
130
|
-
* funcInheritedPermissions: funcMeta.permissions,
|
|
131
|
-
* funcPermissions: funcConfig.permissions
|
|
132
|
-
* })
|
|
133
|
-
* ```
|
|
111
|
+
* A passing global requirement never contributes to the function gate, so a
|
|
112
|
+
* broad global like `signedIn` can't satisfy an admin-only function.
|
|
134
113
|
*/
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
if (globals && globals.length > 0) {
|
|
142
|
-
resolved.push(...globals);
|
|
143
|
-
}
|
|
144
|
-
if (wireInheritedPermissions) {
|
|
145
|
-
for (const meta of wireInheritedPermissions) {
|
|
146
|
-
if (meta.type === 'http') {
|
|
147
|
-
// Look up HTTP permission group from pikkuState
|
|
148
|
-
const group = pikkuState(packageName, 'permissions', 'httpGroup')[meta.route];
|
|
149
|
-
if (group) {
|
|
150
|
-
if (Array.isArray(group)) {
|
|
151
|
-
resolved.push(...group);
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
resolved.push(group);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
else if (meta.type === 'tag') {
|
|
159
|
-
const groups = getTagGroups(pikkuState(packageName, 'permissions', 'tagGroup'), meta.tag);
|
|
160
|
-
for (const group of groups) {
|
|
161
|
-
if (Array.isArray(group)) {
|
|
162
|
-
resolved.push(...group);
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
resolved.push(group);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
else if (meta.type === 'wire') {
|
|
170
|
-
// Individual wire permission (exported, not inline)
|
|
171
|
-
const permission = getPermissionByName(meta.name);
|
|
172
|
-
if (permission) {
|
|
173
|
-
resolved.push(permission);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
// 2. Add inline wire permissions
|
|
179
|
-
if (wirePermissions) {
|
|
180
|
-
if (Array.isArray(wirePermissions)) {
|
|
181
|
-
resolved.push(...wirePermissions);
|
|
182
|
-
}
|
|
183
|
-
else {
|
|
184
|
-
resolved.push(wirePermissions);
|
|
114
|
+
export const runPermissions = async ({ funcPermissions, services, wire, data, packageName = null, label = 'function', }) => {
|
|
115
|
+
const globals = resolveGlobalPermissions(packageName);
|
|
116
|
+
for (const entry of globals) {
|
|
117
|
+
if (!(await verifyPermissions(asGroup(entry), services, data, wire))) {
|
|
118
|
+
services.logger.debug('Permission denied - global permission');
|
|
119
|
+
throw new ForbiddenError('Permission denied');
|
|
185
120
|
}
|
|
186
121
|
}
|
|
187
|
-
// 3. Resolve function inherited permissions (only tags, wire permissions already handled)
|
|
188
|
-
if (funcInheritedPermissions) {
|
|
189
|
-
for (const meta of funcInheritedPermissions) {
|
|
190
|
-
if (meta.type === 'tag') {
|
|
191
|
-
const groups = getTagGroups(pikkuState(packageName, 'permissions', 'tagGroup'), meta.tag);
|
|
192
|
-
for (const group of groups) {
|
|
193
|
-
if (Array.isArray(group)) {
|
|
194
|
-
resolved.push(...group);
|
|
195
|
-
}
|
|
196
|
-
else {
|
|
197
|
-
resolved.push(group);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
// Note: wire permissions are already handled in wireInheritedPermissions
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
// 4. Add inline function permissions
|
|
205
122
|
if (funcPermissions) {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
// Deduplicate and freeze
|
|
214
|
-
combinedPermissionsCache[wireType][uid] = freezeDedupe(resolved);
|
|
215
|
-
return combinedPermissionsCache[wireType][uid];
|
|
216
|
-
};
|
|
217
|
-
/**
|
|
218
|
-
* Runs permission checks using combined permissions from all sources.
|
|
219
|
-
* Combines permissions from wire and function levels, then validates them.
|
|
220
|
-
*/
|
|
221
|
-
export const runPermissions = async (wireType, uid, { wireInheritedPermissions, wirePermissions, funcInheritedPermissions, funcPermissions, services, wire, data, packageName = null, }) => {
|
|
222
|
-
// Combine all permissions: wireInheritedPermissions → wirePermissions → funcInheritedPermissions → funcPermissions
|
|
223
|
-
const allPermissions = combinePermissions(wireType, uid, {
|
|
224
|
-
wireInheritedPermissions,
|
|
225
|
-
wirePermissions,
|
|
226
|
-
funcInheritedPermissions,
|
|
227
|
-
funcPermissions,
|
|
228
|
-
packageName,
|
|
229
|
-
});
|
|
230
|
-
// Check all combined permissions - at least one must pass if any exist
|
|
231
|
-
if (allPermissions.length > 0) {
|
|
232
|
-
for (const permission of allPermissions) {
|
|
233
|
-
const result = await verifyPermissions(typeof permission === 'function' ? { permission } : permission, services, data, wire);
|
|
234
|
-
if (result) {
|
|
235
|
-
return;
|
|
123
|
+
const group = Array.isArray(funcPermissions)
|
|
124
|
+
? { permissions: funcPermissions }
|
|
125
|
+
: funcPermissions;
|
|
126
|
+
if (group && Object.keys(group).length > 0) {
|
|
127
|
+
if (!(await verifyPermissions(group, services, data, wire))) {
|
|
128
|
+
services.logger.debug(`Permission denied - ${label} permission`);
|
|
129
|
+
throw new ForbiddenError('Permission denied');
|
|
236
130
|
}
|
|
237
131
|
}
|
|
238
|
-
services.logger.debug('Permission denied - combined permissions');
|
|
239
|
-
throw new ForbiddenError('Permission denied');
|
|
240
132
|
}
|
|
241
133
|
};
|
|
242
134
|
/**
|
|
243
135
|
* Checks whether a session passes the auth checks (pikkuAuth only) for a
|
|
244
136
|
* given function/agent. Skips pikkuPermission checks since those require
|
|
245
|
-
* request data which isn't available at filter time.
|
|
137
|
+
* request data which isn't available at filter time. Global auth requirements
|
|
138
|
+
* are included so a filtered list honours app-wide auth.
|
|
246
139
|
*
|
|
247
|
-
*
|
|
140
|
+
* `funcPermissions` is the live {@link CorePermissionGroup} from the function or
|
|
141
|
+
* agent config, not the metadata form: the `pikkuAuth` brand only survives on
|
|
142
|
+
* the actual predicate objects, and the by-name registry those metadata entries
|
|
143
|
+
* would resolve against is never populated. Passing metadata here would silently
|
|
144
|
+
* collect nothing and let every gated tool through.
|
|
145
|
+
*
|
|
146
|
+
* @param funcPermissions - The live permission group from the func/agent config
|
|
248
147
|
* @param session - The user's session
|
|
249
148
|
* @param services - Singleton services
|
|
250
149
|
* @param packageName - Optional package namespace
|
|
251
|
-
* @returns true if the session passes
|
|
150
|
+
* @returns true if the session passes the auth checks (or no auth checks exist)
|
|
252
151
|
*/
|
|
253
152
|
export const checkAuthPermissions = async (funcPermissions, session, services, packageName = null) => {
|
|
254
|
-
if (!funcPermissions?.length)
|
|
255
|
-
return true;
|
|
256
|
-
const allPermissions = combinePermissions('agent', `authcheck:${Math.random()}`, {
|
|
257
|
-
funcInheritedPermissions: funcPermissions,
|
|
258
|
-
packageName,
|
|
259
|
-
});
|
|
260
|
-
if (allPermissions.length === 0)
|
|
261
|
-
return true;
|
|
262
153
|
const wire = { session };
|
|
263
|
-
//
|
|
154
|
+
// Collect auth-only (pikkuAuth) predicates from globals and the function's
|
|
155
|
+
// referenced permissions. Data-dependent permissions are ignored — they
|
|
156
|
+
// can't be evaluated without request data at filter time.
|
|
264
157
|
const authPerms = [];
|
|
265
|
-
|
|
266
|
-
if (typeof
|
|
267
|
-
if (
|
|
268
|
-
authPerms.push(
|
|
158
|
+
const collect = (perm) => {
|
|
159
|
+
if (typeof perm === 'function') {
|
|
160
|
+
if (perm.__pikkuAuth) {
|
|
161
|
+
authPerms.push(perm);
|
|
269
162
|
}
|
|
270
163
|
}
|
|
271
|
-
else if (
|
|
272
|
-
for (const funcs of Object.values(
|
|
164
|
+
else if (perm && typeof perm === 'object') {
|
|
165
|
+
for (const funcs of Object.values(perm)) {
|
|
273
166
|
const arr = Array.isArray(funcs) ? funcs : [funcs];
|
|
274
167
|
for (const fn of arr) {
|
|
275
168
|
if (typeof fn === 'function' && fn.__pikkuAuth) {
|
|
@@ -278,11 +171,16 @@ export const checkAuthPermissions = async (funcPermissions, session, services, p
|
|
|
278
171
|
}
|
|
279
172
|
}
|
|
280
173
|
}
|
|
174
|
+
};
|
|
175
|
+
for (const entry of resolveGlobalPermissions(packageName)) {
|
|
176
|
+
collect(entry);
|
|
177
|
+
}
|
|
178
|
+
if (funcPermissions) {
|
|
179
|
+
collect(funcPermissions);
|
|
281
180
|
}
|
|
282
181
|
// No auth permissions = allowed (only data-dependent permissions exist)
|
|
283
182
|
if (authPerms.length === 0)
|
|
284
183
|
return true;
|
|
285
|
-
// All auth permissions must pass
|
|
286
184
|
for (const perm of authPerms) {
|
|
287
185
|
const result = await perm(services, null, wire);
|
|
288
186
|
if (result)
|
package/dist/pikku-state.js
CHANGED
package/dist/scopes.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { CoreUserSession } from './types/core.types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Verifies that a session holds every required scope, throwing on the first
|
|
4
|
+
* one it does not.
|
|
5
|
+
*
|
|
6
|
+
* Scopes are an AND gate: every entry in `required` must be satisfied. This is
|
|
7
|
+
* deliberately distinct from `permissions`, which OR together — a scope can
|
|
8
|
+
* only ever narrow access, so adding one to a function can never widen it.
|
|
9
|
+
*
|
|
10
|
+
* Fails closed: a session without a `scopes` field, or no session at all,
|
|
11
|
+
* satisfies nothing.
|
|
12
|
+
*
|
|
13
|
+
* @param required - Scopes the function declares. Empty means no gate.
|
|
14
|
+
* @param session - The session to check. May be undefined.
|
|
15
|
+
* @throws {MissingScopeError} Naming the first unsatisfied scope.
|
|
16
|
+
*/
|
|
17
|
+
export declare const verifyScopes: (required: readonly string[] | undefined, session: CoreUserSession | undefined) => void;
|
package/dist/scopes.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { MissingScopeError } from './errors/errors.js';
|
|
2
|
+
const SEPARATOR = ':';
|
|
3
|
+
const WILDCARD = '*';
|
|
4
|
+
/**
|
|
5
|
+
* Builds every grant that would satisfy `scope`: the scope itself, a wildcard
|
|
6
|
+
* directly beneath it, a wildcard at each ancestor level, and each plain
|
|
7
|
+
* ancestor id — holding a parent scope grants everything nested beneath it.
|
|
8
|
+
*
|
|
9
|
+
* For `admin:invoices:create` that is:
|
|
10
|
+
* admin:invoices:create, admin:invoices:create:*, *, admin:*, admin:invoices:*,
|
|
11
|
+
* admin, admin:invoices
|
|
12
|
+
*/
|
|
13
|
+
const satisfyingGrants = (scope) => {
|
|
14
|
+
const segments = scope.split(SEPARATOR);
|
|
15
|
+
const grants = [scope, `${scope}${SEPARATOR}${WILDCARD}`];
|
|
16
|
+
for (let i = 0; i < segments.length; i++) {
|
|
17
|
+
grants.push([...segments.slice(0, i), WILDCARD].join(SEPARATOR));
|
|
18
|
+
}
|
|
19
|
+
for (let i = 1; i < segments.length; i++) {
|
|
20
|
+
grants.push(segments.slice(0, i).join(SEPARATOR));
|
|
21
|
+
}
|
|
22
|
+
return grants;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Checks whether `held` satisfies a single required scope.
|
|
26
|
+
*
|
|
27
|
+
* A grant satisfies a requirement when it is the scope itself, a plain ancestor
|
|
28
|
+
* (`admin` covers `admin:invoices:create`), a wildcard at or above it (`admin:*`
|
|
29
|
+
* covers `admin` and `admin:invoices:create`), or the bare `*`. A narrower grant
|
|
30
|
+
* never satisfies a broader requirement — `admin:invoices` does not grant
|
|
31
|
+
* `admin`.
|
|
32
|
+
*/
|
|
33
|
+
const holds = (held, scope) => satisfyingGrants(scope).some((grant) => held.has(grant));
|
|
34
|
+
/**
|
|
35
|
+
* Verifies that a session holds every required scope, throwing on the first
|
|
36
|
+
* one it does not.
|
|
37
|
+
*
|
|
38
|
+
* Scopes are an AND gate: every entry in `required` must be satisfied. This is
|
|
39
|
+
* deliberately distinct from `permissions`, which OR together — a scope can
|
|
40
|
+
* only ever narrow access, so adding one to a function can never widen it.
|
|
41
|
+
*
|
|
42
|
+
* Fails closed: a session without a `scopes` field, or no session at all,
|
|
43
|
+
* satisfies nothing.
|
|
44
|
+
*
|
|
45
|
+
* @param required - Scopes the function declares. Empty means no gate.
|
|
46
|
+
* @param session - The session to check. May be undefined.
|
|
47
|
+
* @throws {MissingScopeError} Naming the first unsatisfied scope.
|
|
48
|
+
*/
|
|
49
|
+
export const verifyScopes = (required, session) => {
|
|
50
|
+
if (!required || required.length === 0) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const held = new Set(session?.scopes ?? []);
|
|
54
|
+
for (const scope of required) {
|
|
55
|
+
if (!holds(held, scope)) {
|
|
56
|
+
throw new MissingScopeError(scope);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A narrow, dedicated embedding service.
|
|
3
|
+
*
|
|
4
|
+
* Vector stores (Qdrant, Pinecone, Supabase/pgvector, …) depend on this to turn
|
|
5
|
+
* text into vectors, at BOTH index time (ingest) and query time (search). The
|
|
6
|
+
* embedding model is fixed at construction so those two moments cannot drift
|
|
7
|
+
* into different vector spaces — a mismatch would silently break similarity
|
|
8
|
+
* search. Provider addons (e.g. `@pikku/addon-openai`) implement it; the app
|
|
9
|
+
* wires a single instance into `singletonServices.aiEmbedding`.
|
|
10
|
+
*
|
|
11
|
+
* This is deliberately smaller than {@link AIAgentRunnerService} (whose optional
|
|
12
|
+
* `embed`/`embedMany` take a per-call model): a vector store should not have to
|
|
13
|
+
* pull in the whole agent-runner tool loop just to embed, and pinning the model
|
|
14
|
+
* to the service is what guarantees index/query consistency.
|
|
15
|
+
*
|
|
16
|
+
* Documents (ingested corpus) and queries (search text) are embedded through
|
|
17
|
+
* separate methods because some models are asymmetric — Cohere's `input_type`,
|
|
18
|
+
* E5's `query:`/`passage:` prefixes, BGE's query instruction — and must know
|
|
19
|
+
* which side they are embedding to produce comparable vectors. Symmetric
|
|
20
|
+
* providers (e.g. OpenAI) point both methods at the same call.
|
|
21
|
+
*/
|
|
22
|
+
export interface AIEmbeddingService {
|
|
23
|
+
/** The embedding model backing this service. Index and query share it. */
|
|
24
|
+
readonly model: string;
|
|
25
|
+
/** The vector dimensionality this model produces, when known. */
|
|
26
|
+
readonly dimensions?: number;
|
|
27
|
+
/** Embed corpus documents (index time), preserving input order. */
|
|
28
|
+
embedDocuments(values: string[]): Promise<number[][]>;
|
|
29
|
+
/** Embed a search query (query time) into a vector. */
|
|
30
|
+
embedQuery(value: string): Promise<number[]>;
|
|
31
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -3,10 +3,12 @@ import type { PikkuRawWire } from '../types/core.types.js';
|
|
|
3
3
|
export declare class PikkuCredentialWireService {
|
|
4
4
|
private credentialService?;
|
|
5
5
|
private wire?;
|
|
6
|
+
private aliases?;
|
|
6
7
|
private credentials;
|
|
7
8
|
private loaded;
|
|
8
9
|
private loadPromise;
|
|
9
|
-
constructor(credentialService?: CredentialService | undefined, wire?: PikkuRawWire | undefined);
|
|
10
|
+
constructor(credentialService?: CredentialService | undefined, wire?: PikkuRawWire | undefined, aliases?: Record<string, string> | undefined);
|
|
11
|
+
private resolveName;
|
|
10
12
|
set(name: string, value: unknown): void;
|
|
11
13
|
get<T = unknown>(name: string): T | null | Promise<T | null>;
|
|
12
14
|
getAll(): Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
@@ -2,20 +2,26 @@ import { defaultPikkuUserIdResolver } from './pikku-user-id.js';
|
|
|
2
2
|
export class PikkuCredentialWireService {
|
|
3
3
|
credentialService;
|
|
4
4
|
wire;
|
|
5
|
+
aliases;
|
|
5
6
|
credentials = {};
|
|
6
7
|
loaded = false;
|
|
7
8
|
loadPromise;
|
|
8
|
-
constructor(credentialService, wire) {
|
|
9
|
+
constructor(credentialService, wire, aliases) {
|
|
9
10
|
this.credentialService = credentialService;
|
|
10
11
|
this.wire = wire;
|
|
12
|
+
this.aliases = aliases;
|
|
13
|
+
}
|
|
14
|
+
resolveName(name) {
|
|
15
|
+
return this.aliases?.[name] ?? name;
|
|
11
16
|
}
|
|
12
17
|
set(name, value) {
|
|
13
|
-
this.credentials[name] = value;
|
|
18
|
+
this.credentials[this.resolveName(name)] = value;
|
|
14
19
|
}
|
|
15
20
|
get(name) {
|
|
21
|
+
const key = this.resolveName(name);
|
|
16
22
|
if (this.loaded)
|
|
17
|
-
return this.credentials[
|
|
18
|
-
return this.lazyLoad().then(() => this.credentials[
|
|
23
|
+
return this.credentials[key] ?? null;
|
|
24
|
+
return this.lazyLoad().then(() => this.credentials[key] ?? null);
|
|
19
25
|
}
|
|
20
26
|
getAll() {
|
|
21
27
|
if (this.loaded)
|
package/dist/services/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export { LocalCredentialService } from './local-credential-service.js';
|
|
|
13
13
|
export { LocalVariablesService } from './local-variables.js';
|
|
14
14
|
export { ConsoleLogger, JsonConsoleLogger } from './logger-console.js';
|
|
15
15
|
export { InMemoryWorkflowService } from './in-memory-workflow-service.js';
|
|
16
|
+
export { QueueWebhookService, pikkuWebhookWorkerFunc, } from './queue-webhook-service.js';
|
|
16
17
|
export { InMemoryQueueService } from './in-memory-queue-service.js';
|
|
17
18
|
export { InMemoryTriggerService } from './in-memory-trigger-service.js';
|
|
18
19
|
export { InMemoryAIRunStateService } from './in-memory-ai-run-state-service.js';
|
|
@@ -22,6 +23,7 @@ export type { ScenarioActor, ScenarioActorConfig, ScenarioActors, } from './scen
|
|
|
22
23
|
export { HttpScenarioActor, createHttpScenarioActors, type HttpScenarioActorsConfig, } from './http-scenario-actors.js';
|
|
23
24
|
export type { JWTService } from './jwt-service.js';
|
|
24
25
|
export type { EmailService, EmailTemplateReference, SendEmailInput, SendEmailResult, SendHTMLEmailInput, SendTemplateEmailInput, SendTextEmailInput, } from './email-service.js';
|
|
26
|
+
export { DEFAULT_WEBHOOK_RETRIES, DEFAULT_WEBHOOK_SIGNATURE_HEADER, PIKKU_OUTGOING_WEBHOOK_QUEUE_NAME, WebhookService, type SendWebhookInput, type SendWebhookResult, type WebhookAttemptRecord, type WebhookAttemptResult, type WebhookDeliveryRecord, type WebhookDeliveryWithAttempts, type WebhookJobData, type WebhookServiceConfig, } from './webhook-service.js';
|
|
25
27
|
export type { Logger } from './logger.js';
|
|
26
28
|
export type { SecretService } from './secret-service.js';
|
|
27
29
|
export type { VariablesService } from './variables-service.js';
|
|
@@ -33,6 +35,7 @@ export type { GatewayService } from './gateway-service.js';
|
|
|
33
35
|
export type { DeploymentService, DeploymentConfig, DeploymentInfo, DeploymentServiceConfig, } from './deployment-service.js';
|
|
34
36
|
export type { AIStorageService } from './ai-storage-service.js';
|
|
35
37
|
export type { AIAgentRunnerParams, AIAgentRunnerResult, AIAgentStepResult, AIEmbedManyParams, AIEmbedManyResult, AIEmbedParams, AIEmbedResult, AIGenerateImageParams, AIGenerateImagePrompt, AIGenerateImageResult, AIGenerateSpeechParams, AIGenerateSpeechResult, AIProviderOptions, AIRerankParams, AIRerankResult, AITranscriptionParams, AITranscriptionResult, AIAgentRunnerService, } from './ai-agent-runner-service.js';
|
|
38
|
+
export type { AIEmbeddingService } from './ai-embedding-service.js';
|
|
36
39
|
export type { CreateRunInput, AIRunStateService, } from './ai-run-state-service.js';
|
|
37
40
|
export type { CredentialStatus, CredentialMeta, } from './typed-secret-service.js';
|
|
38
41
|
export type { CredentialService } from './credential-service.js';
|
|
@@ -41,6 +44,7 @@ export type { CredentialStatusInfo, CredentialMetaInfo, } from './typed-credenti
|
|
|
41
44
|
export type { VariableStatus, VariableMeta } from './typed-variables-service.js';
|
|
42
45
|
export type { MetaService } from './meta-service.js';
|
|
43
46
|
export type { SessionStore } from './session-store.js';
|
|
47
|
+
export type { ScopeService, Role } from './scope-service.js';
|
|
44
48
|
export { NoopAuditService, createInvocationAudit, resolveAuditActorFromWire, resolveAuditConfig, } from './audit-service.js';
|
|
45
49
|
export type { AuditActor, AuditConfig, AuditDurability, AuditEvent, AuditEventBatch, AuditLog, AuditLogWriteInput, AuditOutcome, AuditService, AuditSource, ResolvedAuditConfig, } from './audit-service.js';
|
|
46
50
|
export { InMemorySessionStore } from './in-memory-session-store.js';
|
package/dist/services/index.js
CHANGED
|
@@ -13,11 +13,13 @@ export { LocalCredentialService } from './local-credential-service.js';
|
|
|
13
13
|
export { LocalVariablesService } from './local-variables.js';
|
|
14
14
|
export { ConsoleLogger, JsonConsoleLogger } from './logger-console.js';
|
|
15
15
|
export { InMemoryWorkflowService } from './in-memory-workflow-service.js';
|
|
16
|
+
export { QueueWebhookService, pikkuWebhookWorkerFunc, } from './queue-webhook-service.js';
|
|
16
17
|
export { InMemoryQueueService } from './in-memory-queue-service.js';
|
|
17
18
|
export { InMemoryTriggerService } from './in-memory-trigger-service.js';
|
|
18
19
|
export { InMemoryAIRunStateService } from './in-memory-ai-run-state-service.js';
|
|
19
20
|
export { LocalGatewayService } from './local-gateway-service.js';
|
|
20
21
|
export { HttpScenarioActor, createHttpScenarioActors, } from './http-scenario-actors.js';
|
|
22
|
+
export { DEFAULT_WEBHOOK_RETRIES, DEFAULT_WEBHOOK_SIGNATURE_HEADER, PIKKU_OUTGOING_WEBHOOK_QUEUE_NAME, WebhookService, } from './webhook-service.js';
|
|
21
23
|
export { TypedCredentialService } from './typed-credential-service.js';
|
|
22
24
|
export { NoopAuditService, createInvocationAudit, resolveAuditActorFromWire, resolveAuditConfig, } from './audit-service.js';
|
|
23
25
|
export { InMemorySessionStore } from './in-memory-session-store.js';
|
|
@@ -85,8 +85,6 @@ export interface PermissionDefinitionMeta {
|
|
|
85
85
|
}
|
|
86
86
|
export interface PermissionsGroupsMeta {
|
|
87
87
|
definitions: Record<string, PermissionDefinitionMeta>;
|
|
88
|
-
httpGroups: Record<string, GroupMeta>;
|
|
89
|
-
tagGroups: Record<string, GroupMeta>;
|
|
90
88
|
}
|
|
91
89
|
export interface EmailTemplateLocaleMeta {
|
|
92
90
|
contentHash: string;
|
|
@@ -132,6 +130,17 @@ export interface MetaService {
|
|
|
132
130
|
readDir(relativePath: string): Promise<string[]>;
|
|
133
131
|
/** Read a project source file relative to the project root (one level above .pikku). */
|
|
134
132
|
readProjectFile(relativePath: string): Promise<string | null>;
|
|
133
|
+
/**
|
|
134
|
+
* Read a file from an *installed addon package's* own `.pikku` directory
|
|
135
|
+
* (resolved from node_modules), NOT the app's `.pikku`. `relativePath` is
|
|
136
|
+
* relative to that package's `.pikku` root (use `../` to reach the package
|
|
137
|
+
* root itself, e.g. `../README.md`). Returns null if the package or file is
|
|
138
|
+
* absent. Only local/Node implementations resolve packages; remote impls omit
|
|
139
|
+
* this and callers guard with `?.`.
|
|
140
|
+
*/
|
|
141
|
+
readPackageFile?(packageName: string, relativePath: string): Promise<string | null>;
|
|
142
|
+
/** List a directory inside an installed addon package's `.pikku`. */
|
|
143
|
+
readPackageDir?(packageName: string, relativePath: string): Promise<string[]>;
|
|
135
144
|
getHttpMeta(): Promise<HTTPWiringsMeta>;
|
|
136
145
|
getChannelsMeta(): Promise<ChannelsMeta>;
|
|
137
146
|
getSchedulerMeta(): Promise<ScheduledTasksMeta>;
|
|
@@ -189,6 +198,10 @@ export declare class LocalMetaService implements MetaService {
|
|
|
189
198
|
readFile(relativePath: string): Promise<string | null>;
|
|
190
199
|
readDir(relativePath: string): Promise<string[]>;
|
|
191
200
|
readProjectFile(relativePath: string): Promise<string | null>;
|
|
201
|
+
private packageRootCache;
|
|
202
|
+
private resolvePackageRoot;
|
|
203
|
+
readPackageFile(packageName: string, relativePath: string): Promise<string | null>;
|
|
204
|
+
readPackageDir(packageName: string, relativePath: string): Promise<string[]>;
|
|
192
205
|
clearCache(): void;
|
|
193
206
|
private readMetaJson;
|
|
194
207
|
getHttpMeta(): Promise<HTTPWiringsMeta>;
|