Nacre
Capa de contexto autoalojada y consciente de permisos. La búsqueda devuelve solo lo que el llamador puede leer.
Documentación
Nacre
Tu índice. Tus reglas de acceso. Tu perímetro.
Los agentes ven exactamente lo que se les permite ver.
Nacre es un índice de conocimiento autoalojado con control de acceso de grano fino. Los agentes acceden a él mediante MCP, y las aplicaciones mediante una API REST. Sin interfaz de chat, sin asistente de empresa — solo la capa de contexto que los sustenta.
Por qué
La búsqueda vectorial es un problema resuelto. Lo que no está resuelto: garantizar que un agente que consulta un índice de empresa vea exactamente los documentos para los que el usuario solicitante está autorizado — y poder demostrarlo ante un auditor.
- Permisos que se heredan. Espacios de trabajo → capas, con
read/write/adminheredados de arriba hacia abajo.writeno implicaread;adminimplica ambos. Las concesiones a nivel de documento y las reglas de denegación son comerciales — esta compilación las rechaza y lo dice, en lugar de aceptar una regla que no puede propagar. - El filtrado ocurre dentro del índice. Los filtros de acceso se aplican durante
el recorrido HNSW, no después de la clasificación, por lo que
top_kdevuelve k resultados permitidos en lugar de k menos lo que se haya eliminado. - MCP como superficie de primera clase. HTTP transmisible según la especificación del 28 de julio de 2026, y STDIO local para agentes de desarrollo. Los agentes se autentican con una clave de cuenta de servicio; el descubrimiento OAuth se sirve (RFC 9728), y el registro de clientes es asunto del servidor de autorización, no nuestro.
- Recuperación híbrida, porque los agentes piden identificadores. Vectores densos y
BM25 fusionados con fusión de rango recíproco, más un reordenamiento con codificador cruzado donde
una implementación lo configure. No se ofrece como diferenciador — la línea anterior
es la honesta — pero un agente que busca
SQLSTATE 23505, un número de factura o un nombre de variable necesita la coincidencia literal, y un índice solo denso no la devuelve de forma fiable. - Trae tus propios modelos. Incrustaciones mediante cualquier endpoint compatible con OpenAI, vinculado por capa. Cambiar el modelo en una capa existente es un reindexado que mantiene la búsqueda respondiendo durante todo el proceso, y está condicionado a la recuperación contra un conjunto de consultas que tú proporcionas antes de que cambie.
- Un cliente de línea de comandos.
npx @nacre.work/cliinicia sesión, crea una capa, recorre un directorio e indexa, y busca — las cuatro invocaciones decurlque el inicio rápido detalla, para cuando quieres el resultado en lugar del contrato. Un documento que no se indexa produce una salida distinta de cero, por lo que una ingesta nocturna no puede informar éxito habiendo indexado nada. - Permanece dentro de tu red. Docker Compose, sin llamadas a casa.
Inicio rápido
git clone https://github.com/nacre-work/nacre && cd nacre
cp .env.example .env
docker compose --profile minimal up -d
Guía completa: docs/quickstart.md.
En un Mac con Apple Silicon, lee docs/apple-silicon.md primero — las imágenes son arm64 y el stack es nativo, pero el incrustador es la única pieza que ejecutas en el host.
Estructura
packages/api REST API and authorization service
packages/mcp MCP server (Streamable HTTP + STDIO)
packages/worker indexing pipeline: parse, chunk, embed
packages/core data model, permission resolver, shared types
packages/sdk TypeScript SDK
packages/admin community admin UI
services/parser Python sidecar: bytes → {text, blocks, metadata}
docs/ specifications — normative, and ahead of the code
Estado
Temprano, y funciona. El ciclo funciona de extremo a extremo y se ha manejado a mano
contra un PostgreSQL real y un Qdrant real: crear una organización, crear una
capa, conceder a alguien read, ingestar un documento, consultar el trabajo hasta indexed,
buscar y obtener el fragmento — y buscar como alguien sin la concesión y obtener
nada mientras los vectores siguen en el índice. Ambas superficies funcionan,
REST y MCP sobre Streamable HTTP y STDIO por igual. Revocar una concesión elimina el
documento de los resultados, y el recálculo que actualiza las etiquetas del índice se ejecuta
en el trabajador con una métrica sobre cuánto está retrasado.
La búsqueda tiene límite de velocidad por organización, los métodos no seguros requieren un
Idempotency-Key, las colecciones se paginan por cursor, y el reordenamiento se ejecuta en la ruta
de búsqueda cuando una implementación configura un reordenador. Los vectores marcados como eliminados se recogen,
y el SDK y la interfaz de administración están escritos.
Iniciar sesión funciona: correo electrónico y contraseña, con tokens de actualización rotativos que terminan la
sesión si uno se reproduce. init crea el primer administrador e imprime una
contraseña generada una vez. El SSO es un módulo comercial.
El registro de acceso es legible: GET /v1/audit, más reciente primero, paginado por cursor, como
JSON, JSONL o CSV. org_admin ve qué documentos se leyeron — la pregunta
que un registro de auditoría existe para responder — y platform_admin ve acciones administrativas
y nunca eso, que es la regla 2 aplicada al diario.
Una capa se puede mover a un modelo de incrustación diferente. Qdrant no añadirá un vector con nombre a una colección que ya existe, por lo que la colección se reemplaza en lugar de alterarse: cada punto se copia sin calcular incrustaciones, una declaración para cambiar el puntero, luego re-incrustar una capa a la vez. La búsqueda sigue disponible y sigue siendo una consulta durante todo el proceso. Antes de que una capa cambie, su conjunto de consultas de referencia se puntúa contra el nuevo modelo y una migración que perdiera recuperación se detiene en lugar de activarse — esa puerta está desactivada hasta que escribas un conjunto, porque necesita documentos que solo tú puedes elegir.
Un documento se puede subir como formulario además de enviarse como JSON, y un PDF se
extrae mediante el sidecar del analizador. Ambas señales deben coincidir — la parte declara
application/pdf y los bytes comienzan con %PDF- — porque un tipo declarado que los
bytes contradicen es un desacuerdo, y solo olfatear haría que el tipo declarado fuera decoración.
Cualquier otro formato binario se rechaza en el borde, y un
PDF escaneado sin capa de texto se rechaza en lugar de indexarse como nada.
Los tokens se pueden firmar con una clave Ed25519 en lugar de un secreto compartido, en cuyo
caso la mitad pública se publica en /.well-known/jwks.json y solo el
proceso que emite tokens tiene la privada.
docker compose --profile minimal up se ha ejecutado desde un clon limpio, y
todo el ciclo se ha manejado a través de él.
Lo que no está construido es lo que cubre una licencia comercial, y docs/licensing.md
lo enumera: multiinquilino, SSO, permisos a nivel de documento y reglas de denegación,
ID-JAG, exportación SIEM, un administrador global, cuotas y gráficos Helm de alta disponibilidad.
docs/ es la especificación, y todavía va por delante del código en algunos lugares —
comienza con docs/authz.md, del que depende todo lo demás.
Invariantes
Seis reglas. Romper cualquiera de ellas es un incidente de seguridad, no un error. Detalles en docs/authz.md.
- La organización proviene del token y de ningún otro lugar.
- El filtrado de acceso es un pre-filtro, nunca un post-filtro.
- Un fallo al evaluar permisos deniega el acceso.
- "Sin permiso" y "objeto inexistente" devuelven respuestas idénticas.
- Un documento eliminado nunca se devuelve, incluso antes de la recolección de basura.
writeno implicaread.
Licencia
Apache 2.0 — todo. Todo lo anterior está en este repositorio y permanece ahí.
El multiinquilino, SSO/SCIM, reglas de denegación a nivel de documento, EMA, exportación SIEM, administración global y copias de seguridad son módulos comerciales. Viven en un repositorio privado separado bajo una licencia separada y no se distribuyen con este — consulta docs/licensing.md para la línea entre ambos y la única pregunta que la decide.
Donde esta compilación se encuentra con uno de ellos, lo rechaza abiertamente: una regla deny o una
concesión a nivel de documento se responde 400 con el motivo, en lugar de aceptarse
y no aplicarse silenciosamente.
El nombre y la marca Nacre son marcas comerciales; consulta TRADEMARK.md.
Apoyo a este proyecto
No hay nivel alojado, ni recuento de asientos ni nada medido aquí, por lo que la mitad abierta no gana nada por ser usada — que es el punto, y también por qué vale la pena decir quién lo paga. Los módulos comerciales lo hacen, y son para las organizaciones que los necesitan; un desarrollador que ejecuta esto en un portátil nunca es la persona a la que se le pide.
Si te ahorró una semana, el botón Patrocinar en la parte superior de este repositorio es la otra forma de decirlo. Nada en este repositorio está detrás de él, y nada lo estará.