SMART CONNECTION
Blueprint · Marketplace SMC
Documento 07 de 37

Architecture

Stack técnico · deploy · escalabilidad · event-driven · monorepo modular.

Versión
1.0
Fecha
2026-05-25
Autor
TechLead + Architect
Status
🟢 Activo
Tabla de contenidos

Índice

  1. Mapa interactivo HLA · Visio-style03
  2. Procesos dinámicos · 5 escenarios04
  3. Arquitectura alto nivel · diagrama clásico05
  4. Stack técnico decidido06
  5. Estructura monorepo05
  6. Event-driven · cómo funciona06
  7. Multi-tenancy técnico (RLS)07
  8. Deploy · ambientes · CI/CD08
  9. Observabilidad · LLMOps09
  10. Seguridad operativa10
  11. Escalabilidad técnica · cuándo refactorizar11
  12. ADRs · decisiones registradas12

00Mapa interactivo HLA · Visio-style

Diagrama vivo de la arquitectura Marketplace SMC. Click en cualquier bloque para ver detalle · descripción · stack · owner · canales · docs relacionados. Filtros arriba para aislar el flujo de un canal específico (MeLi · D2C · MP · B2B). Hover destaca la ruta end-to-end que toca ese componente. Zoom con la rueda + ⌘/Ctrl o con los botones · arrastrá para hacer pan.

Marketplace SMC · High Level Architecture
Stack Next.js 16 · Supabase · Channel Adapter Pattern · IA fallback chain
100%
FRONTEND BACKEND · CORE DATA · SUPABASE INTEGRACIONES · CANALES SERVICIOS EXTERNOS OAuth Ticket refresh 6h USER · ACTOR Operador marketplace.smconnection.cl USER · ACTOR Cliente final B2C · B2G · B2B CDN · EDGE CloudFront + Amplify auto-deploy push a main cert ACM · WAF FRONTEND · APP Next.js 16 · App Router React Server Components Tailwind v4 + Radix + @smc/ui BACKEND · API API Routes Server Actions Zod validation JWT middleware PATTERN · CORE Channel Adapter Pattern interfaz uniforme por canal MeLi · D2C · MP · B2B orders · stock · pricing sync AI · ORCHESTRATOR Cerebro IA cross-data analytics SSE streaming chat opportunity scoring SCHEDULER Cron Jobs refresh MeLi 6h sync MP diario cache cleanup 7d DATA · AUTH Supabase Auth JWT · 2FA · sesiones tenant_id en claims DATA · CORE Postgres + RLS multi-tenant · 20+ tablas · pg_cron PITR 30d · daily snapshots DATA · BLOB Supabase Storage imágenes productos · DTE PDF signed URLs · RLS por tenant CANAL · MELI Mercado Libre OAuth 2.0 PKCE tokens cookies httpOnly PolicyAgent aware CANAL · CHILECOMPRA Mercado Público Ticket auth · API REST licitaciones diarias budget alerting CANAL · D2C Storefront propio app cliente operador checkout integrado ADS Meta · Google CANAL · B2B B2B custom REST + API key white-label cliente empresa PAGO MercadoPago pasarela MeLi + D2C webhook events PAGO WebPay Plus Transbank · D2C débito + crédito Chile FACTURACIÓN Open Factura DTE 33 · 39 · 61 SII auto-emisión LOGÍSTICA Couriers Chilexpress · Starken tracking webhooks IA · FALLBACK CHAIN Groq → Gemini → DeepSeek via OpenRouter routing NUNCA Claude (regla Hoku) OBSERVABILIDAD Sentry · PostHog · CW errores · funnels · infra LLMOps log mkt_api_logs

Tip: click en un bloque para ver detalle · Esc cierra · arrastra el canvas para hacer pan · ⌘/Ctrl + scroll para zoom.

💡 Supplier Adapter Pattern · ADR-0003

Análogo al Channel Adapter del HLA principal · existe un Supplier Adapter Pattern para integrarse con proveedores externos que despachan directamente al cliente final (modo dropshipping · Doc 02 BBP P13).

Interfaz uniforme: SupplierAdapter con métodos syncCatalog() · checkStock(sku) · createPurchaseOrder(items, shipTo) · trackShipment(po_id) · handleReturn(order_id). Cada proveedor implementa según su API.

Supplier Adapter Pattern · ADR-0003 Interface única · N implementaciones · 4 auth modes Backend Core · Next.js orchestrator getSupplierAdapter(supplierId) interface SupplierAdapter syncCatalog() · checkStock() · createPurchaseOrder() trackShipment() · handleReturn() · ping() API_KEY mode REST API estándar Header X-API-Key ej: proveedor con SDK ~70% proveedores OAUTH mode OAuth 2.0 flow Refresh token ej: marketplace mayorista ~15% proveedores EMAIL automated Email parser IMAP PDF/CSV adjuntos ej: proveedor sin API ~10% proveedores WHATSAPP biz WhatsApp Business API Templates aprobados ej: pyme local ~5% proveedores Postgres · mkt_suppliers + mkt_supplier_products + mkt_purchase_orders RLS por tenant_id · pg_notify on stock_changed

Beneficio: agregar proveedor nuevo = 1 archivo nuevo + entry en registry. NO refactor del core. Implementación en repo: lib/adapters/suppliers/{supplier-x}.ts. Tests en __tests__/adapters/suppliers-registry.test.ts.

Trigger migración a stock local: SQL materialized view mkt_dropship_migration_candidates detecta SKUs con revenue >$10M CLP en 60 días · sugiere comprar stock para subir margen 15-25pp. Ver Doc 05 §12 schema completo + Doc 21 §03c estrategia migración.

00bProcesos dinámicos · 5 escenarios

Cómo recorre el sistema un caso real paso a paso. Seleccioná un escenario (A · B · C · D · E) para ver su pipeline horizontal con etapas y pasos integración (INT-XXX). Click en un paso para ver descripción · stack · sample payload · errores comunes · docs relacionados.

Tip: cambiar escenario re-renderiza el pipeline · click en cualquier INT-XXX abre detalle del paso · Esc cierra.

01Arquitectura alto nivel

Operador (Browser) marketplace.smconnection.cl Next.js 16 React Server Components API Routes + Server Actions Tailwind v4 + Radix Domain Services Layer orders · inventory · finance · sourcing · ai · analytics + Event Bus interno (PG NOTIFY · pg_cron) + Channel Adapter Pattern Channel Adapters MeLi · MP · D2C · B2B Falabella · Cencosud (futuros) interfaz ChannelAdapter Supabase Postgres Row Level Security · tenant_id en todas las tablas pgvector (embeddings IA) · pg_cron (jobs) Auth (JWT · OAuth) · Storage (imágenes · DTE XML) Servicios externos Open Factura · MercadoPago WebPay · Chilexpress · Starken Groq IA · OpenRouter Sentry · CloudWatch APIs canales api.mercadolibre.com api.mercadopublico.cl developers.falabella.com AWS Amplify (Next.js auto-deploy) main → PRD · develop → QAS · push-to-deploy · GitHub Actions CI

01bArquitectura v5 · Opportunities System

USUARIO en /dashboard/oportunidades Tabla top-50 oportunidades · transparencia · sin saber qué hay debajo 6 · UI · render directo · cero LLM Tabla scores + filtros + transparencia 5 · API /api/opportunities/list · 1 SQL query · cero LLM 4 · Smart Cache Supabase · max 1000 filas · TTL diferenciado 3 · Scoring Engine · 6 señales · math puro JS/SQL · cero LLM 2 · Filters · whitelist + blacklist (libros · usados · sin stock) 1 · Sources gratis (SoloTodo · Mercado Público · OFF · BCentral)

Scoring Engine · 6 señales

#SeñalCómo se midePeso
1Multistore presence# stores con mismo SKU canónico25%
2Price spread(max - min) / min · >15% = oportunidad25%
3Availability rate# stores con is_available / total15%
4Price stabilitybaja varianza precio 7d (demanda sostenida)15%
5Category premiumtabla fija mkt_category_premium10%
6MeLi presenceproducto también en store MeLi (id=260)?10%
🎯 Total score 0-10 · 1 SQL query · cero tokens LLM

02Stack técnico decidido

CapaTecnologíaRazón decisión
FrontendNext.js 16 + React 19 + TypeScriptStack SMC actual · SSR · App Router
UI library@smc/ui (Radix + Tailwind v4 + tv)Estándar interno SMC
BackendNext.js API Routes + Server ActionsMonorepo simple · 1 deploy
BDSupabase Postgres (pgvector + pg_cron)Multi-tenant RLS nativo · escala
AuthSupabase AuthJWT + roles · email + OAuth
StorageSupabase StorageCDN incluido · XML DTE · imágenes
Event BusPostgreSQL NOTIFY + pg_cron + Inngest (opcional)Sin Kafka/Redis al inicio · simple
IA principalGroq Llama 3.3 70BVelocidad + costo · función calling
IA fallbackOpenRouter (Llama 4 Scout · Gemini Flash · DeepSeek)Regla SMC: nunca Claude como fallback
DTEOpen Factura APICompliance SII turnkey
Pasarela pagoMercadoPago Empresa + WebPay PlusCoverage máximo Chile
CouriersChilexpress · Starken · Bluexpress APIsNacional
DeployAWS Amplify (Next.js auto-build)Stack SMC actual · push-to-deploy
ObservabilidadSentry + Supabase Logs + custom mk_api_logsErrors + perf + LLMOps
TestingVitest (unit/integration) + Playwright (e2e)Estándar SMC
CI/CDGitHub ActionsLint · TSC · test · build · deploy
EmailResend o PostmarkTransactional · DTE PDFs

03Estructura monorepo

smc-marketplace-hub/
├── apps/
│   ├── web/                    # Next.js app (frontend + API)
│   │   ├── app/
│   │   │   ├── (auth)/         # login · signup
│   │   │   ├── (dashboard)/    # cockpit operador
│   │   │   │   ├── inventory/
│   │   │   │   ├── channels/
│   │   │   │   │   ├── meli/
│   │   │   │   │   ├── mp/
│   │   │   │   │   ├── d2c/
│   │   │   │   │   └── b2b/
│   │   │   │   ├── orders/
│   │   │   │   ├── finance/
│   │   │   │   ├── cerebro/
│   │   │   │   └── analytics/
│   │   │   └── api/
│   │   │       ├── webhooks/   # meli · mp · webpay · etc.
│   │   │       ├── cron/       # refresh-tokens · mp-tenders
│   │   │       └── v1/         # APIs internas REST
│   │   └── package.json
│   └── storefronts/            # marcas propias futuras
│       └── marca-1/            # primera marca migrada al Hub
│
├── packages/
│   ├── core/                   # @smc/core · dominio puro
│   │   ├── inventory/
│   │   ├── orders/
│   │   ├── finance/
│   │   ├── events/             # Event bus interno
│   │   └── tenants/
│   ├── channels/               # @smc/channels · adapters
│   │   ├── _interface.ts       # interfaz ChannelAdapter
│   │   ├── meli/
│   │   ├── mp/
│   │   ├── d2c/
│   │   ├── b2b/
│   │   └── falabella/
│   ├── ui/                     # @smc/ui (existente)
│   ├── shared/                 # @smc/shared · types · utils
│   ├── ai/                     # @smc/ai · Cerebro · Groq client · prompts
│   └── billing/                # @smc/billing · DTE · Open Factura
│
├── supabase/
│   ├── migrations/             # SQL versionado
│   ├── seed/                   # data fixtures dev
│   └── functions/              # Edge Functions opcional
│
├── .github/
│   └── workflows/              # CI/CD
│
└── docs/                       # blueprint + ADRs (estos docs)
🎯 Por qué monorepo

Compartir tipos TS entre frontend y backend · 1 deploy · 1 versión de toda la app. Si futuro necesita microservicios · cada package se extrae a su propio repo sin refactor.

04Event-driven · cómo funciona

Cada operación significativa emite un evento. Los módulos suscritos reaccionan automático. Esto evita acoplamiento (módulo finance no llama a inventory · escucha eventos).

orders.create() emite: order.created Event Bus PG NOTIFY + pg_cron + mk_evt_operations (event store) + retry · DLQ · idempotency 📦 inventory.reserve reserva stock 📒 finance.create-asiento asiento contable 📤 fulfillment.queue task despacho 🧮 dte.issue factura/boleta 🤖 ai.analyze (async)
💡 Implementación pragmática

No usar Kafka/Redis al inicio · es overkill. Usar Postgres NOTIFY + tabla mk_evt_operations como event store + pg_cron para retries. Cuando volumen pase 10K eventos/día evaluar Inngest o Trigger.dev.

05Multi-tenancy técnico · Row Level Security

Setup RLS Postgres

-- En cada query, el server setea el tenant context
SET app.current_tenant = '<tenant-uuid>';

-- Policy aplicada a TODAS las tablas (excepto mk_tenants y mk_users)
CREATE POLICY tenant_isolation ON mk_products
  USING (tenant_id = current_setting('app.current_tenant')::uuid)
  WITH CHECK (tenant_id = current_setting('app.current_tenant')::uuid);

ALTER TABLE mk_products ENABLE ROW LEVEL SECURITY;
ALTER TABLE mk_products FORCE ROW LEVEL SECURITY;

Flujo request

  1. Operador hace login · recibe JWT que incluye tenant_id
  2. Cada request incluye header X-Tenant-Id
  3. Middleware Next.js valida JWT + tenant_id match con permisos del usuario
  4. Middleware setea SET app.current_tenant = ? en conexión Postgres
  5. Cualquier query subsiguiente está auto-filtrada por RLS
  6. Imposible (técnicamente) que tenant A vea data de tenant B aunque haya bug en código aplicación
✅ Beneficio defensa en profundidad

Aunque un dev olvide filtrar WHERE tenant_id = ? · RLS Postgres bloquea. Defensa de último nivel.

06Deploy · ambientes · CI/CD

AmbienteBranchURLAuto-deploy
Local(working tree)localhost:3000npm run dev
QASdevelopqas.marketplace.smconnection.clpush develop → AWS Amplify
PRDmainmarketplace.smconnection.clpush main → AWS Amplify

Pipeline CI/CD

push branch → GitHub Actions:
   1. install (cache pnpm)
   2. lint (eslint)
   3. type-check (tsc --noEmit)
   4. unit tests (vitest run)
   5. build (next build)
   6. integration tests (vitest --integration)
   7. e2e smoke (playwright · solo en main)
   8. deploy (auto vía Amplify webhook)
   9. health check post-deploy (curl /api/health)
   10. rollback automático si health falla

Migraciones BD

07Observabilidad · LLMOps

TipoHerramientaQué se mide
Errores producciónSentryExcepciones JS · stack traces · usuarios afectados
Performance APIsSentry Performance + Supabase LogsLatencia p50/p95/p99 por endpoint
API externa llamadasmk_api_logs (custom)Endpoint · status · latencia · payload · source
Eventos operativosmk_evt_operationsTodo evento dominio (audit + IA contexto)
LLMOpsCustom log Groq callsTokens · costo · latencia · prompt version · score
UptimeUptimeRobot o BetterStack/api/health ping cada 1 min
BD performanceSupabase dashboardQueries lentas · index usage · pool conexiones
⚠️ Alertas críticas
  • Error rate > 1% en 5 min → Sentry alert
  • Webhook MeLi/MP fallido 3+ veces → email operador
  • DTE rechazado por SII → alerta crítica + Slack
  • Costo Groq diario > $5K CLP → review prompts
  • BD CPU > 80% sostenido → escalar plan Supabase

08Seguridad operativa

09Escalabilidad técnica · cuándo refactorizar

MétricaThresholdAcción
Órdenes/hora por tenant> 500Mover sync canales a workers async (Inngest)
Tamaño BD> 50 GBPlan Supabase Team · evaluar particionado tablas hot
p95 API latency> 800ms sostenidoCache Redis · query optimization · índices
Concurrentes activos> 100Pool conexiones PG · escalar app server
Tenants activos> 50Considerar BD por tier (free/pro/enterprise)
Build time> 5 minTurborepo cache · split apps
Costo Groq mensual> $100K CLPCaching IA · prompt optimization · evaluar modelo más chico
💡 Filosofía Cerebro

No premature optimization · Supabase + Next.js + Amplify aguanta cómodo hasta 500K órdenes/mes. Cuando llegue · refactorizar con data real, no asunciones.

10ADRs · decisiones registradas

Architectural Decision Records · cada decisión clave queda en docs/adrs/NNNN-titulo.md

#DecisiónStatus
ADR-001Single source of truth: 1 BD Postgres con tenant_idAceptado
ADR-002Channel Adapter Pattern para canales externosAceptado
ADR-003Event-driven con PG NOTIFY (no Kafka/Redis MVP)Aceptado
ADR-004Monorepo (no microservicios) hasta >500 órdenes/hAceptado
ADR-005Asientos contables auto · NO entrada manualAceptado
ADR-006Nexport como proveedor importador (no comex propio)Aceptado
ADR-007Open Factura para DTE (no SII directo)Aceptado
ADR-008Groq como IA primaria · OpenRouter fallbackAceptado
ADR-009RLS Postgres como defensa de aislamiento multi-tenantAceptado
ADR-010Primera marca propia migra back-office al Hub · storefront sigue separadoPropuesto