usertrust-acs-adapter 1.4.0
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/README.md +66 -0
- package/dist/composite.d.ts +55 -0
- package/dist/composite.d.ts.map +1 -0
- package/dist/composite.js +143 -0
- package/dist/composite.js.map +1 -0
- package/dist/identity.d.ts +27 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +75 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/mock.d.ts +26 -0
- package/dist/mock.d.ts.map +1 -0
- package/dist/mock.js +128 -0
- package/dist/mock.js.map +1 -0
- package/dist/vocabulary.d.ts +37 -0
- package/dist/vocabulary.d.ts.map +1 -0
- package/dist/vocabulary.js +29 -0
- package/dist/vocabulary.js.map +1 -0
- package/package.json +32 -0
package/README.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# usertrust-acs-adapter
|
|
2
|
+
|
|
3
|
+
ACS/AGT composite-evaluator adapter for the usertrust governance kernel. It occupies the
|
|
4
|
+
SpendGuard composite slot documented by Microsoft's Agent Governance Toolkit: a stateless
|
|
5
|
+
policy layer decides, and the usertrust ledger provides the stateful two-phase reservation
|
|
6
|
+
(PENDING hold → settle or void) behind it.
|
|
7
|
+
|
|
8
|
+
## The composite contract
|
|
9
|
+
|
|
10
|
+
1. The external policy decides FIRST (`allow` / `warn` / `deny` / `escalate` / `transform`).
|
|
11
|
+
2. On `allow`/`warn`, the usertrust ledger atomically reserves (a PENDING hold).
|
|
12
|
+
3. A denied action never consumes a reservation.
|
|
13
|
+
|
|
14
|
+
If the ledger cannot reserve, the `allow` is converted to `deny` with an ACS-vocabulary
|
|
15
|
+
reason (`budget_cost_usd_exceeded`, or `usertrust:policy_denied:<reason>`). A policy that
|
|
16
|
+
returns malformed output fails closed: `deny` with `runtime_error:policy_output_invalid`.
|
|
17
|
+
Each `CompositeResult` is one-shot — a second `settle()` returns `null` and a second (or
|
|
18
|
+
post-settle) `abort()` is a no-op.
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { CompositeEvaluator, createMockGovernor } from "usertrust-acs-adapter";
|
|
24
|
+
|
|
25
|
+
const { governor } = createMockGovernor({ budget: 1000 }); // or createGovernor() from usertrust/headless
|
|
26
|
+
const evaluator = new CompositeEvaluator({
|
|
27
|
+
policy: (action, { inputIdentity, budgets }) =>
|
|
28
|
+
action.kind === "exfiltrate" ? { decision: "deny", reason: "blocked" } : { decision: "allow" },
|
|
29
|
+
governor,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const result = await evaluator.evaluate({
|
|
33
|
+
kind: "tool_call",
|
|
34
|
+
model: "claude-sonnet-4-6",
|
|
35
|
+
estimatedInputTokens: 200,
|
|
36
|
+
maxOutputTokens: 500,
|
|
37
|
+
});
|
|
38
|
+
if (result.verdict.decision === "allow") {
|
|
39
|
+
// ... run the action ...
|
|
40
|
+
await evaluator.settle(result, { inputTokens: 210, outputTokens: 480 });
|
|
41
|
+
} // denied? nothing to clean up — no reservation was made
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`runDemo()` produces an infrastructure-free transcript of all three contract lines.
|
|
45
|
+
|
|
46
|
+
## evaluate_only mode
|
|
47
|
+
|
|
48
|
+
With `mode: "evaluate_only"` the adapter is a pure shadow evaluator: the policy verdict is
|
|
49
|
+
**preserved exactly as decided** (a `deny` stays a `deny` in `result.verdict`), but nothing
|
|
50
|
+
is enforced — `result.enforced` is `false`, the ledger is never touched, no reservation is
|
|
51
|
+
made, and `settle()`/`abort()` are no-ops returning `null`. Use it to observe what a policy
|
|
52
|
+
would do before turning enforcement on. (Note: the usertrust-server layer defines its own,
|
|
53
|
+
different `evaluate_only` semantics — see that package's README.)
|
|
54
|
+
|
|
55
|
+
## ACS compatibility
|
|
56
|
+
|
|
57
|
+
The verdict set, the reserved `runtime_error:*` reason namespace, and the
|
|
58
|
+
`envelope.budgets` counters (`tool_call_count`, `token_count`, `elapsed_seconds`,
|
|
59
|
+
`cost_usd`) follow the Agent Control Specification so the adapter can sit behind an
|
|
60
|
+
ACS-style policy layer unchanged. usertrust meters in usertokens; `cost_usd` carries the
|
|
61
|
+
usertoken cost unless the deployment configures a conversion. Action identity
|
|
62
|
+
(`canonicalJson`/`actionIdentity`) is the adapter's own namespace — unrelated to core's
|
|
63
|
+
audit-chain canonicalization.
|
|
64
|
+
|
|
65
|
+
Patterns and schemas adapted from the Microsoft Agent Governance Toolkit (MIT License) —
|
|
66
|
+
see the repository `NOTICE` file. No Microsoft source code is included.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { TrustReceipt } from "usertrust";
|
|
2
|
+
import type { Authorization, Governor } from "usertrust/headless";
|
|
3
|
+
import type { AcsBudgetsEnvelope, AcsVerdict } from "./vocabulary.js";
|
|
4
|
+
export interface AcsAction {
|
|
5
|
+
kind: string;
|
|
6
|
+
model: string;
|
|
7
|
+
input?: unknown;
|
|
8
|
+
estimatedInputTokens?: number | undefined;
|
|
9
|
+
maxOutputTokens?: number | undefined;
|
|
10
|
+
actor?: string | undefined;
|
|
11
|
+
}
|
|
12
|
+
export type PolicyDecider = (action: AcsAction, context: {
|
|
13
|
+
inputIdentity: string;
|
|
14
|
+
budgets: AcsBudgetsEnvelope;
|
|
15
|
+
}) => AcsVerdict | Promise<AcsVerdict>;
|
|
16
|
+
export interface CompositeResult {
|
|
17
|
+
verdict: AcsVerdict;
|
|
18
|
+
enforced: boolean;
|
|
19
|
+
authorization: Authorization | null;
|
|
20
|
+
inputIdentity: string;
|
|
21
|
+
budgets: AcsBudgetsEnvelope;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The SpendGuard-slot composite contract: a stateless policy decides
|
|
25
|
+
* allow/deny FIRST; on allow the usertrust ledger atomically reserves
|
|
26
|
+
* (two-phase PENDING); denied actions never consume a reservation.
|
|
27
|
+
* Composition shape adapted from the Microsoft Agent Governance Toolkit's
|
|
28
|
+
* documented composite-evaluator integration point (MIT — see NOTICE).
|
|
29
|
+
*/
|
|
30
|
+
export declare class CompositeEvaluator {
|
|
31
|
+
private readonly policy;
|
|
32
|
+
private readonly governor;
|
|
33
|
+
private readonly mode;
|
|
34
|
+
private readonly clock;
|
|
35
|
+
private readonly startedAt;
|
|
36
|
+
/** Results already settled or aborted — a result is one-shot. */
|
|
37
|
+
private readonly finished;
|
|
38
|
+
private toolCallCount;
|
|
39
|
+
private tokenCount;
|
|
40
|
+
private costTotal;
|
|
41
|
+
constructor(opts: {
|
|
42
|
+
policy: PolicyDecider;
|
|
43
|
+
governor: Governor;
|
|
44
|
+
mode?: "enforce" | "evaluate_only";
|
|
45
|
+
clock?: () => number;
|
|
46
|
+
});
|
|
47
|
+
budgetsEnvelope(): AcsBudgetsEnvelope;
|
|
48
|
+
evaluate(action: AcsAction): Promise<CompositeResult>;
|
|
49
|
+
settle(result: CompositeResult, usage?: {
|
|
50
|
+
inputTokens?: number | undefined;
|
|
51
|
+
outputTokens?: number | undefined;
|
|
52
|
+
}): Promise<TrustReceipt | null>;
|
|
53
|
+
abort(result: CompositeResult, error?: unknown): Promise<void>;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=composite.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composite.d.ts","sourceRoot":"","sources":["../src/composite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE9C,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAElE,OAAO,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGtE,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,oBAAoB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B;AAED,MAAM,MAAM,aAAa,GAAG,CAC3B,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,kBAAkB,CAAA;CAAE,KAC3D,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,MAAM,WAAW,eAAe;IAC/B,OAAO,EAAE,UAAU,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;IACpC,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,kBAAkB,CAAC;CAC5B;AAWD;;;;;;GAMG;AACH,qBAAa,kBAAkB;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA8B;IACnD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,iEAAiE;IACjE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkC;IAC3D,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,SAAS,CAAK;gBAEV,IAAI,EAAE;QACjB,MAAM,EAAE,aAAa,CAAC;QACtB,QAAQ,EAAE,QAAQ,CAAC;QACnB,IAAI,CAAC,EAAE,SAAS,GAAG,eAAe,CAAC;QACnC,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;KACrB;IAQD,eAAe,IAAI,kBAAkB;IAS/B,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,eAAe,CAAC;IAiErD,MAAM,CACX,MAAM,EAAE,eAAe,EACvB,KAAK,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,GAC7E,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAezB,KAAK,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAWpE"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { InsufficientBalanceError, PolicyDeniedError } from "usertrust";
|
|
2
|
+
import { actionIdentity } from "./identity.js";
|
|
3
|
+
import { ACS_BUDGET_REASONS, isAcsDecision, runtimeError } from "./vocabulary.js";
|
|
4
|
+
/**
|
|
5
|
+
* Runtime validation of the policy's output: a policy that returns anything
|
|
6
|
+
* other than an object with a known ACS decision fails CLOSED (deny).
|
|
7
|
+
*/
|
|
8
|
+
function asValidVerdict(raw) {
|
|
9
|
+
if (typeof raw !== "object" || raw === null)
|
|
10
|
+
return null;
|
|
11
|
+
return isAcsDecision(raw.decision) ? raw : null;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The SpendGuard-slot composite contract: a stateless policy decides
|
|
15
|
+
* allow/deny FIRST; on allow the usertrust ledger atomically reserves
|
|
16
|
+
* (two-phase PENDING); denied actions never consume a reservation.
|
|
17
|
+
* Composition shape adapted from the Microsoft Agent Governance Toolkit's
|
|
18
|
+
* documented composite-evaluator integration point (MIT — see NOTICE).
|
|
19
|
+
*/
|
|
20
|
+
export class CompositeEvaluator {
|
|
21
|
+
policy;
|
|
22
|
+
governor;
|
|
23
|
+
mode;
|
|
24
|
+
clock;
|
|
25
|
+
startedAt;
|
|
26
|
+
/** Results already settled or aborted — a result is one-shot. */
|
|
27
|
+
finished = new WeakSet();
|
|
28
|
+
toolCallCount = 0;
|
|
29
|
+
tokenCount = 0;
|
|
30
|
+
costTotal = 0;
|
|
31
|
+
constructor(opts) {
|
|
32
|
+
this.policy = opts.policy;
|
|
33
|
+
this.governor = opts.governor;
|
|
34
|
+
this.mode = opts.mode ?? "enforce";
|
|
35
|
+
this.clock = opts.clock ?? Date.now;
|
|
36
|
+
this.startedAt = this.clock();
|
|
37
|
+
}
|
|
38
|
+
budgetsEnvelope() {
|
|
39
|
+
return {
|
|
40
|
+
tool_call_count: this.toolCallCount,
|
|
41
|
+
token_count: this.tokenCount,
|
|
42
|
+
elapsed_seconds: Math.floor((this.clock() - this.startedAt) / 1000),
|
|
43
|
+
cost_usd: this.costTotal,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
async evaluate(action) {
|
|
47
|
+
const inputIdentity = actionIdentity({
|
|
48
|
+
kind: action.kind,
|
|
49
|
+
model: action.model,
|
|
50
|
+
input: action.input ?? null,
|
|
51
|
+
});
|
|
52
|
+
const budgets = this.budgetsEnvelope();
|
|
53
|
+
const raw = await this.policy(action, { inputIdentity, budgets });
|
|
54
|
+
this.toolCallCount += 1;
|
|
55
|
+
const verdict = asValidVerdict(raw) ?? {
|
|
56
|
+
decision: "deny",
|
|
57
|
+
reason: runtimeError("policy_output_invalid"),
|
|
58
|
+
};
|
|
59
|
+
if (verdict.decision !== "allow" && verdict.decision !== "warn") {
|
|
60
|
+
return {
|
|
61
|
+
verdict,
|
|
62
|
+
enforced: this.mode === "enforce",
|
|
63
|
+
authorization: null,
|
|
64
|
+
inputIdentity,
|
|
65
|
+
budgets: this.budgetsEnvelope(),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
if (this.mode === "evaluate_only") {
|
|
69
|
+
return {
|
|
70
|
+
verdict,
|
|
71
|
+
enforced: false,
|
|
72
|
+
authorization: null,
|
|
73
|
+
inputIdentity,
|
|
74
|
+
budgets: this.budgetsEnvelope(),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
const authorization = await this.governor.authorize({
|
|
79
|
+
model: action.model,
|
|
80
|
+
estimatedInputTokens: action.estimatedInputTokens,
|
|
81
|
+
maxOutputTokens: action.maxOutputTokens,
|
|
82
|
+
params: { acs_kind: action.kind, acs_input_identity: inputIdentity },
|
|
83
|
+
actor: action.actor ?? "acs-adapter",
|
|
84
|
+
});
|
|
85
|
+
return {
|
|
86
|
+
verdict,
|
|
87
|
+
enforced: true,
|
|
88
|
+
authorization,
|
|
89
|
+
inputIdentity,
|
|
90
|
+
budgets: this.budgetsEnvelope(),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
let reason;
|
|
95
|
+
if (err instanceof InsufficientBalanceError) {
|
|
96
|
+
reason = ACS_BUDGET_REASONS.cost;
|
|
97
|
+
}
|
|
98
|
+
else if (err instanceof PolicyDeniedError) {
|
|
99
|
+
reason = `usertrust:policy_denied:${err.reason}`;
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
throw err;
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
verdict: { decision: "deny", reason },
|
|
106
|
+
enforced: true,
|
|
107
|
+
authorization: null,
|
|
108
|
+
inputIdentity,
|
|
109
|
+
budgets: this.budgetsEnvelope(),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
async settle(result, usage) {
|
|
114
|
+
if (!result.authorization || this.finished.has(result))
|
|
115
|
+
return null;
|
|
116
|
+
this.finished.add(result);
|
|
117
|
+
try {
|
|
118
|
+
const receipt = await this.governor.settle(result.authorization, usage);
|
|
119
|
+
this.tokenCount += (usage?.inputTokens ?? 0) + (usage?.outputTokens ?? 0);
|
|
120
|
+
this.costTotal += receipt.cost;
|
|
121
|
+
return receipt;
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
// A failed settle stays retryable.
|
|
125
|
+
this.finished.delete(result);
|
|
126
|
+
throw err;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
async abort(result, error) {
|
|
130
|
+
if (!result.authorization || this.finished.has(result))
|
|
131
|
+
return;
|
|
132
|
+
this.finished.add(result);
|
|
133
|
+
try {
|
|
134
|
+
await this.governor.abort(result.authorization, error);
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
// A failed abort stays retryable.
|
|
138
|
+
this.finished.delete(result);
|
|
139
|
+
throw err;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=composite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composite.js","sourceRoot":"","sources":["../src/composite.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bisected action identity, adapted from the ACS input_identity /
|
|
3
|
+
* enforced_identity pattern (Microsoft Agent Governance Toolkit, MIT — see
|
|
4
|
+
* NOTICE): hash the action at decision time, bind approvals to that hash, and
|
|
5
|
+
* re-derive immediately before execution so an action mutated after approval
|
|
6
|
+
* fails closed.
|
|
7
|
+
*
|
|
8
|
+
* Canonicalization scope: this module defines the ACTION-IDENTITY namespace
|
|
9
|
+
* only. It is unrelated to core's audit-chain canonicalization and has no
|
|
10
|
+
* parity coupling with usertrust-verify. Per JSON.stringify semantics, `-0`
|
|
11
|
+
* normalizes to `0` before hashing.
|
|
12
|
+
*/
|
|
13
|
+
export declare function canonicalJson(value: unknown, seen?: WeakSet<object>): string;
|
|
14
|
+
export declare function actionIdentity(value: unknown): string;
|
|
15
|
+
export interface AcsApproval {
|
|
16
|
+
identity: string;
|
|
17
|
+
approvedAt: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function bindApproval(identity: string): AcsApproval;
|
|
20
|
+
export declare class IdentityMismatchError extends Error {
|
|
21
|
+
readonly expected: string;
|
|
22
|
+
readonly actual: string;
|
|
23
|
+
constructor(expected: string, actual: string);
|
|
24
|
+
}
|
|
25
|
+
/** Re-derive the action identity and fail closed if it no longer matches the approval. */
|
|
26
|
+
export declare function assertApprovalMatches(approval: AcsApproval, value: unknown): void;
|
|
27
|
+
//# sourceMappingURL=identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AAEH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,GAAE,OAAO,CAAC,MAAM,CAAiB,GAAG,MAAM,CAgC3F;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAErD;AAED,MAAM,WAAW,WAAW;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAE1D;AAED,qBAAa,qBAAsB,SAAQ,KAAK;IAC/C,SAAgB,QAAQ,EAAE,MAAM,CAAC;IACjC,SAAgB,MAAM,EAAE,MAAM,CAAC;gBAEnB,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAQ5C;AAED,0FAA0F;AAC1F,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAKjF"}
|
package/dist/identity.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { runtimeError } from "./vocabulary.js";
|
|
3
|
+
/**
|
|
4
|
+
* Bisected action identity, adapted from the ACS input_identity /
|
|
5
|
+
* enforced_identity pattern (Microsoft Agent Governance Toolkit, MIT — see
|
|
6
|
+
* NOTICE): hash the action at decision time, bind approvals to that hash, and
|
|
7
|
+
* re-derive immediately before execution so an action mutated after approval
|
|
8
|
+
* fails closed.
|
|
9
|
+
*
|
|
10
|
+
* Canonicalization scope: this module defines the ACTION-IDENTITY namespace
|
|
11
|
+
* only. It is unrelated to core's audit-chain canonicalization and has no
|
|
12
|
+
* parity coupling with usertrust-verify. Per JSON.stringify semantics, `-0`
|
|
13
|
+
* normalizes to `0` before hashing.
|
|
14
|
+
*/
|
|
15
|
+
export function canonicalJson(value, seen = new WeakSet()) {
|
|
16
|
+
if (value === null)
|
|
17
|
+
return "null";
|
|
18
|
+
switch (typeof value) {
|
|
19
|
+
case "string":
|
|
20
|
+
return JSON.stringify(value);
|
|
21
|
+
case "boolean":
|
|
22
|
+
return value ? "true" : "false";
|
|
23
|
+
case "number":
|
|
24
|
+
if (!Number.isFinite(value))
|
|
25
|
+
throw new TypeError("non-finite number in canonical JSON");
|
|
26
|
+
return JSON.stringify(value);
|
|
27
|
+
case "object":
|
|
28
|
+
break;
|
|
29
|
+
default:
|
|
30
|
+
throw new TypeError(`non-JSON value in canonical JSON: ${typeof value}`);
|
|
31
|
+
}
|
|
32
|
+
const obj = value;
|
|
33
|
+
if (seen.has(obj))
|
|
34
|
+
throw new TypeError("circular reference in canonical JSON");
|
|
35
|
+
seen.add(obj);
|
|
36
|
+
try {
|
|
37
|
+
if (Array.isArray(obj)) {
|
|
38
|
+
return `[${obj.map((item) => canonicalJson(item, seen)).join(",")}]`;
|
|
39
|
+
}
|
|
40
|
+
const keys = Object.keys(obj).sort();
|
|
41
|
+
const parts = [];
|
|
42
|
+
for (const key of keys) {
|
|
43
|
+
const entry = obj[key];
|
|
44
|
+
parts.push(`${JSON.stringify(key)}:${canonicalJson(entry, seen)}`);
|
|
45
|
+
}
|
|
46
|
+
return `{${parts.join(",")}}`;
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
seen.delete(obj);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export function actionIdentity(value) {
|
|
53
|
+
return createHash("sha256").update(canonicalJson(value), "utf-8").digest("hex");
|
|
54
|
+
}
|
|
55
|
+
export function bindApproval(identity) {
|
|
56
|
+
return { identity, approvedAt: new Date().toISOString() };
|
|
57
|
+
}
|
|
58
|
+
export class IdentityMismatchError extends Error {
|
|
59
|
+
expected;
|
|
60
|
+
actual;
|
|
61
|
+
constructor(expected, actual) {
|
|
62
|
+
super(`${runtimeError("approval_action_mismatch")}: approval bound to ${expected.slice(0, 12)}… but action re-derives to ${actual.slice(0, 12)}…`);
|
|
63
|
+
this.name = "IdentityMismatchError";
|
|
64
|
+
this.expected = expected;
|
|
65
|
+
this.actual = actual;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** Re-derive the action identity and fail closed if it no longer matches the approval. */
|
|
69
|
+
export function assertApprovalMatches(approval, value) {
|
|
70
|
+
const actual = actionIdentity(value);
|
|
71
|
+
if (actual !== approval.identity) {
|
|
72
|
+
throw new IdentityMismatchError(approval.identity, actual);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { ACS_BUDGET_REASONS, ACS_DECISIONS, isAcsDecision, runtimeError, } from "./vocabulary.js";
|
|
2
|
+
export type { AcsBudgetsEnvelope, AcsDecision, AcsVerdict } from "./vocabulary.js";
|
|
3
|
+
export { actionIdentity, assertApprovalMatches, bindApproval, canonicalJson, IdentityMismatchError, } from "./identity.js";
|
|
4
|
+
export type { AcsApproval } from "./identity.js";
|
|
5
|
+
export { CompositeEvaluator } from "./composite.js";
|
|
6
|
+
export type { AcsAction, CompositeResult, PolicyDecider } from "./composite.js";
|
|
7
|
+
export { createMockGovernor, mockPolicyDecider, runDemo } from "./mock.js";
|
|
8
|
+
export type { DemoStep } from "./mock.js";
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,kBAAkB,EAClB,aAAa,EACb,aAAa,EACb,YAAY,GACZ,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,kBAAkB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACnF,OAAO,EACN,cAAc,EACd,qBAAqB,EACrB,YAAY,EACZ,aAAa,EACb,qBAAqB,GACrB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC3E,YAAY,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { ACS_BUDGET_REASONS, ACS_DECISIONS, isAcsDecision, runtimeError, } from "./vocabulary.js";
|
|
2
|
+
export { actionIdentity, assertApprovalMatches, bindApproval, canonicalJson, IdentityMismatchError, } from "./identity.js";
|
|
3
|
+
export { CompositeEvaluator } from "./composite.js";
|
|
4
|
+
export { createMockGovernor, mockPolicyDecider, runDemo } from "./mock.js";
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,kBAAkB,EAClB,aAAa,EACb,aAAa,EACb,YAAY,GACZ,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACN,cAAc,EACd,qBAAqB,EACrB,YAAY,EACZ,aAAa,EACb,qBAAqB,GACrB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEpD,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/mock.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Governor } from "usertrust/headless";
|
|
2
|
+
import type { PolicyDecider } from "./composite.js";
|
|
3
|
+
/**
|
|
4
|
+
* In-memory Governor for demos and tests: real two-phase semantics
|
|
5
|
+
* (hold/settle/void against a budget) with no TigerBeetle and no disk.
|
|
6
|
+
* Cost model: 1 token = 1 usertoken.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createMockGovernor(opts?: {
|
|
9
|
+
budget?: number;
|
|
10
|
+
}): {
|
|
11
|
+
governor: Governor;
|
|
12
|
+
};
|
|
13
|
+
/** Deny actions whose kind is listed; allow everything else. */
|
|
14
|
+
export declare function mockPolicyDecider(denyKinds: string[]): PolicyDecider;
|
|
15
|
+
export interface DemoStep {
|
|
16
|
+
label: string;
|
|
17
|
+
decision: string;
|
|
18
|
+
reason?: string | undefined;
|
|
19
|
+
budgetRemaining: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Infrastructure-free demo of the composite contract: allow+settle, a policy
|
|
23
|
+
* deny that provably consumes no reservation, then budget exhaustion.
|
|
24
|
+
*/
|
|
25
|
+
export declare function runDemo(): Promise<DemoStep[]>;
|
|
26
|
+
//# sourceMappingURL=mock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../src/mock.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAkC,QAAQ,EAAgB,MAAM,oBAAoB,CAAC;AACjG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGpD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAA;CAAE,CAgEzF;AAED,gEAAgE;AAChE,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,aAAa,CAKpE;AAED,MAAM,WAAW,QAAQ;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAsB,OAAO,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CAgDnD"}
|
package/dist/mock.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { InsufficientBalanceError } from "usertrust";
|
|
3
|
+
import { CompositeEvaluator } from "./composite.js";
|
|
4
|
+
/**
|
|
5
|
+
* In-memory Governor for demos and tests: real two-phase semantics
|
|
6
|
+
* (hold/settle/void against a budget) with no TigerBeetle and no disk.
|
|
7
|
+
* Cost model: 1 token = 1 usertoken.
|
|
8
|
+
*/
|
|
9
|
+
export function createMockGovernor(opts = {}) {
|
|
10
|
+
let budget = opts.budget ?? 10_000;
|
|
11
|
+
let seq = 0;
|
|
12
|
+
const holds = new Map();
|
|
13
|
+
const governor = {
|
|
14
|
+
async authorize(params) {
|
|
15
|
+
const estimatedCost = (params.estimatedInputTokens ?? 100) + (params.maxOutputTokens ?? 4096);
|
|
16
|
+
if (estimatedCost > budget) {
|
|
17
|
+
throw new InsufficientBalanceError("mock", estimatedCost, budget);
|
|
18
|
+
}
|
|
19
|
+
seq += 1;
|
|
20
|
+
const auth = {
|
|
21
|
+
transferId: `tx_mock_${seq}`,
|
|
22
|
+
estimatedCost,
|
|
23
|
+
model: params.model,
|
|
24
|
+
createdAt: Date.now(),
|
|
25
|
+
};
|
|
26
|
+
budget -= estimatedCost;
|
|
27
|
+
holds.set(auth.transferId, auth);
|
|
28
|
+
return auth;
|
|
29
|
+
},
|
|
30
|
+
async settle(auth, params) {
|
|
31
|
+
holds.delete(auth.transferId);
|
|
32
|
+
const actual = (params?.inputTokens ?? 0) + (params?.outputTokens ?? 0);
|
|
33
|
+
const cost = actual > 0 ? actual : auth.estimatedCost;
|
|
34
|
+
budget += auth.estimatedCost - cost;
|
|
35
|
+
return {
|
|
36
|
+
transferId: auth.transferId,
|
|
37
|
+
cost,
|
|
38
|
+
budgetRemaining: budget,
|
|
39
|
+
auditHash: createHash("sha256").update(auth.transferId).digest("hex"),
|
|
40
|
+
chainPath: "mock://chain",
|
|
41
|
+
receiptUrl: null,
|
|
42
|
+
settled: true,
|
|
43
|
+
model: auth.model,
|
|
44
|
+
provider: "mock",
|
|
45
|
+
timestamp: new Date().toISOString(),
|
|
46
|
+
};
|
|
47
|
+
},
|
|
48
|
+
async abort(auth) {
|
|
49
|
+
if (holds.delete(auth.transferId)) {
|
|
50
|
+
budget += auth.estimatedCost;
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
async destroy() {
|
|
54
|
+
for (const auth of holds.values()) {
|
|
55
|
+
budget += auth.estimatedCost;
|
|
56
|
+
}
|
|
57
|
+
holds.clear();
|
|
58
|
+
},
|
|
59
|
+
estimateCost(_model, inputTokens, outputTokens) {
|
|
60
|
+
return inputTokens + outputTokens;
|
|
61
|
+
},
|
|
62
|
+
estimateInputTokens(messages) {
|
|
63
|
+
return Math.ceil(JSON.stringify(messages).length / 4);
|
|
64
|
+
},
|
|
65
|
+
budgetRemaining() {
|
|
66
|
+
return budget;
|
|
67
|
+
},
|
|
68
|
+
// biome-ignore lint/suspicious/noExplicitAny: mock config, never read by the adapter
|
|
69
|
+
config: {},
|
|
70
|
+
};
|
|
71
|
+
return { governor };
|
|
72
|
+
}
|
|
73
|
+
/** Deny actions whose kind is listed; allow everything else. */
|
|
74
|
+
export function mockPolicyDecider(denyKinds) {
|
|
75
|
+
return (action) => denyKinds.includes(action.kind)
|
|
76
|
+
? { decision: "deny", reason: `demo_policy:kind_${action.kind}_denied` }
|
|
77
|
+
: { decision: "allow" };
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Infrastructure-free demo of the composite contract: allow+settle, a policy
|
|
81
|
+
* deny that provably consumes no reservation, then budget exhaustion.
|
|
82
|
+
*/
|
|
83
|
+
export async function runDemo() {
|
|
84
|
+
const { governor } = createMockGovernor({ budget: 60 });
|
|
85
|
+
const evaluator = new CompositeEvaluator({
|
|
86
|
+
policy: mockPolicyDecider(["exfiltrate"]),
|
|
87
|
+
governor,
|
|
88
|
+
});
|
|
89
|
+
const transcript = [];
|
|
90
|
+
const allowed = await evaluator.evaluate({
|
|
91
|
+
kind: "tool_call",
|
|
92
|
+
model: "mock-1",
|
|
93
|
+
estimatedInputTokens: 20,
|
|
94
|
+
maxOutputTokens: 20,
|
|
95
|
+
});
|
|
96
|
+
await evaluator.settle(allowed, { inputTokens: 20, outputTokens: 10 });
|
|
97
|
+
transcript.push({
|
|
98
|
+
label: "governed tool call settles at actual usage",
|
|
99
|
+
decision: allowed.verdict.decision,
|
|
100
|
+
budgetRemaining: governor.budgetRemaining(),
|
|
101
|
+
});
|
|
102
|
+
const denied = await evaluator.evaluate({
|
|
103
|
+
kind: "exfiltrate",
|
|
104
|
+
model: "mock-1",
|
|
105
|
+
estimatedInputTokens: 5,
|
|
106
|
+
maxOutputTokens: 5,
|
|
107
|
+
});
|
|
108
|
+
transcript.push({
|
|
109
|
+
label: "policy deny consumes no reservation",
|
|
110
|
+
decision: denied.verdict.decision,
|
|
111
|
+
reason: denied.verdict.reason,
|
|
112
|
+
budgetRemaining: governor.budgetRemaining(),
|
|
113
|
+
});
|
|
114
|
+
const broke = await evaluator.evaluate({
|
|
115
|
+
kind: "tool_call",
|
|
116
|
+
model: "mock-1",
|
|
117
|
+
estimatedInputTokens: 500,
|
|
118
|
+
maxOutputTokens: 500,
|
|
119
|
+
});
|
|
120
|
+
transcript.push({
|
|
121
|
+
label: "reservation failure denies with ACS budget reason",
|
|
122
|
+
decision: broke.verdict.decision,
|
|
123
|
+
reason: broke.verdict.reason,
|
|
124
|
+
budgetRemaining: governor.budgetRemaining(),
|
|
125
|
+
});
|
|
126
|
+
return transcript;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=mock.js.map
|
package/dist/mock.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock.js","sourceRoot":"","sources":["../src/mock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AAGrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEpD;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAA4B,EAAE;IAChE,IAAI,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC;IACnC,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,MAAM,KAAK,GAAG,IAAI,GAAG,EAAyB,CAAC;IAE/C,MAAM,QAAQ,GAAa;QAC1B,KAAK,CAAC,SAAS,CAAC,MAAuB;YACtC,MAAM,aAAa,GAAG,CAAC,MAAM,CAAC,oBAAoB,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,IAAI,IAAI,CAAC,CAAC;YAC9F,IAAI,aAAa,GAAG,MAAM,EAAE,CAAC;gBAC5B,MAAM,IAAI,wBAAwB,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC;YACnE,CAAC;YACD,GAAG,IAAI,CAAC,CAAC;YACT,MAAM,IAAI,GAAkB;gBAC3B,UAAU,EAAE,WAAW,GAAG,EAAE;gBAC5B,aAAa;gBACb,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;aACrB,CAAC;YACF,MAAM,IAAI,aAAa,CAAC;YACxB,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;YACjC,OAAO,IAAI,CAAC;QACb,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,IAAmB,EAAE,MAAqB;YACtD,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC9B,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,WAAW,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,YAAY,IAAI,CAAC,CAAC,CAAC;YACxE,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC;YACtD,MAAM,IAAI,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;YACpC,OAAO;gBACN,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,IAAI;gBACJ,eAAe,EAAE,MAAM;gBACvB,SAAS,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;gBACrE,SAAS,EAAE,cAAc;gBACzB,UAAU,EAAE,IAAI;gBAChB,OAAO,EAAE,IAAI;gBACb,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,QAAQ,EAAE,MAAM;gBAChB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACnC,CAAC;QACH,CAAC;QACD,KAAK,CAAC,KAAK,CAAC,IAAmB;YAC9B,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;gBACnC,MAAM,IAAI,IAAI,CAAC,aAAa,CAAC;YAC9B,CAAC;QACF,CAAC;QACD,KAAK,CAAC,OAAO;YACZ,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;gBACnC,MAAM,IAAI,IAAI,CAAC,aAAa,CAAC;YAC9B,CAAC;YACD,KAAK,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;QACD,YAAY,CAAC,MAAc,EAAE,WAAmB,EAAE,YAAoB;YACrE,OAAO,WAAW,GAAG,YAAY,CAAC;QACnC,CAAC;QACD,mBAAmB,CAAC,QAAmB;YACtC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACvD,CAAC;QACD,eAAe;YACd,OAAO,MAAM,CAAC;QACf,CAAC;QACD,qFAAqF;QACrF,MAAM,EAAE,EAAS;KACjB,CAAC;IACF,OAAO,EAAE,QAAQ,EAAE,CAAC;AACrB,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,iBAAiB,CAAC,SAAmB;IACpD,OAAO,CAAC,MAAM,EAAE,EAAE,CACjB,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC;QAC9B,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,MAAM,CAAC,IAAI,SAAS,EAAE;QACxE,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AAC3B,CAAC;AASD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO;IAC5B,MAAM,EAAE,QAAQ,EAAE,GAAG,kBAAkB,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;IACxD,MAAM,SAAS,GAAG,IAAI,kBAAkB,CAAC;QACxC,MAAM,EAAE,iBAAiB,CAAC,CAAC,YAAY,CAAC,CAAC;QACzC,QAAQ;KACR,CAAC,CAAC;IACH,MAAM,UAAU,GAAe,EAAE,CAAC;IAElC,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC;QACxC,IAAI,EAAE,WAAW;QACjB,KAAK,EAAE,QAAQ;QACf,oBAAoB,EAAE,EAAE;QACxB,eAAe,EAAE,EAAE;KACnB,CAAC,CAAC;IACH,MAAM,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,CAAC;IACvE,UAAU,CAAC,IAAI,CAAC;QACf,KAAK,EAAE,4CAA4C;QACnD,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,QAAQ;QAClC,eAAe,EAAE,QAAQ,CAAC,eAAe,EAAE;KAC3C,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC;QACvC,IAAI,EAAE,YAAY;QAClB,KAAK,EAAE,QAAQ;QACf,oBAAoB,EAAE,CAAC;QACvB,eAAe,EAAE,CAAC;KAClB,CAAC,CAAC;IACH,UAAU,CAAC,IAAI,CAAC;QACf,KAAK,EAAE,qCAAqC;QAC5C,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,QAAQ;QACjC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM;QAC7B,eAAe,EAAE,QAAQ,CAAC,eAAe,EAAE;KAC3C,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC;QACtC,IAAI,EAAE,WAAW;QACjB,KAAK,EAAE,QAAQ;QACf,oBAAoB,EAAE,GAAG;QACzB,eAAe,EAAE,GAAG;KACpB,CAAC,CAAC;IACH,UAAU,CAAC,IAAI,CAAC;QACf,KAAK,EAAE,mDAAmD;QAC1D,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,QAAQ;QAChC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM;QAC5B,eAAe,EAAE,QAAQ,CAAC,eAAe,EAAE;KAC3C,CAAC,CAAC;IAEH,OAAO,UAAU,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ACS-compatible verdict vocabulary.
|
|
3
|
+
*
|
|
4
|
+
* The decision set, the reserved `runtime_error:*` reason namespace, and the
|
|
5
|
+
* `envelope.budgets` counter names are adapted from the Microsoft Agent
|
|
6
|
+
* Governance Toolkit's Agent Control Specification (MIT License) so that
|
|
7
|
+
* usertrust can act as the stateful backend behind an ACS-style stateless
|
|
8
|
+
* policy layer. See the repository NOTICE file for attribution.
|
|
9
|
+
*/
|
|
10
|
+
export declare const ACS_DECISIONS: readonly ["allow", "warn", "deny", "escalate", "transform"];
|
|
11
|
+
export type AcsDecision = (typeof ACS_DECISIONS)[number];
|
|
12
|
+
export interface AcsVerdict {
|
|
13
|
+
decision: AcsDecision;
|
|
14
|
+
reason?: string | undefined;
|
|
15
|
+
}
|
|
16
|
+
export declare function isAcsDecision(value: unknown): value is AcsDecision;
|
|
17
|
+
/** Build a reason string in the reserved `runtime_error:*` namespace. */
|
|
18
|
+
export declare function runtimeError(code: string): string;
|
|
19
|
+
/** Deny-reason names matching the ACS envelope.budgets counter vocabulary. */
|
|
20
|
+
export declare const ACS_BUDGET_REASONS: {
|
|
21
|
+
readonly toolCalls: "budget_tool_call_count_exceeded";
|
|
22
|
+
readonly tokens: "budget_token_count_exceeded";
|
|
23
|
+
readonly elapsed: "budget_elapsed_seconds_exceeded";
|
|
24
|
+
readonly cost: "budget_cost_usd_exceeded";
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* ACS envelope.budgets counters. Counter names follow the ACS schema.
|
|
28
|
+
* Note: usertrust meters in usertokens; `cost_usd` carries the usertoken cost
|
|
29
|
+
* unless the deployment configures a conversion.
|
|
30
|
+
*/
|
|
31
|
+
export interface AcsBudgetsEnvelope {
|
|
32
|
+
tool_call_count: number;
|
|
33
|
+
token_count: number;
|
|
34
|
+
elapsed_seconds: number;
|
|
35
|
+
cost_usd: number;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=vocabulary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vocabulary.d.ts","sourceRoot":"","sources":["../src/vocabulary.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,aAAa,6DAA8D,CAAC;AACzF,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,MAAM,WAAW,UAAU;IAC1B,QAAQ,EAAE,WAAW,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAElE;AAID,yEAAyE;AACzE,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKjD;AAED,8EAA8E;AAC9E,eAAO,MAAM,kBAAkB;;;;;CAKrB,CAAC;AAEX;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IAClC,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;CACjB"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ACS-compatible verdict vocabulary.
|
|
3
|
+
*
|
|
4
|
+
* The decision set, the reserved `runtime_error:*` reason namespace, and the
|
|
5
|
+
* `envelope.budgets` counter names are adapted from the Microsoft Agent
|
|
6
|
+
* Governance Toolkit's Agent Control Specification (MIT License) so that
|
|
7
|
+
* usertrust can act as the stateful backend behind an ACS-style stateless
|
|
8
|
+
* policy layer. See the repository NOTICE file for attribution.
|
|
9
|
+
*/
|
|
10
|
+
export const ACS_DECISIONS = ["allow", "warn", "deny", "escalate", "transform"];
|
|
11
|
+
export function isAcsDecision(value) {
|
|
12
|
+
return typeof value === "string" && ACS_DECISIONS.includes(value);
|
|
13
|
+
}
|
|
14
|
+
const RUNTIME_ERROR_CODE = /^[a-z][a-z0-9_]*$/;
|
|
15
|
+
/** Build a reason string in the reserved `runtime_error:*` namespace. */
|
|
16
|
+
export function runtimeError(code) {
|
|
17
|
+
if (!RUNTIME_ERROR_CODE.test(code)) {
|
|
18
|
+
throw new TypeError(`invalid runtime_error code: ${JSON.stringify(code)}`);
|
|
19
|
+
}
|
|
20
|
+
return `runtime_error:${code}`;
|
|
21
|
+
}
|
|
22
|
+
/** Deny-reason names matching the ACS envelope.budgets counter vocabulary. */
|
|
23
|
+
export const ACS_BUDGET_REASONS = {
|
|
24
|
+
toolCalls: "budget_tool_call_count_exceeded",
|
|
25
|
+
tokens: "budget_token_count_exceeded",
|
|
26
|
+
elapsed: "budget_elapsed_seconds_exceeded",
|
|
27
|
+
cost: "budget_cost_usd_exceeded",
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=vocabulary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vocabulary.js","sourceRoot":"","sources":["../src/vocabulary.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,CAAU,CAAC;AAQzF,MAAM,UAAU,aAAa,CAAC,KAAc;IAC3C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAK,aAAmC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC1F,CAAC;AAED,MAAM,kBAAkB,GAAG,mBAAmB,CAAC;AAE/C,yEAAyE;AACzE,MAAM,UAAU,YAAY,CAAC,IAAY;IACxC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,SAAS,CAAC,+BAA+B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,iBAAiB,IAAI,EAAE,CAAC;AAChC,CAAC;AAED,8EAA8E;AAC9E,MAAM,CAAC,MAAM,kBAAkB,GAAG;IACjC,SAAS,EAAE,iCAAiC;IAC5C,MAAM,EAAE,6BAA6B;IACrC,OAAO,EAAE,iCAAiC;IAC1C,IAAI,EAAE,0BAA0B;CACvB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "usertrust-acs-adapter",
|
|
3
|
+
"version": "1.4.0",
|
|
4
|
+
"description": "ACS/AGT composite-evaluator adapter: external policy decides, the usertrust ledger reserves",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"author": "Usertools, Inc. <hello@usertools.ai> (https://usertrust.ai)",
|
|
7
|
+
"homepage": "https://usertrust.ai",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/usertools-ai/usertrust.git",
|
|
11
|
+
"directory": "packages/acs-adapter"
|
|
12
|
+
},
|
|
13
|
+
"bugs": "https://github.com/usertools-ai/usertrust/issues",
|
|
14
|
+
"keywords": ["ai", "governance", "agent", "acs", "agt", "policy", "adapter"],
|
|
15
|
+
"type": "module",
|
|
16
|
+
"main": "dist/index.js",
|
|
17
|
+
"types": "dist/index.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"import": "./dist/index.js",
|
|
21
|
+
"types": "./dist/index.d.ts"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsc -b",
|
|
26
|
+
"prepublishOnly": "tsc -b"
|
|
27
|
+
},
|
|
28
|
+
"files": ["dist"],
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"usertrust": "*"
|
|
31
|
+
}
|
|
32
|
+
}
|