Skip to content

Commit bdd9a5f

Browse files
KSemenenkoclaude
andcommitted
Bind PostgreSQL numeric flows positionally and trust the CA certificate without a key
- The Int16 and Decimal wire flows sent `$1` SQL with a parameter named "p1". Npgsql rewrites named parameters only for named placeholders, so it sent Parse with no parameter types and the server correctly refused the `$1` slot as Validation. The flows now pass one positional parameter with its NpgsqlDbType, as an application does for `$1` SQL. - The raw wire TLS check loaded the CA with X509Certificate2.CreateFromPemFile, which also requires a private key in the same file; the CA file holds only the certificate, so it now uses X509CertificateLoader.LoadCertificateFromFile. Verification: integration tests build with -warnaserror; dotnet format verify; governance PASS; locally both Int16BindingRetainsNpgsqlSdkMcpExactPagesWidthOverflowRefusalRepairPolicyOriginalReceiptAndTwoColdCuts and DecimalNumericBindingRetainsNpgsqlSdkMcpExactPagesRefusalRepairPolicyOriginalReceiptAndTwoColdCuts pass after the earlier RuntimeSql, key set and ALPN fixes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 3db6e5f commit bdd9a5f

7 files changed

Lines changed: 13 additions & 13 deletions

File tree

‎tests/KeyLoad.IntegrationTests/QueryExecution/Assertions/WireProtocol/Values/PostgresDecimalClusterPages.cs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ await PageAsync((await McpCallerAssertions.SuccessAsync<QueryPage>(
3838
await caller.Mcp.CallAsync(McpCallerTools.QueryAst, ast, token))).Value, value);
3939
foreach (var prepared in new[] { false, true })
4040
{
41-
var parameter = new global::Npgsql.NpgsqlParameter(PostgresDecimalClusterProtocol.Parameter,
42-
global::NpgsqlTypes.NpgsqlDbType.Numeric)
41+
var parameter = new global::Npgsql.NpgsqlParameter
4342
{
43+
NpgsqlDbType = global::NpgsqlTypes.NpgsqlDbType.Numeric,
4444
Value = value
4545
};
4646
await PageAsync(await wire.ExecuteAsync<QueryPage>(PostgresDecimalClusterProtocol.DriverSql,

‎tests/KeyLoad.IntegrationTests/QueryExecution/Assertions/WireProtocol/Values/PostgresInt16ClusterPages.cs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ await PageAsync((await McpCallerAssertions.SuccessAsync<QueryPage>(
3838
await caller.Mcp.CallAsync(McpCallerTools.QueryAst, ast, token))).Value, value);
3939
foreach (var prepared in new[] { false, true })
4040
{
41-
var parameter = new global::Npgsql.NpgsqlParameter(PostgresInt16ClusterProtocol.Parameter,
42-
global::NpgsqlTypes.NpgsqlDbType.Smallint)
41+
var parameter = new global::Npgsql.NpgsqlParameter
4342
{
43+
NpgsqlDbType = global::NpgsqlTypes.NpgsqlDbType.Smallint,
4444
Value = value
4545
};
4646
await PageAsync(await wire.ExecuteAsync<QueryPage>(PostgresInt16ClusterProtocol.DriverSql,

‎tests/KeyLoad.IntegrationTests/QueryExecution/Lifecycle/WireProtocol/Values/PostgresDecimalClusterCancellation.cs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ await RequestCqrsClusterCallers.RunOwnedAsync(fixture.App, McpCallerProtocol.Nod
2626
var mcp = await global::TUnit.Assertions.Assert.ThrowsAsync<OperationCanceledException>(
2727
() => caller.Mcp.CallAsync(SqlOperationProtocol.ToolName, operation, cancelled.Token));
2828
await global::TUnit.Assertions.Assert.That(mcp?.CancellationToken).IsEqualTo(cancelled.Token);
29-
var parameter = new global::Npgsql.NpgsqlParameter(PostgresDecimalClusterProtocol.Parameter,
30-
global::NpgsqlTypes.NpgsqlDbType.Numeric)
29+
var parameter = new global::Npgsql.NpgsqlParameter
3130
{
31+
NpgsqlDbType = global::NpgsqlTypes.NpgsqlDbType.Numeric,
3232
Value = PostgresDecimalClusterProtocol.BetweenScores
3333
};
3434
var driver = await global::TUnit.Assertions.Assert.ThrowsAsync<OperationCanceledException>(

‎tests/KeyLoad.IntegrationTests/QueryExecution/Lifecycle/WireProtocol/Values/PostgresInt16ClusterCancellation.cs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ await RequestCqrsClusterCallers.RunOwnedAsync(fixture.App, McpCallerProtocol.Nod
2626
var mcp = await global::TUnit.Assertions.Assert.ThrowsAsync<OperationCanceledException>(
2727
() => caller.Mcp.CallAsync(SqlOperationProtocol.ToolName, operation, cancelled.Token));
2828
await global::TUnit.Assertions.Assert.That(mcp?.CancellationToken).IsEqualTo(cancelled.Token);
29-
var parameter = new global::Npgsql.NpgsqlParameter(PostgresInt16ClusterProtocol.Parameter,
30-
global::NpgsqlTypes.NpgsqlDbType.Smallint)
29+
var parameter = new global::Npgsql.NpgsqlParameter
3130
{
31+
NpgsqlDbType = global::NpgsqlTypes.NpgsqlDbType.Smallint,
3232
Value = PostgresInt16ClusterProtocol.ProbeValue
3333
};
3434
var driver = await global::TUnit.Assertions.Assert.ThrowsAsync<OperationCanceledException>(

‎tests/KeyLoad.IntegrationTests/QueryExecution/Scenarios/WireProtocol/Cluster/PostgresRf/PostgresClusterWireTrust.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ internal static async Task AuthenticateAsync(SslStream stream, string host, stri
1010
var failures = new List<Exception>();
1111
await global::KeyLoad.Server.ServerFailureObserver.ObserveAsync(async () =>
1212
{
13-
using var authority = X509Certificate2.CreateFromPemFile(authorityPath);
13+
using var authority = X509CertificateLoader.LoadCertificateFromFile(authorityPath);
1414
await global::KeyLoad.Server.ServerFailureObserver.ObserveAsync(async () =>
1515
{
1616
var trust = new X509ChainPolicy

‎tests/KeyLoad.IntegrationTests/QueryExecution/Scenarios/WireProtocol/Values/PostgresDecimal/PostgresDecimalClusterPolicy.cs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ private static async Task WireAsync(ClusterFixture fixture, SqlNullOrderingClust
5555
state.Reader.Principal.Id, state.Reader.Secret, PostgresClusterCertificate.RootPath(fixture), token);
5656
await global::KeyLoad.Server.ServerFailureObserver.ObserveAsync(async () =>
5757
{
58-
var parameter = new global::Npgsql.NpgsqlParameter(PostgresDecimalClusterProtocol.Parameter,
59-
global::NpgsqlTypes.NpgsqlDbType.Numeric)
58+
var parameter = new global::Npgsql.NpgsqlParameter
6059
{
60+
NpgsqlDbType = global::NpgsqlTypes.NpgsqlDbType.Numeric,
6161
Value = PostgresDecimalClusterProtocol.BetweenScores
6262
};
6363
await PostgresClusterAssertions.ErrorAsync(wire.ExecuteAsync<QueryPage>(

‎tests/KeyLoad.IntegrationTests/QueryExecution/Scenarios/WireProtocol/Values/PostgresInt/PostgresInt16ClusterPolicy.cs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ private static async Task WireAsync(ClusterFixture fixture, SqlNullOrderingClust
5555
state.Reader.Principal.Id, state.Reader.Secret, PostgresClusterCertificate.RootPath(fixture), token);
5656
await global::KeyLoad.Server.ServerFailureObserver.ObserveAsync(async () =>
5757
{
58-
var parameter = new global::Npgsql.NpgsqlParameter(PostgresInt16ClusterProtocol.Parameter,
59-
global::NpgsqlTypes.NpgsqlDbType.Smallint)
58+
var parameter = new global::Npgsql.NpgsqlParameter
6059
{
60+
NpgsqlDbType = global::NpgsqlTypes.NpgsqlDbType.Smallint,
6161
Value = PostgresInt16ClusterProtocol.ProbeValue
6262
};
6363
await PostgresClusterAssertions.ErrorAsync(wire.ExecuteAsync<QueryPage>(

0 commit comments

Comments
 (0)