fix(atproto-lexicon): allow digit-leading NSID authority segments #411

Closed ngerakines.me
targeting main
Closed opened by and assigned to ngerakines.me
targeting main

Closes F-NSID-22.

validate_nsid refused any NSID with a dot-separated segment beginning with a digit, which refuses names that exist on the network: org.4chan.lex.getThing, cn.8.lex.stuff, test.12345.record, and anything under an onion address, which is digit-leading by construction.

An NSID is a domain authority in reversed notation followed by a name, and the two halves have different rules. DNS labels may begin with a digit (RFC 1123 section 2.1), so authority segments may too. Only the first segment is further restricted — it is the TLD — and only the last, which is an identifier rather than a host label and so takes neither a leading digit nor a hyphen.

The cause was expressing all of that as one regex that required every segment to start with a letter. Three rules flattened into one, and the flattening was invisible because the crate's own tests agreed with it: a.b.c and app.bsky.feed.post pass under either reading.

The validator now follows the reference's structure (validateNsid, packages/syntax/src/nsid.ts:89-122) with each rule stated where it applies. That also improves the refusals — a non-ASCII character is now reported as a character-set violation rather than as whichever structural rule it happened to trip first.

Two tests guard the shape of the fix rather than just its effect: one that the exemption reaches neither the first segment nor the name, and one that a hyphen is still refused at either end of any segment. "Digit-leading segments are fine" would be an easy and wrong way to make the six vectors pass.

Closes 7 of the 31 cases pinned in interop_syntax.rs — six vectors, one of which the corpus lists twice. The harness's rot guard is what surfaced them: unpinning was forced by the test, not remembered.

This pull request has no versions submitted yet.