Madagascar Local Authority folosește SQLite ca store runtime pentru registry și Work Orders.
Locația implicită în checkout:
var/host-manager.sqlite
Locația runtime pe jumper:
/usr/local/xdev-host-manager/var/host-manager.sqlite
Path-ul poate fi schimbat cu:
HOST_MANAGER_DB=/path/to/host-manager.sqlite
SQLite este sursa de adevăr runtime. Fișierele din config/ nu mai sunt store-ul live:
config/hosts.yaml seed-uiește documentul hosts_yaml dacă baza este nouă.config/work-orders.yaml seed-uiește documentul work_orders_yaml dacă baza este nouă.config/local-hosts.tsv este manifest generat explicit din registry-ul SQLite./download/hosts.yaml, /download/local-hosts.tsv și /download/monitoring.json sunt randate din SQLite.Aplicația nu face commit/push automat după modificări. Exportul și arhivarea rămân pași operaționali separați.
Schema este creată automat de scripts/host_manager.pl la prima citire/scriere a store-ului.
CREATE TABLE IF NOT EXISTS documents (
name TEXT PRIMARY KEY,
content TEXT NOT NULL,
updated_at TEXT NOT NULL
);
| Obiect | Tip | Rol |
|---|---|---|
documents |
table | Document-store runtime pentru registry și Work Orders |
sqlite_autoindex_documents_1 |
index intern SQLite | Indexul automat creat pentru PRIMARY KEY (name) |
Nu există alte tabele, view-uri, trigger-e sau indexuri definite de aplicație în schema curentă.
documents| Coloană | Tip declarat | Null | Default | Cheie | Descriere |
|---|---|---|---|---|---|
name |
TEXT |
NOT NULL implicit prin PK |
none | PRIMARY KEY |
Identificatorul documentului operațional. Valorile cunoscute sunt hosts_yaml și work_orders_yaml. |
content |
TEXT |
NOT NULL |
none | none | Payload-ul documentului, serializat ca YAML strict compatibil cu parserul aplicației. |
updated_at |
TEXT |
NOT NULL |
none | none | Timestamp ISO UTC setat de aplicație la insert/update. |
| Tabel | Cheie | Coloane | Observații |
|---|---|---|---|
documents |
Primary key | name |
Garantează un singur rând pentru fiecare document operațional. |
SQLite implementează cheia primară textuală prin indexul intern sqlite_autoindex_documents_1.
| Index | Tabel | Coloane | Unic | Creat de | Rol |
|---|---|---|---|---|---|
sqlite_autoindex_documents_1 |
documents |
name |
da | SQLite | Lookup rapid pentru SELECT ... WHERE name = ? și enforcement pentru primary key. |
Nu există indexuri explicite definite de aplicație. Nu există index pe updated_at, pentru că aplicația nu face query-uri de tip listare istorică sau filtrare temporală.
Nu există foreign keys între tabele, pentru că schema curentă are o singură tabelă.
Relațiile de business sunt în interiorul YAML-ului din content, nu modelate relational. De exemplu:
hosts_yamlwork_orders_yamlhost_id textual în YAML, nu printr-un FOREIGN KEYPRAGMA foreign_keys = ON este activat ca pregătire pentru o schemă viitoare cu tabele relaționale, dar în schema curentă nu are efect practic.
| Tabel | Constrângere | Efect |
|---|---|---|
documents |
PRIMARY KEY (name) |
Nu permite două documente cu același name. |
documents |
content TEXT NOT NULL |
Nu permite documente fără payload. |
documents |
updated_at TEXT NOT NULL |
Nu permite rânduri fără timestamp de modificare. |
Nu există CHECK constraints pentru valorile permise în name, formatul YAML sau formatul timestamp-ului. Aceste validări sunt făcute în codul Perl prin parserul strict YAML și prin fluxurile API.
Citire document:
SELECT content FROM documents WHERE name = ?;
Insert/update document:
INSERT INTO documents (name, content, updated_at)
VALUES (?, ?, ?)
ON CONFLICT(name) DO UPDATE
SET content = excluded.content,
updated_at = excluded.updated_at;
Creare schemă:
CREATE TABLE IF NOT EXISTS documents (
name TEXT PRIMARY KEY,
content TEXT NOT NULL,
updated_at TEXT NOT NULL
);
Setări aplicate la conectare:
PRAGMA journal_mode = WAL;
PRAGMA foreign_keys = ON;
Nu există încă tabelă schema_migrations sau schema_version. Schema este implicit versiunea 1 și este definită de blocul CREATE TABLE IF NOT EXISTS documents din scripts/host_manager.pl.
Î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.
hosts_yamlConține registry-ul de hosturi în formatul config/hosts.yaml.
Este citit de:
GET /api/hostsGET /download/hosts.yamlGET /download/local-hosts.tsvGET /download/monitoring.jsonPOST /api/render/local-hosts-tsvEste scris de:
POST /api/hosts/upsertPOST /api/hosts/deletePOST /api/work-orders/confirm, când o acțiune modifică registry-ulAplicația normalizează la salvare:
policy:
storage_authority: "sqlite"
runtime_database: "<HOST_MANAGER_DB>"
work_orders_yamlConține Work Orders în formatul config/work-orders.yaml.
Este citit de:
GET /api/work-ordersPOST /api/work-orders/checklistPOST /api/work-orders/confirmEste scris de:
POST /api/work-orders/checklistPOST /api/work-orders/confirmLa prima accesare a unui document:
documents.config/.Important: după seed, modificările ulterioare ale fișierelor config/hosts.yaml sau config/work-orders.yaml nu schimbă automat baza existentă.
Cu WAL activ, runtime-ul poate avea trei fișiere:
var/host-manager.sqlite
var/host-manager.sqlite-wal
var/host-manager.sqlite-shm
Toate trei aparțin store-ului runtime. Nu se comit în git și nu se înlocuiesc prin deploy de cod.
Pe jumper:
cd /usr/local/xdev-host-manager
sqlite3 var/host-manager.sqlite '.schema'
sqlite3 var/host-manager.sqlite '.tables'
sqlite3 var/host-manager.sqlite 'pragma table_info(documents);'
sqlite3 var/host-manager.sqlite 'pragma index_list(documents);'
sqlite3 var/host-manager.sqlite 'pragma index_info(sqlite_autoindex_documents_1);'
sqlite3 var/host-manager.sqlite 'pragma foreign_key_list(documents);'
sqlite3 var/host-manager.sqlite 'select name, updated_at, length(content) from documents order by name;'
sqlite3 var/host-manager.sqlite 'select content from documents where name = "hosts_yaml";'
sqlite3 var/host-manager.sqlite 'select content from documents where name = "work_orders_yaml";'
Pentru export YAML curent:
curl -fsS -b cookies.txt https://hosts.madagascar.xdev.ro/download/hosts.yaml
Endpoint-urile de download sunt OTP-protected; exemplul presupune o sesiune validă.
Backup recomandat, cu serviciul oprit sau prin API-ul SQLite:
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'"
Pentru o copie brută, include și fișierele WAL/SHM sau oprește serviciul înainte:
sudo systemctl stop host-manager
sudo cp -a var/host-manager.sqlite* backups/host-manager/
sudo systemctl start host-manager
Restore-ul înlocuiește sursa de adevăr runtime și trebuie făcut explicit:
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
Dacă se restaurează o copie brută, tratează host-manager.sqlite, host-manager.sqlite-wal și host-manager.sqlite-shm ca set coerent.
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:
hostshost_nameshost_roleshost_sourceswork_orderswork_order_checklistwork_order_actionsPână atunci, contractul stabil este numele documentelor din documents și formatele YAML randate de aplicație.