@microck/raft 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/README.md +27 -15
  2. package/deploy/build-image.py +4 -2
  3. package/deploy/raft-expire.py +109 -31
  4. package/deploy/verify-controls.py +6 -6
  5. package/deploy/verify-features.py +329 -19
  6. package/deploy/verify-jobs.py +264 -0
  7. package/deploy/verify-limits.py +22 -3
  8. package/deploy/verify-live.py +31 -6
  9. package/deploy/verify-output.py +208 -0
  10. package/deploy/verify-release.py +33 -4
  11. package/deploy/verify-run.py +571 -0
  12. package/deploy/verify-self-update.py +9 -1
  13. package/deploy/verify-sync.py +122 -0
  14. package/docs/benchmarks/read-latency-2026-10-29.json +70 -0
  15. package/docs/boat-capabilities.md +60 -7
  16. package/docs/boat-parity-design.md +1 -0
  17. package/docs/boot-performance.mdx +21 -0
  18. package/docs/contract.md +88 -13
  19. package/docs/first-box.mdx +22 -19
  20. package/docs/guides/background-jobs.mdx +38 -31
  21. package/docs/guides/backup-recovery.mdx +4 -3
  22. package/docs/guides/ci-jobs.mdx +209 -0
  23. package/docs/guides/config-policy.mdx +109 -35
  24. package/docs/guides/files.mdx +2 -2
  25. package/docs/guides/index.mdx +31 -0
  26. package/docs/guides/long-running-services.mdx +9 -3
  27. package/docs/guides/meta.json +7 -2
  28. package/docs/guides/project-setup.mdx +1 -1
  29. package/docs/guides/scripting-ci.mdx +36 -14
  30. package/docs/guides/snapshots-forks.mdx +4 -2
  31. package/docs/guides/troubleshooting.mdx +19 -2
  32. package/docs/guides/upgrades.mdx +11 -9
  33. package/docs/index.mdx +26 -28
  34. package/docs/maintainers/index.mdx +18 -0
  35. package/docs/maintainers/meta.json +12 -0
  36. package/docs/meta.json +5 -9
  37. package/docs/operations.mdx +17 -10
  38. package/docs/publishing.md +14 -4
  39. package/docs/reference/capacity.mdx +2 -1
  40. package/docs/reference/cli.md +135 -43
  41. package/docs/reference/configuration.mdx +10 -6
  42. package/docs/reference/meta.json +3 -1
  43. package/docs/releases/0.2.0.md +1 -0
  44. package/docs/releases/0.2.1.md +1 -0
  45. package/docs/releases/0.3.0.md +1 -0
  46. package/docs/releases/0.4.0.md +1 -0
  47. package/docs/releases/0.5.0.md +1 -0
  48. package/docs/releases/0.6.0.md +17 -0
  49. package/docs/releases/0.7.0.md +23 -0
  50. package/docs/releases/index.mdx +21 -0
  51. package/docs/releases/meta.json +15 -0
  52. package/docs/requirements.mdx +1 -1
  53. package/docs/reviews/docs-audit-2026-10-24.md +92 -0
  54. package/docs/reviews/performance-audit-2026-10-29.md +90 -0
  55. package/docs/site-development.md +1 -0
  56. package/docs/verification.mdx +22 -4
  57. package/package.json +3 -1
  58. package/raft.py +526 -193
  59. package/raft_files.py +13 -1
  60. package/raft_jobs.py +390 -0
  61. package/raft_output.py +166 -0
  62. package/raft_run.py +330 -0
  63. package/skills/raft-cli/SKILL.md +78 -182
@@ -3,16 +3,21 @@
3
3
  "collapsible": true,
4
4
  "defaultOpen": false,
5
5
  "pages": [
6
+ "index",
7
+ "---Develop---",
6
8
  "project-setup",
7
9
  "docker",
8
10
  "files",
11
+ "desktop-services",
12
+ "---Automate---",
9
13
  "background-jobs",
10
14
  "long-running-services",
11
15
  "scripting-ci",
12
- "config-policy",
13
- "desktop-services",
16
+ "ci-jobs",
17
+ "---Operate---",
14
18
  "snapshots-forks",
15
19
  "backup-recovery",
20
+ "config-policy",
16
21
  "upgrades",
17
22
  "troubleshooting"
18
23
  ]
@@ -15,7 +15,7 @@ service. Commands run as guest root in `/workspace` unless you choose another us
15
15
  Create a persistent box after [host setup](../operations.mdx):
16
16
 
17
17
  ```sh title="CONTROLLER: Create a project box"
18
- box=$(raft new --location lab --ttl 3600)
18
+ box=$(raft new --location lab --ttl 3600 --persistent)
19
19
  ```
20
20
 
21
21
  Upload a local project, excluding credentials and files you do not want copied.
@@ -11,15 +11,34 @@ authentication, and hosts with passwordless sudo. No Raft HTTP API, SDK, or API
11
11
  exists. Give access only to trusted jobs: the configured SSH account has host sudo
12
12
  and controls all boxes on that host.
13
13
 
14
+ For one-shot builds, [`raft run`](./ci-jobs.mdx) combines allocation, source upload,
15
+ foreground execution, artifact collection and disposable cleanup. It is an
16
+ orchestration command, not a registered CI runner. The manual lifecycle examples
17
+ below remain useful for persistent debugging workflows.
18
+
14
19
  ## Output formats
15
20
 
16
- Raft does not have a global `--json` option. Parse each command's actual format:
21
+ The development CLI supports `raft --json COMMAND ...` for JSON Lines output.
22
+ Each event has a `type`: `data` carries a structured `value`; `stdout` and
23
+ `stderr` carry base64-encoded bytes in `data`; `error` carries `code` and
24
+ `message`; the final `exit` carries the process exit `code`. Decode stream events
25
+ in order within each channel. Chunks need not end at line boundaries. This keeps
26
+ binary output intact and streams long-running command output without buffering
27
+ it all. Interactive `ssh`, `forward` and `desktop` reject JSON mode before acting.
28
+ Help/version work without configuration. JSON mode suppresses release notices.
29
+
30
+ ```sh
31
+ raft --json list --location lab | jq 'select(.type == "data") | .value'
32
+ raft --json exec "$BOX" -- sh -c 'echo hello; exit 7'
33
+ ```
34
+
35
+ Without global `--json`, parse each command's format:
17
36
 
18
37
  | Command | stdout |
19
38
  | --- | --- |
20
39
  | `new`, `fork`, `recover` | One location-qualified handle |
21
40
  | `exec --detach` | One `rfcmd-` job ID |
22
- | `list` | JSONL: one object per box, with `box`, `state`, `stopAt`, `disk`, `note` |
41
+ | `list` | JSONL: one object per box, with `box`, `state`, `stopAt`, `deleteAt`, `disk`, `note` |
23
42
  | `info` | One pretty-printed native Incus metadata JSON object |
24
43
  | `usage` | One JSON object containing running resource counters |
25
44
  | `capacity --json` | One JSON object per location (JSONL across multiple hosts) |
@@ -27,13 +46,15 @@ Raft does not have a global `--json` option. Parse each command's actual format:
27
46
  | `config` | One pretty-printed JSON object with `file`, `defaults`, `policy` |
28
47
  | `config set/unset`, `policy` | One line describing the change |
29
48
  | `prune` | JSONL candidates or deleted records with `box`, `action` |
30
- | `status` | systemd `ActiveState`, `SubState`, `ExecMainStatus` property lines |
31
- | `logs` | Guest journal text |
32
- | `exec` | Payload stdout/stderr |
49
+ | `status` | Retained JSON record with `state`, `exitCode`, timestamps and `droppedBytes` |
50
+ | `logs` | First 1 MiB of retained combined output |
51
+ | `exec`, `run` | Payload stdout/stderr; `run` lifecycle diagnostics use stderr |
33
52
  | Other inspection/maintenance commands | Human-readable text or no output |
34
53
 
35
54
  `list` emits nothing when there are no boxes. `stopAt` is the host Unix deadline
36
- as a string, or an empty string when absent. `disk` is `"shared"` or the box's
55
+ as a string, or an empty string when absent. `deleteAt` is the Unix time the
56
+ location's retention policy deletes a stopped box, in the same form, or an empty
57
+ string. `disk` is `"shared"` or the box's
37
58
  own disk size, such as `"20GiB"`. `note` is the box note object with
38
59
  `purpose` and optional `owner` and `next`, or `null`. `info` uses native Incus keys rather
39
60
  than a normalized Raft schema. `usage` includes `memoryBytes`, `memoryLimit`,
@@ -52,10 +73,11 @@ raft prune --location lab --older-than 7 | jq -r '.box'
52
73
 
53
74
  `raft new` fills omitted options from the controller's
54
75
  `~/.config/raft/config.json`, so the same script can create different boxes on
55
- different controllers. Pass `--location`, `--ttl`, `--cpu`, `--memory` and
56
- `--disk` in CI.
76
+ different controllers. Pass `--location`, `--ttl`, `--cpu`, `--memory`,
77
+ `--disk` and `--disposable` or `--persistent` in CI.
57
78
  Hosts can also require box note fields; give `--purpose`, `--owner` and `--next`
58
- so a policy cannot fail the job. See [Defaults and note policies](./config-policy.mdx).
79
+ so a policy cannot fail the job. A host retention policy can delete a box left
80
+ stopped between jobs; see [Defaults and host policies](./config-policy.mdx).
59
81
 
60
82
  Do not redirect `2>&1` into machine-readable output. Recovery reports its allocated
61
83
  handle on stderr before import finishes; only a successful completion prints the
@@ -76,10 +98,10 @@ stderr.
76
98
 
77
99
  SSH transport failures may return SSH's status rather than the payload's result.
78
100
  The foreground tunnel replaces the CLI process with SSH and uses SSH's exit code.
79
- A zero exit from `status` means the query succeeded; read `ExecMainStatus` for the
80
- job result and `ActiveState`/`SubState` for whether it finished. Do not interpret a
81
- running job's initial `ExecMainStatus=0` as completion. See
82
- [Background jobs](./background-jobs.mdx).
101
+ A zero exit from `status` means the query succeeded. Wait for a terminal `state`
102
+ and read `exitCode`; running, cancelled and interrupted jobs have no confirmed
103
+ payload exit code. Results remain readable after stop or deletion for seven days.
104
+ See [Background jobs](./background-jobs.mdx).
83
105
 
84
106
  ## Create, wait, run, and stop
85
107
 
@@ -105,7 +127,7 @@ cleanup() {
105
127
  }
106
128
  trap cleanup EXIT
107
129
 
108
- box=$(raft new --location lab --ttl 3600)
130
+ box=$(raft new --location lab --ttl 3600 --persistent)
109
131
  printf 'Created %s\n' "$box" >&2
110
132
  ready=false
111
133
  for attempt in {1..30}; do
@@ -9,7 +9,8 @@ Raft captures filesystem snapshots, rolls back changes, and clones workspaces on
9
9
 
10
10
  ## Target workspace handle
11
11
 
12
- Commands in this guide require a stopped workspace:
12
+ Use a **persistent** workspace and stop it first. Stopping a disposable box deletes
13
+ it and its snapshots; do not use one as the source for this walkthrough.
13
14
 
14
15
  ```sh title="CONTROLLER: Select and stop target workspace"
15
16
  raft list
@@ -66,6 +67,7 @@ raft resume "$box" --ttl 600
66
67
  Forking creates an independent clone on the same host:
67
68
 
68
69
  ```sh title="CONTROLLER: Fork workspace into a new clone"
70
+ raft stop "$box" # Use a persistent box; stop deletes disposable boxes
69
71
  copy=$(raft fork "$box" --ttl 600)
70
72
  echo "Created fork: $copy"
71
73
  ```
@@ -110,4 +112,4 @@ copy=$(raft fork "$box" --ttl 600 --cpu 2 --memory 4GiB)
110
112
  raft resume "$box" --ttl 600 --memory 2GiB
111
113
  ```
112
114
 
113
- Omitted CPU and RAM values keep the source limits; the disk never changes on fork or resume. Forks are persistent by default; add `--disposable` to delete a clone when it stops or expires.
115
+ Omitted CPU and RAM values keep the source limits; the disk never changes on fork or resume. Forks are persistent by default, even when `raft config` sets `disposable true`; add `--disposable` to delete a clone when it stops or expires.
@@ -33,8 +33,8 @@ raft doctor
33
33
 
34
34
  An active expiration timer can still run an older worker. Installing or updating
35
35
  the controller CLI does not deploy host code. `doctor` checks the same worker
36
- protocol as disposable creation and retention cleanup, without running expiry or
37
- changing any boxes. It exits nonzero and names the location on a mismatch.
36
+ protocol as disposable creation, prune and setting a retention policy, without
37
+ running expiry or changing any boxes. It exits nonzero and names the location on a mismatch.
38
38
 
39
39
  Review the host deployment changes, then deploy from the checkout matching your
40
40
  CLI. Replace `lab` with the location reported by the diagnostic:
@@ -106,6 +106,23 @@ files and snapshots. Expired disposable containers are deleted, including their
106
106
  snapshots. Use `raft gc --location lab` to check only one host. The timer normally
107
107
  checks every 15 seconds; host outages, graceful shutdown and long locked
108
108
  operations can delay expiry. See [Lifetime and persistent services](./long-running-services.mdx).
109
+ `raft gc` also applies the location's stopped-box retention.
110
+
111
+ ### A stopped box disappeared
112
+
113
+ A host retention policy deletes boxes left stopped for its hours. Check the
114
+ policy and the host journal, which records every deletion:
115
+
116
+ ```sh title="CONTROLLER: Check retention"
117
+ raft config | jq '.policy'
118
+ ```
119
+
120
+ ```sh title="HOST: Find the deletion"
121
+ sudo journalctl -t raft | grep 'Deleted box'
122
+ ```
123
+
124
+ Deleted boxes cannot be recovered except from a `raft backup` archive. See
125
+ [Defaults and host policies](./config-policy.mdx#delete-boxes-left-stopped).
109
126
 
110
127
  ## Common error scenarios
111
128
 
@@ -17,7 +17,7 @@ parts of Raft. Updating one does not automatically update the others.
17
17
  ## Choose a release and prepare
18
18
 
19
19
  Review [release notes](https://github.com/Microck/raft/releases) and use matching
20
- CLI and deployment sources. The examples below pin `v0.2.0`; replace that version
20
+ CLI and deployment sources. The examples below pin `v0.6.0`; replace that version
21
21
  consistently when adopting another release.
22
22
 
23
23
  ```sh title="CONTROLLER: Inspect the current installation"
@@ -34,7 +34,7 @@ stopping one. Schedule redeployment when interruptions are acceptable.
34
34
  ## Update the controller
35
35
 
36
36
  `raft self-update` installs the latest release through the channel that
37
- installed the CLI, and `raft self-update --version 0.2.0` installs a chosen
37
+ installed the CLI, and `raft self-update --version 0.6.0` installs a chosen
38
38
  one. `raft self-update --check` only reports. For npm installs, npm checks the
39
39
  registry integrity hash of a package published with provenance. For uv tools,
40
40
  Raft downloads the release wheel and refuses it unless its SHA-256 matches the
@@ -43,7 +43,7 @@ release `SHA256SUMS`. See [`self-update`](../reference/cli.md#self-update).
43
43
  To install a release by hand instead, for an npm installation:
44
44
 
45
45
  ```sh title="CONTROLLER: Install a pinned CLI release"
46
- npm install -g @microck/raft@0.2.0
46
+ npm install -g @microck/raft@0.6.0
47
47
  raft --version
48
48
  ```
49
49
 
@@ -52,7 +52,7 @@ release, verify the checksum, then install it with `uv`:
52
52
 
53
53
  ```sh title="CONTROLLER: Install a verified release wheel instead of npm"
54
54
  sha256sum --ignore-missing -c SHA256SUMS
55
- uv tool install --force ./raft-0.2.0-py3-none-any.whl
55
+ uv tool install --force ./raft-0.6.0-py3-none-any.whl
56
56
  raft --version
57
57
  ```
58
58
 
@@ -71,8 +71,8 @@ reports each host whose worker differs from the new CLI.
71
71
  Obtain a separate checkout of the matching release:
72
72
 
73
73
  ```sh title="CONTROLLER: Obtain and deploy matching host code"
74
- git clone --branch v0.2.0 https://github.com/Microck/raft.git raft-v0.2.0
75
- cd raft-v0.2.0
74
+ git clone --branch v0.6.0 https://github.com/Microck/raft.git raft-v0.6.0
75
+ cd raft-v0.6.0
76
76
  python3 deploy/deploy.py --location lab
77
77
  raft doctor
78
78
  ```
@@ -84,8 +84,10 @@ timer. It does not import an image or migrate guest files.
84
84
 
85
85
  Do not bypass a conflicting-resource or storage-size error. Inspect the host and
86
86
  preserve backups before explicit recovery; redeployment does not repair arbitrary
87
- infrastructure drift. Disposable creation/fork and prune check the worker protocol
88
- and fail if it differs from the CLI. That check is not an automatic upgrade.
87
+ infrastructure drift. Disposable creation/fork, prune and setting a retention
88
+ policy check the worker protocol and fail if it differs from the CLI. That check
89
+ is not an automatic upgrade. Raft 0.6.0 raised the protocol for stopped-box
90
+ retention, so hosts deployed by an earlier release need this redeploy.
89
91
 
90
92
  ## Replace the image pin
91
93
 
@@ -103,7 +105,7 @@ backup's guest filesystem rather than rebuilding it from the new image.
103
105
  ## Verify the update
104
106
 
105
107
  ```sh title="CONTROLLER: Smoke-check a new persistent box"
106
- box=$(raft new --location lab --ttl 600)
108
+ box=$(raft new --location lab --ttl 600 --persistent)
107
109
  raft exec "$box" -- node --version
108
110
  raft exec "$box" -- docker info
109
111
  raft stop "$box"
package/docs/index.mdx CHANGED
@@ -1,41 +1,39 @@
1
1
  ---
2
2
  title: Overview
3
- description: Persistent Linux workspaces powered by Incus.
3
+ description: Create persistent Linux development boxes on Ubuntu hosts you control.
4
4
  ---
5
5
 
6
6
  # Raft
7
7
 
8
- Raft is an independent, self-hosted open-source alternative to [boat.dev](https://boat.dev).
9
- It provides persistent Linux workspaces on ARM64 and AMD64 hardware,
10
- supporting command execution, Docker, file transfer, snapshots, forks, and desktop access.
11
- Raft is not affiliated with Boat.
8
+ Raft creates **persistent Linux boxes on your own Ubuntu hosts**. Run commands,
9
+ Docker builds and development services; copy files; save snapshots; or open a
10
+ private desktop. A box is an unprivileged Incus container that shares its host's
11
+ kernel, not a virtual machine.
12
12
 
13
- ## Getting started
13
+ ## Start here
14
14
 
15
- Read [System requirements](./requirements.mdx), follow [Installation and host setup](./operations.mdx), and create your [First working box](./first-box.mdx).
15
+ 1. [Check requirements](./requirements.mdx): a Linux controller and a dedicated Ubuntu host.
16
+ 2. [Set up a host](./operations.mdx): install the CLI and run guided onboarding.
17
+ 3. [Create your first box](./first-box.mdx): run a command, stop it and resume it.
16
18
 
17
- ```sh title="CONTROLLER: Create and use a workspace"
18
- box=$(raft new --location lab --ttl 600)
19
+ Already have a configured host? Run these commands on your **controller**
20
+ (the machine where you installed `raft`). Replace `lab` with your location:
21
+
22
+ ```sh
23
+ box=$(raft new --location lab --ttl 600 --persistent)
19
24
  raft exec "$box" -- node --version
20
25
  raft ssh "$box"
21
- raft stop "$box"
22
26
  ```
23
27
 
24
- Stopping a workspace preserves files and packages on disk. Resuming resets its running lifetime.
25
-
26
- ## Task guides
27
-
28
- | Task | Guide |
29
- | :--- | :--- |
30
- | Prepare a project and reuse its installed dependencies | [Project setup and templates](./guides/project-setup.mdx) |
31
- | Run nested containers and build images | [Docker in workspaces](./guides/docker.mdx) |
32
- | Transfer files between controller and workspace | [File transfer](./guides/files.mdx) |
33
- | Run detached commands with systemd logs | [Background jobs](./guides/background-jobs.mdx) |
34
- | Manage deadlines and restart services after resume | [Lifetime and persistent services](./guides/long-running-services.mdx) |
35
- | Automate the CLI and parse its output | [Scripting and CI](./guides/scripting-ci.mdx) |
36
- | Set defaults for new boxes or require box note fields | [Defaults and note policies](./guides/config-policy.mdx) |
37
- | Forward guest ports or open noVNC desktop | [Desktop and private services](./guides/desktop-services.mdx) |
38
- | Capture disk state or clone workspaces | [Snapshots and forks](./guides/snapshots-forks.mdx) |
39
- | Export portable backups across hosts | [Backup and recovery](./guides/backup-recovery.mdx) |
40
- | Update the CLI, host worker, and workspace image | [Upgrades and image changes](./guides/upgrades.mdx) |
41
- | Inspect host services and diagnose errors | [Troubleshooting](./guides/troubleshooting.mdx) |
28
+ Exit the guest shell, then run `raft stop "$box"` on the controller. Files remain;
29
+ processes stop. Host retention policies can later delete stopped boxes.
30
+
31
+ ## Find a task
32
+
33
+ - [Work with a project](./guides/project-setup.mdx) or [copy files](./guides/files.mdx).
34
+ - [Run Docker](./guides/docker.mdx), [background jobs](./guides/background-jobs.mdx), or [open a desktop](./guides/desktop-services.mdx).
35
+ - [Browse all guides](./guides/index.mdx), [look up a command](./reference/cli.md), or [troubleshoot](./guides/troubleshooting.mdx).
36
+
37
+ Raft is an independent open-source alternative to Boat, not affiliated with it.
38
+ [Compare the trade-offs](./boat-capabilities.md). Setup examples target published
39
+ **0.6.0**; [0.7.0 features](./releases/0.7.0.md) are marked unreleased.
@@ -0,0 +1,18 @@
1
+ ---
2
+ title: Maintain Raft
3
+ description: Design, verification, release and documentation work for Raft contributors.
4
+ ---
5
+
6
+ # Maintain Raft
7
+
8
+ These pages are for changing or releasing Raft, not for creating your first box.
9
+ For everyday use, start with [host setup](../operations.mdx) or the [task guides](../guides/index.mdx).
10
+
11
+ - [Design decisions](../boat-parity-design.md): why Raft uses Incus and host SSH.
12
+ - [Runtime contract](../contract.md): behavior that implementations must preserve.
13
+ - [Verification](../verification.mdx): test commands, evidence and unverified boundaries.
14
+ - [Publishing](../publishing.md): package and image release gates.
15
+ - [Documentation site](../site-development.md): edit, preview and check these docs.
16
+
17
+ Host tests create and delete real workspaces. Read each suite's effects before
18
+ running it, and use dedicated infrastructure you are authorized to change.
@@ -0,0 +1,12 @@
1
+ {
2
+ "title": "Maintainers",
3
+ "collapsible": true,
4
+ "defaultOpen": false,
5
+ "pages": [
6
+ "index",
7
+ "[Design decisions](/docs/boat-parity-design/)",
8
+ "[Verification](/docs/verification/)",
9
+ "[Publishing](/docs/publishing/)",
10
+ "[Documentation site](/docs/site-development/)"
11
+ ]
12
+ }
package/docs/meta.json CHANGED
@@ -2,20 +2,16 @@
2
2
  "title": "Raft",
3
3
  "pages": [
4
4
  "index",
5
- "---Start here---",
5
+ "---Get started---",
6
6
  "requirements",
7
7
  "operations",
8
8
  "first-box",
9
+ "---Use Raft---",
9
10
  "guides",
10
11
  "reference",
11
- "contract",
12
- "---Comparison---",
12
+ "---About---",
13
13
  "boat-capabilities",
14
- "boot-performance",
15
- "---Contributing---",
16
- "boat-parity-design",
17
- "verification",
18
- "publishing",
19
- "site-development"
14
+ "maintainers",
15
+ "releases"
20
16
  ]
21
17
  }
@@ -7,6 +7,8 @@ description: Install the Raft controller CLI, provision a dedicated host, and ac
7
7
 
8
8
  Set up a dedicated Ubuntu host, install the Raft CLI, provision Incus, acquire a workspace image, and verify readiness.
9
9
 
10
+ Examples pin published **0.6.0**. Use matching CLI, deployment scripts and image assets.
11
+
10
12
  Review prerequisites in [System requirements](./requirements.mdx) before starting.
11
13
 
12
14
  ## Guided onboarding
@@ -15,7 +17,7 @@ Install the CLI from npm on your Linux controller, confirm key-based SSH to the
15
17
  host, then let `raft host add` do the remaining steps:
16
18
 
17
19
  ```sh title="CONTROLLER: Onboard a host"
18
- npm install -g @microck/raft@0.5.0
20
+ npm install -g @microck/raft@0.6.0
19
21
  ssh ubuntu@192.0.2.10 true
20
22
  raft host add lab --ssh ubuntu@192.0.2.10 --dry-run
21
23
  raft host add lab --ssh ubuntu@192.0.2.10
@@ -30,6 +32,9 @@ that instead. See [`host add`](./reference/cli.md#host-add) for image options.
30
32
 
31
33
  ## Manual setup
32
34
 
35
+ <details>
36
+ <summary>Advanced: provision each component yourself instead of using host add</summary>
37
+
33
38
  The steps below are what `raft host add` automates. Follow them to inspect or
34
39
  customize each stage.
35
40
 
@@ -62,7 +67,7 @@ sudo -n true && echo "Passwordless sudo is functional"
62
67
  On your Linux controller with Python 3.11.8+, install the published CLI:
63
68
 
64
69
  ```sh title="CONTROLLER: Install published CLI"
65
- npm install -g @microck/raft@0.5.0
70
+ npm install -g @microck/raft@0.6.0
66
71
  raft --version
67
72
  ```
68
73
 
@@ -70,7 +75,7 @@ Installation does not configure hosts or download images. Clone the matching
70
75
  release to obtain the deployment scripts and example configuration:
71
76
 
72
77
  ```sh title="CONTROLLER: Obtain deployment scripts"
73
- git clone --branch v0.5.0 https://github.com/Microck/raft.git raft
78
+ git clone --branch v0.6.0 https://github.com/Microck/raft.git raft
74
79
  cd raft
75
80
  ```
76
81
 
@@ -161,16 +166,16 @@ Workspaces require an unprivileged Debian 13 development image matching the host
161
166
 
162
167
  <Tab value="Download release image">
163
168
 
164
- Download the release archive, checksum, and manifest from [Raft releases](https://github.com/Microck/raft/releases). These examples pin `v0.5.0`, matching the CLI and deployment checkout above. The `sha256sum` check gates import so corrupted archives are rejected:
169
+ Download the release archive, checksum, and manifest from [Raft releases](https://github.com/Microck/raft/releases). These examples pin `v0.6.0`, matching the CLI and deployment checkout above. The `sha256sum` check gates import so corrupted archives are rejected:
165
170
 
166
171
  <Tabs items={["ARM64", "AMD64"]}>
167
172
 
168
173
  <Tab value="ARM64">
169
174
 
170
175
  ```sh title="HOST (ARM64): Download, verify, and import release image"
171
- curl -fsSL -O https://github.com/Microck/raft/releases/download/v0.5.0/raft-dev-arm64.tar.gz
172
- curl -fsSL -O https://github.com/Microck/raft/releases/download/v0.5.0/SHA256SUMS
173
- curl -fsSL -O https://github.com/Microck/raft/releases/download/v0.5.0/manifest-arm64.json
176
+ curl -fsSL -O https://github.com/Microck/raft/releases/download/v0.6.0/raft-dev-arm64.tar.gz
177
+ curl -fsSL -O https://github.com/Microck/raft/releases/download/v0.6.0/SHA256SUMS
178
+ curl -fsSL -O https://github.com/Microck/raft/releases/download/v0.6.0/manifest-arm64.json
174
179
 
175
180
  sha256sum --ignore-missing -c SHA256SUMS && \
176
181
  sudo incus --project raft image import ./raft-dev-arm64.tar.gz --alias raft-dev
@@ -181,9 +186,9 @@ sha256sum --ignore-missing -c SHA256SUMS && \
181
186
  <Tab value="AMD64">
182
187
 
183
188
  ```sh title="HOST (AMD64): Download, verify, and import release image"
184
- curl -fsSL -O https://github.com/Microck/raft/releases/download/v0.5.0/raft-dev-amd64.tar.gz
185
- curl -fsSL -O https://github.com/Microck/raft/releases/download/v0.5.0/SHA256SUMS
186
- curl -fsSL -O https://github.com/Microck/raft/releases/download/v0.5.0/manifest-amd64.json
189
+ curl -fsSL -O https://github.com/Microck/raft/releases/download/v0.6.0/raft-dev-amd64.tar.gz
190
+ curl -fsSL -O https://github.com/Microck/raft/releases/download/v0.6.0/SHA256SUMS
191
+ curl -fsSL -O https://github.com/Microck/raft/releases/download/v0.6.0/manifest-amd64.json
187
192
 
188
193
  sha256sum --ignore-missing -c SHA256SUMS && \
189
194
  sudo incus --project raft image import ./raft-dev-amd64.tar.gz --alias raft-dev
@@ -258,6 +263,8 @@ Check that Incus, the network service, and the expiration timer are active. For
258
263
 
259
264
  </Steps>
260
265
 
266
+ </details>
267
+
261
268
  ## Next step
262
269
 
263
270
  Proceed to [First working box](./first-box.mdx) to launch, verify, and manage your first workspace.
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  title: Publishing
3
+ description: Release packages and native images through verified publication gates.
3
4
  ---
4
5
 
5
6
  # Publishing a clean source release
@@ -8,12 +9,12 @@ Public releases must contain only reusable code, examples, and documentation. Ke
8
9
 
9
10
  ## Release assets and image publishing
10
11
 
11
- Release `main` through the `native images` workflow with a semantic `release_tag`, such as `v0.2.0`. The tag must match both Python and npm versions. Clean upstream Debian bases provide the images.
12
+ Release `main` through the `native images` workflow with a semantic `release_tag`, such as `v0.7.0`. The tag must match both Python and npm versions. Clean upstream Debian bases provide the images.
12
13
 
13
14
  The workflow builds and inspects Python and npm packages, tests their installed executables outside the checkout, and publishes `@microck/raft` using the repository's `NPM_TOKEN` secret with npm provenance. Only then does it create the GitHub release with the wheel, source archive, npm tarball and verified image assets. Published versions are immutable; after partial publication, fix the failure and use a new patch version.
14
15
 
15
16
  ```sh
16
- gh workflow run images.yml --ref main -f release_tag=v0.2.0
17
+ gh workflow run images.yml --ref main -f release_tag=v0.7.0
17
18
  ```
18
19
 
19
20
  - **Validation gating**: Publication requires native lifecycle and full-image recovery jobs alongside fresh AMD64 KVM provisioning and reboot verification.
@@ -30,15 +31,24 @@ Scan **all Git history**, branches, and tags before changing repository visibili
30
31
 
31
32
  ## Release verification commands
32
33
 
34
+ Install `gitleaks`, `uv`, Node.js with `npm`, and the OpenSSH client providing `ssh-keygen` before running these checks. Ensure they are available on `PATH`; `uv sync --locked` does not install these tools.
35
+
33
36
  Run security scanning, linting, formatting checks, and package builds before tagging:
34
37
 
35
38
  ```sh
36
39
  gitleaks dir --redact --no-banner .
37
40
  gitleaks git --redact --no-banner .
38
41
  uv sync --locked
39
- uvx ruff check raft.py deploy/*.py
40
- uvx ruff format --check raft.py deploy/*.py
42
+ uvx ruff check raft.py raft_files.py raft_run.py deploy/*.py
43
+ uvx ruff format --check raft.py raft_files.py raft_run.py deploy/*.py
44
+ uv run python -m compileall -q raft.py raft_files.py raft_run.py deploy
45
+ uv run python deploy/verify-limits.py
46
+ uv run python deploy/verify-image-tests.py
47
+ uv run python deploy/verify-run.py
48
+ uv run python deploy/verify-features.py
49
+ uv run python deploy/verify-self-update.py
41
50
  uv build
51
+ uv run python deploy/verify-release.py
42
52
  ```
43
53
 
44
54
  ## Image distribution rules
@@ -23,7 +23,7 @@ A box from a snapshot (`new --from`) or a fork keeps the source's CPU, RAM and
23
23
  disk instead of any default, and each flag you pass overrides only its own value.
24
24
 
25
25
  ```sh
26
- box=$(raft new --cpu 4 --memory 16GiB --disk 40GiB --ttl 3600 --purpose "Large build")
26
+ box=$(raft new --cpu 4 --memory 16GiB --disk 40GiB --ttl 3600 --persistent --purpose "Large build")
27
27
  ```
28
28
 
29
29
  A CPU or RAM request larger than the whole host fails before anything is
@@ -37,6 +37,7 @@ Change CPU and RAM when you resume a stopped box or fork one:
37
37
 
38
38
  ```sh
39
39
  raft resume "$box" --ttl 1800 --cpu 2 --memory 4GiB
40
+ raft stop "$box" # Fork requires a stopped persistent source
40
41
  copy=$(raft fork "$box" --ttl 1800 --memory 2GiB)
41
42
  ```
42
43