Commit Graph

120 Commits

Author SHA1 Message Date
igm
2fb42c0fa5 add gitea cli 2026-01-10 19:47:06 +08:00
igm
462799ca3d Apply linting fixes and update schema
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 19:17:39 +08:00
igm
dcb48a5d5e Migrate e2e tests to transaction-based isolation
Replace table truncation with transaction rollback for test isolation.
Each test now runs in a transaction that auto-rolls back, improving
test performance and isolation. Tests that call procedures with internal
transactions use getSharedDb() directly with appropriate comments.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 19:16:47 +08:00
RevIQ
cca901a9b9 Merge branch 'whats-left' 2026-01-10 18:10:40 +08:00
RevIQ
42badf3c52 Add DBIP city database and improve geo test coverage
- Add dbip-city-lite package to devenv for GeoIP testing
- Set GEOIP_DATABASE_PATH env var to point to the MMDB database
- Add tests for initGeoReader double-init and error handling
- Add real database tests for IP lookups (US, AU, DE, GB)
- Make real database tests conditional with describe.skipIf
- Improve test coverage from ~97% to 98.82%

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 18:10:30 +08:00
RevIQ
bd53a60497 Merge branch 'more-testing-stuff' 2026-01-10 18:10:03 +08:00
RevIQ
d486e2444e Add org settings layout with responsive nav and member management
- Create SettingsLayout component with left sidebar nav (desktop) and
  horizontal scroll nav (mobile)
- Add settings gear icon to sidebar (Lucide icon, only in org context)
- Fix home icon highlighting to only match exact org home path
- Create /settings/members route with full member management
- Create /settings/sites placeholder route
- Update general settings to use new SettingsLayout

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 18:09:17 +08:00
RevIQ
319edf70db Fix IP address not being set on sessions from localhost
The extractClientIP() function only checked proxy headers (X-Forwarded-For,
CF-Connecting-IP, etc.) which don't exist when running locally without a proxy.

Changes:
- Add clientIP field to APIContext
- Use Bun's server.requestIP() to get client IP from direct socket connection
- Update getGeoInfo() to accept fallback IP parameter
- Pass context.clientIP to getGeoInfo() in auth procedures

Now sessions will have IP address set even for local development (::1 or 127.0.0.1).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 18:08:21 +08:00
RevIQ
74b26818ca Add comprehensive e2e tests for all auth procedures
Tests cover all login scenarios from docs/initial-app.md:
- Signup with password and passkey
- Password login with trusted device (immediate completion)
- Password login with untrusted device (email confirmation)
- Full passkey authentication flow
- User with no auth methods (stays pending)
- Non-existent email (anti-enumeration with fake token)
- Email verification and resend flows
- Password reset with session revocation
- Logout

All auth procedures now have 100% function coverage.
127 tests passing across 3 e2e test files.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 17:55:39 +08:00
RevIQ
b93f5e0b69 lint 2026-01-10 17:52:00 +08:00
RevIQ
fb68f341dd Reorganize layouts with dedicated admin sidebar (dark theme)
- Create admin layout with dark sidebar (zinc-900 background, light text)
- Move dashboard components to layout/dashboard/ subfolder
- Move admin components to layout/admin/ subfolder
- Admin sidebar has: Dashboard, Organizations, Users nav items
- Admin header shows "Admin" badge and "Exit Admin" link
- Update all route imports to use new barrel exports
- Add macOS sed syntax reference to CLAUDE.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 17:45:17 +08:00
RevIQ
bd5bb5f5ef Fix dropdown alignment to respect viewport edges
- Org switcher: align="start" keeps dropdown away from top of viewport
- User menu: align="end" keeps dropdown away from bottom of viewport

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 17:29:36 +08:00
RevIQ
40df74fdd0 Merge branch 'testing-improvements'
Combines testing improvements with org invites feature:
- Sessions and devices now use subrouter structure (me.sessions.*, me.devices.*)
- Added me.invites subrouter for org invitations
- Updated test scripts to include coverage and unit tests

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 17:24:51 +08:00
RevIQ
967e8904a7 lint fix 2026-01-10 17:18:05 +08:00
RevIQ
7047d0e9e0 Merge branch 'header-confirm-email' 2026-01-10 17:17:55 +08:00
RevIQ
d824cf4116 Refactor API to use nested sessions/devices routers and fix test infrastructure
- Update API contract to use nested router structure for sessions and devices
  (me.sessions.list, me.devices.getInfo, etc.)
- Update frontend Svelte components to use new nested API paths
- Fix test assertion patterns for consistency (remove async () => wrappers)
- Fix test-db.ts findRepoRoot to use existsSync for directory checking
  (Bun.file().exists() returns false for directories)
- Add ESLint config override for test files to handle expect().rejects patterns

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 17:17:50 +08:00
RevIQ
d779aa794c Add email verification banner for unverified users
Shows a warning banner at the top of dashboard pages when the user's email
is not verified, with a button to resend the verification email.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 17:17:43 +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
9f4c6ac0b9 Redirect auth flows to / instead of /performance
After login, email verification, trust device, and profile setup,
users are now redirected to / which handles routing to their first
org's dashboard.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 16:55:09 +08:00
RevIQ
5e483941cc Merge branch 'cleanup-header' 2026-01-10 16:42:16 +08:00
RevIQ
55b312a03d Merge branch 'geo-fix' 2026-01-10 16:42:07 +08:00
RevIQ
d51ee4f219 Remove placeholder filters from header and fix dropdown cursor
- Remove hardcoded "This month", "6 countries", "3 domains" filter chips
- Change dropdown menu items from cursor-default to cursor-pointer

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 16:41:58 +08:00
RevIQ
575ca83300 Add GeoIP lookup support and update device fingerprints to base58
- Add maxmind library for GeoIP database lookups when not behind Cloudflare
- Extract client IP from multiple header sources (CF, X-Real-IP, X-Forwarded-For, etc.)
- Change device fingerprints from UUID to base58 with device_ prefix
- Add isValidDeviceFingerprint() that accepts both new and legacy formats
- Colocate unit tests with source files, remove __tests__/unit directory
- Add test coverage reporting to test script

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 16:41:21 +08:00
RevIQ
41af130e85 Remove /settings page and redirect / to first org dashboard
- Delete unused /settings route
- Update root page to redirect authenticated users to their first org
- Falls back to /dashboard if user has no orgs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 16:35:44 +08:00
RevIQ
a1dbc60bcb Merge branch 'phone-number-input-fix' 2026-01-10 16:30:30 +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
3b502d9319 Add comprehensive e2e tests for sessions and devices with 100% coverage
- Add tests for me.sessions (list, revoke, revokeAll)
- Add tests for me.devices (getInfo, trust, listTrusted, untrust, revokeAll)
- Refactor router to use nested namespaces (me.sessions.*, me.devices.*)
- Add createUserAPIContext helper that returns { context, token }
- Add createDevice helper for device tests
- Update createSession to return { token, sessionId }

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 16:23:36 +08:00
RevIQ
6b43910238 Add test coverage and fix webauthn e2e tests to use real sessions
- Add test:e2e:coverage script with Bun's built-in coverage support
- Create bunfig.toml with coverage configuration (text + lcov reporters)
- Fix webauthn tests to create real database sessions/login requests
  instead of mock context objects that bypass auth middleware
- Add createUserAPIContext helper for cleaner test code
- Update security tests to expect NOT_FOUND when accessing other
  user's passkeys

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 16:14:24 +08:00
RevIQ
67562f0bce Merge branch 'testing-more' into phone-number-input-fix 2026-01-10 16:07:42 +08:00
RevIQ
f394b80028 Add PhoneNumberInput component with libphonenumber-js formatting
Uses AsYouType for real-time phone number formatting as user types.
Implements digit-based cursor positioning to handle formatting changes
without cursor jumping.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 16:07:32 +08:00
RevIQ
93abba044a Add root test script using Turborepo
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 15:56:51 +08:00
RevIQ
5e13809c0e Merge branch 'website-fixes-general' 2026-01-10 15:46:10 +08:00
RevIQ
44656b1bd1 Merge branch 'testing-improvements' 2026-01-10 15:45:56 +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
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
60bcbeffb3 hash pasword types fix 2026-01-09 18:44:56 +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