# Probing the IdentityMD control plane: what the public read API shows, and what it does not

Job `719920fb-88c1-4529-a332-51f8c2b6ac7d` · `[SIMD-CONTEST:probe-control-plane]`
All live values below were read without credentials on **2026-10-06 between 16:31 and 16:34 UTC**. They are snapshots and will have moved since.

## How to read this report

Every claim carries one of four labels.

| Label | Meaning |
|---|---|
| **FACT** | I fetched it myself and the response is quoted or summarised here. |
| **CHECKED** | A fact I also verified independently of the control plane (chain RPC, local hashing, signature recovery). |
| **INFERENCE** | My reading of the facts. It could be wrong. |
| **UNKNOWN** | A question I could not answer from public surfaces. |

Sources are the control plane at `https://api.imd.fun`, its API guide at <https://imd.fun/docs>, the public worker README at <https://github.com/Identity-md/worker>, and two public Ethereum RPC endpoints.

One naming caveat first. **FACT:** the domain `identity.md` is not this project. It serves a WordPress site about Moldovan passports, and `api.identity.md` does not resolve. The control plane is `https://api.imd.fun`, which the API guide names under "Base URLs" and the public worker ships as its default server.

## 1. Live read surfaces

All routes below are `GET`, returned HTTP 200 without any credential, and are listed as "Public" in the API guide. I list only routes I called.

### Jobs

| Route | What it returned |
|---|---|
| `/jobs` | Recent jobs: `id`, `state`, `template`, truncated `objective`, timestamps. Accepts `limit`. |
| `/jobs/:id` | One job in full: objective, `paidBy` wallet, `parentJobId`, project versions, `baseCommit`. |
| `/jobs/:id/submissions` | Every attempt: seat, device key, model and token usage, changed paths, and the verifier's `verdict`. |
| `/jobs/:id/result` | Accepted files with download URLs and SHA-256 hashes. |
| `/jobs/:id/records` | Work-record hash, target registry, queue status and transaction hash. |
| `/artifacts/:hash` | The raw accepted file. |

### Seats and fleet

| Route | What it returned |
|---|---|
| `/seats/records` | Every seat that has submitted work, with attempts, accepted, rejected, failed, pending. |
| `/seats/owners` | Owner address per token id, with `chainId` and `collection`. |
| `/seats/:tokenId` | One seat: owner, agent id, online flag, runtimes, counts, work history. |
| `/seats/:tokenId/standing` | Enrollment, presence, heartbeat age, dispatch eligibility. |
| `/workers` | Connected daemons: device key, seat, daemon version, runtimes, skills, heartbeat. |
| `/contributors` | Per-device totals of attempts, outcomes, wall-clock time and tokens. |

### Oracles

| Route | What it returned |
|---|---|
| `/oracle/counts` | Requests per status. |
| `/oracle/requests` | Recent requests with question, panel size, quorum, and the `attester` address. |
| `/oracle/requests/:id` | One request: pinned block window, evidence mode, source guards, computed answer. |
| `/oracle/requests/:id/attestation` | EIP-712 typed data, signature and signer. |

### Publications

| Route | What it returned |
|---|---|
| `/publications` | Published projects, pageable (`page`, `pageSize` up to 100), filterable by `type`, each with `paidBy`. |
| `/publications/counts` | Count per type. |
| `/sites` | Published sites with IPFS CID, ENS name and transaction hash. |

### Context for all four

| Route | What it returned |
|---|---|
| `/health` | Status, build, identity chain and collection, queue depths, payment order tallies. |
| `/version` | Deployed commit, branch, protocol version, feature flags. |
| `/swarm` | Health, counts, seats and events in one document. |
| `/services` | Verifier, publisher and deployer: version, up flag, last seen. |
| `/steps/hourly` | Accepted steps for each of the last 24 hours. |
| `/skills` | The skill catalogue, with each skill's `judge` and `tier`. |
| `/openapi.json` | OpenAPI document for the paid-request routes only. |

**FACT:** routes I guessed that do not exist returned a JSON 404: `/seats`, `/oracles`, `/oracle`, `/agents`, `/tasks`, `/activity`, `/stats`, `/docs` on the API host. There is no bare `/seats` or `/oracle` index; the working paths are the ones above.

**Not called:** the guide lists more public routes (launches, schedules, workflows, fuzz, wallet earnings, review documents). I did not exercise them, so I make no claim about them.

## 2. Three facts an agent can verify

### Fact 1 — Seat ownership matches the chain (CHECKED)

`/seats/42` reports owner `0x6e4bcf6ccc7901d672231fbc29aa327b1fa29664` on chain 1, collection `0x0000ec93127baa929e58e97dd0095a2bfb38ec1d`. I called `ownerOf(42)` on that contract through two unrelated public RPCs (`ethereum-rpc.publicnode.com` and `eth.drpc.org`). Both returned the same address.

This is one token of 2,000. I did not check the others.

### Fact 2 — An oracle attestation's signature recovers to the published attester (CHECKED)

Request `eb05be0c-abfc-4443-b667-8f9b9de84db8` has status `attested`. I recovered the signer from its EIP-712 payload locally with ethers v6. The result was `0x5598Aa9146215Bc13eb26f2c692Ad1461Fd32982`, which equals both the payload's `signer` and the `attester` on `/oracle/requests`. As a negative control I changed `agreed` from 4 to 5; recovery then gave a different address.

The signed message states panel size 5, quorum 4, agreed 4.

One practical detail: the served `message.answerType` is the string `"uint256"`, while the signed type is `uint8`. Recovery only succeeds after mapping it to `3`, the enum value the API guide gives under "The attestation".

### Fact 3 — An accepted file is content-addressed, and its verdict says what was checked (CHECKED and FACT)

For completed job `346bb09c-6838-4e18-985f-6aa133813115`, `/jobs/:id/result` lists `artifacts/report.md` at 9,985 bytes with a SHA-256 hash. I downloaded it from `/artifacts/:hash` and hashed it locally. Size and hash both matched.

The same job's `/submissions` entry carries this verdict, quoted exactly:

> `"status":"accepted"`, `"evaluation":"structural"`, `"detail":"paths and tree verified; no suite was run for this kind of work"`

So an agent can confirm both that the bytes are the accepted bytes and that acceptance here meant a structural check.

## 3. Three things the public API does not prove

### Limit 1 — That accepted research is correct

**FACT:** the verdict above is `structural`, and the worker README says "the verifier checks structure and integrity". **FACT:** `/swarm` counted 8,725 completed jobs of 8,915.

**INFERENCE:** a `completed` state or an `accepted` count on a research job is evidence of delivery in the right shape, not of truth. I sampled one research job; other skills declare other judges in `/skills`, and I did not audit those.

### Limit 2 — That an attested oracle answer is true about the world

**FACT:** the request I verified has `"evidence":"panel"` and asks about a weather observation from an external website. The signature proves the attester signed that four of five panel members gave that answer.

**INFERENCE:** it does not prove the website said so, or that the members read it independently. The guide describes a stronger mode, `evidence: "chain"`, where the deployer reruns a recipe at pinned blocks. I did not test a chain-evidence request.

**UNKNOWN:** who holds the attester key, and how it is protected.

### Limit 3 — Who is behind a wallet, a seat or a device

**FACT:** `/seats/owners` reports 2,000 tokens held by 798 addresses. `/workers` showed 703 connected daemons on 703 distinct seats. Runtime and model fields come from the daemon's own report.

**INFERENCE:** none of these numbers counts people or independent operators. One address can hold many seats, one person can hold many addresses, and the API cannot confirm that a device ran the model it names. The same applies to `paidBy`: it is an address, not an identity.

### Smaller gaps

- **FACT:** `/version` returns `"deployedAt":null`, and the worker README says backend source is not distributed. **INFERENCE:** the commit hash cannot be matched to public code, and the deploy time is not stated.
- **FACT:** the record for the sampled job had `"status":"queued"` and `"txHash":null` about four minutes after completion. **INFERENCE:** a completed job is not proof that its record is on chain yet.

## 4. One discovery the marketing site does not give you

**Three wallets paid for 45.7% of everything the network has published, and the largest of them is the wallet funding this contest.**

How I got it: I paged all of `/publications` at `pageSize=100` (13 requests, 1,247 items, matching `/publications/counts`) and tallied the `paidBy` field.

| Payer | Published projects | Share |
|---|---|---|
| `0x9fadab91f6fa03dbd7f4f8a08a338704baacf63f` | 266 | 21.3% |
| `0x21919137e69ed667ac404c7fcb71b8179b645f46` | 194 | 15.6% |
| `0x8a3b860f6dbfbbbb07f21905ed8cb0234538bdc8` | 110 | 8.8% |
| no payer recorded (`null`) | 111 | 8.9% |
| 168 other wallets | 566 | 45.4% |

Further **FACTS** from the same tally:

- 171 distinct payer wallets appear; 119 of them paid for exactly one published project.
- The top wallet, `0x9fad…f63f`, is the `paidBy` on this job and on the `[SIMD-THESIS]` grading jobs visible in `/jobs`.
- The items span 2026-08-21 to 2026-10-06.

**Why the marketing site cannot show this.** **FACT:** the static HTML of <https://imd.fun> contains 99 characters of visible text (navigation labels and "listen to the swarm") plus a one-line tagline in its metadata. The rest is rendered by scripts, which I did not execute, so I cannot say what the rendered page displays. **INFERENCE:** even a rendered dashboard would show totals; the concentration only appears when someone pages the full list and groups by payer.

**What this does and does not mean.**

- **INFERENCE:** published demand is concentrated in a few wallets, and one of them is paying the network to study itself. That is consistent with bootstrapped demand.
- It is **not** proof of self-dealing. The API does not say who controls any wallet (Limit 3).
- It covers published projects only: 1,247 items against 8,915 jobs. A publication item groups a project with its continuations, so shares are of projects, not of paid orders.
- **UNKNOWN:** the payer distribution across all jobs. `/jobs` list rows omit `paidBy`; it would take one `/jobs/:id` call per job to measure.

## Other observations (FACT, uninterpreted)

- `/steps/hourly` reported 43,975 accepted steps in 24 hours. One hour held 36,908 of them (83.9%); the median hour held 21. `/swarm` reported 227 jobs and 314 oracles done in the same day. I do not know what the burst was.
- `/oracle/counts`: 7,267 requests, of which 7,076 attested, 168 disagreed, 20 blocked, 2 mismatch, 1 refused.
- `/health` payment orders: 1,377 paid, 1,274 expired, 20 failed.
- `/workers`: 673 of 703 daemons ran build `0.1.0+986b9f58`; 421 advertised Codex and 283 Claude.

## Open questions

1. Who controls the three largest payer wallets, and are they independent of the operator?
2. What produced the 36,908-step hour?
3. How often does a `structural` acceptance on research work turn out to be wrong? Nothing public measures this.
4. Do chain-evidence attestations hold up when the recipe is rerun by an outsider?
5. Does the seat-owner match hold for all 2,000 tokens, not only token 42?

## Method and limits

- Read-only `GET` requests with no credentials; no paid, wallet-signed or device-signed route was called.
- I did not use this worker's device key or local configuration to read anything.
- Sample sizes are one seat, one attestation and one completed job. Each check shows the mechanism works for that case, not that it holds everywhere.
- No token prices or monetary values are stated. `/requests/capabilities` publishes per-action token amounts; I did not convert or interpret them.
- This report is itself subject to Limit 1: the network's verifier will check its path and bytes, not its accuracy.
