refactor(jans-cedarling): defer audit entry serialization off hot path#14531
Conversation
* replace SerializedAuditEntry (Box<str>) with typed AuditItem * drop Loggable::get_log_kind in favor of into_audit_payload * replace LockService LogWriter impl with dispatch_audit routing by payload variant * carry pdp_id/app_name as typed fields, not stringified Signed-off-by: dagregi <dagmawi.m@proton.me>
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughCedarling replaces serialized audit strings with typed ChangesTyped audit pipeline
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
jans-cedarling/cedarling/src/lock/transport/rest.rs (1)
314-319: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winUse
expect_errwith a descriptive message and add a message toassert!(matches!(...)).This assertion uses
result.unwrap_err()and a message-lessassert!(matches!(...)). The equivalent gRPC test (test_send_logs_malformed_json, lines 605-615) already follows the required pattern; align this one for parity and better failure diagnostics.As per coding guidelines: "For error checking in tests, use
result.expect_err(...)", "For pattern matching errors in tests, useassert!(matches!(...), "descriptive message")", and "All assertions must include a descriptive message".💚 Proposed fix
- let result = transport.send(&entries, &AuditKind::Log(endpoint)).await; - assert!(matches!( - result.unwrap_err(), - TransportError::Serialization(_) - )); + let error = transport + .send(&entries, &AuditKind::Log(endpoint)) + .await + .expect_err("all-invalid batch must fail mapping"); + assert!( + matches!(error, TransportError::Serialization(_)), + "expected serialization error, got {error:?}" + );🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@jans-cedarling/cedarling/src/lock/transport/rest.rs` around lines 314 - 319, Update the test around the `transport.send` result to use `result.expect_err(...)` with a descriptive failure message, then pass the resulting error to `assert!(matches!(...))` and add a descriptive assertion message. Match the established pattern in `test_send_logs_malformed_json` for consistency.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@jans-cedarling/cedarling/src/lock/transport/mapping.rs`:
- Around line 97-100: Validate that entry.base.timestamp is present and
non-empty before constructing the mapped entry; do not use unwrap_or_default().
Update the validation in the mapping function containing this logic to return
MappingValidationError::MissingField for None or blank timestamps, while
preserving the existing action/resource checks and only assigning
creation_date/event_time after validation.
In `@jans-cedarling/cedarling/src/lock/transport/rest.rs`:
- Around line 91-159: Consolidate the duplicated sample builders across the REST
and gRPC transport tests. Move `sample_log_item`, `sample_metric_item`, and
`sample_health_item` into a shared test-only module, reusing the existing
`mapping.rs` helpers such as `decision_audit_item` and `metric_audit_item` where
applicable, then update both transport test modules to import and call the
shared builders instead of defining local copies.
---
Outside diff comments:
In `@jans-cedarling/cedarling/src/lock/transport/rest.rs`:
- Around line 314-319: Update the test around the `transport.send` result to use
`result.expect_err(...)` with a descriptive failure message, then pass the
resulting error to `assert!(matches!(...))` and add a descriptive assertion
message. Match the established pattern in `test_send_logs_malformed_json` for
consistency.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 02f5145b-2678-4f49-bcaf-fcf21d398c44
📒 Files selected for processing (14)
jans-cedarling/cedarling/src/common/policy_store/log_entry.rsjans-cedarling/cedarling/src/jwt/log_entry.rsjans-cedarling/cedarling/src/lock/health_ticker.rsjans-cedarling/cedarling/src/lock/log_entry.rsjans-cedarling/cedarling/src/lock/log_worker.rsjans-cedarling/cedarling/src/lock/mod.rsjans-cedarling/cedarling/src/lock/transport/grpc.rsjans-cedarling/cedarling/src/lock/transport/mapping.rsjans-cedarling/cedarling/src/lock/transport/mod.rsjans-cedarling/cedarling/src/lock/transport/rest.rsjans-cedarling/cedarling/src/log/err_log_entry.rsjans-cedarling/cedarling/src/log/interface.rsjans-cedarling/cedarling/src/log/log_entry.rsjans-cedarling/cedarling/src/log/log_strategy.rs
💤 Files with no reviewable changes (1)
- jans-cedarling/cedarling/src/lock/log_entry.rs
Signed-off-by: dagregi <dagmawi.m@proton.me>
Signed-off-by: dagregi <dagmawi.m@proton.me>
Signed-off-by: dagregi <dagmawi.m@proton.me>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
jans-cedarling/cedarling/src/lock/transport/rest.rs (1)
248-252: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winUse
expect_errand add a descriptive assertion message.This assertion uses
unwrap_err()and a message-lessassert!(matches!(...)), unlike the sibling error tests here and ingrpc.rs.As per coding guidelines: "For pattern matching errors in tests, use
assert!(matches!(...), "descriptive message")" and "Useexpect_err("explicit comment")instead ofpanic()when expecting errors in tests".♻️ Proposed change
- let result = transport.send(&entries, &AuditKind::Log(endpoint)).await; - assert!(matches!( - result.unwrap_err(), - TransportError::Serialization(_) - )); + let error = transport + .send(&entries, &AuditKind::Log(endpoint)) + .await + .expect_err("all-invalid batch must fail mapping"); + assert!( + matches!(error, TransportError::Serialization(_)), + "expected serialization error, got {error:?}" + );🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@jans-cedarling/cedarling/src/lock/transport/rest.rs` around lines 248 - 252, Update the error assertion in the REST transport test using the existing `transport.send` call: replace `unwrap_err()` with `expect_err(...)` and add a descriptive message to the surrounding `assert!(matches!(...))`, matching the style of the sibling REST and gRPC error tests.Source: Coding guidelines
jans-cedarling/cedarling/src/lock/transport/mapping.rs (1)
331-340: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winReject blank timestamps too
LockServerLogEntry::try_from(&AuditItem)rejectsNone, butSome("")still flows through ascreation_dateandevent_time. Add a non-empty/RFC3339 validation here so malformed timestamps fail instead of being forwarded.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@jans-cedarling/cedarling/src/lock/transport/mapping.rs` around lines 331 - 340, Extend LockServerLogEntry::try_from(&AuditItem) timestamp validation to reject Some("") and other malformed values, not only None. Require a non-empty RFC3339 timestamp before assigning creation_date and event_time, return MappingValidationError::MissingField (or the existing appropriate validation error), and add tests covering blank and invalid timestamp strings.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@jans-cedarling/cedarling/src/lock/transport/mapping.rs`:
- Around line 331-340: Extend LockServerLogEntry::try_from(&AuditItem) timestamp
validation to reject Some("") and other malformed values, not only None. Require
a non-empty RFC3339 timestamp before assigning creation_date and event_time,
return MappingValidationError::MissingField (or the existing appropriate
validation error), and add tests covering blank and invalid timestamp strings.
In `@jans-cedarling/cedarling/src/lock/transport/rest.rs`:
- Around line 248-252: Update the error assertion in the REST transport test
using the existing `transport.send` call: replace `unwrap_err()` with
`expect_err(...)` and add a descriptive message to the surrounding
`assert!(matches!(...))`, matching the style of the sibling REST and gRPC error
tests.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: d7c147db-3f9c-4bbd-b343-4dd3bf203584
📒 Files selected for processing (8)
jans-cedarling/cedarling/examples/log_init.rsjans-cedarling/cedarling/examples/profiling_multi_issuer.rsjans-cedarling/cedarling/examples/profiling_unsigned.rsjans-cedarling/cedarling/src/lock/transport/grpc.rsjans-cedarling/cedarling/src/lock/transport/mapping.rsjans-cedarling/cedarling/src/lock/transport/mod.rsjans-cedarling/cedarling/src/lock/transport/rest.rsjans-cedarling/cedarling/src/lock/transport/test_utils.rs
| }; | ||
|
|
||
| if let Err(err) = sender.try_send(serialized) { | ||
| if let Err(err) = tx.clone().try_send(item) { |
There was a problem hiding this comment.
I think this might have quietly changed the channel backpressure. The old code held one Sender behind the RwLock so when the buffer filled up try_send returned Full and we dropped the entry (that's what the "channel send failed (full or closed)" log is for).
Now we clone a fresh Sender on every dispatch. With futures::channel::mpsc each sender gets its own guaranteed slot on top of the buffer and a freshly cloned sender is never parked so its try_send pushes the message no matter how full the channel already is and only parks the clone we're about to drop.
So try_send here basically never returns Full anymore. Wouldn't this mean that if the Lock Server transport stalls, the channel keeps growing past log_channel_capacity instead of dropping entries?
There was a problem hiding this comment.
I quickly checked with a futures::channel::mpsc::channel(1) and a receiver that never drains: cloning a sender per send enqueued 1000 messages with zero Full rejections but a single reused sender stopped at 2 and rejected the rest. I could be wrong about how this plays out in the worker
There was a problem hiding this comment.
If it's real, a tokio mpsc (whose try_send takes &self) or keeping one shared sender would put the bound back.
There was a problem hiding this comment.
Thanks I almost missed that I will fix it
| "requested_resource": "Jans::Issue", | ||
| "principal_id": "Jans::User", | ||
| }]))) | ||
| .match_body(mockito::Matcher::Any) |
There was a problem hiding this comment.
We dropped the PartialJson body matcher here and switched to Matcher::Any so this test no longer checks the actual payload we send to the Lock Server. I think the reason is that node_name is now a random PdpID so the old hardcoded match wouldn't line up.
There was a problem hiding this comment.
I redid the partial json with node_name removed since just like used is a random uuid
|
|
||
| /// Like [`sample_log_item`], but with the required `action` field left empty so | ||
| /// that mapping into the Lock Server shape fails validation. | ||
| fn malformed_log_item() -> AuditItem { |
There was a problem hiding this comment.
This malformed_log_item builder is basically the same as the inline one in the rest.rs test_send_logs_all_invalid_dropped test (a decision entry with an empty action).
We already moved the sample builders into test_utils. maybe this one could live there too so both transports share it.
| service: "test_app".to_string(), | ||
| node_name: "test-pdp".to_string(), | ||
| status: "running".to_string(), | ||
| engine_status: HashMap::new(), |
There was a problem hiding this comment.
sample_health_item builds with an empty engine_status and the gRPC test_send_health_success dropped its old engine_status.get("core") assertion so we don't cover the engine_status -> proto conversion anymore. Could the sample carry one entry so we keep that check?
| creation_date: timestamp, | ||
| service: (!value.application_id.is_empty()).then_some(value.application_id), | ||
| node_name: value.pdp_id, | ||
| creation_date: entry.base.timestamp.clone().unwrap_or_default(), |
There was a problem hiding this comment.
Nit: the decision path now rejects a missing timestamp (the ok_or(MissingField) in the log mapping) but metrics still fall back to an empty string with unwrap_or_default().
This matches the old behavior so it's not something this PR changed but now that the two paths validate differently. Do you think metrics should reject a missing timestamp too?
There was a problem hiding this comment.
All metrics logs emitted have timestamps so getting an empty string is not possible but I'll still add the check for consistency
Signed-off-by: dagregi <dagmawi.m@proton.me>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
jans-cedarling/cedarling/src/lock/transport/rest.rs (1)
219-222: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winUse
expect_errwith a descriptive message instead ofunwrap_err().Per coding guidelines, error checking in tests should use
expect_err("descriptive message"), andmatches!assertions should include a descriptive message. The gRPC transport's equivalent test (grpc.rslines 505–515) already follows this pattern.💚 Proposed fix
- let result = transport.send(&entries, &AuditKind::Log(endpoint)).await; - assert!(matches!( - result.unwrap_err(), - TransportError::Serialization(_) - )); + let error = transport + .send(&entries, &AuditKind::Log(endpoint)) + .await + .expect_err("all malformed entries should cause a serialization error"); + assert!( + matches!(error, TransportError::Serialization(_)), + "expected serialization error, got {error:?}" + );🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@jans-cedarling/cedarling/src/lock/transport/rest.rs` around lines 219 - 222, Update the test assertion around result in the REST transport test to use expect_err with a descriptive failure message instead of unwrap_err, and add a descriptive message to the matches! assertion while preserving the TransportError::Serialization check.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@jans-cedarling/cedarling/src/lock/transport/rest.rs`:
- Around line 219-222: Update the test assertion around result in the REST
transport test to use expect_err with a descriptive failure message instead of
unwrap_err, and add a descriptive message to the matches! assertion while
preserving the TransportError::Serialization check.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 695d0dcc-4b2c-4cbb-9820-eb135bd63dc3
📒 Files selected for processing (5)
jans-cedarling/cedarling/src/lock/log_worker.rsjans-cedarling/cedarling/src/lock/mod.rsjans-cedarling/cedarling/src/lock/transport/grpc.rsjans-cedarling/cedarling/src/lock/transport/rest.rsjans-cedarling/cedarling/src/lock/transport/test_utils.rs
Signed-off-by: dagregi <dagmawi.m@proton.me>
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
jans-cedarling/cedarling/src/lock/transport/mapping.rs (1)
448-456: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winAdd a descriptive message to the assertion.
The
assert!(matches!(...))assertion violates the repository guideline requiring every assertion to explain what it verifies.Proposed fix
- assert!(matches!(err, TransportError::Serialization(_))); + assert!( + matches!(err, TransportError::Serialization(_)), + "all-malformed batches should return a serialization error", + );🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@jans-cedarling/cedarling/src/lock/transport/mapping.rs` around lines 448 - 456, Add a descriptive failure message to the assert! call in map_entries_fails_when_all_entries_are_malformed, stating that an all-malformed batch should return a TransportError::Serialization error.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@jans-cedarling/cedarling/src/lock/transport/grpc.rs`:
- Line 755: Update the test assertion on received[0].engine_status in the
relevant gRPC transport test to replace unwrap() with expect(), including a
clear message explaining that the core engine status must be present; retain the
existing equality check against "success".
---
Outside diff comments:
In `@jans-cedarling/cedarling/src/lock/transport/mapping.rs`:
- Around line 448-456: Add a descriptive failure message to the assert! call in
map_entries_fails_when_all_entries_are_malformed, stating that an all-malformed
batch should return a TransportError::Serialization error.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: af4f1a01-20e1-491d-814e-a7d29d7608f8
📒 Files selected for processing (3)
jans-cedarling/cedarling/src/lock/transport/grpc.rsjans-cedarling/cedarling/src/lock/transport/mapping.rsjans-cedarling/cedarling/src/lock/transport/test_utils.rs
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
jans-cedarling/cedarling/src/lock/transport/mapping.rs (1)
448-456: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winAdd a descriptive message to the assertion.
The
assert!(matches!(...))assertion violates the repository guideline requiring every assertion to explain what it verifies.Proposed fix
- assert!(matches!(err, TransportError::Serialization(_))); + assert!( + matches!(err, TransportError::Serialization(_)), + "all-malformed batches should return a serialization error", + );🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@jans-cedarling/cedarling/src/lock/transport/mapping.rs` around lines 448 - 456, Add a descriptive failure message to the assert! call in map_entries_fails_when_all_entries_are_malformed, stating that an all-malformed batch should return a TransportError::Serialization error.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@jans-cedarling/cedarling/src/lock/transport/grpc.rs`:
- Line 755: Update the test assertion on received[0].engine_status in the
relevant gRPC transport test to replace unwrap() with expect(), including a
clear message explaining that the core engine status must be present; retain the
existing equality check against "success".
---
Outside diff comments:
In `@jans-cedarling/cedarling/src/lock/transport/mapping.rs`:
- Around line 448-456: Add a descriptive failure message to the assert! call in
map_entries_fails_when_all_entries_are_malformed, stating that an all-malformed
batch should return a TransportError::Serialization error.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: af4f1a01-20e1-491d-814e-a7d29d7608f8
📒 Files selected for processing (3)
jans-cedarling/cedarling/src/lock/transport/grpc.rsjans-cedarling/cedarling/src/lock/transport/mapping.rsjans-cedarling/cedarling/src/lock/transport/test_utils.rs
🛑 Comments failed to post (1)
jans-cedarling/cedarling/src/lock/transport/grpc.rs (1)
755-755: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Use
expectand add an assertion message.This new test assertion uses
unwrap()and provides no explanation on failure, contrary to the Rust testing guidelines.Proposed fix
- assert_eq!(received[0].engine_status.get("core").unwrap(), "success"); + assert_eq!( + received[0] + .engine_status + .get("core") + .expect("core engine status should be present"), + "success", + "core engine status should be serialized as success", + );📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.assert_eq!( received[0] .engine_status .get("core") .expect("core engine status should be present"), "success", "core engine status should be serialized as success", );🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@jans-cedarling/cedarling/src/lock/transport/grpc.rs` at line 755, Update the test assertion on received[0].engine_status in the relevant gRPC transport test to replace unwrap() with expect(), including a clear message explaining that the core engine status must be present; retain the existing equality check against "success".Source: Coding guidelines
Signed-off-by: dagregi <dagmawi.m@proton.me>
| /// Map a batch of typed audit items into the Lock Server wire format | ||
| pub(super) fn map_entries<'a, T>( | ||
| entries: &'a [AuditItem], | ||
| label: &str, |
There was a problem hiding this comment.
I think better to have label as enum with specific entries
There was a problem hiding this comment.
Or I could just remove the param entirely and get it from the audit payload
Signed-off-by: dagregi <dagmawi.m@proton.me>
| http_conf: HttpClientConfig, | ||
| ) -> Result<WorkerSenderAndHandle, InitLockServiceError> { | ||
| let (tx, rx) = mpsc::channel::<SerializedAuditEntry>(bootstrap_conf.log_channel_capacity); | ||
| let (tx, rx) = mpsc::channel::<AuditItem>(bootstrap_conf.log_channel_capacity); |
There was a problem hiding this comment.
I think swapping to tokio's mpsc might panic at startup if someone sets log_channel_capacity to 0. tokio's mpsc::channel panics when the buffer is 0 ("mpsc bounded channel requires buffer > 0") but the old futures::channel::mpsc::channel(0) accepted it
There was a problem hiding this comment.
yes, we should verify that it has a non-zero value
let capacity = bootstrap_conf.log_channel_capacity.max(1);
There was a problem hiding this comment.
now a zero value will be clamped to 1
Signed-off-by: dagregi <dagmawi.m@proton.me>
…n placeholders Signed-off-by: Oleh Bozhok <6554798+olehbozhok@users.noreply.github.com>
Replace runtime .max(1) clamp on log_channel_capacity with compile-time NonZeroUsize. Prevents panic on tokio::mpsc::channel(0). Signed-off-by: Oleh Bozhok <6554798+olehbozhok@users.noreply.github.com>
Signed-off-by: Oleh Bozhok <6554798+olehbozhok@users.noreply.github.com>
Signed-off-by: moabu <47318409+moabu@users.noreply.github.com>
|
@coderabbitai approve |
✅ Action performedComments resolved and changes approved. |
Prepare
Description
Target issue
closes #14512
Implementation Details
Test and Document the changes
Please check the below before submitting your PR. The PR will not be merged if there are no commits that start with
docs:to indicate documentation changes or if the below checklist is not selected.Summary by CodeRabbit