Skip to content

feat(cli): load rules database from file - #78

Open
alexsmolya wants to merge 2 commits into
Coding-Moves:mainfrom
alexsmolya:codex/issue-68-rules-file
Open

feat(cli): load rules database from file#78
alexsmolya wants to merge 2 commits into
Coding-Moves:mainfrom
alexsmolya:codex/issue-68-rules-file

Conversation

@alexsmolya

Copy link
Copy Markdown

What & why

Fixes #68

diskern scan can now accept an optional external rules database:

diskern scan <path> --rules ./my-rules.json

Without --rules, the CLI continues to use the embedded rules database. A supplied file is deserialized through the existing RulesDb model, with explicit errors for unreadable files and malformed JSON. Human-readable output identifies the external rules source, while JSON output remains valid on stdout. The change stays at the CLI boundary and does not move classification logic out of diskern-core.

The user-visible feature is documented in CHANGELOG.md.

Validation

  • cargo fmt --all
  • cargo +1.96.0 clippy -p diskern-core -p diskern-cli --all-targets -- -D warnings
  • cargo +1.96.0 test -p diskern-core -p diskern-cli
  • git diff --check

All passed. The focused suite includes regression coverage for embedded rules, valid external rules, missing files, and malformed JSON.

Checklist

  • cargo fmt --all and the required core/CLI clippy validation are clean
  • The required core/CLI test suite passes
  • Commits are small and focused (one logical change each)
  • Doesn't weaken a safety principle (read-only scans, quarantine over deletion, deterministic verdicts)
  • Workspace-wide GUI validation was not run; it is outside the repository-required core/CLI gate

@Muawiya-contact

Copy link
Copy Markdown
Member

@alexsmolya Welcome, and thanks for the contribution! Nice to have you here. 🙌

I went through the implementation, the tests, the contributing guide and the docs. The change is nicely scoped: it stays at the CLI boundary, fails before the scan starts if the file is bad, and keeps stdout clean in JSON mode. Test coverage for embedded / valid / missing / malformed is good to see.

Left a few comments inline. Only the docs one really blocks, the rest we can talk through. Once that's sorted I'm happy to approve and merge.

Comment thread CHANGELOG.md

### Added

- `diskern scan --rules <file>` to test scans with an external rules database

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to have the entry here. Could you also add a row for --rules <file> to the flags table in crates/diskern-cli/README.md? It's user facing, so it should sit with --top, --verdict and --json rather than only in the CHANGELOG.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed: added --rules <file> to the CLI flags table in crates/diskern-cli/README.md.

Comment thread crates/diskern-cli/src/main.rs Outdated
path.display()
)
})?;
serde_json::from_slice(&contents)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing worth guarding: rules::compile throws away patterns that aren't valid globs and only reports it through tracing::warn!, and the CLI doesn't install a subscriber. So a typo in a pattern matches nothing and the scan still exits 0.

Could we compile the patterns in load_rules and error out early? diskern-core keeps the shipped db honest the same way in every_shipped_pattern_is_a_valid_glob.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented: external rule patterns are compiled and invalid globs are rejected before scanning, with regression coverage.

verdict,
rules,
} => {
let external_rules = rules.as_deref();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the external file replaces the whole db, the protected rules go with it. A rules file with a safe rule for **/*.msi would list C:/Windows/Installer/*.msi under "Safe to remove", which is the case the rule ordering in base.json is there to prevent.

Would you be open to keeping the embedded protected rules in front of the external ones, or warning when the loaded db has none? Happy to go either way.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented: embedded protected rules are evaluated before external rules, with regression coverage preventing external rules from overriding them.

}
}

fn load_rules(path: Option<&std::path::Path>) -> Result<RulesDb> {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional: version is read but never checked, so a file written for a later schema would load quietly with today's semantics. A small check that bails on an unknown version would make the field worth carrying.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The schema version is intentionally unchanged: the repository defines no compatibility or rejection policy for schema versions, so introducing a check here would invent policy beyond this change.

@Muawiya-contact

Copy link
Copy Markdown
Member

On the docs point, this is the table I meant:

| Flag | Default | Effect |
| ----------- | ------- | ------------------------------------------------------- |
| `--top N` | `5` | Findings shown per category; `0` shows every one. |
| `--verdict` | all | `safe`, `review`, `risky` or `protected`. Duplicate sets have no verdict, so they are omitted when this is set. |
| `--json` | off | Full report as JSON; the flags above don't apply. |

A row right under --json would do it, something like:

| --rules | embedded | Load the rules database from a JSON file instead of the embedded one. |

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Let the CLI load a rules file, so rules can be tested without a rebuild

2 participants