A social feed with tiered encryption built on Verus contentmultimap. Posts are encrypted to different z-addresses — only viewers with the right viewing key can decrypt each tier. Public, followers, close friends, or owner-only.
Each VerusID can hold multiple z-addresses (shielded Sapling addresses). By encrypting post content to different z-addresses, you create natural access tiers. The identity owner distributes viewing keys selectively:
Tier hierarchy — The system is hierarchical. If someone has the close-friends viewing key, they can also decrypt follower-tier and see public content. The owner key unlocks everything. This mirrors how real social media works: close friends see more than casual followers.
On-chain storage — Posts are written to the identity's contentmultimap as encrypted blobs. The tier metadata (which z-address was used) is stored alongside, so clients know which key to try. Unencrypted posts have no z-address field.
Key distribution — Viewing keys are shared out-of-band (DM, QR code, VerusID message). Revoking access means rotating the z-address and re-sharing with remaining members. The old key can still read historical posts, but new posts use the new address.
// Social post stored in contentmultimap { "type": "social_post", "body": "Post content here...", // plaintext or encrypted blob "tier": "followers", // public | followers | closefriends | owner "timestamp": 1711123200, // unix epoch "encrypted": true, // whether body is ciphertext "imageCID": "QmXoypiz...", // optional IPFS CID for attached media "zAddr": "zs1follower...qx7r" // z-address content is encrypted to } // API endpoints // POST /dev/multimap/api/social/post // body: { body: "...", tier: "followers" } // Creates an encrypted post on-chain // GET /dev/multimap/api/social/feed // Returns: { posts: [{ body, tier, timestamp, encrypted, imageCID }] }
When a post is encrypted, the body field contains the ciphertext. Clients with the correct viewing key decrypt it locally. Without the key, the post appears as an opaque hex blob.
Encryption at rest — Post content for non-public tiers is encrypted using Sapling note encryption before being written to the chain. Even full-node operators cannot read encrypted posts without the viewing key.
Viewing key isolation — Each tier uses a separate z-address. Compromising the follower viewing key does not expose close-friends or owner content. The hierarchy is enforced by key distribution, not by code — the close-friends key holder is simply also given the follower key.
Output escaping — All post content passes through escapeHtml() before rendering. URLs are validated with safeUrl(). No raw HTML from user data is ever inserted into the DOM.
Content Security Policy — The page sets a strict CSP: scripts only from the page itself, network requests only to api.verus.services and same-origin API endpoints, images only over HTTPS.
Key rotation — If a viewing key is compromised, the identity owner generates a new z-address for that tier, re-encrypts future posts to the new address, and distributes the new viewing key. Historical posts encrypted to the old address remain readable by anyone who had the old key.