@crediolabs/policy-synth 0.2.0 → 0.3.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.
Files changed (184) hide show
  1. package/README.md +4 -4
  2. package/dist/adapters/interpreter/adapter.d.ts +19 -25
  3. package/dist/adapters/interpreter/adapter.js +54 -487
  4. package/dist/adapters/interpreter/index.d.ts +1 -1
  5. package/dist/adapters/interpreter/index.js +1 -1
  6. package/dist/adapters/oz/adapter.js +1 -15
  7. package/dist/errors.d.ts +1 -1
  8. package/dist/index.d.ts +1 -4
  9. package/dist/index.js +1 -4
  10. package/dist/install/build-add-context-rule.d.ts +3 -19
  11. package/dist/install/build-add-context-rule.js +3 -98
  12. package/dist/install/build-install-policy.d.ts +4 -53
  13. package/dist/install/build-install-policy.js +44 -123
  14. package/dist/install/index.d.ts +0 -2
  15. package/dist/install/index.js +0 -7
  16. package/dist/ir/index.d.ts +1 -1
  17. package/dist/ir/types.d.ts +7 -76
  18. package/dist/ir/types.js +0 -2
  19. package/dist/predicate/decode.d.ts +1 -1
  20. package/dist/predicate/decode.js +2 -70
  21. package/dist/predicate/encode.js +45 -229
  22. package/dist/predicate/from-json.js +1 -42
  23. package/dist/record/decode.js +3 -8
  24. package/dist/review-card/builder.d.ts +4 -3
  25. package/dist/review-card/builder.js +18 -162
  26. package/dist/review-card/cross-check.js +2 -105
  27. package/dist/review-card/render-leaf.d.ts +4 -0
  28. package/dist/review-card/render-leaf.js +47 -0
  29. package/dist/run/index.d.ts +36 -139
  30. package/dist/run/index.js +125 -437
  31. package/dist/run/schemas.d.ts +168 -1929
  32. package/dist/run/schemas.js +40 -269
  33. package/dist/seams/types.d.ts +0 -2
  34. package/dist/simulate/deny-cases.d.ts +26 -0
  35. package/dist/simulate/deny-cases.js +282 -0
  36. package/dist/simulate/evaluate.d.ts +18 -0
  37. package/dist/simulate/evaluate.js +271 -0
  38. package/dist/simulate/index.d.ts +4 -0
  39. package/dist/simulate/index.js +8 -0
  40. package/dist/synth/compose-from-recording.d.ts +24 -51
  41. package/dist/synth/compose-from-recording.js +120 -282
  42. package/dist/synth/deny-cases.d.ts +5 -7
  43. package/dist/synth/deny-cases.js +23 -373
  44. package/dist/synth/evaluate.d.ts +0 -21
  45. package/dist/synth/evaluate.js +56 -336
  46. package/dist/synth/index.d.ts +0 -5
  47. package/dist/synth/index.js +0 -5
  48. package/dist/synth/permit-context.d.ts +2 -9
  49. package/dist/synth/permit-context.js +1 -82
  50. package/dist/synth/synthesize-from-recording.d.ts +1 -29
  51. package/dist/synth/synthesize-from-recording.js +41 -356
  52. package/dist/types.d.ts +8 -60
  53. package/dist/types.js +5 -2
  54. package/dist/verify/simulate.d.ts +1 -14
  55. package/dist/verify/simulate.js +2 -88
  56. package/dist/verify/verify.d.ts +1 -7
  57. package/dist/verify/verify.js +0 -8
  58. package/dist-cjs/adapters/interpreter/adapter.d.ts +19 -25
  59. package/dist-cjs/adapters/interpreter/adapter.js +56 -489
  60. package/dist-cjs/adapters/interpreter/index.d.ts +1 -1
  61. package/dist-cjs/adapters/interpreter/index.js +1 -2
  62. package/dist-cjs/adapters/oz/adapter.js +1 -15
  63. package/dist-cjs/errors.d.ts +1 -1
  64. package/dist-cjs/index.d.ts +1 -4
  65. package/dist-cjs/index.js +1 -4
  66. package/dist-cjs/install/build-add-context-rule.d.ts +3 -19
  67. package/dist-cjs/install/build-add-context-rule.js +1 -97
  68. package/dist-cjs/install/build-install-policy.d.ts +4 -53
  69. package/dist-cjs/install/build-install-policy.js +44 -122
  70. package/dist-cjs/install/index.d.ts +0 -2
  71. package/dist-cjs/install/index.js +2 -23
  72. package/dist-cjs/ir/index.d.ts +1 -1
  73. package/dist-cjs/ir/types.d.ts +7 -76
  74. package/dist-cjs/ir/types.js +0 -2
  75. package/dist-cjs/predicate/decode.d.ts +1 -1
  76. package/dist-cjs/predicate/decode.js +2 -70
  77. package/dist-cjs/predicate/encode.js +45 -229
  78. package/dist-cjs/predicate/from-json.js +1 -42
  79. package/dist-cjs/record/decode.js +3 -8
  80. package/dist-cjs/review-card/builder.d.ts +4 -3
  81. package/dist-cjs/review-card/builder.js +23 -167
  82. package/dist-cjs/review-card/cross-check.js +7 -110
  83. package/dist-cjs/review-card/render-leaf.d.ts +4 -0
  84. package/dist-cjs/review-card/render-leaf.js +52 -0
  85. package/dist-cjs/run/index.d.ts +36 -139
  86. package/dist-cjs/run/index.js +125 -444
  87. package/dist-cjs/run/schemas.d.ts +168 -1929
  88. package/dist-cjs/run/schemas.js +41 -270
  89. package/dist-cjs/seams/types.d.ts +0 -2
  90. package/dist-cjs/simulate/deny-cases.d.ts +26 -0
  91. package/dist-cjs/simulate/deny-cases.js +286 -0
  92. package/dist-cjs/simulate/evaluate.d.ts +18 -0
  93. package/dist-cjs/simulate/evaluate.js +274 -0
  94. package/dist-cjs/simulate/index.d.ts +4 -0
  95. package/dist-cjs/simulate/index.js +13 -0
  96. package/dist-cjs/synth/compose-from-recording.d.ts +24 -51
  97. package/dist-cjs/synth/compose-from-recording.js +120 -282
  98. package/dist-cjs/synth/deny-cases.d.ts +5 -7
  99. package/dist-cjs/synth/deny-cases.js +23 -374
  100. package/dist-cjs/synth/evaluate.d.ts +0 -21
  101. package/dist-cjs/synth/evaluate.js +57 -337
  102. package/dist-cjs/synth/index.d.ts +0 -5
  103. package/dist-cjs/synth/index.js +1 -11
  104. package/dist-cjs/synth/permit-context.d.ts +2 -9
  105. package/dist-cjs/synth/permit-context.js +1 -82
  106. package/dist-cjs/synth/synthesize-from-recording.d.ts +1 -29
  107. package/dist-cjs/synth/synthesize-from-recording.js +39 -354
  108. package/dist-cjs/types.d.ts +8 -60
  109. package/dist-cjs/types.js +6 -3
  110. package/dist-cjs/verify/simulate.d.ts +1 -14
  111. package/dist-cjs/verify/simulate.js +2 -88
  112. package/dist-cjs/verify/verify.d.ts +1 -7
  113. package/dist-cjs/verify/verify.js +0 -8
  114. package/package.json +4 -4
  115. package/src/adapters/interpreter/adapter.ts +76 -572
  116. package/src/errors.ts +0 -19
  117. package/src/index.ts +1 -4
  118. package/src/install/build-add-context-rule.ts +5 -139
  119. package/src/install/build-install-policy.ts +93 -214
  120. package/src/install/index.ts +0 -34
  121. package/src/predicate/decode.ts +2 -70
  122. package/src/predicate/encode.ts +49 -261
  123. package/src/predicate/from-json.ts +1 -43
  124. package/src/record/decode.ts +3 -8
  125. package/src/review-card/builder.ts +19 -168
  126. package/src/review-card/cross-check.ts +3 -105
  127. package/src/review-card/render-leaf.ts +48 -0
  128. package/src/run/index.ts +144 -572
  129. package/src/run/schemas.ts +42 -291
  130. package/src/simulate/deny-cases.ts +334 -0
  131. package/src/simulate/evaluate.ts +284 -0
  132. package/src/simulate/index.ts +11 -0
  133. package/src/synth/compose-from-recording.ts +148 -347
  134. package/src/synth/index.ts +0 -13
  135. package/src/synth/synthesize-from-recording.ts +43 -456
  136. package/src/types.ts +13 -49
  137. package/dist/install/authority-overlap.d.ts +0 -134
  138. package/dist/install/authority-overlap.js +0 -0
  139. package/dist/install/build-install-predicate.d.ts +0 -96
  140. package/dist/install/build-install-predicate.js +0 -444
  141. package/dist/install/build-merge-policy.d.ts +0 -70
  142. package/dist/install/build-merge-policy.js +0 -130
  143. package/dist/install/plan-merge-policy.d.ts +0 -49
  144. package/dist/install/plan-merge-policy.js +0 -86
  145. package/dist/install/read-account-rules.d.ts +0 -100
  146. package/dist/install/read-account-rules.js +0 -283
  147. package/dist-cjs/install/authority-overlap.d.ts +0 -134
  148. package/dist-cjs/install/authority-overlap.js +0 -0
  149. package/dist-cjs/install/build-install-predicate.d.ts +0 -96
  150. package/dist-cjs/install/build-install-predicate.js +0 -479
  151. package/dist-cjs/install/build-merge-policy.d.ts +0 -70
  152. package/dist-cjs/install/build-merge-policy.js +0 -134
  153. package/dist-cjs/install/plan-merge-policy.d.ts +0 -49
  154. package/dist-cjs/install/plan-merge-policy.js +0 -90
  155. package/dist-cjs/install/read-account-rules.d.ts +0 -100
  156. package/dist-cjs/install/read-account-rules.js +0 -296
  157. package/src/adapters/interpreter/index.ts +0 -8
  158. package/src/adapters/oz/adapter.ts +0 -376
  159. package/src/adapters/oz/index.ts +0 -9
  160. package/src/codegen/compile-gate.ts +0 -167
  161. package/src/codegen/index.ts +0 -17
  162. package/src/codegen/template.ts +0 -165
  163. package/src/install/authority-overlap.ts +0 -0
  164. package/src/install/build-merge-policy.ts +0 -219
  165. package/src/install/plan-merge-policy.ts +0 -133
  166. package/src/install/read-account-rules.ts +0 -376
  167. package/src/ir/index.ts +0 -13
  168. package/src/ir/types.ts +0 -132
  169. package/src/mandate/index.ts +0 -4
  170. package/src/mandate/to-ir.ts +0 -71
  171. package/src/mandate/types.ts +0 -21
  172. package/src/seams/index.ts +0 -11
  173. package/src/seams/types.ts +0 -81
  174. package/src/synth/deny-cases.ts +0 -663
  175. package/src/synth/evaluate.ts +0 -613
  176. package/src/synth/harness.ts +0 -68
  177. package/src/synth/minimize.ts +0 -48
  178. package/src/synth/permit-context.ts +0 -136
  179. package/src/synth/predicate-literals.ts +0 -27
  180. package/src/synth/synthesize-from-mandate.ts +0 -82
  181. package/src/verify/envelope.ts +0 -28
  182. package/src/verify/index.ts +0 -5
  183. package/src/verify/simulate.ts +0 -311
  184. package/src/verify/verify.ts +0 -243
@@ -6,7 +6,7 @@
6
6
  // expiry.validUntilLedger -> ContextRuleDraft.validUntilLedger
7
7
  // window_spent(t,w) <= L -> `spending_limit` primitive
8
8
  // approval.threshold -> `simple_threshold` / `weighted_threshold`
9
- // Anything needing a capability this backend lacks (oracle price, invocation
9
+ // Anything needing a capability this backend lacks (invocation
10
10
  // count, per-arg comparison/allowlist, guard, nested boolean predicate) is NOT
11
11
  // emitted: it is named in `uncovered` and `covered` is set false. Nothing is
12
12
  // silently dropped.
@@ -40,8 +40,6 @@ const CAPABILITIES = {
40
40
  supportsSpendWindow: true,
41
41
  supportsThreshold: true,
42
42
  supportsTimeExpiry: true,
43
- supportsOraclePrice: false,
44
- supportsInvocationCount: false,
45
43
  supportsGeneralPredicate: false,
46
44
  };
47
45
  export function createOzAdapter(config) {
@@ -206,10 +204,6 @@ function matchSpendingLimit(c) {
206
204
  * cannot express, used to populate `uncovered`. */
207
205
  function describeCondition(cond) {
208
206
  switch (cond.op) {
209
- case 'slippage_floor':
210
- // OZ primitives bound a value against a constant; this bounds one call
211
- // argument against another, which none of them can express.
212
- return `slippage floor on arg[${cond.outArgIndex}] (OZ built-ins cannot bound one argument against another)`;
213
207
  case 'in':
214
208
  return `value allowlist on ${describeSelector(cond.selector)} (arg allowlist)`;
215
209
  case 'eq_seq':
@@ -222,10 +216,6 @@ function describeCondition(cond) {
222
216
  case 'compare': {
223
217
  const s = cond.compare.selector;
224
218
  switch (s.kind) {
225
- case 'oracle_price':
226
- return `oracle price condition on ${s.asset} (oracle price not supported in week-1)`;
227
- case 'invocation_count':
228
- return `invocation-count window (${s.windowSeconds}s) condition (not supported in week-1)`;
229
219
  case 'window_spent':
230
220
  return `spend-window comparison with operator '${cond.compare.operator}' (only 'lte' lowers to spending_limit)`;
231
221
  case 'amount':
@@ -259,10 +249,6 @@ function describeSelector(s) {
259
249
  return `amount(${s.token})`;
260
250
  case 'window_spent':
261
251
  return `window_spent(${s.token})`;
262
- case 'oracle_price':
263
- return `oracle_price(${s.asset})`;
264
- case 'invocation_count':
265
- return `invocation_count(${s.windowSeconds}s)`;
266
252
  case 'calldata':
267
253
  return `calldata[${s.offset}:${s.offset + s.length}]`;
268
254
  default:
package/dist/errors.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type ErrorCode = 'RECORDING_FAILED' | 'RECORDING_VALIDATION_FAILED' | 'SCOPE_UNRESOLVED' | 'SYNTHESIS_ERROR' | 'MALFORMED_PREDICATE' | 'SIMULATION_ERROR' | 'VERIFICATION_FAILED' | 'DENY_CASE_FAILURE' | 'PERMIT_CASE_FAILED' | 'SUMMARY_DRIFT' | 'INSTALL_BUILD_FAILED' | 'INSTALL_CONFIRM_MISSING' | 'INSTALL_CONFIRM_EXPIRED' | 'REVOKE_BUILD_FAILED' | 'REVOKE_CONFIRM_MISSING' | 'USER_REJECTED_SIGN' | 'WALLET_TIMEOUT' | 'WALLET_UNAVAILABLE' | 'PREDICATE_TOO_LARGE' | 'PREDICATE_TOO_DEEP' | 'TOO_MANY_LEAVES' | 'IN_OPERAND_LIMIT' | 'PREDICATE_ORACLE_OVER_LIMIT' | 'POLICY_CAP_EXCEEDED' | 'WASM_TOO_LARGE' | 'MASTER_AUTH_REQUIRED' | 'NONCE_REPLAY' | 'VERSION_MISMATCH' | 'ARITHMETIC_OVERFLOW' | 'AMOUNT_OVERFLOW' | 'RULE_SIGNERS_CHANGED' | 'SCOPE_SELF_CALL' | 'ARG_MISMATCH' | 'CONTRACT_SCOPE' | 'UNSUPPORTED_NODE' | 'STATEFUL_BOUND' | 'NOT_IN_ALLOWLIST' | 'FREQUENCY' | 'SLIPPAGE_FLOOR' | 'ORACLE_STALE' | 'ORACLE_MISSING' | 'ORACLE_NO_CONFIRMATION' | 'ORACLE_DEVIATION_EXCEEDED' | 'ORACLE_MALFORMED_HISTORY' | 'ORACLE_FINGERPRINT_DRIFT' | 'ORACLE_PAUSED' | 'ORACLE_LEAF_INVALID_POSITION' | 'ORACLE_PARAMS_OUT_OF_RANGE' | 'ORACLE_DECIMALS_MISMATCH' | 'ORACLE_THRESHOLD_DECIMALS_OUT_OF_RANGE' | 'ORACLE_THRESHOLD_BASIS_REQUIRED' | 'COMPILE_OK' | 'COMPILE_GATE_FAILED';
1
+ export type ErrorCode = 'RECORDING_FAILED' | 'RECORDING_VALIDATION_FAILED' | 'SCOPE_UNRESOLVED' | 'SYNTHESIS_ERROR' | 'MALFORMED_PREDICATE' | 'SIMULATION_ERROR' | 'VERIFICATION_FAILED' | 'DENY_CASE_FAILURE' | 'PERMIT_CASE_FAILED' | 'SUMMARY_DRIFT' | 'INSTALL_BUILD_FAILED' | 'INSTALL_CONFIRM_MISSING' | 'INSTALL_CONFIRM_EXPIRED' | 'REVOKE_BUILD_FAILED' | 'REVOKE_CONFIRM_MISSING' | 'USER_REJECTED_SIGN' | 'WALLET_TIMEOUT' | 'WALLET_UNAVAILABLE' | 'PREDICATE_TOO_LARGE' | 'PREDICATE_TOO_DEEP' | 'TOO_MANY_LEAVES' | 'IN_OPERAND_LIMIT' | 'POLICY_CAP_EXCEEDED' | 'WASM_TOO_LARGE' | 'MASTER_AUTH_REQUIRED' | 'NONCE_REPLAY' | 'VERSION_MISMATCH' | 'ARITHMETIC_OVERFLOW' | 'AMOUNT_OVERFLOW' | 'RULE_SIGNERS_CHANGED' | 'SCOPE_SELF_CALL' | 'ARG_MISMATCH' | 'CONTRACT_SCOPE' | 'UNSUPPORTED_NODE' | 'STATEFUL_BOUND' | 'NOT_IN_ALLOWLIST' | 'COMPILE_OK' | 'COMPILE_GATE_FAILED';
2
2
  export interface ToolError {
3
3
  code: ErrorCode;
4
4
  message: string;
package/dist/index.d.ts CHANGED
@@ -1,11 +1,8 @@
1
- export * from './adapters/oz/index.ts';
2
1
  export * from './errors.ts';
3
- export * from './ir/index.ts';
4
- export * from './mandate/index.ts';
5
2
  export * from './predicate/index.ts';
6
3
  export * from './record/index.ts';
7
4
  export * from './registry/index.ts';
8
5
  export * from './review-card/index.ts';
9
- export * from './seams/index.ts';
6
+ export * from './simulate/index.ts';
10
7
  export * from './synth/index.ts';
11
8
  export * from './types.ts';
package/dist/index.js CHANGED
@@ -1,11 +1,8 @@
1
- export * from "./adapters/oz/index.js";
2
1
  export * from "./errors.js";
3
- export * from "./ir/index.js";
4
- export * from "./mandate/index.js";
5
2
  export * from "./predicate/index.js";
6
3
  export * from "./record/index.js";
7
4
  export * from "./registry/index.js";
8
5
  export * from "./review-card/index.js";
9
- export * from "./seams/index.js";
6
+ export * from "./simulate/index.js";
10
7
  export * from "./synth/index.js";
11
8
  export * from "./types.js";
@@ -8,8 +8,8 @@ export interface BuildAddContextRuleArgs {
8
8
  * admin session. The deployer signs the install call via the admin rule
9
9
  * already on the account, which is separate from this list. */
10
10
  signers: SignerDraft[];
11
- /** The policy(ies) to attach to the new rule. Only `interpreter` refs
12
- * reach the wire today; `oz_builtin` is reserved for Phase 06 follow-ups. */
11
+ /** The policy(ies) to attach to the new rule. `interpreter` is the only
12
+ * kind: the OpenZeppelin built-in backend was removed. */
13
13
  policies: PolicyRef[];
14
14
  /** Per-policy install nonce; 1 for a fresh install. */
15
15
  installNonce: number;
@@ -19,19 +19,11 @@ export interface BuildAddContextRuleArgs {
19
19
  encodedPredicate: string;
20
20
  /** Hex sha256 of the canonical predicate XDR bytes. */
21
21
  predicateHash: string;
22
- /** Per-policy oracle overrides. Absent on any key uses the wasm default. */
23
- oracleParams?: {
24
- maxStalenessSeconds?: number;
25
- maxDeviationBps?: number;
26
- /** Bound between the primary and secondary feeds. Tighten-only against
27
- * the wasm default, like the other two. */
28
- maxCrossFeedDeviationBps?: number;
29
- };
30
22
  /** Hard pin to the interpreter's wasm grammar. Refusing here fails closed
31
23
  * before the chain does; the contract will refuse a mismatch again. */
32
24
  grammarVersion?: number;
33
25
  }
34
- export declare const DEFAULT_GRAMMAR_VERSION: 1;
26
+ export declare const DEFAULT_GRAMMAR_VERSION: 3;
35
27
  /** The verb `add_context_rule` takes on the wire. */
36
28
  export declare const ADD_CONTEXT_RULE_SYMBOL: "add_context_rule";
37
29
  /** Tuple of `ScVal` arguments to pass to `Operation.invokeHostFunction` for
@@ -46,11 +38,3 @@ export type AddContextRuleArgs = readonly [
46
38
  /** Build the `add_context_rule` invocation args. Throws a `ToolError`-shaped
47
39
  * error on limit breaches or malformed input. */
48
40
  export declare function buildAddContextRuleArgs(draft: ContextRuleDraft, args: BuildAddContextRuleArgs): AddContextRuleArgs;
49
- /** The `PolicyInstallParams` ScVal an interpreter policy receives.
50
- *
51
- * Exported so the merge remedy can re-install a policy through `add_policy`
52
- * using the SAME encoder as a fresh install. Re-implementing it would risk
53
- * exactly the drift this file warns about: the field order is ABI-significant
54
- * and a differing encoding yields a rule that denies every call. */
55
- export type PolicyInstallParamArgs = Pick<BuildAddContextRuleArgs, 'encodedPredicate' | 'predicateHash' | 'installNonce' | 'oracleParams' | 'grammarVersion'>;
56
- export declare function encodePolicyInstallParams(args: PolicyInstallParamArgs): xdr.ScVal;
@@ -48,8 +48,8 @@
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 { OZ_LIMITS, } from "../types.js";
52
- export const DEFAULT_GRAMMAR_VERSION = 1;
51
+ import { GRAMMAR_VERSION, OZ_LIMITS, } from "../types.js";
52
+ export const DEFAULT_GRAMMAR_VERSION = GRAMMAR_VERSION;
53
53
  /** The verb `add_context_rule` takes on the wire. */
54
54
  export const ADD_CONTEXT_RULE_SYMBOL = 'add_context_rule';
55
55
  /** Build the `add_context_rule` invocation args. Throws a `ToolError`-shaped
@@ -65,15 +65,6 @@ export function buildAddContextRuleArgs(draft, args) {
65
65
  if (args.signers.length === 0 && args.policies.length === 0) {
66
66
  throw limitError('INSTALL_BUILD_FAILED', 'a rule with no signers and no policies is refused at install (NoSignersAndPolicies)');
67
67
  }
68
- // OZ's spending_limit caps spend on the CONTEXT CONTRACT - it takes no
69
- // token argument - so it refuses a Default rule on chain with a bare
70
- // #3227. Say which rule shape it needs here, before the encoding, rather
71
- // than letting the user read a numeric trap.
72
- if (args.policies.some((p) => p.kind === 'oz_builtin' && p.primitive.primitive === 'spending_limit')) {
73
- if (draft.contextRuleType.kind !== 'call_contract') {
74
- throw limitError('INSTALL_BUILD_FAILED', `spending_limit caps spend on the rule's context contract, so the rule must be call_contract-scoped to that token - a "${draft.contextRuleType.kind}" rule is refused on chain (#3227)`);
75
- }
76
- }
77
68
  // ---- 2. context_type encoding ----
78
69
  const contextType = encodeContextRuleType(draft.contextRuleType);
79
70
  // ---- 3. name (string) + valid_until (Option<u32>) ----
@@ -95,15 +86,6 @@ const POLICY_INSTALL_PARAM_FIELDS = [
95
86
  'install_nonce',
96
87
  'predicate',
97
88
  'predicate_hash',
98
- 'oracle_max_staleness_seconds',
99
- 'oracle_max_deviation_bps',
100
- // Cross-feed divergence bound. A field added to the contract's
101
- // `PolicyInstallParams` changes the ABI: the host unpacks the map by field
102
- // count, so omitting one fails the entire install with
103
- // `Error(Object, UnexpectedSize)` and no indication of which field is
104
- // missing. The Rust tests build that struct in Rust and never cross this
105
- // boundary, so only a real install against a deployed contract catches it.
106
- 'oracle_max_xfeed_dev_bps',
107
89
  ];
108
90
  function encodeContextRuleType(rule) {
109
91
  switch (rule.kind) {
@@ -145,76 +127,11 @@ function encodePoliciesMap(args) {
145
127
  val: encodePolicyInstallParams(args),
146
128
  }));
147
129
  }
148
- else if (ref.kind === 'oz_builtin') {
149
- entries.push(new xdr.ScMapEntry({
150
- key: Address.fromString(ref.instanceAddress).toScVal(),
151
- val: encodeOzPrimitiveParams(ref.primitive),
152
- }));
153
- }
154
130
  }
155
131
  entries.sort(sortByScValSymbolString);
156
132
  return xdr.ScVal.scvMap(entries);
157
133
  }
158
- /** Encode the install params for one OZ built-in policy.
159
- *
160
- * Field names and types are read from the deployed contracts' own spec:
161
- * SpendingLimitAccountParams { period_ledgers: u32, spending_limit: i128 }
162
- * SimpleThresholdAccountParams { threshold: u32 }
163
- * WeightedThresholdAccountParams { signer_weights: map, threshold: u32 }
164
- * Entries are symbol-string ordered for the same reason the interpreter's
165
- * are: the host orders by symbol, not by XDR bytes.
166
- */
167
- function encodeOzPrimitiveParams(primitive) {
168
- const entries = [];
169
- const push = (name, val) => entries.push(new xdr.ScMapEntry({ key: xdr.ScVal.scvSymbol(name), val }));
170
- const p = primitive.params;
171
- switch (primitive.primitive) {
172
- case 'spending_limit': {
173
- const limit = p.spending_limit;
174
- const period = p.period_ledgers;
175
- if (typeof limit !== 'string' || typeof period !== 'number') {
176
- throw limitError('INSTALL_BUILD_FAILED', 'spending_limit needs { spending_limit: string; period_ledgers: number }');
177
- }
178
- push('period_ledgers', xdr.ScVal.scvU32(period));
179
- push('spending_limit', encodeI128(limit));
180
- break;
181
- }
182
- case 'simple_threshold': {
183
- const threshold = p.threshold;
184
- if (typeof threshold !== 'number') {
185
- throw limitError('INSTALL_BUILD_FAILED', 'simple_threshold needs { threshold: number }');
186
- }
187
- push('threshold', xdr.ScVal.scvU32(threshold));
188
- break;
189
- }
190
- case 'weighted_threshold': {
191
- const threshold = p.threshold;
192
- const weights = p.weights;
193
- if (typeof threshold !== 'number' || !weights) {
194
- throw limitError('INSTALL_BUILD_FAILED', 'weighted_threshold needs { threshold: number; weights: Record<address, number> }');
195
- }
196
- const weightEntries = Object.entries(weights)
197
- .map(([addr, w]) => new xdr.ScMapEntry({
198
- key: Address.fromString(addr).toScVal(),
199
- val: xdr.ScVal.scvU32(w),
200
- }))
201
- .sort((a, b) => (a.key().toXDR('base64') < b.key().toXDR('base64') ? -1 : 1));
202
- push('signer_weights', xdr.ScVal.scvMap(weightEntries));
203
- push('threshold', xdr.ScVal.scvU32(threshold));
204
- break;
205
- }
206
- }
207
- entries.sort((a, b) => sortBySymbolString(a.key(), b.key()));
208
- return xdr.ScVal.scvMap(entries);
209
- }
210
- function encodeI128(value) {
211
- const v = BigInt(value);
212
- return xdr.ScVal.scvI128(new xdr.Int128Parts({
213
- hi: new xdr.Int64(BigInt.asIntN(64, v >> 64n)),
214
- lo: new xdr.Uint64(BigInt.asUintN(64, v)),
215
- }));
216
- }
217
- export function encodePolicyInstallParams(args) {
134
+ function encodePolicyInstallParams(args) {
218
135
  const predicate = Buffer.from(args.encodedPredicate, 'base64');
219
136
  const computedHash = createHash('sha256').update(predicate).digest('hex');
220
137
  if (computedHash !== args.predicateHash) {
@@ -223,15 +140,11 @@ export function encodePolicyInstallParams(args) {
223
140
  // Per-field value encoders. Each entry returns the ScVal to drop into the
224
141
  // map; the key symbol comes from the surrounding loop. Adding a field is
225
142
  // one row here plus the symbol in POLICY_INSTALL_PARAM_FIELDS.
226
- const oracleParams = args.oracleParams;
227
143
  const valueFor = {
228
144
  grammar_version: () => xdr.ScVal.scvU32(args.grammarVersion ?? DEFAULT_GRAMMAR_VERSION),
229
145
  install_nonce: () => xdr.ScVal.scvU32(args.installNonce),
230
146
  predicate: () => xdr.ScVal.scvBytes(predicate),
231
147
  predicate_hash: () => xdr.ScVal.scvBytes(Buffer.from(args.predicateHash, 'hex')),
232
- oracle_max_staleness_seconds: () => encodeOptionU32(oracleParams?.maxStalenessSeconds),
233
- oracle_max_deviation_bps: () => encodeOptionU32(oracleParams?.maxDeviationBps),
234
- oracle_max_xfeed_dev_bps: () => encodeOptionU32(oracleParams?.maxCrossFeedDeviationBps),
235
148
  };
236
149
  const entries = POLICY_INSTALL_PARAM_FIELDS.map((k) => new xdr.ScMapEntry({ key: xdr.ScVal.scvSymbol(k), val: valueFor[k]() }));
237
150
  // The host orders map entries by the SYMBOL STRING, not by XDR bytes. A
@@ -241,14 +154,6 @@ export function encodePolicyInstallParams(args) {
241
154
  entries.sort((a, b) => sortBySymbolString(a.key(), b.key()));
242
155
  return xdr.ScVal.scvMap(entries);
243
156
  }
244
- function encodeOptionU32(v) {
245
- if (v === undefined)
246
- return xdr.ScVal.scvVoid();
247
- if (!Number.isFinite(v) || v < 0 || v > 0xffffffff) {
248
- throw limitError('INSTALL_BUILD_FAILED', `oracle params value ${v} is outside u32 range`);
249
- }
250
- return xdr.ScVal.scvU32(v);
251
- }
252
157
  /** Sort host-map keys by their symbol-string form. The host orders map
253
158
  * entries by the SYMBOL STRING, not by the key's XDR bytes (a length
254
159
  * prefix in the encoding would otherwise put `amount` before `address`).
@@ -1,5 +1,5 @@
1
- import { Contract, rpc, type Transaction } from '@stellar/stellar-sdk';
2
- import { DEFAULT_GRAMMAR_VERSION } from './build-add-context-rule.ts';
1
+ import { rpc, type Transaction } from '@stellar/stellar-sdk';
2
+ import type { ContextRuleDraft } from '../types.ts';
3
3
  /** Minimal Soroban RPC surface the install pipeline needs. Test seams
4
4
  * inject a stub so the builder stays deterministic; production builds
5
5
  * the real one via `createRpcServer` from `../record/rpc.ts`. */
@@ -31,20 +31,14 @@ export interface BuildInstallPolicyArgs {
31
31
  sourceAccount: string;
32
32
  /** Network passphrase - pins the hash the auth digest binds. */
33
33
  networkPassphrase: string;
34
- /** The new rule to install. Mirrors the core `ContextRuleDraft`. */
35
- rule: BuildInstallPolicyRuleDraft;
34
+ /** The new rule to install. */
35
+ rule: ContextRuleDraft;
36
36
  /** Per-rule install nonce; 1 for a fresh install. */
37
37
  installNonce: number;
38
38
  /** Already-encoded (base64) canonical ScVal of the predicate. */
39
39
  encodedPredicate: string;
40
40
  /** Hex sha256 of the canonical predicate XDR bytes. */
41
41
  predicateHash: string;
42
- /** Per-policy oracle overrides. */
43
- oracleParams?: {
44
- maxStalenessSeconds?: number;
45
- maxDeviationBps?: number;
46
- maxCrossFeedDeviationBps?: number;
47
- };
48
42
  /** Grammar version override; defaults to 1. */
49
43
  grammarVersion?: number;
50
44
  /** Base fee in stroops; defaults to BASE_FEE (100). */
@@ -54,41 +48,6 @@ export interface BuildInstallPolicyArgs {
54
48
  /** Ledger window (in ledgers) for the auth entry's `validUntil`. */
55
49
  authValidUntilLedgers?: number;
56
50
  }
57
- export type BuildInstallPolicyRuleDraft = {
58
- contextRuleType: {
59
- kind: 'default';
60
- } | {
61
- kind: 'call_contract';
62
- contract: string;
63
- } | {
64
- kind: 'create_contract';
65
- wasmHash: string;
66
- };
67
- name: string;
68
- validUntilLedger: number | null;
69
- signers: BuildInstallPolicySignerDraft[];
70
- policies: BuildInstallPolicyPolicyRef[];
71
- };
72
- export type BuildInstallPolicySignerDraft = {
73
- kind: 'delegated';
74
- address: string;
75
- } | {
76
- kind: 'external';
77
- verifier: string;
78
- keyBytes: string;
79
- };
80
- export type BuildInstallPolicyPolicyRef = {
81
- kind: 'interpreter';
82
- interpreterAddress: string;
83
- predicateBlobBase64: string;
84
- } | {
85
- kind: 'oz_builtin';
86
- instanceAddress: string;
87
- primitive: {
88
- primitive: 'spending_limit' | 'simple_threshold' | 'weighted_threshold';
89
- params: Record<string, unknown>;
90
- };
91
- };
92
51
  /** Human-readable description of the install call, decoded FROM the built
93
52
  * XDR (not from the input args). The XDR is the source of truth: a
94
53
  * human approving a review card needs the description to mirror the bytes
@@ -134,10 +93,6 @@ export interface InstallCallDescribes {
134
93
  installNonce: number;
135
94
  predicateHash: string;
136
95
  predicateSha256OfEmbeddedBytes: string;
137
- } | {
138
- kind: 'oz_builtin';
139
- address: string;
140
- primitive: 'spending_limit' | 'simple_threshold' | 'weighted_threshold';
141
96
  }>;
142
97
  /** The install nonce, decoded from the interpreter policy's
143
98
  * `install_nonce` field. Echoed at the top level for reviewer convenience;
@@ -217,7 +172,3 @@ export interface BuildRevokePolicyResult {
217
172
  authValidUntilLedger: number;
218
173
  rootInvocationXdr: string;
219
174
  }
220
- /** Re-export so the run-layer does not need to import from
221
- * build-add-context-rule.ts (keeps the install/ -> install/ dependency
222
- * direction intact). */
223
- export { Contract, DEFAULT_GRAMMAR_VERSION };
@@ -17,8 +17,8 @@
17
17
  // forwards each install_param to that policy, so the interpreter stores the
18
18
  // predicate document as part of this same transaction.
19
19
  import { createHash } from 'node:crypto';
20
- import { Address, BASE_FEE, Contract, Keypair, Operation, rpc, scValToBigInt, TransactionBuilder, xdr, } from '@stellar/stellar-sdk';
21
- import { buildAddContextRuleArgs, DEFAULT_GRAMMAR_VERSION } from "./build-add-context-rule.js";
20
+ import { Account, Address, BASE_FEE, Contract, Keypair, Operation, rpc, scValToBigInt, TransactionBuilder, xdr, } from '@stellar/stellar-sdk';
21
+ import { buildAddContextRuleArgs } from "./build-add-context-rule.js";
22
22
  import { accountEntry, authDigest, authPayload, delegatedSignerEntry, signaturePayload, } from "./oz-auth.js";
23
23
  /** Convert a real rpc.Server into the InstallRpcClient surface. The
24
24
  * `getContractVersion` lookup uses `simulateTransaction` against
@@ -72,73 +72,21 @@ export async function buildInstallPolicyXdr(args) {
72
72
  name: args.rule.name,
73
73
  validUntilLedger: args.rule.validUntilLedger,
74
74
  signers: args.rule.signers,
75
- policies: args.rule.policies.map(adaptPolicyRef),
75
+ policies: args.rule.policies,
76
76
  }, {
77
77
  signers: args.rule.signers,
78
- policies: args.rule.policies.map(adaptPolicyRef),
78
+ policies: args.rule.policies,
79
79
  installNonce: args.installNonce,
80
80
  encodedPredicate: args.encodedPredicate,
81
81
  predicateHash: args.predicateHash,
82
- ...(args.oracleParams ? { oracleParams: args.oracleParams } : {}),
83
82
  ...(args.grammarVersion !== undefined ? { grammarVersion: args.grammarVersion } : {}),
84
83
  });
85
- // 2. Fetch the source sequence, then build the recording transaction with a
86
- // bare host call. The recording pass assigns the smart-account auth nonce
87
- // and root invocation needed to construct OZ's AuthPayload.
88
- const source = await args.rpc.getAccount(args.sourceAccount);
89
- const hostFunction = xdr.HostFunction.hostFunctionTypeInvokeContract(new xdr.InvokeContractArgs({
90
- contractAddress: new Address(args.smartAccount).toScAddress(),
91
- functionName: 'add_context_rule',
92
- args: [...callArgs],
93
- }));
94
- const makeOperation = (auth = []) => Operation.invokeHostFunction({ func: hostFunction, auth });
95
- const baseFee = args.baseFee !== undefined ? String(args.baseFee) : BASE_FEE;
96
- const buildTx = (op) => buildUnsignedTx({
97
- sourceAccount: args.sourceAccount,
98
- sequence: source.sequenceNumber(),
99
- fee: baseFee,
100
- networkPassphrase: args.networkPassphrase,
101
- op,
102
- });
103
- const recordingTx = buildTx(makeOperation());
104
- // 3. Recording simulation: capture the smart account's nonce and invocation
105
- // tree. Nothing is signed here.
106
- const recorded = await args.rpc.simulateTransaction(recordingTx);
107
- if (rpc.Api.isSimulationError(recorded)) {
108
- // Short, stable reason. The full `simulateTransaction` error (which
109
- // carries host + URL detail) stays in the SDK's own logs - never
110
- // reflected back into a user-facing message where it would
111
- // reconnoitre the RPC.
112
- throw new Error('install_policy: simulateTransaction failed');
113
- }
114
- const original = (recorded.result?.auth ?? []).find((entry) => entry.credentials().switch().name === 'sorobanCredentialsAddress' &&
115
- Address.fromScAddress(entry.credentials().address().address()).toString() ===
116
- args.smartAccount);
117
- if (!original) {
118
- throw new Error(`install_policy: no Soroban auth entry for smart account ${args.smartAccount}; this call does not route through the smart account`);
119
- }
120
- // 4. `add_context_rule` is authorised by the deploy-time admin rule (rule 0).
84
+ // 2. `add_context_rule` is authorised by the deploy-time admin rule (rule 0).
121
85
  // The delegated signer uses source-account credentials, so its signature
122
86
  // bytes stay empty and the ordinary transaction-envelope signature covers
123
87
  // the call when the consumer signs it.
124
- const validUntilLedger = (await args.rpc.getLatestLedger()).sequence +
125
- (args.authValidUntilLedgers ?? DEFAULT_AUTH_VALID_UNTIL_LEDGERS);
126
- const contextRuleIds = [0];
127
- const digest = authDigest(signaturePayload(args.networkPassphrase, original.credentials().address().nonce(), validUntilLedger, original.rootInvocation()), contextRuleIds);
128
- const authEntries = [
129
- accountEntry(original, validUntilLedger, authPayload([args.sourceAccount], contextRuleIds, () => Buffer.alloc(0))),
130
- ...contextRuleIds.map(() => delegatedSignerEntry(args.smartAccount, digest)),
131
- ];
132
- // 5. Simulate again with the OZ entries already attached. The SDK preserves
133
- // existing auth during assembly and adds the simulated Soroban footprint +
134
- // resource fee, yielding a complete unsigned envelope.
135
- const txWithAuth = buildTx(makeOperation(authEntries));
136
- const enforcing = await args.rpc.simulateTransaction(txWithAuth);
137
- if (rpc.Api.isSimulationError(enforcing)) {
138
- throw new Error('install_policy: auth simulateTransaction failed');
139
- }
140
- const finalTx = rpc.assembleTransaction(txWithAuth, enforcing).build();
141
- // 6. Decode the structured description FROM the final assembled transaction.
88
+ const { finalTx, original, validUntilLedger } = await buildAuthorisedSmartAccountTx(args, 'add_context_rule', [...callArgs], 'install_policy');
89
+ // 3. Decode the structured description FROM the final assembled transaction.
142
90
  // The human approval binds to the exact bytes the wallet will sign.
143
91
  const describes = decodeInstallCallDescribes(finalTx, args.installNonce);
144
92
  return {
@@ -164,11 +112,39 @@ export async function buildInstallPolicyXdr(args) {
164
112
  * deployer can revoke. This builder does not pre-check the signer: it would
165
113
  * be guessing at a contract it cannot read, and the chain is the authority. */
166
114
  export async function buildRevokePolicyXdr(args) {
115
+ // Removal is master-only, so the deploy-time admin rule authorises it. The
116
+ // recorded rootInvocation still includes remove_context_rule(ruleId), binding
117
+ // the auth payload to the exact rule being removed. As with install,
118
+ // source-account credentials carry the delegated signer entry and the
119
+ // consumer supplies only the ordinary envelope signature.
120
+ const { finalTx, original, validUntilLedger } = await buildAuthorisedSmartAccountTx(args, 'remove_context_rule', [xdr.ScVal.scvU32(args.ruleId)], 'revoke_policy');
121
+ return {
122
+ unsignedXdr: finalTx.toEnvelope().toXDR().toString('base64'),
123
+ smartAccount: args.smartAccount,
124
+ sourceAccount: args.sourceAccount,
125
+ call: { contract: args.smartAccount, fn: 'remove_context_rule', ruleId: args.ruleId },
126
+ authNonce: original.credentials().address().nonce().toString(),
127
+ authValidUntilLedger: validUntilLedger,
128
+ rootInvocationXdr: original.rootInvocation().toXDR().toString('base64'),
129
+ };
130
+ }
131
+ /** ~25 minutes at 5s/ledger. */
132
+ const DEFAULT_AUTH_VALID_UNTIL_LEDGERS = 300;
133
+ // ---- internals ----
134
+ /** Record a bare call to the smart account, attach the deploy-time admin rule's
135
+ * auth entries, and re-simulate to assemble the footprint.
136
+ *
137
+ * Install and revoke differ only in the call they wrap, so they share this
138
+ * spine: the recording pass supplies the auth nonce and root invocation OZ's
139
+ * AuthPayload binds to, and the second simulation adds the Soroban footprint +
140
+ * resource fee. Nothing here is signed. `errorPrefix` names the calling tool in
141
+ * the fail-closed messages so a caller can still tell which call failed. */
142
+ async function buildAuthorisedSmartAccountTx(args, functionName, callArgs, errorPrefix) {
167
143
  const source = await args.rpc.getAccount(args.sourceAccount);
168
144
  const hostFunction = xdr.HostFunction.hostFunctionTypeInvokeContract(new xdr.InvokeContractArgs({
169
145
  contractAddress: new Address(args.smartAccount).toScAddress(),
170
- functionName: 'remove_context_rule',
171
- args: [xdr.ScVal.scvU32(args.ruleId)],
146
+ functionName,
147
+ args: callArgs,
172
148
  }));
173
149
  const makeOperation = (auth = []) => Operation.invokeHostFunction({ func: hostFunction, auth });
174
150
  const baseFee = args.baseFee !== undefined ? String(args.baseFee) : BASE_FEE;
@@ -185,19 +161,14 @@ export async function buildRevokePolicyXdr(args) {
185
161
  // carries host + URL detail) stays in the SDK's own logs - never
186
162
  // reflected back into a user-facing message where it would
187
163
  // reconnoitre the RPC.
188
- throw new Error('revoke_policy: simulateTransaction failed');
164
+ throw new Error(`${errorPrefix}: simulateTransaction failed`);
189
165
  }
190
166
  const original = (recorded.result?.auth ?? []).find((entry) => entry.credentials().switch().name === 'sorobanCredentialsAddress' &&
191
167
  Address.fromScAddress(entry.credentials().address().address()).toString() ===
192
168
  args.smartAccount);
193
169
  if (!original) {
194
- throw new Error(`revoke_policy: no Soroban auth entry for smart account ${args.smartAccount}; this call does not route through the smart account`);
170
+ throw new Error(`${errorPrefix}: no Soroban auth entry for smart account ${args.smartAccount}; this call does not route through the smart account`);
195
171
  }
196
- // Removal is master-only, so the deploy-time admin rule authorises it. The
197
- // recorded rootInvocation still includes remove_context_rule(ruleId), binding
198
- // the auth payload to the exact rule being removed. As with install,
199
- // source-account credentials carry the delegated signer entry and the
200
- // consumer supplies only the ordinary envelope signature.
201
172
  const validUntilLedger = (await args.rpc.getLatestLedger()).sequence +
202
173
  (args.authValidUntilLedgers ?? DEFAULT_AUTH_VALID_UNTIL_LEDGERS);
203
174
  const contextRuleIds = [0];
@@ -209,38 +180,12 @@ export async function buildRevokePolicyXdr(args) {
209
180
  const txWithAuth = buildTx(makeOperation(authEntries));
210
181
  const enforcing = await args.rpc.simulateTransaction(txWithAuth);
211
182
  if (rpc.Api.isSimulationError(enforcing)) {
212
- throw new Error('revoke_policy: auth simulateTransaction failed');
213
- }
214
- const finalTx = rpc.assembleTransaction(txWithAuth, enforcing).build();
215
- return {
216
- unsignedXdr: finalTx.toEnvelope().toXDR().toString('base64'),
217
- smartAccount: args.smartAccount,
218
- sourceAccount: args.sourceAccount,
219
- call: { contract: args.smartAccount, fn: 'remove_context_rule', ruleId: args.ruleId },
220
- authNonce: original.credentials().address().nonce().toString(),
221
- authValidUntilLedger: validUntilLedger,
222
- rootInvocationXdr: original.rootInvocation().toXDR().toString('base64'),
223
- };
224
- }
225
- /** ~25 minutes at 5s/ledger. */
226
- const DEFAULT_AUTH_VALID_UNTIL_LEDGERS = 300;
227
- // ---- internals ----
228
- /** Adapter: turn the install-policy wire `PolicyRef` shape into the core
229
- * `PolicyRef` shape `buildAddContextRuleArgs` expects. Keeps the wire
230
- * schema hand-rolled + flat (the strict union would need a recursive
231
- * schema) while delegating to the proven encoder for the actual bytes. */
232
- function adaptPolicyRef(p) {
233
- if (p.kind === 'interpreter') {
234
- return {
235
- kind: 'interpreter',
236
- interpreterAddress: p.interpreterAddress,
237
- predicateBlobBase64: p.predicateBlobBase64,
238
- };
183
+ throw new Error(`${errorPrefix}: auth simulateTransaction failed`);
239
184
  }
240
185
  return {
241
- kind: 'oz_builtin',
242
- instanceAddress: p.instanceAddress,
243
- primitive: p.primitive,
186
+ finalTx: rpc.assembleTransaction(txWithAuth, enforcing).build(),
187
+ original,
188
+ validUntilLedger,
244
189
  };
245
190
  }
246
191
  /** Build an unsigned Soroban transaction envelope. The `sequence` is
@@ -294,14 +239,13 @@ function decodeInstallCallDescribes(tx, expectedInstallNonce) {
294
239
  if (scvArgs.length !== 5) {
295
240
  throw new Error(`install_policy: built op has ${scvArgs.length} args, expected 5 (context_type, name, valid_until, signers, policies)`);
296
241
  }
297
- const contextType = scvArgs[0];
298
242
  const nameScv = scvArgs[1];
299
243
  const validUntilScv = scvArgs[2];
300
244
  const signersScv = scvArgs[3];
301
245
  const policiesScv = scvArgs[4];
302
246
  // The length check above pins these as defined; the local references
303
247
  // satisfy noUncheckedIndexedAccess on the accessors below.
304
- if (!nameScv || !validUntilScv || !signersScv || !policiesScv || !contextType) {
248
+ if (!nameScv || !validUntilScv || !signersScv || !policiesScv) {
305
249
  throw new Error('install_policy: built op args include an undefined slot despite length check');
306
250
  }
307
251
  // name
@@ -382,7 +326,6 @@ function decodeInstallCallDescribes(tx, expectedInstallNonce) {
382
326
  fields.set(fk.sym().toString(), inner.val());
383
327
  }
384
328
  // Interpreter policy fields carry grammar_version/install_nonce/predicate.
385
- // OZ primitives carry spending_limit/period_ledgers/threshold/signers.
386
329
  if (fields.has('predicate') || fields.has('grammar_version') || fields.has('install_nonce')) {
387
330
  const installNonceScv = fields.get('install_nonce');
388
331
  if (installNonceScv?.switch().name !== 'scvU32') {
@@ -411,21 +354,6 @@ function decodeInstallCallDescribes(tx, expectedInstallNonce) {
411
354
  observedInstallNonce = installNonce;
412
355
  continue;
413
356
  }
414
- // OZ built-in primitive. Distinguish by the parameter shape we
415
- // emitted; matching one of the three primitives exactly pins the
416
- // kind we built.
417
- if (fields.has('spending_limit') && fields.has('period_ledgers')) {
418
- policies.push({ kind: 'oz_builtin', address, primitive: 'spending_limit' });
419
- continue;
420
- }
421
- if (fields.has('threshold') && fields.has('signer_weights')) {
422
- policies.push({ kind: 'oz_builtin', address, primitive: 'weighted_threshold' });
423
- continue;
424
- }
425
- if (fields.has('threshold')) {
426
- policies.push({ kind: 'oz_builtin', address, primitive: 'simple_threshold' });
427
- continue;
428
- }
429
357
  throw new Error(`install_policy: policies[${address}] value has an unknown field set; the encoder may have drifted`);
430
358
  }
431
359
  // `observedInstallNonce` is the nonce baked into whichever interpreter
@@ -454,10 +382,3 @@ function decodeInstallCallDescribes(tx, expectedInstallNonce) {
454
382
  installNonce,
455
383
  };
456
384
  }
457
- /** Re-export so the run-layer does not need to import from
458
- * build-add-context-rule.ts (keeps the install/ -> install/ dependency
459
- * direction intact). */
460
- export { Contract, DEFAULT_GRAMMAR_VERSION };
461
- // Local re-import to avoid pulling the class from the SDK module path
462
- // at the top of the file (avoids the unused-import lint).
463
- import { Account } from '@stellar/stellar-sdk';
@@ -1,3 +1 @@
1
- export { ANY, type AuthorityOverlap, type ContextType, effectiveSelectors, findAuthorityOverlaps, type IntendedInstall, intersectSelectors, type MergeResult, mergeIntoAnd, type ObservedRule, type OverlapSeverity, permittedSelectors, type RuleClass, type Selector, signerKey, } from './authority-overlap.ts';
2
1
  export { ADD_CONTEXT_RULE_SYMBOL, type AddContextRuleArgs, type BuildAddContextRuleArgs, buildAddContextRuleArgs, DEFAULT_GRAMMAR_VERSION, } from './build-add-context-rule.ts';
3
- export { type AccountRuleReader, accountRuleReaderFromServer, type CollectedRules, collectObservedRules, decodeContextRule, decodeContextType, decodeSigner, docLedgerKey, MAX_RULE_ID_SCAN, } from './read-account-rules.ts';
@@ -12,11 +12,4 @@
12
12
  // Exported here rather than from the package root to keep the root surface
13
13
  // about synthesis, and because these are transaction-building primitives whose
14
14
  // callers should know they are reaching for them.
15
- // Cross-rule authority analysis. A caller installing a policy needs to know
16
- // whether its signers can already reach the same calls through another context
17
- // rule, because OZ lets the signer name the rule and enforces only that one's
18
- // policies. Without this, a second, tighter rule reads as a restriction while
19
- // restricting nothing.
20
- export { ANY, effectiveSelectors, findAuthorityOverlaps, intersectSelectors, mergeIntoAnd, permittedSelectors, signerKey, } from "./authority-overlap.js";
21
15
  export { ADD_CONTEXT_RULE_SYMBOL, buildAddContextRuleArgs, DEFAULT_GRAMMAR_VERSION, } from "./build-add-context-rule.js";
22
- export { accountRuleReaderFromServer, collectObservedRules, decodeContextRule, decodeContextType, decodeSigner, docLedgerKey, MAX_RULE_ID_SCAN, } from "./read-account-rules.js";
@@ -1 +1 @@
1
- export type { IRCompare, IRCompOp, IRCondition, IRLogic, IRPolicyRule, IRScalarType, IRSelector, IRVecMode, PolicyIR, } from './types.ts';
1
+ export type { IRCompare, IRCompOp, IRCondition, IRLogic, IRPolicyRule, IRScalarType, IRSelector, PolicyIR, } from './types.ts';