{
  "app": "findata",
  "label": "FinData OS — private financial data lakehouse (findata.spboucher.ai)",
  "domain": "findata.spboucher.ai",
  "port": 8600,
  "health_path": "/api/v1/health",
  "dir": "~/apps/findata",
  "extra_paths": [],
  "sync_excludes": [".git/", ".DS_Store", ".venv/", "apps/web/node_modules/", "apps/web/.next/", "apps/web/out/", "data/", "logs/", "backups/", ".env", "__pycache__/", ".pytest_cache/", ".ruff_cache/", "tests/_tmp/"],
  "requires": { "runtimes": ["uv", "node", "pnpm", "pm2", "postgresql@17"], "ram_gb": 6, "disk_gb": 300, "ports": [8600] },
  "ram_mb_observed": 900,
  "size_mb": 20,
  "placement": { "pin": "M3U96a", "prefer": "M3U96a", "avoid": ["M1M32"], "reason": "Storage node chosen in docs/DISCOVERY.md: 1 TB Apple NVMe (508 GB free, SMART verified, 5 GB/s), 32 cores / 96 GB for DuckDB, Postgres 17 + Redis already local, wg1 10.67.0.10. Lake at ~/findata-lake (outside the app dir)." },
  "processes": [
    { "name": "findata-api",    "manager": "pm2", "script": "{{HOME}}/apps/findata/.venv/bin/python", "args": ["-m", "uvicorn", "findata_api.main:app", "--host", "0.0.0.0", "--port", "8600", "--workers", "1"], "interpreter": null, "cwd": "{{HOME}}/apps/findata", "env": {"FINDATA_ROOT": "{{HOME}}/apps/findata", "PATH": "/opt/homebrew/opt/postgresql@17/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin"}, "cron_restart": null, "autorestart": true, "max_memory_restart": "6G" },
    { "name": "findata-worker", "manager": "pm2", "script": "{{HOME}}/apps/findata/.venv/bin/python", "args": ["-m", "findata_ingest.cli", "worker"], "interpreter": null, "cwd": "{{HOME}}/apps/findata", "env": {"FINDATA_ROOT": "{{HOME}}/apps/findata", "PATH": "/opt/homebrew/opt/postgresql@17/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin"}, "cron_restart": null, "autorestart": true, "max_memory_restart": "24G" }
  ],
  "ngrok": null,
  "launchd": [],
  "env_overrides": {},
  "hooks": {
    "post_sync": [
      "test -f .env || { echo 'ERREUR: .env absent (secrets) — copier ~/Desktop/Cluster/secrets/findata/.env'; exit 1; }; chmod 600 .env",
      "export PATH=\"/opt/homebrew/bin:$HOME/.local/bin:$PATH\"; uv sync --frozen 2>&1 | tail -1 && echo '  python deps ok'",
      "export PATH=\"/opt/homebrew/bin:$PATH\"; cd apps/web && pnpm install --frozen-lockfile --silent && pnpm build 2>&1 | tail -2 && echo '  web build ok'",
      "export PATH=\"/opt/homebrew/opt/postgresql@17/bin:/opt/homebrew/bin:$PATH\"; set -a; . ./.env; set +a; .venv/bin/python -m findata_ingest.cli migrate && echo '  migrations ok'",
      "mkdir -p ~/findata-lake logs && chmod 700 ~/findata-lake && echo '  lake dir ok'"
    ],
    "post_start": []
  },
  "ka_repo": false,
  "tunnel": { "domain": "findata.spboucher.ai", "gateway": "BHS64", "note": "DNS GoDaddy A findata.spboucher.ai → 51.161.112.61 vérifié le 2026-11-01 avant déploiement ; route Caddy posée par mld deploy ; findata-api écoute 0.0.0.0:8600 avec garde de provenance (loopback, wg1 10.67.0.0/16, LAN) ; Caddy → wg1 10.67.0.10:8600" },
  "notes": "Monorepo uv (Python 3.13) : services/api (FastAPI :8600, sert aussi la console Next.js statique apps/web/out), services/ingest (worker unique = verrou d'écriture du lac + ordonnanceur), lac Parquet ~/findata-lake, Postgres 17 local (DB findata, rôle findata). Secrets uniquement dans ~/apps/findata/.env (600) ; copie ~/Desktop/Cluster/secrets/findata/.env. Sauvegarde quotidienne 04:00 ET → M4M64a:~/backups/findata (rsync + pg_dump zstd). CLI : .venv/bin/findata status|discover|ingest …"
}
