Appearance
Product & Vendor Management (PVM)
PVM — Product & Vendor Management
Status: deployed (supplier layer, product metadata, taxonomy CRUD/status, comments with presigned attachments + retention cleanup, kits, alternatives, supplementary links, status history, comment abuse reporting, and Brand). External docs/MCP are published (see /common/start-here.html for latest build). Contract-only; infra/alarms/internal storage are out of scope.
Surface map
- Expected base (API Gateway):
https://api.g3nretailstack.com/pvm(custom domain; clean URLs disabled). - Auth: USM session or service-account API key required on all routes. Org-scoped; non-associated callers receive
404 not-found(anti-enumeration). Owners full access. Members need roles: Product Model Administrator (all PVM mutations), Vendor Contract Administrator (supplier ops), Product and Vendor Viewer (read/comment-only). - Pagination: limit default 8, clamp 1–256;
next_tokenopaque JSON cursor. - MCP: protocol publishes to https://mcp.g3nretailstack.com/pvm/PROTOCOL.md (mirrored here at /pvm/PROTOCOL.md).
- OpenAPI:
https://doc.g3nretailstack.com/pvm/openapi.yaml - Role matrix: /common/role-matrix.html
- Troubleshooting (404): /common/troubleshooting.html
- Headers and identity cheat sheet: /common/headers-identity.html
Responses use { success, data?, error?, build, stats?, revision? } with build ID + UTC timestamp in the footer. Stateful record responses include revision. Any mutation that updates an existing revisioned record must include expected_revision; missing → expected-revision-required (HTTP 428), mismatch → conflict (HTTP 409) with the current record snapshot + current revision.
Lifecycles and rules (contract)
- Codes & aliases: codes
^[A-Z][A-Z0-9_-]{0,9}$, immutable. Up to 16 aliases per record{tag ≤24 [A-Za-z0-9_.-], value ≤96}, unique per org; edits while inactive. - Code generation (create): for create endpoints that accept
code, the request may omitcodeand instead providecode_pattern?(≤10 chars,A-Z 0-9 _ - ?,?= wildcard) plus optionalcode_max_attempts?(int 1–64). On exhaustion:code-generation-exhausted(HTTP 409). - Status model: active↔inactive; any → doomed (terminal). Edits only while inactive. Style doom blocked while non-doomed variants exist; variant doom blocked while outbound kit components/alternatives/supplementary links exist, and while active inbound links exist.
- Taxonomy: division/department/category/season are org-scoped. Category is a tree inside a department; parent must be in the same department. Enforced: acyclic, max depth 16. Dooming a division/department/category is blocked while it still has non-doomed children.
- Suppliers: style requires ≥1 vendor AND ≥1 manufacturer with primaries; required
category_id(must reference a non-doomed taxonomy category); optionalbrand_id. Ifbrand_idis set the brand must be linked to all referenced vendors/manufacturers. If a brand has supplier links and you want to setbrand.status=active, you must set primary vendor/manufacturer links first (POST /brand/link/set_primary). Supplier-scoped options must match style suppliers. - Org currency & FX (template econ): each org has an immutable
org_currency(stored internally by PVM).template_econ.currencyis required when monetary fields are set. Ifcurrency != org_currencythentemplate_econ.fxis required and must include{ org_currency, rate_to_org, as_of_utc }(andorg_currencymust match the org’s configured currency). - OGM (option matrix): revisioned, immutable per rev. Clone to edit; switch via
style/ogm/set.ogm.groups[]defines the required option group codes (with priority order). Variants carrymatrix_rev; stale whenmatrix_rev != style.ogm_rev. Ifogm.groups[]is empty, thenvariant/createrequires empty selections and signature is empty (so only one non-doomed variant can exist). - Variants: selections are resolved/validated against Option Group/Option records (by
group_code+option_code). Signature is built in OGM group order (GROUP=OPTION|...), unique among non-doomed variants per style (freed on doom).selections[].sizemay include{ waist, inseam, cup, width }(ignored for signature). Size values are stored as-provided (no unit conversion); interpretation is domain-specific. Edits inactive-only. - UOM dims: when provided,
base_uomis required;sell_uomdefaults toea;conversion_factordefaults to 1 whensell_uom==base_uom, otherwise required. Ifcontrol_typeisserial/both, thenserial_modeis required. - Identifiers/Aliases: uniqueness across non-doomed variants; transfer explicitly moves ownership with history and requires
reason+expected_revision. - Barcodes: digits-only, valid check digit,
(org, value)unique among non-doomed. Reuse only if prior value inactive/doomed ANDallow_reuse=true+reason(reason required when reassigning to a different variant); otherwise 409. One primary perpackaging_level.issued_by∈ {gs1, vendor, org, unknown}. - CLI: direct API Gateway commands under
g3n pvm ...(session + orgcode required). Genericpvm post/getcover any path. - Comments: immutable body; attachments ≤128 MB each (filename/content_type/size_bytes/caption). Status {current, archived, doomed}. Attachments are subject to retention cleanup (defaults: current 90d; archived 30d; doomed 7d).
GET /comment/reportreports the largest comments by attachment size (PMA/owner only; no backfill). - Kits/links: kit components (qty/uom). Alternatives (replacement-style) and supplementary (upsell/cross-sell/accessory/etc.) are variant→variant links with priority/time windows.
Quick start (current slice)
- Create OGM (optional empty):
POST /ogm→ogm_id/ogm_rev. - Create brand and link to suppliers:
POST /brandthenPOST /brand/link/addfor each vendor/manufacturer you plan to reference on a style. If you plan to activate the brand, set primaries first:POST /brand/link/set_primary(vendor + manufacturer). - Create style (inactive):
POST /stylewithcategory_id+ suppliers (vendor/manufacturer primaries; suppliers must be pre-created + verified) +ogm_id+ optionalbrand_id(must be linked to all suppliers when set). - Create variants:
POST /variantwith selections (must resolve to existing option groups/options and match OGMgroups[]when present; optional structured size fields on selections); identifiers/aliases optional; signature uniqueness enforced per style. - Set primaries:
POST /barcode/addthen/barcode/set_primary; add identifiers/aliases as needed. - Switch OGM rev:
POST /style/ogm/setmarks variants stale; list stale via/variant/stale/list; recreate variants on new rev via/variant/recreate. - Comments/kits/links are available:
POST /comment+GET /comment/list+GET /comment/report, kit components under/kit/component/*, and link management under/alternative/*and/supplementary/*.
Clarifications (B5)
- Supplier list capping: styles cap supplier links at 128 vendors and 128 manufacturers. When the cap is exceeded, the oldest non-primary entries are evicted (primary is preserved when present).
- OGM revisions: OGM is immutable; edits require clone →
style/ogm/set; variants become stale whenmatrix_revchanges. - Barcodes: check-digit validation enforced; one primary per packaging level; reuse requires explicit
allow_reuse+ reason. - Comments: PVM comments are immutable (create-only) until the shared comment model is adopted.