fix(data): reject stale portfolio trigger snapshots

This commit is contained in:
2026-06-01 14:39:04 +03:00
parent 6e7a0cb493
commit f493836b77
4 changed files with 55 additions and 19 deletions
@@ -257,6 +257,51 @@ public sealed class PortfolioMigrationPostgresTests(PortfolioMigrationPostgresFi
Assert.Equal(PostgresErrorCodes.FeatureNotSupported, exception.SqlState);
}
[Fact]
public async Task RepeatableReadDraftLinkDeleteRacingPublish_ShouldBeRejectedWithoutInvalidPublicCard()
{
var database = await fixture.CreateMigratedDatabaseAsync();
await using var seedConnection = await database.OpenConnectionAsync();
var seed = await SeedCardAsync(seedConnection, isPublic: false);
await using var deleteConnection = await database.OpenConnectionAsync();
await using var publishConnection = await database.OpenConnectionAsync();
await using var deleteTransaction = await deleteConnection.BeginTransactionAsync(IsolationLevel.RepeatableRead);
await using var publishTransaction = await publishConnection.BeginTransactionAsync();
await ExecuteNonQueryAsync(
deleteConnection,
"DELETE FROM portfolio_game_sessions WHERE portfolio_game_id = @portfolioGameId",
deleteTransaction,
new NpgsqlParameter("portfolioGameId", seed.PortfolioGameId));
await ExecuteNonQueryAsync(
publishConnection,
"""
UPDATE portfolio_games
SET is_public = true,
published_at = COALESCE(published_at, now()),
updated_at = now()
WHERE id = @portfolioGameId
""",
publishTransaction,
new NpgsqlParameter("portfolioGameId", seed.PortfolioGameId));
var deleteSqlState = await CommitAndCaptureSqlStateAsync(deleteTransaction);
var publishSqlState = await CommitAndCaptureSqlStateAsync(publishTransaction);
Assert.Equal(PostgresErrorCodes.FeatureNotSupported, deleteSqlState);
Assert.Null(publishSqlState);
await using var verificationConnection = await database.OpenConnectionAsync();
Assert.True(await ExecuteScalarAsync<bool>(
verificationConnection,
"SELECT is_public FROM portfolio_games WHERE id = @portfolioGameId",
parameters: new NpgsqlParameter("portfolioGameId", seed.PortfolioGameId)));
Assert.Equal(1, await ExecuteScalarAsync<long>(
verificationConnection,
"SELECT COUNT(*) FROM portfolio_game_sessions WHERE portfolio_game_id = @portfolioGameId",
parameters: new NpgsqlParameter("portfolioGameId", seed.PortfolioGameId)));
}
[Theory]
[InlineData("portfolio_game_sessions")]
[InlineData("portfolio_game_masters")]