@crediolabs/policy-synth 0.1.3 → 0.1.5
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/LICENSE +21 -0
- package/README.md +193 -5
- package/dist/adapters/interpreter/adapter.d.ts +38 -0
- package/dist/adapters/interpreter/adapter.js +522 -0
- package/dist/adapters/interpreter/index.d.ts +1 -0
- package/dist/adapters/interpreter/index.js +2 -0
- package/dist/adapters/oz/adapter.js +2 -0
- package/dist/codegen/compile-gate.d.ts +33 -0
- package/dist/codegen/compile-gate.js +119 -0
- package/dist/codegen/index.d.ts +2 -0
- package/dist/codegen/index.js +8 -0
- package/dist/codegen/template.d.ts +18 -0
- package/dist/codegen/template.js +131 -0
- package/dist/errors.d.ts +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/ir/types.d.ts +13 -2
- package/dist/predicate/encode.d.ts +10 -0
- package/dist/predicate/encode.js +249 -0
- package/dist/predicate/index.d.ts +1 -0
- package/dist/predicate/index.js +2 -0
- package/dist/record/decode.d.ts +6 -3
- package/dist/record/decode.js +13 -3
- package/dist/review-card/builder.d.ts +14 -0
- package/dist/review-card/builder.js +261 -0
- package/dist/review-card/conflict.d.ts +40 -0
- package/dist/review-card/conflict.js +111 -0
- package/dist/review-card/cross-check.d.ts +11 -0
- package/dist/review-card/cross-check.js +148 -0
- package/dist/review-card/index.d.ts +3 -0
- package/dist/review-card/index.js +4 -0
- package/dist/run/index.d.ts +31 -0
- package/dist/run/index.js +164 -0
- package/dist/run/schemas.d.ts +2003 -0
- package/dist/run/schemas.js +215 -0
- package/dist/synth/compose-from-recording.d.ts +35 -7
- package/dist/synth/compose-from-recording.js +225 -34
- package/dist/synth/deny-cases.d.ts +12 -0
- package/dist/synth/deny-cases.js +377 -0
- package/dist/synth/evaluate.d.ts +39 -0
- package/dist/synth/evaluate.js +425 -0
- package/dist/synth/harness.d.ts +16 -0
- package/dist/synth/harness.js +26 -0
- package/dist/synth/index.d.ts +4 -0
- package/dist/synth/index.js +4 -0
- package/dist/synth/minimize.d.ts +4 -0
- package/dist/synth/minimize.js +38 -0
- package/dist/synth/predicate-literals.d.ts +5 -0
- package/dist/synth/predicate-literals.js +25 -0
- package/dist/synth/synthesize-from-recording.d.ts +37 -5
- package/dist/synth/synthesize-from-recording.js +550 -18
- package/dist/types.d.ts +40 -1
- package/dist/types.js +17 -0
- package/dist/verify/envelope.d.ts +15 -0
- package/dist/verify/envelope.js +22 -0
- package/dist/verify/index.d.ts +3 -0
- package/dist/verify/index.js +3 -0
- package/dist/verify/simulate.d.ts +31 -0
- package/dist/verify/simulate.js +258 -0
- package/dist/verify/verify.d.ts +21 -0
- package/dist/verify/verify.js +189 -0
- package/dist-cjs/adapters/interpreter/adapter.d.ts +38 -0
- package/dist-cjs/adapters/interpreter/adapter.js +527 -0
- package/dist-cjs/adapters/interpreter/index.d.ts +1 -0
- package/dist-cjs/adapters/interpreter/index.js +8 -0
- package/dist-cjs/adapters/oz/adapter.d.ts +20 -0
- package/dist-cjs/adapters/oz/adapter.js +289 -0
- package/dist-cjs/adapters/oz/index.d.ts +1 -0
- package/dist-cjs/adapters/oz/index.js +8 -0
- package/dist-cjs/codegen/compile-gate.d.ts +33 -0
- package/dist-cjs/codegen/compile-gate.js +123 -0
- package/dist-cjs/codegen/index.d.ts +2 -0
- package/dist-cjs/codegen/index.js +14 -0
- package/dist-cjs/codegen/template.d.ts +18 -0
- package/dist-cjs/codegen/template.js +134 -0
- package/dist-cjs/errors.d.ts +37 -0
- package/dist-cjs/errors.js +3 -0
- package/dist-cjs/index.d.ts +11 -0
- package/dist-cjs/index.js +27 -0
- package/dist-cjs/ir/index.d.ts +1 -0
- package/dist-cjs/ir/index.js +3 -0
- package/dist-cjs/ir/types.d.ts +108 -0
- package/dist-cjs/ir/types.js +12 -0
- package/dist-cjs/mandate/index.d.ts +2 -0
- package/dist-cjs/mandate/index.js +6 -0
- package/dist-cjs/mandate/to-ir.d.ts +3 -0
- package/dist-cjs/mandate/to-ir.js +63 -0
- package/dist-cjs/mandate/types.d.ts +20 -0
- package/dist-cjs/mandate/types.js +9 -0
- package/dist-cjs/package.json +3 -0
- package/dist-cjs/predicate/encode.d.ts +10 -0
- package/dist-cjs/predicate/encode.js +252 -0
- package/dist-cjs/predicate/index.d.ts +1 -0
- package/dist-cjs/predicate/index.js +6 -0
- package/dist-cjs/record/decode.d.ts +79 -0
- package/dist-cjs/record/decode.js +398 -0
- package/dist-cjs/record/freshness.d.ts +17 -0
- package/dist-cjs/record/freshness.js +55 -0
- package/dist-cjs/record/index.d.ts +21 -0
- package/dist-cjs/record/index.js +166 -0
- package/dist-cjs/record/movements.d.ts +20 -0
- package/dist-cjs/record/movements.js +192 -0
- package/dist-cjs/record/rpc.d.ts +22 -0
- package/dist-cjs/record/rpc.js +74 -0
- package/dist-cjs/record/validate.d.ts +22 -0
- package/dist-cjs/record/validate.js +63 -0
- package/dist-cjs/registry/identify.d.ts +11 -0
- package/dist-cjs/registry/identify.js +87 -0
- package/dist-cjs/registry/index.d.ts +3 -0
- package/dist-cjs/registry/index.js +15 -0
- package/dist-cjs/registry/known-addresses.d.ts +16 -0
- package/dist-cjs/registry/known-addresses.js +53 -0
- package/dist-cjs/registry/protocols.d.ts +38 -0
- package/dist-cjs/registry/protocols.js +153 -0
- package/dist-cjs/review-card/builder.d.ts +14 -0
- package/dist-cjs/review-card/builder.js +264 -0
- package/dist-cjs/review-card/conflict.d.ts +40 -0
- package/dist-cjs/review-card/conflict.js +114 -0
- package/dist-cjs/review-card/cross-check.d.ts +11 -0
- package/dist-cjs/review-card/cross-check.js +151 -0
- package/dist-cjs/review-card/index.d.ts +3 -0
- package/dist-cjs/review-card/index.js +10 -0
- package/dist-cjs/run/index.d.ts +31 -0
- package/dist-cjs/run/index.js +178 -0
- package/dist-cjs/run/schemas.d.ts +2003 -0
- package/dist-cjs/run/schemas.js +218 -0
- package/dist-cjs/seams/index.d.ts +1 -0
- package/dist-cjs/seams/index.js +3 -0
- package/dist-cjs/seams/types.d.ts +66 -0
- package/dist-cjs/seams/types.js +12 -0
- package/dist-cjs/synth/compose-from-recording.d.ts +64 -0
- package/dist-cjs/synth/compose-from-recording.js +356 -0
- package/dist-cjs/synth/deny-cases.d.ts +12 -0
- package/dist-cjs/synth/deny-cases.js +380 -0
- package/dist-cjs/synth/evaluate.d.ts +39 -0
- package/dist-cjs/synth/evaluate.js +428 -0
- package/dist-cjs/synth/harness.d.ts +16 -0
- package/dist-cjs/synth/harness.js +29 -0
- package/dist-cjs/synth/index.d.ts +9 -0
- package/dist-cjs/synth/index.js +23 -0
- package/dist-cjs/synth/lower.d.ts +23 -0
- package/dist-cjs/synth/lower.js +119 -0
- package/dist-cjs/synth/minimize.d.ts +4 -0
- package/dist-cjs/synth/minimize.js +41 -0
- package/dist-cjs/synth/predicate-literals.d.ts +5 -0
- package/dist-cjs/synth/predicate-literals.js +28 -0
- package/dist-cjs/synth/scope.d.ts +26 -0
- package/dist-cjs/synth/scope.js +81 -0
- package/dist-cjs/synth/synthesize-from-mandate.d.ts +5 -0
- package/dist-cjs/synth/synthesize-from-mandate.js +37 -0
- package/dist-cjs/synth/synthesize-from-recording.d.ts +49 -0
- package/dist-cjs/synth/synthesize-from-recording.js +711 -0
- package/dist-cjs/types.d.ts +288 -0
- package/dist-cjs/types.js +55 -0
- package/dist-cjs/verify/envelope.d.ts +15 -0
- package/dist-cjs/verify/envelope.js +23 -0
- package/dist-cjs/verify/index.d.ts +3 -0
- package/dist-cjs/verify/index.js +8 -0
- package/dist-cjs/verify/simulate.d.ts +31 -0
- package/dist-cjs/verify/simulate.js +261 -0
- package/dist-cjs/verify/verify.d.ts +21 -0
- package/dist-cjs/verify/verify.js +192 -0
- package/package.json +43 -3
- package/src/adapters/interpreter/adapter.ts +642 -0
- package/src/adapters/interpreter/index.ts +8 -0
- package/src/adapters/oz/adapter.ts +2 -0
- package/src/codegen/compile-gate.ts +162 -0
- package/src/codegen/index.ts +17 -0
- package/src/codegen/template.ts +148 -0
- package/src/errors.ts +2 -0
- package/src/index.ts +2 -0
- package/src/ir/types.ts +9 -2
- package/src/predicate/encode.ts +307 -0
- package/src/predicate/index.ts +3 -0
- package/src/record/decode.ts +21 -10
- package/src/review-card/builder.ts +303 -0
- package/src/review-card/conflict.ts +143 -0
- package/src/review-card/cross-check.ts +158 -0
- package/src/review-card/index.ts +12 -0
- package/src/run/index.ts +213 -0
- package/src/run/schemas.ts +242 -0
- package/src/synth/compose-from-recording.ts +277 -43
- package/src/synth/deny-cases.ts +466 -0
- package/src/synth/evaluate.ts +493 -0
- package/src/synth/harness.ts +40 -0
- package/src/synth/index.ts +12 -0
- package/src/synth/minimize.ts +44 -0
- package/src/synth/predicate-literals.ts +27 -0
- package/src/synth/synthesize-from-recording.ts +655 -19
- package/src/types.ts +38 -2
- package/src/verify/envelope.ts +28 -0
- package/src/verify/index.ts +5 -0
- package/src/verify/simulate.ts +311 -0
- package/src/verify/verify.ts +243 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Untangled Finance Limited
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -4,8 +4,13 @@ Off-chain TypeScript synthesis core for the OpenZeppelin Accounts Policy Builder
|
|
|
4
4
|
|
|
5
5
|
It records a Soroban transaction (from an on-chain hash or a raw envelope XDR),
|
|
6
6
|
synthesises the **minimal** policy that permits exactly that flow, and compiles it
|
|
7
|
-
through the OZ Accounts adapter into a proposed policy.
|
|
8
|
-
|
|
7
|
+
through the OZ Accounts adapter into a proposed policy. When the policy needs
|
|
8
|
+
constraint shapes OZ built-ins cannot express (exact ordered swap paths, oracle
|
|
9
|
+
price bounds, per-method scoping, recipient allowlists), the **interpreter
|
|
10
|
+
adapter** is opted in to emit a parallel predicate-shaped `PolicyDocument` that
|
|
11
|
+
installs alongside the OZ primitives. The synthesis is self-verified end-to-end
|
|
12
|
+
via `simulatePolicy` / `verifyPolicy` and the runner of the deny-case harness
|
|
13
|
+
before any bytes are emitted.
|
|
9
14
|
|
|
10
15
|
The package is pure ESM, node-compatible, and has a single runtime dependency
|
|
11
16
|
(`@stellar/stellar-sdk`). MIT-licensed.
|
|
@@ -73,11 +78,194 @@ events cross-check and lowers `parseConfidence`. It therefore **fails closed** a
|
|
|
73
78
|
the default threshold; to accept a simulation-only recording, pass an explicit
|
|
74
79
|
`confidenceOverride` that clears the gate.
|
|
75
80
|
|
|
81
|
+
## Interpreter predicate emission (the `interpreter` opt-in)
|
|
82
|
+
|
|
83
|
+
OZ built-ins express spending limits, simple thresholds, and weighted
|
|
84
|
+
thresholds. They **cannot** express an exact ordered swap path, an oracle
|
|
85
|
+
price bound, per-method scoping, a recipient allowlist, or an
|
|
86
|
+
invocation-count window. The recording path surfaces those gaps as warnings
|
|
87
|
+
by default ("Not covered by OZ built-in primitives: ..."). When the caller
|
|
88
|
+
opts in to the **interpreter adapter**, the same constraint set is routed to
|
|
89
|
+
the parallel interpreter IR; the adapter compiles it into a canonical
|
|
90
|
+
predicate `PolicyDocument` and merges it with the OZ refs. The byte blob on
|
|
91
|
+
the wire is the canonical XDR the on-chain interpreter will consume.
|
|
92
|
+
|
|
93
|
+
The opt-in is purely additive — every `ToolResponse` shape is unchanged; the
|
|
94
|
+
two new fields are `policyDocuments` (the predicate-shaped interpreter doc)
|
|
95
|
+
and one `policyRef` of `kind: 'interpreter'`.
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
import { Address } from '@stellar/stellar-sdk'
|
|
99
|
+
import {
|
|
100
|
+
synthesizeFromRecording,
|
|
101
|
+
placeholderOzConfig,
|
|
102
|
+
} from '@crediolabs/policy-synth'
|
|
103
|
+
|
|
104
|
+
const oz = placeholderOzConfig('mainnet')
|
|
105
|
+
const smartAccount = Address.contract(Buffer.alloc(32, 0xee)).toString()
|
|
106
|
+
|
|
107
|
+
const result = synthesizeFromRecording(
|
|
108
|
+
recordedTx,
|
|
109
|
+
{
|
|
110
|
+
network: 'mainnet',
|
|
111
|
+
userResponses: {
|
|
112
|
+
windowSeconds: 2592000, // 30 days
|
|
113
|
+
limitAmount: '1000000000', // supplied cap
|
|
114
|
+
validUntilLedger: 200000000, // future ledger
|
|
115
|
+
oraclePriceBound: [ // optional oracle bound
|
|
116
|
+
{ asset: 'CEURC', operator: 'lt', value: '1000000000' },
|
|
117
|
+
],
|
|
118
|
+
swapRecipientAllowlist: ['GOWNER'], // optional allowlist
|
|
119
|
+
},
|
|
120
|
+
interpreter: {
|
|
121
|
+
smartAccountAddress: smartAccount, // MUST be a C... contract address
|
|
122
|
+
installNonce: 1, // first install -> 1
|
|
123
|
+
// oracleParams: { maxStalenessSeconds: 60, maxDeviationBps: 100 }
|
|
124
|
+
// (tighten-only vs the wasm defaults; widening is rejected)
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
oz
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
if (result.ok) {
|
|
131
|
+
console.log(result.data.policyDocuments.length) // >= 1 when constraints are routable
|
|
132
|
+
const interpreterRef = result.data.policyRefs.find((r) => r.kind === 'interpreter')
|
|
133
|
+
console.log(interpreterRef?.predicateBlobBase64) // canonical XDR, base64
|
|
134
|
+
console.log(result.data.contextRule.validUntilLedger)
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The interpreter compile path is **fail-closed**:
|
|
139
|
+
|
|
140
|
+
- `SCOPE_SELF_CALL` — the call's recipient equals the smart account.
|
|
141
|
+
- `ORACLE_LEAF_INVALID_POSITION` — an oracle leaf is wrongly nested.
|
|
142
|
+
- `ORACLE_PARAMS_OUT_OF_RANGE` — `oracleParams` widening vs the wasm defaults.
|
|
143
|
+
- `SYNTHESIS_ERROR` — the interpreter IR is not fully covered.
|
|
144
|
+
- `DENY_CASE_FAILURE` — the emitted predicate fails the deny-case battery;
|
|
145
|
+
`details.failures` lists the flipped dimension(s).
|
|
146
|
+
|
|
147
|
+
A recorded swap that compiles to a permissive policy under OZ alone therefore
|
|
148
|
+
stays permissive unless the interpreter opt-in is supplied AND the predicate
|
|
149
|
+
self-verifies end-to-end.
|
|
150
|
+
|
|
151
|
+
### Self-verify + minimise (always-on with the opt-in)
|
|
152
|
+
|
|
153
|
+
Opting in to the interpreter also turns on the **self-verify pipeline**:
|
|
154
|
+
|
|
155
|
+
1. The adapter emits the candidate predicate.
|
|
156
|
+
2. The synth builds a permit `EvalContext` from the recorded transaction (the
|
|
157
|
+
only call the user actually performed).
|
|
158
|
+
3. The candidate is **minimised** — load-bearing-free top-level conjuncts are
|
|
159
|
+
dropped (`and` predicates only; other shapes are returned unchanged).
|
|
160
|
+
4. The minimised predicate is run through the deny-case battery — a structural
|
|
161
|
+
fingerprint across `contract`, `function`, `args`, `amount`, `window`,
|
|
162
|
+
`oracle`, `recipient`, `frequency`. Each case must deny.
|
|
163
|
+
5. The intended recorded call is evaluated against the predicate; it must
|
|
164
|
+
permit.
|
|
165
|
+
6. The (possibly minimised) predicate is re-encoded; the canonical bytes + the
|
|
166
|
+
SHA-256 hash are stamped back onto the `PolicyDocument` and the
|
|
167
|
+
`interpreter` `policyRef`.
|
|
168
|
+
|
|
169
|
+
A successful `ok: true` is the proof that the emitted document is minimal AND
|
|
170
|
+
self-verified. A failure surfaces the matching gate code (see above).
|
|
171
|
+
|
|
172
|
+
## Simulate and verify (the `verify/` surface)
|
|
173
|
+
|
|
174
|
+
The same self-verify pipeline is exposed as a public API for callers that want
|
|
175
|
+
to re-run a check on a proposed predicate without re-synthesising:
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
import { simulatePolicy, verifyPolicy } from '@crediolabs/policy-synth'
|
|
179
|
+
|
|
180
|
+
// Runtime check: re-evaluate the predicate against the recorded call.
|
|
181
|
+
const runtime = simulatePolicy(predicate, recordedTx, {
|
|
182
|
+
validUntilLedger: 200000000,
|
|
183
|
+
oraclePricesByAsset: { CEURC: { price: '999999999', timestampSeconds: now } },
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
// Static minimality check: prove no top-level conjunct is load-bearing-free.
|
|
187
|
+
const staticCheck = verifyPolicy(predicate, recordedTx)
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
The boundary is pinned:
|
|
191
|
+
|
|
192
|
+
- `SIMULATION_ERROR` — runtime evaluation failed (malformed fixture, missing
|
|
193
|
+
oracle price, uncontrolled throw). The policy may still be minimal.
|
|
194
|
+
- `VERIFICATION_FAILED` — the static minimality check failed. The policy is
|
|
195
|
+
structurally over-broad regardless of how any concrete call evaluates.
|
|
196
|
+
|
|
197
|
+
Both are deterministic: same `(predicate, recordedTx, opts)` → byte-identical
|
|
198
|
+
envelope.
|
|
199
|
+
|
|
200
|
+
## Review-card (the human-audit surface)
|
|
201
|
+
|
|
202
|
+
The package emits a deterministic review-card summary so a human auditor can
|
|
203
|
+
sanity-check the inferred policy without re-running the synthesis:
|
|
204
|
+
|
|
205
|
+
```ts
|
|
206
|
+
import {
|
|
207
|
+
buildReviewCardSummary,
|
|
208
|
+
classifyConflict,
|
|
209
|
+
summaryCrossCheck,
|
|
210
|
+
} from '@crediolabs/policy-synth'
|
|
211
|
+
|
|
212
|
+
const summary = buildReviewCardSummary(proposedPolicy, recordedTx)
|
|
213
|
+
const conflict = classifyConflict(proposedPolicy, recordedTx)
|
|
214
|
+
const crossCheck = summaryCrossCheck(proposedPolicy, recordedTx)
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
The summary is the canonical human-readable digest of the proposed policy;
|
|
218
|
+
`classifyConflict` flags refs that contradict the recording; `summaryCrossCheck`
|
|
219
|
+
re-derives the summary from the raw refs and the recording, and reports
|
|
220
|
+
discrepancies. All three are pure and deterministic.
|
|
221
|
+
|
|
222
|
+
## Codegen escape hatch (the Rust interpreter)
|
|
223
|
+
|
|
224
|
+
When the canonical verifier is unavailable, the recorder can emit a Rust
|
|
225
|
+
source file that performs the same predicate evaluation off-chain via a
|
|
226
|
+
`cargo` build. The escape hatch is OUT of the audited happy path: the
|
|
227
|
+
synthesiser never calls `generateRust` itself; the CLI subcommand is the only
|
|
228
|
+
entry point.
|
|
229
|
+
|
|
230
|
+
```ts
|
|
231
|
+
import { generateRust, compileCheck, hasRustToolchain } from '@crediolabs/policy-synth'
|
|
232
|
+
|
|
233
|
+
if (await hasRustToolchain()) {
|
|
234
|
+
const { source, path } = generateRust(predicate, { out: 'policy.rs' })
|
|
235
|
+
const gate = await compileCheck({ crateDir: '.', predicate })
|
|
236
|
+
if (!gate.ok) console.error('compile gate failed:', gate.error)
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
The escape hatch is toolchain-gated: `hasRustToolchain()` returns `false`
|
|
241
|
+
when `cargo` is not installed, and `compileCheck()` refuses to run on a
|
|
242
|
+
machine without one. The generated source is **not** the on-chain interpreter
|
|
243
|
+
— it is a deterministic off-chain reference that re-evaluates the same
|
|
244
|
+
predicate for parity testing.
|
|
245
|
+
|
|
246
|
+
## Composition rules
|
|
247
|
+
|
|
248
|
+
The merged `policyRefs` on a `ProposedPolicy` are ordered
|
|
249
|
+
`[interpreterRef?, ...oz_builtinRefs]` and bounded by
|
|
250
|
+
`OZ_LIMITS.maxPoliciesPerRule` (5). The orchestrator refuses to install a
|
|
251
|
+
policy that exceeds this cap (`POLICY_CAP_EXCEEDED`). The OZ-side `uncovered`
|
|
252
|
+
warnings that the interpreter actually lowered (per-method scoping, recipient
|
|
253
|
+
allowlists, exact ordered sequences, oracle price bounds, invocation-count
|
|
254
|
+
windows, token-mismatch spending limits) are dropped from the user-facing
|
|
255
|
+
warnings when the interpreter succeeds — the warning list reflects what is
|
|
256
|
+
still UN-enforced, not what OZ alone could not do.
|
|
257
|
+
|
|
76
258
|
## Status
|
|
77
259
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
260
|
+
Implemented and unit-test covered: the recorder, both synthesizer
|
|
261
|
+
front-ends, the OZ Accounts adapter, the interpreter adapter, the
|
|
262
|
+
predicate encoder, the evaluator, the deny-case battery, the minimiser, the
|
|
263
|
+
self-verify pipeline, the simulate / verify surface, the review-card
|
|
264
|
+
builder, the cross-check, and the Rust codegen escape hatch.
|
|
265
|
+
|
|
266
|
+
The on-chain Rust interpreter, install-transaction assembly, and live RPC
|
|
267
|
+
integration are wired in the @crediolabs/policy-builder-cli layer (separate
|
|
268
|
+
package).
|
|
81
269
|
|
|
82
270
|
## License
|
|
83
271
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { IRPolicyRule } from '../../ir/types.ts';
|
|
2
|
+
import type { CustodyAdapter } from '../../seams/types.ts';
|
|
3
|
+
import type { Network, PredicateNode } from '../../types.ts';
|
|
4
|
+
/** [VERIFY] NOT a real deployed address. The interpreter is a per-network
|
|
5
|
+
* deploy artifact we do not have yet; install is a later phase. */
|
|
6
|
+
export declare const PLACEHOLDER_INTERPRETER_ADDRESS = "VERIFY-interpreter-address";
|
|
7
|
+
/** Wasm-level oracle defaults (mirrors INTERPRETER_INSTALL_PARAMS.md OracleParams).
|
|
8
|
+
* Per-policy overrides may TIGHTEN only - they may never exceed these. */
|
|
9
|
+
export declare const ORACLE_DEFAULTS: {
|
|
10
|
+
readonly maxStalenessSeconds: 600;
|
|
11
|
+
readonly maxDeviationBps: 200;
|
|
12
|
+
};
|
|
13
|
+
export interface InterpreterAdapterConfig {
|
|
14
|
+
network: Network;
|
|
15
|
+
/** Per-rule install nonce (first install = 1; replay-protected). */
|
|
16
|
+
installNonce: number;
|
|
17
|
+
/** The smart account this interpreter policy will be installed against. Used
|
|
18
|
+
* by the self-call gate: any `in`-allowlist containing this address is
|
|
19
|
+
* rejected as `SCOPE_SELF_CALL`. */
|
|
20
|
+
smartAccountAddress: string;
|
|
21
|
+
/** Optional per-policy oracle overrides. Must TIGHTEN vs ORACLE_DEFAULTS
|
|
22
|
+
* (i.e. <= each default). A widening value throws ORACLE_PARAMS_OUT_OF_RANGE
|
|
23
|
+
* at compile time. */
|
|
24
|
+
oracleParams?: {
|
|
25
|
+
maxStalenessSeconds?: number;
|
|
26
|
+
maxDeviationBps?: number;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export declare function createInterpreterAdapter(config: InterpreterAdapterConfig): CustodyAdapter;
|
|
30
|
+
/** Lower a single IR rule to the canonical pre-encoding `PredicateNode`. The
|
|
31
|
+
* orchestrator uses this to wire the self-verify + minimise pipeline: after
|
|
32
|
+
* `compile(ir)` succeeds (`covered === true`, `proposed` set), the
|
|
33
|
+
* orchestrator re-derives the PredicateNode via this helper to drive
|
|
34
|
+
* `minimize` and `runHarness` on the SAME shape the encoder saw. Pure and
|
|
35
|
+
* deterministic: same `rule + config` -> byte-identical PredicateNode. The
|
|
36
|
+
* `uncovered` list the adapter surfaces during compile is NOT re-derived
|
|
37
|
+
* here; callers that need it should use the result of `compile(ir)`. */
|
|
38
|
+
export declare function lowerRuleToPredicate(rule: IRPolicyRule, config: InterpreterAdapterConfig): PredicateNode;
|