Commit Graph

115 Commits

Author SHA1 Message Date
RevIQ
72fa560648 Merge branch 'master' into testing-improvements 2026-01-10 15:31:37 +08:00
RevIQ
f9f26bb590 Add shadcn UI components and replace raw HTML form elements
- Install 8 shadcn components: select, skeleton, checkbox, switch, avatar,
  dropdown-menu, tooltip, textarea
- Replace raw <select> elements with Select component in members page
- Replace raw checkbox with Checkbox component in admin user details
- Add Skeleton loading states to admin pages (users list, orgs list,
  user details) for better UX

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 15:26:49 +08:00
RevIQ
2c2556a5ea Add e2e tests for me.* procedures and fix code review issues
- Add comprehensive e2e tests for me.get, me.authStatus, me.setupProfile,
  me.updateProfile, me.setPassword, and me.delete (21 tests)
- Make createDb require explicit connection string (no default env lookup)
- Add database name validation to prevent SQL injection in CREATE DATABASE
- Fix getTestDatabaseUrl to throw instead of returning empty string
- Replace brittle relative path with findRepoRoot() function
- Extract magic numbers (SESSION_EXPIRY_MS, API_TOKEN_EXPIRY_MS, ONE_DAY_MS)
- Consolidate duplicate createAPIContext functions
- Add hasPassword field to meAuthStatus and toUserResponse

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 15:24:42 +08:00
RevIQ
ddd7c0c03b Add generateSecureBase58Token to shared utils with login_ prefix
- Create packages/utils/src/generate-base58-token.ts with typed prefix support
- Function returns `${TPrefix}${string}` for type-safe prefixed tokens
- Add isBase58() validator and parseBase58Token() helper
- Add comprehensive tests (13 test cases)

- Update login request tokens to use "login_" prefix
- Fix login-password.ts to not replace token (cookie/DB mismatch bug)
- Migrate all token generation from generateSecureToken (hex) to
  generateSecureBase58Token (base58)
- Remove duplicate token generation from api-server/utils/crypto.ts

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 19:31:30 +08:00
RevIQ
68fc67ba4a Fix lint errors and formatting
- Wrap error.code with String() in CLI complete-login command
- Apply formatting fixes from linter

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 19:16:23 +08:00
RevIQ
93ef5c3942 Merge branch 'cli-destroy' 2026-01-09 19:13:21 +08:00
RevIQ
d66894e8dc Add admin CLI command and auth guard, use oRPC client
CLI changes:
- Use official oRPC client instead of manual HTTP requests
- Add admin complete-login command for dev workflow
- Remove type assertions, use proper ContractRouterClient typing
- Add @orpc/client and @orpc/contract dependencies

API changes:
- Use oRPC cookie helpers from @orpc/server/helpers
- Improve admin complete-login error messages (expired, already completed)

Dashboard changes:
- Add AuthGuard component to redirect unauthenticated users to /auth/login
- Update confirm page with correct CLI command and copy button
- Remove duplicate auth redirect from dashboard layout

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 19:12:19 +08:00
RevIQ
3031c88148 Add --dangerously-overwrite-existing flag to bootstrap command
Allows re-running bootstrap to delete and recreate the superuser and
reviq org. Deletes all related records (tokens, sessions, passkeys, etc.)
before recreating.

Also configures stricli to use kebab-case for CLI flags globally.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 19:09:09 +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
5995d45e41 Merge branch 'workstream-m' - Admin panel
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 18:26:28 +08:00
RevIQ
20475861a5 Fix linter warnings and build issues
- Replace non-null assertions with runtime checks in org layout queries
- Add handleUnseenRoutes: "ignore" for dynamic dashboard routes

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 18:23:38 +08:00
RevIQ
c8152ce86e Implement Workstream M: Admin Pages (Frontend)
Add superuser admin interface for managing organizations and users:
- Admin layout with access control (redirects non-superusers)
- Admin dashboard with org/user counts and quick actions
- Org management: list, create, view/edit details, manage sites
- User management: list, view details, toggle superuser, confirm email
- SuperuserBadge component for consistent superuser indication
- Sidebar shows admin link (shield icon) for superusers only
- Centralized date formatting utility at $lib/utils/format-date.ts
- Test plan documentation at docs/test-plans/admin.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 18:18:36 +08:00
RevIQ
cc77211969 wip: cleanup 2026-01-09 18:18:31 +08:00
RevIQ
2f40ff119d Merge branch 'workstream-l' 2026-01-09 18:18:07 +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
c1afc39062 Add utils package with Web Crypto password hashing
- Create @reviq/utils package with PBKDF2-SHA256 password hashing
  compatible with Cloudflare Workers (uses crypto.subtle)
- Update api-server and CLI to use new utils package for consistent
  password hashing format across the codebase
- Add pino logging to api-server for better request debugging
- Make login request tokens cryptographically secure base58 strings
  instead of database IDs
- Add migration to make login_requests.token non-nullable with unique
  constraint
- Fix RPCLink URL construction for client-side API calls
- Add db:codegen script to root package.json

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 18:12:33 +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
41b52750d8 Implement Workstream L: Org Pages (Frontend)
Add organization management UI pages:
- /dashboard: Org list with grid cards
- /dashboard/[slug]: Org overview with stats and previews
- /dashboard/[slug]/members: Member management with invites
- /dashboard/[slug]/settings: Org settings, leave, delete
- /invite/accept: Token-based invite acceptance flow

Includes shared org context layout for role detection, reusable
components (role-badge, confirm-dialog), and sidebar nav update.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 17:44:42 +08:00
RevIQ
cee700f063 Merge branch 'workstream-n-completion'
Resolve conflict: use --compile for both CLI binaries

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 17:21:12 +08:00
RevIQ
ed2636ab83 Use nullish coalescing in admin users create
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 17:14:21 +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
9158146462 Build api-server and cli as compiled binaries
- Rename api-server package to @reviq/api-server
- Add --compile flag to bun build for both packages
- Output standalone executables instead of bundled JS

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 17:11:20 +08:00
RevIQ
c4b0509023 Implement shell completions for CLI (Workstream N-Completions)
Add `reviq completions bash/zsh` command with dynamic shell completions:

- Create bash-complete.ts entry point using stricli's proposeCompletions API
- Add completions command with bash and zsh support (fish planned)
- Extract app export to separate app.ts for shared imports
- Add @stricli/auto-complete dependency and __reviq_bash_complete bin entry

Also fix lint/type errors in api-server tests and helpers.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 17:11:10 +08:00
RevIQ
786232e1b1 Merge branch 'workstream-k' 2026-01-09 17:03:07 +08:00
RevIQ
3eb44adf05 Fix TypeScript and lint errors
- Add missing reqHeaders/resHeaders to webauthn test context
- Fix Session.id type from number to string in test
- Remove unnecessary Number() conversion in countOwners

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 17:01:22 +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
f0f1a4f4f7 Merge branch 'workstream-h-v2' 2026-01-09 16:50:52 +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
82078b3a05 Fix floating promise lint errors and apply code formatting
- Add void operator to async calls in $effect() blocks to satisfy
  noFloatingPromises lint rule:
  - passkey/+page.svelte: void authenticate()
  - verify/+page.svelte: void verifyEmail()
- Apply biome formatter import reorganization across auth files

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 16:39:33 +08:00
RevIQ
96807bdc3f Merge branch 'master' into workstream-h-v2
Resolve conflicts in router.ts by adopting master's modular architecture
for me.* procedures while keeping meGet and setupProfile inline.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 16:36:37 +08:00
RevIQ
073db98a91 Implement Workstream H: Auth pages with refactored components
Add 10 authentication pages for the Publisher Dashboard:
- H1: /auth/signup - Account creation with passkey/password
- H2: /auth/setup/user - Profile setup with phone validation
- H3: /auth/login - Email entry with routing logic
- H4: /auth/login/passkey - WebAuthn authentication
- H5: /auth/login/password - Password authentication
- H6: /auth/confirm - Email verification polling
- H7: /auth/trust-device - Device trust prompt
- H8: /auth/verify - Email verification callback
- H9: /auth/forgot-password - Password reset request
- H10: /auth/reset-password - New password form

New reusable components:
- LoadingButton: Button with Loader2 spinner and loading state
- ErrorAlert: Accessible error display with ARIA live region
- PasswordFormField: Composite field with label, input, strength meter
- PasswordInput: Improved with bind:value and cn() class merging

New utilities:
- validation.ts: Email, phone validation, email masking, error parsing
- auth.svelte.ts: Login flow state store for SPA mode guards

Backend updates:
- Implement me.get, me.setupProfile, me.getDeviceInfo, me.trustDevice

Dependencies added:
- @simplewebauthn/browser, libphonenumber-js, ua-parser-js
- zxcvbn, svelte-sonner, shadcn alert component

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 16:32:35 +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
93851afe38 Merge branch 'wt4': Add email sending and documentation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 15:45:39 +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
9456a98eac Implement Workstream G: Email Service with Postmark
- Add postmark dependency and email configuration constants
- Implement sendVerificationEmail, sendPasswordResetEmail,
  sendLoginConfirmationEmail, and sendOrgInviteEmail helpers
- Add HTML + text email templates with inline CSS
- Support dev mode (EMAIL_DEV_MODE=true) for console logging
- Use URL constructor for proper URL building
- Add XSS protection with HTML escaping in templates
- Create .env file with email environment variables

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 15:42:33 +08:00
RevIQ
1858ea9783 Merge branch 'wt2': Add typed context and middleware pattern
- Add procedures/base.ts with typed os implementer and middlewares
- Refactor router to use authMiddleware and loginRequestMiddleware
- Flatten passkey routes to me.listPasskeys/createPasskey/renamePasskey/deletePasskey
- Stub admin procedures with NOT_IMPLEMENTED (to be reimplemented with superuser middleware)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 15:40:55 +08:00
RevIQ
3f94a9e067 Merge branch 'wt2': Add auth procedures and password utilities
Integrates extracted auth handlers and Bun-based password hashing:
- Auth procedures moved to individual handler files
- Password hashing using Bun's argon2id (replaces scrypt)
- Password validation with zxcvbn
- Session, cookie, crypto, email, and geo utilities

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 15:36:32 +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
410b937f9f Implement CLI commands and admin API endpoints
- Add bootstrap command with direct DB access for initial setup
- Implement auth login/logout/status CLI commands
- Implement user create/confirm-email CLI commands
- Implement org create/list/add-site CLI commands
- Add admin.orgs.* and admin.users.* API endpoints
- Add password hashing utility with scrypt
- Add token hashing and authentication utility
- Add superuser runtime checks for admin endpoints
- Wrap multi-step operations in transactions
- Fix config file permissions (0o600) for security
- Remove token display from status command
- Add return statements to void handlers
- Add reviq CLI command to devenv

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 15:30:10 +08:00
RevIQ
8db2adf4c0 Merge branch 'wt2' into wt4 2026-01-09 15:22:12 +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