Commit Graph

25 Commits

Author SHA1 Message Date
igm
2baf10b0cd Replace String() calls with .toString()/.toLocaleString() per ast-grep rule
- Add formatError() helper in CLI to safely handle unknown error types
- Add uniqueTestId() helper for generating unique test identifiers
- Replace String(id) with id.toString() for database ID conversions
- Replace String(n) with n.toLocaleString() for user-facing number formatting
- Fix TypeScript errors in test files (undefined checks, unused variables)
- Update lint commands to include ast-grep scanning

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 15:02:46 +08:00
RevIQ
39863bd947 Add org invites section to dashboard with accept/decline flow
Backend:
- Add me.invites endpoints (list, get, accept, decline) to API contract
- Create invites procedures for fetching user's pending invites
- Only show invites if email matches and is verified
- Refactor me routes into me/_routes.ts for consistency

Frontend:
- Add pending invitations section to /dashboard page
- Create /account/org-invites/[inviteId] page for accept/decline
- Show invite details (org, role, inviter, dates)
- Redirect to org dashboard after accepting

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 17:11:22 +08:00
RevIQ
1bf05465c3 Replace void returns with { success: true } across all API endpoints
- Add successResponseSchema to common.ts for explicit success responses
- Update all auth, me, orgs, and admin procedures to return { success: true }
- Update contract.ts to use successResponseSchema instead of z.void()
- Add ast-grep rule to prevent future z.void() usage in contracts
- Add build:packages script to root package.json
- Fix test file lint errors with eslint-disable comments

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 16:30:22 +08:00
RevIQ
dd7b2ea8e4 Revamp navigation with org switcher and user menu, fix passkey login
Navigation changes:
- Add org-switcher dropdown to sidebar showing user's orgs
- Add user-menu dropdown with account settings and sign out
- Make nav items dynamic based on org context
- Move performance page to /dashboard/[slug]/performance
- Add reports placeholder page at /dashboard/[slug]/reports
- Remove admin link from sidebar (separate layout)
- Update mobile nav to match sidebar changes
- Install shadcn dropdown-menu and popover components

Auth fix:
- Mark login request as completed after passkey verification
- Previously passkey auth didn't complete the login flow, requiring
  unnecessary email verification

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 15:45:03 +08:00
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