@agenticprimitives/tool-policy 0.1.0-alpha.2
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/LICENSE +21 -0
- package/README.md +50 -0
- package/dist/classification.d.ts +5 -0
- package/dist/classification.d.ts.map +1 -0
- package/dist/classification.js +6 -0
- package/dist/classification.js.map +1 -0
- package/dist/decision.d.ts +3 -0
- package/dist/decision.d.ts.map +1 -0
- package/dist/decision.js +103 -0
- package/dist/decision.js.map +1 -0
- package/dist/exact-call.d.ts +12 -0
- package/dist/exact-call.d.ts.map +1 -0
- package/dist/exact-call.js +49 -0
- package/dist/exact-call.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/lint.d.ts +10 -0
- package/dist/lint.d.ts.map +1 -0
- package/dist/lint.js +56 -0
- package/dist/lint.js.map +1 -0
- package/dist/risk-tier.d.ts +16 -0
- package/dist/risk-tier.d.ts.map +1 -0
- package/dist/risk-tier.js +84 -0
- package/dist/risk-tier.js.map +1 -0
- package/dist/types.d.ts +95 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +18 -0
- package/dist/types.js.map +1 -0
- package/package.json +64 -0
- package/spec.md +6 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Agentic Trust Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# @agenticprimitives/tool-policy
|
|
2
|
+
|
|
3
|
+
Protocol-agnostic classification, risk tiers, and exact-call policy primitives. Consumable by MCP, A2A, LangGraph, Vercel AI — any tool runtime.
|
|
4
|
+
|
|
5
|
+
This package is **deliberately transport-free**: no MCP SDK, no LangChain, no Vercel imports. That's what lets a LangGraph user `pnpm add` it without buying into MCP middleware, and what lets `@agenticprimitives/mcp-runtime` use it without being the only consumer.
|
|
6
|
+
|
|
7
|
+
See [`spec.md`](./spec.md) → [`specs/204-tool-policy.md`](../../specs/204-tool-policy.md).
|
|
8
|
+
|
|
9
|
+
## Quick start
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { declareTool, evaluatePolicy } from '@agenticprimitives/tool-policy';
|
|
13
|
+
|
|
14
|
+
const getProfileTool = declareTool(
|
|
15
|
+
{ name: 'get_profile', inputSchema: { /* ... */ }, handler: /* ... */ },
|
|
16
|
+
{
|
|
17
|
+
'@sa-tool': 'delegation-verified',
|
|
18
|
+
'@sa-auth': 'session-token',
|
|
19
|
+
'@sa-validation': 'shape-check',
|
|
20
|
+
'@sa-risk-tier': 'low',
|
|
21
|
+
},
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
const decision = evaluatePolicy({
|
|
25
|
+
toolName: 'get_profile',
|
|
26
|
+
classification: getProfileTool._classification,
|
|
27
|
+
delegation, // from @agenticprimitives/delegation
|
|
28
|
+
callerKind: 'user-session',
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (decision.decision === 'deny') throw new Error(decision.reason);
|
|
32
|
+
if (decision.decision === 'requires-consent') /* prompt user */;
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Exact-call policy
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { exactCall, matchesExactCall } from '@agenticprimitives/tool-policy';
|
|
39
|
+
|
|
40
|
+
const policy = exactCall(safeAddress, '0xa9059cbb', {
|
|
41
|
+
calldataHash: '0xdeadbeef...',
|
|
42
|
+
valueLimit: 0n,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const ok = matchesExactCall({ to, data, value }, policy);
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Status
|
|
49
|
+
|
|
50
|
+
Pre-alpha. Spec stable.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classification.d.ts","sourceRoot":"","sources":["../src/classification.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD,wBAAgB,WAAW,CAAC,CAAC,EAC3B,GAAG,EAAE,CAAC,EACN,cAAc,EAAE,kBAAkB,GACjC,CAAC,GAAG;IAAE,eAAe,EAAE,kBAAkB,CAAA;CAAE,CAI7C"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// declareTool: attach a classification at runtime so non-JSDoc consumers
|
|
2
|
+
// surface the same metadata that the lint script reads from JSDoc tags.
|
|
3
|
+
export function declareTool(def, classification) {
|
|
4
|
+
return Object.assign(def, { _classification: classification });
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=classification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classification.js","sourceRoot":"","sources":["../src/classification.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,wEAAwE;AAIxE,MAAM,UAAU,WAAW,CACzB,GAAM,EACN,cAAkC;IAElC,OAAO,MAAM,CAAC,MAAM,CAAC,GAAa,EAAE,EAAE,eAAe,EAAE,cAAc,EAAE,CAEtE,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decision.d.ts","sourceRoot":"","sources":["../src/decision.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAsB,MAAM,SAAS,CAAC;AAsDjF,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CA4CjE"}
|
package/dist/decision.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// evaluatePolicy — pure decision engine, no I/O, no clocks.
|
|
2
|
+
// Deterministic; same context → same decision. Fail-CLOSED on any
|
|
3
|
+
// unrecognised classification metadata (audit P0-1).
|
|
4
|
+
//
|
|
5
|
+
// Order of operations (fail-closed first):
|
|
6
|
+
// 0. Classification shape: every required tag present + value in
|
|
7
|
+
// the closed enum set → reject otherwise.
|
|
8
|
+
// 1. classification['@sa-auth'] === 'none' AND caller != 'service' → deny
|
|
9
|
+
// 2. classification['@sa-tool'] === 'service-only' AND caller != 'service' → deny
|
|
10
|
+
// 3. classification['@sa-tool'] === 'bootstrap' AND caller != 'service' → deny
|
|
11
|
+
// 4. classification['@sa-tool'] === 'dev-only' → deny (env gate required)
|
|
12
|
+
// 5. classification['@sa-tool'] === 'delegation-verified' AND no delegation → deny
|
|
13
|
+
// 6. classification['@sa-risk-tier'] === 'critical' → requires-consent
|
|
14
|
+
// 7. else → allow
|
|
15
|
+
// Closed enum sets — keep in lockstep with `types.ts ToolClassification`.
|
|
16
|
+
// Any value outside these sets is treated as unknown → deny. This is
|
|
17
|
+
// the wire-format security boundary; loosening any of these requires
|
|
18
|
+
// a coordinated change to the type, the enum here, and (likely) the
|
|
19
|
+
// production preflight that audits classification coverage.
|
|
20
|
+
const KNOWN_TOOL_KINDS = new Set([
|
|
21
|
+
'delegation-verified',
|
|
22
|
+
'service-only',
|
|
23
|
+
'bootstrap',
|
|
24
|
+
'dev-only',
|
|
25
|
+
]);
|
|
26
|
+
const KNOWN_AUTH_KINDS = new Set([
|
|
27
|
+
'session-token',
|
|
28
|
+
'service-hmac',
|
|
29
|
+
'none',
|
|
30
|
+
'none-with-csrf',
|
|
31
|
+
]);
|
|
32
|
+
const KNOWN_RISK_TIERS = new Set(['low', 'medium', 'high', 'critical']);
|
|
33
|
+
/**
|
|
34
|
+
* Validate the *shape* of a classification. Returns null when the
|
|
35
|
+
* classification is well-formed, or a deny-reason string otherwise.
|
|
36
|
+
*
|
|
37
|
+
* Spec invariant: `@sa-tool` AND `@sa-auth` are REQUIRED; `@sa-risk-tier`
|
|
38
|
+
* is required for everything except `service-only` / `bootstrap` /
|
|
39
|
+
* `none-with-csrf` (which have no human risk dimension). Unknown values
|
|
40
|
+
* in ANY of the three tags is unrecoverable — the package can't infer
|
|
41
|
+
* an interpretation it doesn't know.
|
|
42
|
+
*/
|
|
43
|
+
function validateClassificationShape(cls) {
|
|
44
|
+
const tool = cls['@sa-tool'];
|
|
45
|
+
if (typeof tool !== 'string' || !KNOWN_TOOL_KINDS.has(tool)) {
|
|
46
|
+
return `classification: @sa-tool="${tool}" not in known set ${[...KNOWN_TOOL_KINDS].join('|')}`;
|
|
47
|
+
}
|
|
48
|
+
const auth = cls['@sa-auth'];
|
|
49
|
+
if (typeof auth !== 'string' || !KNOWN_AUTH_KINDS.has(auth)) {
|
|
50
|
+
return `classification: @sa-auth="${auth}" not in known set ${[...KNOWN_AUTH_KINDS].join('|')}`;
|
|
51
|
+
}
|
|
52
|
+
// Risk tier is REQUIRED for user-facing tool kinds.
|
|
53
|
+
const userFacing = tool === 'delegation-verified' || tool === 'dev-only';
|
|
54
|
+
const tier = cls['@sa-risk-tier'];
|
|
55
|
+
if (userFacing) {
|
|
56
|
+
if (typeof tier !== 'string' || !KNOWN_RISK_TIERS.has(tier)) {
|
|
57
|
+
return `classification: @sa-risk-tier="${tier}" required for tool=${tool} but not in known set ${[...KNOWN_RISK_TIERS].join('|')}`;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else if (tier !== undefined && !KNOWN_RISK_TIERS.has(tier)) {
|
|
61
|
+
// Set but with an unknown value → deny (no silent acceptance).
|
|
62
|
+
return `classification: @sa-risk-tier="${tier}" not in known set ${[...KNOWN_RISK_TIERS].join('|')}`;
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
export function evaluatePolicy(ctx) {
|
|
67
|
+
const cls = ctx.classification;
|
|
68
|
+
// 0. SHAPE GATE (fail-closed default). Unknown/missing classification
|
|
69
|
+
// metadata is the most common cause of mis-configured tools
|
|
70
|
+
// silently being accepted. Reject here before any rule fires.
|
|
71
|
+
const shapeErr = validateClassificationShape(cls);
|
|
72
|
+
if (shapeErr) {
|
|
73
|
+
return { decision: 'deny', reason: shapeErr };
|
|
74
|
+
}
|
|
75
|
+
if (cls['@sa-auth'] === 'none' && ctx.callerKind !== 'service') {
|
|
76
|
+
return { decision: 'deny', reason: 'tool is @sa-auth:none; only service callers permitted' };
|
|
77
|
+
}
|
|
78
|
+
if (cls['@sa-tool'] === 'service-only' && ctx.callerKind !== 'service') {
|
|
79
|
+
return { decision: 'deny', reason: 'tool is @sa-tool:service-only; user/agent calls rejected' };
|
|
80
|
+
}
|
|
81
|
+
if (cls['@sa-tool'] === 'bootstrap' && ctx.callerKind !== 'service') {
|
|
82
|
+
return { decision: 'deny', reason: 'tool is @sa-tool:bootstrap; only service callers permitted' };
|
|
83
|
+
}
|
|
84
|
+
if (cls['@sa-tool'] === 'dev-only') {
|
|
85
|
+
// Dev-only tools must be gated by environment; we don't read env here
|
|
86
|
+
// (purity), so we deny unless explicitly classified differently by
|
|
87
|
+
// the consumer's runtime. Consumers wanting "allow in dev" should
|
|
88
|
+
// re-declare the tool as service-only with @sa-prod-gate:disabled.
|
|
89
|
+
return { decision: 'deny', reason: 'tool is @sa-tool:dev-only; explicit env gate required' };
|
|
90
|
+
}
|
|
91
|
+
if (cls['@sa-tool'] === 'delegation-verified' && !ctx.delegation) {
|
|
92
|
+
return { decision: 'deny', reason: 'tool requires delegation but none presented' };
|
|
93
|
+
}
|
|
94
|
+
if (cls['@sa-risk-tier'] === 'critical') {
|
|
95
|
+
return {
|
|
96
|
+
decision: 'requires-consent',
|
|
97
|
+
promptId: `consent:critical:${ctx.toolName}`,
|
|
98
|
+
risk: 'critical',
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
return { decision: 'allow' };
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=decision.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decision.js","sourceRoot":"","sources":["../src/decision.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Address, Hex } from '@agenticprimitives/types';
|
|
2
|
+
import type { ExactCallPolicy } from './types';
|
|
3
|
+
export declare function exactCall(target: Address, selector: Hex, opts?: {
|
|
4
|
+
calldataHash?: Hex;
|
|
5
|
+
valueLimit?: bigint;
|
|
6
|
+
}): ExactCallPolicy;
|
|
7
|
+
export declare function matchesExactCall(call: {
|
|
8
|
+
to: Address;
|
|
9
|
+
data: Hex;
|
|
10
|
+
value: bigint;
|
|
11
|
+
}, policy: ExactCallPolicy): boolean;
|
|
12
|
+
//# sourceMappingURL=exact-call.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exact-call.d.ts","sourceRoot":"","sources":["../src/exact-call.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAY/C,wBAAgB,SAAS,CACvB,MAAM,EAAE,OAAO,EACf,QAAQ,EAAE,GAAG,EACb,IAAI,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,GAAG,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GACjD,eAAe,CAajB;AAED,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,GAAG,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAC/C,MAAM,EAAE,eAAe,GACtB,OAAO,CAeT"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Exact-call DSL: a delegation can authorize EXACTLY one call
|
|
2
|
+
// (target + selector + optional calldata hash + optional value cap).
|
|
3
|
+
//
|
|
4
|
+
// Used for critical-tier operations where the user should authorize the
|
|
5
|
+
// exact intent and nothing else.
|
|
6
|
+
import { keccak_256 } from '@noble/hashes/sha3';
|
|
7
|
+
function keccak256OfHex(hex) {
|
|
8
|
+
const cleaned = hex.startsWith('0x') ? hex.slice(2) : hex;
|
|
9
|
+
const bytes = new Uint8Array(cleaned.length / 2);
|
|
10
|
+
for (let i = 0; i < bytes.length; i++)
|
|
11
|
+
bytes[i] = parseInt(cleaned.slice(i * 2, i * 2 + 2), 16);
|
|
12
|
+
const out = keccak_256(bytes);
|
|
13
|
+
let s = '0x';
|
|
14
|
+
for (const b of out)
|
|
15
|
+
s += b.toString(16).padStart(2, '0');
|
|
16
|
+
return s;
|
|
17
|
+
}
|
|
18
|
+
export function exactCall(target, selector, opts) {
|
|
19
|
+
if (!/^0x[0-9a-fA-F]{8}$/.test(selector)) {
|
|
20
|
+
throw new Error(`exactCall: selector must be 4 bytes (0x + 8 hex chars); got "${selector}"`);
|
|
21
|
+
}
|
|
22
|
+
if (opts?.calldataHash && !/^0x[0-9a-fA-F]{64}$/.test(opts.calldataHash)) {
|
|
23
|
+
throw new Error(`exactCall: calldataHash must be 32 bytes (0x + 64 hex chars); got "${opts.calldataHash}"`);
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
target,
|
|
27
|
+
selector,
|
|
28
|
+
calldataHash: opts?.calldataHash,
|
|
29
|
+
valueLimit: opts?.valueLimit,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export function matchesExactCall(call, policy) {
|
|
33
|
+
if (call.to.toLowerCase() !== policy.target.toLowerCase())
|
|
34
|
+
return false;
|
|
35
|
+
if (!call.data.startsWith('0x') || call.data.length < 10)
|
|
36
|
+
return false;
|
|
37
|
+
const callSelector = call.data.slice(0, 10).toLowerCase();
|
|
38
|
+
if (callSelector !== policy.selector.toLowerCase())
|
|
39
|
+
return false;
|
|
40
|
+
if (policy.calldataHash) {
|
|
41
|
+
const computed = keccak256OfHex(call.data);
|
|
42
|
+
if (computed.toLowerCase() !== policy.calldataHash.toLowerCase())
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
if (policy.valueLimit !== undefined && call.value > policy.valueLimit)
|
|
46
|
+
return false;
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=exact-call.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exact-call.js","sourceRoot":"","sources":["../src/exact-call.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,qEAAqE;AACrE,EAAE;AACF,wEAAwE;AACxE,iCAAiC;AAEjC,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAIhD,SAAS,cAAc,CAAC,GAAQ;IAC9B,MAAM,OAAO,GAAG,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAC1D,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACjD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,KAAK,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChG,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAC9B,IAAI,CAAC,GAAG,IAAI,CAAC;IACb,KAAK,MAAM,CAAC,IAAI,GAAG;QAAE,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1D,OAAO,CAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,SAAS,CACvB,MAAe,EACf,QAAa,EACb,IAAkD;IAElD,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,gEAAgE,QAAQ,GAAG,CAAC,CAAC;IAC/F,CAAC;IACD,IAAI,IAAI,EAAE,YAAY,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;QACzE,MAAM,IAAI,KAAK,CAAC,sEAAsE,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;IAC9G,CAAC;IACD,OAAO;QACL,MAAM;QACN,QAAQ;QACR,YAAY,EAAE,IAAI,EAAE,YAAY;QAChC,UAAU,EAAE,IAAI,EAAE,UAAU;KAC7B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,IAA+C,EAC/C,MAAuB;IAEvB,IAAI,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE;QAAE,OAAO,KAAK,CAAC;IAExE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,KAAK,CAAC;IACvE,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAC1D,IAAI,YAAY,KAAK,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE;QAAE,OAAO,KAAK,CAAC;IAEjE,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QACxB,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,QAAQ,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,YAAY,CAAC,WAAW,EAAE;YAAE,OAAO,KAAK,CAAC;IACjF,CAAC;IAED,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,UAAU;QAAE,OAAO,KAAK,CAAC;IAEpF,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { declareTool } from './classification';
|
|
2
|
+
export { exactCall, matchesExactCall } from './exact-call';
|
|
3
|
+
export { evaluatePolicy } from './decision';
|
|
4
|
+
export { clampTtlForRiskTier, requiredCaveatsForRiskTier, evaluateThresholdPolicy, RISK_TIER_REQUIREMENTS, } from './risk-tier';
|
|
5
|
+
export { lintClassification } from './lint';
|
|
6
|
+
export { ThresholdTier } from './types';
|
|
7
|
+
export type { Address, Hex, RiskTier, ToolClassification, ExactCallPolicy, CaveatLike, DelegationLike, CaveatContext, PolicyContext, PolicyDecision, ThresholdPolicyDecision, LintResult, } from './types';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EACL,mBAAmB,EACnB,0BAA0B,EAC1B,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAE5C,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAExC,YAAY,EACV,OAAO,EACP,GAAG,EACH,QAAQ,EACR,kBAAkB,EAClB,eAAe,EACf,UAAU,EACV,cAAc,EACd,aAAa,EACb,aAAa,EACb,cAAc,EACd,uBAAuB,EACvB,UAAU,GACX,MAAM,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// @agenticprimitives/tool-policy — public API
|
|
2
|
+
//
|
|
3
|
+
// See ../../specs/204-tool-policy.md for the full contract.
|
|
4
|
+
//
|
|
5
|
+
// CRITICAL: This package is protocol-agnostic. It MUST NOT import from any
|
|
6
|
+
// transport SDK (see capability.manifest.json:forbiddenImports for the full
|
|
7
|
+
// list and docs/architecture/decisions/0003-tool-policy-protocol-agnostic.md
|
|
8
|
+
// for why).
|
|
9
|
+
export { declareTool } from './classification';
|
|
10
|
+
export { exactCall, matchesExactCall } from './exact-call';
|
|
11
|
+
export { evaluatePolicy } from './decision';
|
|
12
|
+
export { clampTtlForRiskTier, requiredCaveatsForRiskTier, evaluateThresholdPolicy, RISK_TIER_REQUIREMENTS, } from './risk-tier';
|
|
13
|
+
export { lintClassification } from './lint';
|
|
14
|
+
// ThresholdTier is an enum (value export, not type-only).
|
|
15
|
+
export { ThresholdTier } from './types';
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,EAAE;AACF,4DAA4D;AAC5D,EAAE;AACF,2EAA2E;AAC3E,4EAA4E;AAC5E,6EAA6E;AAC7E,YAAY;AAEZ,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EACL,mBAAmB,EACnB,0BAA0B,EAC1B,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAC5C,0DAA0D;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC"}
|
package/dist/lint.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { LintResult } from './types';
|
|
2
|
+
interface LintOpts {
|
|
3
|
+
srcDir: string;
|
|
4
|
+
requiredTags: string[];
|
|
5
|
+
optionalTags?: string[];
|
|
6
|
+
tagBlockPattern?: RegExp;
|
|
7
|
+
}
|
|
8
|
+
export declare function lintClassification(opts: LintOpts): Promise<LintResult>;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=lint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../src/lint.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAK1C,UAAU,QAAQ;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAgBD,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CA4B5E"}
|
package/dist/lint.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// lintClassification — scan a source tree for tool definitions and verify
|
|
2
|
+
// each carries the required JSDoc @sa-* tags.
|
|
3
|
+
//
|
|
4
|
+
// v0 implementation: regex-based scan of the source tree. JSDoc parsing
|
|
5
|
+
// proper happens in v0.1; for the demo we focus on tag presence on
|
|
6
|
+
// function/object definitions that look like tools.
|
|
7
|
+
import { readdirSync, readFileSync, statSync } from 'node:fs';
|
|
8
|
+
import { join, extname } from 'node:path';
|
|
9
|
+
const DEFAULT_PATTERN = /\/\*\*([\s\S]*?)\*\//g;
|
|
10
|
+
const TOOL_HEURISTIC = /(?:export\s+(?:const|function)\s+\w+Tool|name:\s*['"`])/;
|
|
11
|
+
function* walk(dir) {
|
|
12
|
+
for (const entry of readdirSync(dir)) {
|
|
13
|
+
if (entry.startsWith('.'))
|
|
14
|
+
continue;
|
|
15
|
+
if (entry === 'node_modules' || entry === 'dist' || entry === 'coverage')
|
|
16
|
+
continue;
|
|
17
|
+
const p = join(dir, entry);
|
|
18
|
+
const st = statSync(p);
|
|
19
|
+
if (st.isDirectory()) {
|
|
20
|
+
yield* walk(p);
|
|
21
|
+
}
|
|
22
|
+
else if (['.ts', '.tsx', '.js', '.jsx'].includes(extname(entry))) {
|
|
23
|
+
yield p;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export async function lintClassification(opts) {
|
|
28
|
+
const required = new Set(opts.requiredTags);
|
|
29
|
+
const result = { passed: true, errors: [] };
|
|
30
|
+
const blockRe = opts.tagBlockPattern ?? DEFAULT_PATTERN;
|
|
31
|
+
for (const file of walk(opts.srcDir)) {
|
|
32
|
+
const text = readFileSync(file, 'utf8');
|
|
33
|
+
blockRe.lastIndex = 0;
|
|
34
|
+
let m;
|
|
35
|
+
while ((m = blockRe.exec(text)) !== null) {
|
|
36
|
+
const block = m[0];
|
|
37
|
+
const after = text.slice(m.index + block.length, m.index + block.length + 200);
|
|
38
|
+
if (!TOOL_HEURISTIC.test(after))
|
|
39
|
+
continue;
|
|
40
|
+
const present = new Set();
|
|
41
|
+
for (const tag of [...required, ...(opts.optionalTags ?? [])]) {
|
|
42
|
+
const tagRe = new RegExp(`@${tag.replace(/^@/, '').replace(/[.+^${}()|[\]\\]/g, '\\$&')}\\b`);
|
|
43
|
+
if (tagRe.test(block))
|
|
44
|
+
present.add(tag);
|
|
45
|
+
}
|
|
46
|
+
const missing = [...required].filter((t) => !present.has(t));
|
|
47
|
+
if (missing.length > 0) {
|
|
48
|
+
const line = text.slice(0, m.index).split('\n').length;
|
|
49
|
+
result.passed = false;
|
|
50
|
+
result.errors.push({ file, line, missing });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=lint.js.map
|
package/dist/lint.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lint.js","sourceRoot":"","sources":["../src/lint.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { RiskTier, ToolClassification, ThresholdPolicyDecision } from './types';
|
|
2
|
+
export declare function clampTtlForRiskTier(requestedTtlSec: number, risk: RiskTier): number;
|
|
3
|
+
export declare function requiredCaveatsForRiskTier(risk: RiskTier): string[];
|
|
4
|
+
export declare const RISK_TIER_REQUIREMENTS: Record<RiskTier, ThresholdPolicyDecision>;
|
|
5
|
+
/**
|
|
6
|
+
* Map a tool classification to the spec-207 threshold-policy decision.
|
|
7
|
+
*
|
|
8
|
+
* Defaults to `low` (T1 Read) when `@sa-risk-tier` is unset, matching
|
|
9
|
+
* the existing `evaluatePolicy` permissive default for unclassified
|
|
10
|
+
* tools. Callers should run `lintClassification` to catch unset risk
|
|
11
|
+
* tiers as a separate concern; this function intentionally doesn't
|
|
12
|
+
* fail closed on missing classification (that's `evaluatePolicy`'s
|
|
13
|
+
* job).
|
|
14
|
+
*/
|
|
15
|
+
export declare function evaluateThresholdPolicy(classification: ToolClassification): ThresholdPolicyDecision;
|
|
16
|
+
//# sourceMappingURL=risk-tier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"risk-tier.d.ts","sourceRoot":"","sources":["../src/risk-tier.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,QAAQ,EACR,kBAAkB,EAClB,uBAAuB,EACxB,MAAM,SAAS,CAAC;AAiBjB,wBAAgB,mBAAmB,CAAC,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,CAMnF;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,EAAE,CAEnE;AAqBD,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,QAAQ,EAAE,uBAAuB,CAyB5E,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,cAAc,EAAE,kBAAkB,GACjC,uBAAuB,CAGzB"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Risk-tier helpers. The taxonomy is the binding contract — these helpers
|
|
2
|
+
// surface "what should issuance demand for this tier."
|
|
3
|
+
import { ThresholdTier } from './types';
|
|
4
|
+
const TTL_CLAMP_SECONDS = {
|
|
5
|
+
low: 7 * 24 * 60 * 60, // 7 days
|
|
6
|
+
medium: 7 * 24 * 60 * 60, // 7 days
|
|
7
|
+
high: 24 * 60 * 60, // 1 day
|
|
8
|
+
critical: 60 * 60, // 1 hour
|
|
9
|
+
};
|
|
10
|
+
const REQUIRED_CAVEATS = {
|
|
11
|
+
low: ['timestamp'],
|
|
12
|
+
medium: ['timestamp', 'mcp-tool-scope'],
|
|
13
|
+
high: ['timestamp', 'mcp-tool-scope', 'value', 'data-scope'],
|
|
14
|
+
critical: ['timestamp', 'exact-call'],
|
|
15
|
+
};
|
|
16
|
+
export function clampTtlForRiskTier(requestedTtlSec, risk) {
|
|
17
|
+
if (!Number.isFinite(requestedTtlSec) || requestedTtlSec <= 0) {
|
|
18
|
+
throw new Error('clampTtlForRiskTier: requestedTtlSec must be a positive number');
|
|
19
|
+
}
|
|
20
|
+
const max = TTL_CLAMP_SECONDS[risk];
|
|
21
|
+
return Math.min(requestedTtlSec, max);
|
|
22
|
+
}
|
|
23
|
+
export function requiredCaveatsForRiskTier(risk) {
|
|
24
|
+
return [...REQUIRED_CAVEATS[risk]];
|
|
25
|
+
}
|
|
26
|
+
// ─── Spec 207 threshold-policy mapping ────────────────────────────────
|
|
27
|
+
//
|
|
28
|
+
// `@sa-risk-tier` (string) → `ThresholdPolicyDecision` (the shape
|
|
29
|
+
// `mcp-runtime.withDelegation` consumes when gating delegation
|
|
30
|
+
// verification). T1-T3 are tool-call tiers (the only tiers
|
|
31
|
+
// `evaluateThresholdPolicy` returns); T4-T6 are account-level admin
|
|
32
|
+
// tiers and live entirely in `agent-account`.
|
|
33
|
+
//
|
|
34
|
+
// V0 calibration:
|
|
35
|
+
// - low → T1 Read: 1-of-N, no UV gate, no on-chain blessing.
|
|
36
|
+
// - medium → T2 Write: 1-of-N + passkey UV (hybrid mode).
|
|
37
|
+
// - high → T3 Value: quorum caveat required + passkey UV.
|
|
38
|
+
// - critical → T3 Value + on-chain `acceptSessionDelegation` blessing.
|
|
39
|
+
//
|
|
40
|
+
// Future refinements: argument-level caveats (spec 208) will let
|
|
41
|
+
// individual tool arguments shift the tier (e.g. `target` in a known
|
|
42
|
+
// allowlist drops the on-chain blessing requirement). Until then this
|
|
43
|
+
// flat mapping is the single source of truth.
|
|
44
|
+
export const RISK_TIER_REQUIREMENTS = {
|
|
45
|
+
low: {
|
|
46
|
+
tier: ThresholdTier.Read,
|
|
47
|
+
requiresQuorum: false,
|
|
48
|
+
requiresUv: false,
|
|
49
|
+
requiresAcceptedOnChain: false,
|
|
50
|
+
},
|
|
51
|
+
medium: {
|
|
52
|
+
tier: ThresholdTier.Write,
|
|
53
|
+
requiresQuorum: false,
|
|
54
|
+
requiresUv: true,
|
|
55
|
+
requiresAcceptedOnChain: false,
|
|
56
|
+
},
|
|
57
|
+
high: {
|
|
58
|
+
tier: ThresholdTier.Value,
|
|
59
|
+
requiresQuorum: true,
|
|
60
|
+
requiresUv: true,
|
|
61
|
+
requiresAcceptedOnChain: false,
|
|
62
|
+
},
|
|
63
|
+
critical: {
|
|
64
|
+
tier: ThresholdTier.Value,
|
|
65
|
+
requiresQuorum: true,
|
|
66
|
+
requiresUv: true,
|
|
67
|
+
requiresAcceptedOnChain: true,
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Map a tool classification to the spec-207 threshold-policy decision.
|
|
72
|
+
*
|
|
73
|
+
* Defaults to `low` (T1 Read) when `@sa-risk-tier` is unset, matching
|
|
74
|
+
* the existing `evaluatePolicy` permissive default for unclassified
|
|
75
|
+
* tools. Callers should run `lintClassification` to catch unset risk
|
|
76
|
+
* tiers as a separate concern; this function intentionally doesn't
|
|
77
|
+
* fail closed on missing classification (that's `evaluatePolicy`'s
|
|
78
|
+
* job).
|
|
79
|
+
*/
|
|
80
|
+
export function evaluateThresholdPolicy(classification) {
|
|
81
|
+
const risk = classification['@sa-risk-tier'] ?? 'low';
|
|
82
|
+
return RISK_TIER_REQUIREMENTS[risk];
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=risk-tier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"risk-tier.js","sourceRoot":"","sources":["../src/risk-tier.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,uDAAuD;AAOvD,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAExC,MAAM,iBAAiB,GAA6B;IAClD,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAS,SAAS;IACvC,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAM,SAAS;IACvC,IAAI,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,EAAY,QAAQ;IACtC,QAAQ,EAAE,EAAE,GAAG,EAAE,EAAa,SAAS;CACxC,CAAC;AAEF,MAAM,gBAAgB,GAA+B;IACnD,GAAG,EAAE,CAAC,WAAW,CAAC;IAClB,MAAM,EAAE,CAAC,WAAW,EAAE,gBAAgB,CAAC;IACvC,IAAI,EAAE,CAAC,WAAW,EAAE,gBAAgB,EAAE,OAAO,EAAE,YAAY,CAAC;IAC5D,QAAQ,EAAE,CAAC,WAAW,EAAE,YAAY,CAAC;CACtC,CAAC;AAEF,MAAM,UAAU,mBAAmB,CAAC,eAAuB,EAAE,IAAc;IACzE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,eAAe,IAAI,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;IACpF,CAAC;IACD,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACpC,OAAO,IAAI,CAAC,GAAG,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,IAAc;IACvD,OAAO,CAAC,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;AACrC,CAAC;AAED,yEAAyE;AACzE,EAAE;AACF,kEAAkE;AAClE,+DAA+D;AAC/D,2DAA2D;AAC3D,oEAAoE;AACpE,8CAA8C;AAC9C,EAAE;AACF,kBAAkB;AAClB,+DAA+D;AAC/D,4DAA4D;AAC5D,4DAA4D;AAC5D,yEAAyE;AACzE,EAAE;AACF,iEAAiE;AACjE,qEAAqE;AACrE,sEAAsE;AACtE,8CAA8C;AAE9C,MAAM,CAAC,MAAM,sBAAsB,GAA8C;IAC/E,GAAG,EAAE;QACH,IAAI,EAAE,aAAa,CAAC,IAAI;QACxB,cAAc,EAAE,KAAK;QACrB,UAAU,EAAE,KAAK;QACjB,uBAAuB,EAAE,KAAK;KAC/B;IACD,MAAM,EAAE;QACN,IAAI,EAAE,aAAa,CAAC,KAAK;QACzB,cAAc,EAAE,KAAK;QACrB,UAAU,EAAE,IAAI;QAChB,uBAAuB,EAAE,KAAK;KAC/B;IACD,IAAI,EAAE;QACJ,IAAI,EAAE,aAAa,CAAC,KAAK;QACzB,cAAc,EAAE,IAAI;QACpB,UAAU,EAAE,IAAI;QAChB,uBAAuB,EAAE,KAAK;KAC/B;IACD,QAAQ,EAAE;QACR,IAAI,EAAE,aAAa,CAAC,KAAK;QACzB,cAAc,EAAE,IAAI;QACpB,UAAU,EAAE,IAAI;QAChB,uBAAuB,EAAE,IAAI;KAC9B;CACF,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,UAAU,uBAAuB,CACrC,cAAkC;IAElC,MAAM,IAAI,GAAG,cAAc,CAAC,eAAe,CAAC,IAAI,KAAK,CAAC;IACtD,OAAO,sBAAsB,CAAC,IAAI,CAAC,CAAC;AACtC,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { Address, Hex } from '@agenticprimitives/types';
|
|
2
|
+
export type { Address, Hex };
|
|
3
|
+
export type RiskTier = 'low' | 'medium' | 'high' | 'critical';
|
|
4
|
+
export interface ToolClassification {
|
|
5
|
+
'@sa-tool': 'delegation-verified' | 'service-only' | 'bootstrap' | 'dev-only';
|
|
6
|
+
'@sa-auth': 'session-token' | 'service-hmac' | 'none' | 'none-with-csrf';
|
|
7
|
+
'@sa-validation'?: 'shape-check' | 'json-schema' | 'none-no-body' | 'none-path-params' | 'wallet-action-canonical';
|
|
8
|
+
'@sa-risk-tier'?: RiskTier;
|
|
9
|
+
'@sa-owner'?: string;
|
|
10
|
+
'@sa-rate-limit'?: string;
|
|
11
|
+
'@sa-prod-gate'?: 'enabled' | 'disabled';
|
|
12
|
+
}
|
|
13
|
+
export interface ExactCallPolicy {
|
|
14
|
+
target: Address;
|
|
15
|
+
selector: Hex;
|
|
16
|
+
calldataHash?: Hex;
|
|
17
|
+
valueLimit?: bigint;
|
|
18
|
+
}
|
|
19
|
+
export interface CaveatLike {
|
|
20
|
+
enforcer: Address;
|
|
21
|
+
terms: Hex;
|
|
22
|
+
}
|
|
23
|
+
export interface DelegationLike {
|
|
24
|
+
delegator: Address;
|
|
25
|
+
delegate: Address;
|
|
26
|
+
caveats: CaveatLike[];
|
|
27
|
+
}
|
|
28
|
+
export interface CaveatContext {
|
|
29
|
+
timestamp: number;
|
|
30
|
+
mcpTool?: string;
|
|
31
|
+
target?: Address;
|
|
32
|
+
selector?: Hex;
|
|
33
|
+
value?: bigint;
|
|
34
|
+
principal?: Address;
|
|
35
|
+
}
|
|
36
|
+
export interface PolicyContext {
|
|
37
|
+
toolName: string;
|
|
38
|
+
classification: ToolClassification;
|
|
39
|
+
delegation?: DelegationLike;
|
|
40
|
+
caveatContext?: CaveatContext;
|
|
41
|
+
callerKind: 'user-session' | 'agent-session' | 'service';
|
|
42
|
+
callDetails?: {
|
|
43
|
+
to: Address;
|
|
44
|
+
data: Hex;
|
|
45
|
+
value: bigint;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export type PolicyDecision = {
|
|
49
|
+
decision: 'allow';
|
|
50
|
+
} | {
|
|
51
|
+
decision: 'deny';
|
|
52
|
+
reason: string;
|
|
53
|
+
} | {
|
|
54
|
+
decision: 'requires-consent';
|
|
55
|
+
promptId: string;
|
|
56
|
+
risk: RiskTier;
|
|
57
|
+
};
|
|
58
|
+
export interface LintResult {
|
|
59
|
+
passed: boolean;
|
|
60
|
+
errors: Array<{
|
|
61
|
+
file: string;
|
|
62
|
+
line: number;
|
|
63
|
+
missing: string[];
|
|
64
|
+
}>;
|
|
65
|
+
}
|
|
66
|
+
export declare enum ThresholdTier {
|
|
67
|
+
Read = 1,// T1 — view-shape MCP delegation, no on-chain mutation
|
|
68
|
+
Write = 2,// T2 — mutates state but no value transfer above T3 ceiling
|
|
69
|
+
Value = 3,// T3 — token / native value transfer; requires quorum + (high-value) on-chain blessing
|
|
70
|
+
Admin = 4,// T4 — owner / passkey / guardian / mode mutation; account-level (not exposed by evaluateThresholdPolicy)
|
|
71
|
+
Critical = 5,// T5 — impl upgrade / DM change / paymaster change; account-level + timelock
|
|
72
|
+
Recovery = 6
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Decision returned by `evaluateThresholdPolicy(classification)` —
|
|
76
|
+
* the shape mcp-runtime's withDelegation threads into
|
|
77
|
+
* `verifyDelegationToken` so the verify path knows what to enforce.
|
|
78
|
+
*
|
|
79
|
+
* - `tier`: which spec 207 § 5 tier the tool falls into. T1-T3 only;
|
|
80
|
+
* T4-T6 are account-level admin tiers, not tool-call tiers.
|
|
81
|
+
* - `requiresQuorum`: the delegation MUST carry a QuorumEnforcer caveat.
|
|
82
|
+
* True for T3+ (per spec § 5 multisig/org rows).
|
|
83
|
+
* - `requiresUv`: at least one signer must have presented a passkey UV
|
|
84
|
+
* (user-verification) flag. True for T2+ (per spec § 5 hybrid rows).
|
|
85
|
+
* - `requiresAcceptedOnChain`: the account must have called
|
|
86
|
+
* `acceptSessionDelegation(hash)` for this delegation. True for the
|
|
87
|
+
* high-value T3 path (per spec § 6 + § 5 critical-risk-tier).
|
|
88
|
+
*/
|
|
89
|
+
export interface ThresholdPolicyDecision {
|
|
90
|
+
tier: ThresholdTier;
|
|
91
|
+
requiresQuorum: boolean;
|
|
92
|
+
requiresUv: boolean;
|
|
93
|
+
requiresAcceptedOnChain: boolean;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// ─── Spec 207 threshold-policy tiers ──────────────────────────────────
|
|
2
|
+
//
|
|
3
|
+
// Coexists with the string `RiskTier` above. `RiskTier` is a *tool
|
|
4
|
+
// classification* concept (how risky is this tool?); `ThresholdTier` is
|
|
5
|
+
// the *delegation-time gating* tier from spec 207 § 5 (what kind of
|
|
6
|
+
// authorization does this tier demand?). The two map cleanly via
|
|
7
|
+
// `RISK_TIER_REQUIREMENTS` below, but they serve different layers and
|
|
8
|
+
// stay distinct in the type system.
|
|
9
|
+
export var ThresholdTier;
|
|
10
|
+
(function (ThresholdTier) {
|
|
11
|
+
ThresholdTier[ThresholdTier["Read"] = 1] = "Read";
|
|
12
|
+
ThresholdTier[ThresholdTier["Write"] = 2] = "Write";
|
|
13
|
+
ThresholdTier[ThresholdTier["Value"] = 3] = "Value";
|
|
14
|
+
ThresholdTier[ThresholdTier["Admin"] = 4] = "Admin";
|
|
15
|
+
ThresholdTier[ThresholdTier["Critical"] = 5] = "Critical";
|
|
16
|
+
ThresholdTier[ThresholdTier["Recovery"] = 6] = "Recovery";
|
|
17
|
+
})(ThresholdTier || (ThresholdTier = {}));
|
|
18
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA+DA,yEAAyE;AACzE,EAAE;AACF,mEAAmE;AACnE,wEAAwE;AACxE,oEAAoE;AACpE,iEAAiE;AACjE,sEAAsE;AACtE,oCAAoC;AAEpC,MAAM,CAAN,IAAY,aAOX;AAPD,WAAY,aAAa;IACvB,iDAAQ,CAAA;IACR,mDAAS,CAAA;IACT,mDAAS,CAAA;IACT,mDAAS,CAAA;IACT,yDAAY,CAAA;IACZ,yDAAY,CAAA;AACd,CAAC,EAPW,aAAa,KAAb,aAAa,QAOxB"}
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agenticprimitives/tool-policy",
|
|
3
|
+
"version": "0.1.0-alpha.2",
|
|
4
|
+
"description": "Protocol-agnostic classification, risk tiers, and exact-call policy. Consumable by MCP, A2A, LangGraph, and Vercel AI tool runtimes.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/agentictrustlabs/agenticprimitives.git",
|
|
9
|
+
"directory": "packages/tool-policy"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/agentictrustlabs/agenticprimitives/tree/master/packages/tool-policy",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/agentictrustlabs/agenticprimitives/issues"
|
|
14
|
+
},
|
|
15
|
+
"type": "module",
|
|
16
|
+
"main": "./dist/index.js",
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"import": "./dist/index.js"
|
|
22
|
+
},
|
|
23
|
+
"./lint": {
|
|
24
|
+
"types": "./dist/lint.d.ts",
|
|
25
|
+
"import": "./dist/lint.js"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"LICENSE",
|
|
30
|
+
"dist",
|
|
31
|
+
"spec.md",
|
|
32
|
+
"README.md"
|
|
33
|
+
],
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "tsc -p tsconfig.build.json",
|
|
36
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
37
|
+
"test": "vitest run",
|
|
38
|
+
"test:unit": "vitest run test/unit",
|
|
39
|
+
"test:integration": "vitest run test/integration --passWithNoTests",
|
|
40
|
+
"test:watch": "vitest",
|
|
41
|
+
"clean": "rm -rf dist"
|
|
42
|
+
},
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"access": "public"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@noble/hashes": "^1.5.0"
|
|
48
|
+
},
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"@agenticprimitives/types": "workspace:*"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@types/node": "^22.7.0",
|
|
54
|
+
"vitest": "^2.1.0"
|
|
55
|
+
},
|
|
56
|
+
"keywords": [
|
|
57
|
+
"policy",
|
|
58
|
+
"classification",
|
|
59
|
+
"risk-tier",
|
|
60
|
+
"exact-call",
|
|
61
|
+
"agentic",
|
|
62
|
+
"tool-policy"
|
|
63
|
+
]
|
|
64
|
+
}
|