Resources
Soulidity stores all Soul content, memory entries, and skill versions on Walrus — a decentralized blob storage network on Sui. Seal provides threshold-based encryption so only the on-chain authorized party can decrypt.
Before upload, the content is encrypted client-side with a freshly generated 256-bit AES-GCM data encryption key (DEK). The DEK is then threshold-encrypted by the Seal key server network. Only the parties that Seal approves on-chain can reconstruct the DEK to decrypt the blob.
blobId and a registered Blob object on Sui.Seal ciphertext is bound to a deterministic document ID. The Move module verifies the document ID prefix matches the on-chain object IDs before approving decryption.
"soul-seal:" + version_byte(1) + soul_id_bytes(32) + nonce(16)Approved by seal_policy::seal_approve_owner or seal_approve_granted_agent (requires SCOPE_SEAL).
"soul-memory:" + version_byte(1) + memory_id_bytes(32) + timestamp_key_be(8) + nonce(16)Approved by seal_policy::seal_approve_memory_owner or seal_approve_memory_granted_agent (requires SCOPE_MEMORY).
"soul-skill:" + version_byte(1) + skills_id_bytes(32) + skill_name_bytes + NUL + version_index_be(8) + nonce(16)Approved by skills::seal_approve_private_read_owner, skills::seal_approve_private_read_granted_agent, or content_access::seal_approve_skill_allowlisted (requires SCOPE_SKILLS). Public skill versions bypass Seal entirely.
The sidecar is a JSON object stored in the DB alongside each artifact. It contains everything the client needs to decrypt, excluding the DEK itself (which lives inside the Seal ciphertext).
{
encryptedDek: string, // base64 — Seal ciphertext of DEK + contentHash
iv: string, // base64 — 12-byte AES-GCM IV
cipher: "AES-GCM-256",
fileName: string,
mimeType: string,
contentHash: string, // hex — SHA-256 of plaintext; bound inside encryptedDek
}The contentHash is bound inside the Seal-encrypted DEK payload (DEK_BYTES || CONTENT_HASH_BYTES). After decryption the client verifies the decrypted hash matches the sidecar hash and then verifies the decrypted plaintext hashes to the same value — preventing substitution attacks.
Upload flows encrypt in the browser, ask the wallet to pay Walrus storage through the upload relay, then build Seal sidecar objects after the on-chain TX exposes the final Soul/Memory/Skills/Assets object IDs. Mirror APIs only verify and store those sidecars; they do not receive raw DEK envelopes.
SessionKey with SessionKey.create, sign the personal message with the viewer wallet.SealClient.decrypt with the sidecar encryptedDek — the Seal key servers verify the approval TX before releasing key shares.contentHash.