Skip to content

Per-user health data and authenticated API (Step 0) - #1

Merged
Meerav29 merged 14 commits into
masterfrom
feat/per-user-data
Oct 3, 2026
Merged

Meerav29 merged 14 commits into
masterfrom
feat/per-user-data

Conversation

@Meerav29

@Meerav29 Meerav29 commented Oct 3, 2026

Copy link
Copy Markdown
Owner

Summary

Step 0 of the Somada modernization (docs/superpowers/specs/2026-10-03-somada-modernization-design.md). Today every user shares one publicly readable health_data row (id = 1), so the last upload overwrites everyone else's data and anyone can read it. This PR fixes that.

  • DB: per-user rows (user_id unique) with RLS scoped to auth.uid(), plus one read-only synthetic demo row (is_demo). The legacy id = 1 row is left in place but becomes invisible. Migration 0002 is idempotent; supabase/rollback/0002_down.sql restores the old app for the legacy row only.
  • API: /api/health and /api/chat verify the Supabase JWT (401 otherwise) and query PostgREST with the caller's own JWT, so RLS decides visibility. No anon-key reads, no limit=1 fallback, no local-file fallback when Supabase is configured. Demo data is marked is_demo by the server.
  • Legacy index.html: minimal patch: sends the token, upserts by user_id, syncs the "demo data" flag from the server.
  • Demo data: deterministic synthetic generator (scripts/make_demo_seed.py -> supabase/seed_demo.sql).
  • CI: pytest on PRs (54 tests).

NOT verified yet

The SQL (supabase/) has never been executed against a database. Before merging:

  1. Create a scratch Supabase project, apply supabase/migrations/0001 then 0002, run supabase/tests/rls_check.sql (expect ALL RLS CHECKS PASSED), then re-apply 0002 and re-run it.
  2. Follow Task 9 in docs/superpowers/plans/2026-10-03-step0-per-user-privacy-fix.md (preview deploy against the scratch project, then a back-to-back migration + deploy window for production; existing users must re-upload).

Do not merge until the deploy checklist is ready: the new schema and the old frontend/API are not compatible, so the migration and this deploy must go out together.

Test plan

  • python -m pytest -v (54 passed)
  • rls_check.sql on a scratch project
  • Two-account manual check on a Vercel preview (see plan Task 9 Step 1)

🤖 Generated with Claude Code

Meerav29 and others added 14 commits October 3, 2026 00:38
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…heck

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- api/auth.py verify_token: guard against non-dict JSON responses using isinstance check
- api/supabase_http.py http_get_json: catch OSError and http.client.HTTPException to ensure no exceptions escape (ConnectionResetError, RemoteDisconnected, IncompleteRead, etc)
- add tests for edge cases: non-dict/empty responses, network errors

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…fallback

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…pi/chat

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Adds build_demo_health_data() and build_seed_sql() in scripts/make_demo_seed.py to generate a deterministic, synthetic demo dataset for testing and seeding. The generated supabase/seed_demo.sql provides an idempotent upsert of the demo row that works across environments.

Features:
- 120 days of plausible health data (steps, sleep, HRV, etc.) from Gaussian distributions
- Deterministic generation (seed=42) for reproducible testing
- Summary statistics auto-calculated from daily data
- Sample event (exam week) included in the demo
- Idempotent SQL upsert with on conflict clause

Includes:
- scripts/__init__.py (empty package marker)
- scripts/make_demo_seed.py (generator code)
- tests/scripts/test_make_demo_seed.py (6 tests covering shape, determinism, plausibility, and SQL format)
- supabase/seed_demo.sql (generated seed data)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…_demo

Only fall through to the demo row when the own-row query returned 200 with
no rows; any other status returns None. Demo data now carries is_demo: true
so the client can tell the truth. Adds URL-shape tests.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… extend RLS checks

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
somada Ready Ready Preview Oct 3, 2026 5:24am UTC

@Meerav29
Meerav29 merged commit 2dc56b9 into master Oct 3, 2026
3 checks passed

This branch was successfully deployed

1 active deployment
Preview — 1aa0ce7f Deployed Oct 3, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant