Skip to content

WEB-PRIVACY-001B — Redact public Shop product-load failures #256

Description

@daliu

Outcome

The public /shop/:slug page must show one fixed, plain retry message when a product lookup cannot load. It must never inspect, render, or log a rejected Firestore, SDK, provider, or exception value to an anonymous visitor.

Fixed public message:

We could not load this product right now. Please try again later.

Current defect

src/pages/shop/ProductDetail.tsx catches the rejected product lookup and renders err.message directly. The route is public and the production shop service rethrows Firestore lookup failures, so a crawler or anonymous visitor can receive provider diagnostics, project identifiers, paths, or other private detail.

The separate checkout rejection is a different commerce boundary and is explicitly excluded.

Invariant

  • do not capture or inspect the lookup rejection
  • stop the loading state and show exactly one accessible fixed result
  • retain the existing Back to shop link
  • do not emit the rejection through browser console output
  • preserve the distinct missing-product and successful-product projections
  • make no Firebase/provider call in tests and use no real visitor, member, product, or order data

Exact scope

  1. src/pages/shop/ProductDetail.tsx
    • only the getProductBySlug rejection hunk
    • only the early load/not-found error paragraph accessibility attributes
  2. src/App.test.jsx
  3. docs/officers/EVENTS_SHOP_MEMBERS.md
    • separately named Public product-detail load failure privacy — SOURCE ONLY, NOT LIVE section only

Everything else is excluded, especially the handleBuy checkout rejection/form error, shop/event services, checkout/provider/Functions/Rules/root docs/lint/workflows/packages/deploy/data paths and every #249/#246 path.

Acceptance

  • Old-source tests expose a synthetic private canary and execute a hostile message getter, then pass after correction.
  • Rejection shows exactly the fixed accessible result and ends Loading.
  • Back to shop remains available and the lookup runs exactly once.
  • No rejected detail reaches DOM or five console methods.
  • A hostile throwing message getter is never accessed.
  • Resolved null still shows the existing Product not found result.
  • A synthetic success still shows the existing title, price, and product form.
  • Focused and full frontend checks, typecheck, lint safety, SPA/release/artifact guards, build, diff review, and independent security/accessibility/officer reviews pass.
  • Officer impact, officer documentation, and exact deployment truth are recorded.

Safety and deployment truth

Tests use only made-up values and mocks. Do not contact Firebase, Stripe, or another provider; inspect a real account/order/catalog; change provider configuration; or use production data. Source, tests, merge, preview, and green CI do not prove the website, Firebase, provider, or live behavior changed.

Metadata

Metadata

Assignees

Labels

area:firebaseFirebase services and dataarea:privacyPersonal data, consent, minimization, retention, and privacy operationsarea:webWeb application and hostingpriority:P0Launch blocker or urgent security risksize:XSOwner decision or very narrow changetype:securitySecurity or privacy boundarytype:testingTest infrastructure and quality gates

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions