My earlier design (docs/temporal_workflow_design.md, local_website_plan.md) modelled a Commercial Lead approval gate inside the New-SKU workflow — a person who logs in and clicks approve. The 2026-06-12 meeting says that's wrong. Commercial approval happens offline, in the commercial team's own process; the merchant team obtains it and attaches the approval record; the Data Team verifies that attachment as part of its single review. There is no commercial login, no commercial signal, no commercial timer in the workflow.
And on what "Standard vs Customized" even means — the commercial team's role is upstream and external:
| STD vs CUS gives the same single Data-Team approval | Where commercial approval lives |
|---|---|
| STD (standard): commercial pre-approves a development list offline → NPD/PM batch-upload those specs via the STD template. | Outside the tool. Captured as an uploaded approval link/record on the submission. The Data Team's single review includes a checklist item: "commercial approval attached?" — not a separate workflow stage. |
| CUS (customized): CUS PM / M&O / Sales / SP submit a customization request (based on a standard spec); commercial sign-off obtained offline and attached. |
Net effect on the workflows: I've deleted the commercial_lead_decision signal and the upstream CL branch entirely. There is exactly one approval stage — the Data Team — for every flow, which is what Emily confirmed in the questionnaire (Part B Q1–3). The STD/CUS distinction only changes how the request arrives and what must be attached, not who approves in the tool.
Three buckets. Only the first bucket fires workflow signals.
| Role | What they do in the tool | Signals they fire |
|---|---|---|
| PM / NPD PM | Submit STD new-product specs (batch via STD template, or single); provide initial product info. Data Team then completes the record. | submit_new (STD), batch upload |
| Merchandising (M&O) | Submit customized SKU-SPEC requests (e.g. new case-pack from STD 111-S001); request edits / retirement. | submit_new (CUS), submit_edit, submit_retire |
| CUS PM / Sales / SP | Submit customer-specific (CUS) spec requests, based on a standard spec. | submit_new (CUS) |
| Factory (incl. outsourced) | Fill final mass-production dimensions (inner/outer/master shipper, pallet, weights, case pack). Picks the SKU — cannot free-type. Submits own dimension edits. | factory_dimensions_submitted, submit_edit (own dims) |
| Data Team the engine room | The single approval stage. Review → approve / reject-with-reason / edit-and-approve. Creates & completes the master spec (assigns SKU# / SKU-SPEC#). Runs cascade-with-exclude. Decides retire path + overrides guards. Triggers / confirms SAP sync. Manages dropdowns & promotes suggested option values. | review_decision, spec_set, cascade_confirmed, retire_decision, guard_override, sap_sync_requested |
| Role | Why they're in the tool |
|---|---|
| Designer / Ecommerce | Reads SKU# + barcode to produce packaging artwork (AW); supplies images / renderings. Emily corrected my earlier draft: the Designer does NOT set codes. No signal. |
| Sales / Lending | Read-only consumers of approved specs. (Note: Sales/SP also appear as CUS submitters in the June-12 flow — flagged as a question in §7.) |
| Party | Reality | Tool involvement |
|---|---|---|
| Commercial Team / Commercial Lead (incl. Toys Commercial) | Approves the STD development list (Toys July/December sets) and customizations in their own offline process. | None. Approval is uploaded as a record/link and verified by the Data Team. No login, no signal, no timer. |
| Legal / Licensing | Signs licensor contracts; with Commercial, defines committed / permitted markets. | None today. Data Team records permitted markets manually (future: link licensor ID from SAP). |
| SAP | Downstream system of record for material numbers. | Integration only (an activity, not a human) — returns the Material No. Website stays the source of truth. |
The website is great at a single click: submit a form, edit a cell, approve a record. It is bad at the thing in between — a spec that is born from a request, waits on the Data Team, waits on a Factory in another timezone, gets rejected and resubmitted, then finally syncs to SAP — over days, touched by several people, where any step can stall.
Temporal is the tool for exactly that. Each flow becomes one durable workflow that:
The website starts a workflow and signals it (every approve/reject/submit click is a signal). The workflow calls back into the website's API and SAP via activities. The permission matrix still decides who may fire which signal — Temporal sequences already-authorized actions, it doesn't replace login/authz.
This is the most important table for the build: it is the interface all three layers agree on. The clickable demo simulates exactly these signals. Pin this early and the data/Temporal/UI layers can be built against it independently.
| Signal | Fired by | From which page | Carries | Effect |
|---|---|---|---|---|
submit_new | PM, M&O, CUS PM, Sales/SP | New SKU form / Batch Upload | STD|CUS, payload, commercial_approval_ref (CUS) | Starts NewSpecWorkflow |
submit_edit | Factory, M&O, Data Team | SKU Detail / Batch Edit | changed fields + before/after | Starts EditSpecWorkflow |
submit_retire | M&O, NPD | SKU Detail | spec id + reason | Starts RetireSpecWorkflow |
submit_batch_upload | NPD / PM | Batch Upload | Excel file (N rows) | Starts BatchUploadWorkflow |
review_decision | Data Team | Review Queue | approve | reject + required reason | edit-and-approve | The single approval stage |
spec_set | Data Team | Review / SKU Detail | assigned SKU# / SKU-SPEC#, completed fields | Data Team creates/completes the record |
factory_dimensions_submitted | Factory | Batch Edit / SKU Detail | cartons, pallet, weights, CBM | Advances New/Edit past the factory wait |
cascade_confirmed | Data Team | Cascade Confirm modal | which sibling specs to include/exclude (tick-boxes) | Applies a shared-field change across specs |
retire_decision / guard_override | Data Team | Review Queue | retire path; override reason | Drives soft-delete + SAP freeze |
sap_sync_requested | Data Team | Review / Admin | spec id(s) | Manual "Sync now" (if SAP sync is manual — Jarry Q) |
notify_role · send_sla_alert · sync_to_sap · compute_affected_specs · run_retire_guard · write_change_log | system (activities) | — | — | Side-effects: email, SAP push, cascade math, audit. Retried with named policies. |
Six things genuinely deserve a durable workflow; a few more are candidates I'd argue against (§4.8). Diagram legend:
NewSpecWorkflow — ideation → SAP sync coreThe richest flow, and the one Emily drew on 12 Jun. Note: the submitter raises a request; the Data Team creates & completes the master record ("Data team turn to Create / revise SPEC"). STD/CUS only changes how it arrives + what's attached — same single approval.
submit_new(STD) — batch-upload via STD Spec template (commercial-approved dev list)submit_new(CUS) — request based on a standard spec, + commercial_approval_ref attachednotify_role(data_team) + start SLA timerreview_decision — verify completeness + commercial approval attachednotify_role(submitter) email → submitter revises & resubmits (same durable record)spec_set — create/complete record, assign SKU# / SKU-SPEC#notify_role(factory) + SLA timerfactory_dimensions_submitted — cartons, pallet, weights, CBMnotify_role(submitter) "spec request done" (email)sync_to_sap → if material exists: update master; else create → Material No. flows backEditSpecWorkflow — change an existing spec coreThe headline is cascade-with-exclude (Emily Part B Q7): when a SKU-level shared field changes, it must propagate to all that SKU's specs, with a confirm screen to tick off exceptions. This is the single biggest thing Airtable could not do.
submit_edit — picks SKU, submits field change(s)notify_role(data_team) + SLAreview_decision — approve / reject + reasoncompute_affected_specs — list every sibling spec on this SKUcascade_confirmed — tick-boxes to exclude exceptionswrite_change_log → sync_to_sap (affected records)RetireSpecWorkflow — retire / delete coreNever a hard delete. Soft lifecycle status + SAP view-freeze, behind a guard (don't orphan sibling specs / open orders / on-hand stock).
submit_retire — pick spec + reasonnotify_role(data_team) + SLAretire_decision — approve (+ retire path) / rejectrun_retire_guard — sibling specs? open orders? MA stock?guard_override (with reason) — or abortapply_sap_view_freeze (03/Z1 Blocked, not hard delete)BatchUploadWorkflow — many new specs at once batchEmily was firm: NPD won't enter records one-by-one ("they won't buy this idea"). A workflow that validates a whole Excel, reports row-by-row, lets the Data Team accept the valid rows, then fans out one child NewSpecWorkflow per accepted row — a natural Temporal pattern (durable validation + parent/child + partial accept).
submit_batch_upload — STD Spec template, N rowsNewSpecWorkflow for each accepted rowBatchEditWorkflow — edit many specs as one change batch"The Airtable gap" Emily named: select many rows in a grid, change a field (e.g. case-pack / outer dimension), submit as one change request, reviewed once, applied across rows — with per-SKU cascade where the field is shared. (June-12: "batch update, batch create … only need to change the case pack, outer dimension.")
submit_edit (batch) — multi-select rows + field changenotify_role(data_team) + SLAreview_decision — approve / reject + reasoncascade_confirmed — per affected SKU (if shared field)write_change_log → sync_to_sapEmily's flowchart has an explicit "If need Sync to SAP?" gate, then "if material exists → update master, else → create" and material-number-back + notify. Two shapes, decided by Jarry:
sync_to_sap runs as the conditional tail inside each lifecycle workflow (a retried activity). Simplest; matches "approve → Ready → Synced".SapMassSyncWorkflow that the Data Team triggers ("Sync now"), gathers all Ready-for-SAP records, pushes them, and writes Material Nos. back. Matches the older "mass upload Airtable→SAP" idea.I'll build it as a stubbed activity first (returns a fake Material No.) so nothing blocks on SAP access; the conditional structure is already known, only the mechanics (T-code ZMMR008, auth) are open.
| Pattern | What it is |
|---|---|
| Human-in-the-loop wait | notify_role → park on a signal → react. The one piece of code reused everywhere. |
| SLA timer | A durable timer on every human wait. On breach → send_sla_alert to Data Team (email), keep waiting, re-alert. (Emily Part B Q11.) |
| Reject-with-reason loop | Reject (reason required) returns to the submitter to revise & resubmit on the same durable record — not a new ticket. |
| Audit log | The workflow's event history is the change log. write_change_log mirrors it into the website DB for the UI. |
Listed so we can decide deliberately, not by accident. Default: plain CRUD / scheduled job, not Temporal.
| Thing | My call | Why |
|---|---|---|
| Scheduled assortment activation (version + effective date) | Maybe | A durable timer that flips a version live on a future date is a legit Temporal use — if effective-dating actually matters. Else a scheduled job. |
| Barcode-pool low-stock alert | No | A periodic threshold check, not a long-running, human-in-loop process. |
| Suggested option-value approval | No (fold in) | A lightweight approval item in Admin, or part of the main review — not its own workflow. |
| Barcode assignment, BOM edits, permitted-market edits, viewing/search | No | Pure CRUD against the website DB. Temporal would add cost and latency for nothing. |
My plan: data layer → Temporal layer → UI layer. Here's where I think that's right, and where I'd amend it.
The riskiest part of this project isn't any one layer — it's whether the flows are right at all. Emily literally said "assume my flows are wrong, I'll send the real process," that process doc hasn't landed yet, and the Commercial correction shows the design already drifted from reality. If I build a full data layer before the flows are confirmed, I risk polishing a foundation a flow change reshapes.
Two things to chase in parallel — they carry the most rework risk: (1) Emily's real end-to-end process-flow doc, and (2) 30 minutes with Jarry on SAP sync (auto vs manual, and is the write-back truly material-number-only). Don't block on them; do flag that deep work against guesses there is the most likely thing to be thrown away.
SKU (shared) / Spec (per-spec) column; that flag drives the cascade until Emily sends the explicit field list.notify_role(factory) targets.)Sources: Emily's questionnaire "Master Data — What I Need From You" (Parts A–F, role + permission grids); the 2026-06-12 meeting recording (verbatim transcript + flowchart frames); Field Dictionary "Process Steps" tab (Brodie's draft, flagged by Emily as "assume wrong"); docs/local_website_plan.md. The earlier docs/temporal_workflow_design.md is superseded by §0 on the Commercial-Lead point.