Skip to content

pit: claim a pasted list of endings - #138

Merged
ralyodio merged 3 commits into
mainfrom
feat/bulk-tld-paste
Jul 31, 2026
Merged

pit: claim a pasted list of endings#138
ralyodio merged 3 commits into
mainfrom
feat/bulk-tld-paste

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Claiming happened one ending at a time — fine for the one you just thought of, hopeless for the forty in a spreadsheet. Adds a textarea on /pit?tab=yours that takes the list as pasted.

Forgiving about shape, on purpose

The source is a text field, so people paste columns, CSV exports, and hand-typed lines with the dot already on. All of these work without reformatting:

.eggs
yeah, oranges
EGGS            # deduped with .eggs — one claim, not a collision with yourself
# commented-out rejects can stay in the list and be re-pasted

Newlines, commas and semicolons all separate. Leading dots optional. # comments to end of line.

Partial success is the normal case

Any real list has a few someone already holds. Every ending is attempted and reported on, rather than stopping at the first collision with the rest silently unattempted:

claimed 3 — .eggs, .yeah, .oranges. 1 taken by someone else (.taken).
2 rejected (.bank — that name is reserved; .a — a TLD needs at least 2 characters).

Reasons rather than a bare count, since reserved and too short need different fixes. Re-pasting your own list reads as already yours, not as a collision.

Two deliberate constraints

  • Sequential, not parallel. moshpit_tld_log is the record of who claimed what first; interleaving a batch's writes makes that ordering meaningless for the endings inside it.
  • Capped at 200 per paste, with anything past the cap counted and reported rather than silently dropped — a pasted spreadsheet column is exactly the shape of input that becomes ten thousand INSERTs by accident.

Verified

15 new tests — parser pure, claiming against a real throwaway libSQL database, because partial success is the behaviour and a stub would paper over it. 230/230 across the pwa suite.

Also exercised through the real HTTP stack: booted the server, made a session, POSTed the mixed list above with CSRF, and confirmed the flash message, that .taken stayed with its original owner, and that EGGS/.eggs deduped to one row.

🤖 Generated with Claude Code

Claiming happened one ending at a time, which is fine for the one you just
thought of and hopeless for the forty in a spreadsheet. A textarea on
/pit?tab=yours takes the list as pasted.

Forgiving about shape on purpose, because the source is a text field: newlines,
commas and semicolons all separate, leading dots are optional, `#` starts a
comment to end of line, and case and dots fold together so `.Eggs`, `EGGS` and
`eggs` are one claim rather than one claim and two collisions with yourself.
Commenting out the rejects and re-pasting is meant to work.

Partial success is the normal outcome, not the error case — any real list has a
few someone already holds. Every ending is attempted and reported on, rather
than stopping at the first collision with the rest silently unattempted, and
the flash names what happened:

  claimed 3 — .eggs, .yeah, .oranges. 1 taken by someone else (.taken).
  2 rejected (.bank — that name is reserved; .a — a TLD needs at least 2 characters).

Reasons rather than a bare count, since "reserved" and "too short" need
different fixes. Re-pasting your own list reads as "already yours", not as a
collision.

Claimed sequentially, not in parallel. moshpit_tld_log is the record of who
claimed what first, and interleaving a batch's writes makes that ordering
meaningless for the endings inside it. Capped at 200 per paste, with anything
past the cap counted and reported — a pasted spreadsheet column is exactly the
shape of input that becomes ten thousand INSERTs by accident.

15 tests: the parser pure, the claiming against a real throwaway libSQL
database, since partial success is the whole behaviour and a stub would paper
over it.

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

Copy link
Copy Markdown

vu1nz Security Review

0 finding(s) in PR #?

No security issues found.

ralyodio and others added 2 commits July 31, 2026 09:13
Claiming a list left forty endings with no price and nowhere to point, and
forty follow-up edits to fix that. Both knobs an ending already has on its own
row are now offered at the moment you claim it, and apply to everything the
submission lands.

Blank means leave it alone, not clear it. No price leaves an ending unlisted
rather than free — NULL is "not for sale", and 0 would let anyone drain the
namespace.

A settings failure does not lose the claim. The ending is already registered by
then, and dropping a batch of forty because one price had a typo would be worse
than landing forty with no price on them; the failures are reported instead.

Pointing a list at an ending that is inside the list skips itself rather than
erroring — that is just what pasting a list containing its own target looks
like.

The single-ending form goes through the same path, so the settings behave
identically either way instead of being a bulk-only feature. It still says
".eggs is yours." rather than "claimed 1 — .eggs.", since one ending typed into
one box is the commonest path through this page.

8 more tests. 238 across the pwa suite.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claiming an ending left it unpriced, which means invisible to every buyer.
"I claimed forty and nobody could buy a name under any of them" is the failure
that costs something, so the field arrives filled in.

$1.99 rather than a round $2, because that is the cap PRD 0005 sets for a child
name's annual price (§5, §10.1, R3) and this column is exactly that price —
what someone pays to mint `me.whatever`. A one-time Buy Now resale is a
transfer of ownership rather than a term and is uncapped by §10.2.4; it is not
this field.

The cap is exported and the number input carries it as `max`, but setTldPrice
does not enforce it. That requirement arrives with terms, renewals and the
ledger, and this column already holds prices set before any cap existed —
enforcing it now fails six passing sales tests and is a migration, not a
validation tweak.

Clearing the field still means not for sale. The default is an opinion, not a
floor: 1 cent is accepted, and so is nothing.

243 across the pwa suite.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ralyodio
ralyodio merged commit 1d2f1e1 into main Jul 31, 2026
3 checks passed
@ralyodio ralyodio mentioned this pull request Jul 31, 2026
ralyodio added a commit that referenced this pull request Jul 31, 2026
* chore(release): v0.13.3

install.sh resolves releases/latest, so everything merged since v0.13.2 has
been sitting on main unreachable — `moshcode dns enable` exists in the source
and not in anyone's binary.

The headline is the DNS bridge (#141). Moshpit names now resolve for every
program on the machine, not just inside TronBrowser: each OS gets the mechanism
that routes ONE SUFFIX rather than the one that replaces the resolver —
/etc/resolver on macOS, systemd-resolved routing-only domains or dnsmasq on
Linux, an NRPT rule per namespace on Windows.

  moshcode dns enable / disable / status
  moshcode uninstall <engine|tool>          (#150, completion in #151)

The pit gained most of a namespace registry in between: key pins per name
(#137), pasted bulk claiming with per-line price and target (#138, #142, #143,
#146), all-numeric endings (#147), /n/<name> serving a name or a directory
(#145, #149), and Buy Now on an unclaimed name (#148).

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

* chore: restore the em-dash the version bump escaped

The bump rewrote package.json through a JSON serialiser that defaults to ASCII,
turning the em-dash in `description` into —. Valid JSON and the same string
once parsed, but a gratuitous diff in a commit that should touch one line.

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

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ralyodio
ralyodio deleted the feat/bulk-tld-paste branch August 8, 2026 17:05
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