feat: soporte projects y vaults en registry

Añade tablas projects y vaults a registry.db con FTS5, modelos Go,
parser de project.md y vault.yaml, CRUD completo en store, hashing
determinista, validación, y soporte en el indexer para escanear
projects/{name}/ con sus apps, analysis y vaults anidados.
Migration 010 crea las tablas, triggers FTS5, y columna project_id
en apps/analysis. El indexer preserva records remotos (repo_url) al
reindexar, igual que apps/analysis.
This commit is contained in:
2026-04-12 17:29:41 +02:00
parent 1a3e77b0d5
commit 54e62ecb91
8 changed files with 647 additions and 19 deletions
+28 -1
View File
@@ -77,9 +77,28 @@ func ComputeAnalysisHash(a *Analysis) string {
return fmt.Sprintf("%x", h.Sum(nil))
}
// ComputeProjectHash computes a deterministic hash of all content fields of a Project.
func ComputeProjectHash(p *Project) string {
h := sha256.New()
fmt.Fprintf(h, "%s|%s|%s",
p.ID, p.Name, p.Description)
fmt.Fprintf(h, "|%s", marshalStrings(p.Tags))
fmt.Fprintf(h, "|%s|%s|%s|%s", p.RepoURL, p.DirPath, p.Documentation, p.Notes)
return fmt.Sprintf("%x", h.Sum(nil))
}
// ComputeVaultHash computes a deterministic hash of all content fields of a Vault.
func ComputeVaultHash(v *Vault) string {
h := sha256.New()
fmt.Fprintf(h, "%s|%s|%s|%s|%s|%t",
v.ID, v.Name, v.ProjectID, v.Description, v.Path, v.Symlink)
fmt.Fprintf(h, "|%s", marshalStrings(v.Tags))
return fmt.Sprintf("%x", h.Sum(nil))
}
// LoadTimestamps reads existing id → {created_at, updated_at, content_hash} from all tables.
// Called before Purge so we can preserve dates across reindexing.
func (db *DB) LoadTimestamps() (funcs, types, apps, analysis map[string]timestampRecord, err error) {
func (db *DB) LoadTimestamps() (funcs, types, apps, analysis, projects, vaults map[string]timestampRecord, err error) {
funcs, err = loadTable(db, "functions")
if err != nil {
return
@@ -93,6 +112,14 @@ func (db *DB) LoadTimestamps() (funcs, types, apps, analysis map[string]timestam
return
}
analysis, err = loadTable(db, "analysis")
if err != nil {
return
}
projects, err = loadTable(db, "projects")
if err != nil {
return
}
vaults, err = loadTable(db, "vaults")
return
}