32 "decision": "Pre-create brands (single: { brand: { name } }; bulk: POST /stores/v3/bulk/brands/create { brands: [{ name }], returnEntity }), crosswalk the server-assigned ids, then assign products by brand.id. Verified live 2026-08-16 including the bulk path, product assignment by id, and DELETE /stores/v3/brands/{id}. Query with POST /stores/v3/brands/query."
33 },
34 "fallbacks": [
35 {
36 "classification": "cms",
37 "when": "Use only for source brand metadata beyond the name (logo, description, archive copy) — the Wix Brand object carries a name only."
38 }
39 ],
40 "reliability": {
41 "status": "reliable",
42 "flags": []
43 },
44 "pitfalls": [
45 {
46 "code": "name-only-object",
47 "severity": "warning",
48 "summary": "The Wix Brand object is {id, name, revision, dates} only; source brand logos and descriptions have no native home and are dropped unless preserved via the CMS fallback. Record the loss in the faithfulness ledger."
49 },
50 {
51 "code": "unique-name-double-create",
52 "severity": "warning",
53 "summary": "VERIFIED LIVE 2026-08-16: brand name is unique — a second create with the same name returns 409 ALREADY_EXISTS (uniqueConstraintViolation on name). Retries and resumed runs must be crosswalk-guarded or query-first; the failure is per-brand for single creates and would fail that item inside a bulk batch."
58 "summary": "RESOLVED 2026-08-16 (live, n=1): passing product.brand = { name } for a brand name that ALREADY EXISTS does not 409 and does not duplicate — the product came back bound to the existing brand's id. So inline-by-name and pre-create can coexist without write failures. Pre-create by id is still the preferred path because it is the only one that gives the crosswalk a deterministic id at write time and it survives name normalisation differences (case/whitespace variants were not probed)."
59 },
60 {
61 "code": "bulk-results-are-per-item",
62 "severity": "warning",
63 "summary": "POST /stores/v3/bulk/brands/create returns results[] with itemMetadata.{id, originalIndex, success} plus bulkActionMetadata.{totalSuccesses, totalFailures, undetailedFailures} — the usual Stores bulk contract. Correlate by originalIndex, never by position, and never infer success from the HTTP 200. returnEntity:true additionally returns the brand object; itemMetadata.id alone is enough for a crosswalk."
64 }
65 ],
66 "mappingGuidance": [
67 "Pre-create brands via POST /stores/v3/bulk/brands/create, record the server-assigned IDs in the crosswalk, then assign products by brand.id — never by brand.name — so the crosswalk stays deterministic.",
68 "If a run does use inline product.brand.name, do not also pre-create the same names in the same run: pick one path per run and let the crosswalk adopt the id the product create returns.",
69 "Source brand-archive URLs have no Wix equivalent; record each in the URL-preservation map with a redirect decision (category/search target or drop)."
102 "note": "subset run 2026-08-12: brand created via inline product.brand.name (adopted into crosswalk, via=inline-product-create); the preferred bulk pre-create endpoint was NOT exercised in that run"
103 },
104 {
105 "type": "live-run",
106 "path": "migrations/probe-run-20260812/config/wix.env (target site 00000000-0000-0000-0000-000000000000)",
107 "note": "KB verification probe 2026-08-16 (a docs-only flag), safe mode on / site muted: POST /stores/v3/brands → 200 (aef22bd2…); POST /stores/v3/bulk/brands/create with 2 brands → 200, totalSuccesses 2 with per-item ids; probe product created with brand:{id} → bound correctly; second probe product with brand:{name:<existing>} → bound to the SAME existing brand id (no duplicate, no 409); duplicate single create → 409 ALREADY_EXISTS; brands query by $startsWith read all three back; both products and all three brands deleted, query empty afterwards"
108 }
109 ],
110 "notes": "Authored 2026-08-11 from the docs sweep (Brands V3 gap verdict). Corrects the finding #6 working note that Wix has no standalone brand entity: Brands V3 has full CRUD + bulk create, and the product object references brands by id (or auto-creates by name). Promoted to verified-live 2026-08-16 — the pre-create path flagged docs-only earlier (single + bulk) was exercised end to end against a probe product, and the inline-dedupe question raised by the 2026-08-12 subset run is answered: inline by-name binds to an existing brand rather than failing."