- Add type assertions for dynamic route paths in goto() and resolve()
- Add missing key attributes to {#each} blocks
- Wrap navigation hrefs with resolve() for SvelteKit compatibility
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Configure eslint-plugin-svelte with TypeScript parser support
- Add keys to all {#each} blocks for proper reactivity
- Wrap navigation paths with resolve() from $app/paths
- Remove unnecessary children snippets and useless mustaches
- Add @typescript-eslint/parser and svelte-eslint-parser dependencies
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add left nav with descriptions on desktop and horizontal tabs on mobile,
consistent with the organization settings layout pattern.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
- Add reviq auth login --token <token> command for CLI authentication
- Create /account/api-tokens page for token management (superuser only)
- Add me.apiTokens endpoints (list, create, delete)
- Require superuser status and trusted session for token creation
- Show API Tokens nav link only for superusers
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 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>
- 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>
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>
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>
- 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>
- 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>
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>
- 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>
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>
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>
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>
- 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>
- 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>
- 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>
- 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>
- 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>
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>
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>
- 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>
- 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>
- 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>
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>
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>
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>