| … | … | @@ -0,0 +1,64 @@ |
| 1 | # atproto-store |
| 2 | |
| 3 | The **Holepunch-native home for an AT Protocol repository**: records live in a classic |
| 4 | **Hyperbee** (`collection/rkey → DAG-CBOR value`), and a **Hypercore firehose** carries the |
| 5 | signed `#commit` / `#sync` events. This is where the data actually lives in P2P; |
| 6 | [`atproto-repo`](../atproto-repo) is the byte-exact serializer layered over it. |
| 7 | |
| 8 | Part of the **atproto-base** self-custody stack: |
| 9 | |
| 10 | ``` |
| 11 | atproto-repo serialization / codec |
| 12 | atproto-store ← you are here (P2P repo storage + firehose) |
| 13 | atproto-identity seed-anchored did:plc identity + auth |
| 14 | hyper-proto-peer the self-custody peer (multi-device swarm PDS) |
| 15 | atproto-bridge keyless membrane → Bluesky |
| 16 | ``` |
| 17 | |
| 18 | ## Modules |
| 19 | |
| 20 | - **RepoStore** (`lib/repo-store.js`, main) — the Hyperbee record store. `put` / `get` / |
| 21 | `listRecords` keyed by `collection/rkey`. Skips the reserved `__`-namespace so internal |
| 22 | state never leaks into the signed public repo. |
| 23 | - **RepoManager** (`lib/repo-manager.js`) — the write path: applies record ops and drives |
| 24 | commit formatting. |
| 25 | - **FirehoseSequencer** (`lib/sequencer.js`) — the append-only, forward-cursor firehose |
| 26 | Hypercore. `sequenceCommit`, `subscribe(cursor)`. Deterministic across devices. |
| 27 | - **Firehose frames** (`lib/firehose.js`) — `commitFrame` / `syncFrame` / `identityFrame` / |
| 28 | `accountFrame` encode + `decodeCommitFrame` / `decodeFrame`. `#commit` carries ops (the |
| 29 | mandatory AppView-indexing event); `#sync` is a keyless re-baseline. |
| 30 | - **read-view** (`lib/read-view.js`) — keyless read surface assembled from the replicated |
| 31 | store + firehose: `getRepoFromCommit` (signed CAR), `getRecord`, `listRecords`, |
| 32 | `getLatestCommit`. The bridge's read path uses these without ever holding a key. |
| 33 | - **BlobStore** (`lib/blob-store.js`) — content-addressed blob storage. |
| 34 | - **AccountRegistry** (`lib/account-registry.js`) — multi-account host bookkeeping. |
| 35 | - **tid** (`lib/tid.js`) — `tidNow` / `isValidTid`, the 13-char sortable record keys + revs. |
| 36 | - **corestore** (`lib/corestore.js`) — `openCorestore` / `isCorestore` helpers. |
| 37 | |
| 38 | ## Usage |
| 39 | |
| 40 | ```js |
| 41 | import { RepoStore } from 'atproto-store/lib/repo-store.js' |
| 42 | import { FirehoseSequencer } from 'atproto-store/lib/sequencer.js' |
| 43 | |
| 44 | const repo = await new RepoStore(corestore, { name: 'repo:' + did }).ready() |
| 45 | await repo.put('app.bsky.feed.post', tidNow(), { $type: 'app.bsky.feed.post', text, createdAt }) |
| 46 | |
| 47 | const seq = await new FirehoseSequencer(corestore.get({ name: 'firehose:' + did })).ready() |
| 48 | for await (const { bytes } of seq.subscribe(0)) { /* signed #commit frames */ } |
| 49 | ``` |
| 50 | |
| 51 | ## Design notes |
| 52 | |
| 53 | - **Storage vs. serialization.** RepoStore holds the *logical* record set; the signed |
| 54 | MST/commit bytes are produced by [`atproto-repo`](../atproto-repo) at read/sign time. |
| 55 | - **Keyless read path.** `read-view` rebuilds a signed CAR from replicated records + the |
| 56 | firehose's signed commit — the signature travels in the firehose, never re-minted. This |
| 57 | is what lets [`atproto-bridge`](../atproto-bridge) front a peer without its key. |
| 58 | - Bare-native (bare-fs/os/path); the whole stack runs under Bare. |
| 59 | |
| 60 | ## Test |
| 61 | |
| 62 | ``` |
| 63 | bare test/all.js # or: npm test |
| 64 | ``` |