Skip to content

Commit d1f91a3

Browse files
j-patersonclaude
andauthored
Add comprehensive documentation for private spaces (homebase) (#1743)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent ba88963 commit d1f91a3

File tree

2 files changed

+251
-1
lines changed

2 files changed

+251
-1
lines changed

docs/SYSTEMS/SPACES/OVERVIEW.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,25 @@ Spaces are the pages that make up a community's presence on Blankspace. Each com
66

77
### Homebase (Private)
88

9-
Every community member gets their own private homebase - a personal dashboard they can customize.
9+
Every community member gets their own private homebase - a personal dashboard they can customize. Homebase data is **end-to-end encrypted** and tied to the user's space identity, not the community.
1010

1111
**URL:** `/homebase`
1212

1313
**Who can edit:** Only the owner (encrypted, private)
1414

15+
**Key properties:**
16+
- Encrypted with XChaCha20-Poly1305
17+
- Signed with Ed25519
18+
- Tied to identity, not community (follows user across communities)
19+
- Multiple identities = multiple separate homebases
20+
1521
**Use cases:**
1622
- Personal feed dashboard
1723
- Bookmarked communities and tokens
1824
- Private notes and links
1925

26+
See [Private Spaces](PRIVATE_SPACES.md) for detailed architecture, encryption, and cross-community behavior.
27+
2028
---
2129

2230
### Profile Spaces
@@ -142,6 +150,7 @@ Changes are saved to the server and visible to all visitors.
142150

143151
## Related Documentation
144152

153+
- [Private Spaces](PRIVATE_SPACES.md) - Homebase encryption and cross-community behavior
145154
- [Space Architecture](SPACE_ARCHITECTURE.md) - Technical implementation details
146155
- [Public Spaces Pattern](PUBLIC_SPACES_PATTERN.md) - Server/client data flow
147156
- [Multiple Layouts](MULTIPLE_LAYOUTS_OVERVIEW.md) - Desktop and mobile layouts
Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
# Private Spaces (Homebase)
2+
3+
This document describes the architecture of private spaces (homebase) including storage, encryption, identity management, and cross-community behavior.
4+
5+
## Overview
6+
7+
Every user has a **homebase** - a private, encrypted dashboard they can customize with fidgets and tabs. Unlike public spaces, homebase data is:
8+
9+
- **Encrypted** using XChaCha20-Poly1305
10+
- **Signed** using Ed25519
11+
- **Identity-scoped** - tied to a user's space identity, not a community
12+
13+
## Storage Architecture
14+
15+
### Location
16+
17+
Homebase data is stored in Supabase's private storage bucket:
18+
19+
```
20+
{identityPublicKey}/
21+
├── homebase # Main homebase config (layout, theme)
22+
├── homebaseTabOrder # Tab ordering
23+
└── tabs/
24+
├── {tabName1} # Individual tab configs
25+
├── {tabName2}
26+
└── ...
27+
```
28+
29+
### File Format (SignedFile)
30+
31+
All homebase files are stored as `SignedFile` objects:
32+
33+
```typescript
34+
interface SignedFile {
35+
publicKey: string; // Identity public key (who encrypted it)
36+
fileData: string; // Hex-encoded encrypted bytes
37+
fileType: string; // "json"
38+
isEncrypted: boolean; // true
39+
timestamp: string; // ISO timestamp
40+
fileName?: string; // Tab name (for tab files)
41+
signature: string; // Ed25519 signature over the content
42+
}
43+
```
44+
45+
## Identity Model
46+
47+
### Space Identities
48+
49+
Each user wallet can have **multiple space identities**. An identity consists of:
50+
51+
```typescript
52+
interface SpaceIdentity {
53+
rootKeys: {
54+
publicKey: string; // Ed25519 public key (hex)
55+
privateKey: string; // Ed25519 private key (hex)
56+
type: "root";
57+
salt: string; // 32-byte random nonce
58+
};
59+
preKeys: PreSpaceKeys[]; // Ephemeral encryption keys
60+
associatedFids: number[]; // Linked Farcaster IDs
61+
}
62+
```
63+
64+
### Identity Isolation
65+
66+
```
67+
User Wallet
68+
└── Identity A (publicKey: 0xabc...)
69+
│ └── Homebase A
70+
│ ├── Tab: Feed
71+
│ ├── Tab: Bookmarks
72+
│ └── Tab: Notes
73+
74+
└── Identity B (publicKey: 0xdef...)
75+
└── Homebase B (completely separate)
76+
├── Tab: Dashboard
77+
└── Tab: Tokens
78+
```
79+
80+
Each identity has its own:
81+
- Root keys (for signing and encryption)
82+
- Pre-keys (ephemeral, rotatable)
83+
- Homebase configuration
84+
- Tab layouts and fidget settings
85+
86+
## Encryption System
87+
88+
### Algorithm
89+
90+
- **Cipher**: XChaCha20-Poly1305 (symmetric AEAD)
91+
- **Key Derivation**: HKDF with SHA256
92+
- **Signing**: Ed25519
93+
- **Hashing**: BLAKE3
94+
95+
### Key Derivation
96+
97+
Encryption keys are derived from the identity's private key:
98+
99+
```typescript
100+
function stringToCipherKey(privateKey: string): Uint8Array {
101+
return hkdf(sha256, privateKey, "salt", "", 32);
102+
}
103+
```
104+
105+
### Two Key Types
106+
107+
1. **Root Keys** - Long-lived identity keys
108+
- Used for: Main homebase config, tab ordering
109+
- Storage: `{identityPublicKey}/keys/root/{walletAddress}` (encrypted per-wallet)
110+
111+
2. **Pre-Keys** - Ephemeral keys
112+
- Used for: Individual tab configs
113+
- Storage: `{identityPublicKey}/keys/pre/`
114+
- Can be rotated periodically for forward secrecy
115+
116+
### Encryption Flow
117+
118+
```
119+
1. User saves homebase
120+
121+
2. Data serialized to JSON
122+
123+
3. Key derived: HKDF(SHA256, privateKey) → 32-byte key
124+
125+
4. Encrypted: XChaCha20-Poly1305(key, data)
126+
127+
5. Signed: Ed25519.sign(BLAKE3(content), privateKey)
128+
129+
6. Uploaded as SignedFile to Supabase
130+
```
131+
132+
### Decryption Flow
133+
134+
```
135+
1. Fetch SignedFile from Supabase
136+
137+
2. Verify signature: Ed25519.verify(signature, BLAKE3(content), publicKey)
138+
139+
3. Lookup key: rootKeys or preKeys based on encryptingKey
140+
141+
4. Decrypt: XChaCha20-Poly1305(key, encryptedData)
142+
143+
5. Parse JSON, validate timestamps
144+
```
145+
146+
## Cross-Community Behavior
147+
148+
### Key Principle: Identity-Scoped, Not Community-Scoped
149+
150+
Homebase is tied to an **identity**, not a **community**. This has important implications:
151+
152+
| Scenario | Behavior |
153+
|----------|----------|
154+
| Same identity on Community A and B | **Same homebase** - customizations follow the user |
155+
| Different identity on Community A and B | **Different homebases** - completely isolated |
156+
| Switch identities within a community | **Switches homebase** - loads the new identity's config |
157+
158+
### Why This Matters
159+
160+
1. **Privacy**: Communities cannot access each other's user homebases
161+
2. **Portability**: A user's homebase follows their identity across communities
162+
3. **Isolation**: Multiple identities allow complete separation when desired
163+
4. **No Cross-Access**: Even with the same user, different identities are cryptographically separate
164+
165+
### Storage Path Independence
166+
167+
The storage path `{identityPublicKey}/homebase` contains no community identifier:
168+
169+
```
170+
// Identity A's homebase - same path regardless of which community loads it
171+
0xabc123.../homebase
172+
0xabc123.../tabs/Feed
173+
0xabc123.../tabs/Bookmarks
174+
175+
// Identity B's homebase - completely separate tree
176+
0xdef456.../homebase
177+
0xdef456.../tabs/Dashboard
178+
```
179+
180+
## Security Properties
181+
182+
### What's Protected
183+
184+
| Property | Protection |
185+
|----------|------------|
186+
| Homebase content | Encrypted at rest (XChaCha20-Poly1305) |
187+
| Data integrity | Signed (Ed25519 over BLAKE3 hash) |
188+
| Authenticity | Signature verified before storage |
189+
| Forward secrecy | Pre-keys can be rotated |
190+
191+
### What Communities Can See
192+
193+
- The **existence** of a homebase (storage path)
194+
- The **public key** of the identity
195+
- The **encrypted blob** (unreadable without private key)
196+
- The **timestamp** of last modification
197+
198+
### What Communities Cannot See
199+
200+
- Homebase content (fidgets, layouts, tabs)
201+
- Tab names or structure
202+
- Any decrypted data
203+
- Private keys
204+
205+
## API Endpoints
206+
207+
### Save Homebase
208+
209+
```
210+
POST /api/space/homebase
211+
Body: SignedFile (encrypted homebase config)
212+
```
213+
214+
### Load Homebase
215+
216+
```
217+
GET Supabase.storage.from("private").getPublicUrl("{identityKey}/homebase")
218+
```
219+
220+
### Manage Tabs
221+
222+
```
223+
POST /api/space/homebase/tabs
224+
Body: { type: "create" | "delete", ...SignedFile }
225+
```
226+
227+
## Cryptographic Libraries
228+
229+
| Library | Purpose |
230+
|---------|---------|
231+
| `@noble/curves/ed25519` | Ed25519 signing/verification |
232+
| `@noble/ciphers/chacha` | XChaCha20-Poly1305 encryption |
233+
| `@noble/hashes/blake3` | BLAKE3 hashing |
234+
| `@noble/hashes/hkdf` | HKDF key derivation |
235+
| `@noble/hashes/sha256` | SHA256 for HKDF |
236+
237+
## Related Documentation
238+
239+
- [Spaces Overview](OVERVIEW.md) - All space types
240+
- [Space Architecture](SPACE_ARCHITECTURE.md) - Technical implementation
241+
- [State Management](../../ARCHITECTURE/STATE_MANAGEMENT.md) - Store architecture

0 commit comments

Comments
 (0)