docs(secrets): record the container over-rejection and the OtOpcUa 0.6.1 adoption

This commit is contained in:
Joseph Doherty
2026-08-11 09:01:04 -04:00
parent 6084465e23
commit 74066bbe27
2 changed files with 21 additions and 1 deletions
+20
View File
@@ -32,6 +32,26 @@ one of them.
`null` remains correct only where there genuinely is no content root, such as the CLI.
`SecretsOptionsValidator` gains a `string?` constructor alongside the `IHostEnvironment?` one.
### Known interaction: containers, where the rule deliberately over-rejects
- **A containerized deployment can put the store on a mounted volume *inside* the content root, and
0.6.1 will reject it.** Observed on the OtOpcUa docker-dev rig: `Secrets__SqlitePath` was
`/app/data/…` with `/app` the container content root and `/app/data` a mounted volume — absolute,
durable across container replacement, and entirely deliberate. The rule rejects it anyway.
**This is a true positive for the rule as written and a false positive for the operator's
intent**, and the difference is real: in a container the image is replaced on upgrade but the
volume is not, so "inside the content root" is a weaker proxy for "destroyed on upgrade" there
than it is for a Windows service whose whole directory gets renamed.
It is not being relaxed, and no opt-out flag is being added. Distinguishing a mount from an
ordinary directory means reading platform-specific mount tables, and an
`AllowStoreUnderContentRoot` escape hatch is the kind of switch that gets set once to clear a
boot failure and then outlives the reason — which is precisely the failure mode the guard exists
to close. **The workaround is one line**: mount the same volume at a second path outside the
content root (the rig used `/data`) and point `Secrets:SqlitePath` there. The file is at the
volume root either way, so seeded stores carry over with no migration.
### Upgrade note (applies to 0.6.0 as well)
- **A store seeded under the pre-0.6.0 default is orphaned, not migrated, and nothing says so.**