diff --git a/AGENTS.md b/AGENTS.md index 53b4b12..34af42b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,7 +2,7 @@ ## Current Release -**v0.9.26** — Native Google Sign-In + Android Platform Fixes (2026-06-28) +**v0.9.26** — CI Stabilization + Database Namespacing (2026-06-28) ## Product Identity @@ -18,7 +18,8 @@ OpenSprout is a privacy-first, open-source plant care companion. Track watering, - **AI:** MCP server at `apps/mcp/` — 28 tools, 112 tests - **Auth:** Google OAuth (email/password disabled via Supabase) - **Design:** Sora variable font, warm paper light mode, deep botanical dark mode -- **Hosting:** Vercel (web at sprout.kovina.org), Supabase (backend, shared project) +- **Hosting:** Vercel (web at sprout.kovina.org), Supabase (backend, shared project with OpenSend) +- **CI:** GitHub Actions — Java 21 for Android, Node 24 for web, caching via `setup-node` ## Repo Structure @@ -280,6 +281,49 @@ opensprout/ ### Dependencies - `@capacitor/browser@8.0.3` installed and synced to Android project. +## Key Changes in v0.9.26b — CI Stabilization + Route Cleanup + +### CI Fixes (7 PRs) +- **Java 21** — Android Gradle Plugin 8.13 requires JDK 21. CI `actions/setup-java` upgraded from 17 to 21. +- **Android build** — Changed from `CAPACITOR_BUILD=true` (which triggers `output: export` and checks all routes for static export compatibility) to normal `npx next build`. Server-only API routes (`/api/mcp`, `auth/callback`) with `force-dynamic` no longer cause build failures. +- **Static output population** — After normal `next build`, copies generated pages and static assets from `.next/` to `out/` so `npx cap sync` can find the required `index.html`. +- **`chmod +x gradlew`** — Git doesn't preserve the executable bit on `gradlew` in CI runners. +- **Global `working-directory` removed** — The `defaults: run: working-directory: apps/web` caused `npm ci` to run from `apps/web` instead of the project root, breaking MCP devDependency installation. + +### Route Cleanup +- Removed all `force-static`, `generateStaticParams`, and `dynamicParams` hacks that were added during the CI debugging process. +- **Critical revert:** `auth/callback` and `api/mcp/tokens` with `force-static` on GET handlers would cache build-time 401/redirect responses on Vercel, breaking Google OAuth and MCP token management in production. +- All 5 API route files now have zero export overrides (except `api/mcp` which keeps `force-dynamic` for its JSON-RPC handler). + +## Key Changes in v0.9.26c — Database Table Prefix Migration + +### Shared Project Namespacing +The Supabase project `rbdyrymtgfqqkdemicdo` is shared between OpenSprout (plant care) and OpenSend (file sharing). All OpenSprout tables were renamed with an `opensprout_` prefix to match the existing `opensend_` convention. + +### Renamed Tables (14) +| Old name | New name | +|----------|----------| +| `profiles` | `opensprout_profiles` | +| `plants` | `opensprout_plants` | +| `care_schedules` | `opensprout_care_schedules` | +| `task_instances` | `opensprout_task_instances` | +| `care_logs` | `opensprout_care_logs` | +| `journal_entries` | `opensprout_journal_entries` | +| `journal_photos` | `opensprout_journal_photos` | +| `data_transfers` | `opensprout_data_transfers` | +| `sync_devices` | `opensprout_sync_devices` | +| `plant_species` | `opensprout_plant_species` | +| `knowledge_articles` | `opensprout_knowledge_articles` | +| `diagnosis_entries` | `opensprout_diagnosis_entries` | +| `identifications` | `opensprout_identifications` | +| `mcp_tokens` | `opensprout_mcp_tokens` | + +### Code Changes (26 files) +- All `supabase.from()` calls updated to use `opensprout_` prefixed names. +- All `Database` type definitions in `types.ts` and `mcp/src/types.ts` use `opensprout_` as table keys. +- All MCP tool files, test mocks, sync cache mappings, and `db.ts` store names updated. +- `delete_account()` RPC function replaced (table `RENAME` doesn't update hardcoded names in function bodies). + ## Key Changes in v0.9.24 — Platform Completion ### Android @@ -306,10 +350,10 @@ opensprout/ - No tests exist in the web app (only MCP tests) - No crash reporting / analytics (intentional privacy choice) -- App version in `package.json` now synced with git tags at v0.9.26 - Vercel Hobby plan rate-limited for deployments (24h cooldown) -- Supabase project shared with other apps (send.kovina.org) +- Supabase project shared with OpenSend (send.kovina.org) — all tables use `opensprout_` prefix - Android OAuth requires `opensprout://auth/callback` and `https://sprout.kovina.org/auth/complete` added to Supabase Redirect URLs +- Android APK built in CI has placeholder web assets (no static export) — functional for development only ## Build Commands @@ -349,6 +393,7 @@ Located at `apps/mcp/`. Exposes 28 tools for AI agents. Test suite: 112 tests. 5. **RLS + app-level isolation.** Supabase RLS enabled on all tables; MCP server adds explicit `user_id` filters since it uses the service role. 6. **Soft deletes.** Deleted records set `deleted_at` — always filter with `.is("deleted_at", null)`. 7. **Explain recommendations.** Every insight/recommendation includes a `reason` and `dataSource`. Never invent without supporting data. +8. **Name-spaced table names.** All OpenSprout Supabase tables use the `opensprout_` prefix (e.g., `opensprout_plants`). Always use the full prefixed name in `.from()` calls, type definitions, and SQL queries. ## Ecosystem Standards diff --git a/CLAUDE.md b/CLAUDE.md index 93488a0..e1b6c71 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -122,8 +122,16 @@ Two transport modes: Architecture follows the MCP Build Guide: SHA-256 token auth, centralized registration, Streamable HTTP, user-scoped service-role client, token CRUD API routes. +## Database + +- **Shared Supabase project:** `rbdyrymtgfqqkdemicdo` — shared with OpenSend (file sharing app) +- **Name-spacing:** All OpenSprout tables use the `opensprout_` prefix (e.g., `opensprout_plants`, `opensprout_care_schedules`). OpenSend uses `opensend_`. All RLS policies, triggers, and FK references follow the same prefix convention. +- **Migrations:** `supabase/migrations/` contains all DDL history. The `20260628000000_prefix_opensprout_tables.sql` migration renamed all tables from un-prefixed to `opensprout_` prefixed. +- **All `supabase.from()` calls** in TypeScript code use the `opensprout_` table names. TypeScript types in `types.ts` and `mcp/src/types.ts` use `opensprout_` as the Database table keys. + ## Release History +- **v0.9.26** (Jun 28) — CI stabilization + database namespacing. Android CI now builds with Java 21 (fixes AGP 8.13 compile error) and uses normal `next build` (not static export) — all `force-static`/`generateStaticParams` route hacks reverted. All 14 OpenSprout tables renamed to `opensprout_` prefix for shared Supabase project namespacing. Code references, type definitions, MCP tools, and tests updated. - **v0.9.26** (Jun 28) — Native Google Sign-In + Android Fixes. In-app Chrome Custom Tab for Android, browser-popup login for Windows/PWA, platform-aware sign-in dispatch, API routing for Capacitor static export, adaptive icon fix, white flash fix, debug diagnostics page. - **v0.9.25** (Jun 28) — Release Candidate Stabilization. Lint/typecheck/test/build clean, schema verification, build validation, changelog backfill. - **v0.9.24** (Jun 28) — Platform completion. Android versionCode 4, cleartext disabled in production, PWABuilder manifest, store screenshots generator, release automation script, CI with Android build job. diff --git a/supabase/migrations/20260628000000_prefix_opensprout_tables.sql b/supabase/migrations/20260628000000_prefix_opensprout_tables.sql index 4a5c0b0..739586a 100644 --- a/supabase/migrations/20260628000000_prefix_opensprout_tables.sql +++ b/supabase/migrations/20260628000000_prefix_opensprout_tables.sql @@ -31,33 +31,3 @@ COMMENT ON TABLE public.opensprout_knowledge_articles IS 'OpenSprout: care/diagn COMMENT ON TABLE public.opensprout_diagnosis_entries IS 'OpenSprout: symptom→cause→solution'; COMMENT ON TABLE public.opensprout_identifications IS 'OpenSprout: AI identification results'; COMMENT ON TABLE public.opensprout_mcp_tokens IS 'OpenSprout: MCP server auth tokens'; - --- Update the delete_account() function to use new table names --- Table RENAME does not update hardcoded table names in function bodies -CREATE OR REPLACE FUNCTION public.delete_account() -RETURNS void -LANGUAGE plpgsql -SECURITY DEFINER -SET search_path = public -AS $$ -DECLARE - v_user_id uuid; -BEGIN - v_user_id := auth.uid(); - IF v_user_id IS NULL THEN - RAISE EXCEPTION 'Not authenticated'; - END IF; - - DELETE FROM public.opensprout_journal_photos WHERE user_id = v_user_id; - DELETE FROM public.opensprout_journal_entries WHERE user_id = v_user_id; - DELETE FROM public.opensprout_care_logs WHERE user_id = v_user_id; - DELETE FROM public.opensprout_task_instances WHERE user_id = v_user_id; - DELETE FROM public.opensprout_care_schedules WHERE user_id = v_user_id; - DELETE FROM public.opensprout_identifications WHERE user_id = v_user_id; - DELETE FROM public.opensprout_mcp_tokens WHERE user_id = v_user_id; - DELETE FROM public.opensprout_sync_devices WHERE user_id = v_user_id; - DELETE FROM public.opensprout_data_transfers WHERE user_id = v_user_id; - DELETE FROM public.opensprout_plants WHERE user_id = v_user_id; - DELETE FROM public.opensprout_profiles WHERE id = v_user_id; -END; -$$;