# New knowledge base

Things learned while building Baskit Phase 1.

## Live MVP buckets ≠ design aisle labels
`mvp_catalogue.bucket` uses pipeline slugs (`fresh_produce`, `dairy_bakery_chilled`, `household_cleaning`, `staples`, `pantry`, `premium`, `basket_builders`). Map them in the API (`aisle_meta`) rather than hard-coding UI aisle lists.

## Catalogue image join
Prefer a correlated subquery on `catalogue.barcode_norm = mvp_catalogue.barcode` for `image_url`. Many MVP rows have no single “canonical” image; first non-empty retailer image is fine for Phase 1.

## Flutter must not open MySQL
Mobile binaries get reverse-engineered. Even for an internal beta, put PHP (later CI4) in front. Cleartext HTTP is OK only for local WAMP; enable `android:usesCleartextTraffic` for emulators.

## Android emulator localhost
Use `http://10.0.2.2/...` not `localhost` when the API runs on the host machine.

## Scope vs schema gap
Phase 1 build scope (`docs/ui/uploads/Baskit_Phase1_Build_Scope.html`) assumes accounts, baskets, orders, ledger. Dokploy today only has `catalogue` + `mvp_catalogue`. Anything beyond browse must be local/stubbed until that schema exists.

## Returns live in Ops, not the catalogue API
Customer return requests (photo + reason) are stored in Baskit Ops PostgreSQL (`returns` table), exposed at `/api/v1/returns`. Soft-link by `order_code` until Flutter orders sync to Ops. App auth uses the same `X-App-Key` pattern as analytics (`APP_ANALYTICS_KEY`). Money movement stays on the existing `refunds` / wallet path — approve in the Returns inbox does not auto-credit.

## image_picker multipart tip
Send return photos as `MultipartFile.fromBytes` with an explicit `MediaType` (`image/jpeg` or `image/png`). Path-based uploads break on web, and Ops validates MIME + 5 MB like picker receipts.
