"""Read-only structural consistency checks; no PostgreSQL execution claims.""" import csv, hashlib, json, re from pathlib import Path root=Path(__file__).resolve().parents[2] base=root/'docs/investmoz' schema=json.loads((base/'schema.json').read_text(encoding='utf-8')) legacy=json.loads((base/'legacy-schema.json').read_text(encoding='utf-8')) tables={t['name']:t for t in legacy['tables']+schema['tables']} def rows(name): return list(csv.DictReader((base/name).open(encoding='utf-8',newline=''))) catalog=rows('table-catalog.csv') assert {r['Tabela'] for r in catalog}==set(tables) dictionary=rows('data-dictionary.csv') fields={(t,c['name']) for t,v in tables.items() for c in v['columns']} assert {(r['Tabela'],r['Campo']) for r in dictionary}==fields assert len(dictionary)==len(fields) trace=rows('traceability.csv') assert {(r['Tabela'],r['Campo']) for r in trace}==fields erd=(base/'erd.mmd').read_text(encoding='utf-8') erd_fields=set() for table,body in re.findall(r'^\s+(\w+) \{\n(.*?)^\s+\}',erd,re.M|re.S): for line in body.splitlines(): if line.strip(): erd_fields.add((table,line.split()[1])) assert erd_fields==fields seen=set(t['name'] for t in legacy['tables']) for t in schema['tables']: sql=(root/t['migration']).read_text(encoding='utf-8') assert t['sql'] in sql for rel in schema['relationships']: if rel['table']!=t['name']: continue assert rel['target'] in seen or rel['target']==t['name'],rel target=tables[rel['target']] ct=next(c['type'] for c in t['columns'] if c['name']==rel['column']) rt=next(c['type'] for c in target['columns'] if c['name']==rel['target_column']) assert ct==rt,(rel,ct,rt) assert f"{rel['target']} "+('|o' if rel['nullable'] else '||')+f" --o{{ {rel['table']} : {rel['column']}" in erd seen.add(t['name']) for item in schema['indexes']: assert item['sql'] in (root/item['migration']).read_text(encoding='utf-8') names=[i['name'] for i in schema['indexes']]+[c['name'] for c in schema['constraints']] assert len(names)==len(set(names)) assert all(len(n)<=63 for n in names) migrations=list((root/'database/migrations').glob('2026_09_24_*_investmoz_*.php')) assert len(migrations)==15,len(migrations) for path in migrations: php=path.read_text(encoding='utf-8') down=php.split('public function down(): void')[1] assert not re.search(r'DROP .* CASCADE|DROP EXTENSION',down) assert php.count("<<<'SQL'")==php.count('\nSQL);') for line in (base/'checksums.sha256').read_text(encoding='utf-8').splitlines(): digest,path=line.split(' ',1) assert hashlib.sha256((root/path).read_bytes()).hexdigest()==digest,path print(f"PASS: {len(tables)} tables, {len(fields)} columns, {len(schema['relationships'])+len(legacy['relationships'])} FKs, 15 migrations; catalogue/dictionary/ERD/checksums coherent.") print("PostgreSQL/PostGIS lifecycle, authorization and performance are NOT validated by this static check.")