Skip to content

Commit ee04c4b

Browse files
committed
feat: supabase-only self-hosting with guided setup wizard
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)
1 parent 143f861 commit ee04c4b

24 files changed

Lines changed: 2326 additions & 518 deletions

.env.example

Lines changed: 32 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,53 @@
1-
# Root .env.local is the only local application credential file. Local Workers
2-
# use the production Supabase database through its public session pooler and the
3-
# same three least-privilege roles as production Hyperdrive. Keep each password
4-
# identical to the password configured on only its matching production role.
5-
# Administrative migration credentials belong in .env.migrate, never here.
6-
SUPABASE_GATEWAY_DATABASE_URL=postgresql://app_gateway.snqtclnmhcaupqynjyux:replace_with_gateway_role_password@aws-0-ap-south-1.pooler.supabase.com:5432/postgres?sslmode=require&uselibpqcompat=true
7-
SUPABASE_AGENT_DATABASE_URL=postgresql://app_agent.snqtclnmhcaupqynjyux:replace_with_agent_role_password@aws-0-ap-south-1.pooler.supabase.com:5432/postgres?sslmode=require&uselibpqcompat=true
8-
SUPABASE_WEBHOOKS_DATABASE_URL=postgresql://app_webhooks.snqtclnmhcaupqynjyux:replace_with_webhooks_role_password@aws-0-ap-south-1.pooler.supabase.com:5432/postgres?sslmode=require&uselibpqcompat=true
1+
# Run `pnpm dev:setup` to create the permission-restricted .env.local file. These
2+
# neutral placeholders document the contract; do not hand-edit pooler URLs when
3+
# the wizard can assemble and validate them for you.
94

10-
# Clerk development instance. These test keys are for this laptop only; every
11-
# Vercel environment uses the production Clerk instance.
12-
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_replace_me
13-
CLERK_SECRET_KEY=sk_test_replace_me
14-
# The seven optional Clerk/Composio/Daytona/Polar webhook, integration, and checkout keys may stay empty; affected local paths return 503.
15-
CLERK_WEBHOOK_SIGNING_SECRET=
5+
# Supabase session pooler only: *.pooler.supabase.com, port 5432, /postgres,
6+
# and the role-qualified username <role>.<project-ref>. A free dedicated
7+
# Supabase project is sufficient. Administrative credentials stay in
8+
# .env.migrate and never enter the application environment.
9+
SUPABASE_GATEWAY_DATABASE_URL=postgresql://app_gateway.<project-ref>:<generated-role-password>@<region-pooler-host>.pooler.supabase.com:5432/postgres?sslmode=require&uselibpqcompat=true
10+
SUPABASE_AGENT_DATABASE_URL=postgresql://app_agent.<project-ref>:<generated-role-password>@<region-pooler-host>.pooler.supabase.com:5432/postgres?sslmode=require&uselibpqcompat=true
11+
SUPABASE_WEBHOOKS_DATABASE_URL=postgresql://app_webhooks.<project-ref>:<generated-role-password>@<region-pooler-host>.pooler.supabase.com:5432/postgres?sslmode=require&uselibpqcompat=true
1612

17-
# Browser-visible local routing configuration; these values are not secrets.
18-
# The real preview-proxy Worker is service-bound behind the
19-
# gateway and serves each sandbox on *.localhost:8787. No second preview domain
20-
# or cloud development deployment is required.
13+
# Clerk development instance. Production keys are rejected locally. Configure
14+
# the Clerk session token to expose metadata={{user.public_metadata}}.
15+
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_<clerk-publishable-key>
16+
CLERK_SECRET_KEY=sk_test_<clerk-secret-key>
17+
CLERK_WEBHOOK_SIGNING_SECRET=
2118
NEXT_PUBLIC_GATEWAY_URL=http://127.0.0.1:8787
2219

23-
# Daytona development access.
24-
DAYTONA_API_KEY=
20+
# Daytona development access. DAYTONA_SANDBOX_SNAPSHOT is an immutable snapshot
21+
# built from infra/containers/sandbox. The webhook secret is required; unlike
22+
# optional provider groups, it may not stay empty.
23+
DAYTONA_API_KEY=<daytona-api-key>
2524
DAYTONA_API_URL=https://app.daytona.io/api
2625
DAYTONA_PREVIEW_HOST_SUFFIXES=daytonaproxy01.net,proxy.daytona.work
27-
# Required: set an explicit development snapshot so local startup can never
28-
# inherit the production snapshot from the committed Worker configuration.
29-
DAYTONA_SANDBOX_SNAPSHOT=
26+
DAYTONA_SANDBOX_SNAPSHOT=<immutable-snapshot-name>
3027
DAYTONA_TARGET=us
3128
DAYTONA_WORKSPACE_VOLUME=cheatcode-workspaces-development
32-
DAYTONA_WEBHOOK_SIGNING_SECRET=
33-
PREVIEW_TOKEN_SECRET=replace_with_a_distinct_32_byte_secret
34-
# Optional when the Daytona account requires an explicit organization.
29+
DAYTONA_WEBHOOK_SIGNING_SECRET=<daytona-webhook-signing-secret>
3530
DAYTONA_ORG_ID=
3631

37-
# Agent providers and integrations.
32+
# Optional integrations. Skipping Composio disables connected apps; skipping
33+
# DeepSeek means users rely on BYOK for that provider.
3834
COMPOSIO_API_KEY=
3935
COMPOSIO_AUTH_CONFIGS=
4036
COMPOSIO_WEBHOOK_SECRET=
41-
# Optional platform fallback; users can rely on BYOK instead.
4237
DEEPSEEK_PLATFORM_API_KEY=
4338

44-
# Polar local development always uses the sandbox account.
39+
# Optional Polar sandbox billing. Skipping this group disables local checkout
40+
# and billing webhooks while core agent flows remain available.
4541
POLAR_ACCESS_TOKEN=
4642
POLAR_SERVER=sandbox
4743
POLAR_WEBHOOK_SECRET=
4844
POLAR_PRODUCT_ID_PRO=
4945
POLAR_PRODUCT_ID_PREMIUM=
5046

51-
# Internal local contracts.
52-
DATABASE_CONTEXT_SIGNING_SECRET_AGENT=replace_with_a_distinct_32_byte_secret
53-
DATABASE_CONTEXT_SIGNING_SECRET_GATEWAY=replace_with_a_distinct_32_byte_secret
54-
DATABASE_CONTEXT_SIGNING_SECRET_WEBHOOKS=replace_with_a_distinct_32_byte_secret
55-
OUTPUT_DOWNLOAD_SIGNING_SECRET=replace_with_a_distinct_32_byte_secret
47+
# Generated by `pnpm dev:setup`; each value is at least 32 bytes. Values within the
48+
# two documented distinctness groups are never reused.
49+
DATABASE_CONTEXT_SIGNING_SECRET_AGENT=<generated-by-pnpm-dev-setup>
50+
DATABASE_CONTEXT_SIGNING_SECRET_GATEWAY=<generated-by-pnpm-dev-setup>
51+
DATABASE_CONTEXT_SIGNING_SECRET_WEBHOOKS=<generated-by-pnpm-dev-setup>
52+
PREVIEW_TOKEN_SECRET=<generated-by-pnpm-dev-setup>
53+
OUTPUT_DOWNLOAD_SIGNING_SECRET=<generated-by-pnpm-dev-setup>

.env.migrate.example

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
# Copy to .env.migrate only on an authorized operator workstation. This file
2-
# targets the production Supabase database and is never loaded by the app,
3-
# Compose, Wrangler, Next.js, or any Worker.
4-
SUPABASE_MIGRATION_URL=postgresql://postgres:replace_with_production_admin_password@db.snqtclnmhcaupqynjyux.supabase.co:5432/postgres?sslmode=require
5-
SUPABASE_MIGRATION_EXPECTED_HOST=db.snqtclnmhcaupqynjyux.supabase.co
1+
# Generated by `pnpm dev:setup` from a direct or session-pooler Supabase admin
2+
# connection. Keep this file on an authorized workstation only; the app never
3+
# loads it. Placeholders are intentionally project-neutral.
4+
SUPABASE_MIGRATION_URL=postgresql://postgres:<admin-password>@db.<project-ref>.supabase.co:5432/postgres?sslmode=require
5+
SUPABASE_MIGRATION_EXPECTED_HOST=db.<project-ref>.supabase.co
66
SUPABASE_MIGRATION_EXPECTED_DATABASE=postgres
77
SUPABASE_MIGRATION_EXPECTED_ROLE=postgres
8-
SUPABASE_MIGRATION_EXPECTED_SYSTEM_IDENTIFIER=replace_with_pg_control_system_identifier
8+
SUPABASE_MIGRATION_EXPECTED_SYSTEM_IDENTIFIER=<pg-control-system-identifier>

.github/assets/cheatcode-home.png

432 KB
Loading

CONTRIBUTING.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Contributing to Cheatcode
2+
3+
Thanks for helping improve Cheatcode. Read [AGENTS.md](AGENTS.md) before making
4+
changes; it is the canonical architecture, security, and coding guide for
5+
people and coding agents.
6+
7+
## Set up the repository
8+
9+
Use the exact Node and pnpm versions declared in `package.json`, then run:
10+
11+
```bash
12+
nvm install
13+
nvm use
14+
corepack enable
15+
CI=true pnpm install
16+
pnpm dev:setup
17+
```
18+
19+
The guided wizard creates the ignored `.env.local` and `.env.migrate` files,
20+
prepares a dedicated Supabase project, verifies all three runtime database
21+
roles, and can start the Compose stack. A free Supabase project is sufficient.
22+
You also need Clerk development keys and a Daytona API key plus an immutable
23+
sandbox snapshot built from `infra/containers/sandbox`.
24+
25+
Never commit either env file, real credentials, database dumps, or sanitized
26+
copies of secrets. Never run a migration apply against a target you have not
27+
positively identified and reviewed. Migration files are append-only.
28+
29+
Run `pnpm dev:setup --check` for a read-only check of the host, environment,
30+
migration ledger, database connectivity, and signed-context probes.
31+
32+
## Make changes
33+
34+
- Preserve package and application ownership boundaries.
35+
- Read the relevant README before changing a public export, database contract,
36+
deployment topology, sandbox boundary, or environment surface.
37+
- Use pnpm and Turborepo; do not substitute npm or Yarn.
38+
- Keep unrelated worktree changes intact.
39+
- Follow the strict TypeScript and naming conventions in `AGENTS.md`.
40+
41+
To change or rotate local role passwords, signing secrets, or provider values,
42+
rerun `pnpm dev:setup` and replace the relevant prompted values. Existing values are
43+
preserved by default, missing values are generated, and the idempotent migration,
44+
Vault provisioning, and probe sequence resumes safely. There is intentionally no
45+
separate secret-rotation command.
46+
47+
## Verify changes
48+
49+
Run the full final-tree gate chain before requesting review:
50+
51+
```bash
52+
pnpm lint
53+
pnpm typecheck
54+
pnpm turbo build --force
55+
pnpm deadcode
56+
pnpm architecture:check
57+
pnpm turbo skills:build
58+
```
59+
60+
For user-visible or integration behavior, also exercise the real flow with
61+
`agent-browser --auto-connect --session cheatcode-debug`. Inspect screenshots,
62+
the browser console, network activity, and application logs. Do not add a
63+
parallel browser or product-flow test harness.
64+
65+
Every pull request must include verification notes listing commands run, real
66+
flows exercised, and any omitted check with its reason.
67+
68+
## Commits and pull requests
69+
70+
Use Conventional Commits, for example:
71+
72+
```text
73+
feat(agent): add a research tool
74+
fix(db): preserve tenant context on retry
75+
docs(setup): clarify Daytona snapshots
76+
```
77+
78+
Keep commit subjects and human-authored pull request titles on one line and at
79+
or below 72 characters. Explain why the change is needed, call out migration or
80+
architecture effects, and include the verification notes above.
81+
82+
By contributing repository-owned code, you agree that it is provided under the
83+
root [LICENSE](LICENSE). Assets and third-party materials remain subject to
84+
[NOTICE](NOTICE).

0 commit comments

Comments
 (0)