Multiple servers and public joins
Document: SPEC-015. Revision: 0.8. Date: 2026-10-27. Lifecycle: D-072/D-076–D-078 outcomes CONFIRMED; technical completion profile selected under D-049. Implemented in alpha.9; local, isolated hosted and production deployment verification passed. Supersedes: the closed-federation runtime only when FEDERATION_ENABLED is enabled; closed deployments retain their existing admission policy. D-172–D-180 scope is accepted only as specified below; SPEC-013 records the approved one-message history exception.
Approved video-delivery successor — D-167
D-167/SPEC-024 separates managed-presentation continuation from the native microphone lease. A managed grant is capped by its explicitly issued 30-second validity and its underlying identity/key authority, never extended by retries or cached polling. Provider closure must be confirmed before a conflicting cross-host presentation move completes. Native home voice inspection, 15-second attendance and four-second movement fences remain applicable to native voice; extending a managed window does not extend a native lease. See SPEC-024.
The Quiet identity presentation in SPEC-005 (D-118/D-120) groups the account-qualified connections described here beneath one verified server root. It preserves this specification’s internal connection, credential, admission and voice boundaries.
Confirmed experience
- Keep several server connections in the client; select them from server roots in the left navigation tree (D-104, superseding the top-left selector).
- Join a server… accepts a pasted join link and resolves the necessary details inside the client. Opening the same link in a browser provides the corresponding join entry point.
- Show the resolved server name, actual host and selected account, then Join as username@domain. The human explicitly chose this one-button confirmation, not automatic joining on link open.
- Also offer Use an account on this server and Create an account on this server, subject to the destination's account-admission policy.
- Public servers can admit visitors with accounts hosted elsewhere. The visitor needs no second password or second user-managed account.
- A URL such as
https://sloppyvoice.com/<server-id>is a shortcut resolved by a coordination service. It is not the visitor's identity domain or necessarily the destination server. - Existing
@sloppyvoice.comidentities remain intact. The human is considering a future endpoint move; no domain, DNS, account or storage migration has been authorized by that observation.
Authority boundaries
Keep three separate roles. The home account service authenticates the account and approved device. The destination server owns its channels, access, moderation and retained events. The shortcut service resolves an opaque server ID to an authenticated server descriptor. It receives neither passwords nor account/room bearer tokens and does not decide admission. A shortcut is a locator, not a private invitation or identity proof.
Use a stable server UUID in addition to the canonical identity domain and service base URL. Bind saved connections, tokens and shortcut records to that UUID and the authenticated descriptor. Display the hostname beside the server's chosen label. A changed label is ordinary metadata; a changed UUID, authority or unverified endpoint is a reconnect/review event. Never silently deliver an existing token to a replacement mapping. SPEC-010's full-path validation and explicit endpoint-change rules remain.
The client retains its trusted executable origin while connecting to destination APIs. Selecting a server must not replace the renderer with that server's HTML while home keys are unlocked. Keep home credentials/device keys, destination sessions, pending commands, caches, history cursors and sender identities separately scoped. Web and desktop must pass the same two-server tests; changing Electron's navigation allowlist alone does not implement this feature. Public API origin access is explicitly negotiated without cookies; a permissive CORS response grants no account authority.
Use direct client-to-destination traffic, retaining SPEC-009's V2 direction. The destination sees the client's network address. The home service knows where it issues visitor credentials but does not proxy conversation contents. The shortcut service sees link resolutions; it cannot see subsequent chat through its locator role. The Join workspace discloses these metadata boundaries before confirmation. D-221: event-hint sockets (SPEC-027) also go directly from the client to each destination; the home service receives no per-message notification of foreign activity, and a visitor socket receives hints only while its home approval is fresh.
Authentication flow
- Parse the pasted HTTPS shortcut locally. Fetch only the coordinator's bounded public resolution API; do not follow arbitrary redirects or forward URL query/fragment secrets. Resolve and authenticate the destination descriptor and its UUID independently. Also accept a direct compatible server URL so the coordinator is optional.
- Fetch public server details and effective join choices without credentials. Private rooms, members and administrative settings stay undisclosed.
- Show the destination and the selected existing account. No password is sent merely because a link was pasted. If the user chooses another local account, show its full identity before any credential submission.
- On Join, the home service authenticates the approved device and issues a destination-specific directory delegation, accompanied by a short-lived device proof. The destination validates issuer, audience, nonce, expiry, account identity and device possession before issuing its own bounded session. Home passwords, reusable home bearer sessions, recovery material and private keys never go to the destination or coordinator.
- Persist a visitor membership/permissions record at the destination, keyed by canonical home authority plus stable account ID. It is required for bans, history and moderation but has no local password or recovery bypass. A home-server owner role never becomes a destination-server role.
- Add the connection to the menu and select its configured public landing channel, if any; otherwise show the channel list. Joining a server does not start microphone capture or silently move an existing call. Existing channel reactivation and explicit voice-move behavior continue.
The completion profile uses opaque destination-specific delegation, online home-authority checks over authenticated HTTPS, and the existing maintained Ed25519 implementation for device proofs. No new cryptographic primitive or bearer credential reusable at arbitrary hosts is introduced. OAuth Token Exchange, RFC 8693, OAuth Security BCP, RFC 9700, and DPoP, RFC 9449 inform the authority, audience and replay boundaries; this application-specific alpha wire is not advertised as OAuth interoperability. Online inspection avoids trusting a foreign wall clock to extend a forwarding lease. The exact completion contract follows below.
Public/server-readable channels can use the single confirmed Join action without exchanging content-history keys. HTTPS and encrypted media transport remain mandatory. E2EE channels retain device verification, membership and key-sharing requirements; absent keys or changed identities cause a clear in-place explanation, never a downgrade. Local sign-in/registration on a destination continues its own approved-device/recovery process. A convenient join shortcut cannot bypass it.
Public-server policy and coordinator
D-076 confirms separate Allow visitors with an existing account and Allow local account registration controls; local registration defaults closed. Both start disabled on existing and new deployments, preserving private installations. Disabling the federation runtime after visitors exist also pauses affected E2EE posting; schema 4 retains message and media host binding, so disabling runtime support cannot restore legacy unbound traffic. Enabling public visitors can accept compatible home domains while retaining owner-managed blocks and local bans. A block wins over a public-admission setting. Disabling public admission stops new public joins; existing memberships remain under D-077.
Retain existing admitted memberships when public admission is switched off under D-077; remove/revoke separately. Existing members keep their history intervals. Owner-selected public landing channels may be automatically admitted through the Join confirmation; private or incompatible encrypted landing choices cannot be silently substituted. Server visibility, public visitor admission, local registration and channel encryption remain separate controls.
The coordinator stores only server UUID, authenticated authority/base, display label, opaque shortcut ID, verification evidence and lifecycle status. An operator must prove control of the server authority before registration or updates. IDs are not passwords, are not recycled to a different server, and do not authorize private access. Retire or disable a mapping without redirecting it to another authority. Cache only bounded public descriptors and require fresh authority validation on a changed endpoint. Keep a direct-server entry path working if the coordinator is unavailable. A searchable public directory is a separate opt-in feature, not implied by possessing a shareable shortcut.
Keep /.well-known/sloppy-voice working on sloppyvoice.com for the existing identities if the apex hosts shortcuts. Website/download/reserved routes take precedence over shortcut IDs. Moving the current account service to another hostname is a separate migration preserving IDs, keys, data and authority; changing an apex route alone is not that migration.
Federation completion profile (D-049)
The home service continues to own passwords, approved-device rosters, account disablement and the account's single voice slot. The destination owns visitor membership, destination role, channel grants/bans, message acceptance and media leases. No additional home-domain room moderation policy is introduced. A home owner is a member at a destination until that destination's owner explicitly changes the role. Local account lookup always includes its own identity domain, so a foreign namesake cannot intercept sign-in or invitation flows.
An immutable server UUID is initialized once in persistent metadata and returned by mounted GET api/server with serverVersion:1, canonical domain/baseUrl, display name, protocol/capability list and the two public admission booleans. Identity discovery version 2 binds serverId to the identity's base URL. A fresh descriptor must agree with the saved UUID/domain/base before credentials are attached. Private channel names, roster records and block lists are absent from public metadata. Changed identity/base requires explicit reconnect; a label change does not.
POST api/federation/grants is authenticated at home and takes the verified destination domain/base/UUID. The home independently authenticates that descriptor and stores a random 32-byte opaque delegation, scoped to this home account and that destination. The delegation permits only account/device-directory inspection by its destination; it cannot log in at home, modify devices, recover an account, read contacts/messages, or claim/move voice. A destination stores it as a secret, never in URLs, client-visible logs or a public descriptor. Home grants live for at most 30 days; explicit rejoin renews through the home account's current approved-device session. The home account can revoke a grant. Session expiry at a destination does not create a new membership interval or bypass a closed public-join policy.
On explicit Join the client sends the delegation, home domain, active public device, nonce and device signature to destination POST api/federation/join. The signed context binds purpose sloppy-visitor-join/1, destination UUID/base, home domain, delegation digest and nonce. The destination independently discovers the home, calls its mounted POST api/federation/inspect with the delegation, exact audience UUID/base and a fresh request nonce, then verifies the returned identity and SPEC-011 signed roster before validating device possession. Inspection returns no password or home role. A UUID collision with another home authority is rejected explicitly rather than merging accounts. Replays cannot grant another device or create another membership. The destination records home authority, roster, membership status and its own initial member role, then issues its normal bounded session tied to that device. New public admissions require the owner's public-visitor control; existing admitted visitors may reconnect after that control closes under D-077. Account capacity includes visitor records, without pretending they are local password accounts.
Every authenticated foreign request includes a fresh device signature over purpose sloppy-visitor-request/1, destination UUID/base, full canonical method/URL, canonical JSON-body digest, destination-token digest and nonce. The destination checks its own token/device, signature, canonical context and nonce replay before executing the action. Exact command retry uses the existing ticket/payload and a new transport nonce. Nonces are stored for 60 seconds; request proofs have a 30-second issue window with at most 1 second future skew. These proof windows never extend home authorization or media authority. Check current home approval and destination bans again after asynchronous work. Foreign account settings, device approval/recovery and personal Friends stay at home; only host-authorized history-share operations remain on the destination.
Home inspection validates the opaque delegation, audience, current account state and signed roster on every uncached inspection. Directory results may be used for at most 10,000 ms, measured from the destination's request start; responses arriving after that budget are unavailable. Refresh identities of admitted foreign members before accepting new E2EE messages, including members whose clients are offline. The exact required recipient set remains SPEC-011's current approved devices/recovery recipients. Failed refresh marks E2EE posting unavailable under D-078 without deleting membership, overwriting trusted keys or hiding previously readable history. Server-readable channels can continue for other members. Current foreign users cannot act through stale authorization when their home is unavailable. The UI explains this in place and never substitutes plaintext or silently omits a required recipient.
Cross-host voice uses the home account's one authoritative slot. An explicit home-authenticated claim names destination server and a random call UUID; it carries the currently observed prior voice ID when moving. Claiming does not capture audio. A move revokes the old local/foreign renewal, persists the existing 4,000 ms fence, and admits the new claim only after that fence. The home stores only destination identity and opaque call/device IDs, not chat content or the destination's private channel name. Local joins/renewals obey the same slot. A foreign destination can issue a voice lease only when fresh home inspection confirms the matching call/device/destination. The home returns remaining validity in milliseconds; the destination caps expiry at request-start plus that duration and its existing 3,000 ms lease maximum. No positive foreign-clock skew allowance extends media. A delayed/outage response cannot renew a call. Device revocation/recovery/account disablement removes the slot; a malicious destination cannot mint home claims. All moves require fresh PTT, and thread calls follow the same isolated-call rules.
The trusted client keeps an independent API/token/history/draft context for each saved connection. Changing text selection keeps the active media object's API and account keys. Background connections refresh their connection status and current approved-device state through a single rotating read every 5,000 ms, with one request in flight, an 8,000 ms request timeout and no background microphone capture or conversation download. Skip the selected connection and the active call (their existing loops handle freshness). These are fixed client scheduling bounds; they cannot overwrite the visible conversation or another connection's pending command. Account profiles and trust indexes use domain plus account ID, and message/cache scopes include destination UUID plus room ID. New federation-capable signed text/encrypted inner contexts bind destination UUID as well as room ID to prevent a hostile host reusing another host's room identifier. Existing local history remains readable as legacy history; the first foreign E2EE release must pass both forms without accepting an unbound new foreign message.
Coordinator publication requires owner opt-in at the destination. The public server descriptor includes a random publication nonce and the selected canonical coordinator base only after that explicit action. Coordinator registration independently verifies identity discovery, UUID/base and that consent, then creates a random immutable shortcut ID. Refreshes may update the same server's label/location only through fresh identity-authority proof; a different UUID/authority cannot take over an ID. Removing consent retires resolution; reserved website/download/identity paths are never shortcut IDs. No searchable directory is implied. Direct joins and existing connections work without the coordinator. No current account service/DNS migration is included.
Selected connection foundations (D-049)
The following implementation details complete the confirmed endpoint-isolation requirement. They are technical completion choices, not additional human preferences. Exchange and cross-host voice validation remain release gates.
New text carries signed serverId and senderDomain fields together. serverId is the destination's persistent UUID; senderDomain is the author's canonical home domain. E2EE boxes repeat both fields inside the authenticated plaintext. Room metadata supplies the destination UUID/domain, and the connection must compare these with its pinned descriptor before use. Message display, copying and recovery check the selected destination in addition to room/encryption and author identity. A changed UUID or domain cannot be fixed by relabelling a signed envelope. History-share envelopes repeat a bound original's server UUID and include it inside the new box; their existing original-envelope digest covers both new text fields. Old unbound history remains readable only on a home connection. Local legacy senders remain supported while federation is closed; the completed federation runtime requires bound new messages from every sender and never accepts unbound foreign posts or copies.
Federation-capable room state includes voiceServerId, equal to its persistent destination UUID. Media grants carry that serverId; relay peer and revocation indexes include it alongside room/device. Server-readable signed frames and E2EE authenticated inner frames repeat it, and receivers require equality with the pinned room's voice authority before playout. A legacy unbound call cannot exchange frames with a bound call. The closed single-server runtime omits the media binding for compatibility; enabling federation requires the updated relay. Relay leases accept positive durations up to 3,000 ms, including shorter foreign leases capped by remaining home authority; they never round an expiry up. These are fixed wire constraints, not user settings.
The home voice component is selected under D-049 with the existing SPEC-011 explicit-move policy. A claim requires a currently approved home device and an unexpired directory grant to the exact destination. The client supplies a fresh call UUID and, only when moving, the observed previous call UUID. The home retains one foreign slot per account, renewed by its owning device through authenticated home requests every second, with the attendance timeout owned by SPEC-006 (15,000 ms under D-137). The client renews during media preparation; a stopped client cannot reserve voice indefinitely. Repeating the same claim returns its original state without extending attendance. A slot may authorize forwarding only after the existing 4,000 ms fence and while approval/grant/attendance remain valid. Inspection exposes only {id,device,validForMS} to the matching destination, with validity at most 3,000 ms and never beyond slot expiry. Inspection cannot renew attendance. Local calls and foreign claims use the same persistent fence; claiming or joining cannot overwrite another device's pending move. Release, device revocation, grant revocation, timeout and recovery stop renewal and retain a fence. A different device cannot release or renew the slot. These durations reuse SPEC-003/006/011 bounds, not new operator settings. The host caps each lease against the original inspection request-start deadline, including cached results. Clock rollback invalidates cached or active authority instead of extending it.
Local public registration uses the existing username challenge and device-proof format: while the owner's independent registration control is enabled, a fresh challenge for that local username may replace the invitation token in POST api/register. The service checks policy/challenge before password hashing and again at commit, consumes the challenge on success, and assigns ordinary member permissions without implicit private-channel access. An invitation still works when public registration is closed; public registration never replaces or recovers an existing account. The destination's password and device-approval rules remain unchanged. CORS permits independent client origins only in the completed federation runtime; APIs use explicit bearer/device proofs, omit cookies and never send credentialed CORS responses. This does not grant another origin access to the trusted client's vault.
Each client API object has one immutable canonical base URL. A snapshot preserves that base, token, room, recovery context and authentication provider. Relative API paths cannot contain an authority, fragment, backslash, encoded path separator, dot segment or duplicate slash. Requests omit cookies and referrers, disable redirects, and bind pending commands to the original API object, token and room. Changing the selected server creates/selects another object; it never changes the destination of an existing object. This also applies to media-session renewal and compatibility synchronization.
The protected vault keeps a client-wide connection list, keyed by destination UUID and qualified home account, alongside the existing isolated account profiles. Each account profile records its verified home descriptor. Each connection retains its own destination token, selected channel and per-channel draft; API instances keep their pending command independently. Selecting another connection saves the outgoing draft, uses that account's keys and reloads its own room/history cursor. It never carries history positions from another host. Descriptor validation precedes credential dispatch after startup/reconnect; a cached match expires within 300 seconds. Voice owns a snapshot of its account keys and original API, with live trust/preferences resolved only from that qualified account's profile. Text navigation cannot overwrite that call's device keys, roster or server state. Personal gain/mute keys become domain-qualified, with legacy UUID-only settings read only for home-domain peers. Account profile/device/recovery/Friends actions always use the home API, while channel/server administration uses the selected host. User settings lists saved connections for the active account and current home-issued delegations. Removing a saved visitor connection stops this client’s matching call, returns to its home connection when selected, and removes that connection and its drafts; it retains account keys and remote membership. A separate inline-confirmed Revoke access action revokes the home delegation across devices and removes this client’s matching saved connection. Explicit rejoining can authorize that destination again. Home connections are retained while their account profile is stored.
Protected account archives, peer fingerprints and roster pins use domain + ":" + accountUUID. A legacy unqualified archive is read only when its stored identity matches both the requested UUID and domain. Legacy peer pins may be read only for the current home domain; they never grant trust to a foreign namesake or colliding UUID. New writes use qualified keys. Linking copies those qualified trust records through the existing encrypted transfer; no private key is exported. The same local username on another domain selects that domain's saved keys, never the currently active namesake's device. These changes are additive migration, without deleting unrelated account profiles or resetting established home-device trust.
Pasted links accept the existing public HTTPS/base-path grammar after trimming surrounding ASCII whitespace. Query data and arbitrary fragments (except the locally parsed channel locator below), credentials, port overrides and non-HTTPS schemes are rejected before a request. A direct server is checked at its mounted api/server endpoint. A shortcut may have one opaque 8–64 character ASCII alphanumeric/underscore/hyphen path segment. It resolves through /.well-known/sloppy-voice-coordinator, whose version-1 baseUrl must be a canonical HTTPS URL on that same origin; api/servers/<id> returns the immutable server UUID, identity domain and base. Verify those against both the target's public descriptor and its identity-origin descriptor before presenting Join. Never fetch an arbitrary endpoint supplied in a JSON property. Resolution sends no account credentials and grants no admission. Zero redirects, 16 KiB decoded JSON responses, 5-second request and 10-second overall deadlines apply, including slow response bodies. Reject duplicate fields and non-JSON/error responses. Descriptor identities are compared exactly; labels cannot replace the host/domain evidence.
Server-side public fetch has a separate transport from relay/control RPC. The Node adapter uses HTTPS on port 443, resolves and checks every address at connection time, pins the vetted lookup result to that connection, verifies TLS for the original DNS hostname, and disables agent reuse and redirects. It rejects IPv4/IPv6 loopback, private, link-local, shared-address, multicast, unspecified, documentation, benchmarking and reserved ranges, including IPv4-mapped IPv6. No DNS preflight followed by an unchecked second lookup. The Workers adapter requires global_fetch_strictly_public and the default public network boundary; it never uses a service, VPC, origin or Container binding to fetch a user-selected authority. An unavailable safe transport fails closed. Test fixtures may inject an explicit in-memory network; that is not a production private-network exception.
The Workers boundary follows Cloudflare's public-fetch compatibility contract and workerd's documented network behavior. Node connects through a validated lookup callback rather than treating URL syntax as network authorization.
The directory transport adds one fixed POST operation: mounted api/federation/inspect, with a JSON body at most 4,096 bytes and only Accept/Content-Type headers. It has the same HTTPS, connection-level public-address, TLS, timeout and no-redirect boundary. It accepts at most 131,072 response bytes for a complete bounded signed roster; public metadata retains its 16 KiB limit. This is not a general HTTP proxy or an exception for private destinations. Never send a delegation to a changed home base: reauthenticate discovery, compare its entire pinned UUID/domain/base and fail before inspection if they differ. Positive home descriptors may be cached for at most 300 seconds. The destination directory cache holds at most 32 defensive copies/4 MiB and never outlives the 10,000 ms request-start budget; expired entries are not an outage fallback. Concurrent reads may share one in-flight inspection. Current-account refresh must reject changed account IDs, root substitution, roster rollback or non-extending approval history before replacing stored device data.
Selected shortcut service contract (D-049/D-072)
The owner uses server settings to publish or withdraw a shortcut. POST api/server/shortcut accepts exactly {coordinator} (canonical public HTTPS base or null); it requires the local owner. Publication stores {coordinator,nonce} with a random 32-byte nonce, initially absent. Retrying the same coordinator preserves the nonce; withdrawal removes it immediately. This is independent of public admission and searchable listing. The client then sends exactly {server,nonce} to the selected coordinator's POST api/servers, without any account token. Independent discovery must show the identical server UUID/domain/base and publication consent before registration succeeds. The descriptor nonce is public evidence of operator consent, not an account credential.
The coordinator assigns 24 random bytes encoded as a 32-character opaque URL-safe ID. It stores server UUID/domain/base/name, consent nonce, creation/verification times and retired status in its own durable database. Repeated registration with identical server/consent returns the same ID. Resolution at GET api/servers/<id> revalidates identity and consent; it has no stale-success outage cache. A changed UUID/domain or withdrawn/replaced consent permanently retires that ID. Temporary discovery failure returns unavailable without retiring it. A verified base/label update for the same authority, UUID and consent may update the record; saved connections still require their own exact base match. IDs are never assigned to another record.
The reference coordinator has a fixed 10,000-record alpha capacity (including tombstones), a 4,096-byte JSON registration limit, and per-peer limits of 20 registrations and 120 resolutions per minute. Rate records expire after two minutes. These engineering bounds are selected for the alpha fixture, not production capacity promises. All public reads/registrations omit cookies and allow independent client origins; responses never grant admission. The locator HTML escapes labels and offers a link to the configured trusted client with #join=<encoded-shortcut>, plus the shortcut for pasting into any client. It does not load the destination's code or accept a password. COORDINATOR_BASE_URL and JOIN_CLIENT_BASE_URL are required canonical HTTPS deployment values for this service; neither is inferred from an incoming Host header. The reference deployment uses https://sloppyvoice.com/ and https://chat.sloppyvoice.com/. Ordinary website/download/identity routes retain priority; the separate coordinator database uses the existing EU placement rule.
Targeted channel admission (D-122–D-125)
SPEC-022 extends ordinary visitor admission with named-account invitations while public visitor joins remain closed. A newly invited account receives a non-propagating server permit plus a non-propagating channel permit. Ordinary public membership is no longer an implicit entitlement for that account. Current home/device verification, host bans, existing independent permissions, direct-conversation consent and explicit voice movement remain. The copied private channel locator carries no authority by itself. SPEC-022 supersedes the earlier admission/visibility statements only to this extent.
Public directory (D-179)
Owner opt-in publishes a directory description and tags through the existing authenticated server descriptor and shortcut-coordinator verification. A listing is available only while public visitor admission is enabled and current discovery agrees with the stored server identity, coordinator nonce and listing consent. Listing grants no admission or channel visibility. The website exposes a searchable, paginated server directory; it contains no private channels, account lists or visitor data.
Configuration
Directory listing metadata is owner-only server state, absent/unlisted by default. description is plain text, at most 500 characters; tags is a unique array of at most eight nonempty plain-text strings, each at most 32 characters. The public website's coordinator defaults to the explicitly requested https://sloppyvoice.com/. Search accepts at most 100 characters and returns up to 20 currently verified results per page. Reuse existing bounded discovery, public-network checks and coordinator rate controls; failed discovery suppresses the result. These are fixed profile bounds.
D-156 increases the shared VISITOR.directoryMS fixed approval-freshness bound from 1,000 to 10,000 integer milliseconds. It applies to home inspection responses, destination cache reuse, foreign request authorization and encrypted-post recipient checks. It is measured from request start, never response arrival or reuse; at expiry the result is unusable. A home may return a shorter lifetime, including remaining delegation validity. Existing transport timeouts remain separate and may fail earlier. No deployment/user override or persisted migration applies. The independent voice-authority lifetime remains at most 3,000 ms, with fresh inspections on voice admission/renewal; approval-cache lifetime cannot extend it. Home revocations can take up to the longer directory window to affect cached non-voice checks. Older destinations that reject lifetimes above 1,000 ms fail closed against updated homes; update both participating services for this change.
SPEC-008 owns server administrative policy and deployment settings, SPEC-005 owns protected client connections/preferences, and this profile owns the shared wire constraints. These engineering selections implement D-072/D-076–D-078 under D-049; they are not separately stated human preferences.
| Property | Type, initial/default behavior | Writer and timing |
|---|---|---|
| Allow public visitors | Boolean, default false | Server owner; persisted; affects new joins immediately. |
| Allow local registration | Boolean, default false, independent of visitors | Server owner; persisted; invitation-based registration remains when false. |
| Blocked home domains | Canonical domain set, initially empty; block takes precedence | Server owner; deny new sessions and revoke existing affected foreign authority under the selected cutoff. |
| Public landing channel | Ordinary public channel UUID or null; default null | Server owner; validate current access/encryption eligibility; affects subsequent joins only. |
| Public directory listing | Not implemented in this profile; no runtime setting | Shareable shortcuts do not create a searchable directory. |
| Saved server connections | Protected client/account state; initially current configured server only | Explicit joins add entries; removal never deletes the remote account. Server sessions stay scoped to account plus destination UUID/base. |
| Shortcut ID | Coordinator-assigned opaque immutable value; required for a shortcut, no default | Verified operator registration; never recycled or reinterpreted as an invitation. |
FEDERATION_ENABLED | Deployment boolean, default false; strict boolean or literal true/false environment text | Operator only, applied at process start/deploy on control and media. Enables the completed visitor profile, independent client CORS and bound media; does not open visitor admission or registration. Requires the compatible relay and public network adapter. Invalid/null values fail closed. |
| Workers public network boundary | Deployment compatibility flag global_fetch_strictly_public; required for arbitrary-authority federation discovery, no permissive fallback | Operator deployment config; effective after deploy. No private/origin binding override. Node uses the fixed connection-level public-address filter instead. |
| Credential lifetimes and revocation | Existing SPEC-009 sessions: 12 hours; directory delegation and proofs use the fixed bounds below | Device approval, block/ban and home voice authority are rechecked within the defined limits; no stale authorization fallback. |
The home-delegation component is selected for implementation under D-049 with the review profile above: one reusable directory-only grant per account/destination, at most 32 unexpired destination grants per account, 30-day expiry, and explicit revocation. The grant is a random 32-byte secret retained by the two authorities, indexed by its digest at home, and returned only to an approved home-account client when adding/reconnecting that server. Its directory scope survives approval of another device or revocation of the originating device; current roster checks still reject the revoked device at every destination. Grant compromise reveals only the already-shared identity/device directory and that destination's opaque call slot, not home account authority. Reissuing an unexpired grant does not invalidate other approved devices' destination connections. Inspection is rate-limited to 240 requests/grant/minute and returns {nonce,host,identity,validForMS} with validForMS bounded to 10,000 ms; the target starts that budget before sending the request. The inspection body is exactly {grant,host,nonce}. Local account disablement and grant revocation reject inspection immediately. Identity data contains a neutral member role; only the destination's stored role governs its permissions. These are fixed protocol bounds, not configurable lifetime settings. The complete exchange/call/client integration is validated by the acceptance suites below.
Host visibility must not be used as a substitute for membership checks. Unknown policy values and unsupported descriptors fail closed. Deployments remain closed by default; enabling the completed runtime does not enable the owner’s separate visitor or registration controls.
Testing
D-179 unit and service fixtures verify directory metadata bounds, owner authority, public-visitor prerequisites, verified registration, case-insensitive text/tag search, withdrawal/offline suppression, bounded queries/cursors, HTML escaping and safe join-link destinations. Ordinary shortcut resolution remains covered separately.
SPEC-025's scoped presentation-registration POST is explicitly permitted by both public-network authority transports, without enabling arbitrary account commands or forwarding login headers/cookies. The existing public-address validation, finite timeouts and no-redirect behavior remain. Test its fixed method/path/body bounds through the production adapters, rather than using only a permissive in-memory network.
SPEC-025's managed presentation trial tightens call movement after a foreign host registers an existing approved call for provider cleanup. The delegation cannot create or renew a home voice slot. Preserve a durable managed-closure fence through release, expiry, restart and subsequent attempted moves; ordinary native timing alone cannot satisfy it. Verify the pinned old host and exact account/call reference, reject unavailable/false closure confirmation, and clear the fence only after confirmed absence. Native microphone-only reservations retain their current movement behavior. Integration tests cover two independent authorities, failed registration, pending closure beyond four seconds and successful movement after provider closure.
D-156 units verify the exact 10,000 ms constant, successful delayed inspection beyond one second, cache reuse strictly before expiry, rejection at expiry and beyond, shorter home lifetimes, clock rollback, and absence of expired-cache fallback. Federation tests preserve actual outage/revocation behavior after expiry and enforce the independent voice-authority deadline.
Shared units must cover canonical home/server/coordinator identities, pasted-link parsing, reserved paths, wrong/changed descriptors, scheme/path/port restrictions, bounded fetches, token audience/issuer/device binding, nonce/replay/expiry, account-ID collisions and blocked-domain precedence. Server-side discovery needs actual connection-level private-network/DNS-rebinding protection; parser tests alone are insufficient.
Use two independently stored account/room servers and a separate coordinator fixture. Exercise a visitor retaining its original account, a destination-local account, registration enabled/disabled, multiple simultaneous text connections and voice movement across servers/devices. Verify no credential or pending command crosses the wrong server/account, home roles confer no remote privilege, and an untrusted destination cannot read the client vault or execute in its trusted origin. Test coordinator/home/host outages, revoked devices, bans, stale keys, token rotation and changed shortcut mappings. Validate both server-readable and E2EE authorization without mode downgrades. Measure public join latency rather than equating a one-button UI with zero network work.
Acceptance criteria
- An owner can opt a public server into the directory without central manual approval; an ordinary member cannot publish it.
- Searching the website returns currently verified matching listings with escaped name/description/tags and an ordinary join link. Withdrawal, disabled visitors or failed verification removes the listing from results.
- D-156: directory approvals may remain usable for up to 10,000 ms from request start, including transport time; reuse cannot restart that deadline, expired results cannot authorize actions, and voice authority remains separately capped at 3,000 ms.
- A user pastes a shortcut into the desktop or web client's Join a server workspace, sees the verified destination/account, and joins a compatible public server through one explicit Join action without another password/account.
- A signed-in client retains at least two server connections and can change text views without moving voice or mixing sender identities, drafts, history or command results.
- Target-local login and registration are available only under that server's policy; visitor admission and local registration can be configured independently.
- Host inspection sees an appropriately scoped visitor record and local permissions; it never receives home passwords, reusable home sessions, recovery secrets or private device keys.
- Shortcut resolution alone neither admits the user nor initiates a call; an invalid, retired or changed-authority link fails visibly without credential forwarding.
- Removing the coordinator from the fixture leaves existing connections and direct-server entry functional.
- Existing accounts and the live deployment retain their identity/domain/data unless a separate migration is approved and validated.
- Cross-host/device revocation, one-active-call enforcement, E2EE verification and endpoint isolation pass before federation is advertised or public joins are enabled.
Public join links (D-115)
CONFIRMED by the human's public-link request and text-only channel-opening answer on 2026-10-21. Public server and public channel context menus offer copyable links for Add server. A channel link joins the server under normal admission rules and opens/joins the channel for text when allowed; voice remains unchanged. A denied server stays visible without exposing inaccessible channels. Links are locators, never permission grants or invitations.
Technical encoding: a server link is its verified canonical HTTPS base; a channel link appends #channel=<lobby-or-UUID>. Only that exact fragment grammar is accepted; reject extra fields, encodings, queries and invalid IDs. Strip the fragment before existing verified direct/shortcut resolution. Private channels, threads and direct conversations have no public copy action. Server copy is available when public visitor admission or local registration is enabled. Clipboard failure exposes a selectable link.
After an explicit join attempt, retain a verified destination as an account-qualified saved connection marked pendingJoin until admission succeeds. Pending roots show Not joined, support retry/removal, and never request or display channel lists. Reuse existing admitted connections without replacing credentials. Retry uses the originally selected qualified account. After admission, resolve the target only against the permission-filtered room list; absent/denied targets give generic feedback and retain the server. No hidden-room lookup, microphone capture or voice move follows a link. Opening a browser channel URL preserves the target through sign-in and the existing explicit Join confirmation.
Configuration: no new server setting. Optional pendingJoin: boolean in the protected device vault defaults to absent/false; optional pendingChannel retains a requested channel ID and is absent for server-only links. Existing admission, channel inheritance and URL validation remain authoritative.
Testing: unit coverage for strict parsing, canonical generation, fragment-free discovery and identity mismatch; browser coverage for public/private menus, clipboard fallback, denied persistence/retry/removal, existing connections, hidden targets and unchanged voice.
Acceptance criteria:
- Copy and paste a public channel link to admit and open text under existing permissions, without joining voice.
- Denied admission retains a retryable server root across reload without requesting or showing its channels.
- Inaccessible target channels disclose no metadata; successful server admission survives a target failure.
- Existing connection credentials, account isolation and canonical discovery checks remain intact.
D-138 repairs native clipboard writes for the existing public links and adds the same selectable canonical HTTPS channel link to Channel settings for public ordinary channels. Private channels, thread calls and direct/group conversations have no public share-link field. A link remains a locator subject to server admission and channel permission checks, never an invitation. Copy success requires a completed clipboard write; failures leave the link selectable with explicit copy guidance. The desktop grants sanitized clipboard writes only to the selected main application frame; clipboard reads and writes from other frames/origins remain denied. No permission prompt or new user setting is introduced. Native integration tests must exercise an actual write, alongside frame/read denial checks.