Skip to content

feat(pit): accept a whole name in the claim box - #173

Merged
ralyodio merged 1 commit into
mainfrom
feat/pit-claim-full-name
Aug 1, 2026
Merged

feat(pit): accept a whole name in the claim box#173
ralyodio merged 1 commit into
mainfrom
feat/pit-claim-full-name

Conversation

@ralyodio

@ralyodio ralyodio commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Typing hawaiian.chicken into the claim box on /pit fails with "not a valid TLD — letters, digits and dashes only, no dots".

The box was built for an ending (eggs) and hands its value to registerTlds(), which rejects a dotted token. But holding hawaiian.chicken is just two ordinary steps in order — claim .chicken, then mint hawaiian under it — and the form should do both rather than teaching the order to the visitor.

Change

POST /pit/claim forks when the submitted value parses as a Moshpit name:

  • ending is free → claim it, then mint the name → hawaiian.chicken is yours.
  • ending is already yours → just mint the name
  • someone else's ending → redirect to /pit?name=hawaiian.chicken

That last case is the one this deliberately does not answer itself. Minting under someone else's ending isn't ours to do, and whether the name is for sale, taken, or simply unlisted is a question landingFor() already decides — so it hands over that card instead of growing a second, thinner copy of the same rules in the handler.

A bare ending still goes down the existing list path untouched, and a.b.c is still refused rather than coerced into a name.

The success flash lands on exactly the URL this was aimed at:

/pit?ok=hawaiian.chicken+is+yours.&tab=yours

Verification

npm test in apps/pwa336 pass, 0 fail (5 new, route-level against a throwaway libSQL db using the same harness as moshpit-pit-page.test.mjs):

  • a whole name under a free ending takes both, and the flash names the name
  • a name under an ending you already hold just mints
  • someone else's ending redirects to the card, takes nothing, and doesn't steal the ending
  • a bare ending behaves exactly as before and mints no names
  • a.b.c is still refused

🤖 Generated with Claude Code

The claim box was built for an ending (`eggs`) and hands its value to
registerTlds(), which rejects a dotted token. So `scrambled.eggs` — the
thing people actually type — came back as "not a valid TLD", even though
holding it is just two ordinary steps in order.

POST /pit/claim now forks when the value parses as a Moshpit name: claim
the ending if it is free, then mint the name under it, and report the
name that was asked for rather than the ending it had to take first.

Someone else's ending is the one case this cannot finish — minting under
it is not ours to do. Whether that name is for sale, taken, or simply
unlisted is a question landingFor() already answers, so hand over that
card instead of growing a second, thinner copy of the same rules here.

A bare ending still goes down the existing list path untouched, and a
token that is not a name (`a.b.c`) is still refused rather than being
coerced into one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown

vu1nz Security Review

0 finding(s) in PR #?

No security issues found.

@ralyodio
ralyodio merged commit b0ce432 into main Aug 1, 2026
3 checks passed
@ralyodio
ralyodio deleted the feat/pit-claim-full-name branch August 1, 2026 04:17
@ralyodio ralyodio mentioned this pull request Aug 1, 2026
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant