How it works

BitPlan encrypts an HTML plan before it leaves your computer. BRC-100 is the interface BitPlan uses to talk to your wallet; it is not an inscription format. The plan can stay hosted as ciphertext while it changes, then become a permanent 1Sat Ordinal when it is ready.

BITPLANPUBLISHbitplan CLIvalidate · scan · envelopeBRC-100 walletencrypt/wrap · sign · unwrapBRC-100BSV chainencrypted 1Sat OrdinalREAD + DECRYPTindexer / OrdFSreturns ciphertextbitplan.dev viewerrenders browser plaintextpublishwallet.decrypt ↕ plaintext / key
The CLI validates and packages the draft. The wallet performs identity key operations and publishes. In the browser, the wallet unwraps the document key; the SDK opens the payload.

The viewer loads ciphertext from bitplan.dev or 1Sat. In the browser, an authorized wallet or reader link unwraps the document key. Plaintext never reaches the server.

Encryption

A BitPlan envelope is a container. Its BPLN marker, version, and JSON header tell a reader how to open the encrypted body. The header is public and contains no secret key.

The envelope is a container around the encrypted data. It is not an encryption algorithm.

Only you

The wallet encrypts the 32-byte document key to itself, not the whole document. It derives that wrap from the wallet root, [2, "bitplan"], the draft's keyID, and counterparty: "self". The root key and derived key stay in the wallet. The keyID is a public label, not a key.

You and named readers

The CLI creates a fresh random 32-byte document key and encrypts the plan once with the @bsv/sdk AES-256-GCM implementation. The wallet then encrypts that small key for the owner and each reader. A reader's identity key selects their copy; their wallet derives the matching key with the publisher as counterparty.

The SDK gets both the document key and a fresh AES-GCM IV from the operating system's secure random generator. It stops with an error if secure randomness is unavailable. The encrypted plan also commits the exact public header. Changes made without the document key fail authentication.

What this protects

AES-GCM hides the plan and detects changes to its ciphertext. A wrong wallet, key, or counterparty cannot decrypt it. The chain still reveals the envelope size, version, and the publisher and reader identity keys. Access to an older version cannot be revoked because that inscription is permanent.

Publishing

  1. Check locally. The CLI validates the HTML and scans the document and metadata for secrets. A failure stops the upload before the wallet is called.
  2. Confirm. The CLI shows an approximate envelope size and content fee, then asks for confirmation.
  3. Encrypt. The plan is encrypted once with the SDK, then the wallet wraps its 32-byte document key for the owner and each reader. The wallet keeps every identity private key. The CLI builds the envelope.
  4. Publish through the wallet. The wallet signs and broadcasts a new inscription, or spends the current draft coin to create its next version.
  5. Notify OrdFS. By default, the CLI sends the wallet-returned Atomic BEEF to 1Sat. 1Sat attempts to capture it for OrdFS and forwards the transaction to Arcade. The wallet publish remains authoritative; --no-relay opts out.

Sharing

--share-with <identity-key> adds a reader to the next version. The recipient's wallet unwraps the document key using the publisher's public identity key. These public keys identify the counterparties; they are not the symmetric document key. BRC-42 derivation and identity-key operations stay inside each BRC-100 wallet.

The access list is public. Each reader adds only a small wrapped key, not another copy of the document. A later version can drop invited readers, but no transaction can revoke access to an older inscription.

Hosted drafts

A hosted draft uses the same envelope as an on-chain draft. bitplan.dev stores that ciphertext instead of writing it to the chain. CLI uploads use a wallet; browser guest starters use a throwaway reader identity. Neither needs BSV for hosting. bitplan inscribe puts the draft on chain, and the hosted link redirects to that origin forever. Stored draft objects contain only ciphertext and the public envelope header.

A hosted ID is a random 120-bit locator. It does not decrypt anything. A separate random 256-bit update secret stays in the CLI's local state. Update requests carry that bearer over HTTPS; the server stores only its hash and requires the bearer for every new version. Losing the local secret means that machine can no longer update the hosted draft.

Versions

The first inscription's origin outpoint is the draft ID. Each update spends the current 1-sat output and carries the next encrypted envelope forward. /d/<origin> resolves the latest version; ?v=n pins one version.

The first transaction creates the draft coin. Each later version spends its current output and creates a replacement carrying a new envelope; the origin outpoint remains the draft ID.

Reading

The viewer fetches and validates the encrypted envelope, then calls wallet.decrypt. The wallet returns the document key and the SDK decrypts the payload in the browser. The HTML stays in the browser and renders in a sandboxed iframe. The CLI equivalent is bitplan fetch <origin|url>.

bitplan list finds drafts by asking the wallet for outputs in its 1sat basket tagged type:application/x-bitplan. Local state is only a metadata cache; it contains no wallet keys.

Control and recovery

The current coin controls publishing; wallet keys control reading. Those capabilities can diverge. Sharing grants read access; it does not grant the recipient the draft coin or permission to publish the next version. The envelope does not sign authorship; the draft's origin and transaction chain establish who controls publishing.

Ciphertext is public and permanent. Encryption does not restore a delete button, which is why every upload is scanned for secrets.

Start with CLI setup, or inspect the envelope format.

Search BitPlan

Jump to a BitPlan page, docs, or the npm CLI.