OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-note commits / 979ebc4

Refactor README: move architecture, security, API table to docs/
README cut from 444 to 64 lines. Detailed content (architecture diagram, storage layout, auth model, security audit notes, project structure, full API table) moved to docs/architecture.md. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
979ebc46d0a86408a051797b6633edd91d7ada1c
by plankatron <fleeky@gmail.com> · 2026-03-18T14:50:10.000Z

Changed files (2) +201 -367

README.md +25 -367
……@@ -1,329 +1,58 @@
11# Hypernote
22
3P2P note-taking server with per-notebook Hyperdrives, end-to-end encryption, wiki-links, and a built-in WYSIWYG editor.
3P2P note-taking server with per-notebook Hyperdrives, end-to-end encryption, wiki-links, and multi-writer collaboration.
44
5Built on the [Holepunch](https://holepunch.to) stack: Hypercore, Hyperdrive, Hyperbee, and Hyperswarm.
5Built on [Holepunch](https://holepunch.to): Hypercore, Hyperdrive, Hyperbee, Hyperswarm, Autobase.
66
77## Features
88
9- **Per-notebook Hyperdrives** -- each notebook is an isolated Hyperdrive that can be selectively shared and replicated
10- **P2P replication** -- announce notebooks on Hyperswarm for real-time peer-to-peer sync
11- **Hyper:// site publishing** -- auto-publishes a read/write site drive accessible via [Agregore](https://agregore.mauve.moe/) browser
12- **End-to-end encryption** -- per-notebook encryption with Argon2id key derivation and XSalsa20-Poly1305
13- **Ed25519 identity** -- passwordless auth via auto-generated browser keypairs with challenge-response signing
14- **Wiki-links & backlinks** -- `[[Note Title]]` syntax with automatic backlink indexing and knowledge graph
15- **WYSIWYG editor** -- Toast UI Editor with markdown, image upload, and video support
16- **Media upload** -- images, video, and audio stored directly in notebook Hyperdrives
17- **Public sharing** -- `/:username/:notebook/:noteId` URLs for shared notebooks
18- **Note merge & split** -- combine notes or split at heading boundaries
19- **Full-text search** -- search across all notebooks with context snippets
20- **Zero CDN dependencies** -- all assets served locally (works offline and in hyper://)
21- **CLI + Web UI + REST API** -- three ways to interact
22
23## Install
24
25### From pear-git (P2P)
26
27```bash
28# 1. Install pear-git (if you don't have pgh)
29npm install -g pear
30pear dump pear://dpjhhzqgm6wqxc9nmw1y3m7eaptfufr6o5p7r4xegjghju8mkweo ~/.local/share/pear-git
31cat > ~/.local/bin/pgh << 'EOF'
32#!/bin/sh
33exec bare ~/.local/share/pear-git/index.js pgh "$@"
34EOF
35chmod +x ~/.local/bin/pgh
36
37# 2. Clone hypernote
38pgh repo clone punch://1290678432f9573b463d4472a9426c5408b34579bf8576e26957a1321fd5e836/hyper-note
39
40# 3. Install and run
41cd hyper-note
42npm install
43bare hypernote-server.js serve
44```
45
46### From local checkout
47
48```bash
49git clone <repo-url> hyper-note
50cd hyper-note
51npm install
52bare hypernote-server.js serve
53```
54
55### As a Pear app (auto-updates)
56
57```bash
58pgh app install pear://p84snzmpxca3ii7nfdqjbd5wxjdqzccpoj9xjwzz96wpe4m557zo --name hypernote
59hypernote serve
60```
9- Per-notebook Hyperdrives with selective P2P replication
10- Multi-writer collaboration via Autobase + Yjs CRDTs
11- End-to-end encryption (Argon2id + XSalsa20-Poly1305)
12- Ed25519 browser identity with challenge-response auth
13- Wiki-links, backlinks, and knowledge graph
14- WYSIWYG editor (Toast UI), media upload, gallery
15- Hyper:// site publishing for Agregore browser
16- Zero CDN dependencies (works offline)
6117
6218## Quick Start
6319
6420```bash
65# Start server (localhost:4040)
21npm install
6622bare hypernote-server.js serve
6723
68# Start on LAN (accessible from other devices)
24# LAN accessible
6925bare hypernote-server.js serve 4040 --network
7026
71# Custom port, storage, and URL prefix
72bare hypernote-server.js serve 5555 --storage=/path/to/data --prefix=/hypernote
73
74# Promote a user to admin (CLI)
75bare hypernote-server.js promote <publicKey|username>
76```
77
78On first start, the server prints an admin bearer token to the console. Open `http://localhost:4040` in your browser -- an ed25519 identity is generated automatically and the first user is promoted to admin.
79
80### Reverse Proxy
81
82Use `--prefix` when running behind a reverse proxy:
83
84```bash
27# Behind reverse proxy
8528bare hypernote-server.js serve 4040 --network --prefix=/hypernote
8629```
8730
88Access at `http://yourhost/hypernote/`. The prefix is stripped from API routes automatically.
89
90### Agregore (hyper://)
31On first start, an admin token is printed to the console. Open `http://localhost:4040` -- an ed25519 identity is generated automatically and the first user is promoted to admin.
9132
92The server auto-publishes a site drive on Hyperswarm. Access via Agregore browser:
33## Install via pear-git
9334
35```bash
36pgh app install pear://p84snzmpxca3ii7nfdqjbd5wxjdqzccpoj9xjwzz96wpe4m557zo --name hypernote
37hypernote serve
9438```
95hyper://SITE_KEY/
96```
97
98The site key is shown in the server logs and available at `GET /api/site`. When accessed via `hyper://`, the app connects back to the local HTTP server for full read/write access (not read-only).
9939
10040## CLI
10141
10242```bash
103# Notebooks
10443hn notebook list
10544hn notebook create "Work Notes"
106hn notebook delete work-notes
107hn notebook rename work-notes new-slug
108
109# Notes
110hn note list work-notes
11145hn note create work-notes --title "Meeting" --content "# Agenda\n..."
112hn note get work-notes <noteId>
113hn note update work-notes <noteId> --title "Updated"
114hn note delete work-notes <noteId>
115hn note move work-notes <noteId> --to personal
116
117# Search
118hn search "query" --notebook work-notes
119
120# Encryption
121hn share encrypt work-notes --password secret
122hn share decrypt work-notes --password secret
123hn share unlock work-notes --password secret
124
125# Links
126hn links work-notes <noteId>
127
128# P2P Sync
46hn search "query"
12947hn sync status
130hn sync announce work-notes
131hn sync add <driveKey> --slug remote-notes
132hn sync remove remote-notes
133```
134
135Configure the CLI:
136
137```bash
138# Stored in ~/.config/hypernote/cli.json
139hn config set server http://localhost:4040
140hn config set token <bearer-token>
141```
142
143## Architecture
144
145```
146Browser (SPA) Server (Bare runtime)
147 identity.js AuthManager
148 ed25519 keypair WebIdentityProvider
149 challenge signing BearerTokenProvider
150 fetch interception KeetIdentityProvider
151 api.js NoteManager
152 HTTP client per-notebook CRUD
153 hyper:// dual-mode DriveManager
154 app.js Hyperdrive lifecycle
155 hash router ReplicationManager
156 Toast UI Editor Hyperswarm P2P sync
157 IdentityRegistry
158 user accounts + permissions
159 LinkManager
160 wiki-links + backlinks
161 NotebookCrypto
162 per-notebook encryption
163 SitePublisher
164 hyper:// site drive
165```
166
167### Storage Layout
168
169```
170~/.config/hypernote/
171 storage-locator.json # breadcrumb to find storage
172 server-data/
173 server-identity.json # device ed25519 keypair
174 device-mnemonic.enc # encrypted BIP39 mnemonic vault
175 corestore/
176 registry/ # Hyperbee (users, tokens, metadata)
177 notebook-general/ # Hyperdrive for "general" notebook
178 notebook-work/ # Hyperdrive for "work" notebook
179 site-public/ # Hyperdrive for hyper:// site
180 ...
181```
182
183Each notebook Hyperdrive contains:
184
185```
186/metadata.json # notebook name, description, flags
187/notes/{noteId}.json # individual notes (title, content, tags)
188/media/{filename} # uploaded images, video, audio
18948```
19049
191### Authentication
192
193Three auth methods, tried in order:
194
1951. **Web Identity** -- browser generates ed25519 keypair **client-side** using @noble/ed25519 (loaded locally, no CDN). Signs server challenges. Compatible with wirecore/wiredove ANProto format. Headers: `X-Wirecore-PublicKey`, `X-Wirecore-Signature`, `X-Wirecore-Challenge`
1962. **Bearer Token** -- `Authorization: Bearer <token>` for CLI and API clients
1973. **Keet Identity** -- BIP39 mnemonic-based, for cross-device portability
198
199### P2P Replication
200
201Each notebook is a Hyperdrive. To share:
202
2031. **Announce** a notebook on Hyperswarm (`POST /api/notebooks/:slug/announce`)
2042. Peers discover it via the discovery key
2053. Remote peers add it by drive key (`POST /api/sync/add`)
2064. Hyperdrive handles incremental replication automatically
207
208Only announced notebooks are discoverable. The registry (users, tokens, permissions) is never replicated.
209
210### Multi-Writer / Device Linking
211
212Hypernote supports linking multiple instances via [Autobase](https://github.com/holepunchto/autobase) for multi-device and multi-user collaboration.
213
214**How it works:**
2151. An admin on instance A creates a link invite (`POST /api/multiwriter/link`) and gets an invite hex
2162. An admin on instance B joins with that invite (`POST /api/multiwriter/join`)
2173. Both instances share a replicated registry (users, permissions) via Autobase
2184. Mirror sync copies notebooks between instances in the background
219
220**Key endpoints:**
221- `GET /api/multiwriter/status` -- check linking state and peers
222- `POST /api/multiwriter/link` / `POST /api/multiwriter/join` -- instance linking
223- `POST /api/multiwriter/sync` -- trigger manual mirror sync
224- `POST /api/multiwriter/mirror` -- start/stop background mirror sync
225- `POST /api/notebooks/:nb/share` -- toggle Autobase sharing on a notebook
226- Shared notebooks get their own CRDT-based note endpoints (`/shared-notes`, Yjs updates)
227
228See [docs/api.md](docs/api.md) for the complete multiwriter API reference.
229
230### Site Publisher
231
232The server automatically publishes a Hyperdrive containing:
233- All web UI files (`/index.html`, `/web/*`)
234- Notebook data as static JSON (`/api/notebooks.json`, `/api/notebooks/:slug/*`)
235- Media files (`/api/media/:slug/*`)
236- Recent notes feed (`/api/recent.json`)
237
238The site drive is announced on Hyperswarm and accessible via `hyper://SITE_KEY/` in Agregore. When the app detects hyper:// protocol, it routes API calls to the configured local HTTP server for full read/write access.
239
240## API
241
242See [docs/api.md](docs/api.md) for the complete REST API reference.
243
244### Quick Reference
245
246| Method | Endpoint | Description |
247|--------|----------|-------------|
248| GET | `/api/health` | Server health check |
249| GET | `/api/status` | Server status + identity + site key |
250| GET | `/api/whoami` | Current user info |
251| GET | `/api/site` | Site drive key + hyper:// URL |
252| POST | `/api/site/publish` | Force republish site (admin) |
253| GET | `/api/recent` | Recent notes feed |
254| GET | `/api/notebooks` | List notebooks (?mine=true, ?owner=) |
255| POST | `/api/notebooks` | Create notebook |
256| GET | `/api/notebooks/:nb` | Get notebook metadata |
257| PATCH | `/api/notebooks/:nb` | Update notebook |
258| DELETE | `/api/notebooks/:nb` | Delete notebook |
259| POST | `/api/notebooks/:nb/rename` | Rename notebook slug |
260| GET | `/api/notebooks/:nb/notes` | List notes (?limit, ?offset) |
261| POST | `/api/notebooks/:nb/notes` | Create note |
262| GET | `/api/notebooks/:nb/notes/:id` | Get note |
263| PATCH | `/api/notebooks/:nb/notes/:id` | Update note |
264| DELETE | `/api/notebooks/:nb/notes/:id` | Delete note |
265| POST | `/api/notebooks/:nb/notes/:id/move` | Move note to another notebook |
266| POST | `/api/notebooks/:nb/media` | Upload media |
267| GET | `/api/notebooks/:nb/media/:file` | Serve media file (no auth) |
268| GET | `/api/search?q=term` | Full-text search |
269| POST | `/api/notebooks/:nb/encrypt` | Encrypt notebook |
270| POST | `/api/notebooks/:nb/decrypt` | Decrypt notebook |
271| POST | `/api/notebooks/:nb/unlock` | Unlock encrypted notebook |
272| POST | `/api/notebooks/:nb/share` | Share notebook (token or multiwriter) |
273| GET | `/api/notebooks/:nb/shares` | List share tokens (admin) |
274| DELETE | `/api/notebooks/:nb/shares/:hash` | Revoke share token (admin) |
275| GET | `/api/notebooks/:nb/notes/:id/links` | Get outgoing wiki-links |
276| GET | `/api/notebooks/:nb/notes/:id/backlinks` | Get backlinks |
277| GET | `/api/graph` | Knowledge graph (?notebook=) |
278| POST | `/api/notebooks/:nb/merge` | Merge two notes |
279| POST | `/api/notebooks/:nb/notes/:id/split` | Split note at headings |
280| POST | `/api/notebooks/:nb/announce` | Announce on Hyperswarm |
281| POST | `/api/notebooks/:nb/unannounce` | Stop announcing |
282| GET | `/api/notebooks/:nb/drive-info` | Hyperdrive info |
283| GET | `/api/sync/status` | P2P sync status |
284| POST | `/api/sync/add` | Add remote notebook |
285| DELETE | `/api/sync/remote/:nb` | Remove remote notebook |
286| POST | `/api/auth/challenge` | Get signing challenge |
287| GET | `/api/user/profile` | Get user profile |
288| PATCH | `/api/user/profile` | Update display name/theme |
289| POST | `/api/user/username` | Set username |
290| GET | `/api/user/username/:u/available` | Check username availability |
291| GET | `/api/users` | Public user directory |
292| GET | `/api/admin/users` | List all users (admin) |
293| DELETE | `/api/admin/users/:id` | Delete user (admin) |
294| GET | `/api/admin/stats` | Server stats (admin) |
295| POST | `/api/admin/promote` | Promote user (admin) |
296| POST | `/api/admin/demote` | Demote user (admin) |
297| POST | `/api/admin/notebooks/:nb/transfer` | Transfer ownership (admin) |
298| GET | `/api/multiwriter/status` | Multi-writer status (admin) |
299| POST | `/api/multiwriter/link` | Create link invite (admin) |
300| POST | `/api/multiwriter/join` | Join with invite (admin) |
301| POST | `/api/multiwriter/add-writer` | Add writer key (admin) |
302| POST | `/api/multiwriter/sync` | Trigger mirror sync (admin) |
303| POST | `/api/multiwriter/mirror` | Start/stop mirror (admin) |
304| GET | `/api/notebooks/:nb/shared-notes` | List shared notes |
305| POST | `/api/notebooks/:nb/shared-notes` | Create shared note |
306| POST | `/api/notebooks/:nb/shared-notes/:id/yjs` | Apply Yjs update |
307| GET | `/api/notebooks/:nb/shared-notes/:id/content` | Get shared note content |
308| GET | `/api/debug/identity-chain` | Identity chain (localhost) |
50Configure: `hn config set server http://localhost:4040`
30951
31052## Deployment
31153
312### pear-git CI/CD
313
314Hypernote deploys automatically via pear-git:
315
31654```bash
317git push pear master # triggers auto-deploy
318pgh deploy log hyper-note # check deploy status
319```
320
321The CI pipeline (`.pear-git/ci.yaml`) installs dependencies, then pear-git runs `pear stage` -> `pear release` -> `pear seed`.
322
323### Manual
324
325```bash
326bare hypernote-server.js serve 4040 --network
55git push pear master # triggers auto-deploy via pear-git CI/CD
32756```
32857
32958For production, run in tmux or as a systemd service.
……@@ -331,84 +60,13 @@ For production, run in tmux or as a systemd service.
33160## Testing
33261
33362```bash
334# Run all tests (150+ assertions)
335npm test
336
337# Run specific test
338bare node_modules/.bin/brittle test/unit/note-manager.test.js
63npm test # 150+ assertions across 17 test files
33964```
34065
341Test coverage: identity, auth, notebooks, notes, encryption, sharing, links, merge/split, replication, rate limiting, storage, CLI config, web routes.
342
343## Project Structure
66## Documentation
34467
345```
346hypernote/
347 hypernote-server.js # server entry point
348 package.json
349 bin/hn # CLI entry point
350 .pear-git/ci.yaml # pear-git CI config
351 lib/
352 auth.js # AuthManager (multi-method)
353 note-manager.js # notebook + note CRUD
354 drive-manager.js # per-notebook Hyperdrive lifecycle
355 replication.js # Hyperswarm P2P sync
356 site-publisher.js # hyper:// site drive publisher
357 notebook-crypto.js # per-notebook encryption
358 link-manager.js # wiki-links + backlinks + graph
359 anproto.js # ANProto ed25519 signatures
360 storage-locator.js # storage breadcrumb system
361 errors.js # custom error classes
362 response.js # HTTP response helpers
363 multiwriter/
364 manager.js # multi-writer orchestration
365 instance-linker.js # invite-based instance linking
366 shared-registry.js # Autobase-backed shared user registry
367 registry-apply.js # registry operation application
368 auth/
369 base-provider.js # auth provider interface
370 bearer-token.js # bearer token auth
371 web-identity.js # browser ed25519 auth
372 keet-identity.js # BIP39 mnemonic auth
373 challenge-manager.js # challenge-response protocol
374 identity-registry.js # user + identity storage
375 rate-limiter.js # per-IP rate limiting
376 identity/
377 identity-manager.js # device keypair management
378 secure-storage.js # encrypted mnemonic vault
379 routes/
380 index.js # HTTP router
381 auth.js # identity + auth endpoints
382 notebooks.js # notebook + note + media endpoints
383 sharing.js # encryption + sharing endpoints
384 links.js # links + backlinks + graph endpoints
385 sync.js # P2P sync endpoints
386 multiwriter.js # instance linking + shared notebooks
387 web.js # static files + vendor + public URLs
388 cli/
389 client.js # HTTP client for CLI
390 config.js # CLI config file
391 output.js # CLI output formatting
392 commands/ # CLI subcommands
393 web/
394 index.html # SPA entry point
395 js/
396 app.js # main app + router + views
397 api.js # HTTP client (dual-mode: HTTP + hyper://)
398 identity.js # ed25519 auth + fetch interception
399 markdown.js # markdown rendering
400 css/
401 app.css # dark theme styles
402 vendor/
403 toastui-editor-all.min.js # Toast UI editor (local, no CDN)
404 toastui-editor.min.css # Toast UI styles (local, no CDN)
405 test/
406 unit/ # 17 test files (brittle)
407 helpers/
408 fixtures.js # test helpers
409 docs/
410 api.md # REST API reference
411```
68- [REST API Reference](docs/api.md) -- all 65+ endpoints
69- [Architecture](docs/architecture.md) -- system design, storage layout, auth, security model, project structure
41270
41371## License
41472
docs/architecture.md +176 -0
……@@ -0,0 +1,176 @@
1# Hypernote Architecture
2
3## System Overview
4
5```
6Browser (SPA) Server (Bare runtime)
7 identity.js AuthManager
8 ed25519 keypair WebIdentityProvider (challenge-response)
9 challenge signing BearerTokenProvider (CLI/API tokens)
10 fetch interception KeetIdentityProvider (BIP39)
11 api.js requireAuth helper (shared across routes)
12 HTTP client NoteManager
13 hyper:// dual-mode per-notebook CRUD
14 app.js encryption key cache (30m TTL)
15 hash router DriveManager
16 Toast UI Editor Hyperdrive lifecycle
17 ReplicationManager
18 Hyperswarm P2P sync (Set-based peer tracking)
19 MultiwriterManager
20 Autobase instance linking + mirror sync
21 identity sync mutex
22 callback token TTL (30m)
23 IdentityRegistry
24 user accounts + permissions
25 LinkManager
26 wiki-links + backlinks
27 NotebookCrypto
28 per-notebook encryption
29 SitePublisher
30 hyper:// site drive
31```
32
33## Storage Layout
34
35```
36~/.config/hypernote/
37 storage-locator.json # breadcrumb to find storage
38 server-data/
39 server-identity.json # device ed25519 keypair
40 device-mnemonic.enc # encrypted BIP39 mnemonic vault
41 corestore/
42 registry/ # Hyperbee (users, tokens, metadata)
43 notebook-general/ # Hyperdrive for "general" notebook
44 notebook-work/ # Hyperdrive for "work" notebook
45 site-public/ # Hyperdrive for hyper:// site
46 ...
47```
48
49Each notebook Hyperdrive contains:
50
51```
52/metadata.json # notebook name, description, flags
53/notes/{noteId}.json # individual notes (title, content, tags)
54/media/{filename} # uploaded images, video, audio
55```
56
57## Authentication
58
59Three auth methods, tried in order:
60
611. **Web Identity** -- browser generates ed25519 keypair **client-side** using @noble/ed25519 (loaded locally, no CDN). Signs server challenges. Compatible with wirecore/wiredove ANProto format. Headers: `X-Wirecore-PublicKey`, `X-Wirecore-Signature`, `X-Wirecore-Challenge`
622. **Bearer Token** -- `Authorization: Bearer <token>` for CLI and API clients
633. **Keet Identity** -- BIP39 mnemonic-based, for cross-device portability
64
65**Legacy/unsigned requests** -- if a known public key is presented without a valid challenge signature, the request is authenticated with `verified: false` and receives read-only permissions. New auto-registered identities start with read-only access; the first user is promoted to admin automatically.
66
67## P2P Replication
68
69Each notebook is a Hyperdrive. To share:
70
711. **Announce** a notebook on Hyperswarm (`POST /api/notebooks/:slug/announce`)
722. Peers discover it via the discovery key
733. Remote peers add it by drive key (`POST /api/sync/add`)
744. Hyperdrive handles incremental replication automatically
75
76Only announced notebooks are discoverable. The registry (users, tokens, permissions) is never replicated.
77
78## Multi-Writer / Device Linking
79
80Hypernote supports linking multiple instances via [Autobase](https://github.com/holepunchto/autobase) for multi-device and multi-user collaboration.
81
82**How it works:**
831. An admin on instance A creates a link invite (`POST /api/multiwriter/link`) and gets an invite hex
842. An admin on instance B joins with that invite (`POST /api/multiwriter/join`)
853. Both instances share a replicated registry (users, permissions) via Autobase
864. Mirror sync copies notebooks between instances in the background
87
88See [api.md](api.md) for the complete multiwriter API reference.
89
90## Site Publisher
91
92The server automatically publishes a Hyperdrive containing:
93- All web UI files (`/index.html`, `/web/*`)
94- Notebook data as static JSON (`/api/notebooks.json`, `/api/notebooks/:slug/*`)
95- Media files (`/api/media/:slug/*`)
96- Recent notes feed (`/api/recent.json`)
97
98The site drive is announced on Hyperswarm and accessible via `hyper://SITE_KEY/` in Agregore. When the app detects hyper:// protocol, it routes API calls to the configured local HTTP server for full read/write access.
99
100## Security Model
101
102- **Auth-gated endpoints** -- shared `requireAuth` helper enforces auth consistently across all route modules
103- **Legacy auth is read-only** -- unsigned sessions get `verified: false` and read-only permissions
104- **Sensitive diagnostics gated** -- `/api/whoami` full identity chain data is admin-only
105- **Encryption key TTL** -- cached keys expire after 30 minutes with auto-eviction
106- **Private notebook filtering** -- anonymous `GET /api/notebooks` hides private/encrypted notebooks
107- **Request timeout** -- HTTP requests time out after 120 seconds
108- **Media upload rate limiting** -- 50 uploads per minute per IP
109- **Search result caps** -- `maxResults` defaults to 100; `recentNotes` uses per-notebook caps
110- **Callback token TTL** -- multiwriter callback tokens expire after 30 minutes
111- **Notebook rename rollback** -- rolls back on failure
112- **Identity sync mutex** -- serialized to prevent race conditions
113- **Peer count correctness** -- Set-based tracking (no negative counts)
114- **DEBUG env var** -- sensitive logs only emitted when `DEBUG=1`
115
116## Project Structure
117
118```
119hypernote/
120 hypernote-server.js # server entry point
121 package.json
122 bin/hn # CLI entry point
123 .pear-git/ci.yaml # pear-git CI config
124 lib/
125 auth.js # AuthManager (multi-method)
126 note-manager.js # notebook + note CRUD
127 drive-manager.js # per-notebook Hyperdrive lifecycle
128 replication.js # Hyperswarm P2P sync
129 site-publisher.js # hyper:// site drive publisher
130 notebook-crypto.js # per-notebook encryption
131 link-manager.js # wiki-links + backlinks + graph
132 anproto.js # ANProto ed25519 signatures
133 storage-locator.js # storage breadcrumb system
134 errors.js # custom error classes
135 response.js # HTTP response helpers
136 multiwriter/
137 manager.js # multi-writer orchestration
138 instance-linker.js # invite-based instance linking
139 shared-registry.js # Autobase-backed shared user registry
140 registry-apply.js # registry operation application
141 auth/
142 base-provider.js # auth provider interface
143 bearer-token.js # bearer token auth
144 web-identity.js # browser ed25519 auth
145 keet-identity.js # BIP39 mnemonic auth
146 challenge-manager.js # challenge-response protocol
147 identity-registry.js # user + identity storage
148 rate-limiter.js # per-IP rate limiting
149 identity/
150 identity-manager.js # device keypair management
151 secure-storage.js # encrypted mnemonic vault
152 routes/
153 index.js # HTTP router
154 auth.js # identity + auth endpoints
155 auth-helpers.js # shared requireAuth helper
156 notebooks.js # notebook + note + media endpoints
157 sharing.js # encryption + sharing endpoints
158 links.js # links + backlinks + graph endpoints
159 sync.js # P2P sync endpoints
160 multiwriter.js # instance linking + shared notebooks
161 web.js # static files + vendor + public URLs
162 cli/
163 client.js # HTTP client for CLI
164 config.js # CLI config file
165 output.js # CLI output formatting
166 commands/ # CLI subcommands
167 web/
168 index.html # SPA entry point
169 js/ # app.js, api.js, identity.js, markdown.js
170 css/app.css # dark theme styles
171 vendor/ # Toast UI editor (local, no CDN)
172 test/unit/ # 17 test files (brittle)
173 docs/
174 api.md # REST API reference
175 architecture.md # this file
176```