Skip to content

stack-single 1.4.0

Choose a tag to compare

@TAIPANBOX TAIPANBOX released this 25 Oct 16:26
· 10 commits to main since this release
a5018e2

stack-single 1.4.0 (a minor release: it was planned as 1.3.2 and renamed, because it turns the record plane on by default and removes the containers of profiles that are off, both of which an operator sees)

Seven defects were measured on a forge upgrade from 1.1.35 to 1.3.1 on 2026-10-19, and one on a fresh 1.3.1 box (gcp2). Each has a gate, teeth cases and a feature file in this release. The static allow-lists a 1.3.1 re-run widened are cut back on this run. One more defect, in this release's own installer, was found on its first live run (forge, 2026-10-25) and fixed before the tag (D14).

Upgrade first

  1. The record plane now starts on every box that does not set WITH_RECORD=0. It is a core control and runs the pinned trailryx-node image, with no build. A box that must stay without it runs WITH_RECORD=0 ./install.sh, and that run stops and removes record-seal if it was running.
  2. Installer-managed profiles this run turns off lose their containers; operator-started profiles keep theirs. record, typed, typed-risk-signal, delegation and openai-door are started by this installer from its flags, so a run that turns one off stops and removes its containers, by name. egress, egress-browser, finops, routines and manual are started by you, and this installer never removes them. A RUNNING container of one of those is started again at this run's pinned image, so an upgrade leaves no old image behind; a stopped one stays stopped. The closing report lists each one it kept, with its image.
  3. A box given its own CLIENT_KEYS_FILE must add its broker's key to that file. Agent tokens are on by default, and the MCP broker needs a key of its own. Add a line <secret>:broker (the secret, a colon, then the word broker), bound in your identity map to agent://<trust domain>/agents/*. Or run ADD_BROKER_KEY=1 ./install.sh, and the installer mints the secret and appends that line, keeping the file's mode, once the identity map binds broker. Without one of those the installer refuses before it writes anything. The README said broker:<secret> before this release; that form was never read. A box whose keys an earlier run took from its keys file keeps them in .env and need not name the file again, but with agent tokens on the broker's line has to come from that file, so such a re-run is refused by name: name the file and the map again (with ADD_BROKER_KEY=1 if the file has no broker line yet), or run WITH_AGENT_TOKENS=0.
  4. A box that ran 1.3.1 more than once had the agents' and the fire drills' keys put on its static allow-lists. This run removes both ids from the gateway's list and the broker's list, unless you name them in STATIC_KEY_IDS. The closing report says which ids it removed. To keep the agents' static key while you move the agents to tokens, name it on every run: STATIC_KEY_IDS=agents ./install.sh. The choice is not sticky: a run without it removes the agents' key again, which is the secure behaviour, so keep naming it until the agents use a token. The key must be one the box holds; the installer refuses a name it does not hold. Until an agent uses a token, a call it makes with a removed static key is refused 401 agent_token_required.
  5. Then re-run ./install.sh. Nothing else needs doing: the volumes of an upgraded box are re-owned to their services' users on every run.

What changed

  • Every read-write volume of a non-root service is re-owned to its uid, recursively, on every run (CLAUDE.md invariant 49). The gateway's retained-reservation journal and typryx's ledger were left with the uid of an earlier release, so the gateway stopped and the typed plane could not write. The one-shots now chown -R each volume.
  • A compose profile this run does not name has no container left behind (invariant 50). The cleanup covers every profile the compose file defines, not two by hand. After the 1.1.35 to 1.3.1 upgrade the FinOps console still ran its 0.6.0 image.
  • The record plane is on by default (invariant 51). WITH_RECORD=1 no longer builds trailryx from source; only BUILD_FROM_SOURCE=1 does.
  • The bus directory can be entered by others, but nothing is written in it by anyone but the setup script (invariant 52). The FinOps console's stream was created correctly, but the directory above it did not let its uid in. Measured on a fresh 1.3.1 box as "permission denied" on open.
  • A re-run keeps exactly the static allow-list the last run wrote; felyx and the broker are named on every run the box holds them; the installer's own agents and fire-drills keys are cut from a widened list (invariant 53, amending 47). A second run no longer adds them; an upgrade removes them unless STATIC_KEY_IDS names them, and the closing report says so.
  • The broker's key line is <secret>:broker everywhere, and ADD_BROKER_KEY=1 adds it (invariant 48). The refusal names both ways out.
  • A re-run whose keys are kept in .env is refused by name, not by a shell error (invariant 48, D14). With agent tokens on and no CLIENT_KEYS_FILE named, the check read the unset variable, stopped on a shell error and printed the refusal meant for a box that gave a keys file; with ADD_BROKER_KEY=1 it wrote .env before stopping. 1.3.1 refused the same box cleanly.

Measured

  • forge, 2026-10-19, upgrade 1.1.35 to 1.3.1: the broker line refusal (logs 19 to 31); the gateway's journal and typryx's ledger left with an earlier uid (logs 31 to 35); the FinOps console still on image v0.6.0 after the upgrade; the second install run widened the allow-list to the agents' and drills' keys.
  • gcp2, 2026-10-19, a fresh 1.3.1 box: the FinOps console started with "permission denied" on open of its own stream (its logs 13b).
  • The gates: broker-key-is-the-keys-file-line.sh, volumes-are-reowned.sh, profiles-off-are-removed.sh, record-plane-is-on-by-default.sh, costcrew-can-reach-its-stream.sh, and agent-tokens-are-wired.sh extended with a two-run section and a section for a .env that a 1.3.1 re-run widened. Each of those gates was run red on 1.3.1, before its fix, and failed for the stated reason. The new teeth cases ran against the fixed tree, where each planted fault goes red.
  • forge, 2026-10-25, on 1.3.1: the FinOps console v0.10.0 ran once the bus directory was 0751; set back to 0750 it stopped on "permission denied" on open, 7 restarts in 12 seconds.
  • forge, 2026-10-25, the first live run of this installer, upgrading 1.3.1 to 1.4.0. From the main of that day it stopped on D14 before writing anything. From the fixed tree a plain run refused by name, with .env and the running containers unchanged. With WITH_AGENT_TOKENS=0, the box's setting since 1.3.1, the upgrade ran: 56 checks ok, none failed; record-seal started on trailryx-node 1.4.0 and sealed a pack of 633 records in 4 segments, which its own check reports VERIFIED (unsigned: the root has no keyryx signature yet); the running FinOps console was kept at its pinned image and opened its stream (bus directory 0751, its stream 10003:10001 0640); no container restarted. A second run: 56 ok, none failed, no container recreated, .env unchanged.
  • broker-key-is-the-keys-file-line.sh case F was red on the main of 2026-10-25 (10 problems, among them CLIENT_KEYS_FILE: unbound variable) and green on the fix; its teeth case removes the guard and the gate goes red.

Not measured

  • The upgrade with agent tokens on, on a box with its own keys: forge ran it with WITH_AGENT_TOKENS=0, as it has run since 1.3.1. gcp2 was not run for this release.
  • A record pack signed by keyryx: the forge pack is unsigned. Whether the record plane seals typryx's four event types was not checked in that pack.
  • An operator-started container re-upped at this run's pins is measured by the cleanup gate's stub only. Compose recreates a container whose configuration changed, which a digest pin does change, and no gate measures that on a live stack; on forge the FinOps console already ran at this release's pin, so that path was not exercised. A re-up that fails stops the run and names the service.
  • The DPoP door origins (TODO(1.4.0, D13) in install.sh): the gateway still accepts a proof for one origin only. The setting that lists them is not in any tokenfuse release this pin reads, and this release does not wait for it.