dd0a846b64
Secrets were per-node SQLite, so a secret written on one node was invisible to the rest of a cluster. G-7's design resolved the "shared SQL store vs Akka replicator" fork to build only the former; both are built here so the choice is a deployment decision (availability vs partition tolerance) rather than a library limitation. Two new packages — ZB.MOM.WW.Secrets.Replicator.SqlServer (shared store, plus a local-store-with-hub mode) and .Replicator.AkkaDotNet (peer-to-peer over distributed pub/sub). Core gains ISecretsStoreMigrator, one shared SecretLastWriterWins predicate so no two stores can disagree on a tie, the transport-agnostic reconciler, and ReplicatingSecretStore — which closes a real gap: nothing had ever called ISecretReplicator.PublishAsync, so the seam was inert and local writes would not have propagated at all. Verified 182 pass / 1 skip / 0 warnings, including 15 live tests against a real SQL Server 2022 (the SQLite suite ported case-for-case, so any behavioural divergence between the stores fails) and a 9-test in-process 2-node Akka cluster over real remoting. A post-build review caught six defects, all fixed and now covered: both replication modes could not resolve from the container (no test had built one), an unbounded fetch that broke past SQL Server's 2100-parameter cap, a poison row that aborted the rest of its batch forever, Enum.Parse on peer input that could restart the actor in a loop, null crypto blobs crossing the trust boundary, and a silently dropped pull-read failure. Packed at 0.2.0 and vulnerability-scanned clean; not yet published to the feed. Claude-Session: https://claude.ai/code/session_01BL2Vu1ESDQ9SCN4gVKkdts
23 lines
1.2 KiB
C#
23 lines
1.2 KiB
C#
namespace ZB.MOM.WW.Secrets.Abstractions;
|
|
|
|
/// <summary>
|
|
/// Provisions the schema backing an <see cref="ISecretStore"/>. Implementations are idempotent —
|
|
/// running a migration repeatedly is safe — and refuse to run against a store whose on-disk schema
|
|
/// version is <em>newer</em> than the build supports, rather than silently downgrading it.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This seam exists so the startup migration hosted service and the CLI stay store-agnostic: the
|
|
/// SQLite store, the shared SQL-Server store, and any future provider are all provisioned through
|
|
/// the same call, and swapping the store never touches the migration wiring.
|
|
/// </remarks>
|
|
public interface ISecretsStoreMigrator
|
|
{
|
|
/// <summary>Creates or updates the secret-store schema to the version this build supports.</summary>
|
|
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
|
/// <returns>A task that completes when the schema is at the supported version.</returns>
|
|
/// <exception cref="SecretStoreMigrationException">
|
|
/// The store's schema version is newer than this build supports.
|
|
/// </exception>
|
|
Task MigrateAsync(CancellationToken cancellationToken);
|
|
}
|