@crediolabs/policy-synth 1.0.0 → 1.1.1
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/install/build-add-context-rule.js +48 -16
- package/dist/install/build-install-policy.d.ts +41 -0
- package/dist/install/build-install-policy.js +51 -5
- package/dist/predicate/encode.d.ts +12 -0
- package/dist/predicate/encode.js +5 -1
- package/dist/run/index.d.ts +14 -5
- package/dist/run/index.js +263 -14
- package/dist/run/schemas.d.ts +2279 -476
- package/dist/run/schemas.js +192 -26
- package/dist/synth/lower.d.ts +6 -2
- package/dist/synth/lower.js +21 -8
- package/dist/synth/synthesize-from-recording.js +1 -1
- package/dist/types.d.ts +18 -1
- package/dist-cjs/install/build-add-context-rule.js +48 -16
- package/dist-cjs/install/build-install-policy.d.ts +41 -0
- package/dist-cjs/install/build-install-policy.js +52 -5
- package/dist-cjs/predicate/encode.d.ts +12 -0
- package/dist-cjs/predicate/encode.js +5 -0
- package/dist-cjs/run/index.d.ts +14 -5
- package/dist-cjs/run/index.js +263 -13
- package/dist-cjs/run/schemas.d.ts +2279 -476
- package/dist-cjs/run/schemas.js +193 -27
- package/dist-cjs/synth/lower.d.ts +6 -2
- package/dist-cjs/synth/lower.js +21 -8
- package/dist-cjs/synth/synthesize-from-recording.js +1 -1
- package/dist-cjs/types.d.ts +18 -1
- package/package.json +1 -1
- package/src/install/build-add-context-rule.ts +65 -21
- package/src/install/build-install-policy.ts +100 -12
- package/src/predicate/encode.ts +5 -1
- package/src/run/index.ts +280 -23
- package/src/run/schemas.ts +229 -43
- package/src/synth/lower.ts +22 -8
- package/src/synth/synthesize-from-recording.ts +1 -1
- package/src/types.ts +25 -6
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
// the account refuses with `Error(Auth, InvalidAction)`.
|
|
49
49
|
import { createHash } from 'node:crypto';
|
|
50
50
|
import { Address, xdr } from '@stellar/stellar-sdk';
|
|
51
|
+
import { scvI128FromDecimal } from "../predicate/encode.js";
|
|
51
52
|
import { GRAMMAR_VERSION, OZ_LIMITS, } from "../types.js";
|
|
52
53
|
export const DEFAULT_GRAMMAR_VERSION = GRAMMAR_VERSION;
|
|
53
54
|
/** The verb `add_context_rule` takes on the wire. */
|
|
@@ -121,27 +122,58 @@ function encodeSigner(s) {
|
|
|
121
122
|
function encodePoliciesMap(args) {
|
|
122
123
|
const entries = [];
|
|
123
124
|
for (const ref of args.policies) {
|
|
124
|
-
//
|
|
125
|
-
//
|
|
126
|
-
//
|
|
127
|
-
//
|
|
128
|
-
//
|
|
129
|
-
//
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
125
|
+
// Each policy carries its OWN params. This loop once applied one set of
|
|
126
|
+
// install params to every entry, which is why nothing but the interpreter
|
|
127
|
+
// could be expressed; before that it dropped other kinds in silence, so a
|
|
128
|
+
// caller attaching a cap received a rule without it and no indication.
|
|
129
|
+
// Both directions were wrong. An unknown kind still fails loudly below - a
|
|
130
|
+
// dropped policy is a missing restriction.
|
|
131
|
+
switch (ref.kind) {
|
|
132
|
+
case 'interpreter':
|
|
133
|
+
entries.push(new xdr.ScMapEntry({
|
|
134
|
+
key: Address.fromString(ref.interpreterAddress).toScVal(),
|
|
135
|
+
val: encodePolicyInstallParams(args),
|
|
136
|
+
}));
|
|
137
|
+
break;
|
|
138
|
+
case 'spending_limit':
|
|
139
|
+
entries.push(new xdr.ScMapEntry({
|
|
140
|
+
key: Address.fromString(ref.policyAddress).toScVal(),
|
|
141
|
+
val: encodeSpendingLimitParams(ref),
|
|
142
|
+
}));
|
|
143
|
+
break;
|
|
144
|
+
default: {
|
|
145
|
+
const kind = JSON.stringify(ref.kind ?? null);
|
|
146
|
+
throw limitError('INSTALL_BUILD_FAILED', `policy kind ${kind} is not supported; dropping it here would install a rule missing the restriction you asked for`);
|
|
147
|
+
}
|
|
136
148
|
}
|
|
137
|
-
entries.push(new xdr.ScMapEntry({
|
|
138
|
-
key: Address.fromString(ref.interpreterAddress).toScVal(),
|
|
139
|
-
val: encodePolicyInstallParams(args),
|
|
140
|
-
}));
|
|
141
149
|
}
|
|
142
150
|
entries.sort(sortByScValSymbolString);
|
|
143
151
|
return xdr.ScVal.scvMap(entries);
|
|
144
152
|
}
|
|
153
|
+
/** OpenZeppelin `spending_limit`'s install params: `{ period_ledgers: u32,
|
|
154
|
+
* spending_limit: i128 }`, emitted in symbol-string order. Validated here
|
|
155
|
+
* rather than left to the chain, because a rolling cap that fails at submit
|
|
156
|
+
* has already cost the caller a signature. */
|
|
157
|
+
function encodeSpendingLimitParams(ref) {
|
|
158
|
+
if (!Number.isInteger(ref.periodLedgers) || ref.periodLedgers <= 0) {
|
|
159
|
+
throw limitError('INSTALL_BUILD_FAILED', `spending_limit periodLedgers must be a positive integer - it counts LEDGERS, not seconds; got: ${ref.periodLedgers}`);
|
|
160
|
+
}
|
|
161
|
+
if (!/^[0-9]+$/.test(ref.spendingLimit) || BigInt(ref.spendingLimit) <= 0n) {
|
|
162
|
+
throw limitError('INSTALL_BUILD_FAILED', `spending_limit must be a positive integer in the token's smallest unit; got: ${ref.spendingLimit}`);
|
|
163
|
+
}
|
|
164
|
+
const entries = [
|
|
165
|
+
new xdr.ScMapEntry({
|
|
166
|
+
key: xdr.ScVal.scvSymbol('period_ledgers'),
|
|
167
|
+
val: xdr.ScVal.scvU32(ref.periodLedgers),
|
|
168
|
+
}),
|
|
169
|
+
new xdr.ScMapEntry({
|
|
170
|
+
key: xdr.ScVal.scvSymbol('spending_limit'),
|
|
171
|
+
val: scvI128FromDecimal(ref.spendingLimit),
|
|
172
|
+
}),
|
|
173
|
+
];
|
|
174
|
+
entries.sort((a, b) => sortBySymbolString(a.key(), b.key()));
|
|
175
|
+
return xdr.ScVal.scvMap(entries);
|
|
176
|
+
}
|
|
145
177
|
function encodePolicyInstallParams(args) {
|
|
146
178
|
const predicate = Buffer.from(args.encodedPredicate, 'base64');
|
|
147
179
|
const computedHash = createHash('sha256').update(predicate).digest('hex');
|
|
@@ -93,6 +93,13 @@ export interface InstallCallDescribes {
|
|
|
93
93
|
installNonce: number;
|
|
94
94
|
predicateHash: string;
|
|
95
95
|
predicateSha256OfEmbeddedBytes: string;
|
|
96
|
+
} | {
|
|
97
|
+
/** An OpenZeppelin built-in bounding the SUM across calls, which the
|
|
98
|
+
* predicate cannot: the interpreter sees one call and keeps no state. */
|
|
99
|
+
kind: 'spending_limit';
|
|
100
|
+
address: string;
|
|
101
|
+
periodLedgers: number;
|
|
102
|
+
spendingLimit: string;
|
|
96
103
|
}>;
|
|
97
104
|
/** The install nonce, decoded from the interpreter policy's
|
|
98
105
|
* `install_nonce` field. Echoed at the top level for reviewer convenience;
|
|
@@ -105,6 +112,21 @@ export interface InstallCallDescribes {
|
|
|
105
112
|
export interface BuildInstallPolicyResult {
|
|
106
113
|
/** Unsigned Soroban transaction envelope, base64 XDR. */
|
|
107
114
|
unsignedXdr: string;
|
|
115
|
+
/** Length and SHA-256 of `unsignedXdr`, so a caller that has to move it can
|
|
116
|
+
* prove it arrived whole.
|
|
117
|
+
*
|
|
118
|
+
* This envelope runs to several thousand characters, and the only route
|
|
119
|
+
* from a tool result onto disk is the caller re-emitting it. A truncated
|
|
120
|
+
* copy is not obviously wrong - it fails later as
|
|
121
|
+
* "failed to decode XDR: xdr value invalid", which reads like a malformed
|
|
122
|
+
* transaction rather than a transport problem. Observed in practice: one of
|
|
123
|
+
* two envelopes written in the same session lost its tail and its base64
|
|
124
|
+
* length went from a multiple of four to `len % 4 == 3`.
|
|
125
|
+
*
|
|
126
|
+
* Check both before signing. They are cheap, and they turn a silent,
|
|
127
|
+
* fatal truncation into a retry. */
|
|
128
|
+
unsignedXdrLength: number;
|
|
129
|
+
unsignedXdrSha256: string;
|
|
108
130
|
/** Smart account contract address (echo). */
|
|
109
131
|
smartAccount: string;
|
|
110
132
|
/** Source account (echo) - the address that must sign. */
|
|
@@ -161,6 +183,11 @@ export declare function buildRevokePolicyXdr(args: {
|
|
|
161
183
|
}): Promise<BuildRevokePolicyResult>;
|
|
162
184
|
export interface BuildRevokePolicyResult {
|
|
163
185
|
unsignedXdr: string;
|
|
186
|
+
/** Same integrity pair as the install result, for the same reason: a revoke
|
|
187
|
+
* envelope also has to reach a signer intact, and a truncated copy fails as
|
|
188
|
+
* a malformed transaction rather than as a transport error. */
|
|
189
|
+
unsignedXdrLength: number;
|
|
190
|
+
unsignedXdrSha256: string;
|
|
164
191
|
smartAccount: string;
|
|
165
192
|
sourceAccount: string;
|
|
166
193
|
call: {
|
|
@@ -172,3 +199,17 @@ export interface BuildRevokePolicyResult {
|
|
|
172
199
|
authValidUntilLedger: number;
|
|
173
200
|
rootInvocationXdr: string;
|
|
174
201
|
}
|
|
202
|
+
/** The actionable half of a failed simulation, with the transport half left out.
|
|
203
|
+
*
|
|
204
|
+
* `sim.error` names both why the chain refused the call and which host was
|
|
205
|
+
* asked, and the second half must not reach a caller. So we return only
|
|
206
|
+
* Soroban's own `Error(Type, #Code)` forms: those are contract state, and they
|
|
207
|
+
* are what tells an operator whether the source account lacks authority, a
|
|
208
|
+
* nonce is stale, or a predicate refused. Without them "simulateTransaction
|
|
209
|
+
* failed" names nothing a caller can act on.
|
|
210
|
+
*
|
|
211
|
+
* Returns "" when the error carries no such form, so the caller keeps its short
|
|
212
|
+
* stable message rather than gaining an empty parenthesis. */
|
|
213
|
+
export declare function simulationReason(sim: {
|
|
214
|
+
error?: string;
|
|
215
|
+
}): string;
|
|
@@ -62,6 +62,14 @@ export function rpcClientFromServer(server, networkPassphrase) {
|
|
|
62
62
|
},
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
|
+
/** `unsignedXdr` plus the length and digest that prove it arrived whole. */
|
|
66
|
+
function xdrIntegrity(unsignedXdr) {
|
|
67
|
+
return {
|
|
68
|
+
unsignedXdr,
|
|
69
|
+
unsignedXdrLength: unsignedXdr.length,
|
|
70
|
+
unsignedXdrSha256: createHash('sha256').update(unsignedXdr, 'utf8').digest('hex'),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
65
73
|
/** Build the unsigned transaction envelope for `account.add_context_rule(...)`.
|
|
66
74
|
* The output XDR is signed by the wallet, not by us. */
|
|
67
75
|
export async function buildInstallPolicyXdr(args) {
|
|
@@ -90,7 +98,7 @@ export async function buildInstallPolicyXdr(args) {
|
|
|
90
98
|
// The human approval binds to the exact bytes the wallet will sign.
|
|
91
99
|
const describes = decodeInstallCallDescribes(finalTx, args.installNonce);
|
|
92
100
|
return {
|
|
93
|
-
|
|
101
|
+
...xdrIntegrity(finalTx.toEnvelope().toXDR().toString('base64')),
|
|
94
102
|
smartAccount: args.smartAccount,
|
|
95
103
|
sourceAccount: args.sourceAccount,
|
|
96
104
|
call: { contract: args.smartAccount, fn: 'add_context_rule' },
|
|
@@ -119,7 +127,7 @@ export async function buildRevokePolicyXdr(args) {
|
|
|
119
127
|
// consumer supplies only the ordinary envelope signature.
|
|
120
128
|
const { finalTx, original, validUntilLedger } = await buildAuthorisedSmartAccountTx(args, 'remove_context_rule', [xdr.ScVal.scvU32(args.ruleId)], 'revoke_policy');
|
|
121
129
|
return {
|
|
122
|
-
|
|
130
|
+
...xdrIntegrity(finalTx.toEnvelope().toXDR().toString('base64')),
|
|
123
131
|
smartAccount: args.smartAccount,
|
|
124
132
|
sourceAccount: args.sourceAccount,
|
|
125
133
|
call: { contract: args.smartAccount, fn: 'remove_context_rule', ruleId: args.ruleId },
|
|
@@ -131,6 +139,21 @@ export async function buildRevokePolicyXdr(args) {
|
|
|
131
139
|
/** ~25 minutes at 5s/ledger. */
|
|
132
140
|
const DEFAULT_AUTH_VALID_UNTIL_LEDGERS = 300;
|
|
133
141
|
// ---- internals ----
|
|
142
|
+
/** The actionable half of a failed simulation, with the transport half left out.
|
|
143
|
+
*
|
|
144
|
+
* `sim.error` names both why the chain refused the call and which host was
|
|
145
|
+
* asked, and the second half must not reach a caller. So we return only
|
|
146
|
+
* Soroban's own `Error(Type, #Code)` forms: those are contract state, and they
|
|
147
|
+
* are what tells an operator whether the source account lacks authority, a
|
|
148
|
+
* nonce is stale, or a predicate refused. Without them "simulateTransaction
|
|
149
|
+
* failed" names nothing a caller can act on.
|
|
150
|
+
*
|
|
151
|
+
* Returns "" when the error carries no such form, so the caller keeps its short
|
|
152
|
+
* stable message rather than gaining an empty parenthesis. */
|
|
153
|
+
export function simulationReason(sim) {
|
|
154
|
+
const codes = [...new Set((sim.error ?? '').match(/Error\([^)]*\)/g) ?? [])];
|
|
155
|
+
return codes.length > 0 ? ` (${codes.join(', ')})` : '';
|
|
156
|
+
}
|
|
134
157
|
/** Record a bare call to the smart account, attach the deploy-time admin rule's
|
|
135
158
|
* auth entries, and re-simulate to assemble the footprint.
|
|
136
159
|
*
|
|
@@ -160,8 +183,10 @@ async function buildAuthorisedSmartAccountTx(args, functionName, callArgs, error
|
|
|
160
183
|
// Short, stable reason. The full `simulateTransaction` error (which
|
|
161
184
|
// carries host + URL detail) stays in the SDK's own logs - never
|
|
162
185
|
// reflected back into a user-facing message where it would
|
|
163
|
-
// reconnoitre the RPC.
|
|
164
|
-
|
|
186
|
+
// reconnoitre the RPC. `simulationReason` re-adds only the chain's own
|
|
187
|
+
// error codes, which say why the call was refused without saying where
|
|
188
|
+
// the RPC lives.
|
|
189
|
+
throw new Error(`${errorPrefix}: simulateTransaction failed${simulationReason(recorded)}`);
|
|
165
190
|
}
|
|
166
191
|
const original = (recorded.result?.auth ?? []).find((entry) => entry.credentials().switch().name === 'sorobanCredentialsAddress' &&
|
|
167
192
|
Address.fromScAddress(entry.credentials().address().address()).toString() ===
|
|
@@ -180,7 +205,7 @@ async function buildAuthorisedSmartAccountTx(args, functionName, callArgs, error
|
|
|
180
205
|
const txWithAuth = buildTx(makeOperation(authEntries));
|
|
181
206
|
const enforcing = await args.rpc.simulateTransaction(txWithAuth);
|
|
182
207
|
if (rpc.Api.isSimulationError(enforcing)) {
|
|
183
|
-
throw new Error(`${errorPrefix}: auth simulateTransaction failed`);
|
|
208
|
+
throw new Error(`${errorPrefix}: auth simulateTransaction failed${simulationReason(enforcing)}`);
|
|
184
209
|
}
|
|
185
210
|
return {
|
|
186
211
|
finalTx: rpc.assembleTransaction(txWithAuth, enforcing).build(),
|
|
@@ -354,6 +379,27 @@ function decodeInstallCallDescribes(tx, expectedInstallNonce) {
|
|
|
354
379
|
observedInstallNonce = installNonce;
|
|
355
380
|
continue;
|
|
356
381
|
}
|
|
382
|
+
// OpenZeppelin `spending_limit`: { period_ledgers: u32, spending_limit: i128 }.
|
|
383
|
+
if (fields.has('period_ledgers') || fields.has('spending_limit')) {
|
|
384
|
+
const periodScv = fields.get('period_ledgers');
|
|
385
|
+
if (periodScv?.switch().name !== 'scvU32') {
|
|
386
|
+
throw new Error(`install_policy: spending_limit policy ${address} is missing a u32 period_ledgers`);
|
|
387
|
+
}
|
|
388
|
+
const limitScv = fields.get('spending_limit');
|
|
389
|
+
if (limitScv?.switch().name !== 'scvI128') {
|
|
390
|
+
throw new Error(`install_policy: spending_limit policy ${address} is missing an i128 spending_limit`);
|
|
391
|
+
}
|
|
392
|
+
const parts = limitScv.i128();
|
|
393
|
+
const spendingLimit = ((BigInt(parts.hi().toString()) << 64n) +
|
|
394
|
+
BigInt(parts.lo().toString())).toString();
|
|
395
|
+
policies.push({
|
|
396
|
+
kind: 'spending_limit',
|
|
397
|
+
address,
|
|
398
|
+
periodLedgers: periodScv.u32(),
|
|
399
|
+
spendingLimit,
|
|
400
|
+
});
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
357
403
|
throw new Error(`install_policy: policies[${address}] value has an unknown field set; the encoder may have drifted`);
|
|
358
404
|
}
|
|
359
405
|
// `observedInstallNonce` is the nonce baked into whichever interpreter
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { xdr } from '@stellar/stellar-sdk';
|
|
1
2
|
import { type PredicateNode } from '../types.ts';
|
|
2
3
|
export interface EncodedPredicate {
|
|
3
4
|
/** base64 of the canonical ScVal XDR of the predicate root. */
|
|
@@ -8,3 +9,14 @@ export interface EncodedPredicate {
|
|
|
8
9
|
/** Encode a `PredicateNode` to the canonical ScVal wire format and hash it.
|
|
9
10
|
* Pure function: same input -> byte-identical output every run. */
|
|
10
11
|
export declare function encodePredicate(node: PredicateNode): EncodedPredicate;
|
|
12
|
+
/** Build `ScVal::I128(Int128Parts{hi, lo})` from a signed decimal string.
|
|
13
|
+
* `Int128Parts` encodes the value as `(hi << 64) + lo` with `hi` a SIGNED
|
|
14
|
+
* 64-bit int and `lo` an UNSIGNED 64-bit int (this is NOT signed-magnitude).
|
|
15
|
+
* The inverse split is `hi = v >> 64n` (arithmetic right shift) and
|
|
16
|
+
* `lo = v & 0xFFFF...`. The SDK's `Int64` constructor takes a signed
|
|
17
|
+
* bigint/string/number. */
|
|
18
|
+
/** Canonical i128 encoding of a base-10 decimal string, with the Int64 range
|
|
19
|
+
* guard on the high word. Exported so the install builder encodes an
|
|
20
|
+
* OpenZeppelin amount the same way a predicate literal is encoded - a second
|
|
21
|
+
* implementation is how a value above 2^64 silently loses its high word. */
|
|
22
|
+
export declare function scvI128FromDecimal(decimal: string): xdr.ScVal;
|
package/dist/predicate/encode.js
CHANGED
|
@@ -231,7 +231,11 @@ function scvAddressFromStrkey(strkey) {
|
|
|
231
231
|
* The inverse split is `hi = v >> 64n` (arithmetic right shift) and
|
|
232
232
|
* `lo = v & 0xFFFF...`. The SDK's `Int64` constructor takes a signed
|
|
233
233
|
* bigint/string/number. */
|
|
234
|
-
|
|
234
|
+
/** Canonical i128 encoding of a base-10 decimal string, with the Int64 range
|
|
235
|
+
* guard on the high word. Exported so the install builder encodes an
|
|
236
|
+
* OpenZeppelin amount the same way a predicate literal is encoded - a second
|
|
237
|
+
* implementation is how a value above 2^64 silently loses its high word. */
|
|
238
|
+
export function scvI128FromDecimal(decimal) {
|
|
235
239
|
const v = BigInt(decimal);
|
|
236
240
|
const hi = v >> 64n;
|
|
237
241
|
const lo = v & UINT64_MAX;
|
package/dist/run/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { type ErrorCode, type PredicateNode, type ProposedPolicy, type RecordedT
|
|
|
2
2
|
import { type AuthorityOverlap } from '../install/authority-overlap.ts';
|
|
3
3
|
import { type BuildInstallPolicyResult, type BuildRevokePolicyResult } from '../install/build-install-policy.ts';
|
|
4
4
|
import { getInterpreterInfo } from '../install/get-interpreter-info.ts';
|
|
5
|
-
import { type RecordTransactionInput, type SimulatePolicyInput, type SynthesizePolicyInput, type VerifyPolicyInput } from './schemas.ts';
|
|
5
|
+
import { type InstallPolicyInput, type RecordTransactionInput, type SimulatePolicyInput, type SynthesizePolicyInput, type VerifyPolicyInput } from './schemas.ts';
|
|
6
6
|
export type { DeclarePolicyInput, GetInterpreterInfoInput, InstallPolicyInput, OzBuiltinPolicy, RecordTransactionInput, RevokePolicyInput, SimulatePolicyInput, SynthesizePolicyInput, VerifyPolicyInput, } from './schemas.ts';
|
|
7
7
|
export { ComposeUserResponsesSchema, DeclarePolicyInputSchema, GetInterpreterInfoInputSchema, InstallPolicyInputSchema, InterpreterOptionsSchema, MAINNET_RPC_URL, NetworkSchema, PINNED_INTERPRETER_ADDRESS_BY_NETWORK, PINNED_INTERPRETER_GRAMMAR_VERSION, PINNED_INTERPRETER_MAINNET_ADDRESS, PINNED_INTERPRETER_TESTNET_ADDRESS, PINNED_INTERPRETER_WASM_SHA256, PINNED_OZ_POLICY_ADDRESS_BY_NETWORK, PINNED_OZ_POLICY_WASM_SHA256, PredicateLeafSchema, PredicateNodeSchema, RecordedTransactionSchema, RecordTransactionInputSchema, RevokePolicyInputSchema, RPC_URL_BY_NETWORK, SynthesizePolicyInputSchema, TESTNET_RPC_URL, ToolErrorSchema, } from './schemas.ts';
|
|
8
8
|
export type RunRecordTransactionInput = RecordTransactionInput;
|
|
@@ -51,13 +51,22 @@ export declare function runInstallPolicy(raw: unknown): Promise<ToolResponse<Bui
|
|
|
51
51
|
* policy payload, so the interpreter pin is not re-checked here.
|
|
52
52
|
* Pin selection follows `input.network` (defaults to `testnet`). */
|
|
53
53
|
export declare function runRevokePolicy(raw: unknown): Promise<ToolResponse<BuildRevokePolicyResult>>;
|
|
54
|
+
/** Scope a rule to whatever contract its predicate pins.
|
|
55
|
+
*
|
|
56
|
+
* Taking this from the predicate rather than from a separate argument means
|
|
57
|
+
* the rule's scope cannot drift from what the predicate actually checks. A
|
|
58
|
+
* predicate that pins no contract yields the default (account-wide) type,
|
|
59
|
+
* which is what an unpinned predicate means. Only the top level is walked:
|
|
60
|
+
* a contract pin nested under an `or` does not scope the rule, because the
|
|
61
|
+
* other branch would not be covered by it. */
|
|
62
|
+
export declare function contextTypeForPredicate(predicate: PredicateNode): NonNullable<InstallPolicyInput['rule']>['contextRuleType'];
|
|
54
63
|
/** `simulate_policy` body - evaluate a predicate against one recorded call.
|
|
55
64
|
*
|
|
56
65
|
* The evaluator is a second implementation of the on-chain semantics, and the
|
|
57
66
|
* conformance harness asserts it agrees with the Rust interpreter case for
|
|
58
67
|
* case. A verdict here is therefore a claim about what the contract would do,
|
|
59
68
|
* not a guess. */
|
|
60
|
-
export declare function runSimulatePolicy(raw: unknown): ToolResponse<{
|
|
69
|
+
export declare function runSimulatePolicy(raw: unknown): Promise<ToolResponse<{
|
|
61
70
|
permitted: boolean;
|
|
62
71
|
reason: string | null;
|
|
63
72
|
call: {
|
|
@@ -65,7 +74,7 @@ export declare function runSimulatePolicy(raw: unknown): ToolResponse<{
|
|
|
65
74
|
fn: string;
|
|
66
75
|
argCount: number;
|
|
67
76
|
};
|
|
68
|
-
}
|
|
77
|
+
}>>;
|
|
69
78
|
/** `declare_policy` body - the DECLARATIVE front-end.
|
|
70
79
|
*
|
|
71
80
|
* `synthesize_policy` infers a predicate from a transaction that happened;
|
|
@@ -92,7 +101,7 @@ export declare function runDeclarePolicy(raw: unknown): ToolResponse<{
|
|
|
92
101
|
* very transaction it was synthesised from. A deny case that permits means it
|
|
93
102
|
* is too LOOSE: some mutation of that transaction still gets through. `ok` is
|
|
94
103
|
* true only when neither holds. */
|
|
95
|
-
export declare function runVerifyPolicy(raw: unknown): ToolResponse<{
|
|
104
|
+
export declare function runVerifyPolicy(raw: unknown): Promise<ToolResponse<{
|
|
96
105
|
ok: boolean;
|
|
97
106
|
permit: {
|
|
98
107
|
permitted: boolean;
|
|
@@ -104,6 +113,6 @@ export declare function runVerifyPolicy(raw: unknown): ToolResponse<{
|
|
|
104
113
|
reason: string | null;
|
|
105
114
|
}>;
|
|
106
115
|
dimensionsCovered: number;
|
|
107
|
-
}
|
|
116
|
+
}>>;
|
|
108
117
|
export declare function runGetInterpreterInfo(raw: unknown): Promise<ToolResponse<ReturnType<typeof getInterpreterInfo>>>;
|
|
109
118
|
export declare function caughtError(toolName: RunToolName, code: ErrorCode, e: unknown): ToolError;
|