OverviewFilesCommitsIssuesDocsReleasesPeers

atproto-identity commits / 2834abc

docs: add README
Package purpose, module map, API, usage, and its place in the atproto-base self-custody stack (atproto-repo → atproto-store → atproto-identity → hyper-proto-peer → atproto-bridge). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2834abc8752c9fa69d368768026ddfaa0cc9d5bf
by plankatron <fleeky@gmail.com> · 2026-07-05T21:46:46.000Z

Changed files (1) +67 -0

README.md +67 -0
……@@ -0,0 +1,67 @@
1# atproto-identity
2
3**Seed-anchored, self-custody AT Protocol identity.** One BIP-39 mnemonic derives both the
4Ed25519 key (Hypercore identity) and the secp256k1 key (`did:plc` signing) — so a user's
5atproto DID is rooted in a seed they alone hold, not a hosting PDS. Includes offline
6`did:plc` genesis + update building, did:key codec, session/service auth, device attestation,
7and swarm discovery.
8
9Part of the **atproto-base** self-custody stack:
10
11```
12atproto-repo serialization / codec
13atproto-store P2P repo storage + firehose
14atproto-identity ← you are here (identity + auth)
15hyper-proto-peer the self-custody peer (multi-device swarm PDS)
16atproto-bridge keyless membrane → Bluesky
17```
18
19## Modules
20
21- **Identity derivation** (`lib/atproto-identity.js`, main; `lib/binding.js`,
22 `lib/did-key.js`) — `deriveIdentity` (mnemonic → keys at `ATPROTO_SIGNING_PATH` /
23 `ATPROTO_RECOVERY_PATH`), `createAtprotoIdentity`, `deriveAtprotoKey`, `encodeDidKey` /
24 `decodeDidKey` (both curves, varint-multicodec).
25- **did:plc ops** (`lib/did-plc.js`) — `buildGenesisOp`, `buildUpdateOp`, `encodeOp`,
26 `didForCreateOp` (DID = `did:plc:` + base32(sha256(signed genesis))[:24]), `opCid`,
27 `checkGenesisOp` / `checkUpdateOp`. Full-state ops, low-S signatures — byte-exact vs a
28 real registered DID.
29- **PLC directory** (`lib/plc-directory.js`) — `PlcDirectory` client for the submit
30 ceremony (`GET /:did/log/last`, `POST /:did`).
31- **Auth** (`lib/auth.js`) — `hashPassword` / `verifyPassword` (scrypt), `signJwt` /
32 `verifyJwt` (HS256 session tokens), and **`signAssertion` / `verifyAssertion`** (ES256K —
33 atproto's inter-service / `getServiceAuth` token shape). `parseBearer`, scopes.
34- **Device attestation** (`lib/device-attestation.js`, `lib/device-chain.js`,
35 `lib/attested-anchor.js`) — attest additional device keys to one root identity
36 (`attestDeviceChain`, `buildAttestedAnchor`, `buildAttestedIdentity`) so N devices share
37 one DID. `rotateVerificationMethod` keeps the root's 72h PLC recovery authority.
38- **Discovery** (`lib/discovery.js`) — `discoveryTopic(did)` for Hyperswarm rendezvous.
39
40## Usage
41
42```js
43import { deriveIdentity, buildGenesisOp, didForCreateOp } from 'atproto-identity/lib/...'
44import { signAssertion, verifyAssertion } from 'atproto-identity/lib/auth.js'
45
46const id = await deriveIdentity(mnemonic, { handle, pdsUrl })
47const genesis = buildGenesisOp({ ...id, handle, pds })
48const did = didForCreateOp(genesis) // did:plc:...
49
50// service-auth (the token hyper-proto-peer mints for the bridge's AppView proxy):
51const jwt = signAssertion({ iss: did, aud: 'did:web:api.bsky.app', exp, lxm }, privKey)
52```
53
54## Design notes
55
56- **The offline half is proven** (genesis byte-exact vs a real `did:plc`; golden test). The
57 live submit ceremony (`POST /:did` head-chaining, tombstone, recovery) is being wired via
58 `PlcDirectory` — see the `did-plc` reference skill for the full op contract.
59- **Self-custody, not custodial.** The peer holds its own rotation key and submits PLC ops
60 directly to the directory — it never delegates signing to a hosting PDS.
61- Pure JS crypto (`@noble`), Bare-safe.
62
63## Test
64
65```
66bare test/all.js # or: npm test (incl. golden-did-plc byte-exactness)
67```