MULTI_TENANT_ARCHITECTURE.md
1 # Multi-Tenant Architecture: Identity-Agnostic Node Core 2 3 > **Status**: Implementation Complete 4 > **Version**: 0.5 5 > **Date**: 2026-01-27 6 7 ## Overview 8 9 Refactor Abzu to separate **Machine Identity** (infrastructure) from **User Identity** (accounts). This enables household deployments, guest hosting, and node federation. 10 11 --- 12 13 ## Core Principle: Two Identity Types 14 15 ``` 16 ┌─────────────────────────────────────────────────────────────┐ 17 │ MACHINE IDENTITY (Infrastructure) │ 18 │ - Mesh address derivation │ 19 │ - DHT participation & routing │ 20 │ - Transport layer operations │ 21 │ - Persists with the node │ 22 ├─────────────────────────────────────────────────────────────┤ 23 │ USER IDENTITY (Accounts) │ 24 │ - Message signing & encryption │ 25 │ - Mailbox ownership │ 26 │ - Contact relationships │ 27 │ - Portable between nodes │ 28 └─────────────────────────────────────────────────────────────┘ 29 ``` 30 31 --- 32 33 ## Architecture 34 35 ### Layer Separation 36 37 ``` 38 ┌─────────────────────────────────────────────────────────────┐ 39 │ Federation Layer (future) │ 40 │ Mailbox blob replication between trusted nodes │ 41 ├─────────────────────────────────────────────────────────────┤ 42 │ Account Layer (NEW) │ 43 │ AccountManager: hosts N user identities, permission model │ 44 ├─────────────────────────────────────────────────────────────┤ 45 │ Node Layer (REFACTORED) │ 46 │ AbzuNode: machine_identity for routing/DHT │ 47 ├─────────────────────────────────────────────────────────────┤ 48 │ Transport Layer (unchanged) │ 49 │ FakeTLS, QUIC — uses ephemeral keys per connection │ 50 └─────────────────────────────────────────────────────────────┘ 51 ``` 52 53 ### Component Ownership 54 55 | Component | Current | New Owner | 56 |-----------|---------|-----------| 57 | Machine Keypair | `Node.identity` | `Node.machine_identity` | 58 | Mesh Address | Node | Node (derived from machine key) | 59 | Routing Table | Node | Node (shared infrastructure) | 60 | DHT Operations | Node | Node (signed by machine key) | 61 | User Keypair | N/A | Account | 62 | Message Signing | Node | Account | 63 | Mailbox | Node | Account (1 per account) | 64 | Contacts | Node | Account | 65 | Storage | Flat | Per-Account encrypted | 66 67 --- 68 69 ## Account Model 70 71 ### Account Types 72 73 ```rust 74 pub enum AccountType { 75 Admin, // Full control, can inspect Child accounts 76 Adult, // Equal authority, no inspection rights 77 Child, // Inspectable by Admin accounts 78 Guest, // Private, uses node as encrypted relay only 79 } 80 ``` 81 82 ### Account Structure 83 84 ```rust 85 pub struct Account { 86 pub id: AccountId, 87 pub keypair: Keypair, // User's Ed25519 identity 88 pub account_type: AccountType, 89 pub mailbox_id: DhtKey, // Derived from user pubkey 90 pub storage: AccountStorage, // Encrypted vault 91 } 92 93 pub struct AccountManager { 94 node: Arc<AbzuNode>, // Shared infrastructure 95 accounts: DashMap<AccountId, Account>, 96 } 97 ``` 98 99 ### Child Key Derivation (Security) 100 101 > [!IMPORTANT] 102 > Child private keys are NOT stored in plaintext for Admin inspection. 103 104 Options for parental oversight: 105 106 1. **Sub-key derivation**: Child key derived from Admin master key 107 2. **Dual encryption**: Messages encrypted to both Child and Admin pubkeys 108 3. **Capability escrow**: Child's read-capability encrypted to Admin 109 110 --- 111 112 ## Guest Model 113 114 > [!NOTE] 115 > True Guests hold their own keys on their own device. 116 117 **Guest ≠ Stored User**. A Guest uses the node as an **encrypted relay**: 118 119 - Guest's private key stays on their device (phone/laptop) 120 - Node only stores/forwards encrypted blobs 121 - Node cannot read Guest content 122 - Guest can switch to a different relay node anytime 123 124 If someone gives you their private key, they're not a Guest — they're a dependent User. 125 126 --- 127 128 ## Account Portability 129 130 Accounts are **mandatory portable**: 131 132 ```rust 133 struct AccountExport { 134 keypair: EncryptedKeypair, // Password-protected 135 mailbox_data: Vec<u8>, // Encrypted blob 136 contacts: Vec<u8>, // Encrypted blob 137 metadata: AccountMetadata, 138 } 139 140 impl Account { 141 fn export(&self, password: &str) -> AccountExport; 142 fn import(export: AccountExport, password: &str) -> Result<Account>; 143 } 144 ``` 145 146 User can export → move to any Abzu node → import. 147 148 --- 149 150 ## Refactor Plan 151 152 ### Phase 1: Identity Split ✅ COMPLETE 153 154 **Goal**: Split single identity into machine vs user within existing single-tenant code. 155 156 | Change | Description | 157 |--------|-------------| 158 | Renamed `Node.identity` → `Node.machine_identity` | Explicit naming | 159 | Added user identity tracking | Managed through AccountManager | 160 | Routing uses `machine_identity` | Infrastructure operations | 161 | Chat/signing uses account identity | User operations | 162 163 **Checkpoint**: All tests pass. Behavior unchanged. 164 165 ### Phase 2: AccountManager ✅ COMPLETE 166 167 **Goal**: Extract user_identity into Account struct. 168 169 | Component | Implementation | 170 |-----------|----------------| 171 | `Account` struct | Implemented in `abzu-account/` crate | 172 | `AccountStorage` | Per-account encrypted storage (planned) | 173 | `AccountManager` | Account CRUD with async API | 174 175 **Checkpoint**: Single account works. All tests pass. 176 177 ### Phase 3: Multi-Account + Permissions ✅ COMPLETE 178 179 **Goal**: Multiple accounts with permission model. 180 181 | Feature | Implementation | 182 |---------|----------------| 183 | Multiple accounts | N accounts per node via AccountManager | 184 | Account types | Admin, Adult, Child, Guest implemented | 185 | Permission model | Admin can delete Child, Guest is private | 186 | SDK integration | AbzuClient exposes all account methods | 187 188 **Checkpoint**: Admin can inspect Child. Guest is private. 205+ tests pass. 189 190 ### Phase 4: SDK Integration ✅ COMPLETE 191 192 **Goal**: High-level SDK exposes account management. 193 194 | Feature | Implementation | 195 |---------|----------------| 196 | AbzuClient account API | `create_account`, `list_accounts`, `delete_account`, `switch_account` | 197 | Current account tracking | `current_account`, `account_count` | 198 | FFI mapping | `SdkError::AccountError` → `AbzuError::AccountError` | 199 | Comprehensive tests | 11 new async tests for account management | 200 201 **Checkpoint**: Full account lifecycle via SDK. All workspace tests pass. 202 203 ### Phase 5: Federation (Future) 204 205 **Goal**: Mailbox replication between trusted nodes. 206 207 | Feature | Implementation | 208 |---------|----------------| 209 | Trusted node registry | Explicit peer list | 210 | Mailbox blob sync | Encrypted blobs only | 211 | Availability handoff | Partner serves blobs when primary offline | 212 | Account export/import | Password-protected portable identities | 213 214 --- 215 216 ## Verification Strategy 217 218 ### Git Worktrees (Not Shadow Repos) 219 220 Use git worktrees for comparative testing — not physical directory copies: 221 222 ```bash 223 # Before Phase 1 224 git tag v0.5.0-pre-multitenant 225 226 # Create worktree for comparison 227 git worktree add ../abzu-baseline v0.5.0-pre-multitenant 228 229 # After Phase 1, compare 230 cargo test --workspace # Current 231 cargo test --manifest-path ../abzu-baseline/Cargo.toml # Baseline 232 ``` 233 234 ### Rollback Tags 235 236 ```bash 237 git tag -a v0.5.0-pre-multitenant -m "Before multi-tenant refactor" 238 git tag -a v0.5.1-identity-split -m "Machine/User identity separated" 239 git tag -a v0.5.2-account-manager -m "AccountManager implemented" 240 git tag -a v0.5.3-multi-account -m "Multi-account + permissions" 241 ``` 242 243 ### Test Requirements 244 245 | Phase | Requirement | Status | 246 |-------|-------------|--------| 247 | Phase 1 | All tests pass, behavior identical | ✅ Complete | 248 | Phase 2 | Single account works, new Account tests | ✅ Complete | 249 | Phase 3 | Multi-account tests, permission tests | ✅ Complete | 250 | Phase 4 | SDK integration tests | ✅ Complete | 251 | Phase 5 | Federation sync tests | ⏳ Future | 252 253 --- 254 255 ## Rate Limiting 256 257 ### Tiered Model 258 259 | Level | Purpose | 260 |-------|---------| 261 | **Per-Account** | Prevent one user from monopolizing node resources | 262 | **Per-Node (Global)** | Protect node from mesh blacklisting | 263 264 --- 265 266 ## API Evolution 267 268 ### Before (Current) 269 270 ```rust 271 let node = AbzuNode::with_identity(keypair, config)?; 272 node.send_message(recipient, payload).await?; 273 ``` 274 275 ### After Phase 1 (Identity Split) 276 277 ```rust 278 let node = AbzuNode::new(config)?; // machine_identity auto-generated 279 // user_identity is internal, soon to become Account 280 node.send_message(recipient, payload).await?; 281 ``` 282 283 ### After Phase 3 (Multi-Account) 284 285 ```rust 286 let node = AbzuNode::new(config)?; 287 let admin = node.create_account(keypair1, AccountType::Admin)?; 288 let child = node.create_account(keypair2, AccountType::Child)?; 289 290 node.send_message(&admin, recipient, payload).await?; 291 ``` 292 293 --- 294 295 ## Open Questions (Resolved) 296 297 | Question | Resolution | 298 |----------|------------| 299 | Guest identity location? | **Client-side only** — node is encrypted relay | 300 | Federation scope? | **Mailbox blobs only** — not full node state | 301 | Account portability? | **Mandatory** — export/import supported | 302 | Rate limiting? | **Tiered** — per-account + per-node | 303 304 --- 305 306 ## Next Steps 307 308 - [x] Review and incorporate external feedback 309 - [x] Create `v0.5.0-pre-multitenant` tag 310 - [x] Phase 1: Identity split 311 - [x] Phase 2: AccountManager implementation 312 - [x] Phase 3: Multi-account + permissions 313 - [x] Phase 4: SDK integration 314 - [ ] Phase 5: Federation (future) 315 - [ ] Account export/import API 316 - [ ] Child key derivation refinement