Auditoría técnica — Shopify como integración de TimeLiber
Fecha de corte: 2026-08-31
Estado: propuesta; no autoriza despliegue ni selección irreversible de distribución
Fuentes Shopify: únicamente documentación oficial vigente consultada en la fecha de corte
Resumen ejecutivo
La recomendación es la opción C: una capa general de integraciones dentro de TimeLiber Commerce, con Shopify como primer adaptador. No se debe reconstruir identidad, tenants, persistencia ni el producto TimeLiber dentro del template de Shopify.
En la fase inicial tampoco se justifica operar un microservicio de integraciones independiente. El bounded context integrations/shopify puede vivir en el backend FastAPI de Commerce, con contratos que permitan extraerlo después. El template oficial React Router/TypeScript de TimeLiber Connect debe conservarse como una superficie Shopify pequeña —instalación/launch embebido y experiencia mínima exigida por Shopify— que invoque por HTTP a Commerce. El cerebro, datos normalizados, políticas, automatizaciones y autorización siguen en TimeLiber.
commerce.timeliber.com.co (producto principal)
│
├── /dashboard UI y autorización TimeLiber
├── /api/v1/integrations contratos internos
│
└── Integration Layer (FastAPI, inicialmente modular)
├── Shopify adapter ── GraphQL Admin API
├── Meta/WhatsApp adapter (futuro)
├── CRM adapter (futuro)
└── Payments adapter (futuro)
▲
│ HTTP interno firmado
TimeLiber Connect (compañero Shopify mínimo)
instalación/launch/App Bridge/token exchange
Esta conclusión es un GO técnico condicionado: la arquitectura es viable, pero una Public App no debe entrar a revisión hasta probar instalación, reinstalación, revocación, RLS, webhooks, borrado y recuperación de tokens en un entorno desechable y una Development Store.
1. Estado actual comprobado
TimeLiber Commerce
| Área | Confirmado en código | Madurez |
|---|---|---|
| Backend | Python 3.13, FastAPI, SQLAlchemy 2 async, Alembic | Esqueleto operativo |
| Frontend | React 19, React Router 7, Vite 6, TypeScript, Tailwind 4 | Shell fundacional; no es el template Shopify |
| Auth | Argon2id, JWT access/refresh, rotación Redis, fail-closed para MFA pendiente | Unitariamente cubierto; rutas aún no montadas |
| Usuarios/empresas | users, organizations, organization_members; roles owner/admin/member |
Implementado |
| Multi-tenancy | filtros explícitos, contexto PostgreSQL y RLS en organizations/organization_members |
SQL offline validado; falta prueba PostgreSQL real |
| Datos | commerce_db en PostgreSQL central; Redis DB 8 |
Declarado; no migrado en producción |
| Integraciones | Ningún dominio productivo todavía | Por construir |
| Webhooks/workers | Ninguno en Commerce | Por construir |
| Infra | Compose, Traefik, timeliber-net, proxy-net, health checks |
Configuración validada |
| Secrets | Pydantic settings y .env.example; secretos no versionados |
Falta secret manager/rotación productiva |
Capacidades reutilizables del monorepo
infra/core: PostgreSQL y Redis compartidos por motor, pero con base y credenciales exclusivas de Commerce.- Traefik: HTTPS, certificados y routing por host/path.
- LGTM: Alloy, Loki, Tempo, Mimir y Grafana; Commerce aún debe instrumentarse.
- n8n/Evolution: útiles después de que Commerce emita eventos internos seguros; no deben recibir tokens Shopify ni ser la fuente de verdad.
- Payments contiene un patrón útil de webhook: verificar, persistir, deduplicar, responder rápido y reintentar. Debe adaptarse, no importarse entre verticales.
- Operator demuestra integración cross-vertical por HTTP, compatible con la regla de no importar modelos de otras verticales.
TimeLiber Connect
El usuario declara que existe una app de desarrollo Shopify Partner creada con Shopify CLI, React Router y TypeScript, conectada a una Development Store. Ese código no fue localizado dentro de /home/admin_/software/timeliber-workspace ni en las rutas vecinas inspeccionadas. Por ello no se afirman versiones, sesiones, rutas ni estado de ese template. Antes de implementarlo se necesita incorporar su ruta al alcance de auditoría o moverlo a una ubicación acordada.
La app localizada en /home/admin_/software/freelance/apps/api corresponde a PulseCommerce/FastAPI, no al template descrito. Se mantuvo en solo lectura y sólo sirve como fuente de patrones.
2. Comparación arquitectónica
| Opción | Ventajas | Problemas | Veredicto |
|---|---|---|---|
| A. Integrar el template Shopify en FastAPI | Menos procesos aparentes | Mezcla runtimes y dos modelos de sesión; fuerza reescritura del template oficial; acopla TimeLiber a Shopify | No recomendada |
| B. TimeLiber Connect como servicio completo | Aislamiento claro del proveedor | Duplica tenants, auth, datos, observabilidad y lógica; crea consistencia distribuida demasiado pronto | No ahora |
| C. Integration Layer general | Reutiliza identidad/RLS; contratos uniformes; otros proveedores caben sin contaminar dominios | Exige diseñar puertos, eventos e idempotencia desde el inicio | Recomendada |
La variante concreta es C modular + compañero Shopify delgado. Commerce contiene el caso de uso; TimeLiber Connect resuelve únicamente obligaciones propias de la superficie Shopify. Si volumen, disponibilidad o equipos divergen, el bounded context puede extraerse a integrations.timeliber.com.co sin cambiar su contrato.
3. Instalación y autenticación Shopify
Una app pública, múltiples instalaciones
TimeLiber Connect es una sola aplicación Shopify por entorno y método de
distribución, no una aplicación diferente por comercio. Todas las tiendas
independientes instalan la misma app pública. client_id, secreto y
configuración de distribución pertenecen a la app/entorno; cada autorización
crea una instalación tenant-bound distinta con su shop_id, dominio, scopes,
estado y token cifrado. DEV y PROD pueden usar configuraciones de app separadas
para aislar pruebas, pero nunca se crea una app por tenant.
Shopify distingue:
- apps embebidas creadas con CLI: Shopify Managed Installation y token exchange;
- apps standalone/API-only: authorization code grant;
- client credentials: sólo tiendas de la misma Shopify organization, por lo que no sirve para comercios independientes.
El template oficial usa Managed Installation por defecto. Los scopes viven en shopify.app.toml y se publican con shopify app deploy. Los tokens offline sirven para webhooks, sincronizaciones y jobs; los online están ligados al staff y su sesión. Shopify documenta además que las Public Apps deberán usar tokens offline expirables para Admin API a más tardar el 1 de enero de 2027, así que TimeLiber debe diseñar refresh/rotación desde el primer MVP.
Fuentes: autenticación, Managed Installation, access tokens, standalone OAuth.
Flujo recomendado desde TimeLiber
- Usuario autenticado elige una organización en
commerce.timeliber.com.co/dashboard. - TimeLiber crea
connection_intent: nonce aleatorio,organization_id,user_id, expiración corta y uso único. - “Conectar Shopify” dirige a una superficie de instalación propiedad de Shopify; no solicita escribir manualmente
*.myshopify.com. - Shopify instala/abre TimeLiber Connect y autentica al merchant.
- El compañero obtiene la identidad canónica de shop y un token offline expirable mediante el flujo oficial.
- El merchant vincula la instalación al intent autenticado de TimeLiber. El backend verifica nonce, usuario, membresía, shop y firma antes de persistir.
- TimeLiber Connect conserva el token en su session store cifrado; Commerce registra únicamente identidad, scopes y vínculo tenant↔shop.
- El usuario regresa a Integraciones con estado
connected, scopes y última sincronización; jamás ve el token.
La exigencia de iniciar instalación en una superficie Shopify y no pedir manualmente el dominio está en los App Store requirements, sección 2.3.
4. Distribución pública
- Public distribution permite múltiples merchants independientes y conduce a App Store Review.
- Custom distribution sólo cubre una tienda o varias tiendas de la misma organización Shopify Plus; no satisface el objetivo SaaS.
- La distribución no se puede cambiar después de seleccionarla. Debe decidirse únicamente sobre la configuración PROD.
- Toda Public App aprobada tiene listing. Limited visibility conserva una URL instalable pero no aparece en búsqueda/categorías; fully visible sí se indexa. Ambas pasan los mismos requisitos y revisión.
Recomendación: no fijar todavía la distribución de DEV; crear una configuración/app PROD separada y seleccionar Public Distribution cuando los gates técnicos estén verdes. Para un piloto controlado posterior a review, Limited Visibility reduce descubrimiento sin evitar la revisión; no es un atajo de compliance.
Fuentes: seleccionar distribución, visibilidad del listing, proceso de review.
5. GraphQL y scopes mínimos
El REST Admin API es legacy desde el 1 de octubre de 2024 y las nuevas Public Apps enviadas desde el 1 de abril de 2025 deben usar GraphQL Admin API. TimeLiber no debe crear nuevas llamadas REST. Se fijará explícitamente una versión estable soportada y se revisará trimestralmente; en la fecha de corte la documentación muestra 2026-07 para webhooks.
Fuentes: estrategia GraphQL, anuncio para Public Apps, versionado REST/legacy.
| Scope | Uso inicial permitido | Nota |
|---|---|---|
read_orders |
Order, líneas compradas, transacciones, fulfillment y datos relacionados | Único scope del MVP nivel 1; por defecto cubre pedidos de los últimos 60 días |
read_products |
Productos, variantes, imágenes y colecciones | Fuera del MVP; las líneas del pedido no lo necesitan |
read_inventory |
Niveles/items de inventario que permita el modelo GraphQL | Fuera del MVP |
read_locations |
Locations | Fuera del MVP |
No solicitar write_*. La configuración efectiva se redujo el 2026-09-01 a
read_orders; los otros scopes de lectura permanecen como posibilidades futuras,
no como permisos declarados. Tampoco solicitar read_all_orders en MVP: requiere
permiso adicional y evidencia de necesidad. Si el piloto demuestra que 60 días no
alcanzan, se abre una decisión específica y se solicita posteriormente.
Fuente canónica: Shopify API access scopes. Shopify exige además pedir sólo scopes necesarios en los App Store requirements.
6. Modelo multi-tenant propuesto
Todas las tablas llevan organization_id y RLS. Ninguna consulta comercial acepta sólo shop_domain como boundary.
integration_connections
id UUIDorganization_id UUID NOT NULLprovider(shopify, futurometa, etc.)external_account_id(Shopify Shop GID/ID canónico)external_account_label(*.myshopify.comnormalizado)status(pending,connected,degraded,revoked,uninstalled)granted_scopesconnected_by_user_idconnected_at,last_verified_at,disconnected_at,created_at,updated_at,deleted_at
Restricciones: unique global (provider, external_account_id) para impedir vincular una tienda a dos tenants accidentalmente; índice parcial unique de conexión activa según la política de una/múltiples tiendas que se decida.
shopify_installations
connection_idFK tenant-boundaryshop_id,shop_domaincanónicosscopes,api_versioninstalled_at,uninstalled_at,last_token_refresh_at
Los tokens offline/refresh residen únicamente en la tabla Session de
commerce_connect_db, cifrados por el session storage del conector. Commerce
no los recibe. Las columnas de credencial creadas inicialmente en
shopify_installations permanecen nullable por compatibilidad y no se usan en
el flujo vigente.
Soporte operacional
integration_connection_intents: nonce hash, tenant/user, expiración y consumo único.webhook_receipts:organization_id, provider, webhook ID unique, topic, shop ID, HMAC status, payload mínimo/cifrado o referencia, estado y timestamps.integration_jobs: tenant, tipo, cursor, intento, próxima ejecución, lease y error sanitizado.- Proyecciones (
shopify_orders, productos, inventario) siempre conorganization_id, soft delete e índices parciales.
RLS es la segunda barrera; services y repositories siguen filtrando explícitamente por organization_id. El runtime no posee tablas ni tiene BYPASSRLS.
7. Protected Customer Data
Pedidos son Protected Customer Data incluso si no se consultan campos identificadores. El modelo oficial tiene niveles:
- nivel 0: sin customer data;
- nivel 1: customer data excluyendo nombre, dirección, teléfono y email;
- nivel 2: incluye cualquiera de esos cuatro campos y exige revisión de protección de datos.
Para “nuevo pedido → WhatsApp” con nombre/teléfono se requiere nivel 2, solicitud explícita de cada campo y demostrar minimización/necesidad. En Development Stores se pueden seleccionar campos para desarrollo sin completar review, pero eso no predice aprobación pública.
Recomendación por fases:
- MVP técnico nivel 1: IDs, número, estado, moneda, totales y líneas, evitando PII.
- Gate separado para WhatsApp: justificar teléfono y quizá nombre; no pedir email/dirección si no son necesarios.
- Antes de nivel 2: cifrado de backups, DEV/STAGING/PROD separados, DLP, mínimo acceso de personal, contraseñas fuertes, audit log de accesos y plan de incidentes.
- Consentimiento/opt-out y finalidad de mensajería deben resolverse jurídicamente; la aprobación Shopify no sustituye autorización para contactar al comprador.
Fuente: Protected Customer Data.
8. Webhooks y procesamiento asíncrono
Suscripciones iniciales
orders/createorders/updatedorders/cancelledapp/uninstalled- opcional recomendado:
app/scopes_update - obligatorios:
customers/data_request,customers/redact,shop/redact
Las suscripciones app-specific declaradas en shopify.app.toml son la opción recomendada cuando aplican igual a todas las tiendas. Los webhooks están versionados y deben revisarse trimestralmente.
Pipeline
Shopify HTTPS
→ verificar HMAC sobre bytes crudos
→ validar shop/topic/tamaño
→ INSERT receipt idempotente por X-Shopify-Webhook-Id
→ responder 2xx rápidamente
→ Redis durable job queue (fase inicial)
→ worker reclama con lease y reintentos/backoff
→ GraphQL reconciliation cuando sea necesario
→ actualizar proyección tenant-bound
→ emitir evento interno sin token y con PII mínima
→ automatizaciones TimeLiber/n8n
No usar BackgroundTasks como garantía durable: una caída después del 2xx perdería trabajo. Redis ya existe, pero se necesita una librería/worker con persistencia y política de dead-letter; PostgreSQL conserva receipts y estado auditable. Si el volumen supera la operación de Redis, evaluar Pub/Sub/EventBridge, ambos soportados oficialmente.
Shopify pide verificar HMAC y deduplicar con X-Shopify-Webhook-Id. Los tres webhooks de privacidad deben responder 2xx y completar la acción dentro de 30 días, salvo retención legal aplicable. shop/redact llega 48 horas después de desinstalar.
Fuentes: webhooks, suscripciones, privacy law compliance.
9. Producción y dominios
Recomendación inicial
- Producto, UI, OAuth callbacks y HTTPS webhooks:
commerce.timeliber.com.co. - API por path:
https://commerce.timeliber.com.co/api/v1/.... - No crear
api.,connect.ointegrations.todavía: Traefik ya separa frontend/backend por prioridad y path, y otro host aumenta DNS, CORS, cookies, certificados y observabilidad. - Reservar conceptualmente
integrations.timeliber.com.copara una extracción futura, no para el MVP.
El template Shopify puede usar el mismo origen público mediante rutas dedicadas o desplegarse detrás del mismo Traefik como servicio interno separado. La URL pública no obliga a fusionar runtimes.
Controles faltantes antes de producción
- DNS y TLS ya apuntados deben verificarse externamente, no asumirse por configuración local.
- Secrets productivos mediante secret manager o archivos de host con permisos mínimos; rotación de Shopify client secret y encryption key.
commerce_dbincluido en backups; hoy el script central todavía no lo enumera.- Backups cifrados y restauración ensayada antes de Protected Customer Data nivel 2.
- Worker independiente, health/readiness y apagado ordenado.
- Telemetría OTEL/estructurada sin payloads, tokens, emails, teléfonos o direcciones.
- Métricas: latencia/errores GraphQL, throttle cost, webhook lag/duplicate/failure, queue depth, token refresh y conexiones degradadas.
- DEV/STAGING/PROD con bases, Redis namespaces, claves, Shopify app configs y tiendas separadas.
10. DEV frente a PROD
Mantener TimeLiber Connect DEV sólo para Development Stores y crear TimeLiber Connect PROD antes de elegir distribución pública.
Ventajas: credenciales y callback separados, scopes experimentales no contaminan review, webhooks de prueba no llegan a producción, rotación segura y menor riesgo de PII. Costes: duplicar configuración del Dev Dashboard y controlar drift.
Mitigación: un mismo código, archivos shopify.app.dev.toml/shopify.app.prod.toml, variables externas, despliegue CI con App Automation Token y una checklist que compare scopes, topics, URLs y API version. Nunca copiar tokens ni client secrets entre ambientes.
Shopify recomienda seleccionar distribución en la app PROD cuando hay apps separadas: distribution method.
11. Checklist de App Store Review
Obligatorio para enviar
- Public Distribution seleccionada en PROD; decisión irreversible aprobada.
- App completa y estable, no beta; automated checks exitosos.
- Al menos un listing y lenguaje primario.
- URLs HTTPS, redirect URLs y contactos válidos.
- Scopes mínimos y API GraphQL soportada.
- Compliance webhooks declarados.
- Solicitud Protected Customer Data presentada u opt-out explícito antes del review.
- Instrucciones, credenciales de reviewer y screencast de onboarding/core feature en inglés o subtitulado.
Obligatorio para aprobar
- Instalación iniciada en Shopify, OAuth/token exchange inmediato, redirect final útil y reinstalación funcional.
- App Bridge actual y autenticación por ID/session token para experiencia embebida.
- UI interactiva sin 3xx/4xx/5xx bloqueantes; datos sincronizados con exactitud.
- HMAC, idempotencia, uninstall y privacy webhooks demostrables.
- TLS válido, secretos protegidos y sólo scopes justificables.
- Privacy policy enlazada y tratamiento de datos coherente.
- Si cobra: Shopify App Pricing/Billing API; no billing off-platform.
- Listing, nombre, pricing y claims exactos; soporte/contacto operativo.
Recomendado
- Limited Visibility durante piloto posterior a aprobación.
- Pruebas E2E de install/reinstall/uninstall y expiración/refresh.
- Load test de webhook burst, replay y duplicados.
- Restore drill, runbooks, alertas y panel operativo.
- Self-review oficial antes de enviar.
Puede hacerse después
- Fully Visible y optimización del listing.
- Scopes opcionales adicionales y
read_all_orderssi existe evidencia. - Más proveedores y extracción a microservicio.
- EventBridge/PubSub si la carga justifica abandonar la cola inicial.
Fuentes: App Store requirements, pass app review, submit for review, privacy requirements.
12. Qué reutilizar y qué desarrollar
Reutilizar
- User/auth, organizations/memberships y capability matrix de Commerce.
- PostgreSQL/Redis/Traefik y redes centrales.
- RLS y separación owner/runtime.
- Patrón Payments de inbox/idempotencia/reintentos, reimplementado dentro de Commerce.
- Observabilidad LGTM e integración HTTP cross-workspace.
- Del template Shopify: configuración oficial, Managed Installation, App Bridge, autenticación y rutas webhook compatibles, después de auditar el código real.
Desarrollar
- Bounded context
integrationsy adaptershopify. - Connection intents y linking Shopify↔TimeLiber.
- Cifrado/rotación de credenciales externas.
- Cliente GraphQL versionado con rate/throttle handling y cursores.
- Tablas y RLS descritos.
- Webhook inbox, cola durable, worker, reconciliation y dead-letter.
- UI Integraciones/estado/reconectar/desconectar.
- Compliance, políticas, auditoría PII, runbooks, backup/restore.
- Contrato HTTP mínimo con TimeLiber Connect.
El primer slice HTTP ya implementado expone creación de intents y listado de conexiones con Bearer auth, membresía/capability, rate limit Redis y errores de dominio estables. La instalación Shopify, OAuth/token exchange y webhook ingress no se consideran implementados por la existencia de estas rutas.
13. Riesgos y bloqueadores
| Riesgo/bloqueador | Severidad | Respuesta |
|---|---|---|
| Template TimeLiber Connect no disponible para auditoría | Alta | Incorporar ruta/código antes del diseño detallado |
| RLS aún no probado en PostgreSQL real | Crítica | Gate previo a persistir instalaciones |
| Flujo “Conectar” incompatible con inicio obligatorio en Shopify | Alta | Redirigir a superficie Shopify y vincular por intent |
| Token offline expirable/refresh mal implementado | Crítica | Diseñar rotación atómica y pruebas de concurrencia |
| PII para WhatsApp exige nivel 2 y consentimiento/finalidad | Crítica | MVP sin PII; gate legal/técnico separado |
commerce_db ausente del backup actual |
Alta | Agregar sólo cuando se autorice producción; probar restore/cifrado |
| Redis no es por sí solo una cola durable diseñada | Alta | Seleccionar worker/queue, receipts PostgreSQL y DLQ |
| Selección de distribución irreversible | Alta | Hacerla sólo en PROD tras aprobación interna |
| Review exige experiencia embebida consistente | Alta | Mantener compañero Shopify mínimo con App Bridge |
14. Roadmap y complejidad
| Fase | Resultado | Complejidad | Gate |
|---|---|---|---|
| 0. Cerrar auditoría | Código real de TimeLiber Connect localizado; configs redacted comparadas | S | Sin secretos ni incógnitas estructurales |
| 1. Seguridad tenant | Migraciones/RLS en PostgreSQL desechable, auth HTTP segura | M | Cross-tenant y downgrade verdes |
| 2. Integration foundation | connections, intents, crypto, capabilities y UI base | M | Ningún token visible; RLS integral |
| 3. Instalación DEV | Managed install/token exchange y linking con Development Store | L | install/reinstall/uninstall reales |
| 4. Lectura GraphQL | pedidos/productos/inventario/locations, cursores y throttling | L | Conciliación campo a campo sin PII |
| 5. Webhooks/workers | inbox, HMAC, dedupe, queue, replay y reconciliation | L | burst/retry/restart sin pérdidas |
| 6. Compliance/operación | privacy topics, retention, backups cifrados, OTEL, runbooks | XL | restore e incident drill |
| 7. PCD nivel 2 opcional | teléfono/nombre mínimos y flujo WhatsApp consentido | XL | aprobación Shopify + revisión legal |
| 8. PROD y review | app PROD, listing, reviewer pack y automated checks | L | aprobación Shopify |
S ≈ 1–3 días, M ≈ 3–7, L ≈ 1–3 semanas, XL ≈ 3–6 semanas para una persona con acceso y ambientes listos. Son rangos técnicos, no compromisos de calendario; App Review y aprobación PCD dependen de Shopify.
Definition of Done antes de modificar producto de forma irreversible
- Arquitectura C y límites de TimeLiber Connect aprobados mediante ADR.
- Código real del template auditado; ninguna sesión/auth/DB se duplica sin justificación.
- Public Distribution no seleccionada hasta aprobar el gate correspondiente.
- RLS demuestra aislamiento entre al menos dos organizaciones con runtime sin
BYPASSRLS. - Modelo de conexiones y token lifecycle revisado con threat model.
- Install, reinstall, uninstall, refresh y scopes_update pasan E2E en Development Store.
- GraphQL
2026-07o versión estable elegida consulta sólo scopes mínimos y respeta throttling. - Webhooks verifican HMAC sobre bytes crudos, deduplican, persisten antes del 2xx y sobreviven reinicios.
- Compliance topics pasan casos de data request/redact/shop redact.
- Logs/trazas no contienen tokens ni PII; backups están cifrados y restaurados en ensayo.
- DEV/STAGING/PROD están separados por app config, secretos, datos y tiendas.
- Checklist de review, screencast, credenciales, soporte, privacy policy y listing están completos.
Decisión concreta propuesta
Arquitectura: Integration Layer modular en TimeLiber Commerce + TimeLiber Connect como compañero Shopify delgado.
Dominio inicial: commerce.timeliber.com.co, un solo origen con routing por paths.
API: GraphQL Admin API versionada; cero REST nuevo.
Autorización: Managed Installation/token exchange para la superficie embebida, offline expirable para background jobs; linking tenant por intent de un solo uso.
Distribución: DEV sin decisión irreversible; PROD separada y Public Distribution sólo después de gates, inicialmente Limited Visibility si se desea un piloto controlado tras review.
Datos: PostgreSQL tenant-bound + RLS, tokens cifrados, inbox de webhooks y worker durable.
MVP: lectura sin PII de pedidos/productos/inventario/locations; PCD nivel 2 y WhatsApp quedan detrás de un gate explícito.
Actualización de patrones líderes — 31 de agosto de 2026
La documentación oficial vigente refuerza estas decisiones:
- Para apps renderizadas en Shopify Admin, Shopify recomienda token exchange y el template React Router oficial; no conviene reimplementar OAuth a mano.
- Las apps públicas deben diseñarse desde ahora para offline access tokens expirables, con refresh server-side para jobs y webhooks.
shop_domainidentifica el contexto externo, pero Commerce debe seguir imponiendoorganization_idy RLS en cada operación.- Webhooks no son una fuente de verdad suficiente: se requiere inbox idempotente, cola y reconciliación periódica mediante GraphQL.
- GraphQL Admin API es la superficie principal; REST no debe entrar en el diseño nuevo.
Fuentes: OAuth y rendimiento, autenticación, tokens, multi-tenancy, webhooks y reconciliación, suscripciones.