fix(secrets-cli): shipped appsettings.json no longer sets a relative SqlitePath (scadaproj#49)

The CLI's own appsettings.json set "SqlitePath": "secrets.db", which the store-path validator
rejects as relative, so the headless CLI failed at startup when run from its own directory unless
Secrets__SqlitePath overrode it. The key is removed: the per-user default
(<LocalApplicationData>/ZB.MOM.WW/secrets.db) applies, and an app's appsettings.json in the working
directory or the environment still override it. Regression test validates the shipped file.

Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
This commit is contained in:
Joseph Doherty
2026-11-09 15:13:42 -05:00
parent 64efb49996
commit 262e11feaf
2 changed files with 47 additions and 1 deletions
@@ -1,6 +1,5 @@
{
"Secrets": {
"SqlitePath": "secrets.db",
"MasterKey": {
"Source": "Environment",
"EnvVarName": "ZB_SECRETS_MASTER_KEY"
@@ -0,0 +1,47 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using ZB.MOM.WW.Secrets.DependencyInjection;
namespace ZB.MOM.WW.Secrets.Tests.Cli;
/// <summary>
/// scadaproj#49: the <c>appsettings.json</c> the CLI ships must pass the store-path validator. It
/// used to set <c>"SqlitePath": "secrets.db"</c>, which the validator rejects as relative, so the
/// headless CLI could not start from its own directory unless an environment variable overrode it.
/// </summary>
public sealed class ShippedCliSettingsTests
{
private static string RepoFile(params string[] relative)
{
for (DirectoryInfo? dir = new(AppContext.BaseDirectory); dir is not null; dir = dir.Parent)
{
if (File.Exists(Path.Combine(dir.FullName, "ZB.MOM.WW.Secrets.slnx")))
{
return Path.Combine(new[] { dir.FullName }.Concat(relative).ToArray());
}
}
throw new InvalidOperationException("Could not locate ZB.MOM.WW.Secrets.slnx above the test output.");
}
private static SecretsOptions Validate(IConfiguration config)
{
var services = new ServiceCollection();
services.AddZbSecrets(config, "Secrets");
using ServiceProvider sp = services.BuildServiceProvider();
return sp.GetRequiredService<IOptions<SecretsOptions>>().Value;
}
[Fact]
public void The_cli_appsettings_passes_store_path_validation()
{
IConfiguration config = new ConfigurationBuilder()
.AddJsonFile(RepoFile("src", "ZB.MOM.WW.Secrets.Cli", "appsettings.json"), optional: false)
.Build();
SecretsOptions options = Validate(config);
Assert.True(Path.IsPathFullyQualified(options.SqlitePath));
}
}