Unblock postgres_instance_config PATCH (#163)#215
Conversation
The `pgConfig` schema has no `required` array and no field descriptions
start with "Optional", so the resolver marks every property required and
the generated model emits bare `T` fields. Serializing
`PgConfig { max_connections: 200, ..Default::default() }` then sends
zero/null/first-variant for every other property, and the live API
rejects all of them with
`Validation failed for following fields: pg_config.*`. The wrapping
`postgresInstanceConfig` also lists both nested objects as required,
making a partial PATCH unrepresentable.
Flip all 23 `PgConfig` fields and both `PostgresInstanceConfig` nested
fields to `Option<T>` with `skip_serializing_if = "Option::is_none"`,
add matching `OPTIONALITY_EXEMPTIONS` entries (caught automatically as
stale when the spec is fixed upstream), and re-enable the deferred
PATCH round-trip in the postgres integration test. The integration
test also gains a gated `CLICKHOUSE_CLOUD_POSTGRES_CONFIG_PROBE=1`
phase that captures the 6×2 behaviour matrix the upstream report
needs to cite real responses rather than assumptions.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Blocked: response shape returns string-encoded numbersMarking this PR as draft and blocked. The request-shape fix in this branch works (PATCH/POST now succeed against the live API per the captured matrix), but the response shape can't be deserialised into the spec-declared types. What we seeFor {"result":{"pgConfig":{"max_connections":"200"},"pgBouncerConfig":{},"message":"…"}}
This affects every strictly-numeric The same asymmetry applies in both directions: requests must send JSON numbers (string-encoded values are rejected), but responses come back string-encoded. So we can't just flip the field types — the model would then serialise wrong on the request side. Why this PR is pausedA client-side workaround (custom Next steps
|
The behaviour matrix captured in #163 shows the live API rejects any postgresInstanceConfig PATCH or POST body that omits either nested object: omitting pgBouncerConfig yields `BAD_REQUEST: request body.pgBouncerConfig: 'undefined'`, omitting pgConfig yields the symmetric error. Sending `{}` for either is accepted (matrix body 2 → 200). The previous commit had flipped both to Option<T> with skip_serializing_if so partial PATCHes could send only the changed half, but that shape doesn't match the API. Flip pg_config and pg_bouncer_config on PostgresInstanceConfig back to required (bare T with #[serde(default)] so the default envelope still serialises to `{ "pgConfig": {}, "pgBouncerConfig": {} }`), drop the two corresponding OPTIONALITY_EXEMPTIONS entries, and update the fixture/integration tests to construct the new shape. Inner pgConfig fields stay Option<T> with skip_serializing_if — those remain opt-in per the spec's all-optional partial-update semantics. Response-side deserialisation is still broken (the API returns strictly-numeric pgConfig fields wrapped in JSON strings), which is tracked separately and blocks the integration round-trip. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
PgConfigfield (23) plus bothPostgresInstanceConfignested fields (pgConfig,pgBouncerConfig) toOption<T>withskip_serializing_if = "Option::is_none", soClient::postgres_instance_config_patchcan express a real partial update. Pair the change with 25OPTIONALITY_EXEMPTIONSentries inspec_coverage_test.rs; the staleness detector will tell us automatically when upstream fixes the spec.integration_postgres_test.rs(GET baseline → PATCHmax_connections→ poll-until-applied → PATCH back).CLICKHOUSE_CLOUD_POSTGRES_CONFIG_PROBE=1probe phase that fires the 6 × 2 behaviour-matrix scenarios from the issue's follow-up comment via rawreqwestand prints a markdown table on stderr. Default off so it doesn't run on every integration test.Closes #163.
Follow-ups
OPTIONALITY_EXEMPTIONSentries become stale andfield_optionality_matches_specwill flag them — remove the block.Test plan
cargo build --tests(whole workspace)cargo clippy --testscargo test(all non-ignored tests pass)cargo test -p clickhouse-cloud-api --test spec_coverage_test field_optionality_matches_live_spec -- --ignored— 25 new exemptions all register against the live spec, no stale entriescargo test -p clickhouse-cloud-api --test integration_postgres_test -- --ignored --nocapture(live cloud creds required)CLICKHOUSE_CLOUD_POSTGRES_CONFIG_PROBE=1 cargo test -p clickhouse-cloud-api --test integration_postgres_test -- --ignored --nocapture— capture behaviour matrix for upstream🤖 Generated with Claude Code