+8
-8
README.md
+8
-8
README.md
···
1
# Cistern
2
3
Cistern is an attempt at implementing a private, personal quick-capture system
4
-
on AT Protocol. Cistern "items" are encrypted, so that they are only readable
5
-
by the holder of the correct secret key—stored off-protocol. These items are
6
intended to be ephemeral, and to be deleted after they've been read.
7
8
The intention is for Cistern to bridge the gap between where ideas are had and
9
where they can be stored long-term. For example, let's say you have an idea
10
-
while at a restaurant. You create an item using your phone, and once you're
11
-
back at your desk and you open Obsidian, that item is automatically pulled from
12
-
your PDS, decrypted, and deleted from your PDS. If your notebook was open at
13
-
the time you created your item, the Cistern Obsidian plugin would have been
14
-
notified of the new item via the Jetstream, and so you would find your memo
15
-
waiting for you once you got home.
···
1
# Cistern
2
3
Cistern is an attempt at implementing a private, personal quick-capture system
4
+
on AT Protocol. Cistern "items" are encrypted, so that they are only readable by
5
+
the holder of the correct secret key—stored off-protocol. These items are
6
intended to be ephemeral, and to be deleted after they've been read.
7
8
The intention is for Cistern to bridge the gap between where ideas are had and
9
where they can be stored long-term. For example, let's say you have an idea
10
+
while at a restaurant. You create an item using your phone, and once you're back
11
+
at your desk and you open Obsidian, that item is automatically pulled from your
12
+
PDS, decrypted, and deleted from your PDS. If your notebook was open at the time
13
+
you created your item, the Cistern Obsidian plugin would have been notified of
14
+
the new item via the Jetstream, and so you would find your memo waiting for you
15
+
once you got home.
+1
-1
packages/crypto/deno.jsonc
+1
-1
packages/crypto/deno.jsonc
+4
-3
packages/crypto/src/keys.ts
+4
-3
packages/crypto/src/keys.ts
···
1
import { XWing } from "@noble/post-quantum/hybrid.js";
2
3
-
export function generateKeys() {
4
return XWing.keygen();
5
}
6
7
-
export function serializeKey(key: Uint8Array) {
8
return key.toBase64();
9
}
10
11
-
export function deserializeKey(key: string) {
12
return Uint8Array.fromBase64(key);
13
}
···
1
import { XWing } from "@noble/post-quantum/hybrid.js";
2
+
import type { KeyPair } from "./types.ts";
3
4
+
export function generateKeys(): KeyPair {
5
return XWing.keygen();
6
}
7
8
+
export function serializeKey(key: Uint8Array): string {
9
return key.toBase64();
10
}
11
12
+
export function deserializeKey(key: string): Uint8Array {
13
return Uint8Array.fromBase64(key);
14
}
+5
packages/crypto/src/types.ts
+5
packages/crypto/src/types.ts
+1
-1
packages/lexicon/deno.jsonc
+1
-1
packages/lexicon/deno.jsonc
+4
-4
packages/lexicon/mod.ts
+4
-4
packages/lexicon/mod.ts
···
1
import item from "./schemas/item.json" with { type: "json" };
2
import pubkey from "./schemas/pubkey.json" with { type: "json" };
3
4
-
import { Lexicons } from "@atproto/lexicon";
5
6
-
const lexicons = new Lexicons();
7
8
-
lexicons.add(item);
9
-
lexicons.add(pubkey);
10
11
export { item, lexicons, pubkey };
···
1
import item from "./schemas/item.json" with { type: "json" };
2
import pubkey from "./schemas/pubkey.json" with { type: "json" };
3
4
+
import { type LexiconDoc, Lexicons } from "@atproto/lexicon";
5
6
+
const lexicons: Lexicons = new Lexicons();
7
8
+
lexicons.add(item as LexiconDoc);
9
+
lexicons.add(pubkey as LexiconDoc);
10
11
export { item, lexicons, pubkey };
+4
-4
packages/lexicon/schemas/item.json
+4
-4
packages/lexicon/schemas/item.json
···
1
{
2
-
"version": 1,
3
"id": "app.cistern.lexicon.item",
4
"description": "An encrypted memo intended to be accessed and deleted later.",
5
"defs": {
···
23
"type": "string",
24
"description": "TID representing when this item was created",
25
"format": "tid"
26
-
}
27
"ciphertext": {
28
"type": "string",
29
"description": "Encapsulated shared ciphertext",
···
32
"nonce": {
33
"type": "string",
34
"description": "Base64-encoded nonce used for content encryption",
35
-
"maxLength": 32,
36
},
37
"algorithm": {
38
"type": "string",
···
50
},
51
"contentLength": {
52
"type": "integer",
53
-
"description": "Original content length in bytes",
54
},
55
"contentHash": {
56
"type": "string",
···
1
{
2
+
"lexicon": 1,
3
"id": "app.cistern.lexicon.item",
4
"description": "An encrypted memo intended to be accessed and deleted later.",
5
"defs": {
···
23
"type": "string",
24
"description": "TID representing when this item was created",
25
"format": "tid"
26
+
},
27
"ciphertext": {
28
"type": "string",
29
"description": "Encapsulated shared ciphertext",
···
32
"nonce": {
33
"type": "string",
34
"description": "Base64-encoded nonce used for content encryption",
35
+
"maxLength": 32
36
},
37
"algorithm": {
38
"type": "string",
···
50
},
51
"contentLength": {
52
"type": "integer",
53
+
"description": "Original content length in bytes"
54
},
55
"contentHash": {
56
"type": "string",
+1
-1
packages/lexicon/schemas/pubkey.json
+1
-1
packages/lexicon/schemas/pubkey.json