# Fix plan — 2026-11-03

Ordered by user impact, then by effort. Each item names the repo and file,
an effort estimate (XS under an hour, S a morning, M a day or two), and the
check that closes it. Nothing here is filed as a GitHub issue yet; the proposed
issue list is at the bottom so they can be opened in batches without flooding
the board.

## Wave 1 — production-facing, small

### 1. Serve `drape.to/privacy` and `/terms` (P1)

- **Repo:** `Drape-Marketing`. **Effort:** S.
- **Why first:** these are the App Store Connect canonical URLs and every
  marketing footer links them; a reviewer or a user following the link gets a
  404 today.
- **Fix:** the `rewrites()` in `next.config.ts` are not honoured by the Amplify
  deployment. Either add equivalent rewrite rules in the Amplify app settings,
  or replace the rewrite with real routes (`app/privacy/page.tsx` and
  `app/terms/page.tsx`) that render the existing HTML so no host feature is
  needed. The second option is more robust.
- **Verify:** `curl -I https://drape.to/privacy` and `/terms` return 200 after
  deploy; the crawler's marketing pass shows both routes at 200 in production.

### 2. Allow product image hosts in the marketing site (P2)

- **Repo:** `Drape-Marketing`, `next.config.ts`. **Effort:** XS.
- **Fix:** add `images.remotePatterns` for `v3b.fal.media` and the Supabase
  storage host (`mfxtjylgcryarajinvbd.supabase.co`, or `*.supabase.co`).
- **Verify:** `/product/<any id>` shows the product image in production; the
  local dev server no longer throws on the route.

### 3. Show the admin login error (P3)

- **Repo:** `Drape-admin-v1`, `lib/api.ts` and `app/login/page.tsx`.
  **Effort:** XS.
- **Fix:** mirror the brand portal's client: skip the 401 redirect for the login
  request (a `skipAuthRedirect` option, or do not redirect when already on
  `/login`) and surface `detail` from the response.
- **Verify:** a wrong password on `admin.drape.to/login` shows "Invalid admin
  credentials" and keeps the email field; the crawler's
  `login-bad-credentials` capture shows the message.

### 4. Fix the featured-products endpoint (P4)

- **Repo:** `Drape-`, `backend-postgres` (`/api/products/featured`).
  **Effort:** S to M, cause unknown until the traceback is read.
- **Fix:** pull the exception from Sentry or the ECS logs for a direct call to
  the endpoint, fix it, and add it to the integration tests. Consider having
  the app distinguish "no featured drops" from "could not load" so the next
  backend failure is visible.
- **Verify:** `curl https://api.drape.to/api/products/featured` returns 200;
  the Featured screen populates when a product is flagged featured.

## Wave 2 — hygiene, one change per app

### 5. Purge committed test credentials (H1)

- **Repo:** `Drape-`. **Effort:** S.
- **Fix:** remove the email and password from the four files, keep only
  `DRAPE_TEST_EMAIL` / `DRAPE_TEST_PASSWORD` placeholders, and provision a
  non-personal QA account whose password lives in a secrets store. The repo's
  own guidance already notes history still holds older secrets; if the repo is
  ever shared externally, run BFG once for all of them.
- **Verify:** `grep -r DRAPE_TEST_PASSWORD=` across the repo returns only
  placeholders.

### 6. Landmarks, headings and `lang` in shared layouts (H2)

- **Repos:** `Drape-brand`, `Drape-admin-v1`, `Drape-Marketing`. **Effort:** S
  total.
- **Fix:** wrap page content in `main` in each app's root or group layout; give
  the auth pages (login, signup, apply, forgot/reset password, verify email,
  accept invite) a visible or visually-hidden `h1`; set `lang="en"` on the
  `html` element in the marketing and brand layouts.
- **Verify:** the crawler's minor-findings count for "No main landmark", "No h1"
  and "No lang attribute" drops to zero.

### 7. Deploy the brand portal (H3)

- **Repo:** `Drape-brand`. **Effort:** XS.
- **Fix:** the local branch already has a titled 404 page; production is
  behind. Ship the next brand deploy and confirm.
- **Verify:** `brand.drape.to/<unknown>` has a title and a "404" heading.

### 8. Eager-load hero images (H4)

- **Repos:** `Drape-Marketing` (`/`, `/for-brands`), `Drape-brand` (`/`).
  **Effort:** XS.
- **Fix:** add `priority` to the above-the-fold `next/image` hero on each page.
- **Verify:** the LCP warning no longer prints in the dev console.

### 9. Silence the hydration warning (D2)

- **Repo:** `Drape-brand`, root layout. **Effort:** XS.
- **Fix:** `suppressHydrationWarning` on the `html` element, since the theme
  script intentionally mutates it before hydration.
- **Verify:** no hydration message in the dev console on `/`.

## Wave 3 — dev environment

### 10. Make local dev match the CORS rules (D1)

- **Where:** `Drape-AI/start-drape-local.sh` and its stop script (local only,
  not in a repo). **Effort:** XS.
- **Fix:** print and open `brand.localhost:<port>` and `admin.localhost:<port>`;
  pick a free port instead of silently skipping when 3001 is busy; stop only the
  ports the script started.

### 11. Inject Stripe secrets into the dev task definition (D3)

- **Repo:** `Drape-`, `backend-postgres/deploy/task-def-dev.json`.
  **Effort:** XS plus the secret values in Secrets Manager.
- **Fix:** commit the pending change that adds the seven `STRIPE_*` secrets
  (plus Mux, Langfuse and the webhook secrets) to the dev task definition, and
  deploy dev.
- **Verify:** the seller billing screen on a dev build no longer shows the
  "Stripe is not configured" notice.

### 12. Seed dev with a resolvable store and real product images (D4)

- **Where:** dev database. **Effort:** S.
- **Fix:** give the QA Atelier store an active slug so `<slug>.localhost`
  resolves through `/api/tenant/<slug>`, and attach apparel images to its two
  products.
- **Verify:** the storefront, `/l?code=...` and `/p?...` routes can be captured
  in their live states on the next audit.

### 13. Replace the stale Maestro flows (D5)

- **Repo:** `Drape-`, `frontend/.maestro` and `frontend/qa/maestro`.
  **Effort:** M.
- **Fix:** retire flows that assert screens which no longer exist, adopt the
  audit tour as the smoke flow, and keep credentials in environment variables.
  The tour runs in about 12 minutes against a Release simulator build.
- **Verify:** `maestro test audit-tour.yaml` passes on a fresh simulator.

### 14. Scope Watchman to the app (nice-to-have)

- **Repo:** `Drape-`, `frontend/.watchmanconfig`. **Effort:** XS.
- **Fix:** add a `.watchmanconfig` so the watch root is `frontend/` with
  `node_modules`, `ios/Pods` and build output ignored. The first Metro start on
  a fresh machine currently crawls the whole repo for about 40 minutes.

## Needs a decision, not a fix

- **Tenant root.** `https://<brand>.drape.to/` redirects to the portal login in
  both environments. If a shopper is meant to land on the storefront, that root
  should go to `/shop`.
- **Signed-in audits.** 41 portal and admin routes have never been captured.
  A brand login and an admin login for a QA account would let the same crawler
  cover them next time.

## Proposed GitHub issues (not yet filed)

| Proposed title | Repo | Labels | Wave |
| --- | --- | --- | --- |
| Marketing: `/privacy` and `/terms` return 404 in production | Drape-Marketing | bug, production, app-store | 1 |
| Marketing: configure `next/image` remote hosts for product images | Drape-Marketing | bug, production | 1 |
| Admin: wrong password reloads login with no message | Drape-admin-v1 | bug, production, ux | 1 |
| Backend: `/api/products/featured` returns 500 | Drape- | bug, production, backend | 1 |
| Remove committed test credentials from docs and QA files | Drape- | security, hygiene | 2 |
| Add `main` landmark, page `h1`s and `lang` across web apps | Drape-brand, Drape-admin-v1, Drape-Marketing | a11y, hygiene | 2 |
| Eager-load hero images flagged as LCP | Drape-Marketing, Drape-brand | performance | 2 |
| Brand portal: suppress intentional theme hydration mismatch | Drape-brand | hygiene | 2 |
| Dev task definition: inject Stripe and related secrets | Drape- | dev-env | 3 |
| Dev seed: resolvable store slug and real product images | Drape- | dev-env | 3 |
| Refresh Maestro flows to match the current app | Drape- | qa, dev-env | 3 |
| Add `.watchmanconfig` to scope Metro's watch root | Drape- | dev-env | 3 |
