fix(billing): make payment-gateway credential a write-only secret #263

Merged
vas2000-work merged 1 commit from fix/pms-342-payment-gateway-write-only-secret into main 2026-06-16 23:49:26 +02:00
Owner

GET /payment-gateways previously returned the decrypted gateway config (e.g. a Stripe secret key) to the client on every visit to the gateways page, defeating the at-rest encryption the moment the page is opened. Treat the credential as a write-only secret.

PaymentGatewayConfigResponse no longer carries the decrypted config; it exposes only non-secret metadata (provider, is_active, is_test_mode) plus configured: bool so the client can render the list without ever seeing the plaintext. list_payment_gateways stops decrypting entirely; decryption stays server-internal for actual gateway calls.

UpsertPaymentGatewayConfigRequest.config becomes Option: omitting it on update preserves the stored secret (metadata-only UPDATE that leaves config_encrypted untouched), while providing it replaces the secret. A first-time create with no config is a 400, since config_encrypted is NOT NULL and there is no existing secret to keep.

Adds an integration test asserting the upsert and list response bodies contain no plaintext credential field, that a config-less update preserves the stored encrypted secret, and that creating a gateway without a config is rejected.

#PMS-342

GET /payment-gateways previously returned the decrypted gateway config (e.g. a Stripe secret key) to the client on every visit to the gateways page, defeating the at-rest encryption the moment the page is opened. Treat the credential as a write-only secret. PaymentGatewayConfigResponse no longer carries the decrypted `config`; it exposes only non-secret metadata (provider, is_active, is_test_mode) plus `configured: bool` so the client can render the list without ever seeing the plaintext. list_payment_gateways stops decrypting entirely; decryption stays server-internal for actual gateway calls. UpsertPaymentGatewayConfigRequest.config becomes Option: omitting it on update preserves the stored secret (metadata-only UPDATE that leaves config_encrypted untouched), while providing it replaces the secret. A first-time create with no config is a 400, since config_encrypted is NOT NULL and there is no existing secret to keep. Adds an integration test asserting the upsert and list response bodies contain no plaintext credential field, that a config-less update preserves the stored encrypted secret, and that creating a gateway without a config is rejected. #PMS-342
fix(billing): make payment-gateway credential a write-only secret
All checks were successful
Check / fmt + clippy + compile + unit/doc tests (pull_request) Successful in 56s
E2E / Playwright against staging (pull_request) Successful in 1m1s
Integration / integration tests (pull_request) Successful in 6m3s
Create release / Create release from merged PR (pull_request) Has been skipped
8d31b36a70
GET /payment-gateways previously returned the decrypted gateway config (e.g. a Stripe secret key) to the client on every visit to the gateways page, defeating the at-rest encryption the moment the page is opened. Treat the credential as a write-only secret.

PaymentGatewayConfigResponse no longer carries the decrypted `config`; it exposes only non-secret metadata (provider, is_active, is_test_mode) plus `configured: bool` so the client can render the list without ever seeing the plaintext. list_payment_gateways stops decrypting entirely; decryption stays server-internal for actual gateway calls.

UpsertPaymentGatewayConfigRequest.config becomes Option: omitting it on update preserves the stored secret (metadata-only UPDATE that leaves config_encrypted untouched), while providing it replaces the secret. A first-time create with no config is a 400, since config_encrypted is NOT NULL and there is no existing secret to keep.

Adds an integration test asserting the upsert and list response bodies contain no plaintext credential field, that a config-less update preserves the stored encrypted secret, and that creating a gateway without a config is rejected.

#PMS-342
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/mokosh-server!263
No description provided.