RFC: Sovereign User Data — portable identity bundles and federated user operations #255
imajin-jin
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Migrated from #251
Summary
An architectural RFC for how user data is stored, owned, and operated on across the Imajin platform. Defines the relationship between service-owned tables (runtime model) and user-owned portable data bundles (canonical truth).
Problem
Today, a user's data is scattered across 13+ service databases, organized by what each service needs. The user's identity is sovereign (DID, keypair, portable) but their data is not — it's shaped by services, not owned by users. This is structurally the same model as every platform, just self-hosted instead of cloud-hosted.
For Imajin to deliver on sovereignty, users need to be able to:
Architectural Position
Service tables are the runtime model
Postgres stays. Services query shared indexes for performance — loading an event chat with 400 attendees can't fan out to 400 per-user databases. Relational tables are the right choice for coordinated reads.
The user's data bundle is canonical truth
The exportable, signed, portable data object is the source of truth for what belongs to a user. If the node disappears, the bundle is what survives. Postgres is effectively a cache of user-owned data.
Design: Append Log per DID
Every mutation that touches a user's data appends to a per-DID event log:
Why append log over dynamic export
The append log wins because it also provides:
Federated User Operations
Each service implements a standard interface:
exportForDid(did)Returns all data owned by this DID from this service, in a portable format.
deleteForDid(did)Removes all data for this DID. Returns a signed deletion receipt. Open questions:
transferForDid(did, targetNode)Coordinates with target node to migrate data. Verify DID ownership on both ends.
countForDid(did)Returns data footprint — useful for pre-delete review ("you have 47 assets, 312 messages, 3 tickets").
Orchestrator
Auth service (as identity authority) fans out operations to all registered services. The service manifest (#227) provides the map of "who has data for this DID."
The Data Bundle
A user's portable data object, assembled from the append log or dynamic export:
{ "did": "did:imajin:ryan", "exported_at": "2026-03-09T16:45:00Z", "node": "jin.imajin.ai", "signature": "...", "sections": { "identity": { "attestations": [...], "tier": "hard" }, "profile": { "handle": "ryan", "display_name": "...", ... }, "media": { "assets": [...], "contexts": [...] }, "events": { "tickets": [...] }, "chat": { "messages": [...] }, "connections": { "graph": [...] }, "learn": { "enrollments": [...], "progress": [...] }, "fair": { "manifests": [...] } } }Signed by the user's DID keypair. Verifiable by any node.
Open Questions
Related
Beta Was this translation helpful? Give feedback.
All reactions