# Vue Dashboard auto-load runtime operations

Use this reference for FinanceManager FastAPI + Vue User Mode sprints where the dashboard should start, auto-load local runtime data, and be opened in-browser for the user.

## Durable pattern

- Keep Vue render read-only and local-first: page mount may call only local FastAPI endpoints; provider refreshes, OpenFIGI/CoinGecko/FMP/Finnhub/etc. must remain explicit click/CLI/scheduled actions.
- Add a shared local-status component/read model that shows: FastAPI connected, Runtime DB available, external providers on render = no, last local data fetch.
- Add a refresh button that clears local API cache and re-fetches local DTOs; do not make it call provider APIs.
- User Mode pages should auto-load their primary local DTOs on mount:
  - Command Center: overview + top local positions.
  - Portfolio: asset/platform allocation + top/unvalued positions.
  - Crypto: aggregate coin rows + detail drawer on row click.
  - Equity/Cash: local equity DTOs + cash summary, no valuation guessing.
  - Wallets: aggregate wallet table + wallet detail drawer; no addresses/secrets.
  - Reports: list existing runtime reports only; do not show fake “generate” controls unless implemented.
- Keep provider keys backend/runtime-only. Never introduce `VITE_*` secrets for finance providers.

## FastAPI/SQLite/TestClient pitfall

FastAPI dependency-injected SQLite connections can cross threads under `TestClient` or async worker execution. If a test injects an in-memory connection or a runtime connection is yielded into request handling, use `sqlite3.connect(..., check_same_thread=False)` for that connection factory or test fixture. Otherwise requests may fail with:

`sqlite3.ProgrammingError: SQLite objects created in a thread can only be used in that same thread`

Keep this as a threading compatibility fix, not a general excuse to share one mutable connection broadly without request scoping.

## Verification recipe

Run all of these before commit/push:

```bash
python -m compileall -q src tests
pytest -q
cd frontend
npm install
npm run test
npm run build
cd ..
git diff --check
```

Then run targeted safety scans that ignore generated caches/artifacts and confirm:

- no source/provider secrets in `src`, `tests`, `frontend/src`, docs, or package files;
- no secrets in `frontend/dist`;
- no tracked `frontend/node_modules`, `frontend/dist`, `.env.local`, SQLite DBs, reports, or runtime files.

Remove generated `__pycache__`, `.pytest_cache`, `frontend/dist`, `frontend/node_modules`, and TS build info before staging unless the repo intentionally tracks a generated artifact.

## Browser sanity / user-link recipe

Preflight before starting services:

```bash
# Detect stale dashboard processes before they mask the current checkout.
ss -ltnp '( sport = :8000 or sport = :5173 )' || true

# If old uvicorn/node processes are bound to those ports, kill only those PIDs,
# then verify the ports are free before restarting.

# Frontend dependencies may have been intentionally removed after Git-safety cleanup.
# If frontend/node_modules is missing, reinstall from the lockfile before npm run dev.
cd frontend
[ -d node_modules ] || npm ci
cd ..
```

Start services from the repo using the proven Tailscale-safe pattern:

```bash
# Backend from repo root
source ~/jarvis_runtime/finance-system/venv/bin/activate
export JARVIS_FINANCE_RUNTIME_DIR="$HOME/jarvis_runtime/finance-system"
unset JARVIS_FINANCE_DB_PATH
PYTHONPATH=src uvicorn jarvis_finance.api.main:app --host 127.0.0.1 --port 8000
```

```bash
# Frontend from frontend/ — critical for external/Tailscale clients
TS_IP=$(tailscale ip -4 | head -n1)
VITE_API_BASE_URL="http://$TS_IP:5173" npm run dev -- --host 0.0.0.0 --port 5173
```

When giving the user a remote/Tailscale link, do **not** let the built frontend call `http://127.0.0.1:8000` from the user's browser; that points at the user's device, not the server. Either rely on Vite's `/api` proxy by using same-origin `/api` calls, or start Vite with an API base that routes through the externally reachable frontend/proxy URL, for example:

```bash
cd frontend
VITE_API_BASE_URL=http://<tailscale-or-host-ip>:5173 npm run dev -- --host 0.0.0.0 --port 5173
```

If using `scripts/start_vue_dashboard.sh`, verify whether it actually forwards `VITE_API_BASE_URL`; if not, start the frontend process directly with the env var or patch the script before handing over the link. Do not trust a green `/api/health` curl alone: probe the served dev module or browser state to confirm `import.meta.env.VITE_API_BASE_URL` is the Tailscale origin, e.g. `curl http://<tailscale-ip>:5173/src/api/client.ts | grep VITE_API_BASE_URL`, then browser-verify `FastAPI verbunden: ja` and `Runtime-DB verfügbar: ja`.

This keeps browser API calls on the same externally reachable origin (`http://<host>:5173/api/...`) while Vite proxies them to the local backend on `127.0.0.1:8000`. Never put finance provider secrets into `VITE_*`; this value is only the public API base/origin.

Check readiness locally and through the user-visible route:

```bash
curl -fsS http://127.0.0.1:8000/api/health
curl -fsS http://127.0.0.1:5173/ >/dev/null
curl -fsS http://127.0.0.1:5173/api/health
curl -fsS http://<tailscale-or-host-ip>:5173/api/health
```

Open `http://<tailscale-or-host-ip>:5173/` for the user, or `http://127.0.0.1:5173/` only when browsing on the same host, and verify in-browser:

- document title is `JARVIS Finance Dashboard`;
- `FastAPI verbunden: ja`;
- `Runtime-DB verfügbar: ja`;
- `Daten geladen` is visible;
- no render-time external provider resources appear in browser performance entries (`coingecko`, `openfigi`, `yahoo`, `alphavantage`, etc.).

For row drawers, DOM `click()` can be more reliable than accessibility-row clicks when table rows are deep/truncated in browser snapshots.

## Commit/push discipline

Commit only after tests, build, scans, and browser sanity. When pushing with the FinanceManager runtime GitHub token, use a temporary authenticated request/header or askpass mechanism, never store a token-bearing remote and never print the token. Verify `git rev-parse HEAD` equals authenticated `git ls-remote origin refs/heads/main` after push.

## Background-process hygiene

When starting backend/frontend through Hermes background processes, keep the session IDs in the user-facing final note so they can be killed later. If a delayed watch notification arrives after a process was already killed, verify with the process list before alarming the user.