Multi-protocol guardian: SQL Server (TDS) frontend - #2
Draft
thecombinator wants to merge 6 commits into
Draft
Conversation
… original Query literals can contain sensitive predicates (account numbers, ID numbers, emails). The analysis agent only needs the query's shape, so: - New internal/sqlnorm package: shared literal normalizer (string, dollar-quoted, and numeric literals; identifier-safe) - PostgreSQL and Redshift agents send literal-redacted query text to Bedrock; a prompt note explains the redaction - explain_query is pinned server-side to the trusted original query, so plan quality is unaffected and the model can no longer EXPLAIN arbitrary SQL - Query fingerprinting reuses the same normalizer (one definition of query shape for cache keys and redaction) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ract First structural step toward multi-protocol support (SQL Server/TDS alongside PostgreSQL) per docs/multiprotocol-design.md: - New internal/pipeline: the decision core (skip-list -> filter -> cache -> agent -> cache write -> report -> mode application), extracted verbatim from Proxy.analyzeQuery / analyzeQueryShunt, including reason-string suffixes, fail-open semantics, and best-effort cache/report handling. Narrow interfaces (Analyzer, ApprovalCache, Filter) keep frontends and tests decoupled from the full agent/cache surfaces. - internal/proxy delegates both analyze functions to the pipeline; behavior unchanged, all existing tests green unmodified. - New internal/wire: the Frontend contract that protocol frontends (pgwire today, TDS next) implement against the shared pipeline. - Pipeline unit tests lock the behavioral contract: mode application, cache-hit suffixes, fail-open on agent error, shunt routing flags, report entries. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
SQL Server clients can now connect through the proxy: sqlcmd/SSMS -> proxy -> SQL Server, verified against Azure SQL Edge with sqlcmd. - internal/wire/tds: TDS packet framing (8-byte headers, EOM status, type constants per MS-TDS) with defensive length limits, plus a packet-aware passthrough server: client->backend relays whole TDS packets (establishing the message-boundary layer that milestone 3 interception builds on), backend->client streams raw bytes. - cmd/pgproxy: optional TDS listener via TDS_LISTEN_ADDR and TDS_BACKEND_ADDR; the binary can now front PostgreSQL and SQL Server simultaneously. - Encryption: PRELOGIN is relayed untouched, so peers negotiate directly; this milestone targets unencrypted dev loops (sqlcmd -N disable). TLS termination (TDS 8.0 strict encryption preferred) is scheduled with interception. Observed handshake through the proxy: Prelogin -> Login7 -> SQLBatch, each surfaced with type, length, and EOM: the interception points for milestone 3 are already visible in the packet log. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
SQL Server clients now get the same governance as PostgreSQL clients: rejected batches never reach the backend and the client receives a native ERROR token with the reason and the suggested fix. - internal/wire/tds: message assembly (multi-packet until EOM), SQLBatch SQL extraction (ALL_HEADERS + UTF-16LE per MS-TDS), ERROR+DONE response encoding (error 50999, severity 16) rendered by sqlcmd/SSMS/drivers, fail-open on parse anomalies, and a T-SQL skip list for session/tooling chatter. - internal/agent: TSQLAgent, a SQL Server engine-specialist persona judging on query shape alone (conservative by design until DMV and SHOWPLAN tools land); literals redacted before transmission like the other dialects. - internal/sqlnorm: shared shape Fingerprint for dialects without a native parser-based normalizer; T-SQL verdicts share the approval cache. - cmd/pgproxy: TDS frontend wires a tsql pipeline when analysis is enabled; shunt mode falls back to blocking on TDS for now. - Live integration test (TDS_IT_BACKEND) drives go-mssqldb through the frontend against a real backend: approved flows, rejection carries reason+fix, connection survives rejection. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…one 4) The tsql persona now reasons like a DBA instead of judging query text alone: - internal/agent/tools_tsql.go: read-only SQL Server tools over go-mssqldb: get_schema (sys.columns), get_indexes (sys.indexes + dm_db_index_usage_stats), get_table_stats (dm_db_partition_stats), and explain_query via SHOWPLAN_XML on a dedicated session (SHOWPLAN is session-sticky; never runs on a pooled connection). explain is pinned to the trusted original query; the model only ever sees the literal-redacted shape. - internal/agent/bedrock.go: direct Bedrock Converse client restored as a Converser implementation (temperature 0, MaxTokens 4096), for deployments that call Bedrock without the Portkey gateway. - TSQLAgent executes tool calls in its agentic loop; prompt upgraded from shape-only judging to a methodical tools-first process with a conservative fallback when tools fail. - cmd/pgproxy: TDS analysis uses Bedrock directly; TDS_BACKEND_DSN enables the DMV/SHOWPLAN toolset. - Live integration test (TSQL_IT_DSN) verifies all four tools against a real backend, ShowPlanXML included. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Modern Microsoft clients (SSMS 20+, .NET SqlClient 5+, ODBC 18+, go-mssqldb encrypt=strict) encrypt by default and cannot be talked down to plaintext. The frontend now terminates TDS 8.0 strict encryption, which is ordinary TLS from the first byte: - First-byte dispatch: a TLS ClientHello (0x16) enters strict termination (ALPN tds/8.0, TLS 1.2+); a TDS packet type enters the legacy 7.x path unchanged. - Boundary translation for 7.x backends: the PRELOGIN ENCRYPTION option is rewritten in both directions (backend told NOT_SUP, the tunnel is the encryption; client told STRICT), and the LOGIN7 TDSVersion field is presented to the backend as 7.4 (a strict client stamps 8.0, which a 7.x engine refuses). - Certificates via TDS_TLS_CERT_PATH/TDS_TLS_KEY_PATH, or TDS_TLS_SELF_SIGNED=true for dev loops. Note: strict mode mandates certificate validation per spec (trustservercertificate is ignored); the integration test pins the cert like a real client. - Interception is unchanged inside the tunnel: the live strict test verifies approved flow and guardian rejection over TLS. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The proxy now fronts SQL Server as well as PostgreSQL: same binary, same decision pipeline, same governance semantics. A TDS client (sqlcmd, SSMS, .NET, ODBC, go-mssqldb) connects through the proxy; SQL batches are fingerprinted, cached, and judged by a SQL Server specialist agent with DMV and SHOWPLAN tools; rejections return as native SQL errors (Msg 50999) carrying the reason and a suggested fix. TDS 8.0 strict encryption is terminated at the frontend.
Design rationale and roadmap:
docs/multiprotocol-design.md.Commits (each independently reviewable)
wire.Frontendcontract. The decision core (skip-list, cache, agent, mode, report) moves tointernal/pipelinebehind narrow interfaces. Zero behavior change; existing tests pass unmodified.Known limitations (deliberate v1 scope)
Verification
Full suite green and unmodified. Live integration tests against SQL Server (
TDS_IT_BACKEND) cover passthrough, interception, rejection-with-fix, connection survival after rejection, and strict TLS end to end.Review focus requested
The pipeline extraction (touches
internal/proxy), and the TLS boundary code (tls.go, PRELOGIN/LOGIN7 rewrites) per SECURITY.md.🤖 Generated with Claude Code