@alfe.ai/openclaw-identity 0.0.10 → 0.0.12
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/dist/index.cjs +26 -1
- package/dist/index.d.cts +146 -1
- package/dist/index.d.ts +146 -1
- package/dist/index.js +21 -1
- package/dist/plugin2.cjs +192 -223
- package/dist/plugin2.js +192 -223
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,27 @@
|
|
|
1
|
+
Object.defineProperties(exports, {
|
|
2
|
+
__esModule: { value: true },
|
|
3
|
+
[Symbol.toStringTag]: { value: "Module" }
|
|
4
|
+
});
|
|
1
5
|
const require_plugin = require("./plugin2.cjs");
|
|
2
|
-
|
|
6
|
+
//#region src/runtime-contract.ts
|
|
7
|
+
/**
|
|
8
|
+
* Build the gate context object used by sift evaluation. This is the
|
|
9
|
+
* round-6 "strict namespacing" shape — `args` is a top-level field, not
|
|
10
|
+
* spread, so an attacker-controlled `tool` field inside `toolArgs` cannot
|
|
11
|
+
* override the gate's `tool` value.
|
|
12
|
+
*
|
|
13
|
+
* Stage E's gate calls:
|
|
14
|
+
* ability.has(
|
|
15
|
+
* { subject: "agent", action: "exec", scope: `agent:${ctx.agentId}` },
|
|
16
|
+
* buildGateContext(event),
|
|
17
|
+
* );
|
|
18
|
+
*/
|
|
19
|
+
function buildGateContext(event) {
|
|
20
|
+
return {
|
|
21
|
+
tool: event.toolName,
|
|
22
|
+
args: event.toolArgs
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
exports.buildGateContext = buildGateContext;
|
|
27
|
+
exports.default = require_plugin.plugin;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,2 +1,147 @@
|
|
|
1
1
|
import plugin from "./plugin.cjs";
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
//#region src/policy-cache.d.ts
|
|
4
|
+
|
|
5
|
+
type IdentityFailureMode = "open" | "closed" | "permissive";
|
|
6
|
+
/**
|
|
7
|
+
* Evaluate whether a tool call should be blocked based on the cached policy
|
|
8
|
+
* and failure mode.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/runtime-contract.d.ts
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The tool the agent is about to call.
|
|
16
|
+
*
|
|
17
|
+
* `toolName` SHOULD be namespaced (e.g., `gmail:send_email`, `calendar:create_event`)
|
|
18
|
+
* so sift `$glob: "gmail:*"` conditions work and namespace collisions are
|
|
19
|
+
* impossible. Plugins that don't yet namespace their tools will be migrated
|
|
20
|
+
* during Stage I rollout.
|
|
21
|
+
*/
|
|
22
|
+
interface ToolCallEvent {
|
|
23
|
+
/** Namespaced tool name, e.g. "gmail:send_email". */
|
|
24
|
+
readonly toolName: string;
|
|
25
|
+
/** Arbitrary argument bag passed to the tool's `execute` function. */
|
|
26
|
+
readonly toolArgs: Record<string, unknown>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* What initiated the tool call. Three buckets:
|
|
30
|
+
* - "user_message" — a human (or another agent) sent a message that the
|
|
31
|
+
* agent is now responding to. `actingIdentityId` is the
|
|
32
|
+
* identity of the message sender.
|
|
33
|
+
* - "scheduled" — autonomous run (cron/trigger). `actingIdentityId` is
|
|
34
|
+
* the agent's own identity (`idn_agt_*`).
|
|
35
|
+
* - "tool_chain" — a follow-up tool call from a previous tool's result
|
|
36
|
+
* within the same agent invocation. `actingIdentityId`
|
|
37
|
+
* is whatever resolved at the start of the chain.
|
|
38
|
+
* - "api" — a tool call invoked via the agent's REST API by an
|
|
39
|
+
* external caller authenticated with an `alfe_*` token.
|
|
40
|
+
* `actingIdentityId` may be undefined; `tokenPermissions`
|
|
41
|
+
* carries the gate-relevant `Permission[]`.
|
|
42
|
+
*/
|
|
43
|
+
type ToolCallTrigger = "user_message" | "scheduled" | "tool_chain" | "api";
|
|
44
|
+
/**
|
|
45
|
+
* How the caller authenticated.
|
|
46
|
+
* - "jwt" — Clerk JWT path (human user). `actingIdentityId` resolved from
|
|
47
|
+
* the JWT's `sub` via the identity service.
|
|
48
|
+
* - "agent" — autonomous agent (no external caller). `actingIdentityId` is
|
|
49
|
+
* the agent's own `idn_agt_*`.
|
|
50
|
+
* - "token" — `alfe_*` API token. `tokenPermissions` is set; the gate uses
|
|
51
|
+
* the token's permissions directly without an identity lookup.
|
|
52
|
+
* - "none" — no auth context (fail-closed in prod via IdentityFailureMode).
|
|
53
|
+
*/
|
|
54
|
+
type ToolCallAuthMethod = "jwt" | "agent" | "token" | "none";
|
|
55
|
+
/**
|
|
56
|
+
* Permission shape the gate consumes. This is a structural duplicate of
|
|
57
|
+
* `Permission` from `@auriclabs/roles@0.1.1` so the openclaw plugin doesn't
|
|
58
|
+
* have to depend on the library directly (the library is consumed inside the
|
|
59
|
+
* gate itself in Stage E). Keep the two shapes in lockstep.
|
|
60
|
+
*/
|
|
61
|
+
interface RuntimePermission {
|
|
62
|
+
readonly subject: string;
|
|
63
|
+
readonly action: string;
|
|
64
|
+
readonly scope?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Round 7 storage shape: sift conditions stored per-permission. The runtime
|
|
67
|
+
* gate evaluates the condition against `{ tool, args }` (round 6 strict
|
|
68
|
+
* namespacing). Glob source travels under `$glob`; the compiled regex
|
|
69
|
+
* travels under `_glob_re` with a `_glob_v` version marker (round 7 audit
|
|
70
|
+
* 3.6 storage shape).
|
|
71
|
+
*/
|
|
72
|
+
readonly conditions?: Record<string, unknown>;
|
|
73
|
+
readonly type?: "can" | "cannot";
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Calling context for the tool call. Populated by the OpenClaw daemon at
|
|
77
|
+
* dispatch time.
|
|
78
|
+
*/
|
|
79
|
+
interface ToolCallContext {
|
|
80
|
+
/** Required: the tenant (`org_*`) that owns the agent. */
|
|
81
|
+
readonly tenantId: string;
|
|
82
|
+
/** Required: the agent (`agt_*`) that is about to call the tool. */
|
|
83
|
+
readonly agentId: string;
|
|
84
|
+
/** Required: how the caller authenticated. */
|
|
85
|
+
readonly authMethod: ToolCallAuthMethod;
|
|
86
|
+
/** Required: what initiated the call. */
|
|
87
|
+
readonly trigger: ToolCallTrigger;
|
|
88
|
+
/**
|
|
89
|
+
* The identity (`idn_*`) the agent is acting on behalf of. Resolution
|
|
90
|
+
* order:
|
|
91
|
+
* 1. If `trigger === "user_message"`: the chat-context identity (sender).
|
|
92
|
+
* 2. If `trigger === "scheduled"` or `trigger === "tool_chain"`: the
|
|
93
|
+
* agent's own `idn_agt_*` (autonomous default).
|
|
94
|
+
* 3. If `authMethod === "token"`: optional; the token-path gate uses
|
|
95
|
+
* `tokenPermissions` and may skip identity resolution entirely.
|
|
96
|
+
* 4. Otherwise: undefined; the per-agent `IdentityFailureMode` decides
|
|
97
|
+
* whether to allow / deny / log-and-continue.
|
|
98
|
+
*/
|
|
99
|
+
readonly actingIdentityId?: string;
|
|
100
|
+
/**
|
|
101
|
+
* Round 5 / Round 7: `alfe_*` tokens carry their own flat `Permission[]`
|
|
102
|
+
* directly. When `authMethod === "token"`, the daemon populates this with
|
|
103
|
+
* `TokenEntity.permissions` (post Stage B.0.7 atomic flip — pre-flip the
|
|
104
|
+
* authorizer derives this from `record.scopes` via `scopesToPermissions`).
|
|
105
|
+
* The Stage E gate evaluates these permissions directly at scope
|
|
106
|
+
* `agent:<agentId>` without an identity lookup.
|
|
107
|
+
*/
|
|
108
|
+
readonly tokenPermissions?: readonly RuntimePermission[];
|
|
109
|
+
/** Optional: chat conversation id (when trigger is `user_message`). */
|
|
110
|
+
readonly conversationId?: string;
|
|
111
|
+
/** Optional: channel id (when trigger is `user_message`). */
|
|
112
|
+
readonly channelId?: string;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Return value of the `before_tool_call` hook.
|
|
116
|
+
* - `undefined` — allow.
|
|
117
|
+
* - `{ block: true, blockReason: string }` — deny with reason surfaced to
|
|
118
|
+
* the agent's response (Stage E behaviour).
|
|
119
|
+
*/
|
|
120
|
+
type ToolCallHookResult = undefined | {
|
|
121
|
+
block: true;
|
|
122
|
+
blockReason: string;
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* Strongly-typed `before_tool_call` hook signature. The plugin's stub uses
|
|
126
|
+
* this signature today; Stage E swaps the stub for the real `agent:exec` +
|
|
127
|
+
* sift gate against `@auriclabs/roles`.
|
|
128
|
+
*/
|
|
129
|
+
type BeforeToolCallHook = (event: ToolCallEvent, ctx: ToolCallContext) => Promise<ToolCallHookResult>;
|
|
130
|
+
/**
|
|
131
|
+
* Build the gate context object used by sift evaluation. This is the
|
|
132
|
+
* round-6 "strict namespacing" shape — `args` is a top-level field, not
|
|
133
|
+
* spread, so an attacker-controlled `tool` field inside `toolArgs` cannot
|
|
134
|
+
* override the gate's `tool` value.
|
|
135
|
+
*
|
|
136
|
+
* Stage E's gate calls:
|
|
137
|
+
* ability.has(
|
|
138
|
+
* { subject: "agent", action: "exec", scope: `agent:${ctx.agentId}` },
|
|
139
|
+
* buildGateContext(event),
|
|
140
|
+
* );
|
|
141
|
+
*/
|
|
142
|
+
declare function buildGateContext(event: ToolCallEvent): {
|
|
143
|
+
tool: string;
|
|
144
|
+
args: Record<string, unknown>;
|
|
145
|
+
};
|
|
146
|
+
//#endregion
|
|
147
|
+
export { type BeforeToolCallHook, type IdentityFailureMode, type RuntimePermission, type ToolCallAuthMethod, type ToolCallContext, type ToolCallEvent, type ToolCallHookResult, type ToolCallTrigger, buildGateContext, plugin as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,147 @@
|
|
|
1
1
|
import plugin from "./plugin.js";
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
//#region src/policy-cache.d.ts
|
|
4
|
+
|
|
5
|
+
type IdentityFailureMode = "open" | "closed" | "permissive";
|
|
6
|
+
/**
|
|
7
|
+
* Evaluate whether a tool call should be blocked based on the cached policy
|
|
8
|
+
* and failure mode.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/runtime-contract.d.ts
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The tool the agent is about to call.
|
|
16
|
+
*
|
|
17
|
+
* `toolName` SHOULD be namespaced (e.g., `gmail:send_email`, `calendar:create_event`)
|
|
18
|
+
* so sift `$glob: "gmail:*"` conditions work and namespace collisions are
|
|
19
|
+
* impossible. Plugins that don't yet namespace their tools will be migrated
|
|
20
|
+
* during Stage I rollout.
|
|
21
|
+
*/
|
|
22
|
+
interface ToolCallEvent {
|
|
23
|
+
/** Namespaced tool name, e.g. "gmail:send_email". */
|
|
24
|
+
readonly toolName: string;
|
|
25
|
+
/** Arbitrary argument bag passed to the tool's `execute` function. */
|
|
26
|
+
readonly toolArgs: Record<string, unknown>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* What initiated the tool call. Three buckets:
|
|
30
|
+
* - "user_message" — a human (or another agent) sent a message that the
|
|
31
|
+
* agent is now responding to. `actingIdentityId` is the
|
|
32
|
+
* identity of the message sender.
|
|
33
|
+
* - "scheduled" — autonomous run (cron/trigger). `actingIdentityId` is
|
|
34
|
+
* the agent's own identity (`idn_agt_*`).
|
|
35
|
+
* - "tool_chain" — a follow-up tool call from a previous tool's result
|
|
36
|
+
* within the same agent invocation. `actingIdentityId`
|
|
37
|
+
* is whatever resolved at the start of the chain.
|
|
38
|
+
* - "api" — a tool call invoked via the agent's REST API by an
|
|
39
|
+
* external caller authenticated with an `alfe_*` token.
|
|
40
|
+
* `actingIdentityId` may be undefined; `tokenPermissions`
|
|
41
|
+
* carries the gate-relevant `Permission[]`.
|
|
42
|
+
*/
|
|
43
|
+
type ToolCallTrigger = "user_message" | "scheduled" | "tool_chain" | "api";
|
|
44
|
+
/**
|
|
45
|
+
* How the caller authenticated.
|
|
46
|
+
* - "jwt" — Clerk JWT path (human user). `actingIdentityId` resolved from
|
|
47
|
+
* the JWT's `sub` via the identity service.
|
|
48
|
+
* - "agent" — autonomous agent (no external caller). `actingIdentityId` is
|
|
49
|
+
* the agent's own `idn_agt_*`.
|
|
50
|
+
* - "token" — `alfe_*` API token. `tokenPermissions` is set; the gate uses
|
|
51
|
+
* the token's permissions directly without an identity lookup.
|
|
52
|
+
* - "none" — no auth context (fail-closed in prod via IdentityFailureMode).
|
|
53
|
+
*/
|
|
54
|
+
type ToolCallAuthMethod = "jwt" | "agent" | "token" | "none";
|
|
55
|
+
/**
|
|
56
|
+
* Permission shape the gate consumes. This is a structural duplicate of
|
|
57
|
+
* `Permission` from `@auriclabs/roles@0.1.1` so the openclaw plugin doesn't
|
|
58
|
+
* have to depend on the library directly (the library is consumed inside the
|
|
59
|
+
* gate itself in Stage E). Keep the two shapes in lockstep.
|
|
60
|
+
*/
|
|
61
|
+
interface RuntimePermission {
|
|
62
|
+
readonly subject: string;
|
|
63
|
+
readonly action: string;
|
|
64
|
+
readonly scope?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Round 7 storage shape: sift conditions stored per-permission. The runtime
|
|
67
|
+
* gate evaluates the condition against `{ tool, args }` (round 6 strict
|
|
68
|
+
* namespacing). Glob source travels under `$glob`; the compiled regex
|
|
69
|
+
* travels under `_glob_re` with a `_glob_v` version marker (round 7 audit
|
|
70
|
+
* 3.6 storage shape).
|
|
71
|
+
*/
|
|
72
|
+
readonly conditions?: Record<string, unknown>;
|
|
73
|
+
readonly type?: "can" | "cannot";
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Calling context for the tool call. Populated by the OpenClaw daemon at
|
|
77
|
+
* dispatch time.
|
|
78
|
+
*/
|
|
79
|
+
interface ToolCallContext {
|
|
80
|
+
/** Required: the tenant (`org_*`) that owns the agent. */
|
|
81
|
+
readonly tenantId: string;
|
|
82
|
+
/** Required: the agent (`agt_*`) that is about to call the tool. */
|
|
83
|
+
readonly agentId: string;
|
|
84
|
+
/** Required: how the caller authenticated. */
|
|
85
|
+
readonly authMethod: ToolCallAuthMethod;
|
|
86
|
+
/** Required: what initiated the call. */
|
|
87
|
+
readonly trigger: ToolCallTrigger;
|
|
88
|
+
/**
|
|
89
|
+
* The identity (`idn_*`) the agent is acting on behalf of. Resolution
|
|
90
|
+
* order:
|
|
91
|
+
* 1. If `trigger === "user_message"`: the chat-context identity (sender).
|
|
92
|
+
* 2. If `trigger === "scheduled"` or `trigger === "tool_chain"`: the
|
|
93
|
+
* agent's own `idn_agt_*` (autonomous default).
|
|
94
|
+
* 3. If `authMethod === "token"`: optional; the token-path gate uses
|
|
95
|
+
* `tokenPermissions` and may skip identity resolution entirely.
|
|
96
|
+
* 4. Otherwise: undefined; the per-agent `IdentityFailureMode` decides
|
|
97
|
+
* whether to allow / deny / log-and-continue.
|
|
98
|
+
*/
|
|
99
|
+
readonly actingIdentityId?: string;
|
|
100
|
+
/**
|
|
101
|
+
* Round 5 / Round 7: `alfe_*` tokens carry their own flat `Permission[]`
|
|
102
|
+
* directly. When `authMethod === "token"`, the daemon populates this with
|
|
103
|
+
* `TokenEntity.permissions` (post Stage B.0.7 atomic flip — pre-flip the
|
|
104
|
+
* authorizer derives this from `record.scopes` via `scopesToPermissions`).
|
|
105
|
+
* The Stage E gate evaluates these permissions directly at scope
|
|
106
|
+
* `agent:<agentId>` without an identity lookup.
|
|
107
|
+
*/
|
|
108
|
+
readonly tokenPermissions?: readonly RuntimePermission[];
|
|
109
|
+
/** Optional: chat conversation id (when trigger is `user_message`). */
|
|
110
|
+
readonly conversationId?: string;
|
|
111
|
+
/** Optional: channel id (when trigger is `user_message`). */
|
|
112
|
+
readonly channelId?: string;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Return value of the `before_tool_call` hook.
|
|
116
|
+
* - `undefined` — allow.
|
|
117
|
+
* - `{ block: true, blockReason: string }` — deny with reason surfaced to
|
|
118
|
+
* the agent's response (Stage E behaviour).
|
|
119
|
+
*/
|
|
120
|
+
type ToolCallHookResult = undefined | {
|
|
121
|
+
block: true;
|
|
122
|
+
blockReason: string;
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* Strongly-typed `before_tool_call` hook signature. The plugin's stub uses
|
|
126
|
+
* this signature today; Stage E swaps the stub for the real `agent:exec` +
|
|
127
|
+
* sift gate against `@auriclabs/roles`.
|
|
128
|
+
*/
|
|
129
|
+
type BeforeToolCallHook = (event: ToolCallEvent, ctx: ToolCallContext) => Promise<ToolCallHookResult>;
|
|
130
|
+
/**
|
|
131
|
+
* Build the gate context object used by sift evaluation. This is the
|
|
132
|
+
* round-6 "strict namespacing" shape — `args` is a top-level field, not
|
|
133
|
+
* spread, so an attacker-controlled `tool` field inside `toolArgs` cannot
|
|
134
|
+
* override the gate's `tool` value.
|
|
135
|
+
*
|
|
136
|
+
* Stage E's gate calls:
|
|
137
|
+
* ability.has(
|
|
138
|
+
* { subject: "agent", action: "exec", scope: `agent:${ctx.agentId}` },
|
|
139
|
+
* buildGateContext(event),
|
|
140
|
+
* );
|
|
141
|
+
*/
|
|
142
|
+
declare function buildGateContext(event: ToolCallEvent): {
|
|
143
|
+
tool: string;
|
|
144
|
+
args: Record<string, unknown>;
|
|
145
|
+
};
|
|
146
|
+
//#endregion
|
|
147
|
+
export { type BeforeToolCallHook, type IdentityFailureMode, type RuntimePermission, type ToolCallAuthMethod, type ToolCallContext, type ToolCallEvent, type ToolCallHookResult, type ToolCallTrigger, buildGateContext, plugin as default };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,22 @@
|
|
|
1
1
|
import { t as plugin } from "./plugin2.js";
|
|
2
|
-
|
|
2
|
+
//#region src/runtime-contract.ts
|
|
3
|
+
/**
|
|
4
|
+
* Build the gate context object used by sift evaluation. This is the
|
|
5
|
+
* round-6 "strict namespacing" shape — `args` is a top-level field, not
|
|
6
|
+
* spread, so an attacker-controlled `tool` field inside `toolArgs` cannot
|
|
7
|
+
* override the gate's `tool` value.
|
|
8
|
+
*
|
|
9
|
+
* Stage E's gate calls:
|
|
10
|
+
* ability.has(
|
|
11
|
+
* { subject: "agent", action: "exec", scope: `agent:${ctx.agentId}` },
|
|
12
|
+
* buildGateContext(event),
|
|
13
|
+
* );
|
|
14
|
+
*/
|
|
15
|
+
function buildGateContext(event) {
|
|
16
|
+
return {
|
|
17
|
+
tool: event.toolName,
|
|
18
|
+
args: event.toolArgs
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
//#endregion
|
|
22
|
+
export { buildGateContext, plugin as default };
|