Cuotas y costes — los topes de uso y de gasto
El motor de cuota cubre tres géneros: la cuota de tokens y la cuota de almacenamiento (Phase 207) más la cuota de coste (Phase 216, hold-and-settle sobre la matemática del dinero real). Las cuotas son la herramienta del operador para los topes de uso en …
El motor de cuota cubre tres géneros: la cuota de tokens y la cuota de almacenamiento (Phase 207) más la cuota de coste (Phase 216, hold-and-settle sobre la matemática del dinero real). Las cuotas son la herramienta del operador para los topes de uso en instalaciones multiusuario; vinculan a cada usuario con una cuota configurada — administradores incluidos — y una cuota sin configurar = ilimitado (fail-open: cero cambio de comportamiento para las instalaciones existentes).
Función Community (la herramienta del operador). Fuentes:docs/QUOTAS.md(Phase 207 + 216),docs/MODEL_COSTS.md,docs/API.md(la sección Costs, quotas, and per-user model policy). Filas de procedencia:FACT-CENSUS.mdF-QUOTA-1.
Las invariancias de fondo
- Ningún segundo contador. La verdad del consumo (tokens/coste) queda en el ledger existente
WorkspaceTokenUsage(packages/server/src/services/quotaService.ts).QuotaBalance/QuotaHold/QuotaReset= estado derivado y anclado, nunca una tabla de conteo. - Reset = el ancla del ledger. Un reset escribe de nuevo
QuotaReset(kind, at)que acota la ventana rodante — el historial de uso/coste nunca se borra ni se anula. - La barrera a nivel de servicio, pre-turn — NO el middleware de auth (el control necesita datos del dominio, no la forma de la solicitud). Las barreras arrancan antes de la primera llamada LLM en el orchestrator y antes de la ingesta en las vías de carga.
- Fail-open para cuotas sin configurar. La cadena de resolución termina en "ilimitado" cuando nada está configurado (D-08).
- La matemática del dinero es Decimal→cents. TODA la aritmética de costes pasa por
Prisma.Decimaly aterriza en cents enteros — nunca float (costQuotaService.ts, la doctrina COST-01).
La cadena de resolución (D-08)
| Nivel | Fuente | Notas |
|---|---|---|
| 1 | El override por usuario | User.tokenQuotaLimit / User.storageQuotaGb / las filas de coste por usuario — vía PUT /api/quota/:userId (admin) |
| 2 | El preset de la instalación | Las claves SystemConfig (abajo) — DB > ENV > predeterminado |
| 3 | Ilimitado | El valor centinela "0" / "" / unset = no configurado → fail-open |
Las claves de configuración (SystemConfig, editables vía Settings)
| Clave | Predeterminado | Significado |
|---|---|---|
QUOTA_TOKEN_DEFAULT | el centinela unset | El tope de tokens de la instalación para cada usuario sin override |
QUOTA_STORAGE_GB_DEFAULT | el centinela unset | El tope de almacenamiento de la instalación (GB) |
QUOTA_COST_EUR_DEFAULT | el centinela unset ("0"/"" = ilimitado) | El tope de COSTE de la instalación — cadena decimal EUR |
QUOTA_COST_FALLBACK_INPUT_CENTS_PER_1M | un suelo integrado distinto de cero | La tarifa de respaldo SC-4 para modelos SIN precio — input, cents enteros por 1M tokens |
QUOTA_COST_FALLBACK_OUTPUT_CENTS_PER_1M | un suelo integrado distinto de cero | La tarifa de respaldo SC-4 para modelos SIN precio — output |
La doctrina SC-4: un modelo sin precio nunca evita la cuota de coste — las tarifas de respaldo se aplican con warn-once (warnFallbackOnce): un modelo sin precio jamás puede resultar gratis.
Las cuotas de tokens (quotaService.ts)
resolveTokenQuota(userId)→{ limit, source }—limit: null= ilimitado;sourcedice qué nivel del D-08 decidió.- La ventana rodante parte de la última ancla
QuotaResetpara(userId, kind: "token")(o de la época si nunca se reajustó); el uso en ventana se suma desde el ledgerWorkspaceTokenUsage. - Superar la cuota lanza
QuotaError(status+payload) — el campoquotadel payload es el contrato que frontend, widget y los handlers de conectores leen. No hay middleware que burler: la barrera corre DENTRO de la vía del servicio.
Las cuotas de coste (costQuotaService.ts, Phase 216) — hold-and-settle
La reserva en dos fases:
- Reserve (antes de la llamada LLM) —
reserveCostQuota(principal, estimateCents)ejecuta UNA transacción interactiva: unupdateManycondicional cuyo predicado (spentCents + estimate <= limitCents) Postgres evalúa con row-lock, de modo que N barreras concurrentes se SERIALIZAN en lugar de todas pasar sobre un control viejo (SC-2) + el insert deQuotaHolden la misma transacción. - Settle (al segmento de uso) —
settleCostHoldcierra el hold y reembolsaestimate − actual. El overshoot en vuelo (actual > estimate) = la ventana aceptada — ningún kill de un stream en curso. - En reposo vale la invariancia:
settledSpent + Σ(lead abiertas) ≤ límite. - La fuente del precio por fila: el snapshot FROZEN de Phase 203 donde existe; si no, las tarifas de respaldo SC-4 (warn-once); las filas en una moneda fuera de la dominante se tarifican igual (nunca silenciosamente gratis, jamás excluidas).
- Reset —
resetCostQuotaescribe la anclaQuota(kind "cost")y RECONSTRUYE el saldo desde ledger-suma + holds abiertos (D-02).
Las cuotas de almacenamiento
checkStorageQuota / resolveStorageQuota aplican el override por usuario storageQuotaGb, el preset QUOTA_STORAGE_GB_DEFAULT o lo ilimitado. Las barreras arrancan en las vías de carga antes del dispatch al collector.
El principal para los widgets
Los visitantes anónimos del widget no son usuarios — resolveWidgetQuotaPrincipal liga el tráfico widget al principal de la organización del widget: el consumo del widget pesa sobre la cadena de cuota de la organización, no sobre identidades por visitante.
Dónde arrancan las barreras (los sitios de consumo)
| Superficie | Barrera | Archivo |
|---|---|---|
| Chat (JWT, widget proxy, conectores — un orchestrator) | barrera de tokens + coste pre-turn / pre-LLM | packages/server/src/agent/orchestrator.ts |
| Carga de documento | la barrera de almacenamiento pre-ingest | packages/server/src/routes/uploads.ts, routes/documents.ts |
| El barrido de reset | el reset horario de las cuotas de tokens (pg-boss cron: initQuotaResetScheduler) | services/quotaResetJob.ts |
| Las lecturas self-service | GET /api/quota/me, rollups, reset manual | routes/quota.ts |
El flujo del operador
- El predeterminado de la instalación — la UI de Settings → las claves
QUOTA_*(oPUT /api/system/settings). - El override por usuario —
PUT /api/quota/:userId(admin) o la UI de cuota. - Los precios por usuario — la familia COSTS (Phase 209:
/api/users/:userId/pricing, las claves de proveedores propios bajo/api/me/provider-keys) alimenta el mismo motor. - El reset manual en cualquier momento:
POST /api/quota/:userId/reset; el barrido horario sostiene el estado estacionario.
Los precios de los modelos (MODEL_COSTS)
Configuración: Settings → Providers → elegir el proveedor → la acción pricing del modelo → el coste por-1M-token input/output (p. ej. 1.50 y 6.00) + la moneda → Save. La fórmula: cost = tokens × rate, calculada server-side en cada escritura de uso, con el snapshot congelado al tiempo de ejecución (un cambio posterior de tarifa nunca reescribe el historial). Monedas: USD, EUR, GBP, JPY, CNY, INR — totales por moneda, ninguna conversión en v1. N/A = precio sin configurar (los modelos cloud unset; la UI muestra "N/A" — la administración debe configurar); $0.00 = explícitamente gratis (los modelos locales/Ollama se rellenaron a 0 en la migración; override posible). Los límites de la v1: ninguna conversión entre monedas; solo el coste de la iteración principal (las sub-pipelines tool/MCP/synthesis excusas); el coste está disponible en el evento done (no a mitad de stream).
La referencia de endpoints
La tabla completa vive en API reference → Costs, quotas, and per-user model policy.
Véase también
- Scaling — el comportamiento de las cuotas bajo despliegue multi-instancia
Esta guía cubre la superficie operativa de las cuotas y los costes; la profundidad técnica vive en el post gemelo:
Provenance
| Sección | Fuente |
|---|---|
| Invariancias / la cadena de resolución / las claves | docs/QUOTAS.md (core invariants, D-08, las claves — Phase 207/203) — F-QUOTA-1 |
| Las cuotas de coste / hold-and-settle | docs/QUOTAS.md (§ Cost quotas — Phase 216) + costQuotaService.ts |
| Los precios de los modelos | docs/MODEL_COSTS.md (Phase 203/209/216) |
| Los sitios de las barreras | docs/QUOTAS.md (§ Where the gates fire) |
---
Referencia operativa — Simmetric Chat v0.28.1 (documentos actualizados el 2026-10-02, SHA del censo `aca5b8ff`).