Showing 3 changed files with 187 additions and 0 deletions
+185 -0
.doc/database.md
@@ -0,0 +1,185 @@
1
+# SQLite Database
2
+
3
+Madagascar Local Authority folosește SQLite ca store runtime pentru registry și Work Orders.
4
+
5
+Locația implicită în checkout:
6
+
7
+```text
8
+var/host-manager.sqlite
9
+```
10
+
11
+Locația runtime pe jumper:
12
+
13
+```text
14
+/usr/local/xdev-host-manager/var/host-manager.sqlite
15
+```
16
+
17
+Path-ul poate fi schimbat cu:
18
+
19
+```text
20
+HOST_MANAGER_DB=/path/to/host-manager.sqlite
21
+```
22
+
23
+## Rol
24
+
25
+SQLite este sursa de adevăr runtime. Fișierele din `config/` nu mai sunt store-ul live:
26
+
27
+- `config/hosts.yaml` seed-uiește documentul `hosts_yaml` dacă baza este nouă.
28
+- `config/work-orders.yaml` seed-uiește documentul `work_orders_yaml` dacă baza este nouă.
29
+- `config/local-hosts.tsv` este manifest generat explicit din registry-ul SQLite.
30
+- `/download/hosts.yaml`, `/download/local-hosts.tsv` și `/download/monitoring.json` sunt randate din SQLite.
31
+
32
+Aplicația nu face commit/push automat după modificări. Exportul și arhivarea rămân pași operaționali separați.
33
+
34
+## Schema curentă
35
+
36
+Schema este creată automat de `scripts/host_manager.pl` la prima citire/scriere a store-ului.
37
+
38
+```sql
39
+CREATE TABLE IF NOT EXISTS documents (
40
+    name TEXT PRIMARY KEY,
41
+    content TEXT NOT NULL,
42
+    updated_at TEXT NOT NULL
43
+);
44
+```
45
+
46
+Setări aplicate la conectare:
47
+
48
+```sql
49
+PRAGMA journal_mode = WAL;
50
+PRAGMA foreign_keys = ON;
51
+```
52
+
53
+În schema curentă există o singură tabelă generică, `documents`. Conținutul operațional rămâne serializat în formatul YAML strict deja folosit de aplicație. Alegerea este deliberată pentru migrarea minimă: sursa de adevăr se mută din working tree în SQLite fără să schimbăm încă parserul, UI-ul sau formatul exporturilor.
54
+
55
+## Documente
56
+
57
+### `hosts_yaml`
58
+
59
+Conține registry-ul de hosturi în formatul `config/hosts.yaml`.
60
+
61
+Este citit de:
62
+
63
+- `GET /api/hosts`
64
+- `GET /download/hosts.yaml`
65
+- `GET /download/local-hosts.tsv`
66
+- `GET /download/monitoring.json`
67
+- `POST /api/render/local-hosts-tsv`
68
+
69
+Este scris de:
70
+
71
+- `POST /api/hosts/upsert`
72
+- `POST /api/hosts/delete`
73
+- `POST /api/work-orders/confirm`, când o acțiune modifică registry-ul
74
+
75
+Aplicația normalizează la salvare:
76
+
77
+```yaml
78
+policy:
79
+  storage_authority: "sqlite"
80
+  runtime_database: "<HOST_MANAGER_DB>"
81
+```
82
+
83
+### `work_orders_yaml`
84
+
85
+Conține Work Orders în formatul `config/work-orders.yaml`.
86
+
87
+Este citit de:
88
+
89
+- `GET /api/work-orders`
90
+- `POST /api/work-orders/checklist`
91
+- `POST /api/work-orders/confirm`
92
+
93
+Este scris de:
94
+
95
+- `POST /api/work-orders/checklist`
96
+- `POST /api/work-orders/confirm`
97
+
98
+## Seed inițial
99
+
100
+La prima accesare a unui document:
101
+
102
+1. Aplicația caută rândul în `documents`.
103
+2. Dacă rândul există, conținutul din SQLite câștigă.
104
+3. Dacă rândul lipsește, aplicația citește fișierul seed din `config/`.
105
+4. Dacă fișierul seed lipsește, aplicația creează un document gol valid.
106
+5. Documentul este inserat în SQLite și de atunci SQLite devine autoritatea.
107
+
108
+Important: după seed, modificările ulterioare ale fișierelor `config/hosts.yaml` sau `config/work-orders.yaml` nu schimbă automat baza existentă.
109
+
110
+## Fișiere SQLite
111
+
112
+Cu WAL activ, runtime-ul poate avea trei fișiere:
113
+
114
+```text
115
+var/host-manager.sqlite
116
+var/host-manager.sqlite-wal
117
+var/host-manager.sqlite-shm
118
+```
119
+
120
+Toate trei aparțin store-ului runtime. Nu se comit în git și nu se înlocuiesc prin deploy de cod.
121
+
122
+## Inspecție
123
+
124
+Pe jumper:
125
+
126
+```bash
127
+cd /usr/local/xdev-host-manager
128
+sqlite3 var/host-manager.sqlite '.schema'
129
+sqlite3 var/host-manager.sqlite 'select name, updated_at, length(content) from documents order by name;'
130
+sqlite3 var/host-manager.sqlite 'select content from documents where name = "hosts_yaml";'
131
+sqlite3 var/host-manager.sqlite 'select content from documents where name = "work_orders_yaml";'
132
+```
133
+
134
+Pentru export YAML curent:
135
+
136
+```bash
137
+curl -fsS -b cookies.txt https://hosts.madagascar.xdev.ro/download/hosts.yaml
138
+```
139
+
140
+Endpoint-urile de download sunt OTP-protected; exemplul presupune o sesiune validă.
141
+
142
+## Backup
143
+
144
+Backup recomandat, cu serviciul oprit sau prin API-ul SQLite:
145
+
146
+```bash
147
+cd /usr/local/xdev-host-manager
148
+sqlite3 var/host-manager.sqlite ".backup 'backups/host-manager/host-manager.sqlite.$(date +%Y%m%d_%H%M%S).bak'"
149
+```
150
+
151
+Pentru o copie brută, include și fișierele WAL/SHM sau oprește serviciul înainte:
152
+
153
+```bash
154
+sudo systemctl stop host-manager
155
+sudo cp -a var/host-manager.sqlite* backups/host-manager/
156
+sudo systemctl start host-manager
157
+```
158
+
159
+## Restore
160
+
161
+Restore-ul înlocuiește sursa de adevăr runtime și trebuie făcut explicit:
162
+
163
+```bash
164
+sudo systemctl stop host-manager
165
+sudo cp backups/host-manager/host-manager.sqlite.YYYYMMDD_HHMMSS.bak var/host-manager.sqlite
166
+sudo chown host-manager:host-manager var/host-manager.sqlite
167
+sudo systemctl start host-manager
168
+curl -fsS http://127.0.0.1:8088/healthz >/dev/null
169
+```
170
+
171
+Dacă se restaurează o copie brută, tratează `host-manager.sqlite`, `host-manager.sqlite-wal` și `host-manager.sqlite-shm` ca set coerent.
172
+
173
+## Evoluție probabilă
174
+
175
+Schema generică `documents` este potrivită pentru tranziția curentă. Dacă aplicația are nevoie de query-uri structurale, validări SQL sau merge/audit mai granular, următorul pas ar trebui să fie o migrare versionată către tabele dedicate, de exemplu:
176
+
177
+- `hosts`
178
+- `host_names`
179
+- `host_roles`
180
+- `host_sources`
181
+- `work_orders`
182
+- `work_order_checklist`
183
+- `work_order_actions`
184
+
185
+Până atunci, contractul stabil este numele documentelor din `documents` și formatele YAML randate de aplicație.
+1 -0
README.md
@@ -41,6 +41,7 @@ The web UI is OTP-protected for all registry data, downloads, exports, and write
41 41
 For agent/operator context, see:
42 42
 
43 43
 - [`agents.md`](agents.md)
44
+- [`.doc/database.md`](.doc/database.md)
44 45
 - [`.doc/development-log.md`](.doc/development-log.md)
45 46
 - [`.doc/host-manager.md`](.doc/host-manager.md)
46 47
 - [`.doc/local-hosts.md`](.doc/local-hosts.md)
+1 -0
agents.md
@@ -5,6 +5,7 @@ Madagascar Local Authority is the local authority application for the Madagascar
5 5
 Start with these documents:
6 6
 
7 7
 - [README.md](README.md) - current repository, deployment model, runtime paths, GitPrep remote.
8
+- [.doc/database.md](.doc/database.md) - SQLite runtime store schema, seed rules, backup and restore.
8 9
 - [.doc/host-manager.md](.doc/host-manager.md) - application behavior, OTP, Work Orders, local CA, registry rules.
9 10
 - [.doc/local-hosts.md](.doc/local-hosts.md) - local DNS rules, resolver sync, source priority.
10 11
 - [.doc/development-log.md](.doc/development-log.md) - scope and architecture decisions over time.