Modelo de Dominio
Entidades lógicas, límites de propiedad y qué modelos están persistidos hoy versus planificados para futuras migraciones de base de datos.
AACsearch usa una restricción de base de datos congelada: no se realizan cambios en el esquema de Prisma sin aprobación explícita. Esto significa que algunos conceptos de dominio existen como entidades lógicas implementadas mediante soluciones alternativas en tablas existentes, mientras que otros son modelos Prisma completamente persistidos.
Esta página mapea cada concepto de dominio a su estado actual de implementación.
Modelos persistidos (Prisma, activos hoy)
Organization (Organización)
El workspace principal. Todos los recursos de AACsearch pertenecen a una organización.
Organization
id String @id
name String
slug String @unique
plan String (resuelto a la matriz de características vía @repo/payments/lib/entitlements)
members[] Member[]
createdAt DateTimeLas organizaciones son aprovisionadas por el plugin de organización de Better Auth y son el límite de tenant para
todas las operaciones de búsqueda. Cada llamada a la API incluye organizationId; las lecturas entre organizaciones nunca están permitidas.
SearchIndex (Índice de búsqueda)
El recurso central de búsqueda. Hoy un SearchIndex representa un proyecto lógico (tienda + índice).
SearchIndex
id String @id
organizationId String (se convertirá en projectId cuando llegue la entidad Project)
userId String? (discriminador de propietario — el índice puede pertenecer a org o usuario)
slug String
collectionName String (versionado: {orgShortId}_{slug}_v{N})
aliasName String ({orgShortId}_{slug})
schemaVersion Int
status String
createdAt DateTimeSearchApiKey (Clave API de búsqueda)
Almacena claves API hasheadas para todos los tipos de claves. El texto plano se muestra una vez en la creación y nunca se almacena.
SearchApiKey
id String @id
indexId String
organizationId String
hashedKey String @unique (hash bcrypt — NUNCA almacenar texto plano)
prefix String (ss_search_* | ss_connector_* | ss_scoped_*)
scopes String[] (search | ingest | admin | connector_write)
allowedOrigins String[]
rateLimitPerMinute Int
expiresAt DateTime?
lastUsedAt DateTime?Importante: Los tokens de conector reutilizan SearchApiKey con scopes: ["connector_write"] y
prefix: "ss_connector_*". No existe una tabla ConnectorToken separada (solución alternativa por base de datos congelada).
SearchIngestBuffer (Buffer de ingestión)
La capa de durabilidad para la ruta de escritura. Las solicitudes se ponen en cola aquí; el trabajador en segundo plano drena hacia AACSearch.
SearchIngestBuffer
id String @id
organizationId String
indexId String
documents Json (array de ProductDocument)
status String (pending | processing | success | failed)
attempts Int @default(0)
errorMessage String?
processedAt DateTime?
createdAt DateTimeSearchRateLimitBucket (Bucket de límite de velocidad)
Rastreo de límite de velocidad con ventana deslizante por clave.
SearchUsageEvent (Evento de uso de búsqueda)
Filas de uso crudas escritas por recordSearchUsage() en cada solicitud de búsqueda.
SearchUsageEvent
id String @id
indexId String
orgId String
query String
resultCount Int
latencyMs Int
filters Json?
sort String?
userAgent String? (máximo 256 caracteres)
sessionId String?
referrer String?
createdAt DateTimeSearchConnectorSyncJob (Trabajo de sincronización del conector)
Seguimiento de trabajos de sincronización persistidos (además del mapa en memoria en connector-public.ts).
Modelos de conocimiento (7)
KnowledgeSpace, DataSource, IngestionJob, KnowledgeDocument, KnowledgeChunk, GraphNode, GraphEdge
Pertenecen al módulo de conocimiento (superficie de producto separada para preguntas y respuestas internas, no búsqueda en tienda). Consulte Conocimiento y administración para el uso.
Modelos de Wallet / IA (7)
AiWallet, AiWalletTransaction, AiQuotaReservation, AiUsageEvent, AiPricingRule, FxRate, WalletTopupOrder
Utilizados por el módulo de medición / billing-wallet de v0.6. Estado actual: en desarrollo activo.
Entidades solo lógicas (no persistidas aún)
Estas describen la forma de dominio prevista pero no tienen un modelo Prisma dedicado hoy. Crearlas requiere aprobación de descongelamiento de base de datos.
Project (Proyecto)
Project (lógico)
id String
organizationId String
name String
platform prestashop | bitrix | bitrix24 | api | demo
status String
defaultLocale String
currency String
allowedOrigins String[]Solución alternativa actual: 1 SearchIndex = 1 proyecto implícito. El organizationId en SearchIndex
actúa como el vínculo proyecto-organización.
Connector / SyncJob (Conector / Trabajo de sincronización, lógico)
Connector (lógico)
id String
projectId String
type prestashop | bitrix
status String
lastSeenAt DateTime
lastSyncAt DateTime
SyncJob (lógico)
id String
type full | delta | reindex | delete
status queued | running | succeeded | failed | cancelled
totalItems Int
processedItems IntSolución alternativa actual: Los tokens de conector usan SearchApiKey con el ámbito connector_write.
El seguimiento de trabajos de sincronización es en memoria en connector-public.ts (se pierde al reiniciar — aceptable para MVP
ya que los módulos CMS reintentarán en caso de fallo del latido).
WidgetConfig (Configuración del widget, lógica)
WidgetConfig (lógico)
projectId String
theme light | dark | auto
layout inline | modal
filters FacetConfig[]
sortOptions SortOption[]
trackingEnabled BooleanSolución alternativa actual: El widget se configura completamente a través de atributos data-* en la etiqueta <script>.
No existe control de versiones de borrador/publicado.
AnalyticsEvent (Evento de analíticas, lógico)
AnalyticsEvent (lógico)
projectId String
sessionId String
type search_query | zero_results | result_click | widget_open | filter_used
query String?
productId String?
position Int?
filters Json?
locale String
userAgent String?
referrer String?
timestamp DateTimeEstado actual: SearchUsageEvent captura filas crudas de recordSearchUsage(). Un AnalyticsEvent
dedicado con tipos de eventos del widget no está persistido aún.
Tokens de búsqueda con ámbito (sin estado)
Los tokens con ámbito no son un modelo de base de datos. Son afirmaciones firmadas con HMAC sin estado:
ss_scoped_{base64(JSON payload)}.{firma HMAC-SHA256}El payload incluye organizationId, indexId, scopedFilter (combinado con AND con los filtros del llamador),
y expiresAt opcional. La verificación está en packages/api/modules/search/lib/scoped-token.ts.
Discriminador de propiedad
SearchIndex admite dos propietarios:
- Propiedad de organización:
organizationIdestablecido,userIdnulo — el caso normal para workspaces multiusuario - Propiedad de usuario:
userIdestablecido,organizationIdnulo — para proyectos personales/demo
Ayudantes de consulta: listSearchIndexesByOwner, getSearchIndexByOwnerSlug, createSearchIndexByOwner
en packages/database/prisma/queries/search.ts.
Architecture
Monorepo layout, service boundaries, the layered backend principle, and the data flow for write and read paths.
Autenticación y Multi-tenencia
Cómo funcionan las organizaciones como workspaces, cómo fluye el contexto de sesión a través de la API y el modelo de seguridad para búsqueda multi-tenant.