test: cover the account-name and hash guards - #514
Merged
Merged
Conversation
CI's Go job failed at 99.8% against the 99.9% gate: two recent security fixes added uncovered statements. debian_group.go gained a validateAccountName guard in GetGroup, CreateGroup, UpdateGroup, and DeleteGroup with no rejection test, and defaultHashPassword's error branch was unreachable because Generate always succeeds with a nil salt. Add an invalid-name row to each group test, mirroring the existing user-side pattern, where the gomock controller's strict expectations prove no command ran. Move the sha512crypt call behind a generateHash package variable, following the hashPassword injection convention, and add a test that injects a failing generator to cover the wrapped error. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
CI's Go job failed at 99.8% against the 99.9% gate: two recent security
fixes added the same guards in many places, and only the group provider
and the password hash error path had rejection tests.
Cover the remaining gaps:
- debian_user.go: add an invalid-name row to GetUser, CreateUser,
UpdateUser, and DeleteUser, mirroring the group pattern.
- debian_ssh_key.go: add an invalid-username row to ListKeys, AddKey,
and RemoveKey.
- validate.go: expose validatePasswordInput via export_test.go and add
a direct test for its name-side rejection, which CreateUser and
ChangePassword can never reach since validateAccountName already
rejects a colon or line break in the name before either caller gets
there.
- internal/controller/api/node/user handlers: add a 400 row with an
invalid name in the path to every handler that calls validateName
(user/group get, update, delete, password, and SSH key add/list/
delete), which also exercises internal/validation's account_name
validator for the first time and closes out init()'s coverage.
- PutNodeUser and PutNodeGroup additionally gained a body-level
account_name check (dive over Groups/Members); add a row with an
invalid entry in each to cover that branch too.
Verified with `just test`: 100.0% (up from 99.8%), meets the 99.9% gate.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FuKUsHFG1EqZXamffh9M2c
Codecov Report✅ All modified and coverable lines are covered by tests. @@ Coverage Diff @@
## main #514 +/- ##
==========================================
- Coverage 99.93% 99.90% -0.04%
==========================================
Files 488 489 +1
Lines 23108 23174 +66
==========================================
+ Hits 23094 23153 +59
- Misses 14 21 +7
... and 1 file with indirect coverage changes Continue to review full report in Codecov by Harness.
🚀 New features to boost your workflow:
|
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.
Main's
Gojob fails at 99.8% against the 99.9% gate. Two merged security fixes added guard statements with no rejection tests. This restores the gate to 100.0%.Provider (
internal/provider/node/user):debian_user.go— invalid-name rows forGetUser,CreateUser,UpdateUser,DeleteUserdebian_group.go— invalid-name rows forGetGroup,CreateGroup,UpdateGroup,DeleteGroupdebian_ssh_key.go— invalid-username rows forListKeys,AddKey,RemoveKeyvalidatePasswordInput's name branch is unreachable through the API, becausevalidateAccountNamerejects colons and newlines first. Exposed throughexport_test.goand tested directly in a newvalidate_public_test.go.In every provider row the
setupsets no exec expectation, so gomock's strict controller fails if a command is ever invoked — that is the "no command ran" assertion, not just an error-string check.Handlers (
internal/controller/api/node/user): a 400 row for an invalid path name on all ten — user get/update/delete/password, group get/update/delete, and the three SSH-key operations.PutNodeUserandPutNodeGroupneeded one more row each: their bodies carryGroups/Memberstaggedomitempty,dive,account_name, and the body-level rejection was untested and distinct from the path-parameter one.internal/validationinit: theaccount_namevalidator closure had never been exercised anywhere in the repository. It is now covered as a side effect of the handler rows, sincevalidateNamecallsvalidation.Var(name, "required,account_name").Hash error path:
defaultHashPassword's error branch was unreachable, because the crypt library always succeeds with a nil salt. The library call now sits behind agenerateHashpackage variable — the same injection conventionhashPasswordalready uses — with a setter and reset inexport_test.goand a row that injects a failure. Production wiring and hash format are unchanged.Out of scope and untouched, since they predate this and were present when the gate passed:
process/debian.goProcesses,file_upload.go, the docker and power handlers, andagent/handler.gostartInProgressKeepAlive.Two commits rather than one: the second could not be amended into the first, and the history reads fine as a pair.
🤖 Generated with Claude Code
https://claude.ai/code/session_01FuKUsHFG1EqZXamffh9M2c