# Paid-request flow investigation

Test target: https://explorer.imd.fun/request. Observations on 2026-09-25 UTC. **No signatures, transactions, payments, or publication were performed.** This is an investigation deliverable, not an implementation of production fixes or proof of completed paid delivery.

**Verdict:** The page obtained real quotes for all six Job kinds, both Launch kinds, all six combinations of the three UI Oracle answer types and two evidence types, and one explicit Release request. The Release placeholder and a separate Counter release returned 422 without the referenced recheck guidance. Thus the reported Release issue is **partly confirmed**, not a universal Release outage. The most consequential observed issues are unactionable Release errors, free quotes gated on wallet funding/allowance, and omitted purchase terms at confirmation.

## Flow map

| Step | What the customer sees | What is sent | What comes back / evidence |
|---|---|---|---|
| Open without a wallet | Intro; after hydration, “No wallet in this browser.” No request form or tabs. At 390px there was no horizontal overflow. | `GET https://explorer.imd.fun/request`; client `GET /api/requests/capabilities` | HTTP 200 HTML; capabilities list four actions, 0.5 IMD, 600-second quotes. [no-wallet](evidence/no-wallet.json), 2026-09-25T07:24:42.154Z ([390px screenshot](evidence/no-wallet.png)) |
| Connect | Wallet address, balance, price; a first-time 5 IMD Permit2 approval prompt when allowance is zero. Free quote button disabled for the simulated unfunded/unapproved wallet. | Account request and balance/allowance reads; client creates a 32-byte bearer token locally. | Account/RPC behavior was simulated locally, not a real wallet connection or chain balance verification. [zero-balance](evidence/zero-balance.json), 2026-09-25T07:24:44.258Z ([390px screenshot](evidence/zero-balance.png)) |
| Job | Report: sourced document; Website: React source/static export; Contracts: Foundry/tests, no deployment; Image, Audio, Video: generated media. | `POST /api/requests/quote`, `{requestKey,action:"job.open",input:{objective,skill,...}}`. Report/media include named output path/MIME; Website/Contracts omit outputs, `github`, and `ipfs`. | All six HTTP 201. Exact page-generated bodies and full responses: [report](evidence/cases/report.json), [website](evidence/cases/website.json), [contracts](evidence/cases/contracts.json), [image](evidence/cases/image.json), [audio](evidence/cases/audio.json), [video](evidence/cases/video.json). |
| Launch | Contracts or Uniswap v4 hook; tests, independent review, deployment explicitly on Sepolia. | `action:"launch.open"`; `shape:"chain"`, two steps (build-contract-project, adversarial-review), kind-specific references, `onchain:"evm_project"` or `"univ4_hook"`. No explicit chain ID in these two job bodies. | Both HTTP 201. [launch-contracts](evidence/cases/launch-contracts.json), [launch-hook](evidence/cases/launch-hook.json). Client copy verified in [Launch snapshot](evidence/launch-contracts-before.json). Actual deployment untested. |
| Release | Contracts, review, Sepolia deployment, site against deployed contracts, IPFS and GitHub. Plan checked when quoting. | `action:"workflow.open"`; request, empty context, draft duplicating objective (first 8,000 chars), three steps, `github:true`, `ipfs:true`; permissions include Sepolia `chainId:11155111`. | Placeholder: HTTP 422. Explicit ERC-20: HTTP 201. Counter: HTTP 422. [release-placeholder](evidence/cases/release-placeholder.json), [release-explicit](evidence/cases/release-explicit.json), [release-counter](evidence/cases/release-counter.json). |
| Oracle | Yes/no, number, address; web sources or Ethereum chain data; lookback day/week/month; says five agents, four agreeing, one-day validity. | `action:"oracle.request"`; `v:1`, question, `chainId:1`, `window:{hours:24}` in tested cases, answerType, evidence, `panelSize:5`, `quorum:4`, `validForSeconds:86400`. | All six UI combinations HTTP 201; response pins exact blocks and hashes. The matrix below links each full call. |
| Quote ready | Request action, 0.5 IMD, recipient, countdown, “Nothing is charged until you sign and pay.” No objective or admission-only term shown. | Quote succeeds; client GETs only its own order to display state. | Quoted order includes inputJson, inputHash, issuedAt/expiresAt, payment, and `terms:{purchase:"action-admission",resultGuaranteed:false}`. [website-after](evidence/website-after.json), 2026-09-25T07:24:50.592Z ([390px screenshot](evidence/website-after.png)) |
| Sign and pay | Button present; never clicked. | Documented flow: unsigned `/submit` challenge, Permit2 payment signature, EIP-712 QuoteApproval, signed submit. | Signing/payment/admission/results **not tested**. Any unsigned expiry check below cannot establish payment correctness. |

## VERIFIED findings

“VERIFIED” means the stated observation is in the linked capture, not that every inferred impact or production root cause has been proven. Wallet-dependent UI findings are explicitly qualified as simulations. Expected behavior is distinguished from observed behavior.

### F1 — high — Release rejection has no usable recovery information

**Impact:** A customer can be unable to obtain a Release quote and has no specific revision to make, abandoning the purchase or guessing repeatedly.

- Exact URL/call: `POST https://explorer.imd.fun/api/requests/quote`, bearer token and JSON headers/body in [release-placeholder](evidence/cases/release-placeholder.json) at 2026-09-25T07:24:56.600Z. Select Release, paste the page's placeholder, GET A QUOTE. A separate direct replay is [release-placeholder-direct](evidence/cases/release-placeholder-direct.json) at 2026-09-25T07:22:54.080679+00:00. Direct upstream parity at `https://api.imd.fun/requests/quote` also returned the same 422 with no recheck structures: [upstream-release-placeholder](evidence/cases/upstream-release-placeholder.json) at 2026-09-25T07:28:55.657216+00:00.
- Input text: `A fixed-supply ERC-20 called Tip Vault, and a one-page site that shows its supply and a connected wallet's balance.`. The linked call contains the complete wrapper/draft/permissions, not just the text.
- Observed: HTTP 422, `error:invalid_input`; `problems[0].code:recheck_failed`; detail says `needs_revision` and refers to recheck questions, suggestions, reviewItems and prerequisites. **None of those four data structures is included in the full response.**
- A different, explicit Counter request also returned that error: [release-counter](evidence/cases/release-counter.json) at 2026-09-25T07:27:08.466Z. Every Release response is in the matrix, including successes.
- The page renders the problem as a JSON object in the alert: [release-placeholder-after](evidence/release-placeholder-after.json), 2026-09-25T07:24:59.496Z ([390px screenshot](evidence/release-placeholder-after.png)). The public client formatter stringifies problem objects; its catch handler truncates error messages to 300 characters ([captured public bundle](evidence/3jd6qc4qmrbau.js)). Truncation was not needed to explain this short response.
- Expected: a supported placeholder should quote or explain the precise missing decisions; a legitimate refusal should return and render actionable questions. This expectation does **not** mean every natural-language request must be admitted.
- Counterevidence: [release-explicit](evidence/cases/release-explicit.json) at 2026-09-25T07:26:59.210Z returned 201 for an ERC-20 request specifying supply, decimals, recipient, privileges, chain, tests, review and publication. **The assertion that Release never works is refuted.** Why the Counter failed is unknown; no private evaluator logs were accessed.

### F2 — medium — Free quotes require a wallet and sufficient balance/allowance in the page

**Impact:** A new customer must install/connect/fund a wallet and potentially authorize spending before they can discover whether their request is quoteable.

- URL/input: `GET https://explorer.imd.fun/request`, no injected wallet, 390×844 viewport. [no-wallet](evidence/no-wallet.json), 2026-09-25T07:24:42.154Z ([390px screenshot](evidence/no-wallet.png)). Observed: no action tabs, descriptions or quote form after hydration.
- With a locally injected synthetic account and RPC responses of zero balance/allowance, the page displays APPROVE 5 IMD and disables GET A QUOTE: [zero-balance](evidence/zero-balance.json), 2026-09-25T07:24:44.258Z ([390px screenshot](evidence/zero-balance.png)). No approval was clicked. This verifies the page's reaction to those responses, **not** an interaction with MetaMask or Rabby.
- Public JavaScript gates GET A QUOTE on both insufficient allowance and insufficient balance; live [initial-report](evidence/cases/initial-report.json) at 2026-09-25T07:20:57.177039+00:00 nevertheless returned 201 with only a freshly generated bearer token and no wallet or payment.
- Expected (UX recommendation): allow composition and free quoting before wallet funding/allowance; require those only for payment. At minimum show tabs/examples before wallet connection and explain that quoting is free.

### F3 — medium — Confirmation omits admission-only terms and the work being purchased

**Impact:** A customer can reach payment without seeing that no result is guaranteed or a final summary of the objective/options they are approving.

- URL/call/input: Website form and exact POST in [website](evidence/cases/website.json) at 2026-09-25T07:24:48.170Z; resulting screen [website-after](evidence/website-after.json), 2026-09-25T07:24:50.592Z ([390px screenshot](evidence/website-after.png)).
- Observed: response contains `terms.purchase:"action-admission"` and `terms.resultGuaranteed:false`. The screen shows action “Job”, price, recipient, expiry and payment warning, but not these terms, the objective, the Website kind, or the normalized input. Same omission observed for the successful Release quote ([screen](evidence/release-explicit-after.json)).
- Expected: a concise pre-signing statement that 0.5 IMD buys admission, not a guaranteed completed result, plus the selected kind/objective and delivery settings. The wording about nothing being charged until payment does not explain what the payment buys.
- Verified limits: price and countdown themselves matched the response. Signing correctness, refunds and downstream delivery were not tested.

### F4 — medium — No choice to disable GitHub publication; Website has no hosting option

**Impact:** Customers cannot choose the documented delivery/privacy options, and a customer seeking a live website can order only source/static export through the Website card without a hosting control.

- URL/input/time: Website [website](evidence/cases/website.json) at 2026-09-25T07:24:48.170Z, [form](evidence/website-before.json); Report [report](evidence/cases/report.json) at 2026-09-25T07:25:05.631Z, [form](evidence/report-before.json).
- Observed: page sends neither `github:false` nor `ipfs` for these jobs; no controls expose them. Response inputJson also omits them. Release explicitly sets GitHub/IPFS true, with no site-label option.
- Documented comparison: [Job body](https://imd.fun/docs/#job-body) says code jobs and research-report default GitHub publication to true and permits `github:false`; `ipfs` accepts true or a naming label. [Captured docs](evidence/docs.txt), retrieval metadata [here](evidence/docs.json).
- Expected: make publication defaults clear and offer GitHub opt-out where supported; offer optional Website hosting and a site label. **No actual GitHub/IPFS publication was observed or initiated.** The future default publication consequence is inferred from docs, not proven by paying.
- Fairness: the Website card promises source and static export, not expressly a public hosted URL. Thus absence of `ipfs` is a verified feature gap, not proof of a broken hosting promise.

### F5 — low — Oracle advanced API choices are unavailable in the form

**Impact:** Customers needing list/hash answers, custom consensus settings or precise evidence constraints must leave the public request form and build an API client.

- URL/input/time: Oracle form, [oracle-address-chain-before](evidence/oracle-address-chain-before.json), 2026-09-25T07:26:50.013Z ([390px screenshot](evidence/oracle-address-chain-before.png)); exact request [oracle-address-chain](evidence/cases/oracle-address-chain.json) at 2026-09-25T07:26:50.065Z.
- Observed: UI exposes only bool, uint256 and address, fixes panel size/quorum at 5/4 and validity at 86,400 seconds, and offers only hour lookbacks. The panel size/quorum and validity are honestly described in the UI.
- [Oracle body docs](https://imd.fun/docs/#oracle-body) additionally allow bytes32, address[], bytes32[], configurable panel/quorum/validity, explicit block windows, definitions, guards, tolerance and consumer domain. Direct quote results for omitted types are recorded below; these are API calls, **not page-generated bodies**.
- Expected (feature recommendation): advanced controls or an explicit link to an equivalent API request, while keeping clear defaults for simple questions. UI omission does not by itself indicate a backend defect.

### F6 — low — A ready quote offers no visible edit/discard path

**Impact:** A customer who notices a mistake after quoting cannot use the displayed controls to amend it immediately and may wait for expiry or manipulate saved state.

- URL/input/time: [website](evidence/cases/website.json) at 2026-09-25T07:24:48.170Z; [website-after](evidence/website-after.json), 2026-09-25T07:24:50.592Z ([390px screenshot](evidence/website-after.png)).
- Observed: form and action tabs disappear; only SIGN AND PAY, request history and credential disclosure remain. No Edit, Discard or New request control is visible while quoted. Public bundle renders New request only when the order state is final.
- Expected: discard this unpaid quote and return to an editable form using a new requestKey, while preserving history. **A full ten-minute UI wait/recovery was not exercised**; API expiry checks are separately recorded.

### F7 — medium — Release character limit does not fit the quote body limit

**Impact:** A customer can write within the form's permitted length and still receive a request-too-large error before plan validation.

- URL/input/time: [release-8100-under-field-limit](evidence/cases/release-8100-under-field-limit.json) at 2026-09-25T07:28:08.112764+00:00, `POST https://explorer.imd.fun/api/requests/quote`. Exact harmless 8,100-character input and serialized bytes are saved in that call.
- Observed: HTTP 413 for a 16509-byte JSON envelope. Release's textarea advertises `maxLength:16000` ([captured form](evidence/release-placeholder-before.json)); the public client duplicates up to 8,000 characters in draft.objective. The API's documented 16 KiB envelope limit is therefore reached before the form's character limit.
- Expected: enforce the UTF-8 serialized envelope budget before sending, show a useful counter/error, and harmonize the workflow schema and endpoint limit. The over-limit call was a direct replay of the client serialization, not an 8,100-character browser submission.
- The API rejecting an oversized body is correct; the finding concerns the client/API budget mismatch, not bypass of server validation.

### F8 — low — The documented 10-quotes/minute limit is not a strict observed cap

**Impact:** API users cannot treat the published rate as an accurate boundary, and operators may be allowing more quote evaluation than the documentation suggests.

- Exact calls: `POST https://explorer.imd.fun/api/requests/quote`, [rate-window-1](evidence/cases/rate-window-1.json) through [rate-window-11](evidence/cases/rate-window-11.json); every intervening call is linked in the matrix. All used the same test bearer token and harmless Report objective, with distinct request keys.
- Observed: all 11 new quotes returned HTTP 201 between 2026-09-25T07:32:31.283430+00:00 and 2026-09-25T07:32:44.176030+00:00, entirely within one UTC calendar minute and within 60 seconds. The sequence followed 61 seconds of no test requests. [Run metadata](evidence/rate-window-run.json).
- Expected under a strict reading of [Paid requests errors/limits](https://imd.fun/docs/#paid): the eleventh quote should return HTTP 429 `request_limit`, since the documentation says 10 quotes per minute per IP and per token. The same-token condition is captured; external source-IP stability is not independently established.
- Scope: this verifies an observable documentation/behavior mismatch, **not** that rate limiting is absent or exploitable. A refill/burst algorithm or configuration could explain it. The earlier 11-call probe crossed a minute boundary and does not independently establish this finding. No more calls were made to find a higher threshold; the 120-requests/minute limiter was not exercised.
- Fix: document actual burst/refill/window semantics and return rate metadata, or enforce the advertised strict per-token limit. Do not infer a security bypass from this bounded sample.

## Prioritized concrete fixes

1. **P1, F1:** Return structured evaluator questions, review items and prerequisites on Release rejection. Render them as an editable checklist; replace the placeholder with a known quoteable example. Regression-check the failing placeholder, failing Counter and successful explicit ERC-20 together.
2. **P1, F2:** Separate free quote eligibility from wallet balance/allowance. Show the form before wallet connection; gate only payment and retain a zero-funds quote test.
3. **P1, F3:** Before signatures, display admission-only/no-guaranteed-result terms and a human-readable summary of objective, kind, chain, publication and Oracle consensus settings.
4. **P2, F7:** Validate serialized UTF-8 byte size, including repeated Release text; harmonize server/body and field limits. Render 413 with specific shortening guidance.
5. **P2, F4:** Expose GitHub publication choice with clear defaults; add optional Website IPFS hosting/site-label settings. Distinguish static export from a hosted website.
6. **P2, F6:** Add Edit/Discard quote that creates a fresh key and never signs/submits the old one.
7. **P3, F5:** Add Oracle advanced settings or API export for unsupported form choices; keep the existing panel/quorum explanation.
8. **P3, F8:** Clarify or align the published quote rate limit, including burst/refill/window semantics; add a deterministic boundary check.

## Full quote and validation matrix

Each linked JSON capture contains UTC time, exact URL/method, request headers, exact serialized body, status, response headers and full response body. `requestBody` and `responseBody` are JSON strings preserving their original text; parse them once to inspect objects. Browser rows are actual page-generated requests to the live explorer proxy; direct rows are explicitly marked. Test credentials belong only to these unpaid test orders.

| Test | Method | UTC | HTTP | Result and evidence |
|---|---|---|---|---|
| initial-report | direct POST | 2026-09-25T07:20:57.177039+00:00 | 201 | created; [initial-report](evidence/cases/initial-report.json) |
| release-placeholder-direct | direct POST | 2026-09-25T07:22:54.080679+00:00 | 422 | invalid_input / recheck_failed; [release-placeholder-direct](evidence/cases/release-placeholder-direct.json) |
| website | browser POST | 2026-09-25T07:24:48.170Z | 201 | created; [website](evidence/cases/website.json) |
| release-placeholder | browser POST | 2026-09-25T07:24:56.600Z | 422 | invalid_input / recheck_failed; [release-placeholder](evidence/cases/release-placeholder.json) |
| report | browser POST | 2026-09-25T07:25:05.631Z | 201 | created; [report](evidence/cases/report.json) |
| contracts | browser POST | 2026-09-25T07:25:14.154Z | 201 | created; [contracts](evidence/cases/contracts.json) |
| image | browser POST | 2026-09-25T07:25:22.440Z | 201 | created; [image](evidence/cases/image.json) |
| audio | browser POST | 2026-09-25T07:25:31.139Z | 201 | created; [audio](evidence/cases/audio.json) |
| video | browser POST | 2026-09-25T07:25:39.857Z | 201 | created; [video](evidence/cases/video.json) |
| launch-contracts | browser POST | 2026-09-25T07:25:48.266Z | 201 | created; [launch-contracts](evidence/cases/launch-contracts.json) |
| launch-hook | browser POST | 2026-09-25T07:25:56.517Z | 201 | created; [launch-hook](evidence/cases/launch-hook.json) |
| oracle-bool-panel | browser POST | 2026-09-25T07:26:05.066Z | 201 | created; [oracle-bool-panel](evidence/cases/oracle-bool-panel.json) |
| oracle-bool-chain | browser POST | 2026-09-25T07:26:14.272Z | 201 | created; [oracle-bool-chain](evidence/cases/oracle-bool-chain.json) |
| oracle-uint256-panel | browser POST | 2026-09-25T07:26:23.269Z | 201 | created; [oracle-uint256-panel](evidence/cases/oracle-uint256-panel.json) |
| oracle-uint256-chain | browser POST | 2026-09-25T07:26:32.109Z | 201 | created; [oracle-uint256-chain](evidence/cases/oracle-uint256-chain.json) |
| oracle-address-panel | browser POST | 2026-09-25T07:26:40.962Z | 201 | created; [oracle-address-panel](evidence/cases/oracle-address-panel.json) |
| oracle-address-chain | browser POST | 2026-09-25T07:26:50.065Z | 201 | created; [oracle-address-chain](evidence/cases/oracle-address-chain.json) |
| release-explicit | browser POST | 2026-09-25T07:26:59.210Z | 201 | created; [release-explicit](evidence/cases/release-explicit.json) |
| release-counter | browser POST | 2026-09-25T07:27:08.466Z | 422 | invalid_input / recheck_failed, requirement_uncovered, requirement_uncovered; [release-counter](evidence/cases/release-counter.json) |
| same-key-same-body | direct POST | 2026-09-25T07:27:24.189715+00:00 | 200 | replay; [same-key-same-body](evidence/cases/same-key-same-body.json) |
| same-key-changed-body | direct POST | 2026-09-25T07:27:30.606847+00:00 | 409 | request_key_conflict; [same-key-changed-body](evidence/cases/same-key-changed-body.json) |
| empty-objective | direct POST | 2026-09-25T07:27:36.870692+00:00 | 400 | invalid_request; [empty-objective](evidence/cases/empty-objective.json) |
| objective-8001 | direct POST | 2026-09-25T07:27:43.114898+00:00 | 400 | invalid_request; [objective-8001](evidence/cases/objective-8001.json) |
| empty-question | direct POST | 2026-09-25T07:27:49.363010+00:00 | 400 | invalid_request; [empty-question](evidence/cases/empty-question.json) |
| question-2001 | direct POST | 2026-09-25T07:27:55.612285+00:00 | 400 | invalid_request; [question-2001](evidence/cases/question-2001.json) |
| body-over-16k | direct POST | 2026-09-25T07:28:01.857606+00:00 | 413 | request_too_large; [body-over-16k](evidence/cases/body-over-16k.json) |
| release-8100-under-field-limit | direct POST | 2026-09-25T07:28:08.112764+00:00 | 413 | request_too_large; [release-8100-under-field-limit](evidence/cases/release-8100-under-field-limit.json) |
| api-oracle-bytes32-panel | direct POST | 2026-09-25T07:28:14.347978+00:00 | 201 | created; [api-oracle-bytes32-panel](evidence/cases/api-oracle-bytes32-panel.json) |
| api-oracle-bytes32-chain | direct POST | 2026-09-25T07:28:21.093906+00:00 | 201 | created; [api-oracle-bytes32-chain](evidence/cases/api-oracle-bytes32-chain.json) |
| api-oracle-address[]-panel | direct POST | 2026-09-25T07:28:27.668774+00:00 | 201 | created; [api-oracle-address[]-panel](evidence/cases/api-oracle-address-list-panel.json) |
| api-oracle-address[]-chain | direct POST | 2026-09-25T07:28:34.558062+00:00 | 201 | created; [api-oracle-address[]-chain](evidence/cases/api-oracle-address-list-chain.json) |
| api-oracle-bytes32[]-panel | direct POST | 2026-09-25T07:28:41.703611+00:00 | 201 | created; [api-oracle-bytes32[]-panel](evidence/cases/api-oracle-bytes32-list-panel.json) |
| api-oracle-bytes32[]-chain | direct POST | 2026-09-25T07:28:48.953770+00:00 | 201 | created; [api-oracle-bytes32[]-chain](evidence/cases/api-oracle-bytes32-list-chain.json) |
| upstream-release-placeholder | direct POST | 2026-09-25T07:28:55.657216+00:00 | 422 | invalid_input / recheck_failed; [upstream-release-placeholder](evidence/cases/upstream-release-placeholder.json) |
| rate-1 | direct POST | 2026-09-25T07:30:53.586009+00:00 | 201 | created; [rate-1](evidence/cases/rate-1.json) |
| rate-2 | direct POST | 2026-09-25T07:30:54.916456+00:00 | 201 | created; [rate-2](evidence/cases/rate-2.json) |
| rate-3 | direct POST | 2026-09-25T07:30:56.136512+00:00 | 201 | created; [rate-3](evidence/cases/rate-3.json) |
| rate-4 | direct POST | 2026-09-25T07:30:57.407719+00:00 | 201 | created; [rate-4](evidence/cases/rate-4.json) |
| rate-5 | direct POST | 2026-09-25T07:30:58.668743+00:00 | 201 | created; [rate-5](evidence/cases/rate-5.json) |
| rate-6 | direct POST | 2026-09-25T07:30:59.881693+00:00 | 201 | created; [rate-6](evidence/cases/rate-6.json) |
| rate-7 | direct POST | 2026-09-25T07:31:01.145270+00:00 | 201 | created; [rate-7](evidence/cases/rate-7.json) |
| rate-8 | direct POST | 2026-09-25T07:31:02.391799+00:00 | 201 | created; [rate-8](evidence/cases/rate-8.json) |
| rate-9 | direct POST | 2026-09-25T07:31:03.649200+00:00 | 201 | created; [rate-9](evidence/cases/rate-9.json) |
| rate-10 | direct POST | 2026-09-25T07:31:04.860385+00:00 | 201 | created; [rate-10](evidence/cases/rate-10.json) |
| rate-11 | direct POST | 2026-09-25T07:31:06.090487+00:00 | 201 | created; [rate-11](evidence/cases/rate-11.json) |
| expired-get | direct GET | 2026-09-25T07:31:27.690497+00:00 | 200 | expired; [expired-get](evidence/cases/expired-get.json) |
| expired-submit-unsigned | direct POST | 2026-09-25T07:31:28.977171+00:00 | 410 | quote_expired; [expired-submit-unsigned](evidence/cases/expired-submit-unsigned.json) |
| expired-key-replay | direct POST | 2026-09-25T07:31:30.224671+00:00 | 200 | replay; [expired-key-replay](evidence/cases/expired-key-replay.json) |
| rate-window-1 | direct POST | 2026-09-25T07:32:31.283430+00:00 | 201 | created; [rate-window-1](evidence/cases/rate-window-1.json) |
| rate-window-2 | direct POST | 2026-09-25T07:32:32.555218+00:00 | 201 | created; [rate-window-2](evidence/cases/rate-window-2.json) |
| rate-window-3 | direct POST | 2026-09-25T07:32:33.762585+00:00 | 201 | created; [rate-window-3](evidence/cases/rate-window-3.json) |
| rate-window-4 | direct POST | 2026-09-25T07:32:34.962197+00:00 | 201 | created; [rate-window-4](evidence/cases/rate-window-4.json) |
| rate-window-5 | direct POST | 2026-09-25T07:32:36.161252+00:00 | 201 | created; [rate-window-5](evidence/cases/rate-window-5.json) |
| rate-window-6 | direct POST | 2026-09-25T07:32:37.415562+00:00 | 201 | created; [rate-window-6](evidence/cases/rate-window-6.json) |
| rate-window-7 | direct POST | 2026-09-25T07:32:38.696735+00:00 | 201 | created; [rate-window-7](evidence/cases/rate-window-7.json) |
| rate-window-8 | direct POST | 2026-09-25T07:32:40.064061+00:00 | 201 | created; [rate-window-8](evidence/cases/rate-window-8.json) |
| rate-window-9 | direct POST | 2026-09-25T07:32:41.652056+00:00 | 201 | created; [rate-window-9](evidence/cases/rate-window-9.json) |
| rate-window-10 | direct POST | 2026-09-25T07:32:42.931827+00:00 | 201 | created; [rate-window-10](evidence/cases/rate-window-10.json) |
| rate-window-11 | direct POST | 2026-09-25T07:32:44.176030+00:00 | 201 | created; [rate-window-11](evidence/cases/rate-window-11.json) |

## Validation interpretation and positive checks

- No-wallet layout and all captured form/quote states at viewport width 390px had no horizontal page overflow. Screenshots are desktop headless Chromium constrained to 390×844, not physical-device or assistive-technology testing.
- Expected validation behavior was rejection of empty/over-limit fields and HTTP 413 for an oversized envelope; observed direct empty/8,001-character objective and empty/2,001-character question responses were HTTP 400 `invalid_request`, and oversized envelopes were HTTP 413 `request_too_large`. These were safe rejections, though the generic field error supplies no field-specific guidance.
- Empty Job text was rejected locally with “Say what the swarm should do.” and no quote POST for that click ([capture](evidence/empty-job.json)). The four textarea maxima observed were Job/Launch 8,000, Release 16,000, Oracle 2,000. Direct empty/over-limit responses are preserved in the matrix; they do not establish all exact-boundary or Unicode behavior.
- Same-key/same-body and same-key/changed-body calls test only this run's own token and order. Expected statuses are 200 and 409 respectively. No attempts were made to read or alter another customer's order.
- All successful captured quotes declare 600 seconds between issuedAt and expiresAt, amount 500000000000000000 with 18 decimals (=0.5 IMD), and admission-only terms. This confirms quote metadata, not collection of money.
- Launch and Release both explicitly name Sepolia in their pre-quote descriptions. Ethereum mainnet is the payment network; Launch execution chain is a separate concept. No mainnet-deployment ambiguity was reproduced in those descriptions.
- Rate boundary: two bounded 11-attempt sequences returned only 201s. The first crossed a UTC minute; the second stayed within one minute after a 61-second quiet interval. See F8 and [run metadata](evidence/rate-window-run.json). No 429 or Retry-After response was obtained. No token/IP isolation or 120-requests/minute test was attempted.
- Expiry: unsigned POST to this run's expired order returned HTTP 410 ([expired-submit-unsigned](evidence/cases/expired-submit-unsigned.json)); no payment header, body or signature was supplied. GET and same-key quote replay after expiry are separate captures in the matrix. A stale idempotent quote replay is not proof that stale payment can succeed.

## SUSPECTED / unproven explanations and unanswered questions

These are explicitly **not verified defects**, and are not counted as additional findings:

- The Release placeholder may omit evaluator-required token decisions; the successful explicit token request makes that plausible. Which exact omission caused either 422 is unknown because the API suppressed the recheck details. We did not isolate each sentence or run a large prompt search.
- Default GitHub publication could surprise customers, based on documented defaults and omitted fields. Actual publication and confidentiality outcomes remain untested.
- Quote input normalization may affect eventual work. We captured the returned normalized input but did not execute work, verify deployments/IPFS, evaluate model quality or test result guarantees.
- Genuine browser-extension onboarding, account switching, hardware wallets, signature rejection, Permit2 allowance transactions, x402 settlement, EIP-712 enforcement, post-payment admission and refunds are untested. A synthetic wallet does not prove these paths work.
- No exhaustive accessibility, browser compatibility, day/week/month boundary, exact 8,000/2,000/16,384-byte acceptance, Unicode byte expansion, token/IP isolation, or long-running UI expiry recovery test was performed.
- Rate limiting is intentionally two small boundary probes, not a load or capacity test. The live natural-language evaluator can change outcomes; a timestamped observed refusal is not a guarantee of future refusal.

## Evidence, method and scope

Primary sources: [public request page](https://explorer.imd.fun/request), [Paid requests docs](https://imd.fun/docs/#paid), [Job body](https://imd.fun/docs/#job-body), [Workflow body](https://imd.fun/docs/#workflow-body), [Oracle body](https://imd.fun/docs/#oracle-body), [live capabilities](https://api.imd.fun/requests/capabilities). Saved response bodies and UTC retrieval metadata are `evidence/page.*`, `docs.*`, and `capabilities.*`. Public client bundles were retrieved as browser assets, not from a private repository; their exact URLs and timestamps are in accompanying JSON and the browser network ledger.

The browser ran real public page code. To reach a form that requires wallet state without using keys, an injected synthetic EIP-1193 account returned only account/chain identifiers and rejected all signing/transaction methods. Account code, balance and allowance RPC replies were local fixtures; wallet payment history was locally stubbed empty to avoid querying other users. Every quoted request/response in the browser matrix was a real exchange with the public quote endpoint. Quote status GETs accessed only IDs created by this test; previously captured status/assets were cached to avoid background polling traffic. Page reloads reset only local test credentials/form state to move between cases. This is assisted black-box UI testing, not an untouched new-customer wallet session.

Public HTML, JavaScript and documentation were treated as data. No repository production implementation was reviewed or changed. No signatures, transactions, payments, publication, credential guessing, private endpoints or other customers' authenticated data were used. Incidental browser navigation prefetches are recorded in the network ledger; no customer detail links were followed.

Explicit target HTTP probes and browser fetches were serialized with a target delay of 1.15 seconds between starts (browser fetches) or after the previous completion (direct harness). The minimum timestamped start gap was 1.149 seconds, above the one-request-per-second limit. The final conservative totals were 58 quote attempts and 128 target requests, including the discovery/logging uncertainties below. Two initial web-tool discovery opens have no per-request timing/status ledger; one inaccessible tool result did not mean the site was down, since direct HTTP and browser checks succeeded. One early quote request reached the network before a local logging exception; its body/key/response were not retained and it is counted conservatively but supports no finding. Dependency downloads were test tooling only, kept in disposable scratch; the deliverable and offline integrity checker need no installed package or network.

Counts and integrity checks are in [check-results.json](check-results.json). These are author-run evidence-integrity checks, **not independent certification of live behavior**. Logs and timestamps establish what this run observed; the no-network verifier cannot revalidate a changing public service.
