1{2 "app": "findata",3 "label": "FinData OS — private financial data lakehouse (findata.spboucher.ai)",4 "domain": "findata.spboucher.ai",5 "port": 8600,6 "health_path": "/api/v1/health",7 "dir": "~/apps/findata",8 "extra_paths": [],9 "sync_excludes": [10 ".git/",11 ".DS_Store",12 ".venv/",13 "apps/web/node_modules/",14 "apps/web/.next/",15 "apps/web/out/",16 "data/",17 "logs/",18 "backups/",19 ".env",20 "__pycache__/",21 ".pytest_cache/",22 ".ruff_cache/",23 "tests/_tmp/"24 ],25 "requires": {26 "runtimes": [27 "uv",28 "node",29 "pnpm",30 "pm2",31 "postgresql@17"32 ],33 "ram_gb": 6,34 "disk_gb": 1500,35 "ports": [36 860037 ]38 },39 "ram_mb_observed": 900,40 "size_mb": 20,41 "placement": {42 "pin": "M3U96a",43 "prefer": "M3U96a",44 "avoid": [45 "M1M32"46 ],47 "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)."48 },49 "processes": [50 {51 "name": "findata-api",52 "manager": "pm2",53 "script": "{{HOME}}/apps/findata/infra/scripts/run-under-sshd.sh",54 "args": [55 "{{HOME}}/apps/findata",56 "{{HOME}}/apps/findata/.venv/bin/python",57 "-m",58 "uvicorn",59 "findata_api.main:app",60 "--host",61 "0.0.0.0",62 "--port",63 "8600",64 "--workers",65 "1"66 ],67 "interpreter": null,68 "cwd": "{{HOME}}/apps/findata",69 "env": {70 "FINDATA_ROOT": "{{HOME}}/apps/findata",71 "PATH": "/opt/homebrew/opt/postgresql@17/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin"72 },73 "cron_restart": null,74 "autorestart": true,75 "max_memory_restart": "6G",76 "kill_timeout": 3000077 },78 {79 "name": "findata-worker",80 "manager": "pm2",81 "script": "{{HOME}}/apps/findata/infra/scripts/run-under-sshd.sh",82 "args": [83 "{{HOME}}/apps/findata",84 "{{HOME}}/apps/findata/.venv/bin/python",85 "-m",86 "findata_ingest.cli",87 "worker"88 ],89 "interpreter": null,90 "cwd": "{{HOME}}/apps/findata",91 "env": {92 "FINDATA_ROOT": "{{HOME}}/apps/findata",93 "PATH": "/opt/homebrew/opt/postgresql@17/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin"94 },95 "cron_restart": null,96 "autorestart": true,97 "max_memory_restart": "24G",98 "kill_timeout": 360000099 },100 {101 "name": "findata-bulk-1",102 "manager": "pm2",103 "script": "{{HOME}}/apps/findata/infra/scripts/run-under-sshd.sh",104 "args": [105 "{{HOME}}/apps/findata",106 "{{HOME}}/apps/findata/.venv/bin/python",107 "-m",108 "findata_ingest.cli",109 "worker",110 "--role",111 "bulk"112 ],113 "interpreter": null,114 "cwd": "{{HOME}}/apps/findata",115 "env": {116 "FINDATA_ROOT": "{{HOME}}/apps/findata",117 "PATH": "/opt/homebrew/opt/postgresql@17/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin"118 },119 "cron_restart": null,120 "autorestart": true,121 "max_memory_restart": "12G",122 "kill_timeout": 3600000123 },124 {125 "name": "findata-bulk-2",126 "manager": "pm2",127 "script": "{{HOME}}/apps/findata/infra/scripts/run-under-sshd.sh",128 "args": [129 "{{HOME}}/apps/findata",130 "{{HOME}}/apps/findata/.venv/bin/python",131 "-m",132 "findata_ingest.cli",133 "worker",134 "--role",135 "bulk"136 ],137 "interpreter": null,138 "cwd": "{{HOME}}/apps/findata",139 "env": {140 "FINDATA_ROOT": "{{HOME}}/apps/findata",141 "PATH": "/opt/homebrew/opt/postgresql@17/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin"142 },143 "cron_restart": null,144 "autorestart": true,145 "max_memory_restart": "12G",146 "kill_timeout": 3600000147 },148 {149 "name": "findata-bulk-3",150 "manager": "pm2",151 "script": "{{HOME}}/apps/findata/infra/scripts/run-under-sshd.sh",152 "args": [153 "{{HOME}}/apps/findata",154 "{{HOME}}/apps/findata/.venv/bin/python",155 "-m",156 "findata_ingest.cli",157 "worker",158 "--role",159 "bulk"160 ],161 "interpreter": null,162 "cwd": "{{HOME}}/apps/findata",163 "env": {164 "FINDATA_ROOT": "{{HOME}}/apps/findata",165 "PATH": "/opt/homebrew/opt/postgresql@17/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin"166 },167 "cron_restart": null,168 "autorestart": true,169 "max_memory_restart": "12G",170 "kill_timeout": 3600000171 },172 {173 "name": "findata-bulk-4",174 "manager": "pm2",175 "script": "{{HOME}}/apps/findata/infra/scripts/run-under-sshd.sh",176 "args": [177 "{{HOME}}/apps/findata",178 "{{HOME}}/apps/findata/.venv/bin/python",179 "-m",180 "findata_ingest.cli",181 "worker",182 "--role",183 "bulk"184 ],185 "interpreter": null,186 "cwd": "{{HOME}}/apps/findata",187 "env": {188 "FINDATA_ROOT": "{{HOME}}/apps/findata",189 "PATH": "/opt/homebrew/opt/postgresql@17/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin"190 },191 "cron_restart": null,192 "autorestart": true,193 "max_memory_restart": "12G",194 "kill_timeout": 3600000195 }196 ],197 "ngrok": null,198 "launchd": [],199 "env_overrides": {},200 "hooks": {201 "post_sync": [202 "test -f .env || { echo 'ERREUR: .env absent (secrets) — copier ~/Desktop/Cluster/secrets/findata/.env'; exit 1; }; chmod 600 .env",203 "export PATH=\"/opt/homebrew/bin:$HOME/.local/bin:$PATH\"; uv sync --frozen 2>&1 | tail -1 && echo ' python deps ok'",204 "export PATH=\"/opt/homebrew/bin:$PATH\"; cd apps/web && pnpm install --frozen-lockfile --silent && pnpm build 2>&1 | tail -2 && echo ' web build ok'",205 "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'",206 "mkdir -p ~/findata-lake logs && chmod 700 ~/findata-lake && echo ' lake dir ok'"207 ],208 "post_start": []209 },210 "ka_repo": false,211 "tunnel": {212 "domain": "findata.spboucher.ai",213 "gateway": "BHS64",214 "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"215 },216 "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 … | 2026-11-01 soir : lac froid FINDATA_LAKE_COLD=/Volumes/ssd/findata (SSD externe 4 To, marqueur .findata-cold-root) pour les archives brutes et les datasets non « hot » ; 4 workers bulk (findata-bulk-1..4) pour backfill/options/fundamentals en parallèle ; téléchargement complet FirstRate lancé via `findata ingest backfill-all`. | TCC macOS : PM2/launchd n'ont pas l'Accès complet au disque → tous les processus passent par infra/scripts/run-under-sshd.sh (ré-exécution via sshd localhost, clé id_ed25519_maclustr) pour accéder au SSD externe. Alternative propre : accorder FDA à node + python dans Réglages → Confidentialité (GUI)."217}218