Uncommitted work-in-progress from 2026-07-08, carried forward: - audit-engine: refine two-pass metadata + content-inspection audit model - audit-matching, content-inspector, shape-audit-spec: supporting matching and spec updates for the two-pass model - task-audit route/panel: UI and API polish - add @napi-rs/canvas dependency, Dockerfile/next.config adjustments for it - test updates and additions (audit-engine, audit-decision-logic, run-task-audit) - add loose dev notes (clone runbook, issues implementation, overdue filter bug report, shared count helper plan)
3.8 KiB
3.8 KiB
Horizon Dev-Clone Runbook — 2026-06-25
Stand up a development instance of Horizon on a separate Linux host that runs the latest (working-tree) code against an exact copy of live production data.
- Target host:
root@dev02.nb.wulf.cloud - Dev domain:
https://horizon-dev.seubert.cloud - Source of truth (code):
/opt/projects/OnDeck/ondeck(working tree, incl. uncommitted changes) - Source of truth (stack):
/opt/stacks/horizon - Prod DB: container
horizon-db, databasehorizon, userhorizon_user
Decisions (locked)
| Decision | Choice |
|---|---|
| Where dev runs | Separate host dev02.nb.wulf.cloud, executed hands-on this session |
| Code version | Working tree as-is (includes uncommitted automation-settings / sync changes) |
| Auth | Entra (Azure AD) SSO — dev redirect URI added to app f6c778cf-c850-47d0-85e7-aff1d1c3288b |
| Data | Exact pg_dump restore of live horizon DB (real client PII on dev box) |
| Routing/TLS | New Pangolin site = newt client on dev host + resource for the dev domain |
Target architecture
| Concern | Prod | Dev clone |
|---|---|---|
| App container | horizon-app :3000 |
horizon-dev-app :3000 |
| DB container | horizon-db |
horizon-dev-db (fresh volume) |
| Backup sidecar | horizon-backup |
optional / off initially |
| Domain | horizon.seubert.cloud |
horizon-dev.seubert.cloud |
| Routing | Pangolin via newt |
new Pangolin site (newt on dev host) + resource |
| Auth | Entra SSO | Entra SSO + dev redirect URI |
| Secrets | prod | regenerated NEXTAUTH_SECRET, DB_PASSWORD |
Execution sequence
- Pre-flight (dev host): Docker + compose v2 present; ≥ ~10 GB free on
/; outbound 443 reachable (newt → Pangolin). - Pangolin: create a new site; install/run
newton the dev host; add resourcehorizon-dev.seubert.cloud→http://horizon-dev-app:3000; verify DNS + cert. (Use thepangolinskill.) - Azure AD: add redirect URI
https://horizon-dev.seubert.cloud/api/auth/callback/azure-adto Entra appf6c778cf-c850-47d0-85e7-aff1d1c3288b. - Ship code: rsync
/opt/projects/OnDeck/ondeck→ dev host, excludingnode_modules,.next,.git. - Stack + env: copy
/opt/stacks/horizon; rename containers tohorizon-dev-*; setNEXTAUTH_URL=https://horizon-dev.seubert.cloud; regenerateNEXTAUTH_SECRETandDB_PASSWORD; keep Azure creds; keep read-only AFW/AMS creds; leaveGRAPH_*unset. - Data copy:
pg_dumplivehorizon-db→ gzip → transfer → restore into freshly-initializedhorizon-dev-db; thenprisma migrate deploy(ordb push) to reconcile schema with working-tree code. - Build & start:
docker compose up -d horizon-dev-db(wait healthy) → restore dump →docker compose build horizon-dev-app && docker compose up -d. - Smoke test: health endpoint; Entra login; spot-check real client/policy/task data present.
Safety guards (dev must not perturb prod or external systems)
- No external cron trigger wired on dev →
/api/cron/*stays gated byCRON_SECRET, nothing calls it (no auto-generated tasks / scheduled jobs firing). - AFW/AMS uses read-only user
1100080_RO→ sync cannot mutate the AMS. GRAPH_*unset (as in prod) → no SharePoint/email writes.- Dev
NEXTAUTH_SECRET/DB_PASSWORDregenerated so dev secrets ≠ prod.
Obligations / cleanup
- PII: dev box now holds a full copy of real client PII — ensure
dev02is secured commensurately and the copy is removed when the dev instance is decommissioned. - Temp SSH key:
claude-horizon-dev-clone-2026-06-25added toroot@dev02:~/.ssh/authorized_keys. Remove that line when finished. - Consider a teardown step (drop dev DB volume, remove Pangolin resource + site, remove Azure redirect URI) when dev is no longer needed.