From 5e397195b9ec9c678cdd4a62b10cf573c02d863e Mon Sep 17 00:00:00 2001 From: Andy Dixon Date: Thu, 16 Apr 2026 00:00:00 +0100 Subject: [PATCH] Add .github/copilot-instructions.md for AI-assisted development Documents build commands, architecture, WKWebView constraints, conventions, the protocol addition checklist, and database migration patterns. --- .github/copilot-instructions.md | 98 +++++++++++++++++++++++ build/nexus-ssh-icon.svg | 137 ++++++++++++++++++++++++++++++++ 2 files changed, 235 insertions(+) create mode 100644 .github/copilot-instructions.md create mode 100644 build/nexus-ssh-icon.svg diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..d412575 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,98 @@ +# Copilot Instructions — Nexus Terminal + +## Build & Test + +```bash +make deps # go mod download + npm install +make build # production build → build/bin/nexus-terminal.app +make dev # wails dev with hot reload +make test # go test ./... -v -count=1 +make lint # golangci-lint run ./... + +# Single package test +go test ./internal/storage/ -v -count=1 -run TestProfileCRUD +``` + +The frontend has no separate build step — `npm run build` (called by Wails) copies xterm vendor libs from `node_modules` into `frontend/src/js/lib/` and `frontend/src/css/lib/`. All frontend assets are embedded at compile time via `frontend/embed.go`. + +## Architecture + +Wails v2 desktop app: Go backend + HTML/CSS/JS frontend rendered in a native webview (WKWebView on macOS). + +**Go backend** (`internal/`): +- `app/` — lifecycle bootstrap: opens SQLite, inits secret stores, wires everything together +- `api/` — single `Service` struct bound to Wails; every public method is callable from JS as `window.go.api.Service.MethodName()` +- `sessions/` — manages concurrent protocol sessions; owns SSH/Telnet/RAW/GitHub client lifecycles +- `storage/` — SQLite repository (WAL mode) with embedded sequential migrations in `storage/migrations/` +- `secrets/` — two-tier credential storage: OS keychain (preferred) → AES-256-GCM encrypted file vault (fallback) +- `models/` — shared domain types and defaults; protocol configs are JSON-encoded in the DB +- `sshclient/`, `telnetclient/`, `rawclient/`, `githubclient/` — protocol implementations + +**Frontend** (`frontend/`): +- Plain HTML/CSS/JS — no framework, no bundler, no ES modules +- `index.html` is the app shell; loads CSS then JS in strict order +- `src/js/` — 13 modules, each IIFE-wrapped, exporting to `window.NexusTerminal` +- `src/css/` — modular stylesheets; `tokens.css` defines all design tokens +- Vendor libs (xterm.js, addons) live in `src/js/lib/` and `src/css/lib/` — auto-copied, gitignored + +**Go ↔ JS communication:** +- **Synchronous:** Frontend calls `window.go.api.Service.*()` (returns Promise) +- **Asynchronous:** Backend pushes events via `wailsRuntime.EventsEmit()`; frontend listens with `window.runtime.EventsOn()` +- **Bidirectional events** for secret prompts and host key verification: backend emits a request event with a `requestID`, frontend shows a modal, then emits a response event with the same ID. The Go side blocks on a channel keyed by that ID. + +Key events: `session:data`, `session:state`, `session:closed`, `session:raw:data`, `session:github:repos`, `session:secret:prompt`/`session:secret:response`, `session:hostkey:verify`/`session:hostkey:response`. + +## WKWebView Constraints (Critical) + +The macOS webview silently blocks or breaks several standard web APIs. These constraints affect every frontend change: + +1. **No `window.confirm()`, `window.prompt()`, `window.alert()`** — they either return false/null silently or do nothing. All user prompts must use the custom modal system (DOM-based backdrop + modal with `is-visible` class toggling). + +2. **No ES modules** — `