Direct conversations and temporary groups
Document: SPEC-018. Revision: 1.5. Date: 2026-11-03. Lifecycle: requested outcomes confirmed under D-087, temporary history retention under D-088 and first-contact acceptance under D-089; the reviewed completion design is approved under D-090. Alpha.11 is deployed; D-092/D-147 refine client presentation under SPEC-005 without changing the shared protocol; Pinned is the current label for the saved-contact list formerly called Friends. Supersedes: D-088 selects temporary-group history with a four-hour default and one-year ceiling in place of SPEC-006's general seven-day horizon for this new type only. Navigation, creation-right and storage amendments are implemented; validation and limits are recorded in the implementation and release reports.
Confirmed request and review boundary
D-128–D-130 now request screen sharing inside accepted direct conversations and ad hoc groups under SPEC-023. D-134 approves completion, integrated in local alpha.24, without changing this document's contact/invitation acceptance, host, E2EE, membership, history or one-active-call rules. A screen request cannot admit a new participant or implicitly answer/move a call; a third person still requires a distinct accepted group. Screen-policy settings for these types must not make them ordinary editable channels or grant server administration to their creator.
D-087 requests direct text messaging from Pinned and Recent, a Server Members list for finding other people, one-to-one calling from the same lists, and an easy way to add people to ad hoc non-persistent channels. R-013/R-014 already require direct messaging/calls locally and across domains. R-015/D-002 require E2EE for direct communication; there is no server-readable fallback.
The requested outcomes are approved requirements. D-088 answers Q-58: temporary voice ends, but group text remains in configurable history with a four-hour default and a one-year ceiling. This rejects the earlier deletion-on-close recommendation. D-089 answers Q-59: first contact requires acceptance before ordinary messages or ringing. D-090 approves the reviewed directory, hosting, retention-control and lifecycle design and authorizes implementation. Engineering selections below complete its bounded profile. Existing public admission settings remain unchanged.
SPEC-005 owns the interface. SPEC-008 owns directory, admission and server enforcement. This document owns shared conversation identity, membership, lifecycle and compatibility. SPEC-003/011/015 retain identity/device trust; SPEC-006 owns ordinary message retention; SPEC-004/016/017 own audio, key lifetimes and routing.
Conversation types (D-090)
| Type | Participants and purpose | Lifetime and content |
|---|---|---|
| Direct conversation | Exactly two qualified accounts; independent of any shared server channel | Stable conversation identity. Encrypted messages use SPEC-006's existing seven-day retention, original acceptance timestamps and eligible linked-device/recovery copies. Ending voice or closing its view does not delete text. |
| Temporary group | Explicitly invited people, including its creator; text and optional voice | Unlisted, with explicit live membership. Its live session closes after everyone leaves; encrypted text remains for its configured retention period under D-088. Closure does not create a persistent writable channel. |
| Existing channel/thread | Existing access, host and inherited thread rules | Unchanged. A direct/group interaction does not create a persistent server channel or widen its membership. |
A person is identified by canonical home authority plus stable account UUID; nicknames and saved last-known channels are labels. A direct conversation has an immutable pair of account identities and one canonical ID at its authority. Opening it from another server, list or device resolves the same pair. Self-DMs are outside this increment. Changing the selected server does not change the active account or remap a person to a same-named local account.
Adding a third person creates a new temporary group with a new ID and keys. It never adds the person to the original two-person transcript. Invitees see the proposed participants and must accept. Accepted newcomers receive messages from their admission onward, not earlier group history. Leave/removal ends future access; re-admission while the same group survives follows the existing eligible-period rule without exposing the absence. Copying or quoting old messages into a group is a separate deliberate send by a participant.
Ordinary members may create direct conversations and temporary groups under bounded quotas. This is an approved exception to owner-only creation for these hidden conversation types only; SPEC-012's persistent-channel creation permissions remain. These objects are not editable through ordinary channel administration or revealed by its listings.
First-contact acceptance and invitation lifecycle (D-089/D-090)
CONFIRMED D-089/R-097: an account sends a first-contact request; the recipient must accept before ordinary DMs or ringing are permitted. Apply this gate to all entry points, including Pinned, Recent, Server Members, exact addresses and direct API calls. A pending request cannot authorize ordinary messaging or ringing.
Completion profile: the request contains authenticated identity and request state, without arbitrary message body, attachment or automatic media negotiation. An unsent draft stays with its author. Accepting authorizes communication between the pair but does not automatically save either person to Pinned or answer a call. Both parties' affirmative actions establish the pair; concurrent reciprocal requests resolve idempotently to that same accepted relationship.
Pinned remains a private, one-way address book. Saving a person, encountering them in Recent, or sharing a server is not evidence of their consent. All three lists can initiate requests, subject to the completed admission and abuse-control contract, but cannot bypass D-089's gate. Immediate contact by shared-server members or arbitrary known addresses was not selected. D-090 subsequently approves the detailed blocking and invitation rules below.
The recipient can accept, dismiss or block. Blocks are account-wide qualified-identity records enforced by the account authority, independent of Pinned and Recent. A blocked sender cannot create another request, message, ring or group invitation to the blocker. Do not disclose whether refusal means block, account unavailability or policy. Removing a friend does not block; unblocking does not automatically restore accepted contact permission. Dismissal must not create repeated alerts through request retries; bounded cooldowns and quotas are required before implementation.
Inviting someone to a temporary group requires the inviter's accepted contact permission with that person under the selected policy. The invitee explicitly accepts the group even if the pair already permits DMs. Recheck all group members for applicable blocks before admission, so an inviter cannot bypass a block through a third party. Blocking during a direct call terminates that pair's call; in a shared temporary group it withdraws the blocker's membership and closes their media, leaving unrelated members connected. The Block action explains that consequence. Ordinary shared-channel moderation and personal listening controls retain their existing semantics.
Call lifecycle (D-090)
A call invitation is distinct from text navigation, contact approval, group admission and voice attendance. Client-visible states include inviting, ringing, accepted, connecting, active and ended, with terminal declined, cancelled, expired and failed outcomes. A server acceptance is not evidence that the other person is online, has seen it or has answered. A bounded ring expires rather than becoming a delayed incoming call when an offline device reconnects.
Authorized signed-in devices receive the same incoming invitation. Acceptance is atomic: the first valid answer owns the account's existing single voice slot; other devices dismiss the ring. Decline/cancel/answer races serialize at the call authority. Cancel before acceptance makes later answers fail; cancel after acceptance ends that invitation's call rather than reviving or duplicating it. Retry uses the original operation identity.
Accepting a call never silently abandons another active call. The client offers explicit movement under SPEC-011/015, preserves the cross-host fence and requires fresh PTT. Opening or sending a DM while talking elsewhere leaves voice unchanged. No peer ICE exchange, audio capture or playout begins merely from a contact request or ring. After both parties accept/join, SPEC-017 private E2EE routing applies, including both-party direct permission, relay-only preferences and single-upload fallback. D-105 supersedes the original hold-to-talk-only input rule: calls inherit host PTT policy, personal enabled PTT always wins, and optional voice activation requires explicit enabling under SPEC-004. Maximum talkspurt and all capture authority gates remain.
Temporary group voice uses the same accepted membership boundary. Any joined participant can invite another permitted contact; admission is explicit and triggers fresh keys/cleared PTT. The creator can remove a participant or end the group; others can leave. The creator leaving does not end everyone else's conversation: ownership transfers to the earliest admitted remaining account in authoritative admission order. The UI shows the current owner. A server operator may deny service or disable an account under existing authority, but receives no conversation participant status or decryption keys by virtue of a server role.
Creating a group from a one-to-one call does not silently add listeners to that call. Create the new group, invite the existing peer and additional people, and offer each current caller an explicit move. The old two-person call may continue until each chooses to move or leave. Group invitations and text admission never themselves claim the voice slot.
Temporary lifecycle and retained history (D-088; P-032)
Temporary membership is explicit and independent of whether voice is active: a text-only participant keeps a joined group alive. Navigating elsewhere keeps that joined session until Leave or session loss; a visible active-conversation entry provides a return path. Liveness is maintained by authenticated joined clients, not by an offline address-book entry or outstanding invitation. Multiple approved devices count as one account with separate joined sessions.
Selected lifecycle: the last explicit Leave closes the group immediately; if all clients disappear without leaving, allow a two-minute reconnect grace before closing. A server restart reconstructs the original deadline and cannot reset it. Pending invitations do not keep an empty group alive. The creator is its first joined member, so an unanswered invitation also expires when that session is gone. End group closes it for everyone immediately. Closed IDs cannot be reopened by old invitations, retries, queued sends or delayed presence renewals.
CONFIRMED D-088: the voice session is temporary, but its text remains in configurable history. The default retention is four hours and the maximum is one year. This requirement replaces the initial proposal to erase text and exclude recovery copies on closure. It does not change ordinary DM/channel retention.
Selected completion: the creator chooses retention when forming the group, with four hours preselected and the value visible to every invitee. Measure each message's lifetime from its host acceptance, following the existing data model. Fix the selected duration for that group so later administrative changes cannot unexpectedly prolong retention or erase promised history. Use a new group to choose a different duration. D-090 selects this timing/control model; one year means 365 days of elapsed time.
At closure, revoke live attendance and media, stop new text and invitations, clear unsent group drafts, and show the eligible transcript as read-only until its messages expire. The participant's conversation history provides a return path even though the group is absent from active server channels. Starting again with the same people creates a new group and requires new invitations; the old group ID is never reopened. No voice recording is created.
The closed group's retained membership evidence continues to authorize eligible history reads, device shares and recovery; closure is not a new admission or blanket removal of those rights. Never expand eligibility beyond the participant's actual membership periods. Enforce account/device revocation and service-denial policy on every read, while a later personal block prevents new contact rather than rewriting already accepted history. Closing the group never copies one-to-one DM content into it.
Persist an authenticated expiry for each message derived from its group's fixed retention and original acceptance. SPEC-011 device-history and recovery copies carry that expiry and cannot reset it. The current code's seven-day assumptions require a versioned, bounded retention profile for this new type; merely raising a global constant is invalid. Local protected transcripts must prune by the same expiry, and reads deny expired material immediately even if physical cleanup is pending. Old clients lacking the retention profile cannot join or receive copies that they might retain incorrectly. Existing storage quotas still apply; long retention is not permission for unlimited storage or a promise of unlimited capacity.
After the last retained message expires, remove the transcript and unneeded group metadata, retaining only bounded non-content identities needed for replay/command safety. Recent may retain participant identities under SPEC-014 but cannot open expired group history. DMs and independent Pinned entries remain intact. This promises application-controlled expiration, not erasure of screenshots, deliberate copies, modified clients or forensic copies. Retained encrypted archives/recovery do not gain forward secrecy from temporary voice keys.
Hosting, offline delivery and security (D-090)
Keep one authority per conversation. Canonical DM authority: use the home service of the lexicographically first (canonical domain, account UUID) in the immutable pair, with an exact wire ordering defined in the completion profile. Same-domain pairs naturally stay local. This prevents opposite-direction first opens or simultaneous calls creating two DM histories. Host failure makes that conversation temporarily unavailable; do not silently fork it onto the other home or the selected community server.
A new temporary group is hosted by its creator's home service; its authority stays fixed after ownership transfer. Participants see the actual authority. Selecting a person from Server Members is only discovery: it does not make that community the conversation host, give its moderators private membership, or force either person to stay in that community.
Cross-domain requests require a new authenticated, recipient-addressed inbox and purpose-bound conversation admission. Reuse SPEC-010/015 authenticated discovery, public-network restrictions and approved-device proofs, but do not reuse a generic public-server Join as consent for a private conversation. An accepted invitation grants only its exact conversation. It does not open public visitor admission, local registration, server directories or ordinary channels. Existing domain blocks and the federation runtime remain effective; closed policy produces a clear failure without inventing a destination account or forwarding home credentials.
Both homes must validate the accepted pair and intended authority before issuing scoped admission. A fresh account/device verification and signed roster are required for encrypted sending, including when recipient devices are offline. If a necessary home is unavailable, pause new encrypted sending under D-078 and preserve already readable eligible text. Once the conversation host durably accepts encrypted text, an offline recipient can retrieve it within the existing retention horizon. Do not present acceptance as delivery or a read receipt.
Reuse the approved SPEC-009/011 signed, per-device encrypted text envelope for this increment, binding conversation type, authority, ID, participants/membership revision and original expiry. Both ordinary DMs and temporary-group text include current approved devices and approved recovery recipients, subject to eligible membership and their respective retention. Retain TOFU/key-change handling and the stated lack of text forward secrecy; SPEC-016's ratcheting-text evaluation continues independently. Do not introduce a new cryptographic algorithm through this feature.
The engineering completion profile below defines exact capability names, endpoints, strict request/response shapes, signatures and scope binding, canonical pair resolution, inbox authorization, acceptance/block revisions, lifetimes/quotas, state transitions, expiry/tombstone storage and schema compatibility. Unsupported clients/hosts show an update/unavailable explanation. Old servers must reject the new storage schema rather than interpret a hidden conversation as an ordinary channel. Existing channel text, device recovery and public/private voice behavior must remain compatible.
Incoming unread projection (D-104)
Conversation summaries add optional lastIncomingMessageSeq: the greatest retained, eligible message position whose author is not the viewer, or zero. Apply the same expiry and membership-period filters as lastMessageSeq; neither field grants history access. Old summaries may omit the incoming field; a client may retain the legacy aggregate unread summary but must not claim a person-specific incoming DM from an unknown projection. Local protected read positions remain keyed by full account plus authority UUID/conversation ID, advance monotonically only for successfully loaded visible history, and publish no receipt. Client presentation belongs to SPEC-005.
D-194/D-195 native order: summaries also add optional lastMessageAt, a nonnegative safe Unix-millisecond timestamp from the greatest retained, viewer-eligible message sequence, with zero when none exists. Apply the same membership-interval and expiry filtering as lastMessageSeq; this is the last sent or received text acceptance time and discloses no otherwise ineligible message. It grants no access, presence or read receipt. An older response omitting the field supplies unknown recency, treated as zero for native sorting. The host derives it on read; no new persisted clock, client-writable value or configuration is introduced. Opening a conversation, pinning, ringing or updating membership cannot update this field.
Configuration
D-088 selects the four-hour default and one-year ceiling; D-090 approves the reviewed creation-time policy. The values below are fixed engineering bounds for this implementation, with no operator override. Existing settings retain their owning specifications and precedence.
| Item | Classification, value and scope | Validation, timing and persistence |
|---|---|---|
| First-contact acceptance | Fixed product rule, confirmed D-089; no ordinary DMs or ringing before acceptance | Enforce at the server for every entry point. Saving a friend, a Recent encounter or sharing a server cannot override it. No user/operator bypass setting is introduced. The request/block state and quotas below apply. |
historyRetentionSeconds | Per-temporary-group creation policy, creator-written; default 14400 seconds confirmed D-088. Maximum one year confirmed; selected exact maximum 31536000 seconds (365 days). | Strict integer seconds in multiples of 60, range 60–31536000; minimum/granularity are engineering selections. Omission selects 14400; null, zero, negative, fractional, unknown unit or over-cap values reject. Authenticated creation input is persisted immutably and included in invite/history context; no inherited server value or later override. Each original acceptance fixes message expiry; copies keep it. No secret value. Versioned storage/capability must reject incompatible readers. |
| DM content retention | Existing fixed SPEC-006 rule, 604800 seconds from original host acceptance | New copies cannot extend expiry. Closing voice or hiding a DM does not expire otherwise eligible text. |
| Temporary reconnect grace | Fixed 120000 ms, host-authoritative; starts when the last joined session expires | Explicit final Leave/End closes immediately; delayed responses/restarts cannot extend it. Joined-client presence renews every 5000 ms and expires after 20000 ms; reconnect grace starts at the last recorded expiry, not at cleanup time. |
| Ring lifetime | Fixed 30000 ms from host acceptance | Exact retries never extend it; an old call cannot ring upon later reconnect. No persistent missed-call transcript is selected. |
| Temporary invitation lifetime | Fixed 600000 ms from host acceptance, additionally capped by group lifetime | One-use recipient-bound admission; closed/full/revoked context rejects acceptance. Pending invites reserve capacity but do not keep the group alive. |
| Temporary account cap | Fixed 10 distinct accounts including creator, consistent with the current voice fixture | Count joined members and distinct pending reserved seats atomically. Reject excess without creating a partially admitted group. Approved-device limits remain SPEC-011's. |
| Directory and conversation bounds | Fixed: 50 entries/page; 100 hosted conversations/account at each authority and 100 foreign home-inbox entries/account; 1000 conversations/host; 10 live temporary groups/account at each authority; 100 blocks/account; 50 pending incoming contact requests/account | Exact-address lookup 20/account/minute; new contact requests 5/account/minute and 20/account/day; request lifetime seven days, dismissal cooldown 24 hours. Existing message/body/device/storage quotas apply without increase. |
| Accepted pairs, blocks, invites, membership, host and closure | Operational state; no configuration default | New accounts have no accepted pairs/blocks/invites; exact type/version checks, authenticated writers and transactional persistence are required. Unknown state fails closed. |
| Pinned / Recent | Existing SPEC-014 account-private contacts and per-client recent retention | Existing bounds and protected storage remain. Versioned people snapshots use destinationVersion:1 and optional legacy channel context. A direct encounter needs no fictional channel. Legacy entries remain readable, and Message/Call resolve qualified identities without trusting saved locations. |
| Voice and privacy settings | Existing SPEC-004/016/017, including voiceRelayOnly and configured STUN | Apply unchanged to new private encrypted call scopes. Temporary groups do not alter public channel routing or the bounded hosted relay lifetime. |
Engineering completion profile (D-090)
The client keeps the existing one-request ordinary-channel sync loop. A separate two-second account poll reads the home conversation inbox and current summaries from known conversation authorities; selected conversation history is also refreshed. Joined-device presence renews at the configured five-second interval. Capability metadata is cached for five minutes, independently of fresh authorization checks. No read receipts or presence indicators are published. D-221: SPEC-027 hints may start these reads earlier; they reach only members entitled to the read (never members who left, other accounts' notices or non-participants), carry no content, and the two-second polls continue.
Advertise direct-conversations/1. Direct control uses authenticated /api/direct reads/actions, with mutations carrying an immutable UUID, issue time and canonical payload. Accept new operations for five minutes, retain results for one day, reject conflicting retries and expired mutations after result pruning. Root account actions remain bound to the active approved device; hidden conversation text/media continue using scoped room APIs and existing command tickets. Schema 5 adds a message expiry column (old rows retain original seven-day expiry) and excludes hidden conversation types from every ordinary channel/admin path. No existing identities, account keys, messages or permissions are reset.
A direct object uses a normal random room UUID plus immutable conversation:{kind,retentionSeconds} in its room descriptor and signed/encrypted text context. Type is direct or temporary. The canonical pair index orders canonical ASCII domain then lowercase account UUID with ordinary code-unit ordering, never locale collation. Its host is the first account's verified home. Message acceptance fixes expires = accepted + retentionSeconds*1000; history, shares, recovery and client display all enforce the same deadline. Closed/left temporary members retain only their eligible-period read rights. Persistent membership and per-device live presence are distinct records.
A separate authenticated server directory returns qualified ID, username, domain and nickname only. Exact-address lookup returns the same projection and never a password, device or private-channel list. Conversation-only visitors are excluded. Direct and group list projections include only the authenticated participant/invitee's objects. Pending contact requests do not create text membership; acceptance admits the immutable pair atomically. Requests are one-per-pair; duplicate retries do not create another alert. Decline starts the cooldown, and blocks are qualified account-private home records.
Cross-domain conversation access uses the existing destination-bound home directory delegation and fresh signed device proofs, with a distinct direct-connect purpose. A new foreign record is conversation-only; it grants no public-server membership, directory enumeration, room administration or ordinary-channel admission. A later explicit public-server Join may promote it only under the ordinary admission policy. Foreign contact/call/group actions check current home approval and domain restrictions; public visitor admission may remain closed.
The configured loopback development authority may host local-account DMs and groups. Only an exact match to that already-configured authority is accepted as local; cross-domain discovery, capabilities and notification destinations continue to require the public HTTPS authority contract.
Conversation authorities deliver bounded content-free inbox notifications to participant homes through a durable outbox. A notification supplies the authority descriptor and an opaque callback token; the destination authenticates identity discovery and reads the audience-bound payload from that authority over the public-only transport. Notifications bind local recipient, conversation authority/ID, type, participant identities and monotonically increasing version. They grant no membership and never carry message bodies or keys. The receiving home can obtain current call state only from the authority; a notice never authorizes playout or membership. Each receiving home validates its local recipient, expected canonical DM/creator-home authority, limits and blocked sender before storing an index. Call state is checked at the actual authority before answer; stale notifications cannot ring expired calls or grant admission. Retry backoff is bounded between one and sixty seconds, expires after seven days, and survives restart; successful delivery retires its opaque token.
Group invitation eligibility uses a short-lived, audience-bound contact capability issued by the inviter/target pair's canonical authority after acceptance. The group host verifies it directly with that authority and rechecks current group/block membership before committing. It grants neither text nor voice membership and does not replace invitee acceptance. Cross-host block checks use the home delegation to inspect only the named candidate participants, returning a combined allow/deny result without exporting the full private block list. Failure or stale policy fails closed for new communication. Each home maintains monotonically increasing revocation versions for affected qualified pairs. Acceptance captures those versions; a newer revocation requires new acceptance even after unblocking. Audience-bound invalidation callbacks are queued to affected conversation authorities; active media retains the existing hard authority deadline.
Contact, invitation, presence, call and closed-history APIs must serialize transitions with the room revision. Incoming ringing lasts thirty seconds, the first answering device is authoritative, and pending/expired invitations never permit media preparation or lease issuance. Group presence is renewed only for explicitly joined, unexpired device sessions. Another approved device joins explicitly; dismissing an unaccepted invitation cannot create a rejoin right. Admission rechecks account and group capacity. Unread positions are filtered by the viewer's eligible periods, and departed members receive a departure-time membership snapshot without subsequent call state or newly added people. The last explicit departure closes immediately; all-disconnect closure uses last presence expiry plus two minutes. Cleanup and access-time checks share those exact deadlines. Expired operations, delayed renewals and restart cannot resurrect closed conversations. Closed-group metadata is retired after both its configured history horizon and the one-day command-result horizon have elapsed. Membership rows and outbox state are removed with it. A call that has not connected within thirty seconds of acceptance ends; active direct calls require both voice leases after that deadline, while a temporary-group call can continue with one connected member. Only the answering device may end its active account call; late declines on other devices reject.
Testing
Audit regression coverage uses the real public command handlers and disposable SQLite databases. Creating either a DM or temporary group on schema 9, followed by repeated restart, must preserve unrelated ACLs, hierarchy, selected login/PTT policy, sessions and retained history. Removed, owner-revoked, dismissed and expired invitees cannot obtain voluntary-rejoin rights through repeated Leave, Accept/Join or replayed acceptance receipts; a fresh authorized invitation still requires explicit acceptance. Voluntary departure retains its existing rejoin and absence-history rules. Direct maintenance tests count shared voice/presence reads and retain exact ring, presence and grace deadlines across restart. See tests/audit-direct-state.test.ts. These restore D-090/D-125 contracts without adding a new setting or migration profile.
Native request-cadence regression holds an accepted group in the foreground over the real HTTPS fixture and counts requests per account: the independent two-second inbox loop produces about one inbox read and one Home contacts/presence read per cycle, and completed or failed text syncs and direct views add none. Any baseline controller sharing the generated account is deactivated for the measurement so its own loop is not counted.
Native-order projection tests cover outgoing and incoming acceptance timestamps, empty history, eligibility gaps, expiry, inactive/removed temporary members, and unchanged recency after open/read/call operations.
Test incoming unread projection against own messages, foreign peers, expired messages and ineligible intervals; test account/authority/DM-versus-group isolation and monotonic persisted local read positions.
Required unit coverage: canonical qualified pairs and simultaneous creation; type/scope/version separation; request/accept/decline/block and expiry races; per-device single-answer handling; idempotent message/call/group operations; approved-device/recovery recipients; membership intervals and no earlier transcript on group conversion; typed Recent destination migration; malformed/unknown state and all finalized quota boundaries. Retention tests include omitted four-hour default, exact one-year ceiling, rejection above it, invalid values, unchanged expiry through copies, read-only closed history, and preservation of ordinary seven-day content. Fake clocks must cover exact ring/invite/liveness/grace/content deadlines, repeated requests, delayed work and restart reconstruction.
SPEC-005 client validation covers navigation/voice separation, qualified identity, unread counts versus receipts, scoped drafts, first-contact and incoming-call presentation, group participant selection, accessible keyboard/touch actions and stale async result isolation. SPEC-008 server units cover ordinary-member directory projection and revocation, purpose-bound inbox/visitor admission, no server-role escalation, block enforcement, atomic recipient/capacity checks and durable closure/outbox cleanup.
Integration must demonstrate local and two-authority DMs with an offline recipient, linked devices and recovery within retention; unavailable home/changed key failures; simultaneous calls answered on different devices; group creation from a DM without history disclosure; all-participant leave/disconnect/reconnect and closure across host restart; temporary-group history readable through approved devices/recovery before expiry and unavailable after it; and independent existing-channel calls. Real browser/relay tests must render audio over direct, mixed and forced-relay routes, preserve one relay upload per frame, enforce fresh PTT on movement/membership change and maintain public-channel relay behavior. Physical platform/ringing/audio checks remain separate evidence.
Acceptance criteria
- Current-schema DM/group creation and two subsequent restarts preserve existing channel denial, hierarchy, policy, sessions and retained content; creating an older conversation type cannot lower the storage schema.
- Removed, revoked, dismissed or expired invitees cannot gain admission through repeated Leave followed by Accept/Join or an old successful receipt; authorized fresh invitation and legitimate voluntary rejoin remain available with unchanged history eligibility.
lastMessageAtmatches the original acceptance time of the last eligible retained message; expired/ineligible history and view/call operations cannot advance it.
- Incoming-message indicators exclude the viewer’s own messages and expired/ineligible history; opening the summary does not mark conversations read, and opening one eligible transcript clears only that conversation locally.
- Pinned, Recent and the selected server's Server Members directory each provide phone/message icons and a filled/outline thumbtack with full qualified identities and accessible labels under SPEC-005/D-147; no Group or Channel button remains in sidebar rows. D-092 moves Add people into the connected call controls, retaining explicit invitations/movement and the original private DM transcript; text selection never starts/moves voice.
- A normal server member can find another enabled member without learning hidden channel membership, administrative fields or unapproved presence; unauthenticated/removed visitors cannot enumerate the directory.
- The same qualified pair resolves to one encrypted DM across lists, selected servers and approved devices; accepted offline messages remain readable within the original retention limit, subject to current trust and eligibility.
- D-089: before recipient acceptance, ordinary messages and ringing are rejected through lists, typed addresses and direct API calls; pending requests, Pinned and shared-server membership cannot bypass this gate. Accepted contact still requires explicit call answering.
- The completed request/block lifecycle prevents repeated alerts from retries and third-party invitation bypass, with boundary tests for the selected cooldowns and quotas.
- A one-to-one call requires explicit acceptance and has one answering device; moving an existing call observes the current fence and fresh-PTT requirement.
- Adding people creates a separate temporary group; new members cannot retrieve, decrypt or recover earlier DM text or pre-admission group text.
- Temporary groups accept explicit text-only membership, support adding people without persistent-channel creation rights, and close under the approved lifecycle with no stale invitation or delayed renewal resurrecting them.
- D-088: a new temporary group defaults to four hours of text retention, supports a valid chosen duration up to one year and rejects values beyond the ceiling; ending voice leaves eligible text readable until expiry without reopening the live group.
- Group-history copies and recovery preserve the original expiry; after expiry no conforming history/archive/share/recovery path serves the text, and ordinary channel/DM retention remains unchanged.
- Cross-domain conversation admission works without opening public server joins or granting ordinary-channel/directory access; homes and host retain authenticated scoped authority, and unsupported/outage states never downgrade encryption.
- Existing channel/thread history, account identities, Pinned/Recent isolation, device recovery, single-call behavior and alpha.10 route/fan-out tests pass after migration; implementation/release status is recorded separately from this approved specification.