Findings — 2026-11-03
Each finding carries a verdict from running the same crawl locally and in production. Production means it reproduces on the live site today. Both means the behaviour is identical in both environments. Dev only means it cannot be observed in production and is a local-environment matter.
Real in production
| # | Surface | Finding | Evidence | Severity |
|---|---|---|---|---|
| P1 | Marketing | drape.to/privacy and drape.to/terms return 404 | /privacy.html returns 200, so the files are deployed and the next.config.ts rewrite is not applied by the host. Every marketing footer links the clean URLs, and the config comment calls them the App Store Connect canonical URLs. Local serves both. | Critical |
| P2 | Marketing | Product share page loses its image | /product/<id> renders the product, but /_next/image answers 400 for the v3b.fal.media source because images.remotePatterns is not configured. Locally the same gap throws a runtime error and the page shows "This page couldn't load". All 24 production products use fal.media or mfxtjylgcryarajinvbd.supabase.co. | Needs attention |
| P3 | Admin | Wrong password reloads the login page with no message | The API returns 401 "Invalid admin credentials", but lib/api.ts redirects to /login on every 401, including the login request, so the page reloads and the email field empties. Reproduced on admin.localhost and admin.drape.to. The brand portal's client skips the redirect for login and shows "Invalid email or password". | Needs attention |
| P4 | Backend | GET /api/products/featured returns 500 | "Internal server error" from dev-api.drape.to and api.drape.to when called directly. The app's Featured screen shows "No featured drops" rather than an error. | Needs attention |
Hygiene — same in both environments
| # | Surface | Finding | Evidence | Severity |
|---|---|---|---|---|
| H1 | Drape- repo | A test account password is committed in four files | kcb1099@gmail.com with its password appears in frontend/docs/CHANGELOG_ENGINEERING.md, frontend/docs/PROD_ENV_TEMPLATE.md, frontend/docs/ENVIRONMENT_RECOVERY_PLAYBOOK.md and frontend/qa/maestro/rc1_gate.yaml. The credentials no longer work (401 on dev and prod) but they contradict the repo's own secrets policy. | Needs attention |
| H2 | Brand portal, storefront, admin, marketing | No main landmark and often no h1 | 36 pages across the four surfaces have no main landmark; around 20 signed-out brand-portal and storefront pages have no h1; the marketing and brand html elements have no lang. Identical counts in production, so it lives in the shared layouts. | Minor |
| H3 | Brand portal (production) | The 404 page has no title and no heading | Production's unknown-route page renders without a title or h1; the local develop build has both ("404"). Production is behind the branch here. | Minor |
| H4 | Marketing, brand portal | Hero images are lazy-loaded | Next's dev server flags the hero image on marketing / and /for-brands and on the brand landing as the Largest Contentful Paint without loading="eager". The warning only prints in dev; the behaviour ships. | Minor |
Dev environment only
| # | Where | Finding | Evidence | Note |
|---|---|---|---|---|
| D1 | Dev API CORS | Plain localhost:3004 and localhost:3005 are blocked | server.py allows localhost on 3000 to 3003 and any *.localhost host. The first brand and admin crawls on plain localhost failed every API call and were discarded; brand.localhost and admin.localhost work. | start-drape-local.sh should open the subdomain hosts |
| D2 | Brand portal | Hydration mismatch warning on / | The inline theme script sets data-theme before React hydrates. Production React strips the warning, so it is not observable on brand.drape.to, but the mismatch is in the code. | suppressHydrationWarning on html |
| D3 | App, seller billing | "Stripe is not configured on this server" | The committed deploy/task-def-dev.json injects no STRIPE_* secrets; task-def-prod.json injects all seven. | An uncommitted edit to the dev task definition adds them |
| D4 | Dev data | Seed products show the wrong photo and no tenant resolves | Both QA Atelier products (Ink Wide Trousers, Cream Oversized Shirt) show a wakeskate photo. No store on dev has a slug that /api/tenant/<slug> resolves, so the storefront, door landing (/l) and QR product page (/p) could only be captured in their not-found states. Those states match production. | Seed a store with a slug and real images |
| D5 | frontend/.maestro | The committed Maestro flows no longer match the app | 01-signup fails at its second step (asserts a "Create Account" title); the brutal-audit flow expects a login path that moved. A replacement tour flow is in the downloads. | Refresh or replace |
Mobile app — 47 screens, Release build on the dev API
What held up:
- Signup and login validate empty submits with clear copy ("Please fill in all fields.", "Please enter your email and password. Reset password →").
- Onboarding runs welcome → Select your culture → Define your style → Body profile, with the biometric consent gate in place.
- Home, The Market, Explore, Featured, Arrivals, Saved, Bag, Scan, Sell, Refer, Messages, Orders, Render archive, Look board, Notifications, Profile, Fit setup, Body photo, Saved looks, Privacy policy and Privacy & Terms all render.
- The seller hub, orders, messages, analytics (correctly gated to Pro Seller) and billing render for a consumer account; brand routes fall back to home.
- Deep links opened without their parameters fall back sensibly: look board asks for a username, save-closet says "Missing product info", checkout-return shows "Order cancelled", billing-return shows "Could not confirm".
- The Scan screen detects the simulator and offers a manual path.
Not exercised: try-on rendering (spends Fashn credits), marketplace purchase (Stripe), body-photo upload (needs a photo library), and the brand and seller signed-in roles.
Where local and production differ
| Surface | Route | Local | Production |
|---|---|---|---|
| Marketing | /privacy, /terms | 200 | 404 |
| Marketing | /product/<id> | Runtime error page | Renders, image missing |
| Marketing | /download | Heading "DOWNLOAD DRAPE" | Heading "BE FIRST TO TRY DRAPE" (production predates the branch) |
| Brand portal | unknown route | 404 page with title and heading | 404 page with neither |
| Storefront | /shop | "Brand not found" (no dev tenant) | CHECKtheFeed storefront renders |
| Storefront | / | redirects to /login | redirects to /login (a shopper on a brand subdomain lands on the portal login) |
Expected outcomes, not findings
The crawler deliberately submits empty forms, signs in with a non-existent
account, opens /verify-email, /reset-password and /accept-invite with an
invalid token, and requests an unknown route. The resulting 4xx responses and
error states were captured to document the UI, and are listed in the report
under "expected outcomes from deliberate probes". No account was created on
production and no data was written.