Skip to content

feat(cli): apply local stack configuration parity - #6092

Open
jgoux wants to merge 47 commits into
agent/stack-package-export-auditfrom
agent/local-stack-launch-adapter
Open

feat(cli): apply local stack configuration parity#6092
jgoux wants to merge 47 commits into
agent/stack-package-export-auditfrom
agent/local-stack-launch-adapter

Conversation

@jgoux

@jgoux jgoux commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Builds one deep launch adapter that resolves project config, environment bindings, remote overrides, exclusions, database bootstrap inputs, and functions into explicit stack runtime inputs.

Adds an executable parity ledger so unsupported local-start settings fail or warn deliberately instead of being silently ignored. Implements core topology, Auth and credential translation, data-plane services, ordered seed bootstrap, and functions configuration while preserving lazy Edge Runtime activation and secure JWKS-based verification.

Conventional migrations remain blocked when enabled migration files are present, and declarative schema paths remain blocked. Replaying either through a partial executor would lose legacy statement-history, pipeline, or schema-diff semantics; those settings should only be enabled after a parity-correct executor exists.

Depends on #6090 and #6079.

jgoux added 30 commits August 5, 2026 14:52
# Conflicts:
#	packages/stack/src/StackBuilder.ts
#	packages/stack/src/StackBuilder.unit.test.ts
#	packages/stack/src/services/analytics.ts
#	packages/stack/src/services/auth.ts
#	packages/stack/src/services/mailpit.ts
#	packages/stack/src/services/postgres.ts
#	packages/stack/src/services/postgrest.ts
#	packages/stack/src/services/realtime.ts
#	packages/stack/src/services/services.unit.test.ts
#	packages/stack/src/services/storage.ts
#	packages/stack/src/services/studio.ts
…k-launch-adapter

# Conflicts:
#	packages/stack/docs/architecture.md
#	packages/stack/src/LocalStack.ts
…l-stack-launch-adapter

# Conflicts:
#	apps/cli/src/next/config/local-stack-config-parity.ts
#	apps/cli/src/next/config/local-stack-config-parity.unit.test.ts
jgoux added 17 commits August 5, 2026 20:50
…l-stack-launch-adapter

# Conflicts:
#	apps/cli/src/next/config/local-stack-config-parity.ts
#	apps/cli/src/next/config/local-stack-config-parity.unit.test.ts
…l-stack-launch-adapter

# Conflicts:
#	apps/cli/src/next/config/local-stack-config-parity.ts
#	apps/cli/src/next/config/local-stack-config-parity.unit.test.ts
…upabase/cli into agent/local-stack-launch-adapter

# Conflicts:
#	apps/cli/src/next/config/local-stack-config-parity.ts
#	apps/cli/src/next/config/local-stack-config-parity.unit.test.ts
…upabase/cli into agent/local-stack-launch-adapter

# Conflicts:
#	apps/cli/src/next/config/local-stack-config-parity.ts
#	apps/cli/src/next/config/local-stack-config-parity.unit.test.ts
…' into agent/local-stack-launch-adapter

# Conflicts:
#	packages/stack/src/services/health-budgets.ts
#	packages/stack/src/services/health-budgets.unit.test.ts
@jgoux
jgoux marked this pull request as ready for review August 5, 2026 20:09
@jgoux
jgoux requested a review from a team as a code owner August 5, 2026 20:09

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 48c1da6e1c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +101 to +103
elif [ "$applied_hash" != "$checksum" ]; then
echo "Updating seed hash to $history_path..."
update_seed_hash "$history_path" "$checksum"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Re-run dirty seed SQL before updating its hash

When a seed already exists in supabase_migrations.seed_files with a different checksum, this branch only updates the stored hash and never calls apply_seed. In a reused local stack after editing supabase/seed.sql, the database does not receive the new SQL, but the hash is advanced so future starts consider it applied; dirty seeds need to execute the seed batch before recording the new checksum.

Useful? React with 👍 / 👎.

Comment on lines +43 to +47
if (loaded.appliedRemote === undefined || loaded.document === undefined) return false;
const remotes = nestedValue(loaded.document, ["remotes"]);
if (!isRecord(remotes)) return false;
const remote = remotes[loaded.appliedRemote];
return isRecord(remote) && nestedValue(remote, path) !== undefined;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve remote DB bootstrap precedence

Real loadProjectConfigFile removes the remotes subtree after merging the selected remote, so loaded.document.remotes is absent for an applied remote and remoteDefines() returns false. With a remote that sets db.seed.enabled or db.migrations.enabled and a conflicting SUPABASE_DB_* env var, the env var wins and can enable seeds or migration discovery that the selected remote disabled; consult loaded.remoteOverridePaths instead of the stripped document.

Useful? React with 👍 / 👎.

Comment on lines +120 to +123
if (secret.length < 32) {
throw new LocalCredentialsError({
path,
detail: "The local JWT shared secret must contain at least 32 characters.",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Accept Go-compatible JWT secrets

Configs with auth.jwt_secret between 16 and 31 characters are accepted by the Go CLI, but this new credentials resolver rejects them before the stack starts. Since translateAuthStackConfig now passes the project auth.jwt_secret into credentials.signing, existing local configs in that range regress; lower this threshold to the Go-compatible 16-character minimum or reject it earlier as an intentional parity break.

Useful? React with 👍 / 👎.

Comment on lines +304 to +305
return Object.fromEntries(
Object.entries(input.external).map(([name, provider]) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve custom Auth providers

For [auth.external.<custom>] entries, Go keeps the provider in its external-provider map, but the project schema does not expose unknown provider ids on ProjectConfig["auth"]["external"]. Iterating only input.external therefore drops a configured custom provider, so local Auth starts without a provider the user configured; include or explicitly block raw authDocument.external keys that are not in the schema-known set.

Useful? React with 👍 / 👎.

Comment on lines +38 to +41
const gcp =
enabled && backend === "bigquery"
? {
projectId: required(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Skip BigQuery checks when analytics is excluded

When a project has analytics.enabled = true and backend = "bigquery" but the user launches with --exclude analytics, resolveCoreStackConfig passes base.analytics = false, yet this branch still requires the BigQuery GCP fields before honoring input.base === false. That makes an intentionally excluded analytics service abort startup because of missing credentials for a service that will not run; return false before validating analytics-only settings.

Useful? React with 👍 / 👎.

envBoolean({
loaded: input.loadedProjectConfig,
environment: input.projectEnvironment,
configured: smtpDocument.enabled === undefined ? true : auth.email.smtp?.enabled === true,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Respect an omitted SMTP enabled flag

When the raw [auth.email.smtp] table is present but enabled is omitted, this forces SMTP on even though the decoded config default is enabled = false and Go only validates/uses SMTP when that flag is true. A config that merely declares the table or leaves commented examples partially uncommented now requires host/port/user/pass and changes Auth behavior; use the decoded auth.email.smtp?.enabled value unless an environment override explicitly enables SMTP.

Useful? React with 👍 / 👎.

Comment on lines +359 to +366
uri: envString({
loaded: input.loaded,
environment: input.environment,
path: `auth.hook.${name}.uri`,
configured: hook.uri,
enabled: sectionPresent,
}),
secrets: envString({

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate enabled Auth hooks before exporting them

When an auth.hook.* entry is enabled, Go rejects configs with no uri, and HTTP/HTTPS hooks also require secrets. This mapper just forwards undefined values as empty Auth env vars, so an enabled-but-incomplete hook can start Auth with invalid hook settings instead of failing during config translation; apply the same validation before returning the hook.

Useful? React with 👍 / 👎.

Comment on lines +601 to +606
enableSignup: envBoolean({
loaded: input.loadedProjectConfig,
environment: input.projectEnvironment,
configured: auth.sms.enable_signup,
path: "auth.sms.enable_signup",
}),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Disable phone signup without an SMS provider

When auth.sms.enable_signup is true but none of the SMS providers is enabled, Go's validation warns and flips phone signup back to false. This translation preserves the true value while resolveSmsProvider() returns undefined, causing Auth to receive phone signup enabled with no provider configured; mirror the Go fallback before building the Auth config.

Useful? React with 👍 / 👎.

mode,
startupMode: "lazy",
startupMode,
edgeRuntime: excluded.has("edge-runtime") ? false : {},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep Edge Runtime off for native launches

For --mode native with the other docker-only services disabled, setting edgeRuntime to {} prevents StackConfigResolver's native-mode default from disabling Edge Runtime when it is unspecified. The resolved config then includes the docker-only Edge Runtime and StackBuilder rejects the launch unless users also add --exclude edge-runtime; leave this field undefined in native mode unless explicitly requested.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant