---
name: vault_manifest_read
kind: function
lang: go
domain: infra
version: "1.0.0"
purity: impure
signature: "func VaultManifestRead(repoRoot string) ([]VaultManifestEntry, error)"
description: "Lee todos los manifests vault.yaml bajo projects/*/vaults/ del repo y devuelve una lista plana de entradas de vault con su ProjectID inferido del path."
tags: [vault, manifest, yaml, infra, projects, storage]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports:
  - "fmt"
  - "os"
  - "path/filepath"
  - "strings"
  - "gopkg.in/yaml.v3"
params:
  - name: repoRoot
    desc: "Ruta absoluta a la raiz del repositorio fn_registry. Se usa como base para el glob projects/*/vaults/vault.yaml."
output: "Slice plano de VaultManifestEntry (ProjectID, Name, Description, Path, Tags, ManifestFile). Vacio si no hay manifests. Error si un yaml no parsea, con el path concreto en el mensaje."
tested: true
tests:
  - "TestVaultManifestRead_HappyPath"
  - "TestVaultManifestRead_MalformedYAML"
  - "TestVaultManifestRead_EmptyDir"
test_file_path: "functions/infra/vault_manifest_read_test.go"
file_path: "functions/infra/vault_manifest_read.go"
---

## Ejemplo

```go
entries, err := VaultManifestRead("$HOME/fn_registry")
if err != nil {
    log.Fatal(err)
}
for _, e := range entries {
    fmt.Printf("%s/%s -> %s\n", e.ProjectID, e.Name, e.Path)
}
// app_turismo/turismo_spain -> /home/lucas/vaults/turismo_spain
// app_finance/finance_data  -> /home/lucas/vaults/finance_data
```

## Notas

`VaultManifestEntry` es un tipo local de esta funcion (no un tipo del registry). Contiene:
- `ProjectID` — basename del directorio `projects/<proj>/`, inferido del path del manifest.
- `Name`, `Description`, `Path`, `Tags` — copiados del yaml tal cual.
- `ManifestFile` — path absoluto al vault.yaml de origen, util para mensajes de error y trazabilidad.

El parseo usa `gopkg.in/yaml.v3` (ya en go.mod). Si un manifest falla, la funcion devuelve
error inmediatamente con el path del fichero problemático. Los manifests sin entradas
`vaults:` contribuyen cero entries (no es error). Si no existe ningun `projects/*/vaults/vault.yaml`
el resultado es slice vacio sin error.
