pit: page the endings list instead of stopping at 200 - #174
Merged
Conversation
`GET /api/moshpit/tlds` answered with 200 rows and nothing saying it had stopped. `?limit=` and `?offset=` were parsed on the `?q=` branch and ignored on every other one, so asking for page two returned page one — which is indistinguishable from a registry that holds exactly 200 things. The failure that produces is not a missing feature. A client reads "absent from the list" as "nobody holds it", and acts on that. The same list read through `?mine=1` was already complete, so the two disagreed about what exists and neither said which to believe. Every answer now carries `total`, `limit` and `offset`. The default page stays 200 so nothing that reads this today sees different rows, and the reported limit is the one applied rather than the one asked for. `?mine=1` stays unpaged by default — it was the call telling the whole truth, and giving it a default page size would have moved the bug rather than fixed it — but it pages when asked. listTlds gains the `created_at DESC, tld` tiebreak listTldsForUser already documents. A bulk claim writes one timestamp across every ending in it, so created_at is not a total order, and a page boundary landing inside a batch repeats one ending and skips another. Paging the list at all required fixing that first. `?limit=` is capped at 1000. Without a ceiling it is a way to ask for every row in the table, which is what the pager exists to avoid. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
vu1nz Security Review0 finding(s) in PR #? No security issues found. |
ralyodio
marked this pull request as ready for review
August 1, 2026 04:24
Merged
ralyodio
added a commit
that referenced
this pull request
Aug 1, 2026
install.sh resolves releases/latest, so the ten commits merged since v0.14.0 have been sitting on main unreachable — including the reason `curl <name>` did not work. The headline is parking. A parked name always resolved somewhere, but the address it pointed at was a host that routes by Host header and answers "Application not found" for a name it has never heard of, so `curl scrambled.eggs` resolved and then died one layer up (#180). It could not be fixed there: the platform rejects a Moshpit ending as a custom domain and no public CA will certify a TLD outside the DNS root. The bridge is already running locally for the name to resolve at all, so it now serves the answer too — parked names point at loopback and a catch-all responder 302s them to the Pit. Underneath that was a quieter one. fetchTlds read the first page of the ending list and stopped; the registry answers 200 rows and reports the real total, but 200 rows look exactly like a complete list of 200. `.eggs` sat past that line, so `dns install` wrote a config that did not route it and the name failed to resolve — a DNS-shaped symptom three layers from the cause. It was hiding 94% of the namespace: 3707 endings, 200 visible (#181). Also here: dns resolve now reports a parked name's page in the Pit instead of an IP that answers for nobody, with --open to go there (#179) the pit's /n/ pages are crawlable — robots.txt, a generated sitemap, and canonical tags that name the pit host rather than the app host it shares a service with (#175, #176) the claim box takes a whole name, claiming the ending first when it is free and minting the name under it (#173) the endings list pages instead of stopping at 200 (#174), the paste field reads names as well as endings (#172), related endings keep the name you are reading (#177), and integrations ship JSON support matrices (#178) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
GET /api/moshpit/tldsreturned 200 rows and nothing in the response said it had stopped there.?limit=,?offset=,?page=and?cursor=were all accepted and silently ignored — parsed on the?q=search branch, dropped on every other one — so asking for page two returned page one.That is indistinguishable from a registry that holds exactly 200 endings.
This is not a cosmetic gap. A client reads "absent from the list" as "nobody has claimed it" and acts on it. Meanwhile
?mine=1returned the complete list, so the two views disagreed about what exists and nothing in either said which to believe. On an account holding 3,684 endings, the plain list showed 5% of them and looked complete.The fix
Every answer now carries
total,limitandoffset:{ "total": 3684, "limit": 200, "offset": 0, "tlds": [ ... ] }limitis the one applied, not the one asked for.?mine=1stays unpaged by default. It was the one call telling the whole truth; giving it a default page size would have moved the bug rather than fixed it. It pages when explicitly asked.?limit=is capped at 1000. Without a ceiling it is a way to ask for every row in the table, which is what a pager exists to avoid.?limit=abc,0,-5,?offset=-1) falls back to the default page rather than erroring or returning nothing.The ordering, which had to be fixed first
listTldsordered bycreated_at DESCalone. A bulk claim writes one timestamp across every ending in it, socreated_atis not a total order — a page boundary landing inside a batch shows one ending twice and skips another entirely.listTldsForUseralready documents this and carries the, tldtiebreak.listTldsnow does too. Paging a list ordered by a non-unique key is how you get a pager that silently loses rows, so this was a prerequisite rather than a tidy-up.Tests
New
test/moshpit-tlds-pagination.test.mjs— 6 tests, and all 6 fail againstmainand pass with this change (verified by checking out the old sources and re-running). Coverage: the total is reported, limit/offset are obeyed, paging the whole list start to finish loses nothing and repeats nothing (the tiebreak case, using 260 endings that share one timestamp), the ceiling caps, junk falls back, and?mine=1stays whole.Full
apps/pwasuite: 337 pass, 0 fail, 0 skipped.🤖 Generated with Claude Code