@microck/raft 0.0.0-stage → 0.2.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.
- package/.github/assets/raft-logo.png +0 -0
- package/LICENSE +21 -0
- package/README.md +162 -2
- package/deploy/benchmark-boot.py +150 -0
- package/deploy/build-image.py +95 -0
- package/deploy/deploy.py +176 -0
- package/deploy/incus-network.conf +4 -0
- package/deploy/install-incus.sh +22 -0
- package/deploy/raft-expire.py +62 -0
- package/deploy/raft-expire.service +8 -0
- package/deploy/raft-expire.timer +8 -0
- package/deploy/raft-network.service +12 -0
- package/deploy/raft-network.sh +40 -0
- package/deploy/verify-controls.py +241 -0
- package/deploy/verify-features.py +461 -0
- package/deploy/verify-fresh-host.py +301 -0
- package/deploy/verify-image-tests.py +139 -0
- package/deploy/verify-image.py +95 -0
- package/deploy/verify-limits.py +110 -0
- package/deploy/verify-live.py +903 -0
- package/deploy/verify-release.py +132 -0
- package/deploy/verify-tools.py +105 -0
- package/docs/benchmarks/amd64-native-ci.json +137 -0
- package/docs/benchmarks/arm64-baseline-a.json +108 -0
- package/docs/benchmarks/arm64-baseline-b.json +108 -0
- package/docs/benchmarks/arm64-candidate-a.json +109 -0
- package/docs/benchmarks/arm64-desktop-local.json +22 -0
- package/docs/benchmarks/arm64-native-ci.json +137 -0
- package/docs/boat-capabilities.md +64 -0
- package/docs/boat-parity-design.md +26 -0
- package/docs/boot-performance.mdx +102 -0
- package/docs/contract.md +93 -0
- package/docs/first-box.mdx +82 -0
- package/docs/guides/background-jobs.mdx +92 -0
- package/docs/guides/backup-recovery.mdx +111 -0
- package/docs/guides/desktop-services.mdx +87 -0
- package/docs/guides/docker.mdx +84 -0
- package/docs/guides/files.mdx +91 -0
- package/docs/guides/meta.json +14 -0
- package/docs/guides/snapshots-forks.mdx +107 -0
- package/docs/guides/troubleshooting.mdx +127 -0
- package/docs/incus.example.json +3 -0
- package/docs/index.mdx +36 -0
- package/docs/meta.json +21 -0
- package/docs/operations.mdx +224 -0
- package/docs/publishing.md +48 -0
- package/docs/reference/capacity-limits.mdx +83 -0
- package/docs/reference/cli.md +279 -0
- package/docs/reference/configuration.mdx +77 -0
- package/docs/reference/meta.json +10 -0
- package/docs/releases/0.2.0.md +22 -0
- package/docs/requirements.mdx +47 -0
- package/docs/reviews/code-review-2026-10-06.md +168 -0
- package/docs/site-development.md +80 -0
- package/docs/verification.mdx +231 -0
- package/images/incus/build.sh +57 -0
- package/images/incus/desktop.sh +21 -0
- package/images/incus/raft-desktop.service +7 -0
- package/package.json +46 -4
- package/raft.py +955 -0
- package/raft_files.py +134 -0
- package/skills/raft-cli/SKILL.md +117 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Documentation site
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Documentation site
|
|
6
|
+
|
|
7
|
+
The Fumadocs site in `website/` compiles Markdown and MDX files in
|
|
8
|
+
`docs/` directly. Edit those files to update both GitHub documentation and the site.
|
|
9
|
+
`docs/meta.json` and directory `meta.json` files control sidebar order and groups. Review reports stay outside the site navigation.
|
|
10
|
+
|
|
11
|
+
## Run locally
|
|
12
|
+
|
|
13
|
+
Use Node.js 24 and pnpm 11.25.0. Python 3 serves the local static preview.
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
cd website
|
|
17
|
+
pnpm install --frozen-lockfile
|
|
18
|
+
pnpm dev --hostname 127.0.0.1 --port 4300
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Open `http://127.0.0.1:4300/docs/`. The site includes navigation, full-text search,
|
|
22
|
+
code highlighting and a table of contents. Light mode is the default; the theme switch also offers dark mode.
|
|
23
|
+
|
|
24
|
+
## Check and build
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
pnpm lint
|
|
28
|
+
pnpm types:check
|
|
29
|
+
pnpm build
|
|
30
|
+
pnpm test
|
|
31
|
+
pnpm start
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Build output
|
|
35
|
+
|
|
36
|
+
The build copies benchmark reports and example configuration from `docs/` into the static export. Generated assets and Next.js output stay outside version control. The site is a separate package from the Python CLI.
|
|
37
|
+
|
|
38
|
+
### Site tests
|
|
39
|
+
|
|
40
|
+
`pnpm test` checks the exported pages, links, search, Markdown downloads, and 404s over controller loopback. It does not contact workspace hosts.
|
|
41
|
+
|
|
42
|
+
Set `RAFT_DOCS_TEST_PORT` if port 4391 is occupied.
|
|
43
|
+
|
|
44
|
+
## Machine-readable documentation
|
|
45
|
+
|
|
46
|
+
- `/llms.txt` lists the Markdown files for every documentation page.
|
|
47
|
+
- `/llms-full.txt` exports the complete documentation.
|
|
48
|
+
- `/llms.mdx/docs/contract/content.md` exports the contract as Markdown.
|
|
49
|
+
|
|
50
|
+
GitHub Pages serves fixed files. Use the explicit Markdown URLs; documentation
|
|
51
|
+
pages return HTML regardless of the `Accept` header.
|
|
52
|
+
|
|
53
|
+
## Hosting
|
|
54
|
+
|
|
55
|
+
The public site is [raft.micr.dev](https://raft.micr.dev/). GitHub Pages serves
|
|
56
|
+
`website/out/` at the domain root. Search runs in the browser using a build-time index.
|
|
57
|
+
|
|
58
|
+
- Pull requests build and test the site. Pushes to `main` deploy the verified export.
|
|
59
|
+
- Set the repository Pages publishing source to **GitHub Actions**.
|
|
60
|
+
- For a fork, replace `website/public/CNAME` and the `metadataBase` URL in
|
|
61
|
+
`website/app/layout.tsx` with your domain, then configure Pages and DNS.
|
|
62
|
+
|
|
63
|
+
For a local production preview, `pnpm start` serves the same export at
|
|
64
|
+
`http://127.0.0.1:4300/`. Any static HTTP host can serve the exported files.
|
|
65
|
+
Publishing the documentation does not provide public
|
|
66
|
+
ingress to Raft workspaces.
|
|
67
|
+
|
|
68
|
+
## Typography
|
|
69
|
+
|
|
70
|
+
| Element | Font |
|
|
71
|
+
| --- | --- |
|
|
72
|
+
| Page titles | Funnel Display |
|
|
73
|
+
| Body text | Inter |
|
|
74
|
+
| Code blocks | Monospace |
|
|
75
|
+
|
|
76
|
+
The pairing follows boat.dev. Upright Latin WOFF2 files from Fontsource live in `website/public/fonts/`; their SIL Open Font Licenses are in `boat-fonts-license.txt`.
|
|
77
|
+
|
|
78
|
+
`next/font/local` serves the bundled fonts without third-party requests.
|
|
79
|
+
|
|
80
|
+
Light mode uses Boat's white background, dark text, and thin borders. The theme switch also offers dark mode.
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Verification
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Verification
|
|
6
|
+
|
|
7
|
+
Raft is verified using real disposable Incus workspaces, guest processes, files, Docker builds, and network connections. Tests contain no mocked services and verify Raft behavior rather than conformance with the hosted Boat service.
|
|
8
|
+
|
|
9
|
+
## Verification boundaries
|
|
10
|
+
|
|
11
|
+
Tests do not certify arbitrary long-running workloads, host loss, multi-tenant security boundaries, or exact Boat image/version parity. ARM64 host reboot and physical storage capacity are not certified by the AMD64 VM test. Containers share the host kernel and do not offer VM isolation.
|
|
12
|
+
|
|
13
|
+
Storage accounting covers shared pools rather than per-box quotas. Large backup transfers hold the host lifecycle lock, which delays expiration checks.
|
|
14
|
+
|
|
15
|
+
## Coverage matrix
|
|
16
|
+
|
|
17
|
+
| Implemented workflow | E2E assertion |
|
|
18
|
+
| --- | --- |
|
|
19
|
+
| Create/list/info/delete | Qualified handle, native state, ownership and cleanup |
|
|
20
|
+
| Root terminal/exec | Real PTY, workspace directory, literal arguments and exit code |
|
|
21
|
+
| Resource sizing | Effective CPU affinity and cgroup memory limit |
|
|
22
|
+
| Host capacity | Mixed-size budgets, stopped/frozen boxes, low RAM/disk and four saved slots; live create/stop/resume/destroy changes in CPU/memory allocations |
|
|
23
|
+
| Background jobs | Journal output, nonzero exit status, cancellation of child processes, inspection after cancellation or log rotation, and rejection of unknown job IDs |
|
|
24
|
+
| TTL/extend/resume | Host-enforced stop, manual `gc`, retained files, uninterrupted lifetime extension and 30-day resume |
|
|
25
|
+
| Usage | Real cgroup counters and explicitly shared-pool disk scope |
|
|
26
|
+
| File transfer | Binary content, paths containing spaces, stopped-workspace transfers, preservation of the destination after a failed download, and real controller write-error rejection |
|
|
27
|
+
| Docker | Real image build and container execution |
|
|
28
|
+
| Snapshot/restore/fork | File rollback, independent copy, retained network identity and deterministic concurrent-resume rejection under the real host lock |
|
|
29
|
+
| Backup/recovery | Stopped source, no overwrite, snapshots, content, permissions and fresh MAC |
|
|
30
|
+
| Private forwarding | Guest HTTP response through controller loopback tunnel |
|
|
31
|
+
| Desktop | WebSocket/RFB negotiation, framebuffer, pointer, keyboard, clipboard and reconnect |
|
|
32
|
+
| Network separation | Positive service control, negative IPv4/IPv6 peer, host and metadata probes |
|
|
33
|
+
| Development image | Real developer-user tool checks, immutable selection and credential-path archive rejection |
|
|
34
|
+
| Deployment/firewall | Repeat deployment removes stale rules without restarting Incus; failed filtering blocks normal and socket startup; boot timestamps prove filtering precedes Incus |
|
|
35
|
+
| Storage contract | Disposable oversized pool is rejected without automatic resizing |
|
|
36
|
+
| CLI options and errors | Help for all 28 commands; default location, TTL and desktop port; all six sizing profiles; global and per-location reports; invalid TTLs, sizes, required arguments, handles, paths, snapshot names, jobs and ports |
|
|
37
|
+
|
|
38
|
+
## Command and option audit (2026-10-06)
|
|
39
|
+
|
|
40
|
+
<details>
|
|
41
|
+
<summary>Coverage, regressions and remaining limits</summary>
|
|
42
|
+
|
|
43
|
+
The audit checked help for all 26 commands and expanded the live suites to cover defaults, invalid arguments, manual garbage collection, maximum lifetimes and unknown job IDs. Two ARM64 hosts passed extended lifecycle tests, all six sizing profiles and all 31 development-tool checks.
|
|
44
|
+
|
|
45
|
+
After the fixes, live lifecycle and same-host recovery passed again. Cross-host recovery passed with a 384,827,472-byte archive. Test boxes and archives were removed without rebooting or reconfiguring the existing hosts.
|
|
46
|
+
|
|
47
|
+
The audit found and fixed two CLI bugs:
|
|
48
|
+
|
|
49
|
+
- Unknown background jobs appeared to succeed. Job inspection now distinguishes unknown IDs, loaded jobs and canceled jobs with retained journal entries. Tests cover inspection after cancellation and journal rotation.
|
|
50
|
+
- SSH could report success after a controller write failed. Downloads and backups now copy the stream through Python so local write errors reach the caller. Real `/dev/full` tests verify both receiving paths. The same Incus/SSH producer falsely succeeded with the previous implementation and raised `ENOSPC` with the fix.
|
|
51
|
+
|
|
52
|
+
This covers implemented workflows and selected option combinations, not every possible workload or environment. A full-image export exceeded the local controller's free disk space and was interrupted. Full-sized archive validation runs on disposable CI hosts with sufficient scratch space.
|
|
53
|
+
|
|
54
|
+
The [final runtime validation](https://github.com/Microck/raft/actions/runs/37542355027) tests commit `ac618e64`. ARM64 and AMD64 both passed extended lifecycle tests with daemon restarts, capacity transitions and full development-image backup/recovery. [Packaging checks](https://github.com/Microck/raft/actions/runs/37542355021) passed on Python 3.11 and 3.14, and [documentation checks](https://github.com/Microck/raft/actions/runs/37542355020) passed.
|
|
55
|
+
|
|
56
|
+
</details>
|
|
57
|
+
|
|
58
|
+
## New workspace controls
|
|
59
|
+
|
|
60
|
+
`python3 deploy/verify-features.py --location lab` verifies recursive trees and unsafe-archive rejection, templates from a running source, snapshot deletion, CPU/RAM overrides, disposable timer deletion, and retention preview/apply. It uses only its own fixtures. Run the archive checks without `--location` to avoid allocating boxes.
|
|
61
|
+
|
|
62
|
+
For an older deployment whose services should stay unchanged, `--isolated-worker` stages the current worker under a private temporary path. This checks worker logic without installing it; automatic timer integration is verified on disposable CI hosts. Current deployments use the normal verification mode; the isolated mode rejects them before allocation.
|
|
63
|
+
|
|
64
|
+
## Workspace controls validation (2026-10-07)
|
|
65
|
+
|
|
66
|
+
<details>
|
|
67
|
+
<summary>Native feature tests and transfer regressions</summary>
|
|
68
|
+
|
|
69
|
+
At runtime commit `a7fef1f5`, ARM64 and AMD64 passed the new workspace-control suite in [native CI](https://github.com/Microck/raft/actions/runs/37603576786). It verifies installed-timer deletion, retention preview and exclusions, live-source snapshot templates, snapshot deletion, and effective CPU/RAM limits after resume and fork.
|
|
70
|
+
|
|
71
|
+
Directory tests cover binary files, permissions, relative symlinks, hardlinks, empty directories and existing destinations. Unix sockets and unsafe archive entries are rejected. A real Incus transfer truncated between complete archive entries fails without publishing a partial directory.
|
|
72
|
+
|
|
73
|
+
Both architectures passed extended lifecycle tests, full development-image recovery, startup measurements and clean-template inspection. Fresh provisioning, image import, firewall ordering and reboot passed on a disposable AMD64 KVM host.
|
|
74
|
+
|
|
75
|
+
The source-race fix also passed a real concurrent writer test that swaps files and directories for external symlinks. Accepted archives retain only the selected files. Two configured ARM64 hosts passed the final feature suite with a staged worker, without changing installed services. Local fixtures and staged files were removed.
|
|
76
|
+
|
|
77
|
+
</details>
|
|
78
|
+
|
|
79
|
+
## Running verification suites
|
|
80
|
+
|
|
81
|
+
Test commands require configured hosts and immutable image fingerprints. Suites destroy only the fixtures they create.
|
|
82
|
+
|
|
83
|
+
Allocation and archive inspection:
|
|
84
|
+
- `python3 deploy/verify-limits.py`: Checks allocation policies without a host. Add `--location lab` to verify live create, stop, resume, and destroy reporting.
|
|
85
|
+
- `python3 deploy/verify-image-tests.py`: Inspects archive structures, including symlinks, hardlinks, FIFOs, and credential detection.
|
|
86
|
+
|
|
87
|
+
Live host suites (expand the check you need):
|
|
88
|
+
|
|
89
|
+
<details>
|
|
90
|
+
<summary>Lifecycle</summary>
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
python3 deploy/verify-live.py --location lab --extended
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
</details>
|
|
97
|
+
|
|
98
|
+
<details>
|
|
99
|
+
<summary>Daemon restart on a dedicated test host</summary>
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
python3 deploy/verify-live.py --location lab --restart-incus
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
</details>
|
|
106
|
+
|
|
107
|
+
<details>
|
|
108
|
+
<summary>Cross-host recovery</summary>
|
|
109
|
+
|
|
110
|
+
```sh
|
|
111
|
+
python3 deploy/verify-controls.py --source lab --target second-host --directory /path/to/archive-storage
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
</details>
|
|
115
|
+
|
|
116
|
+
<details>
|
|
117
|
+
<summary>Same-host recovery</summary>
|
|
118
|
+
|
|
119
|
+
```sh
|
|
120
|
+
python3 deploy/verify-controls.py --source lab --target lab --directory /path/to/archive-storage
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
</details>
|
|
124
|
+
|
|
125
|
+
<details>
|
|
126
|
+
<summary>Full development-image recovery</summary>
|
|
127
|
+
|
|
128
|
+
```sh
|
|
129
|
+
python3 deploy/verify-controls.py --source lab --target second-host --directory /path/to/archive-storage --development-image
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
</details>
|
|
133
|
+
|
|
134
|
+
`verify-tools.py <qualified-box>` executes 31 tool checks as the unprivileged `developer` user inside a running workspace. It compiles and runs code across installed runtimes and package managers without external agent authentication.
|
|
135
|
+
|
|
136
|
+
## Extended lifecycle results (2026-10-05)
|
|
137
|
+
|
|
138
|
+
<details>
|
|
139
|
+
<summary>Test evidence and run details</summary>
|
|
140
|
+
|
|
141
|
+
The extended lifecycle suite and strengthened tool checks passed on two ARM64 Ubuntu hosts with Incus 6.0.6 on 2026-10-05.
|
|
142
|
+
|
|
143
|
+
Both hosts executed all six sizing combinations, all 31 developer tool checks, Docker builds, file transfers, stopped snapshots, forks, restore, jobs, and private HTTP and desktop tunnels.
|
|
144
|
+
|
|
145
|
+
Desktop testing validated keyboard input, exact clipboard synchronization, pointer coordinates, framebuffer updates, and secondary client connections. Headed Chromium testing passed with sandboxing enabled, confirming canvas rendering at 1280x720 over the noVNC interface.
|
|
146
|
+
|
|
147
|
+
**Admission and backup runs**
|
|
148
|
+
|
|
149
|
+
The four-saved-box admission test passed, including rejection of a fifth create, fork, or recovery attempt. Full development-image recovery succeeded with a 5,254,224,965-byte archive, verifying inventories, tool checks, permissions, fresh MACs, and snapshot rollback.
|
|
150
|
+
|
|
151
|
+
The execution wrapper reported exit 143 after the success message; independent native inventory and archive checks confirmed that all fixtures and temporary archives were removed.
|
|
152
|
+
|
|
153
|
+
Debian fixture backup and recovery passed across the following tests:
|
|
154
|
+
- Same-host recovery: 385,278,177-byte archive with snapshot rollback and distinct MAC/IP identities.
|
|
155
|
+
- Reverse cross-host recovery: 385,282,465-byte archive.
|
|
156
|
+
- Forward cross-host admission run: 385,272,379-byte archive (exit code 0).
|
|
157
|
+
|
|
158
|
+
All recovery fixtures were destroyed; existing operator hosts were not rebooted or reconfigured.
|
|
159
|
+
|
|
160
|
+
</details>
|
|
161
|
+
|
|
162
|
+
## Review-fix validation (2026-10-06)
|
|
163
|
+
|
|
164
|
+
<details>
|
|
165
|
+
<summary>Test evidence and run details</summary>
|
|
166
|
+
|
|
167
|
+
On 2026-10-06, the extended suite passed on two configured ARM64 hosts after redeploying review fixes. Both ran all 31 tool checks, six sizing profiles, and deterministic race rejection when a source container started before obtaining the host lock. Cross-host recovery passed with a 385,265,470-byte archive.
|
|
168
|
+
|
|
169
|
+
Both hosts had no remaining test boxes; existing hosts were not rebooted or reconfigured.
|
|
170
|
+
|
|
171
|
+
The image inspector passed 15 test cases, including non-root SSH keys, symlinks, hardlinks, and clean controls. Network testing verified initial and repeated firewall application while preserving unrelated chains.
|
|
172
|
+
|
|
173
|
+
The [review-fix native run](https://github.com/Microck/raft/actions/runs/37496577945) passed all native steps on ARM64 and AMD64: development-image builds, extended lifecycle with daemon restarts, capacity transitions, and clean-image inspection. Recovery archives were 3,844,136,311 bytes on ARM64 and 3,985,872,081 bytes on AMD64.
|
|
174
|
+
|
|
175
|
+
**Disposable KVM host tests**
|
|
176
|
+
|
|
177
|
+
Fresh provisioning on a disposable AMD64 KVM host confirmed:
|
|
178
|
+
- Repeat deployment removed injected rules while leaving Incus daemon start timestamps unchanged.
|
|
179
|
+
- Failed firewall installation blocked both normal and socket-activated Incus startup.
|
|
180
|
+
- Host reboot verified firewall rules became active before Incus started.
|
|
181
|
+
- A disposable pool resized to 61 GiB caused deployment to fail and preserved the existing size.
|
|
182
|
+
|
|
183
|
+
ARM64 host reboot and physical disk capacity remain outside this verification.
|
|
184
|
+
|
|
185
|
+
</details>
|
|
186
|
+
|
|
187
|
+
## Native image validation (2026-10-06)
|
|
188
|
+
|
|
189
|
+
<details>
|
|
190
|
+
<summary>Test evidence and run details</summary>
|
|
191
|
+
|
|
192
|
+
On 2026-10-06, the [native CI run](https://github.com/Microck/raft/actions/runs/37447415532) built ARM64 and AMD64 images on Ubuntu 24 and passed extended lifecycle tests on both. Workspaces executed all six sizing combinations, 31 tool checks, sandboxed Chromium, noVNC desktop sessions, and peer isolation checks. Timings are recorded in [Boot performance](./boot-performance.mdx).
|
|
193
|
+
|
|
194
|
+
In the [release-validation run](https://github.com/Microck/raft/actions/runs/37469540182), native image jobs passed full development-image recovery on both architectures. Package inventories matched and all 31 tool checks passed. Archives measured 3,844,135,523 bytes on ARM64 and 3,985,894,517 bytes on AMD64.
|
|
195
|
+
|
|
196
|
+
</details>
|
|
197
|
+
|
|
198
|
+
## Fresh-host and reboot validation
|
|
199
|
+
|
|
200
|
+
<details>
|
|
201
|
+
<summary>Test evidence and run details</summary>
|
|
202
|
+
|
|
203
|
+
The [release run](https://github.com/Microck/raft/actions/runs/37469540182) validated fresh-host setup on a disposable AMD64 KVM instance running Ubuntu 24. The test verified canonical deployment, repeat deployment, image import, and lifecycle execution.
|
|
204
|
+
|
|
205
|
+
Following a VM reboot, changed kernel boot IDs and active services were verified alongside retained files, snapshots, container states, Docker, and bridge isolation. The host test uses a sparse 100 GiB virtual disk and accessible KVM.
|
|
206
|
+
|
|
207
|
+
It preserves the production deployer's 80 GiB free-disk check but does not prove physical storage capacity. ARM64 host reboot, host loss, and cross-architecture recovery remain unverified. The VM, SSH keys, and controller configuration were disposable; existing operator hosts were not rebooted or reconfigured.
|
|
208
|
+
|
|
209
|
+
</details>
|
|
210
|
+
|
|
211
|
+
## Packaging and release checks
|
|
212
|
+
|
|
213
|
+
<details>
|
|
214
|
+
<summary>Test evidence and run details</summary>
|
|
215
|
+
|
|
216
|
+
Package builds run via `uv build`. Source and wheel archives are inspected to exclude version-control files and local caches. Clean wheel installation is verified outside the worktree alongside Ruff, syntax checks, and secret scans.
|
|
217
|
+
|
|
218
|
+
Packaging workflows passed on Python 3.11 and 3.14. Guidelines for visibility changes and repository hygiene are detailed in [Publishing](./publishing.md).
|
|
219
|
+
|
|
220
|
+
</details>
|
|
221
|
+
|
|
222
|
+
## Capacity command validation (2026-10-06)
|
|
223
|
+
|
|
224
|
+
<details>
|
|
225
|
+
<summary>Test evidence and run details</summary>
|
|
226
|
+
|
|
227
|
+
On 2026-10-06, `raft limits` passed read-only text and JSON inspection and live lifecycle tests on two ARM64 Ubuntu hosts. Tests verified allocation adjustments during create, stop, resume, and destroy cycles.
|
|
228
|
+
|
|
229
|
+
Allocation fixtures validated mixed sizing budgets, frozen containers, low RAM and disk conditions, host reserves, and admission limits. The four-stopped-box admission test verified that creation, forking, and recovery reject a fifth container when slots are exhausted. These are conservative allocation checks, not workload saturation benchmarks.
|
|
230
|
+
|
|
231
|
+
</details>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Run inside a fresh native ARM64 or AMD64 Debian 13 Incus image, without host secrets.
|
|
3
|
+
set -eu
|
|
4
|
+
case "$(dpkg --print-architecture)" in
|
|
5
|
+
arm64) node_arch=arm64 ;;
|
|
6
|
+
amd64) node_arch=x64 ;;
|
|
7
|
+
*) echo 'Raft images support ARM64 and AMD64' >&2; exit 1 ;;
|
|
8
|
+
esac
|
|
9
|
+
export DEBIAN_FRONTEND=noninteractive
|
|
10
|
+
apt-get update -qq
|
|
11
|
+
apt-get install -y --no-install-recommends apparmor ca-certificates curl git openssh-server rsync jq ripgrep file less sudo locales python3 python3-pip python3-venv pipx build-essential clang cmake ninja-build golang rustc cargo default-jdk maven gradle kotlin scala ruby ruby-bundler php-cli composer erlang-base elixir r-base docker.io docker-cli docker-buildx chromium chromium-sandbox ffmpeg unzip xz-utils tar x11vnc xvfb x11-utils novnc websockify openbox dbus-x11
|
|
12
|
+
# Ubuntu hosts restrict unprofiled user namespaces. Load a guest-local rule
|
|
13
|
+
# for Chromium's exact executable so its sandbox can create its namespaces.
|
|
14
|
+
# Incus's outer confinement and the host-wide restriction remain in force.
|
|
15
|
+
cat > /etc/apparmor.d/raft-chromium <<'PROFILE'
|
|
16
|
+
abi <abi/4.0>,
|
|
17
|
+
include <tunables/global>
|
|
18
|
+
profile raft-chromium /usr/lib/chromium/chromium flags=(unconfined) {
|
|
19
|
+
userns,
|
|
20
|
+
}
|
|
21
|
+
PROFILE
|
|
22
|
+
systemctl enable apparmor
|
|
23
|
+
systemctl restart apparmor
|
|
24
|
+
mkdir -p /workspace /opt/raft
|
|
25
|
+
node_archive="node-v24.21.0-linux-${node_arch}.tar.xz"
|
|
26
|
+
curl -fsSL -A 'OpenAI File Downloader, XaiImageApiFetch/1.0' "https://nodejs.org/dist/v24.21.0/${node_archive}" -o /tmp/raft-node.tar.xz
|
|
27
|
+
curl -fsSL -A 'OpenAI File Downloader, XaiImageApiFetch/1.0' https://nodejs.org/dist/v24.21.0/SHASUMS256.txt -o /tmp/raft-node.sha256
|
|
28
|
+
cd /tmp
|
|
29
|
+
awk -v archive="$node_archive" '$2 == archive {print $1 " raft-node.tar.xz"}' raft-node.sha256 | sha256sum -c -
|
|
30
|
+
tar -xJf /tmp/raft-node.tar.xz -C /usr/local --strip-components=1
|
|
31
|
+
PIPX_HOME=/opt/raft/pipx PIPX_BIN_DIR=/usr/local/bin pipx install uv==0.12.23
|
|
32
|
+
npm install -g pnpm@12.9.1 bun@1.4.2 deno@2.9.6
|
|
33
|
+
curl -fsSL -A 'OpenAI File Downloader, XaiImageApiFetch/1.0' https://dot.net/v1/dotnet-install.sh -o /tmp/raft-dotnet-install.sh
|
|
34
|
+
bash /tmp/raft-dotnet-install.sh --version 10.0.401 --install-dir /usr/local/share/dotnet
|
|
35
|
+
ln -s /usr/local/share/dotnet/dotnet /usr/local/bin/dotnet
|
|
36
|
+
useradd -m -s /bin/bash developer
|
|
37
|
+
printf 'developer ALL=(ALL) NOPASSWD:ALL\n' > /etc/sudoers.d/raft-developer
|
|
38
|
+
chmod 440 /etc/sudoers.d/raft-developer
|
|
39
|
+
mkdir -p /etc/ssh/sshd_config.d /etc/systemd/system/ssh.service.d
|
|
40
|
+
printf 'PasswordAuthentication no\nKbdInteractiveAuthentication no\nPermitRootLogin prohibit-password\nHostKey /etc/ssh/ssh_host_ed25519_key\n' > /etc/ssh/sshd_config.d/00-raft.conf
|
|
41
|
+
# Generate keys before sshd validates them; published templates contain no host keys.
|
|
42
|
+
# Only the advertised Ed25519 key is needed; generating unused RSA keys slows first boot.
|
|
43
|
+
cat > /etc/systemd/system/ssh.service.d/raft-keys.conf <<'UNIT'
|
|
44
|
+
[Service]
|
|
45
|
+
ExecStartPre=
|
|
46
|
+
ExecStartPre=/bin/sh -ec 'test -f /etc/ssh/ssh_host_ed25519_key || ssh-keygen -q -t ed25519 -N "" -f /etc/ssh/ssh_host_ed25519_key'
|
|
47
|
+
ExecStartPre=/usr/sbin/sshd -t
|
|
48
|
+
UNIT
|
|
49
|
+
systemctl enable docker ssh
|
|
50
|
+
systemctl start docker
|
|
51
|
+
docker info --format '{{.ServerVersion}}'
|
|
52
|
+
dpkg-query -W > /opt/raft/packages.tsv
|
|
53
|
+
npm list -g --depth=0 --json > /opt/raft/npm-packages.json
|
|
54
|
+
apt-get clean
|
|
55
|
+
rm -rf /var/lib/apt/lists/* /tmp/raft-node* /tmp/raft-dotnet-install.sh /root/.npm/_cacache /root/.npm/_logs
|
|
56
|
+
rm -f /etc/ssh/ssh_host_*
|
|
57
|
+
truncate -s 0 /etc/machine-id
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -eu
|
|
3
|
+
export DISPLAY=:99
|
|
4
|
+
Xvfb :99 -screen 0 1280x720x24 -nolisten tcp &
|
|
5
|
+
xvfb_pid=$!
|
|
6
|
+
trap 'kill "$xvfb_pid" 2>/dev/null || true' EXIT
|
|
7
|
+
# Start clients as soon as X accepts requests, rather than sleeping on every launch.
|
|
8
|
+
attempt=0
|
|
9
|
+
until xdpyinfo >/dev/null 2>&1; do
|
|
10
|
+
attempt=$((attempt + 1))
|
|
11
|
+
if [ "$attempt" -ge 100 ]; then
|
|
12
|
+
echo 'Xvfb did not become ready within five seconds' >&2
|
|
13
|
+
exit 1
|
|
14
|
+
fi
|
|
15
|
+
sleep 0.05
|
|
16
|
+
done
|
|
17
|
+
runuser -u developer -- env DISPLAY=:99 openbox &
|
|
18
|
+
# This dedicated Xvfb display has no login manager to wait for.
|
|
19
|
+
X11VNC_AVOID_WINDOWS=never x11vnc -display :99 -localhost -nopw -forever -shared -rfbport 5900 &
|
|
20
|
+
websockify --web=/usr/share/novnc 0.0.0.0:6080 127.0.0.1:5900 &
|
|
21
|
+
wait
|
package/package.json
CHANGED
|
@@ -1,6 +1,48 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@microck/raft",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Self-hosted Linux workspaces powered by Incus, an open-source alternative to boat.dev",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/Microck/raft.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://raft.micr.dev",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/Microck/raft/issues"
|
|
13
|
+
},
|
|
14
|
+
"bin": {
|
|
15
|
+
"raft": "raft.py"
|
|
16
|
+
},
|
|
17
|
+
"os": [
|
|
18
|
+
"linux"
|
|
19
|
+
],
|
|
20
|
+
"files": [
|
|
21
|
+
"raft.py",
|
|
22
|
+
"raft_files.py",
|
|
23
|
+
"deploy/*.py",
|
|
24
|
+
"deploy/*.sh",
|
|
25
|
+
"deploy/*.conf",
|
|
26
|
+
"deploy/*.service",
|
|
27
|
+
"deploy/*.timer",
|
|
28
|
+
"docs/**/*.md",
|
|
29
|
+
"docs/**/*.mdx",
|
|
30
|
+
"docs/**/*.json",
|
|
31
|
+
"images/incus/*.sh",
|
|
32
|
+
"images/incus/*.service",
|
|
33
|
+
"skills/raft-cli/SKILL.md",
|
|
34
|
+
".github/assets/raft-logo.png"
|
|
35
|
+
],
|
|
36
|
+
"keywords": [
|
|
37
|
+
"raft",
|
|
38
|
+
"sandbox",
|
|
39
|
+
"incus",
|
|
40
|
+
"self-hosted",
|
|
41
|
+
"linux",
|
|
42
|
+
"cli"
|
|
43
|
+
],
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public",
|
|
46
|
+
"provenance": true
|
|
47
|
+
}
|
|
48
|
+
}
|