feat(tenant): setup CLI, CD glue, bundled compose, docs + security fix
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.
This commit is contained in:
@@ -148,11 +148,15 @@ describe('buildManageUrl', () => {
|
||||
expect(buildManageUrl('example.test')).toBe('https://example.test/me')
|
||||
})
|
||||
|
||||
it('falls back to NEXT_PUBLIC_APP_URL then to the prod default', () => {
|
||||
it('falls back to NEXT_PUBLIC_APP_URL then to the configured default', () => {
|
||||
process.env.NEXT_PUBLIC_APP_URL = 'https://my.test'
|
||||
expect(buildManageUrl(null)).toBe('https://my.test/me')
|
||||
delete process.env.NEXT_PUBLIC_APP_URL
|
||||
expect(buildManageUrl(null)).toBe('https://hackerspace.sh/me')
|
||||
// With no host header and no NEXT_PUBLIC_APP_URL set, buildManageUrl now
|
||||
// resolves through appBaseUrl(), whose default is localhost (the old
|
||||
// hardcoded https://hackerspace.sh fallback was removed so a fork/instance
|
||||
// never leaks the platform domain into its emails).
|
||||
expect(buildManageUrl(null)).toBe('http://localhost:3000/me')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user