The PUT handler in src/http/routes/admin/tenants.ts builds tenantInfo with truthy guards:
if (databasePoolUrl) {
tenantInfo.database_pool_url = encrypt(databasePoolUrl)
}
if (databasePoolMode) {
tenantInfo.database_pool_mode = databasePoolMode
}
The body schema marks both as nullable: true, but a request with databasePoolUrl: null or databasePoolMode: null skips the assignment entirely. The merge upsert then leaves the existing column unchanged, so operators can't reset pool config back to the default.
The PATCH handler at lines 396-401 already does the three-way check correctly. PUT just needs the same.
Repro:
curl -X PUT 'http://localhost:5000/tenants/abc' \
-H "apikey: $ADMIN_API_KEYS" \
-H 'content-type: application/json' \
-d '{
"anonKey": "...", "databaseUrl": "...", "jwtSecret": "...", "serviceKey": "...",
"databasePoolUrl": "postgresql://...",
"databasePoolMode": "transaction"
}'
curl -X PUT 'http://localhost:5000/tenants/abc' \
-H "apikey: $ADMIN_API_KEYS" \
-H 'content-type: application/json' \
-d '{
"anonKey": "...", "databaseUrl": "...", "jwtSecret": "...", "serviceKey": "...",
"databasePoolUrl": null,
"databasePoolMode": null
}'
# database_pool_url and database_pool_mode are still the encrypted/string values from the first call.
The PUT handler in
src/http/routes/admin/tenants.tsbuildstenantInfowith truthy guards:The body schema marks both as
nullable: true, but a request withdatabasePoolUrl: nullordatabasePoolMode: nullskips the assignment entirely. The merge upsert then leaves the existing column unchanged, so operators can't reset pool config back to the default.The PATCH handler at lines 396-401 already does the three-way check correctly. PUT just needs the same.
Repro: