How is-a.dev Enforces Subdomain Naming Conventions: Multi-Layer Validation Explained
is-a.dev guarantees subdomain compliance through a three-tier defense system combining static JSON block lists, automated CI filename validation, and synthetic DNS record generation.
The is-a-dev/register repository manages thousands of free subdomains under the is-a.dev namespace. To maintain DNS integrity and prevent routing conflicts, the project implements rigorous is-a.dev subdomain naming conventions enforced automatically during every pull request via the tests/json.test.js validation suite.
Static Block Lists for Reserved and Internal Names
Globally Reserved Subdomains
The foundation of the naming policy lives in util/reserved.json, a static array of strings representing names prohibited for user registration. This list includes high-risk terms like admin, api, and dev that could create security vulnerabilities or routing ambiguities if claimed by individual users.
Internal System Subdomains
Platform infrastructure names such as www and ns1 are cataloged in util/internal.json. These entries represent subdomains reserved for the service's own operational needs, ensuring that critical DNS records remain under administrative control and cannot be overwritten by user submissions.
Automated CI Validation with validateFileName
Block List Enforcement in Tests
When a contributor opens a pull request, the CI suite in tests/json.test.js (lines 35-36) loads both block lists and validates the proposed subdomain against them:
const internalDomains = require("../util/internal.json");
const reservedDomains = require("../util/reserved.json");
// Validation checks:
t.false(internalDomains.includes(subdomain), `${file}: Subdomain name is registered internally`);
t.false(reservedDomains.includes(subdomain), `${file}: Subdomain name is reserved`);
Any filename matching entries in these arrays triggers an immediate test failure, blocking the merge and preventing namespace collisions.
Syntax and Hostname Compliance
The validateFileName function (lines 96-118 of tests/json.test.js) applies RFC 1123 hostname validation through regex and string analysis. This function enforces the following critical rules:
- Filename structure: Must end with
.jsonand must not contain the literal string.is-a.dev - Character restrictions: All lowercase letters, no consecutive hyphens (
--), and valid hostname characters only - Length limits: Maximum 253 characters per DNS standards
- Root label restrictions: The left-most subdomain label cannot start with an underscore (checked via
t.false(rootSubdomain.startsWith("_"))on lines 17-18) - Suffix protection: Subdomains cannot end with reserved or internal names (verified via
!internalDomains.some(i => subdomain.endsWith('.' + i))on lines 12-15)
Synthetic Record Generation and DNS Guards
Automatic System Record Creation
The util/raw-api.js script (lines 14-54) preemptively generates DNS entries for all internal and reserved names, writing them to raw-api/v2.json before processing user submissions. This ensures protected names always resolve to controlled endpoints, such as CNAME: "internal.is-a.dev" for internal services or URL: "https://is-a.dev/reserved" for blocked terms.
DNS Configuration Enforcement
In dnsconfig.js (lines 142-144), the build process explicitly creates A records for reserved names while ignoring them in public zone generation (lines 166-167). This mirrors the validation logic at the infrastructure layer, preventing edge cases where test-validated files might bypass DNS-level protections.
Practical Examples of Validation
Valid Subdomain Registration
A compliant submission for example.is-a.dev uses the filename example.json:
{
"owner": {
"username": "alice"
},
"records": {
"A": ["192.0.2.10"]
}
}
This passes all checks: lowercase, no double hyphens, valid hostname syntax, and no block list matches.
Invalid: Reserved Name Violation
Attempting to register admin.json fails during CI execution because "admin" appears in util/reserved.json. The test suite outputs: admin.json: Subdomain name is reserved.
Invalid: Underscore in Root Label
A file named _private.json fails the specific check:
t.false(rootSubdomain.startsWith("_"), `${file}: Root subdomains should not start with an underscore`);
The PR is rejected despite passing other hostname regex validations.
Summary
- Static block lists in
util/reserved.jsonandutil/internal.jsondefine prohibited subdomain strings at the repository level. - Automated CI testing via
tests/json.test.jsvalidates filenames against RFC 1123 standards, syntax rules, and block list membership before merge. - Synthetic record generation in
util/raw-api.jsensures reserved names always resolve to platform-controlled endpoints, preventing accidental overwrites. - DNS configuration guards in
dnsconfig.jsapply the same restrictions during zone file compilation, maintaining consistency between validation and deployment.
Frequently Asked Questions
What characters are allowed in is-a.dev subdomains?
Subdomains must use lowercase letters, digits, dots, and single hyphens only. The validateFileName function rejects uppercase characters, consecutive hyphens (--), and underscores in root labels through strict regex validation matching RFC 1123 hostname standards.
Can I register a subdomain that starts with an underscore?
No. The validation code explicitly checks t.false(rootSubdomain.startsWith("_")) to prevent root labels from beginning with underscores. While DNS technically permits underscores in some service record contexts, is-a.dev blocks them at the root level to avoid conflicts with platform infrastructure and future service implementations.
How does is-a.dev prevent conflicts with system subdomains?
The platform maintains util/internal.json containing operational names like www and ns1. During CI execution, tests/json.test.js verifies that no proposed subdomain matches these protected strings exactly or ends with them as suffixes, while util/raw-api.js generates synthetic records to ensure these names always resolve to internal endpoints.
Where are the reserved and internal subdomain lists defined?
Reserved names (globally blocked terms like admin and api) live in util/reserved.json, while internal platform names reside in util/internal.json. Both files are simple JSON arrays consumed by the validation suite in tests/json.test.js and the API generation script in util/raw-api.js, ensuring consistent enforcement across the entire registration pipeline.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →