Skip to content

ormos ui: the local web app, served by this machine - #84

Merged
nicodes merged 2 commits into
mainfrom
feat/local-ui
Sep 21, 2026
Merged

nicodes merged 2 commits into
mainfrom
feat/local-ui

Conversation

@nicodes

@nicodes nicodes commented Sep 21, 2026

Copy link
Copy Markdown
Owner

The komizo-treatment slice for Ormos (template: komizo PRs #135–#137), built on the agent's local core — the part that survives with the hosted relay/db/app gone.

What ships

  • ormos ui subcommand (internal/system/ui.go + dispatch in run.go): SolidJS 1.9 + Tailwind 4 app built to a static export (ui/ → internal/ui/dist, committed), served on loopback :8481 by default; --bind widens to the tailnet with the same loud-when-unspecified rules komizo uses. Zero auth by design — reachability is the boundary, Tailscale is the identity.
  • Reads (this machine only, no relay): status (version/host/os/shell/state dir/policy), listening ports filtered by the local policy.json (the agent's own proxyAllowed decision), terminals this UI opened with output tails, agent audit log (sessions.log) tail.
  • Actions — server-enforced allowlist {open, kill} only: open spawns a PTY (no relay, bounded 8), confined to the policy's allowedRoots and refused under terminalsDisabled; kill ends a session this UI opened. Nothing the page sends passes through a shell; cwd is EvalSymlinks-resolved and must land inside the policy roots.
  • Contract tests (ui_test.go, ui_dispatch_test.go): loopback-default pin, no Clerk/PocketBase/relay remnants in the web tree, allowlist enforced server-side (403/400/404/405 matrix), reads from local files, injection never reaches spawn (traversal, symlink escape, non-allowlisted shell), terminal limit, dispatch driven through Main (the komizo #136 unreachable-command bug class), real-serve over loopback incl. SPA fallback + embedded asset.
  • CI byte-drift gate: rebuild ui/ and git diff --exit-code internal/ui/dist — the committed bytes must be what the source produces. package-lock.json pinned; npm ci in CI.
  • README: ormos ui + tailscale serve --bg 8481 phone flow.

Deliberate v1 cuts

No typing/interactive input (WebSocket input is a later slice — v1 is read-mostly plus open/kill), no preview passthrough, no PB/Clerk features. Hosted volumes and the torn-down stack are untouched.

A SolidJS + Tailwind app embedded as a static export and served on
loopback: status, policy-allowed listening ports, terminals this UI
opened with output tails, and the agent audit log. No auth by design --
reachability is the boundary, Tailscale is the identity, and the wildcard
only ever arrives typed. Actions are a server-enforced allowlist
(open/kill), confined to the policy's allowedRoots and refused under
terminalsDisabled; injection never reaches a spawn because nothing the
page sends passes through a shell. Dist is committed and CI byte-verifies
it from source; dispatch and the no-remnants/no-public-listener contracts
are pinned by tests. Typing over WebSocket is a later slice; v1 is
read-mostly plus the pair.
The platform-selection CI guard found internal/ui buildable on windows --
the embed package now carries the agent's own build tag, so every platform
the guard checks still selects relay alone. The injection test compared the
raw fixture path against the server's resolved log; darwin resolves /var to
/private/var, so the assertion now resolves the fixture path first.
@nicodes
nicodes merged commit beb3e79 into main Sep 21, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant