Skip to content

v0.6.0

Choose a tag to compare

@github-actions github-actions released this 05 Oct 23:59
· 39 commits to main since this release
ac20edd

Desk v0.6.0

New desks are signed. Desk keeps a signing key for each desk it makes, starts new desks at configVersion "6" with that key, and its decision record checks the trail's signatures with the desk's public keys. You can rotate a desk's key, and Desk finishes or undoes a rotation that a stop cut short. Desk moves to Runtime v0.27.1, Runner v0.6.0 and Gateway v0.9.1, and each job's Activity tab now reads Runner's journal.

Before you update: back up every desk's Jobs store. Runner v0.6.0 migrates each store to its schema "2" on its first start, and the Runner that earlier Desks bundle (v0.5.0) then refuses that store. Desk's updater does not copy the store, and a rollback selects the earlier Desk, not the earlier data: after a rollback, Jobs cannot open a migrated store until a copy from before the update is put back. Stop Desk, copy each Jobs workspace folder, then update (installation and updates).

What changes for you

  • A desk you make now is signed. Where the runtime reads configVersion "6", Desk keeps an Ed25519 key for the desk in its own configuration folder, writes the desk's jpack.json at "6" naming that key, and locks it. Each deciding run's record is then signed by the runtime. Desks made earlier, and the project Desk was started on, are not changed.
  • The decision record (Admin → Project) checks signatures with the desk's public keys, shows those keys for you to hand to a holder, and shows the runtime's own check of the key.
  • Rotate a desk's key from the decision record, on your confirmation.
  • The Activity tab reads Runner's journal of job activity.
  • The Runs table and run page say "Not recorded" for a run time Runner did not store or that cannot be read, instead of failing.

Signed desks: key custody (#219, ADR-0010 PR 3a)

  • Where the key is. One seed per desk at <Desk configuration folder>/secrets/signing/<desk id>.seed, 0600, in a folder that is 0700 and held to Desk's custody checks: real folders, not links, writable by the user alone. The runtime writes the seed (jpack audit key generate) and never over a file; Desk never reads its bytes. The desk's public keys are kept beside it, in <desk id>.keys.jsonl.

  • New desks at "6".

    The runtime reads Desk can keep a key The new desk
    "6" yes "6", signed
    "6" no "5", unsigned, and the creation says why
    "5", not "6" (not asked) "5", unsigned, and the creation says so

    A creation that fails at any step leaves no key behind. A creation stopped by a crash is finished or cleared at the next start, and a key whose desk was published is never removed because a file could not be read for a moment.

  • The decision record passes the desk's public keys to jpack audit verify only where the key list's key in force is the seed's own (jpack audit key public); otherwise it passes none, and says why. It shows the runtime's packs validate check of the key in the runtime's words.

  • No path is shown. Every sentence the panel passes on has the key's location, the configuration folder and the home folder replaced, in every spelling the runtime prints.

  • What a signature binds. A holder of the key signed these exact bytes. It binds nothing against the owner, who holds the key, or against a program running as the owner's user, which can read it. A Jobs run is not signed by this release.

Rotating a desk's key (#231, ADR-0010 PR 3b)

  • Your action, never scheduled. The decision record offers "Rotate signing key" behind a confirmation. Desk makes the next key, has the runtime hand signing over to it (jpack audit key rotate), adds it to the desk's list of public keys, and puts it in the current key's place.
  • Whether the runtime handed signing over is read from the trail's signature sidecar, not from its answer alone. A rotation it refused is undone. A rotation that a stop cut short is finished or undone at the next start, or, where Desk cannot tell which, left as it is, and the decision record says so.
  • What a rotation does not do:
    • it revokes nothing: whoever holds the old key can still sign as it;
    • a holder needs the new public key, and to be told about the old one;
    • a record written during the rotation may be unsigned;
    • the old seed's name is removed, but its bytes may remain on the disk;
    • a lost key cannot be rotated away from.
  • The decision record passes every key, in order, and checks that the list agrees with the trail's own rotations.
  • A desk keeps at most 64 keys, and Desk offers no rotation past that.
  • The project Desk was started on has no key in this release, so it has none to rotate.

One lock for every change to keys (#230)

Two Desk processes can share one configuration folder, for example Desk started on two projects. One's start-up cleanup could remove the other's new desk key. Now:

  • What takes the lock: a key's creation, the start-up cleanup, a rotation and its recovery each hold one exclusive lock on Desk's signing folder.
  • Cleanup and recovery that find the lock taken change nothing, and leave it for the next start.
  • A creation or rotation waits up to ten seconds, then refuses with a plain message.

The Activity tab reads Runner's journal (#228, closes #218)

  • It shows Runner's own log of job activity, in Runner's order. Each row is marked as a journal entry or a record, and no row names a person as the actor.
  • It reads the journal forward, one page at a time, and shows no entry until it has read to the end. It renders the newest 500, with a control for earlier ones, and keeps at most 20,000.
  • A runner that serves no journal leaves the record rows as before, with one line saying so.
  • The journal is neither chained nor signed, and the tab says so.
  • A change in the Jobs proxy: /api/operations/ now refuses any Jobs path that contains a percent-encoding, on every forwarded route. The page never sends one.

"Not recorded" for a missing run time (#226, closes #223)

The Runs table, the run page and the Jobs index show "Not recorded" for a run time Runner did not store or that cannot be read, where they threw before.

Component updates (#227)

  • Runtime v0.27.1. It refuses a signing key kept where another user could remove or replace it, which Desk's custody already meets. Every audit verify report now also says, among what it does not establish, that the trail records decisions, not refused or failed attempts (runtime ADR-0048); the decision record shows that sentence as the runtime writes it.
  • Runner v0.6.0. A journal of job activity, which the Activity tab reads; exports of a run whose job has no mapping v2 (version 3 or later, with "inputs":"not-mapped"), which the verification download names by version as before; and the store migration above. Desk's limits on what it reads from Runner are unchanged: Runner v0.6.0's export and chain limits are those of v0.5.0.
  • Gateway v0.9.1. It seals a session that only a discarded registry line names; Desk's managed gateway is unaffected on the paths Desk uses.

Existing job releases keep their frozen Runtime. Desk's release stays at state epoch 1: the storage change is Runner's store, and the backup above is the explicit step.

Verification

CI ran frontend behaviour, all twelve locale catalogues, the Go chassis tests, the Jobs companion against the pinned Runner and Runtime, the local Gateway checks and the native archive builds.

  • Review: each change to key handling had a cross-vendor round, recorded on its pull request with a disposition for every finding.
    • #219 had three rounds. The last high-severity finding, a read error at start that could remove a published desk's key, was fixed before merge.
    • #231 had one round. Its one finding that could leave a desk without a usable key, rotation past the key list's bound, was fixed before merge. Four others are filed as #239.
  • Mutation checks: every safeguard of #219 and #231 has a row in scripts/mutation-check.sh. The rows that each fix added or changed were run and caught before its merge. The full set for #219 is being run after merge.

Not exercised: macOS and Windows for key custody (custody is Unix-only, and keeps no key on a build that cannot establish ownership); a key owned by another user (faked through a test seam); a rotation stopped at every moment by a real crash (tests stop it at each step through a seam); two real Desk processes on one configuration folder (tested with a second lock holder in one process); a native speaker's reading of the new messages.

See installation and updates and release verification.

Component Pin
Runtime v0.27.1
Runner and source worker v0.6.0
Gateway and required Desk adapters v0.9.1

Platforms

This release contains complete Linux/amd64, macOS Apple Silicon (arm64), and
macOS Intel (amd64) archives. All three archives were built and smoke-tested on
native GitHub-hosted runners before publication; neither macOS archive is merely
cross-compiled. Component versions come from the same release lock.

macOS executables are not Developer ID signed or notarized. Gatekeeper may block
downloaded executables; verify the release and checksums, then use Apple's
Privacy & Security → Open Anyway procedure
for the blocked executable. Native CI does not exercise these dialogs. The Codex
subscription subprocess bridge remains Linux-only.

No Windows archive is published. Windows execution is untested, and the managed
installer supports only Linux and macOS.