dev_arc_aws/.kiro/steering/project-guide.md
Samuel James ad4687660c
All checks were successful
Build & Push Images / build (push) Successful in 41s
CI / validate (push) Successful in 51s
Build & Push Images / deploy (push) Successful in 30s
Document the Forgejo CI/CD + racknerd2 setup as the baseline
Make the automated pipeline the documented "setup moving forward" and
finish scrubbing the last stale GitHub-Actions/racknerd1 references that
never reached main.

- HANDOFF.md: refresh the stale 2026-06-21 snapshot. New "CI/CD & deploy"
  section (push to main -> build + push to registry.snsnetlabs.com ->
  auto-deploy to racknerd2 over SSH, SHA-pinned, /api/health gate),
  racknerd2 validation-host + SSH-tunnel access notes, Forgejo workflow
  rule, and a current Deployment + orientation section.
- .kiro/steering/project-guide.md: Forgejo-only Git workflow (no gh),
  CI/CD row, registry host, racknerd2 + forgejo-runner SSH entries, and a
  CI/CD pipeline section.
- .kiro/hooks/tunnel-racknerd2-8080.kiro.hook: the "View ArchNest on
  racknerd2" hook (ssh -L 8080:localhost:8080 -N) to view the deployed
  site at http://localhost:8080 (racknerd2's edge only allows port 22).
- src/pages/Settings.tsx: About panel repo URL -> Forgejo.
- .dockerignore: .github -> .forgejo.
- TERMIX_MIGRATION.md / docs/OPEN-SOURCE-RELEASE.md: drop stale
  .github/workflows + "GitHub Actions deploy" references.

Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-25 13:37:39 -04:00

6.1 KiB

ArchNest — Project Guide for Kiro

Steering file for AI sessions working on this repo. Covers architecture decisions, workflow rules, and patterns to follow. Read alongside design-rules.md (visual conventions) which is injected separately.


Quick Context

ArchNest is a self-hosted ops dashboard — live infrastructure monitoring, SSH terminal/tunnels/files, Docker container management, remote desktop, and bookmarks. Private Forgejo repo (never public) — no GitHub. CI/CD is Forgejo Actions: push to main builds images, pushes to registry.snsnetlabs.com, and auto-deploys to racknerd2 (validation/preview host) over SSH. See HANDOFF.md → "CI/CD & deploy" and deploy/README.md.

Tech Stack (exact versions matter)

Layer Tech
Frontend React 19, Vite 8, TypeScript 6, Tailwind CSS v4, React Router 7
Charts Recharts 3
Icons Lucide React (verify exports exist at runtime, not just TS types)
Terminal xterm.js 6 (@xterm/xterm + @xterm/addon-fit)
Backend Fastify 5, TypeScript 5.7, ESM (tsx dev, tsc -b build)
DB better-sqlite3 (SQLite)
Auth @fastify/jwt + bcryptjs + server-tracked sessions
Validation zod
SSH ssh2 library
AWS @aws-sdk/client-ec2, @aws-sdk/client-sts
Deploy Docker Compose (Alpine images)
CI/CD Forgejo Actions (.forgejo/workflows/): ci.yml validate; build.yml build+push to registry.snsnetlabs.com then auto-deploy to racknerd2. No GitHub.

Git Workflow

  • Remote: origin → private Forgejo forgejo.archnest.local:3000/sam/dev_arc_aws (SSH via ProxyJump). Forgejo-only — no GitHub, no gh CLI.
  • Container registry: registry.snsnetlabs.com (user sam, package token). Unproxied host so large layers bypass Cloudflare's body cap; web UI/packages stay on forgejo.snsnetlabs.com.
  • Never commit on main. Always create kiro/<feature> branches.
  • Commit style: imperative title + body explaining why, with trailers:
    Co-authored-by: Samuel James <ssamjame@amazon.com>
    Co-authored-by: Kiro <noreply@kiro.dev>
    
  • Before committing: npm run build (frontend) + cd backend && npx tsc --noEmit (backend). Forgejo CI runs the same.
  • Stage specific files — never git add -A blindly
  • PR flow: git push -u origin <branch> → open a PR on Forgejo (web UI/API) → merge to main. Merging to main auto-builds + auto-deploys to racknerd2 (build.yml). deploy.yml is a manual dispatch for deploying/rolling back any tag.

Code Patterns to Follow

Frontend

  • One page component per route in src/pages/
  • All backend calls go through src/lib/api.ts (typed apiFetch wrapper)
  • No global state library — plain React state + localStorage for prefs
  • Auth via src/lib/AuthContext.tsx (JWT in localStorage)
  • New pages need: route in App.tsx, entry in api.ts, sidebar link

Backend

  • One route file per feature in backend/src/routes/
  • Integration adapters in backend/src/integrations/ (must implement testConnection())
  • SSH-based features use backend/src/ssh/connect.ts shared transport
  • Request validation with zod schemas
  • Audit logging via logEvent() from db/index.ts
  • Secrets encrypted at rest (AES-256-GCM via db/crypto.ts)
  • Never expose secret values to frontend — only secretKeys: string[]

Adding a New Integration

  1. Create adapter in backend/src/integrations/<name>.ts
  2. Register in backend/src/integrations/registry.ts
  3. Add type to IntegrationType union
  4. Add route if needed in backend/src/routes/
  5. Add api.ts functions + TS interfaces on frontend
  6. Add card in Settings integrations section

Policies

  • Versioning: development happens on even major versions; odd majors are released/stable lines. We are currently developing v2 (the prior released line is v1, see the v1.0 git tag). Image/version tags should reflect this — dev builds carry the even (v2) version.
  • Zero mock data — every number comes from a live API/SSH/DB call
  • Design-first for big features — write a docs/<feature>.md before coding
  • No footer on any page
  • Primary target: 1920px+ viewport, should feel spacious
  • Mesh gate defaults OFF — never lock the live instance
  • OpenSSL legacy provider in backend Dockerfile — don't remove (needed for old PEM keys)

Environment

  • Required env vars: ARCHNEST_SECRET_KEY, ARCHNEST_JWT_SECRET
  • Optional: ARCHNEST_DB_PATH, PORT, ARCHNEST_GUAC_CRYPT_KEY, ARCHNEST_CORS_ORIGIN, ARCHNEST_AGENT_TOKEN, ARCHNEST_AGENT_STALE_MS
  • Frontend dev proxies /apihttp://localhost:4000

Key Files to Read First

  1. README.md — architecture overview
  2. HANDOFF.md — current state + standing rules
  3. design-decisions.md — visual conventions + per-page implementation notes
  4. ROADMAP.md — deferred/tiered work
  5. docs/ — subsystem design documents

SSH Config (for reference)

  • ssh forgejo → Git operations (User: forgejo, via ProxyJump linode)
  • ssh forgejo-admin → root shell on Forgejo host (for admin tasks)
  • ssh forgejo-runner → host running the Forgejo Actions runner (has Docker; builds images). Runner config /opt/config.yaml sets container.docker_host: automount.
  • ssh racknerd2 → validation/preview host (root). Runs the deployed stack from /opt/archnest/. Mesh IP 100.96.217.250. Edge only allows port 22 — view the site via the SSH tunnel hook (-L 8080:localhost:8080) at http://localhost:8080.
  • ssh linode → jump host at 172.238.163.85

CI/CD pipeline (full detail in deploy/README.md)

  • Push to mainbuild.yml: job build (build + push :latest and :<sha> to the registry) → job deploy (needs build; SSH to racknerd2, docker compose pull && up -d pinned to <sha>, /api/health gate).
  • Required Forgejo Actions secrets: FORGEJO_REGISTRY_TOKEN, RACKNERD2_SSH_KEY.
  • The build job installs docker-ce-cli from Docker's apt repo (Debian's docker.io is too old for the host daemon). Don't switch it back to docker.io.
  • racknerd2 /opt/archnest/docker-compose.yml PULLS registry images; the repo-root docker-compose.yml BUILDS locally (dev/manual).