Files
obsidian-vault/personal/projects/archive/virfield-release-cleanup-2026-10-16/docs/superpowers/specs/2026-10-08-desktop-r3-design.md.md
T
Taiga c687ef21f5 [2026-10-16 08:45:15] syncthing-out: personal/projects/archive/virfield-release-cleanup-2026-10-16/README.md.md personal/projects/archive/virfield-release-cleanup-2026-10-16/docs/AGENT-GUIDE.md.md personal/projects/archive/virfield-release-cleanup-2026-10-16/docs/ARCHITECTURE.md.md personal/projects/archive/virfield-release-cleanup-2026-10-16/docs/COMPOSITIONAL-PLATFORM.md.md personal/projects/archive/virfield-release-cleanup-2026-10-16/docs/IMAGE-PIPELINE.md.md personal/projects/archive/virfield-release-cleanup-2026-10-16/docs/OPERATIONS.md.md personal/projects/archive/virfield-release-cleanup-2026-10-16/docs/REMOTE-DEBUG.md.md personal/projects/archive/virfield-release-cleanup-2026-10-16/docs/VERIFICATION.md.md personal/projects/archive/virfield-release-cleanup-2026-10-16/docs/VIRFIELD-3-PLAN.md.md personal/projects/archive/virfield-release-cleanup-2026-10-16/docs/acceptance/2026-10-16.json.md personal/projects/archive/virfield-release-cleanup-2026-10-16/docs/acceptance/broker-reviewer-readonly.patch.md personal/projects/archive/virfield-release-cleanup-2026-10-16/docs/fixtures/execution-broker-darwin-process-group.patch.md personal/projects/archive/virfield-release-cleanup-2026-10-16/docs/history/AGENT-GUIDE-before-2026-10-14.md.md personal/projects/archive/virfield-release-cleanup-2026-10-16/docs/history/ARCHITECTURE-before-2026-10-14.md.md personal/projects/archive/virfield-release-cleanup-2026-10-16/docs/history/COMPOSITIONAL-PLATFORM-before-2026-10-14.md.md personal/projects/archive/virfield-release-cleanup-2026-10-16/docs/history/IMAGE-PIPELINE-before-2026-10-14.md.md personal/projects/archive/virfield-release-cleanup-2026-10-16/docs/history/OPERATIONS-before-2026-10-14.md.md personal/projects/archive/virfield-release-cleanup-2026-10-16/docs/history/README-before-2026-10-14.md.md personal/projects/archive/virfield-release-cleanup-2026-10-16/docs/history/REMOTE-DEBUG-before-2026-10-14.md.md personal/projects/archive/virfield-release-cleanup-2026-10-16/docs/history/VERIFICATION-before-2026-10-14.md.md personal/projects/archive/virfield-release-cleanup-2026-10-16/docs/history/VERIFICATION-checkpoints-through-2026-10-15.md.md personal/projects/archive/virfield-release-cleanup-2026-10-16/docs/history/VIRFIELD-3-PLAN-before-2026-10-14.md.md personal/projects/archive/virfield-release-cleanup-2026-10-16/docs/reference/lume-0.5.3-api.json.md personal/projects/archive/virfield-release-cleanup-2026-10-16/docs/superpowers/plans/2026-10-07-tart-adoption-pipeline.md.md personal/projects/archive/virfield-release-cleanup-2026-10-16/docs/superpowers/plans/2026-10-07-tart-guest-identity.md.md (... +7 more)
2026-10-16 08:45:16 +00:00

5.1 KiB
Executable File

Архив исходника docs/superpowers/specs/2026-10-08-desktop-r3-design.md

Источник: Virfield, commit a1460d3372bdfbb5cb19d633d41dd5d3fb3164e6. Снимок перед релизной очисткой. Исторические утверждения ниже относятся к моменту исходной записи; актуальное состояние — в personal/projects/virfield.

> **Reconciled status — 2026-10-14:** This is a dated design/execution record.
> It is not a current deployment runbook or live task tracker. See
> [current delivery state](../../VIRFIELD-3-PLAN.md) and
> [current acceptance](../../VERIFICATION.md); old paths/statuses and unchecked
> example steps below describe their original execution context.
> **2026-10-15 decision:** automatic VM account-password rotation is rejected;
> standard `admin/admin` is the approved target, still pending implementation.
> Historical rotation steps below are superseded by the [maintained plan](../../VIRFIELD-3-PLAN.md#decisions-and-current-boundary).

# R3: Desktop access to VM leases

Status: live (2026-10-08); see VERIFICATION.md "R3 desktop access". Follows R2
(`2026-10-08-hackintosh-nodes-r2-design.md`).

## Goal

Open the desktop of a ready VM lease (Tart on this Mac, or a macOS VM on the
HTPC) in Screen Sharing.app with one command or one click, the way Lume's
`vncUrl` worked in v2. Target ports stay private: nothing new listens on the
LAN.

Out of scope: bare-metal node leases (the MacBook), a browser noVNC view (a
possible later step over the same tunnel), and pre-boot or Recovery screens.

## Decisions

- **Source: guest macOS Screen Sharing.** Each VM lease enables it during
  lease preparation, so existing goldens need no rebuild. Clients sign in as
  `admin` with the lease's own password, which Virfield already generates and
  stores per lease. Runtime VNC was rejected: Tart's `--vnc-experimental`
  listens on every interface of this Mac behind a weak VNC password, and
  QEMU's VNC has no password.
- **Endpoints.**
  - Tart: `<lease IP>:5900` on Tart's host-only network.
  - HTPC VM: the guest's 5900 is forwarded by passt (`USER_PORTS=22,5900`,
    QEMU's own VNC moved off 5900) and published on the node loopback at the
    lease SSH port + 1000 (22100 → 23100). Virfield reaches it through the
    pinned node SSH connection, like guest SSH.
- **Access: the existing lease tunnel, per service.** `OpenTunnel` gains a
  service, `ssh` (default, unchanged) or `desktop`, with at most one tunnel per
  lease and service on `127.0.0.1:<random>` of the daemon host. Tunnels keep
  their lifetime rules: closed on release, expiry, drift or explicit close.
- **Credential delivery.** The `desktop` tunnel response includes
  `url: vnc://admin:<lease password>@127.0.0.1:<port>`. Only an authenticated
  API caller receives it; the password is the lease's guest password, which a
  lease owner may already use for sudo.

## Components

| Unit | Change |
|---|---|
| `internal/guestssh` | `leaseScript` enables Screen Sharing (`launchctl enable system/com.apple.screensharing`, then `kickstart -k`); `Prepare` verifies the guest listens on 5900. `Manager.LeasePassword(l)` reads the lease credential. |
| `internal/baremetal` | VM containers publish `127.0.0.1:<ssh port+1000>:5900` with `USER_PORTS=22,5900` and QEMU VNC on another port; `DialService(ctx, l, "desktop")` tunnels through the node to that port. Config validation reserves the desktop range. |
| `internal/provider`, `internal/fleet` | `ServiceDialer` interface `DialService(ctx, lease, service) (net.Conn, error)`; the fleet routes by lease provider. The primary runtime's default dials `lease.IP:5900` for desktop. |
| `internal/control/tunnel.go` | Tunnels keyed by lease and service; desktop tunnels dial through `ServiceDialer` and return the `vnc://` URL from the preparer's lease password. |
| `internal/httpapi` | `POST /api/v1/leases/{id}/tunnel` accepts an optional `{"service":"desktop"}` body; `DELETE` accepts `?service=desktop`. |
| `cmd/virfield` | `virfield desktop LEASE_ID [--print]` opens the tunnel and runs `open <url>`. |
| `internal/mcpadapter` | `vm_tunnel` and `vm_tunnel_close` take an optional `service`. |
| `internal/web/app.js` | A "Desktop" button on ready VM leases opens the returned URL. |

## Errors

- Desktop on a host lease or a non-ready lease: `lease_unavailable`.
- Guest not listening on 5900 at preparation: `lease_ssh_failed` (the lease
  never becomes ready), with the stage log kept privately.
- Node unreachable at connection time: the tunnel accepts and closes the
  client connection, as SSH tunnels do today.

## Testing

- Unit: lease script contains the Screen Sharing enablement and Prepare
  rejects a guest without 5900; tunnel service routing and per-service
  lifetime; node desktop dial through a forwarding test server; container
  arguments; HTTP body and query handling; CLI `desktop --print`.
- Live: one Tart lease and one HTPC lease: the desktop tunnel returns Apple
  RFB (`RFB 003.889`), Screen Sharing signs in with the lease password
  (screenshot), and the tunnel is closed after release.