fix: stop reporting nhs.uk and police.uk names as unregistered

Like ac.uk, these suffixes aren't run by Nominet, whose RDAP server (the only one IANA lists for uk) answers 404 for names under them, so england.nhs.uk and met.police.uk came back as available. Nominet's WHOIS says outright that it isn't the registry for them. Their operators publish neither RDAP nor WHOIS, so list them as sub-registries with no servers: lookups now fail with no_server instead of guessing (whoisHints can still name a server).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
jakeandClaude Opus 5.5 committed 2026-10-03 16:45:57 -04:00
1 parent a14f8a245b
commit 6710a2878f
4 files changed
+26

No files matched your search

+12
View File
@@ -221,6 +221,18 @@ describe("error reporting", () => {
expect(vi.mocked(whoisQuery)).toHaveBeenCalledTimes(1);
});
it("doesn't read the TLD registry's 404 as unregistered for a suffix it doesn't run", async () => {
// Nominet's RDAP (listed for uk) answers 404 for nhs.uk names it doesn't hold
const customFetch: FetchLike = vi.fn(async () => new Response("", { status: 404 }));
const res = await lookup("england.nhs.uk", {
customBootstrapData: { ...bootstrap, services: [[["uk"], ["https://rdap.nominet.uk/uk/"]]] },
customFetch,
});
expect(res).toMatchObject({ ok: false, errorCode: "no_server" });
expect(customFetch).not.toHaveBeenCalled();
expect(vi.mocked(whoisQuery)).not.toHaveBeenCalled();
});
it("reports the last RDAP failure's own code", async () => {
const customFetch: FetchLike = vi.fn(async () => new Response("down", { status: 500 }));
const res = await lookup("example.com", {
+7
View File
@@ -26,3 +26,10 @@ test("SUB_REGISTRIES points each suffix at its own CentralNic RDAP path", () =>
test("SUB_REGISTRIES sends ac.uk to Jisc's WHOIS, with no RDAP", () => {
expect(SUB_REGISTRIES["ac.uk"]).toEqual({ whois: "whois.ja.net" });
});
test("SUB_REGISTRIES keeps nhs.uk and police.uk names away from Nominet", () => {
// Nominet's RDAP answers 404 for them, which would read as "not registered"
expect(SUB_REGISTRIES["nhs.uk"]).toEqual({});
expect(SUB_REGISTRIES["police.uk"]).toEqual({});
expect(getSubRegistrySuffix("england.nhs.uk")).toBe("nhs.uk");
});
+4
View File
@@ -47,6 +47,10 @@ export const SUB_REGISTRIES: Readonly<Record<string, SubRegistry>> = {
// Jisc runs ac.uk. Nominet's RDAP answers 404 for its names (which reads as "not registered"),
// and Nominet's WHOIS answers with the ac.uk delegation itself.
"ac.uk": { whois: "whois.ja.net" },
// Nor does Nominet hold nhs.uk or police.uk names ("Nominet is not the registry for this domain
// name"), and their operators publish neither RDAP nor WHOIS
"nhs.uk": {},
"police.uk": {},
};
/** The sub-registry suffix a domain falls under (e.g. "uk.com" for google.uk.com), if any. */
+3
View File
@@ -21,6 +21,9 @@ describe("discoverWhoisServer for sub-registry suffixes", () => {
// Nominet's whois.nic.uk answers ac.uk names with the ac.uk delegation itself
expect(await discoverWhoisServer("ac.uk")).toEqual({ server: "whois.ja.net" });
expect(whoisQuery).not.toHaveBeenCalled();
// nhs.uk's operator publishes no WHOIS, and IANA would name Nominet's
expect(await discoverWhoisServer("nhs.uk")).toEqual({});
expect(whoisQuery).not.toHaveBeenCalled();
});
it("still lets whoisHints override it", async () => {