Commit graph

328 commits

Author SHA1 Message Date
318b277e44 feat(growth): add edit/delete, goals, CSV export, and WHO percentile enhancements
- Add PUT and DELETE endpoints for growth records
- Add CSV export for pediatrician visits
- Add goal tracking with localStorage persistence
- Color-coded percentiles (green/yellow/red zones)
- Show WHO percentile lines (15th, 50th, 85th) on chart
- Growth velocity indicator (kg/month between readings)
- Enhanced WHO standards card with actual vs target + goal progress
- Better empty state with encouraging prompt
- Fix UUID type for growth record IDs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 13:52:02 +05:30
1628588d5a fix(ai): correct env var names and fresh session per home modal open
AI route was reading LITELLM_URL/LITELLM_KEY but env vars are named
LITELLM_BASE_URL/LITELLM_API_KEY — causing 503 on every request.

Home page chat now creates a fresh session each time the modal opens
and resets homeSessionId on close, so conversations don't pile into
the same old session.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 13:31:30 +05:30
299e878e38 fix(ai): proper chat layout, mobile sidebar, empty states, loading dots
- h-screen with overflow-hidden so messages scroll within viewport
- Sidebar is slide-over on mobile (fixed + overlay) with translate animation
- Sidebar defaults closed; auto-selects first session on load
- Empty state when no session selected with "New Chat" CTA
- Typing indicator with animated bouncing dots
- Chat bubbles properly aligned (user right, AI left) with rounded corners
- Delete confirm moved to its own modal (not nested in session list item)
- Removed stale debug console.log
- Dark mode fixes: border, hover states, disabled button

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 13:24:33 +05:30
70aa35384b fix(medical): dark mode support and tab wrapping fix
Added dark: variants to all cards, inputs, selects, text, and buttons
throughout the medical page. Added whitespace-nowrap + flex-shrink-0 to
all tab buttons to prevent labels like "Doctor Visit" from wrapping.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 13:22:14 +05:30
bc2eb9a50f feat(home): full age breakdown and dark mode fixes
Age now shows years, months and days (e.g. "1 year, 3 months, 5 days").
Added dark: variants to all white cards, inputs, selects, and text on the
home page so dark mode no longer shows white boxes on a dark background.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 13:11:03 +05:30
75afc177ce fix(home): move useEffect hooks above early returns to fix Rules of Hooks violation
All three useEffect calls were placed after an early return when childId was
null, causing React error #310 on the home page. Moved them above the
conditional returns and guarded each body with if (!childId) return.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 13:01:26 +05:30
50a6827bfd fix(admin): use bcrypt in admin password set to match signin verification
Simple hash_ format stored by admin PATCH was incompatible with bcrypt
verification in /api/auth/signin, causing "Invalid password" on login.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 12:57:33 +05:30
6ce459e4f6 fix(admin): restore stats API from debug stub
Route was returning { test: "ok", count: N } instead of the expected
overview/conversions/growth/childrenByAge structure, crashing the dashboard.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 12:27:36 +05:30
85d313bc86 fix(admin): use correct column name 'expires' in admin_sessions queries
verifyAdminSession() and requireAdmin() both used expires_at but the
admin_sessions table column is named expires — causing every session
check to silently fail and always redirect to /admin-login.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 12:22:17 +05:30
fc0e75b5ad fix(admin): scope FamilyProvider out of admin routes, ensure cookies on admin fetches
Root causes:
- tia_admin_session is httpOnly so document.cookie could never read it → all
  client-side cookie checks always failed and redirected before any data fetched
- Sub-pages used localStorage.getItem("admin_token") which was never stored,
  and passed Authorization: Bearer null headers the server ignores

Fixes:
- FamilyProvider: use usePathname() hook instead of window.location.pathname
- admin/layout.tsx: rewrite as server component using verifyAdminSession()
  (new lib/admin-auth.ts helper that uses next/headers cookies()) → server-side
  redirect to /admin-login if session invalid; extract sidebar to AdminSidebar.tsx
- admin/page.tsx: remove broken document.cookie guard (layout handles auth now)
- admin-login/page.tsx: replace document.cookie check with GET /api/admin/auth call
- All 7 admin sub-pages: remove localStorage guard, remove Authorization: Bearer
  headers, add credentials: include to every fetch call

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 12:16:10 +05:30
5e36c8a848 remove: /api/setup route — bootstrap should be done via psql, not HTTP
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 11:58:01 +05:30
07bb149dd8 fix: notifications IDOR — verify child belongs to caller's family
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 11:57:57 +05:30
389f66955c fix: stop leaking password reset tokens in response
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 11:57:54 +05:30
8e7a3fbe35 Clean up debug logs 2026-05-17 11:26:01 +05:30
480de976ef Verify session server-side before redirect 2026-05-17 11:24:46 +05:30
6247bb42bc Fix hydration - check typeof window 2026-05-17 11:22:43 +05:30
4212c1f632 Debug login flow 2026-05-17 11:20:53 +05:30
754a602e48 Add debug logging to FamilyProvider
Move admin check to top-level useEffect before any async calls.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 11:13:01 +05:30
e7539468c1 Fix FamilyProvider admin check - move inside useEffect
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 11:03:54 +05:30
70376d2e96 Fix FamilyProvider redirect for admin pages
Skip family check when pathname starts with /admin
to prevent redirect to onboarding

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 11:01:37 +05:30
d94a15e38e Fix admin login: redirect path, add logout, remove unused code
- Fix redirect from /admin/login to /admin-login
- Add DELETE endpoint for logout
- Connect logout button to API
- Remove unused admin state/localStorage

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 10:54:15 +05:30
ffaa92cd13 Revert: Remove token from response (HttpOnly cookie is sufficient)
Login page checks cookie on load via useEffect, no need for
localStorage token. More secure this way.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 10:52:08 +05:30
73cfd2a761 Fix admin login response missing token
The API was setting the session token as a cookie but not
returning it in the JSON response. Login page expects token
in the response to store in localStorage.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 10:50:35 +05:30
d18213fc7d Test route 2026-05-17 10:47:35 +05:30
dc54fd31c6 Debug route 2026-05-17 10:45:11 +05:30
724a914fa7 Add debug 2026-05-17 10:43:32 +05:30
a2bc6b6857 Simplify admin stats 2026-05-17 09:47:36 +05:30
5f80ec4570 Fix admin pages to use cookie auth 2026-05-17 01:20:26 +05:30
c11484b910 Fix rate limit variable scope 2026-05-17 01:14:32 +05:30
e47001365e Rate limit controlled via RATE_LIMIT_ENABLED env 2026-05-17 01:12:15 +05:30
f84ee96e2b Enhanced debug 2026-05-17 00:52:39 +05:30
082c2bcdd8 Add debug endpoint 2026-05-17 00:46:12 +05:30
cb7d9411ff Fix JOIN - sessions directly to family_members 2026-05-17 00:38:15 +05:30
7b6f033d42 Fix UUID join in auth.ts 2026-05-17 00:35:49 +05:30
a43bb060ff Fix UUID join types 2026-05-17 00:31:32 +05:30
57d1b070f4 Fix onboarding schema 2026-05-17 00:25:56 +05:30
92878a6bd9 Fix schema columns 2026-05-17 00:25:23 +05:30
e4b2019325 Fix family_members column 2026-05-17 00:18:49 +05:30
514b115326 Fix onboarding SQL column names
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 00:15:51 +05:30
e7a5de3cc2 Fix onboarding to use custom session auth
Was using next-auth which wasn't working with custom sessions.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 00:13:56 +05:30
340cf4322e Add audit_log and password_resets migrations
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 00:01:07 +05:30
a54f30ddcb Security hardening - all 8 patches applied
Patch 1: Add requireFamily to chat route
Patch 2: Add requireFamily to family routes
Patch 3: Create admin-auth.ts, apply to all admin routes
Patch 4: Delete debug and migrate routes, update middleware
Patch 5: Create audit_log table and schema
Patch 6: Create password reset flow (reset-request, reset-confirm)
Patch 7: Replace with real HTTP security tests
Patch 8: RLS migrations already exist (01-app-role, 02-enable-rls)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 23:59:43 +05:30
f4a1d4544b Fix scoped.ts TypeScript error - simplify to avoid transaction type issue
The Drizzle transaction generic type was causing a type mismatch error.
Since withFamilyContext and getScopedDb were not used anywhere,
simplify the file to just re-export sql and dbUnscoped.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 23:17:38 +05:30
b3e8b0a75f Fix TypeScript error in AI route 2026-05-16 23:13:24 +05:30
5acb2760cc Fix db imports: use dbUnscoped 2026-05-16 23:12:33 +05:30
2196c3d07d Security hardening: auth, bcrypt, rate-limiting, RLS, audit 2026-05-16 23:11:01 +05:30
4cf886ea43 Add security libs: auth, audit, rate-limit, scoped db 2026-05-16 23:10:56 +05:30
149d8bc72c auth: fix family_id join with uuid cast 2026-05-16 23:05:20 +05:30
ca4e1355d6 Dockerfile: enable pnpm in builder stage 2026-05-16 22:38:02 +05:30
aec1e4bcab Dockerfile: use pnpm install --ignore-scripts to bypass build approval 2026-05-16 22:37:16 +05:30