Commit graph

162 commits

Author SHA1 Message Date
Samuel James
a7fbbabeb2
Fix blank RDP screen in multi-session view: scale display + fit on activate (#44)
The multi-session RemoteDesktop tabs (05e78f0) appended the Guacamole display
into an off-DOM container before connecting, and never called display.scale().
Frames arrived while the canvas was detached/zero-sized, so the desktop rendered
but painted to an invisible area — connected-but-blank.

Fix: track the display per session, fit/scale it to the visible panel when a
session becomes active, on the display's own onresize, and on window resize.
Verified the VM/xrdp/guacd side streams frames fine (13-36 img frames in direct
guacd tests); this was purely the client-side mount/scale regression.

Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-22 15:12:00 -04:00
Samuel James
6c1f167f15
Document xrdp blank-screen fix #2: disable xfwm4 compositing on virtio GPU (#43)
Even with XFCE running, the screen stayed blank because xfwm4's GPU compositor
fails on the Virtio GPU (no GL driver): "Another compositing manager is running",
"failed to load driver: virtio_gpu". Fixed by disabling xfwm4 compositing via
xfconf and forcing LIBGL_ALWAYS_SOFTWARE for the RDP user. Verified a fresh
session renders cleanly through guacd.

Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-22 15:01:22 -04:00
Samuel James
060ac6c078
Document xrdp blank-screen fix (Wayland-only GNOME needs XFCE) (#42)
After replacing gnome-remote-desktop with xrdp, the connection succeeded but
showed a blank screen: GNOME 50 on Fedora is Wayland-only and can't run on
xrdp's Xorg backend, so the session started and died in ~2s. Fixed by installing
XFCE (an X11 desktop that works without GL) and creating the missing
/etc/xrdp/startwm.sh to launch it. Verified xfce4-session/xfwm4 persist and
guacd streams sustained desktop frames.

Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-22 14:50:55 -04:00
Claude
05e78f0fa5
Support multiple remote desktop sessions as tabs with disconnect controls 2026-06-22 18:44:42 +00:00
Claude
a47583a8e4
Update RDP handoff doc: connection now succeeds, blank screen is new symptom 2026-06-22 18:30:12 +00:00
Samuel James
d1fefd3a63
Resolve RDP debugging: root cause + xrdp fix for gnome-remote-desktop (#41)
The "Server refused connection (wrong security type?)" failure was root-caused
end-to-end: guacd 1.5.5 ships FreeRDP 2.11.5, whose NLA/CredSSP client cannot
authenticate against gnome-remote-desktop, which mandates NLA (HYBRID_REQUIRED_
BY_SERVER) with no option to disable it. The earlier EGL/Mesa/Zink GPU theory
was a red herring.

Proven at every layer: direct xfreerdp v3 to the VM, the real guacd protocol
path (all security modes fail identically), and guacd's own logs. Also verified
guacd:1.6.0 still ships FreeRDP 2.11.7, so an image bump would NOT fix it.

Fix applied to the test VM: replaced gnome-remote-desktop with xrdp (masked the
GNOME user service so it can't re-grab port 3389), which interoperates with
guacd's FreeRDP 2. Verified a real session streams through guacd with
security=any. No ArchNest code change was needed — the existing security/
ignore-cert handling in guacamole.ts is correct.

Documents this as a general finding since other users will hit GNOME's built-in
RDP the same way.

Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-22 14:18:04 -04:00
Claude
74f8b9f705
Add RDP debugging handoff doc for next investigator 2026-06-22 14:54:47 +00:00
Claude
9578820bbd
Add RDP security mode override for hosts that reject auto-negotiated security 2026-06-22 13:26:06 +00:00
Claude
903645e789
Trust self-signed certs on RDP connections (FreeRDP rejects them by default) 2026-06-22 13:19:12 +00:00
Claude
f3dcbab444
Merge icon fallback chain and SSH name-based icon matching
# Conflicts:
#	src/pages/Infrastructure.tsx
2026-06-21 20:15:48 +00:00
Claude
03159ecde4
Match SSH connection name to specific icon (e.g. Linode, Portainer) before falling back to generic Linux icon 2026-06-21 20:13:18 +00:00
Claude
437f14e330
Add icon candidates for proxmox, weather, remote_desktop integrations 2026-06-21 20:11:34 +00:00
Claude
ba8683f5a8
Add per-integration custom icon + multi-repo fallback chain for Node Status
Settings → Integrations now has a universal "Icon" field (any integration
type) accepting a pasted URL or an uploaded image, stored as config.iconUrl.
This overrides the built-in icon for that integration's Node Status tile.

Node Status tiles now resolve their icon through a priority chain: custom
iconUrl, then each built-in CDN candidate in order (assets-public first
where available, falling back to the existing dashboard-icons CDN), and
finally the generic per-kind Lucide icon if every candidate 404s. AWS now
tries samuelsjames.github.io/assets-public's aws-logo.svg before the
jsDelivr fallback; SSH gets a Linux logo from the same repo. Proxmox,
Weather, and Remote Desktop have no built-in candidates yet (no matching
assets in that repo) and fall back to the generic icon until added.
2026-06-21 20:11:34 +00:00
Samuel James
4f765b512a
Add per-integration custom icon + multi-repo fallback chain for Node Status (#40)
Settings → Integrations now has a universal "Icon" field (any integration
type) accepting a pasted URL or an uploaded image, stored as config.iconUrl.
This overrides the built-in icon for that integration's Node Status tile.

Node Status tiles now resolve their icon through a priority chain: custom
iconUrl, then each built-in CDN candidate in order (assets-public first
where available, falling back to the existing dashboard-icons CDN), and
finally the generic per-kind Lucide icon if every candidate 404s. AWS now
tries samuelsjames.github.io/assets-public's aws-logo.svg before the
jsDelivr fallback; SSH gets a Linux logo from the same repo. Proxmox,
Weather, and Remote Desktop have no built-in candidates yet (no matching
assets in that repo) and fall back to the generic icon until added.

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 16:03:51 -04:00
Samuel James
9f10e8ee6f
Group all integration node tiles by integration except Proxmox (#39)
Generalizes the Uptime Kuma monitor-grouping pattern to every integration:
Node Status now collapses each integration's resources into one tile (e.g.
30 EC2 instances under one "AWS" tile) instead of flooding the grid, with
members listed in Node Detail on selection. Proxmox stays ungrouped since
its VMs/LXCs are managed individually elsewhere in the app.

Adds integrationType to the /api/integrations/resources response so the
frontend can group/exclude by adapter type rather than resource kind (kind
alone can't distinguish Proxmox VMs from AWS VMs, for example).

Documents the grouping rule in HANDOFF.md and adds a paid-tier roadmap
entry for per-integration node tabs that will show every individual node.

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 09:35:55 -04:00
Samuel James
9a1d2803a2
Fix monitor ID type mismatch causing all Uptime Kuma statuses to read unknown (#38)
heartbeatList/importantHeartbeatList emit monitor IDs as strings (server
iterates object keys), while monitorList and the live heartbeat event use
numbers. The lastHeartbeat map was keyed by the numeric monitor.id, so
string-keyed lookups from heartbeatList/importantHeartbeatList never hit.

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 09:21:09 -04:00
Samuel James
b4943b1155
Listen for heartbeatList in Uptime Kuma adapter to catch monitors with no status-change history (#37)
importantHeartbeatList only contains entries for status transitions, so a
monitor that's been continuously up since creation never populates it,
showing as "unknown" in ArchNest despite being healthy in Uptime Kuma.

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 09:06:01 -04:00
Claude
d50ec0076e
Group monitoring-app resources into one Node Status tile per integration
Integrations whose resources represent many sub-items (Uptime Kuma's
monitors) now collapse into a single tile using the Uptime Kuma CDN
icon, instead of flooding Node Status with one tile per monitor.
Selecting that tile lists every underlying monitor's status in a
scrollable Node Detail panel, so hundreds of monitors stay manageable.

Also drops the temporary debug logging added while diagnosing the
listener-timing bug, now that real monitor/heartbeat data confirmed
coming through.
2026-06-21 13:00:50 +00:00
Claude
0b9acd32a5
Fix Node Status grid not scrolling when it overflows
The grid's flex column parent had no min-h-0, so it grew to fit all
content instead of being capped to the card height — overflow-y:auto
on the grid itself never had anything to scroll within.
2026-06-21 12:56:54 +00:00
Claude
f390e8c586
Fix Uptime Kuma listResources missing monitorList/heartbeat events
Listeners for monitorList/importantHeartbeatList/heartbeat were being
attached after the login ack resolved, but the server pushes that
data right after login — sometimes in the same tick as the ack — so
Socket.IO dropped it before a listener existed. Listeners now attach
before login is sent.
2026-06-21 12:50:44 +00:00
Claude
89dd3471db
Add temporary debug logging to Uptime Kuma listResources
Diagnosing why a connected Uptime Kuma instance with real monitors is
producing zero Resources — logs monitor count, active flags, and last
heartbeat per monitor so we can see exactly what the Socket.IO session
returns.
2026-06-21 12:16:44 +00:00
Claude
58f007e6db
Add per-resource kind labeling and proper Node Status icons
Each adapter now tags its Resources with a kind (vm, container, app,
host, network) so Node Status tiles show the right icon instead of a
generic server glyph — Proxmox LXCs/Docker containers get a container
icon, VMs get a VM icon, Uptime Kuma monitors get an app icon, etc.

Also stops silently swallowing listResources() failures — they're now
logged as warnings, since a connected-but-empty integration (e.g.
Uptime Kuma reporting zero monitors) was previously indistinguishable
from a real adapter error.
2026-06-21 12:03:25 +00:00
Claude
8a60279720
Add selectable node status tiles and a Node Detail card
Clicking a tile in Node Status highlights it and surfaces its name,
source integration, status, and detail in a new Node Detail card on
the bottom row, between Integration Health and a now-narrower Recent
Activity card.
2026-06-21 11:43:10 +00:00
Claude
99ca1ba39c
Tighten Integration Health row spacing and make the list scrollable
Status text now sits close to the name instead of being pushed to the
far edge, and the list caps at a fixed height with scroll so it stays
usable as more integrations are added.
2026-06-21 11:38:16 +00:00
Claude
bcdecd86d6
Merge branch 'claude/youthful-cerf-ibvxfb' 2026-06-21 11:03:38 +00:00
Claude
bbb26dab0d
Implement real Uptime Kuma monitor reporting via Socket.IO
Uptime Kuma has no REST API for monitor data; connect over the same
Socket.IO session the web UI uses (login, then read monitorList and
heartbeat events) so connected monitors now surface as Resources.
Switches the integration's credentials from an API key to
username/password, matching what Uptime Kuma's session login expects.
2026-06-21 11:00:47 +00:00
Claude
d0cd9d83a7
Force explicit grid gap + clip panes to fix missing row gap in 4-pane view
Use an explicit inline gap instead of relying solely on a dynamically
templated Tailwind class, and clip each pane's content (overflow-hidden)
so a pane can't visually bleed into the row gap below it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
2026-06-21 10:16:18 +00:00
Claude
f191119a28
Add breathing room around terminal pane borders and content
Wider gap between panes in split view (borders were crowding each other
in 4-up grid), more inset between the pane border and the connect/
disconnect header, and a small horizontal gutter around the xterm mount
so the prompt text doesn't sit flush against the border.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
2026-06-21 09:54:40 +00:00
Claude
1da719c541
Merge branch 'claude/youthful-cerf-ibvxfb': in-app shell prompt picker, Help page scroll fix, Glance/System Status tweaks
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk

# Conflicts:
#	src/pages/Help.tsx
2026-06-21 09:26:42 +00:00
Claude
4674f4e209
Fix Help page scroll, widen Connected Integrations grid, color-code System Status ring
- Help page now scrolls (it sat under a clipped section with no overflow handling).
- Connected Integrations on Glance shows 5 per row in a scrollable area with the
  transparent ghost scrollbar, instead of growing the card unbounded.
- System Status KPI ring is now a thicker, vertically centered, multi-segment
  donut broken down by integration type, each type colored consistently from a
  shared first-come-first-served palette (src/lib/integrationColors.ts) so e.g.
  whichever type connects first always gets the same color everywhere it's used.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
2026-06-21 09:21:56 +00:00
Claude
a964591431
Add in-app shell prompt picker: install Starship + Nerd Font on demand
Lets a user pick one of three Starship presets (Nerd Font Symbols,
Pastel Powerline, Tokyo Night) from the Terminal page and install
Starship + a Nerd Font on the active pane's SSH host with one click,
instead of running a script by hand. Idempotent on the host side, and
available to all authenticated users like the rest of the SSH/Docker
tooling.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
2026-06-21 09:10:30 +00:00
Claude
5ed6bb591f
Add host setup script for Starship + JetBrainsMono Nerd Font
Pairs with the Terminal page's Nerd Font glyph fallback: run this on any VM you SSH into from ArchNest to get a full icon-rich Starship prompt, not just working icon rendering.
2026-06-21 09:03:33 +00:00
Samuel James
ae066a738c
Containers/Infrastructure styling fixes + Terminal Nerd Font fallback (#36)
* Add mesh prerequisite gate (NetBird verification before app config)

Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.

- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
  meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird

* Make mesh verification universal (CIDR check, not NetBird-specific)

Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.

* Add reachability fallback for routed meshes (VPC peering, etc.)

A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.

* Add Mesh section to Settings for configuring/testing the mesh gate

Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk

* Show a host-specific Docker remote-API setup script in Settings

When adding/editing a Docker integration with a tcp:// or http:// remote
URL, display a copyable systemd override + curl verification script
scoped to the entered host:port, so enabling the daemon's API doesn't
require looking up the steps separately.

* Expand Help page with quick-start guide and real-world examples

Adds a quick-start ordering card and per-feature example callouts (with icons) so first-time users see concrete use cases, not just descriptions.

* Update HANDOFF/README for handoff: mesh gate shipped, Docker UX work, no feature queued

Corrects the stale 'mesh gate not built' framing (it shipped across 4 commits, all merged) and documents the Docker setup-script hint + Help page expansion done this session. Leaves a clear next-task list for the picking-up agent: decide on merging claude/youthful-cerf-ibvxfb, then check with the user for the next priority.

* Improve Containers table/tab readability: bold centered headers, taller rows, filing-cabinet tabs

* Make Node Status card scrollable with a 5-column layout and invisible-by-default scrollbar

* Add Nerd Font icon fallback to the Terminal so Starship-style prompts render correctly

Bundles Symbols Nerd Font Mono (MIT, ryanoasis/nerd-fonts) as a glyph-only @font-face and appends it to every Terminal font-family option, so distro icons / git branch glyphs / etc. from prompts like Starship show up instead of broken-glyph boxes. It carries no letterforms, so it never changes how normal text renders.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 05:01:39 -04:00
Claude
f41b700904
Add Nerd Font icon fallback to the Terminal so Starship-style prompts render correctly
Bundles Symbols Nerd Font Mono (MIT, ryanoasis/nerd-fonts) as a glyph-only @font-face and appends it to every Terminal font-family option, so distro icons / git branch glyphs / etc. from prompts like Starship show up instead of broken-glyph boxes. It carries no letterforms, so it never changes how normal text renders.
2026-06-21 09:00:39 +00:00
Claude
9372767443
Make Node Status card scrollable with a 5-column layout and invisible-by-default scrollbar 2026-06-21 08:52:58 +00:00
Claude
98b69e47d5
Improve Containers table/tab readability: bold centered headers, taller rows, filing-cabinet tabs 2026-06-21 08:47:52 +00:00
Samuel James
fecaa61c3f
Add files via upload 2026-06-21 04:38:58 -04:00
Samuel James
1594afdb5a
Add files via upload 2026-06-21 04:38:26 -04:00
Samuel James
07116a0475
Docker setup-script hint + expanded Help page (#35)
* Add mesh prerequisite gate (NetBird verification before app config)

Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.

- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
  meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird

* Make mesh verification universal (CIDR check, not NetBird-specific)

Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.

* Add reachability fallback for routed meshes (VPC peering, etc.)

A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.

* Add Mesh section to Settings for configuring/testing the mesh gate

Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk

* Show a host-specific Docker remote-API setup script in Settings

When adding/editing a Docker integration with a tcp:// or http:// remote
URL, display a copyable systemd override + curl verification script
scoped to the entered host:port, so enabling the daemon's API doesn't
require looking up the steps separately.

* Expand Help page with quick-start guide and real-world examples

Adds a quick-start ordering card and per-feature example callouts (with icons) so first-time users see concrete use cases, not just descriptions.

* Update HANDOFF/README for handoff: mesh gate shipped, Docker UX work, no feature queued

Corrects the stale 'mesh gate not built' framing (it shipped across 4 commits, all merged) and documents the Docker setup-script hint + Help page expansion done this session. Leaves a clear next-task list for the picking-up agent: decide on merging claude/youthful-cerf-ibvxfb, then check with the user for the next priority.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 04:34:59 -04:00
Claude
5703f93027
Update HANDOFF/README for handoff: mesh gate shipped, Docker UX work, no feature queued
Corrects the stale 'mesh gate not built' framing (it shipped across 4 commits, all merged) and documents the Docker setup-script hint + Help page expansion done this session. Leaves a clear next-task list for the picking-up agent: decide on merging claude/youthful-cerf-ibvxfb, then check with the user for the next priority.
2026-06-21 08:30:00 +00:00
Claude
36a79abe94
Expand Help page with quick-start guide and real-world examples
Adds a quick-start ordering card and per-feature example callouts (with icons) so first-time users see concrete use cases, not just descriptions.
2026-06-21 08:28:54 +00:00
Claude
628187befb
Show a host-specific Docker remote-API setup script in Settings
When adding/editing a Docker integration with a tcp:// or http:// remote
URL, display a copyable systemd override + curl verification script
scoped to the entered host:port, so enabling the daemon's API doesn't
require looking up the steps separately.
2026-06-20 22:15:43 +00:00
Samuel James
fcac50cc02
Add Mesh section to Settings for configuring/testing the mesh gate (#34)
* Add mesh prerequisite gate (NetBird verification before app config)

Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.

- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
  meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird

* Make mesh verification universal (CIDR check, not NetBird-specific)

Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.

* Add reachability fallback for routed meshes (VPC peering, etc.)

A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.

* Add Mesh section to Settings for configuring/testing the mesh gate

Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-20 17:46:35 -04:00
Claude
4a4a5a01b3
Add Mesh section to Settings for configuring/testing the mesh gate
Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
2026-06-20 21:44:27 +00:00
Samuel James
70f88efdc8
Add mesh prerequisite gate (#33)
* Add mesh prerequisite gate (NetBird verification before app config)

Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.

- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
  meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird

* Make mesh verification universal (CIDR check, not NetBird-specific)

Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.

* Add reachability fallback for routed meshes (VPC peering, etc.)

A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-20 17:30:46 -04:00
Claude
800072ffbb
Add reachability fallback for routed meshes (VPC peering, etc.)
A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.
2026-06-20 21:26:25 +00:00
Claude
0409159327
Make mesh verification universal (CIDR check, not NetBird-specific)
Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.
2026-06-20 21:22:06 +00:00
Claude
46d95fca61
Add mesh prerequisite gate (NetBird verification before app config)
Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.

- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
  meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird
2026-06-20 21:15:55 +00:00
Samuel James
cdd93f204e
docs: sync HANDOFF/README/design-decisions; add mesh-gate design (#32)
Bring the docs in line with what shipped since the auth phases, and hand
off the next planned feature cleanly for another agent to pick up.

- HANDOFF.md: new TL;DR (auth complete; persistent terminals + Docker
  three-ways shipped); prominent "next task = Mesh Prerequisite Gate"
  callout warning not to code before the open decisions are answered;
  corrected standing rules (kiro/<feature> branches, gh-based workflow,
  npm run build over plain tsc, Co-authored-by trailers); architecture
  sections updated for TerminalSessionContext, dockerSsh/agents routes,
  docker_agent_reports table, ssh/docker.ts, and the new agent env vars;
  new "Docker: three ways" section.
- README.md: Containers/Terminal page rows, route-group list, SSH layer,
  agent/ dir, ARCHNEST_AGENT_TOKEN/ARCHNEST_AGENT_STALE_MS, current-state
  paragraph, and doc reading order.
- design-decisions.md: Terminal (persistence) and Containers (three
  sources + detail tab) page notes; backend Docker-transport note; mesh
  gate flagged under Future Integration Notes.
- docs/mesh-prerequisite-gate.md (new): full design with lockout-safety
  invariants and the open decisions (A-D) needed before implementation.

Docs only; no code changed.

Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:42:47 -04:00
Samuel James
35fd7fc703
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.

Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
  TCP API, reusing the existing SSH transport (jump-host chaining, host-key
  verification, key/password auth) via connectTarget + execCommand. No dockerd
  socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
  and an interactive `docker exec` shell builder. Container refs are validated
  against a strict allowlist and single-quoted to prevent command injection;
  action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
  shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
  WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
  OpenSSH-certificate (OPKSSH) fallback that the terminal route has.

Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
  collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
  secret-looking env values locally, and POSTs it to ArchNest. VMs need
  outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
  (POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
  503 when unset, so it is disabled by default) plus user-auth read endpoints
  (hosts list with staleness flag, per-host containers, single-container
  detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.

Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
  detail tabs opened by clicking a container name. Agent detail shows
  overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
  degrade gracefully. Agent rows are read-only; docker/ssh keep management.

Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
  (push self-hosted now / pull-agent paid), terminal grid tiering.

Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.

Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.

Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00