diff --git a/ZB.MOM.WW.Auth/Directory.Build.props b/ZB.MOM.WW.Auth/Directory.Build.props
index 5e21819..c48c525 100644
--- a/ZB.MOM.WW.Auth/Directory.Build.props
+++ b/ZB.MOM.WW.Auth/Directory.Build.props
@@ -5,7 +5,7 @@
enable
enable
latest
- 0.1.1
+ 0.1.2
true
diff --git a/ZB.MOM.WW.Auth/src/ZB.MOM.WW.Auth.ApiKeys/Sqlite/SqliteAuthSchema.cs b/ZB.MOM.WW.Auth/src/ZB.MOM.WW.Auth.ApiKeys/Sqlite/SqliteAuthSchema.cs
index f3afd55..86b87a5 100644
--- a/ZB.MOM.WW.Auth/src/ZB.MOM.WW.Auth.ApiKeys/Sqlite/SqliteAuthSchema.cs
+++ b/ZB.MOM.WW.Auth/src/ZB.MOM.WW.Auth.ApiKeys/Sqlite/SqliteAuthSchema.cs
@@ -5,8 +5,15 @@ namespace ZB.MOM.WW.Auth.ApiKeys.Sqlite;
///
public static class SqliteAuthSchema
{
- /// The schema version this build creates and supports.
- public const int CurrentVersion = 1;
+ ///
+ /// The schema version this build creates and supports. This is 2, not 1,
+ /// to match the deployed databases of the donor (MxAccessGateway) this store was
+ /// extracted from: that store reached its final shape via a v1→v2 history and stamps
+ /// version = 2 on disk. The final schema has been byte-identical since v1, so a
+ /// single-shot create stamped as 2 interoperates with existing gateway-auth.db
+ /// files (the migrator only refuses an on-disk version newer than this).
+ ///
+ public const int CurrentVersion = 2;
/// Name of the single-row table tracking the applied schema version.
public const string SchemaVersionTable = "schema_version";
diff --git a/ZB.MOM.WW.Auth/src/ZB.MOM.WW.Auth.ApiKeys/Sqlite/SqliteAuthStoreMigrator.cs b/ZB.MOM.WW.Auth/src/ZB.MOM.WW.Auth.ApiKeys/Sqlite/SqliteAuthStoreMigrator.cs
index 416cad8..8234692 100644
--- a/ZB.MOM.WW.Auth/src/ZB.MOM.WW.Auth.ApiKeys/Sqlite/SqliteAuthStoreMigrator.cs
+++ b/ZB.MOM.WW.Auth/src/ZB.MOM.WW.Auth.ApiKeys/Sqlite/SqliteAuthStoreMigrator.cs
@@ -35,7 +35,7 @@ public sealed class SqliteAuthStoreMigrator(AuthSqliteConnectionFactory connecti
$"Auth database schema version {existingVersion} is newer than supported version {SqliteAuthSchema.CurrentVersion}.");
}
- await ApplyVersionOneAsync(connection, transaction, cancellationToken).ConfigureAwait(false);
+ await ApplySchemaAsync(connection, transaction, cancellationToken).ConfigureAwait(false);
await WriteSchemaVersionAsync(connection, transaction, cancellationToken).ConfigureAwait(false);
await transaction.CommitAsync(cancellationToken).ConfigureAwait(false);
@@ -78,7 +78,10 @@ public sealed class SqliteAuthStoreMigrator(AuthSqliteConnectionFactory connecti
: Convert.ToInt32(version, CultureInfo.InvariantCulture);
}
- private static async Task ApplyVersionOneAsync(
+ // Single-shot create of the final schema (all DDL is CREATE ... IF NOT EXISTS, so it is
+ // idempotent against an already-provisioned database). The applied version is stamped
+ // separately by WriteSchemaVersionAsync.
+ private static async Task ApplySchemaAsync(
SqliteConnection connection,
SqliteTransaction transaction,
CancellationToken cancellationToken)
diff --git a/ZB.MOM.WW.Auth/tests/ZB.MOM.WW.Auth.ApiKeys.Tests/SqliteMigratorTests.cs b/ZB.MOM.WW.Auth/tests/ZB.MOM.WW.Auth.ApiKeys.Tests/SqliteMigratorTests.cs
index c5e08c8..f7870d0 100644
--- a/ZB.MOM.WW.Auth/tests/ZB.MOM.WW.Auth.ApiKeys.Tests/SqliteMigratorTests.cs
+++ b/ZB.MOM.WW.Auth/tests/ZB.MOM.WW.Auth.ApiKeys.Tests/SqliteMigratorTests.cs
@@ -34,6 +34,27 @@ public sealed class SqliteMigratorTests : IDisposable
Assert.Equal(1, await CountSchemaVersionRowsAsync());
}
+ [Fact]
+ public void CurrentVersion_Is2_ToMatchDonorGatewayDeployedSchema() =>
+ // The store was extracted from MxAccessGateway, whose deployed gateway-auth.db is
+ // stamped version 2. The library must stamp 2 (not reset to 1) so it does not refuse
+ // those existing databases on first boot. Locking this invariant.
+ Assert.Equal(2, SqliteAuthSchema.CurrentVersion);
+
+ [Fact]
+ public async Task MigrateAsync_AgainstExistingVersion2Db_DoesNotThrow_AndStaysAt2()
+ {
+ // The deployed-gateway scenario: a database already provisioned at version 2.
+ var migrator = new SqliteAuthStoreMigrator(Factory);
+ await migrator.MigrateAsync(CancellationToken.None);
+ await SetVersionAsync(2);
+
+ await migrator.MigrateAsync(CancellationToken.None); // must not throw
+
+ Assert.Equal(2, await ReadVersionAsync());
+ Assert.True(await TableExistsAsync(SqliteAuthSchema.ApiKeysTable));
+ }
+
[Fact]
public async Task MigrateAsync_FutureSchemaVersion_Throws()
{