- Create @reviq/frontend-utils package for frontend-specific utilities
- Add OrgAvatar component with size variants (xs, sm, md, lg, xl)
- Display org initials with deterministic colors when no logo available
- Add getOrgInitials and getOrgColor utility functions
- Update org-switcher and all org display pages to use OrgAvatar
- Add noNonNullAssertion lint rule as error in biome.jsonc
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
PostgreSQL 17.6+ adds random \restrict/\unrestrict tokens to pg_dump
output (CVE-2025-8714 security fix), causing schema.sql to appear
changed on every dump even when the schema hasn't changed.
These wrapper scripts run dbmate and strip the \restrict lines from
the output to keep schema.sql stable.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create gotoLogin() helper for login redirects with search params
- Add /terms and /privacy public routes with Tailwind typography
- Update auth-guard to allow unauthenticated access to public pages
- Fix resolve() usage across navigation components using as const pattern
- Fix eslint-disable-next-line placement for svelte/no-navigation-without-resolve
- Document SvelteKit resolve() patterns in CLAUDE.md
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Pin tea CLI to 0.10.1 to avoid TTY bug in 0.11.x
- Add .claude/skills/gitea for PR creation workflow
- Document tea CLI usage in CLAUDE.md
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create new @reviq/common package with environment-agnostic utilities:
- Date formatting: formatDate, formatDateTime, formatLongDate,
formatRelativeDate, formatRelativeTime
- User utilities: getUserInitials, formatRole
Consolidate date formatting from publisher-dashboard into shared package.
All utilities include comprehensive test coverage with bun:test.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 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>