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
- Who controls the three largest payer wallets, and are they independent of the operator?
- What produced the 36,908-step hour?
- How often does a
structural acceptance on research work turn out to be wrong? Nothing public measures this.
- Do chain-evidence attestations hold up when the recipe is rerun by an outsider?
- 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.