Sloppy Voice DevelopersSloppy Voice ↗

Domain identity and service discovery

Document: SPEC-010. Revision: 0.1. Date: 2026-10-19. Lifecycle: Approved for implementation under D-058, implementing D-056/D-057 and R-074–R-076. Supersedes: the unresolved discovery/delegation mechanism in SPEC-002 for this profile. Shipped voice-chat/1 remains governed by SPEC-009.

Identity and location

The account address is username@identity-domain. An omitted suffix means the selected account service's canonical identity domain, not its web hostname, parent DNS zone, or the room currently being viewed. SPEC-003 owns address interpretation and account identity. An address resembles an email address but does not imply a mailbox, email verification or an XMPP account.

D-057 keeps existing accounts at @sloppyvoice.com, served by https://chat.sloppyvoice.com/. Preserve account/device UUIDs, passwords, sessions, keys, permissions and history. No identity migration or alias to @chat.sloppyvoice.com is authorised. D-109 resolves Q-49 with the independent identity domain shittyshittybangbang.com, served by https://shittyshittybangbang.com/, with separate storage, application secrets and bootstrap. alpha.sloppyvoice.com below remains an illustration.

The identity domain identifies an account authority. The service base URL identifies an HTTPS application location, including an optional path prefix. A domain may delegate its endpoint without renaming accounts. Two independent authorities cannot simultaneously own the same identity domain. DNS changes alone neither migrate stored identities nor transfer authority, keys or history.

Discovery records

Use the locally defined experimental service label _sloppy-voice._tcp.<identity-domain>. This label is not an IANA registration or an XMPP service. Do not publish _xmpp-* records for this protocol. Review registration before claiming general standards interoperability.

The preferred DNS record is URI (type 256, RFC 7553), which contains the complete HTTPS base URL. SRV (RFC 2782) is an optional root-path fallback for deployments with a reachable direct target. SRV contains priority, weight, port and hostname; it cannot contain /sloppyvoice/ or any other URL path. SVCB/HTTPS transport records do not replace this application identity-to-path mapping.

Current Cloudflare records, TTL 300 seconds, DNS only:


_sloppy-voice._tcp.sloppyvoice.com. 300 IN URI 0 0 "https://chat.sloppyvoice.com/"

_sloppy-voice._tcp.sloppyvoice.com. 300 IN SRV 0 0 0 .

The SRV dot target explicitly says there is no SRV service. It must not be converted into a hostname or retried at an invented address. In this profile, URI discovery takes precedence; an SRV-only client cannot discover this installation. The independent HTTPS discovery mechanism below is the client discovery mechanism.

The negative SRV record is deliberate. On 2026-10-19, Cloudflare rewrote an SRV target of chat.sloppyvoice.com to _dc-srv.9bcd65b345ab._sloppy-voice._tcp.sloppyvoice.com, which returned AAAA 100:: and no A record. That target cannot reach the Worker. Cloudflare documents rewriting SRV targets to bypass its proxy; a Worker has no conventional origin to expose. The trial record was corrected to the dot target. Do not disable the Worker's proxy or pin Cloudflare anycast IP addresses to make SRV appear to work.

For a direct server, an illustrative valid record is 0 0 443 voice.example.net. at the identity domain's service label, provided the target has usable A/AAAA records, is not a CNAME, and agrees with the authenticated descriptor. A DNS SRV fallback constructs a root HTTPS URL only; a path deployment must publish URI. The initial profile permits one active URI endpoint, priority/weight 0 0; multi-endpoint failover and geographic selection require a later authenticated policy. A control endpoint record does not select a media relay or change the Canada → EU → US preference.

Authenticated HTTPS discovery

DNS supplies discoverable routing hints. Before sending any password, signed login proof, bearer token or invitation key to a discovered location, every client must fetch:


https://<identity-domain>/.well-known/sloppy-voice

This is at the identity origin's root, even if the application is mounted below a path. The experimental well-known suffix requires registration review before public interoperability claims. The operator must serve this path directly with valid TLS for the identity domain; an apex-to-www website redirect must exempt it. Do not follow redirects for discovery or use a document returned from a different identity host. TLS also validates the endpoint's hostname when connecting to it. A valid certificate for an arbitrary DNS-supplied target alone does not authorise it to receive an identity domain's credentials.

Version 1 response, 200, Content-Type: application/json, UTF-8:


{

  "discoveryVersion": 1,

  "domain": "sloppyvoice.com",

  "baseUrl": "https://chat.sloppyvoice.com/",

  "profiles": ["voice-chat/1"],

  "federation": {"mode": "closed"}

}

All five fields are required. domain must equal the canonical requested identity domain. profiles is a nonempty, duplicate-free list of supported protocol names; no common supported profile is an explicit incompatibility. federation.mode is exactly closed in this first discovery profile. Later federation modes, credentials and server-to-server endpoints need their own versioned contract; do not advertise them now. Unknown fields can be ignored; unknown versions, missing fields, wrong types, duplicate JSON keys and unsupported security values fail closed. The descriptor carries no secrets, usernames, member lists, private allowlists or content keys.

The public descriptor uses Access-Control-Allow-Origin: * without credential allowance; fetch it with credentials omitted and no referrer. This does not loosen the separate authenticated API origin policy. Browser clients use this document directly and do not depend on raw DNS access or a new public DNS-proxy API. Native clients and future federation adapters may also query URI/SRV. They must still authenticate the identity mapping using this document. DNSSEC is recommended for DNS publication; a validating resolver's bogus result must not be treated as a trusted alternative. An unsigned record is never sufficient credential-delegation proof.

Resolution sequence:

  • Parse the address using SPEC-003 and establish its identity domain. Preserve the distinction between the chosen local account service and a foreign room host.
  • Fetch and validate the identity-origin descriptor. An unsupported/missing descriptor is an explicit discovery failure; do not guess chat., reuse the parent domain, scrape a login page or navigate to an invitation's arbitrary origin.
  • Use its validated baseUrl. Available DNS hints should agree. A stale/mismatched hint is diagnostic only and cannot replace the authenticated URL; URI absence, SRV dot or lack of browser DNS APIs does not defeat a valid descriptor. DNS is not a second permission authority.
  • Fetch api/info relative to that base without credentials. The discovery-capable response retains SPEC-009's existing fields and adds baseUrl (string) and capabilities (array of unique strings containing identity-discovery/1). Require the same canonical domain and baseUrl, a compatible profile, and origin equal to the base URL's origin. Any mismatch stops login; never repair it by changing the requested account domain.
  • Present the fully qualified identity and service location. Attach credentials only to the selected, validated service and intended route. Selecting another domain is explicit; a foreign suffix must never be stripped and submitted to the local login endpoint.

Malformed responses, invalid TLS, timeouts, redirects, unsupported profiles or wrong domains are failures, not triggers for insecure fallback. The descriptor may be cached only within the bounds in Configuration. Never use an expired cache to send credentials after a failed refresh. A changed base URL triggers an explicit reconnect/sign-in; do not silently forward an existing bearer session to a newly discovered endpoint. Changing location still requires an operator migration that preserves the authority's state, not just a new JSON value.

For initial compatibility, an explicitly configured existing root service may continue the SPEC-009 login flow with its current domain check. It must be labelled as configured service access, not successful automatic discovery. Old clients do not implement URI/SRV discovery, the descriptor, a path mount or qualified login-field parsing merely because DNS records exist.

URL paths and instance boundaries

Illustrative future delegation: identity alpha.sloppyvoice.com, base URL https://chat.sloppyvoice.com/sloppyvoice/. Its URI record belongs at _sloppy-voice._tcp.alpha.sloppyvoice.com, and its descriptor belongs at https://alpha.sloppyvoice.com/.well-known/sloppy-voice. With dedicated hosting the base can instead be https://alpha.sloppyvoice.com/. Neither choice transfers @sloppyvoice.com away from the existing service.

The base URL always ends in /. Join relative routes without a leading slash: new URL("api/info", baseUrl) yields /sloppyvoice/api/info for the path example. Apply this consistently to assets, API calls, navigation, setup, invitation URLs, realtime routes, desktop startup URLs and service-worker scope if introduced. Never join "/api/info", which discards the prefix. Match complete prefix segments; /sloppyvoice-other/ is not part of /sloppyvoice/.

Initial public URL grammar: HTTPS port 443 only; a valid DNS hostname; root / or slash-separated nonempty ASCII segments containing letters, digits, _ or -, followed by /; maximum 2048 ASCII characters. Reject userinfo, query, fragment, IP literals, dot segments, backslashes, percent escapes, duplicate slashes and other schemes/ports. Validate raw input before URL-parser normalization can erase forbidden segments. Hostnames are lowercase; path case is preserved. Local loopback HTTP development remains explicit SPEC-002 configuration and is never a public discovery fallback.

The edge router selects the instance before authentication and enforces the configured mount; each instance has independent account storage, bootstrap state, secrets and media authority. In the current Worker, changing a path does not change the DOMAIN binding or the domain-v1 object. Shared storage or one login session across unrelated identity domains is forbidden. Invitations, device storage, caches and command/session audiences must bind the canonical identity and instance context; retain account UUIDs as durable references.

Paths on one HTTPS origin share a browser security boundary. Namespacing local storage by domain/base URL avoids accidental collisions but does not isolate an instance from malicious scripts in another path on that origin. Prefer dedicated hostnames for independently trusted instances. Separate origins still require correct API/CORS, cookie, CSP and credential isolation; a hostname is not itself an account-permission grant.

Future server-side discovery accepts only public HTTPS destinations, rejects loopback/private/link-local/reserved/multicast addresses, and must enforce the restriction on actual connection resolution as well as initial lookup. Redirects remain disabled. An adapter unable to prevent DNS rebinding/private-network access must not expose arbitrary remote discovery fetches. The current increment needs no unauthenticated server-side URL fetch proxy.

Configuration

The following runtime values are selected under D-058/P-028. SPEC-002 continues to own SERVICE_DOMAIN, PUBLIC_ORIGIN, ALLOWED_ORIGINS and local development exceptions. SPEC-003 owns username parsing. SPEC-010 owns the new URL/discovery schema; client and server specifications reference it.

Property/ruleKind, type, default and validationWriter, precedence, timing and persistence
PUBLIC_BASE_URLNew deployment string; omitted means PUBLIC_ORIGIN + "/"; explicit empty/null invalid; grammar above; its origin must equal PUBLIC_ORIGIN.Operator environment/Worker vars, same source precedence as SPEC-002; startup validation; restart/deploy to change. Nonsecret; never inferred from an untrusted Host or forwarded header. Existing root deployments preserve their URL.
Desktop service locationExtension of SPEC-002's SLOPPY_VOICE_URL, legacy VOICE_CHAT_URL and Gentoo server file to accept a full base URL; an existing bare origin normalizes to its root. Add optional package string defaultControlBaseUrl; missing falls back to existing defaultControlOrigin, then the existing generic-build behavior. Empty/null/invalid values fail rather than falling through.Retain existing environment/launcher-over-package precedence. Validate the effective base before navigation; retain existing root device storage through explicit migration. Add packaging option --server-base-url; specifying it with --server-origin is an error. SPEC-002/005 reference this inventory in place of their older origin-only interface.
Descriptor domainDerived from immutable SERVICE_DOMAIN, no independent override.Operator owns the identity; changing it after initialization is rejected, not an account rename.
Descriptor baseUrlDerived from PUBLIC_BASE_URL; no separate admin UI override.Website/identity-origin publication must match the application configuration. Do not keep competing manual defaults.
DNS URI/SRVOperator DNS publication; one URI 0 0 for this profile; optional direct-root SRV 0 0 443 target. or explicit 0 0 0 .; TTL 300 seconds for this installation.Stored in DNS, independent of app deployment. Never treat a missing URI as permission to strip a path. No secrets. Resolver caches may delay changes.
Descriptor version/capabilityFixed integer 1 and string identity-discovery/1; not a runtime setting.Server advertises only after the matching contract is implemented; persistent identity/data schema remains separate.
Federation announcementFixed {"mode":"closed"} in this profile; no new enable-federation switch.Derived from implemented policy, not a declaration that overrides enforcement.
Fetch limitsFixed 16,384 decoded response bytes, 5,000 ms per request and 10,000 ms total resolution deadline, zero redirects.Applied by clients/adapters; not operator tuning knobs in v1. Abort on limit; partial responses unusable.
Cache boundsFixed maximum 300 seconds for positive descriptors, further reduced by HTTP freshness; absent freshness defaults to 300 seconds; no-store/no-cache honoured; errors cached at most 60 seconds.Cache by canonical identity domain; no credential data. Expired entries cannot authorise new login. DNS caching respects record TTL independently.

Omitted settings use only their stated defaults; null is not inheritance. Explicit loopback development may use SPEC-002's HTTP exception for locally configured base URLs; public discovery never advertises that exception. Invalid settings fail startup or discovery without changing persisted accounts. Profile/schema upgrades require version negotiation and mixed-version fixtures; the build must not claim discovery capability merely because a configuration field is present. SPEC-002/005 reference this authoritative base-URL inventory. The current clients perform fresh HTTPS discovery on each explicit selection and do not cache descriptors or query DNS directly. The shared DNS parser supports supplied hints for future resolver adapters; live DNS resolution is not claimed.

Testing

Unit tests cover SPEC-003 address parsing, local-domain selection, canonical equality and invalid/multiple suffixes; descriptor schema and duplicate keys; URI/SRV interpretation including dot; host/path validation before normalization; relative route joining; prefix-boundary matching; profile negotiation; timeout/size/cache limits; omitted/default/null configuration and origin mismatches. Expected failures must occur before credential dispatch or invitation consumption.

Use recorded DNS fixtures for a direct target, missing URI, an SRV dot, conflicting hints, a CNAME target, Cloudflare's rewritten target, DNSSEC failure, and a URI containing a path. Verify that browser discovery succeeds with no DNS API, authenticated HTTPS mapping wins over an untrusted hint, and a changed descriptor does not receive old tokens automatically. Include SSRF/rebinding tests for any future server fetch adapter; parser unit tests alone are insufficient evidence.

Integration tests host two isolated instances, one at root and one below /sloppyvoice/, with distinct identity domains and accounts sharing a local username. Confirm all APIs/assets/invites/setup remain within the selected mount, origin/domain/session mismatches fail, permissions and keys never cross instances, and the existing sloppyvoice.com account UUIDs/history survive upgrading the original service. Test legacy explicitly configured root clients separately from discovery-capable clients. Verify the apex descriptor is JSON rather than the website redirect or SPA HTML.

Deployment checks query both authoritative nameservers plus a recursive resolver, compare the URI with the configured service, and validate TLS/descriptor/info responses. DNS publication alone passes only the DNS portion. It cannot pass automatic login, path hosting, multi-device support or federation acceptance.

Acceptance criteria

  • saxon on the existing service and saxon@sloppyvoice.com select the same account; a foreign suffix never silently selects it. Existing IDs, keys, sessions, roles and history remain unchanged.
  • The current DNS URI resolves to https://chat.sloppyvoice.com/; the SRV record is 0 0 0 ., with no unreachable Worker origin represented as a working route.
  • A browser with no DNS API discovers an implemented service through valid identity-origin HTTPS JSON; invalid TLS, redirects, schema/domain/profile mismatches and expired cache entries cannot receive credentials.
  • A native client handles URI, direct SRV and explicit SRV absence without treating DNS alone as credential-delegation proof.
  • A distinct test identity delegated to /sloppyvoice/ loads assets and completes setup, invitations, login, text and voice API routing under that prefix; the original instance remains isolated.
  • The same-origin limitation is documented and no test or UI claims that two path mounts isolate mutually untrusted scripts.
  • Live /api/info advertises the extension only after its behavior is implemented; old voice-chat/1 clients retain explicit root-service access without being misrepresented as discovery-capable.
  • The discovery descriptor announces closed; DNS publication does not enable foreign authentication, disclose private policy or start a second authority for sloppyvoice.com.

Sources and delivery status

Primary sources reviewed 2026-10-19: RFC 2782 — SRV, RFC 7553 — URI, RFC 8615 — well-known locations, RFC 9460 — SVCB/HTTPS, Cloudflare record types, Cloudflare SRV rewriting, and MDN same-origin policy. The protocol composition, precedence and numeric bounds are project proposals, not requirements imposed by these RFCs.

D-058 selects this profile for alpha.6. Qualified login parsing, HTTPS descriptor publication, explicit discovery and mount-prefix routing are implemented; native live DNS resolution and server federation remain outside this increment. The alpha.6 release report records tested and deployed scope. See the deployment record and A-40.