--- url: /faq.md --- # FAQ ## Data Sovereignty These answers cover storage ownership: who controls the canister and what stays under your control outside the Rabbithole interface. ### Who controls my storage canister? In the completed flow, you do. Rabbithole is a temporary controller during setup or an approved update so it can install or retry the deployment, then removes itself during handoff. See [Data Sovereignty](/how-it-works/sovereignty/index.md) for details. ### Can I use my own frontend? Yes. Your canister serves its own frontend, which you can replace. The canister API is public — you can interact with it through [Candid](https://internetcomputer.org/docs/building-apps/interact/candid/candid-concepts). ### What happens to my data if I stop paying? With On-chain Storage, your data remains in your canister while it has cycles. With Blob Storage, your canister keeps the file record and verification data, but blob availability depends on Blob Storage funding and retention. You can top up cycles directly without going through Rabbithole. If Pro expires, storage falls back to the storage license issued during storage creation. The owner keeps personal encrypted storage within the license limits, but automatic cycle top-ups and shared access require active Pro. ## General These are short answers about the product model and everyday limits. ### What is Rabbithole? A decentralized file storage app built on the Internet Computer, designed around end-to-end encryption and personal canister ownership. ### How much does it cost? You pay a fixed setup price to create your storage. This covers canister creation, the initial cycles balance, deployment operations, storage license, and the infrastructure needed to complete the handoff. The storage license defines included encrypted storage and the maximum file size for the base scenario. Pro adds capabilities on top of the license: encrypted uploads without base limits, shared access, and automatic cycle top-ups. See [What Pro gives you](/how-it-works/pro.md) for details. ### What file types are supported? All file types. Rabbithole stores binary file data, so the file format does not matter. ### Is there a file size limit? For encrypted uploads, the limit depends on storage license or active Pro. The license defines included encrypted storage and the maximum file size. Active Pro, among other things, removes those base license limits. Rabbithole does not add a separate technical file-size limit. Upload and encryption work in fragments, so the browser does not need to keep the whole file in memory when working with large files. Practical limits are still possible: with On-chain Storage, the file is written into the canister, and large uploads can run into limits of the subnet where the user's canister is deployed, as well as the cycle balance. ### Why does upload sometimes show Waiting for cycles? This is an On-chain Storage upload waiting for a safe cycle buffer. If the owner has active Pro, Rabbithole can top up the canister and continue the same upload session. Without Pro, the owner needs to top up the canister manually. ## Security These answers summarize the confidentiality and recovery model. ### Can the Rabbithole team read my files? No. Rabbithole's code and product interface do not include a mechanism that gives the team separate access to user files. Your browser encrypts the file before upload, so Rabbithole does not receive plaintext data. The canister keeps access rules and trusted records, while file bytes follow the selected storage mode already encrypted. ### What happens if I lose my device? You can recover access through Internet Identity's device recovery mechanism. Your encryption keys are derived from your identity, not stored on any specific device. ### Has Rabbithole been audited? The code is open source and available for community review. Formal audits are planned. ### What encryption does Rabbithole use? AES-GCM with per-fragment encryption. Keys are derived through ICP's vetKeys threshold cryptography. See [Encryption](/how-it-works/encryption/index.md) for details. ## Technical These answers cover development, self-deployment, and direct canister access. ### Where can I learn the basic Internet Computer terms? The [Core concepts](/getting-started/concepts.md) page explains the Internet Computer, canisters, principals, Internet Identity, controllers, and cycles in the Rabbithole context. ### Can I self-host Rabbithole? Yes. The code is [open source](https://github.com/rabbithole-app/v2). You can deploy your own canisters and frontend. ### Can I build my own client? Yes. The canister API is public. You can build any client that communicates with the canisters via Candid. --- url: /getting-started/concepts.md --- # Core concepts These terms come from the Internet Computer, not from Rabbithole branding. Rabbithole uses them in a product context, so this page maps the platform words to the parts of the app you will see in the docs. For the canonical IC wording, see the [Internet Computer glossary](https://docs.internetcomputer.org/references/glossary/). ## Internet Computer The [Internet Computer](https://internetcomputer.org/) is a decentralized network for running applications directly on-chain. Unlike blockchains that are mainly used as settlement layers, the Internet Computer can host backend logic, state, and web-facing canisters in the same environment. Rabbithole uses it across the product: the main frontend, the main backend canister, the storage canisters created for users, and holding or moving user funds from other networks through [Chain Fusion](https://docs.internetcomputer.org/concepts/chain-fusion/). ## Canister A [canister](https://docs.internetcomputer.org/concepts/canisters/) is the Internet Computer's smart-contract unit. It bundles code and state, runs on the network, and can be reached over the Internet. In the Rabbithole architecture, the main backend is a canister. Each user storage is also a canister. A storage canister keeps file records, permissions, and, depending on the storage mode, file bytes. ## Principal A [principal](https://docs.internetcomputer.org/concepts/principals/) is an IC identifier for something that can call canisters. It can represent a user, another canister, or the anonymous caller. In Rabbithole docs, the word usually means your user principal: the identity used to own storage, call canisters, and receive permissions. ## Internet Identity [Internet Identity](https://id.ai) is the Internet Computer's native authentication system. It lets you sign in with passkeys or supported OpenID accounts instead of creating a Rabbithole password. Internet Identity gives each frontend origin a separate principal for the same user. That helps prevent different apps from tracking you through one global account identifier. In Rabbithole, this is the identity layer your browser uses to call canisters, own storage, and request access to encrypted files. For implementation details, see the [Internet Identity guide](https://docs.internetcomputer.org/guides/authentication/internet-identity/). ## Controller A controller has administrative rights over a canister. A controller can upgrade canister code, change settings, or delete the canister. For Rabbithole storage, controller status matters during setup and updates. Rabbithole may temporarily need controller access while it creates or updates your storage canister. After a successful handoff, the intended final state is that you control the canister. ## Cycles [Cycles](https://docs.internetcomputer.org/concepts/cycles/) are the unit used to pay for resources on the Internet Computer: processing, memory, storage, and network bandwidth. Each canister has a cycles account, and its resource usage is charged to that account. In Rabbithole, cycles keep your storage canister running. The setup fee covers canister creation and the initial cycle balance. Later, a storage canister may need more cycles to continue operating. ## How the pieces fit together When you create storage, Rabbithole deploys a storage canister and funds it with cycles. You sign in through Internet Identity, and Rabbithole receives a principal for your session. After setup handoff, that principal is the owner identity Rabbithole uses for your storage canister. Your browser encrypts files before upload. The encryption page explains the key flow in more detail. --- url: /getting-started/introduction.md --- # Rabbithole — encrypted, decentralized file storage you control Rabbithole is file storage for people who want a familiar cloud drive without a central owner that must be trusted with files, access rules, and encryption keys. In a traditional cloud product, your files, backend logic, interface, and access rules live inside the operator's infrastructure. Rabbithole works differently: it creates separate storage for your account on the [Internet Computer](https://internetcomputer.org/), with its own web interface, code, state, and access rules. The Internet Computer matters here because it is not just a blockchain label. It is a network where the application can run as a whole: frontend, backend, state, and user storage do not need to be moved into a traditional cloud account. That lets Rabbithole create more than a row in a company database: it creates a separate storage canister and hands control of it to you. You can think of a [canister](https://docs.internetcomputer.org/concepts/canisters/) as a smart-contract application: it has code, state, and its own resource balance. In Rabbithole, that canister keeps file records, permissions, and, depending on the storage mode, the file bytes themselves. The file is encrypted directly in your browser before upload. Plaintext data is not sent to the storage backend, and keys are not derived from a password or stored by Rabbithole as a master key. The technical pages explain [vetKeys](https://docs.internetcomputer.org/concepts/vetkeys/) and storage modes later; the starting point is simpler: storage control and cryptography are built into the architecture instead of depending only on a service promise. New to Internet Computer terms? Read [Core concepts](/getting-started/concepts.md) first. ## How it works in 30 seconds ```mermaid flowchart LR subgraph YB["Your Browser"] A[Your file] --> B[Split into fragments] B --> C[Encrypt locally] end subgraph BC["Internet Computer"] C --> D[Your personal canister] end style YB fill:#f0f9ff,stroke:#0284c7 style BC fill:#dcfce7,stroke:#16a34a style C fill:#6c63ff,color:#fff style D fill:#22c55e,color:#fff ``` 1. You sign in with [Internet Identity](https://id.ai), without creating a Rabbithole password. 2. Rabbithole creates an independent storage canister for your account. 3. You upload files through the app. 4. Your browser encrypts the file before upload. 5. When you download it, the browser verifies and decrypts the file locally. ## The core idea Most cloud storage products ask you to trust an operator's promise: that it will protect the backend, enforce permissions correctly, keep the service alive, and not expose your files or keys. Rabbithole tries to move more of that trust into architecture. Storage ownership is expressed through canister control. Access rules live with the storage canister. Files are encrypted in your browser, and key derivation is handled by the network instead of a password-derived master key stored by Rabbithole. The result is not magic, and it does not remove every assumption. Your browser, the Internet Computer protocol, and Rabbithole's code still matter. But the center of gravity changes: the product relies less on "trust us" and more on protocol boundaries, canister ownership, and cryptography. ## How vetKeys fit in Imagine a safe with no single master key. For each file, Rabbithole asks the network to derive a file key through [vetKeys](https://docs.internetcomputer.org/concepts/vetkeys/): each vetKD node returns only its own piece, and the full key is assembled in your browser. One node can't open the safe by itself and never sees the full key. Standard and High Replication are Rabbithole's product names for two VetKey levels. The node counts belong to the key service, not to file copies. Read [Keys and vetKeys](/how-it-works/encryption/vetkeys.md) when you want that detail. ## How it compares | Service | E2E Encrypted | Zero-Knowledge | Open Source | Decentralized | You own infrastructure | Key derivation | | -------------- | :-----------: | :------------: | :---------: | :-----------: | :--------------------: | ------------------------------ | | Google Drive | — | — | — | — | — | Company keys | | Dropbox | — | — | — | — | — | Company keys | | Tresorit | Yes | Yes | — | — | — | Password-derived | | ProtonDrive | Yes | Yes | Partial | — | — | Password-derived | | Internxt | Yes | Yes | Yes | — | — | Password-derived | | Filen | Yes | Yes | Partial | — | — | Password-derived | | Storj | Yes | Yes | Yes | Yes | — | Client-side | | **Rabbithole** | **Yes** | **Yes** | **Yes** | **Yes** | **Yes** | **Threshold crypto (vetKeys)** | **How Rabbithole differs:** - **No passwords for key derivation** — your key comes from your [Internet Identity](https://id.ai), computed by the network itself - **Per-user canister** — you own the smart contract where your data lives. After a successful handoff, Rabbithole removes itself as controller - **Reviewable implementation** — the code is [open source](https://github.com/rabbithole-app/v2), encryption runs in your browser, and key derivation is enforced by IC consensus Plaintext is not uploaded to the canister or Blob Storage. Rabbithole still relies on your browser, IC consensus, and correct code. The [Trust Model](/how-it-works/trust-model.md) page lists those assumptions. :::tip\{title="Want to go deeper?"} - [Core concepts](/getting-started/concepts.md) — canisters, principals, controllers, cycles, and vetKeys - [How Encryption Works](/how-it-works/encryption/index.md) — the user-level privacy model - [Keys and vetKeys](/how-it-works/encryption/vetkeys.md) — Standard, High Replication, and key derivation - [Data Sovereignty](/how-it-works/sovereignty/index.md) — canister creation, controller transfer, what if Rabbithole disappears - [Trust Model](/how-it-works/trust-model.md) — threat model, what you do and don't need to trust ::: --- url: /getting-started/quickstart.md --- # Quick Start ## Get started 1. Visit [rabbithole.app](https://rabbithole.app) 2. Click **Login** and authenticate with [Internet Identity](https://id.ai) 3. **Create your storage** — pay a fixed setup fee. Rabbithole deploys your personal canister on the blockchain in about a minute. 4. Start working with your storage: After your storage is ready, you can: - Upload and download files. - Organize files into folders. - Rename, move, and delete items. - Share files or folders with other users. If words like canister, principal, or cycles are new to you, read [Core concepts](/getting-started/concepts.md) before the deeper technical pages. Rabbithole is built around end-to-end encryption. Files are protected before upload. :::tip\{title="Want to know more?"} Read [How Encryption Works](/how-it-works/encryption/index.md) to understand how files are protected, or [Data Sovereignty](/how-it-works/sovereignty/index.md) to learn what you control. ::: --- url: /how-it-works/authentication.md --- # Authentication Authentication in Rabbithole starts with Internet Identity and ends with a principal that can call canisters. Verified attributes, such as email, are a separate layer. They help Rabbithole support collaboration and notifications without turning email into your password or encryption key. ## Sign in without passwords Rabbithole uses **[Internet Identity](https://id.ai)**, the Internet Computer's authentication system. You can sign in with several passwordless methods. - **Passkeys** such as Touch ID, Face ID, Windows Hello, or security keys - **OpenID accounts** such as Google, Apple, or Microsoft when the sign-in flow supports them - **SSO** when organization sign-in is available for your account - **Hardware security keys** such as YubiKey There is no Rabbithole password to remember and no password database for Rabbithole to protect. Your device or identity provider proves who you are to Internet Identity, and Rabbithole receives a cryptographic identity called a **principal**. ```mermaid sequenceDiagram participant U as You participant II as Internet Identity participant R as Rabbithole U->>II: Sign in with passkey or OpenID II-->>U: Delegation for this app U->>R: Call Rabbithole as your principal R-->>U: Your storage, settings, and files ``` ## Separate authentication from attributes Your **principal** is enough to authenticate you. Rabbithole doesn't need an email address to know which account is calling the backend. Some sign-in flows can also share **verified identity attributes**, such as email or name. These attributes are separate from authentication. - Authentication answers: **which principal is calling?** - Attributes answer: **what verified email or name did you choose to share?** Rabbithole uses attributes only when they are available through the Internet Identity flow and tied to the signed-in principal. ## Use email for collaboration Rabbithole is built for sharing private storage, including with people who haven't joined yet. A verified email supports workflows that are difficult to build with principals alone. - **Invite by email**: A storage owner can invite an email address before that person has a Rabbithole account. When the person later signs in with the matching verified email, Rabbithole can connect that invitation to their principal automatically. - **Future notifications**: Email can deliver important storage, sharing, billing, or security notifications when you aren't signed in. - **Less repeated verification**: If your email is already verified through the Internet Identity or OpenID flow, Rabbithole doesn't need a separate email confirmation loop for the same fact. Email is not your password, private key, or encryption key. Your account and file access are still controlled by your Internet Identity principal and the permissions stored in your canister. Read [Shared access](/how-it-works/sharing/index.md) to see how verified email invites become storage-canister permissions. ## Preserve privacy by default Internet Identity is designed so apps don't receive a global user identifier. You get a separate, stable pseudonym for each application frontend origin, which helps prevent cross-app tracking. For Rabbithole, this means: - Other apps can't identify your Rabbithole account from their own Internet Identity login. - Rabbithole doesn't receive your Internet Identity anchor number or passkey secrets. - Biometric data never leaves your device; it only unlocks your local passkey. - Shared attributes are limited to what the sign-in flow provides and what you allow. ## Reuse one account across storage apps Your personal storage canister serves its own frontend. Without extra handling, direct canister URLs and `rabbithole.app` would be separate web origins. Rabbithole solves this with a **broker delegation** flow. You sign in through Rabbithole, and Rabbithole issues a target-scoped delegation to the storage app session. The storage app can call these canisters. - Your storage canister - The Rabbithole backend - The IC management canister, when needed for canister operations This keeps the user experience simple. You don't need a separate account just because you opened your storage directly. ## Why one user can have different principals Internet Identity protects privacy by avoiding one global identifier across all apps. The same Internet Identity anchor receives different principals for different application origins. For Rabbithole, this matters in two scenarios: - Signing in through `rabbithole.app` gives the principal for the main Rabbithole app. - Signing in directly through `.icp0.io` gives a different principal because it is a different application origin. In the normal flow, the storage still sees the main-app principal: the storage app receives a delegation from Rabbithole and uses it to call the storage canister. The user doesn't need to think about the difference. ```mermaid flowchart TD II[One Internet Identity anchor] RH[rabbithole.app] StorageOrigin["Storage URL"] P1[Rabbithole principal] P2[Direct sign-in principal] Delegation[Rabbithole delegation
for the storage app] II --> RH --> P1 II --> StorageOrigin --> P2 P1 --> Delegation ``` The backup direct sign-in principal is used by recovery access. It lets the owner prove ownership through the storage origin when they need a direct path to their canister. ## Trust verified attributes An ordinary form field is only a claim. A verified identity attribute is different: it is signed or certified by the Internet Identity flow and submitted to Rabbithole in a way the backend can verify. Rabbithole verifies the attribute payload before storing it. 1. The payload must be signed by the trusted Internet Identity signer canister. 2. The payload must belong to the same principal that calls Rabbithole. 3. The nonce must be issued by Rabbithole and unused. 4. The origin must match the expected Rabbithole origin. 5. The timestamp must be fresh. Only after those checks does Rabbithole store attributes such as `email`, `name`, `verifiedEmail`, and `authProvider`. *** ## Technical details The technical flow has two moving parts: delegations prove that a session can act as a principal, and identity attributes prove specific profile facts that the user shared through the sign-in flow. :::details\{title="Delegations, principals, and certified attributes"} ### Principal A **principal** is the cryptographic identifier Rabbithole uses as your account ID. It looks like this: ```text o57ld-4as4d-f6pr2-nnmyc-mslbj-67jt3-3huxb-x6jul-f3doo-yxyhi-wqe ``` Your principal is used to: - identify your Rabbithole user record, - check storage permissions, - derive access to encrypted file keys through vetKeys, - and control your personal storage canister where applicable. The principal depends on the application origin. This protects privacy: different apps can't compare one global ID and learn that they are seeing the same person. ### Delegation chain Internet Identity doesn't hand Rabbithole your passkey private key. Instead, it signs a short-lived delegation to a session key. Rabbithole also uses a broker delegation when the storage frontend needs to act as the same user session. ```mermaid sequenceDiagram autonumber participant S as Storage app participant R as Rabbithole app participant II as Internet Identity participant C as Storage canister S->>S: Generate session key pair S->>R: Request delegation with session public key R->>II: Sign in with passkey or OpenID II-->>R: Delegation to Rabbithole session R->>R: Create target-scoped storage delegation R-->>S: Delegation chain S->>C: Call canister as user's principal ``` The target scope limits where the delegated session can be used. ### Identity attribute sync When attributes are available, the browser receives signed attributes from Internet Identity with a one-time nonce. It then performs the finish call using an identity that carries those attributes. The backend checks the signature, nonce, origin, time, and caller, then stores the verified attributes for the principal. Storage invite claiming stays separate and only uses the verified email after sign-in. ```mermaid sequenceDiagram autonumber participant B as Browser participant II as id.ai / Internet Identity participant API as Rabbithole backend B->>API: _internet_identity_sign_in_start() API-->>B: one-time nonce B->>II: Sign in and request email/name attributes with nonce II-->>B: Delegation and signed attributes B->>API: _internet_identity_sign_in_finish() API->>API: Check signature, nonce, origin, time, caller API->>API: Store verified attributes for principal B->>API: claimVerifiedEmailAccess() API->>API: Claim storage invites for verified email ``` The backend rejects stale, unsigned, reused, wrong-origin, or wrong-signer payloads before it stores attributes. ### Further reading Use these resources to learn more about Internet Identity and identity attributes. - [Internet Identity](https://id.ai) - [Internet Identity GitHub repository](https://github.com/dfinity/internet-identity) - [Internet Identity specification](https://docs.internetcomputer.org/reference/internet-identity-spec/) - [Identity Attributes design discussion](https://forum.dfinity.org/t/identity-attributes/64212) - [Shared access in Rabbithole](/how-it-works/sharing/index.md) ::: --- url: /how-it-works/encryption/how-encryption-works.md --- # How encryption works ## What this page covers This page is for readers who want the lower-level model: file derivation inputs, transport keys, chunk encryption, and the boundary between access control and cryptography. For the user-level explanation, start with [Encryption](/how-it-works/encryption/index.md). For the key-service choice, read [Keys and vetKeys](/how-it-works/encryption/vetkeys.md). ## Unique key for each file Each encrypted file has a key ID. In the storage canister, that key ID is made from the key owner principal and the file identifier. The canister builds the vetKD derivation input from those values and uses the `file_storage_dapp` domain separator. The result is deterministic: the same file key ID derives the same key material again. That lets Rabbithole decrypt a file later without storing the raw file key in the canister. ```mermaid flowchart TB subgraph VK["vetKeys - threshold derivation"] MK[Master secret\nsplit across IC nodes] --> D1 MK --> D2 MK --> D3 end D1["derivation ID: file A"] --> K1[Key for file A] D2["derivation ID: file B"] --> K2[Key for file B] D3["derivation ID: file C"] --> K3[Key for file C] K1 --> E1[Encrypted file A] K2 --> E2[Encrypted file B] K3 --> E3[Encrypted file C] style VK fill:#ddd6fe,stroke:#7c3aed style K1 fill:#6c63ff,color:#fff style K2 fill:#6c63ff,color:#fff style K3 fill:#6c63ff,color:#fff style E1 fill:#dcfce7,stroke:#16a34a style E2 fill:#dcfce7,stroke:#16a34a style E3 fill:#dcfce7,stroke:#16a34a ``` One master secret produces different keys for different derivation IDs. A key for one file does not open the rest of your files. ## Key request flow The canister checks access before it asks the Internet Computer to derive a key. A caller without read access is rejected before the vetKD call. ```mermaid sequenceDiagram autonumber participant B as Browser participant S as Storage canister participant P as Permission checks participant V as IC vetKD API B->>B: Generate temporary transport key pair B->>S: getEncryptedVetkey(keyId, transport public key) S->>P: Check subscription and read access P-->>S: Allowed or rejected S->>V: vetkd_derive_key(input, context, key id, transport public key) V-->>S: Encrypted vetKey S-->>B: Encrypted vetKey B->>S: getVetkeyVerificationKey() S-->>B: Verification key B->>B: Decrypt and verify locally B->>B: Encrypt or decrypt file chunks ``` The transport key pair is temporary. The public part goes to the canister. The secret part stays in the browser, so the encrypted vetKey response is useful only to that browser request. ## Chunking and encryption Rabbithole encrypts file chunks in the browser. The implementation uses the Internet Computer vetKeys client library for derived key material and authenticated encryption. | Parameter | Current value | | ------------------------------------- | ------------------------------------------------- | | Canister max chunk size | 2,097,152 bytes | | Default on-chain pre-encryption chunk | 1,900,000 bytes | | Blob Storage chunk | 1,048,576 bytes | | AES-GCM overhead | 28 bytes: 12-byte IV + 16-byte authentication tag | | Blob Storage pre-encryption chunk | 1,048,548 bytes | Large files are split into chunks. Each encrypted chunk carries its own authentication data, so tampering with ciphertext is detected during decryption. ## Blob Storage integrity When Blob Storage is used, encrypted chunks are uploaded outside the canister. The canister stores the file record and the data needed to verify the blob: content hashes, Merkle tree information, and IC-certified metadata. That gives Rabbithole two separate checks: - encryption protects confidentiality; - integrity verification detects silent replacement or corruption. Read [File integrity](/how-it-works/storage/integrity.md) for the storage-side verification model. ## TEE support Trusted Execution Environment support can harden runtime isolation when it is available on the relevant IC subnet. It is not the core privacy assumption for Rabbithole. The main confidentiality boundary is still client-side encryption plus canister-gated vetKey derivation. TEE is an extra layer, not the reason Rabbithole can avoid reading encrypted file contents. ## Limits of the model Encryption narrows the trust surface, but it does not remove every assumption. - The browser must run the intended Rabbithole frontend code. - The Internet Computer protocol and vetKD service must behave correctly. - A user who already downloaded and decrypted a file may keep their copy after access is revoked. - File metadata, such as names, sizes, and folder structure, does not receive the same confidentiality guarantees as file contents. The broader assumptions are listed in the [Trust Model](/how-it-works/trust-model.md). --- url: /how-it-works/encryption/index.md --- # Encryption ## Encryption starts in your browser Rabbithole encrypts file contents in your browser before upload. The storage path then receives encrypted bytes: the canister, Blob Storage, or On-chain Storage does not receive a readable file. That difference matters. Rabbithole can move the file, store metadata, check permissions, and verify integrity, but it does not need the readable file contents to do that work. ```mermaid flowchart LR subgraph Browser["Your browser"] F[Your file] --> SP[Split into chunks] SP --> E1[Chunk 1] SP --> E2[Chunk 2] SP --> E3[Chunk N] VK[vetKeys\nIC threshold nodes] -.->|derive file key| ENC E1 --> ENC[AES-GCM\nencrypt] E2 --> ENC E3 --> ENC end subgraph Storage["Your storage"] ENC --> CH[Encrypted chunks] CH --> META[Access rules\nand verification data] end style Browser fill:#f0f9ff,stroke:#0284c7 style Storage fill:#dcfce7,stroke:#16a34a style VK fill:#ddd6fe,stroke:#7c3aed style ENC fill:#6c63ff,color:#fff style CH fill:#22c55e,color:#fff ``` ## What this means for you Rabbithole handles sealed data instead of readable data. - The Rabbithole team cannot read file contents. - Internet Computer nodes and storage services store encrypted chunks, not the plaintext file. - The storage canister controls who may request the file key. - The key is delivered encrypted for the browser session that requested it. - Storage mode is still separate: Blob Storage and On-chain Storage decide where bytes live, while encryption decides whether those bytes are readable. This is the main idea: Rabbithole is not asking you to trust a promise that the operator will not look. It moves the readable file out of the operator's path. There are still assumptions, especially around your browser, the served frontend, and the Internet Computer protocol. Those assumptions are listed in the [Trust Model](/how-it-works/trust-model.md). ## Where the key comes from Rabbithole does not ask you to create an encryption password. When an encrypted file needs to be opened, your browser asks the storage canister for a file key. The canister checks whether your principal has access, then asks the Internet Computer's [vetKeys](https://docs.internetcomputer.org/concepts/vetkeys/) service to derive that key. The important part: the key does not sit ready-made in the canister, and it is not handed to Rabbithole. The Internet Computer returns an encrypted response that only the browser making the request can open. Read [Keys and vetKeys](/how-it-works/encryption/vetkeys.md) if you want to understand how Standard differs from High Replication. ## Sharing does not re-encrypt the file When you share a file, Rabbithole changes access rules. It does not upload a second encrypted copy for the recipient. If the recipient has access, the canister lets their browser request the same file key. If access is revoked, the canister stops allowing future key requests for the revoked scope. As with any file-sharing system, revocation cannot erase a copy someone already downloaded. ```mermaid sequenceDiagram participant A as User A - owner participant C as Canister participant VK as vetKeys - IC nodes participant B as User B - recipient A->>C: Grants access to User B Note over C: Canister updates access rules B->>C: Requests file C->>C: Checks User B access C->>VK: Requests file-key derivation VK-->>B: Returns key encrypted for B B->>B: Decrypts file in browser ``` Read [Encrypted sharing](/how-it-works/sharing/encryption-in-shared-access.md) for the shared-access flow. ## Learn more ## Encryption topics ### [Keys and vetKeys](/how-it-works/encryption/vetkeys.md) ### [How encryption works](/how-it-works/encryption/how-encryption-works.md) ### [Storage modes](/how-it-works/storage/index.md) ### [Shared access](/how-it-works/sharing/index.md) ### [Trust Model](/how-it-works/trust-model.md) ## Official Internet Computer references ### [vetKeys](https://docs.internetcomputer.org/concepts/vetkeys/) ### [Canister smart contracts](https://docs.internetcomputer.org/concepts/canisters/) --- url: /how-it-works/encryption/vetkeys.md --- # Keys and vetKeys ## Why Rabbithole does not ask for an encryption password Many encrypted storage products derive file keys from a password or a recovery phrase. Rabbithole uses a different model: your browser signs in with [Internet Identity](https://id.ai), and the storage canister asks the Internet Computer to derive file keys with [vetKeys](https://docs.internetcomputer.org/concepts/vetkeys/). The storage canister does not get a raw password from you. It checks whether the caller has access to the file, then requests an encrypted key response for that browser session. ## Analogy: a safe and a locked envelope Imagine a safe with no single master key. Several IC key-service nodes each hold only their share of the ability to produce a file key. Your browser brings a locked envelope. The network puts the derived file key into that envelope, and only your browser has the temporary secret needed to open it. No individual node sees the full key. Rabbithole does not receive the readable file contents. The storage canister's job is to decide whether a principal is allowed to ask for the key in the first place. ## What happens during key derivation The normal flow is short: 1. Your browser asks the storage canister for the key of an encrypted file. 2. The canister checks access rules for your principal and that file. 3. The canister calls the Internet Computer vetKD API with the file's derivation input and your browser's temporary public transport key. 4. The browser receives an encrypted vetKey, verifies it, and turns it into key material for local encryption or decryption. The same file derives the same key material again, so Rabbithole does not need to store a permanent file key in the canister. ## Standard and High Replication When you create encrypted storage, Rabbithole asks which VetKey level to use. This chooses which Internet Computer key service Rabbithole uses for derivation. | Level | Current key-service replication | Approx. derive cost | Good default for | | ------------------ | ------------------------------- | ------------------- | ----------------------------------------------------------------- | | Standard (default) | 13 nodes | About $0.014 | Most encrypted storage | | High Replication | 34 nodes | About $0.035 | Users who want a larger key service and accept higher derive cost | The 13 and 34 numbers describe the current IC threshold key service behind each Rabbithole level. They do not describe the number of file copies, and they do not necessarily describe the subnet where your storage canister runs. If the Internet Computer or Rabbithole configuration changes later, check the current options on the storage creation screen. The docs explain the model; the creation screen shows the exact option you are about to buy. ## How OpenCloud fits in [OpenCloud](https://opencloud.org/) lets builders create Internet Computer cloud engines with selected nodes and providers. Its [pricing guide](https://opencloud.org/pricing) currently shows a 4 x nano-node Hobby engine example. That is a hosting choice, not a replacement for the VetKey level. A storage canister has a hosting subnet. VetKey derivation uses the IC subnet that holds the selected vetKD master key. The management canister routes the derivation request between those layers. For Rabbithole users today, the visible encryption choice remains Standard or High Replication. OpenCloud matters because future deployments could expose hosting control separately from the key-service level used for encryption. ## Cost and cycles Each encrypted upload or download that needs a fresh key derivation consumes cycles. Rabbithole estimates the derivation cost in dollars for readability, but the canister pays the network in cycles. This is separate from storage cost. Storage cost pays for keeping bytes available. Derivation cost pays for asking the network to produce the encrypted file key response. --- url: /how-it-works/payment.md --- # Payment & Cycles Your storage runs in a separate Internet Computer canister. The canister needs [cycles](https://docs.internetcomputer.org/concepts/cycles/) to store data, process operations, and stay available. Think of cycles as prepaid fuel for the canister. Rabbithole can help with top-ups through [Pro](/how-it-works/pro.md), but the canister belongs to you, so you can also fund it directly with Internet Computer tools. ## What you pay for Payment in Rabbithole is not one subscription doing everything. There is the one-time storage setup, the license for a base amount of encrypted data, and the cycles that keep the canister running. | What | When it is paid | What it gives you | | -------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | **Storage creation** | Once | The storage canister, initial cycle balance, storage app installation, and storage license. | | **Rabbithole Pro** | Per subscription period | Shared access, storage updates, encrypted uploads without base license limits, automatic cycle top-ups, and 2 TC of included cycle balance. | | **Cycles** | As they are spent | Canister work: uploads, file operations, storage, vetKey derivation, and storage availability. | ## Storage license and Pro The storage license is the baseline. It is issued when storage is created, and it still applies if Pro expires or is canceled. You can keep using personal encrypted storage within the license limits: included storage and maximum file size. Pro adds features that run through Rabbithole on top of that license. While Pro is active, it adds: - encrypted uploads without the base license limits; - automatic cycle top-ups, where Rabbithole tops up the canister when needed; - storage code and frontend asset updates after your approval; - shared access and access management. The full feature list is on the [What Pro gives you](/how-it-works/pro.md) page. ## How automatic cycle top-ups work Automatic top-ups are operation-driven, not calendar-driven. Before expensive operations, such as a large On-chain Storage upload, the canister checks its balance. If you have active Pro, it can request a top-up from the Rabbithole backend. ```mermaid flowchart TD S["Storage canister
needs cycles"] --> B["Rabbithole backend"] B --> I{"Included
Pro balance left?"} I -->|Yes| P["Use up to 2 TC
per Pro period"] I -->|No| A{"Paid auto-top-up
enabled?"} A -->|Yes| U["Charge your
balance"] A -->|No| M["Manual top-up
required"] P --> CMC["Cycles Minting Canister"] U --> CMC CMC --> S ``` The backend uses two sources in this order: 1. **Included cycle balance**: 2 TC for you during the Pro period. This balance is shared across your storage canisters. The [What Pro gives you](/how-it-works/pro.md) page explains it in more detail. 2. **Paid auto-top-up**: paid funding from your balance, used only after included funding is exhausted and you enable auto-top-up. Without active Pro, the rule is simpler: the upload continues if the canister already has enough cycles. If it does not, you top it up manually. ## Supported tokens The token list can change as payment providers add or remove support for specific networks. Rabbithole shows the available options before you confirm a payment. | Network | Tokens | | ----------------- | -------------------------- | | Internet Computer | ICP, ckETH, ckUSDC, ckUSDT | | Base | ETH, USDC, USDT | | Solana | SOL, USDC, USDT | Your balance is used for Pro period renewal and, if you enable auto-top-up, for paid auto-top-up after included funding is exhausted. ## What cycles pay for Cycles pay for Internet Computer resources and related storage operations. | Resource | What cycles pay for | | -------------------- | ------------------------------------------------------------------------- | | **Compute** | Uploads, downloads, file operations, and access checks | | **Stable Memory** | Metadata, permissions, hashes, and verification records | | **On-chain Storage** | File bytes, if you store them inside the canister | | **Blob Storage** | File-byte storage and transfer through Blob Storage, when this mode is on | | **vetKeys** | Key derivation for opening encrypted files | ## Canister Cycles card The **Canister Cycles** card in the storage sidebar shows the cycle buffer: whether the canister has enough for uploads, normal operations, and the Internet Computer freezing reserve. It is visible only to the owner and recovery owners because this is operational and billing information for the canister. The card separates the cycle balance into practical zones: - **Freeze** is the reserve the canister needs to avoid freezing. - **Safe floor** is the freeze reserve plus the estimated cost of active uploads, key derivation, finalization work, and a margin. - **Target** is the safe floor plus the buffer Rabbithole uses for automatic cycle top-ups. - **Headroom** is the balance above the target that is available for regular work. Use **Top up** when the balance approaches the safe floor or before a large On-chain Storage upload. With active Pro, Rabbithole can top up the canister for you. Without Pro, use manual top-up. :::details\{title="How the card is calculated"} The storage canister refreshes runtime metrics through the Internet Computer Management Canister and returns normalized card metrics to the app. The frontend does not call `canister_status` directly for this sidebar card. The safe floor is an estimate, not a fixed network value: ```text safeFloor = freezingReserve + remainingUploadWriteCost + remainingUploadHashInstructionCycles + activeVetKeyDerivationCost + activeCommitCost + margin ``` Parallel uploads increase active reservations until they finish, are canceled, or their upload sessions expire. The safe floor and target can rise while several large uploads are in progress. ::: ## Self-managed funding You do not need Pro to keep the storage alive. The canister belongs to you, so you can top it up directly. Available options: - **manual top-up** through the [NNS dapp](https://nns.ic0.app), `icp-cli`, or an ICP wallet; - **automated top-up** through third-party services such as [CycleOps](https://cycleops.dev). :::tip\{title="Your canister, your choice"} Rabbithole Pro removes some operational work. The canister itself remains a standard Internet Computer smart contract that you can manage with IC tooling. ::: ## What happens when cycles run out When a canister runs out of cycles, ownership does not change. Availability does: the network can restrict the canister's work. **On-chain Storage.** The canister enters a frozen state when cycles drop below the freezing threshold. Data is preserved, but the canister may stop processing calls until you add cycles. If a canister remains unfunded long enough, the Internet Computer can remove it according to the canister lifecycle rules. **Blob Storage.** If Blob Storage cannot charge for storage, data becomes unavailable on the gateway. In the current configuration, there is a 30-day grace period. After 30 days with zero balance, the gateway removes the data permanently. :::note\{title="Monitor the balance before it gets low"} Active Pro reduces operational work because Rabbithole can top up the canister when needed. If you do not use Pro, set up monitoring or check the balance regularly, especially for On-chain Storage. ::: ## Technical details This section is for readers who want approximate costs and the internal top-up flow. :::details\{title="Cycle costs and top-up flows"} ### Cycle costs Current approximate values: | Resource | Cost | | ----------------------- | ----------------------------- | | Canister creation | \~0.5 TC | | Initial storage balance | 1.5 TC | | Stable Memory | \~127 GiB-seconds per cycle | | Compute (update call) | \~590K cycles per instruction | | Blob Storage (30 days) | \~38.5B cycles per GB | | Blob upload | \~115.4B cycles per GB | | Blob download | \~76.9B cycles per GB | These values are operational estimates for the current product configuration. Internet Computer pricing, Blob Storage pricing, and exchange rates can change. **TC = trillion cycles.** 1 TC = 1 XDR. The USD estimate is a reference value and changes with the XDR/USD rate. ### CMC top-up flow ```mermaid sequenceDiagram participant S as Storage canister participant B as Rabbithole backend participant T as Treasury / balances participant CMC as Cycles Minting Canister S->>B: ensureStorageCyclesForUpload() B->>B: Check owner's Pro status B->>T: Included funding or paid auto-top-up T->>CMC: ICP transfer B->>CMC: notify_top_up(storage canister) CMC-->>S: Cycles added ``` The storage canister does not mint cycles itself. It asks the backend for a top-up, and the backend buys cycles through the Cycles Minting Canister. If the CMC returns an ambiguous status, the operation goes into an administrative recovery queue. This is an operational recovery mechanism, not a normal user action. ### Cashier flow (Blob Storage) ```mermaid sequenceDiagram participant UC as Your canister participant CA as Cashier participant GW as Storage Gateway CA->>UC: _immutableObjectStorageRefillCashier() UC->>CA: Send cycles CA->>CA: Credit storage payment account GW->>CA: Check budget before accepting uploads Note over CA: Tracks usage
per canister ``` Cashier uses a pull model: it initiates cycle collection from your canister when the Blob Storage payment account needs refilling. Those cycles pay for storing and transferring bytes in Blob Storage. The canister must have enough cycles for both its own computation and storage fees. ### Monitoring You can check your canister's cycle balance in several ways: - **In Rabbithole**: the storage sidebar shows the **Canister Cycles** card. - **With `icp-cli`**: for full canister status, use the identity linked to your Internet Identity for `rabbithole.app`. The setup is described in [How to verify ownership](/how-it-works/sovereignty/verify-ownership.md). ```bash icp canister status -n ic --identity rabbithole-app ``` - **Through NNS**: if the canister is added to NNS and managed by the matching identity. ::: --- url: /how-it-works/pro.md --- # What Pro gives you Rabbithole Pro adds features to storage you already created: shared access, storage updates, automatic cycle top-ups, and encrypted uploads without the base license limits. These features run through Rabbithole, but they do not change ownership: the storage remains your Internet Computer canister. :::tip\{title="Short version"} The [storage license](/how-it-works/payment.md#storage-license-and-pro) gives you base personal encrypted storage. Pro adds the parts Rabbithole operates for you: shared access, updates, automatic cycle top-ups, and 2 TC of included cycle balance per subscription period. ::: ## What Pro includes These features are available while Pro is active. | Feature | What changes | | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Shared access** | You can share storages, folders, and files, manage permissions, handle access requests, and [invite by email](/how-it-works/sharing/email-invites.md) people who have not used Rabbithole yet. | | **[Storage updates](/how-it-works/sovereignty/updates.md)** | After you approve the update, Rabbithole can install a new storage code version or storage web interface. | | **Encrypted uploads without base limits** | Pro removes the base license limits for encrypted upload size and total encrypted storage. | | **[Automatic cycle top-ups](/how-it-works/payment.md#how-automatic-cycle-top-ups-work)** | If a storage needs cycles before an operation or when its balance drops, Rabbithole can top up the canister automatically. | | **2 TC included cycle balance** | Each Pro period includes up to 2 TC for automatic top-ups across your storage canisters. This limit is shared across your storages. | ## How automatic top-ups and 2 TC work together Internet Computer canisters need [cycles](/getting-started/concepts.md#cycles) to pay for compute, memory, storage, and network operations. Pro enables automatic cycle top-ups for your storages and includes up to **2 TC** per subscription period. 2 TC is not a separate canister and it is not tokens in your wallet. It is the limit Rabbithole can spend on top-ups for your storage canisters during the current Pro period. If you have several storages, the shared limit is spent on the canisters that need cycles. Automatic top-up usually runs before an expensive operation, for example before a large [On-chain Storage](/how-it-works/storage/on-chain-storage.md) upload, or when a canister approaches its safe cycle floor. 2 TC means 2 trillion cycles. On the Internet Computer, **1 TC = 1 XDR**. Any USD estimate is only a reference value and changes with the XDR/USD rate. If the included limit is already used up, Rabbithole can continue with paid automatic top-ups from your balance. This only happens when you enable that setting. ## What Pro does not change Pro adds service features, but it does not make Rabbithole the storage owner. - The storage remains an independent Internet Computer canister. - You keep control of the canister. - For an update, Rabbithole gets only the temporary access window you approve. - Pro does not give Rabbithole a bypass path to files or encryption keys. - Access rules and vetKey issuance are still checked inside the storage canister. - You can top up the canister manually through IC tools even when Pro is not active. ## When Pro is not active Without active Pro, you can still use the storage within the base license: personal encrypted storage within the issued limits. Until Pro is renewed, features that require Rabbithole are not available: shared access, access management, updates through Rabbithole, encrypted uploads without the base license limits, and automatic cycle top-ups. If the canister needs cycles, you top it up manually. ## Related pages - [Payment & Cycles](/how-it-works/payment.md) - [Shared access](/how-it-works/sharing/index.md) - [Storage updates](/how-it-works/sovereignty/updates.md) - [Storage](/how-it-works/storage/index.md) --- url: /how-it-works/sharing/email-invites.md --- # Email invites Email invites let you share access with a person before you know their Internet Computer principal. You enter an email address, choose a permission, and Rabbithole keeps the invite waiting until the right person signs in. The email itself is not a password and not an encryption key. It is a verified [Identity Attribute](/how-it-works/authentication.md#trust-verified-attributes) that helps Rabbithole connect an invite to the right principal. ## When to use an email invite Use an email invite when you know who must receive access, but that person hasn't joined Rabbithole yet. - Invite a colleague before they create an account. - Share a folder with a future participant of a project. - Prepare emergency access that is released after long owner inactivity. - Let future notifications use the same verified email. This is different from sharing with a principal. A principal works when the recipient already has an account. Email works when you only know the person by their address. :::note Which emails are verified today Internet Identity supports passkey sign-in, OpenID providers such as Google, Microsoft, and Apple, and SSO where it is available. For Rabbithole, a verified email is an attribute that comes from a supported Internet Identity flow and passes backend verification in Rabbithole. Typing any email address and verifying it through a Rabbithole confirmation email is not implemented yet. That can become a separate profile setting later, but the current invite flow relies on email from a supported sign-in provider. ::: ## What the recipient experiences The recipient doesn't need a special link to claim the invite. They sign in to Rabbithole with Internet Identity and share the matching verified email from a supported sign-in provider. ```mermaid sequenceDiagram autonumber participant Owner participant App as Rabbithole participant Recipient Owner->>App: Invites person@company.com Recipient->>App: Signs in through a provider with the same verified email App->>App: Verifies Identity Attributes App->>App: Connects the invite to the recipient account App-->>Recipient: Shows the shared storage ``` Rabbithole can do this because it verifies the email through the identity flow. It doesn't trust a profile field that anyone can type. ## Why Rabbithole can trust the email A verified email is different from text typed into a form. Rabbithole accepts it only after the backend verifies the identity payload. The backend checks these facts before using the email: 1. The payload comes from the trusted Internet Identity signer. 2. The signed-in principal is the same principal that owns the attributes. 3. The nonce was issued by Rabbithole and has not been used before. 4. The origin matches Rabbithole. 5. The timestamp is fresh. 6. The email is marked as verified. After those checks, Rabbithole can use the email to connect pending invites, support future notifications, and reduce repeated verification steps. :::details Technical view: email commitments and pending grants Rabbithole doesn't need to store a global plain email identifier for access matching. The frontend and canister calculate an email commitment from: - a Rabbithole storage-access domain separator, - the storage canister ID, - and the normalized email address. Because the storage canister ID is part of the commitment, the same email doesn't become one reusable global access identifier across all storages. ```mermaid sequenceDiagram autonumber participant O as Owner participant UI as Share dialog participant S as Storage canister participant API as Rabbithole backend participant R as Recipient O->>UI: Enter email and permission UI->>UI: Build storage-scoped email commitment UI->>S: createAccessBatch(email target) S->>S: Store pending email grant S-->>API: Storage access event API->>API: Index pending email grant R->>API: _internet_identity_sign_in_finish() API->>API: Store verified email and match commitment R->>API: claimVerifiedEmailAccess() API->>S: claimPendingAccessByBackendAttestation() S->>S: Create principal access grant ``` The storage canister accepts backend attestation only from the trusted Rabbithole backend configured for that storage. A direct storage app session can also claim matching email grants after it receives verified attributes from the identity flow. ::: ## Related pages Use these pages to understand the surrounding model. - [Authentication and identity attributes](/how-it-works/authentication.md#trust-verified-attributes) - [Permission model](/how-it-works/sharing/permissions.md) - [Encrypted sharing](/how-it-works/sharing/encryption-in-shared-access.md) --- url: /how-it-works/sharing/encryption-in-shared-access.md --- # Encrypted sharing Sharing an encrypted file doesn't mean Rabbithole creates a new encrypted copy for every recipient. Instead, the storage canister checks whether the recipient has access. If they do, the Internet Computer derives the file key for that session. This keeps sharing fast and keeps the owner out of the recipient's read path. The owner doesn't need to be online when the recipient opens a shared file. ## What changes when you share Think of an encrypted file as having two parts: - the encrypted file bytes, - and a rule that says who can receive the key needed to decrypt them. When you share the file, Rabbithole changes the rule. It doesn't upload the file again, and it doesn't send the recipient a key from the owner. ```mermaid flowchart LR File[Encrypted file] Rule[Access rule] Recipient[Recipient] Key[File key for this session] File --> Recipient Rule --> Key Key --> Recipient ``` The storage canister checks the rule before the recipient gets the key material needed to decrypt the file. ## How the recipient gets the key The raw key is not handed to the canister. The browser creates a temporary transport key pair and sends only the public part to the canister. The derived file key comes back encrypted for that browser session. Only the browser holding the matching temporary secret can decrypt and use it. ```mermaid sequenceDiagram autonumber participant B as Recipient browser participant S as Storage canister participant FS as Permission store participant V as IC vetKD API B->>B: Generate transport key pair B->>S: getEncryptedVetkey(keyId, transport public key) S->>FS: Check Read access for principal FS-->>S: Access allowed or rejected S->>S: Build derivation input from key owner and key name S->>V: vetkd_derive_key(input, context, transport public key) V-->>S: Encrypted vetKey S-->>B: Encrypted vetKey B->>B: Decrypt and verify locally B->>B: Decrypt file chunks ``` If the user does not have `Read` access for the key ID, the canister rejects the request before key derivation. ## What this means for permissions Sharing changes permissions, not file contents. - The encrypted file bytes stay where they are. - The storage canister records who can read or edit the file. - A recipient with **View** access can request the key for that file. - A revoked recipient can no longer request new keys for the revoked scope. Email invites work for encrypted files in the same way. The invite can wait until the person signs in, and then the canister grants that person's principal the right to request the needed key. The full operation-to-permission table lives in the [Permission model](/how-it-works/sharing/permissions.md). :::note What changes without active Pro Storage license keeps the owner's personal encrypted storage available, but invited users can request keys only while the owner has active Pro. Durable access and recovery access are separate sovereign scenarios described in the permission model. ::: ## Revocation limits Revoking access stops future key requests and future file operations. It can't remove a file copy or key material that the recipient already downloaded before revocation. This is the same practical limit as any file-sharing system: revocation controls future access, not already-exported data. ## Related pages Read these pages for the larger model. - [How encryption works](/how-it-works/encryption/index.md) - [Keys and vetKeys](/how-it-works/encryption/vetkeys.md) - [Permission model](/how-it-works/sharing/permissions.md) - [Storage modes](/how-it-works/storage/index.md) --- url: /how-it-works/sharing/index.md --- # Shared access Shared access opens a storage, folder, or file to another person. The storage stays yours, and the person you invite gets only the access you choose. You can share with an existing Rabbithole user profile or with an email address. Email invites let you grant access before the recipient creates a Rabbithole account. Shared access is part of [Pro](/how-it-works/pro.md). A storage license keeps the owner's personal encrypted storage available, but it does not replace active Pro for invites, access management, or invited users. ## What this means in practice Most flows come down to three choices: what to share, which access to grant, and who receives it. Rabbithole then shows that access where the recipient expects to find it. - Share a whole storage, a folder, or a single file. - Give **View**, **Edit**, or **Manage** access. - Invite a person by email before they know Rabbithole. - Let a person request access when they open a storage without permission. - See incoming storages in **Shared with me**. If a recipient with **Edit** access uploads a file, they use the owner's storage canister. The owner controls both visibility and storage resource usage. :::tip Why email invites matter You can share access with a future user. When that person later signs in with the same verified email from [Identity Attributes](/how-it-works/authentication.md#trust-verified-attributes), Rabbithole connects the invite to their account automatically. ::: ## How Rabbithole keeps sharing safe Rabbithole does not treat sharing as a note in a central database. The storage itself checks access. In Internet Computer terms, each storage is a canister: an independent smart contract with access rules, file structure, and frontend assets. When someone opens a shared file, the storage canister checks that person's principal before it returns file data or an encryption key. A principal is the cryptographic account ID that Internet Identity gives to the app. ```mermaid sequenceDiagram autonumber participant Owner participant App as Rabbithole app participant Storage as Storage canister participant Recipient Owner->>App: Share a folder or file App->>Storage: Save the access rule Recipient->>Storage: Open shared content Storage->>Storage: Check recipient principal and permission Storage-->>Recipient: Return only allowed content ``` :::details Technical view: canisters, events, and the Shared with me list The storage canister makes the access decision. Rabbithole backend keeps a synchronized index so users can discover storages shared with them in the main app. ```mermaid sequenceDiagram autonumber participant O as Owner participant UI as Rabbithole or storage app participant S as Storage canister participant API as Rabbithole backend participant R as Recipient O->>UI: Share storage, folder, or file UI->>S: createAccessBatch() S->>S: Store principal grant or pending email grant S-->>API: onStorageAccessChanged() API->>API: Update Shared with me index R->>API: listSharedWithMeStorageViews() API-->>R: Active or pending shared storages R->>S: Open storage as delegated principal S->>S: Check permission before each protected operation ``` If the backend index is unavailable, the storage canister still owns the permission decision. The index improves discovery and notifications; it doesn't replace canister checks. ::: ## Terms used in this section These terms appear on the deeper pages. - **Canister**: an Internet Computer smart contract. A Rabbithole storage is a canister. - **Principal**: the cryptographic account ID used for permission checks. - **Verified email**: an [Identity Attribute](/how-it-works/authentication.md#trust-verified-attributes) proved by the sign-in flow, not a free-form text field. - **Grant**: an access rule stored by the storage canister. - **Active Pro**: the state required for shared access and access management. - **vetKey**: a cryptographic key derived on demand after the canister checks access. ## Learn more ## Shared access topics ### [Invite people by email](/how-it-works/sharing/email-invites.md) ### [Permission model](/how-it-works/sharing/permissions.md) ### [Encrypted sharing](/how-it-works/sharing/encryption-in-shared-access.md) ### [Authentication and identity attributes](/how-it-works/authentication.md#trust-verified-attributes) ### [What Pro gives you](/how-it-works/pro.md) --- url: /how-it-works/sharing/permissions.md --- # Permission model Permissions answer a simple question: what can this person do with this storage, folder, or file? Rabbithole keeps that decision close to the data. The storage canister checks permissions before it lists files, changes content, changes sharing, or returns an encryption key. ## Permission levels Rabbithole shows three permission levels in the interface. | Permission | What the recipient can do | | ---------- | ------------------------------------------------------------ | | **View** | Open folders and files that are shared with them. | | **Edit** | View content and change it: upload, rename, move, or delete. | | **Manage** | Edit content and manage access for the shared scope. | Choose **View** for a reader, **Edit** for a collaborator, and **Manage** for someone who can also invite or remove other people. ## Operations and required permissions The same permission model controls file operations, shared access, and key requests for encrypted files. The name after `/` is the canister permission. | Operation | Required permission | | ------------------------------------- | ------------------------------ | | Open a folder or download a file | **View** / `Read` | | Request the key for an encrypted file | **View** / `Read` | | Upload, rename, move, or delete | **Edit** / `ReadWrite` | | Manage shared access | **Manage** / `ReadWriteManage` | Blob Storage changes where file bytes live. It does not bypass permission checks in the storage canister. :::note Shared access and Pro Shared access and access management require the storage owner to have active Pro. Storage license keeps the owner's personal encrypted storage available, but it does not keep shared access active after Pro expires. ::: ## What a scope means A scope is the thing you shared. It can be the whole storage, one folder, or one file. | Where the permission is granted | What it covers | | ------------------------------- | ------------------------------------ | | **Storage** | The whole storage. | | **Folder** | That folder and the files inside it. | | **File** | Only that file. | ```mermaid flowchart LR Storage[Storage] Folder[Shared folder] File[File inside the folder] Storage --> Folder Folder --> File StorageRule[Storage permission
covers the whole chain] FolderRule[Folder permission
covers folder and file] FileRule[File permission
covers only the file] StorageRule -.-> Storage FolderRule -.-> Folder FileRule -.-> File ``` If a person has access to a folder, they can access files inside that folder at the same permission level unless a stronger rule applies elsewhere. :::details Technical view: key IDs and effective permissions Internally, the canister resolves folder and file entries to stable key IDs. Permission checks use those key IDs and walk up the parent chain to find the strongest effective permission. A folder grant can therefore apply to a file inside the folder, and a root grant can apply to the whole storage. ::: ## Invites and active access Rabbithole distinguishes between access that is already active and access that is waiting for the recipient. - **Active access** means the storage canister knows the recipient's principal. - **Pending access** means Rabbithole is waiting for the recipient to claim the invite, usually through a verified email. When an email invite is claimed, pending access becomes active access for the recipient's principal. :::details Technical view: grants The canister stores active access as a principal grant and waiting access as a pending grant. A pending email grant can later create a principal grant after the verified email matches. Managers can still see the invite history, including whether the email invite was claimed through Rabbithole or through the direct storage app. ::: ## Special access classes Most sharing uses standard access. Rabbithole also has rarer access classes for recovery and predefined policies. | User-facing type | Technical class | What it is for | | -------------------------------------------------------------------- | ----------------- | ------------------------------------------------------------------------------------ | | **Standard access** | `ordinary` | Normal sharing and approved access requests. | | **Durable access** | `durable` | Access described in advance by a policy and activated when the owner stays inactive. | | **Recovery access** | `ownerEquivalent` | A backup owner principal with owner-level powers. | Standard access depends on the owner's Pro status. Durable access and recovery access cover sovereign scenarios: they can preserve access to permitted data even when the owner's Pro is not active. :::details Durable access Durable access is for emergency workflows. The owner defines in advance who receives access, which scope they receive, and which permission they receive if the owner is inactive for a configured period. While the owner keeps using the storage, the canister records owner activity and resets the timer. If the owner stays inactive long enough, the policy is released and creates normal access grants for the selected recipients. ```mermaid sequenceDiagram autonumber participant Owner participant Storage as Storage canister participant Recipient Owner->>Storage: Create emergency-access policy Owner->>Storage: Use the storage Storage->>Storage: Reset owner-activity timer Note over Storage: If owner stays inactive long enough Storage->>Storage: Release policy Storage-->>Recipient: Grant predefined access ``` ::: :::details Recovery access Recovery access covers the most conservative scenario: the owner must still be able to open the storage directly even if the main Rabbithole interface is unavailable. In the normal flow, you sign in through `rabbithole.app`, and the storage app receives a delegation from Rabbithole. The storage then sees the same principal that the main app uses. If the owner signs in directly through the storage URL, such as `.icp0.io`, Internet Identity treats that URL as a different application. For privacy, Internet Identity derives a separate principal for each application origin. Recovery access stores that storage-origin principal as a backup owner principal. Read more on the [Authentication](/how-it-works/authentication.md#why-one-user-can-have-different-principals) page. ::: ## Access requests If a signed-in user opens a storage without permission, Rabbithole can show a request access action. The owner or a manager can approve or reject that request. ```mermaid sequenceDiagram autonumber participant User participant Storage as Storage canister participant Manager User->>Storage: Request access Manager->>Storage: Review pending request alt Approved Manager->>Storage: Choose scope and permission Storage-->>User: Access becomes active else Rejected Storage-->>User: Request is closed end ``` When a request is approved, the manager chooses what to share and which permission to grant. ## What revocation can and can't do Revoking access stops future access checks. The recipient can't continue to list, edit, manage, or derive keys for the revoked scope. Revocation can't erase data the recipient already downloaded. This is the normal limit of file sharing: you can stop future access, but you can't pull back a copy that already left the system. ## Related pages These pages cover the systems that permissions depend on. - [Shared access overview](/how-it-works/sharing/index.md) - [Email invites](/how-it-works/sharing/email-invites.md) - [Encrypted sharing](/how-it-works/sharing/encryption-in-shared-access.md) --- url: /how-it-works/sovereignty/index.md --- # Data sovereignty in Rabbithole In Rabbithole, storage ownership is tied to a canister rather than only to an account record. When you create storage, Rabbithole deploys a personal Internet Computer canister for you with storage code, data, and its own web interface. After the handoff completes, Rabbithole removes itself from the controllers. The storage remains part of the Internet Computer, but control moves to you. :::tip Short version Rabbithole helps create the storage and remains a service around it. The storage itself belongs to you: you can open it directly, fund it with cycles, and decide whether to accept future updates. ::: ## What you control After the initial handoff, your Internet Identity principal becomes the controller of the storage canister. That gives you direct control over the infrastructure that stores file records, access rules, frontend assets, and, in On-chain Storage, the file bytes themselves. You control these parts of your storage: - **Canister settings**: your principal manages controllers and upgrades. - **Direct access**: your canister serves its own frontend at `https://.icp0.io`. - **Cycle funding**: you can keep the storage running through automatic cycle top-ups in Rabbithole Pro or direct Internet Computer tooling. - **Updates**: you choose whether Rabbithole gets temporary access to install a new version. - **Deletion**: you can delete the canister and its data when you no longer need the storage. ## What Rabbithole still does Sovereignty does not mean Rabbithole disappears from the user experience. It means Rabbithole can still help with infrastructure that you control. Rabbithole can still provide: - the main app interface at `rabbithole.app`; - storage creation and initial setup; - storage code and frontend asset updates when you have active Pro and approve temporary access; - automatic cycle top-ups when the canister needs cycles before expensive operations; - Blob Storage coordination when you choose the lower-cost storage mode. ## How storage is created Rabbithole uses temporary access only to create and initialize your storage. The handoff happens before the storage becomes your independent canister. ```mermaid flowchart TB subgraph S1["Step 1: Payment"] U1[You] -->|fixed price| PAY[Rabbithole] end subgraph S2["Step 2: Deployment"] direction TB PAY -->|create canister| CAN[New canister] CAN -->|controllers: You + Rabbithole| W[Install WASM module] W --> FE[Install frontend assets] end subgraph S3["Step 3: Handoff"] FE --> RV[Revoke asset write permission] RV --> RM[Remove Rabbithole as controller] RM ==> OWN[You are the sole controller] end subgraph S4["Result: Your storage"] OWN --> A1[rabbithole.app] OWN --> A2["https://<canister-id>.icp0.io"] end style S1 fill:#e0f2fe,stroke:#0284c7 style S2 fill:#fef3c7,stroke:#d97706 style S3 fill:#dcfce7,stroke:#16a34a style S4 fill:#f0fdf4,stroke:#16a34a style OWN fill:#22c55e,color:#fff style RM fill:#fb923c,color:#000 style RV fill:#fed7aa,stroke:#d97706 style A1 fill:#a5d8ff,stroke:#0284c7 style A2 fill:#a5d8ff,stroke:#0284c7 ``` The creation flow has three phases: 1. **You pay for deployment**. The setup payment covers canister creation, the initial cycle balance, deployment operations, and related infrastructure costs. 2. **Rabbithole installs the storage**. The canister receives the storage code and frontend assets it will serve. 3. **Rabbithole completes the handoff**. The service revokes its asset write permission and removes itself from the canister controllers. After that handoff, Rabbithole no longer has permanent administrative access to your canister. The intended final state is your principal as the only controller. ## What happens if Rabbithole is unavailable Rabbithole is one interface to your storage, not the owner of the canister. If `rabbithole.app` is unavailable, the canister can still serve its own frontend while it has enough cycles. ```mermaid flowchart LR subgraph NORMAL["Normal operation"] direction LR U1[You] -->|rabbithole.app| C1[Your canister] U1 -->|direct URL| C1 end subgraph GONE["Rabbithole is unavailable"] direction LR U2[You] -.->|rabbithole.app| X[Unavailable] U2 ==>|"direct: canister-id.icp0.io"| C2[Your canister] end style NORMAL fill:#dcfce7,stroke:#16a34a style GONE fill:#fef3c7,stroke:#d97706 style X fill:#fca5a5,stroke:#ef4444 style C1 fill:#22c55e,color:#fff style C2 fill:#22c55e,color:#fff ``` What remains available depends on your storage mode: - **On-chain Storage**: file bytes stay inside your canister while it remains funded. - **Blob Storage**: your canister keeps the trusted file record and verification data, while file-byte availability depends on the Blob Storage retention lifecycle. ## Model boundaries Data sovereignty removes Rabbithole as a permanent controller, but it does not remove every operational dependency. These limits are worth understanding up front. - **Cycles are still required**. An unfunded canister can freeze and may later be removed by the Internet Computer network. - **Blob Storage has a separate availability model**. The canister keeps the file record, but file bytes depend on Blob Storage funding and retention. - **Encryption is a separate topic**. Sovereignty controls ownership and administration; encryption controls file confidentiality. - **Lost identity is still a risk**. If you lose access to the Internet Identity that controls the canister, Rabbithole cannot recover control for you. ## Continue reading These pages explain the sovereignty model and related product areas in more detail. - [How to verify ownership](/how-it-works/sovereignty/verify-ownership.md) - [Storage updates](/how-it-works/sovereignty/updates.md) - [Authentication](/how-it-works/authentication.md) - [Storage](/how-it-works/storage/index.md) - [Payment & Cycles](/how-it-works/payment.md) --- url: /how-it-works/sovereignty/updates.md --- # Storage updates After the handoff, Rabbithole cannot update your canister on its own. That is intentional: to install a new version, the service needs a temporary access window that you approve. This model lets Rabbithole deliver fixes and new features without remaining a permanent administrator of your storage. Update delivery is a Rabbithole Pro service feature. Pro does not change the control model: an update still requires your approval and temporary access to the canister. ## Why temporary controller access is required A canister update changes the code that serves the storage. On the Internet Computer, only a canister controller can perform that operation. That means Rabbithole cannot silently update your storage after control has been handed to you. When you approve an update, a task-limited process runs: 1. You add Rabbithole as a temporary controller. 2. Rabbithole installs the new WASM module or frontend assets. 3. Rabbithole removes itself from the controllers. 4. The storage is back under your control. ```mermaid sequenceDiagram participant U as You participant R as Rabbithole participant C as Your canister R-->>U: New version available U->>C: Add Rabbithole as temporary controller U->>R: Approve update R->>C: Install new WASM or frontend assets R->>C: Remove itself as controller Note over C: You are the sole controller again ``` ## What happens to data A normal update changes canister code but should not erase data. File records, access rules, and stored data live in Stable Memory, which survives canister upgrades. Before an update, you can create a snapshot from the Rabbithole interface. A snapshot captures the current Stable Memory and WASM module. If the update fails or behaves incorrectly, you can restore the canister to the snapshot. ## What Rabbithole does at the protocol level During the initial handoff and later updates, Rabbithole works with two different kinds of access: - **Frontend asset permissions**. Rabbithole can install or update the web interface files served by your canister. After handoff, the service revokes its asset write permission. - **Canister controller rights**. Rabbithole receives them only for the operation, installs the intended version, and removes itself from the controllers. The initial handoff ends with an `IC.update_settings` call using the final controller list. After Rabbithole is removed, the service has no admin override: controller rules are enforced by the Internet Computer management canister. ## What to check after an update After the update completes, check the **Controllers** table on the canister page inside Rabbithole. The list should contain only the principals you expect. If you want to verify this directly with Internet Computer tooling, use the [How to verify ownership](/how-it-works/sovereignty/verify-ownership.md) guide. ## Continue reading - [Data sovereignty](/how-it-works/sovereignty/index.md) - [How to verify ownership](/how-it-works/sovereignty/verify-ownership.md) - [Payment & Cycles](/how-it-works/payment.md) --- url: /how-it-works/sovereignty/verify-ownership.md --- # How to verify ownership Ownership verification answers a simple question: who can manage your storage canister right now? For most users, the Rabbithole interface is enough. `icp-cli` is useful if you want to verify the same fact directly with Internet Computer tooling. In both cases, compare the controllers with the principal you use to sign in to Rabbithole through Internet Identity. ## Check in Rabbithole Open the canister settings page inside the Rabbithole app: ```text /dashboard//canister ``` The **Controllers** table should contain only the principals you expect. The current user's row is shown in bold. After the handoff is complete, Rabbithole must not remain listed there. If you just created storage or approved an update, wait for the operation to finish: during setup or update, temporary controller access can be part of the normal process. ## Why the plain CLI principal can be different Internet Identity protects privacy by deriving a principal for each application web address. That means the principal for `rabbithole.app` can differ from your regular local `icp-cli` identity. Because of that, these two commands can be misleading on their own: ```bash icp identity principal icp canister settings show -n ic ``` They may use a local CLI identity rather than the Internet Identity principal you use in Rabbithole. For an accurate check, link a local identity to Internet Identity through Rabbithole's login host. ## Check with icp-cli First, check that your `icp-cli` version supports Internet Identity linking: ```bash icp identity link ii --help ``` If the command is unavailable, update `icp-cli` to a version that supports `icp identity link ii`. Then create a local identity linked to your Internet Identity for Rabbithole. In `icp-cli` 0.2.7, the app address is passed with `--host`: ```bash icp identity link ii --host https://rabbithole.app rabbithole-app ``` The command opens the Internet Identity sign-in flow and stores a delegation for Rabbithole. You can then print the principal for that identity: ```bash icp identity principal --identity rabbithole-app ``` Now verify the canister settings as that identity: ```bash icp canister settings show -n ic --identity rabbithole-app ``` Check the `controllers` field in the output: - your principal must be listed as a controller; - Rabbithole must not remain listed after the handoff is complete. When the delegation expires, refresh the sign-in: ```bash icp identity login rabbithole-app ``` ## Verify the code Controller verification shows who manages the canister. If you also want to verify the installed code, compare the module hash with the published release. The Internet Computer documentation explains the general process in its guide to [reproducible builds](https://docs.internetcomputer.org/building-apps/best-practices/reproducible-builds). ## Continue reading - [Data sovereignty](/how-it-works/sovereignty/index.md) - [Storage updates](/how-it-works/sovereignty/updates.md) - [Authentication](/how-it-works/authentication.md) --- url: /how-it-works/storage/blob-storage.md --- # How Blob Storage works ## What Blob Storage is Blob Storage is the recommended mode for most encrypted files. The bytes live outside your canister, while the canister keeps the file record, access rules, and the data your browser uses to detect replacement. The storage layer sees only ciphertext. Blob Storage handles byte storage and delivery, while browser-side encryption protects file confidentiality before upload. :::tip Trade-off You pay less and handle large files more comfortably. In exchange, long-term byte availability depends on the Blob Storage lifecycle. ::: :::note Important distinction The external storage layer keeps the **file itself**. Your personal canister keeps the **trusted file record, access rules, and verification data**. ::: ## Where the file lives ![Blob Storage architecture](/diagrams/fossflow-diagram-2.png) The Blob Storage path looks like this: - your browser prepares and uploads the file; - your personal canister keeps the trusted record and access state; - **Blob Gateway** accepts uploads and returns files during download; - **Cashier** and **Cleanup service** handle billing and cleanup or retention events. ## How upload works ### Prepare chunks in the browser The browser splits the file into chunks and encrypts each chunk locally. Encrypted chunks are written to a temporary browser spool so the full encrypted file does not have to stay in memory. ### Upload chunks to Blob gateway The browser reads encrypted chunks from the spool and sends them to Blob gateway. The gateway stores the data in S3-compatible object storage. ### Write the result into the canister After successful upload, Rabbithole writes the result into the canister. The canister stores the trusted file record: size, hashes, metadata, and access state. ## How download works ```mermaid flowchart LR C[Your personal canister] -->|certified file info| B[Your browser] G[Blob gateway] -->|encrypted file| B B -->|verify first| V[Integrity check] V --> D[Decrypt locally] ``` The browser does two things before opening the file: 1. It gets the expected file fingerprint from your canister. 2. It checks that the file downloaded from Blob Storage matches that fingerprint. Only after that does decryption happen, if encryption was enabled for that file. ## How billing and cleanup fit in File bytes in Blob Storage have their own lifecycle. The canister remains the trusted system of record, but byte availability depends on Blob Storage funding and retention rules. - **Blob Gateway** accepts uploads and returns files during download. - **Cashier** keeps storage funded. - **Cleanup service** synchronizes deletion and retention events with your canister. ## Why this model is cheaper Blob Storage is cheaper because the file itself does not have to live inside canister memory. Your canister stores a much smaller amount of information: file records, access state, and verification data. ## What this mode trusts Trust is split across several parts: - The Internet Computer keeps your canister state. - The canister certifies trusted file metadata. - The browser verifies downloaded bytes before opening them. - Blob Storage is responsible for byte availability and retention. Blob Storage and On-chain Storage use the same end-to-end encryption, but their availability models differ. ## Continue reading ## Related pages ### [How Rabbithole verifies your files](/how-it-works/storage/integrity.md) ### [How On-chain Storage works](/how-it-works/storage/on-chain-storage.md) ### [Payment & Cycles](/how-it-works/payment.md) ## Official references ### [Canister smart contracts](https://docs.internetcomputer.org/building-apps/essentials/canisters) ### [Asset certification](https://learn.internetcomputer.org/hc/en-us/articles/34276431179412-Asset-Certification) ### [Certified data](https://docs.internetcomputer.org/tutorials/developer-liftoff/level-3/3.3-certified-data) --- url: /how-it-works/storage/index.md --- # Storage ## Storage mode, license, and Pro are separate Rabbithole uses several related concepts in the storage flow. They control different parts of the product: - **Storage mode** decides where file bytes live. - **Storage license** defines the base encrypted storage limits. - **Pro** adds extra features for storage you already created. Storage mode does not replace encryption or access control. File contents are encrypted in the browser before upload, and in both modes the storage canister keeps ownership, access rules, and trusted file records. The full subscription feature list is on the [What Pro gives you](/how-it-works/pro.md) page. :::tip Short version For ordinary files, **Blob Storage** is usually the better fit: it is cheaper and handles large files more comfortably. Choose **On-chain Storage** when you want to avoid the external storage layer and cost or file size is not the main constraint. ::: ## Two storage modes ### Blob Storage Recommended Blob Storage keeps file bytes in external object storage, while your canister keeps the file record, access rules, and verification data. The external layer sees only encrypted bytes. - About **$0.05 per GB per month**. - Best for larger files and lower cost. - The file is stored in external object storage. - Your personal canister keeps access rules and file verification data. ### On-chain Storage Advanced mode On-chain Storage keeps the file directly inside your personal canister. There are fewer components to trust, but the cost is higher and the cycle balance matters more. - About **$1.04 per GB per month**. - Best for small, high-value files. - The file is stored directly in your personal canister. - There is no dependency on an external storage layer. ## Comparison | | Blob Storage | On-chain Storage | | ---------------------------- | -------------------------------------------- | ------------------------------------- | | **Best for** | Everyday storage | Special scenarios and maximum control | | **Estimated cost** | About **$0.05/GB/month** | About **$1.04/GB/month** | | **Where the file lives** | External object storage | Your personal canister | | **What your canister keeps** | File record, access rules, verification data | File record, access rules, file bytes | | **Upload concern** | Blob Storage availability and record commit | Cycle balance and canister safe floor | | **Trust model** | IC + local verification + storage service | IC + cryptography | :::note About pricing These are rough estimates for comparison. Real storage cost can change over time. ::: :::note Integrity and availability are different things Verification helps detect silent replacement of a file. It does not guarantee that a file will remain available forever. Availability depends on the storage mode, cycle balance, and retention rules of the selected storage service. ::: ## What stays the same in both modes Both modes keep the same user model. The byte location changes; ownership and access keep the same meaning. - Your personal canister keeps ownership, access rules, and trusted file records. - Encrypted files are encrypted in the browser before upload. - The canister checks permissions before file operations and key derivation. - Storage license and Pro decide which encrypted uploads are allowed. - Integrity verification remains part of the storage path. ## What happens if Rabbithole is unavailable? **On-chain Storage:** your file remains inside your canister as long as the canister stays funded with [cycles](/how-it-works/payment.md). **Blob Storage:** your canister still keeps the file record and the information needed to verify the file. File-byte availability depends on Blob Storage funding and retention policy. :::note Rabbithole is an interface, not the owner of your data The durable file record lives in your canister. Rabbithole helps you use it and manage service operations, but it does not become the data owner. ::: ## Learn more ## Understand how storage works ### [How Blob Storage works](/how-it-works/storage/blob-storage.md) ### [How On-chain Storage works](/how-it-works/storage/on-chain-storage.md) ### [How Rabbithole verifies your files](/how-it-works/storage/integrity.md) ### [Payment & Cycles](/how-it-works/payment.md) ### [What Pro gives you](/how-it-works/pro.md) ## Official Internet Computer references ### [Canister smart contracts](https://docs.internetcomputer.org/building-apps/essentials/canisters) ### [Query calls](https://docs.internetcomputer.org/building-apps/interact-with-canisters/query-calls) ### [Canister storage and stable memory](https://internetcomputer.org/docs/building-apps/canister-management/storage) --- url: /how-it-works/storage/integrity.md --- # How Rabbithole verifies your files ## Why this matters When a file is stored outside your browser, two different questions appear: - **Can someone read it?** - **Can someone replace it without you noticing?** Encryption answers the first question. File verification answers the second. :::tip What this means in practice If a file is silently replaced on the way to you, Rabbithole refuses to open it. You get a failed download or integrity error instead of a tampered file. ::: ## Blob Storage verification ![Blob Storage verification](/diagrams/fossflow-diagram-3.png) With Blob Storage, the browser does not trust the gateway blindly. ### Ask the canister for the expected file info The browser gets the expected file hash and related metadata from your canister. ### Verify that this metadata is authentic The metadata is delivered through an Internet Computer certification flow, so the browser can verify that it really came from your canister. ### Compare the downloaded file against that hash If the downloaded file does not match, the browser rejects it before opening. ## On-chain Storage verification ```mermaid flowchart LR C[Your canister] -->|encrypted chunks| B[Your browser] B --> V[Integrity check] V --> D[Decrypt locally] ``` With On-chain Storage there is no external storage gateway in the file path, so the verification path is simpler. The browser still verifies what it receives before decryption, but it does not need a separate external delivery path. ## What is certified by the Internet Computer For Blob Storage, Rabbithole certifies the metadata that tells the browser which file to expect. That includes values such as: - the file hash - file size - content type This lets the browser detect tampering before decryption. ## What is checked locally in the browser The browser recomputes the hash of the downloaded file and compares it with the certified value from the canister. Only if they match does decryption continue. :::note Why both steps matter Certification proves that the expected metadata really came from your canister.\ Local verification proves that the downloaded encrypted file matches that metadata. ::: ## Technical details :::details Certified metadata and local hashing ### Blob Storage path For Blob Storage, the browser performs two linked checks: 1. It verifies certified metadata returned by your canister. 2. It hashes the downloaded blob locally and compares it with the certified hash. The certified metadata currently includes: - the expected file hash - file size - content type The browser verifies that this metadata was certified by the Internet Computer, then verifies that the downloaded blob matches it byte-for-byte. ### What hash is used Rabbithole uses **SHA-256** for the certified file hash and for local comparison in the browser. ### Why certification and hashing are separate - **Certification** proves the expected metadata really came from your canister. - **Local hashing** proves the downloaded blob matches that metadata. Both checks are needed. Certification alone does not prove the gateway delivered the right file. Local hashing alone does not prove the expected hash was trustworthy. ### On-chain Storage path With On-chain Storage there is no separate external delivery layer, so the verification path is shorter: - the browser downloads file data from your canister - the browser still verifies integrity before opening - decryption only happens after integrity passes ::: ## Continue reading ## Related pages ### [How Blob Storage works](/how-it-works/storage/blob-storage.md) ### [How On-chain Storage works](/how-it-works/storage/on-chain-storage.md) ### [Trust Model](/how-it-works/trust-model.md) ## Official references ### [Certified data](https://docs.internetcomputer.org/tutorials/developer-liftoff/level-3/3.3-certified-data) ### [Motoko CertifiedData](https://docs.internetcomputer.org/motoko/core/CertifiedData) ### [Query calls](https://docs.internetcomputer.org/building-apps/interact-with-canisters/query-calls) --- url: /how-it-works/storage/on-chain-storage.md --- # How On-chain Storage works ## What On-chain Storage is On-chain Storage keeps the file directly inside your personal canister. There is no external storage service for the bytes: the canister keeps the file itself, the file record, and access rules. This mode is simpler to reason about, but it costs more. Every stored byte lives in canister memory and is paid for with cycles, so On-chain Storage is a better fit for small, high-value files. :::tip Trade-off You remove the external storage layer. In exchange, cost is higher, and cycle balance becomes part of normal storage operations. ::: ## Where the file lives ![On-chain Storage architecture](/diagrams/fossflow-diagram-4.png) The On-chain Storage path is shorter: - your browser prepares and uploads the file directly to the canister; - your personal canister keeps the file, trusted record, and access state; - there is no external gateway or external object storage layer in the file path. ## How upload works Before upload, the canister checks that it can safely accept the file: you have write access, the declared size fits the storage, and the cycle balance is enough for the operation. ### Prepare the file in the browser The browser encrypts the file locally and splits it into chunks, so upload does not require one large request. ### Send chunks to the canister The canister accepts file chunks one by one and keeps the upload within the allowed size and available cycles. ### Store the file and trusted record After all chunks are transferred, the canister stores the file and records the data your browser uses for later verification. ## When cycles are low In On-chain Storage, cycle balance quickly becomes a practical constraint: the file lives inside canister memory, and writing bytes also costs cycles. If the safe balance is not enough during upload, two outcomes are possible. - **Active Pro is enabled**: Rabbithole can request an automatic cycle top-up. The interface shows **Waiting for cycles...**, and the upload waits for funding. - **Active Pro is not enabled**: the owner must top up the canister manually. After top-up, a compatible retry can continue the upload. This is not an ownership error and does not mean the file is lost. The canister is refusing to start work it cannot safely finish. ## How download works ### Request file chunks from the canister The browser asks your canister for file data. There is no external file gateway in the file path. ### Verify and open locally The browser checks integrity and decrypts the file on your device. ## Why it costs more On-chain Storage costs more because every stored byte lives inside canister memory and affects the canister's operating balance. - The network maintains file bytes over time. - Stable memory and computation are paid from the canister's cycle balance. - Large files require a larger safe floor and may trigger funding checks more often. ## Practical limits On-chain Storage makes sense when: - files are relatively small; - the number of files is limited; - simpler architecture matters more than cost efficiency; - you are ready to monitor cycles or use active Pro. For large media collections or cost-sensitive bulk storage, it is usually a poor fit. ## Why the trust model is simpler With On-chain Storage, there is no external file gateway and no external object storage layer holding the file. That makes the storage path easier to reason about: - your browser prepares the file; - your canister stores the file; - your browser verifies and opens it again. ## Technical details :::details Upload session On-chain Storage does not write a large file directly into its final state. Upload runs through a session: the canister creates a temporary record, reserves the declared size, accepts file chunks, and only then moves data into the final file version. ```mermaid sequenceDiagram participant B as Browser participant C as Canister participant F as Cycle funding B->>C: beginUploadSession C->>C: Create a temporary record C->>C: Reserve the declared size alt cycles are low C-->>B: Waiting for cycles... F-->>C: Cycle top-up end alt upload can continue loop for each file chunk B->>C: appendUploadChunk C->>C: Write chunk into the temporary record end B->>C: finishUploadSession C->>C: Move data into the final file version C-->>B: File saved else upload cannot continue B->>C: abortUploadSession C->>C: Release temporary resources end ``` If cycles are low, the session waits for funding. A compatible retry can continue the existing session, so upload does not have to start from zero. If the upload cannot continue, the client tries to abort the session and release temporary resources. ::: ## Continue reading ## Related pages ### [How Blob Storage works](/how-it-works/storage/blob-storage.md) ### [How Rabbithole verifies your files](/how-it-works/storage/integrity.md) ### [Payment & Cycles](/how-it-works/payment.md) ## Official references ### [Canister smart contracts](https://docs.internetcomputer.org/building-apps/essentials/canisters) ### [Canister storage and stable memory](https://internetcomputer.org/docs/building-apps/canister-management/storage) ### [Motoko stable memory](https://internetcomputer.org/docs/motoko/base/ExperimentalStableMemory) --- url: /how-it-works/trust-model.md --- # Trust Model ## What do you need to trust? Every storage system has a trust model. Use this page to see what Rabbithole removes from the trust path and what you still need to trust. File contents are encrypted in your browser before upload. Rabbithole, storage infrastructure, and node operators do not receive the readable file. Privacy and availability are separate properties. Encryption protects file contents. Availability depends on the storage mode, cycle balance, and, for Blob Storage, retention rules of the external storage layer. If TEE support is available on the relevant IC subnet, it can improve runtime isolation. Treat it as an additional hardening layer, not as Rabbithole's primary privacy guarantee. ### You do NOT need to trust - **Rabbithole team** — we never see plaintext file contents - **ICP node operators** — they process encrypted blobs - **Network infrastructure** — encryption happens before data touches the network ### You DO need to trust - **The encryption code** — it's [open source](https://github.com/rabbithole-app/v2), audit it yourself - **Your browser** — the encryption runs in your browser's JavaScript engine - **Internet Identity** — for authentication (also open source) - **ICP consensus** — that the network correctly executes canister code ## Threat model First, separate the properties. Encryption protects file contents, access control decides who may request the file and key, and integrity verification helps detect byte replacement. The table below avoids a single protected/not protected label and shows the boundary instead: how protection works and what remains a separate responsibility. | Scenario | How protection works | Boundary | | ---------------------------------------- | -------------------------------------------------------- | ---------------------------------------------------------------- | | Rabbithole team gets access to files | Plaintext file contents do not reach Rabbithole | The file is encrypted in the browser before upload | | Man-in-the-middle attack | The browser verifies response and transport authenticity | It relies on IC certified responses and HTTPS | | ICP node operator peeks at data | Nodes receive encrypted data only | Data reaches IC after browser-side encryption | | Government requests data from Rabbithole | Rabbithole does not have plaintext file contents | Metadata and service records are not file contents | | You lose your device | Access can be recovered through Internet Identity | The lost device still needs operating-system protection | | Unwanted canister upgrade | Installing a new version requires the controller | If you are the controller, review code before upgrading | | Canister runs low on cycles | File-content privacy does not change | This is an availability issue: top up manually or use active Pro | | Blob Storage stops retaining bytes | The canister keeps the trusted file record | Byte availability depends on Blob Storage funding and retention | ## Rabbithole vs Traditional Cloud ```mermaid flowchart TB subgraph Traditional["Traditional Cloud (Google, Dropbox)"] direction TB U1[You] -->|upload| CS[Company Server] CS --> F1[Your files\nreadable by company] MK[Master key] --> CS GOV1[Government] -->|can request data| CS style CS fill:#fca5a5,stroke:#dc2626 style MK fill:#fca5a5,stroke:#dc2626 style GOV1 fill:#fef3c7,stroke:#d97706 end subgraph Rabbithole["Rabbithole"] direction TB U2[You] ==>|encrypted upload| CAN[Your Canister] CAN --> F2[Encrypted fragments\nunreadable] GOV2[Government] -.-x|nothing to decrypt| CAN style CAN fill:#86efac,stroke:#16a34a style F2 fill:#86efac,stroke:#16a34a style GOV2 fill:#fef3c7,stroke:#d97706 end style Traditional fill:#fef2f2,stroke:#dc2626 style Rabbithole fill:#f0fdf4,stroke:#16a34a ``` ## Comparison with other solutions | Solution | Decentralization | Trust Required | Data Sovereignty | | ----------------- | :--------------: | :------------: | :---------------------------------------: | | Google Drive | — | High | None | | Dropbox | — | High | None | | Tresorit | — | Medium | Partial (E2E, but company controls infra) | | IPFS + Encryption | High | Medium | Partial (no built-in encryption) | | **Rabbithole** | **High** | **Low** | **Full (you own the canister)** | :::note\{title="No system is perfect"} Rabbithole reduces trust assumptions, but it does not remove them entirely. If you find a weakness, [report it](https://github.com/rabbithole-app/v2/issues). ::: --- url: /legal/privacy.md --- # Privacy Policy **Last updated: May 31, 2026** ## The short version Rabbithole's file path is encrypted: we **cannot** access your file contents. Files are encrypted in your browser before they reach the network. We have no master keys and no backdoors for decrypting file contents. ## What we don't collect - **File contents** — we never see plaintext - **Encryption keys** — they are derived via threshold cryptography and never exist in one place - **Passwords** — there are none; authentication is via Internet Identity (passkeys/biometrics) - **Email addresses by default** — registration does not require email. If you consent to share a verified email attribute, Rabbithole uses it for features such as invite-by-email access and future notifications. - **Browsing history or tracking data** — no analytics, no cookies, no third-party trackers ## What we do process ### Internet Identity Principal When you sign in, your browser generates a cryptographic identity (Principal ID) via Internet Identity. This identity is: - Unique to Rabbithole (cannot be used to track you across other apps) - Not linked to any personal information - Stored only on the Internet Computer blockchain ### Canister interactions Your personal storage canister records: - File metadata (names, sizes, folder structure) — stored in your canister, not encrypted - File contents — encrypted before they are written to the selected storage mode - Access permissions you set Your canister stores file records, access rules, and on-chain file bytes. Blob Storage files keep their bytes outside the canister, with verification data stored in your canister. After a successful setup handoff, Rabbithole is removed from controllers. ### Payment information When creating a storage canister, payment covers Internet Computer network costs, the initial cycles balance, deployment operations, and related Rabbithole infrastructure. We do not store payment details. ## Data location Your canister data is stored on the [Internet Computer](https://internetcomputer.org), distributed across independent nodes operated by different parties worldwide. Node operators do not receive readable file contents. ## Data retention Your data persists as long as your canister has cycles (fuel). You can: - Top up cycles directly without Rabbithole - Delete your data at any time - Export your data at any time If Rabbithole ceases to exist, your canister remains accessible via its direct URL while it has cycles. On-chain files remain in the canister; Blob Storage file availability depends on the Blob Storage retention lifecycle. ## Third-party services - **Internet Identity** — authentication provider (open source, operated by DFINITY Foundation) - **Internet Computer** — decentralized blockchain network - **Blob Storage infrastructure** — used when files are stored outside the canister; it stores ciphertext, not readable file contents We do not use Google Analytics, Facebook Pixel, or any third-party tracking service. ## Open source Our code is [open source on GitHub](https://github.com/rabbithole-app/v2). You can verify many technical claims in this policy by reading the source code. Operational settings, external providers, and network behavior can also affect how a deployed instance works. ## Changes to this policy We will update this page if our practices change. Since we're open source, any changes are visible in our commit history. ## Contact Questions about privacy? Open an issue on [GitHub](https://github.com/rabbithole-app/v2/issues) or reach out on [X (Twitter)](https://x.com/rabbithole_ic). --- url: /legal/terms.md --- # Terms of Service **Last updated: May 18, 2026** ## Overview Rabbithole is a decentralized encrypted file storage service built on the Internet Computer blockchain. By using Rabbithole, you agree to these terms. ## Your storage canister When you create storage, a smart contract (canister) is deployed on the Internet Computer. After setup completes successfully: - **You are the sole controller** — Rabbithole removes itself from controllers during handoff. During setup, retries, or approved updates, Rabbithole may be added temporarily to install, retry, or update the deployment. - **You own your data** — your canister stores ownership, access rules, and trusted records; on-chain files are stored in the canister, while Blob Storage files store their file bytes outside the canister - **You are responsible** for your canister's cycle balance (operational fuel) ## What you can store You may store any files that are legal in your jurisdiction. We cannot read file contents because encryption happens in your browser. You are solely responsible for what you store. ## What we provide - **Web interface** at rabbithole.app for managing your files - **Canister deployment** service for creating personal storage - **Frontend updates** delivered to your canister (optional, you control whether to accept) ## What we don't guarantee - **Uptime of rabbithole.app** — the web interface may experience downtime. However, your canister remains accessible at its direct URL regardless of rabbithole.app status - **Data recovery** — if you lose access to your Internet Identity, we cannot recover your data. We have no master keys or backdoors - **Cycle management** — if your canister runs out of cycles, it may be removed by the Internet Computer network. You are responsible for maintaining a sufficient cycle balance ## Payments - Storage creation requires a one-time setup payment. It covers canister creation, the initial cycles balance, deployment operations, and related infrastructure costs. - Payments are non-refundable once the canister is deployed - Future cycle top-ups can be done directly through the Internet Computer without Rabbithole ## Intellectual property - **Your files** remain yours. We claim no ownership or rights over your data - **Rabbithole software** is open source under the licenses specified in our [GitHub repository](https://github.com/rabbithole-app/v2) ## Limitation of liability To the maximum extent permitted by applicable law, Rabbithole is provided "as is" and "as available" without warranties of any kind. We are not liable for: - Loss of data due to canister cycle depletion, storage-mode funding, deletion, or failed exports - Loss of access due to Internet Identity, wallet, browser, device, or network issues - Failed canister upgrades, failed retries, or rejected updates - Indirect, incidental, special, consequential, exemplary, or punitive damages arising from use of the service Nothing in these terms limits liability that cannot be limited under applicable law. ## Termination - You can stop using Rabbithole at any time. Your canister continues to operate independently - You can delete your canister and all data at any time - We may discontinue the rabbithole.app interface, but your canister continues independently while it has cycles. File availability depends on your selected storage mode and storage funding. ## Changes to these terms We may update these terms. Changes will be posted on this page. Continued use of Rabbithole after changes constitutes acceptance. ## Governing law These terms are intended to apply where permitted by law. They do not limit non-waivable consumer protection rights in your jurisdiction. The final governing-law and venue rules for a paid transaction may also depend on the legal entity, wallet, checkout provider, and jurisdiction involved in that transaction. ## Contact Questions? Open an issue on [GitHub](https://github.com/rabbithole-app/v2/issues) or reach out on [X (Twitter)](https://x.com/rabbithole_ic). --- url: /agent-resources.md --- # Agent resources This docs site implements the [Agent-Friendly Documentation Spec](https://agentdocsspec.com/). It publishes plain-text entry points that AI agents can fetch before answering questions about Rabbithole. ## Files for agents Use these files when an agent needs to read the English documentation: - /llms.txt: a discovery index listing the documentation pages. Use it when the agent can fetch only the pages it needs. - /llms-full.txt: the full English documentation in one text file. Use it when the agent needs the whole docs context and has enough context window. ## What to tell an agent Paste this into your agent: ```txt Use /llms.txt from this documentation site as the Rabbithole docs index. ``` ## Copy a single page The Markdown links for individual pages are listed in `/llms.txt`. For example: /getting-started/introduction.md. When browsing manually, use **Copy Markdown** in the page header to copy the current page without navigation or site chrome. --- url: /index.md --- # Rabbithole Encrypted Storage on the Internet Computer > No passwords. No master keys. Your files are protected by mathematics, not promises. [Why Rabbithole](/getting-started/introduction) | [How Encryption Works](/how-it-works/encryption) ## Features - 🏛️ **Personal storage**: Your storage is a separate Internet Computer canister with its own web interface. After control is transferred, it belongs to you, while Rabbithole remains a service around it, not the owner of your data. - 🔐 **Encryption before upload**: Rabbithole encrypts the file before it leaves your device. The storage works with encrypted data, not readable file contents. - 🗝️ **Keys on demand**: The file key is not sitting ready in storage or at Rabbithole. It is derived through vetKeys at access time and returned encrypted for your browser. - 🤝 **Encrypted sharing**: You can share a storage, folder, or file while keeping encryption. Rabbithole changes the access rule instead of creating a second file copy. - 🔒 **Passwordless sign-in**: Rabbithole uses Internet Identity for passkeys, biometrics, or supported social login. Rabbithole does not keep a separate password database. - 📖 **Verifiable trust model**: Rabbithole does not ask you to trust words alone. The code is open, and the docs show how encryption, vetKeys, permissions, and storage ownership work.