Skip to content

refactor!: trim the feature flags and stop testing their powerset - #70

Merged
Kilerd merged 1 commit into
mainfrom
refactor/feature-flags
Aug 1, 2026
Merged

refactor!: trim the feature flags and stop testing their powerset#70
Kilerd merged 1 commit into
mainfrom
refactor/feature-flags

Conversation

@Kilerd

@Kilerd Kilerd commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Seven flags produced a 127-job CI matrix (2^7 − 1), and most of those jobs told us nothing.

A. Stop testing the powerset

test-feature-matrix.py enumerated every subset. It now runs nothing enabled → each flag alone → all together: N + 2 jobs.

That finds the same bugs. A feature that forgets a #[cfg] fails its "alone" job; a conflict between two of them fails the "all" job. task × prometheus share no code and never had anything to say. 127 jobs becomes 7.

B. One flag removed, one pair repaired

message is gone — it gated a 160-line module and a single tokio/rt feature. The message system is now always available, like configuration and validation.

cors / static_files turned out to be broken, not redundant. The first version of this PR merged them, on the grounds that they were dependency-identical:

tower-http = { version = "0.6", optional = true, features = ["cors", "fs"] }

But that sameness was the bug, not the design — either flag enabled both halves, so an application that only wanted a CORS layer still compiled the entire static-file stack. Each flag now enables only its own half:

cors         = ["dep:tower-http", "tower-http/cors"]
static_files = ["dep:tower-http", "tower-http/fs"]
tower-http   = { version = "0.6", optional = true, default-features = false }

tower-http/cors costs nothing extra (cors = [] upstream); tower-http/fs pulls http-range-header, futures-util, http-body-util, mime_guess and friends. Measured on the real tree: 186 crates with cors alone against 192 with static_files alone.

So the flags keep their names and meanings, and now they actually mean something.

Final flag set

flag dependency
openapi oas, gotcha_core
prometheus axum-prometheus
cors tower-http/cors (no extra dependencies)
static_files tower-http/fs
task cron

⚠️ Breaking

features = ["message"] should be dropped — the message system is always available. cors and static_files are unchanged for callers.

Verification

All seven combinations build and test locally, plus workspace build with --all-features, cargo clippy --all-features --workspace, cargo fmt --check.

[]                                             OK
[prometheus]                                   OK
[openapi]                                      OK
[cors]                                         OK
[static_files]                                 OK
[task]                                         OK
[prometheus openapi cors static_files task]    OK

🤖 Generated with Claude Code

Seven flags produced a 127-job CI matrix (2^7 - 1), and most of those jobs told us nothing.

**Matrix.** `test-feature-matrix.py` enumerated the powerset. It now runs "nothing enabled", each
flag alone, and all together — N + 2 jobs. That finds the same bugs: a missing `#[cfg]` fails the
"alone" job and a conflict between flags fails the "all" job, while `task` x `prometheus`, which
share no code, never had anything to say. 127 jobs becomes 7.

**Flags.** `message` gated a 160-line module and a single `tokio/rt` feature, so it is always
available now, like configuration and validation. The remaining four each gate a dependency an
application might genuinely not want: `openapi` (oas, gotcha_core), `prometheus`
(axum-prometheus), `cors` and `static_files` (tower-http), `task` (cron).

**`cors` / `static_files` were broken, not redundant.** The dependency was declared as
`tower-http = { features = ["cors", "fs"] }`, so *either* flag enabled *both* halves — an
application that wanted only a CORS layer still compiled the whole static-file stack. Each flag
now enables only its own half (`tower-http/cors` costs nothing extra; `tower-http/fs` brings
http-range-header, futures-util, http-body-util and mime_guess). Measured: 186 crates with `cors`
alone against 192 with `static_files` alone.

BREAKING: `features = ["message"]` should be dropped — the message system is always available.
`cors` and `static_files` keep their names and meanings.

Verified locally: all seven combinations build and test, workspace builds with --all-features,
clippy --all-features, fmt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Kilerd
Kilerd force-pushed the refactor/feature-flags branch from 026ee72 to 104abaf Compare August 1, 2026 13:16
@Kilerd
Kilerd merged commit a26a583 into main Aug 1, 2026
11 checks passed
@Kilerd Kilerd mentioned this pull request Aug 1, 2026
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