···11# Cistern
2233-Cistern is a private, end-to-end encrypted quick-capture system built on AT Protocol. Items are encrypted using post-quantum cryptography and stored temporarily in your Personal Data Server (PDS), then automatically retrieved and deleted after consumption.
33+Cistern is a private, end-to-end encrypted quick-capture system built on AT
44+Protocol. Memos are encrypted using post-quantum cryptography and stored
55+temporarily in your Personal Data Server (PDS), then automatically retrieved and
66+deleted after consumption.
4755-The system bridges the gap between where ideas are captured and where they are stored long-term. Create an encrypted item on your phone, and it automatically appears in your desktop application, decrypted and ready to use.
88+The system bridges the gap between where ideas are captured and where they are
99+stored long-term. Create an encrypted memo on your phone, and it automatically
1010+appears in your desktop application, decrypted and ready to use.
611712## Architecture
813914Cistern is a Deno monorepo consisting of five packages:
10151116### `@cistern/crypto`
1212-Core cryptographic operations using post-quantum algorithms. Implements X-Wing key encapsulation with XChaCha20-Poly1305 authenticated encryption and SHA3-512 integrity verification. Handles keypair generation, encryption, and decryption.
1717+1818+Core cryptographic operations using post-quantum algorithms. Implements X-Wing
1919+key encapsulation with XChaCha20-Poly1305 authenticated encryption and SHA3-512
2020+integrity verification. Handles keypair generation, encryption, and decryption.
13211422### `@cistern/lexicon`
1515-AT Protocol schema definitions for Cistern record types. Defines `app.cistern.lexicon.pubkey` (public key records) and `app.cistern.lexicon.item` (encrypted item records). Includes code generation from JSON schemas.
2323+2424+AT Protocol schema definitions for Cistern record types. Defines
2525+`app.cistern.pubkey` (public key records) and `app.cistern.memo` (encrypted memo
2626+records). Includes code generation from JSON schemas.
16271728### `@cistern/shared`
1818-Common utilities and authentication logic. Handles DID resolution via Slingshot service and creates authenticated RPC clients using app passwords.
2929+3030+Common utilities and authentication logic. Handles DID resolution via Slingshot
3131+service and creates authenticated RPC clients using app passwords.
19322033### `@cistern/producer`
2121-Creates and encrypts items for storage. Manages public key selection, encrypts plaintext content, and uploads encrypted items to the PDS as AT Protocol records.
3434+3535+Creates and encrypts memos for storage. Manages public key selection, encrypts
3636+plaintext content, and uploads encrypted memos to the PDS as AT Protocol
3737+records.
22382339### `@cistern/consumer`
2424-Retrieves, decrypts, and deletes items. Generates keypairs, manages private keys locally, retrieves items via polling or real-time streaming (Jetstream), and handles item deletion after consumption.
4040+4141+Retrieves, decrypts, and deletes memos. Generates keypairs, manages private keys
4242+locally, retrieves memos via polling or real-time streaming (Jetstream), and
4343+handles memo deletion after consumption.
25442645## Security Model
27462828-Private keys never leave the consumer device. Public keys are stored in the PDS as records, while private keys remain off-protocol. Only the holder of the matching private key can decrypt items encrypted with the corresponding public key.
4747+Private keys never leave the consumer device. Public keys are stored in the PDS
4848+as records, while private keys remain off-protocol. Only the holder of the
4949+matching private key can decrypt memos encrypted with the corresponding public
5050+key.
29513052## Testing
31533254Run all unit tests:
5555+3356```bash
3457deno test --allow-env
3558```
36593760Run end-to-end tests (requires AT Protocol credentials):
6161+3862```bash
3963CISTERN_HANDLE="your.bsky.social" \
4064CISTERN_APP_PASSWORD="xxxx-xxxx-xxxx-xxxx" \
···4455## Record Types
6677-| Collection | Description |
88-|------------|-------------|
99-| `app.cistern.lexicon.pubkey` | Public key records with human-readable names, referenced by items via AT-URI |
1010-| `app.cistern.lexicon.item` | Encrypted item records containing ciphertext, nonce, algorithm metadata, and public key reference |
77+| Collection | Description |
88+| -------------------- | ------------------------------------------------------------------------------------------------- |
99+| `app.cistern.pubkey` | Public key records with human-readable names, referenced by memos via AT-URI |
1010+| `app.cistern.memo` | Encrypted memo records containing ciphertext, nonce, algorithm metadata, and public key reference |
···11{
22 "lexicon": 1,
33- "id": "app.cistern.lexicon.pubkey",
44- "description": "A public key used to encrypt Cistern items",
33+ "id": "app.cistern.pubkey",
44+ "description": "A public key used to encrypt Cistern memos",
55 "defs": {
66 "main": {
77 "type": "record",
88- "description": "A public key used to encrypt Cistern items",
88+ "description": "A public key used to encrypt Cistern memos",
99 "record": {
1010 "type": "object",
1111 "required": ["name", "algorithm", "content", "createdAt"],
+2-2
packages/lexicon/src/index.ts
···11-export * as AppCisternLexiconItem from "./types/app/cistern/lexicon/item.ts";
22-export * as AppCisternLexiconPubkey from "./types/app/cistern/lexicon/pubkey.ts";
11+export * as AppCisternMemo from "./types/app/cistern/memo.ts";
22+export * as AppCisternPubkey from "./types/app/cistern/pubkey.ts";
···55const _mainSchema = /*#__PURE__*/ v.record(
66 /*#__PURE__*/ v.string(),
77 /*#__PURE__*/ v.object({
88- $type: /*#__PURE__*/ v.literal("app.cistern.lexicon.item"),
88+ $type: /*#__PURE__*/ v.literal("app.cistern.memo"),
99 /**
1010 * Algorithm used for encryption, in <kem>-<cipher>-<hash> format.
1111 */
···2929 */
3030 nonce: /*#__PURE__*/ v.bytes(),
3131 /**
3232- * Encrypted item contents
3232+ * Encrypted memo contents
3333 */
3434 payload: /*#__PURE__*/ v.bytes(),
3535 /**
3636- * URI to the public key used to encrypt this item
3636+ * URI to the public key used to encrypt this memo
3737 */
3838 pubkey: /*#__PURE__*/ v.resourceUriString(),
3939 /**
4040- * TID representing when this item was created
4040+ * TID representing when this memo was created
4141 */
4242 tid: /*#__PURE__*/ v.tidString(),
4343 }),
···53535454declare module "@atcute/lexicons/ambient" {
5555 interface Records {
5656- "app.cistern.lexicon.item": mainSchema;
5656+ "app.cistern.memo": mainSchema;
5757 }
5858}