feat: add TOTP 2FA, API key switcher, login progress bar, and alpha hardening plan

- TOTP 2FA: full setup/confirm/disable/login flow with Argon2id + ChaCha20-Poly1305
  encrypted secret storage, QR code generation, and bcrypt-hashed backup codes
- API key switcher: OAuth vs personal API key toggle in AIUI chat settings with
  status indicator, key validation, and help text
- Login progress bar: server startup detection with health check polling, form
  disabled until server is ready
- AI quarantine docs: comprehensive HTML page documenting all 6 security layers
- Settings: AI Data Access permission toggles with per-category control
- Alpha hardening plan: 28-task overnight automation plan across 7 phases
  (onboarding, login, app install, AIUI, UI polish, security, ISO build)
- Backlog: node discovery spatial map feature for alpha demo

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-06 12:23:57 +00:00
parent 0b3c23ff76
commit e55fd3baf0
16 changed files with 2402 additions and 152 deletions

View File

@@ -87,18 +87,47 @@ class RPCClient {
}
// Convenience methods
async login(password: string): Promise<void> {
async login(password: string): Promise<{ requires_totp?: boolean } | null> {
return this.call({
method: 'auth.login',
params: {
password,
metadata: {
// Add any metadata needed
},
},
})
}
async loginTotp(code: string): Promise<{ success: boolean }> {
return this.call({ method: 'auth.login.totp', params: { code } })
}
async loginBackup(code: string): Promise<{ success: boolean }> {
return this.call({ method: 'auth.login.backup', params: { code } })
}
async totpSetupBegin(password: string): Promise<{
qr_svg: string
secret_base32: string
pending_token: string
}> {
return this.call({ method: 'auth.totp.setup.begin', params: { password } })
}
async totpSetupConfirm(params: {
code: string
password: string
pendingToken: string
}): Promise<{ enabled: boolean; backup_codes: string[] }> {
return this.call({ method: 'auth.totp.setup.confirm', params })
}
async totpDisable(password: string, code: string): Promise<{ disabled: boolean }> {
return this.call({ method: 'auth.totp.disable', params: { password, code } })
}
async totpStatus(): Promise<{ enabled: boolean }> {
return this.call({ method: 'auth.totp.status', params: {} })
}
async changePassword(params: {
currentPassword: string
newPassword: string