CtrlK
BlogDocsLog inGet started
Tessl Logo
SkillPublic

local-env

Supabase seeding, auth user sync, and local development environment setup

56

Quality

70%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide
SecuritybySnyk

Passed

No findings from the security scan

Fix and improve this skill with Tessl

tessl review fix ./.agents/skills/local-env/SKILL.md
SKILL.md
Quality
Evals
Security

Local Environment Skill — POSCursor (Expo Router, NativeWind v4, WatermelonDB/Supabase)

Environment Files

FilePurposeSupabase Project
.envDefault (may point to production)YOUR_SUPABASE_PROJECT
.env.localLocal development overridesUser-specific
.env.testJest testsLocal/test project
.env.productionProduction buildYOUR_SUPABASE_PROJECT

CRITICAL: Never use the production URL (YOUR_SUPABASE_PROJECT.supabase.co) for local development or tests. The jest-setup.ts safety guard will throw if this URL is detected.

Env Variables

EXPO_PUBLIC_SUPABASE_URL=https://<project-ref>.supabase.co
EXPO_PUBLIC_SUPABASE_ANON_KEY=<publishable-key>

These are loaded by babel-plugin-inline-dotenv at build time and accessed via process.env.EXPO_PUBLIC_* in src/database/supabase.ts.

Role System

The app has 7 user roles, each routing to a dedicated Expo Router group:

RoleRoute GroupColor
admin/(admin)Red #DC2626
collector/(collector)Emerald #059669
loan_encoder/(loan-encoder)Blue #2563EB
payment_encoder/(payment-encoder)Orange #EA580C
expenses_encoder/(expenses-encoder)Violet #7C3AED
borrower/(borrower)Slate #1E293B
main_office/(admin)Slate #1E293B

Defined in src/constants/roles.ts with labels, colors, icons, and home routes.

Auth Architecture

Authentication flows through three tables that must be synchronized:

  1. auth.users — Supabase Auth internal table (email, password hash)
  2. auth.identities — Required for Supabase Auth to recognize the user. Missing identities cause "Invalid login credentials" errors even with correct passwords.
  3. public.user_profiles — App-level profile with role, full_name, auth_id (FK to auth.users.id)

Common Auth Failure Pattern

Login fails → auth.users exists → auth.identities MISSING → "Invalid login credentials"

Fix: When seeding users, always create all three records together.

Seeding Users via SQL

Use the supabase-mcp-server apply_migration or execute_sql tool:

-- 1. Create auth user
INSERT INTO auth.users (id, email, encrypted_password, email_confirmed_at, created_at, updated_at, instance_id, aud, role)
VALUES (
    '<uuid>',
    'admin@jetfarm.com',
    crypt('password123', gen_salt('bf')),
    NOW(), NOW(), NOW(),
    '00000000-0000-0000-0000-000000000000',
    'authenticated',
    'authenticated'
);

-- 2. Create identity (CRITICAL — do not skip!)
INSERT INTO auth.identities (id, user_id, identity_data, provider, provider_id, last_sign_in_at, created_at, updated_at)
VALUES (
    '<uuid>',
    '<same-user-uuid>',
    jsonb_build_object('sub', '<same-user-uuid>', 'email', 'admin@jetfarm.com'),
    'email',
    '<same-user-uuid>',
    NOW(), NOW(), NOW()
);

-- 3. Create user profile
INSERT INTO public.user_profiles (id, auth_id, email, role, full_name, is_active, created_at, updated_at)
VALUES (
    '<new-uuid>',
    '<same-user-uuid>',
    'admin@jetfarm.com',
    'admin',
    'System Admin',
    true,
    NOW(), NOW()
);

Relevant Scripts

ScriptPurposeRun With
scripts/seed-test-users.mjsSeeds admin + collector test usersnode scripts/seed-test-users.mjs
scripts/seed-collectors.mjsCreates collector records in app_collectorsnode scripts/seed-collectors.mjs
scripts/signup-collectors.jsSigns up collectors via Supabase Authnode scripts/signup-collectors.js
scripts/create_test_user.jsCreates a single test usernode scripts/create_test_user.js
scripts/verify-auth.mjsVerifies auth.users ↔ user_profiles syncnode scripts/verify-auth.mjs
scripts/verify_collector_logins.mjsTests collector login credentialsnode scripts/verify_collector_logins.mjs
scripts/verify-connection.mjsChecks Supabase connection is workingnode scripts/verify-connection.mjs

Supabase Migrations

Located in supabase/migrations/:

  • 20260401000000_initial_schema.sql — Full schema (tables, RLS, functions)
  • 20260402102153_fix_users.sql — Auth user fixes

Apply via: supabase-mcp-server apply_migration tool or supabase db push.

Starting the App

# Start Expo dev server
npx expo start

# Android
npx expo run:android

# Web
npx expo start --web

Stale Session Cleanup

src/database/supabase.ts automatically clears stale auth tokens on web:

  • Extracts project ref from URL
  • Removes any sb-*-auth-token localStorage entries that don't match the current project
  • Prevents "Invalid Refresh Token" errors from cross-project contamination

Troubleshooting Checklist

  1. "Invalid login credentials" → Check auth.identities exists for the user
  2. "Invalid Refresh Token" → Clear browser localStorage or the app will auto-clean on next load (web only)
  3. Login works but dashboard empty → Check user_profiles.role matches the expected route, run sync
  4. Sync returns 0 rows → Verify Supabase URL matches the project with data
  5. RLS blocking queries → Check scripts/fix_rls_local.sql for local dev RLS bypass
  6. 500 "Database error querying schema" on login → GoTrue NULL token bug. Fix:
    docker exec supabase_db_jetfarm-local psql -U postgres -c \
      "UPDATE auth.users SET confirmation_token=COALESCE(confirmation_token,''), recovery_token=COALESCE(recovery_token,''), email_change=COALESCE(email_change,''), email_change_token_new=COALESCE(email_change_token_new,''), email_change_token_current=COALESCE(email_change_token_current,''), reauthentication_token=COALESCE(reauthentication_token,''), phone_change=COALESCE(phone_change,'') WHERE confirmation_token IS NULL OR recovery_token IS NULL OR email_change IS NULL;"
    docker restart supabase_auth_jetfarm-local
    Prevention: Migration 20260404120000_fix_auth_null_tokens.sql runs automatically on db reset. Regression tests: src/services/__tests__/AuthService.regression.test.ts (14 tests, BUG-001/002/003) Health check script: node scripts/check-auth-schema.mjs — run before expo start if login fails.

GoTrue NULL Token Bug — Root Cause Summary

FactorDetail
SymptomPOST /auth/v1/token → 500 Database error querying schema
Root causeauth.users rows have NULL in token text columns; GoTrue v2+ panics scanning NULL into Go string
Affected columnsconfirmation_token, recovery_token, email_change, email_change_token_new, email_change_token_current, reauthentication_token, phone_change
Why it happenedSeed INSERT statements omitted these columns → defaulted to NULL
Permanent fixMigration 20260404130000_constrain_auth_null_tokens.sql adds NOT NULL DEFAULT ''
Regression guard14 tests in AuthService.regression.test.ts tagged BUG-001/002/003
Repository

zazakia/JetFarm

Path

.agents/skills/local-env/SKILL.md

Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.