@crediolabs/policy-synth 0.3.1 → 0.5.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/dist/adapters/interpreter/adapter.d.ts +2 -2
- package/dist/adapters/interpreter/adapter.js +11 -3
- package/dist/errors.d.ts +6 -1
- package/dist/install/authority-overlap.d.ts +101 -0
- package/dist/install/authority-overlap.js +239 -0
- package/dist/install/build-add-context-rule.d.ts +1 -1
- package/dist/install/index.d.ts +1 -0
- package/dist/install/index.js +4 -0
- package/dist/install/read-account-rules.d.ts +79 -0
- package/dist/install/read-account-rules.js +241 -0
- package/dist/predicate/decode.js +22 -1
- package/dist/predicate/encode.js +52 -5
- package/dist/predicate/from-json.js +14 -1
- package/dist/record/index.d.ts +10 -0
- package/dist/record/index.js +32 -1
- package/dist/record/rpc.d.ts +4 -0
- package/dist/record/rpc.js +4 -1
- package/dist/registry/identify.d.ts +10 -1
- package/dist/registry/identify.js +4 -1
- package/dist/registry/on-chain-spec.d.ts +37 -0
- package/dist/registry/on-chain-spec.js +152 -0
- package/dist/review-card/builder.js +40 -0
- package/dist/review-card/cross-check.js +34 -0
- package/dist/review-card/render-leaf.d.ts +1 -1
- package/dist/review-card/render-leaf.js +7 -0
- package/dist/run/index.d.ts +25 -4
- package/dist/run/index.js +108 -4
- package/dist/run/schemas.d.ts +350 -6
- package/dist/run/schemas.js +95 -6
- package/dist/simulate/deny-cases.js +11 -0
- package/dist/simulate/evaluate.js +86 -5
- package/dist/synth/declare.d.ts +43 -0
- package/dist/synth/declare.js +127 -0
- package/dist/synth/index.d.ts +1 -0
- package/dist/synth/index.js +1 -0
- package/dist/synth/synthesize-from-recording.js +1 -1
- package/dist/types.d.ts +21 -1
- package/dist/types.js +1 -1
- package/dist-cjs/adapters/interpreter/adapter.d.ts +2 -2
- package/dist-cjs/adapters/interpreter/adapter.js +11 -3
- package/dist-cjs/errors.d.ts +6 -1
- package/dist-cjs/install/authority-overlap.d.ts +101 -0
- package/dist-cjs/install/authority-overlap.js +248 -0
- package/dist-cjs/install/build-add-context-rule.d.ts +1 -1
- package/dist-cjs/install/index.d.ts +1 -0
- package/dist-cjs/install/index.js +13 -2
- package/dist-cjs/install/read-account-rules.d.ts +79 -0
- package/dist-cjs/install/read-account-rules.js +252 -0
- package/dist-cjs/predicate/decode.js +22 -1
- package/dist-cjs/predicate/encode.js +52 -5
- package/dist-cjs/predicate/from-json.js +14 -1
- package/dist-cjs/record/index.d.ts +10 -0
- package/dist-cjs/record/index.js +31 -0
- package/dist-cjs/record/rpc.d.ts +4 -0
- package/dist-cjs/record/rpc.js +7 -3
- package/dist-cjs/registry/identify.d.ts +10 -1
- package/dist-cjs/registry/identify.js +4 -0
- package/dist-cjs/registry/on-chain-spec.d.ts +37 -0
- package/dist-cjs/registry/on-chain-spec.js +159 -0
- package/dist-cjs/review-card/builder.js +40 -0
- package/dist-cjs/review-card/cross-check.js +34 -0
- package/dist-cjs/review-card/render-leaf.d.ts +1 -1
- package/dist-cjs/review-card/render-leaf.js +7 -0
- package/dist-cjs/run/index.d.ts +25 -4
- package/dist-cjs/run/index.js +108 -2
- package/dist-cjs/run/schemas.d.ts +350 -6
- package/dist-cjs/run/schemas.js +96 -7
- package/dist-cjs/simulate/deny-cases.js +11 -0
- package/dist-cjs/simulate/evaluate.js +86 -5
- package/dist-cjs/synth/declare.d.ts +43 -0
- package/dist-cjs/synth/declare.js +130 -0
- package/dist-cjs/synth/index.d.ts +1 -0
- package/dist-cjs/synth/index.js +3 -1
- package/dist-cjs/synth/synthesize-from-recording.js +1 -1
- package/dist-cjs/types.d.ts +21 -1
- package/dist-cjs/types.js +1 -1
- package/package.json +1 -1
- package/src/adapters/interpreter/adapter.ts +13 -5
- package/src/errors.ts +5 -0
- package/src/install/authority-overlap.ts +323 -0
- package/src/install/index.ts +20 -0
- package/src/install/read-account-rules.ts +313 -0
- package/src/predicate/decode.ts +22 -1
- package/src/predicate/encode.ts +55 -5
- package/src/predicate/from-json.ts +14 -1
- package/src/record/index.ts +59 -2
- package/src/record/rpc.ts +4 -1
- package/src/registry/identify.ts +4 -1
- package/src/registry/on-chain-spec.ts +168 -0
- package/src/review-card/builder.ts +45 -2
- package/src/review-card/cross-check.ts +35 -1
- package/src/review-card/render-leaf.ts +8 -1
- package/src/run/index.ts +125 -2
- package/src/run/schemas.ts +100 -6
- package/src/simulate/deny-cases.ts +12 -1
- package/src/simulate/evaluate.ts +101 -9
- package/src/synth/declare.ts +206 -0
- package/src/synth/index.ts +5 -0
- package/src/synth/synthesize-from-recording.ts +1 -1
- package/src/types.ts +16 -1
package/dist/run/schemas.d.ts
CHANGED
|
@@ -1494,25 +1494,123 @@ export declare const VerifyPolicyInputSchema: z.ZodObject<{
|
|
|
1494
1494
|
predicate?: unknown;
|
|
1495
1495
|
}>;
|
|
1496
1496
|
export type VerifyPolicyInput = z.infer<typeof VerifyPolicyInputSchema>;
|
|
1497
|
+
/** A rule ALREADY on the account, as the caller observed it. Supplying these
|
|
1498
|
+
* turns on the cross-rule authority scan: a signer belonging to several rules
|
|
1499
|
+
* picks which one applies, so a predicate only constrains a key when the
|
|
1500
|
+
* policed rule is the only rule that key is on. */
|
|
1501
|
+
export declare const ObservedRuleSchema: z.ZodObject<{
|
|
1502
|
+
id: z.ZodNumber;
|
|
1503
|
+
contextType: z.ZodDiscriminatedUnion<"kind", [z.ZodObject<{
|
|
1504
|
+
kind: z.ZodLiteral<"default">;
|
|
1505
|
+
}, "strip", z.ZodTypeAny, {
|
|
1506
|
+
kind: "default";
|
|
1507
|
+
}, {
|
|
1508
|
+
kind: "default";
|
|
1509
|
+
}>, z.ZodObject<{
|
|
1510
|
+
kind: z.ZodLiteral<"call_contract">;
|
|
1511
|
+
contract: z.ZodString;
|
|
1512
|
+
}, "strip", z.ZodTypeAny, {
|
|
1513
|
+
kind: "call_contract";
|
|
1514
|
+
contract: string;
|
|
1515
|
+
}, {
|
|
1516
|
+
kind: "call_contract";
|
|
1517
|
+
contract: string;
|
|
1518
|
+
}>, z.ZodObject<{
|
|
1519
|
+
kind: z.ZodLiteral<"create_contract">;
|
|
1520
|
+
wasmHash: z.ZodString;
|
|
1521
|
+
}, "strip", z.ZodTypeAny, {
|
|
1522
|
+
kind: "create_contract";
|
|
1523
|
+
wasmHash: string;
|
|
1524
|
+
}, {
|
|
1525
|
+
kind: "create_contract";
|
|
1526
|
+
wasmHash: string;
|
|
1527
|
+
}>]>;
|
|
1528
|
+
signers: z.ZodArray<z.ZodDiscriminatedUnion<"kind", [z.ZodObject<{
|
|
1529
|
+
kind: z.ZodLiteral<"delegated">;
|
|
1530
|
+
address: z.ZodString;
|
|
1531
|
+
}, "strip", z.ZodTypeAny, {
|
|
1532
|
+
address: string;
|
|
1533
|
+
kind: "delegated";
|
|
1534
|
+
}, {
|
|
1535
|
+
address: string;
|
|
1536
|
+
kind: "delegated";
|
|
1537
|
+
}>, z.ZodObject<{
|
|
1538
|
+
kind: z.ZodLiteral<"external">;
|
|
1539
|
+
verifier: z.ZodString;
|
|
1540
|
+
keyBytes: z.ZodString;
|
|
1541
|
+
}, "strip", z.ZodTypeAny, {
|
|
1542
|
+
kind: "external";
|
|
1543
|
+
verifier: string;
|
|
1544
|
+
keyBytes: string;
|
|
1545
|
+
}, {
|
|
1546
|
+
kind: "external";
|
|
1547
|
+
verifier: string;
|
|
1548
|
+
keyBytes: string;
|
|
1549
|
+
}>]>, "many">;
|
|
1550
|
+
policyAddresses: z.ZodArray<z.ZodString, "many">;
|
|
1551
|
+
predicate: z.ZodOptional<z.ZodType<unknown, z.ZodTypeDef, unknown>>;
|
|
1552
|
+
}, "strip", z.ZodTypeAny, {
|
|
1553
|
+
signers: ({
|
|
1554
|
+
address: string;
|
|
1555
|
+
kind: "delegated";
|
|
1556
|
+
} | {
|
|
1557
|
+
kind: "external";
|
|
1558
|
+
verifier: string;
|
|
1559
|
+
keyBytes: string;
|
|
1560
|
+
})[];
|
|
1561
|
+
id: number;
|
|
1562
|
+
policyAddresses: string[];
|
|
1563
|
+
contextType: {
|
|
1564
|
+
kind: "default";
|
|
1565
|
+
} | {
|
|
1566
|
+
kind: "call_contract";
|
|
1567
|
+
contract: string;
|
|
1568
|
+
} | {
|
|
1569
|
+
kind: "create_contract";
|
|
1570
|
+
wasmHash: string;
|
|
1571
|
+
};
|
|
1572
|
+
predicate?: unknown;
|
|
1573
|
+
}, {
|
|
1574
|
+
signers: ({
|
|
1575
|
+
address: string;
|
|
1576
|
+
kind: "delegated";
|
|
1577
|
+
} | {
|
|
1578
|
+
kind: "external";
|
|
1579
|
+
verifier: string;
|
|
1580
|
+
keyBytes: string;
|
|
1581
|
+
})[];
|
|
1582
|
+
id: number;
|
|
1583
|
+
policyAddresses: string[];
|
|
1584
|
+
contextType: {
|
|
1585
|
+
kind: "default";
|
|
1586
|
+
} | {
|
|
1587
|
+
kind: "call_contract";
|
|
1588
|
+
contract: string;
|
|
1589
|
+
} | {
|
|
1590
|
+
kind: "create_contract";
|
|
1591
|
+
wasmHash: string;
|
|
1592
|
+
};
|
|
1593
|
+
predicate?: unknown;
|
|
1594
|
+
}>;
|
|
1497
1595
|
/** Pinned interpreter address (testnet).
|
|
1498
1596
|
* Single source for the MCP layer; do not embed elsewhere. */
|
|
1499
|
-
export declare const PINNED_INTERPRETER_TESTNET_ADDRESS = "
|
|
1500
|
-
/** Pinned interpreter address (mainnet), redeployed 2026-08-22 from a reproducible build. The mainnet
|
|
1597
|
+
export declare const PINNED_INTERPRETER_TESTNET_ADDRESS = "CCBHVZ6HGGV7C4SNHCZ3S5665Z2WEMHTMBAEPO4XW6PKON464BEBANU5";
|
|
1598
|
+
/** Pinned interpreter address (mainnet), redeployed 2026-08-22 for grammar 4, from a reproducible build. The mainnet
|
|
1501
1599
|
* interpreter IS the binary exercised on testnet - both instances were created
|
|
1502
1600
|
* from the same uploaded wasm hash (see PINNED_INTERPRETER_WASM_SHA256), and
|
|
1503
|
-
* both were read back with `grammar_version()` returning
|
|
1601
|
+
* both were read back with `grammar_version()` returning 4. The address differs
|
|
1504
1602
|
* because instance ids are network-scoped. UNAUDITED at the time of writing.
|
|
1505
1603
|
*
|
|
1506
1604
|
* These four constants move together or not at all. The grammar version and
|
|
1507
1605
|
* wasm hash are single values covering BOTH networks, so re-pinning one network
|
|
1508
1606
|
* alone would have the builder emit a version the other network refuses - with
|
|
1509
1607
|
* a green test run, since `grammar-version-parity.test.ts` would then pass. */
|
|
1510
|
-
export declare const PINNED_INTERPRETER_MAINNET_ADDRESS = "
|
|
1608
|
+
export declare const PINNED_INTERPRETER_MAINNET_ADDRESS = "CDN755TDYZM3ZQ5OXTJ6TIBUBWZV2KRI2BYJPBXD2MVWED4STT3VBN52";
|
|
1511
1609
|
/** Pinned interpreter wasm sha256 (hex). */
|
|
1512
|
-
export declare const PINNED_INTERPRETER_WASM_SHA256 = "
|
|
1610
|
+
export declare const PINNED_INTERPRETER_WASM_SHA256 = "b5ba1e35ccf20cd8c13c3a2c3098bf337033a92bcaf475d63c03ddc0cba0fcae";
|
|
1513
1611
|
/** The grammar version the interpreter enforces (matches SELF_VERSION in
|
|
1514
1612
|
* contracts/policy-interpreter/src/version.rs). */
|
|
1515
|
-
export declare const PINNED_INTERPRETER_GRAMMAR_VERSION =
|
|
1613
|
+
export declare const PINNED_INTERPRETER_GRAMMAR_VERSION = 4;
|
|
1516
1614
|
/** Default Soroban RPC for the install / revoke / info tools. The recorder
|
|
1517
1615
|
* keeps its own copy in record/rpc.ts because it hands back a fetcher rather
|
|
1518
1616
|
* than a Server; the two are deliberately different surfaces, so this is
|
|
@@ -1533,7 +1631,165 @@ export declare const RPC_URL_BY_NETWORK: Record<Network, string>;
|
|
|
1533
1631
|
* matching passphrase when the wallet signs (a mismatch yields invalid
|
|
1534
1632
|
* hashes). */
|
|
1535
1633
|
export declare const NETWORK_PASSPHRASES: Record<Network, string>;
|
|
1634
|
+
export declare const DeclarePolicyInputSchema: z.ZodObject<{
|
|
1635
|
+
fn: z.ZodString;
|
|
1636
|
+
contract: z.ZodOptional<z.ZodString>;
|
|
1637
|
+
/** Smallest unit, unsigned decimal STRING - an i128 is wider than
|
|
1638
|
+
* Number.MAX_SAFE_INTEGER, so a number here would silently round. */
|
|
1639
|
+
maxAmount: z.ZodOptional<z.ZodString>;
|
|
1640
|
+
amountArgIndex: z.ZodOptional<z.ZodNumber>;
|
|
1641
|
+
recipients: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
1642
|
+
recipientArgIndex: z.ZodOptional<z.ZodNumber>;
|
|
1643
|
+
allowZeroCap: z.ZodOptional<z.ZodBoolean>;
|
|
1644
|
+
/** Minimum output as a ratio of the call's own input. num/den are decimal
|
|
1645
|
+
* STRINGS for the same reason maxAmount is: an i128 ratio does not
|
|
1646
|
+
* survive a JS number. */
|
|
1647
|
+
minOutputRatio: z.ZodOptional<z.ZodObject<{
|
|
1648
|
+
num: z.ZodString;
|
|
1649
|
+
den: z.ZodString;
|
|
1650
|
+
inputArgIndex: z.ZodNumber;
|
|
1651
|
+
outputArgIndex: z.ZodNumber;
|
|
1652
|
+
}, "strict", z.ZodTypeAny, {
|
|
1653
|
+
num: string;
|
|
1654
|
+
den: string;
|
|
1655
|
+
inputArgIndex: number;
|
|
1656
|
+
outputArgIndex: number;
|
|
1657
|
+
}, {
|
|
1658
|
+
num: string;
|
|
1659
|
+
den: string;
|
|
1660
|
+
inputArgIndex: number;
|
|
1661
|
+
outputArgIndex: number;
|
|
1662
|
+
}>>;
|
|
1663
|
+
}, "strict", z.ZodTypeAny, {
|
|
1664
|
+
fn: string;
|
|
1665
|
+
contract?: string | undefined;
|
|
1666
|
+
maxAmount?: string | undefined;
|
|
1667
|
+
amountArgIndex?: number | undefined;
|
|
1668
|
+
recipients?: string[] | undefined;
|
|
1669
|
+
recipientArgIndex?: number | undefined;
|
|
1670
|
+
allowZeroCap?: boolean | undefined;
|
|
1671
|
+
minOutputRatio?: {
|
|
1672
|
+
num: string;
|
|
1673
|
+
den: string;
|
|
1674
|
+
inputArgIndex: number;
|
|
1675
|
+
outputArgIndex: number;
|
|
1676
|
+
} | undefined;
|
|
1677
|
+
}, {
|
|
1678
|
+
fn: string;
|
|
1679
|
+
contract?: string | undefined;
|
|
1680
|
+
maxAmount?: string | undefined;
|
|
1681
|
+
amountArgIndex?: number | undefined;
|
|
1682
|
+
recipients?: string[] | undefined;
|
|
1683
|
+
recipientArgIndex?: number | undefined;
|
|
1684
|
+
allowZeroCap?: boolean | undefined;
|
|
1685
|
+
minOutputRatio?: {
|
|
1686
|
+
num: string;
|
|
1687
|
+
den: string;
|
|
1688
|
+
inputArgIndex: number;
|
|
1689
|
+
outputArgIndex: number;
|
|
1690
|
+
} | undefined;
|
|
1691
|
+
}>;
|
|
1692
|
+
export type DeclarePolicyInput = z.infer<typeof DeclarePolicyInputSchema>;
|
|
1536
1693
|
export declare const InstallPolicyInputSchema: z.ZodEffects<z.ZodObject<{
|
|
1694
|
+
/** Rules already on the account. Supplying them turns on the cross-rule
|
|
1695
|
+
* authority scan, which reports every existing rule a signer of this
|
|
1696
|
+
* install could name INSTEAD - including an unpoliced one, against which
|
|
1697
|
+
* the predicate never runs. Absent means the scan is skipped, and the
|
|
1698
|
+
* result says so rather than reporting "no overlaps found". */
|
|
1699
|
+
existingRules: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1700
|
+
id: z.ZodNumber;
|
|
1701
|
+
contextType: z.ZodDiscriminatedUnion<"kind", [z.ZodObject<{
|
|
1702
|
+
kind: z.ZodLiteral<"default">;
|
|
1703
|
+
}, "strip", z.ZodTypeAny, {
|
|
1704
|
+
kind: "default";
|
|
1705
|
+
}, {
|
|
1706
|
+
kind: "default";
|
|
1707
|
+
}>, z.ZodObject<{
|
|
1708
|
+
kind: z.ZodLiteral<"call_contract">;
|
|
1709
|
+
contract: z.ZodString;
|
|
1710
|
+
}, "strip", z.ZodTypeAny, {
|
|
1711
|
+
kind: "call_contract";
|
|
1712
|
+
contract: string;
|
|
1713
|
+
}, {
|
|
1714
|
+
kind: "call_contract";
|
|
1715
|
+
contract: string;
|
|
1716
|
+
}>, z.ZodObject<{
|
|
1717
|
+
kind: z.ZodLiteral<"create_contract">;
|
|
1718
|
+
wasmHash: z.ZodString;
|
|
1719
|
+
}, "strip", z.ZodTypeAny, {
|
|
1720
|
+
kind: "create_contract";
|
|
1721
|
+
wasmHash: string;
|
|
1722
|
+
}, {
|
|
1723
|
+
kind: "create_contract";
|
|
1724
|
+
wasmHash: string;
|
|
1725
|
+
}>]>;
|
|
1726
|
+
signers: z.ZodArray<z.ZodDiscriminatedUnion<"kind", [z.ZodObject<{
|
|
1727
|
+
kind: z.ZodLiteral<"delegated">;
|
|
1728
|
+
address: z.ZodString;
|
|
1729
|
+
}, "strip", z.ZodTypeAny, {
|
|
1730
|
+
address: string;
|
|
1731
|
+
kind: "delegated";
|
|
1732
|
+
}, {
|
|
1733
|
+
address: string;
|
|
1734
|
+
kind: "delegated";
|
|
1735
|
+
}>, z.ZodObject<{
|
|
1736
|
+
kind: z.ZodLiteral<"external">;
|
|
1737
|
+
verifier: z.ZodString;
|
|
1738
|
+
keyBytes: z.ZodString;
|
|
1739
|
+
}, "strip", z.ZodTypeAny, {
|
|
1740
|
+
kind: "external";
|
|
1741
|
+
verifier: string;
|
|
1742
|
+
keyBytes: string;
|
|
1743
|
+
}, {
|
|
1744
|
+
kind: "external";
|
|
1745
|
+
verifier: string;
|
|
1746
|
+
keyBytes: string;
|
|
1747
|
+
}>]>, "many">;
|
|
1748
|
+
policyAddresses: z.ZodArray<z.ZodString, "many">;
|
|
1749
|
+
predicate: z.ZodOptional<z.ZodType<unknown, z.ZodTypeDef, unknown>>;
|
|
1750
|
+
}, "strip", z.ZodTypeAny, {
|
|
1751
|
+
signers: ({
|
|
1752
|
+
address: string;
|
|
1753
|
+
kind: "delegated";
|
|
1754
|
+
} | {
|
|
1755
|
+
kind: "external";
|
|
1756
|
+
verifier: string;
|
|
1757
|
+
keyBytes: string;
|
|
1758
|
+
})[];
|
|
1759
|
+
id: number;
|
|
1760
|
+
policyAddresses: string[];
|
|
1761
|
+
contextType: {
|
|
1762
|
+
kind: "default";
|
|
1763
|
+
} | {
|
|
1764
|
+
kind: "call_contract";
|
|
1765
|
+
contract: string;
|
|
1766
|
+
} | {
|
|
1767
|
+
kind: "create_contract";
|
|
1768
|
+
wasmHash: string;
|
|
1769
|
+
};
|
|
1770
|
+
predicate?: unknown;
|
|
1771
|
+
}, {
|
|
1772
|
+
signers: ({
|
|
1773
|
+
address: string;
|
|
1774
|
+
kind: "delegated";
|
|
1775
|
+
} | {
|
|
1776
|
+
kind: "external";
|
|
1777
|
+
verifier: string;
|
|
1778
|
+
keyBytes: string;
|
|
1779
|
+
})[];
|
|
1780
|
+
id: number;
|
|
1781
|
+
policyAddresses: string[];
|
|
1782
|
+
contextType: {
|
|
1783
|
+
kind: "default";
|
|
1784
|
+
} | {
|
|
1785
|
+
kind: "call_contract";
|
|
1786
|
+
contract: string;
|
|
1787
|
+
} | {
|
|
1788
|
+
kind: "create_contract";
|
|
1789
|
+
wasmHash: string;
|
|
1790
|
+
};
|
|
1791
|
+
predicate?: unknown;
|
|
1792
|
+
}>, "many">>;
|
|
1537
1793
|
/** The smart account contract address (C...) that will receive the rule. */
|
|
1538
1794
|
smartAccount: z.ZodString;
|
|
1539
1795
|
/** The signer that authorises the install (G... wallet). Used only for
|
|
@@ -1918,6 +2174,28 @@ export declare const InstallPolicyInputSchema: z.ZodEffects<z.ZodObject<{
|
|
|
1918
2174
|
[k: string]: unknown;
|
|
1919
2175
|
};
|
|
1920
2176
|
network?: "mainnet" | "testnet" | undefined;
|
|
2177
|
+
existingRules?: {
|
|
2178
|
+
signers: ({
|
|
2179
|
+
address: string;
|
|
2180
|
+
kind: "delegated";
|
|
2181
|
+
} | {
|
|
2182
|
+
kind: "external";
|
|
2183
|
+
verifier: string;
|
|
2184
|
+
keyBytes: string;
|
|
2185
|
+
})[];
|
|
2186
|
+
id: number;
|
|
2187
|
+
policyAddresses: string[];
|
|
2188
|
+
contextType: {
|
|
2189
|
+
kind: "default";
|
|
2190
|
+
} | {
|
|
2191
|
+
kind: "call_contract";
|
|
2192
|
+
contract: string;
|
|
2193
|
+
} | {
|
|
2194
|
+
kind: "create_contract";
|
|
2195
|
+
wasmHash: string;
|
|
2196
|
+
};
|
|
2197
|
+
predicate?: unknown;
|
|
2198
|
+
}[] | undefined;
|
|
1921
2199
|
rpcUrl?: string | undefined;
|
|
1922
2200
|
allowUnpinnedRpcUrl?: boolean | undefined;
|
|
1923
2201
|
allowUnpinnedInterpreter?: boolean | undefined;
|
|
@@ -1955,6 +2233,28 @@ export declare const InstallPolicyInputSchema: z.ZodEffects<z.ZodObject<{
|
|
|
1955
2233
|
[k: string]: unknown;
|
|
1956
2234
|
};
|
|
1957
2235
|
network?: "mainnet" | "testnet" | undefined;
|
|
2236
|
+
existingRules?: {
|
|
2237
|
+
signers: ({
|
|
2238
|
+
address: string;
|
|
2239
|
+
kind: "delegated";
|
|
2240
|
+
} | {
|
|
2241
|
+
kind: "external";
|
|
2242
|
+
verifier: string;
|
|
2243
|
+
keyBytes: string;
|
|
2244
|
+
})[];
|
|
2245
|
+
id: number;
|
|
2246
|
+
policyAddresses: string[];
|
|
2247
|
+
contextType: {
|
|
2248
|
+
kind: "default";
|
|
2249
|
+
} | {
|
|
2250
|
+
kind: "call_contract";
|
|
2251
|
+
contract: string;
|
|
2252
|
+
} | {
|
|
2253
|
+
kind: "create_contract";
|
|
2254
|
+
wasmHash: string;
|
|
2255
|
+
};
|
|
2256
|
+
predicate?: unknown;
|
|
2257
|
+
}[] | undefined;
|
|
1958
2258
|
rpcUrl?: string | undefined;
|
|
1959
2259
|
allowUnpinnedRpcUrl?: boolean | undefined;
|
|
1960
2260
|
allowUnpinnedInterpreter?: boolean | undefined;
|
|
@@ -1992,6 +2292,28 @@ export declare const InstallPolicyInputSchema: z.ZodEffects<z.ZodObject<{
|
|
|
1992
2292
|
[k: string]: unknown;
|
|
1993
2293
|
};
|
|
1994
2294
|
network?: "mainnet" | "testnet" | undefined;
|
|
2295
|
+
existingRules?: {
|
|
2296
|
+
signers: ({
|
|
2297
|
+
address: string;
|
|
2298
|
+
kind: "delegated";
|
|
2299
|
+
} | {
|
|
2300
|
+
kind: "external";
|
|
2301
|
+
verifier: string;
|
|
2302
|
+
keyBytes: string;
|
|
2303
|
+
})[];
|
|
2304
|
+
id: number;
|
|
2305
|
+
policyAddresses: string[];
|
|
2306
|
+
contextType: {
|
|
2307
|
+
kind: "default";
|
|
2308
|
+
} | {
|
|
2309
|
+
kind: "call_contract";
|
|
2310
|
+
contract: string;
|
|
2311
|
+
} | {
|
|
2312
|
+
kind: "create_contract";
|
|
2313
|
+
wasmHash: string;
|
|
2314
|
+
};
|
|
2315
|
+
predicate?: unknown;
|
|
2316
|
+
}[] | undefined;
|
|
1995
2317
|
rpcUrl?: string | undefined;
|
|
1996
2318
|
allowUnpinnedRpcUrl?: boolean | undefined;
|
|
1997
2319
|
allowUnpinnedInterpreter?: boolean | undefined;
|
|
@@ -2029,6 +2351,28 @@ export declare const InstallPolicyInputSchema: z.ZodEffects<z.ZodObject<{
|
|
|
2029
2351
|
[k: string]: unknown;
|
|
2030
2352
|
};
|
|
2031
2353
|
network?: "mainnet" | "testnet" | undefined;
|
|
2354
|
+
existingRules?: {
|
|
2355
|
+
signers: ({
|
|
2356
|
+
address: string;
|
|
2357
|
+
kind: "delegated";
|
|
2358
|
+
} | {
|
|
2359
|
+
kind: "external";
|
|
2360
|
+
verifier: string;
|
|
2361
|
+
keyBytes: string;
|
|
2362
|
+
})[];
|
|
2363
|
+
id: number;
|
|
2364
|
+
policyAddresses: string[];
|
|
2365
|
+
contextType: {
|
|
2366
|
+
kind: "default";
|
|
2367
|
+
} | {
|
|
2368
|
+
kind: "call_contract";
|
|
2369
|
+
contract: string;
|
|
2370
|
+
} | {
|
|
2371
|
+
kind: "create_contract";
|
|
2372
|
+
wasmHash: string;
|
|
2373
|
+
};
|
|
2374
|
+
predicate?: unknown;
|
|
2375
|
+
}[] | undefined;
|
|
2032
2376
|
rpcUrl?: string | undefined;
|
|
2033
2377
|
allowUnpinnedRpcUrl?: boolean | undefined;
|
|
2034
2378
|
allowUnpinnedInterpreter?: boolean | undefined;
|
package/dist/run/schemas.js
CHANGED
|
@@ -177,6 +177,15 @@ export const PredicateLeafSchema = z.lazy(() => z.union([
|
|
|
177
177
|
element: z.number().int().nonnegative(),
|
|
178
178
|
field: z.string(),
|
|
179
179
|
}),
|
|
180
|
+
// num/den are i128 decimal strings, matching `literal_i128`. The regex
|
|
181
|
+
// is the boundary guard; the ratio's SIGN is checked at encode, where
|
|
182
|
+
// the message can explain that a negative ratio inverts the comparison.
|
|
183
|
+
z.object({
|
|
184
|
+
kind: z.literal('call_arg_scaled'),
|
|
185
|
+
index: z.number().int().nonnegative(),
|
|
186
|
+
num: z.string().regex(/^-?[0-9]+$/),
|
|
187
|
+
den: z.string().regex(/^-?[0-9]+$/),
|
|
188
|
+
}),
|
|
180
189
|
z.object({ kind: z.literal('literal_address'), value: z.string() }),
|
|
181
190
|
z.object({ kind: z.literal('literal_i128'), value: z.string().regex(/^-?[0-9]+$/) }),
|
|
182
191
|
z.object({ kind: z.literal('literal_symbol'), value: z.string() }),
|
|
@@ -195,16 +204,32 @@ export const PredicateLeafSchema = z.lazy(() => z.union([
|
|
|
195
204
|
* `and`; the lazy + annotation pattern keeps the recursion type-safe. */
|
|
196
205
|
export const PredicateNodeSchema = z.lazy(() => z.union([
|
|
197
206
|
z.object({ op: z.literal('and'), children: z.array(PredicateNodeSchema) }),
|
|
207
|
+
z.object({ op: z.literal('or'), children: z.array(PredicateNodeSchema) }),
|
|
198
208
|
z.object({
|
|
199
209
|
op: z.literal('eq'),
|
|
200
210
|
left: PredicateLeafSchema,
|
|
201
211
|
right: PredicateLeafSchema,
|
|
202
212
|
}),
|
|
213
|
+
z.object({
|
|
214
|
+
op: z.literal('lt'),
|
|
215
|
+
left: PredicateLeafSchema,
|
|
216
|
+
right: PredicateLeafSchema,
|
|
217
|
+
}),
|
|
203
218
|
z.object({
|
|
204
219
|
op: z.literal('lte'),
|
|
205
220
|
left: PredicateLeafSchema,
|
|
206
221
|
right: PredicateLeafSchema,
|
|
207
222
|
}),
|
|
223
|
+
z.object({
|
|
224
|
+
op: z.literal('gt'),
|
|
225
|
+
left: PredicateLeafSchema,
|
|
226
|
+
right: PredicateLeafSchema,
|
|
227
|
+
}),
|
|
228
|
+
z.object({
|
|
229
|
+
op: z.literal('gte'),
|
|
230
|
+
left: PredicateLeafSchema,
|
|
231
|
+
right: PredicateLeafSchema,
|
|
232
|
+
}),
|
|
208
233
|
z.object({
|
|
209
234
|
op: z.literal('in'),
|
|
210
235
|
needle: PredicateLeafSchema,
|
|
@@ -246,6 +271,26 @@ export const VerifyPolicyInputSchema = SimulatePolicyInputSchema;
|
|
|
246
271
|
* the temporal dead zone (no JS hoisting for `const`). */
|
|
247
272
|
const MAX_SIGNERS_PER_RULE = 15;
|
|
248
273
|
const MAX_POLICIES_PER_RULE = 5;
|
|
274
|
+
const SignerDraftSchema = z.discriminatedUnion('kind', [
|
|
275
|
+
z.object({ kind: z.literal('delegated'), address: z.string() }),
|
|
276
|
+
z.object({ kind: z.literal('external'), verifier: z.string(), keyBytes: z.string() }),
|
|
277
|
+
]);
|
|
278
|
+
const ContextTypeSchema = z.discriminatedUnion('kind', [
|
|
279
|
+
z.object({ kind: z.literal('default') }),
|
|
280
|
+
z.object({ kind: z.literal('call_contract'), contract: z.string() }),
|
|
281
|
+
z.object({ kind: z.literal('create_contract'), wasmHash: z.string() }),
|
|
282
|
+
]);
|
|
283
|
+
/** A rule ALREADY on the account, as the caller observed it. Supplying these
|
|
284
|
+
* turns on the cross-rule authority scan: a signer belonging to several rules
|
|
285
|
+
* picks which one applies, so a predicate only constrains a key when the
|
|
286
|
+
* policed rule is the only rule that key is on. */
|
|
287
|
+
export const ObservedRuleSchema = z.object({
|
|
288
|
+
id: z.number().int().nonnegative(),
|
|
289
|
+
contextType: ContextTypeSchema,
|
|
290
|
+
signers: z.array(SignerDraftSchema),
|
|
291
|
+
policyAddresses: z.array(z.string()),
|
|
292
|
+
predicate: PredicateNodeSchema.optional(),
|
|
293
|
+
});
|
|
249
294
|
const ContextRuleDraftSchema = z
|
|
250
295
|
.object({
|
|
251
296
|
contextRuleType: z.discriminatedUnion('kind', [
|
|
@@ -280,23 +325,23 @@ const ContextRuleDraftSchema = z
|
|
|
280
325
|
// existing four.
|
|
281
326
|
/** Pinned interpreter address (testnet).
|
|
282
327
|
* Single source for the MCP layer; do not embed elsewhere. */
|
|
283
|
-
export const PINNED_INTERPRETER_TESTNET_ADDRESS = '
|
|
284
|
-
/** Pinned interpreter address (mainnet), redeployed 2026-08-22 from a reproducible build. The mainnet
|
|
328
|
+
export const PINNED_INTERPRETER_TESTNET_ADDRESS = 'CCBHVZ6HGGV7C4SNHCZ3S5665Z2WEMHTMBAEPO4XW6PKON464BEBANU5';
|
|
329
|
+
/** Pinned interpreter address (mainnet), redeployed 2026-08-22 for grammar 4, from a reproducible build. The mainnet
|
|
285
330
|
* interpreter IS the binary exercised on testnet - both instances were created
|
|
286
331
|
* from the same uploaded wasm hash (see PINNED_INTERPRETER_WASM_SHA256), and
|
|
287
|
-
* both were read back with `grammar_version()` returning
|
|
332
|
+
* both were read back with `grammar_version()` returning 4. The address differs
|
|
288
333
|
* because instance ids are network-scoped. UNAUDITED at the time of writing.
|
|
289
334
|
*
|
|
290
335
|
* These four constants move together or not at all. The grammar version and
|
|
291
336
|
* wasm hash are single values covering BOTH networks, so re-pinning one network
|
|
292
337
|
* alone would have the builder emit a version the other network refuses - with
|
|
293
338
|
* a green test run, since `grammar-version-parity.test.ts` would then pass. */
|
|
294
|
-
export const PINNED_INTERPRETER_MAINNET_ADDRESS = '
|
|
339
|
+
export const PINNED_INTERPRETER_MAINNET_ADDRESS = 'CDN755TDYZM3ZQ5OXTJ6TIBUBWZV2KRI2BYJPBXD2MVWED4STT3VBN52';
|
|
295
340
|
/** Pinned interpreter wasm sha256 (hex). */
|
|
296
|
-
export const PINNED_INTERPRETER_WASM_SHA256 = '
|
|
341
|
+
export const PINNED_INTERPRETER_WASM_SHA256 = 'b5ba1e35ccf20cd8c13c3a2c3098bf337033a92bcaf475d63c03ddc0cba0fcae';
|
|
297
342
|
/** The grammar version the interpreter enforces (matches SELF_VERSION in
|
|
298
343
|
* contracts/policy-interpreter/src/version.rs). */
|
|
299
|
-
export const PINNED_INTERPRETER_GRAMMAR_VERSION =
|
|
344
|
+
export const PINNED_INTERPRETER_GRAMMAR_VERSION = 4;
|
|
300
345
|
/** Default Soroban RPC for the install / revoke / info tools. The recorder
|
|
301
346
|
* keeps its own copy in record/rpc.ts because it hands back a fetcher rather
|
|
302
347
|
* than a Server; the two are deliberately different surfaces, so this is
|
|
@@ -335,8 +380,52 @@ export const NETWORK_PASSPHRASES = {
|
|
|
335
380
|
// `sourceAccount` is the signing wallet (G...).
|
|
336
381
|
const STELLAR_CONTRACT_ADDRESS = /^C[2-7A-Z]{55}$/;
|
|
337
382
|
const STELLAR_ACCOUNT_ADDRESS = /^G[2-7A-Z]{55}$/;
|
|
383
|
+
// ===== declare_policy =====
|
|
384
|
+
//
|
|
385
|
+
// The declarative front-end: the constraint stated outright, with no
|
|
386
|
+
// transaction to decode. Deliberately NOT a revival of the removed
|
|
387
|
+
// `MandateSpec` - that carried a rolling `spendingLimit` the interpreter
|
|
388
|
+
// cannot evaluate and an `approvalThreshold` needing OZ primitives nobody
|
|
389
|
+
// deployed. Only fields grammar 3 can actually enforce appear here.
|
|
390
|
+
export const DeclarePolicyInputSchema = z
|
|
391
|
+
.object({
|
|
392
|
+
fn: z.string().min(1, 'fn must name the method to pin'),
|
|
393
|
+
contract: z
|
|
394
|
+
.string()
|
|
395
|
+
.regex(STELLAR_CONTRACT_ADDRESS, 'contract must be a Stellar contract address (C...)')
|
|
396
|
+
.optional(),
|
|
397
|
+
/** Smallest unit, unsigned decimal STRING - an i128 is wider than
|
|
398
|
+
* Number.MAX_SAFE_INTEGER, so a number here would silently round. */
|
|
399
|
+
maxAmount: z
|
|
400
|
+
.string()
|
|
401
|
+
.regex(/^[0-9]+$/, 'maxAmount must be an unsigned integer in the smallest unit')
|
|
402
|
+
.optional(),
|
|
403
|
+
amountArgIndex: z.number().int().nonnegative().max(U32_MAX).optional(),
|
|
404
|
+
recipients: z.array(z.string()).min(1, 'recipients must not be empty').optional(),
|
|
405
|
+
recipientArgIndex: z.number().int().nonnegative().max(U32_MAX).optional(),
|
|
406
|
+
allowZeroCap: z.boolean().optional(),
|
|
407
|
+
/** Minimum output as a ratio of the call's own input. num/den are decimal
|
|
408
|
+
* STRINGS for the same reason maxAmount is: an i128 ratio does not
|
|
409
|
+
* survive a JS number. */
|
|
410
|
+
minOutputRatio: z
|
|
411
|
+
.object({
|
|
412
|
+
num: z.string().regex(/^[0-9]+$/, 'num must be an unsigned integer'),
|
|
413
|
+
den: z.string().regex(/^[0-9]+$/, 'den must be an unsigned integer'),
|
|
414
|
+
inputArgIndex: z.number().int().nonnegative().max(U32_MAX),
|
|
415
|
+
outputArgIndex: z.number().int().nonnegative().max(U32_MAX),
|
|
416
|
+
})
|
|
417
|
+
.strict()
|
|
418
|
+
.optional(),
|
|
419
|
+
})
|
|
420
|
+
.strict();
|
|
338
421
|
export const InstallPolicyInputSchema = z
|
|
339
422
|
.object({
|
|
423
|
+
/** Rules already on the account. Supplying them turns on the cross-rule
|
|
424
|
+
* authority scan, which reports every existing rule a signer of this
|
|
425
|
+
* install could name INSTEAD - including an unpoliced one, against which
|
|
426
|
+
* the predicate never runs. Absent means the scan is skipped, and the
|
|
427
|
+
* result says so rather than reporting "no overlaps found". */
|
|
428
|
+
existingRules: z.array(ObservedRuleSchema).optional(),
|
|
340
429
|
/** The smart account contract address (C...) that will receive the rule. */
|
|
341
430
|
smartAccount: z
|
|
342
431
|
.string()
|
|
@@ -201,11 +201,22 @@ function visit(node, facts) {
|
|
|
201
201
|
for (const child of node.children)
|
|
202
202
|
visit(child, facts);
|
|
203
203
|
return;
|
|
204
|
+
// NOT descended into. A deny case works by violating ONE constraint and
|
|
205
|
+
// asserting the predicate refuses the call. Violating one branch of an
|
|
206
|
+
// `or` proves nothing, because another branch can still permit, so the
|
|
207
|
+
// generated case would either fail or pass for the wrong reason. A sound
|
|
208
|
+
// deny case for a disjunction must violate EVERY branch at once, which
|
|
209
|
+
// this generator does not construct - so it emits none.
|
|
210
|
+
case 'or':
|
|
211
|
+
return;
|
|
204
212
|
case 'in':
|
|
205
213
|
facts.memberships.push(node);
|
|
206
214
|
return;
|
|
207
215
|
case 'eq':
|
|
216
|
+
case 'lt':
|
|
208
217
|
case 'lte':
|
|
218
|
+
case 'gt':
|
|
219
|
+
case 'gte':
|
|
209
220
|
facts.comparisons.push(node);
|
|
210
221
|
}
|
|
211
222
|
}
|