spec(SD-0002 §2): solution proposal — canonical CSV, Shopify dialect, upsert + preview-confirm
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -226,7 +226,79 @@ Scenario: BUC-4 — The catalog leaves whole, on demand
|
|||||||
|
|
||||||
## 2. Solution Proposal
|
## 2. Solution Proposal
|
||||||
|
|
||||||
*(not yet authored — next in the section-at-a-time loop)*
|
**Build software:** CSV file import/export in the storefront admin — a new
|
||||||
|
**Products** surface where a merchant uploads a CSV to add and update products
|
||||||
|
in bulk, and downloads a CSV of the full catalog at any time.
|
||||||
|
|
||||||
|
**The shape of it:**
|
||||||
|
|
||||||
|
- **One canonical CSV format**, Shopify-flavored: one row per variant,
|
||||||
|
consecutive rows sharing a `Handle` form one product (with its options,
|
||||||
|
variants, and images). The column set is a deliberate superset of Shopify's
|
||||||
|
product CSV — adding component columns (the kits seam, #15), volume,
|
||||||
|
cost/tax fields — so a Shopify export is structurally familiar and our
|
||||||
|
format never needs to churn when siblings arrive. The full column
|
||||||
|
specification is §6.
|
||||||
|
- **Two accepted dialects, auto-detected:** the canonical format, and
|
||||||
|
Shopify's own product-CSV export (mapped onto canonical at the boundary).
|
||||||
|
The header row identifies the dialect; the merchant never picks from a
|
||||||
|
menu. This is the migrating merchant's path (BUC-1): their existing export
|
||||||
|
imports directly.
|
||||||
|
- **Import is upsert-only.** A row whose `Handle` is new creates a product; a
|
||||||
|
known `Handle` updates it (variants matched by option-value combination).
|
||||||
|
Nothing is ever deleted by an import — the mechanism is non-destructive by
|
||||||
|
construction, so a partial file can never silently destroy catalog
|
||||||
|
(BUC-2's safety, structurally).
|
||||||
|
- **Validate-all → preview → confirm.** The whole file is validated and
|
||||||
|
diffed against the catalog before anything is written. The merchant sees a
|
||||||
|
summary — N products to add, M to update, K rows in error — and can drill
|
||||||
|
into any record to see exactly which fields will change and to what.
|
||||||
|
Nothing applies until they confirm; confirming applies the valid records
|
||||||
|
and leaves the error rows listed, unapplied, and actionable (BUC-1a,
|
||||||
|
BUC-2). Unrecognized columns are warned about in the preview and ignored,
|
||||||
|
never silently dropped.
|
||||||
|
- **Synchronous, with a stated capacity** of ~5,000 rows per file. No job
|
||||||
|
queue in the MVP; the design names the async seam for when catalogs
|
||||||
|
outgrow it (§6.9). One deliberate exception rides that seam's first rail:
|
||||||
|
**images**.
|
||||||
|
- **Images are fetched and hosted.** `Image Src` URLs are downloaded into
|
||||||
|
platform object storage after the catalog rows commit, with renditions
|
||||||
|
(thumbnail / card / detail) generated at fetch. Images that can't be
|
||||||
|
fetched, aren't images, or fall below the resolution bar are **rejected**
|
||||||
|
(the product shows a placeholder), with the outcome reported per image.
|
||||||
|
The catalog is self-contained: exports reference our hosted copies, and
|
||||||
|
the storefront never depends on a third-party host staying alive.
|
||||||
|
- **Imports are first-class records.** Every import run is kept — file name,
|
||||||
|
dialect detected, who ran it, add/update/error counts, image-fetch
|
||||||
|
outcomes — with a detail view the merchant can leave and return to
|
||||||
|
(the post-commit image phase reports there and on the Products page).
|
||||||
|
- **Export is one gesture:** the complete catalog (optionally filtered by
|
||||||
|
status) as a canonical CSV. Export → re-import is lossless and idempotent —
|
||||||
|
the acceptance bar from #13 and BUC-4's round-trip guarantee.
|
||||||
|
|
||||||
|
**Why this approach.** CSV is the medium merchant catalogs already live in:
|
||||||
|
every platform exports it, every spreadsheet tool speaks it, and the
|
||||||
|
migrating merchant (the sharpest pain, PP-2) holds one today. Accepting
|
||||||
|
Shopify's dialect directly converts the largest migration population's
|
||||||
|
existing artifact into a working catalog with zero transformation effort.
|
||||||
|
Upsert-only plus preview-confirm makes a powerful bulk mechanism safe to hand
|
||||||
|
to a non-technical merchant: the destructive operations simply don't exist,
|
||||||
|
and every change is consented to with full knowledge (OHM: consent & agency).
|
||||||
|
|
||||||
|
**Alternatives weighed** (detail in §6.7): a per-item editing UI first
|
||||||
|
(rejected — Epic #12's explicit boundary, and it does nothing for migration);
|
||||||
|
integration APIs / direct platform connectors (rejected — heavy, narrow, and
|
||||||
|
premature before the catalog model exists); accepting spreadsheet formats
|
||||||
|
(XLSX) (rejected for MVP — CSV covers the actual artifacts merchants hold;
|
||||||
|
XLSX is an adapter behind the same boundary later); do-nothing / concierge
|
||||||
|
data entry by the operator (rejected — doesn't scale past a demo and builds
|
||||||
|
no product capability).
|
||||||
|
|
||||||
|
**Solution-specific non-goals:** no deletion semantics of any kind in the
|
||||||
|
CSV; no scheduled/automated re-import; no foreign dialects beyond Shopify's
|
||||||
|
product CSV in the MVP; no kit *semantics* (the format carries the columns;
|
||||||
|
#15 defines their meaning); no image editing/cropping — the platform hosts
|
||||||
|
what the merchant's URLs provide, or rejects it.
|
||||||
|
|
||||||
## 3. Product Personas
|
## 3. Product Personas
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user