Document the Forgejo CI/CD + racknerd2 setup as the baseline
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

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>
This commit is contained in:
Samuel James 2026-06-25 13:37:39 -04:00
parent bddf891c0a
commit ad4687660c
7 changed files with 69 additions and 34 deletions

View file

@ -1,6 +1,6 @@
node_modules
dist
.git
.github
.forgejo
pics
*.md

View file

@ -0,0 +1,14 @@
{
"enabled": true,
"name": "View ArchNest on racknerd2 (localhost:8080)",
"description": "Opens an SSH local port-forward (localhost:8080 -> racknerd2 8080) so the deployed ArchNest site can be viewed in a browser at http://localhost:8080. RackNerd's edge only allows port 22, so this tunnels the web app over SSH. Trigger it to start the tunnel; stop the hook's process to close it.",
"version": "1",
"when": {
"type": "userTriggered"
},
"then": {
"type": "runCommand",
"command": "ssh -o BatchMode=yes -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -L 8080:localhost:8080 -N racknerd2",
"timeout": 0
}
}

View file

@ -10,8 +10,10 @@
ArchNest is a **self-hosted ops dashboard** — live infrastructure monitoring,
SSH terminal/tunnels/files, Docker container management, remote desktop, and
bookmarks. Deployed at `archnest.snsnetlabs.com` via Docker Compose on
`racknerd1`. Private Forgejo repo (never public).
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)
@ -27,20 +29,22 @@ bookmarks. Deployed at `archnest.snsnetlabs.com` via Docker Compose on
| Validation | zod |
| SSH | ssh2 library |
| AWS | `@aws-sdk/client-ec2`, `@aws-sdk/client-sts` |
| Deploy | Docker Compose (Alpine images), GitHub Actions → racknerd1 |
| 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 instance (SSH via ProxyJump)
- **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)
- **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>``gh pr create` → squash-merge
- **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
@ -100,4 +104,13 @@ bookmarks. Deployed at `archnest.snsnetlabs.com` via Docker Compose on
- `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 `main``build.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).

View file

@ -1,35 +1,43 @@
# ArchNest — Handoff Notes
Status snapshot as of **2026-06-21**. Written so a fresh AI session (or human) can pick this up with zero prior context. Branch names rotate every session — always run `git branch --show-current` and work on a fresh feature branch off `main` (recent branches have used a `kiro/<feature>` or `claude/<feature>` naming pattern).
Status snapshot as of **2026-06-25**. Written so a fresh AI session (or human) can pick this up with zero prior context. Always run `git branch --show-current` and work on a fresh feature branch off `main` (convention: `kiro/<feature>`).
> **Repo is on Forgejo — no GitHub.** `origin` = `forgejo.archnest.local:3000/sam/dev_arc_aws` (push via SSH). The container registry is `registry.snsnetlabs.com` (separate unproxied host). There is no `gh` CLI / GitHub Actions here.
## TL;DR
ArchNest is **live and deployed** at `archnest.snsnetlabs.com`, auto-deploying via GitHub Actions (`.github/workflows/deploy.yml`) on every merge to `main` — push triggers a build + SCP + `docker compose up -d --build` on `racknerd1`, with a health-check gate (`/api/health`). Deployment is no longer the open task; it's working infrastructure now.
ArchNest is **feature-complete and stable** as a self-hosted ops dashboard. The runtime stack is **better-sqlite3 + `@fastify/jwt`/bcrypt sessions + Docker Compose** (the Postgres/Redis/Cognito/Akamai stack in `README.md` + `docs/aws-architecture/` is the *planned paid AWS scale-up target*, not what runs today). All major subsystems are built and merged. **Auth Phases 1-3 done** (Phase 4 SSO is a deferred paid AWS add-on — see `ROADMAP.md`); **Mesh Prerequisite Gate** shipped (Settings → Mesh, defaults OFF).
**Auth is feature-complete for self-hosted** (Phases 1-3: user menu, password/sessions/login-log, multi-user roles; Phase 4 SSO deferred to a paid AWS add-on — see `ROADMAP.md`).
## CI/CD & deploy — THE SETUP MOVING FORWARD
Since then, **Docker container visibility/management was expanded** (shipped, deployed):
- **Persistent SSH terminal sessions** (PR #30) — terminals stay connected across in-app page navigation.
- **Docker-over-SSH management** + **Docker push-agent monitoring** (PR #31) — see the "Docker: three ways" section below.
Fully automated. **Every push to `main`** runs Forgejo Actions on the `forgejo-runner` host:
**The Mesh Prerequisite Gate is now built and shipped** (no longer the open task): NetBird-mesh-required-before-config, with universal CIDR-based verification (not NetBird-specific), a routed-mesh/VPC-peering reachability fallback, and a dedicated "Mesh" section in Settings to configure/test it. Defaults OFF, so it does not lock the live instance. Commits: `46d95fc` (gate), `0409159` (universal CIDR check), `800072f` (routed-mesh fallback), `4a4a5a0` (Settings UI) — all merged to `main`.
```
push main ─► .forgejo/workflows/ci.yml → validate (tsc + build, frontend & backend)
─► .forgejo/workflows/build.yml
job build → build + push images → registry.snsnetlabs.com/sam/{archnest,archnest-backend} (:latest + :<sha>)
job deploy → (needs build) ssh racknerd2 → docker compose pull + up -d @ this <sha> → /api/health gate
```
Most recently (this session, real user dogfooding rather than a planned feature): walked the user through replacing a broken/insecure Docker-TCP-API integration attempt with a working **SSH Host** integration to a real VM ("Portainer VM," running Portainer + a test container), confirmed Docker-over-SSH container management works end to end, and added supporting UX:
- **Docker setup-script hint in Settings** (commit `628187b`, branch `claude/youthful-cerf-ibvxfb`, **pushed but NOT YET merged to `main`** — user explicitly deferred merging once already; revisit with the user before merging) — when editing a Docker (`type: 'docker'`) integration's `baseUrl`, Settings now renders a copyable systemd-override + `curl` verification script scoped to that exact host/port, so users don't have to hand-derive the remote-API-enablement steps themselves.
- **Help page expansion** (commit `36a79ab`, same branch, pushed) — every page entry in `src/pages/Help.tsx` now has at least one real-world example callout (icon + optional label + scenario text), plus a "New here? Start in this order" quick-start card above the grid, aimed at first-time users who don't yet know which page does what.
- **Registry**: `registry.snsnetlabs.com` (user `sam`). It is a **dedicated unproxied (DNS-only) Cloudflare host** so large image layers bypass Cloudflare's ~100 MB body cap (the backend has 260 MB+ layers). The Forgejo **web UI / packages list** stays on `forgejo.snsnetlabs.com` (Cloudflare Access SSO).
- **Runner**: `forgejo-runner` host (ssh alias `forgejo-runner`), forgejo-runner v6.3.1, runs jobs in `node:22-bookworm` containers. Its config `/opt/config.yaml` sets `container.docker_host: automount` (mounts the host docker.sock into jobs so they can build images); systemd drop-in points the service at that config. The build job installs **`docker-ce-cli` from Docker's official apt repo** (NOT Debian's `docker.io`, which is too old — API 1.41 vs the daemon's required 1.44+).
- **Required Forgejo Actions secrets**: `FORGEJO_REGISTRY_TOKEN` (package-scoped token for `sam`, used for registry login/push), `RACKNERD2_SSH_KEY` (private key for `root@racknerd2`, used by the deploy job).
- **`deploy.yml`** is a manual `workflow_dispatch` (deploy/rollback to any tag without rebuilding); the auto-deploy lives in `build.yml`'s `deploy` job.
### racknerd2 — validation / preview host (NOT permanent)
racknerd2 (ssh alias `racknerd2`) is where the deployed build can be **viewed for accuracy**. It only pulls + runs the images (1.9 GiB RAM — never builds). Mesh IP **100.96.217.250**; `/opt/archnest/{docker-compose.yml,.env}` drive a registry-image compose (frontend 8080, backend internal, guacd sidecar). Ports are bound to the mesh IP by default (Docker bypasses ufw, so binding to a specific IP is what keeps it off the public interface).
**Access for review**: RackNerd's edge only allows **inbound port 22** on racknerd2 (80/443/8080 are dropped upstream), so the site is **not directly reachable on its public IP**. View it via the **SSH local-forward tunnel** — Kiro hook **"View ArchNest on racknerd2 (localhost:8080)"** (`.kiro/hooks/tunnel-racknerd2-8080.kiro.hook`) runs `ssh -L 8080:localhost:8080 -N racknerd2`; trigger it, then open **http://localhost:8080**. A real public URL (later) goes through the NPM reverse proxy on linode (TLS), not racknerd2's raw IP.
### → NEXT TASK for the picking-up agent
No new feature is queued. Pick up from here:
1. **Decide with the user whether to merge `claude/youthful-cerf-ibvxfb` into `main`.** It contains the Docker setup-script hint (`628187b`) and the Help page expansion (`36a79ab`), both already build-clean (`npm run build` passes). Nothing else is blocking it.
2. **Ask the user if removing the unused Docker API integration (the one superseded by the SSH Host setup) is done** — this was a live-instance UI action on their end, not something done via this repo's code.
3. Otherwise, check with the user for the next priority — there is no pending design doc or half-built feature waiting right now (mesh gate and Docker UX work above are both fully shipped or ready-to-merge).
**Nothing is queued; the pipeline above is the baseline.** Push to `main` → it auto-builds and auto-deploys to racknerd2; view via the tunnel hook. Pick the next priority with the user (the `ROADMAP.md` tiered/paid add-ons are the menu). Optional small follow-ups noted but not requested: bump `package.json`/About panel to **v2** (convention recorded below); add a one-click "stop tunnel" hook.
## Standing rules (read before doing anything)
- **Versioning convention**: development happens on **even** major versions, releases on **odd**. We are currently developing **v2** (prior released line is v1 — see the `v1.0` git tag). Dev image/version tags carry the even (v2) number. `package.json` (root + backend) still reads `0.0.0` and the Settings → About panel is hardcoded `v1.0.0`; neither has been bumped to v2 yet.
- **Branch**: never commit on `main`. Create a fresh feature branch off `main` (recent convention: `kiro/<short-feature>`). Confirm with `git branch --show-current` before starting.
- **Workflow per change**: type-check (`npx tsc --noEmit -p .` in repo root AND in `backend/`) — and for frontend changes prefer a full `npm run build` (which runs `tsc -b && vite build`; the stricter `tsc -b` has caught errors a plain `tsc --noEmit` missed via stale incremental cache) → commit → `git fetch origin main && git rebase origin/main``git push -u origin <branch>` → open a PR with `gh pr create` → squash-merge (`gh pr merge <n> --squash --delete-branch`) → poll the resulting run (`gh run list --branch main`, then `gh run watch <id> --exit-status`) until `validate` and `deploy` both succeed (deploy's last step is "Health check (backend /api/health)").
- **Workflow per change**: type-check (`npx tsc --noEmit -p .` in repo root AND in `backend/`) — for frontend changes prefer a full `npm run build` (`tsc -b && vite build`; stricter than plain `tsc --noEmit`) → commit → `git fetch origin main && git rebase origin/main``git push -u origin <branch>` → open a PR on Forgejo (web UI/API) and merge to `main`. **Merging to `main` auto-triggers CI: validate + build + push + auto-deploy to racknerd2** (`.forgejo/workflows/`). There is no `gh` CLI here. Watch a run via the runner: `ssh forgejo-runner 'docker ps'` (job containers) / `journalctl -u forgejo-runner`, and confirm the result by checking the SHA-tagged image in `registry.snsnetlabs.com` and `/api/health` on racknerd2 (via the tunnel hook).
- **`git add -A` caution**: this has twice swept up unrelated untracked files (e.g. a bookmark-import JSON the user asked to be generated, not committed) into unrelated PRs. Prefer `git add <specific files>` and always check `git diff --cached --stat` before committing.
- **Never open a PR unless the user's intent is clearly "ship this."** For exploratory/planning asks, use `AskUserQuestion` to confirm scope first — see how the Phase 2/3/4 plan below was scoped before any code was written.
- **Mock data policy**: zero mock/fabricated data. Verify with `grep -ri "mock\|fake\|placeholder" src/ backend/src/` if continuing feature work and unsure.
@ -129,14 +137,14 @@ Moved out of the core build. Planned as a **paid add-on shipped when ArchNest is
Moved to **`ROADMAP.md`** ("Known non-blocking stubs"). Summary: the Infrastructure "Network" sub-tab is intentionally disabled, and the Settings Appearance and Notifications sections are non-functional placeholders. None are flagged as work to do unless explicitly asked — check the latest conversation/commits before assuming a direction.
## Deployment (already working — reference only)
## Deployment (current — Forgejo Actions, automated)
`docker-compose.yml` (3 services: `archnest` frontend, `archnest-backend`, `guacd`) + `.github/workflows/deploy.yml` (push-to-`main` → SCP + `docker compose up -d --build` on `racknerd1`, gated on an `/api/health` check) are live and require no further setup. If a deploy fails, check the GitHub Actions run's `deploy` job steps in order — `Pre-flight` (host `.env` exists), `Copy repo to racknerd1`, `Build, restart, and clean up`, `Health check`.
Full pipeline is documented in **"CI/CD & deploy — THE SETUP MOVING FORWARD"** near the top of this file and in **`deploy/README.md`**. Summary: push to `main` → Forgejo Actions builds + pushes images to `registry.snsnetlabs.com` and auto-deploys to **racknerd2** (validation host) over SSH, SHA-pinned, `/api/health` gated. View racknerd2 via the SSH tunnel hook → `http://localhost:8080` (its public IP only allows port 22). The old GitHub-Actions→racknerd1 SCP pipeline is gone (migrated to Forgejo). `docker-compose.yml` at the repo root still BUILDS locally (dev/manual); `deploy/docker-compose.yml` PULLS from the registry (what racknerd2 runs).
## Quick orientation for a new session
1. Read this file, then `ROADMAP.md` (deferred/tiered work), then `docs/` (subsystem design docs — `docker-agent-monitoring.md`, `mesh-prerequisite-gate.md`), then `TERMIX_MIGRATION.md` for feature-level history, then skim `git log --oneline -30`.
2. Frontend: prefer `npm run build` (`tsc -b && vite build`) over a plain `tsc --noEmit` (stricter, catches more). Backend: `npx tsc --noEmit -p .` from `backend/`. Both must pass before any commit.
3. **The Mesh Prerequisite Gate is built and shipped** (Settings → Mesh; defaults OFF). **There is no other planned feature queued right now** — check the "→ NEXT TASK" section above first (merge decision on `claude/youthful-cerf-ibvxfb`), then ask the user for the next priority. Auth Phases 1-3 are done; Phase 4 SSO is a deferred paid AWS add-on (`ROADMAP.md`).
1. Read this file, then `deploy/README.md` (build/deploy pipeline), then `ROADMAP.md` (deferred/tiered work), then `docs/` (subsystem design docs — `docker-agent-monitoring.md`, `mesh-prerequisite-gate.md`, `rdp-debug-handoff.md`, `aws-architecture/system-design.md`), then `TERMIX_MIGRATION.md` for feature history, then skim `git log --oneline -30`.
2. Frontend: prefer `npm run build` (`tsc -b && vite build`) over plain `tsc --noEmit`. Backend: `npx tsc --noEmit -p .` from `backend/`. Both must pass before any commit (Forgejo CI runs exactly this).
3. **Nothing is queued and nothing is half-built.** All major subsystems are merged; CI/CD auto-builds + auto-deploys to racknerd2 on every push to `main`. Check the "→ NEXT TASK" section above, then ask the user for the next priority (`ROADMAP.md` lists deferred/paid add-ons).
4. If asked to add a feature, follow existing patterns: integration adapters in `backend/src/integrations/`, SSH-backed engines in `backend/src/ssh/`, one route file per feature in `backend/src/routes/`, one `api.ts` entry + page component per frontend feature. Subsystem-level work gets a `docs/` design doc first.
5. For anything ambiguous in scope, use `AskUserQuestion` rather than guessing — that's how the auth phases, the Docker agent tiering, and the mesh-gate decisions were all scoped.
5. For anything ambiguous in scope, ask the user rather than guessing — that's how the auth phases, Docker agent tiering, and mesh-gate decisions were all scoped.

View file

@ -2,7 +2,7 @@
Status doc for porting Termix's full feature set into ArchNest as a single app, single backend, single auth, single database — reskinned to match ArchNest's design. Written so any session (human or AI) can see exactly what's done, what's next, and why decisions were made.
**Migration status: COMPLETE.** All 8 phases below are DONE and verified. No further feature work is queued on this branch. If you're picking this project up, the only remaining task is the GitHub Actions deploy setup — see `HANDOFF.md` and the Deployment section of `README.md`. Do not start new feature work here without explicit instruction.
**Migration status: COMPLETE.** All 8 phases below are DONE and verified. No further feature work is queued from this migration. CI/CD has since moved to **Forgejo Actions** (build → `registry.snsnetlabs.com` → auto-deploy to racknerd2) — see `HANDOFF.md` and `deploy/README.md`. Do not start new feature work here without explicit instruction.
Source: `https://github.com/SamuelSJames/Termix` (user's fork), cloned for reference at the time of writing. Upstream is `Termix-SSH/Termix`, an Electron + Express + Drizzle ORM self-hosted SSH/RDP/VNC management app — **not** a small terminal widget. It ships as its own Docker image with a `guacd` sidecar for RDP/VNC.

View file

@ -63,8 +63,8 @@ internal working notes that don't belong in a public project:
| `docs/rdp-debug-handoff.md` | Contains lab creds (`sam` / `happy2026`) + private VM IP `192.168.122.55` + personal host names | **Exclude** (or heavily genericize into a "Remote Desktop setup" guide with no creds/IPs) |
| `HANDOFF.md` | Internal session-to-session working notes | **Exclude** |
| `docs/OPEN-SOURCE-RELEASE.md` (this file) | Internal release plan | **Exclude** |
| `archnest.snsnetlabs.com` references in `.env.example`, `docker-compose.yml`, `.github/workflows/deploy.yml` | Personal domain/deploy target | **Genericize** to `example.com` / `localhost`; the deploy workflow should be removed or replaced with a generic CI (build + lint only, no SCP-to-my-server) |
| `.github/workflows/deploy.yml` | SSHes/SCPs to the personal `racknerd1` server | **Remove**; replace with a generic build/test CI workflow |
| `archnest.snsnetlabs.com` references in `.env.example`, `docker-compose.yml` | Personal domain/deploy target | **Genericize** to `example.com` / `localhost` |
| Forgejo CI (`.forgejo/workflows/`) | Already build/validate only (no SCP/personal server). The build workflow pushes to a private registry + deploys to a private host | **Keep but genericize** the registry host + deploy job, or strip the deploy job for a public build-only CI |
| `agent/` deploy specifics | Fine to include the agent script, but scrub any host-specific URLs/tokens in its README | **Review + genericize** |
| `assets/` personal background images | Large PNGs; keep the ones the UI needs (hero banner, logo, KPI backgrounds), drop unused experiments (`opt1.bg`, `settings-custom-bg`, `pics/`) | **Trim to what's referenced** |
| Test/scratch files | `backend/data/`, any `*.db`, session logs | Already gitignored — confirm none are force-added |
@ -115,7 +115,7 @@ LICENSE, README.md, CONTRIBUTING.md, screenshots/ # new, written for OSS
HANDOFF.md
docs/rdp-debug-handoff.md
docs/OPEN-SOURCE-RELEASE.md (this file)
.github/workflows/deploy.yml (replace with generic CI)
.forgejo/workflows/ (genericize: strip registry host + deploy job, or build-only CI)
backend/data/, *.db, session logs, *.tsbuildinfo
unused assets/ experiments + pics/
```
@ -212,7 +212,7 @@ Notes for credibility:
- [ ] Create fresh public repo, copy INCLUDE list, exclude EXCLUDE list.
- [ ] Genericize personal domain → `example.com`/`localhost` in
`.env.example`, `docker-compose.yml`.
- [ ] Replace `.github/workflows/deploy.yml` with a generic build/lint CI (no SCP).
- [ ] Genericize `.forgejo/workflows/` for public use (strip the private registry host + the racknerd2 deploy job, or ship build-only CI).
- [ ] Add `LICENSE` (MIT), public `README.md`, `CONTRIBUTING.md`.
- [ ] Capture + add screenshots (sanitized data, dark theme).
- [ ] Re-run a secret scan on the NEW repo before first push

View file

@ -1343,7 +1343,7 @@ function AboutSection() {
const rows: [string, string][] = [
['App', 'ArchNest Dashboard v1.0.0'],
['Author', 'Samuel James'],
['Repo', 'github.com/SamuelSJames/archnest'],
['Repo', 'forgejo.snsnetlabs.com/sam/dev_arc_aws'],
['Stack', 'React 19, Vite, TypeScript'],
['License', 'MIT'],
]