- Fix auth verify handler to read token_hash (GoTrue param name) instead
of token, and verify OTP server-side before redirecting
- Fix reset-password page to handle both token_hash and pre-existing
session from verify handler
- Fix intermittent dashboard 500 by adding error handling and retry to
members_with_dues query in safeGetSession
- Fix RLS policies using members.user_id (nonexistent) → members.id for
cron_execution_logs and bulk_emails tables
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All new migrations are now embedded in post-deploy.sql (idempotent),
so they run automatically on `docker compose up` via the migrate container.
Both deploy/ and docker/migrate/ copies are kept in sync.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add chown to give kong user write permissions to /var/lib/kong
- Fixes 'can't create /var/lib/kong/kong.yml: Permission denied' error
- Allows entrypoint script to generate kong.yml from template
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Change ORIGIN from hardcoded localhost to use environment variable
- Allows production deployment with correct domain for CSRF protection
- Maintains localhost default for local development
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add proper CORS configuration to all Kong routes
- Allow portal.monacousa.org and localhost origins
- Configure allowed methods, headers, and credentials
- Fixes 'Cross-site POST form submissions are forbidden' error
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Gitea Actions now builds monacousa-db, monacousa-kong, and
monacousa-migrate alongside the portal image on every push to main
- Fix Kong Dockerfile permission issue (use COPY --chmod instead of RUN chmod)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Custom Docker images embed all config so production servers no longer
need SQL files, kong.yml, or shell scripts. Kong generates config from
env vars at startup. Migrate container auto-detects fresh vs existing
DB and runs appropriate scripts.
New images: monacousa-db, monacousa-kong, monacousa-migrate
New commands: deploy.sh build-images, deploy.sh push-images
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add deploy/post-deploy.sql: idempotent script that ensures storage
RLS policies, buckets, notifications table, and migration 017 are
applied on every deploy
- Add migrate service to docker-compose: one-shot container that runs
post-deploy.sql after storage-api creates its tables
- Add migrate command to deploy.sh with retry logic
- Fix studio/storage healthchecks (start_period, || exit 0)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Use supabaseAdmin for admin settings operations (bypasses RLS completely)
- Add proper error handling to updateSettings action
- Update notifications to be expandable with full message display
- Clicking notifications in dropdown now goes to /notifications?id=X
- Auto-scroll and expand notification when opening from dropdown link
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix RLS policies: Add WITH CHECK clause to all FOR ALL policies
(fixes 502 errors on admin settings and other updates)
- Add /notifications page for users to view all notifications
- Add /admin/notifications page for admins to create/manage notifications
- Add notifications link to admin sidebar
- Fix NotificationCenter to use goto() for internal navigation
- Fix email.ts to fall back to environment variables for SMTP
(allows welcome emails to work when app_settings SMTP not configured)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The Supabase postgres image includes a migrate.sh that tries to connect
as supabase_admin without proper credentials. Override it with an empty
script since migrations are handled by init.sql.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move GRANT statements for document_folders and user_notification_preferences
to after their respective CREATE TABLE statements. The grants were failing
because they referenced tables that hadn't been created yet.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The setupCheckHandle hook caches whether setup is needed for 1 minute.
After creating the admin, this cache wasn't cleared, causing a redirect
loop between /login and /setup.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix admin settings 502 error by adding INSERT/UPDATE/DELETE grants
- Fix Button component to render <a> when href prop is provided
- Add welcome email for admin created during initial setup
- Add in-app notifications system with NotificationCenter component
- Add notifications table with RLS policies and welcome trigger
- Add API endpoints for fetching and marking notifications as read
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
init.sql changes:
- Add INSERT grant for members table (for /join signup)
- Add INSERT grant for dues_payments (for board recording payments)
- Add full CRUD grants for events, documents, document_folders
- Add UPDATE grant for email_templates (admin management)
- Add anon role grants for public event viewing and RSVP creation
README changes:
- Add "Important Notes" section explaining dynamic env vars
- Add first-time setup and database initialization docs
- Add troubleshooting for 403 errors with grant fix commands
- Add troubleshooting for "account not configured" errors
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
RLS policies define WHAT rows can be accessed, but GRANT statements
control WHETHER a table can be accessed at all. This was causing 403
errors when authenticated users tried to access tables.
Added grants for:
- Core tables: members, membership_statuses, membership_types
- Dues: dues_payments (SELECT)
- Events: events, event_types, event_rsvps (full CRUD), event_rsvps_public
- Documents: documents, document_categories, document_folders
- Settings: app_settings (SELECT for public settings)
- Email: email_logs (SELECT for own logs)
- Preferences: user_notification_preferences (SELECT, INSERT, UPDATE)
- Views: members_with_dues, events_with_counts
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changes $env/static/public to $env/dynamic/public for all Supabase
URL and API key configuration. This allows the app to read environment
variables at runtime instead of build time, enabling deployment with
different configurations without rebuilding the Docker image.
Files updated:
- hooks.server.ts: Use dynamic env for PUBLIC_SUPABASE_URL/KEY
- lib/server/supabase.ts: Lazy-init admin client with dynamic env
- lib/server/storage.ts: Use dynamic env for browser-accessible URLs
- lib/supabase.ts: Use dynamic env for browser client
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
These fields can be filled in later by the user. The admin setup page
only collects essential fields (name, email, password).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The membership_statuses table requires display_name but the setup page
was not providing it when creating the initial Active status.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The Supabase postgres image's internal migrate.sh requires supabase_admin
to have a password matching POSTGRES_PASSWORD. Added zz-set-passwords.sh
to run after init.sql and set passwords dynamically using the environment
variable.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The Supabase postgres image sets these passwords based on POSTGRES_PASSWORD.
Hardcoding 'postgres' caused the image's migrate.sh to fail.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- storage.objects and storage.buckets are created by storage-api service
- Wrapped all storage bucket inserts and policy operations in DO blocks
- Check if table exists before running storage operations
- Prevents errors during initial database setup
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
These functions are normally created by GoTrue but our init.sql
runs first. Needed for RLS policies that use auth.uid().
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added GRANT ALL for service_role on:
- membership_statuses, membership_types, members tables
- All tables and sequences in public schema
- Default privileges for future tables
Fixes 'permission denied' errors during admin setup.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
$env/static/private reads at build time, not runtime.
Changed to $env/dynamic/private so the key is read at runtime
from the container environment.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The auth.users table is created by GoTrue, not the database init.
FK constraints to auth.users fail because init.sql runs before auth starts.
Removed FK from members and audit_logs tables.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- PostgREST and postgres-meta images don't have /bin/sh
- Removed CMD-SHELL healthchecks that were causing unhealthy status
- Changed dependent services from service_healthy to service_started
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Changed from single DOMAIN variable to PORTAL_DOMAIN and API_DOMAIN
- Matches nginx config: portal.monacousa.org, api.monacousa.org, studio.monacousa.org
- Updated docker-compose.yml to use correct domain variables with defaults
- Updated setup.sh to validate both domain variables
- Updated .env.example with separate domain configuration
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use openssl rand -hex for secrets (no special chars)
- Use awk instead of sed for .env updates (handles any chars)
- Use awk for kong.yml generation (handles JWT tokens)
- Suppress source errors for malformed .env
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove Traefik service and related labels
- Expose ports to localhost only (3000, 8000, 3001)
- Update README with nginx proxy configuration examples
- Remove ACME_EMAIL and Traefik auth from .env.example
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- docker-compose.yml: Standalone compose with Traefik, Supabase, portal
- init.sql: Combined database schema + all 16 migrations
- kong.yml.template: Kong config with API key placeholders
- setup.sh: Auto-generates secrets (JWT, passwords, API keys)
- .env.example: Comprehensive environment template
- README.md: Complete deployment guide
No source code cloning required - just copy files and run setup.sh
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Creates scripts/update-kong-keys.sh
- Reads ANON_KEY and SERVICE_ROLE_KEY from .env
- Generates kong.yml with correct API keys
- Run after setting up .env to configure Kong authentication
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Treat "table does not exist" errors as needing setup
- Redirect to /setup on unexpected errors (safer default)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create 00-init-schemas.sql that runs before Supabase init scripts
- Creates required roles: anon, authenticated, service_role, supabase_admin, etc.
- Creates required schemas: auth, storage, extensions, _realtime, graphql
- Sets up proper grants and permissions for Supabase services
- Mount init script to /docker-entrypoint-initdb.d/ in db container
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add /setup route for first-run admin user creation
- Add setup check hook to redirect to /setup when no users exist
- Fix storage container dependency (service_started vs service_healthy)
- Fix migrations mount path (don't overwrite Supabase init scripts)
- Add favicon and apple touch icon links to app.html
- Show success message on login after setup completion
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Mounting to /docker-entrypoint-initdb.d was replacing the Supabase
postgres image's built-in initialization scripts that create the
auth schema, roles, etc. Now mounting to /migrations instead.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The supabase/postgres image already has all required schemas and roles
pre-configured. The custom migration was conflicting with the image's
built-in initialization.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Kong's declarative config doesn't support env vars, so API keys must be
embedded in kong.yml. Added generate-kong-config.sh script and integrated
it into deploy.sh to automatically generate kong.yml from .env values.
Run ./scripts/generate-kong-config.sh once after setting up .env, then
docker compose up -d will work correctly.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Creates required auth, storage, extensions, _realtime, and graphql_public
schemas that must exist before GoTrue can run its migrations. Also creates
necessary roles (anon, authenticated, service_role, supabase_admin) and
the base auth.users table structure.
Fixes: "no schema has been selected to create in (SQLSTATE 3F000)"
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>