feat: supabase-only self-hosting with guided setup wizard - #108
Merged
Conversation
Phase B of the OSS-ready program. Local development now targets any Supabase project, not the owner's: - dev-worker-config validates a project-agnostic session-pooler shape (any project ref; host/port/database/ref equality across the three role URLs) instead of hard-pinning one production project - scripts/local-env-contract.ts extracts the env contract shared by dev and setup; scripts/setup-keys.ts makes missing key metadata a compile error - migration 0003_target_parity installs the vector and pg_stat_statements extensions and revokes all Data-API-role and implicit-PUBLIC access, current and default, so the post-apply target assertion passes on fresh projects exactly as on production; the supabase-target contract gains schema-privilege and effective-default-ACL checks scoped to postgres-owned ACLs (supabase_admin default ACLs are platform-managed) - pnpm dev:setup: guided clack wizard — preflight, prompts with validation and generated secrets, atomic 0600 env writes (bare values; control chars, edge whitespace, leading quotes, '#', and '$' rejected as unrepresentable across dotenv parsers), confirm-before-write, migrations via a sanitized child env, role-password and Vault provisioning on the admin connection, pooler-login and signed-context probes reusing the production signer, and an optional force-recreated stack start; --check doctor mode is read-only - 0000 baseline revised: the unrunnable supabase_admin default-ACL recreations (denied 42501 on every Supabase project; platform state that already exists everywhere) are removed with an explanatory comment; the one-time production ledger hash update and the remedy for any stray environment are documented in packages/db/README.md - README rewritten as a public front page; CONTRIBUTING added; env examples neutralized (no production identifiers)
iamjr15
force-pushed
the
oss/phase-b-selfhost
branch
from
July 31, 2026 18:19
b62dece to
ee04c4b
Compare
2 tasks
iamjr15
added a commit
that referenced
this pull request
Jul 31, 2026
Two checker corrections found by the first post-Wave-B `--apply` against production (the assertion had not run since the contract was tightened). Both live-probe-verified on production AND a fresh 2026 project: 1. **63-byte truncation**: the runtime-ACL union's first branch selected `relname` (type `name`), so the union resolved `object_name` to `name` and truncated every function signature past 63 bytes — the six long-signature `webhooks_*` functions could never match the expected set. One-line `::text` cast. 2. **supautils auto-membership**: every role `postgres` creates is granted back to `postgres` (grantor `supabase_admin`) on every Supabase project — verified by creating a probe role on a fresh project. The zero-membership check now exempts exactly `app_* → postgres` and flags all else. ## Verification notes - [x] `pnpm lint` / `pnpm typecheck` - [x] Live `pnpm db:migrate -- --dry-run` against production with the fixed checker: **"Production schema contract verified."** with 0000 baselined and 0001/0002/0003 applied. (DB-state note recorded in the PR trail: the one-time 0000 ledger-hash update documented in #108 was executed before the apply; two stale `max`-tier entitlement rows were normalized to `premium` to satisfy 0001's CHECK constraint.)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase B of the OSS-ready program: self-hosting becomes real. Local development targets any Supabase project (free tier suffices) instead of hard-pinning the owner's production database, and
pnpm dev:setupwalks a contributor from a fresh clone to a verified running stack.scripts/dev-worker-config.tsaccepts any Supabase session pooler (host pattern, port 5432, exact TLS params,<role>.<projectRef>usernames, host/port/db/ref equality across the three role URLs). The previous production coordinates pass unchanged.scripts/local-env-contract.ts) extracted fromdev.tsbehavior-neutrally; wizard key metadata is compile-time exhaustive.0003_target_parity: installsvector+pg_stat_statements, revokes all Data-API-role and implicit-PUBLIC access (current + default ACLs) so the post-apply target assertion passes on fresh projects exactly as on production. Contract gains schema-privilege and effective-default-ACL checks scoped topostgres-owned ACLs.pnpm dev:setup: preflight → guided prompts (Supabase/Clerk/Daytona/optional groups) with generated secrets → confirm → atomic 0600 env writes (bare values;#,$, quotes, edge whitespace, control chars rejected as unrepresentable across dotenv parsers) → migrations via sanitized child env → role passwords + Vault rows on the admin connection → pooler-login and signed-context probes (production signer reused) → optional force-recreated stack start.--checkis a zero-mutation doctor.The 0000 baseline was revised to delete twelve
supabase_admindefault-ACL recreations that are denied with SQLSTATE 42501 on every Supabase project (verified live on production AND on a fresh 2026 project) and that recreate platform state which already exists everywhere. Production baselined 0000 without executing it, so its ledger row must be updated once:followed immediately by
pnpm db:migrate -- --dry-runproving no divergence and 0001/0002/0003 pending. The remedy for any stray environment is documented inpackages/db/README.md. Alternatives (engine-side superseded-checksum compat map; reverting the baseline) were evaluated and declined — the revert resurrects the fresh-project blocker, and compat machinery violates the repo's no-legacy rule.Verification notes
pnpm lint/pnpm typecheck/pnpm turbo build --force/pnpm deadcode/pnpm architecture:check/pnpm turbo skills:build— independent clean-install reruns, all green--dry-runreview +--apply(0001/0002/0003), then a fullpnpm dev:setupe2e against a throwaway free-tier project (already created) with an authenticated browser flow, re-run preservation test, and--check.