Skip to content

feat(config): add db.migrations.checks severities and exclusions (CLI-2782, CLI-2783) - #7312

Open
mdonnalley wants to merge 4 commits into
nextfrom
mikedonnalley/cli-2782-1-dbmigrationschecks-config-schema-absent-warn
Open

mdonnalley wants to merge 4 commits into
nextfrom
mikedonnalley/cli-2782-1-dbmigrationschecks-config-schema-absent-warn

Conversation

@mdonnalley

Copy link
Copy Markdown

Summary

Adds a [db.migrations.checks] section to config.toml. Each of the nine migration security
rules gets a severity (error, warn or off), and [db.migrations.checks.exclude] lists
"schema.name" objects to skip per rule. Nothing reads the policy yet; the migration apply
path consumes it in a follow-up.

  • Unknown rule names, invalid severities and malformed exclusion entries fail config loading
    with path-scoped messages, including a "did you mean" suggestion for misspelled rules. This
    section is stricter than the rest of the config so an older CLI never ignores a rule a
    teammate set.
  • An absent section leaves every rule unset; the CLI resolver treats unset rules as warn.
  • The section is published in the CLI config JSON Schema. CliConfig gains
    db.migrations.checks; the new constants are exported from @supabase/config/internal only.

Linked issue

Closes CLI-2782
Closes CLI-2783
Part of CLI-2786
Part of CLI-2787

@mdonnalley
mdonnalley requested a review from a team as a code owner October 23, 2026 16:39
: [
{
path: [key],
issue: `${key} must be "error", "warn" or "off" (got ${JSON.stringify(value)})`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚪ Severity: LOW

env(...) references are interpolated before this validator runs, so an invalid severity can resolve to a CI secret; embedding JSON.stringify(value) here carries that secret into the config-parse error shown on stderr. Captured build logs can expose credentials; malformed exclusion entries use the same value-echo path.
Helpful? Add 👍 / 👎

💡 Fix Suggestion

Suggestion: Don't echo the received value in the validation message. env(...) references are resolved before this validator runs, so the value may be a secret. Report only the expected values, for example <key> must be "error", "warn" or "off". Make the same change in exclusionIssues, where JSON.stringify(entry) is embedded in the message. Describe the problem there without the value, for example "must be a "schema.name" string". If a position helps debugging, include the array index instead of the value.

⚠️ Experimental Feature: This code suggestion is automatically generated. Please review carefully.

Suggested change
issue: `${key} must be "error", "warn" or "off" (got ${JSON.stringify(value)})`,
issue: `${key} must be "error", "warn" or "off"`,

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🤖 AI Review

Verified all four findings from both completed reviews. Confirmed the Go configuration compatibility regression, silent acceptance of non-table exclusions, and a documentation nit. Whitespace acceptance is verified, but whether it violates the intended naming contract remains uncertain. No findings overlap.

Findings

Severity Location Category Sources Claim
🔴 CRITICAL packages/config/src/db.ts:154 compatibility claude Using the newly advertised db.migrations.checks section breaks Go-delegated commands that load project configuration, including db diff --use-pg-schema.
🟡 MINOR packages/config/src/db-migration-checks.ts:125 config-validation codex Non-table objects such as Date instances can be silently accepted as an empty exclusion table.
⚪ NIT packages/config/src/db-migration-checks.ts:50 validation claude The object-name pattern permits whitespace immediately before the separator, potentially allowing typoed exclusions such as public .countries.
⚪ NIT packages/config/src/db-migration-checks.ts:81 docs claude The published description's wording, "Runs against --db-url read this section from config.toml only," is awkward and could be clearer.

Stats

Claude findings: 3 · Codex findings: 1 · Confirmed: 3 · Refuted: 0 · Uncertain: 1


Models: claude-opus-5-5 + gpt-6.1-sol · Trigger: auto · Workflow run

This review runs once per PR. A maintainer can request another with a /ai-review comment.

Comment thread packages/config/src/db.ts
tags,
})
.pipe(Schema.withDecodingDefaultKey(Effect.succeed([...defaultSchemaPaths]))),
checks: Schema.optionalKey(MigrationChecks),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔴 CRITICAL · compatibility · source: claude

Using the newly advertised db.migrations.checks section breaks Go-delegated commands that load project configuration, including db diff --use-pg-schema.

Evidence: packages/config/src/db.ts:154 accepts checks. apps/cli-go/pkg/config/db.go:100-103 has no corresponding field. apps/cli-go/pkg/config/config.go:587-620 loads config.toml without removing checks, then :816-823 calls UnmarshalExact and returns unknown-key errors. apps/cli-go/internal/utils/flags/db_url.go:65-93 loads this configuration for direct, local, and linked database targets.

Suggested fix: Add a parsed-but-unused Checks map[string]any field with toml:"-" and json:"checks" tags to the Go migrations struct, following the existing Compute/Local pattern. Test configuration loading with base and remote checks sections.

Comment on lines +125 to +126
const isPlainObject = (value: unknown): value is Readonly<Record<string, unknown>> =>
typeof value === "object" && value !== null && !Array.isArray(value);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 MINOR · config-validation · source: codex

Non-table objects such as Date instances can be silently accepted as an empty exclusion table.

Evidence: packages/config/src/db-migration-checks.ts:125-126 accepts Date objects; :151-156 reports no issues for objects without enumerable properties; :199-211 normalizes them to an empty object. Additionally, packages/config/src/lib/env.ts:236-242 converts such objects to plain empty objects before the loader validates them at io.ts:675.

Suggested fix: Require a plain record in the exclusion validator and preserve non-plain objects during environment interpolation so schema validation can reject them. Add a loader test rejecting a TOML datetime assigned to exclude.

const Severity = Schema.Literals(SEVERITIES);

// Only the first dot separates schema from name; whitespace is allowed inside either.
const ObjectName = Schema.String.check(Schema.isPattern(/^(?!\s)[^.]+\.[\s\S]*\S(?![\s\S])/u));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚪ NIT · validation · source: claude

The object-name pattern permits whitespace immediately before the separator, potentially allowing typoed exclusions such as public .countries.

Evidence: packages/config/src/db-migration-checks.ts:49-50 checks whitespace only at the outer string boundaries. Focused checks against the published pattern accepted public .countries, public\t.t, and public. t. Tests at db-migration-checks.unit.test.ts:146-172 cover internal spaces and outer boundaries but omit separator-adjacent whitespace.

Suggested fix: Clarify whether whitespace at component boundaries is supported, then add separator-adjacent cases and enforce the intended rule.

Adjudication (uncertain): Acceptance of the examples is verified. However, the resolver merely forwards object strings at apps/cli/src/command-internal/migration-checks-policy.ts:29-30, and no matching implementation or trusted contract establishes that separator-adjacent whitespace must be invalid. The claimed inevitable failure to match therefore cannot be confirmed.

),
}).annotate({
description:
'Security checks run on each migration. Each rule takes "error", "warn" or "off"; a rule left unset uses "warn". Runs against --db-url read this section from config.toml only.',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚪ NIT · docs · source: claude

The published description's wording, "Runs against --db-url read this section from config.toml only," is awkward and could be clearer.

Evidence: packages/config/src/db-migration-checks.ts:80-81 contains this sentence. apps/docs/public/cli/config.schema.json:1970 and :4799 publish the same wording.

Suggested fix: Reword to: "When migrations run against --db-url, this section is read only from the local config.toml."

Comment thread .github/workflows/cli-go-ci.yml Outdated
- run: |
set -o pipefail
pkgs=$(go list ./pkg/... | grep -Ev 'pkg/api' | paste -sd ',' -)
pkgs=$(go list -C pkg ./... | grep -Ev 'pkg/api' | paste -sd ',' -)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why is it necessary ? Should we base this on next branch that remove Go entirely ? Since we're aiming for post Nov 2 for this feature.

…-2782, CLI-2783)

Adds the [db.migrations.checks] table with per-rule severities and per-rule
exclusion lists. Rule names, severities and exclusion entries are validated with
path-scoped messages, and the section is published in the CLI config JSON Schema.
A CLI policy resolver defaults unset rules to warn.
Exclusion entries reject whitespace next to the schema separator, and the --db-url note
in the section description is reworded.
@mdonnalley
mdonnalley changed the base branch from develop to next October 26, 2026 17:50
@mdonnalley
mdonnalley force-pushed the mikedonnalley/cli-2782-1-dbmigrationschecks-config-schema-absent-warn branch from ef79030 to 46072c9 Compare October 26, 2026 17:51
@mdonnalley
mdonnalley enabled auto-merge October 26, 2026 18:45

This branch has not been deployed

No deployments
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.

2 participants