fix(grpc): allow credential rotation when legacy provider.type exceeds current limit#1350
Open
latenighthackathon wants to merge 1 commit into
Conversation
…s current limit Closes NVIDIA#1347. Reported by @KodeDaemon in the NVIDIA Developer Discord after upgrading NemoClaw 0.0.38 -> 0.0.39 left the inference provider stranded with `provider.type exceeds maximum length (79 > 64)` on every credential update. `update_provider_record` rebuilt the merged Provider from `existing.r#type` and ran `validate_provider_fields` over it. The CLI's `provider update` sends `r#type: ""`, so the existing value is preserved without modification, but the validator still measured it. Any record whose stored type predates current MAX_PROVIDER_TYPE_LEN (or was written by a path that bypassed validation, e.g. the TUI form which forwards r#type to the request without going through normalize_provider_type) became unupdateable: the only escape was `provider delete` + recreate, which loses any provider.config entries the caller never sees. Split the validator into create-time (validate_provider_fields, full check including immutable name/type) and update-time (validate_provider_mutable_fields, checks only credentials/config maps). The update path validates only what the caller is mutating; immutable fields carried forward from existing are trusted because they passed validation when stored. Tests: new regression in `update_provider_allows_credential_rotation_on_legacy_oversized_type` inserts a Provider with a 79-char type directly via `store.put_message` (bypassing gRPC validation), updates a credential, asserts the update succeeds and the original type is preserved. Existing `update_provider_validates_merged_result` still covers the case where incoming credential entries push the merged map past limits. Signed-off-by: latenighthackathon <latenighthackathon@users.noreply.github.com>
063f82b to
d2fe817
Compare
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.
Summary
openshell provider update <name> --credential ...re-validates the immutabletypefield on every call, stranding any legacy record whose stored type exceeds the currentMAX_PROVIDER_TYPE_LEN(64). Split provider validation into create-time and update-time variants so the update path only validates fields the caller is mutating (credentials,config); immutable name/type are carried forward from the existing record without re-checking length.Related Issue
Closes #1347.
Reported by @KodeDaemon in the NVIDIA Discord community after upgrading NemoClaw 0.0.38 to 0.0.39:
openshell provider listconfirmed an existing inference provider had a 79-charactertypevalue. NemoClaw's onboard re-runsopenshell provider update inference --credential ...on every upgrade, and that path failed becauseupdate_provider_recordrebuilt the merged Provider fromexisting.r#typeand ran the fullvalidate_provider_fieldsover it, even though the caller only touches credentials. The CLI'sprovider updatesendsr#type: "", so the existing value was preserved without modification, but the validator still measured it.Two ways legacy data ends up oversized: (1) records that predate
validate_provider_fields(added by #145, later split out in #777); (2) write paths that bypassnormalize_provider_type, e.g. the TUI form at crates/openshell-tui/src/lib.rs:1563 which forwardsr#typeto the request directly. Either way, the only escape wasprovider delete+ recreate, which loses anyprovider.configentries the caller never sees.Changes
crates/openshell-server/src/grpc/validation.rs:validate_provider_fieldskeeps the full create-time check (name + type + credentials + config), now delegating the map checks to a new helper.validate_provider_mutable_fieldsvalidates onlycredentialsandconfig; used by the update path.crates/openshell-server/src/grpc/provider.rs:update_provider_recordcallsvalidate_provider_mutable_fieldsinstead ofvalidate_provider_fields. Immutable name/type carried forward fromexistingare trusted because they passed validation when stored.Testing
cargo test -p openshell-server --lib grpc::provider(32 passed including new regression)cargo test -p openshell-server --lib grpc::validation(76 passed)cargo clippy -p openshell-server --all-targets -- -D warnings(clean)cargo fmt --all -- --check(clean)New regression
update_provider_allows_credential_rotation_on_legacy_oversized_typeinserts a Provider with a 79-character type directly viastore.put_message(bypassing gRPC validation, simulating a legacy record), then callsupdate_provider_recordto rotate a credential and asserts both that the update succeeds and the original 79-character type is preserved on the stored record. Existingupdate_provider_validates_merged_resultcontinues to assert that an oversized incoming credential key is still rejected, so incoming-mutation validation is unchanged.Checklist
Signed-off-by: latenighthackathon latenighthackathon@users.noreply.github.com