# SQLite Database

Madagascar Local Authority folosește SQLite ca sursă de adevăr runtime pentru hosturi, aliasuri, vhosturi, Work Orders, workeri de date și certificate.

Locația implicită în checkout:

```text
var/host-manager.sqlite
```

Locația runtime pe jumper:

```text
/usr/local/xdev-host-manager/var/host-manager.sqlite
```

Path-ul poate fi schimbat cu:

```text
HOST_MANAGER_DB=/path/to/host-manager.sqlite
```

## Principii

Hosturile sunt identificate prin FQDN complet, nu prin short name. Exemplu: `gw.local` și `gw.remote` sunt identități diferite. Coloana compatibilă `legacy_id` păstrează ID-ul scurt folosit de UI-ul curent, dar cheia reală este `hosts.fqdn`.

Schema evită să transforme `hosts` într-un tabel cu prea multe coloane. Datele specializate stau în tabele separate:

- aliasuri: [`host_aliases`](tables/host_aliases.md)
- roluri: [`host_roles`](tables/host_roles.md)
- surse: [`host_sources`](tables/host_sources.md)
- flaguri: [`host_flags`](tables/host_flags.md)
- SSH: [`host_ssh`](tables/host_ssh.md)
- vhosturi mutabile: [`vhosts`](tables/vhosts.md)
- certificate: [`certificates`](tables/certificates.md), [`certificate_dns_names`](tables/certificate_dns_names.md)
- workeri și observații: [`data_workers`](tables/data_workers.md), [`dhcp_leases`](tables/dhcp_leases.md), [`mdns_observations`](tables/mdns_observations.md)

[`documents`](tables/documents.md) rămâne doar tabel legacy pentru migrarea din modelul vechi document-store. Aplicația nu îl mai folosește ca sursă de adevăr.

## Schema Version

Schema curentă este versiunea `2`.

```sql
schema_meta('schema_version') = '2'
```

[`schema_meta`](tables/schema_meta.md) păstrează și metadate runtime precum `registry_updated_at`.

## Catalog

| Tabel | Rol |
|-------|-----|
| [`schema_meta`](tables/schema_meta.md) | metadate de schemă/runtime |
| [`documents`](tables/documents.md) | document-store legacy pentru migrare |
| [`hosts`](tables/hosts.md) | hosturi canonice, identificate prin FQDN |
| [`host_aliases`](tables/host_aliases.md) | aliasuri păstrate inclusiv după retragere |
| [`host_roles`](tables/host_roles.md) | roluri active/retrase per host |
| [`host_sources`](tables/host_sources.md) | surse active/retrase per host |
| [`host_flags`](tables/host_flags.md) | flaguri extensibile per host |
| [`host_ssh`](tables/host_ssh.md) | profile SSH per host |
| [`vhosts`](tables/vhosts.md) | vhosturi mutabile între hosturi |
| [`data_workers`](tables/data_workers.md) | workeri/surse care colectează date |
| [`dhcp_leases`](tables/dhcp_leases.md) | date observate din DHCP lease/reservation |
| [`mdns_observations`](tables/mdns_observations.md) | date observate din mDNS |
| [`certificates`](tables/certificates.md) | certificate emise de CA locală |
| [`certificate_dns_names`](tables/certificate_dns_names.md) | SAN DNS names pentru certificate |
| [`work_orders`](tables/work_orders.md) | Work Orders |
| [`work_order_checklist`](tables/work_order_checklist.md) | checklist items pentru Work Orders |
| [`work_order_actions`](tables/work_order_actions.md) | acțiuni confirmabile pentru Work Orders |

## Relații Principale

```mermaid
erDiagram
  hosts ||--o{ host_aliases : has
  hosts ||--o{ vhosts : serves
  hosts ||--o{ host_roles : has
  hosts ||--o{ host_sources : has
  hosts ||--o{ host_flags : has
  hosts ||--o{ host_ssh : has
  hosts ||--o{ dhcp_leases : may_match
  hosts ||--o{ mdns_observations : may_match
  hosts ||--o{ certificates : may_own
  certificates ||--o{ certificate_dns_names : has
  data_workers ||--o{ dhcp_leases : collects
  data_workers ||--o{ mdns_observations : collects
  work_orders ||--o{ work_order_checklist : has
  work_orders ||--o{ work_order_actions : has
  hosts ||--o{ work_order_actions : targets
```

## Migrare și Seed

La prima inițializare a unei baze fără rânduri în `hosts`, aplicația seed-uiește din:

1. `documents.name = 'hosts_yaml'`, dacă există din vechiul model
2. `config/hosts.yaml`, dacă documentul legacy lipsește
3. document gol valid, dacă lipsește și seed-ul

Work Orders se seed-uiesc similar din `documents.name = 'work_orders_yaml'` sau `config/work-orders.yaml`.

Seed-ul curent produce:

- 11 hosturi cunoscute
- aliasuri scurte derivate pentru hosturi și vhosturi
- vhosturile `hosts.*`, `pmx.*` și `pbs.*`
- workerii `dhcp-router` și `mdns-listener`
- Work Order-ul existent pentru retragerea numelor legacy

`config/local-hosts.tsv` rămâne manifest generat explicit din tabelele runtime, dar scriptul de sync citește manifestul direct din SQLite-ul runtime de pe jumper.

## Inspecție

Pe jumper:

```bash
cd /usr/local/xdev-host-manager
sqlite3 var/host-manager.sqlite '.tables'
sqlite3 var/host-manager.sqlite '.schema hosts'
sqlite3 var/host-manager.sqlite '.schema host_aliases'
sqlite3 var/host-manager.sqlite '.schema vhosts'
sqlite3 var/host-manager.sqlite 'pragma foreign_key_list(vhosts);'
sqlite3 var/host-manager.sqlite 'pragma index_list(host_aliases);'
sqlite3 var/host-manager.sqlite 'select fqdn, legacy_id, status, dns_ip from hosts order by legacy_id;'
sqlite3 var/host-manager.sqlite 'select alias_name, host_fqdn, alias_kind, status from host_aliases order by alias_name;'
sqlite3 var/host-manager.sqlite 'select vhost_fqdn, host_fqdn, status from vhosts order by vhost_fqdn;'
```

## Backup

Backup recomandat:

```bash
cd /usr/local/xdev-host-manager
sqlite3 var/host-manager.sqlite ".backup 'backups/host-manager/host-manager.sqlite.$(date +%Y%m%d_%H%M%S).bak'"
```

Cu WAL activ, o copie brută trebuie să trateze fișierele ca set coerent:

```text
var/host-manager.sqlite
var/host-manager.sqlite-wal
var/host-manager.sqlite-shm
```

## Restore

Restore-ul înlocuiește sursa de adevăr runtime:

```bash
sudo systemctl stop host-manager
sudo cp backups/host-manager/host-manager.sqlite.YYYYMMDD_HHMMSS.bak var/host-manager.sqlite
sudo chown host-manager:host-manager var/host-manager.sqlite
sudo systemctl start host-manager
curl -fsS http://127.0.0.1:8088/healthz >/dev/null
```
