Tier 2 productization for single-tenant instances, plus fixes from an
adversarial review pass.
New:
- scripts/setup.mjs: 'pnpm setup' CLI (doctor/provision/create-admin/all),
idempotent, creates the first admin via the Supabase Admin API (email_confirm),
flag > env > .env.local precedence, masked interactive prompts, --yes/--force.
- scripts/apply-migrations.sh + deploy/deploy.sh: reproducible, idempotent CD
glue (previously only on the prod droplet), tracked via public._migrations_applied.
- docker-compose.full.yml + .env.full.example: one-command app + self-hosted
Supabase bundle (compose config validated).
- docs/SINGLE_TENANT.md (deploy + CLI guide) and docs/CUSTOMIZE.md (the
documented lib/tenant.ts config pattern for white-labeling); README pointer.
- __tests__/tenant.test.ts: 19 unit tests for resolveTenantConfig + isMarketingPath.
Security (found by review, pre-existing):
- Drop the stale handle_space_signup() auth trigger, which derived member role
and space from client-controlled raw_user_meta_data and could self-insert an
admin. Membership is created only by the vetted server actions.
Migration scripts/056_drop_stale_signup_trigger.sql + folded into schema.sql.
Fixes:
- setup.mjs masked-password prompt hung (callback passed to readline/promises
question); use the awaited form.
- notifications-enqueue.test: base-URL default is now localhost (platform-domain
fallback removed), not hackerspace.sh.
- docs accuracy (logo/BrandMark, apply-migrations does not restart PostgREST, --yes).
Gates: tsc 0, lint 0 errors, 664 unit tests, build ok.