Commit Graph

21 Commits

Author SHA1 Message Date
RevIQ
0e6a028ef0 Add missing hasPassword property to user responses
The API contract requires hasPassword in user responses but it was
missing from toUserResponse helper and meAuthStatus handler.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 18:31:31 +08:00
RevIQ
d4e20d41b5 Merge branch 'cli-improvements-1' with @reviq/utils password hashing
- Use executeBootstrap helper from @reviq/db for CLI bootstrap
- Update @reviq/db to use @reviq/utils for PBKDF2-SHA256 password hashing
  (Cloudflare Workers compatible)
- Keep @scure/base for base58 token encoding
- Remove redundant password.ts from @reviq/db (import directly from @reviq/utils)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 18:17:45 +08:00
RevIQ
cfe26c8820 Merge branch 'workstream-i' 2026-01-09 18:12:45 +08:00
RevIQ
1083cde9b7 Implement Workstream I: Account pages with code review fixes
Add account management UI with profile settings, authentication options,
device/passkey management, and session management pages.

Key changes:
- Add account pages: profile, auth, devices, sessions
- Add dialog components: confirm, add-passkey, change-password, rename-passkey
- Return passkeyId from verifyRegistration to fix race condition
- Add hasPassword field to user schema
- Add aria-label to dialog close button for accessibility
- Add avatar URL validation and fix phone input styling
- Add comprehensive test plan documentation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 18:04:02 +08:00
RevIQ
77e6754427 Merge branch 'master' into cli-improvements-1 2026-01-09 18:02:46 +08:00
RevIQ
6b9b04d1d0 Improve API token format and enhance auth status command
- Change token format to reviq_<base58> prefix instead of raw hex
- Add me.authStatus API endpoint for detailed auth information
- Enhance CLI `reviq auth status` to show token details from API
- Add comprehensive tests for token generation (18 tests)
- Extract bootstrap logic to @reviq/db for reusability and testing
- Remove default db export; callers must use createDb() directly

Token changes:
- New format: reviq_<base58-encoded-32-bytes>
- Added parseToken() for validation
- Added isValidTokenFormat() helper

Auth status endpoint returns:
- User profile information
- Auth method (api_token or session)
- Token/session details (name, expiration, last used)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 17:59:02 +08:00
RevIQ
d04f061120 Fix lint and formatting issues
- Sort imports alphabetically in helpers.ts and router.ts
- Simplify boolean comparison in users/update.ts

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 17:13:14 +08:00
RevIQ
786232e1b1 Merge branch 'workstream-k' 2026-01-09 17:03:07 +08:00
RevIQ
c0966365f3 Refactor admin procedures into separate files
Extract admin procedures from router.ts into dedicated files under
procedures/admin/ with consolidated exports via _routes.ts. Adds shared
helper functions for response transformation and includes race condition
fixes via transaction-scoped existence checks.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 17:00:04 +08:00
RevIQ
2655c57b9e Merge branch 'wt3': WebAuthn enhancements and virtual authenticator
- Enhanced createRegistrationOptions to look up existing users
- Added virtual-authenticator testing package
- Added WebAuthn e2e and unit tests

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 16:55:14 +08:00
RevIQ
9cf95095c3 Implement Workstream J: Org procedures (backend)
Add complete organization management procedures:
- orgs.list, create, get, update, delete, leave
- orgs.members.list, updateRole, remove
- orgs.invites.list, create, cancel, accept
- orgs.sites.list

Key features:
- Role-based access control (owner > admin > member)
- Transaction-protected owner count checks to prevent race conditions
- Privilege escalation prevention (only owners can invite owners)
- Graceful constraint violation handling with friendly error messages
- Email sending for org invitations

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 16:50:29 +08:00
RevIQ
bd9be3e441 Add comprehensive WebAuthn e2e/unit tests and virtual authenticator package
- Create @reviq/virtual-authenticator package with cryptographically valid
  WebAuthn credential generation for testing
- Add e2e tests for WebAuthn registration, authentication, passkey management
- Add unit tests for passkey-helpers and VirtualAuthenticator
- Add security tests for counter replay and tampered responses
- Configure test database environment in devenv.nix
- Add turbo.json test tasks and workspace configuration

Test results: 98 tests passing (54 virtual-authenticator, 25 e2e, 19 unit)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 16:46:02 +08:00
RevIQ
2d445cc47b Merge branch 'workstream-f1' 2026-01-09 16:31:58 +08:00
RevIQ
860d791125 Implement Workstream F1: me.get and me.setupProfile procedures
- Add me.get procedure returning user profile with needsSetup flag
- Add me.setupProfile procedure for initial profile setup after signup
- Add nonEmptyString/optionalString schema helpers with tests
- Use Web Crypto API (SubtleCrypto) for Cloudflare Workers compatibility
- Use @formatjs/intl-durationformat for duration formatting
- Remove node:crypto dependency from crypto utilities

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 16:29:41 +08:00
RevIQ
9b898678c7 Refactor me.* procedures with code review fixes
- Fix silent failures: add 404 NOT_FOUND for invalid resources in
  passkeysRename, revokeSession, trustDevice, untrustDevice
- Fix race condition in passkeysDelete using transaction
- Extract helper functions: requireDeviceFingerprint, defaultDeviceName
- Improve type safety in updateProfile with Kysely's Updateable<Users>
- Extract me.* procedures to separate files under procedures/me/
- Standardize naming to verb-first: listPasskeys, renamePasskey, deletePasskey

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 16:24:10 +08:00
RevIQ
617fa78046 Fix Session.id type and restore nested passkey routes
- Change Session.id from number to string to match DB bigint type
- Restore me.passkeys.{list,rename,delete} nested route structure
- Remove unnecessary String() conversion in logout procedure
- Auto-formatted procedure files

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 15:44:45 +08:00
RevIQ
a4d1f28f3d Add typed context and middleware for oRPC procedures
Use implement(contract).$context<APIContext>() for proper type safety
in all procedure handlers. Create authMiddleware and loginRequestMiddleware
using os.middleware() and apply with .use() on routes requiring auth.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 15:36:26 +08:00
RevIQ
829d365e80 Implement auth procedures with code review fixes
Add complete auth backend (Workstream D):
- Auth middleware for session/API key authentication
- Signup with password or passkey (WebAuthn)
- Login flow with device trust and email confirmation
- Password reset and email verification
- Session management and logout

Utilities created:
- cookies.ts: Cookie helpers and configuration
- crypto.ts: Token generation and hashing
- password.ts: zxcvbn validation, argon2id hashing
- geo.ts: IP/location extraction from headers
- email.ts: Stubbed email sending
- session.ts: Session creation and device trust

Code review improvements applied:
- Use ORPCError instead of Error in procedures
- Add ast-grep rule to enforce ORPCError usage
- Remove error info leakage (generic messages)
- Optimize N+1 query with JOIN in login-password
- Extract signupWithPassword/signupWithPasskey for testability
- Add 15-minute WebAuthn challenge expiry check
- Strengthen CookieOptions type definitions

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 15:19:15 +08:00
RevIQ
30ee35b25c Restructure passkey routes to me.passkeys namespace
- Remove createPasskey since verifyRegistration handles adding passkeys
- Move listPasskeys → me.passkeys.list
- Move renamePasskey → me.passkeys.rename
- Move deletePasskey → me.passkeys.delete

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 12:38:07 +08:00
RevIQ
b46146faa5 Implement WebAuthn passkey authentication
Add complete WebAuthn support for passkey registration and authentication:
- Install @simplewebauthn/server for WebAuthn utilities
- Create passkey-helpers.ts with base64url/Uint8Array conversion utilities
- Create webauthn.ts with registration/authentication option generation and verification
- Create context.ts with API context types
- Implement all WebAuthn router handlers (createRegistrationOptions, verifyRegistration, createAuthenticationOptions, verifyAuthentication)
- Implement passkey management handlers (listPasskeys, createPasskey, renamePasskey, deletePasskey)
- Add WebAuthn configuration constants and environment variables

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 12:34:26 +08:00
RevIQ
93132d76c0 Add api-server and CLI applications
- Create api-server with Bun.serve:
  - oRPC router with stub handlers for all procedures
  - Auth middleware placeholder
  - CORS configuration
- Create CLI tool with stricli:
  - bootstrap command for initial superuser creation
  - Placeholder commands for auth, user, org management

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 11:45:03 +08:00