Skip to content

docs(config): document the CliConfig/ProjectConfig/CliSettings naming convention - #6335

Merged
Coly010 merged 3 commits into
developfrom
columferry/cli-2238-document-the-supabaseconfig-naming-convention-cliconfig
Aug 26, 2026
Merged

docs(config): document the CliConfig/ProjectConfig/CliSettings naming convention#6335
Coly010 merged 3 commits into
developfrom
columferry/cli-2238-document-the-supabaseconfig-naming-convention-cliconfig

Conversation

@Coly010

Copy link
Copy Markdown
Contributor

What changed

Records the @supabase/config naming convention (decided 2026-08-24, applied mechanically by CLI-2235 / #6328) as normative documentation:

  • New ADR 0020 — the vocabulary decision and rationale: 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 named CliConfig), plus the prefix rule: Cli* = the local checkout side, bare Project* = the hosted Supabase project, and value-helpers follow the config family regardless of their inputs (resolveCliConfigValue, MissingCliConfigValueError).
  • Repo-root 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 name project-config-loading.md.)

Stale-vocabulary sweep across *.md came back clean: ADRs 0009/0018 already carry CLI-2235 rename addendums and stay untouched as historical records, and every remaining CliConfig hit (including legacy SIDE_EFFECTS.md files) uses the current document-family meaning.

Why

Renames are free only while packages/config is private: 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 (CliConfig meant the settings service, ProjectConfig meant 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 in cli-config-loading.md and 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. BaseCliConfig is deliberately never cited as a prefix-rule example — its name is under an open ruling on CLI-2230.

Fixes CLI-2238

@Coly010
Coly010 requested a review from a team as a code ownerAugust 26, 2026 09:16
@github-actions

github-actionsBot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Supabase CLI preview

npx --yes https://pkg.pr.new/supabase/cli/supabase@bb51e41fce93a9268d7edb6a9438e49ebdbe3527

Preview package for commit bb51e41.

@Coly010Coly010 self-assigned this Aug 26, 2026

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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: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".

Comment threaddocs/adr/0020-config-naming-vocabulary.md Outdated
@Coly010
Coly010 added this pull request to the merge queueAug 26, 2026
Merged via the queue into develop with commit cc6ebb7Aug 26, 2026
34 checks passed
@Coly010
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)
Sign up for freeto 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

@Coly010@jgoux