Supplier Source Profile — Supplier C
A characterization of one synthetic supplier's data as it would arrive at the platform. Profile is synthetic; structural archetype only — no real catalogue file underlies it.
Status
Authored: 2026-05-18. Last updated: 2026-05-18 with v0 decisions tightened on the two commitments this archetype originally forced — a missing-column warning at ingest (not full schema-drift detection — v0 expects operator awareness when a supplier's file shape changes; the platform flags missing saved-mapping columns and otherwise leaves drift to operator re-mapping) and per-supplier missing-product handling as a mapping-config setting (two v0 modes: ignore-missing-rows, snapshot-diff; operator-confirm-per-push and grace-period both deferred post-v0). Both are captured in scope.md under Per-supplier mapping config: v0 capabilities. C's own missing-product mode defaults to snapshot-diff, with the known consequence that products absent from a delta push will be misclassified as inactive; the v0 resolution is to request a status column from the supplier rather than build per-push operator gating into the platform. Stage: v0 scoping. Synthetic. Modelled on the structural archetype of an Australian drum-and-percussion wholesale distributor running a mixed-exclusivity portfolio — AU-exclusive distribution on a handful of major drum, cymbal, and electronic-percussion brands, non-exclusive wholesale on stick, head, and small-percussion accessory brands that other AU distributors also carry. No real supplier file informs the contents of this profile; it captures the kind of supplier this archetype represents and the kinds of mess such a supplier produces.
This is the "degraded distributor" slot in the v0 supplier set described in scope.md, the third and final synthetic supplier in the v0 ingestion test surface alongside supplier-a-profile.md (rich-data) and supplier-b-profile.md (medium). The archetype was chosen to cover the Drums v0-priority facet category (otherwise unrepresented across A and B), to apply ingest-format pressure unlike either A's portal-CSV or B's human-formatted Excel (specifically: emailed attachments with per-push schema drift), and to introduce deliberate cross-supplier overlap at the accessory tier so that v0 actually exercises canonical identity resolution under collision — a path A and B both opt out of via AU-exclusive distribution.
Identity
- Synthetic ID: Supplier C.
- Role: Australian wholesale distributor of drum-and-percussion product. Mixed-exclusivity portfolio: AU-exclusive distributor for a small set of major drum, cymbal, and electronic-percussion brands; non-exclusive AU wholesaler for stick, head, and small-percussion accessory brands that are also stocked by other AU distributors.
- Catalogue size: approximately 8,000–20,000 stocked AU SKUs including variants. Larger SKU count than Supplier A despite a narrower category footprint, driven by accessory-tier multiplication (every stick model × tip type × wood; every head × size × type; every cymbal × diameter × weight).
Product coverage
- Acoustic drum kits and individual drums (snares, toms, kicks), drum hardware (stands, pedals, racks, thrones), cymbals across all roles (rides, crashes, hi-hats, splashes, effects), electronic drum kits and modules, drumsticks across all tip and wood variants, drumheads across sizes and types, hand percussion (congas, bongos, djembes, shakers, tambourines, frame drums), and a long tail of cases, bags, parts, and accessories.
- Brand mix: mixed-exclusivity, multi-brand. A small number of exclusive AU distribution arrangements on flagship drum, cymbal, and electronic-percussion conglomerate brands. A long tail of non-exclusive accessory-tier brands (sticks, heads, small percussion) where C is one of several AU wholesalers carrying the brand. Brand handling at the canonical layer is identical to Supplier A and B's pattern: each row's brand goes into the canonical brand field as a single string.
- v0-priority category coverage: Drums (exclusively — no other v0 supplier covers this category). Pedals & Effects, Print Music, and Electric Guitars are covered elsewhere across A and B; C completes the four-category v0 priority set.
- Overlap with other v0 suppliers: present at the accessory tier. Non-exclusive stick, head, and small-percussion brands carried by C may also appear in another AU distributor's catalogue. Whether any of those brands also sits at the tail of Supplier A's adjacent-audio portfolio is an A-side question; v0 test-data composition can ensure at least one overlapping MPN is loaded under two suppliers (C plus any other) to exercise the canonical identity-resolution path. This is the only v0 supplier where canonical identity must resolve across suppliers, not just within.
Source format
Emailed attachments. CSV and Excel, mixed inconsistently. No portal, no API. Pushes are at the distributor's discretion — sometimes monthly, sometimes after multi-month gaps, sometimes flurries when a new brand line launches.
The defining property is per-push schema drift:
- Column order changes between pushes — a price column moves earlier in the row because someone at the supplier wanted it easier to read.
- Column names rename without notice —
RRPbecomesRRP inc GSTbecomesRetail Priceover three successive pushes. - Columns appear and disappear between pushes — a new spec column shows up because someone decided to start exporting it; a column that was present last month is gone this month because the person running the export forgot it.
- Spec columns that do persist may be carried under different names in different brand sub-feeds within the same push.
- Mixed file formats — most pushes are CSV, some are
.xlsx, occasionally an.xlsfrom an older tool. File extension and contents may not match (a.csvthat's actually tab-separated; an.xlsxwith a single trivial sheet).
Refresh cadence: ad-hoc. No predictable schedule. New-product launches drive bursts; long quiet periods between. Price changes arrive whenever the supplier feels like it, often without flagging which rows changed.
No supplier-side push API at v0. Ingestion path is the per-supplier mapping config described in scope.md. The mapping editor at v0 provides a missing-column warning — if a saved mapping references a column absent from the new push, the ingest blocks and flags the operator. No diff/rename engine, no automated drift remediation. Operators handle real drift by hand-editing the saved mapping. Real schema-drift detection is deferred post-v0.
Field inventory
Field set is uneven and inconsistent across both rows and pushes. The shape that follows describes the typical state of a single push; per-push schema drift means the exact column set varies.
Reliably present:
- Product name — one column, free-form, frequently SKU-stuffed (
"VIC FIRTH 5A AMERICAN CLASSIC WOOD TIP HICKORY"). Carries brand, model, variant tokens, and option tokens concatenated, with no consistent separator convention. - Supplier SKU — the distributor's internal code. Loosely brand-prefixed but inconsistently formatted across brand sub-feeds.
- RRP — usually present, sometimes with currency symbol inline as a display artefact (carried over from the source spreadsheet's number formatting).
Intermittently present:
- MPN — present for major-brand items (drum kits, cymbals, electronic modules, hardware from the exclusive-distribution brands), absent for accessory-tier items (sticks, heads, small percussion). Identity discipline thus splits per row within the same supplier file.
- GTIN/barcode — present where MPN is present, absent where MPN is absent. Sparse on the accessory tail.
- Brand — sometimes a dedicated column, sometimes implicit from a SKU prefix, sometimes only recoverable by parsing it out of the product name string. Inconsistent across brand sub-feeds.
- Category — when present, single-level and coarse (
Drums,Cymbals,Sticks,Hardware,Percussion,Electronic). Cannot serve as the canonical category directly. - Image URL — present for roughly 30–50% of catalogue. Hero items (kits, flagship cymbals, electronic modules) reliably have images; the accessory tail is largely image-less. Where present, frequently thumbnail-resolution.
- Short description / blurb — sparse. Hero items and new releases only.
- Specs — scattered, drifting, and tier-dependent. Shell material, bearing edge, head diameter, weight, ply count, cymbal weight, stick length, stick diameter, head ply, head film thickness, etc. each appear as their own column when populated, under different column names across brand sub-feeds and across pushes.
Notably absent:
- Lifecycle / status column. No status field at all. Discontinued products simply stop appearing in the next push (see Mess profile).
- Wholesale cost. Same structural absence as Supplier A and B — AU wholesale cost is per-retailer trade-discount terms applied to RRP, not a property of the file. v0 carries cost as a single canonical field per the
scope.mddecision, withnullor supplier-mapping-derived defaults for this supplier. - Variant grouping. No field links variants of the same underlying product. Each size, finish, and configuration is its own row, with no grouping signal. Same shape as Supplier B's variant-absent case rather than Supplier A's variant-present-but-disagreeing case.
- Marketing highlights. Not a convention for this archetype.
- Dimensions / weight. Intermittent and tier-dependent — populated for heavy items like full kits and hardware racks where freight matters, sparse or absent on cymbals, sticks, heads, and small percussion.
Identifiers
- Mixed identity discipline within the supplier. MPN-anchored on major-brand items; supplier-SKU-fallback on accessory-tier items where MPN is absent. The per-supplier identity-resolution path must switch per-row based on availability, not per-supplier as a single choice.
- Supplier-SKU consistency within the supplier. The distributor's internal SKU is intended to be unique within the supplier. In practice, SKU reuse occurs occasionally — when a discontinued product's SKU value gets reassigned to a new product and the catalogue is mid-transition, both rows can appear briefly in the same push. The per-supplier mapping must detect and flag this rather than silently overwriting.
- GTIN/ISBN/ISMN absent for accessories. No fallback path beyond supplier-SKU on the accessory tail.
- Cross-supplier identity collision at the canonical layer. Because C is non-exclusive on accessory-tier brands, the same MPN may arrive via C and via another supplier's catalogue. The canonical layer's MPN-anchored identity must collapse these into a single canonical record while preserving per-field provenance (which supplier's value populated which canonical field). This is the v0 test case for canonical identity resolution under collision; it does not arise from A or B alone.
Mess profile
This is the load-bearing section. Each item is a specific mess the canonical model or the ingestion mapping must absorb.
- Per-push schema drift. Column order, column names, and the set of populated columns change between successive pushes from the same supplier. The mapping editor at v0 provides a missing-column warning when a saved mapping references a column absent from the new push; the operator re-edits the saved mapping by hand to absorb the change. Full schema-diff detection (rename surfacing, automated remediation, preserved confirmations) is deferred post-v0 — at v0, with Tyler as the only operator, hand-editing the saved mapping is acceptable. The archetype's drift is a real source of mapping-editor maintenance load but doesn't force first-class diff tooling into v0.
- No lifecycle signal — discontinued rows vanish. Source emits no status column. EOL products simply stop appearing in the next push. The canonical layer's binary
active/inactivefield (perscope.md) is driven by the per-supplier missing-product handling setting in the mapping config (v0-scope captures the two available modes). For C, the configured mode is snapshot-diff, with the known consequence that any push that's actually a delta will mark its non-included previously-seen products asinactiveuntil they reappear. The v0 resolution is to escalate this to the supplier as a data-quality issue — request a status column rather than build per-push operator gating into v0. Operator-confirm-per-push is deferred post-v0; reintroduce only if the supplier-conversation route fails. - SKU-stuffed product name strings. Names carry brand, model, variant, and option tokens concatenated as free-form text (
"VIC FIRTH 5A AMERICAN CLASSIC WOOD TIP HICKORY","REMO AMBASSADOR COATED 14 INCH", etc.). Brand may or may not also be present in a brand column; variant axes are not separable without per-brand parsing rules in the ingest mapping. Different shape from Supplier A'sModel Name, Opt1, Opt2positional convention — less disciplined, no separator structure, brand-and-variant intermixed. The canonical name field stores a clean canonical name; per-supplier mapping does the extraction. - Mixed identifier discipline within one push. MPN present on major-brand rows, absent on accessory-tier rows. Per-row identity resolution must switch between MPN-anchored and supplier-SKU-fallback paths within the same ingest, not as a per-supplier configuration choice. Exercises both identity paths in one supplier.
- Cross-supplier identity collision on accessory tier. Non-exclusive stick, head, and small-percussion brands generate canonical identity collisions whenever the same MPN appears via C and via any other supplier in the v0 load. The canonical layer must collapse to one canonical record and retain per-field provenance — without duplicating canonical records, and without silently overwriting one supplier's value with another's. First v0 supplier where this path is exercised at all.
- Specs scattered across drifting column names. Where specs are populated, the column names carrying them drift between pushes and differ across brand sub-feeds within the same push (
Shell→Shell Material→Material). The per-supplier mapping mechanism that absorbs schema drift handles this too — not a new canonical concern, but does increase mapping-editor maintenance load. - Sparse, thumbnail-grade image coverage. Roughly half the catalogue carries no image URL at all; what's present is often thumbnail-resolution. The v0 image-URL pass-through policy (per
scope.md) accommodates this structurally — the mess is degraded coverage rather than a new architectural concern. Retailer-output consequence: retailers using exports for new-product onboarding will have to source images out-of-band for many accessory-tier rows. - Supplier-SKU reuse within a push. Discontinued SKU values occasionally get reassigned to new products mid-transition; both rows may appear in the same push. Per-supplier mapping must detect collisions on supplier-SKU within a push and flag rather than silently overwrite. Cheap to resolve once recognised as a mode.
What this synthetic supplier stress-tests, and the v0 decisions it forces or exercises
This profile stresses five concerns. Some force new v0 decisions; others exercise paths already named for A and B but not previously exercised at all.
-
Missing-column warning at ingest (captured at v0-scope). Per-push schema drift means the mapping editor needs at least some awareness that a saved mapping has become stale against the incoming file. v0 commits only to the minimum useful version: if a saved mapping references a column absent from the new push, the ingest blocks and flags the operator. No diff/rename engine, no automated remediation, no UI for confirming drift. Real schema-drift detection is deferred post-v0; at v0 with Tyler as the only operator, hand-editing the saved mapping when drift occurs is acceptable. Captured in
scope.mdunder Per-supplier mapping config: v0 capabilities. -
Missing-product handling without a source status column (captured at v0-scope). No status field in the source means the canonical
active/inactivefield cannot be set from a column. v0-scope captures the resolution: a per-supplier missing-product handling setting in the mapping config, with two v0 modes (ignore-missing-rows, snapshot-diff). C defaults to snapshot-diff, with the known consequence that any push that's actually a delta will misclassify its non-included previously-seen products asinactive. v0 treats this as a supplier data-quality issue: the resolution is to request a status column from the supplier, not to build per-push operator gating into the platform. Operator-confirm-per-push and grace-period are both deferred post-v0; reintroduce only if the supplier-conversation route fails. -
Canonical identity resolution under cross-supplier collision (exercises canonical-model intent, previously untested). The canonical layer's MPN-anchored identity must collapse rows carrying the same MPN from different suppliers into a single canonical record, preserving per-field provenance. Neither A nor B exercises this — both are AU-exclusive. C is the only v0 supplier that does, and only on its non-exclusive accessory tier. v0 test-data composition will need to include at least one accessory MPN loaded under both C and another supplier to exercise the path. Implementation-level concern, but the v0 test surface depends on it. The canonical-model design intent is that this collapse is structural and policy-driven (e.g., field-level "preferred supplier wins" rules), not a per-collision manual reconciliation.
-
Mixed identity-resolution path within a single supplier (exercises existing decision). MPN-anchored and supplier-SKU-fallback paths both fire within a single push from this supplier, switched per row. Confirms that v0's identity-resolution implementation must support per-row path selection, not just per-supplier configuration. The existing
scope.mdtreatment of identity is consistent with this; this profile makes the per-row case concrete. -
SKU-stuffed name parsing (exercises Supplier A's per-supplier mapping pattern, in a messier form). Different shape from A's
Model Name, Opt1, Opt2positional convention — no separator structure, brand and variant intermixed in free-form text. Same per-supplier mapping mechanism applies: declare per-brand parsing rules that extract canonical name, brand, and variant tokens. Canonical layer never sees the raw stuffed string. Increases per-supplier mapping-config authoring effort; no new canonical-model concern.
If the layered canonical + transformation model and the per-supplier mapping editor can absorb these cleanly under the v0 decisions above, the thesis in ../decisions/0001-layered-canonical-model.md holds against the degraded end of the supplier range and across cross-supplier identity collision — closing the v0 supplier-set test surface.
Both decisions are now captured at v0-scope rather than buried in this supplier profile.
Update behaviour
- Ad-hoc cadence, no schedule. Pushes arrive when the supplier feels like sending them — sometimes monthly, sometimes after multi-month gaps. New-product launches drive bursts; long quiet periods between.
- Pushes are not consistently snapshot or delta. Some pushes are intended as full catalogue refreshes; others are addendums covering only a new brand line or a small set of new releases. There is no flag in the file or accompanying email indicating which kind of push it is. Under the v0 missing-product handling resolution, C runs on snapshot-diff with the known consequence that any delta push will misclassify its non-included previously-seen products as
inactive. v0 does not solve this in the platform — the response is to request a status column from the supplier. - Discontinued lines vanish from next refresh. No status column; the per-supplier missing-product handling setting (see Mess profile and
scope.md) drives canonical-layer behaviour. - Price changes are erratic and unflagged. RRP revisions arrive whenever the supplier touches the file, often without flagging which rows changed. The canonical layer's price field updates whenever a row's price changes between pushes; no source-side change indication is available.
- Schema drifts every few pushes. The mapping editor must accommodate this without forcing re-mapping from scratch.
- Brand additions and removals. The supplier occasionally takes on a new accessory-tier brand or drops one. Adding a brand is typically signalled only by new rows appearing in the next push; dropping a brand is signalled only by all of its rows disappearing. The mapping editor's per-supplier mapping config absorbs additions transparently (rows just flow through existing mappings if the schema is recognised, or surface as schema drift if it isn't); drops are caught by the configured missing-product handling mode.
Open questions
- v0 test-data composition for cross-supplier identity collision. v0 needs at least one overlapping accessory MPN loaded under both C and another supplier to exercise the canonical identity-resolution path. Practical question of test-data composition rather than a design decision, but worth noting as a v0 prerequisite — without it, the cross-supplier collision path is untested.
- Per-supplier mapping behaviour on within-push supplier-SKU collisions. Flag-and-block, flag-and-warn-but-load, or load-both-and-let-the-canonical-layer-resolve? Cheap to resolve once the mode is recognised.
- Per-brand name-parsing rules. SKU-stuffed product names need per-brand parsing rules to extract canonical name, brand, and variant. Maintenance effort scales with brand count. Whether v0 ships with parsing rules for all carried brands, only the major brands, or a "best-effort fall-through" default for unknown brands is a v0 scope question for the per-supplier mapping editor.
(The schema-drift detection, missing-product handling, and snapshot-vs-delta interpretation questions originally listed here were resolved on 2026-05-18 and captured in scope.md — see the Status section above and Per-supplier mapping config: v0 capabilities in v0-scope.)