fix(secrets): UI reports a committed change as saved when its audit throws (scadaproj#34)
SecretEditor and ConfirmDeleteModal wrote the success audit inside the same try as the store write, so a throwing IAuditWriter after a committed add/rotate/delete showed an error, wrote a Failure audit and skipped the resolver-cache eviction - the old plaintext kept resolving for the TTL. The mutation try now covers only the cipher + store call; the success audit is best-effort afterwards and logs a warning (no value) on failure, so the change is reported saved, the callback fires and the cache is evicted. - tests: AuditFailureAfterCommitTests (add, rotate, delete) with a throwing success audit; all fail without the fix - code-reviews: Secrets-013 Resolved; README regenerated Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
| Last reviewed | 2026-11-09 |
|
||||
| Reviewer | Claude (scadaproj#15) |
|
||||
| Commit reviewed | `91fb2b4` |
|
||||
| Open findings | 15 |
|
||||
| Open findings | 14 |
|
||||
|
||||
## Summary
|
||||
|
||||
@@ -438,7 +438,7 @@ _Unresolved._
|
||||
| Severity | Medium |
|
||||
| Priority | P2 |
|
||||
| Category | Correctness & logic bugs |
|
||||
| Status | Open |
|
||||
| Status | Resolved |
|
||||
| Location | `ZB.MOM.WW.Secrets/src/ZB.MOM.WW.Secrets.Ui/Components/SecretEditor.razor:138` (also `ConfirmDeleteModal.razor:91`) |
|
||||
|
||||
**Description**
|
||||
@@ -465,7 +465,7 @@ Move the success audit out of the mutation `try`. Once the store write returns,
|
||||
|
||||
**Resolution**
|
||||
|
||||
_Unresolved._
|
||||
Resolved 2026-11-09 in the commit tagged `(scadaproj#34)` (Secrets `0.6.6`, unpublished). In both `SecretEditor.SubmitAsync` and `ConfirmDeleteModal.ConfirmAsync` the mutation `try` now covers only the cipher + store call and sets `saved`/`deleted` as soon as the store returns; the success audit moved to a separate best-effort `WriteSuccessAuditAsync` that catches and logs a warning (name, action and actor only — never the value) through an optional `ILogger<T>`. The existing post-commit block (cache `Invalidate` + `OnSaved`/`OnDeleted`) therefore always runs for a committed change. Regression tests `AuditFailureAfterCommitTests` (add, rotate, delete) use a `CapturingAuditWriter.SuccessFault` that throws on every Success write and assert: committed, callback raised, cache evicted for the name, no error shown, no Failure audit. All three fail without the fix.
|
||||
|
||||
|
||||
### Secrets-014 — UI "Add secret" silently overwrites an existing (or tombstoned) secret, clobbers its metadata, and audits it as `secret.add`
|
||||
|
||||
Reference in New Issue
Block a user