Skip to content

feat(cli): group flat subcommands under noun-led command groups#124

Merged
mostafa merged 1 commit into
mainfrom
feat/cli-command-groups
May 17, 2026
Merged

feat(cli): group flat subcommands under noun-led command groups#124
mostafa merged 1 commit into
mainfrom
feat/cli-command-groups

Conversation

@mostafa
Copy link
Copy Markdown
Member

@mostafa mostafa commented May 17, 2026

Summary

Reorganize the 12 flat top-level rsigma subcommands into five noun-led command groups (engine, rule, backend, pipeline, attack) so the CLI scales as more subcommands arrive. The flat aliases keep working as visible-deprecated forwarders for one release, will be hidden in the next, and removed in v1.0. No breaking change in this release.

Migration map

Old (flat, deprecated) New (grouped)
rsigma eval ... rsigma engine eval ...
rsigma daemon ... rsigma engine daemon ...
rsigma parse ... rsigma rule parse ...
rsigma validate ... rsigma rule validate ...
rsigma lint ... rsigma rule lint ...
rsigma fields ... rsigma rule fields ...
rsigma condition ... rsigma rule condition ...
rsigma stdin ... rsigma rule stdin ...
rsigma convert RULES ... rsigma backend convert RULES ...
rsigma list-targets rsigma backend targets
rsigma list-formats TARGET rsigma backend formats TARGET
rsigma resolve ... rsigma pipeline resolve ...

What you'll see

Invoking any flat alias prints one stderr line:

warning: `rsigma <old>` is deprecated; use `rsigma <new>` instead. This alias will be hidden in the next release and removed in v1.0.

stdout is unchanged. Exit codes are unchanged. Every flag accepted by the old form is accepted by the new form with identical defaults and semantics.

Why noun-led groups

Every group is a noun (engine, rule, backend, pipeline, attack), so command paths read as "rsigma's X tooling: do Y" rather than the awkward verb-on-verb chains a run/convert group would produce (rsigma convert run RULES vs the chosen rsigma backend convert RULES). The five groups are deliberately stable and small so future commands have an obvious home rather than landing as more top-level sprawl.

attack group reserved

rsigma attack --help lists no subcommands in this release. The AttackCommands enum is intentionally empty and is reserved for MITRE ATT&CK tooling that will land in a separate change. No new top-level attack-coverage or attack-update commands will ever ship; both will land as attack subcommands.

Deprecation timeline

  • This release: flat aliases visible in rsigma --help with [deprecated] tag, stderr warning on invocation.
  • Next release: #[command(hide = true)] removes them from --help but invocations still work.
  • v1.0: flat aliases removed.

Internal refactor

  • Each subcommand's clap arguments now live in crates/rsigma-cli/src/commands/<name>.rs as a pub struct <Name>Args deriving clap::Args.
  • The daemon's 35-field arg set + cmd_daemon body + parse_input_format + parse_tz_offset moved out of main.rs into a new crates/rsigma-cli/src/commands/daemon.rs (mirroring the existing commands/eval.rs pattern).
  • main.rs dropped from ~1360 lines to ~520, with the dispatch becoming a thin two-layer match (group → leaf). No behavior change.

Test plan

  • cargo build -p rsigma (default features) — clean
  • cargo build -p rsigma --all-features --tests — clean
  • cargo test -p rsigma --features daemon182 passed across 13 suites, 0 failed
  • cargo clippy -p rsigma --all-features --all-targets -- -D warnings — clean
  • cargo fmt --all -- --check — clean
  • New tests/cli_deprecation.rs (17 tests) covers each deprecated alias: still succeeds, prints stderr warning, identical stdout to the new form where comparable; plus --help lists every group + every deprecated alias with [deprecated].
  • Every existing CLI integration test invocation migrated to the new grouped paths (~150 sites).
  • Pre-existing --no-default-features build errors in commands/resolve.rs and commands/validate.rs (unconditional rsigma_runtime/tokio use that should be daemon-gated) are unchanged. Out of scope here.

Docs

Follow-ups

Reorganize the 12 flat top-level subcommands into five noun-led groups
(engine, rule, backend, pipeline, attack) so the CLI scales as more
subcommands arrive (most immediately, `attack coverage` and `attack
update` from the upcoming MITRE ATT&CK contributor PR).

Migration map:

  eval         -> engine eval
  daemon       -> engine daemon
  parse        -> rule parse
  validate     -> rule validate
  lint         -> rule lint
  fields       -> rule fields
  condition    -> rule condition
  stdin        -> rule stdin
  convert      -> backend convert
  list-targets -> backend targets
  list-formats -> backend formats
  resolve      -> pipeline resolve

The flat aliases continue to work for one release as visible-deprecated
forwarders. Each flat variant carries `[deprecated]` in its clap `about`
text and prints a stderr warning before dispatching to the same `cmd_*`
helper. They will be hidden via `#[command(hide = true)]` in the next
release and removed in v1.0. Every flag, default, exit code, and stdout
shape is preserved.

The `attack` group ships now as an empty `AttackCommands` enum so the
ATT&CK contributor PR plugs `attack coverage` / `attack update` into a
stable surface rather than introducing new top-level commands.

Internal refactor: each subcommand's clap arguments now live in
`crates/rsigma-cli/src/commands/<name>.rs` as `pub struct <Name>Args`
deriving `clap::Args`, with the daemon's 35-field arg set + `cmd_daemon`
body + `parse_input_format` + `parse_tz_offset` moved out of `main.rs`
into a new `commands/daemon.rs`. `main.rs` dropped from ~1360 lines to
~520 with no behavior change; the dispatch becomes a thin two-layer
match (group -> leaf).

Tests: every CLI integration test invocation migrated to the new
grouped paths (~150 sites). New `tests/cli_deprecation.rs` (17 tests)
covers each deprecated alias plus help-text assertions for every group.
Full suite: 182 passed across 13 suites. Clippy clean across
`--all-features`. Fmt clean.

Docs: `crates/rsigma-cli/README.md` restructured under per-group
headings with a Migrating from flat commands table at the top; root
README, BENCHMARKS, rsigma-eval and rsigma-convert READMEs updated to
the new examples; CHANGELOG gets an Unreleased entry describing the
rename, deprecation timeline, and `attack` reservation.
@mostafa mostafa merged commit 05c677b into main May 17, 2026
10 checks passed
@mostafa mostafa deleted the feat/cli-command-groups branch May 17, 2026 07:48
SecurityEnthusiast pushed a commit to SecurityEnthusiast/rsigma that referenced this pull request May 17, 2026
Follow-up to timescale#124. The initial migration covered every direct
`rsigma <cmd>` invocation in markdown but missed spots where the binary
name is implicit or path-qualified:

- Docker examples in README.md and SECURITY.md invoking
  `ghcr.io/timescale/rsigma:latest validate /rules/` and
  `... daemon ...`; now `rule validate` and `engine daemon`.
- .github/workflows/ci.yml calling `./target/release/rsigma validate`
  and `... resolve ...`; now `rule validate` and `pipeline resolve`.
  Without this, every CI run against the SigmaHQ corpus and the
  dynamic-pipeline golden suite would emit the deprecation warning at us.
- Bundled pipeline YAML header comments (sysmon, ecs_windows,
  ocsf_postgres, ocsf_postgres_multi_table) showed users the old
  `rsigma eval` / `rsigma daemon` / `rsigma convert` invocation
  examples. Updated to `engine eval`, `engine daemon`, `backend convert`.
- Integration test module headers and `.expect()` error strings in
  `crates/rsigma-cli/tests/cli_daemon*.rs` and `tests/common/mod.rs`
  still referred to "rsigma daemon" / "rsigma resolve" / "rsigma
  validate" as the canonical name.

No behavior change. Deprecation aliases keep working for users on the
old paths; this just stops the project itself from printing the warning
at us on every CI run and stops the bundled documentation from teaching
the deprecated shape.
SecurityEnthusiast pushed a commit to SecurityEnthusiast/rsigma that referenced this pull request May 17, 2026
Replaces the placeholder Unreleased section with a full release-notes
draft following the format of the v0.11.0 / v0.10.0 / v0.9.0 entries.
Covers every PR merged to main since v0.11.0:

- Daemon and CLI observability (PR timescale#107) - tower-http access logs,
  per-request OTLP tracing, batch spans, source resolution spans, DLQ
  visibility, NATS/sink lifecycle, correlation eviction warnings, rule
  load diagnostics, daemon lifecycle, global `--log-format` flag.
- Eval rule loading performance (PRs timescale#119, timescale#121, timescale#122, timescale#123) - batched
  loaders rebuild indexes once per batch via `Engine::add_rules` /
  `extend_compiled_rules` / `add_collection`; single-rule path
  amortized O(1) via `RuleIndex::append_rule` and a doubling-watermark
  `FieldBloomIndex`. SigmaHQ corpus (~3,120 rules) now loads in ~120 ms.
- CLI command groups (PR timescale#124) - the noun-led `engine` / `rule` /
  `backend` / `pipeline` / `attack` grouping with the existing
  migration table preserved verbatim.
- Test reliability (PRs timescale#115, timescale#123) - cli_daemon_http and
  cli_daemon_otlp E2E suites de-flaked on macOS under load; eval bloom
  test made deterministic against random AHash seeds.
- Dependency and CI bumps.

All command-name references within the draft already use the new
noun-led paths (`engine eval`, `rule validate`, etc.) so the next
release ships with consistent terminology throughout the notes.
@mostafa mostafa mentioned this pull request May 19, 2026
5 tasks
SecurityEnthusiast pushed a commit to SecurityEnthusiast/rsigma that referenced this pull request May 20, 2026
The "operability, performance, and documentation" release.

* Workspace bumped 0.11.0 -> 0.12.0; all 10 inter-crate dep pins
  refreshed; Cargo.lock regenerated under --locked.
* CHANGELOG.md [Unreleased] section flipped to [0.12.0] - 2026-05-19;
  comparison link updated to v0.11.0...v0.12.0; tag reference added
  to the bottom-of-file link block.
* CHANGELOG also gained a Documentation site (PR timescale#129) section under
  the existing observability / eval-perf / CLI-groups / test-reliability
  / dependencies headings, and the TL;DR theme moved from "operations
  and load performance" to "operability, performance, and documentation"
  to reflect the new docs site as a top-line deliverable.

Covers all 13 PRs merged since v0.11.0: timescale#107 (observability),
timescale#111/timescale#113/timescale#114/timescale#120 (dependency batches), timescale#115/timescale#123 (test
reliability), timescale#119/timescale#121/timescale#122/timescale#123 (eval rule loading perf), timescale#124
(CLI command groups), timescale#127 (CLI docs followup), timescale#129 (documentation
site).
mostafa added a commit that referenced this pull request May 21, 2026
The CLI command groups (#124) and alias hiding (#125/#139) now ship in
the same upcoming release, so the two-stage deprecation lifecycle the
original notes described (visible -> hidden -> removed) collapses into
one (hidden -> removed). Updates the affected docs to read coherently
with this single-release reality:

- CHANGELOG: drop the standalone "Deprecated CLI aliases hidden from
  --help" subsection added a moment ago. Merge its content into the
  existing "CLI command groups" section, retitled "(PRs #124, #139)".
  The merged entry describes the final shipped state (aliases hidden
  but functional), uses the new warning text, and replaces the
  three-stage timeline list with a two-stage one (this release: hidden;
  v1.0: removed via #126). The sample --help output no longer lists
  deprecated rows and drops the stale `attack` group placeholder.

- CHANGELOG: in the Detached dynamic sources entry, drop the misleading
  "same three-release cycle as the CLI command groups (#125, #126)"
  reference. #135's own deprecation runs over three releases on its
  own track; the comparison to CLI groups was true at draft time but
  is no longer accurate.

- crates/rsigma-cli/README.md: the migration timeline previously
  claimed aliases "were visible in the previous release" - false,
  since the groups land in the same release that hides them. Rewritten
  to describe the current state without inventing a prior release.

- docs/cli/index.md: the "Migration from flat subcommands (pre-0.11)"
  section was anchored to a wrong version number, claimed five groups
  (it's four; `attack` was dropped on main), and presented alias
  hiding as a future intermediate step under #125. Rewritten as a
  flat description of the current state with the v1.0 removal pointer
  retained.

- docs/getting-started/concepts.md: one-liner about flat aliases
  updated to mention they are hidden and forward with a warning, with
  the v1.0 removal note inline.

No source code changes. All 17 cli_deprecation tests still pass.
mostafa added a commit that referenced this pull request May 21, 2026
…verbatim

v0.12.0 shipped on 2026-05-20 with PR #124's flat aliases visible-
deprecated, including a CHANGELOG entry for `### CLI command groups
(PR #124)`. The previous follow-up commit (ba4dc01) mistakenly rewrote
that entry in place to describe the post-#139 state (hidden aliases,
"PRs #124, #139", collapsed timeline), modifying tagged release notes
that should be a historical record.

This commit:

- Restores the v0.12.0 `### CLI command groups (PR #124)` subsection
  byte-for-byte from origin/main.
- Keeps the legitimate edit to the [Unreleased] `### Detached dynamic
  sources (#135)` entry: drop the "same three-release cycle as the CLI
  command groups (#125, #126)" reference that's no longer accurate.
- Adds a new [Unreleased] subsection `### Deprecated CLI aliases
  hidden from --help (#125)` describing PR #139 as a standalone
  follow-up to v0.12.0's #124, with the new warning text and pointer
  to #126 for v1.0 removal.

Net diff against origin/main is now scoped entirely to the
[Unreleased] section. v0.12.0 and every earlier tagged release are
untouched.
mostafa added a commit that referenced this pull request May 21, 2026
Adds `#[command(hide = true)]` to every deprecated flat top-level
variant in `enum Commands` (`Eval`, `Daemon`, `Parse`, `Validate`,
`Lint`, `Fields`, `Condition`, `Stdin`, `Convert`, `ListTargets`,
`ListFormats`, `Resolve`). The dispatch arms and the forwarding
behavior are unchanged, so:

- Every alias still runs successfully and still prints the migration
  warning on stderr.
- `rsigma <alias> --help` is still routable and renders the same flag
  list as the new grouped form, so scripts that introspect a subcommand
  keep working through the deprecation window.
- `rsigma --help` now lists only the four noun-led groups (`engine`,
  `rule`, `backend`, `pipeline`) plus `help`.

The `deprecation_warn` helper text is updated to match the new
lifecycle stage: "This alias is hidden from `--help` and will be
removed in v1.0."

Tests:

- `root_help_lists_all_groups_and_deprecated_aliases` rewritten as
  `root_help_hides_deprecated_aliases`; asserts `[deprecated]` is no
  longer rendered and each alias token is absent from the Commands
  block of `rsigma --help` (scoped to the Commands block so substrings
  like `engine daemon` or `stdin` flag values don't false-positive).
- `deprecated_daemon_help_lists_new_path` renamed to
  `deprecated_daemon_help_still_works`; drops the obsolete root-help
  assertion but keeps the alias-specific `--help` reachability check.
- Per-alias smoke tests (success / warning / stdout parity) are
  unchanged; all 17 deprecation tests still pass.

Docs:

- `crates/rsigma-cli/README.md` migration section rewritten. Aliases
  described as "hidden, undocumented forwarders" with the note that
  `rsigma <alias> --help` is still routable so existing scripts keep
  working. Timeline collapsed to hidden -> removed in v1.0.
- `docs/cli/index.md` migration section rewritten: drops the wrong
  pre-0.11 version anchor, the obsolete "five groups" + `attack`
  placeholder, and the now-completed intermediate hide step (#125).
- `docs/getting-started/concepts.md` one-liner updated to mention
  aliases are hidden, forward with a warning, and are removed at v1.0.
- CHANGELOG gets a new `### Deprecated CLI aliases hidden from
  --help (#125)` entry under `## [Unreleased]`. The v0.12.0 release
  notes for the original `### CLI command groups (PR #124)` work are
  untouched (tagged release; historical record). The unrelated
  `### Detached dynamic sources (#135)` entry drops a stale "same
  three-release cycle as the CLI command groups (#125, #126)"
  comparison that's no longer accurate.

Verification:

- `cargo build -p rsigma --all-features`: clean
- `cargo test -p rsigma --features daemon --test cli_deprecation`: 17 passed
- `cargo test -p rsigma --features daemon` (full suite): 199 passed, 0 failed
- `cargo clippy -p rsigma --all-features --all-targets -- -D warnings`: clean
- `cargo fmt --all -- --check`: clean
- `cargo build -p rsigma --no-default-features`: unchanged from baseline
  (10 pre-existing errors in commands/resolve.rs and commands/validate.rs
  unrelated to this PR)

Removal at v1.0 tracked in #126.

Closes #125.
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.

1 participant