El control plane es un único binario de Go, controlplane, configurado por un
pequeño conjunto de flags en su subcomando serve y un puñado de variables de
entorno — no un fichero de configuración desmesurado. Los valores por defecto se
eligen para fallar cerrado: binds en loopback, TLS activado, sin credenciales de
serie. Todo lo que figura a continuación está tomado de las propias definiciones de
comandos del binario y de su composition root; donde un ajuste no puede confirmarse en
el código fuente, no se lista aquí.
Los secretos que conectan fuentes reales y custodian claves reales permanecen en ficheros en poder del operador o en secretos montados referenciados por variable de entorno — nunca en el almacén. Para la ruta extremo a extremo ejecutable, consulta la guía de self-host; para el listado completo de flags, consulta la referencia de la CLI.
El subcomando serve
controlplane serve ejecuta el servidor HTTP REST/web y el servidor gRPC en un solo
proceso, con la consola web servida desde el mismo origen que la API. Estas son las
entradas de configuración habituales.
| Flag | Por defecto | Propósito |
|---|---|---|
--listen | 127.0.0.1:8443 | Dirección de escucha HTTP (API REST + consola web embebida). |
--grpc-listen | 127.0.0.1:8444 | Dirección de escucha gRPC (control-plane / ingesta del collector). |
--data-dir | $OLIVARES_DATA_DIR o ./olivares-data | Clave de firma de auditoría, material TLS y — para SQLite — el fichero del almacén. |
--engine | sqlite | Motor del almacén: sqlite o postgres. |
--dsn | vacío (fichero SQLite en el data dir) | Cadena de conexión del almacén. |
--checkpoint-interval | 1h | Con qué frecuencia se escribe un checkpoint de auditoría firmado sobre la cadena de cada tenant. 0 lo desactiva. |
--insecure | desactivado | Sirve HTTP/gRPC en texto plano. Solo para desarrollo en localhost. |
--seed-demo | desactivado | Carga un estate de ejemplo sintético. Se niega a arrancar en un bind que no sea loopback. |
TLS está activado por defecto. Sin --tls-cert/--tls-key suministrados, el motor
garantiza un certificado autofirmado en el directorio de datos una vez, por
adelantado, antes de que ningún listener acepte una conexión — de modo que tanto el
servidor HTTP como el gRPC usan el mismo certificado y ninguno cae a texto plano.
Cuando genera ese certificado, registra en el log el fingerprint SHA-256 para que los
clientes puedan confiar en él o fijarlo (pin).
--insecure es la única forma de servir texto plano, y la ruta gRPC falla
cerrado: fuera de --insecure, el servidor se niega a construir un listener en
texto plano en lugar de degradar silenciosamente. Úsalo solo contra 127.0.0.1
durante el desarrollo local.
--seed-demo aprovisiona un administrador de demo con una contraseña pública,
presente en el árbol de fuentes y datos de estate fabricados — solo para demos y
E2E. El motor se niega a arrancarlo si alguno de los listeners no es loopback. Usa un
directorio de datos desechable.
Un segundo nivel de flags gobierna las topologías distribuidas y de TLS mutuo —
--admin-dsn y --allow-privileged-db-role (Postgres), --grpc-client-ca (TLS mutuo
del collector) y --region/--known-regions (residencia de datos). Se cubren más
abajo y se listan al completo en la referencia de la CLI.
Variables de entorno
El motor lee un pequeño número de variables de entorno en el arranque. Las que figuran abajo están confirmadas en el composition root y el wiring.
Directorio de datos y fuentes
| Variable | Efecto |
|---|---|
OLIVARES_DATA_DIR | Directorio de datos por defecto cuando no se indica --data-dir (cae de vuelta a ./olivares-data). Contiene la clave de firma de auditoría, el material TLS y el fichero del almacén SQLite. Persístelo entre reinicios. |
OLIVARES_SOURCES_CONFIG | Ruta a un fichero JSON que conecta fuentes de observación reales, proveedores de roster de identidad y fuentes de documentos de conocimiento antes de que el motor arranque. |
OLIVARES_SOURCES_CONFIG es la única entrada a través de la cual se resuelven las
fuentes de señal no-demo y los proveedores de roster. Es la configuración portadora de
secretos del operador y se mantiene deliberadamente fuera del almacén. El motor la lee
en el arranque y registra cada fuente antes de que el runtime arranque.
El tratamiento es honesto en lugar de fail-fast. Una variable ausente, un fichero ilegible o con JSON inválido, o una lista de fuentes configurada-pero-vacía, todos ellos advierten y producen una configuración vacía — el motor nunca aborta el arranque. Una fuente sin configurar hace aflorar un aviso en lugar de tumbar el plane o fingir que funciona: sin nada conectado, el mapa de acceso simplemente se mantiene vacío. Para poblarlo, configura al menos una fuente — consulta conectar una fuente y, para la ruta cooperativa de Claude Code, conectar Claude Code.
Punto de decisión de autorización
El control de acceso nativo basado en atributos y basado en roles siempre gobierna. Un punto de decisión de políticas (PDP) externo, cuando se selecciona, es una capa adicional solo-restrictiva que únicamente puede estrechar la decisión que el RBAC integrado ya ha tomado — nunca ampliarla.
| Variable | Efecto |
|---|---|
OLIVARES_PDP_ENGINE | Selecciona el PDP externo: cedar, opa o none (vacío/none = solo ABAC nativo). |
OLIVARES_PDP_CEDAR_FILE | Motor Cedar: ruta al fichero de políticas del operador. |
OLIVARES_PDP_OPA_URL / _OPA_PATH / _OPA_TOKEN | Motor OPA: URL base, ruta de decisión y bearer token para el endpoint del Open Policy Agent. |
Dos adaptadores se sitúan tras una misma juntura — un evaluador Cedar embebido (la ruta
en Go puro) y un adaptador OPA-sobre-HTTP. Si OLIVARES_PDP_ENGINE selecciona un motor
pero su configuración es inválida (un fichero Cedar ilegible, un target OPA
malformado), el motor desactiva únicamente el PDP externo, mantiene el motor ABAC
nativo y el RBAC haciendo cumplir las reglas, y lo registra con contundencia. Un fichero
de políticas roto nunca deja peticiones sin gobernar y nunca tumba el plane. Para el
modelo deny-by-default, consulta gobernanza.
Clave de firma de auditoría
El ledger de auditoría es append-only, encadenado por hash y anclado por checkpoints firmados con Ed25519. La clave de firma por evento se resuelve en el arranque, fallando cerrado para cada fuente custodiada.
| Variable | Efecto |
|---|---|
OLIVARES_AUDIT_SIGNING_KEY | Clave de firma aprovisionada por el cliente, en base64, inline. |
OLIVARES_AUDIT_SIGNING_KEY_FILE | Ruta a un secreto montado que contiene la clave (preferido — el valor nunca entra en el entorno del proceso). |
OLIVARES_KEY_CUSTODY | Postura de custodia declarada (byok o cmek). Un arranque cuya custodia real de la clave no coincide con la declarada es rechazado. |
Sin ninguna de estas establecida, la clave se acuña en el primer arranque en el
directorio de datos — el fallback honesto para nodo único / desarrollo. Compartir una
única clave entre réplicas (mediante el valor de entorno o un secreto montado) es
obligatorio para alta disponibilidad: de lo contrario, cada nodo acuña la suya propia y
el ledger se bifurca en el failover. La firma por evento siempre permanece on-box. La
custodia envuelta por KMS (clave gestionada por el cliente) es una postura adicional
configurada a través de OLIVARES_KEY_WRAP; consulta la
referencia de la CLI.
Selección del almacén
El motor selecciona su almacén a partir de --engine.
| Motor | Cuándo usarlo | Notas |
|---|---|---|
sqlite (por defecto) | Binario único, nodo único, instalaciones air-gapped. | Almacén embebido en Go puro, cero dependencias externas. Sin --dsn, el fichero del almacén reside en el directorio de datos. |
postgres | Despliegues multi-tenant y de escalado horizontal. | Añade aislamiento de tenant por row-level-security. Requiere un rol de aplicación de mínimo privilegio. |
SQLite es el valor por defecto y no necesita ningún servicio externo — es el almacén listo para air-gap, de cero dependencias, para la topología de nodo único, y el que ejecuta el despliegue Docker Compose de un solo comando. Pasa a Postgres cuando necesites aislamiento multi-tenant o escalado horizontal, no antes.
Elegir postgres opta por el respaldo de row-level-security que aísla los tenants. El
motor se niega a arrancar contra un superusuario de Postgres o un rol BYPASSRLS —
lo cual desactivaría ese respaldo — a menos que --allow-privileged-db-role sobrescriba
explícitamente la salvaguarda (solo single-tenant / desechable). Para lecturas de
sistema completas entre tenants (listado de organizaciones, cobertura de checkpoints
multi-tenant) proporciona un rol de administración NOSUPERUSER BYPASSRLS dedicado
mediante --admin-dsn; sin él, esas lecturas se ejecutan limitadas por RLS y pueden
devolver vacío. OLIVARES_DB_MAX_CONNS acota el pool de aplicación por nodo.
Multi-tenancy y residencia
Una única instancia es multi-tenant por construcción en Postgres, con row-level
security aislando los datos de cada tenant. La residencia de datos se superpone encima
mediante --region.
- Región única (por defecto, sin
--region): sin aplicación de residencia. - Acotada por región (
--region eu,--region us, …): la instancia sirve solo a los tenants fijados a su región de origen y deniega el acceso entre regiones fallando cerrado.--known-regionslista los códigos de región válidos en todo el despliegue; el pin de un tenant debe ser uno de ellos, y una configuración de región malformada falla el arranque antes de que se abra el almacén.
Checkpoints de auditoría
--checkpoint-interval controla con qué frecuencia se escribe un checkpoint firmado
sobre la cadena de cada tenant (por defecto 1h; 0 lo desactiva). Se escribe un
checkpoint final en el apagado limpio antes de que el almacén se cierre, de modo que la
cadena queda anclada tanto en el apagado como en el intervalo. Consulta
verificar una release para saber cómo se verifica la
cadena firmada aguas abajo.
Valores por defecto seguros
Estas posturas están en vigor sin configuración alguna más allá de serve. Son la
postura por defecto del producto, no un endurecimiento opcional.
| Área | Por defecto | Qué significa |
|---|---|---|
| Credenciales | Ninguna de serie | Sin nombre de usuario ni contraseña por defecto. En el primer arranque sin usuarios, el motor acuña un token de configuración de un solo uso y lo imprime únicamente en la salida estándar — nunca en los logs. |
| Transporte | TLS activado | HTTP y gRPC sirven sobre TLS; se genera un certificado autofirmado en el directorio de datos si no se suministra ninguno, y su fingerprint se registra en el log. |
| Dirección de bind | Loopback | --listen y --grpc-listen toman por defecto 127.0.0.1. La accesibilidad fuera del host es una decisión deliberada del operador. |
| Modo texto plano | Desactivado | --insecure es la única forma de servir texto plano, y la ruta gRPC falla cerrado. Solo para desarrollo en localhost. |
| Seeding de demo | Desactivado | --seed-demo está desactivado y se niega a cualquier bind que no sea loopback, porque acuña un administrador de demo con contraseña pública. |
| Telemetría a casa | Desactivada | El motor no llama a casa (phone home). Las conexiones salientes existen solo hacia las fuentes que configures — que es lo que hace posible un control plane air-gapped con cero egress. |
Los binds en loopback significan que el motor no es alcanzable fuera del host hasta que
los cambies. Cuando lo publiques — pongamos por caso mapeando un puerto del host en
Docker Compose — TLS ya está activado para protegerlo; no emparejes un bind publicado
con --insecure. En una instalación nueva, el motor imprime un bloque
FIRST-BOOT SETUP en la salida estándar con el token de configuración de un solo uso
(léelo de los logs del contenedor bajo Compose); el administrador lo usa para crear el
primer usuario y, a continuación, se autentica.
Para saber qué observa el producto, dónde gobierna y dónde la cobertura es escalonada, lee honestidad y límites.