feat(secrets): 0.6.2 — the content-root rejection message teaches the container case

Suggested by the OtOpcUa session, the only real containerized deployment in this family
and the one that hit the false positive. A store on a volume mounted inside the content
root is durable across container replacement but is rejected anyway, because the rule
cannot tell a mount from an ordinary directory. The message now says so, gives the fix,
and forecloses the wrong one by stating that no override exists.

A false positive's entire cost is the confusion in the moment, so an error that names its
own fix costs nothing on the true-positive path and turns the false positive into a
two-minute edit. Message only, no behaviour change.

Their case for keeping the rule strict is recorded in the CHANGELOG because it is better
than the trade-off I had written: the workaround is an improvement rather than a
concession, an override flag has the lifecycle of a knob set once and never revisited,
and mount detection would make the verdict depend on runtime platform state so the same
path would pass on one host and fail on another.
This commit is contained in:
Joseph Doherty
2026-08-11 09:04:02 -04:00
parent 74066bbe27
commit c5e894d9b3
4 changed files with 56 additions and 2 deletions
@@ -80,7 +80,12 @@ public sealed class SecretsOptionsValidator : OptionsValidatorBase<SecretsOption
+ "that directory on upgrade, which takes the secret store with it and leaves the "
+ "process to create a fresh empty one at the same path — an outage that presents as "
+ "an authentication failure, not as a deployment error. Put the store in a sibling "
+ "directory that the upgrade does not touch.",
+ "directory that the upgrade does not touch. IF THIS PATH IS ON A MOUNTED VOLUME: "
+ "the volume is durable, but this rule cannot tell a mount from an ordinary "
+ "directory — mount the same volume at a second path OUTSIDE the content root and "
+ "point Secrets:SqlitePath there. The file sits at the volume root either way, so "
+ "an existing store carries over. Do not look for an override to disable this "
+ "check; there deliberately is not one.",
builder);
}
}