feat(web): mask secrets/codes by default with an explicit reveal (BUNYIP-371) #449
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/BUNYIP-371-mask-secrets-screenshare"
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?
BUNYIP-371. Best-effort privacy masking so secrets/codes are not exposed during casual screen sharing.
Context
Vas asked for KeePassXC-style privacy (hide secrets during a screen share). A web app CANNOT mark itself hidden to native screen capture the way a native app does, and a CSS blur is defeated by disabling GPU compositing - so this is best-effort in-app masking that stops ACCIDENTAL exposure, not a determined viewer. That limitation is documented in the code (the
sensitive_revealdoc comment + the app.js handler comment).Change
New
sensitive_reveal(label, content)Maud helper (bunyip-web/src/handlers/dashboard.rs): wraps a rendered secret in a block that is blurred (blur-sm) by default, with an eye button that toggles the blur. A delegated[data-sensitive-toggle]handler inassets/js/app.jsflips the class +aria-pressed+ icon. The value stays in the DOM (visual masking, not removal, so it is still copyable once revealed).Applied to the user-facing plaintext-secret sites:
Out of scope (already handled or lower risk, per the scope decision): the Stripe secret key + webhook secret already render masked to last-4 (BUNYIP-432/443); password inputs already have a show/hide toggle; the admin Stripe webhook signing secret (shown once) is admin-only and was left out of this user-facing pass.
Verification
just check-container(fmt + clippy-D warnings+ workspace tests) passes.sensitive_reveal_blurs_content_but_keeps_it_in_the_dom(the component masks by default, keeps content in the DOM) +twofa_qr_view_masks_the_setup_key_by_default(applied to the TOTP view).🤖 Generated with Claude Code