# Read-only FinanceManager deployment and Tailscale audit

Use this before any deployment, restart, migration, rollback, or Tailnet exposure of a sensitive financial dashboard. The audit must remain metadata-only unless the user explicitly authorizes reading productive content.

## Safety boundary

Do not open the productive database, raw imports, exports, reports, secrets, backup contents, or application logs. Safe evidence includes repository metadata, process metadata, listener addresses, service/container metadata, PID-file values, file modes/sizes/mtimes, route names, HTTP status/allowlisted headers, and Tailscale self/Serve/Funnel configuration. Do not restart, stop, kill, migrate, deploy, restore, chmod, or rewrite configuration during the audit.

## Audit sequence

1. **Repository and candidate revision**
   - Record branch, HEAD, last commit, tags, worktree status, remotes with credentials redacted, and worktree inventory.
   - Recheck `git status` at the end. A tree that becomes dirty during the audit indicates concurrent work; do not deploy or inspect/reset the unrelated diff.
   - Compare candidate and canonical deployment revisions with `git merge-base --is-ancestor` both ways. Do not call branches equivalent merely because commit messages or files look similar.

2. **Resolve the actual runtime before probing URLs**
   - Inventory matching user/system services, Docker/Compose containers, listeners, and process metadata.
   - For each candidate process correlate PID, listener, command with credential-like arguments redacted, cwd, executable, cgroup/service/container, branch, and HEAD.
   - Distinguish production services from foreign applications on the expected ports and from loopback-only Vite/test previews. An open default port is not proof that FinanceManager is running.
   - Treat stale PID files as evidence of an old launch only. Verify `/proc/<pid>`; never infer a running revision from a dead PID.
   - If no Finance backend/frontend process exists, report **no active deployment** and running revision `N/A`; list previews separately.

3. **Startup and supervision mechanism**
   - Read start/stop/restart scripts, unit files, Compose metadata, package scripts, and reverse-proxy configuration.
   - Check for hard-coded repo roots, ports, hosts, old Tailnet addresses, broad `0.0.0.0` binds, unmanaged background jobs, force-kill-by-port behavior, and health checks that only test “port open.”
   - Cross-check environment variable names against the code that consumes them. Detect obsolete variables, default proxy targets, and status code that can mistake a foreign listener for FinanceManager.

4. **Tailscale runtime**
   - Parse `tailscale status --json` and emit only self state, hostname, DNS name, Tailnet IPs, online/exit-node state, and version; do not dump peers.
   - Inspect both `tailscale serve status --json` and `tailscale funnel status --json` with headers/auth/token-like values redacted.
   - Resolve every Serve/Funnel proxy target to a local listener. A configured HTTPS proxy whose backend is absent is a broken exposure, not a healthy dashboard.
   - Treat `AllowFunnel`/Funnel status as an internet-exposure warning requiring explicit review. Do not place financial UI behind it by default.
   - Prefer Tailnet-only HTTPS Serve to a loopback frontend/reverse proxy. Keep the finance API on loopback and proxy `/api` server-side.

5. **Safe HTTP and CORS probes**
   - Probe only known health/root endpoints and print status plus allowlisted headers; discard bodies.
   - An OpenAPI probe may report title/version/path names and route count, but not response examples or domain data.
   - Do not send probes to a port until its owning application is identified. A response from the wrong app is not Finance evidence.
   - Trace browser request topology before diagnosing CORS. If the frontend uses relative `/api` plus a server-side proxy, browser-to-backend CORS may be irrelevant. Still compare configured origins and current Tailnet host/IP to detect stale direct-access paths.

6. **Runtime and rollback metadata**
   - Confirm runtime is outside Git and stat known DB/log/backup/secrets paths without opening them.
   - Report mode, owner, size bucket, mtime, and aggregate file/checksum counts. Never print sensitive filenames when counts suffice.
   - Flag productive data, reports, logs, and backups that are group/world readable; the desired private baseline is normally `0700` directories and `0600` files.
   - Identify exact backup, checksum verification, restore-confirmation, schema-migration, and code rollback mechanisms. Backup existence alone is not rollback readiness.
   - Compare backup-file and checksum-sidecar counts, but do not assume unmatched counts identify valid/invalid pairs without a filename-level audit authorization.

## Release and rollback recommendation shape

If the audit finds no deployment or an unsafe/ambiguous runtime, recommend rather than execute:

1. freeze an approved clean commit in an immutable release worktree/directory;
2. run the repository's full verification gate and `git diff --check`;
3. create and verify a pre-migration DB backup and restore-test it to a separate temporary path;
4. tighten runtime permissions;
5. allocate conflict-free dedicated ports;
6. bind backend and frontend/reverse proxy to loopback;
7. use a supervised service and built frontend rather than an unmanaged Vite dev process where practical;
8. disable Funnel and configure Tailnet-only Serve;
9. record deployed/prior commits, schema version, backup identifier, ports, and service version in a non-sensitive release manifest;
10. smoke-test safe health, Tailnet HTTPS, proxy/CORS behavior, and absence of direct backend exposure;
11. roll code back by switching to the recorded prior immutable release; restore the DB only for an incompatible migration and only from the verified pre-deploy backup.

## Reporting

Lead with the operational conclusion: active deployment yes/no, running revision or `N/A`, Tailnet exposure state, and whether deployment is safe now. Then separate facts, important findings, safest plan, limitations (for example firewall rules requiring privilege), and an explicit statement of files/actions changed. Never imply that an audit performed deployment work.