The IMD Flow presentation pages are separate from settlement. The home page retrieves official capabilities for a read-only job/workflow/oracle demonstration with a visitor-entered illustrative balance. It does not obtain a payment quote, sign, or submit an action. The separate /preview calculator uses entirely illustrative visitor-entered numbers and does not fetch requirements. The current English job.open integration is at /checkout, available in safe preparation mode. Separate operator gates control swaps and signed payment submission. See LIVE_IMD_TEST.md for the current setup, which supersedes the earlier landing-page release redirect. Official capabilities and OpenAPI were refreshed on 2026-10-05 before adding the home-page demonstration.
Sources inspected on 2026-10-05: https://imd.fun/docs/ , https://api.imd.fun/requests/capabilities , https://api.imd.fun/openapi.json . Exact JSON snapshots are in evidence/. Check them again before integration changes.
Flow and validation
- Fetch and validate capabilities: Ethereum, expected IMD address, 18 decimals, enabled actions, positive atomic amounts, x402 v2 exact Permit2. Unknown payment shape is rejected.
- The user enters a job.open report objective. The client supplies an explicit research-report skill, three citations, a report output and github:false; no other paid action is exposed.
requests/checkexposes blockers before quoting. - Create a random 32-byte bearer secret and UUID request key. Quote with action/input. Check price against fresh capability pricing, for job.open only. Keep the quote id, expiry, hash and payer in sessionStorage.
- Empty submit obtains the saved prepared input. The API may normalize input; show the returned input rather than signing unseen changes. Require explicit review before paying.
- Compute
max(required - balance, 0)with bigint. Quote only this difference, review maximum ETH, then purchase. No action prices are constants in application logic. - Read IMD allowance to official Permit2. The separate allowance button approves exactly the payment amount. We deliberately do not call SDK
createPermit2ApprovalTx, which encodes unlimited approval in 2.27.0. A pre-existing larger allowance is not increased by this app. - Fetch status first. A pending or completed order is followed, not signed anew. Empty submit returns current challenge; validate quote id/hash, action, recipient, asset, network, amount, resource and expiry.
@x402/coreand@x402/evm2.27.0 build the payment. The current core SDK also needs an explicitspendControls.allowedAssetsentry for IMD. Its cap is the reviewed quote amount. Requirements are retained verbatim after strict schema validation.- A signer wrapper validates the Permit2 domain, standard witness types, fixed SDK exact-payment spender, amount, recipient and deadline before forwarding the request to the wallet.
- Strip SDK extensions, canonicalize the exact payment JSON, SHA-256 hash, and sign IdentityMD's QuoteApproval with the same account. No domain verifyingContract is invented for QuoteApproval: its official domain has name, version and chainId.
- Save exactly those signed bytes for retries. Stop after signing. Only a separate explicit confirmation submits
PAYMENT-SIGNATUREplus{quoteSignature}. Check status manually; no automatic payment or new signature on retry. Recovered payloads are cryptographically verified against both signatures before sending.
Deadline rules
SDK source inspected: @x402/evm 2.27.0 createPermit2PayloadForProxy: deadline = floor(Date.now()/1000) + maxTimeoutSeconds; validAfter=0. The app never substitutes quote.expiresAt-5 and never edits accepted.maxTimeoutSeconds.
Reject before signing when the generated deadline is not strictly before quote expiry, is beyond the offered window, or has ten seconds or less remaining. Fetch a fresh challenge / create a new quote if necessary. This may fail closed under clock skew or changed server rules; do not weaken it to make an expired payment pass. An expired swap and an expired IdentityMD quote are separate checks.
Proxy
Only fixed https://api.imd.fun GET capabilities/OpenAPI/status and POST check/quote/submit paths. No user URL, redirect following, cookies, credential persistence, retry queue or arbitrary headers. Forward only the bearer credential and payment signature needed for that request; preserve payment response headers/status. Upstream responses are bounded to 64 KiB and POST bodies to 16 KiB; upstream requests time out after 60 seconds. Signed submissions are rejected with 403 unless the separate server payment flag and swap release gate are enabled. A confirmation header is also required; it is an intent marker, not authentication. Cross-origin browser requests are refused. Per-process request budget is 120/minute; a public multi-instance deployment additionally needs edge rate limits.
The RPC proxy permits selected read/simulation methods and refuses eth_sendTransaction / eth_sendRawTransaction, including inside batches. Actual user-approved transactions go through the browser wallet. RPC provider secrets stay server-side.
Verified and not verified
Verified: live schema fetch, browser capabilities selection and pricing, contract fork execution, strict validation, two-signature SDK sequence with test signatures, rejection before signing on invalid deadlines, build/types and proxy rejection tests.
Not executed: a real wallet connection/signature in an installed browser wallet, IMD approval transaction, mainnet purchase, real x402 settlement/admission. No mainnet transactions were authorized for this task. A configured deployed router and human-controlled wallet are required for those acceptance checks. The payment UI code is not a claim that live admission was completed.
Only EOA wallets without account code are enabled for signing. ERC-1271 / EIP-7702 / account-abstraction support is UNRESOLVED and deliberately rejected. Order/signature recovery uses browser-session storage and is exposed to same-origin script compromise; no private wallet key is ever stored. Do not embed third-party scripts. Use HTTPS and production CSP/edge controls before public hosting.
Independence from IdentityMD
Anyone can use the verified public pool and prepare normal API payments without changing IMD. Reliable production admission still depends on IdentityMD's availability, current policy, facilitator and acceptance of the actual signed payload. One atomic ETH-to-admission experience requires cooperation; see V2_DESIGN.md.
Current live challenge correction
The actual challenge resource and resourceUrl are https://api.imd.fun/requests/{id}, while HTTP submission goes to /requests/{id}/submit. The previous submit-suffixed resource check was wrong and is covered by a captured-response regression test. The client compares the full quote, including expiry/policy/terms, and SHA-256 of canonical prepared input. QuoteHash is the server-supplied identifier bound in QuoteApproval, not recomputed using an invented algorithm. OpenAPI types are checked before creating an order. /requests/check currently appears in the guide but not OpenAPI paths; its real response was verified.
The real API plus production client/state machine/wallet adapter reached awaiting_payment_signature with zero initial IMD and an actual POOL4 purchase on local Anvil. No live signature/payment/admission is claimed. See JOB_OPEN_MILESTONE.md and evidence/milestone-client-fork.json.
ETH-first checkout presentation
The checkout presents “Pay with ETH” as funding a job. ETH estimates, maximum input and slippage stay visible; IMD balances and settlement details are available in expandable sections. Existing IMD reduces the required purchase, potentially to zero. The purchase still requires wallet confirmation, and a separate payment authorization and submission starts the job. This wording does not introduce native-ETH IdentityMD settlement, gas subsidies or automatic signatures. Safe-mode restrictions remain unchanged.
Confirmed job admission now permits an explicit new order with a fresh request key and cleared payment signatures. Unresolved submitted payments still block reset. A status refresh after admission is supported. These controls do not activate mainnet deployment or spending.
Mainnet deployment update — 2026-10-05
The user confirmed deployment from 0xFC2D201c44b18E85eD39fbF9FD098B4c3D7BaD14. Router: 0xf476a72f0e4d31f1cbaaa629a550cd982bab8d26, Ethereum chain 1, block 26128548. Transaction: 0x87123526b82e77b89d95850807696df2690b6aa59a7f2aac0108deb571ee97bf. Gas paid: 0.000255657297530583 ETH.
Creation input matches the compiled artifact exactly. Runtime instructions and all immutable values match the compiled router and expected market configuration. Runtime hash: 0x50eb37a199fe108bdd0dc0ae8f37d0cc82ea0a62eb8d84f16d5219a060bc66ee. A fork-only simulated purchase using the deployed address passed at block 26128559. Evidence: deployment/mainnet-verification.json. This supersedes earlier statements that the router is undeployed. It is not explorer source verification or an independent audit.
Production configuration is being connected to this deployment with the runtime hash pinned. Wallet confirmation and separate payment submission remain mandatory. No live swap or paid job acceptance has been verified. The next step is a user-confirmed first transaction and settlement, following docs/LIVE_IMD_TEST.md. Deployment alone does not establish successful end-to-end job payment.
Wallet account-code restriction removed — 2026-10-05
The checkout no longer rejects a payer solely because eth_getCode returns contract code, including EIP-7702 delegation. Ethereum chain and connected-payer checks remain mandatory. Router runtime hash, amount, recipient, expiry, allowance and both signature validations are unchanged. This removes the observed local blocker; it does not certify every smart wallet or guarantee IdentityMD acceptance. Current payment validation still requires recoverable 65-byte signatures for the same payer. Arbitrary ERC-1271-only or counterfactual account signatures are not newly implemented. Reuse existing IMD: obtain a fresh quote and refresh the balance before any additional purchase.