Seguridad
Última actualización: 2026-05-05
Esta página tiene dos lectores. Un comprador F100 que llega desde un enlace de ventas para entender qué entrega Mycelium en control de acceso lógico. Y un investigador de seguridad que busca reportar una vulnerabilidad. Ambos están abajo.
Parte A. Control de acceso dentro de tu tenant (RBAC Fase 4)
Mycelium entrega control de acceso por rol con globs de carpeta dentro de cada tenant. Cada JWT lleva un claim roles. Cada ruta que toca el vault resuelve el conjunto de roles contra la ruta objetivo antes de leer o escribir. Las denegaciones producen entradas estructuradas de registro de auditoría con el conjunto de roles, la ruta objetivo y la identidad del actor.
Este es el primer entregable en el camino de control SOC 2 CC6.1. La ventana de auditoría está apuntada a 2027. Aún no estamos certificados SOC 2. El mapeo abajo es lo que un auditor leería al cierre de trimestre contra los Trust Services Criteria de la AICPA.
A1. Librería de roles por defecto (auto-sembrada al crear el tenant)
Cada tenant creado en el motor de ejecución de Mycelium se hidrata con esta librería de roles. El operador puede crear, editar o eliminar roles vía la API de administración después de la creación. La semántica de globs sigue la convención de gitignore: ** coincide con cero o más segmentos de ruta, * coincide con cualquier número de caracteres dentro de un solo segmento.
| Rol | Globs de lectura | Globs de escritura | Propósito |
|---|---|---|---|
tenant_admin | ** | ** | Acceso total. Fallback por defecto para JWTs heredados y fuentes webhook sin un rol propietario natural. |
executive | ** | ** | Acceso total. Distinguible de tenant_admin en auditoría. |
hr | External Inputs/Workday/**, External Inputs/Microsoft 365/users/**, External Inputs/Slack/hr-*/** | External Inputs/Workday/** | Datos de la fuerza laboral. |
legal | External Inputs/Confluence/legal/**, External Inputs/DocuSign/**, External Inputs/Slack/legal-*/** | External Inputs/Confluence/legal/** | Legal y contratos. |
gtm | External Inputs/Salesforce/**, External Inputs/HubSpot/**, External Inputs/Slack/sales-*/**, External Inputs/Gmail/** | External Inputs/Salesforce/**, External Inputs/HubSpot/** | Ingresos y clientes. |
engineering | External Inputs/GitHub/**, External Inputs/Linear/**, External Inputs/GitLab/**, External Inputs/Slack/eng-*/** | External Inputs/GitHub/**, External Inputs/Linear/**, External Inputs/GitLab/** | Código y tickets. |
it | External Inputs/ServiceNow/**, External Inputs/Jira/**, External Inputs/Box/it/** | External Inputs/ServiceNow/**, External Inputs/Jira/** | Gestión de servicios de TI. |
finance | External Inputs/SAP/**, External Inputs/Workday/expense_report/**, External Inputs/Workday/journal_entry/**, External Inputs/Snowflake/finance/** | External Inputs/SAP/** | Finanzas y contabilidad. |
data | External Inputs/Snowflake/**, External Inputs/Databricks/** | External Inputs/Snowflake/**, External Inputs/Databricks/** | Equipo de datos. |
viewer | ** | (ninguno) | Rol de auditoría sólo lectura. |
A2. Superficie de la API de administración
Todos los endpoints de administración requieren el token de tenant administrador. La creación o reemplazo de la librería de roles rechaza con HTTP 400 si la librería propuesta excede el límite por tenant (10 KB de JSON serializado, cubre ~50 roles realistas), o si la lista de herencia propuesta introduce un ciclo. La detección de ciclos corre al guardar, así el operador ve un 400 limpio en vez de un 500 en la primera lectura.
GET /admin/roles/{tenant_id}: lista la librería de rolesPOST /admin/roles/{tenant_id}: crea o reemplaza un rolDELETE /admin/roles/{tenant_id}/{role_name}: elimina un rol (HTTP 409 en rol protegido)GET /admin/audit/denials/{tenant_id}: cola reciente de denegaciones de auditoríaPOST /admin/jwt/{tenant_id}: emite un JWT con alcance de rol vía HTTP
Eliminar rechaza roles protegidos. tenant_admin es el fallback para JWTs heredados sin claim roles Y el rol-fuente por defecto para fuentes webhook sin un rol propietario natural. Eliminarlo dejaría al tenant sin un rol que cubra el fallback heredado o el fallback webhook, dejando la instalación inutilizable. Los operadores que quieren una identidad de fallback distinta crean primero un rol de reemplazo con los mismos globs ** bajo otro nombre.
A3. Comportamiento de denegación en webhooks
Cada fuente webhook mapea a un rol por defecto para la ingesta. Si los globs de escritura del rol ya no cubren la carpeta de la fuente (porque el operador eliminó o redujo el alcance del rol), el receptor sigue devolviendo HTTP 200 (contrato del webhook) pero emite una línea de auditoría webhook.<source>.denied con status: "denied", el conjunto roles y la ruta objetivo. El payload del evento se escribe a vaults/<tenant_id>/.dead-letter/<source>/<event_id>.json con un id de evento estable para que las redentregas se desdupliquen.
Los operadores reintentan después de arreglar la librería de roles vía POST /admin/webhooks/replay/{tenant_id}/{event_id}. Si el reintento sigue tropezando con el RBAC, el archivo dead-letter se queda en su lugar. Sólo un reintento totalmente exitoso lo elimina.
A4. Compatibilidad hacia atrás
Los JWTs emitidos antes de la Fase 4 no llevan claim roles. La capa de autenticación detecta una clave roles ausente y cae a ["tenant_admin"], así los tokens existentes siguen funcionando con acceso total hasta que el operador los re-emita con roles explícitos. Los tenants persistidos antes de la Fase 4 se hidratan con roles=[]; el fallback de autenticación en arranque en frío también los cubre.
Un token que SÍ lleva un claim roles con una lista vacía es un token deniega-todo deliberado, no un fallback heredado. La capa de autenticación devuelve [] y cada compuerta RBAC deniega. Esta es la affordance explícita de revocación para llamadores de primera parte. Las formas de claim mal formadas (no listas) se tratan como herencia y caen a tenant_admin, ya que un claim mal formado suele ser un problema de deserialización de un proxy con bugs antes que una revocación deliberada, y fallar cerrado allí dejaría inutilizables a llamadores legítimos.
A5. Salvedades operativas (la parte que la mayoría de páginas esconde)
Lo que NO está hecho es la señal de confianza. Tres salvedades que los operadores que evalúan Mycelium deben conocer sobre la Fase 4:
- Suposición de un solo worker. El cache del registro de tenants vive en proceso. Correr uvicorn con
--workers > 1y mutar roles vía la API de administración deja a los otros workers sirviendo datos de rol obsoletos hasta que se recargan. Para despliegues de un solo worker (el default de la Fase 4), esto es invisible. Los despliegues multi-worker necesitan un cache de tenants respaldado por Redis O un hook de invalidación fan-out. Alcance de la Fase 5. - El override del rol por defecto por tenant y por fuente aún no está expuesto. El mapeo de fuente webhook a rol de ingesta por defecto está hardcodeado en
src/rbac.py::_SOURCE_DEFAULT_ROLE. Los operadores que quieren bajar o subir el rol por defecto de una fuente por tenant editan los globs del rol para ajustar la cobertura, no el mapeo de fuente. El override del mapeo de fuente por tenant es un endpoint de administración de la Fase 5. - La vista de denegaciones del registro de auditoría se trunca.
GET /admin/audit/denials/{tenant_id}lee las últimas ~10K líneas deaudit-log.jsonly filtra a denegaciones para ese tenant. Los tenants con muy alto volumen de denegaciones ven sólo el segmento más reciente. La Fase 5 agrega paginación basada en cursor.
A6. Mapeo SOC 2 CC6.1
CC6.1 de los Trust Services Criteria de la AICPA requiere software, infraestructura y arquitecturas de seguridad de acceso lógico sobre activos de información protegida. Los entregables de la Fase 4 mapean como sigue. Aún no estamos certificados SOC 2. La ventana de auditoría está apuntada a 2027.
| Requisito CC6.1 | Entregable de la Fase 4 |
|---|---|
| Verificar identidades | Claims JWT sub + tenant_id (existentes, sin tocar). |
| Aplicar permisos por rol | Nuevo claim JWT roles + compuertas assert_can_read / assert_can_write en cada ruta que toca el vault. |
| Conjuntos de reglas para limitar el acceso lógico | ACLs por glob de carpeta Role.read_globs / Role.write_globs en cada Rol. |
| Separación de funciones incompatibles | La librería de roles por defecto auto-siembra 10 roles alineados a los equipos funcionales F100. |
| Revisión periódica de roles de acceso | Endpoints de administración para listar, crear, eliminar y ver denegaciones (ver A2 arriba). |
| Cadena de evidencia auditable | Cada denegación emite una línea estructurada de auditoría JSONL que lleva roles, target_path, user_id, tenant_id, status: "denied". El fanout del broadcaster SSE no cambia; los suscriptores pueden filtrar por status. |
El registro de auditoría en audit-log.jsonl más la librería de roles en tenants[*].roles es la cadena de evidencia que un auditor CC6.1 lee al cierre de trimestre.
A7. Diferido a la Fase 5+
- Aplicación de
visibility:en frontmatter por entrada (ACLs por glob de carpeta primero). - Overrides del rol por defecto por tenant y por fuente (los operadores ajustan más allá de la librería sembrada).
- Interfaz de administración frontend para gestión de roles (los endpoints JSON + curl + el CLI cubren la Fase 4).
- Cache de tenants multi-worker (respaldado por Redis o invalidación fan-out).
- Paginación basada en cursor en la vista de denegaciones.
Parte B. Divulgación de vulnerabilidades
Mycelium opera un programa de divulgación coordinada. Los investigadores que reportan vulnerabilidades de buena fe y siguiendo las reglas a continuación son reconocidos en nuestro CHANGELOG público y acreditados en cualquier aviso de seguridad relacionado.
B1. Reportes
Envía los reportes de vulnerabilidades a security@mycelium-ai.co. Los envíos cifrados son bienvenidos; huella digital de la llave PGP disponible a solicitud.
Por favor incluye:
- Una descripción clara y reproducible del problema
- La URL, endpoint, versión o componente afectado
- Salida de prueba de concepto o pasos que demuestren el impacto
- Tu nombre preferido para el crédito (o una solicitud de permanecer anónimo)
B2. Cronograma de respuesta
- Acuse de recibo dentro de un día hábil
- Clasificación inicial y evaluación de severidad dentro de cinco días hábiles
- Plan de remediación y fecha objetivo dentro de quince días hábiles
- Ventana de divulgación pública: noventa días desde el reporte inicial, o antes si una corrección ha salido y la base de clientes ha sido notificada, lo que ocurra primero
B3. Alcance
Dentro del alcance:
- mycelium-ai.co y todos los subdominios operados por Mycelium
- La capa de memoria de código abierto en github.com/adelaidasofia/ai-brain-starter
- Los endpoints del motor de ejecución productizado expuestos a clientes bajo carta de compromiso (sujeto a la Sección B4)
Fuera del alcance:
- Servicios de terceros (infraestructura de Vercel, Resend, PostHog, Anthropic, OpenAI, etc.). Por favor reporta al proveedor directamente.
- Ingeniería social a empleados, contratistas o clientes piloto de Mycelium
- Ataques físicos a oficinas o hardware de Mycelium
- Pruebas de denegación de servicio o de límites de tasa sin autorización previa por escrito
B4. Puerto seguro
La investigación realizada de acuerdo con esta política se considera autorizada y Mycelium no procederá con acción civil ni la reportará a las autoridades. Los investigadores deben evitar acceder o modificar datos del cliente, deben detener las pruebas de inmediato cuando se les solicite, y deben dar a Mycelium tiempo razonable para remediar antes de la divulgación pública.
B5. Reconocimiento
Los investigadores que sigan esta política y envíen reportes de vulnerabilidades válidos son reconocidos en el CHANGELOG público y (con el consentimiento del investigador) en cualquier aviso de seguridad publicado. No ofrecemos recompensas en efectivo actualmente; esperamos lanzar un programa pagado después de que la auditoría SOC 2 Type II se complete.
B6. Privacidad y consultas de interesados
Para preguntas de privacidad o solicitudes de interesados bajo el RGPD, RGPD del Reino Unido, CCPA o LGPD, escribe a privacy@mycelium-ai.co.
Mycelium · fundado en 2026