Naming conventions
OrbitalReg enforces a single slug grammar for new projects and repositories. Slugs appear in URL paths, in API-token scopes, and in client-side configs (.npmrc, pip.conf, ~/.docker/config.json, …), so a consistent grammar avoids three classes of pain at once.
The rule
^[a-z][a-z0-9]*(\.[a-z0-9]+)*$In English:
- Lowercase letters
a–zand digits0–9only. - The first character must be a letter (no leading digit).
- Dots
.are the only segment separator. No hyphens, underscores, spaces, or other punctuation. - No consecutive dots, no leading dot, no trailing dot.
- Length: 2–63 characters inclusive (matches the DNS-label ceiling, which keeps slugs URL-safe across every adapter).
Examples
| Slug | OK? | Reason |
|---|---|---|
acme.platform | ✅ | Standard Maven-style coordinate. |
acme.foo.bar2 | ✅ | Digits inside a segment are fine. |
internal.tools | ✅ | Two segments, all lowercase. |
gh | ✅ | Two-character minimum is fine. |
Acme.Platform | ❌ | Uppercase letters. |
acme-platform | ❌ | Hyphen. |
acme_platform | ❌ | Underscore. |
2acme.platform | ❌ | Leading digit. |
acme..platform | ❌ | Consecutive dots. |
.acme | ❌ | Leading dot. |
acme.platform. | ❌ | Trailing dot. |
Why this grammar
Consistency across the install. Without a rule, operators end up with
Acme-Platform,acme_platform, andacme.platformside by side — same company, three slugs, none of them mutually discoverable in a search-by-prefix.URL- and path-safe across every adapter. Maven's coordinate grammar, npm's scope grammar, Docker's repository-name grammar, and DNS labels all overlap exactly here: lowercase letters, digits, and dots. Hyphens / underscores are valid in some adapters but not all (Cargo refuses leading digits, and several adapters percent-encode underscores inconsistently).
Maven / Java idiom.
tld.company.productis a 25-year-old convention; matching it removes friction for the largest single body of registry consumers.
How enforcement works
- POST
/api/v1/projectsand POST/api/v1/reposreject a non-compliant slug with HTTP 400 and a structured envelope:jsonCLI / Terraform-provider / scripted callers can switch on{ "error": "invalid_slug", "field": "slug", "message": "slug must be lowercase letters/digits with dots as separators (no hyphens, underscores, leading digits, or special chars)", "examples": ["acme.platform", "internal.tools", "team.foo.api"], "suggestion": "acme.platform" }error == "invalid_slug"without parsing the English message; thesuggestionfield, when present, is a best-effort rewrite of the rejected input that already passes validation. - PATCH
/api/v1/projects/{id}and PATCH/api/v1/repos/{id}only validate when the patch body actually moves the slug. A no-op edit (or any patch that touches other fields only) on a legacy row never fails on slug grounds. - The OrbitalReg dashboard's create-form for projects and repositories live-validates the slug input on every keystroke, surfaces the same error message inline, and offers a one-click "Did you mean
acme.platform?" suggestion that fixes the most common typos (Acme-Platform,acme_platform,2acme.platform).
Existing legacy slugs
Slugs that pre-date this rule stay valid forever — renaming them would break every bookmark, CI config, and API-token scope that references them. The rule only applies to:
- Newly-created projects and repositories.
- Existing projects / repositories whose slug is being explicitly changed via PATCH.
For operators who want to migrate voluntarily, the admin dashboard has a "Slug audit" page under Identity & Access in the sidebar (or the "Legacy-named projects (N)" banner on the Admin overview when one or more rows are non-compliant). Each row shows:
- the current slug,
- the human-friendly name,
- a suggested rename that already passes validation.
Renaming preserves the row's UUID, so role-bindings, retention policies, security blocks, webhook subscriptions, and audit-log references all continue to work after the rename. URL bookmarks, CI configs, and any hard-coded clients have to be updated by hand.
Caveats
- "Are digits OK?" Yes. Digits are allowed inside any segment (
acme.foo.bar2,team.svc1,service42.api) — they just can't be the very first character. The leading-digit ban is a defensive default that mirrors Cargo's crate-name rules and the DNS-label convention from RFC 1035, and it sidesteps the small set of clients that do path-parsing without quoting. If you have a use case that needs a leading digit, file an issue — we'd rather hear the motivating example than relax the rule by default. - Reserved slugs (e.g.
admin,api,system) are not enforced today. If they ever conflict with a routing prefix we'll add a small rejection list as a follow-up — for the moment, the routing layer scopes everything under/api/...and the UI under/projects/...//repos/...so collisions are not possible. - Multi-tenancy / namespace prefixes. OrbitalReg is single-tenant by design; slugs are flat. If multi-tenancy ever ships, tenants will get their own slug namespace rather than tenant-prefixed slugs.
- Slug-rename redirects. Today a renamed slug returns 404 at the old URL — there is no automatic 301/302 redirect. Plan rename windows accordingly. A redirect-and-soak workflow is on the long-tail roadmap.