{
  "version": 2,
  "rootId": "f_270gyvgs",
  "flows": {
    "f_270gyvgs": {
      "id": "f_270gyvgs",
      "title": "Tienda online — pedido completo",
      "nodes": {
        "n_5qappjsk": {
          "id": "n_5qappjsk",
          "kind": "start",
          "label": "Cliente visita la tienda",
          "position": {
            "x": 80,
            "y": 214
          }
        },
        "n_0izulfk9": {
          "id": "n_0izulfk9",
          "kind": "end",
          "label": "Pedido entregado y notificado",
          "position": {
            "x": 2832,
            "y": 214
          }
        },
        "n_veeorhxz": {
          "id": "n_veeorhxz",
          "kind": "step",
          "type": "info",
          "label": "Visión del sistema",
          "infoTitle": "tienda.desarrollado.com — arquitectura",
          "infoBody": "SPA React → API Node (Express) → MySQL pedidos + Redis sesiones.\nPagos vía Stripe. Almacén WMS en sub-flujo fulfillment.\n\nEste demo usa: flujos, sub-flujos, requisitos (todos los tipos), HTTP, dataLayer, catálogo de versiones y diagramas Mermaid.",
          "subflowId": null,
          "spec": {
            "description": "",
            "since": "",
            "until": "",
            "versionNotes": {},
            "http": {
              "method": "",
              "path": ""
            },
            "requirements": [],
            "inputs": [],
            "outputs": [],
            "formFields": [],
            "payloadIn": "",
            "payloadOut": "",
            "dataRefs": []
          },
          "position": {
            "x": 424,
            "y": 214
          },
          "structures": [
            {
              "name": "tienda.desarrollado.com",
              "since": "2.0",
              "fields": "frontend SPA, CDN estáticos"
            },
            {
              "name": "api.tienda.desarrollado.com",
              "since": "2.0",
              "fields": "REST /api/*, JWT auth"
            },
            {
              "name": "hooks.stripe.com",
              "since": "2.5",
              "fields": "webhooks payment_intent.*"
            }
          ]
        },
        "n_q9t0q8pf": {
          "id": "n_q9t0q8pf",
          "kind": "step",
          "type": "subflow",
          "label": "Explorar catálogo",
          "infoTitle": "",
          "infoBody": "",
          "subflowId": "f_nth7mpnn",
          "spec": {
            "description": "",
            "since": "",
            "until": "",
            "versionNotes": {},
            "http": {
              "method": "",
              "path": ""
            },
            "requirements": [],
            "inputs": [],
            "outputs": [],
            "formFields": [],
            "payloadIn": "",
            "payloadOut": "",
            "dataRefs": []
          },
          "position": {
            "x": 768,
            "y": 214
          }
        },
        "n_lre7cp7s": {
          "id": "n_lre7cp7s",
          "kind": "step",
          "type": "subflow",
          "label": "Checkout y envío",
          "infoTitle": "",
          "infoBody": "",
          "subflowId": "f_pc14twox",
          "spec": {
            "description": "",
            "since": "",
            "until": "",
            "versionNotes": {},
            "http": {
              "method": "",
              "path": ""
            },
            "requirements": [],
            "inputs": [],
            "outputs": [],
            "formFields": [],
            "payloadIn": "",
            "payloadOut": "",
            "dataRefs": []
          },
          "position": {
            "x": 1112,
            "y": 214
          }
        },
        "n_ktaxg6bh": {
          "id": "n_ktaxg6bh",
          "kind": "step",
          "type": "subflow",
          "label": "Cobro con tarjeta",
          "infoTitle": "",
          "infoBody": "",
          "subflowId": "f_0w5jyjws",
          "spec": {
            "description": "",
            "since": "",
            "until": "",
            "versionNotes": {},
            "http": {
              "method": "",
              "path": ""
            },
            "requirements": [],
            "inputs": [],
            "outputs": [],
            "formFields": [],
            "payloadIn": "",
            "payloadOut": "",
            "dataRefs": []
          },
          "position": {
            "x": 1456,
            "y": 214
          }
        },
        "n_v6ym8ji5": {
          "id": "n_v6ym8ji5",
          "kind": "step",
          "type": "subflow",
          "label": "Preparar y enviar",
          "infoTitle": "",
          "infoBody": "",
          "subflowId": "f_0dlfvnv8",
          "spec": {
            "description": "",
            "since": "",
            "until": "",
            "versionNotes": {},
            "http": {
              "method": "",
              "path": ""
            },
            "requirements": [],
            "inputs": [],
            "outputs": [],
            "formFields": [],
            "payloadIn": "",
            "payloadOut": "",
            "dataRefs": []
          },
          "position": {
            "x": 1800,
            "y": 214
          }
        },
        "n_mum5axg3": {
          "id": "n_mum5axg3",
          "kind": "step",
          "type": "step",
          "label": "Notificar al cliente",
          "infoTitle": "",
          "infoBody": "",
          "subflowId": null,
          "spec": {
            "description": "Email + push con resumen del pedido, factura y enlace de tracking.",
            "since": "3.2",
            "http": {
              "method": "POST",
              "path": "/api/notifications/order-shipped"
            },
            "requirements": [
              {
                "name": "Email del cliente",
                "kind": "document",
                "required": true,
                "note": "Del checkout"
              },
              {
                "name": "Tracking activo",
                "kind": "object",
                "required": true,
                "note": "Del paso de despacho"
              },
              {
                "name": "Plantilla transaccional",
                "kind": "tool",
                "required": true,
                "note": "SendGrid / Resend configurado"
              }
            ],
            "inputs": [
              {
                "name": "orderId",
                "type": "string",
                "required": true
              },
              {
                "name": "channels",
                "type": "array",
                "required": true,
                "example": "[\"email\",\"push\"]"
              }
            ],
            "outputs": [
              {
                "name": "notificationId",
                "type": "string",
                "required": true
              }
            ]
          },
          "position": {
            "x": 2144,
            "y": 214
          }
        },
        "n_h0rel311": {
          "id": "n_h0rel311",
          "kind": "step",
          "type": "info",
          "label": "Tablas principales",
          "infoTitle": "Modelo relacional (MySQL)",
          "infoBody": "Ver también panel Datos y diagrama ER en Diagramas.\norders 1—N order_items · customers 1—N orders · products 1—N order_items",
          "subflowId": null,
          "spec": {
            "description": "",
            "since": "",
            "until": "",
            "versionNotes": {},
            "http": {
              "method": "",
              "path": ""
            },
            "requirements": [],
            "inputs": [],
            "outputs": [],
            "formFields": [],
            "payloadIn": "",
            "payloadOut": "",
            "dataRefs": []
          },
          "position": {
            "x": 2488,
            "y": 214
          },
          "structures": [
            {
              "name": "customers",
              "since": "2.0",
              "fields": "id, email, name, phone, created_at"
            },
            {
              "name": "products",
              "since": "2.0",
              "fields": "sku, name, price, stock, category"
            },
            {
              "name": "orders",
              "since": "2.0",
              "fields": "id, customer_id, status, total, shipping_address"
            },
            {
              "name": "order_items",
              "since": "2.0",
              "fields": "order_id, sku, quantity, unit_price"
            },
            {
              "name": "payments",
              "since": "2.5",
              "fields": "order_id, stripe_intent_id, amount, status"
            },
            {
              "name": "shipments",
              "since": "3.2",
              "fields": "order_id, tracking, carrier, shipped_at"
            }
          ]
        }
      },
      "edges": [
        {
          "id": "e_t3ke8jnp",
          "from": "n_h0rel311",
          "to": "n_0izulfk9"
        },
        {
          "id": "e_g8vesuof",
          "from": "n_5qappjsk",
          "to": "n_veeorhxz"
        },
        {
          "id": "e_7fmnzzvl",
          "from": "n_veeorhxz",
          "to": "n_q9t0q8pf"
        },
        {
          "id": "e_dg9y3f8k",
          "from": "n_q9t0q8pf",
          "to": "n_lre7cp7s"
        },
        {
          "id": "e_cj75tvrj",
          "from": "n_lre7cp7s",
          "to": "n_ktaxg6bh"
        },
        {
          "id": "e_u9j4odc2",
          "from": "n_ktaxg6bh",
          "to": "n_v6ym8ji5"
        },
        {
          "id": "e_mvwdgot6",
          "from": "n_v6ym8ji5",
          "to": "n_mum5axg3"
        },
        {
          "id": "e_bm3z9rgz",
          "from": "n_mum5axg3",
          "to": "n_h0rel311"
        }
      ]
    },
    "f_nth7mpnn": {
      "id": "f_nth7mpnn",
      "title": "Explorar catálogo",
      "nodes": {
        "n_gsrgs68z": {
          "id": "n_gsrgs68z",
          "kind": "start",
          "label": "Cliente entra",
          "position": {
            "x": 80,
            "y": 214
          }
        },
        "n_eg2ajau8": {
          "id": "n_eg2ajau8",
          "kind": "end",
          "label": "Producto elegido",
          "position": {
            "x": 1456,
            "y": 214
          }
        },
        "n_ud9yosxb": {
          "id": "n_ud9yosxb",
          "kind": "step",
          "type": "step",
          "label": "Listar productos — GET /api/products",
          "infoTitle": "",
          "infoBody": "",
          "subflowId": null,
          "spec": {
            "description": "Catálogo paginado con filtros por categoría, precio y disponibilidad.",
            "since": "2.0",
            "until": "",
            "versionNotes": {
              "1.0": "HTML estático + formulario mailto.",
              "2.0": "GET /api/products con filtros y paginación.",
              "3.0": "Stock por SKU sincronizado con almacén."
            },
            "http": {
              "method": "GET",
              "path": "/api/products?category=&page=1&limit=24"
            },
            "requirements": [
              {
                "name": "Conexión a internet",
                "kind": "tool",
                "required": true,
                "note": "WiFi o datos móviles"
              },
              {
                "name": "Navegador actualizado",
                "kind": "tool",
                "required": true,
                "note": "Chrome, Firefox o Safari reciente"
              },
              {
                "name": "Categoría deseada",
                "kind": "knowledge",
                "required": false,
                "note": "Ej. electrónica, hogar"
              }
            ],
            "outputs": [
              {
                "name": "products",
                "type": "array",
                "required": true,
                "example": "[{ sku, name, price, stock }]"
              }
            ]
          },
          "position": {
            "x": 424,
            "y": 214
          }
        },
        "n_5nz72mru": {
          "id": "n_5nz72mru",
          "kind": "step",
          "type": "step",
          "label": "Ver detalle — GET /api/products/{sku}",
          "infoTitle": "",
          "infoBody": "",
          "subflowId": null,
          "spec": {
            "description": "Ficha con imágenes, variantes, reseñas y stock por almacén.",
            "since": "2.0",
            "http": {
              "method": "GET",
              "path": "/api/products/{sku}"
            },
            "inputs": [
              {
                "name": "sku",
                "type": "string",
                "required": true,
                "example": "LAP-15-512"
              }
            ],
            "requirements": [
              {
                "name": "SKU válido",
                "kind": "knowledge",
                "required": true,
                "note": "Del listado anterior"
              },
              {
                "name": "Producto activo",
                "kind": "approval",
                "required": true,
                "note": "No mostrar si status=discontinued"
              }
            ],
            "outputs": [
              {
                "name": "product",
                "type": "object",
                "required": true
              }
            ]
          },
          "position": {
            "x": 768,
            "y": 214
          }
        },
        "n_hehjp5b3": {
          "id": "n_hehjp5b3",
          "kind": "step",
          "type": "step",
          "label": "Añadir al carrito — POST /api/cart/items",
          "infoTitle": "",
          "infoBody": "",
          "subflowId": null,
          "spec": {
            "description": "Incrementa cantidad; desde v3.0 reserva stock temporal en Redis.",
            "since": "2.0",
            "versionNotes": {
              "2.0": "Carrito en cookie + Redis session:{id}.",
              "3.0": "Reserva temporal de stock al añadir al carrito."
            },
            "http": {
              "method": "POST",
              "path": "/api/cart/items"
            },
            "formFields": [
              {
                "name": "sku",
                "type": "string",
                "required": true
              },
              {
                "name": "quantity",
                "type": "number",
                "required": true
              }
            ],
            "requirements": [
              {
                "name": "Sesión o JWT",
                "kind": "document",
                "required": true,
                "note": "Cookie session_id o Authorization Bearer"
              },
              {
                "name": "Stock disponible",
                "kind": "object",
                "required": true,
                "note": "quantity ≤ stock (v3.0 reserva 15 min)"
              }
            ],
            "payloadOut": {
              "sku": "LAP-15-512",
              "quantity": 1
            },
            "outputs": [
              {
                "name": "cart",
                "type": "object",
                "required": true,
                "example": "{ items[], subtotal }"
              }
            ]
          },
          "position": {
            "x": 1112,
            "y": 214
          }
        }
      },
      "edges": [
        {
          "id": "e_mwi1xqjh",
          "from": "n_hehjp5b3",
          "to": "n_eg2ajau8"
        },
        {
          "id": "e_fnz070p8",
          "from": "n_gsrgs68z",
          "to": "n_ud9yosxb"
        },
        {
          "id": "e_x67hqqu2",
          "from": "n_ud9yosxb",
          "to": "n_5nz72mru"
        },
        {
          "id": "e_ucll51mp",
          "from": "n_5nz72mru",
          "to": "n_hehjp5b3"
        }
      ]
    },
    "f_pc14twox": {
      "id": "f_pc14twox",
      "title": "Checkout y envío",
      "nodes": {
        "n_ogisc72y": {
          "id": "n_ogisc72y",
          "kind": "start",
          "label": "Carrito listo",
          "position": {
            "x": 80,
            "y": 214
          }
        },
        "n_x6d8twkg": {
          "id": "n_x6d8twkg",
          "kind": "end",
          "label": "Pedido creado",
          "position": {
            "x": 1456,
            "y": 214
          }
        },
        "n_b2qdu9w1": {
          "id": "n_b2qdu9w1",
          "kind": "step",
          "type": "step",
          "label": "Datos de envío — PUT /api/checkout/shipping",
          "infoTitle": "",
          "infoBody": "",
          "subflowId": null,
          "spec": {
            "description": "Dirección, código postal y método de envío (estándar o express).",
            "since": "2.0",
            "http": {
              "method": "PUT",
              "path": "/api/checkout/shipping"
            },
            "formFields": [
              {
                "name": "fullName",
                "type": "string",
                "required": true
              },
              {
                "name": "address",
                "type": "string",
                "required": true
              },
              {
                "name": "city",
                "type": "string",
                "required": true
              },
              {
                "name": "postalCode",
                "type": "string",
                "required": true
              },
              {
                "name": "shippingMethod",
                "type": "string",
                "required": true,
                "example": "standard | express"
              }
            ],
            "requirements": [
              {
                "name": "Carrito no vacío",
                "kind": "object",
                "required": true,
                "note": "Al menos un ítem"
              },
              {
                "name": "Documento de identidad",
                "kind": "document",
                "required": false,
                "note": "Para factura en algunos países"
              },
              {
                "name": "Zona de cobertura",
                "kind": "knowledge",
                "required": true,
                "note": "Consultar /api/shipping/zones"
              },
              {
                "name": "Dinero para envío",
                "kind": "money",
                "required": true,
                "note": "Costo según método y peso"
              }
            ],
            "outputs": [
              {
                "name": "shippingCost",
                "type": "number",
                "required": true
              },
              {
                "name": "estimatedDays",
                "type": "number",
                "required": true
              }
            ]
          },
          "position": {
            "x": 424,
            "y": 214
          }
        },
        "n_90ht1cv7": {
          "id": "n_90ht1cv7",
          "kind": "step",
          "type": "step",
          "label": "Aplicar cupón — POST /api/checkout/coupon",
          "infoTitle": "",
          "infoBody": "",
          "subflowId": null,
          "spec": {
            "description": "Descuento porcentual o fijo. Un cupón activo por pedido.",
            "since": "2.5",
            "http": {
              "method": "POST",
              "path": "/api/checkout/coupon"
            },
            "inputs": [
              {
                "name": "code",
                "type": "string",
                "required": true,
                "example": "VERANO20"
              }
            ],
            "requirements": [
              {
                "name": "Código promocional",
                "kind": "other",
                "required": true,
                "note": "Vigente y no agotado"
              },
              {
                "name": "Aprobación marketing",
                "kind": "approval",
                "required": false,
                "note": "Cupones B2B requieren validación manual"
              }
            ],
            "outputs": [
              {
                "name": "discount",
                "type": "number",
                "required": true
              }
            ]
          },
          "position": {
            "x": 768,
            "y": 214
          }
        },
        "n_zhb6arq1": {
          "id": "n_zhb6arq1",
          "kind": "step",
          "type": "step",
          "label": "Confirmar pedido — POST /api/checkout",
          "infoTitle": "",
          "infoBody": "",
          "subflowId": null,
          "spec": {
            "description": "Crea order en estado pending_payment. Calcula totales e impuestos.",
            "since": "2.0",
            "http": {
              "method": "POST",
              "path": "/api/checkout"
            },
            "requirements": [
              {
                "name": "Datos de envío completos",
                "kind": "object",
                "required": true,
                "note": "Paso anterior"
              },
              {
                "name": "Inventario reservado",
                "kind": "object",
                "required": false,
                "note": "v3.0 — TTL Redis stock_hold"
              },
              {
                "name": "Cliente identificado",
                "kind": "person",
                "required": true,
                "note": "Usuario registrado o guest email"
              }
            ],
            "outputs": [
              {
                "name": "orderId",
                "type": "string",
                "required": true,
                "example": "ord_8f3a2b"
              },
              {
                "name": "total",
                "type": "number",
                "required": true
              }
            ]
          },
          "position": {
            "x": 1112,
            "y": 214
          }
        }
      },
      "edges": [
        {
          "id": "e_njmvzmal",
          "from": "n_zhb6arq1",
          "to": "n_x6d8twkg"
        },
        {
          "id": "e_ly67pjsp",
          "from": "n_ogisc72y",
          "to": "n_b2qdu9w1"
        },
        {
          "id": "e_o2rlo572",
          "from": "n_b2qdu9w1",
          "to": "n_90ht1cv7"
        },
        {
          "id": "e_p40r7nrk",
          "from": "n_90ht1cv7",
          "to": "n_zhb6arq1"
        }
      ]
    },
    "f_0w5jyjws": {
      "id": "f_0w5jyjws",
      "title": "Cobro con tarjeta",
      "nodes": {
        "n_wolom6ew": {
          "id": "n_wolom6ew",
          "kind": "start",
          "label": "Pago pendiente",
          "position": {
            "x": 80,
            "y": 214
          }
        },
        "n_dlw3stf2": {
          "id": "n_dlw3stf2",
          "kind": "end",
          "label": "Pago confirmado",
          "position": {
            "x": 1456,
            "y": 214
          }
        },
        "n_e1mxziz3": {
          "id": "n_e1mxziz3",
          "kind": "step",
          "type": "step",
          "label": "Crear PaymentIntent — POST /api/payments/intent",
          "infoTitle": "",
          "infoBody": "",
          "subflowId": null,
          "spec": {
            "description": "Stripe PaymentIntent con amount y currency. Devuelve client_secret para Elements.",
            "since": "2.5",
            "until": "",
            "versionNotes": {
              "2.5": "Stripe PaymentIntent + webhook payment_intent.succeeded.",
              "3.2": "Antifraude + reembolsos parciales desde panel."
            },
            "http": {
              "method": "POST",
              "path": "/api/payments/intent"
            },
            "formFields": [
              {
                "name": "orderId",
                "type": "string",
                "required": true
              },
              {
                "name": "paymentMethod",
                "type": "string",
                "required": true,
                "example": "card"
              }
            ],
            "requirements": [
              {
                "name": "Pedido pending_payment",
                "kind": "object",
                "required": true,
                "note": "orderId del checkout"
              },
              {
                "name": "Tarjeta válida",
                "kind": "document",
                "required": true,
                "note": "Visa, MC, Amex — vía Stripe Elements"
              },
              {
                "name": "Fondos suficientes",
                "kind": "money",
                "required": true,
                "note": "total del pedido"
              },
              {
                "name": "Revisión antifraude",
                "kind": "approval",
                "required": false,
                "note": "Radar score < umbral (v3.2)"
              }
            ],
            "outputs": [
              {
                "name": "clientSecret",
                "type": "string",
                "required": true
              },
              {
                "name": "paymentIntentId",
                "type": "string",
                "required": true
              }
            ]
          },
          "position": {
            "x": 424,
            "y": 214
          }
        },
        "n_ursxjw13": {
          "id": "n_ursxjw13",
          "kind": "step",
          "type": "step",
          "label": "Webhook payment_intent.succeeded",
          "infoTitle": "",
          "infoBody": "",
          "subflowId": null,
          "spec": {
            "description": "Stripe notifica éxito. API marca order paid y encola fulfillment.",
            "since": "2.5",
            "http": {
              "method": "POST",
              "path": "/api/webhooks/stripe"
            },
            "inputs": [
              {
                "name": "type",
                "type": "string",
                "required": true,
                "example": "payment_intent.succeeded"
              },
              {
                "name": "data.object.id",
                "type": "string",
                "required": true
              }
            ],
            "requirements": [
              {
                "name": "Firma Stripe-Signature",
                "kind": "document",
                "required": true,
                "note": "Header verificado con webhook secret"
              },
              {
                "name": "Operador de pagos",
                "kind": "person",
                "required": false,
                "note": "Monitoreo alertas en panel"
              }
            ],
            "outputs": [
              {
                "name": "orderStatus",
                "type": "string",
                "required": true,
                "example": "paid"
              }
            ]
          },
          "position": {
            "x": 768,
            "y": 214
          }
        },
        "n_eo0fewdv": {
          "id": "n_eo0fewdv",
          "kind": "step",
          "type": "step",
          "label": "Emitir factura PDF",
          "infoTitle": "",
          "infoBody": "",
          "subflowId": null,
          "spec": {
            "description": "Genera PDF con número fiscal y lo adjunta al pedido.",
            "since": "2.5",
            "requirements": [
              {
                "name": "Pedido pagado",
                "kind": "approval",
                "required": true,
                "note": "status=paid"
              },
              {
                "name": "Datos fiscales del cliente",
                "kind": "document",
                "required": true,
                "note": "NIF/RUC si aplica"
              },
              {
                "name": "Plantilla de factura",
                "kind": "tool",
                "required": true,
                "note": "Motor PDF en servidor"
              }
            ],
            "outputs": [
              {
                "name": "invoiceUrl",
                "type": "string",
                "required": true,
                "example": "/invoices/ord_8f3a2b.pdf"
              }
            ]
          },
          "position": {
            "x": 1112,
            "y": 214
          }
        }
      },
      "edges": [
        {
          "id": "e_eydzcrz1",
          "from": "n_eo0fewdv",
          "to": "n_dlw3stf2"
        },
        {
          "id": "e_i9nqmj8y",
          "from": "n_wolom6ew",
          "to": "n_e1mxziz3"
        },
        {
          "id": "e_pnamzqjs",
          "from": "n_e1mxziz3",
          "to": "n_ursxjw13"
        },
        {
          "id": "e_eskhewwv",
          "from": "n_ursxjw13",
          "to": "n_eo0fewdv"
        }
      ]
    },
    "f_0dlfvnv8": {
      "id": "f_0dlfvnv8",
      "title": "Preparar y enviar",
      "nodes": {
        "n_mfvfy6dm": {
          "id": "n_mfvfy6dm",
          "kind": "start",
          "label": "Cola almacén",
          "position": {
            "x": 80,
            "y": 214
          }
        },
        "n_fll2h4d8": {
          "id": "n_fll2h4d8",
          "kind": "end",
          "label": "Paquete en tránsito",
          "position": {
            "x": 1456,
            "y": 214
          }
        },
        "n_d01bbegg": {
          "id": "n_d01bbegg",
          "kind": "step",
          "type": "step",
          "label": "Asignar picking — POST /api/warehouse/pick",
          "infoTitle": "",
          "infoBody": "",
          "subflowId": null,
          "spec": {
            "description": "Operario de almacén recibe lista de SKUs y ubicaciones (WMS).",
            "since": "3.0",
            "versionNotes": {
              "3.0": "Estado picking → packed → shipped en orders.status.",
              "3.2": "Integración courier + SMS/email automático."
            },
            "http": {
              "method": "POST",
              "path": "/api/warehouse/pick"
            },
            "requirements": [
              {
                "name": "Pedido paid",
                "kind": "object",
                "required": true,
                "note": "En cola fulfillment"
              },
              {
                "name": "Operario de almacén",
                "kind": "person",
                "required": true,
                "note": "Rol warehouse_picker"
              },
              {
                "name": "Escáner de barras",
                "kind": "tool",
                "required": true,
                "note": "Validar SKU en estantería"
              },
              {
                "name": "Ingredientes de empaque",
                "kind": "ingredient",
                "required": true,
                "note": "Caja, relleno, cinta adhesiva"
              }
            ],
            "inputs": [
              {
                "name": "orderId",
                "type": "string",
                "required": true
              }
            ],
            "outputs": [
              {
                "name": "pickListId",
                "type": "string",
                "required": true
              }
            ]
          },
          "position": {
            "x": 424,
            "y": 214
          }
        },
        "n_e33mtteb": {
          "id": "n_e33mtteb",
          "kind": "step",
          "type": "step",
          "label": "Empaquetar — PATCH /api/orders/{id}/pack",
          "infoTitle": "",
          "infoBody": "",
          "subflowId": null,
          "spec": {
            "description": "Peso y dimensiones para etiqueta de envío.",
            "since": "3.0",
            "http": {
              "method": "PATCH",
              "path": "/api/orders/{id}/pack"
            },
            "formFields": [
              {
                "name": "weightKg",
                "type": "number",
                "required": true
              },
              {
                "name": "boxSize",
                "type": "string",
                "required": true,
                "example": "M"
              }
            ],
            "requirements": [
              {
                "name": "Ítems recogidos",
                "kind": "object",
                "required": true,
                "note": "Pick list completada"
              },
              {
                "name": "Balanza",
                "kind": "tool",
                "required": true,
                "note": "Peso real del paquete"
              }
            ],
            "outputs": [
              {
                "name": "packageId",
                "type": "string",
                "required": true
              }
            ]
          },
          "position": {
            "x": 768,
            "y": 214
          }
        },
        "n_a6qx0ryv": {
          "id": "n_a6qx0ryv",
          "kind": "step",
          "type": "step",
          "label": "Despachar — POST /api/shipments",
          "infoTitle": "",
          "infoBody": "",
          "subflowId": null,
          "spec": {
            "description": "Genera etiqueta courier y tracking number.",
            "since": "3.2",
            "http": {
              "method": "POST",
              "path": "/api/shipments"
            },
            "requirements": [
              {
                "name": "Paquete empacado",
                "kind": "object",
                "required": true,
                "note": "packageId"
              },
              {
                "name": "Courier contratado",
                "kind": "person",
                "required": true,
                "note": "Integración API mensajería"
              },
              {
                "name": "Etiqueta impresa",
                "kind": "object",
                "required": true,
                "note": "PDF código de barras"
              }
            ],
            "outputs": [
              {
                "name": "trackingNumber",
                "type": "string",
                "required": true,
                "example": "CO123456789"
              },
              {
                "name": "carrier",
                "type": "string",
                "required": true
              }
            ]
          },
          "position": {
            "x": 1112,
            "y": 214
          }
        }
      },
      "edges": [
        {
          "id": "e_xfxw22th",
          "from": "n_a6qx0ryv",
          "to": "n_fll2h4d8"
        },
        {
          "id": "e_tv2hqlmc",
          "from": "n_mfvfy6dm",
          "to": "n_d01bbegg"
        },
        {
          "id": "e_icncj03w",
          "from": "n_d01bbegg",
          "to": "n_e33mtteb"
        },
        {
          "id": "e_qcw03u29",
          "from": "n_e33mtteb",
          "to": "n_a6qx0ryv"
        }
      ]
    }
  },
  "catalog": {
    "versions": [
      {
        "id": "1.0",
        "label": "Shop 1.0",
        "summary": "MVP — catálogo estático y pedidos por email"
      },
      {
        "id": "2.0",
        "label": "Shop 2.0",
        "summary": "API REST, carrito en sesión, checkout básico"
      },
      {
        "id": "2.5",
        "label": "Shop 2.5",
        "summary": "Pagos con tarjeta (Stripe), webhooks, factura PDF"
      },
      {
        "id": "3.0",
        "label": "Shop 3.0",
        "summary": "Inventario en tiempo real, reservas de stock"
      },
      {
        "id": "3.2",
        "label": "Shop 3.2",
        "summary": "Almacén WMS, tracking y notificaciones push"
      }
    ],
    "defaultView": "3.2",
    "defaultCompare": "2.0"
  },
  "dataLayer": {
    "databases": [
      {
        "id": "db_shop_mysql",
        "label": "MySQL — tienda principal",
        "engine": "mysql",
        "description": "Pedidos, catálogo y clientes en VPS producción",
        "since": "2.0",
        "host": "db.tienda.desarrollado.com",
        "tables": [
          {
            "id": "tbl_customers",
            "name": "customers",
            "since": "2.0",
            "fields": "id, email, name, phone",
            "primaryKey": "id",
            "description": "Registrados y guest checkout",
            "until": ""
          },
          {
            "id": "tbl_products",
            "name": "products",
            "since": "2.0",
            "fields": "sku, name, price, stock, category",
            "primaryKey": "sku",
            "description": "Catálogo",
            "until": ""
          },
          {
            "id": "tbl_orders",
            "name": "orders",
            "since": "2.0",
            "fields": "id, customer_id, status, total, shipping_json",
            "primaryKey": "id",
            "description": "pending_payment → paid → shipped",
            "until": ""
          },
          {
            "id": "tbl_order_items",
            "name": "order_items",
            "since": "2.0",
            "fields": "order_id, sku, quantity, unit_price",
            "primaryKey": "id",
            "description": "Líneas del pedido",
            "until": ""
          },
          {
            "id": "tbl_payments",
            "name": "payments",
            "since": "2.5",
            "fields": "order_id, stripe_intent_id, amount, status",
            "primaryKey": "id",
            "description": "Cobros Stripe",
            "until": ""
          },
          {
            "id": "tbl_shipments",
            "name": "shipments",
            "since": "3.2",
            "fields": "order_id, tracking, carrier, shipped_at",
            "primaryKey": "id",
            "description": "Envíos",
            "until": ""
          }
        ]
      },
      {
        "id": "db_shop_redis",
        "label": "Redis — sesiones y carrito",
        "engine": "redis",
        "description": "TTL 24h sesión; reservas de stock 15 min (v3.0)",
        "since": "2.0",
        "host": "redis.internal:6379",
        "tables": [
          {
            "id": "tbl_sessions",
            "name": "session:{id}",
            "since": "2.0",
            "fields": "cart_json, customer_id, expires",
            "primaryKey": "session:{id}",
            "description": "Carrito anónimo",
            "until": ""
          },
          {
            "id": "tbl_stock_hold",
            "name": "stock_hold:{sku}",
            "since": "3.0",
            "fields": "quantity, order_draft_id, expires_at",
            "primaryKey": "stock_hold:{sku}",
            "description": "Reserva temporal",
            "until": ""
          }
        ]
      },
      {
        "id": "db_stripe_api",
        "label": "Stripe API (externo)",
        "engine": "api",
        "description": "PaymentIntents y webhooks — no es SQL",
        "since": "2.5",
        "host": "api.stripe.com",
        "tables": [
          {
            "id": "tbl_payment_intents",
            "name": "payment_intents",
            "since": "2.5",
            "fields": "id, amount, currency, status, client_secret",
            "primaryKey": "id",
            "description": "",
            "until": ""
          }
        ]
      }
    ],
    "connections": [
      {
        "id": "cx_products",
        "label": "Listar catálogo",
        "flowId": "f_270gyvgs",
        "nodeLabel": "Listar productos — GET /api/products",
        "databaseId": "db_shop_mysql",
        "tableId": "tbl_products",
        "operation": "read",
        "fields": "sku, name, price, stock"
      },
      {
        "id": "cx_cart",
        "label": "Añadir al carrito",
        "flowId": "f_270gyvgs",
        "nodeLabel": "Añadir al carrito — POST /api/cart/items",
        "databaseId": "db_shop_redis",
        "tableId": "tbl_sessions",
        "operation": "read_write",
        "fields": "cart_json"
      },
      {
        "id": "cx_stock_hold",
        "label": "Reserva stock",
        "flowId": "f_270gyvgs",
        "nodeLabel": "Añadir al carrito — POST /api/cart/items",
        "databaseId": "db_shop_redis",
        "tableId": "tbl_stock_hold",
        "operation": "write",
        "fields": "quantity, expires_at",
        "since": "3.0"
      },
      {
        "id": "cx_checkout",
        "label": "Crear pedido",
        "flowId": "f_270gyvgs",
        "nodeLabel": "Confirmar pedido — POST /api/checkout",
        "databaseId": "db_shop_mysql",
        "tableId": "tbl_orders",
        "operation": "write",
        "fields": "customer_id, status, total"
      },
      {
        "id": "cx_order_items",
        "label": "Líneas del pedido",
        "flowId": "f_270gyvgs",
        "nodeLabel": "Confirmar pedido — POST /api/checkout",
        "databaseId": "db_shop_mysql",
        "tableId": "tbl_order_items",
        "operation": "write",
        "fields": "order_id, sku, quantity"
      },
      {
        "id": "cx_payment",
        "label": "PaymentIntent",
        "flowId": "f_270gyvgs",
        "nodeLabel": "Crear PaymentIntent — POST /api/payments/intent",
        "databaseId": "db_stripe_api",
        "tableId": "tbl_payment_intents",
        "operation": "write",
        "fields": "amount, currency, status"
      },
      {
        "id": "cx_payment_db",
        "label": "Registrar pago",
        "flowId": "f_270gyvgs",
        "nodeLabel": "Webhook payment_intent.succeeded",
        "databaseId": "db_shop_mysql",
        "tableId": "tbl_payments",
        "operation": "write",
        "fields": "order_id, stripe_intent_id, status"
      },
      {
        "id": "cx_order_paid",
        "label": "Marcar pagado",
        "flowId": "f_270gyvgs",
        "nodeLabel": "Webhook payment_intent.succeeded",
        "databaseId": "db_shop_mysql",
        "tableId": "tbl_orders",
        "operation": "update",
        "fields": "status"
      },
      {
        "id": "cx_pick",
        "label": "Picking WMS",
        "flowId": "f_270gyvgs",
        "nodeLabel": "Asignar picking — POST /api/warehouse/pick",
        "databaseId": "db_shop_mysql",
        "tableId": "tbl_order_items",
        "operation": "read",
        "fields": "sku, quantity"
      },
      {
        "id": "cx_ship",
        "label": "Registro envío",
        "flowId": "f_270gyvgs",
        "nodeLabel": "Despachar — POST /api/shipments",
        "databaseId": "db_shop_mysql",
        "tableId": "tbl_shipments",
        "operation": "write",
        "fields": "order_id, tracking, carrier"
      },
      {
        "id": "cx_stock_dec",
        "label": "Descontar inventario",
        "flowId": "f_270gyvgs",
        "nodeLabel": "Empaquetar — PATCH /api/orders/{id}/pack",
        "databaseId": "db_shop_mysql",
        "tableId": "tbl_products",
        "operation": "update",
        "fields": "stock"
      }
    ]
  },
  "diagrams": {
    "preferred": "sequence",
    "custom": "gantt\n  title Roadmap tienda (modo Libre)\n  dateFormat YYYY-MM-DD\n  section Catálogo\n  API productos v2     :done,    cat, 2025-01-01, 45d\n  Stock en tiempo real :active,  stk, 2025-03-01, 60d\n  section Checkout\n  Carrito Redis        :done,    cart, 2025-02-01, 30d\n  Pagos Stripe         :done,    pay,  2025-04-01, 40d\n  section Almacén\n  WMS picking          :         wms,  2025-06-01, 50d\n  Tracking courier     :         trk,  2025-07-15, 35d"
  }
}