otto-intel-mcp 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -18
- package/dist/account-userop-policy-definition.d.ts +14 -0
- package/dist/account-userop-policy-definition.js +12 -0
- package/dist/account-userop-policy-relation.d.ts +371 -0
- package/dist/account-userop-policy-relation.js +87 -0
- package/dist/adapter/cdp-signer.d.ts +76 -9
- package/dist/adapter/cdp-signer.js +274 -33
- package/dist/adapter/evm-call-failure.d.ts +29 -0
- package/dist/adapter/evm-call-failure.js +109 -0
- package/dist/adapter/refusal.d.ts +1 -1
- package/dist/adapter/refusal.js +13 -0
- package/dist/adapter/route-simulator.d.ts +91 -0
- package/dist/adapter/route-simulator.js +143 -0
- package/dist/adapter-cdp-index.d.ts +1 -1
- package/dist/executable-equities.d.ts +55 -0
- package/dist/executable-equities.js +116 -0
- package/dist/executable-yield-markets.d.ts +261 -0
- package/dist/executable-yield-markets.js +154 -0
- package/dist/execution-account-gas-quote.d.ts +141 -0
- package/dist/execution-account-gas-quote.js +443 -0
- package/dist/execution-account-gas-review.d.ts +123 -0
- package/dist/execution-account-gas-review.js +104 -0
- package/dist/execution-account-gas-runtime.d.ts +33 -0
- package/dist/execution-account-gas-runtime.js +131 -0
- package/dist/execution-account-gas-view.d.ts +936 -0
- package/dist/execution-account-gas-view.js +56 -0
- package/dist/execution-config.d.ts +3 -0
- package/dist/execution-config.js +4 -0
- package/dist/execution-delegated-definition.d.ts +7 -6
- package/dist/execution-delegated-definition.js +13 -2
- package/dist/execution-delegation-admin-definition.d.ts +127 -5
- package/dist/execution-delegation-admin-definition.js +155 -5
- package/dist/execution-delegation-admin.d.ts +48 -2
- package/dist/execution-delegation-admin.js +422 -12
- package/dist/execution-delegation-cap-store.d.ts +386 -0
- package/dist/execution-delegation-cap-store.js +1150 -0
- package/dist/execution-delegation-exit-definition.d.ts +309 -0
- package/dist/execution-delegation-exit-definition.js +204 -0
- package/dist/execution-delegation-exit-store.d.ts +114 -0
- package/dist/execution-delegation-exit-store.js +671 -0
- package/dist/execution-delegation-exit.d.ts +4 -0
- package/dist/execution-delegation-exit.js +614 -0
- package/dist/execution-delegation-finality.d.ts +22 -0
- package/dist/execution-delegation-finality.js +90 -0
- package/dist/execution-delegation-operation-store.d.ts +129 -0
- package/dist/execution-delegation-operation-store.js +1107 -0
- package/dist/execution-delegation-operations-definition.d.ts +282 -0
- package/dist/execution-delegation-operations-definition.js +117 -0
- package/dist/execution-delegation-operations.d.ts +6 -0
- package/dist/execution-delegation-operations.js +282 -0
- package/dist/execution-delegation-policy.d.ts +154 -8
- package/dist/execution-delegation-policy.js +273 -40
- package/dist/execution-delegation.d.ts +51 -0
- package/dist/execution-delegation.js +441 -31
- package/dist/execution-errors.d.ts +1 -1
- package/dist/execution-errors.js +122 -0
- package/dist/execution-index.d.ts +7 -2
- package/dist/execution-index.js +7 -2
- package/dist/execution-journal-schema.d.ts +96 -0
- package/dist/execution-journal-schema.js +368 -0
- package/dist/execution-journal-tables.d.ts +14 -0
- package/dist/execution-journal-tables.js +227 -0
- package/dist/execution-policy-compatibility.d.ts +34 -0
- package/dist/execution-policy-compatibility.js +76 -0
- package/dist/execution-registration.d.ts +54 -2
- package/dist/execution-registration.js +151 -5
- package/dist/execution-sponsored-account-profile.d.ts +32 -0
- package/dist/execution-sponsored-account-profile.js +59 -0
- package/dist/execution-sponsored-account.d.ts +1519 -0
- package/dist/execution-sponsored-account.js +222 -0
- package/dist/execution-sponsored-definition.d.ts +1713 -0
- package/dist/execution-sponsored-definition.js +185 -0
- package/dist/execution-sponsored-gas-policy.d.ts +27 -0
- package/dist/execution-sponsored-gas-policy.js +110 -0
- package/dist/execution-sponsored-hosted.d.ts +3 -0
- package/dist/execution-sponsored-hosted.js +71 -0
- package/dist/execution-sponsored-index.d.ts +1322 -0
- package/dist/execution-sponsored-index.js +102 -0
- package/dist/execution-sponsored-mcp-definition.d.ts +1662 -0
- package/dist/execution-sponsored-mcp-definition.js +94 -0
- package/dist/execution-sponsored-receipt.d.ts +47 -0
- package/dist/execution-sponsored-receipt.js +74 -0
- package/dist/execution-sponsored-registration.d.ts +14 -0
- package/dist/execution-sponsored-registration.js +77 -0
- package/dist/execution-sponsored-runtime.d.ts +84 -0
- package/dist/execution-sponsored-runtime.js +149 -0
- package/dist/execution-sponsored-settlement.d.ts +15 -0
- package/dist/execution-sponsored-settlement.js +88 -0
- package/dist/execution-sponsored-store.d.ts +67 -0
- package/dist/execution-sponsored-store.js +517 -0
- package/dist/execution-sponsored-transport.d.ts +90 -0
- package/dist/execution-sponsored-transport.js +180 -0
- package/dist/execution-tool-definitions.d.ts +21 -21
- package/dist/execution-tool-definitions.js +0 -7
- package/dist/execution-tools.d.ts +53 -1
- package/dist/execution-tools.js +171 -13
- package/dist/execution-worker-guard.d.ts +28 -0
- package/dist/execution-worker-guard.js +124 -0
- package/dist/hybrid-yield-index.d.ts +10 -0
- package/dist/hybrid-yield-index.js +11 -0
- package/dist/hybrid-yield-markets.d.ts +96 -0
- package/dist/hybrid-yield-markets.js +124 -0
- package/dist/hybrid-yield.d.ts +411 -0
- package/dist/hybrid-yield.js +155 -0
- package/dist/hyperliquid-order-builder.js +4 -0
- package/dist/lifi-execution-client.d.ts +6 -0
- package/dist/lifi-execution-client.js +3 -0
- package/dist/lp-userop-account.d.ts +461 -0
- package/dist/lp-userop-account.js +417 -0
- package/dist/lp-userop-authority.d.ts +49 -0
- package/dist/lp-userop-authority.js +211 -0
- package/dist/lp-userop-definition.d.ts +233 -0
- package/dist/lp-userop-definition.js +85 -0
- package/dist/lp-userop-hosted.d.ts +3 -0
- package/dist/lp-userop-hosted.js +73 -0
- package/dist/lp-userop-index.d.ts +1569 -0
- package/dist/lp-userop-index.js +112 -0
- package/dist/lp-userop-mcp-definition.d.ts +1220 -0
- package/dist/lp-userop-mcp-definition.js +46 -0
- package/dist/lp-userop-operation.d.ts +1230 -0
- package/dist/lp-userop-operation.js +140 -0
- package/dist/lp-userop-registration.d.ts +14 -0
- package/dist/lp-userop-registration.js +70 -0
- package/dist/lp-userop-settlement.d.ts +89 -0
- package/dist/lp-userop-settlement.js +184 -0
- package/dist/lp-userop.d.ts +643 -0
- package/dist/lp-userop.js +343 -0
- package/dist/native-yield-account-definition.d.ts +1192 -0
- package/dist/native-yield-account-definition.js +232 -0
- package/dist/native-yield-account-gas.d.ts +58 -0
- package/dist/native-yield-account-gas.js +228 -0
- package/dist/native-yield-account-index.d.ts +23 -0
- package/dist/native-yield-account-index.js +28 -0
- package/dist/native-yield-account-policy.d.ts +168 -0
- package/dist/native-yield-account-policy.js +525 -0
- package/dist/native-yield-account-rpc.d.ts +8 -0
- package/dist/native-yield-account-rpc.js +128 -0
- package/dist/native-yield-account-runtime.d.ts +71 -0
- package/dist/native-yield-account-runtime.js +125 -0
- package/dist/native-yield-account-store.d.ts +40 -0
- package/dist/native-yield-account-store.js +307 -0
- package/dist/native-yield-account.d.ts +662 -0
- package/dist/native-yield-account.js +371 -0
- package/dist/native-yield-consent-store.d.ts +20 -0
- package/dist/native-yield-consent-store.js +317 -0
- package/dist/native-yield-definition.d.ts +288 -0
- package/dist/native-yield-definition.js +105 -0
- package/dist/native-yield-reader.d.ts +4 -0
- package/dist/native-yield-reader.js +137 -0
- package/dist/native-yield-settlement.d.ts +48 -0
- package/dist/native-yield-settlement.js +167 -0
- package/dist/native-yield-simulation.d.ts +18 -0
- package/dist/native-yield-simulation.js +45 -0
- package/dist/native-yield-userop-account.d.ts +675 -0
- package/dist/native-yield-userop-account.js +357 -0
- package/dist/native-yield-userop-authority.d.ts +214 -0
- package/dist/native-yield-userop-authority.js +296 -0
- package/dist/native-yield-userop-definition.d.ts +331 -0
- package/dist/native-yield-userop-definition.js +105 -0
- package/dist/native-yield-userop-hosted.d.ts +3 -0
- package/dist/native-yield-userop-hosted.js +71 -0
- package/dist/native-yield-userop-index.d.ts +1522 -0
- package/dist/native-yield-userop-index.js +142 -0
- package/dist/native-yield-userop-mcp-definition.d.ts +1356 -0
- package/dist/native-yield-userop-mcp-definition.js +50 -0
- package/dist/native-yield-userop-operation.d.ts +845 -0
- package/dist/native-yield-userop-operation.js +127 -0
- package/dist/native-yield-userop-policy.d.ts +23 -0
- package/dist/native-yield-userop-policy.js +25 -0
- package/dist/native-yield-userop-registration.d.ts +17 -0
- package/dist/native-yield-userop-registration.js +76 -0
- package/dist/native-yield-userop-settlement.d.ts +8 -0
- package/dist/native-yield-userop-settlement.js +79 -0
- package/dist/native-yield-userop-simulation.d.ts +18 -0
- package/dist/native-yield-userop-simulation.js +34 -0
- package/dist/native-yield-userop.d.ts +35 -0
- package/dist/native-yield-userop.js +156 -0
- package/dist/native-yield-verify.d.ts +30 -0
- package/dist/native-yield-verify.js +141 -0
- package/dist/native-yield.d.ts +17 -0
- package/dist/native-yield.js +119 -0
- package/dist/stdio-main.js +0 -0
- package/dist/stock-buy-definition.d.ts +338 -0
- package/dist/stock-buy-definition.js +127 -0
- package/dist/stock-buy-oracle.d.ts +8 -0
- package/dist/stock-buy-oracle.js +22 -0
- package/dist/stock-buy.d.ts +17 -0
- package/dist/stock-buy.js +164 -0
- package/dist/tool-definitions.d.ts +3 -1
- package/dist/tool-definitions.js +55 -2
- package/dist/vendor/lp-v3/lp-v3-atomic-contract.d.ts +445 -0
- package/dist/vendor/lp-v3/lp-v3-atomic-contract.js +90 -0
- package/dist/vendor/lp-v3/lp-v3-atomic-evidence.d.ts +14 -0
- package/dist/vendor/lp-v3/lp-v3-atomic-evidence.js +82 -0
- package/dist/vendor/lp-v3/lp-v3-atomic-index.d.ts +80 -0
- package/dist/vendor/lp-v3/lp-v3-atomic-index.js +19 -0
- package/dist/vendor/lp-v3/lp-v3-atomic-plan.d.ts +43 -0
- package/dist/vendor/lp-v3/lp-v3-atomic-plan.js +112 -0
- package/dist/vendor/lp-v3/lp-v3-atomic-read-contract.d.ts +312 -0
- package/dist/vendor/lp-v3/lp-v3-atomic-read-contract.js +41 -0
- package/dist/vendor/lp-v3/lp-v3-atomic-read-index.d.ts +3 -0
- package/dist/vendor/lp-v3/lp-v3-atomic-read-index.js +3 -0
- package/dist/vendor/lp-v3/lp-v3-atomic-read-rpc.d.ts +49 -0
- package/dist/vendor/lp-v3/lp-v3-atomic-read-rpc.js +88 -0
- package/dist/vendor/lp-v3/lp-v3-atomic-read.d.ts +17 -0
- package/dist/vendor/lp-v3/lp-v3-atomic-read.js +232 -0
- package/dist/vendor/lp-v3/lp-v3-atomic-settlement.d.ts +105 -0
- package/dist/vendor/lp-v3/lp-v3-atomic-settlement.js +162 -0
- package/dist/vendor/lp-v3/lp-v3-collect-protocol-contract.d.ts +606 -0
- package/dist/vendor/lp-v3/lp-v3-collect-protocol-contract.js +59 -0
- package/dist/vendor/lp-v3/lp-v3-collect-protocol-index.d.ts +168 -0
- package/dist/vendor/lp-v3/lp-v3-collect-protocol-index.js +23 -0
- package/dist/vendor/lp-v3/lp-v3-collect-protocol-observation.d.ts +32 -0
- package/dist/vendor/lp-v3/lp-v3-collect-protocol-observation.js +228 -0
- package/dist/vendor/lp-v3/lp-v3-collect-protocol-plan.d.ts +11 -0
- package/dist/vendor/lp-v3/lp-v3-collect-protocol-plan.js +91 -0
- package/dist/vendor/lp-v3/lp-v3-collect-protocol-reconcile.d.ts +9 -0
- package/dist/vendor/lp-v3/lp-v3-collect-protocol-reconcile.js +124 -0
- package/dist/vendor/lp-v3/lp-v3-contract.d.ts +538 -0
- package/dist/vendor/lp-v3/lp-v3-contract.js +137 -0
- package/dist/vendor/lp-v3/lp-v3-evidence.d.ts +25 -0
- package/dist/vendor/lp-v3/lp-v3-evidence.js +168 -0
- package/dist/vendor/lp-v3/lp-v3-plan.d.ts +22 -0
- package/dist/vendor/lp-v3/lp-v3-plan.js +135 -0
- package/dist/vendor/lp-v3/types.d.ts +131 -0
- package/dist/vendor/lp-v3/types.js +6 -0
- package/dist/vendor/lp-v3/v4-math.d.ts +18 -0
- package/dist/vendor/lp-v3/v4-math.js +90 -0
- package/dist/yield-deposit-definition.d.ts +374 -0
- package/dist/yield-deposit-definition.js +123 -0
- package/dist/yield-deposit.d.ts +16 -0
- package/dist/yield-deposit.js +149 -0
- package/dist/yield-route-semantics.d.ts +27 -0
- package/dist/yield-route-semantics.js +71 -0
- package/dist/yield-withdraw-definition.d.ts +357 -0
- package/dist/yield-withdraw-definition.js +90 -0
- package/dist/yield-withdraw.d.ts +11 -0
- package/dist/yield-withdraw.js +122 -0
- package/package.json +239 -7
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/** Public fee terms keep the user's estimate separate from Otto's sponsorship budgets. */
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { ACCOUNT_GAS_REVIEW_SCHEMA } from './execution-account-gas-review.js';
|
|
4
|
+
export const ACCOUNT_GAS_FAILURE_CODES = [
|
|
5
|
+
'ACCOUNT_GAS_REVIEW_REQUIRED', 'ACCOUNT_GAS_REVIEW_CHANGED', 'ACCOUNT_GAS_REVIEW_STALE',
|
|
6
|
+
'ACCOUNT_GAS_REVIEW_UNAVAILABLE', 'ACCOUNT_GAS_REVIEW_INVALID', 'ACCOUNT_GAS_FUNDING_REQUIRED',
|
|
7
|
+
'ACCOUNT_GAS_SPONSOR_INELIGIBLE', 'ACCOUNT_GAS_QUOTE_UNAVAILABLE',
|
|
8
|
+
];
|
|
9
|
+
export const ACCOUNT_GAS_FAILURE_SCHEMA = z.enum(ACCOUNT_GAS_FAILURE_CODES);
|
|
10
|
+
/** Closed codes only; provider payloads and URLs are never exposed. */
|
|
11
|
+
export function accountGasFailure(error) {
|
|
12
|
+
if (!(error instanceof Error))
|
|
13
|
+
return undefined;
|
|
14
|
+
const code = 'code' in error ? error.code : error.message;
|
|
15
|
+
if (['SPONSOR_GAS_POLICY_UNAVAILABLE', 'SPONSOR_GAS_POLICY_INVALID', 'SPONSOR_GAS_POLICY_INACTIVE', 'SPONSOR_GAS_POLICY_STALE'].includes(String(code)))
|
|
16
|
+
return 'ACCOUNT_GAS_REVIEW_UNAVAILABLE';
|
|
17
|
+
const parsed = ACCOUNT_GAS_FAILURE_SCHEMA.safeParse(code);
|
|
18
|
+
return parsed.success ? parsed.data : undefined;
|
|
19
|
+
}
|
|
20
|
+
/** Emitted only before a claim when the affirmative payer statement differs from the owned review. */
|
|
21
|
+
export class AccountGasConfirmationRefusal extends Error {
|
|
22
|
+
code = 'ACCOUNT_GAS_REVIEW_CHANGED';
|
|
23
|
+
constructor() { super('ACCOUNT_GAS_REVIEW_CHANGED'); this.name = 'AccountGasConfirmationRefusal'; }
|
|
24
|
+
}
|
|
25
|
+
const uint = z.string().regex(/^(0|[1-9][0-9]*)$/).refine(value => /^(0|[1-9][0-9]*)$/.test(value) && BigInt(value) < 2n ** 256n);
|
|
26
|
+
const positive = uint.refine(value => /^(0|[1-9][0-9]*)$/.test(value) && BigInt(value) > 0n);
|
|
27
|
+
function publicGasParts(amount) {
|
|
28
|
+
const common = { actualCostWei: amount.optional(), reviewRequired: z.literal(true).optional(), reviewFailure: ACCOUNT_GAS_FAILURE_SCHEMA.optional() };
|
|
29
|
+
const sponsor = { ...common, payer: z.literal('sponsor'), paymentReview: ACCOUNT_GAS_REVIEW_SCHEMA.refine(review => review.payer === 'sponsor').optional(),
|
|
30
|
+
maximumCostWei: amount, activationChainHalted: z.literal(true).optional() };
|
|
31
|
+
const account = z.object({ ...common, payer: z.literal('account'), paymentReview: ACCOUNT_GAS_REVIEW_SCHEMA.refine(review => review.payer === 'account') }).strict();
|
|
32
|
+
return { sponsor, account };
|
|
33
|
+
}
|
|
34
|
+
export function accountGasPublicSchema(amount) {
|
|
35
|
+
const { sponsor, account } = publicGasParts(amount);
|
|
36
|
+
return z.discriminatedUnion('payer', [z.object(sponsor).strict(), account]);
|
|
37
|
+
}
|
|
38
|
+
export function accountGasBudgetPublicSchema(amount) {
|
|
39
|
+
const { sponsor, account } = publicGasParts(amount);
|
|
40
|
+
return z.discriminatedUnion('payer', [z.object({ ...sponsor, maximumUserCostWei: amount, maximumActivationCostWei: amount }).strict(), account]);
|
|
41
|
+
}
|
|
42
|
+
export const ACCOUNT_GAS_PUBLIC_SCHEMA = accountGasPublicSchema(positive);
|
|
43
|
+
export function accountGasViewMatches(value) {
|
|
44
|
+
const review = value.gas.paymentReview;
|
|
45
|
+
return !review || (review.payer === value.gas.payer && review.quote.account.toLowerCase() === value.account.toLowerCase() && review.quote.chainId === value.chainId);
|
|
46
|
+
}
|
|
47
|
+
export function accountGasView(operation, budgets) {
|
|
48
|
+
const common = { ...(operation.context.activation.gasPaymentReviewEnabled ? { reviewRequired: true } : {}),
|
|
49
|
+
...(operation.gasReviewFailure ? { reviewFailure: operation.gasReviewFailure } : {}),
|
|
50
|
+
...(operation.receipt ? { actualCostWei: operation.receipt.actualGasCostWei } : {}) };
|
|
51
|
+
if (operation.gasReview?.payer === 'account')
|
|
52
|
+
return { ...common, payer: 'account', paymentReview: operation.gasReview };
|
|
53
|
+
return { ...common, payer: 'sponsor', ...(operation.gasReview ? { paymentReview: operation.gasReview } : {}),
|
|
54
|
+
...budgets, ...(operation.gasCapBreach ? { actualCostWei: operation.gasCapBreach.actualGasCostWei, activationChainHalted: true } : {}) };
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=execution-account-gas-view.js.map
|
|
@@ -22,6 +22,9 @@ export declare const LIFI_DIAMOND_ADDRESS: `0x${string}`;
|
|
|
22
22
|
* (EXSC-737) (#2226)"), `src/Periphery/FeeForwarder.sol` `@custom:version 2.0.0`; 3037 bytes,
|
|
23
23
|
* byte-identical on Base and Arbitrum (CREATE2); same `collectTokenFees` selector; live legs
|
|
24
24
|
* carry unchanged distributions (LI.FI platform + Otto). Reviewed 2026-08-26.
|
|
25
|
+
* - Optimism (10), v2 only: reviewed 2026-09-11 against official deployment commit
|
|
26
|
+
* 58d815734effc6e7878a43279f01933fb9cf1847, exact on-chain code and a decoded live fee leg.
|
|
27
|
+
* Evidence: docs/0911_optimism_lifi_evidence.md. This does not expand the CCTP route set.
|
|
25
28
|
*
|
|
26
29
|
* Adding a deployment here is a REVIEW, not a config edit: confirm the registry entry, read the
|
|
27
30
|
* bytecode, decode one live leg's distributions, then add — never widen to a pattern.
|
package/dist/execution-config.js
CHANGED
|
@@ -23,6 +23,9 @@ export const LIFI_DIAMOND_ADDRESS = getAddress('0x1231DEB6f5749EF6cE6943a275A1D3
|
|
|
23
23
|
* (EXSC-737) (#2226)"), `src/Periphery/FeeForwarder.sol` `@custom:version 2.0.0`; 3037 bytes,
|
|
24
24
|
* byte-identical on Base and Arbitrum (CREATE2); same `collectTokenFees` selector; live legs
|
|
25
25
|
* carry unchanged distributions (LI.FI platform + Otto). Reviewed 2026-08-26.
|
|
26
|
+
* - Optimism (10), v2 only: reviewed 2026-09-11 against official deployment commit
|
|
27
|
+
* 58d815734effc6e7878a43279f01933fb9cf1847, exact on-chain code and a decoded live fee leg.
|
|
28
|
+
* Evidence: docs/0911_optimism_lifi_evidence.md. This does not expand the CCTP route set.
|
|
26
29
|
*
|
|
27
30
|
* Adding a deployment here is a REVIEW, not a config edit: confirm the registry entry, read the
|
|
28
31
|
* bytecode, decode one live leg's distributions, then add — never widen to a pattern.
|
|
@@ -32,6 +35,7 @@ export const LIFI_FEE_FORWARDER_V1 = getAddress('0xC18D9E84b8687A2645447A61e52c4
|
|
|
32
35
|
export const LIFI_FEE_FORWARDER_V2 = getAddress('0xCE40449B773a3E6E5e769ADb4e567179d4828cbd');
|
|
33
36
|
export const LIFI_FEE_FORWARDERS_BY_CHAIN = Object.freeze({
|
|
34
37
|
1: Object.freeze([LIFI_FEE_FORWARDER_V1_MAINNET, LIFI_FEE_FORWARDER_V2]),
|
|
38
|
+
10: Object.freeze([LIFI_FEE_FORWARDER_V2]),
|
|
35
39
|
56: Object.freeze([LIFI_FEE_FORWARDER_V1, LIFI_FEE_FORWARDER_V2]),
|
|
36
40
|
137: Object.freeze([LIFI_FEE_FORWARDER_V1, LIFI_FEE_FORWARDER_V2]),
|
|
37
41
|
8453: Object.freeze([LIFI_FEE_FORWARDER_V1, LIFI_FEE_FORWARDER_V2]),
|
|
@@ -18,8 +18,8 @@ export declare const SUBMIT_UNDER_DELEGATION_INPUT_SCHEMA: z.ZodObject<{
|
|
|
18
18
|
intent_digest: z.ZodString;
|
|
19
19
|
account_binding: z.ZodObject<{
|
|
20
20
|
kind: z.ZodEnum<{
|
|
21
|
-
safe: "safe";
|
|
22
21
|
eoa: "eoa";
|
|
22
|
+
safe: "safe";
|
|
23
23
|
}>;
|
|
24
24
|
address: z.ZodString;
|
|
25
25
|
chainId: z.ZodNumber;
|
|
@@ -42,9 +42,9 @@ export declare const SUBMIT_UNDER_DELEGATION_INPUT_SCHEMA: z.ZodObject<{
|
|
|
42
42
|
value: z.ZodString;
|
|
43
43
|
data: z.ZodString;
|
|
44
44
|
kind: z.ZodEnum<{
|
|
45
|
-
call: "call";
|
|
46
|
-
approve_reset: "approve_reset";
|
|
47
45
|
approve: "approve";
|
|
46
|
+
approve_reset: "approve_reset";
|
|
47
|
+
call: "call";
|
|
48
48
|
}>;
|
|
49
49
|
}, z.core.$strict>>;
|
|
50
50
|
}, z.core.$strict>], "kind">;
|
|
@@ -79,8 +79,8 @@ export declare const SUBMIT_UNDER_DELEGATION_INPUT_SCHEMA: z.ZodObject<{
|
|
|
79
79
|
prepareInput: z.ZodObject<{
|
|
80
80
|
accountProfile: z.ZodObject<{
|
|
81
81
|
kind: z.ZodEnum<{
|
|
82
|
-
safe: "safe";
|
|
83
82
|
eoa: "eoa";
|
|
83
|
+
safe: "safe";
|
|
84
84
|
}>;
|
|
85
85
|
address: z.ZodString;
|
|
86
86
|
chainId: z.ZodNumber;
|
|
@@ -114,9 +114,9 @@ export declare const DELEGATED_SEND_RESULT_SCHEMA: z.ZodObject<{
|
|
|
114
114
|
steps: z.ZodArray<z.ZodObject<{
|
|
115
115
|
index: z.ZodNumber;
|
|
116
116
|
kind: z.ZodEnum<{
|
|
117
|
-
call: "call";
|
|
118
|
-
approve_reset: "approve_reset";
|
|
119
117
|
approve: "approve";
|
|
118
|
+
approve_reset: "approve_reset";
|
|
119
|
+
call: "call";
|
|
120
120
|
}>;
|
|
121
121
|
to: z.ZodString;
|
|
122
122
|
transaction_hash: z.ZodString;
|
|
@@ -129,6 +129,7 @@ export declare const DELEGATED_SEND_RESULT_SCHEMA: z.ZodObject<{
|
|
|
129
129
|
policy_name: z.ZodString;
|
|
130
130
|
rules_digest: z.ZodString;
|
|
131
131
|
per_swap_cap_usd: z.ZodLiteral<5000>;
|
|
132
|
+
user_cap_usd: z.ZodNumber;
|
|
132
133
|
}, z.core.$strict>;
|
|
133
134
|
delegation: z.ZodObject<{
|
|
134
135
|
expires_at: z.ZodString;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { z } from 'zod';
|
|
8
8
|
import { EXECUTION_ENVELOPE_SCHEMA, PREPARE_SWAP_INPUT_SCHEMA, } from './execution-tool-definitions.js';
|
|
9
|
-
import { MODEL_B_PER_SWAP_CAP_USD } from './execution-delegation-policy.js';
|
|
9
|
+
import { MODEL_B_PER_SWAP_CAP_MIN_USD, MODEL_B_PER_SWAP_CAP_USD, } from './execution-delegation-policy.js';
|
|
10
10
|
export const DELEGATED_EXECUTION_TOOL_NAME = 'otto_submit_under_delegation';
|
|
11
11
|
/** Per-request caller authentication rides THIS header — never a tool argument (arguments are logged). */
|
|
12
12
|
export const DELEGATION_AUTH_HEADER = 'x-otto-delegation-auth';
|
|
@@ -78,7 +78,18 @@ export const DELEGATED_SEND_RESULT_SCHEMA = z
|
|
|
78
78
|
policy_id: z.string(),
|
|
79
79
|
policy_name: z.string(),
|
|
80
80
|
rules_digest: z.string().regex(/^[0-9a-f]{64}$/),
|
|
81
|
+
/** The ENGINE's ceiling — the constant in the one shared project policy. Still a literal. */
|
|
81
82
|
per_swap_cap_usd: z.literal(MODEL_B_PER_SWAP_CAP_USD),
|
|
83
|
+
/**
|
|
84
|
+
* The cap THIS person chose when they minted, enforced by Otto's server on top of the ceiling.
|
|
85
|
+
* A bounded integer rather than a literal, because it is the whole point that it can be lower —
|
|
86
|
+
* but it can never exceed the ceiling, and that bound is here rather than left to the caller.
|
|
87
|
+
*/
|
|
88
|
+
user_cap_usd: z
|
|
89
|
+
.number()
|
|
90
|
+
.int()
|
|
91
|
+
.min(MODEL_B_PER_SWAP_CAP_MIN_USD)
|
|
92
|
+
.max(MODEL_B_PER_SWAP_CAP_USD),
|
|
82
93
|
})
|
|
83
94
|
.strict(),
|
|
84
95
|
delegation: z.object({ expires_at: z.string() }).strict(),
|
|
@@ -108,7 +119,7 @@ export const DELEGATED_TOOL_ANNOTATIONS = Object.freeze({
|
|
|
108
119
|
export const DELEGATED_EXECUTION_TOOL_DEFINITION = Object.freeze({
|
|
109
120
|
name: DELEGATED_EXECUTION_TOOL_NAME,
|
|
110
121
|
title: 'Submit an Otto-prepared swap under a CDP end-user delegation',
|
|
111
|
-
description: `Submit a verified otto_prepare_swap envelope on Base under the end user's CDP delegation. Arguments: { userId, envelope (the otto_prepare_swap result), prepareInput (the exact otto_prepare_swap request, with slippage.minAmountOut) } — validated strictly AFTER the caller is authenticated, so the listed input schema is intentionally permissive. Server-to-server only: the caller presents Otto's delegation secret in the \`${DELEGATION_AUTH_HEADER}\` request header (never in arguments); a call without it is refused before anything is read. Before any send the server confirms, in this order: the Model-B project policy is installed and reads back by name and rules digest; the user's grant is active past the envelope's valid_until; the account is one of that end user's own CDP accounts as CDP reports them; the envelope passes the 13-check verifier for exactly the request that produced it; the plan is inside the fence (allow-listed input token, reviewed spender, gross at or below the ${MODEL_B_PER_SWAP_CAP_USD} USD per-swap cap).
|
|
122
|
+
description: `Submit a verified otto_prepare_swap envelope on Base under the end user's CDP delegation. Arguments: { userId, envelope (the otto_prepare_swap result), prepareInput (the exact otto_prepare_swap request, with slippage.minAmountOut) } — validated strictly AFTER the caller is authenticated, so the listed input schema is intentionally permissive. Server-to-server only: the caller presents Otto's delegation secret in the \`${DELEGATION_AUTH_HEADER}\` request header (never in arguments); a call without it is refused before anything is read. Before any send the server confirms, in this order: the Model-B project policy is installed and reads back by name and rules digest; the user's grant is active past the envelope's valid_until; the account is one of that end user's own CDP accounts as CDP reports them; the envelope passes the 13-check verifier for exactly the request that produced it; the plan is inside the fence (allow-listed input token, reviewed spender, gross at or below the ${MODEL_B_PER_SWAP_CAP_USD} USD engine ceiling); and the plan is at or below the per-swap cap THIS user chose when they minted, which is recorded against their grant on this server. A delegation with no recorded cap is REFUSED (DELEGATION_CAP_UNRECORDED) rather than defaulted to the ceiling \u2014 the grant cannot be used for delegated sends; check status and use Stop if it remains active. For an eligible confirmed grant, the three steps (allowance reset, approval, swap) are submitted in order under the delegation, each waited to a sealed canonical block; a halt clears the allowance and reports the read-back. One delegated plan at a time per user. Coinbase's engine bounds the delegated key to Model-B swap shapes through LI.FI up to the ${MODEL_B_PER_SWAP_CAP_USD} USD ceiling, which is shared by every delegated user and cannot be narrowed per user by the engine; the user's own lower cap and the receiver binding are Otto's server-side checks, and the user can revoke at any time.`,
|
|
112
123
|
inputSchema: DELEGATED_TOOL_TRANSPORT_SCHEMA,
|
|
113
124
|
strictInputSchema: SUBMIT_UNDER_DELEGATION_INPUT_SCHEMA,
|
|
114
125
|
outputSchema: DELEGATED_SEND_RESULT_SCHEMA,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* execution-delegation-admin-definition.ts — the
|
|
3
|
-
* D10 = (a), 2026-08-29): `otto_delegation_fence`, `otto_delegation_status`, `otto_delegation_revoke
|
|
2
|
+
* execution-delegation-admin-definition.ts — the four header-authed delegation ADMIN tools (PR-1b, seat ruling
|
|
3
|
+
* D10 = (a), 2026-08-29): `otto_delegation_fence`, `otto_delegation_status`, `otto_delegation_revoke`, and
|
|
4
|
+
* `otto_delegation_cap` (Founder word `delegate cap choice`, 2026-09-02 — the per-swap cap a person chose,
|
|
5
|
+
* recorded against the grant they just minted).
|
|
4
6
|
*
|
|
5
7
|
* Same seam and admission as `otto_submit_under_delegation`: they register only with a rig, the caller presents
|
|
6
8
|
* Otto's server secret in the `x-otto-delegation-auth` request header (never in arguments), the registered
|
|
@@ -18,7 +20,9 @@ import { DELEGATED_TOOL_TRANSPORT_SCHEMA } from './execution-delegated-definitio
|
|
|
18
20
|
export declare const DELEGATION_FENCE_TOOL_NAME: "otto_delegation_fence";
|
|
19
21
|
export declare const DELEGATION_STATUS_TOOL_NAME: "otto_delegation_status";
|
|
20
22
|
export declare const DELEGATION_REVOKE_TOOL_NAME: "otto_delegation_revoke";
|
|
21
|
-
|
|
23
|
+
/** Records the per-swap cap the person chose, against the grant they just minted. */
|
|
24
|
+
export declare const DELEGATION_CAP_TOOL_NAME: "otto_delegation_cap";
|
|
25
|
+
export declare const DELEGATION_ADMIN_TOOL_NAMES: readonly ["otto_delegation_fence", "otto_delegation_status", "otto_delegation_revoke", "otto_delegation_cap"];
|
|
22
26
|
/** The one PUBLIC delegation tool: the fence's public promise (present / name / digest / cap) — never user or grant data. */
|
|
23
27
|
export declare const DELEGATION_FENCE_STATUS_TOOL_NAME: "otto_delegation_fence_status";
|
|
24
28
|
export declare const DELEGATION_FENCE_INPUT_SCHEMA: z.ZodObject<{}, z.core.$strict>;
|
|
@@ -49,9 +53,75 @@ export declare const DELEGATION_STATUS_RESULT_SCHEMA: z.ZodObject<{
|
|
|
49
53
|
delegation: z.ZodObject<{
|
|
50
54
|
active: z.ZodBoolean;
|
|
51
55
|
expires_at: z.ZodOptional<z.ZodString>;
|
|
56
|
+
per_swap_cap_usd: z.ZodOptional<z.ZodNumber>;
|
|
52
57
|
}, z.core.$strict>;
|
|
53
58
|
revocation_requested_here: z.ZodBoolean;
|
|
59
|
+
ruleset_version: z.ZodNumber;
|
|
60
|
+
mint_enabled: z.ZodBoolean;
|
|
54
61
|
}, z.core.$strict>;
|
|
62
|
+
/**
|
|
63
|
+
* 🔴 TWO PHASES, BECAUSE THE RECORD NOW COMES BEFORE THE GRANT.
|
|
64
|
+
*
|
|
65
|
+
* Rounds 1 and 2 recorded a cap against a grant that already existed, and the codex gate broke both the
|
|
66
|
+
* same way: an expiry is the only thing a send can learn about a live grant, so two grants that share one
|
|
67
|
+
* are indistinguishable at enforcement however the row is keyed. Round 3 removes the collision instead of
|
|
68
|
+
* describing it.
|
|
69
|
+
*
|
|
70
|
+
* `reserve` — the SERVER picks a whole-second instant at or BEFORE the person's chosen duration that no
|
|
71
|
+
* durable row for this user occupies, writes the cap against it, and answers with the instant. The
|
|
72
|
+
* caller then mints with `mint_expires_at`, which is that instant plus a one-millisecond filler CDP
|
|
73
|
+
* truncates away (a bare `.000Z` is refused upstream — see `mintExpiryFor`).
|
|
74
|
+
* `confirm` — after the mint, the server re-reads the grant from CDP and refuses unless the instant CDP
|
|
75
|
+
* reports IS the reserved one and the exact generation-bound mint claim still stands. A mismatch or
|
|
76
|
+
* stale confirm stays unconfirmed and authorises nothing. CDP exposes only a user-wide revoke, so the
|
|
77
|
+
* server does not risk deleting a newer permission; the person uses a fresh explicit Stop instead.
|
|
78
|
+
*
|
|
79
|
+
* The user is still never named by the caller — both phases resolve the identity from the access token.
|
|
80
|
+
*/
|
|
81
|
+
export declare const DELEGATION_CAP_RESERVE_INPUT_SCHEMA: z.ZodObject<{
|
|
82
|
+
phase: z.ZodLiteral<"reserve">;
|
|
83
|
+
accessToken: z.ZodString;
|
|
84
|
+
perSwapCapUsd: z.ZodNumber;
|
|
85
|
+
requestedDays: z.ZodNumber;
|
|
86
|
+
mintKey: z.ZodString;
|
|
87
|
+
}, z.core.$strict>;
|
|
88
|
+
export declare const DELEGATION_CAP_CONFIRM_INPUT_SCHEMA: z.ZodObject<{
|
|
89
|
+
phase: z.ZodLiteral<"confirm">;
|
|
90
|
+
accessToken: z.ZodString;
|
|
91
|
+
mintKey: z.ZodString;
|
|
92
|
+
}, z.core.$strict>;
|
|
93
|
+
export declare const DELEGATION_CAP_INPUT_SCHEMA: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
94
|
+
phase: z.ZodLiteral<"reserve">;
|
|
95
|
+
accessToken: z.ZodString;
|
|
96
|
+
perSwapCapUsd: z.ZodNumber;
|
|
97
|
+
requestedDays: z.ZodNumber;
|
|
98
|
+
mintKey: z.ZodString;
|
|
99
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
100
|
+
phase: z.ZodLiteral<"confirm">;
|
|
101
|
+
accessToken: z.ZodString;
|
|
102
|
+
mintKey: z.ZodString;
|
|
103
|
+
}, z.core.$strict>], "phase">;
|
|
104
|
+
export declare const DELEGATION_CAP_RESULT_SCHEMA: z.ZodObject<{
|
|
105
|
+
phase: z.ZodEnum<{
|
|
106
|
+
reserve: "reserve";
|
|
107
|
+
confirm: "confirm";
|
|
108
|
+
}>;
|
|
109
|
+
user_id: z.ZodString;
|
|
110
|
+
expires_at: z.ZodString;
|
|
111
|
+
mint_expires_at: z.ZodOptional<z.ZodString>;
|
|
112
|
+
per_swap_cap_usd: z.ZodNumber;
|
|
113
|
+
state: z.ZodEnum<{
|
|
114
|
+
revoked: "revoked";
|
|
115
|
+
superseded: "superseded";
|
|
116
|
+
reserved: "reserved";
|
|
117
|
+
confirmed_active: "confirmed_active";
|
|
118
|
+
expired: "expired";
|
|
119
|
+
legacy: "legacy";
|
|
120
|
+
}>;
|
|
121
|
+
ruleset_version: z.ZodNumber;
|
|
122
|
+
recorded: z.ZodBoolean;
|
|
123
|
+
}, z.core.$strict>;
|
|
124
|
+
export type DelegationCapResult = z.infer<typeof DELEGATION_CAP_RESULT_SCHEMA>;
|
|
55
125
|
export declare const DELEGATION_REVOKE_INPUT_SCHEMA: z.ZodUnion<readonly [z.ZodObject<{
|
|
56
126
|
accessToken: z.ZodString;
|
|
57
127
|
}, z.core.$strict>, z.ZodObject<{
|
|
@@ -73,6 +143,9 @@ export declare const DELEGATION_FENCE_STATUS_RESULT_SCHEMA: z.ZodObject<{
|
|
|
73
143
|
present: z.ZodBoolean;
|
|
74
144
|
policy_name: z.ZodString;
|
|
75
145
|
per_swap_cap_usd: z.ZodLiteral<5000>;
|
|
146
|
+
per_swap_cap_min_usd: z.ZodLiteral<1>;
|
|
147
|
+
ruleset_version: z.ZodNumber;
|
|
148
|
+
mint_enabled: z.ZodBoolean;
|
|
76
149
|
project_id: z.ZodOptional<z.ZodString>;
|
|
77
150
|
rules_digest: z.ZodOptional<z.ZodString>;
|
|
78
151
|
reason: z.ZodOptional<z.ZodEnum<{
|
|
@@ -86,12 +159,15 @@ export type DelegationFenceStatusResult = z.infer<typeof DELEGATION_FENCE_STATUS
|
|
|
86
159
|
export declare const DELEGATION_FENCE_STATUS_TOOL_DEFINITION: Readonly<{
|
|
87
160
|
name: "otto_delegation_fence_status";
|
|
88
161
|
title: "Read the Model-B delegation fence (public promise: present, name, rules digest, per-swap cap)";
|
|
89
|
-
description: "PUBLIC and read-only, no header: whether the Model
|
|
162
|
+
description: "PUBLIC and read-only, no header: reports whether the Model B project policy still fences existing delegated sends, its name and rules digest, the shared cap ceiling, and mint_enabled for new Model B trade setup. New trade-permission creation is retired, so mint_enabled is false on the serving retirement build. Existing status, revoke and exits remain available. No user, grant, address or policy contents are exposed. Arguments: {}.";
|
|
90
163
|
inputSchema: z.ZodObject<{}, z.core.$strict>;
|
|
91
164
|
outputSchema: z.ZodObject<{
|
|
92
165
|
present: z.ZodBoolean;
|
|
93
166
|
policy_name: z.ZodString;
|
|
94
167
|
per_swap_cap_usd: z.ZodLiteral<5000>;
|
|
168
|
+
per_swap_cap_min_usd: z.ZodLiteral<1>;
|
|
169
|
+
ruleset_version: z.ZodNumber;
|
|
170
|
+
mint_enabled: z.ZodBoolean;
|
|
95
171
|
project_id: z.ZodOptional<z.ZodString>;
|
|
96
172
|
rules_digest: z.ZodOptional<z.ZodString>;
|
|
97
173
|
reason: z.ZodOptional<z.ZodEnum<{
|
|
@@ -152,7 +228,7 @@ export declare const DELEGATION_FENCE_TOOL_DEFINITION: Readonly<{
|
|
|
152
228
|
export declare const DELEGATION_STATUS_TOOL_DEFINITION: Readonly<{
|
|
153
229
|
name: "otto_delegation_status";
|
|
154
230
|
title: "Read one end user's delegation status (token-bound)";
|
|
155
|
-
description: `Read back, for the end user identified by a CDP access token, their CDP accounts, whether the Model-B fence is present, and whether an active delegation reads back (with its expiry). Arguments: { accessToken } \u2014 the server resolves the user from the token; a client-sent user id is refused. Output is bound to that user; nothing about any other user is returned. ${string}`;
|
|
231
|
+
description: `Read back, for the end user identified by a CDP access token, their CDP accounts, whether the Model-B fence is present, and whether an active delegation reads back (with its expiry and the per-swap cap recorded for it). Arguments: { accessToken } \u2014 the server resolves the user from the token; a client-sent user id is refused. delegation.per_swap_cap_usd is the number THIS user chose at mint time; it is ABSENT when no cap is recorded for the grant, which means the delegated send will refuse it \u2014 say so rather than showing the shared ceiling. fence.per_swap_cap_usd is that shared ceiling and is never a per-user number. Output is bound to that user; nothing about any other user is returned. ${string}`;
|
|
156
232
|
inputSchema: z.ZodObject<{}, z.core.$loose>;
|
|
157
233
|
strictInputSchema: z.ZodObject<{
|
|
158
234
|
accessToken: z.ZodString;
|
|
@@ -169,8 +245,11 @@ export declare const DELEGATION_STATUS_TOOL_DEFINITION: Readonly<{
|
|
|
169
245
|
delegation: z.ZodObject<{
|
|
170
246
|
active: z.ZodBoolean;
|
|
171
247
|
expires_at: z.ZodOptional<z.ZodString>;
|
|
248
|
+
per_swap_cap_usd: z.ZodOptional<z.ZodNumber>;
|
|
172
249
|
}, z.core.$strict>;
|
|
173
250
|
revocation_requested_here: z.ZodBoolean;
|
|
251
|
+
ruleset_version: z.ZodNumber;
|
|
252
|
+
mint_enabled: z.ZodBoolean;
|
|
174
253
|
}, z.core.$strict>;
|
|
175
254
|
annotations: Readonly<{
|
|
176
255
|
readOnlyHint: true;
|
|
@@ -206,3 +285,46 @@ export declare const DELEGATION_REVOKE_TOOL_DEFINITION: Readonly<{
|
|
|
206
285
|
openWorldHint: true;
|
|
207
286
|
}>;
|
|
208
287
|
}>;
|
|
288
|
+
export declare const DELEGATION_CAP_TOOL_DEFINITION: Readonly<{
|
|
289
|
+
name: "otto_delegation_cap";
|
|
290
|
+
title: "Confirm an in-flight legacy Model B cap (new reservations retired)";
|
|
291
|
+
description: `Legacy Model B cap confirmation. New { phase: "reserve" } requests are retired and refused before any claim or reservation is written. { phase: "confirm", accessToken, mintKey } remains available for a permission already minted against a prior reservation: the server re-reads CDP and confirms only the exact still-current claim and reserved expiry. A mismatch or Stop overlap remains unconfirmed; a fresh explicit Stop handles the current grant. Without a confirmed per-user cap, delegated sends refuse. This tool does not issue new permissions. ${string}`;
|
|
292
|
+
inputSchema: z.ZodObject<{}, z.core.$loose>;
|
|
293
|
+
strictInputSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
294
|
+
phase: z.ZodLiteral<"reserve">;
|
|
295
|
+
accessToken: z.ZodString;
|
|
296
|
+
perSwapCapUsd: z.ZodNumber;
|
|
297
|
+
requestedDays: z.ZodNumber;
|
|
298
|
+
mintKey: z.ZodString;
|
|
299
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
300
|
+
phase: z.ZodLiteral<"confirm">;
|
|
301
|
+
accessToken: z.ZodString;
|
|
302
|
+
mintKey: z.ZodString;
|
|
303
|
+
}, z.core.$strict>], "phase">;
|
|
304
|
+
outputSchema: z.ZodObject<{
|
|
305
|
+
phase: z.ZodEnum<{
|
|
306
|
+
reserve: "reserve";
|
|
307
|
+
confirm: "confirm";
|
|
308
|
+
}>;
|
|
309
|
+
user_id: z.ZodString;
|
|
310
|
+
expires_at: z.ZodString;
|
|
311
|
+
mint_expires_at: z.ZodOptional<z.ZodString>;
|
|
312
|
+
per_swap_cap_usd: z.ZodNumber;
|
|
313
|
+
state: z.ZodEnum<{
|
|
314
|
+
revoked: "revoked";
|
|
315
|
+
superseded: "superseded";
|
|
316
|
+
reserved: "reserved";
|
|
317
|
+
confirmed_active: "confirmed_active";
|
|
318
|
+
expired: "expired";
|
|
319
|
+
legacy: "legacy";
|
|
320
|
+
}>;
|
|
321
|
+
ruleset_version: z.ZodNumber;
|
|
322
|
+
recorded: z.ZodBoolean;
|
|
323
|
+
}, z.core.$strict>;
|
|
324
|
+
annotations: Readonly<{
|
|
325
|
+
readOnlyHint: false;
|
|
326
|
+
destructiveHint: false;
|
|
327
|
+
idempotentHint: true;
|
|
328
|
+
openWorldHint: true;
|
|
329
|
+
}>;
|
|
330
|
+
}>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* execution-delegation-admin-definition.ts — the
|
|
3
|
-
* D10 = (a), 2026-08-29): `otto_delegation_fence`, `otto_delegation_status`, `otto_delegation_revoke
|
|
2
|
+
* execution-delegation-admin-definition.ts — the four header-authed delegation ADMIN tools (PR-1b, seat ruling
|
|
3
|
+
* D10 = (a), 2026-08-29): `otto_delegation_fence`, `otto_delegation_status`, `otto_delegation_revoke`, and
|
|
4
|
+
* `otto_delegation_cap` (Founder word `delegate cap choice`, 2026-09-02 — the per-swap cap a person chose,
|
|
5
|
+
* recorded against the grant they just minted).
|
|
4
6
|
*
|
|
5
7
|
* Same seam and admission as `otto_submit_under_delegation`: they register only with a rig, the caller presents
|
|
6
8
|
* Otto's server secret in the `x-otto-delegation-auth` request header (never in arguments), the registered
|
|
@@ -14,16 +16,26 @@
|
|
|
14
16
|
* proxy exposes only the token variant (asserted in PR-2).
|
|
15
17
|
*/
|
|
16
18
|
import { z } from 'zod';
|
|
17
|
-
import { MODEL_B_PER_SWAP_CAP_USD } from './execution-delegation-policy.js';
|
|
19
|
+
import { MODEL_B_DELEGATION_EXPIRY_MAX_DAYS, MODEL_B_DELEGATION_EXPIRY_MIN_DAYS, MODEL_B_PER_SWAP_CAP_MIN_USD, MODEL_B_PER_SWAP_CAP_USD, } from './execution-delegation-policy.js';
|
|
18
20
|
import { DELEGATION_AUTH_HEADER, DELEGATED_TOOL_TRANSPORT_SCHEMA, } from './execution-delegated-definition.js';
|
|
21
|
+
import { CAP_RECORD_STATES, MINT_KEY_PATTERN } from './execution-delegation-cap-store.js';
|
|
19
22
|
export const DELEGATION_FENCE_TOOL_NAME = 'otto_delegation_fence';
|
|
20
23
|
export const DELEGATION_STATUS_TOOL_NAME = 'otto_delegation_status';
|
|
21
24
|
export const DELEGATION_REVOKE_TOOL_NAME = 'otto_delegation_revoke';
|
|
25
|
+
/** Records the per-swap cap the person chose, against the grant they just minted. */
|
|
26
|
+
export const DELEGATION_CAP_TOOL_NAME = 'otto_delegation_cap';
|
|
22
27
|
export const DELEGATION_ADMIN_TOOL_NAMES = Object.freeze([
|
|
23
28
|
DELEGATION_FENCE_TOOL_NAME,
|
|
24
29
|
DELEGATION_STATUS_TOOL_NAME,
|
|
25
30
|
DELEGATION_REVOKE_TOOL_NAME,
|
|
31
|
+
DELEGATION_CAP_TOOL_NAME,
|
|
26
32
|
]);
|
|
33
|
+
/** A chosen per-swap cap, as every schema on this surface bounds it: whole USD, 1 … the engine ceiling. */
|
|
34
|
+
const PER_SWAP_CAP_SCHEMA = z
|
|
35
|
+
.number()
|
|
36
|
+
.int()
|
|
37
|
+
.min(MODEL_B_PER_SWAP_CAP_MIN_USD)
|
|
38
|
+
.max(MODEL_B_PER_SWAP_CAP_USD);
|
|
27
39
|
/** The one PUBLIC delegation tool: the fence's public promise (present / name / digest / cap) — never user or grant data. */
|
|
28
40
|
export const DELEGATION_FENCE_STATUS_TOOL_NAME = 'otto_delegation_fence_status';
|
|
29
41
|
const END_USER_ID_PATTERN = /^[a-zA-Z0-9-]{1,100}$/;
|
|
@@ -67,9 +79,118 @@ export const DELEGATION_STATUS_RESULT_SCHEMA = z
|
|
|
67
79
|
/** Active = reads back from CDP, not expired, and no revocation was requested on this server. */
|
|
68
80
|
active: z.boolean(),
|
|
69
81
|
expires_at: z.string().optional(),
|
|
82
|
+
/**
|
|
83
|
+
* The per-swap cap recorded for THIS grant — the number the person chose when they minted.
|
|
84
|
+
* ABSENT when none is recorded, and that absence is load-bearing: a delegated send for a grant
|
|
85
|
+
* with no recorded cap refuses, so the surface reading this must say the permission is not usable
|
|
86
|
+
* rather than quietly showing the ceiling.
|
|
87
|
+
*/
|
|
88
|
+
per_swap_cap_usd: PER_SWAP_CAP_SCHEMA.optional(),
|
|
70
89
|
})
|
|
71
90
|
.strict(),
|
|
72
91
|
revocation_requested_here: z.boolean(),
|
|
92
|
+
/**
|
|
93
|
+
* The cap-ruleset version THIS worker implements. The page and the agent CLI refuse to reserve or
|
|
94
|
+
* mint against a server reporting less than the version they were built for — a rolling deploy runs
|
|
95
|
+
* two binaries at once and the Coinbase fence is identical on both, so the fence cannot tell them
|
|
96
|
+
* apart and this is what does.
|
|
97
|
+
*/
|
|
98
|
+
ruleset_version: z.number().int().min(1),
|
|
99
|
+
/**
|
|
100
|
+
* Whether a NEW permission can be created on this worker at all (the staged-deploy gate). It never
|
|
101
|
+
* gates this read and never gates revoke: pausing the creation of authority must not pause its
|
|
102
|
+
* withdrawal, and a permission that already stands keeps working under its own cap.
|
|
103
|
+
*/
|
|
104
|
+
mint_enabled: z.boolean(),
|
|
105
|
+
})
|
|
106
|
+
.strict();
|
|
107
|
+
/* ── cap (round 3: RESERVE an expiry and record the cap against it, then CONFIRM the mint) ── */
|
|
108
|
+
/**
|
|
109
|
+
* 🔴 TWO PHASES, BECAUSE THE RECORD NOW COMES BEFORE THE GRANT.
|
|
110
|
+
*
|
|
111
|
+
* Rounds 1 and 2 recorded a cap against a grant that already existed, and the codex gate broke both the
|
|
112
|
+
* same way: an expiry is the only thing a send can learn about a live grant, so two grants that share one
|
|
113
|
+
* are indistinguishable at enforcement however the row is keyed. Round 3 removes the collision instead of
|
|
114
|
+
* describing it.
|
|
115
|
+
*
|
|
116
|
+
* `reserve` — the SERVER picks a whole-second instant at or BEFORE the person's chosen duration that no
|
|
117
|
+
* durable row for this user occupies, writes the cap against it, and answers with the instant. The
|
|
118
|
+
* caller then mints with `mint_expires_at`, which is that instant plus a one-millisecond filler CDP
|
|
119
|
+
* truncates away (a bare `.000Z` is refused upstream — see `mintExpiryFor`).
|
|
120
|
+
* `confirm` — after the mint, the server re-reads the grant from CDP and refuses unless the instant CDP
|
|
121
|
+
* reports IS the reserved one and the exact generation-bound mint claim still stands. A mismatch or
|
|
122
|
+
* stale confirm stays unconfirmed and authorises nothing. CDP exposes only a user-wide revoke, so the
|
|
123
|
+
* server does not risk deleting a newer permission; the person uses a fresh explicit Stop instead.
|
|
124
|
+
*
|
|
125
|
+
* The user is still never named by the caller — both phases resolve the identity from the access token.
|
|
126
|
+
*/
|
|
127
|
+
export const DELEGATION_CAP_RESERVE_INPUT_SCHEMA = z
|
|
128
|
+
.object({
|
|
129
|
+
phase: z.literal('reserve'),
|
|
130
|
+
accessToken: ACCESS_TOKEN_SCHEMA,
|
|
131
|
+
perSwapCapUsd: PER_SWAP_CAP_SCHEMA,
|
|
132
|
+
/**
|
|
133
|
+
* How long the person asked for. The server turns it into an instant itself — a caller-supplied expiry
|
|
134
|
+
* would put the choice of the enforcement key back in the browser, and it is the server choosing it
|
|
135
|
+
* that makes the key unique.
|
|
136
|
+
*/
|
|
137
|
+
requestedDays: z
|
|
138
|
+
.number()
|
|
139
|
+
.int()
|
|
140
|
+
.min(MODEL_B_DELEGATION_EXPIRY_MIN_DAYS)
|
|
141
|
+
.max(MODEL_B_DELEGATION_EXPIRY_MAX_DAYS),
|
|
142
|
+
/**
|
|
143
|
+
* The `idempotencyKey` the caller WILL pass to `createDelegation`. It makes the reservation itself
|
|
144
|
+
* retry-safe: pressing again after a lost response returns the same instant rather than consuming a
|
|
145
|
+
* second one. It is NOT the enforcement key — `(userId, expiry)` is.
|
|
146
|
+
*/
|
|
147
|
+
mintKey: z.string().regex(MINT_KEY_PATTERN, 'must be the mint idempotency key'),
|
|
148
|
+
})
|
|
149
|
+
.strict();
|
|
150
|
+
export const DELEGATION_CAP_CONFIRM_INPUT_SCHEMA = z
|
|
151
|
+
.object({
|
|
152
|
+
phase: z.literal('confirm'),
|
|
153
|
+
accessToken: ACCESS_TOKEN_SCHEMA,
|
|
154
|
+
/** Which reservation this mint was for. The reserved instant is read from the store, never from the caller. */
|
|
155
|
+
mintKey: z.string().regex(MINT_KEY_PATTERN, 'must be the mint idempotency key'),
|
|
156
|
+
})
|
|
157
|
+
.strict();
|
|
158
|
+
export const DELEGATION_CAP_INPUT_SCHEMA = z.discriminatedUnion('phase', [
|
|
159
|
+
DELEGATION_CAP_RESERVE_INPUT_SCHEMA,
|
|
160
|
+
DELEGATION_CAP_CONFIRM_INPUT_SCHEMA,
|
|
161
|
+
]);
|
|
162
|
+
export const DELEGATION_CAP_RESULT_SCHEMA = z
|
|
163
|
+
.object({
|
|
164
|
+
phase: z.enum(['reserve', 'confirm']),
|
|
165
|
+
user_id: z.string().regex(END_USER_ID_PATTERN),
|
|
166
|
+
/**
|
|
167
|
+
* The RESERVED whole-second instant — the enforcement key. On `confirm` it is also what CDP reports for
|
|
168
|
+
* the live grant, because the call refuses otherwise.
|
|
169
|
+
*/
|
|
170
|
+
expires_at: z.string(),
|
|
171
|
+
/**
|
|
172
|
+
* What to hand `createDelegation`: the reserved instant plus the one-millisecond filler. Present on
|
|
173
|
+
* `reserve` only — by `confirm` the mint has already happened.
|
|
174
|
+
*/
|
|
175
|
+
mint_expires_at: z.string().optional(),
|
|
176
|
+
/**
|
|
177
|
+
* The cap IN FORCE at that instant, read back from the binding index — not necessarily the number the
|
|
178
|
+
* caller asked for.
|
|
179
|
+
*/
|
|
180
|
+
per_swap_cap_usd: PER_SWAP_CAP_SCHEMA,
|
|
181
|
+
/**
|
|
182
|
+
* Where this permission is in its lifecycle. `reserved` authorises NOTHING — only `confirmed_active`
|
|
183
|
+
* does, and only while it is the one the send gate reads back.
|
|
184
|
+
*/
|
|
185
|
+
state: z.enum(CAP_RECORD_STATES),
|
|
186
|
+
/** The cap ruleset this record requires; a worker that implements an older one refuses it. */
|
|
187
|
+
ruleset_version: z.number().int().min(1),
|
|
188
|
+
/**
|
|
189
|
+
* True when THIS call wrote the transition. False when it had already happened for this mint key:
|
|
190
|
+
* a reservation is immutable and a confirmation is one-shot, so the fields above are what already
|
|
191
|
+
* stands, and a caller wanting a different number mints a new permission.
|
|
192
|
+
*/
|
|
193
|
+
recorded: z.boolean(),
|
|
73
194
|
})
|
|
74
195
|
.strict();
|
|
75
196
|
/* ── revoke ── */
|
|
@@ -97,7 +218,21 @@ export const DELEGATION_FENCE_STATUS_RESULT_SCHEMA = z
|
|
|
97
218
|
.object({
|
|
98
219
|
present: z.boolean(),
|
|
99
220
|
policy_name: z.string(),
|
|
221
|
+
/**
|
|
222
|
+
* The ENGINE's ceiling, shared by every delegated user — never one person's cap. A public tool has no
|
|
223
|
+
* user, so it can only ever publish this number and the floor below it.
|
|
224
|
+
*/
|
|
100
225
|
per_swap_cap_usd: z.literal(MODEL_B_PER_SWAP_CAP_USD),
|
|
226
|
+
/** The floor of the range a person may choose at mint time; their choice is enforced server-side. */
|
|
227
|
+
per_swap_cap_min_usd: z.literal(MODEL_B_PER_SWAP_CAP_MIN_USD),
|
|
228
|
+
/** The cap-ruleset version this worker implements; a client built for a newer one refuses to mint. */
|
|
229
|
+
ruleset_version: z.number().int().min(1),
|
|
230
|
+
/**
|
|
231
|
+
* Whether this worker will create a NEW permission at all. Published so the page and the CLI can say
|
|
232
|
+
* so before a person signs in, rather than discovering it at the reserve. Permissions that already
|
|
233
|
+
* stand keep working, and revoke always works.
|
|
234
|
+
*/
|
|
235
|
+
mint_enabled: z.boolean(),
|
|
101
236
|
/** Otto's PUBLIC CDP project id (a UUID): the authority the agent CLI binds its mint to. */
|
|
102
237
|
project_id: z
|
|
103
238
|
.string()
|
|
@@ -114,7 +249,7 @@ export const DELEGATION_FENCE_STATUS_RESULT_SCHEMA = z
|
|
|
114
249
|
export const DELEGATION_FENCE_STATUS_TOOL_DEFINITION = Object.freeze({
|
|
115
250
|
name: DELEGATION_FENCE_STATUS_TOOL_NAME,
|
|
116
251
|
title: 'Read the Model-B delegation fence (public promise: present, name, rules digest, per-swap cap)',
|
|
117
|
-
description: `PUBLIC and read-only, no header: whether the Model
|
|
252
|
+
description: `PUBLIC and read-only, no header: reports whether the Model B project policy still fences existing delegated sends, its name and rules digest, the shared cap ceiling, and mint_enabled for new Model B trade setup. New trade-permission creation is retired, so mint_enabled is false on the serving retirement build. Existing status, revoke and exits remain available. No user, grant, address or policy contents are exposed. Arguments: {}.`,
|
|
118
253
|
inputSchema: DELEGATION_FENCE_STATUS_INPUT_SCHEMA,
|
|
119
254
|
outputSchema: DELEGATION_FENCE_STATUS_RESULT_SCHEMA,
|
|
120
255
|
annotations: Object.freeze({
|
|
@@ -142,7 +277,7 @@ export const DELEGATION_FENCE_TOOL_DEFINITION = Object.freeze({
|
|
|
142
277
|
export const DELEGATION_STATUS_TOOL_DEFINITION = Object.freeze({
|
|
143
278
|
name: DELEGATION_STATUS_TOOL_NAME,
|
|
144
279
|
title: "Read one end user's delegation status (token-bound)",
|
|
145
|
-
description: `Read back, for the end user identified by a CDP access token, their CDP accounts, whether the Model-B fence is present, and whether an active delegation reads back (with its expiry). Arguments: { accessToken } — the server resolves the user from the token; a client-sent user id is refused. Output is bound to that user; nothing about any other user is returned. ${AUTH_SENTENCE}`,
|
|
280
|
+
description: `Read back, for the end user identified by a CDP access token, their CDP accounts, whether the Model-B fence is present, and whether an active delegation reads back (with its expiry and the per-swap cap recorded for it). Arguments: { accessToken } — the server resolves the user from the token; a client-sent user id is refused. delegation.per_swap_cap_usd is the number THIS user chose at mint time; it is ABSENT when no cap is recorded for the grant, which means the delegated send will refuse it — say so rather than showing the shared ceiling. fence.per_swap_cap_usd is that shared ceiling and is never a per-user number. Output is bound to that user; nothing about any other user is returned. ${AUTH_SENTENCE}`,
|
|
146
281
|
inputSchema: DELEGATED_TOOL_TRANSPORT_SCHEMA,
|
|
147
282
|
strictInputSchema: DELEGATION_STATUS_INPUT_SCHEMA,
|
|
148
283
|
outputSchema: DELEGATION_STATUS_RESULT_SCHEMA,
|
|
@@ -167,4 +302,19 @@ export const DELEGATION_REVOKE_TOOL_DEFINITION = Object.freeze({
|
|
|
167
302
|
openWorldHint: true,
|
|
168
303
|
}),
|
|
169
304
|
});
|
|
305
|
+
export const DELEGATION_CAP_TOOL_DEFINITION = Object.freeze({
|
|
306
|
+
name: DELEGATION_CAP_TOOL_NAME,
|
|
307
|
+
title: "Confirm an in-flight legacy Model B cap (new reservations retired)",
|
|
308
|
+
description: `Legacy Model B cap confirmation. New { phase: "reserve" } requests are retired and refused before any claim or reservation is written. { phase: "confirm", accessToken, mintKey } remains available for a permission already minted against a prior reservation: the server re-reads CDP and confirms only the exact still-current claim and reserved expiry. A mismatch or Stop overlap remains unconfirmed; a fresh explicit Stop handles the current grant. Without a confirmed per-user cap, delegated sends refuse. This tool does not issue new permissions. ${AUTH_SENTENCE}`,
|
|
309
|
+
inputSchema: DELEGATED_TOOL_TRANSPORT_SCHEMA,
|
|
310
|
+
strictInputSchema: DELEGATION_CAP_INPUT_SCHEMA,
|
|
311
|
+
outputSchema: DELEGATION_CAP_RESULT_SCHEMA,
|
|
312
|
+
annotations: Object.freeze({
|
|
313
|
+
readOnlyHint: false,
|
|
314
|
+
destructiveHint: false,
|
|
315
|
+
// Idempotent by construction: the record is immutable, so a repeat returns what is already there.
|
|
316
|
+
idempotentHint: true,
|
|
317
|
+
openWorldHint: true,
|
|
318
|
+
}),
|
|
319
|
+
});
|
|
170
320
|
//# sourceMappingURL=execution-delegation-admin-definition.js.map
|