Change language

rp-registry

Propósito

El registro de módulos y soluciones: qué existe, de qué está hecha cada solución
y los propios bytes. Responde a dos lectores que no comparten nada más. Ptah
pide un índice y luego objetos por digest, sin conocer nunca un nombre y
verificando cada byte que recibe. El portal y el chat hacen la pregunta opuesta:
qué soluciones existen, qué aportaría esta y qué necesita primero.

Ambos viven en un mismo servicio porque un catálogo que nombra módulos que el
almacén de objetos no contiene es precisamente el fallo que esto pretende evitar,
y solo puede comprobarse donde ambas mitades son visibles.

Límite de responsabilidad

rp-registry nunca toca un clúster. Publica un catálogo y sirve bytes; convertir
una selección en una plataforma en ejecución corresponde a lm-kubernetes, que
escribe recursos personalizados Solution, y reconciliarlos corresponde a ptah.
Mantener esa separación significa que un registro puede servir a muchos clústeres
sin tener credenciales para ninguno de ellos.

Almacenamiento

Dos almacenes, deliberadamente no más.

objects es un único almacén KV que contiene dos tipos de valores bajo dos
prefijos: bytes de módulos por digest (obj) y documentos de soluciones por capa
y nombre (sol). Ambos se leen completos mediante una clave exacta, por lo que
son el mismo tipo de almacenamiento utilizado dos veces. KVStore distingue los
binarios del JSON mediante una cabecera que escribe por sí mismo, así que aquí no
es necesario decodificar ninguno de los dos prefijos.

catalog es SQL, porque contiene la parte que cambia y la parte que se consulta:
qué artefacto resuelve actualmente a qué digest, en qué capa. Los bytes son
inmutables y se direccionan por contenido, así que no necesitan una tabla; los
nombres cambian con cada publicación y se consultan por capa, por tipo y entre
capas.

La asignación publicada no se almacena. Es un fold sobre layers y modules
calculado bajo demanda, y su digest es la revision. Almacenarla mantendría una
segunda copia de la verdad que queda obsoleta justo cuando acaba de producirse
una publicación y un clúster pregunta por qué no puede verla.

Capas

Una capa es la salida de una compilación. converged publica sus módulos,
club publica los suyos y declara extends: ["converged"], y la asignación que
lee cada consumidor se compone de todas ellas —una capa de producto se incorpora
después de la base que extiende, por lo que gana un módulo que reemplaza
deliberadamente—. El orden de publicación deja de importar y ninguna
compilación puede borrar nombres que no haya creado.

La publicación reemplaza una capa por completo en lugar de fusionarla: una
publicación es toda la salida de esa capa, por lo que un nombre que la nueva
compilación ya no produce tiene que desaparecer. Fusionarlas dejaría el nombre
apuntando a bytes que ya no compila nada.

Servir los bytes

ensureObjectCached devuelve una clave de Valkey, no el objeto. Los bytes se
materializan en la caché con ámbito y la ui los lee desde allí, que es la misma
transferencia que utiliza la galería para las imágenes y por la misma razón: un
módulo puede pesar hasta 2 MiB, y responder con el payload lo haría pasar por
storage → ms → ui en cada fallo de caché, a través de un canal pensado para
solicitudes.

Las dos rutas que utiliza un clúster —/registry/index.json y
/registry/<digest>— las sirve el host de ui de club, no este servicio
(club/core/frontend/landing/src/ptah-registry.ts). ptah habla HTTP plano y nada
más, así que algo con una interfaz HTTP tiene que responder por él, y eso es la
ui; la imagen base queda fuera, porque un producto sin registro no tiene nada que
servir. Las rutas son anónimas, porque la autenticidad se basa en el digest: ptah
verifica cada byte que recibe contra el digest que solicitó, así que un secreto
compartido añadiría algo que distribuir y revocar sin añadir una garantía.

Un digest que ninguna capa nombra no se sirve aunque los bytes estén almacenados.
Los objetos sin nombre son basura de una publicación interrumpida o algo que un
llamador ha adivinado, y servirlos convertiría esto en un almacén de blobs abierto.

Límites

Un objeto está limitado a 2 MiB. Los módulos reales ocupan decenas de kilobytes
—todo el conjunto del backend de converged ocupa aproximadamente 0,44 MiB
comprimido— y ptah rechaza cualquier cosa de más de 64 MiB, así que esto queda
muy por debajo de ambos límites. No es una optimización: el registro está pensado
para contener módulos de la comunidad, y una carga del tamaño de una imagen de
contenedor significa que alguien publicó el artefacto equivocado.

Los objetos se almacenan exactamente como llegan. El registro no comprime ni
descomprime: los paquetes de módulos son brotli, las fuentes de workflows son
sin procesar porque centimanus las ejecuta directamente, y el digest cubre los
bytes almacenados en ambos casos. Cualquier recodificación rompería el
direccionamiento por contenido en el único salto que existe para protegerlo.

Fuente

modules/repositories/rp-registry