Wiki · Workflow companion

New ingredient / vendor onboard

A first PO or new vendor add. Cascade: NS vendor record, D1 vendors + vendor_items, baseline vendor_costs entries, sourcing alternative analysis for items that could use this vendor, and AP terms setup.

Stub · Contract present, runner stub-only
What this is

New ingredient / vendor onboard

New vendor onboarding is the lighter sibling of new_customer. The cascade covers vendor master data, baseline vendor_costs for initial items, NS vendor record, and a sourcing analysis pass that surfaces existing items the new vendor could supply (often the reason for the onboard in the first place).

Critical block: the no-duplicate precondition. Duplicate vendors are even worse than duplicate customers — they fragment cost history and break weighted-average computations.

Risk level 3 (medium).

When to use it

Trigger conditions

Heuristic

Vendor duplicate check uses name OR email — same logic as new_customer. A common pattern: subsidiary of an existing parent vendor. Mike confirms with the buyer before overriding.

Step-by-step what happens

The 2 beats

  1. 01

    Write vendor + vendor_items

    INSERT into vendors for the new entity. Batch INSERT into vendor_items for the initial item mappings (vendor_item_code → internal item).

    Writes vendors, vendor_items
    Time ~150ms
    Kind d1_write
    Status stub
  2. 02

    NS vendor record

    Enqueue NS vendor creation via customscript_gfs_platform_query RESTlet. NS internal id back-fills on drain.

    Writes NetSuite vendor record
    Time ~3–8s
    Kind ns_push
    Status stub
    Note retry · 3 attempts exponential
Outcomes

What's different after the workflow runs

Vendor
Created
D1 + NS
Initial items
Linked
vendor_items batch
Duplicate guard
Blocked
name OR email
AP setup
Initialized
terms + tax_id
Failure modes

What can go wrong and how to recover

Duplicate vendor found

Precondition blocks. Mike confirms: is this a subsidiary? If yes, override + tag. Often the right answer is to use the parent vendor record and add this as a new vendor_items mapping.

No initial items provided

Vendor is created but vendor_items is empty. The first PO will need to link items manually. Often happens for service vendors.

NS vendor push fails

Retry policy is 3 exponential attempts. Drainer recovers within 15 minutes.

Vendor also overlaps as customer

Per the R115 brain dump, several entities are both (Bongards, Echo Lake Foods). The customer + vendor records exist separately; they don't conflict.

Related

Adjacent workflows + diagrams

For developers

Code paths + invariants

ConcernWhere
Workflow contractworkflow_definitions WHERE workflow_type='new_ingredient_vendor_onboard'
Duplicate checkname (lower) OR email (lower)
Customer-vendor overlapsee feedback_customer_vendor_overlap memory
NS RESTletcustomscript_gfs_platform_query
Reflexion tagnew_vendor
Risk level3
Expected duration~30 min
Triggermanual · sources=vendor_intake_form
// Same dup-check shape as new_customer const dup = await db.prepare( "SELECT id, companyname FROM vendors " + "WHERE LOWER(companyname) = LOWER(?) OR LOWER(email) = LOWER(?)" ).bind(name, email).first(); if (dup) throw new Error('duplicate_vendor');
Changelog

Dated trail · spot stale claims

Dated trail of when this doc was last touched, what changed, and what to look at if it feels stale.

DateRoundChangeTouched by
2026-05-26R586Added CHANGELOG · SCHEMA · RUNBOOK · BACKLOG sections — wiki became best-in-class operating documentation.Mike + Claude
2026-05-25R584/R585Wiki originally shipped — 8-section structure (hero / what / when / steps / outcomes / failure-modes / related / for-developers).Mike + Claude
If today is more than 60 days past the latest changelog row, treat live system behavior as the source of truth. The doc may have drifted — verify against the workflow contract in workflow_definitions WHERE workflow_type='new_ingredient_vendor_onboard' before acting on these claims.
Schema · data contract

The machine-readable spec

Canonical fields, table names, endpoint signatures. What code should match, what tests should assert. workflow_type · new_ingredient_vendor_onboard · risk_level · 3.

Inputs (required + optional)

FieldTypeDescription
vendor_namestringLegal name. Required.
contact_emailstringPrimary contact.
categorystring'protein' | 'grain' | 'produce' | 'dairy' | 'other'
certificationsjson?Array of cert names + expiry.
initial_itemsjson?Items the vendor will supply.

D1 tables written

TableOperationTrigger
proposed_actionsINSERTVendor creation proposal
vendorsINSERT (post-HITL)D1 mirror
vendor_certificationsINSERTPer-cert rows
ns_pending_pushesINSERTNS vendor creation

Endpoints called

MethodPathPurpose
POST/api/workflow/executeRunner entrypoint
POST/api/proposed-actions/:id/decideHITL approval

Events fired

event_typeWhenSubscribers
vendor.onboardedPost-HITL + NS pushcompliance + AP setup
Runbook · when it breaks

It broke at 2am — what now

Different from "how do I use this." This is the page Mike pulls up when something is wrong: logs to check, recovery steps, who to escalate to.

Scenario · Vendor onboarded but no certifications recorded

vendor_certifications writes are conditional on input.

  1. Add manually: INSERT INTO vendor_certifications (vendor_id, cert_name, expires_at) VALUES (...)
  2. Reminder: Set a calendar reminder for cert expiry.

Scenario · Vendor created in NS but not in D1

NS push went through but the post-NS d1_write didn't reflect.

  1. Force sync: POST /api/sync/run?tier=hot&table=vendors
  2. Verify ID linkage: SELECT id, ns_internal_id FROM vendors WHERE name LIKE '%<name>%'

Scenario · Certification expiry not surfacing

No reminder workflow today.

  1. Manual check: SELECT vendor_id, cert_name, expires_at FROM vendor_certifications WHERE expires_at < date('now','+60 days')
  2. Reach out: Email vendor to refresh cert.

Logs to check

Kill switch · emergency stop

If this workflow is misbehaving in a high-impact way (creating bad proposed_actions in volume, pushing wrong things to NS), flip a kill switch:

See kill-switches-state-machine.html for the full state machine + recovery procedure.

Escalation

Primary: Mike Levine (single-admin) · mikelevine@globalfoodsolutions.co. For prolonged outage during business hours, notify warehouse lead + accounting lead so they can defer dependent work.

Backlog · open questions

What's not done · what's uncertain

What's not done, what's uncertain, what we punted. Captured so it survives context switches and doesn't die in someone's head.