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.