Modelo de dominio
El modelo de datos de Inbox Autónomo tiene nueve recursos de primer nivel más algunas tablas internas (tokens revocados, certificados de cliente revocados). Todo es multi-tenant por Workspace — cada fila pertenece a exactamente un workspace, y cada solicitud a la API se filtra automáticamente por el workspace derivado del claim sub del JWT.
Diagrama de relaciones
Workspace
│
┌───────────┬─────────┼─────────┬───────────┐
▼ ▼ ▼ ▼ ▼
Inbox Email Agent Webhook SystemEvent
│ │ │ │
│ │ │ └── WebhookDelivery
│ │ │
│ └── AgentRun ──┘
│
└── (Agent asociado opcional)
Recursos de un vistazo
| Recurso | Propósito | Ciclo de vida |
|---|---|---|
| Workspace | Raíz multi-tenant, refleja una cuenta Kobana | Creado vía el hook de aprovisionamiento de kobana-app |
| Inbox | Una dirección de correo enrutable + política de procesamiento | Creado vía API; se desactiva en lugar de eliminarse |
| Un mensaje recibido + estado de procesamiento | Creado por la ingesta de SES o por POST /emails | |
| Agent | Una configuración de LLM (modelo, system prompt, skills) | Creado vía API |
| AgentRun | Una única ejecución de un agente sobre un correo | Creado por el worker; solo lectura vía API |
| Webhook | Una suscripción a uno o más slugs de SystemEvent | Creado vía API |
| WebhookDelivery | Un intento de hacer POST de un payload de webhook | Creado por el dispatcher; solo lectura vía API |
| SystemEvent | Un registro inmutable de un evento de dominio | Emitido por handlers/workers; solo lectura vía API |
Campos compartidos
Todo recurso expone:
| Campo | Tipo | Notas |
|---|---|---|
id | UUID v4 | Identificador interno. |
created_at | ISO 8601 | Establecido en la creación. |
updated_at | ISO 8601 | Actualizado por Prisma en cada cambio. |
deleted_at | ISO 8601 | null | Marcador de soft-delete. |
Algunos recursos exponen adicionalmente:
| Campo | Tipo | Notas |
|---|---|---|
external_id | UUID v4 | Identificador estable del sistema de origen (Workspace, Inbox, Agent). |
metadata | JSON | Metadata gestionada por el sistema. |
custom_metadata | JSON | Formato libre, nunca inspeccionado por el sistema. |
Soft delete
Los recursos que admiten eliminación son soft-deleted: se establece deleted_at, pero la fila permanece en Postgres. Las queries filtran por WHERE deleted_at IS NULL mediante un middleware de Prisma. Recrear una fila que entra en conflicto con una soft-deleted (p. ej. el mismo email en Inbox) devuelve 409 conflict — restaura el original vía herramientas internas en lugar de recrearlo.
Idempotencia y unicidad
| Recurso | Constraint único |
|---|---|
| Workspace | external_id |
| Inbox | email (global, no por workspace) |
message_id (el messageId del SES) | |
| Agent | external_id |
| Webhook | — (el label no es único) |
La unicidad de Email.message_id es lo que hace idempotente al handler de ingesta de SES: SNS puede reintentar la misma notificación, pero el segundo insert choca con la unique constraint y el handler devuelve 200 de inmediato.