diff --git a/ZB.MOM.WW.Secrets/src/ZB.MOM.WW.Secrets.Cli/Interactive/BundleService.cs b/ZB.MOM.WW.Secrets/src/ZB.MOM.WW.Secrets.Cli/Interactive/BundleService.cs index be6d8c9..f243b29 100644 --- a/ZB.MOM.WW.Secrets/src/ZB.MOM.WW.Secrets.Cli/Interactive/BundleService.cs +++ b/ZB.MOM.WW.Secrets/src/ZB.MOM.WW.Secrets.Cli/Interactive/BundleService.cs @@ -99,7 +99,10 @@ public sealed class BundleService /// verbatim replicate would be silently rejected by the LWW gate, so that single case is written /// through instead — a local-write that restamps the row as /// current, which is exactly what makes the operator's forced choice durable rather than flipped - /// back on the next reconciliation. + /// back on the next reconciliation. Note the narrowed remnant of this: a + /// that forces an older, tombstoned bundle row over a + /// newer live local row resurrects it, because that forced + /// path clears the tombstone. /// /// /// The full session to import into. diff --git a/ZB.MOM.WW.Secrets/tests/ZB.MOM.WW.Secrets.Tests/Cli/Interactive/BundleServiceTests.cs b/ZB.MOM.WW.Secrets/tests/ZB.MOM.WW.Secrets.Tests/Cli/Interactive/BundleServiceTests.cs index 8c159a6..da6efef 100644 --- a/ZB.MOM.WW.Secrets/tests/ZB.MOM.WW.Secrets.Tests/Cli/Interactive/BundleServiceTests.cs +++ b/ZB.MOM.WW.Secrets/tests/ZB.MOM.WW.Secrets.Tests/Cli/Interactive/BundleServiceTests.cs @@ -239,11 +239,15 @@ public sealed class BundleServiceTests : IDisposable string raw = await File.ReadAllTextAsync(BundlePath, CancellationToken.None); Assert.DoesNotContain(sentinel, raw, StringComparison.Ordinal); - // The base64 ciphertext of the sealed row is present in the file. + // The base64 ciphertext of the sealed row is present in the file. Assert structurally through + // the codec rather than by raw-text match: System.Text.Json escapes '+' as +, so a raw + // Contains on the base64 string is flaky whenever the ciphertext base64 contains a '+'. StoredSecret? row = await source.Store.GetAsync(new SecretName("svc/secret"), CancellationToken.None); Assert.NotNull(row); - Assert.Contains(Convert.ToBase64String(row!.Ciphertext), raw, StringComparison.Ordinal); Assert.Contains("\"Ciphertext\"", raw, StringComparison.Ordinal); + SecretBundle parsed = SecretBundleCodec.Deserialize(raw); + BundleEntry parsedEntry = Assert.Single(parsed.Entries); + Assert.Equal(Convert.ToBase64String(row!.Ciphertext), parsedEntry.Ciphertext); } [Fact]