Encrypted, ephemeral, private memos on atproto

feat(consumer): stub module and interface

graham.systems 3d1b2761 ad3f47cc

verified
Changed files
+139 -13
packages
+34 -13
deno.lock
··· 1 1 { 2 2 "version": "5", 3 3 "specifiers": { 4 - "jsr:@noble/ciphers@*": "2.0.1", 5 4 "jsr:@noble/ciphers@^2.0.1": "2.0.1", 6 5 "jsr:@noble/curves@2.0": "2.0.1", 7 - "jsr:@noble/hashes@*": "2.0.1", 8 6 "jsr:@noble/hashes@2": "2.0.1", 9 7 "jsr:@noble/hashes@2.0": "2.0.1", 10 8 "jsr:@noble/hashes@^2.0.1": "2.0.1", 11 - "jsr:@noble/post-quantum@*": "0.5.2", 12 9 "jsr:@noble/post-quantum@~0.5.2": "0.5.2", 13 - "jsr:@std/assert@^1.0.14": "1.0.15", 10 + "jsr:@std/assert@^1.0.14": "1.0.14", 14 11 "jsr:@std/expect@^1.0.17": "1.0.17", 15 - "jsr:@std/internal@^1.0.10": "1.0.12", 16 - "jsr:@std/internal@^1.0.12": "1.0.12", 17 - "npm:@atcute/lex-cli@*": "2.3.1", 12 + "jsr:@std/internal@^1.0.10": "1.0.10", 13 + "npm:@atcute/client@^4.0.5": "4.0.5", 18 14 "npm:@atcute/lex-cli@^2.3.1": "2.3.1", 19 15 "npm:@atcute/lexicons@^1.2.2": "1.2.2", 20 16 "npm:@atproto/lexicon@~0.5.1": "0.5.1" ··· 39 35 "jsr:@noble/hashes@2.0" 40 36 ] 41 37 }, 42 - "@std/assert@1.0.15": { 43 - "integrity": "d64018e951dbdfab9777335ecdb000c0b4e3df036984083be219ce5941e4703b", 38 + "@std/assert@1.0.14": { 39 + "integrity": "68d0d4a43b365abc927f45a9b85c639ea18a9fab96ad92281e493e4ed84abaa4", 44 40 "dependencies": [ 45 - "jsr:@std/internal@^1.0.12" 41 + "jsr:@std/internal" 46 42 ] 47 43 }, 48 44 "@std/expect@1.0.17": { 49 45 "integrity": "316b47dd65c33e3151344eb3267bf42efba17d1415425f07ed96185d67fc04d9", 50 46 "dependencies": [ 51 47 "jsr:@std/assert", 52 - "jsr:@std/internal@^1.0.10" 48 + "jsr:@std/internal" 53 49 ] 54 50 }, 55 - "@std/internal@1.0.12": { 56 - "integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027" 51 + "@std/internal@1.0.10": { 52 + "integrity": "e3be62ce42cab0e177c27698e5d9800122f67b766a0bea6ca4867886cbde8cf7" 57 53 } 58 54 }, 59 55 "npm": { 56 + "@atcute/client@4.0.5": { 57 + "integrity": "sha512-R8Qen8goGmEkynYGg2m6XFlVmz0GTDvQ+9w+4QqOob+XMk8/WDpF4aImev7WKEde/rV2gjcqW7zM8E6W9NShDA==", 58 + "dependencies": [ 59 + "@atcute/identity", 60 + "@atcute/lexicons" 61 + ] 62 + }, 63 + "@atcute/identity@1.1.1": { 64 + "integrity": "sha512-zax42n693VEhnC+5tndvO2KLDTMkHOz8UExwmklvJv7R9VujfEwiSWhcv6Jgwb3ellaG8wjiQ1lMOIjLLvwh0Q==", 65 + "dependencies": [ 66 + "@atcute/lexicons", 67 + "@badrap/valita" 68 + ] 69 + }, 60 70 "@atcute/lex-cli@2.3.1": { 61 71 "integrity": "sha512-HrHD91CFSFd/p0UFe3akFA1HXiboQwd5LbYiU0srKdLxGX+NLTX/EdCdhbLV6M7LsXdmxk7PB6BMcprsX4rbvg==", 62 72 "dependencies": [ ··· 150 160 }, 151 161 "workspace": { 152 162 "members": { 163 + "packages/consumer": { 164 + "dependencies": [ 165 + "npm:@atcute/client@^4.0.5", 166 + "npm:@atcute/lexicons@^1.2.2" 167 + ] 168 + }, 153 169 "packages/crypto": { 154 170 "dependencies": [ 155 171 "jsr:@noble/ciphers@^2.0.1", ··· 163 179 "npm:@atcute/lex-cli@^2.3.1", 164 180 "npm:@atcute/lexicons@^1.2.2", 165 181 "npm:@atproto/lexicon@~0.5.1" 182 + ] 183 + }, 184 + "packages/shared": { 185 + "dependencies": [ 186 + "npm:@atcute/lexicons@^1.2.2" 166 187 ] 167 188 } 168 189 }
+7
packages/consumer/README.md
··· 1 + # `@cistern/consumer` 2 + 3 + The Consumer module is responsible for the following: 4 + 5 + - Generating key pairs 6 + - Retrieving and decrypting items 7 + - Subscribing to Jetstream to monitor for items
+10
packages/consumer/deno.jsonc
··· 1 + { 2 + "name": "@cistern/consumer", 3 + "exports": { 4 + ".": "./mod.ts" 5 + }, 6 + "imports": { 7 + "@atcute/client": "npm:@atcute/client@^4.0.5", 8 + "@atcute/lexicons": "npm:@atcute/lexicons@^1.2.2" 9 + } 10 + }
+67
packages/consumer/mod.ts
··· 1 + import { Client, CredentialManager } from "@atcute/client"; 2 + import { resolveMiniDoc } from "@cistern/shared"; 3 + import type { Did } from "@atcute/lexicons/syntax"; 4 + import type { ConsumerOptions, ConsumerParams, LocalKeyPair } from "./types.ts"; 5 + 6 + export async function createConsumer( 7 + options: ConsumerOptions, 8 + ): Promise<Consumer> { 9 + const miniDoc = await resolveMiniDoc(options.handle); 10 + const manager = new CredentialManager({ service: miniDoc.pds }); 11 + const rpc = new Client({ handler: manager }); 12 + await manager.login({ 13 + identifier: miniDoc.handle, 14 + password: options.appPassword, 15 + }); 16 + 17 + return new Consumer({ 18 + miniDoc, 19 + manager, 20 + rpc, 21 + options, 22 + }); 23 + } 24 + 25 + /** 26 + * Client for generating keys and decoding Cistern items. 27 + */ 28 + export class Consumer { 29 + did: Did; 30 + keypair?: LocalKeyPair; 31 + rpc: Client; 32 + manager: CredentialManager; 33 + 34 + constructor(params: ConsumerParams) { 35 + this.did = params.miniDoc.did; 36 + this.keypair = params.options.keypair; 37 + this.rpc = params.rpc; 38 + this.manager = params.manager; 39 + } 40 + 41 + /** 42 + * Generates a key pair, uploading the public key to PDS and returning the pair. 43 + * @todo Generate key pair 44 + * @todo Store private key in local registry 45 + * @todo Upload public key to PDS 46 + */ 47 + async generateKeyPair() {} 48 + 49 + /** 50 + * Returns an async iterator that returns pages of the user's items from their PDS. 51 + * @todo List items from repo 52 + */ 53 + async listItems() {} 54 + 55 + /** 56 + * Subscribes to the Jetstreams for the user's items. 57 + * @todo Add `@atcute/jetstream` dependency 58 + * @todo Return an async iterator 59 + */ 60 + async getItemSubscription() {} 61 + 62 + /** 63 + * Deletes an item from the user's PDS by record key. 64 + * @todo Delete item from PDS 65 + */ 66 + async deleteItem() {} 67 + }
+21
packages/consumer/types.ts
··· 1 + import type { Client, CredentialManager } from "@atcute/client"; 2 + import type { MiniDoc } from "@cistern/shared"; 3 + import type { AppCisternLexiconPubkey } from "@cistern/lexicon"; 4 + 5 + export interface LocalKeyPair { 6 + privateKey: string; 7 + publicKey: AppCisternLexiconPubkey.Main; 8 + } 9 + 10 + export interface ConsumerOptions { 11 + handle: string; 12 + appPassword: string; 13 + keypair?: LocalKeyPair; 14 + } 15 + 16 + export interface ConsumerParams { 17 + miniDoc: MiniDoc; 18 + manager: CredentialManager; 19 + rpc: Client; 20 + options: ConsumerOptions; 21 + }