fix(web): Stripe key format, change-email/2FA edge, feedback-respond cap (BUNYIP-117) #163

Merged
YousifShkara merged 1 commit from fix/web-edge-117-validation-and-error-surfacing into main 2026-06-17 04:13:05 +02:00
Owner

Cross-cutting web-edge validation gaps called out by BUNYIP-117. The domain layer is correct in every case; the gap is that bunyip-web posts unbounded / unformatted input to the API and (for several admin POSTs) discards the API result with let _ = ..., so a backend rejection produces no inline feedback and over-length input lands in the DB cap or round-trips silently.

Stripe config (admin.rs::stripe_save): replaced the prior let _ = update_stripe_config(...).await with a Result match. New edge validation: app_tag bounded to 200 chars, secret_key checked for sk_ or rk_ prefix and bounded to 255 chars when present, webhook_secret checked for whsec_ prefix and bounded to 255 chars when present. Empty inputs still mean "no change" (the API treats omission as the persisted-value carrier). A new stripe_error_page helper renders the page with the supplied inline error so a failed save no longer silently 200-redirects.

2FA code inputs (auth_pages.rs::twofa_verify form + dashboard.rs::twofa_setup form): both now carry pattern="[0-9]{6}" maxlength="6" minlength="6" required. The browser bounds + format-checks before submit; the authoritative check still lives in services::totp::verify_code. Before this, a non-numeric code round-tripped to the API.

Change email (dashboard.rs::settings_email): new_email gets type="email" maxlength="254" required and an inline shape check at the handler via the BUNYIP-115 validate::email helper, so garbage like "x@y" no longer round-trips. Required attribute on current_password too, with a clean inline message when it is empty.

Feedback respond (admin.rs::feedback_respond): bounded the admin response body to 16,000 chars (the same cap chat messages get) so a runaway paste does not silently produce an oversize stored row or oversize outbound email.

Reuses the shared validators in bunyip-web/src/handlers/validate.rs introduced by the BUNYIP-112/113/115/122 bundle PR; this commit builds on top of that one. cargo test -p bunyip-web all green, just lint and just typecheck clean. Deferred to a follow-up: full sweep of the remaining let _ = ... swallowing sites in admin (entitlement grants, app group set, etc.) - these are lower-frequency surfaces and out of scope for the v1 cross-cutting fix.

#BUNYIP-117

Cross-cutting web-edge validation gaps called out by BUNYIP-117. The domain layer is correct in every case; the gap is that bunyip-web posts unbounded / unformatted input to the API and (for several admin POSTs) discards the API result with `let _ = ...`, so a backend rejection produces no inline feedback and over-length input lands in the DB cap or round-trips silently. Stripe config (admin.rs::stripe_save): replaced the prior `let _ = update_stripe_config(...).await` with a Result match. New edge validation: app_tag bounded to 200 chars, secret_key checked for `sk_` or `rk_` prefix and bounded to 255 chars when present, webhook_secret checked for `whsec_` prefix and bounded to 255 chars when present. Empty inputs still mean "no change" (the API treats omission as the persisted-value carrier). A new `stripe_error_page` helper renders the page with the supplied inline error so a failed save no longer silently 200-redirects. 2FA code inputs (auth_pages.rs::twofa_verify form + dashboard.rs::twofa_setup form): both now carry `pattern="[0-9]{6}" maxlength="6" minlength="6" required`. The browser bounds + format-checks before submit; the authoritative check still lives in `services::totp::verify_code`. Before this, a non-numeric code round-tripped to the API. Change email (dashboard.rs::settings_email): new_email gets `type="email" maxlength="254" required` and an inline shape check at the handler via the BUNYIP-115 `validate::email` helper, so garbage like "x@y" no longer round-trips. Required attribute on current_password too, with a clean inline message when it is empty. Feedback respond (admin.rs::feedback_respond): bounded the admin response body to 16,000 chars (the same cap chat messages get) so a runaway paste does not silently produce an oversize stored row or oversize outbound email. Reuses the shared validators in `bunyip-web/src/handlers/validate.rs` introduced by the BUNYIP-112/113/115/122 bundle PR; this commit builds on top of that one. `cargo test -p bunyip-web` all green, `just lint` and `just typecheck` clean. Deferred to a follow-up: full sweep of the remaining `let _ = ...` swallowing sites in admin (entitlement grants, app group set, etc.) - these are lower-frequency surfaces and out of scope for the v1 cross-cutting fix. #BUNYIP-117
fix(web): Stripe key format, change-email/2FA edge, feedback-respond cap (BUNYIP-117)
All checks were successful
Create release / Create release from merged PR (pull_request) Has been skipped
Check / fmt / clippy / build / test (pull_request) Successful in 1m30s
b4dcaa0573
Cross-cutting web-edge validation gaps called out by BUNYIP-117. The domain layer is correct in every case; the gap is that bunyip-web posts unbounded / unformatted input to the API and (for several admin POSTs) discards the API result with `let _ = ...`, so a backend rejection produces no inline feedback and over-length input lands in the DB cap or round-trips silently.

Stripe config (admin.rs::stripe_save): replaced the prior `let _ = update_stripe_config(...).await` with a Result match. New edge validation: app_tag bounded to 200 chars, secret_key checked for `sk_` or `rk_` prefix and bounded to 255 chars when present, webhook_secret checked for `whsec_` prefix and bounded to 255 chars when present. Empty inputs still mean "no change" (the API treats omission as the persisted-value carrier). A new `stripe_error_page` helper renders the page with the supplied inline error so a failed save no longer silently 200-redirects.

2FA code inputs (auth_pages.rs::twofa_verify form + dashboard.rs::twofa_setup form): both now carry `pattern="[0-9]{6}" maxlength="6" minlength="6" required`. The browser bounds + format-checks before submit; the authoritative check still lives in `services::totp::verify_code`. Before this, a non-numeric code round-tripped to the API.

Change email (dashboard.rs::settings_email): new_email gets `type="email" maxlength="254" required` and an inline shape check at the handler via the BUNYIP-115 `validate::email` helper, so garbage like "x@y" no longer round-trips. Required attribute on current_password too, with a clean inline message when it is empty.

Feedback respond (admin.rs::feedback_respond): bounded the admin response body to 16,000 chars (the same cap chat messages get) so a runaway paste does not silently produce an oversize stored row or oversize outbound email.

Reuses the shared validators in `bunyip-web/src/handlers/validate.rs` introduced by the BUNYIP-112/113/115/122 bundle PR; this commit builds on top of that one. `cargo test -p bunyip-web` all green, `just lint` and `just typecheck` clean. Deferred to a follow-up: full sweep of the remaining `let _ = ...` swallowing sites in admin (entitlement grants, app group set, etc.) - these are lower-frequency surfaces and out of scope for the v1 cross-cutting fix.

#BUNYIP-117
YousifShkara deleted branch fix/web-edge-117-validation-and-error-surfacing 2026-06-17 04:13:05 +02:00
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/bunyip!163
No description provided.