@crediolabs/policy-synth 0.1.17 → 0.2.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 +44 -246
- package/dist/adapters/interpreter/adapter.d.ts +6 -7
- package/dist/adapters/interpreter/adapter.js +28 -48
- package/dist/adapters/oz/adapter.js +12 -13
- package/dist/codegen/compile-gate.js +5 -0
- package/dist/codegen/template.js +17 -0
- package/dist/install/authority-overlap.d.ts +134 -0
- package/dist/install/authority-overlap.js +0 -0
- package/dist/install/build-add-context-rule.d.ts +8 -0
- package/dist/install/build-add-context-rule.js +17 -46
- package/dist/install/build-install-policy.d.ts +12 -5
- package/dist/install/build-install-policy.js +32 -23
- package/dist/install/build-merge-policy.d.ts +70 -0
- package/dist/install/build-merge-policy.js +130 -0
- package/dist/install/get-interpreter-info.js +2 -2
- package/dist/install/index.d.ts +3 -1
- package/dist/install/index.js +8 -1
- package/dist/install/oz-auth.js +5 -3
- package/dist/install/plan-merge-policy.d.ts +49 -0
- package/dist/install/plan-merge-policy.js +86 -0
- package/dist/install/read-account-rules.d.ts +100 -0
- package/dist/install/read-account-rules.js +283 -0
- package/dist/predicate/decode.js +1 -1
- package/dist/predicate/encode.js +171 -10
- package/dist/record/decode.js +5 -6
- package/dist/registry/protocols.d.ts +1 -1
- package/dist/registry/protocols.js +1 -1
- package/dist/review-card/builder.d.ts +6 -0
- package/dist/review-card/builder.js +9 -1
- package/dist/run/index.d.ts +104 -18
- package/dist/run/index.js +359 -75
- package/dist/run/schemas.d.ts +479 -18
- package/dist/run/schemas.js +132 -24
- package/dist/synth/compose-from-recording.d.ts +10 -15
- package/dist/synth/compose-from-recording.js +79 -124
- package/dist/synth/deny-cases.d.ts +5 -0
- package/dist/synth/deny-cases.js +52 -13
- package/dist/synth/evaluate.js +69 -119
- package/dist/synth/harness.d.ts +13 -1
- package/dist/synth/harness.js +22 -1
- package/dist/synth/index.d.ts +1 -1
- package/dist/synth/synthesize-from-recording.d.ts +31 -21
- package/dist/synth/synthesize-from-recording.js +129 -155
- package/dist-cjs/adapters/interpreter/adapter.d.ts +6 -7
- package/dist-cjs/adapters/interpreter/adapter.js +28 -48
- package/dist-cjs/adapters/oz/adapter.js +12 -13
- package/dist-cjs/codegen/compile-gate.js +5 -0
- package/dist-cjs/codegen/template.js +17 -0
- package/dist-cjs/install/authority-overlap.d.ts +134 -0
- package/dist-cjs/install/authority-overlap.js +0 -0
- package/dist-cjs/install/build-add-context-rule.d.ts +8 -0
- package/dist-cjs/install/build-add-context-rule.js +17 -45
- package/dist-cjs/install/build-install-policy.d.ts +12 -5
- package/dist-cjs/install/build-install-policy.js +32 -23
- package/dist-cjs/install/build-merge-policy.d.ts +70 -0
- package/dist-cjs/install/build-merge-policy.js +134 -0
- package/dist-cjs/install/get-interpreter-info.js +2 -2
- package/dist-cjs/install/index.d.ts +3 -1
- package/dist-cjs/install/index.js +24 -3
- package/dist-cjs/install/oz-auth.js +5 -3
- package/dist-cjs/install/plan-merge-policy.d.ts +49 -0
- package/dist-cjs/install/plan-merge-policy.js +90 -0
- package/dist-cjs/install/read-account-rules.d.ts +100 -0
- package/dist-cjs/install/read-account-rules.js +296 -0
- package/dist-cjs/predicate/decode.js +1 -1
- package/dist-cjs/predicate/encode.js +171 -10
- package/dist-cjs/record/decode.js +5 -6
- package/dist-cjs/registry/protocols.d.ts +1 -1
- package/dist-cjs/registry/protocols.js +1 -1
- package/dist-cjs/review-card/builder.d.ts +6 -0
- package/dist-cjs/review-card/builder.js +9 -1
- package/dist-cjs/run/index.d.ts +104 -18
- package/dist-cjs/run/index.js +360 -74
- package/dist-cjs/run/schemas.d.ts +479 -18
- package/dist-cjs/run/schemas.js +133 -25
- package/dist-cjs/synth/compose-from-recording.d.ts +10 -15
- package/dist-cjs/synth/compose-from-recording.js +79 -124
- package/dist-cjs/synth/deny-cases.d.ts +5 -0
- package/dist-cjs/synth/deny-cases.js +52 -13
- package/dist-cjs/synth/evaluate.js +69 -119
- package/dist-cjs/synth/harness.d.ts +13 -1
- package/dist-cjs/synth/harness.js +22 -1
- package/dist-cjs/synth/index.d.ts +1 -1
- package/dist-cjs/synth/synthesize-from-recording.d.ts +31 -21
- package/dist-cjs/synth/synthesize-from-recording.js +129 -153
- package/package.json +1 -1
- package/src/adapters/interpreter/adapter.ts +28 -48
- package/src/adapters/oz/adapter.ts +12 -13
- package/src/codegen/compile-gate.ts +5 -0
- package/src/codegen/template.ts +17 -0
- package/src/install/authority-overlap.ts +0 -0
- package/src/install/build-add-context-rule.ts +29 -56
- package/src/install/build-install-policy.ts +41 -23
- package/src/install/build-merge-policy.ts +219 -0
- package/src/install/get-interpreter-info.ts +2 -2
- package/src/install/index.ts +36 -2
- package/src/install/oz-auth.ts +5 -3
- package/src/install/plan-merge-policy.ts +133 -0
- package/src/install/read-account-rules.ts +376 -0
- package/src/predicate/decode.ts +1 -1
- package/src/predicate/encode.ts +176 -10
- package/src/record/decode.ts +5 -6
- package/src/registry/protocols.ts +1 -1
- package/src/review-card/builder.ts +17 -1
- package/src/run/index.ts +500 -102
- package/src/run/schemas.ts +145 -24
- package/src/synth/compose-from-recording.ts +87 -132
- package/src/synth/deny-cases.ts +59 -13
- package/src/synth/evaluate.ts +70 -118
- package/src/synth/harness.ts +29 -1
- package/src/synth/index.ts +1 -0
- package/src/synth/synthesize-from-recording.ts +209 -192
- package/src/contracts/policy-template/OZ_POLICY_TRAIT.md +0 -196
package/dist-cjs/run/schemas.js
CHANGED
|
@@ -8,15 +8,15 @@
|
|
|
8
8
|
// step with the TS source of truth.
|
|
9
9
|
//
|
|
10
10
|
// i128 amounts and other large integers are carried as base-10 decimal strings
|
|
11
|
-
// end-to-end
|
|
12
|
-
//
|
|
13
|
-
//
|
|
11
|
+
// end-to-end. Networks are pinned to the same closed set the core defines.
|
|
12
|
+
// The discriminated union on `source` exposes BOTH synthesize_policy
|
|
13
|
+
// front-ends through a single tool input.
|
|
14
14
|
//
|
|
15
15
|
// This module is the SINGLE source of truth for these shapes. The MCP package
|
|
16
16
|
// imports them here so its tool-shape bindings stay in step; the CLI imports
|
|
17
17
|
// them here so it can build the same args envelope the MCP transport builds.
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
-
exports.ToolErrorSchema = exports.GetInterpreterInfoInputSchema = exports.RevokePolicyInputSchema = exports.InstallPolicyInputSchema = exports.NETWORK_PASSPHRASES = exports.DEFAULT_AUTH_VALID_UNTIL_LEDGERS = exports.RPC_URL_BY_NETWORK = exports.PINNED_INTERPRETER_ADDRESS_BY_NETWORK = exports.MAINNET_RPC_URL = exports.TESTNET_RPC_URL = exports.PINNED_INTERPRETER_GRAMMAR_VERSION = exports.PINNED_INTERPRETER_WASM_SHA256 = exports.PINNED_INTERPRETER_MAINNET_ADDRESS = exports.PINNED_INTERPRETER_TESTNET_ADDRESS = exports.VerifyPolicyInputSchema = exports.SimulatePolicyInputSchema = exports.OraclePriceFixtureSchema = exports.PredicateNodeSchema = exports.PredicateLeafSchema = exports.SynthesizePolicyInputSchema = exports.SynthesizePolicyRecordingInputSchema = exports.InterpreterOptionsSchema = exports.SynthesizePolicyMandateInputSchema = exports.RecordTransactionInputSchema = exports.OzAdapterConfigSchema = exports.ComposeUserResponsesSchema = exports.MandateSpecSchema = exports.RecordedTransactionSchema = exports.ParseConfidenceSchema = exports.OnChainEventSchema = exports.TokenMovementSchema = exports.ContractInvocationSchema = exports.ScValSchema = exports.NetworkSchema = void 0;
|
|
19
|
+
exports.ToolErrorSchema = exports.GetInterpreterInfoInputSchema = exports.RevokePolicyInputSchema = exports.MergePolicyInputSchema = exports.InstallPolicyInputSchema = exports.NETWORK_PASSPHRASES = exports.DEFAULT_AUTH_VALID_UNTIL_LEDGERS = exports.RPC_URL_BY_NETWORK = exports.PINNED_INTERPRETER_WASM_SHA256_BY_NETWORK = exports.PINNED_INTERPRETER_ADDRESS_BY_NETWORK = exports.MAINNET_RPC_URL = exports.TESTNET_RPC_URL = exports.PINNED_INTERPRETER_GRAMMAR_VERSION = exports.PINNED_INTERPRETER_WASM_SHA256_TESTNET = exports.PINNED_INTERPRETER_WASM_SHA256 = exports.PINNED_INTERPRETER_MAINNET_ADDRESS = exports.PINNED_INTERPRETER_TESTNET_ADDRESS = exports.VerifyPolicyInputSchema = exports.SimulatePolicyInputSchema = exports.OraclePriceFixtureSchema = exports.PredicateNodeSchema = exports.PredicateLeafSchema = exports.SynthesizePolicyInputSchema = exports.SynthesizePolicyRecordingInputSchema = exports.InterpreterOptionsSchema = exports.SynthesizePolicyMandateInputSchema = exports.RecordTransactionInputSchema = exports.OzAdapterConfigSchema = exports.ComposeUserResponsesSchema = exports.MandateSpecSchema = exports.RecordedTransactionSchema = exports.ParseConfidenceSchema = exports.OnChainEventSchema = exports.TokenMovementSchema = exports.ContractInvocationSchema = exports.ScValSchema = exports.NetworkSchema = void 0;
|
|
20
20
|
const zod_1 = require("zod");
|
|
21
21
|
const address_ts_1 = require("../synth/address.js");
|
|
22
22
|
/** Soroban `valid_until` is a u32 ledger sequence; a value above this cannot be
|
|
@@ -126,7 +126,21 @@ exports.MandateSpecSchema = zod_1.z
|
|
|
126
126
|
})
|
|
127
127
|
.optional(),
|
|
128
128
|
})
|
|
129
|
-
.passthrough()
|
|
129
|
+
.passthrough()
|
|
130
|
+
// TS-F4/F6: a `recipients` allowlist is only meaningful against a SEP-41
|
|
131
|
+
// method whose arg 1 IS the recipient (SAC/SEP-41 `transfer(from, to,
|
|
132
|
+
// amount)` and SEP-41 `mint(to, amount)`). Without this gate the
|
|
133
|
+
// `to-ir.ts` lowering pins the allowlist to `RECIPIENT_ARG_INDEX = 1`
|
|
134
|
+
// for any contract+method, which would let a non-SEP-41 method's
|
|
135
|
+
// arg[1] (e.g. an amount, an op type, an arbitrary address payload)
|
|
136
|
+
// be silently constrained as if it were a recipient. Refusing
|
|
137
|
+
// non-SEP-41 methods at the boundary is the fail-closed shape.
|
|
138
|
+
.refine((v) => v.recipients === undefined ||
|
|
139
|
+
v.recipients.length === 0 ||
|
|
140
|
+
v.method === 'transfer' ||
|
|
141
|
+
v.method === 'mint', {
|
|
142
|
+
message: 'recipients is only valid when method is a SEP-41 method (transfer or mint); other methods do not have a recipient at arg[1]',
|
|
143
|
+
});
|
|
130
144
|
/** ComposeUserResponses mirrors the core. */
|
|
131
145
|
exports.ComposeUserResponsesSchema = zod_1.z
|
|
132
146
|
.object({
|
|
@@ -144,6 +158,21 @@ exports.ComposeUserResponsesSchema = zod_1.z
|
|
|
144
158
|
swapRecipientAllowlist: zod_1.z
|
|
145
159
|
.array(zod_1.z.string().refine(address_ts_1.isStellarAddress, 'must be a Stellar address (G... or C...)'))
|
|
146
160
|
.optional(),
|
|
161
|
+
// Per-asset oracle-price bound, one entry per asset. Reaches
|
|
162
|
+
// `compose-from-recording` and emits an `oracle_price` compare. Declared
|
|
163
|
+
// here because the object is `.passthrough()`: the field already worked
|
|
164
|
+
// undeclared, which left the accepted surface wider than the documented
|
|
165
|
+
// one. `decimals` is REQUIRED - oracle prices normalise to 9 dp and a
|
|
166
|
+
// threshold silently assumed to share that basis is what let a raw 14-dp
|
|
167
|
+
// bound permit everything.
|
|
168
|
+
oraclePriceBound: zod_1.z
|
|
169
|
+
.array(zod_1.z.object({
|
|
170
|
+
asset: zod_1.z.string().refine(address_ts_1.isStellarAddress, 'must be a Stellar address (G... or C...)'),
|
|
171
|
+
operator: zod_1.z.enum(['eq', 'lt', 'lte', 'gt', 'gte']),
|
|
172
|
+
value: zod_1.z.string().regex(/^[0-9]+$/),
|
|
173
|
+
decimals: zod_1.z.number().int().min(0).max(U32_MAX),
|
|
174
|
+
}))
|
|
175
|
+
.optional(),
|
|
147
176
|
})
|
|
148
177
|
.passthrough();
|
|
149
178
|
/** OzAdapterConfig - the per-network OZ built-in instance addresses. */
|
|
@@ -267,7 +296,12 @@ exports.PredicateLeafSchema = zod_1.z.lazy(() => zod_1.z.union([
|
|
|
267
296
|
windowSeconds: zod_1.z.number().int().positive(),
|
|
268
297
|
}),
|
|
269
298
|
zod_1.z.object({ kind: zod_1.z.literal('now') }),
|
|
270
|
-
|
|
299
|
+
// `valid_until` is NOT in the public predicate grammar: the encoder +
|
|
300
|
+
// decoder already throw on it, so accepting it here would let a
|
|
301
|
+
// hand-crafted payload through the schema and only surface a 200+
|
|
302
|
+
// character internal-commentary error at encode time. Drop it - the
|
|
303
|
+
// policy's expiry is carried at the install layer (MandateSpec +
|
|
304
|
+
// validUntilLedger) instead.
|
|
271
305
|
zod_1.z.object({
|
|
272
306
|
kind: zod_1.z.literal('invocation_count_in_window'),
|
|
273
307
|
windowSecs: zod_1.z.number().int().positive(),
|
|
@@ -427,20 +461,28 @@ const MandateSpecSchemaForRule = zod_1.z
|
|
|
427
461
|
// install/revoke/get_info schemas live HERE (after the helper) so the const
|
|
428
462
|
// reference resolves at module init. They are the new tools on top of the
|
|
429
463
|
// existing four.
|
|
430
|
-
/** Pinned interpreter address (testnet).
|
|
464
|
+
/** Pinned interpreter address (testnet).
|
|
431
465
|
* Single source for the MCP layer; do not embed elsewhere. */
|
|
432
|
-
exports.PINNED_INTERPRETER_TESTNET_ADDRESS = '
|
|
433
|
-
/** Pinned interpreter address (mainnet)
|
|
434
|
-
*
|
|
435
|
-
* that was exercised on testnet (same wasm sha256, see
|
|
436
|
-
* PINNED_INTERPRETER_WASM_SHA256). The address differs because instance
|
|
437
|
-
* ids are network-scoped. UNAUDITED at the time of writing - see
|
|
438
|
-
* DEPLOYMENTS.md:29-32 for the recorded decision and what is still pending. */
|
|
466
|
+
exports.PINNED_INTERPRETER_TESTNET_ADDRESS = 'CALHNU4LXZRKFAXYRBODTGDANTNXHJPBTJNYGLUWLIFIP24NWSGWIE4K';
|
|
467
|
+
/** Pinned interpreter address (mainnet), deployed 2026-08-04.
|
|
468
|
+
* UNAUDITED at the time of writing. */
|
|
439
469
|
exports.PINNED_INTERPRETER_MAINNET_ADDRESS = 'CALZAMUPREIRY4TULBEXIK77AUTOEJG63XLCPUWEHHQDOVK6ZVVS7VQ2';
|
|
440
|
-
/** Pinned interpreter wasm sha256 (hex)
|
|
470
|
+
/** Pinned interpreter wasm sha256 (hex), mainnet.
|
|
471
|
+
*
|
|
472
|
+
* The two networks no longer run the same binary. Testnet carries the
|
|
473
|
+
* selector-leaf minimum and the signer-set cap; mainnet predates both. Read
|
|
474
|
+
* the hash through `PINNED_INTERPRETER_WASM_SHA256_BY_NETWORK` rather than
|
|
475
|
+
* this constant unless mainnet is specifically what is meant, or
|
|
476
|
+
* `get_interpreter_info` will report a hash the queried network does not
|
|
477
|
+
* run. */
|
|
441
478
|
exports.PINNED_INTERPRETER_WASM_SHA256 = '6e6c13d93e197aa380303a42cd120f5ddb080dd36ef2a343ee1dbd04ca52a443';
|
|
479
|
+
/** Pinned interpreter wasm sha256 (hex), testnet. Byte-identical to the
|
|
480
|
+
* artifact built from `contracts/policy-interpreter` at the commit that
|
|
481
|
+
* introduced errors 216 and 217, verified by fetching the deployed wasm back
|
|
482
|
+
* off chain. */
|
|
483
|
+
exports.PINNED_INTERPRETER_WASM_SHA256_TESTNET = 'a4d58bc88fd82bbb8e223941ba5889db919717fae92ced13f6f55bfe583b8e22';
|
|
442
484
|
/** The grammar version the interpreter enforces (matches SELF_VERSION in
|
|
443
|
-
*
|
|
485
|
+
* contracts/policy-interpreter/src/version.rs). */
|
|
444
486
|
exports.PINNED_INTERPRETER_GRAMMAR_VERSION = 1;
|
|
445
487
|
/** Default Soroban RPC for the install / revoke / info tools. The recorder
|
|
446
488
|
* keeps its own copy in record/rpc.ts because it hands back a fetcher rather
|
|
@@ -452,14 +494,18 @@ exports.TESTNET_RPC_URL = 'https://soroban-testnet.stellar.org';
|
|
|
452
494
|
* RPC rather than always testnet. Public mainnet endpoint, the same one
|
|
453
495
|
* the deploy script hit during the 2026-08-04 mainnet rollout. */
|
|
454
496
|
exports.MAINNET_RPC_URL = 'https://mainnet.sorobanrpc.com';
|
|
455
|
-
/** Pin + RPC lookup for the gate enforcement.
|
|
456
|
-
*
|
|
457
|
-
*
|
|
458
|
-
*
|
|
497
|
+
/** Pin + RPC lookup for the gate enforcement. Addresses, RPCs and wasm
|
|
498
|
+
* hashes are all network-scoped: the networks diverged when the
|
|
499
|
+
* selector-leaf and signer-cap controls were deployed to testnet ahead of
|
|
500
|
+
* mainnet. */
|
|
459
501
|
exports.PINNED_INTERPRETER_ADDRESS_BY_NETWORK = {
|
|
460
502
|
testnet: exports.PINNED_INTERPRETER_TESTNET_ADDRESS,
|
|
461
503
|
mainnet: exports.PINNED_INTERPRETER_MAINNET_ADDRESS,
|
|
462
504
|
};
|
|
505
|
+
exports.PINNED_INTERPRETER_WASM_SHA256_BY_NETWORK = {
|
|
506
|
+
testnet: exports.PINNED_INTERPRETER_WASM_SHA256_TESTNET,
|
|
507
|
+
mainnet: exports.PINNED_INTERPRETER_WASM_SHA256,
|
|
508
|
+
};
|
|
463
509
|
exports.RPC_URL_BY_NETWORK = {
|
|
464
510
|
testnet: exports.TESTNET_RPC_URL,
|
|
465
511
|
mainnet: exports.MAINNET_RPC_URL,
|
|
@@ -474,13 +520,26 @@ exports.NETWORK_PASSPHRASES = {
|
|
|
474
520
|
testnet: 'Test SDF Network ; September 2015',
|
|
475
521
|
mainnet: 'Public Global Stellar Network ; September 2015',
|
|
476
522
|
};
|
|
523
|
+
// Stellar strkey shapes (StrKey base32, no checksum byte, version byte
|
|
524
|
+
// 0x30/0x40 prefixed by the decoder, then 32 base32 chars giving a 56-char
|
|
525
|
+
// total). The shared `isStellarAddress` helper accepts BOTH wallet (G...) and
|
|
526
|
+
// contract (C...) addresses; the install schema has to distinguish them
|
|
527
|
+
// because the smart account is a contract (C...) - a wallet address would
|
|
528
|
+
// mean the rule is being installed against the WRONG account kind entirely.
|
|
529
|
+
// `sourceAccount` is the signing wallet (G...).
|
|
530
|
+
const STELLAR_CONTRACT_ADDRESS = /^C[2-7A-Z]{55}$/;
|
|
531
|
+
const STELLAR_ACCOUNT_ADDRESS = /^G[2-7A-Z]{55}$/;
|
|
477
532
|
exports.InstallPolicyInputSchema = zod_1.z
|
|
478
533
|
.object({
|
|
479
534
|
/** The smart account contract address (C...) that will receive the rule. */
|
|
480
|
-
smartAccount: zod_1.z
|
|
535
|
+
smartAccount: zod_1.z
|
|
536
|
+
.string()
|
|
537
|
+
.regex(STELLAR_CONTRACT_ADDRESS, 'smartAccount must be a Stellar contract address (C...)'),
|
|
481
538
|
/** The signer that authorises the install (G... wallet). Used only for
|
|
482
539
|
* sequence number + auth nonce simulation; never persisted, never signed. */
|
|
483
|
-
sourceAccount: zod_1.z
|
|
540
|
+
sourceAccount: zod_1.z
|
|
541
|
+
.string()
|
|
542
|
+
.regex(STELLAR_ACCOUNT_ADDRESS, 'sourceAccount must be a Stellar account address (G...)'),
|
|
484
543
|
/** Target network for the install. Selects which interpreter pin and
|
|
485
544
|
* which RPC URL are valid by default. Defaults to `testnet` so the
|
|
486
545
|
* pre-mainnet callers keep working: they were always pointing at
|
|
@@ -510,21 +569,63 @@ exports.InstallPolicyInputSchema = zod_1.z
|
|
|
510
569
|
* everything. Selecting `network: 'mainnet'` is NOT an opt-in -
|
|
511
570
|
* the mainnet pin is its own deny-by-default anchor. */
|
|
512
571
|
allowUnpinnedInterpreter: zod_1.z.boolean().optional(),
|
|
572
|
+
/** Opt-in to installing when a signer of this rule can already reach the
|
|
573
|
+
* same calls through a context rule that has NO policy attached. OZ lets
|
|
574
|
+
* the signer choose which rule authorises a call and enforces only that
|
|
575
|
+
* rule's policies, so an unpoliced rule covering the same calls makes
|
|
576
|
+
* this policy decorative. Default-deny, because the caller almost
|
|
577
|
+
* certainly believes they are restricting something. */
|
|
578
|
+
allowAuthorityOverlap: zod_1.z.boolean().optional(),
|
|
579
|
+
/** Skip the cross-rule authority scan entirely. The scan costs one RPC
|
|
580
|
+
* read per rule on the account; skipping it means the response carries
|
|
581
|
+
* no statement about what the signers can already do. */
|
|
582
|
+
skipAuthorityScan: zod_1.z.boolean().optional(),
|
|
513
583
|
/** Base fee in stroops; defaults to BASE_FEE (100). */
|
|
514
584
|
baseFee: zod_1.z.number().int().positive().optional(),
|
|
515
585
|
})
|
|
516
586
|
.refine((v) => Boolean(v.smartAccount) && Boolean(v.sourceAccount), {
|
|
517
587
|
message: 'smartAccount and sourceAccount are required',
|
|
518
588
|
});
|
|
589
|
+
/** `merge_policy` input.
|
|
590
|
+
*
|
|
591
|
+
* The tightening remedy for a cross-rule overlap: replace a rule's predicate
|
|
592
|
+
* with the conjunction of it and a new one. Two transactions, in order,
|
|
593
|
+
* because OZ refuses to re-attach a policy already on the rule - so the
|
|
594
|
+
* caller runs `detach`, waits for it to confirm, then runs `reinstall`. */
|
|
595
|
+
exports.MergePolicyInputSchema = zod_1.z
|
|
596
|
+
.object({
|
|
597
|
+
smartAccount: zod_1.z
|
|
598
|
+
.string()
|
|
599
|
+
.regex(STELLAR_CONTRACT_ADDRESS, 'smartAccount must be a Stellar contract address (C...)'),
|
|
600
|
+
sourceAccount: zod_1.z
|
|
601
|
+
.string()
|
|
602
|
+
.regex(STELLAR_ACCOUNT_ADDRESS, 'sourceAccount must be a Stellar account address (G...)'),
|
|
603
|
+
/** The rule whose predicate is being tightened. */
|
|
604
|
+
ruleId: zod_1.z.number().int().nonnegative(),
|
|
605
|
+
/** The predicate to conjoin, base64 canonical ScVal, as emitted by
|
|
606
|
+
* `synthesize_policy`. */
|
|
607
|
+
incomingPredicateBlobBase64: zod_1.z.string().min(1),
|
|
608
|
+
/** Which half of the remedy to build. */
|
|
609
|
+
step: zod_1.z.enum(['detach', 'reinstall']),
|
|
610
|
+
network: exports.NetworkSchema.optional(),
|
|
611
|
+
rpcUrl: zod_1.z.string().url().optional(),
|
|
612
|
+
allowUnpinnedRpcUrl: zod_1.z.boolean().optional(),
|
|
613
|
+
baseFee: zod_1.z.number().int().positive().optional(),
|
|
614
|
+
})
|
|
615
|
+
.strict();
|
|
519
616
|
exports.RevokePolicyInputSchema = zod_1.z
|
|
520
617
|
.object({
|
|
521
618
|
/** The smart account contract address (C...). */
|
|
522
|
-
smartAccount: zod_1.z
|
|
619
|
+
smartAccount: zod_1.z
|
|
620
|
+
.string()
|
|
621
|
+
.regex(STELLAR_CONTRACT_ADDRESS, 'smartAccount must be a Stellar contract address (C...)'),
|
|
523
622
|
/** The wallet that will sign the removal. The ACCOUNT decides whether it
|
|
524
623
|
* accepts that signer; this schema does not assert a rule it cannot
|
|
525
624
|
* verify, since the account's source is not in this repo. Proven on
|
|
526
625
|
* testnet: the account's deployer can revoke. */
|
|
527
|
-
sourceAccount: zod_1.z
|
|
626
|
+
sourceAccount: zod_1.z
|
|
627
|
+
.string()
|
|
628
|
+
.regex(STELLAR_ACCOUNT_ADDRESS, 'sourceAccount must be a Stellar account address (G...)'),
|
|
528
629
|
/** Target network for the revoke. Same `testnet`-default as install,
|
|
529
630
|
* so pre-mainnet callers keep working without an explicit flag. */
|
|
530
631
|
network: exports.NetworkSchema.optional(),
|
|
@@ -546,8 +647,15 @@ exports.GetInterpreterInfoInputSchema = zod_1.z.object({
|
|
|
546
647
|
/** When true, perform an optional live `grammar_version()` RPC call to
|
|
547
648
|
* verify the deployed contract matches the pin. */
|
|
548
649
|
verifyLive: zod_1.z.boolean().optional(),
|
|
549
|
-
/** Optional RPC URL override.
|
|
650
|
+
/** Optional RPC URL override. When `verifyLive` is true, the URL must
|
|
651
|
+
* equal the pinned RPC for the selected network unless
|
|
652
|
+
* `allowUnpinnedRpcUrl: true` is also set (same opt-in shape as
|
|
653
|
+
* install/revoke - the live grammar_version() answer binds to whichever
|
|
654
|
+
* RPC returned it). */
|
|
550
655
|
rpcUrl: zod_1.z.string().url().optional(),
|
|
656
|
+
/** Opt-in to using a non-pinned RPC URL when `verifyLive` is true. Same
|
|
657
|
+
* semantics as install/revoke: the caller accepts the trust shift. */
|
|
658
|
+
allowUnpinnedRpcUrl: zod_1.z.boolean().optional(),
|
|
551
659
|
});
|
|
552
660
|
// ===== Error envelope (canonical) =====
|
|
553
661
|
//
|
|
@@ -28,28 +28,23 @@ export interface ComposeUserResponses {
|
|
|
28
28
|
* invocation_count bound; absent -> FREQUENCY_BOUND_MISSING. */
|
|
29
29
|
invocationLimit?: number;
|
|
30
30
|
/** Per-asset oracle-price bound(s). Each entry lowers to a single
|
|
31
|
-
* `oracle_price(asset) OP value` compare in the interpreter IR.
|
|
32
|
-
* entries on the same asset emit multiple leaves. */
|
|
31
|
+
* `oracle_price(asset) OP value` compare in the interpreter IR. */
|
|
33
32
|
oraclePriceBound?: OraclePriceBound[];
|
|
34
33
|
/** Minimum acceptable swap output per unit of input, as `num/den` (e.g.
|
|
35
|
-
* `{num:'95',den:'100'}` = accept losing at most 5%).
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* recording. The recorded in/out pair is a price at one moment, and
|
|
41
|
-
* freezing it as policy would deny ordinary trades as soon as the rate
|
|
42
|
-
* moves. Absent, no floor is emitted and the existing unbounded-output
|
|
43
|
-
* warning stands. */
|
|
34
|
+
* `{num:'95',den:'100'}` = accept losing at most 5%). REQUIRED to be
|
|
35
|
+
* supplied by the caller: never derived from the recording (the recorded
|
|
36
|
+
* in/out pair is a price at one moment, and freezing it as policy would
|
|
37
|
+
* deny ordinary trades as soon as the rate moves). Absent, no floor is
|
|
38
|
+
* emitted and the existing unbounded-output warning stands. */
|
|
44
39
|
swapMinOutRatio?: {
|
|
45
40
|
num: string;
|
|
46
41
|
den: string;
|
|
47
42
|
};
|
|
48
43
|
/** Recipient allowlist for a swap (call_arg[3] on SoroSwap's
|
|
49
|
-
* swap_exact_tokens_for_tokens). When supplied,
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
44
|
+
* swap_exact_tokens_for_tokens). When supplied, REPLACES the default pin.
|
|
45
|
+
* Absent -> recipient is pinned to the recorded value (mirroring SEP-41)
|
|
46
|
+
* and RECIPIENT_ALLOWLIST_EMPTY surfaces as informational, never a silent
|
|
47
|
+
* free pass. */
|
|
53
48
|
swapRecipientAllowlist?: string[];
|
|
54
49
|
}
|
|
55
50
|
/** Composition options. */
|