Skip to content

koto 1.7.0

Choose a tag to compare

@jpzk jpzk released this 24 Oct 19:24
Immutable release. Only release title and notes can be modified.

koto 1.7.0

TUI: sessions (#49)

  • Sessions are now rows in the tree, nested under their group (main included). The group row itself is the default session; selecting a session row switches the active session.
  • alt+n opens a new-session dialog. The name is validated inline; Enter creates the session and switches to it, Esc cancels.
  • New daemon RPC SessionCreate (ACL verb session_create) registers a named session in sessions.json before its first send, so it survives a TUI restart and is visible to every client. It refuses empty/default names, goal-* names, invalid names and unregistered groups.
  • Fix: /session <name> for a session the daemon had not listed yet used to snap back to the default session. The TUI now keeps locally created sessions in the tree until the daemon lists them.
  • Needs both sides on 1.7.0. The new-session dialog calls SessionCreate; a 1.7.0 TUI against a 1.6.0 daemon cannot create sessions. Upgrade the daemon (koto install) and koto-tui together.

TUI: keymap (#51 + #49)

  • alt+n: new session (new)
  • ctrl+n: new group (unchanged)
  • ctrl+x (tree): destroy the hovered group, with a confirm dialog (new)
  • ctrl+s (tree): stop the hovered group's VM, with a confirm dialog
  • ctrl+v: toggle mouse mode (wheel scroll vs native select/copy); with a draft in the input bar it pastes
  • ctrl+o: jump to any group or session (fuzzy)
  • ctrl+t: fold/unfold jobs on the current row
  • When more than one dialog could be open, the order is: destroy confirm, then stop confirm, then the new-session dialog.
  • An earlier draft of #49 put mouse mode on ctrl+x. That binding was dropped; ctrl+x is destroy only.
  • The help cheatsheet and command palette list the new keys.

Security: Go toolchain go1.26.9 → go1.26.10 (#53)

  • Fixes GO-2026-6809 (crypto/x509), which govulncheck found reachable in all four modules (protocol, tui, fcguest, daemon).
  • go1.26.10 came out 2026-10-19, so it is less than 6 weeks old. The operator approved an exception to the 6-week dependency age rule for this security fix on 2026-10-24. The toolchain and build image are pinned by hash.

Security: undici 8.12.2 + integer-conversion bounds checks (#54)

  • undici 8.10.2 → 8.12.2 in the guest's pi install, set through an npm overrides entry. This fixes 3 Dependabot alerts:
    • GHSA-xjj6-f33q-929c (high): denial of service from an unhandled error when a response has too many content-encodings.
    • GHSA-4qv8-2p9j-2685 (medium): denial of service from unbounded memory use in the EventSource parser.
    • GHSA-f72v-6w45-q472 (medium): Subresource Integrity bypass with non-lowercase algorithm tokens.
  • 8.12.2 is the oldest patched version. It came out on 2026-10-15, so it is less than 6 weeks old. The operator approved an exception to the 6-week rule for this security fix.
  • The only change to package-lock.json is the undici entry (version, resolved and integrity). We checked the tarball's integrity against the registry and confirmed with npm ci --ignore-scripts in a hash-pinned node container that every copy of undici resolves to 8.12.2. The rootfs build checks the lockfile hash and the undici version.
  • Fixed 7 CodeQL alerts (go/incorrect-integer-conversion: a strconv.Atoi result converted to int32 without an upper bound check). Each site now checks bounds instead of silently wrapping:
    • Ports in the ctl replies and gRPC spawn replies must be between 0 and 65535. Any other value returns an error.
    • Word counts and the host memory cap are clamped to the int32 range.
    • The TUI's limit and max_iterations reject NaN, ±Inf and out-of-range values before the RPC is sent.
    • Every site has unit tests for the max, min and overflow values.
  • The Dependabot and CodeQL alerts close once the default branch (develop) has the fix. That happens when release/1.7.0 is merged back into develop after the release is published.

Assets

  • koto: rebuilt (daemon changes + toolchain).
  • koto-tui: rebuilt (TUI changes + toolchain).
  • rootfs.img (fedora44): rebuilt for two reasons. (1) The guest agent (fc-agent) is now compiled with go1.26.10; the 1.6.0 rootfs had it compiled with go1.26.9, and GO-2026-6809 is reachable in fcguest. (2) The pi install inside the guest now ships undici 8.12.2 (#54). The rootfs build checks the OS (fedora44), the fc-agent toolchain, the undici version and that the pi lockfile hash matches the committed package-lock.json (a67466a8…).
  • vmlinux 6.1.188: the 1.6.0 asset, reused byte-for-byte. fcguest/build-kernel.sh is unchanged since 1.6.0.
  • firecracker 1.17.0: the 1.6.0 asset (itself reused from 1.5.2), byte-for-byte. fcguest/build-firecracker.sh is unchanged since 1.6.0.
  • Both reused assets were downloaded from release 1.6.0 and checked against its signed SHA256SUMS before they were repackaged.

Tests

  • On release/1.7.0 @37d5f21 (#54 merged) with the go1.26.10 image: build and vet for all 4 modules; go test for tui, protocol, fcguest and daemon all pass, including the new integer-conversion tests.
  • The final release candidate (koto cf2c75ef, koto-tui 4bbf41ee, rootfs e389ba0c, 1.6.0 vmlinux and firecracker) was installed and passed the claude-wan, claude-none and minimax end-to-end cases, each on the first try (EXIT=0). In claude-wan the guest reached the internet; in claude-none it had no egress, as expected; minimax answered PONG. koto-tui started and drew its screen.

Known issues

  • Guest boot has a fixed 30s limit. On a heavily loaded host a guest can miss it and the send fails with a boot timeout; retrying once load drops works. The fix (fix/guest-boot-timeout) is planned for the next release.
  • GO-2026-5932 (golang.org/x/crypto/openpgp) still shows up in dependency scans. govulncheck finds the vulnerable code is not reachable, and there is no fixed version upstream.
  • Carried over from 1.6.0: koto ctl history can return a partially written reply if it is polled while the reply is still being written. Accept a reply only once it is stable across two polls.

🤖 Generated with Claude Code