Data Rooms

A data room is a shared, credential-governed, end-to-end-encryptable space — a set of records readable and writable by exactly the parties the room itself admits. It is the first construct in the ecosystem that is neither a person nor a community: a room has its own DID, issues its own DTG credentials, and can move from one host to another without a single credential being reissued. Rooms landed in the VTI between 2026-09-03 and 2026-09-17, were the headline of the Eucalyptus release candidate, and shipped in the VTI-Eucalyptus release of 2026-10-07 (coordinated-releases).

Why rooms exist

The motivating case is shared memory for AI agents. A personal agent already has private memory in its holder’s VTA (vta/memory/*). What was missing was a space an agent can also recall from and write to, whose access control belongs to the people in it — a team’s shared context, a working group’s notes, a family’s records. The design note is explicit that a room serves two audiences at once: humans reading and curating it as shared information, and their agents recalling from it as shared memory. One record model, never a human wiki beside an agent store.

The second motivation is the one that shaped the architecture: the host must not be trusted with anything but availability. A community operator running a VTC is the worst-placed party to read its members’ shared material, and an encrypted-at-rest store that still keeps a member list has quietly handed that operator the membership. So the design inverts the assumption most storage is built on: there is no member list, and there must not be one. Every operation is authorized by a presentation of credentials the room issued, verified against the room’s own DID — never by a host ACL, a session, or a roster. A host that kept a roster would become part of the room’s membership, and the room could no longer leave it. The absence of the roster is what makes a room portable.

How a room works

The room is a DTG node. It has a DID (did:webvh, ideally witnessed — see did-webvh; did:peer and did:key rooms also work for the browser demo). Its identifier is the roomId. Because it is a node in the decentralized-trust-graph, the existing credential vocabulary applies one level down: a VIC (invitation-credential) to enter once (joining is consent — a two-party act), a VMC (membership-credential) to prove membership thereafter, and one new type, the Verifiable Authority Credential (VAC), for what a member may do — read, write, curate, admin. The VAC is attenuable: a member’s VTA derives a narrower, hours-scoped, single-action grant for their agent without going back to the issuer. VACs (and a companion VDC for delegation) were added to dtg-credentials in September 2026 and to the spec as Working Draft 02.

Four topologies, one protocol. T1 Personal (a room on my own host, anyone I invite), T2 Community (a room on a VTC, governed by the community’s rooms.rego), T3 Cross-community (one home host, members from several communities — free once T2 exists, because a VMC binds a member to the room, not to a community), and T4 Peer (two VRC-linked peers). What differs is where the room lives and who governs creation, never what a room is. This is why the Trust-Task family is top-level rooms/*, not vtc/rooms/*.

Three visibility tiers, fixed at creation. open (cleartext, server-searchable), attributed (bodies encrypted; the host still sees which member acted), and private (encrypted, membership proven by an unlinkable zero-knowledge presentation). The ladder measures what the host can see. As of Eucalyptus RC-0, open and attributed serve; private is stored but refused until the DTG working group settles the same-subject ZK profile.

MLS is the group layer. On the sealed tiers, records are encrypted under keys derived from an MLS (RFC 9420) group. The mapping is exact: the DTG is MLS’s Authentication Service, the host is its Delivery Service (trusted for availability only), a membership change is a Commit made only by the owner, and the invitation carries the Welcome. One leaf per member — and the leaf is the member’s VTA, not their devices. The VTA acts as a decryption-and-proving oracle: an agent sends ciphertext and gets plaintext, asks for a presentation and gets an attenuated one; nothing key-shaped ever crosses. An epoch key chain lets a member (including one who has just joined) read records sealed under earlier epochs; the rungs are ciphertext the host stores but cannot open.

Hosts are interchangeable. Two hosts implement rooms/* today: vtc-service in-process (T2/T3) and the standalone room-host binary (T1/T4) — a deliberately tiny service with no policy engine, no roster and no admin surface, which stores ciphertext and answers Trust Tasks. It serves over HTTP, or over DIDComm and TSP via a mediator (connecting as its own did:peer:2, so a host on a laptop behind NAT is reachable), with identical authorization on every carrier because the presenter comes from the document’s own proof. It can run as a read mirror of another host’s room, pulling as an ordinary member with a read chain. Its identity can be enrolled with and governed by a VTA, following the same provisioning pattern as mediators and DID hosts (vta-topology).

The host is kept honest, not trusted. Records are signed and AEAD-bound to (roomId, key, version, epoch), so a host cannot forge, alter or relocate one. Silence is the remaining attack, so hosts compute a Merkle data commitment over a room’s records and serve inclusion traces, and the owner periodically anchors the MLS epoch authenticator, head version and commitment in the room’s witnessed did:webvh log — the one statement a host cannot make, forge, or show two members two versions of. Lifecycle is renewed, never reaped: a room the owner stops renewing goes lapsed → dormant → reclaimable, and a nominated successor can claim a dormant room.

A browser can be a member. vti-rooms-wasm compiles the member half (MLS group custody, sealing, opening, the epoch chain) to WebAssembly, so a tab holds its own key and its own group state and asks a host for nothing it could compute itself — the basis for a planned public demo site where someone with no wallet and no agent can be invited into a room by link. The VTA Wallet gained a rooms console the same fortnight, driving rooms/keys/* at the member’s VTA and rooms/owner/* at the owner’s.

Where it stands

Crates: vti-rooms (storage, wire types, authorization — depends only on vti-common), vti-rooms-dtg (the DTG chain verifier, kept separate so a host can reuse storage without a credential library), room-host (binary), vti-rooms-wasm (npm-bound, unpublished). The design went through three revisions and two security reviews before the first code merged on 2026-09-03 (#1237); by 2026-09-17 there had been roughly fifty PRs and vti-rooms was at 0.2.9. The pnm rooms {create,list,get,put,curate,renew} CLI is the member surface. Still open: the private tier’s ZK profile, a pull-shaped join for members with no inbox, cryptographic deletion as a verb, and the remaining leg of the epoch chain into an agent’s VTA. The crate READMEs say it plainly: early; the API will change.

As of Eucalyptus (2026-10-07). Rooms were the one headline of the release candidate that then stood still while the rest of the stack moved: between 2026-09-18 and the tag, vti-rooms went from 0.2.22 to 0.11.0 and vti-rooms-dtg to 0.13.0, but the changelog entries are empty — these are version bumps carried by the workspace’s dependency churn (DTG Credentials v1, data-integrity 0.8, trust-tasks-rs 0.22 → 0.27), not room features. The substantive changes are small and all on the host side: room-host acknowledges a frame it refuses rather than leaving the sender to time out (#1569), records duplicate executions (#1571), and warns on unknown configuration keys (#1678). The browser wallet’s rooms console (packages/core/src/rooms/) was not touched in the window, and private rooms are still stored but refused pending the same-subject ZK profile. Everything above describes the shipped state.