feat(billing): masked write-only Stripe/gateway key in the config UI #422
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/mapps-363-stripe-masked-key"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements MAPPS-363 (slice of PMS-636): an admin can enable Stripe and enter its API key from the payment-gateway config UI, write-only and never shown back.
What changed (mokosh-apps, client only)
The payment-gateway modal previously entered credentials as a raw "Config (JSON)" textarea and decoded a
configfield the server no longer returns. PMS-342 already made the secret write-only server-side (the GET exposes only aconfiguredflag, never the plaintext), so the client was stale and, worse, editing a gateway to flip Active re-sentconfig: {}which the server encrypts and stores, silently wiping the real key.passwordinput. It always starts blank; on saveconfigis sent only when a key was typed, so leaving it blank keeps the existing secret (PMS-342 omit-to-keep). A first-time gateway still requires a key, guarded client-side because the server 400s a create with no config.RemoteGatewaynow decodesconfiguredinstead of the droppedconfig; save failures route throughApiError::user_message().No server change: the encrypted
payment_gateway_configsbackend and theconfiguredstatus already exist; this reusesPUT /payment-gateways(upsert) andGET /payment-gateways.Acceptance criteria
is_activetoggle, unchanged).payment_gateway_configspath (no new secret store).Notes
config.api_key, which fully covers Stripe. Provider-specific multi-field config for Authorize.Net / PayPal (login id + transaction key, client id + secret) is out of scope here and would be a separate PMS-636 slice.configured, not a masked value. If a last4 display is wanted, it needs a small mokosh-server enhancement toPaymentGatewayConfigResponse.No local Rust toolchain; relying on CI (clippy + fmt + wasm check + tests).
The payment-gateway config modal entered credentials as a raw "Config (JSON)" textarea and decoded a `config` field the server no longer returns (PMS-342 made the secret write-only, exposing only a `configured` flag). Two problems: the plaintext key was editable/echo-shaped rather than write-only, and editing an existing gateway to toggle Active re-sent `config: {}`, which the server encrypts and stores, silently wiping the real key. Replace the JSON textarea with a masked, write-only API-key `password` input: it always starts blank, and on save `config` is sent only when a key was typed, so a blank field keeps the existing secret (omit-to-keep). A first-time gateway still requires a key (guarded client-side, since the server 400s a create with no config). Surface configured vs not-configured with a badge in the modal and a new "Credentials" column, and route save failures through `user_message()`. Decode `configured` instead of the dropped `config`. No server change: the write-only backend and `configured` status already exist. #MAPPS-363 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>Code-review follow-ups on the write-only gateway key: the key field's "API key" caption was a bare span, so it was not programmatically associated with the input; make it a `<label for="gateway_api_key">` like every sibling field. Also align the list column's status text with the modal ("Not configured" instead of "Missing"). #MAPPS-363 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>