S1: Rust workspace, static builds and gates #11

Closed
opened 2026-10-05 15:32:07 +00:00 by kayg · 14 comments
Owner

The Rust side of the monorepo and its gates. Decisions 7, 20 and 40.

  • Cargo workspace, rust-toolchain.toml (stable, with musl targets for x86_64 and aarch64)
  • Crates (empty, documented): infraternal (the binary: server and agent modes), protocol, plugin-api, server, agent, shim, plugins/ssh
  • Lints: #![forbid(unsafe_code)] everywhere except shim, clippy pedantic as errors, no unwrap outside tests; cargo-deny for licenses and advisories
  • Static musl release builds for x86_64 and aarch64; a check that proves the binary is static
  • scripts/verify fast runs the Rust gates (fmt, clippy, test, deny, static build)
  • .forgejo/workflows/ci.yml runs scripts/verify fast on the infraternal-dev runner
The Rust side of the monorepo and its gates. Decisions 7, 20 and 40. - [ ] Cargo workspace, `rust-toolchain.toml` (stable, with musl targets for x86_64 and aarch64) - [ ] Crates (empty, documented): `infraternal` (the binary: `server` and `agent` modes), `protocol`, `plugin-api`, `server`, `agent`, `shim`, `plugins/ssh` - [ ] Lints: `#![forbid(unsafe_code)]` everywhere except `shim`, clippy pedantic as errors, no `unwrap` outside tests; `cargo-deny` for licenses and advisories - [ ] Static musl release builds for x86_64 and aarch64; a check that proves the binary is static - [ ] `scripts/verify fast` runs the Rust gates (fmt, clippy, test, deny, static build) - [ ] `.forgejo/workflows/ci.yml` runs `scripts/verify fast` on the `infraternal-dev` runner
Author
Owner

Starting implementation on branch s1-workspace, based on 4560d9dd64. I have read CLAUDE.md, DECISIONS.md, and docs/ARCHITECTURE.md; this slice follows decisions 7, 20, 34, and 40.

Starting implementation on branch s1-workspace, based on 4560d9dd64cec2da88254eb5014aa180728f1b5f. I have read CLAUDE.md, DECISIONS.md, and docs/ARCHITECTURE.md; this slice follows decisions 7, 20, 34, and 40.
Author
Owner

Finding: this worktree has no Cargo workspace, Rust toolchain, or verify script yet; rustup reports 'no installed toolchains' and no default toolchain. I will pin and install Rust 1.99.0 and add the Rust-only checks under scripts/verify.d/rust.sh.

Finding: this worktree has no Cargo workspace, Rust toolchain, or verify script yet; rustup reports 'no installed toolchains' and no default toolchain. I will pin and install Rust 1.99.0 and add the Rust-only checks under scripts/verify.d/rust.sh.
Author
Owner

Finding: this environment cannot reach its Docker socket ('permission denied' for /var/run/docker.sock), and Forgejo reports 0 existing action tasks for kayg/infraternal, so there is no runner cache history to verify. I will validate the Rust gates directly in this worktree and omit cache configuration until the runner's cache support is demonstrated.

Finding: this environment cannot reach its Docker socket ('permission denied' for /var/run/docker.sock), and Forgejo reports 0 existing action tasks for kayg/infraternal, so there is no runner cache history to verify. I will validate the Rust gates directly in this worktree and omit cache configuration until the runner's cache support is demonstrated.
Author
Owner

Finding: Cargo 1.99 rejects a crate that inherits and locally changes ('cannot override workspace.lints in lints'). The shim will declare the same shared Clippy lints locally with unsafe_code=deny; the other six crates inherit the workspace forbid policy.

Finding: Cargo 1.99 rejects a crate that inherits and locally changes ('cannot override workspace.lints in lints'). The shim will declare the same shared Clippy lints locally with unsafe_code=deny; the other six crates inherit the workspace forbid policy.
Author
Owner

Finding: Cargo 1.99 rejects a crate that inherits [lints] workspace = true and locally changes unsafe_code (error: cannot override workspace.lints in lints). The shim will declare the same shared Clippy lints locally with unsafe_code=deny; the other six crates inherit the workspace forbid policy.

Finding: Cargo 1.99 rejects a crate that inherits `[lints] workspace = true` and locally changes `unsafe_code` (error: cannot override workspace.lints in lints). The shim will declare the same shared Clippy lints locally with unsafe_code=deny; the other six crates inherit the workspace forbid policy.
Author
Owner

Finding: the first workspace build reaches quote and proc-macro2 but fails before linking Rust code because the environment has no cc linker (linker cc not found). CI will install its host C build tools; I will provision the same build prerequisite locally and rerun the gate.

Finding: the first workspace build reaches `quote` and `proc-macro2` but fails before linking Rust code because the environment has no `cc` linker (`linker cc not found`). CI will install its host C build tools; I will provision the same build prerequisite locally and rerun the gate.
Author
Owner

Finding: the aarch64 musl build reaches the configured Rust-bundled LLD and CRT, but the wrapper adds -flavor gnu, which Rust 1.99 LLD rejects as an unknown argument. The command line already contains direct GNU linker options, so I am removing that redundant flag and will repeat both static builds.

Finding: the aarch64 musl build reaches the configured Rust-bundled LLD and CRT, but the wrapper adds `-flavor gnu`, which Rust 1.99 LLD rejects as an unknown argument. The command line already contains direct GNU linker options, so I am removing that redundant flag and will repeat both static builds.
Author
Owner

Finding: the first complete fast gate passed, including static PIE x86_64 (658,808 bytes) and static aarch64 (564,752 bytes), but cargo-deny warned that five allowed licenses were not present in the graph. I am narrowing deny.toml to the licenses the locked graph actually uses so the gate is clean.

Finding: the first complete fast gate passed, including static PIE x86_64 (658,808 bytes) and static aarch64 (564,752 bytes), but cargo-deny warned that five allowed licenses were not present in the graph. I am narrowing deny.toml to the licenses the locked graph actually uses so the gate is clean.
Author
Owner

Update on caching: the repository has no prior Actions tasks, so runner cache availability remains unverified. I will add the Forgejo cache action as best-effort with continue-on-error, keyed by OS, architecture, Cargo.lock, and rust-toolchain.toml; an unsupported runner will still run the gates normally.

Update on caching: the repository has no prior Actions tasks, so runner cache availability remains unverified. I will add the Forgejo cache action as best-effort with continue-on-error, keyed by OS, architecture, Cargo.lock, and rust-toolchain.toml; an unsupported runner will still run the gates normally.
Author
Owner

Review finding: the CLI currently prints server: not implemented or agent: not implemented, while the issue requires the exact message not implemented. I am changing both branches and the static smoke check to assert the requested text.

Review finding: the CLI currently prints `server: not implemented` or `agent: not implemented`, while the issue requires the exact message `not implemented`. I am changing both branches and the static smoke check to assert the requested text.
Author
Owner

Finding: the final gate reported clippy::match_same_arms (exit 101) because both required subcommands now print the same exact text and return code. The compiler-provided fix is to merge the patterns; the static smoke gate will continue invoking both commands separately.

Finding: the final gate reported clippy::match_same_arms (exit 101) because both required subcommands now print the same exact text and return code. The compiler-provided fix is to merge the patterns; the static smoke gate will continue invoking both commands separately.
Author
Owner

Finished on branch s1-workspace at head dd2338ebeff1364c7f9d82ed534941bd4f30b4fa. The committed fast gate passed locally; a temporary Nix shell supplied the missing host C compiler. Cache is configured as best-effort, but this repository has no previous Actions tasks, so runner cache support is still unverified. Binary sizes: x86_64-unknown-linux-musl 657,976 bytes; aarch64-unknown-linux-musl 563,728 bytes. file reports static-pie/static linking for both and readelf confirms PT_INTERP is absent.

scripts/verify fast output verbatim:

==> fmt

==> clippy
Checking infraternal v0.1.0 (/home/kayg/Developer/infraternal/.worktrees/s1-workspace/crates/infraternal)
Finished dev profile [unoptimized + debuginfo] target(s) in 0.10s

==> test
Compiling infraternal v0.1.0 (/home/kayg/Developer/infraternal/.worktrees/s1-workspace/crates/infraternal)
Finished test profile [unoptimized + debuginfo] target(s) in 0.14s
Running unittests src/main.rs (target/debug/deps/infraternal-239f4951fa340219)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

 Running unittests src/lib.rs (target/debug/deps/infraternal_agent-eadaa10b8c42bfd9)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

 Running unittests src/lib.rs (target/debug/deps/infraternal_plugin_api-4480fd7032f11ca2)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

 Running unittests src/lib.rs (target/debug/deps/infraternal_plugin_ssh-22a9a893799c7f17)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

 Running unittests src/lib.rs (target/debug/deps/infraternal_protocol-342516d5dbf00714)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

 Running unittests src/lib.rs (target/debug/deps/infraternal_server-3a7dcd467cd5ddf2)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

 Running unittests src/lib.rs (target/debug/deps/infraternal_shim-2036f3f8f778c3eb)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

Doc-tests infraternal_agent

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

Doc-tests infraternal_plugin_api

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

Doc-tests infraternal_plugin_ssh

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

Doc-tests infraternal_protocol

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

Doc-tests infraternal_server

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

Doc-tests infraternal_shim

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

==> cargo-deny
advisories ok, bans ok, licenses ok, sources ok

==> static builds
Compiling infraternal v0.1.0 (/home/kayg/Developer/infraternal/.worktrees/s1-workspace/crates/infraternal)
Finished release profile [optimized] target(s) in 4.25s
target/x86_64-unknown-linux-musl/release/infraternal: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), static-pie linked, stripped
PT_INTERP: absent; size: 657976 bytes
Compiling infraternal v0.1.0 (/home/kayg/Developer/infraternal/.worktrees/s1-workspace/crates/infraternal)
Finished release profile [optimized] target(s) in 4.43s
target/aarch64-unknown-linux-musl/release/infraternal: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, stripped
PT_INTERP: absent; size: 563728 bytes
server subcommand: exit 2, not implemented
agent subcommand: exit 2, not implemented

+---------------------------+--------------+
| Rust gate | Result |
+---------------------------+--------------+
| fmt | PASS |
| clippy | PASS |
| test | PASS |
| cargo-deny | PASS |
| static builds | PASS |
+---------------------------+--------------+

Finished on branch s1-workspace at head dd2338ebeff1364c7f9d82ed534941bd4f30b4fa. The committed fast gate passed locally; a temporary Nix shell supplied the missing host C compiler. Cache is configured as best-effort, but this repository has no previous Actions tasks, so runner cache support is still unverified. Binary sizes: x86_64-unknown-linux-musl 657,976 bytes; aarch64-unknown-linux-musl 563,728 bytes. `file` reports static-pie/static linking for both and readelf confirms PT_INTERP is absent. `scripts/verify fast` output verbatim: ==> fmt ==> clippy Checking infraternal v0.1.0 (/home/kayg/Developer/infraternal/.worktrees/s1-workspace/crates/infraternal) Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.10s ==> test Compiling infraternal v0.1.0 (/home/kayg/Developer/infraternal/.worktrees/s1-workspace/crates/infraternal) Finished `test` profile [unoptimized + debuginfo] target(s) in 0.14s Running unittests src/main.rs (target/debug/deps/infraternal-239f4951fa340219) running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Running unittests src/lib.rs (target/debug/deps/infraternal_agent-eadaa10b8c42bfd9) running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Running unittests src/lib.rs (target/debug/deps/infraternal_plugin_api-4480fd7032f11ca2) running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Running unittests src/lib.rs (target/debug/deps/infraternal_plugin_ssh-22a9a893799c7f17) running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Running unittests src/lib.rs (target/debug/deps/infraternal_protocol-342516d5dbf00714) running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Running unittests src/lib.rs (target/debug/deps/infraternal_server-3a7dcd467cd5ddf2) running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Running unittests src/lib.rs (target/debug/deps/infraternal_shim-2036f3f8f778c3eb) running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Doc-tests infraternal_agent running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Doc-tests infraternal_plugin_api running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Doc-tests infraternal_plugin_ssh running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Doc-tests infraternal_protocol running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Doc-tests infraternal_server running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Doc-tests infraternal_shim running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ==> cargo-deny advisories ok, bans ok, licenses ok, sources ok ==> static builds Compiling infraternal v0.1.0 (/home/kayg/Developer/infraternal/.worktrees/s1-workspace/crates/infraternal) Finished `release` profile [optimized] target(s) in 4.25s target/x86_64-unknown-linux-musl/release/infraternal: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), static-pie linked, stripped PT_INTERP: absent; size: 657976 bytes Compiling infraternal v0.1.0 (/home/kayg/Developer/infraternal/.worktrees/s1-workspace/crates/infraternal) Finished `release` profile [optimized] target(s) in 4.43s target/aarch64-unknown-linux-musl/release/infraternal: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, stripped PT_INTERP: absent; size: 563728 bytes server subcommand: exit 2, not implemented agent subcommand: exit 2, not implemented +---------------------------+--------------+ | Rust gate | Result | +---------------------------+--------------+ | fmt | PASS | | clippy | PASS | | test | PASS | | cargo-deny | PASS | | static builds | PASS | +---------------------------+--------------+
Author
Owner

Orchestrator review of the job (it delivered one commit, dd2338e):

  • The commit was split into 5 atomic commits (owner rule): workspace and crates → rust-lld static linking → cargo-deny → scripts/verify → CI. Head 39630d6.
  • Changed panic = "abort" to unwind. With abort, one panicking session task kills the whole server and every connection. With unwind, tokio isolates the task. Binary: 706 KB with unwind, 658 KB with abort (x86_64).
  • The gate needs readelf and file on PATH. The CI image installs binutils and file. On a local machine they are a prerequisite.
  • scripts/verify fast passes again (fmt, clippy, test, deny, static builds for x86_64 and aarch64). The branch is pushed, and Forgejo CI runs on it.
Orchestrator review of the job (it delivered one commit, `dd2338e`): - The commit was split into 5 atomic commits (owner rule): workspace and crates → rust-lld static linking → cargo-deny → scripts/verify → CI. Head `39630d6`. - Changed `panic = "abort"` to `unwind`. With abort, one panicking session task kills the whole server and every connection. With unwind, tokio isolates the task. Binary: 706 KB with unwind, 658 KB with abort (x86_64). - The gate needs `readelf` and `file` on PATH. The CI image installs binutils and file. On a local machine they are a prerequisite. - `scripts/verify fast` passes again (fmt, clippy, test, deny, static builds for x86_64 and aarch64). The branch is pushed, and Forgejo CI runs on it.
Author
Owner

Closed by the orchestrator during the 2026-10-28 handover (#254), on the owner's request to close finished issues. Evidence: Workspace/gates merged as 39630d6 (in dev and prod) after orchestrator split into atomic commits; gate PASS in the issue. Reopen if anything is still missing.

Closed by the orchestrator during the 2026-10-28 handover (#254), on the owner's request to close finished issues. Evidence: Workspace/gates merged as 39630d6 (in dev and prod) after orchestrator split into atomic commits; gate PASS in the issue. Reopen if anything is still missing.
kayg closed this issue 2026-10-28 17:52:06 +00:00
Sign in to join this conversation.
No labels
launch-qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/infraternal#11
No description provided.