Files
..

redisproxy prepared target sessions

2026-09-28: password-only Redis authentication

Reason and behavior

Redis supports both the legacy/default-user AUTH password form and the ACL AUTH username password form. Target and gateway account validation now accepts an exactly empty Redis username only when a password exists. Direct connections, prepared sessions, health tests, topology discovery, Sentinel, replication and Cluster node dials use the same selected credentials. Password-only target accounts send one AUTH argument; named ACL accounts send two.

Redis gateway accounts follow the same distinction. A blank username plus a password accepts client AUTH password and HELLO ... AUTH default password. An empty username and an explicit default username cannot be configured together because both are the same downstream protocol identity. A gateway with no accounts remains the separate no-authentication mode.

Scope and compatibility

Only Redis accepts password mode without a username. MongoDB, MySQL, PostgreSQL, SQL Server, RabbitMQ, HTTP(S), SSH and SFTP retain their named-account rules; TCP has no protocol authentication. Existing Redis default users and encrypted secrets remain valid. The JSON shape and SQLite schema do not change, so no migration is required.

Actual validation

Go 1.25.0 model and API tests cover persistence, redaction, target/gateway tests, default-user aliasing and rejection by non-Redis protocols. RESP net.Pipe fixtures cover direct and Cluster upstream command shapes plus direct and Cluster gateway acceptance/rejection. These are protocol fixtures, not validation against a live Redis or Sentinel server.

2026-09-26: account-free upstream targets

Reason and behavior

Redis deployments may disable upstream authentication. A Redis target can now store an empty account list; its draft/saved tests, health probes, topology discovery, prepared sessions and gateway connections omit upstream AUTH. Redis gateway client authentication is optional. An empty gateway account list accepts clients without local AUTH; configured gateway accounts still require the existing username/password checks. Standalone and Cluster gateway paths remove client credentials from forwarded HELLO ... AUTH ... when the selected upstream is account-free.

Adding any target account ends the empty-list mode and requires a valid selected account. Rejected configured credentials do not trigger anonymous retry for standalone, Cluster or replication nodes. Redis Sentinel retains its explicit 自动尝试目标账号或无认证 compatibility option when no Sentinel account is selected; an explicit Sentinel account disables that fallback. Cluster redirects use the same selected data-account rule for every discovered node.

Scope and compatibility

The empty selection is accepted only for Redis targets with zero accounts (and for the separately account-free TCP protocol). Other target protocols keep their existing account requirement. Existing Redis targets and encrypted account JSON are unchanged; no schema migration or credential conversion is performed. Gateway account mappings keep an empty targetAccountId for an account-free Redis destination and must be updated if credentials are later added.

Actual validation

Go 1.25.0 model, cluster, gateway and redisproxy package tests plus focused API regressions passed with serial compilation and workspace-local temporary/cache directories; related vet checks passed. Coverage includes draft/save/test, default and per-gateway-account mappings, startup/switching, periodic health checks, standalone/Cluster/Sentinel connection setup, authentication fallback boundaries and removal of client HELLO AUTH arguments. The protocol checks use local RESP/net.Pipe fixtures; they are not live Redis or Sentinel validation.

2026-09-22: protocol-authenticated idle standby

Reason and behavior

Previously target protocol connections were created only after a downstream client needed them. Handler.PrepareSession now eagerly opens and authenticates one real single-node target session without a downstream client. It clears PreparedTarget on the setup snapshot to prevent recursive borrowing. The parent gateway pool owns publishing, periodic heartbeats, replacement, rejection backoff and shutdown.

Redis uses RESP PING/PONG. AUTH and initial SELECT complete during preparation. open preserves its BufferedConn and clears the handshake deadline on successful setup, so an idle standby does not inherit a 15-second handshake timeout.

Checkout checks current target credential validity before accessing the pool. A prepared value is checked against target identity/account, database/authSource, outbound route, TLS, compression and session options. The request context is used for a fresh heartbeat before handing the session to protocol serving code. A failed heartbeat closes the standby and falls back to the existing new-connection path; a canceled request returns its context error. No business command is replayed. Checked-out connections are never returned to this standby pool: transactions, cursors and subscriptions cannot be shared with another client.

Preparation is bounded by the configured connect timeout (15 seconds by default). Heartbeats have a five-second upper bound and respect earlier context cancellation. Their cancellation callback is stopped, or joined if already running, before returning ownership. Canceling a completed setup or heartbeat context cannot close a successfully handed-off session.

Setup failures preserve only typed authentication, permission and host-identity rejection categories using outbound.FailureKind. Unknown errors use a generic message. Original server-controlled error text is not retained in the returned error chain, and there is no string-based password-error guessing. The parent pool can stop reconnecting explicit rejections instead of repeatedly attempting login.

Scope and compatibility

Only this protocol directory is changed by this adapter task. No schema migration, production data change, new explicit transaction or business write is introduced. Disabled persistence and clustered targets continue through the original open path. Existing protocol serving/audit behavior remains in place. Shared pool wiring and project-wide change-rationale documentation belong to the parent integration task.

Actual validation

Go 1.25.0, GOFLAGS=-p=2, GOTMPDIR=artifacts/portable-validation/build-work and its cache were used for:

  • go test ./internal/protocol/mysqlproxy ./internal/protocol/pgproxy ./internal/protocol/mongoproxy ./internal/protocol/redisproxy -count=1 -timeout=120s — passed.
  • go vet ./internal/protocol/mysqlproxy ./internal/protocol/pgproxy ./internal/protocol/mongoproxy ./internal/protocol/redisproxy — passed.
  • Prepared fixture coverage includes eager authentication, Ping, same-connection checkout with a second heartbeat, failed-heartbeat replacement, cancellation, blocked setup/heartbeat deadlines, credential validation, identity/database mismatches, explicit typed authentication rejection and credential-safe errors.
  • MySQL/PostgreSQL also verify database overrides leave the default standby available; MongoDB verifies pre-auth hello isolation and custom AuthSource on authentication, idle Ping and checkout Ping; Redis checks buffering/deadlines.
  • The attempted targeted race run was unavailable because this environment has CGO disabled (go: -race requires cgo). No race-pass claim is made.

These are local protocol fixtures, not live database or production-server tests. No frontend build, embedded asset build, deployment or commit was performed here.