Inventario de materiales
molto metadata escribe un documento CycloneDX 1.6 sin timestamp, así dos ejecuciones sobre un grafo producen bytes idénticos.
molto metadata responde a una pregunta: qué hay dentro de este binario, de dónde vino y bajo qué
licencia.
molto metadata # CycloneDX 1.6 por stdout
molto metadata -o sbom.json # a un archivo
molto metadata --include-dev # también lo que sólo alcanza [dev-deps]
La salida es JSON CycloneDX 1.6, que Dependency-Track, Grype y Trivy leen sin traducir.
Qué contiene
| Sección | Qué hay dentro |
|---|---|
metadata.component |
Tu paquete: nombre, versión y lo que declare [package] |
components[] |
Cada paquete que enlaza el build, una entrada por cada uno |
dependencies[] |
Las aristas, incluidas las de tu propio paquete |
Cada componente lleva su versión exacta, la licencia que declaró su recipe, el SHA-256 de los bytes
que se descargaron y una propiedad molto:source con el origen y su revisión ya resueltos:
registry+https://…, git+https://…#5a1e8ff…, path+modules/http.
Tres cosas que conviene saber
Una dependencia path no tiene checksum ni versión. Sus bytes son lo que haya en disco, que es
justo su razón de ser. Aparece con molto:unverified = true, y molto metadata lo dice por
stderr. Nada se omite en silencio: un inventario que esconde lo que no pudo verificar es peor que
no tener ninguno.
Las dependencias de desarrollo quedan fuera por defecto. Un inventario describe lo que se
distribuye. --include-dev las añade con "scope": "excluded", que es como CycloneDX dice «está
en el grafo, no en el artefacto».
El documento no tiene timestamp, ni tampoco serialNumber. Dos ejecuciones sobre el mismo
grafo producen los mismos bytes, así que se puede commitear, diferenciar y comparar entre máquinas.
Los dos campos son opcionales en el esquema, de modo que lo que sale sigue siendo un documento 1.6
conforme.
De dónde salen las licencias
De [package] para tu propio paquete, y de la tabla [about] del
recipe.toml de cada dependencia para el resto. Una dependencia cuyo
recipe no declara licencia no obtiene campo licenses: una cadena vacía sería una afirmación, y el
silencio no lo es.
Si un componente de tu informe no tiene licencia, el arreglo está aguas arriba: al recipe que lo
publica le falta una tabla [about].
Lo que cuesta
Resolver el grafo, que es lo que lee los recipes. En un proyecto ya construido esto no toca la red:
una coordenada publicada no cambia nunca, así que la respuesta anterior del registry sigue valiendo
y las fuentes ya están en ~/.molto/cache. En un clon recién hecho descarga, exactamente igual que
haría un build.
No lee Molto.lock. El lock registra versiones, orígenes y checksums, y deliberadamente no
licencias: ese dato ya vive en cada recipe, y un lock que lo guardara por duplicado podría
contradecirse.