Files
fn_registry/functions/infra/audit_services_spec.md
egutierrez 7913116a8e chore: auto-commit (129 archivos)
- .claude/agents/fn-analizador/SKILL.md
- .claude/agents/fn-constructor/SKILL.md
- .claude/agents/fn-executor/SKILL.md
- .claude/agents/fn-mejorador/SKILL.md
- .claude/agents/fn-orquestador/SKILL.md
- .claude/agents/fn-recopilador/SKILL.md
- .claude/commands/app.md
- .claude/commands/compile.md
- .claude/commands/cpp-app.md
- .claude/commands/create_functions.md
- ...

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 22:23:12 +02:00

61 lines
2.3 KiB
Markdown

---
name: audit_services_spec
kind: function
lang: go
domain: infra
version: "1.0.0"
purity: impure
signature: "func AuditServicesSpec(registryRoot string) ([]ServiceSpecAudit, error)"
description: "Audita apps con tag 'service': reporta drift entre el bloque service: del app.md y los datos requeridos por el monitor (port, health_endpoint, systemd_unit, pc_targets). Lee registry.db read-only via sql.Open. Issue 0105."
tags: [audit, services, doctor, registry, sqlite, issue-0105]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: error_go_core
imports:
- database/sql
- github.com/mattn/go-sqlite3
tested: false
file_path: functions/infra/audit_services_spec.go
params:
- name: registryRoot
desc: "Ruta absoluta a la raiz del fn_registry (donde vive registry.db)."
output: "Slice de ServiceSpecAudit (uno por app con tag service). OK=false si Issues no esta vacio."
---
# audit_services_spec
Reporta apps con tag `service` cuya `service:` block esta incompleta.
## Cuando usarla
- Subcomando `fn doctor services-spec` (este es su unico consumer hoy).
- Antes de desplegar `services_monitor` (issue 0106) — si esta funcion devuelve `OK=false` para alguna app, el monitor no puede reconciliar estado.
- En CI/cron para detectar regresiones cuando alguien crea app `tag: service` sin bloque.
## Ejemplo
```go
audits, err := infra.AuditServicesSpec("$HOME/fn_registry")
for _, a := range audits {
if !a.OK {
fmt.Println(a.AppID, "issues:", a.Issues)
}
}
```
## Reglas que valida
- bloque presente (alguno de runtime/systemd_unit/port/health_endpoint != default).
- `runtime` declarado y en allowlist (`systemd-user`, `systemd-system`, `docker-compose`, `stdio`, `manual`).
- `pc_targets` con al menos 1 pc_id (cruzado contra tabla `service_targets`).
- `runtime` empieza con `systemd-``systemd_unit` obligatorio.
- `restart_policy` (si declarada) en `always`, `on-failure`, `none`.
## Gotchas
- Lee `registry.db` en modo `?mode=ro`; si la base no existe o esta locked retorna error.
- `service:` bloque parcial pasa el check `HasBlock=true` pero falla validaciones especificas — ver `Issues[]` para detalles.
- No valida que el `port` este libre o el `systemd_unit` exista en disco; eso lo hace `services_status_go_infra` (runtime check).