Skip to content

feat: Rework favor rule and capability against checks#16

Merged
jdehaan merged 16 commits into
mainfrom
feat/favor-rule-capability
May 17, 2026
Merged

feat: Rework favor rule and capability against checks#16
jdehaan merged 16 commits into
mainfrom
feat/favor-rule-capability

Conversation

@jdehaan
Copy link
Copy Markdown
Member

@jdehaan jdehaan commented May 17, 2026

remove checks entirely if possible

Fixes #9

jdehaan added 16 commits May 17, 2026 17:52
Add Intersect(Vec<String>) filter variant that keeps only items
whose display form appears in the provided other set. The filter
accepts a variable reference as argument (e.g., intersect($other))
which is resolved at eval time via the Expression evaluator.

- Filter enum variant + dispatch in filters/mod.rs
- Implementation in filters/list.rs using HashSet
- list_arg_filter category in expr.rs for parsing
- Unit tests for filter function and expression evaluation
Add ForEach variant to RuleCondition that iterates over a list and
produces one Finding per item. Each item is injected into the value
map under the configured item_var name, enabling template substitution
in the outcome (finding_id, title, description).

- ForEach { source, item_var, severity } condition variant
- eval_for_each() method returning Vec<Finding>
- Extract eval_conditions() helper to keep run() within complexity limit
- Unit tests for per-item finding generation and empty-list case
Replace the compiled OldCrashDumpsCheck with a YAML rule that uses
the existing old_files capability and the new for_each condition type
to produce per-file findings.

- Add rules/old-crash-dumps.yaml
- Remove crates/hah-checks/src/drift.rs module
- Remove unused tempfile/filetime dev-dependencies from hah-checks
- Update registry (7 compiled + 17 YAML = 24 total checks)
Replace the compiled SnapAptDuplicateCheck with a YAML rule using:
- intersect filter to find packages in both snap and apt
- reject_in filter to exclude allowlisted packages
- for_each condition for per-package findings
- Seed config.allowlist.packages into the DSL value map

Also adds the reject_in filter (set subtraction, opposite of intersect).

- Add rules/snap-apt-duplicate.yaml
- Remove crates/hah-checks/src/snap.rs module
- Update registry (6 compiled + 18 YAML = 24 total checks)
Add SymlinkTarget probe variant that returns the symlink target as a
Str, or Null if the path is not a symlink or does not exist. This
enables filesystem introspection beyond read-file and file-size.

Port ResolvedConfigCheck to a declarative YAML rule using:
- service_active probe as guard (systemd-resolved must be active)
- symlink_target probe to read /etc/resolv.conf link target
- All condition with contains() check for correct target

- Add ProbeSpec::SymlinkTarget variant with read_link implementation
- Add rules/resolved-config.yaml
- Remove ResolvedConfigCheck from network.rs and registry
- Update to 5 compiled + 19 YAML = 24 total checks
- Add symlink_target probe to probe section with example
- Add intersect and reject_in filters to filter table
- Add for_each condition type to conditions table and example
- Add new rule files to examples table (snap-apt-duplicate, resolved-config, old-crash-dumps)
…+ YAML

Add NtpActiveServices capability that returns the list of active NTP
service labels (ntp, chrony, openntpd, systemd-timesyncd). The YAML
rule uses count + numeric_threshold to detect conflicts (>1 active).

- Add CapabilitySpec::NtpActiveServices variant and dispatch
- Add ntp_active_services() in capabilities.rs
- Add rules/ntp-conflict.yaml
- Remove NtpConflictCheck from network.rs and registry
- 4 compiled + 20 YAML = 24 total checks
Add LargeInitramfs capability that scans /boot for initramfs images
exceeding a configurable threshold and returns 'filename size_mb'
strings. The YAML rule uses for_each to produce per-image findings.

- Add CapabilitySpec::LargeInitramfs { threshold_mb } and dispatch
- Add large_initramfs() in capabilities.rs
- Add rules/initramfs-size.yaml
- Remove boot.rs module and registry entry
- 3 compiled + 21 YAML = 24 total checks
Convert LegacySourcesFormatCheck, LegacyNetworkInterfacesCheck, and
UserDefinedPackageCheck to capability-based YAML rules. Remove the
hah-checks crate entirely — all 24 checks are now declarative.

- Add LegacyAptSources, LegacyNetworkInterfaces, InstalledDenylist
  capabilities with testable internal helpers
- Add rules: legacy-apt-sources.yaml, legacy-network-interfaces.yaml,
  user-denylist.yaml
- Remove hah-checks from workspace and delete crate directory
- 0 compiled + 24 YAML = 24 total checks
Remove references to hah-checks crate. Document that all checks are now
declarative YAML rules backed by capabilities in hah-dsl.
The ntp-conflict check now uses a pure YAML rule with a shell one-liner
that prints active NTP service names. This removes the need for a
dedicated Rust capability — the DSL's command trigger + pipeline
filters (lines | non_empty | count) handle the logic entirely.

- Remove CapabilitySpec::NtpActiveServices and ntp_active_services()
- Update ntp-conflict.yaml to use sh -c trigger
- Update docs/dsl.md capabilities table
Move all capability implementations from hah-dsl/src/capabilities.rs into
the new hah-caps crate, with one module per domain (apt, files, initramfs,
journal, kernel, network, sysctl).

hah-dsl retains a thin caps_bridge adapter that dispatches CapabilitySpec
variants to hah-caps functions and converts CapValue into RuleValue.

- Add crates/hah-caps with CapValue enum and 7 capability modules
- Replace hah-dsl capabilities.rs with caps_bridge.rs
- Update dispatch_capability in rule.rs to delegate to caps_bridge
- Update architecture.md, dsl.md, dev/README.md for new crate layout
@jdehaan jdehaan merged commit c069a85 into main May 17, 2026
1 check passed
@jdehaan jdehaan deleted the feat/favor-rule-capability branch May 17, 2026 17:44
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.

Shift more into declarative rule files

1 participant