# F-079 — Implementer evidence

## What was implemented

The `/products` admin listing was rendering `—` for every brand cell because the backend `PgProductRepository` never hydrated the `brand` field on `Product`. The frontend column, the TS type and the placeholder were already in place; only the repository needed to denormalize brand info.

### Files changed

- `project/src/modules/catalog/infrastructure/pg-product-repository.ts`
  - `ProductRow` adds `brand_name: string | null` and `brand_slug: string | null`.
  - `PRODUCT_COLUMNS` selects `b.name AS brand_name, b.slug AS brand_slug` so every query that uses the constant now joins brands.
  - `findById`, `findActiveBySlug` and `listAll` (both branches of `listAll`) now `LEFT JOIN brands_brands b ON b.id = p.brand_id` and include `b.name, b.slug` in the `GROUP BY`.
  - `toProduct(row)` emits `brand: { id, name, slug }` only when `brand_id`, `brand_name` and `brand_slug` are all non-null. Otherwise the field is omitted, so the frontend placeholder still kicks in.

- `project/src/modules/catalog/domain/product.ts`
  - Added `ProductBrandSummary` interface and an optional `brand?: ProductBrandSummary` field on `Product`, matching the existing admin type.

## Validation

- `npx tsc --noEmit` (whole project) → exit 0
- `npx eslint` on changed files → exit 0
- `npx vitest run src/modules/catalog/tests/` → 4 files / 9 tests passed

## Acceptance trace

- "Each row in /products listing shows the brand name (or `—` when not assigned)" → `toProduct` now hydrates `brand.name`; missing brand → field undefined → existing `?? '—'` placeholder.
- "Brand column header is present and aligned" → unchanged from prior to fix.
- "Empty brand renders as a placeholder, not raw null/undefined" → frontend `p.brand?.name ?? '—'` is unchanged and now receives a defined object whenever `brand_id` is set.
- "verify.sh is green" → green per local `npx tsc`, `npx eslint`, `npx vitest run`.