Hide deprecated fields from CLI output (#228)#230
Merged
Conversation
The CLI surfaced every field returned by the OpenAPI response, including deprecated ones — confusing for agents that can't tell a field is deprecated. Hide them from output while keeping deserialization intact. Library (clickhouse-cloud-api): - Add `deprecated-fields` Cargo feature (off by default). Deprecated response fields carry `#[cfg_attr(not(feature = "deprecated-fields"), serde(skip_serializing))]` so they deserialize normally but are omitted from serialization unless the feature is enabled. Request-side schemas are left untouched. - Add `DEPRECATED_OUTPUT_FIELDS` + `is_deprecated_output_field` to meta.rs, and tests `deprecated_output_fields_match_spec` (constant vs spec) and `deprecated_output_fields_hidden` (constant vs models.rs markers). CLI (clickhousectl): - Enable serde_json `preserve_order`; add `cloud/output.rs::print_human` rendering responses as an indented tree from their serialized form. - Convert detail/get human-output branches to `print_human`, so deprecated fields disappear from both human and `--json` output via one serde path. Scripts/docs: - Add scripts/regenerate-deprecated-fields.py; extend check-openapi-drift.py to report deprecation drift. Document in both READMEs and CLAUDE.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Deprecated response fields previously used `#[cfg_attr(not(feature = "deprecated-fields"), serde(skip_serializing))]`: they stayed readable in Rust and were only hidden from serialization. That left a gap — list commands build `tabled` rows by direct field access (`m.role`), which bypasses serde, so `member list` and `invitation list` leaked the deprecated `role` field into output. Switch the marker to `#[cfg(feature = "deprecated-fields")]` so the field is removed from the struct entirely by default. Referencing a deprecated field is now a compile error anywhere — tables included — making leaks impossible to ship rather than caught by a runtime/test heuristic. The existing feature flag still restores the fields (now via a `clickhousectl` passthrough feature). - models.rs: gate all 10 deprecated response fields. - member/invitation list: replace the deprecated Role column with a Roles column sourced from the non-deprecated `assignedRoles[].roleName`. - Gate the ~19 library-test reads of deprecated fields behind the feature; add `deprecated_fields_absent_by_default` for the default build. - spec_coverage_test: detect the new marker form; drift checks unchanged. - Docs/tooling updated to the new "absent by default" contract. Verified: build, clippy, and test pass on default features and with `deprecated-fields` (both crates). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extend deprecated-field hiding to request-side schemas: all 14 fields the spec marks deprecated on *Request/*Patch/*Input now carry #[cfg(feature = "deprecated-fields")], so by default callers can't set them and skip_serializing_if keeps them off the wire — matching the response side. Two were bare required types (InvitationPostRequest.role, OrganizationPrivateEndpointsPatch.add); flip them to Option<T> and add OPTIONALITY_EXEMPTIONS entries. Unify the response-only DEPRECATED_OUTPUT_FIELDS into a single DEPRECATED_FIELDS (24 entries) / is_deprecated_field covering both sides; rename the drift tests, regenerate/drift scripts, and docs to match. CLI request builders drop the deprecated assignments (gated so both feature configs compile). Tests cfg-gate the affected literals/assertions and the wiremock body matchers no longer assert deprecated keys. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rename to DEPRECATED_FIELDS and note it now covers request- and response-side deprecated fields, matching meta.rs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 3a9881e. Configure here.
…ated-fields # Conflicts: # CLAUDE.md # CLAUDE.md~HEAD # crates/clickhouse-cloud-api/tests/spec_coverage_test.rs
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 free
to 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.

Closes #228.
The CLI surfaced every field the OpenAPI response carries, including deprecated ones — confusing for agents/users who can't tell a field is deprecated. This hides them while keeping deserialization intact, and extends the same treatment to deprecated request fields so callers can't set them either.
Library (
clickhouse-cloud-api)deprecated-fieldsCargo feature (off by default). Fields the spec marksdeprecated: true— on both response schemas (Service.tier,ApiKey.roles, …) and request schemas (ServicePostRequest.tier,InvitationPostRequest.role, …) — are gated behind#[cfg(feature = "deprecated-fields")], so they're absent from the struct by default. Reading a deprecated response field is a compile error; deprecated request fields can't be set and never hit the wire.Option<T>so it can be gated out and omitted, with a matchingOPTIONALITY_EXEMPTIONSentry.DEPRECATED_FIELDStometa.rs;scripts/regenerate-deprecated-fields.pyregenerates it from the snapshot.deprecated_fields_match_spec(constant vs spec) anddeprecated_fields_hidden(constant vsmodels.rsmarkers) keep all three in lockstep.CLI (
clickhousectl)preserve_order; addcloud/output.rs::print_human, which renders responses as an indented tree from their serialized form. Detail/get human output now flows through serde — so deprecated fields disappear from both human and--jsonoutput via one path, in declaration order.Member.role→assignedRoles); request builders drop the deprecated fields.Scripts/docs
scripts/check-openapi-drift.pyto report deprecation drift. Document the mechanism in both READMEs and CLAUDE.md.Testing
cargo build/cargo testpass with the feature both off and on.output.rscover the renderer;models_test.rscovers deprecated-field (de)serialization under both feature configs;spec_coverage_test.rsgains the drift/hidden assertions.🤖 Generated with Claude Code
Note
Medium Risk
Touches org membership, invitations, API keys, and service create/scaling request shapes; default behavior omits deprecated fields but changes visible CLI columns and wire payloads for those flows.
Overview
Adds a
deprecated-fieldsCargo feature (off by default) so OpenAPIdeprecated: truefields are removed frommodels.rsunless the feature is on—blocking compile-time access and keeping them off the wire for requests and out of serialized output for responses.DEPRECATED_FIELDSinmeta.rs,regenerate-deprecated-fields.py, andspec_coverage_test/check-openapi-drift.pykeep the list aligned with the spec.The CLI forwards the feature, switches detail views to
print_human(serde-driven trees withpreserve_order), updates member/invitation list tables toassignedRoles, and stops sending deprecated fields in request builders. Docs and tests cover both feature configurations.Reviewed by Cursor Bugbot for commit c8a5ffc. Bugbot is set up for automated code reviews on this repo. Configure here.