When EncryptID server returns plain text errors (e.g. "Internal Server
Error"), the client's .json() calls threw SyntaxError which surfaced
as an ugly parse error to users. Add .catch() to all unsafe .json()
calls in session.ts, login-button.ts, and recovery.ts so auth
gracefully falls back to unsigned tokens instead.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- login-button.ts: no-known-accounts state shows passkey-first button
(unscoped WebAuthn) with email magic link fallback, auto-revealed on
NotAllowedError. Fix stale usernameInput ref.
- server.ts (auth.rspace.online): add localStorage known accounts system.
Returning users see their stored usernames as clickable buttons.
handleAuth() accepts optional username for scoped auth. Saves account
after successful login. renderSigninAccounts() called on page init.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When no known accounts exist in localStorage, show a username/email
input field instead of immediately triggering the unscoped passkey
picker. User types their username, then gets a scoped passkey prompt
for only that account's credentials.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Logout no longer removes the account from the picker — users see
"Sign in as [username]" on next visit. fetchScopedCredentials now
returns full PublicKeyCredentialDescriptor with transports so the
browser can locate the right authenticator without showing a picker.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Scoped passkey prompts via /api/auth/start so the browser only shows
matching credentials for the selected account. Known accounts stored
in localStorage and surfaced as a picker (1 account = named button,
multiple = list). "Use a different account" falls back to unscoped.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a user logs out in one browser, all other sessions are now revoked
on their next page load or token refresh. Adds logged_out_at column to
users table, server-side revocation checks on verify/refresh endpoints,
and a new /api/session/logout endpoint.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wallets stored in local WalletStore are now bidirectionally synced with
the encrypted AccountVault on the server. On login, vault wallets are
restored to the local store; on wallet changes, local state is pushed
back to the vault. The server user profile wallet_address is also set
on login so mobile devices (without PRF) get the address via JWT.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Zero-knowledge vault stores account data (profile, emails, devices,
wallets, preferences) as AES-256-GCM encrypted blob via backup API.
Key derived from WebAuthn PRF — server never sees plaintext. Dashboard
UI with save/restore buttons triggers passkey re-auth for encryption.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 5 — EncryptID → DocCrypto bridge:
- Add EncryptedDocBridge connecting WebAuthn PRF to document encryption
- Add per-doc relay mode to SyncServer (encrypted spaces bypass participant mode)
- Wire encryption toggle to syncServer.setRelayOnly() on PATCH /:slug/encryption
- Restore relay mode for encrypted spaces on server startup
- Initialize DocBridge from PRF on login, clear on sign-out (both login-button + identity)
- Use bridge helpers for encrypted backup toggle in My Account
Phase 6 — Space scoping UI:
- Add "Modules" tab to Edit Space modal (enable/disable modules, scope toggles, encryption)
- Auto-filter app switcher by space's enabledModules via renderShell()
- Show "G" badge on global-scoped modules in app switcher
- Show lock icon in header for encrypted spaces
- Add getSpaceShellMeta() helper for auto-populating shell options
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements the EncryptID identity system for the r-ecosystem:
- WebAuthn/Passkey authentication with PRF extension for key derivation
- Client-side cryptographic key derivation (AES-256, ECDSA P-256, Ed25519)
- Social recovery system with guardians (no seed phrases!)
- Session management with authentication levels
- Cross-app SSO via Related Origin Requests
- Web components: login button and guardian setup panel
- Hono server for authentication endpoints
- Docker deployment configuration
Domain: encryptid.jeffemmett.com
RP ID: jeffemmett.com (for cross-subdomain passkey usage)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>