Most Hypermedia content is public by design: signed, content-addressed, and free to copy. For content that should stay private, the protocol has a visibility model. A document or comment can be marked private. Nodes then hand its blobs only to peers and readers who can prove they belong to the space. This page describes what the daemon does today. The feature is still changing, and part of it is switched off.
How it works
Two visibility values
Visibility is a string with two values: the empty string, meaning public, and Private. It lives on Ref and comment blobs, the two kinds that place content somewhere. Changes carry no visibility of their own, and neither do files.
Per blob, per space
The daemon keeps a table of which spaces each blob is visible in. A public blob has a single "everyone" row. A private blob has one row per space that may see it. A blob with no explicit visibility inherits it from whatever links to it. A Change inherits from the Change or Ref that depends on it. A file blob inherits from anything that links to it. Propagation does not depend on order, and one public record wins: if any public Ref reaches a Change, that Change is public for everyone.
Blob | Visibility |
|---|---|
Change | none of its own; it has no visibility record and is not public until a public Ref or Change chain reaches it, and a private Ref that reaches it gives it that Ref's space |
Ref | explicit; a private Ref is visible in its own space and must use a single-segment path such as |
Comment | explicit; a private comment is visible to the commenter's space and the target's space; the daemon's |
Capability, Contact, Profile | always public |
DagPB and raw file blobs | inherited from whatever links to them |
Because visibility sits on the Ref, the same Changes can be private work in progress and later become public through a new public Ref.
Private document creation is disabled
The daemon's PrepareChange RPC refuses a private change unless the document is already private. It returns a failed-precondition error that says private document creation is disabled. The Seed desktop and web apps removed their Private option in the same September 2026 change. Root documents can never be private, and private paths must be a single segment. Existing private documents keep working. The gate sits only in that RPC. The indexer has no such gate, so a client that builds and signs its own Changes and a private Ref can still publish a new private document, and every node will index it. Team notes call this Phase 1 of private documents (shipped early 2026, then gated). Phase 2 adds inheritance and invitations and is still in design; see Roadmap.
A second known gap: the daemon's own CreateRef RPC publishes version and tombstone Refs as public, whatever the document's visibility. Clients that publish private documents sign their Refs themselves. The security audit log records this as an open finding.
Who may read private content over HTTP
On a desktop daemon, the local API hides nothing. Every local caller sees every blob. Visibility is enforced only when the daemon runs with the -public-only flag, as hosted sites and gateways do.
On a public-only node, a request must carry a bearer token minted by the daemon (see Identity), and private content is served when the token's principal:
is the space owner, or
holds a WRITER or AGENT capability scoped to the root of the space, or
is an AGENT of a key that holds such a root grant.
A WRITER scoped to a sub-path can write there but is denied private reads there. This asymmetry comes from how the read predicate is written, and it is a tracked issue. In public-only mode, even the owner's own daemon denies its own private document to an unauthenticated HTTP request. The Seed web app forwards the visitor's cookie as that bearer token on every daemon call.
How peers are gated
Peer-to-peer delivery is the only place with real access control. It has two layers.
Peer authentication. A peer proves it holds an account by signing an ephemeral capability naming the account and the server's peer, fresh within one minute. The server remembers that proof in memory for the connection.
Authorization. A private blob is served to a peer only if one of these holds: the peer is allowlisted for an in-flight push; it is authenticated as the space owner; it is the server the space names in its home document's siteUrl (resolved by fetching that site's /hm/api/config and comparing the peer ID); or it is authenticated as an account holding a WRITER capability for the space, at any path.
Set reconciliation is filtered the same way. The server computes which spaces the peer may see and folds range fingerprints over the filtered view, so an unauthorized peer never learns that hidden blobs exist. Plain blob listing never lists private blobs. A daemon that holds a WRITER grant for a space authenticates automatically before syncing with that space's site.
Two facts matter here. First, AGENT keys count for HTTP reads but not for peer sync. An AGENT alone gets nothing private over the network, while a WRITER on a single page gives that peer the whole space's private blobs. Second, the siteUrl server is trusted because the home document says so. A space owner who points siteUrl at a hostile host grants that host the space's private blobs. This is by design, and it is why the team says a private document "requires a server for now". Integrity lists this among the trusted parts.
No encryption
Private means access control on delivery. Nothing is encrypted. Any node that legitimately holds the blobs holds them in the clear, and a node's owner can read its own store. Visibility also cannot be revoked. What has been delivered to a peer stays there.
Working with private content
In the Seed app
The desktop and web apps no longer offer a Private option when creating a document. When they did, private drafts got random single-segment paths. Private documents are visible in the app only to the owner and to root-level writers. The web app filters them out for anonymous visitors and shows them to signed-in collaborators through the bearer cookie. Because of the daemon gate above, the apps cannot create new private documents today.
CLI
The Seed CLI has no flag for private visibility on document create. It publishes public Refs. It can read a private document from a site only with a bearer cookie, and it does not manage one. Treat the CLI as a public-content tool today.
SDK
In the SDK, createVersionRef and the other Ref builders accept a visibility option, and createComment does too, so a client can publish private Refs and comments itself. PrepareDocumentChange accepts visibility. Reading private content from a site needs the Authorization: Bearer header from POST /hm/api/auth. See SDK.
Web API
The Seed API on a site returns private resources only to requests carrying the auth cookie or an explicit bearer header whose principal passes the root-grant rule above. Otherwise they are absent from listings, and Resource reports them as not found. GET /hm/api/file and image routes forward the same cookie to the daemon. See Web API.
Agents
Seed Agents publish documents as public. The runtime's document writes do not pass a visibility through to the Ref, even though an agent draft can record a visibility field. A comment written by an agent inherits the visibility of the document or comment it replies to, as the daemon's own comment RPC does. The agent server reads through the site's public API. So an agent that holds a root WRITER grant for a space can read that space's private documents only if its requests carry a bearer token for its key. The runtime does not send one today. External agents using the CLI are in the same position.
Where this is going
As of September 2026 the direction is Phase 2 of private documents: read and write grants on private documents, inheritance for children of private documents, anyone-with-the-link access, and invitations to people who have no account yet. The HM26 node redesign gives private documents optional names instead of random paths. The team has also stated that without encryption, reading and syncing are the same permission. That shapes how sync permissions will be expressed. See Roadmap and Permissions.
See also
Do you like what you are reading? Subscribe to receive updates.
Unsubscribe anytime