diff --git a/README.md b/README.md index a8b1350..f09fa22 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,128 @@ # ArchNest -A self-hosted ops dashboard — infrastructure monitoring, a bookmark hub for your homelab/cloud links, an embedded terminal, and system settings, all in one place. Real backend, real integrations, no mock data. +A self-hosted ops dashboard for a homelab/cloud setup: live infrastructure +monitoring across 9 real integration types, a categorized bookmark hub, a +full SSH suite (terminal, tunnels, file manager, host-to-host transfer, live +host metrics), Docker container management, and RDP/VNC/Telnet remote desktop +— all in one app, with zero mock data anywhere. -Frontend: React 19 + TypeScript + Vite, styled with Tailwind CSS v4, charts via Recharts, icons via Lucide React. -Backend: Fastify + TypeScript + SQLite (`better-sqlite3`), JWT auth, AES-256-GCM encrypted integration secrets. +**This repo is private and will never be public.** This README is written for +the owner and for any AI session picking up the project cold — it should be +detailed enough that neither needs to re-derive context from scratch. -**For a full handoff/status writeup (what's done, what's not, how to resume), see [`HANDOFF.md`](./HANDOFF.md).** +## What this is, in one paragraph + +ArchNest replaced a Homarr-style bookmark dashboard plus a handful of +disconnected admin tools (Proxmox UI, Portainer, separate SSH terminals, +WinSCP-equivalents) with one app that talks directly to the underlying +systems. It started as a 6-page mockup/portfolio piece and has since grown +into an 11-page real tool with a real Fastify backend, real SSH/Docker/cloud +integrations, and no synthetic data — every number on every page comes from +a live API call, a SQLite-backed table, or an SSH command run against a +managed host. + +## Current state & direction + +**Live and deployed** at `archnest.snsnetlabs.com`, auto-deploying on every +merge to `main` via `.github/workflows/deploy.yml`. All 11 pages and their +backend routes are built and working — there is no pending/on-hold page. +The active area of work is **the auth system**: the user menu's +Profile/Appearance/Security links were fixed in Phase 1; Phases 2-4 +(password change + sessions + login audit log, multi-user accounts, +Authentik SSO) are planned but not started — see `HANDOFF.md` for the full +phase breakdown and exactly where to resume. + +If you're a fresh AI session: read this file, then `HANDOFF.md` (current +task state + standing workflow rules), then `design-decisions.md` (visual +conventions + accurate per-page implementation notes), then +`TERMIX_MIGRATION.md` (history of how the SSH/Docker/Guacamole feature set +was built) if you need historical context on a specific feature. ## Pages -| Page | Route | Status | -|------|-------|--------| -| Glance | `/` | Done — real backend data (system status, resource overview, alerts, network traffic) | -| Infrastructure | `/infrastructure` | Done — resource distribution, node status grid, cost/trend breakdown, all from real integration data. "Network" sub-tab planned as a future addition. | -| BookNest | `/booknest` | Done — categorized bookmark hub wired to the real bookmarks API | -| Terminal | `/terminal` | **Pending / on hold** — will be based on a fork of the (archived) Termix project; user has the fork and intends to hand this off to another AI session to integrate. Do not start this without explicit instruction. | -| Settings | `/settings` | Done — Profile (real user identity + avatar, editable via API), Appearance, Integrations (8 real adapters), Notifications, Data & Backup, About | +| Page | Route | What it does | +|------|-------|---------------| +| Glance | `/` | Home dashboard — system/integration health, resource overview, recent activity, shortcuts | +| Infrastructure | `/infrastructure` | Resource inventory across all integrations — distribution donut, per-resource status grid, integration health, activity | +| BookNest | `/booknest` | Categorized bookmark hub — quick access, favorites, link health, full CRUD | +| Terminal | `/terminal` | Web SSH terminal — multi-tab, split panes, tmux attach, cert auth (OPKSSH) | +| Tunnels | `/tunnels` | SSH tunnel manager — local/remote/dynamic (SOCKS5) forwarding, auto-start, live status | +| Files | `/files` | SFTP file browser/editor over managed SSH hosts, with host-to-host transfer | +| Containers | `/containers` | Docker container management — start/stop/restart/pause/remove, logs, interactive exec | +| Remote Desktop | `/remote-desktop` | RDP/VNC/Telnet sessions via a Guacamole sidecar | +| Host Metrics | `/host-metrics` | Live CPU/memory/disk/network/processes/ports/firewall/login-activity per SSH host, polled every 5s | +| Settings | `/settings` | Profile, Appearance, Security, Integrations, Notifications, Data & Backup, About — deep-linkable via `?tab=` | +| Help | `/help` | Static guided tour of every page above | +| Login / Enrollment | `/login`, `/enrollment` | Auth entry points — not in the sidebar nav | -See `archnest-blueprint.md` for the original per-page design spec and `design-decisions.md` for the visual/UX conventions and lessons learned while building each page — read that file before making layout changes, it documents *why* things are built the way they are (hero banner layering, card blend techniques, icon library gotchas, etc.). +See `design-decisions.md`'s "Page Notes" section for a detailed, per-page +breakdown of layout, real data sources, and known quirks — it's kept in sync +with the actual code, not a spec written before the page existed. + +## Architecture + +### Frontend (`/src`) +- React 19 + Vite + TypeScript, Tailwind CSS v4, Recharts (donuts/area + charts), Lucide React icons, React Router. +- `src/lib/api.ts` — typed fetch wrapper (`apiFetch`) + one function per + backend endpoint + matching TS interfaces. This is the contract between + frontend and backend; any new backend route needs a matching entry here. +- `src/lib/AuthContext.tsx` — auth state backed by `localStorage` (single JWT, + no session tracking yet — Phase 2 of the auth roadmap). +- `src/pages/` — one file per route (see table above), plus `Login.tsx` / + `Enrollment.tsx` for the unauthenticated/first-run flows. +- `src/components/` — `TopBar.tsx` (title, global search across pages/ + integrations/bookmarks, user dropdown), `Sidebar.tsx` (nav + system-health + rollup widget). +- `App.tsx` — route table, plus per-route hero-banner config (`showHero`, + `heroPaddingTop`, `heroObjectPosition` lookup maps) and `topBarHeight` + lookup for pages with a subtitle (currently only BookNest). + +### Backend (`/backend`) +- Fastify 5, TypeScript, ESM (`tsx` for dev, `tsc -b` for build), entrypoint + `src/server.ts`. +- `backend/src/db/index.ts` — SQLite schema + `logEvent()` audit log. + Single-user schema today (no `role` column, no multi-account concept — + see `HANDOFF.md` Phase 3). +- `backend/src/db/crypto.ts` — AES-256-GCM `encryptSecret`/`decryptSecret`, + keyed by `ARCHNEST_SECRET_KEY`. +- `backend/src/routes/` — one file per feature area: + - `auth.ts` — setup, login, profile (`/api/setup`, `/api/auth/login`, + `/api/auth/me`) + - `integrations.ts` — integration CRUD + connection testing + - `bookmarks.ts` — bookmarks + categories CRUD + - `events.ts` — activity log retrieval + - `terminal.ts` — SSH terminal WebSocket (`connect`/`input`/`resize`/ + `list_tmux`/`disconnect`) + - `tunnels.ts` — SSH tunnel CRUD + connect/disconnect + - `files.ts` — SFTP list/read/write/mkdir/rename/delete/chmod/download/upload + - `docker.ts` — Docker exec WebSocket (interactive container shell) + - `guacamole.ts` — Guacamole WebSocket proxy for remote desktop + - `metrics.ts` — live host metrics endpoint + - `transfer.ts` — host-to-host file transfer orchestration (start/poll/cancel) + - `data.ts` — full backup export/import (integrations + secrets + bookmarks + tunnels) +- `backend/src/integrations/` — one adapter per type, all real (none are + stubs): `proxmox.ts`, `docker.ts`, `netbird.ts`, `cloudflare.ts`, `aws.ts`, + `uptimeKuma.ts`, `weather.ts`, `ssh.ts`, `remoteDesktop.ts`. Each implements + `testConnection()` (required) and `listResources()` (optional); + `registry.ts` maps `IntegrationType` → adapter. +- `backend/src/ssh/` — the shared SSH transport layer used by Terminal, + Files, Tunnels, Transfers, and Host Metrics: + - `connect.ts` — jump-host chaining, host-key verification, certificate auth + - `sftp.ts` — ephemeral SFTP connections for file ops + - `transfer.ts` — streamed host-to-host copy/move with progress + cancel + - `metrics/` — 10 sequential collectors (cpu, memory, disk, uptime, + network, system, processes, ports, firewall, login-stats) — sequential + on purpose, to stay under OpenSSH's `MaxSessions` limit per host. +- Docker images run on Alpine; **OpenSSL legacy provider is enabled** in + `backend/Dockerfile` (`OPENSSL_CONF=/etc/ssl/openssl-legacy.cnf`) so + old-format encrypted PEM keys (`BEGIN RSA PRIVATE KEY` + `DEK-Info`) still + decrypt under OpenSSL 3 — don't remove this without understanding why. +- **Required env vars, no defaults**: `ARCHNEST_SECRET_KEY`, + `ARCHNEST_JWT_SECRET`. The server refuses to start without both. Optional: + `ARCHNEST_DB_PATH`, `PORT`, `ARCHNEST_GUAC_CRYPT_KEY` / + `ARCHNEST_GUACD_HOST` / `ARCHNEST_GUACD_PORT`, `ARCHNEST_CORS_ORIGIN`, + `ARCHNEST_SESSION_LOG_DIR` (optional terminal session logging). ## Development @@ -34,23 +139,26 @@ npm install ARCHNEST_SECRET_KEY=$(openssl rand -hex 32) ARCHNEST_JWT_SECRET=$(openssl rand -hex 32) npm run dev ``` -Both `ARCHNEST_SECRET_KEY` (encrypts integration secrets at rest) and `ARCHNEST_JWT_SECRET` (signs auth tokens) are required env vars with no defaults — the server will refuse to start without them. `ARCHNEST_DB_PATH` optionally overrides the SQLite file location (defaults to a local path under `backend/`). `PORT` overrides the listen port (default 4000-range, check `server.ts`). +`ARCHNEST_DB_PATH` optionally overrides the SQLite file location (defaults to +a local path under `backend/`). `PORT` overrides the listen port (check +`server.ts` for the default). -Type-check both before committing: +Type-check both before committing — this is the minimum bar, not a substitute +for testing in a browser: ```bash npx tsc --noEmit # from repo root, frontend cd backend && npx tsc --noEmit # backend ``` -Vite/the browser surface some runtime errors (e.g. missing icon exports) that the type-checker won't catch, so also smoke-test pages in a browser. +Vite/the browser surface some runtime errors (e.g. missing icon exports — +see the lucide-react gotcha in `design-decisions.md`) that the type-checker +won't catch. ## Tech Stack **Frontend** -- React 19 + Vite + TypeScript -- React Router for routing -- Tailwind CSS v4 -- Recharts (donuts, line/area charts) -- Lucide React (icons) +- React 19 + Vite + TypeScript, React Router, Tailwind CSS v4 +- Recharts (donuts, line/area charts), Lucide React (icons) +- xterm.js (Terminal page terminal rendering) **Backend** - Fastify 5 + TypeScript, `tsx` for dev, `tsc -b` for build @@ -58,16 +166,56 @@ Vite/the browser surface some runtime errors (e.g. missing icon exports) that th - `@fastify/jwt` for auth tokens, `bcryptjs` for password hashing - `zod` for request validation - AES-256-GCM (Node `crypto`) for encrypting integration secrets at rest -- Integration adapters: Proxmox, Docker, NetBird, Cloudflare, AWS, Uptime Kuma, Weather, SSH (see `backend/src/integrations/`) +- SSH client library powering the SSH transport layer (`backend/src/ssh/`) +- Guacamole Lite protocol for RDP/VNC/Telnet, proxied to a `guacd` sidecar -**Deploy target:** Docker on `racknerd1` → NPM (Nginx Proxy Manager) proxy at `archnest.snsnetlabs.com`. +**Integrations**: Proxmox, Docker, NetBird, Cloudflare, AWS, Uptime Kuma, +Weather (wttr.in), SSH, Remote Desktop (RDP/VNC/Telnet via Guacamole) — see +`backend/src/integrations/` for adapter implementations. + +**Deploy target:** Docker on `racknerd1` → Nginx Proxy Manager at +`archnest.snsnetlabs.com`. ## Deployment -**Live and deployed** at `archnest.snsnetlabs.com`. The pipeline at `.github/workflows/deploy.yml` triggers on every push to `main`: it copies the repo to `racknerd1` over SCP and runs `docker compose up -d --build` there, gated on an `/api/health` check. No further setup is needed — merging a PR to `main` redeploys automatically. +**Live and deployed.** `.github/workflows/deploy.yml` triggers on every push +to `main`: builds, SCPs the repo to `racknerd1`, and runs +`docker compose up -d --build` there, gated on an `/api/health` health check. +No further setup is needed — merging a PR to `main` redeploys automatically. -If a deploy fails, check the workflow run's `deploy` job steps in order: `Pre-flight` (confirms host `.env` exists), `Copy repo to racknerd1`, `Build, restart, and clean up`, `Health check (backend /api/health)`. +`docker-compose.yml` runs 3 services: `archnest` (frontend), `archnest-backend`, +and `guacd` (remote desktop sidecar). -For reference, the one-time setup that was done to stand this up: host provisioning (Docker/Compose on `racknerd1`, deploy SSH user, `/opt/archnest` directory), `/opt/archnest/.env` populated from `.env.example` with real secrets, `RACKNERD_HOST`/`RACKNERD_USER`/`RACKNERD_SSH_KEY` added as GitHub Actions secrets, and DNS/Nginx Proxy Manager pointed at the host. +If a deploy fails, check the workflow run's `deploy` job steps in order: +`Pre-flight` (confirms host `.env` exists) → `Copy repo to racknerd1` → +`Build, restart, and clean up` → `Health check (backend /api/health)`. -See `HANDOFF.md` for current feature work in progress (multi-user accounts, SSO, security settings). +One-time setup already done (reference only, shouldn't need repeating): host +provisioning (Docker/Compose on `racknerd1`, deploy SSH user, `/opt/archnest` +directory), `/opt/archnest/.env` populated from `.env.example` with real +secrets, `RACKNERD_HOST`/`RACKNERD_USER`/`RACKNERD_SSH_KEY` added as GitHub +Actions secrets, DNS/Nginx Proxy Manager pointed at the host. + +## Documentation map + +- **`README.md`** (this file) — architecture, tech stack, deployment, page list. +- **`HANDOFF.md`** — current task state, standing workflow rules (git workflow, + mock-data policy, secrets discipline), and the auth/SSO roadmap. Read this + before starting any new work session. +- **`design-decisions.md`** — visual/UX conventions (colors, typography, card + style, animations) plus a detailed, accurate-as-of-now "Page Notes" section + per page — what's actually rendered and where its data comes from. This is + the file to update whenever a page's layout or data source changes. +- **`TERMIX_MIGRATION.md`** — phase-by-phase history of how the SSH/Tunnels/ + Files/Containers/Remote Desktop/Host Metrics/Transfer/Data-export feature + set was built (originally scoped as a migration from a forked Termix + project, hence the name). Useful for historical "why was it built this + way" context on those specific features. + +Two older docs were deleted as part of a documentation cleanup +(`archnest-blueprint.md`, the original 6-page mockup pitch with fictional +config files and placeholder numbers; `glance.md`, an early Glance-only spec +with the same problem). Their still-accurate content (color palette, +dropdown menu shape, card styling) was folded into `design-decisions.md`, +and everything else was superseded by the real, deployed implementation +described above. diff --git a/archnest-blueprint.md b/archnest-blueprint.md deleted file mode 100644 index 57c4677..0000000 --- a/archnest-blueprint.md +++ /dev/null @@ -1,405 +0,0 @@ -# ArchNest Dashboard — Blueprint - -> Complete spec for a 6-page custom dashboard. Portfolio showcase piece. - ---- - -## Global Design Language - -### Color Palette -| Role | Value | Usage | -|------|-------|-------| -| Background (page) | `#0D0E10` | Near-black, warm undertone | -| Background (cards) | `#141518` | Slightly elevated surfaces | -| Background (sidebar) | `#0A0B0D` | Darker than page | -| Border (cards) | `#1E2025` | Subtle 1px card outlines | -| Border (hover/active) | `#C8A434` | Gold highlight on interaction | -| Accent (primary) | `#C8A434` | Gold — links, active states, progress bars | -| Accent (success) | `#2ECC71` | Green — operational, running, completed | -| Accent (warning) | `#E67E22` | Orange — warnings, medium alerts | -| Accent (danger) | `#E74C3C` | Red — critical, high alerts, errors | -| Text (primary) | `#E8E6E0` | Warm white/cream | -| Text (secondary) | `#7A7D85` | Muted gray — labels, timestamps | -| Text (accent) | `#C8A434` | Gold — active nav, status labels | - -### Typography -| Element | Style | -|---------|-------| -| Card titles | 12-13px, uppercase, letter-spacing 1px, secondary color | -| Large numbers | 28-36px, bold, primary color | -| Body text | 14px, primary color | -| Labels/descriptions | 12-13px, secondary color | -| Nav items | 14px, secondary (gold when active) | - -### Card Style -- Border radius: 12px -- Background: `#141518` -- Border: 1px solid `#1E2025` -- Padding: 20-24px -- No shadows (flat design) -- Hover: border transitions to gold (0.2s ease) - ---- - -## Shared Components (appear on every page) - -### Sidebar (fixed left, ~80px) -- **Logo**: ArchNest arch icon (gold gradient) + "ARCHNEST" text (gold, 10px caps) -- **Nav items**: icon (18px) + label (14px), active = gold text + gold left border (3px) -- **Bottom**: Green dot + "System Status" / "All Systems Operational" (gold) - -**Final Nav (6 items):** - -| # | Icon | Label | Route | -|---|------|-------|-------| -| 1 | grid | Glance | `/` | -| 2 | server | Infrastructure | `/infrastructure` | -| 3 | globe | Network | `/network` | -| 4 | bookmark | BookNest | `/booknest` | -| 5 | terminal | Terminal | `/terminal` | -| 6 | settings | Settings | `/settings` | - -### Top Bar (~56px height) -- **Left**: Page title (bold, uppercase, 18px) -- **Center-right**: Search bar (rounded, ~300px, placeholder varies by page) -- **Right**: Bell icon (with badge) + User avatar (36px, gold ring) + "ArchNest Ops" / "Administrator" + chevron - -### Hero Banner -- Full width of main content area, 12px radius, overflow hidden -- Image: `archnest-brand.png` (dark cityscape + gold arch) -- Height varies: ~200px on Glance, ~120px on sub-pages -- Not shown on Terminal or Settings pages - -### Page Footer / Status Bar -- Height: ~40px, subtle top border -- Content: Contextual stats (varies per page) + "Last updated: 2m ago" (right) - ---- - -## Interactions & Behaviors - -- Sidebar nav: click navigates, gold highlight on active -- Card hover: border → gold (0.2s) -- Close buttons (X): hide/collapse cards -- "View all" links: navigate to full views -- Progress rings/bars: animated fill on load -- Sparklines: subtle animation, periodic update - ---- - -## Responsive Behavior - -- **Desktop (>1200px)**: Full layout -- **Tablet (768-1200px)**: Sidebar → icons only (~50px), cards 2-column -- **Mobile (<768px)**: Sidebar → bottom nav, cards single column - ---- - -## Tech Stack - -- React 19 + Vite + TypeScript -- Zustand (state) -- Chart.js or Recharts (sparklines, donuts, area charts) -- Lucide React (icons) -- xterm.js (terminal page) -- CSS Modules or Tailwind -- Deploy: Docker on racknerd1 → NPM proxy at archnest.snsnetlabs.com - ---- - -## Assets - -| Asset | CDN Path | Usage | -|-------|----------|-------| -| Logo | `logos/brands/archnest-logo.png` | Sidebar | -| Banner | `backgrounds/archnest-brand.png` | Hero | -| Network bg | `backgrounds/archnest-network-bg.jpg` | Network page alt | -| Geometric bg | `backgrounds/archnest-geometric-bg.jpg` | Texture overlay | - -CDN base: `https://raw.githubusercontent.com/SamuelSJames/assets-public/master/` - ---- - -## Page 1: Glance (`/`) - -> Main operations dashboard — system health at a glance - -### Status Cards Row (4 cards) - -| Card | Icon | Number | Subtitle | Extra | -|------|------|--------|----------|-------| -| System Status | checkmark | 100% | All Systems Operational | Circular progress ring + sparkline | -| Infrastructure | server | 24 | Total Resources | 🟢24 Running 🟡0 Warning 🔴0 Critical | -| Security | shield | 2 | Active Alerts | 🟡2 Low 🟡0 Medium 🔴0 High | -| Network | nodes | 98.7% | Network Uptime | Sparkline | - -### Middle Row (3 columns: 30% | 40% | 30%) - -**Resource Overview** (left): -- 5 progress bars: Compute 18/24, Storage 12.4/20 TB, Database 8/12, Network 98.7%, Containers 32/40 - -**Recent Activity** (center): -- Backup completed (2m) | Security scan completed (8m) | Instance launched (15m) | Config updated (22m) | User login (35m) - -**Top Alerts** (right): -- 🔴 High CPU Usage – App Server 02 (2m) -- 🟡 Disk Space Low – Database Cluster 01 (15m) -- 🟡 Unauthorized Login – Web Frontend (32m) -- 🟡 SSL Cert Expiring – api.archnest.io (1h) - -### Bottom Row (2 columns: 65% | 35%) - -**Network Traffic** (left): -- Area chart (gold gradient) + stats: Incoming 1.23 Gbps (↓12.4%), Outgoing 1.08 Gbps (↑8.7%) - -**Shortcuts** (right): -- 4 icon buttons: Add Server | Create Backup | Deploy App | View Logs - -### Footer Stats -- System Status 100% | 24 Resources | 2 Alerts | 98.7% Uptime - ---- - -## Page 2: Infrastructure (`/infrastructure`) - -> Monitor and manage your cloud infrastructure - -### Sub-Tabs -Overview | Compute | Storage | Network | Database | Containers | Load Balancers | DNS | Backups | Tags - -**Actions**: "+ Add Resource" button, gear icon - -### Status Cards Row (5 cards) - -| Card | Number | Subtitle | Trend | -|------|--------|----------|-------| -| Total Resources | 128 | Across all regions | ↑12.4% 7d | -| Total Cost (MTD) | $24,560.75 | Across all services | ↓8.7% month | -| Resource Health | 98.7% | Healthy | ↑2.1% 7d | -| Active Alerts | 2 | Requires attention | ↓63% 7d | -| Uptime | 99.98% | Global uptime | ↑0.01% 7d | - -### Middle Row (30% | 40% | 30%) - -**Resource Distribution** (left): -- Donut chart: 128 Total — Compute 38 (29.7%), Storage 24 (18.8%), Database 16 (12.5%), Network 20 (15.6%), Containers 18 (14.1%), Others 12 (9.4%) - -**Infrastructure Map** (center): -- Dark world map with gold glowing dots (region markers), connection lines -- Footer: 6 Regions | 18 AZs | 128 Resources | 🟢 Live - -**Top Resources by Utilization** (right): -- web-app-01 (m6i.large) 85% | api-server-02 (c6i.xlarge) 72% | db-primary (db.r6g.xlarge) 68% | cache-cluster 55% | worker-node-01 48% - -### Bottom Row (35% | 35% | 30%) - -**Resource Trend** (left): -- Multi-line area chart (7 days): Compute, Storage, Database, Network lines - -**Cost Breakdown MTD** (center): -- Donut: $24,560.75 Total — Compute $12,450 (50.7%), Storage $5,213 (21.2%), Database $3,452 (14.1%), Network $2,134 (8.7%), Others $1,310 (5.3%) - -**Recent Activity** (right): -- EC2 web-app-01 created (2m) | RDS backup (15m) | SG updated (32m) | S3 bucket created (1h) | LB updated (2h) - -### Footer Stats -- AWS | 6 Regions | 18 AZs | 128 Resources | 98.7% Health | $24,560.75 MTD | 2 Alerts - ---- - -## Page 3: Network (`/network`) - -> Monitor and manage your network performance and security - -### Sub-Tabs -Overview | Traffic | Topology | Devices | Interfaces | VPN | DNS | Firewalls | Load Balancers | Alerts | Reports - -**Actions**: "Last 24 Hours" dropdown, "Export Report" button - -### Status Cards Row (6 cards) - -| Card | Number | Trend | -|------|--------|-------| -| Network Health | 98.7% "Excellent" | ↑2.3% yesterday | -| Total Traffic | 1.23 Tbps | ↑18.6% yesterday | -| Packet Loss | 0.02% | ↓0.01% yesterday | -| Active Connections | 28,457 | ↑6.7% yesterday | -| Threats Blocked | 152 | ↑12.4% yesterday (⚠) | -| Avg. Latency | 12.4 ms | ↓8.1% yesterday | - -### Middle Row (25% | 50% | 25%) - -**Top Talkers** (left): -- web-app-01 203.4 Gbps | db-primary 156.7 Gbps | cache-cluster 98.3 Gbps | api-gateway 76.1 Gbps | backup-server 54.8 Gbps - -**Network Topology** (center): -- Dark world map with gold node dots, connection lines, glow effects -- Legend: 🟢 Live | 🟡 Warning | 🔴 Critical -- Controls: Zoom +/-, Fullscreen - -**Interface Utilization + Alert Summary** (right, stacked): -- Interfaces: ethernet1/1 85%, 1/2 72%, 1/3 68%, 1/4 55%, 1/5 48% (green/gold bars) -- Alert Summary: 🔴 2 Critical | 🟡 5 Warning | 🟢 12 Info - -### Bottom Row (35% | 35% | 30%) - -**Traffic Over Time** (left): -- Area chart (24h): Inbound (gold), Outbound (amber), Total (teal) -- Y: 250 Gbps – 1.5 Tbps, X: 00:00–20:00 - -**Protocol Distribution** (center): -- Donut: 1.23 Tbps Total — TCP 65.2%, UDP 18.7%, ICMP 7.3%, DNS 4.1%, Others 4.7% - -**Recent Events** (right): -- ethernet1/2 UP (2m) | High bandwidth web-app-01 (8m) | New device 10.0.1.45 (15m) | VPN tunnel us-west-2 (22m) | Blocked threat 185.199.108.153 (35m) - -### Footer Stats -- 6 Regions | 42 Sites | 248 Devices | 1,245 Interfaces | 28,457 Connections | 98.7% Health - ---- - -## Page 4: BookNest (`/booknest`) - -> Your Digital Library — categorized bookmarks with health monitoring - -### Page Stats (below title) -🔗 **312** Links | 📁 **18** Categories | ⭐ **12** Favorites - -### Layout: Main (75%) + Right Sidebar (25%) - -### Quick Access Row (5 cards) -| Category | Icons shown | Count | -|----------|------------|-------| -| Infrastructure | Proxmox, Cloudflare, Portainer, Cockpit, CasaOS | 5 links | -| Development | GitHub, GitLab, Gitea, VSCode, Docker | 5 links | -| AI Tools | ChatGPT, Claude, AI icons, OpenWebUI | 5 links | -| AWS | AWS service icons | 5 links | -| Networking | NetBird, Wireshark, Cisco, Ubiquiti | 5 links | - -### Bookmark Groups — Row 1 (4 columns) - -**Infrastructure & Self Hosted** (10 links): -CasaOS, Proxmox (pve1), Proxmox (mtr), Portainer, Cockpit, Cloudflare, NPM, NetBird, Linode, RackNerd - -**Development & Code** (8 links): -GitHub, Gitea, Trillium Notes, VSCode Web, Docker Hub, GitLab, Terraform Registry, Ansible Galaxy - -**Lab & Networking** (8 links): -GNS3, EVE-NG, OpenClaw, NetBird, Cisco Docs, Juniper Docs, Wireshark, iPerf3 - -**AWS** (8 links): -AWS Console, IAM, EC2, S3, CloudFormation, Route 53, VPC, Billing - -### Bookmark Groups — Row 2 (4 columns) - -**AI Tools** (7 links): -ChatGPT, Claude, Gemini, PartyRock, Perplexity, OpenWebUI, Ollama - -**Learning** (6 links): -WGU, Udemy, AWS Skill Builder, YouTube, LinkedIn Learning, Coursera - -**Finance** (5 links): -Bank, Budget, Investments, Retirement, Credit Cards - -**Life** (6 links): -Calendar, Email, Photos, Drive, Notes, Travel - -### Right Sidebar Widgets - -**Favorites**: Proxmox (pve1), GitHub, AWS Console, ChatGPT, NetBird - -**Recently Used**: Proxmox 5m, GitHub 15m, AWS Console 1h, Trilium 2h, GNS3 3h - -**Link Health** (donut): 304 Online, 6 Warning, 2 Offline (312 total) - -**Category Breakdown** (donut): Infrastructure 32%, Development 24%, AI Tools 18%, Learning 10%, Finance 8%, Life 8% - -### Link Item Design -- Icon (colored, 16-20px) + Name (14px) + Star toggle (right, gold when favorited) - ---- - -## Page 5: Terminal (`/terminal`) - -> Embedded SSH terminal — no hero banner, no cards grid - -### Layout: Full-height terminal viewport - -### Tab Bar (top, 40px) -- Tabs: host name + colored dot (🟢 connected, ⚪ disconnected) -- Active tab: gold bottom border -- "+" button: open new connection -- Quick-connect dropdown with saved hosts - -**Saved Hosts:** -| Label | Connection | -|-------|-----------| -| Pre (Audio) | ssh pre | -| Proxmox | ssh mtr | -| Linode (NPM) | ssh linode | -| RackNerd 1 | ssh racknerd1 | -| RackNerd 3 (Forge) | ssh racknerd3 | -| Studio (DevOps) | ssh studio | - -### Terminal Viewport -- Font: JetBrains Mono / Fira Code, 14px -- Prompt: Gold | Commands: Warm white | Output: Secondary gray | Errors: Red | Dirs: Teal -- Cursor: Gold block, blinking -- Scrollback: 5000 lines - -### Status Bar (bottom, 28px) -- 🟢 Connected | Host: `pre` | Session: 12m 34s | Shell: bash -- Right: Split pane | Fullscreen | Disconnect - -### Implementation -- xterm.js for browser terminal -- Node.js WebSocket-to-SSH bridge on racknerd1 - ---- - -## Page 6: Settings (`/settings`) - -> User preferences and system configuration — no hero banner - -### Layout: Settings Nav (200px left) + Content (right, scrollable) - -### Nav Sections -1. Profile | 2. Appearance | 3. Integrations | 4. Notifications | 5. Data & Backup | 6. About - -### Profile -- Avatar (64px, gold ring) + Display Name + Role (badge) + Email + Timezone -- "Save Changes" button (gold) - -### Appearance -- Theme: Dark/Light toggle -- Accent: Color swatches (Gold active, Teal, Purple, Blue, Green, Red) -- Font Size: 12-16px slider -- Sidebar: Expanded/Collapsed toggle -- Animations: On/Off -- Card Border Radius: 4-16px slider - -### Integrations -| Service | Status | Config Fields | -|---------|--------|---------------| -| Proxmox | 🟢 | Host URL, API Token | -| Docker | 🟢 | Socket/remote URL | -| NetBird | 🟢 | API key | -| Cloudflare | 🟢 | API token, Zone ID | -| AWS | 🟢 | Access Key, Secret (masked), Region | -| Uptime Kuma | ⚪ | URL, API key | -| Weather API | 🟢 | Location, Units | - -- Masked secrets with eye toggle, "Test Connection" per card - -### Notifications -- Enable toggle | Threshold dropdown (All/Critical/Warning+) | Email toggle | Browser push | Sound + volume - -### Data & Backup -- Export/Import Bookmarks (JSON) | Export Settings | Reset to Defaults (danger) | Clear Cache - -### About -- App: ArchNest Dashboard v1.0.0 -- Author: Samuel James -- Repo: github.com/SamuelSJames/archnest -- Stack: React 19, Vite, TypeScript -- License: MIT diff --git a/design-decisions.md b/design-decisions.md index baacc32..0024f20 100644 --- a/design-decisions.md +++ b/design-decisions.md @@ -1,225 +1,283 @@ -# ArchNest — Design Decisions & Lessons Learned +# ArchNest — Design Decisions & Page Reference -> This file captures all visual/UX decisions made during Glance page development. -> Apply these consistently to ALL future pages to avoid repeated iteration. +> Living reference for visual/UX conventions and what's actually built on each page. +> Apply the Global Rules consistently to any new page. The Page Notes section +> describes the **real, deployed** implementation — not a mockup. If you change a +> page's layout or data source, update its section here in the same PR. +> +> This file replaces the old `archnest-blueprint.md` (original 6-page mockup +> pitch, since deleted — superseded by the real 11-page app below) and +> `glance.md` (original Glance spec with fictional config files like +> `systems.config`/`infra.config` that were never built — also deleted). Anything +> from those files still true (color palette, typography, card style, dropdown +> menu shape) has been folded in below. --- -## Global Rules (Apply to Every Page) +## Global Rules (apply to every page) ### Sidebar -- **Expanded width**: 200px (matches mockup proportions — needs room for labels) -- **Collapsed width**: 64px (icon only) -- **User can manually collapse/expand** via toggle button (not just responsive) -- **Main content margin-left** must match sidebar width exactly +- Expanded width: 200px. Collapsed width: 64px (icons only). +- User can manually collapse/expand via a toggle button (not just responsive breakpoints). +- Main content `margin-left` must match the sidebar width exactly. +- Bottom of sidebar: live "System Status" widget — green dot + "All Systems + Operational" or "X Issue(s) Detected", driven by polling integration status + (not the fictional ping-sweep config described in the old spec). ### Page Title (Top Bar) -- **Color**: Gold (#C8A434) — NOT white. Use inline `style={{ color: '#C8A434' }}` if Tailwind class doesn't apply -- **Font**: 18px, bold, uppercase, tracking-wide -- **No border on top bar** — blends into the page background +- Color: gold `#C8A434` — not white. Use inline `style={{ color: '#C8A434' }}` + if a Tailwind class doesn't apply. +- Font: 18px, bold, uppercase, tracking-wide. +- No border on the top bar — it blends into the page background. +- Pages with a `pageSubtitles` entry (currently only BookNest) render a larger + 28px title + subtitle line instead, and the top bar grows from 56px → 72px — + see `TopBar.tsx`'s `pageSubtitles` map and `App.tsx`'s `topBarHeight` lookup, + which must be kept in sync or the layout clips/gaps. -### Colors — Use Inline Styles When Tailwind Fails -- Tailwind v4 `@theme` custom colors (text-gold, bg-card, etc.) may not always apply -- If a color isn't rendering correctly, fall back to inline `style={{ color: '#C8A434' }}` -- Always verify visually after changes +### Colors +| Role | Value | +|------|-------| +| Background (page) | `#0D0E10` | +| Background (cards) | `#141518` | +| Background (sidebar) | `#0A0B0D` | +| Border (cards) | `#1E2025` | +| Border/accent (hover/active) | `#C8A434` (gold) | +| Success | `#2ECC71` | +| Warning | `#E67E22` | +| Danger | `#E74C3C` | +| Text (primary) | `#E8E6E0` | +| Text (secondary) | `#7A7D85` | + +Tailwind v4 `@theme` custom colors (`text-gold`, `bg-card`, etc.) don't always +apply reliably — fall back to inline `style={{ color: '#C8A434' }}` when a +color isn't rendering, and verify visually after changes. + +### Typography +- Card titles: 10-11px, uppercase, tracking-[1.5px], secondary color, font-medium. +- Large numbers: 24-28px, bold, primary color. +- Subtitles/labels: 10-11px, secondary color. +- Body text in lists: 13px, primary color. +- Timestamps: 11px, secondary color. + +### Card Style +- Border radius: 12px. Background `#141518`. Border 1px solid `#1E2025`. +- Padding: 16-24px depending on density. No shadows (flat design). +- Hover: border transitions to gold, 0.2s ease. ### Content Alignment -- **All rows must share the same horizontal padding** (`px-6` applied once at the parent container level) -- **Do NOT** use different padding for different rows — this causes misalignment -- The hero banner, status cards, middle row, and bottom row must all line up left and right edges - -### Hero Banner + KPI Overlap -- Banner height: 200px -- Status cards overlap via negative margin: `-mt-12` -- Banner image: `object-cover` with `object-position: center 25%` (show the top/skyline, not center) -- Cards use `backdrop-blur-sm` and `bg-card/95` for glass effect over the banner - -### KPI Card Sizing -- KPI 1 (System Status) and KPI 4 (Network): **wider** — `1.3fr` -- KPI 2 (Infrastructure) and KPI 3 (Security): **standard** — `1fr` -- Grid: `grid-cols-[1.3fr_1fr_1fr_1.3fr]` -- Cards have compact padding: `p-4` (not p-5 or p-6) - -### No Footer -- The mockup does NOT have a footer/status bar -- Do not add one unless explicitly requested - -### Target Display -- Primary design target: **16-inch screen / 1920px width** -- Lots of horizontal space available — don't constrain content width unnecessarily -- Design should feel spacious, not cramped - -### Typography Sizes (smaller than default) -- Card titles: 10-11px, uppercase, tracking-[1.5px], secondary color, font-medium -- Large numbers: 24-28px, bold, primary color -- Subtitles/labels: 10-11px, secondary color -- Body text in lists: 13px, primary color -- Timestamps: 11px, secondary color -- Breakdowns: 9-10px, secondary color +- All rows in a page share the same horizontal padding (`px-6` at the parent + container level) so the hero banner, status cards, and content rows line up + left/right. ### Animations -- Card hover: border → gold, 0.2s ease -- Progress ring: animates from 0 to value in 1s -- Sparklines: draw animation 1s -- Progress bars: fill animation 0.8s +- Card hover: border → gold, 0.2s ease. +- Progress ring / sparkline: animate from 0 on load, ~1s. +- Progress bars: fill animation ~0.8s. ### Icons -- Source: Lucide React (imported per component, tree-shaken) -- Size: 14-18px depending on context -- Color: gold for active/accent, text-secondary for inactive -- Gold glow on active sidebar items: `shadow-[0_0_6px_rgba(200,164,52,0.5)]` +- Lucide React, 14-18px depending on context. Gold for active/accent, secondary + color for inactive. Gold glow on active sidebar items: + `shadow-[0_0_6px_rgba(200,164,52,0.5)]`. +- **Gotcha**: the installed lucide-react version's TypeScript types list some + brand/wordmark icons (`Github`, `Gitlab`, `Linkedin`, `Youtube`) that aren't + actually exported at runtime — `tsc --noEmit` stays clean while the page + renders blank with a runtime `SyntaxError` only visible in the Vite dev log. + Verify icon names against the package's actual exports before importing + anything brand-flavored. + +### No Footer +- No page has a fixed footer/status bar. Don't add one unless explicitly requested. + +### Target Display +- Primary design target: 16-inch / 1920px-wide screen. Don't constrain content + width unnecessarily — design should feel spacious. + +### User Avatar & Dropdown (TopBar, every page) +- 36px circle, gold border + glow, shows uploaded avatar image or initials. +- Adjacent: display name + "Administrator" role label, chevron (rotates on open). +- Dropdown menu: header (name + email) → **Profile** (`/settings?tab=profile`) + → **Appearance** (`/settings?tab=appearance`) → **Security** + (`/settings?tab=security`) → **Help & Support** (`/help`) → divider → + **Sign Out** (red, danger styling). See `TopBar.tsx`. --- -## Page-Specific Notes +## Page Notes (what's actually built, page by page) -### Glance Page -- No footer -- Status cards overlap hero banner -- Middle row: 3 equal-ish columns (30/40/30) -- Bottom row: 2 columns (65/35) -- Network Traffic card has its own background image at low opacity -- User avatar dropdown has: Profile, Appearance, Security, Help & Support, Sign Out +All pages below consume real backend data via `src/lib/api.ts` — **zero mock +data anywhere in the app.** Where a section says "real backend data," it means +an actual SQL-backed or live-polled endpoint, not a config file or static array. -### Infrastructure Page -- Hero banner rendered at the **App.tsx layout level** (not per-page), so it can extend - behind the sticky TopBar — conditional via `showHero = location.pathname === '/infrastructure'`. - TopBar and the search input are transparent on hero routes so the banner shows through. -- Hero image: `object-position: center 5%` to reveal the full arch + sky; faded out via - `linear-gradient` mask (vertical) + a `radial-gradient(ellipse 70% 100% at center, ...)` - overlay (sides/corners) — borderless, blends into page background. -- Sub-tabs trimmed to **Overview only** (Compute → Tags are future work, not built yet). -- Status cards: `rgba(10,10,12,0.5)` background (more transparent than other pages), - content centered (`justify-content/alignItems: center`) with a fixed row height (110px) - so there's breathing room instead of empty space below left-aligned content. -- Middle row (`grid-cols-[1fr_1.6fr]`): **Resource Distribution** (donut) and **Node Status** - (server tile grid). Both use the `/blank-kpi-bg.png` background art with a `cardDim` - (semi-transparent dark overlay) + `cardVignette` (radial-gradient `closest-side` blend) - combo — keeps the background pattern visible but subdued, with borders blended rather - than hard-edged. Card titles are rendered as our own text, NOT baked into the image - (baked-in labels got covered by the dim overlay). -- **Node Status** card: originally a world-map-style region dot plot, replaced with a - 4-column tile grid (one tile per server, colored status dot + name) — a world map - didn't make sense for a small/single-site infra. Reuse this "small-scale" reasoning - for any future map-like cards. -- Bottom row (`grid-cols-[1.4fr_1fr_1fr]`): Resource Trend / Cost Breakdown / Recent - Activity — **left plain/regular**, no dim/vignette blending (explicit user preference, - only the middle row gets the hero-style blend). Resource Trend uses the - `/archnest-network-traffic-bg.png` background (plain, no dim/vignette) with 4 trend - lines: blue `#3B82F6` (compute), orange `#E67E22` (storage), green `#2ECC71` (database), - brown `#8B5E3C` (network). -- `cardVignette` radial-gradient must use the `closest-side` keyword (not a fixed `%`) - — otherwise straight edges of the card don't reach full opacity and a hard border line - remains visible (only corners fade correctly with a fixed percentage). +### Glance (`/`) +- Hero banner (image with radial-gradient fade mask) + KPI cards overlapping + the bottom edge via negative margin. +- 4 status cards: **System Status** (% of integrations reachable), + **Infrastructure** (resource count + health breakdown from + `api.listResources()`), **Integrations** (connected/total from + `api.listIntegrations()`), **Bookmarks** (total + favorites from + `api.listBookmarks()`). +- Middle row (3 columns): Resource Overview (top 6 resources + status), + Recent Activity (5 latest from `api.listEvents(5)`), problem/critical + resources widget. +- Bottom row: Connected Integrations grid + 4 Shortcuts buttons (to Settings, + BookNest, Infrastructure). +- No footer. Hides the hero gracefully if the banner image fails to load. +- There is **no** `systems.config`/`infra.config`/ping-sweep/fail2ban + machinery — that was speculative spec from before the backend existed. + Health figures are derived directly from each integration adapter's + `testConnection()` result, polled by the existing `/api/integrations` list. -### BookNest Page -- Hero banner reused at the App.tsx layout level (`showHero` now includes `/booknest`), - with page-specific tuning via small lookup maps in `App.tsx` keyed on `location.pathname`: - `heroPaddingTop` (how far content sits below the hero top) and `heroObjectPosition` - (horizontal/vertical crop of the arch image) — `70px` / `54% 8%` for BookNest vs. - `72px` / `center 5%` for Infrastructure. Extend these maps rather than hardcoding a - single value when a future page needs different hero framing. -- **Large hero title + subtitle**: unlike other pages, BookNest's TopBar title is NOT the - small 18px uppercase label — it's rendered at 28px with a subtitle line ("Your Digital - Library") underneath, driven by a new `pageSubtitles` map in `TopBar.tsx`. When a page - has a subtitle, the header height grows from 56px → 72px (`TopBar.tsx`), and `App.tsx`'s - `topBarHeight` lookup keeps the content section's `calc(100vh - Npx)` in sync — both - must be updated together or the layout will clip/gap. -- **Stats row lives directly under the hero subtitle** (Links / Categories / Favorites), - not in its own separate bar — matches the blueprint's hero-header block grouping. -- **"Quick Access" section label** added above the 5 quick-access category cards (gold, - same `sectionTitle` style) — the row is intentionally pulled up via a small negative - hero-padding tune so it slightly overlaps the bottom edge of the hero, like the blueprint. -- **"+ Add Bookmark" button**: same gold-fill button style as Infrastructure's "+ Add - Resource", placed inline next to the "Quick Access" label rather than the page-stats row. -- **Right sidebar spans both grid rows** (`gridRow: '1 / span 2'` in a `gridTemplateRows: - 'auto 1fr'` grid) so the Favorites card can rise up near the hero while the main column's - page-stats row stays in row 1 of column 1 only — keeps the two from overlapping/clipping. - Negative margins were tried first and discarded: content pushed above the scroll - container's natural top edge gets clipped by `overflow-y-auto`, so prefer reshaping the - grid/flow over negative-margin hacks when something needs to "reach upward." -- **Sidebar cards stretch to match the main column's full height** so the last card's - (Category Breakdown) bottom border lines up with the bottom of the bookmark groups grid: - sidebar wrapper is `display:flex; flex-direction:column; height:100%` (grid's default - `align-items: stretch` already gives it the matching height), and each card uses - `flex: 1 0 auto` (Favorites gets `flex: 1.4 0 auto` to read as visibly taller, per - explicit request) so they share the leftover vertical space instead of all packing tight - at content height. -- lucide-react gotcha (see Global Rules candidate): the installed version does **not** - export brand/wordmark icons (`Github`, `Gitlab`, `Linkedin`, `Youtube`) even though - TypeScript's type declarations list them — `tsc --noEmit` stays clean while the page - renders blank with a runtime `SyntaxError` only visible in the Vite dev log. Verify - icon names against `Object.keys(require('lucide-react'))` before importing anything - brand-flavored; substitutes used here: `GitBranch`/`GitFork` (GitHub/GitLab/Gitea), - `SquarePlay` (YouTube), `Briefcase` (LinkedIn Learning). +### Infrastructure (`/infrastructure`) +- Hero banner at the `App.tsx` layout level (`showHero` includes this route), + extending behind the sticky, transparent-on-hero-routes TopBar. +- Sub-tabs: **Overview** (only enabled tab) and **Network** (disabled, + "Coming soon" — intentional, leave alone unless asked). +- 4 status cards: Total Resources, Healthy, Warnings, Critical — from + `api.listResources()`. +- Middle row: Resource Distribution (donut by integration type) + Node Status + (4-col tile grid, one tile per resource — replaced an earlier world-map + concept since a map doesn't make sense for a small/single-site setup). +- Bottom row: Integration Health list + Recent Activity (`api.listEvents(4)`). +- Card backgrounds use a `cardDim` + `cardVignette` (radial-gradient, + `closest-side` keyword — a fixed `%` leaves a visible hard edge on straight + sides) combo on the middle row only, per explicit visual preference; bottom + row stays plain/regular. -### Settings Page -- No mockup image existed for this page — built directly from the blueprint's Page 6 - spec rather than iterating against a screenshot. -- Layout: fixed-width (200px) left nav listing the 6 sections (Profile, Appearance, - Integrations, Notifications, Data & Backup, About) + a scrollable content panel on - the right showing the active section. No hero banner (not in the blueprint spec for - this page, and a settings page doesn't need one). -- Active section is local component state (a string id) mapped through a - `sectionComponents` record to the corresponding section-renderer function — simplest - approach for a page with no routing/deep-linking requirement. -- Shared style helpers (`cardBase`, `sectionTitle`, `labelStyle`, `inputStyle`) plus two - small reusable components defined in the same file: `Toggle` (on/off pill switch) and - `GoldButton` (gold-filled primary / danger-outline variant) — kept local to - `Settings.tsx` rather than extracted, since no other page needs them yet. -- **Integrations** cards mask secret fields (API keys/tokens) behind dots with an eye - icon to reveal/hide, plus a "Test Connection" button per card — matches the blueprint's - explicit "masked secrets with eye toggle" instruction. -- **Avatar upload** (Profile section): the avatar circle is clickable and opens a hidden - `` via a `useRef` + `.click()` call rather than a - visible file input — keeps the round avatar as the only visible control. On change, - `FileReader.readAsDataURL` converts the selected image to a base64 data URL stored in - component state, which becomes the circle's `backgroundImage` (cover-fit), replacing - the "AO" initials fallback. A hover-only camera-icon overlay (Tailwind `group` / - `group-hover:opacity-100`) signals the circle is clickable without cluttering the - default state. This is a frontend-only preview (no backend upload endpoint exists yet). +### BookNest (`/booknest`) +- Hero banner reused at layout level with page-specific tuning + (`heroPaddingTop`/`heroObjectPosition` lookup maps in `App.tsx`). +- Large 28px title + "Your Digital Library" subtitle (the one page using + `pageSubtitles`), header grows to 72px. +- Page stats row (Links / Categories / Favorites) + "Delete All" bulk action. +- Main column: Quick Access (top 5 categories) + bookmark groups grid (4 cols, + full CRUD with hover edit/delete/star). +- Right sidebar (spans both grid rows via `gridRow: '1 / span 2'`): Favorites, + Recently Added (5 newest), Link Health donut, Category Breakdown donut. +- Add/edit bookmark modal supports auto-detected favicons via + `guessServiceIconUrl()` or manual icon entry. +- All data from `api.listBookmarks()` / `api.listBookmarkCategories()` with + real create/update/delete calls — no local-only state. + +### Terminal (`/terminal`) +- Left sidebar: SSH hosts (integrations of type `ssh`), click to connect. +- Tab bar + 1/2/4-pane split layout, each pane an independent xterm instance. +- Preferences panel (theme: ArchNest Dark/Matrix/Solarized/Midnight Blue, font + size 11-16px, font family) — stored in `localStorage` + (`archnest-terminal-prefs`), not synced server-side. +- WebSocket to `/api/terminal`: `connect`/`input`/`resize`/`list_tmux`/`disconnect` + messages; supports attaching to an existing tmux session or starting a new one. +- Certificate auth (OPKSSH) shells out to the system `ssh` binary under a pty + rather than using the JS SSH client. +- Session logging to `ARCHNEST_SESSION_LOG_DIR` is backend-supported but has + no dedicated viewer UI yet. + +### Tunnels (`/tunnels`) +- List + create form for local/remote/dynamic (SOCKS5) SSH tunnels. +- Create form fields conditionally show/hide based on mode (no endpoint + host/port fields for dynamic mode). +- Status color map: stopped `#7A7D85`, connecting `#C8A434`, retrying + `#E0A030`, connected `#2ECC71`, error `#E74C3C`. Polls every 3s. +- Backed by `api.listTunnels()/createTunnel()/connectTunnel()/disconnectTunnel()/deleteTunnel()`. + +### Files (`/files`) +- SSH host selector + breadcrumb-navigable SFTP directory browser. +- File editor modal: plain textarea, files up to 50MB (anything larger is + download-only). Heuristic binary detection (null bytes/control chars) decides + base64 vs. text encoding. +- Inline directory creation, rename, delete, upload, download. +- Host-to-host transfer modal: pick source file + destination host/path, + copy-or-move toggle, live progress bar fed by `api.getTransfer(id)` polling. + +### Containers (`/containers`) +- Docker host selector (integrations of type `docker`) + container list. +- Per-container state badge (running/paused/exited/dead) with context-aware + action buttons (Start/Stop/Restart/Pause/Unpause/Remove) — buttons disable + themselves for invalid transitions (e.g. can't pause a stopped container). +- Live CPU/memory stats polled only for running containers. +- Logs modal (configurable tail count) and an exec modal (interactive shell via + WebSocket to `/api/docker/exec`). + +### Remote Desktop (`/remote-desktop`) +- Left sidebar: hosts from integrations of type `remote_desktop`. +- Main area is a Guacamole canvas tunneled over WebSocket to `/api/guacamole`, + proxying to the `guacd` sidecar container (RDP/VNC/Telnet). +- Requires `ARCHNEST_GUAC_CRYPT_KEY` — sessions fail without it (the backend + warns on startup if it's missing). + +### Host Metrics (`/host-metrics`) +- Left sidebar: SSH hosts. Selecting one starts a 5-second polling loop against + `api.getHostMetrics(integrationId)`, cleared on deselect. +- Cards: CPU/Memory/Disk gauges (color thresholds: green <75%, yellow 75-90%, + red ≥90%) + Uptime, then Network Interfaces, Processes (top 10), + Listening Ports, Firewall Rules (UFW/iptables), Login Activity. +- Backed by 10 sequential SSH-exec collectors under `backend/src/ssh/metrics/` + (cpu, memory, disk, uptime, network, system, processes, ports, firewall, + login-stats) — sequential on purpose, to avoid exceeding OpenSSH's + `MaxSessions` limit per host. + +### Settings (`/settings`) +- Fixed 200px left nav, 7 sections: Profile, Appearance, Security, + Integrations, Notifications, Data & Backup, About. URL-deep-linkable via + `?tab=` (`useSearchParams`) — use this pattern for any future section. +- **Profile**: display name, email, avatar upload (`FileReader.readAsDataURL` + → base64 data URL, persisted via `api.updateMe()` — this one *is* a real + backend round-trip, unlike the rest of the page below). +- **Appearance**: accent color swatches — **local-state only, doesn't persist + or apply anywhere** (see Known Stubs in `HANDOFF.md`). +- **Security**: password-change form + 2FA toggle — currently placeholder UI + pending the Phase 2 auth work in `HANDOFF.md`. +- **Integrations**: one card per type (Proxmox/Docker/NetBird/Cloudflare/AWS/ + Uptime Kuma/Weather/Remote Desktop/SSH), each with type-specific fields + (secrets masked, eye-toggle to reveal, "Test Connection" button). Real CRUD + via `api.createIntegration()/updateIntegration()/deleteIntegration()/testIntegration()`. +- **Notifications**: toggles — placeholder, no delivery mechanism (see + Known Stubs in `HANDOFF.md`). +- **Data & Backup**: full JSON export/import of integrations + secrets + + bookmarks + tunnels via `backend/src/routes/data.ts` — this is the one + endpoint that intentionally round-trips decrypted secrets, by design, for + backup portability. +- **About**: static version/license/links info. + +### Help (`/help`) +- Fully static — no backend calls. 11 guide cards (one per real page) with a + short description and tips. Update this page whenever a new page ships. + +### Login (`/login`) / Enrollment (`/enrollment`) +- `Login.tsx`: username/password form → `api.login()` → `AuthContext`. +- `Enrollment.tsx`: two-step first-run flow — (1) create the admin account via + `api.setup()`, gated to only work while the `users` table is empty; (2) + optional "Connect Your Services" integration onboarding grid (skippable, + same integration form as Settings). Routed to based on + `GET /api/system/setup-status`. --- -## Backend (added once frontend reached "good enough" state) +## Backend Architecture (current, not aspirational) -- New `backend/` package (separate `package.json`/`tsconfig.json`, own `node_modules`, - own Dockerfile) — Fastify + TypeScript, `better-sqlite3` for storage, deployed as a - second container alongside the existing frontend container (`docker-compose.yml` now - has `archnest` + `archnest-backend`, with a named volume for the SQLite file). -- Auth: single-user, JWT-based (`@fastify/jwt`). `POST /api/setup` creates the one user - and only succeeds while the `users` table is empty — this is what powers the - first-run enrollment page. `GET /api/system/setup-status` tells the frontend whether - to show enrollment/login or the normal app. -- Integration credentials are split across two tables: `integrations` (type, name, - status, non-secret `config_json`) and `secrets` (per-key AES-256-GCM-encrypted - values, key derived from the `ARCHNEST_SECRET_KEY` env var) — keeps secrets out of any - generic "list integrations" query/response by construction, not by remembering to - redact a field. -- Each integration type has an adapter module under `backend/src/integrations/` - exporting `testConnection(config, secrets)`; `registry.ts` maps `IntegrationType` → - adapter. Only `uptime_kuma` and `docker` are real so far (simple HTTP health checks); - the rest return a "not yet implemented" result until built out — this lets the - Integrations UI and `POST /api/integrations/:id/test` endpoint work end-to-end for - every type without blocking on every adapter being finished. -- Vite dev server proxies `/api` → `http://localhost:4000` (`vite.config.ts`) so the - frontend can call relative `/api/...` paths in both dev and prod (prod routes `/api` - to the backend container via NPM). -- Next steps (not yet done): build the enrollment/login frontend pages, strip the mock - arrays out of Glance/Infrastructure/BookNest/Settings and replace with calls to this - API, add bookmark category seeding. +- `backend/` — Fastify 5 + TypeScript (ESM, `tsx` dev / `tsc -b` build), + `better-sqlite3` for storage, deployed as its own Docker container alongside + the frontend and a `guacd` sidecar. +- Auth: single-user-schema JWT (`@fastify/jwt`) today — see `HANDOFF.md` for + the multi-user/SSO roadmap (Phases 2-4, not yet built). +- Integration credentials split across `integrations` (non-secret config) and + `secrets` (AES-256-GCM-encrypted, keyed by `ARCHNEST_SECRET_KEY`) tables — + secrets never appear in a generic "list integrations" response by + construction, not by remembering to redact a field. +- Every integration type has an adapter in `backend/src/integrations/` + implementing `testConnection()` (required) and `listResources()` (optional); + `registry.ts` maps `IntegrationType` → adapter. All 9 types + (proxmox/docker/netbird/cloudflare/aws/uptime_kuma/weather/ssh/remote_desktop) + are real, working adapters — none are stubs anymore. +- `backend/src/ssh/` is the shared SSH transport layer powering Terminal, + Files, Tunnels, Transfers, and Host Metrics: `connect.ts` (jump-host + chaining, host-key verification, cert auth), `sftp.ts` (ephemeral SFTP), + `transfer.ts` (host-to-host streamed copy/move with progress + cancel), and + `metrics/` (the 10 collectors listed above). +- Vite dev server proxies `/api` → `http://localhost:4000`; prod routes `/api` + to the backend container via Nginx Proxy Manager. ## Future Integration Notes - -### Live Provider Data (AWS, Linode, etc.) -- All KPI/status card data (resource counts, health, pricing, budgets, cost breakdowns, - utilization, regions/map data) is currently mocked/static. -- The Infrastructure page (and likely Glance) should eventually integrate with real - cloud provider APIs — AWS, Linode, or any other VPC/cloud provider — via user-supplied - API keys, to pull live data such as: - - Resource inventory/counts and health status - - Pricing and budget/cost data (replacing the static Cost Breakdown numbers) - - Resource utilization metrics - - Region/datacenter info for the Infrastructure Map -- Design the data layer so it's provider-agnostic (a common interface/adapter per - provider) since users may connect more than one provider's API key. +- AWS/Cloudflare/NetBird/Proxmox/Uptime Kuma adapters are real but currently + surface basic resource inventory + health only — deeper cost/pricing/budget + data (mentioned in the old blueprint) is not implemented and not currently + planned; revisit only if explicitly requested. diff --git a/glance.md b/glance.md deleted file mode 100644 index 14ffb26..0000000 --- a/glance.md +++ /dev/null @@ -1,356 +0,0 @@ -# Glance Page — Detailed Specification - -> Purpose: The Glance page is the operational heartbeat of ArchNest. It provides an at-a-glance view of system health, resource utilization, security posture, and network connectivity across your homelab infrastructure. Every element answers a simple question: "Is everything okay right now?" - ---- - -## Layout Structure - -The Glance page uses this vertical stack (top to bottom): -1. **Top Bar** (sticky, 56px) -2. **Hero Banner** (200px, rounded, with KPI cards overlapping the bottom ~25%) -3. **Middle Row** (3 columns: 30% | 40% | 30%) -4. **Bottom Row** (2 columns: 65% | 35%) - -**No footer.** The page scrolls naturally without a fixed status bar at the bottom. - ---- - -## Top Bar - -**Display:** -- Height: 56px, sticky at top, z-index above all content -- Background: Page color (#0D0E10), no border -- Left: Page title "GLANCE" (18px, bold, uppercase, primary text with subtle gold drop-shadow glow) -- Center-right: Search bar (260px, rounded-full, placeholder "Search resources...", card background) -- Right: Notification bell (with red badge count) + User avatar + dropdown trigger - -### User Avatar & Dropdown Menu - -**Avatar Display:** -- 32px circle with 2px gold border and subtle gold glow -- Shows initials "AO" in gold -- Adjacent: "ArchNest Ops" (12px, primary) + "Administrator" (9px, secondary) -- Chevron icon (rotates on open) - -**Dropdown Menu (on click):** -- Position: Below avatar, aligned right -- Background: Card color with border, rounded-xl, shadow -- Header section: User name + email -- Menu items: - - **Profile** — navigates to Settings > Profile section - - **Appearance** — navigates to Settings > Appearance section - - **Security** — navigates to Settings > Security/Integrations section - - **Help & Support** — opens documentation/wiki link -- Divider - - **Sign Out** — logs out of session (red text, danger action) - ---- - -## Hero Banner - -**Display:** -- Full width of content area, 200px height, 12px border radius, overflow hidden -- Image: `archnest-hero-banner.png` from `/public` (local) or CDN -- Image positioning: `object-cover` with `object-position: center 30%` — prioritizes showing the upper portion (skyline/arch) rather than center-cropping -- The bottom ~25% of the banner is overlapped by the KPI status cards (negative margin) -- If image fails to load: shows card background color (#141518), no broken icon - ---- - -## Top Row — Status KPI Cards (4 cards) - -### Card Grid Layout - -**IMPORTANT — Asymmetric widths:** -- KPI 1 (System Status): **1.3fr** — wider, has progress ring + sparkline -- KPI 2 (Infrastructure): **1fr** — standard width -- KPI 3 (Security): **1fr** — standard width -- KPI 4 (Network): **1.3fr** — wider, has sparkline chart - -Grid: `grid-cols-[1.3fr_1fr_1fr_1.3fr]` with 12px gap. - -**Card styling (all 4):** -- Background: `#141518` at 95% opacity with backdrop-blur (glass effect over banner) -- Border: 1px solid #1E2025, 12px radius -- Padding: 16px -- Hover: border transitions to gold (0.2s) - ---- - -### 1. System Status - -**What it represents:** Overall system health — a composite "green light" that confirms all critical services are reachable and all local packages/security updates are current. - -**How it gets its data:** -- **Ping sweep**: Every 5 minutes, the backend pings all endpoints defined in a `systems.config` file (IP addresses of LXC containers, VMs, physical hosts, and key services). If all respond, health = 100%. -- **Package currency check**: Queries `apt` (or equivalent) on monitored hosts for pending security updates. Any pending security update reduces the percentage. -- **Calculation**: `(reachable_hosts / total_hosts) * weight_A + (up_to_date_hosts / total_hosts) * weight_B`. Default weights: 70% reachability, 30% package currency. - -**Display:** -- Card title: "SYSTEM STATUS" (10px, uppercase, tracking 1.5px, secondary color, font-medium) -- Layout: Title top, then flex row with text left and ring right -- Left content: - - "All Systems" (13px, bold, primary) - - "Operational" (13px, bold, gold, italic) -- Right content: Progress Ring (44px diameter, 3px stroke, gold on dark track) -- Divider: 1px border-top, border/60 opacity -- Below divider: Sparkline (gold line chart, 20px height, no axes, showing last 12 check results) -- Footer text: "Last checked: 2m ago" (9px, secondary) - -**Thresholds:** -- 100%: "All Systems Operational" (gold text) -- 80–99%: "Degraded" (orange text) -- Below 80%: "Critical" (red text) - ---- - -### 2. Infrastructure - -**What it represents:** Total count of managed resources (LXC containers, VMs, Docker containers, bare-metal hosts) and their operational state. - -**How it gets its data:** -- **Config-driven**: Reads from `infra.config` which contains API endpoints, SSH keys, and connection details for each resource (Proxmox API for LXC/VMs, Docker socket/API for containers, SSH for bare-metal). -- **Status polling**: Every 5 minutes, queries each resource's API or SSH to determine if it's running, stopped, or unreachable. -- **Disk usage check**: Pulls primary disk utilization from each resource. Any resource exceeding 70% disk usage triggers a warning signal. - -**Display:** -- Card title: "INFRASTRUCTURE" (10px, uppercase, tracking 1.5px, secondary color) -- Icon + number row: Server icon (16px, gold) + "24" (24px, bold, primary) -- Subtitle: "Total Resources" (10px, secondary) -- Divider -- Breakdown row (9px): green dot + "24 Running" | yellow dot + "0 Warning" | red dot + "0 Critical" - -**Signal logic:** -- 🟢 Running: Resource is responsive and disk < 70% -- 🟡 Warning: Resource is responsive but disk ≥ 70%, or resource response is slow (>2s) -- 🔴 Critical: Resource is unreachable or disk ≥ 90% - ---- - -### 3. Security - -**What it represents:** Active security alerts — failed intrusion attempts, brute-force attacks detected by fail2ban, and outdated security packages. - -**How it gets its data:** -- **Fail2ban logs**: Queries fail2ban on each monitored host for currently banned IPs and recent ban events (last 24h). -- **Auth log monitoring**: Parses `/var/log/auth.log` (or equivalent) for failed login attempts exceeding a threshold (e.g., 5+ failures from same IP in 10 minutes). -- **Security package check**: Counts hosts with pending security-specific updates (`apt list --upgradable` filtered to security repo). -- **Alert count**: Sum of active fail2ban bans + hosts with outdated security packages. - -**Display:** -- Card title: "SECURITY" (10px, uppercase, tracking 1.5px, secondary color) -- Icon + number row: Shield icon (16px, gold) + "2" (24px, bold, primary) -- Subtitle: "Active Alerts" (10px, secondary) -- Divider -- Breakdown row (9px): green dot + "2 Low" | yellow dot + "0 Medium" | red dot + "0 High" - -**Severity logic:** -- Low (green): Informational — single failed login attempt, package update available -- Medium (yellow): Multiple failed attempts from same IP, security package >7 days overdue -- High (red): Active brute-force attack (10+ attempts in 5 min), critical vulnerability unpatched >14 days - ---- - -### 4. Network - -**What it represents:** Local network uptime — confirms internet connectivity and DNS resolution are functioning. - -**How it gets its data:** -- **Ping probes**: Every 60 seconds, pings multiple resolvers (e.g., 1.1.1.1, 8.8.8.8, and one internal DNS) from the ArchNest host. -- **Uptime calculation**: Tracks successful/failed pings over a rolling 24-hour window. Uptime % = (successful_pings / total_pings) * 100. -- **Sparkline data**: Stores the last 24 data points (one per hour) for the mini trend chart. - -**Display:** -- Card title: "NETWORK" (10px, uppercase, tracking 1.5px, secondary color) -- Icon + number row: Network icon (16px, gold) + "98.7%" (24px, bold, primary) -- Subtitle: "Network Uptime" (10px, secondary) -- Divider -- Below divider: Area sparkline chart (gold gradient fill, 24px height, no axes, 24 data points representing hourly uptime) - -**Thresholds:** -- ≥99%: Healthy (no indicator needed) -- 95–99%: Minor instability (orange sparkline highlight) -- <95%: Degraded (red sparkline highlight, triggers alert) - ---- - -## Middle Row — Detail Panels (3 columns: 30% | 40% | 30%) - -### 5. Resource Overview (left, 30%) - -**What it represents:** Top 5 resource utilization metrics across your infrastructure — a quick view of where capacity is being consumed. - -**How it gets its data:** -- Pulls from the same infrastructure polling that feeds the Infrastructure KPI -- **Compute**: Running LXC/VM count vs total allocated slots (from infra.config) -- **Storage**: Sum of used disk across all storage pools vs total capacity (e.g., Proxmox storage API, `df` on hosts) -- **Database**: Active database instances vs provisioned (PostgreSQL/MariaDB connection count or instance count) -- **Network**: Same uptime % from the Network KPI (displayed as a bar for consistency) -- **Containers**: Running Docker containers vs total defined in docker-compose or container configs - -**Display:** -- Card title: "RESOURCE OVERVIEW" (uppercase, secondary color) -- Close button (X) in top-right corner -- 5 rows, each containing: - - Icon (category-specific, 16px, secondary color) - - Label (e.g., "Compute", "Storage") — 13px, primary color - - Progress bar (gold fill on dark track, rounded ends) - - Value text (e.g., "18 / 24" or "12.4 / 20 TB") — 12px, secondary color - -**Bar color logic:** -- 0–69%: Gold (#C8A434) -- 70–89%: Warning orange (#E67E22) -- 90–100%: Danger red (#E74C3C) - ---- - -### 6. Recent Activity (center, 40%) - -**What it represents:** A chronological feed of the most recent system events — gives context on what just happened across the infrastructure. - -**How it gets its data:** -- **Event aggregation**: Collects events from multiple sources: - - Backup completion notifications (from cron jobs or backup tools like restic/borgbackup) - - Security scan results (from scheduled ClamAV/rkhunter scans) - - Instance state changes (container start/stop/create from Proxmox/Docker APIs) - - Configuration changes (git commits to infra-as-code repos, or config file modification timestamps) - - Authentication events (successful logins from auth.log) -- **Storage**: Events stored in a lightweight local database (SQLite or JSON file) with timestamp, type, title, source, and severity. - -**Display:** -- Card title: "RECENT ACTIVITY" (uppercase, secondary color) -- Close button (X) in top-right corner -- 5 items, each containing: - - Icon (event-type-specific: checkmark for completion, shield for security, play for launch, gear for config, user for login) — 14px, in a small rounded container (28px, page background) - - Event title (13px, bold, primary color) — e.g., "Backup completed" - - Source subtitle (11px, secondary color) — e.g., "Database Cluster 01" - - Relative timestamp (11px, secondary color, right-aligned) — e.g., "2m ago" - -**Event ordering:** Newest first, max 5 displayed. - ---- - -### 7. Top Alerts (right, 30%) - -**What it represents:** The most urgent issues requiring attention — prioritized by severity then recency. - -**How it gets its data:** -- **Alert aggregation**: Combines alerts from: - - High CPU/RAM usage events (from resource polling — any resource >85% CPU or >90% RAM for 5+ minutes) - - Disk space warnings (from Infrastructure polling — any disk >70%) - - Security events (from fail2ban/auth.log — active attacks) - - SSL certificate expiry (checks cert expiry dates for tracked domains, alerts at 30/14/7 days) - - Service down events (from System Status polling — any unreachable service) - -**Display:** -- Card title: "TOP ALERTS" (uppercase, secondary color) -- "View all" link (gold, top-right) — navigates to a full alerts view -- Up to 4 items, each containing: - - Severity dot (🔴 red/large for high, 🟡 yellow for medium) — 6px diameter - - Alert title (13px, primary color, font-medium) — e.g., "High CPU Usage" - - Source subtitle (11px, secondary color) — e.g., "App Server 02" - - Relative timestamp (11px, secondary color, right-aligned) — e.g., "2m ago" - -**Sort order:** High severity first, then by recency within same severity level. - ---- - -## Bottom Row — Charts & Actions (2 columns: 65% | 35%) - -### 8. Network Traffic (left, 65%) - -**What it represents:** Visual representation of network throughput over the last 24 hours — helps spot unusual spikes or drops in traffic. - -**How it gets its data:** -- **Interface monitoring**: Reads network interface stats (bytes in/out) from the primary gateway or router. Options: - - SNMP polling from router/switch - - `vnstat` on the ArchNest host or gateway - - Proxmox node network stats API -- **Sampling**: Records bytes in/out every 5 minutes, calculates Mbps/Gbps rate -- **Current values**: Latest sample provides the "Incoming X.XX Gbps" and "Outgoing X.XX Gbps" figures -- **Trend calculation**: Compares current hour's average to same hour yesterday for the percentage change (↑/↓) - -**Display:** -- Card title: "NETWORK TRAFFIC" (uppercase, secondary color) -- Background: Custom background image (`archnest-network-traffic-bg.png`) rendered at ~20% opacity behind the chart, giving the card a unique visual identity -- Area chart (overlaid on background): - - Fill: Gold/amber gradient (top: #C8A434 at ~30% opacity, fading to transparent) - - Line: Gold (#C8A434) for inbound, amber (#E67E22) for outbound - - X-axis: 24-hour span (no visible labels) - - Y-axis: Auto-scaled (no visible labels) -- Stats (right side of chart, vertically stacked): - - "Incoming" label (11px, secondary) + "1.23 Gbps" (18px, bold, primary) + "↓ 12.4%" (11px, red) - - "Outgoing" label (11px, secondary) + "1.08 Gbps" (18px, bold, primary) + "↑ 8.7%" (11px, green) - ---- - -### 9. Shortcuts (right, 35%) - -**What it represents:** Quick-action buttons for common administrative tasks — one-click access to frequent operations. - -**How it works:** -- Each shortcut triggers a predefined action or navigates to a specific workflow: - - **Add Server**: Opens a form/modal to add a new resource to `infra.config` (host IP, type, credentials) - - **Create Backup**: Triggers an on-demand backup job for a selected resource or all resources - - **Deploy App**: Opens a deployment workflow (e.g., pull latest docker-compose, restart containers) - - **View Logs**: Navigates to a log viewer or opens a terminal session with log tailing - -**Display:** -- Card title: "SHORTCUTS" (uppercase, secondary color) -- 4 buttons in a horizontal row: - - Each button: Outlined/stroked icon inside a bordered rounded container (40px) - - Icon style: Lucide outlined icons (18px), secondary color, gold on hover - - Label below icon: 10px, secondary color, centered - - Container: 1px border (#1E2025), 8px radius, hover → gold border + gold icon - ---- - -## Data Refresh & Polling Summary - -| Data Source | Poll Interval | Used By | -|-------------|---------------|---------| -| System ping sweep | 5 minutes | System Status KPI | -| Package update check | 1 hour | System Status KPI | -| Infrastructure resource status | 5 minutes | Infrastructure KPI, Resource Overview | -| Disk usage per resource | 5 minutes | Infrastructure KPI, Resource Overview, Top Alerts | -| Fail2ban / auth.log | 2 minutes | Security KPI, Top Alerts | -| Security package check | 1 hour | Security KPI | -| Network ping probes | 60 seconds | Network KPI | -| Network interface throughput | 5 minutes | Network Traffic chart | -| Event log (activity) | Real-time (push) or 1 minute | Recent Activity | -| SSL cert expiry | 24 hours | Top Alerts | -| CPU/RAM per resource | 5 minutes | Top Alerts | - ---- - -## Configuration Dependencies - -| Config File | Purpose | -|-------------|---------| -| `systems.config` | List of IPs/hosts to ping for System Status | -| `infra.config` | Resource definitions with API endpoints, SSH keys, connection types | -| `alerts.config` | Threshold definitions (disk %, CPU %, failed login count, cert days) | -| `network.config` | Resolver IPs to ping, interface to monitor for traffic | - ---- - -## Interaction Behaviors - -| Element | Action | Result | -|---------|--------|--------| -| X button (Resource Overview) | Click | Hides the card for current session | -| X button (Recent Activity) | Click | Hides the card for current session | -| "View all" (Top Alerts) | Click | Navigates to full alerts list view | -| Shortcut button | Click | Triggers associated action/workflow | -| Status card | Hover | Gold border transition (0.2s) | -| Progress ring | Page load | Animates from 0 to value (1s) | -| Sparkline | Page load | Draws line animation (1s) | -| Progress bars | Page load | Fill animation (0.8s staggered) | -| User avatar/chevron | Click | Opens/closes user dropdown menu | -| Dropdown: Profile | Click | Navigates to Settings > Profile | -| Dropdown: Appearance | Click | Navigates to Settings > Appearance | -| Dropdown: Security | Click | Navigates to Settings > Security | -| Dropdown: Help & Support | Click | Opens docs/wiki link | -| Dropdown: Sign Out | Click | Ends session, returns to login | -| Click outside dropdown | Click | Closes the dropdown menu |