Skip to content

feat(config): add toProjectConfig and the ProjectConfig hosted subset (CLI-2230) - #6339

Merged
Coly010 merged 39 commits into
developfrom
columferry/cli-2230-create-a-toprojectconfig-function-that-is-exported-from-the
Aug 27, 2026
Merged

feat(config): add toProjectConfig and the ProjectConfig hosted subset (CLI-2230)#6339
Coly010 merged 39 commits into
developfrom
columferry/cli-2230-create-a-toprojectconfig-function-that-is-exported-from-the

Conversation

@Coly010

@Coly010Coly010 commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

What changed

Implements CLI-2230: 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_otpsign_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 (#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_autoconfirmnot 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 absentdb_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 (docs(config): document the CliConfig/ProjectConfig/CliSettings naming convention #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 #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 (registry-derived push mapper — carries the three requirements previously parked as CLI-2230 comments) and CLI-2267 (parity fixtures pinning the replicated legacy parsers against config-sync/*).

Fixes CLI-2230

🤖 Generated with Claude Code

… (CLI-2230)
Introduce the hosted-project subset type ProjectConfig and its normalizers
on the pure entrypoint of @supabase/config:
- fromConfigDocument(config): projection of a CliConfig/EffectiveConfig down
to the hosted sections (api, auth, db, realtime, storage, workers,
experimental).
- fromApiProjectConfig(input): translation of a Management API v2
project-config response (envelope, data object, or bare attributes) via a
registry-driven mapping (233 rows mined from the legacy config-sync
mappers): renames, boolean inversions, duration/byte-size unit conversions,
GoTrue key mapping, x-secret omission (the API reports HMAC digests). The
raw attributes are attached as a non-enumerable _apiResponse per ADR 0019,
with a registry-derived unmappedApiFields() escape-hatch reader.
- toProjectConfig(source): thin dispatcher over both normalizers.
The comparison-core operand type BaseCliConfig is replaced by the
family-neutral EffectiveConfig = DeepPartial<Omit<CliConfig, "remotes">> so
the sparse ProjectConfig is assignable to subtractCliConfig/omitDefaultValues
without casts; no runtime change (ruling recorded on CLI-2230 and in ADR
0018's 2026-08-26 addendum).
apps/cli gains a type-drift guard pinning the generated
V2GetProjectConfigOutput attributes against the package's lenient input
schema (assignability plus per-section key-set assertions), and the new
ProjectConfigParseError is registered in the error-actionability table as a
platform-response failure.
@Coly010Coly010 self-assigned this Aug 26, 2026
#6339
Correctness:
- fromConfigDocument deep-copies hosted sections and omits every x-secret
leaf (schema-derived via the collector extracted to lib/secret-paths.ts) —
decoded documents hold plaintext credentials, and the API arm omits
secrets, so the subtract composition rendered them as drift.
- Registry-driven document-side canonicalization (new normalizeDocument row
column): duration spellings ("24h" -> "24h0m0s") and byte-size spellings
converge with the API arm so one logical value diffs clean.
- Mirror schema now types every never-mapped field Schema.Unknown — a
platform type change on a field nothing reads no longer fails every decode
(ADR 0019 rule 2 held only for unknown keys before).
- ProjectConfigParseError carries message/detail/suggestion (rendered by
normalize-error), schema-issue paths lift into apiPath, actionability adds
fingerprint_suffix api_response + has_suggestion.
- Type-mismatch handling unified: smtp_host/port and string rows throw via
expect* instead of fabricating enabled:false or vanishing; CIDR entries
that fail to classify throw instead of silently emptying a security
allowlist; expectNumber rejects non-finite; numeric passthrough rows
narrow.
- _apiResponse is cloned + deep-frozen at attach (no caller aliasing);
attachApiResponse export restores it across spread/clone round-trips;
invisibility claim narrowed (serializers yes, debug inspectors no).
- unmappedApiFields: depth cap, unmappedSecretApiPaths deny list
(external_figma_secret — the one genuine orphan digest), consumed-set
semantics documented.
- New exports comparableProjectConfigPaths/isComparableProjectConfigPath so
diff consumers never hand-maintain field lists.
- New registry-integrity unit test: all 233 rows' paths resolve against the
CliConfigSchema and mirror ASTs (470 generated cases); drift guard gains
the missing key-set levels; inverse implementations dropped until the push
mapper derives them.
Docs updated (README example, loading doc, ADR 0018 consequence note).
@Coly010
Coly010 marked this pull request as ready for review August 26, 2026 13:18
@Coly010
Coly010 requested a review from a team as a code ownerAugust 26, 2026 13:18
…0-create-a-toprojectconfig-function-that-is-exported-from-the
# Conflicts:
#	packages/config/README.md

@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:93b4679b71

ℹ️ 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 threadpackages/config/src/project-config/registry.ts Outdated
Comment threadpackages/config/src/project-config/registry-auth.ts Outdated
Comment threadpackages/config/src/project-config/registry-row.ts Outdated
Comment threadpackages/config/src/project-config/registry-auth.ts
Comment threadpackages/config/src/project-config/project-config.ts Outdated
Comment threadpackages/config/src/project-config/project-config.ts Outdated
- unmappedSecretApiPaths now lists all four orphan digests, sourced from the
generated V1GetAuthServiceConfigOutput contract (external_figma_secret,
external_slack_secret, hook_after_user_created_secrets,
nimbus_oauth_client_secret) — the legacy interface was a subset, not the
authority. A new apps/cli contract-guard test cross-checks every auth
apiPath and every secret-suffixed contract key against the registry, which
also closes the open-Record vacuity in the integrity test's auth checks.
- attachFrozenApiResponse no longer escapes untyped: a depth-capped pre-walk
(shared with unmappedApiFields' cap) bounds depth and cycles before
structuredClone, clone failures wrap into ProjectConfigParseError, and
deepFreeze gains a cycle guard.
- fromConfigDocument prunes containers emptied by secret-stripping (and
genuinely empty ones) instead of leaving {} litter that subtraction reports
as drift.
- README example rewritten and executed: subtract local-vs-remote and filter
LEAF paths through isComparableProjectConfigPath (the previous snippet
self-subtracted and filtered section names — always empty).
- Real phantom-drift pin replaces the agreeing-case test;
comparableProjectConfigPaths' docstring narrowed to the section-level
claim it actually delivers.
- Exhaustive schema-derived secret-strip guard (all 39 hosted-reachable
x-secret patterns); attachApiResponse throws typed on non-object input;
quantization rationale documented on the byte canonicalization; ADR 0019
addendum records the attach helper, structural verbatim, and the
debug-inspector caveat.
Registry rows, the row type, and unmappedSecretApiPaths are now exported from
the package root to serve the apps/cli contract guard (and future push
mappers).
@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@1aa5919ac6963c2cca9306a2fc3520884d9f4569

Preview package for commit 1aa5919.

@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:0424ac7edd

ℹ️ 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 threadpackages/config/src/project-config/project-config.ts Outdated
Comment threadpackages/config/src/project-config/project-config.ts
Comment threadpackages/config/src/project-config/project-config.ts Outdated
- Replace the two size-parser index as-casts with charAt() access (repo
no-cast rule; review thread P1).
- expectInteger narrows integer-typed mapped fields (max_rows, db settings
uints, pooler sizes, storage limits/maxes, major_version, uintRow) — a
fractional value on an int-contract field now throws
ProjectConfigParseError instead of landing in ProjectConfig; duration
numbers (session hours, frequency seconds) deliberately stay float-tolerant.
- Apple/Google client_id combine throws on non-string main/additional values
instead of silently omitting consumed-but-malformed input.
- parseDuration rejects digit-less components ("s", ".h") the way Go's
ParseDuration does — the legacy port reads them as zero, which would let
canonicalizeDurationString rewrite a malformed document value to "0s";
malformed values now stay verbatim.

@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:6af9880506

ℹ️ 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 threadpackages/config/src/project-config/registry-auth.ts Outdated
Comment threadpackages/config/README.md Outdated
…path encoding
- copyHostedValueWithoutSecrets deep-copies array elements (a hosted array
can hold objects, e.g. experimental.inspect.rules — slice() aliased them
back to the possibly-frozen input).
- walkUnmapped preserves an unknown EMPTY object instead of pruning it — a
newly introduced, not-yet-populated API section is drift signal, not noise.
- pathKey JSON-encodes the segment array — no join delimiter is
collision-free against arbitrary raw keys.
- password_required_characters throws on a present non-string (unrecognized
strings still omit — enum-ahead skew; null still means absent), matching
every other mapped auth field.
- The apps/cli contract guard now also asserts every auth alsoConsumes path
(the apple/google additional_client_ids fold) against
V1GetAuthServiceConfigOutput.

@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:adfdca9b4e

ℹ️ 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 threadpackages/config/src/project-config/project-config.ts Outdated
Comment threadpackages/config/src/project-config/registry-auth.ts Outdated
Comment threadpackages/config/src/project-config/registry-auth.ts Outdated
Comment threadpackages/config/src/project-config/project-config.ts Outdated
Comment threadpackages/config/src/project-config/registry-auth.ts
…ng, bounded walks
- Map the three hosted OAuth-server settings the original mining missed:
auth.oauth_server.{enabled, allow_dynamic_registration,
authorization_url_path} <- oauth_server_* (note the authorization_path ->
authorization_url_path rename; no sync precedent, name-matched against the
generated contract).
- unmappedApiFields prunes KNOWN containers that are empty
(postgres_settings: {}, auth: {}) while still preserving empty objects at
unknown paths — the previous blanket preservation fabricated drift for
ordinary responses.
- Raw-attributes validation bounds total node VISITS (100k cap, typed error)
in addition to depth: a ~40-level shared-reference DAG stays inside the
depth bound but costs ~2^41 tree paths, hanging both the validator and the
path-dependent walkUnmapped (which cannot memoize by node). Real network
JSON never shares references, so rejection is the honest semantics.
- sms_test_otp and security_captcha_provider throw on present non-strings
(null still omits; unrecognized provider strings still omit as enum-ahead
skew), matching every other mapped auth field.

@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:f21f7e40d4

ℹ️ 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 threadpackages/config/src/project-config/project-config.ts Outdated
Comment threadpackages/config/src/project-config/registry-auth.ts Outdated
Comment threadpackages/config/src/project-config/registry-auth.ts Outdated
Comment threadapps/cli/src/shared/telemetry/error-actionability.ts Outdated
Comment threadpackages/config/src/project-config/project-config.ts
…se taxonomy, readonly metadata
- Depth/work-bound the raw attributes BEFORE schema decode: the mirror's
auth record is Schema.Json, whose decode recurses arbitrarily, so a deep
auth value overflowed with a raw RangeError ahead of the attach-time bound.
- ProjectConfigParseError gains a closed reason union: caller misuse (a
toProjectConfig source with neither/both keys or a non-object, non-object
attachApiResponse operands) is a programming error — plain message, no
upgrade suggestion, and the apps/cli actionability adapter buckets it as
invalid_input/request_input instead of corrupting the external api_status
KPI. toProjectConfig also guards non-object sources before Object.hasOwn
so JS callers get the typed error, not a native TypeError.
- _apiResponse is readonly at the type level — the runtime value is deep-
frozen, so compile-permitted mutation would throw in this ESM package;
nested values stay unknown (consumer narrowing owns anything deeper).
- README example scoped honestly: it computes one direction of a drift
check; remote-only settings need the reverse subtraction intersected with
document-declared paths, and the complete computation is CLI-2156's job.

@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:0df89a29b4

ℹ️ 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 threadpackages/config/src/project-config/project-config.ts Outdated
…uencies, provider narrowing
- _apiResponse values are typed as a recursive ReadonlyJsonValue, so nested
record mutation no longer compiles. One caveat no user-space type closes:
the lib's Array.isArray guard (arg is any[]) yields a mutable view
(microsoft/TypeScript#17002) — documented, with a readonly-preserving
guard shown and pinned in tests; runtime deep-freeze backstops.
- The three *_max_frequency seconds fields narrow via expectInteger (the
contract types them isInt); only the genuinely fractional session-hour
rows stay on expectNumber.
- sms_provider throws on a present non-string before the five ===
comparisons (null/empty still omit all five).

@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:51d9793bca

ℹ️ 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 threadpackages/config/src/project-config/project-config.ts
Comment threadpackages/config/src/project-config/registry-auth.ts Outdated
Comment threadpackages/config/src/project-config/project-config.ts
…ion, duration bounds
- fromConfigDocument guards non-object operands (null/undefined/array) with
the typed caller-misuse error instead of a native TypeError or a silent {}.
- The empty-container prune now removes only containers the copy itself
EMPTIED via secret stripping — an originally-empty object is declared
data: record entries whose values are empty structs by schema design
(storage.analytics.buckets, storage.vector.buckets) keep their entries,
and a genuinely-empty section (default workers) survives as declared.
- Session-hour durations narrow through a bounded validator (0..1e6 hours):
the contract only requires them finite, but huge values overflow the ns
conversion ("InfinityhNaNmNaNs") or stringify in exponent notation no
duration parser reads.

@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:e2db9a610d

ℹ️ 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 threadpackages/config/src/project-config/registry-auth.ts Outdated
Comment threadpackages/config/src/project-config/registry-auth.ts Outdated
Comment threadpackages/config/src/project-config/registry-auth.ts Outdated
Comment threadpackages/config/src/project-config/registry.ts Outdated
…flow, own-key lookups
- expectNumber is module-private again (knip: its last external caller moved
to expectInteger/expectNumberBetween) — fixes the Check code quality CI
failure on the previous push.
- Apple/Google client_id validates the additional_client_ids sibling BEFORE
the null-anchor early return — a malformed sibling behind a null main id
was silently consumed.
- parseDuration caps at Go's max int64 nanoseconds (matching Go's
value-out-of-range error), so a document duration like 1e21h stays
verbatim instead of canonicalizing into exponent notation or
InfinityhNaNmNaNs; ramInBytes likewise rejects a non-finite suffix
product (1e308KiB no longer canonicalizes to InfinityYiB).
- The password charset lookup answers own entries only — an API-controlled
key like "constructor" resolved the inherited function instead of
omitting the unrecognized charset.
…guard
9_223_372_036_854_775_807 is not representable in float64 and trips
oxlint's no-loss-of-precision (CI denies warnings); 2 ** 63 is exact and
one nanosecond above Go's max int64 — the guard is approximate by design.

@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:b0c66bba02

ℹ️ 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 threadpackages/config/src/project-config/registry-auth.ts Outdated
Comment threadpackages/config/src/project-config/registry.ts Outdated
Comment threadpackages/config/src/project-config/project-config.ts Outdated
Comment threadpackages/config/src/project-config/registry-auth.ts Outdated
Comment threadpackages/config/src/project-config/registry-auth.ts
Comment threadpackages/config/src/project-config/project-config.ts Outdated
…s, freeze translation
- *_max_frequency seconds bound to Go's representable range (an integer past
int64-ns seconds formatted a duration this package's own parser rejects).
- storage.file_size_limit rejects negative API byte counts — "-1B" persists
a value ramInBytes cannot read back.
- Session hours map faithfully (deliberate divergence from the legacy
apply's Math.round): 1.5 → "1h30m0s", preserving push-side round-trips.
- durationString prints fractional seconds in the hours/minutes branches
like Go's Duration.String() — the legacy port truncates them there, which
would let canonicalization silently change "1h0.5s" into "1h0m0s".
- deepFreeze failures on structured-cloneable non-JSON values (typed arrays)
translate into the typed caller-misuse error instead of a native
TypeError. Also reorders ReadonlyJsonValue above ProjectConfig's docstring
(round 4 had orphaned it from its type).

@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:645be1f3ef

ℹ️ 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 threadpackages/config/src/project-config/registry-auth.ts Outdated
Comment threadpackages/config/src/project-config/project-config.ts Outdated
…s, non-plain rejection
- The mapping engine runs a row whose anchor key is absent when one of its
alsoConsumes siblings IS present, so a malformed sibling behind an absent
Apple/Google client_id is validated instead of silently consumed.
- durationString formats fractional seconds with toFixed(9) — a
sub-microsecond remainder under toPrecision stringified in exponent
notation ("1h1ns" -> "1h0m1.000000000e-9s") that Go duration syntax
rejects; Go prints "1h0m0.000000001s".
- The pre-clone validation walk rejects non-plain objects (Map/Set/Date/
typed arrays/class instances) with the typed caller-misuse error:
Object.freeze only freezes their wrappers, so they'd punch live mutators
through the deep-frozen metadata. Parsed JSON never produces one.

@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:576490531c

ℹ️ 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 threadapps/cli/src/shared/telemetry/error-actionability.ts
Comment threadpackages/config/src/project-config/registry-auth.ts Outdated
Comment threadpackages/config/src/project-config/project-config.ts Outdated
Comment threadpackages/config/src/project-config/project-config.ts
…source type, secret validation
- structuredClone failures carry the caller-misuse reason (a function-valued
attribute is programmatic input, not a platform response) so telemetry
stops classifying it as an external api_status failure.
- parseDuration's range bound tightens from Go's int64 to
Number.MAX_SAFE_INTEGER nanoseconds: past it, float accumulation silently
rounds small components away ("2502h1ns" would canonicalize to
"2502h0m0s", changing the value). The API-side frequency/session-hour
bounds move inside the same canonical domain so every duration the API arm
can emit is one the document arm can re-parse.
- Envelope unwrap enforces the type discriminator when present: a response
for a different resource throws instead of partially mapping wherever
attribute names overlap; a typeless envelope stays tolerated.
- Secret rows validate a present value is a string (HMAC digest) before
omitting it — a malformed smtp_pass: 123 no longer vanishes without a
parse error or drift signal.

@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:22e3406a1c

ℹ️ 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 threadpackages/config/src/project-config/registry-auth.ts
Comment threadpackages/config/src/project-config/registry-auth.ts
Comment threadpackages/config/src/project-config/project-config.ts Outdated
Comment threadpackages/config/src/project-config/registry-auth.ts
…loor, envelope accessor boundary
- sms.test_otp canonicalizes document records through the push serialize
(mapToEnv, auth.sync.ts:2603-2609) + pull envToMap re-parse, so keys or
values holding literal commas converge on the post-push hosted record —
same convergence rule as the CSV-backed arrays.
- The session-hour floor is asymmetric like int64 itself: -2^63 ns is the
valid Go minimum and its hours spelling rounds back to exactly -2^63
through magnitude-then-sign, while the ceiling still stops short of +2^63.
- Envelope properties (data, attributes, type) are read exactly once each
through a boundary that translates throwing accessors into
ProjectConfigParseError caller_misuse — a getter can no longer pass the
shape check and then leak a raw Error on a second read.

@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:c5dbc95353

ℹ️ 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 threadpackages/config/src/project-config/project-config.ts Outdated
Comment threadpackages/config/src/project-config/registry-auth.ts Outdated
Comment threadpackages/config/src/project-config/registry-auth.ts
…ty, empty test_otp absence, +2^63 document rejection
- isComparableProjectConfigPath accepts descendants of mapped container
paths (sms.test_otp record entries from leaf-path traversals), while bare
prefixes still read as sections, not mapped values.
- An empty (or round-trip-emptied) test_otp map normalizes to unmanaged
absence: the push wrapper omits sms_test_otp when the serialized map is
empty (auth.sync.ts:2487-2495), so projecting {} fabricated permanent
drift. normalizeDocument gains undefined→remove semantics with
emptied-ancestor pruning, consistent with the copy's self-emptied rule.
- parseDuration rejects a positive total landing exactly on 2^63 (one past
Go's max) while the in-loop strict bound still admits the valid -2^63
endpoint — document and API arms now agree at both endpoints.

@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:11e6da0ff2

ℹ️ 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 threadpackages/config/src/project-config/project-config.ts
Comment threadpackages/config/src/project-config/registry-auth.ts
Comment threadpackages/config/src/project-config/registry-auth.ts
Comment threadpackages/config/src/project-config/project-config.ts Outdated
… uint clamps, dispatcher accessor guard
- Multiple enabled SMS providers in a document converge on the push switch's
first-enabled precedence (auth.sync.ts:2498-2539): later enabled flags flip
to false before the sentinel sweep prunes their siblings, matching the API
arm's report of the post-push hosted state.
- Every uint-clamped row (auth uintRow, api.max_rows, db settings, storage
feature limits) clamps document-side negatives too: the push mapper sends
them unchanged while the pull direction clamps, so a pushed -1 projects
back as 0 and the document spelling must converge on that reading.
- toProjectConfig reads its selected source property through a guarded
boundary — a throwing apiResponse/cliConfig accessor now surfaces as
ProjectConfigParseError caller_misuse instead of a raw Error.

@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:05240eb3b5

ℹ️ 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 threadpackages/config/src/project-config/registry.ts Outdated
Comment threadpackages/config/src/project-config/registry.ts Outdated
Comment threadpackages/config/src/project-config/project-config.ts Outdated
Comment threadpackages/config/src/project-config/registry-auth.ts
…empty schemas absence, attach spread guard
- Session-duration document canonicalization applies the push pipeline's own
h/m sub-second truncation (normalizeDurationStr runs the truncating legacy
formatter, auth.sync.ts:986-987 + config-sync.duration.ts:39-45, before
durationToHours) — a document "1h0.5s" stores exactly one hour, so its
canonical spelling predicts that reading; sub-minute magnitudes keep their
fraction, and the API arm's Go-faithful formatter still renders hosted
sub-second bits honestly.
- An explicitly empty api.schemas array normalizes to unmanaged absence:
push sends db_schema only when non-empty (api.sync.ts:137-139) and "" is
the disable sentinel, so the API arm can never project [].
- attachFrozenApiResponse's enumerable-props spread is guarded — a throwing
caller getter surfaces as ProjectConfigParseError caller_misuse.

@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:74abe4e610

ℹ️ 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 threadpackages/config/src/project-config/registry-auth.ts Outdated
Comment threadpackages/config/src/project-config/project-config.ts Outdated
…ction accessor guard
- Sub-minute fractional session durations quantize to the push formatter's
seconds branch (toPrecision(10), config-sync.duration.ts:47-55) by
re-parsing that exact rendering through the push-verbatim parseDuration —
"59.123456789s" pushes as "59.12345679s", so the canonical spelling
predicts it; below one second the two formatters' branches are identical.
- fromConfigDocument wraps each section read AND its recursive copy in a
guarded boundary: a throwing getter at any depth surfaces as
ProjectConfigParseError caller_misuse instead of a raw error.

@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:fb00ff3d7f

ℹ️ 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 threadpackages/config/src/project-config/registry-auth.ts Outdated
…ession canonicalization
Session fields travel as fractional hours (durationToHours is a bare
parseDuration / 3.6e12, auth.sync.ts:2621-2627) and map back through
Math.round(|hours| * 3.6e12) — a trip that is not always exact ('1024h4s'
returns one nanosecond high). Document canonicalization now rides the same
round trip after the formatter truncation, landing on the exact value the
API arm reports after a push; all previously pinned spellings are exact
through the trip and stay unchanged.
…(CLI-2230)
Adjudicated fixes from the 2026-08-27 drift audit of the codex review rounds
against CLI-2230's design intent:
- Leniency: the pre-decode walk no longer rejects non-finite numbers —
JSON.parse('{"x":1e400}') yields Infinity, so a real platform payload with
an overflowing literal in an unknown field must decode (ADR 0019 rule 2).
caller_misuse is reserved for values JSON.parse cannot produce
(bigint/undefined/NaN). Non-finite values surface as null from
unmappedApiFields (scalars and inside array leaves, identity preserved for
all-finite arrays).
- SMTP absence semantics: an absent smtp_host says nothing — sibling rows
(user/admin_email/port/sender_name) and rate_limit.email_sent map normally;
only the explicit ""/null legacy sentinel disables. Previously a sparse
response lost these values from both the output and unmappedApiFields.
- ADR 0021 records the previously-undocumented convergence-predictor ruling:
both normalizers emit the post-push convergent form, not a verbatim
representation (SMS provider precedence, disabled-sentinel pruning,
null-gated booleans, canonicalization); docstrings and README carry the
not-verbatim caveat. ADR 0019 gains a dated leniency-boundary addendum;
ADR index gains 0020/0021.
- registry-integrity now resolves the three hand-written sentinel/precedence
tables against the schema ASTs (previously unguarded — a schema rename
silently no-opped them) and pins the SMS precedence order.
- Stale Math.trunc comment above the fraction arithmetic rewritten to match
the round-20 final state (legacy push parser is the fraction authority).
- ReadonlyJsonValue exported (referenced by public types); sentinel tables
exported for the integrity guards; smtpExplicitlyDisabledInAttributes
simplified to mirror smsProviderExplicitlyUnset.
Follow-ups filed: CLI-2266 (registry-derived push mapper, carrying the three
requirements parked on CLI-2230), CLI-2267 (legacy-parser parity fixtures).

@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:492ee25c0d

ℹ️ 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 threadpackages/config/src/project-config/registry-auth.ts
The document arm preserved a fractional or out-of-range smtp port verbatim
(auth.email.smtp.port is an unrestricted Schema.Number), while the push
encoding stringifies (auth.sync.ts:2390) and the API-side row parses with
parseUint16 and omits on failure — so the two projections disagreed after
applying such a document. The port row's new normalizeDocument replays the
exact push→pull round trip (parseUint16(String(port)), omit when invalid;
non-number values stay untouched per the type-mismatch rule). Schema domain
deliberately unchanged.

@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:5d0fe98239

ℹ️ 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 threadpackages/config/src/project-config/project-config.ts
Comment threadpackages/config/src/project-config/project-config.ts
Comment threadpackages/config/src/project-config/project-config.ts Outdated
…apped granularity, boundary guard
Three adjudicated threads:
- Presence-relativity (document-only): a decoded CliConfig materializes
schema defaults (all 19 providers enabled:false, smtp {enabled:false}),
while legacy push emits only raw-file-present providers
(authSubsetFromConfig, auth.sync.ts:1075-1084) and skips absent smtp
subsets (:1020-1024) — so the convergence prediction is exact only for
fields the input speaks for. ADR 0021 gains a Limits section
(omitDefaultValues composition + intersection rule; residual categories
tracked on CLI-2266). The email_sent sub-claim was verified NOT to
diverge: a decoded document always carries an explicit smtp.enabled, so
the explicit-false-only rule already agrees with push.
- Unmapped granularity (rejected behavior change): consumption is
subtree-wide by design (same ruling family as alsoConsumes); docstring
narrowed to registry apiPath granularity, full fidelity via _apiResponse,
pinned by a cidr comment-key test.
- unmappedApiFields input boundary (accepted): operand now guarded like the
sibling adapters — non-object operands and throwing _apiResponse getters
raise typed caller_misuse instead of leaking native errors.

@jgouxjgoux 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.

Three reproducible correctness findings from review of the current head.

Comment threadpackages/config/src/project-config/project-config.ts
Comment threadpackages/config/src/project-config/registry.ts Outdated
Comment threadpackages/config/src/project-config/project-config.ts
…m with push emission
Addresses the three review findings on the current head:
- [P1] fromConfigDocument (and toProjectConfig) now accept the loaded pair
({ config, document } — LoadedCliConfig is structurally assignable) and
mask the decoded projection by raw-document presence, mirroring the nine
legacy push gates exactly (push.raw-presence.ts + auth.sync.ts:927/
951-960/1023/1075-1084): raw-absent ssl_enforcement, image_transformation,
s3_protocol, captcha, per-hook, and smtp (plus its rate_limit_email_sent
coupling) are omitted; auth.external keeps raw-present providers plus
apple always, with decoded values. Presence uses the same !== undefined
predicate as legacyPresenceIn. Without a document, the decoded-input
behavior stands per ADR 0021's Limits section; the loaded pair is now the
documented recommended path (loadCliConfig supplies document,
saveCliConfig does not). A presence-parity test in apps/cli pins the
package mask against legacyPresenceIn key-for-key.
- [P2] api.max_rows on the document arm mirrors push's max_rows > 0 gate as
its exact negation !(value > 0) — 0, negatives, and NaN (TOML nan is a
valid float literal) are omitted rather than projected or clamped. API
arm unchanged; flips when CLI-2266 makes push send the field explicitly.
- [P2] the document arm no longer asserts what push cannot emit: disabled
storage.analytics/storage.vector containers and the entire
auth.oauth_server section (authToUpdateBody has no oauth_server handling)
are omitted; the API arm keeps actual hosted state and the
fields-both-operands-speak-for rule keeps diffs honest.
Review hardening folded in: pair-unwrap reads go through the guarded
accessor pattern (throwing getters surface as typed caller_misuse, nested
dispatcher case included), a present-but-non-object document throws instead
of silently disabling masking, schema-key collision pins for the config/
document shape sniffing, an exhaustive presence-parity key-set check, and
ADR 0021 gains the unmanaged-by-push enumeration + CLI-2267 reference.
@Coly010
Coly010 enabled auto-merge August 27, 2026 13:33

@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:1aa5919ac6

ℹ️ 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 threadpackages/config/src/project-config/project-config.ts
Comment threadpackages/config/src/project-config/registry-auth.ts
Comment threadpackages/config/src/project-config/registry.ts
@Coly010
Coly010 disabled auto-merge August 27, 2026 13:57
@Coly010
Coly010 added this pull request to the merge queueAug 27, 2026
Merged via the queue into develop with commit c3064f1Aug 27, 2026
50 checks passed
@Coly010
Coly010 deleted the columferry/cli-2230-create-a-toprojectconfig-function-that-is-exported-from-the branch August 27, 2026 14:07
kanadgupta added a commit that referenced this pull request Aug 27, 2026
…156)
CLI-2230 (#6339) landed the registry-driven ProjectConfig convergence
normalizers with config diff as their intended consumer (ADR 0021), which
made this branch's self-contained translation tables a parallel
implementation of the same mapping. The classifier now takes two
ProjectConfig projections — fromConfigDocument({config, document}) locally
(raw-presence-masked) and fromApiProjectConfig(response) remotely — walks
the union of their leaves filtered by isComparableProjectConfigPath, and
keeps the declared-set-driven classes, masked transparency (registry
isSecret rows), and env naming. remote_only suppression baselines on the
default config's projection, falling back to the raw default value for
push-gated containers (network restrictions' allow-all) and then the zero
value. Deletes config-diff.{managed,auth,read}.ts (~900 lines); scope
reporting moves to the command layer off the raw response attributes; ADR
0022 rewritten to record the consolidation; --target registered in the
CLI-1896 value-consuming flag guard; purity-pin allowlists extended.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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