Uh oh!
There was an error while loading. Please reload this page.
docs(config): document the CliConfig/ProjectConfig/CliSettings naming convention - #6335
Merged
Coly010 merged 3 commits intoAug 26, 2026
Conversation
… convention (CLI-2238)
Contributor
Supabase CLI previewnpx --yes https://pkg.pr.new/supabase/cli/supabase@bb51e41fce93a9268d7edb6a9438e49ebdbe3527Preview package for commit |
…the prefix rule (CLI-2238)
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit:fe03566f0f
ℹ️ 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".
Uh oh!
There was an error while loading. Please reload this page.
…nds (review: codex P2)
jgoux
approved these changes
Aug 26, 2026
Uh oh!
There was an error while loading. Please reload this page.
Coly010
deleted the
columferry/cli-2238-document-the-supabaseconfig-naming-convention-cliconfig
branch
August 26, 2026 10:32
pullBot
pushed a commit
to oogalieboogalie/cli
that referenced
this pull request
Aug 27, 2026
… (CLI-2230) (supabase#6339) ## What changed Implements [CLI-2230](https://linear.app/supabase/issue/CLI-2230/create-a-toprojectconfig-function-that-is-exported-from-the-config): the hosted-project subset type `ProjectConfig` and its normalizers, exported from `@supabase/config`'s pure (browser-safe) entrypoint so the CLI and Studio share one mapper. - **`fromConfigDocument(config)`** — projection of a `CliConfig` document (or any `EffectiveConfig`) down to the hosted sections (`api`, `auth`, `db`, `realtime`, `storage`, `workers`, `experimental`). - **`fromApiProjectConfig(input)`** — translation of a Management API v2 project-config response (full envelope, `data` object, or bare `data.attributes`). Registry-driven: 233 mapping rows mined from the legacy `config push` sync mappers (`config-sync/*.sync.ts`), covering renames (`rate_limit_otp` → `sign_in_sign_ups`), boolean inversions (`disable_signup`, `mailer_autoconfirm`), unit conversions (seconds/hours → Go duration strings, int64 bytes → BytesSize), the GoTrue key table (19 OAuth providers, 6 hooks, 5 SMS providers), and `x-secret` omission (the API only reports HMAC digests). Decode is lenient per ADR 0019 — unknown/API-ahead keys never fail; the raw attributes ride along as a **non-enumerable `_apiResponse`** (invisible to encodes, spreads, and structural walks; never persisted), with a registry-derived `unmappedApiFields()` reader. - **`toProjectConfig(source)`** — thin dispatcher over both (`{ cliConfig }` / `{ apiResponse }`). ### Operand widening (ruling on CLI-2230) `ProjectConfig` is deliberately **sparse** — an API response never mentions sections it doesn't manage, and flooding in schema defaults would fabricate drift. To make it a first-class operand of the comparison core, `BaseCliConfig` is replaced by the family-neutral `EffectiveConfig = DeepPartial<Omit<CliConfig, "remotes">>` on `subtractCliConfig`/`omitDefaultValues`. No runtime change — the subtraction walk already had the right absence semantics. Recorded in ADR 0018's 2026-08-26 addendum; the naming-rule generalization lands separately with CLI-2238 (supabase#6335). ### apps/cli - A type-drift guard (`project-config-api-drift.unit.test.ts`) pins the generated `V2GetProjectConfigOutput` attributes against the package's lenient input schema: assignability (catches type widening) plus per-section key-set assertions (catch added/removed/renamed fields) — so OpenAPI drift fails compile before it can silently break the mapping. No runtime dependency on `packages/api` was added. - `ProjectConfigParseError` registered in the error-actionability table as `apiStatus` (a malformed platform response, not a user config mistake). ### Reviewer notes - Deliberate divergences from the legacy apply semantics are documented inline where they occur: API `null` → omit (sparse output has no local document to fall back to), `uri_allow_list` trimming, `smtp_host: ""` treated as disabled, `sms_autoconfirm` **not** inverted (matches `auth.sync.ts:1677/:2485` — only the mailer counterpart inverts). - An explicit `db_schema: ""` maps to `{ api: { enabled: false } }` only, mirroring `applyRemoteApiConfig`'s early return; an *absent* `db_schema` doesn't gate the sibling fields. - Follow-up candidate deliberately not in this PR: a parity test pinning the replicated legacy helpers (duration/BytesSize/parseUint16/envToMap/password charsets) against their `apps/cli` originals. (ADR 0019's attach helper *did* land in the second round below, as `attachApiResponse`.) ### Second review round (commit 93b4679) — adjudication record A two-set review (architect/engineer/security/DX + adversarial execution) ran against bdd607f. The registry mapping itself survived three independent verification passes with zero defects; every accepted finding about the surrounding surface is fixed in 93b4679: - **Secrets**: `fromConfigDocument` now deep-copies and omits every `x-secret` leaf (schema-derived, `lib/secret-paths.ts`) — decoded documents hold plaintext credentials, and the subtract composition rendered them as drift. - **Spelling convergence**: new registry `normalizeDocument` column canonicalizes document-side duration and byte-size spellings so both normalizers emit one form for one logical value. - **Leniency**: the mirror schema types every never-mapped field `Schema.Unknown`, so a platform type change on a field nothing reads can no longer fail every decode. - **Errors**: `ProjectConfigParseError` gained `message`/`detail`/`suggestion` (upgrade-then-report), schema-issue paths lift into `apiPath`, telemetry adds `fingerprint_suffix: "api_response"` + `has_suggestion`. - **Type-mismatch unification**: string rows, `smtp_host`/`smtp_port`, and CIDR entries now throw typed errors instead of fabricating values (`enabled: false`), vanishing silently, or partially filtering a security allowlist; `expectNumber` rejects non-finite. - **`_apiResponse`**: cloned + deep-frozen at attach (no caller aliasing); `attachApiResponse` export restores it across spread/clone round-trips; invisibility claim narrowed (serializers and walks — debug inspectors like Bun's `console.log` still print it; never log an API-sourced config). - **`unmappedApiFields`**: recursion depth cap; `unmappedSecretApiPaths` deny list (`external_figma_secret` — the one genuine orphan digest; the review's other two candidates don't exist in the legacy source). - **New guards/exports**: `registry-integrity.unit.test.ts` (all 233 rows' paths resolve against the schema ASTs, 470 generated cases); drift-guard key-set levels completed; `comparableProjectConfigPaths`/`isComparableProjectConfigPath` so diff consumers never hand-maintain field lists; `inverse` implementations dropped until the push mapper derives them. **Explicit rejections** (reviewed, not silently deferred): 1. *`alsoConsumes` static consumed-set*: "consumed" means known-to-this-registry-version, not mapped-on-this-run — an `alsoConsumes` sibling whose anchor didn't run stays suppressed by design and remains in `_apiResponse`. Documented in `walkUnmapped`. 2. *WeakMap sidecar for `_apiResponse`*: deferred — clone+freeze resolves the aliasing hazard and the narrowed docstring is honest; revisit if CLI-2156 consumption shows inspectors bite (ADR 0019 records the alternative). 3. *`fromCliConfig`/`fromApiResponse` renaming*: the shipped names are already recorded in ADR 0020 (supabase#6335), Linear, and coordinated docs — symmetry isn't worth re-coordinating three artifacts. 4. *Branding `EffectiveConfig`*: took the ADR 0018 consequence note instead (widening removes the static every-section guarantee; callers own operand completeness). 5. *`ProjectConfigApiAttributes` placement* and *`"sideEffects": false`*: deferred to their owning issues with notes filed — CLI-2234 (export-surface audit) and CLI-2232 (verify the bundler claim against a built artifact). ### Verification round (commits 5f389c9 + 0424ac7) An executed verification pass over 93b4679 re-ran all prior attacks (10/10 now pass) and surfaced residuals, fixed in 0424ac7: - **Orphan digests were 3, not 1** — the generated `V1GetAuthServiceConfigOutput` contract (not the legacy interface) is the authority; `external_slack_secret`, `hook_after_user_created_secrets`, and `nimbus_oauth_client_secret` join the deny list, and a new apps/cli **contract-guard test** cross-checks every auth apiPath + secret-suffixed contract key against the registry (also closing the open-Record vacuity in the integrity test's auth checks). Registry rows are now exported from the package root to serve it. - **Clone/freeze regression fixed**: deep/cyclic/non-cloneable payloads now throw `ProjectConfigParseError` instead of raw `RangeError`/`DOMException` (depth-capped pre-walk, wrapped clone, cycle-guarded `deepFreeze`). - **README example rewritten and executed** (the previous snippet self-subtracted and filtered section names — always empty); secret-stripped projections prune emptied containers; a real phantom-drift pin replaces an agreeing-case test; `comparableProjectConfigPaths`' docstring narrowed to the section-level claim it delivers; ADR 0019 gained a dated addendum (attach helper, structural "verbatim", debug-inspector caveat). - **Documented-not-changed**: byte-size canonicalization quantizes at 4 significant digits symmetrically on both arms — sub-0.1% differences comparing equal is a deliberate property (user-authored spellings are exact). The merge commit resolves the pre-agreed README conflict with supabase#6335 (their `## Naming` section wins, its "in flight" sentence flipped) and de-stales ADR 0020's phrasing, per the coordinated rebase checklist. Known external: root `check:all` fails on `@supabase/cli-go#lint:check` (5 gosec findings in Go files byte-identical to develop — develop-side/toolchain, not this PR). ### Drift-audit round (commit 492ee25) A 2026-08-27 audit compared the post-codex state against CLI-2230's design intent. All eight structural commitments verified intact (pure entrypoint, no `packages/api` dependency, sparse output + `EffectiveConfig`, ADR 0019 guardrails, registry-driven with `inverse` unimplemented, purity graph, naming, secret stripping). Three executed repros surfaced semantic drift introduced by the codex rounds; fixed here: - **Leniency**: `JSON.parse('{"x":1e400}')` yields `Infinity`, so the round-12 non-finite pre-decode rejection hard-failed a real JSON payload on an *unknown* field (mis-bucketed as `caller_misuse`). The walk now rejects only bigint/`undefined`/`NaN` (values `JSON.parse` cannot produce); non-finite values decode and surface as `null` from `unmappedApiFields` (scalars and inside array leaves, identity preserved for all-finite arrays). ADR 0019 gains a dated leniency-boundary addendum. - **SMTP absence semantics**: an absent `smtp_host` previously counted as the disabled sentinel, silently dropping `smtp_user`/`smtp_admin_email`/`rate_limit.email_sent` from both the output and `unmappedApiFields` — contradicting the SMS absent-vs-sentinel rule beside it. Absence now says nothing; only the explicit `""`/`null` legacy sentinel disables (three-state, extended to the `email_sent` cross-section rule). - **Convergence-predictor ruling (ADR 0021)**: the codex rounds had incrementally turned both normalizers into *post-push convergence predictors* (SMS provider precedence flips extra enabled providers, disabled-sentinel pruning, `null`-gated booleans, CSV/uint/duration canonicalization) — defensible (it kills phantom drift for CLI-2156) but never adjudicated or documented. Ruling: **accepted**, now recorded in ADR 0021, the `ProjectConfig`/`fromConfigDocument`/`fromApiProjectConfig` docstrings, and the README ("not a verbatim representation" caveat). - **Guards**: the three hand-written sentinel/precedence tables (`DISABLED_SENTINEL_PRUNES`, `DISABLED_SENTINEL_ENTRY_SWEEPS`, `SMS_PROVIDER_PUSH_PRECEDENCE`) now resolve every path/key against the schema ASTs in `registry-integrity` — previously a schema rename silently no-opped them — and the SMS precedence order is pinned against the legacy push switch (`auth.sync.ts:2498-2539`). - Residual cleanups: the stale `Math.trunc` comment above the fraction arithmetic (round-11/14 artifact the round-20 revert missed), `ReadonlyJsonValue` exported (it appears in public types), `smtpExplicitlyDisabledInAttributes` simplified to mirror `smsProviderExplicitlyUnset`, ADR index gains 0020/0021. An engineer-review pass over the fix diff verified every change; its findings (the `email_sent` asymmetry, stale ADR citations, formatter gate, doc phrasing) are folded in. 984/984 package tests, 461/461 apps/cli guard tests, typechecks clean both packages. Follow-ups filed so they survive CLI-2230 closing: [CLI-2266](https://linear.app/supabase/issue/CLI-2266/derive-the-config-push-mapper-from-the-projectconfig-mapping-registry) (registry-derived push mapper — carries the three requirements previously parked as CLI-2230 comments) and [CLI-2267](https://linear.app/supabase/issue/CLI-2267/pin-supabaseconfigs-replicated-legacy-parsers-with-parity-fixtures-in) (parity fixtures pinning the replicated legacy parsers against `config-sync/*`). Fixes CLI-2230 🤖 Generated with [Claude Code](https://claude.com/claude-code)
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 freeto 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.
What changed
Records the
@supabase/confignaming convention (decided 2026-08-24, applied mechanically by CLI-2235 / #6328) as normative documentation:CliConfig= the full config-file document (supabase/config.toml/.json, the local superset),ProjectConfig= the hosted-project subset (a sparse overlay of the hosted sections, being introduced by CLI-2230),CliSettings= the CLI's own runtime settings (formerly namedCliConfig), plus the prefix rule:Cli*= the local checkout side, bareProject*= the hosted Supabase project, and value-helpers follow the config family regardless of their inputs (resolveCliConfigValue,MissingCliConfigValueError).AGENTS.md— new "Config Naming Vocabulary" section so agent/human sessions load the convention at start instead of re-deriving it from PR history.packages/config/README.md— the intro blockquote becomes a proper "Naming" section (public contract documentation once the package publishes).packages/config/docs/cli-config-loading.md— the Vocabulary section already used the settled names; this adds the prefix rule stated as a rule, linking ADR 0020. (The issue referenced this file by its pre-CLI-2235 nameproject-config-loading.md.)Stale-vocabulary sweep across
*.mdcame back clean: ADRs 0009/0018 already carry CLI-2235 rename addendums and stay untouched as historical records, and every remainingCliConfighit (including legacySIDE_EFFECTS.mdfiles) uses the current document-family meaning.Why
Renames are free only while
packages/configisprivate: true— CLI-2169 flips it public, and Studio is already an external consumer waiting on the package (supabase/supabase#48906). The vocabulary drifted once before (CliConfigmeant the settings service,ProjectConfigmeant the document); without a recorded decision it would drift again.Reviewer context
Coordinated with the in-flight CLI-2230 branch: it owns the
ProjectConfig: reserved…vocabulary bullet incli-config-loading.mdand will add a "ProjectConfig mapping" README subsection after this PR's "Naming" section, updating the "introduced by CLI-2230 (in flight)" sentence when it lands.BaseCliConfigis deliberately never cited as a prefix-rule example — its name is under an open ruling on CLI-2230.Fixes CLI-2238