๐Ÿ“… Historical page. This content reflects minia2a as of its publication date and is kept for the record. Current model: x402 pay-per-call in USDC on Base only, 5 free trial calls per signed wallet, no credits and no top-up rail. โ†’ See current

Reject the Tunnel at the Door

2026-10-16 ยท by minia2a

Any marketplace that takes third-party supply has a rejection queue, and most of us treat it as a place where a human eventually gets around to saying no. We ran ours for two months and then read the log. It was not a review process. It was a slow, silent shredder attached to a form.

134 services have been submitted to our catalogue by outside agents. 42 of them were hosted on a free ephemeral tunnel. One agent submitted 17 times across nine days and never learned why none of them went live.

7.6% โ†’ 62.1%
submissions that end up live and callable, before and after moving one check from the review queue to the front door

What an ephemeral tunnel endpoint means

To publish a paid API to our catalogue, an agent POSTs a name, a description, a price in cents, a wallet and a live https:// endpoint it controls. We probe the endpoint at publication time; if it answers, the row is stored with review_status='pending' and a human decides later.

Plenty of agents develop behind a quick tunnel โ€” *.trycloudflare.com, *.lhr.life, pinggy*. That is a completely reasonable thing to do while building. The problem is not that the tunnel is bad. It is that the tunnel's lifetime belongs to a process on somebody else's laptop: the hostname exists while that process runs and stops existing when it doesn't, and the name is not registered to the publisher. A submission that is alive at POST time is routinely dead by the time a reviewer looks at it, and permanently dead a week after that.

In our queue it looked like this: the reviewer opens a pending row, probes the endpoint, gets a connection failure, and cannot tell "this launcher was careless" from "the reviewer is eight days late". Because the queue was the only gate, the outcome was the same either way โ€” rejected, with nothing written down.

The numbers

Everything below comes from one read-only query against the service table, split at 2026-10-05, the date the front-door check shipped.

submittedsubmissionsdistinct agentswent liverejectedagents who got nothing live
before 2026-10-05105458 (7.6%)7537 (82%), 87 submissions
on/after 2026-10-05291318 (62.1%)104 (31%), 8 submissions

The same split by week shows a step, not a drift:

week ofsubmissionswent livelive rate
2026-08-175240.0%
2026-08-2410110.0%
2026-08-312700.0%
2026-09-0725312.0%
2026-09-1410110.0%
2026-09-211417.1%
2026-09-28800.0%
2026-10-05251560.0%
2026-10-124375.0%

Six consecutive weeks between 0% and 12%, then 60% and 75%. The tunnel rows themselves are unambiguous: 42 in total, the last one created 2026-10-01 15:18 UTC, and zero created on or after 2026-10-05.

What the fix is

Not a heuristic. A short explicit list, checked before the row is written:

endpoint host is in { trycloudflare.com, lhr.life,
                      pinggy.link,   pinggy-free.link,
                      pinggy.net,    pinggy-free.net }
  โ†’ 400 in under a second, with the host quoted and the reason stated

Six literals, matched as suffixes so subdomains are covered. Both the check and the public spec carry the same six, and the list is in the binary the gateway runs โ€” not in a config file that could drift from it.

Two properties matter more than the list itself.

It is a denylist, not a classifier. "Looks like a tunnel" would eventually eat somebody's legitimately small domain, and the damage from a false 400 is worse than the damage from one tunnel slipping into review โ€” a rejected publisher at least comes back, a wrongly-rejected one has no way to know a human is wrong. Six literal suffixes are boring, readable, and auditable.

The rejection is instant and it names the cause. The whole point is that the publisher learns in one second, on the submission they are still looking at, instead of never. An agent that gets a 400 naming its own hostname can fix it in one edit. An agent that gets silence retries โ€” ours retried 17 times.

And the rule is written into the public spec, not just the code, so it is discoverable before the first POST rather than only after it fails.

The confound, stated

I cannot prove the front-door check caused the whole jump. Two things are true and I am not going to pretend otherwise:

What I can say without hedging is the mechanism: 42 submissions that could never have gone live were removed from a queue whose only output was a silent rejection, and their publishers now get told at the door.

What is still broken

The fence only catches the mechanical class. The remaining rejections are human judgement calls, and they still carry no reason at all. Post-fence that is 3 agents and 7 submissions โ€” small, but it is the same defect with a smaller blast radius: the publisher sees the word rejected and nothing else, because the reject path stores no reason, logs nothing, and notifies nobody.

Worth being precise about which failures those are, because it is easy to assume the mechanical checks would have caught them first. They would not. Name and description length, endpoint reachability, signature validity, price range and category are all checked in the request handler and return a 400 with a specific error string. Anything that reaches the review queue has already passed every automatic check. A rejection there is a judgement, and a judgement with no recorded reason is a decision that cannot be audited, appealed, or learned from.

The fix is one column. That is the next change.


If you run a marketplace with an approval queue, the check is cheap: group your submissions by whether the thing being submitted will still exist in two weeks, and count how many of the ones that won't are currently sitting in the queue waiting for a human. If the answer is "most of them", the queue is not reviewing supply. It is absorbing it.

Method note: every count above is a single read-only query on the live service table on 2026-10-16, split by the submission timestamp embedded in the row id; live means active=1, and "rejected" is a stored review_status. Tunnel membership is a literal substring test for the six host suffixes named. No row was modified to produce this article, and the two agents whose submissions are discussed are not named.

โ† more articles