pub const PERSONA: &str = "persona";Expand description
The holder’s identity attributes, profiles, bindings and contacts
(persona/*) — the fourth store, beside VAULT (secrets and
credentials), MEMORY (agent memory) and APP_STATE (uninterpreted
application JSON).
It is a distinct store because disclosure control is its point, and a
maintainer that cannot read a record cannot decide which of its members may
leave, cannot audit which ones did, and cannot answer “what have I shared
with whom”. APP_STATE promises never to interpret its records, so it
cannot host this; and a namespace there is collision avoidance rather than a
trust boundary, so a compromised application sharing a context could remove
the holder’s identity data.
Two scopes share the keyspace, and the split is a security control rather than a filing decision. The pool and profiles are agent-scoped — above every context — so that the correlation index can see the risk it most needs to report: the same value presented by two personas in two different contexts, which a per-context index cannot see by construction. Bindings, contacts and disclosure records are context-scoped, because a persona lives in a context and so do its counterparties.
Nothing inside a context may read the agent-scoped prefixes. The holder pushes a materialised projection down; a context never pulls. That is enforced at dispatch, not here, but the prefix split is what makes the enforcement expressible.
Agent-scoped:
pa:<attributeId>— one attribute of the pool.pp:<profileId>— one profile.pxi:<hmac>— correlation index, keyed by a keyed hash of the value so exact-match lookup works with no plaintext index over personal data.pxr:<attributeId>:<profileId>— attribute → profile reverse index, so a delete can name its referring profiles without scanning every profile.
Context-scoped:
pb:<contextId>:<personaDid>— binding of a profile to a persona DID.pc:<contextId>:<contactId>— a contact’s current revision.pcr:<contextId>:<contactId>:<rev>— superseded contact revisions, reference-counted rather than reaped on a flat TTL: a revision behind a disclosure record is evidence the holder can still be asked to account for.pd:<contextId>:<seq:020>— append-only disclosure record.plp:<contextId>:<profileId>— context-local profile (inline entries only). A separate prefix, not a flag onpp:, so a context-scoped list scans a space that structurally cannot contain a pool profile — a filter bug there would be the same one-line leak the authorization rule exists to remove.plb:<contextId>:<personaDid>— binding of a local profile.
The holder’s identity is the account → in BACKED_UP. A restored agent
that came back without it would be an agent that no longer knows who its
holder is.