fix(cli): validate logs --level and --source values - #3170
Conversation
Both flags took any string and forwarded it to the gateway, where an unrecognized value is ignored rather than rejected. The two fail in opposite directions: level_matches ranks an unknown level below every real one, so `--level warning` returns every level instead of warn and above, while source_matches compares exact strings, so a mistyped `--source` returns nothing. Neither reports an error. Make both flags value enums so a typo is an argument error that names the valid values. Matching stays case-insensitive, `--source` is still repeatable, and the defaults are unchanged. The gateway's permissiveness is deliberate for a log line's own level, since a sandbox emitting an unusual level should not disappear. The same ranking is applied to the caller's threshold, where it only disables the filter. Validating in the CLI leaves the log-line behavior alone and rejects the value a user can actually get wrong. Signed-off-by: Nathan DeMoss <ndemoss28@gmail.com>
There was a problem hiding this comment.
🟡 Changes recommended
A small test gap remains for the claimed case-insensitive --source behavior (mixed-case source values are not currently covered by tests).
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR tightens openshell logs CLI argument handling by validating --level and --source values client-side (via clap ValueEnum) to prevent silent “no-op” filtering when users provide typos, while preserving the gateway’s permissive behavior for log-line metadata.
Changes:
- Converted
--levelto a case-insensitiveValueEnum(error|warn|info|debug|trace) and made it optional to preserve the “no filter” default. - Converted
--sourceto a case-insensitive, repeatableValueEnum(gateway|sandbox|all) defaulting toall. - Added CLI parsing tests for accepted/rejected values, repeated
--source, and unchanged defaults.
File summaries
| File | Description |
|---|---|
| crates/openshell-cli/src/main.rs | Adds LogLevel/LogSource enums for clap validation and updates logs argument parsing plus unit tests. |
Review details
- Files reviewed: 1/1 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
@natedemoss is this a co-pilot configuration you're specifically using in your environment? |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
|
Sorry for the delayed response, but if you asking about the copilot review, that's just a personal GitHub setting on my account that auto-requests Copilot review on any PR I open(think its a default setting tbh), nothing repo-side, happy to turn it off. |
|
I was thinking about logging yesterday. Would a numeric level as is common in tooling in the Kubernetes ecosystem be a more useful direction to go into? (It's not core to this change, but at least related). |
sylvesterkaczmarek
left a comment
There was a problem hiding this comment.
I think ocsf should remain an accepted --level value. The gateway already treats OCSF as the INFO rank, so it is a real level in the system rather than just an invalid string that happened to pass. Rejecting an existing working filter is avoidable; could the enum include ocsf while still rejecting typos?
Summary
openshell logsaccepts any string for--leveland--sourceand forwards it to the gateway, where an unrecognized value is silently ignored rather than rejected. A typo produces wrong output with no indication anything went wrong, and the two flags fail in opposite directions.Related Issue
No issue required: obvious localized bug fix in CLI argument handling.
Changes
--levelis now a value enum (error,warn,info,debug,trace), case-insensitive, defaulting to no filter.--sourceis now a value enum (gateway,sandbox,all), case-insensitive, still repeatable and still defaulting toall.--source, and unchanged defaults.The bug
--level warninginstead ofwarnreturns every level, and a mistyped--sourcereturns nothing:That output is from running the gateway's own
level_matchesandsource_matches(crates/openshell-server/src/grpc/validation.rs) against each level and source.level_matchesranks an unrecognized level at 5, below every real level, so using one as the threshold lets everything through.source_matchescompares by exact string, so a mistyped source matches nothing.Why this belongs in the CLI
The server's
// unknown levels always passlooks deliberate, and for a log line's own level it is: a sandbox emitting an unusual level should not silently disappear. The sameto_numis also applied to the caller's threshold, where the same permissiveness just disables the filter.Validating in the CLI keeps the server's behavior for log lines intact and rejects the case the user can actually get wrong, at the point where the error can name the valid values. It also gives the flags shell completion.
The gateway still accepts unrecognized levels from other clients. Tightening that is a wider change across the SDKs and seemed worth separating from this.
Testing
mise run pre-commitpassesNo mise or Docker locally, so I ran the steps individually:
cargo fmt --all -- --checkcleancargo test -p openshell-clipasses, 0 failures, including the five new testscargo clippy -p openshell-cli --all-targets -- -D warningscleanopenshell logs --level warn,--level ERROR, and repeated--sourceall still parse as before, and the defaults are unchanged.Two behavior changes worth calling out
--level ocsfused to be accepted. The gateway groupsINFO | OCSFat the same rank, so it behaved asinfo. It is not in the docs or the flag help, so it is not in the enum, but it did work and would now be rejected. Happy to add it if you would rather keep it.A script passing an invalid level today gets all levels back and exits 0. After this it gets an argument error. That is the point of the change, but it is a visible difference for anyone who has been relying on the broken filter without noticing.
Checklist
Assisted by Opus 5.0.