Conversation
Greptile SummaryFixes a bug where The new Confidence Score: 5/5Safe to merge — targeted fix with a clear regression test and no observable behaviour change for callers that already pass No P0 or P1 findings. The new No files require special attention. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[fnox set KEY VALUE] --> B{--provider flag?}
B -- yes --> C[Use explicit provider]
B -- no --> D{Existing secret\nhas provider?}
D -- yes --> E[Reuse existing provider\n🆕 new fallback]
D -- no --> F{default_provider\nconfigured?}
F -- yes --> G[Use default provider]
F -- no --> H[Store as plaintext]
C & E & G --> I[Encrypt / store with provider]
H --> J[Store as default value]
I & J --> K[Save config file]
Reviews (3): Last reviewed commit: "perf(config): add get_secret for non-clo..." | Re-trigger Greptile |
There was a problem hiding this comment.
Code Review
This pull request updates the set command to automatically reuse a secret's existing provider when updating its value if no provider is explicitly specified. It also adds a comprehensive integration test to ensure this behavior works correctly with multiple providers. A performance concern was raised regarding the inefficient cloning of the secrets map during the provider lookup, suggesting a more direct access method instead.
3acd925 to
018faf1
Compare
When multiple providers were configured without a `default_provider`, running `fnox set` on an existing secret without `--provider` stored the new value as plaintext while leaving the original `provider` key in place. Subsequent `fnox get` calls then failed, since fnox would try to decrypt a value that was no longer encrypted. Before falling back to `default_provider` or plaintext, we now reuse the secret's existing provider. This allows updates to stay encrypted and readable without requiring `--provider` on every call. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Avoid cloning the entire secrets map in `set` just to read the existing secret's provider. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
018faf1 to
40830ab
Compare
### 🚀 Features - **(library)** top-level Fnox::discover() / get / list convenience API by [@bglusman](https://github.com/bglusman) in [#442](#442) ### 🐛 Bug Fixes - **(docs)** stack banner and pin close button on mobile by [@jdx](https://github.com/jdx) in [#437](#437) - **(set)** fall back to current provider when updating secrets by [@rpendleton](https://github.com/rpendleton) in [#439](#439) ### 📚 Documentation - **(site)** show release version and github stars by [@jdx](https://github.com/jdx) in [#443](#443) - add cross-site announcement banner by [@jdx](https://github.com/jdx) in [#434](#434) - respect banner expires field by [@jdx](https://github.com/jdx) in [#436](#436) ### 🛡️ Security - **(build)** deterministic provider ordering in generated schema by [@jdx](https://github.com/jdx) in [#432](#432) ### 🔍 Other Changes - **(release)** append en.dev sponsor blurb to release notes by [@jdx](https://github.com/jdx) in [#431](#431) ### 📦️ Dependency Updates - bump communique to 1.0.3 by [@jdx](https://github.com/jdx) in [#435](#435) - bump communique 1.0.3 → 1.0.4 by [@jdx](https://github.com/jdx) in [#438](#438) ### New Contributors - @bglusman made their first contribution in [#442](#442)
### 🚀 Features - **(library)** top-level Fnox::discover() / get / list convenience API by [@bglusman](https://github.com/bglusman) in [#442](#442) ### 🐛 Bug Fixes - **(docs)** stack banner and pin close button on mobile by [@jdx](https://github.com/jdx) in [#437](#437) - **(set)** fall back to current provider when updating secrets by [@rpendleton](https://github.com/rpendleton) in [#439](#439) ### 📚 Documentation - **(site)** show release version and github stars by [@jdx](https://github.com/jdx) in [#443](#443) - add cross-site announcement banner by [@jdx](https://github.com/jdx) in [#434](#434) - respect banner expires field by [@jdx](https://github.com/jdx) in [#436](#436) ### 🛡️ Security - **(build)** deterministic provider ordering in generated schema by [@jdx](https://github.com/jdx) in [#432](#432) ### 🔍 Other Changes - **(release)** append en.dev sponsor blurb to release notes by [@jdx](https://github.com/jdx) in [#431](#431) ### 📦️ Dependency Updates - bump communique to 1.0.3 by [@jdx](https://github.com/jdx) in [#435](#435) - bump communique 1.0.3 → 1.0.4 by [@jdx](https://github.com/jdx) in [#438](#438) - bump communique to 1.1.2 by [@jdx](https://github.com/jdx) in [#444](#444) ### New Contributors - @bglusman made their first contribution in [#442](#442)
## Upstream release Bumps bundled fnox binary from 1.20.0 to 1.22.0. **Release**: https://github.com/jdx/fnox/releases/tag/v1.22.0 ## Release notes v1.22.0 introduces a top-level library API for embedding fnox in Rust applications, and fixes a sharp edge in `fnox set` that could turn an encrypted secret into plaintext. ## Added **Top-level `Fnox` library API** ([#442](jdx/fnox#442)) -- @bglusman Downstream Rust consumers can now use fnox as a library in three lines instead of replicating the internals of `GetCommand::run`: ```rust use fnox::Fnox; let fnox = Fnox::discover()?; // walks up + merges parent + local + global config let value = fnox.get("MY_KEY").await?; let names = fnox.list()?; ``` The new `Fnox` type lives in `src/library.rs` and is re-exported from the crate root. Highlights: - `Fnox::discover()` mirrors the binary's full config-discovery and merge chain via `Config::load_smart`, including the `FNOX_PROFILE` env var. - `Fnox::open(path)` loads an explicit config without the upward-search/merge behavior. - `Fnox::with_profile("staging")` builder for non-default profiles. - `get()` returns `FnoxError::SecretNotFound` with a populated "Did you mean…" suggestion, matching the CLI's UX so callers don't need to recompute it. - `Fnox` is cheap to clone (`Config` is held behind an `Arc`) and safe to hold across `.await`. `set()` is intentionally not part of this first cut; it'll get its own design pass. ## Fixed **`fnox set` no longer silently downgrades encrypted secrets to plaintext** ([#439](jdx/fnox#439)) -- @rpendleton When multiple providers were configured without a `default_provider`, running `fnox set` on an existing secret without `--provider` would write the new value as plaintext while leaving the original `provider = "..."` key in place. The next `fnox get` then failed trying to "decrypt" a value that was no longer encrypted. `fnox set` now reuses the secret's existing provider before falling back to `default_provider` or plaintext, so updates stay encrypted and readable without having to pass `--provider` on every call: ```bash fnox set --provider age MY_SECRET "original-value" # encrypted with age fnox set MY_SECRET "new-value" # still encrypted with age ``` **Deterministic provider ordering in the generated schema** ([#432](jdx/fnox#432)) -- @jdx Within-category provider ordering in `build/generate_providers.rs` was inheriting `fs::read_dir` order, which is OS- and filesystem-dependent. That non-determinism flowed into `docs/public/schema.json` and caused autofix.ci to keep reshuffling 100+ lines between runs. A secondary sort by provider name fixes the churn; running `fnox schema` twice now produces byte-identical output. **Mobile docs banner layout** ([#437](jdx/fnox#437)) -- @jdx At `<=640px` the announcement banner now switches to a column layout with the close button pinned to the top-right corner, instead of cramming the message and "Read more" link onto one squeezed line. ## Changed - Docs site nav now shows the current release version (read from `Cargo.toml` at build time) and a GitHub star count, matching the mise/aube docs ([#443](jdx/fnox#443)) -- @jdx - Added a dismissible cross-site announcement banner that fetches its config from `jdx.dev/banner.json` and respects the `expires` field ([#434](jdx/fnox#434), [#436](jdx/fnox#436)) -- @jdx ## New Contributors * @bglusman made their first contribution in [#442](jdx/fnox#442) **Full Changelog**: jdx/fnox@v1.21.0...v1.22.0 ## 💚 Sponsor fnox fnox is maintained by [@jdx](https://github.com/jdx) under [**en.dev**](https://en.dev) — a small independent studio building developer tooling like [mise](https://mise.jdx.dev/), [aube](https://aube.en.dev/), hk, and more. Keeping fnox secure, maintained, and free is funded by sponsors. If fnox is handling secrets or config for you or your team, please consider [sponsoring at en.dev](https://en.dev). Sponsorships are what let fnox stay independent and the project keep moving. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
When multiple providers were configured without a `default_provider`, running `fnox set` on an existing secret without `--provider` stored the new value as plaintext while leaving the original `provider` key in place. Subsequent `fnox get` calls then failed, since fnox would try to decrypt a value that was no longer encrypted. Before falling back to `default_provider` or plaintext, we now reuse the secret's existing provider. This allows updates to stay encrypted and readable without requiring `--provider` on every call. --------- Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
### 🚀 Features - **(library)** top-level Fnox::discover() / get / list convenience API by [@bglusman](https://github.com/bglusman) in [jdx#442](jdx#442) ### 🐛 Bug Fixes - **(docs)** stack banner and pin close button on mobile by [@jdx](https://github.com/jdx) in [jdx#437](jdx#437) - **(set)** fall back to current provider when updating secrets by [@rpendleton](https://github.com/rpendleton) in [jdx#439](jdx#439) ### 📚 Documentation - **(site)** show release version and github stars by [@jdx](https://github.com/jdx) in [jdx#443](jdx#443) - add cross-site announcement banner by [@jdx](https://github.com/jdx) in [jdx#434](jdx#434) - respect banner expires field by [@jdx](https://github.com/jdx) in [jdx#436](jdx#436) ### 🛡️ Security - **(build)** deterministic provider ordering in generated schema by [@jdx](https://github.com/jdx) in [jdx#432](jdx#432) ### 🔍 Other Changes - **(release)** append en.dev sponsor blurb to release notes by [@jdx](https://github.com/jdx) in [jdx#431](jdx#431) ### 📦️ Dependency Updates - bump communique to 1.0.3 by [@jdx](https://github.com/jdx) in [jdx#435](jdx#435) - bump communique 1.0.3 → 1.0.4 by [@jdx](https://github.com/jdx) in [jdx#438](jdx#438) ### New Contributors - @bglusman made their first contribution in [jdx#442](jdx#442)
### 🚀 Features - **(library)** top-level Fnox::discover() / get / list convenience API by [@bglusman](https://github.com/bglusman) in [jdx#442](jdx#442) ### 🐛 Bug Fixes - **(docs)** stack banner and pin close button on mobile by [@jdx](https://github.com/jdx) in [jdx#437](jdx#437) - **(set)** fall back to current provider when updating secrets by [@rpendleton](https://github.com/rpendleton) in [jdx#439](jdx#439) ### 📚 Documentation - **(site)** show release version and github stars by [@jdx](https://github.com/jdx) in [jdx#443](jdx#443) - add cross-site announcement banner by [@jdx](https://github.com/jdx) in [jdx#434](jdx#434) - respect banner expires field by [@jdx](https://github.com/jdx) in [jdx#436](jdx#436) ### 🛡️ Security - **(build)** deterministic provider ordering in generated schema by [@jdx](https://github.com/jdx) in [jdx#432](jdx#432) ### 🔍 Other Changes - **(release)** append en.dev sponsor blurb to release notes by [@jdx](https://github.com/jdx) in [jdx#431](jdx#431) ### 📦️ Dependency Updates - bump communique to 1.0.3 by [@jdx](https://github.com/jdx) in [jdx#435](jdx#435) - bump communique 1.0.3 → 1.0.4 by [@jdx](https://github.com/jdx) in [jdx#438](jdx#438) - bump communique to 1.1.2 by [@jdx](https://github.com/jdx) in [jdx#444](jdx#444) ### New Contributors - @bglusman made their first contribution in [jdx#442](jdx#442)
When multiple providers were configured without a
default_provider, runningfnox seton an existing secret without--providerstored the new value as plaintext while leaving the originalproviderkey in place. Subsequentfnox getcalls then failed, since fnox would try to decrypt a value that was no longer encrypted.Before falling back to
default_provideror plaintext, we now reuse the secret's existing provider. This allows updates to stay encrypted and readable without requiring--provideron every call.