import json import re import subprocess from pathlib import Path ROOT = Path(__file__).resolve().parents[1] FRONTEND = ROOT / "frontend" REGISTRY = FRONTEND / "private-data-registry.js" def test_private_database_registry_covers_every_shipped_indexeddb_store(): harness = f""" const databases = require({json.dumps(str(REGISTRY))}); process.stdout.write(JSON.stringify(databases)); """ completed = subprocess.run( ["node", "-e", harness], text=True, capture_output=True, check=True ) registered = set(json.loads(completed.stdout)) opened = set() for path in FRONTEND.glob("*.js"): source = path.read_text() opened.update(re.findall(r"dbName\s*=\s*['\"](stackchain-[^'\"]+)['\"]", source)) opened.update(re.findall(r"createIndexedDbTransaction\([^\n]+['\"](stackchain-[^'\"]+)['\"]", source)) assert registered == opened assert registered == { "stackchain-background-outbox-v1", "stackchain-offline-work-v2", "stackchain-unfiled-captures-v1", "stackchain-voice-transcripts-v1", "stackchain-search-reply-drafts-v1", "stackchain-conversation-reply-drafts-v1", "stackchain-today-action-mailbox-v1", "stackchain-app-badge-preference-v1", } def test_every_private_data_purge_context_consumes_the_shared_registry(): for name in ("private-device-data.js", "session.js", "service-worker.js"): source = (FRONTEND / name).read_text() assert "stackchainPrivateDatabases" in source assert not re.search(r"deletePrivateDatabase\(['\"]stackchain-", source) html = (FRONTEND / "index.html").read_text() assert html.index('static/private-data-registry.js') < html.index('static/session.js') def test_private_inventory_loads_after_registry_and_before_storage_controller(): html = (FRONTEND / "index.html").read_text() registry = html.index('static/private-data-registry.js') inventory = html.index('static/private-data-inventory.js') controller = html.index('static/device-storage.js') assert registry < inventory < controller