From 949237fa6af708d37e09d1707fde311eab860f6a Mon Sep 17 00:00:00 2001 From: kerthcet Date: Sat, 1 Aug 2026 08:31:27 +0100 Subject: [PATCH 1/2] release v0.0.1 Signed-off-by: kerthcet --- .github/workflows/release.yaml | 101 +++++++++++++++ Cargo.lock | 222 +++++++++++++++++---------------- README.md | 15 ++- hack/scripts/install.sh | 58 ++++++--- pyproject.toml | 2 +- sandd/Cargo.toml | 6 +- 6 files changed, 278 insertions(+), 126 deletions(-) create mode 100644 .github/workflows/release.yaml diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..a11bad6 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,101 @@ +name: Release + +on: + push: + tags: + - 'v*' + +env: + CARGO_TERM_COLOR: always + +permissions: + contents: write + +jobs: + build: + name: Build ${{ matrix.asset }} + runs-on: ${{ matrix.runner }} + strategy: + fail-fast: false + matrix: + include: + # Linux builds target musl and link statically, so one binary per arch + # runs on any distro regardless of glibc version. + - runner: ubuntu-22.04 + target: x86_64-unknown-linux-musl + asset: sandd-linux-amd64 + - runner: ubuntu-22.04-arm + target: aarch64-unknown-linux-musl + asset: sandd-linux-arm64 + - runner: macos-13 + target: x86_64-apple-darwin + asset: sandd-darwin-amd64 + - runner: macos-14 + target: aarch64-apple-darwin + asset: sandd-darwin-arm64 + steps: + - uses: actions/checkout@v4 + + - name: Install Rust toolchain + uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: stable + target: ${{ matrix.target }} + + - name: Install musl tools + if: endsWith(matrix.target, '-musl') + run: sudo apt-get update && sudo apt-get install -y musl-tools + + - name: Build daemon + run: cargo build --package sandd --release --locked --target ${{ matrix.target }} + + - name: Rename binary + run: mv target/${{ matrix.target }}/release/sandd ${{ matrix.asset }} + + - name: Verify static linking + if: endsWith(matrix.target, '-musl') + run: | + # rustc emits a static-PIE for musl targets, which `file` reports as + # "static-pie linked" rather than "statically linked" -- accept either. + file ${{ matrix.asset }} + if ! file ${{ matrix.asset }} | grep -qE "static-pie linked|statically linked"; then + echo "::error::Expected a statically linked musl binary." + exit 1 + fi + + - name: Verify binary runs + run: ./${{ matrix.asset }} --help + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.asset }} + path: ${{ matrix.asset }} + if-no-files-found: error + + release: + name: Publish release + needs: build + runs-on: ubuntu-latest + steps: + - name: Download artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + merge-multiple: true + + - name: Generate checksums + run: | + cd artifacts + sha256sum sandd-* > sandd-checksums.txt + cat sandd-checksums.txt + + - name: Create release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release create "$GITHUB_REF_NAME" \ + --repo "$GITHUB_REPOSITORY" \ + --title "$GITHUB_REF_NAME" \ + --generate-notes \ + artifacts/* diff --git a/Cargo.lock b/Cargo.lock index 6f68d5e..98dcf1c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -53,7 +53,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -64,7 +64,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -549,7 +549,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -597,21 +597,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.2" @@ -948,7 +933,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi", "libc", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -1120,7 +1105,7 @@ checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" dependencies = [ "libc", "wasi", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -1167,23 +1152,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "native-tls" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "net2" version = "0.2.39" @@ -1224,7 +1192,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -1264,49 +1232,12 @@ version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" -[[package]] -name = "openssl" -version = "0.10.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a45fa2aa886c42762255da344f0a0d313e254066c46aad76f300c3d3da62d967" -dependencies = [ - "bitflags 2.11.1", - "cfg-if 1.0.4", - "foreign-types", - "libc", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "openssl-probe" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" -[[package]] -name = "openssl-sys" -version = "0.9.116" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28a22dc7140cda5f096e5e7724a6962ca81a7f8bfd2979f9b18c11af56318c4" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "parking_lot" version = "0.9.0" @@ -1374,12 +1305,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "pkg-config" -version = "0.3.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" - [[package]] name = "plotters" version = "0.3.7" @@ -1646,6 +1571,20 @@ version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if 1.0.4", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + [[package]] name = "rustc_version" version = "0.2.3" @@ -1665,7 +1604,52 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c54fcab019b409d04215d3a17cb438fd7fbf192ee61461f20f4fe18704bc138" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pki-types" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", ] [[package]] @@ -1716,7 +1700,7 @@ dependencies = [ [[package]] name = "sandd" -version = "0.0.0" +version = "0.0.1" dependencies = [ "anyhow", "base64", @@ -1756,7 +1740,7 @@ version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" dependencies = [ - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -1997,7 +1981,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -2006,6 +1990,12 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" version = "2.0.117" @@ -2053,7 +2043,7 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -2118,7 +2108,7 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -2153,16 +2143,6 @@ dependencies = [ "syn", ] -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - [[package]] name = "tokio-process" version = "0.2.5" @@ -2201,6 +2181,16 @@ dependencies = [ "tokio-sync", ] +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + [[package]] name = "tokio-signal" version = "0.2.9" @@ -2236,9 +2226,11 @@ checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" dependencies = [ "futures-util", "log", - "native-tls", + "rustls", + "rustls-native-certs", + "rustls-pki-types", "tokio", - "tokio-native-tls", + "tokio-rustls", "tungstenite", ] @@ -2385,8 +2377,9 @@ dependencies = [ "http", "httparse", "log", - "native-tls", "rand", + "rustls", + "rustls-pki-types", "sha1", "thiserror", "utf-8", @@ -2416,6 +2409,12 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "utf-8" version = "0.7.6" @@ -2446,12 +2445,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "version_check" version = "0.9.5" @@ -2615,7 +2608,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -2683,6 +2676,15 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.61.2" @@ -2889,6 +2891,12 @@ dependencies = [ "syn", ] +[[package]] +name = "zeroize" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" + [[package]] name = "zmij" version = "1.0.21" diff --git a/README.md b/README.md index 02cc6e2..b3b8076 100644 --- a/README.md +++ b/README.md @@ -80,10 +80,16 @@ make install ```bash # Direct mode (no tunnel) -curl -fsSL https://get.sandd.dev/install.sh | sudo bash +curl -fsSL https://raw.githubusercontent.com/InftyAI/SandD/main/hack/scripts/install.sh | sudo bash # Tunnel mode (with Tailscale) -curl -fsSL https://get.sandd.dev/install.sh | sudo bash -s -- --tunnel +curl -fsSL https://raw.githubusercontent.com/InftyAI/SandD/main/hack/scripts/install.sh | sudo bash -s -- --tunnel +``` + +This installs the latest release. To pin a specific version: + +```bash +curl -fsSL https://raw.githubusercontent.com/InftyAI/SandD/main/hack/scripts/install.sh | sudo bash -s -- --version v0.1.0 ``` #### Alternative Methods @@ -101,6 +107,11 @@ make daemon-release # Binary at: ./target/release/sandd ``` +**Build from the main branch:** +```bash +cargo install --git https://github.com/InftyAI/SandD sandd +``` + ## Quick Start ### Direct Mode (Development) diff --git a/hack/scripts/install.sh b/hack/scripts/install.sh index 1f8c485..98a3257 100755 --- a/hack/scripts/install.sh +++ b/hack/scripts/install.sh @@ -78,12 +78,16 @@ check_root() { } detect_os() { - if [[ -f /etc/os-release ]]; then + # OS is the distro id (used to pick a package manager); PLATFORM is the + # coarse kernel name used in release asset names. + if [[ "$(uname)" == "Darwin" ]]; then + OS="macos" + PLATFORM="darwin" + elif [[ -f /etc/os-release ]]; then . /etc/os-release OS=$ID OS_VERSION=$VERSION_ID - elif [[ "$(uname)" == "Darwin" ]]; then - OS="macos" + PLATFORM="linux" else log_error "Unsupported operating system" exit 1 @@ -103,7 +107,7 @@ detect_os() { ;; esac - log_info "Detected: $OS ($ARCH)" + log_info "Detected: $OS ($PLATFORM/$ARCH)" } install_dependencies() { @@ -132,21 +136,47 @@ install_dependencies() { install_sandd() { log_info "Installing SandD daemon..." - # Check if Rust/Cargo is installed - if command -v cargo &> /dev/null; then - log_info "Installing via cargo..." - cargo install sandd + ASSET="sandd-${PLATFORM}-${ARCH}" + + # "latest" resolves via GitHub's redirect so the script never needs to know + # the current tag; an explicit version addresses the tag directly. + if [[ "$SANDD_VERSION" == "latest" ]]; then + DOWNLOAD_URL="https://github.com/InftyAI/SandD/releases/latest/download/${ASSET}" else - # Download binary - log_info "Downloading binary..." - DOWNLOAD_URL="https://github.com/InftyAI/SandD/releases/download/${SANDD_VERSION}/sandd-${OS}-${ARCH}" + DOWNLOAD_URL="https://github.com/InftyAI/SandD/releases/download/${SANDD_VERSION}/${ASSET}" + fi - curl -fsSL "$DOWNLOAD_URL" -o /tmp/sandd - chmod +x /tmp/sandd - mv /tmp/sandd "$INSTALL_DIR/sandd" + log_info "Downloading $ASSET ($SANDD_VERSION)..." + TMP_BIN=$(mktemp) + if curl -fsSL "$DOWNLOAD_URL" -o "$TMP_BIN"; then + # 755 explicitly: mktemp creates 0600, so `chmod +x` would leave 0711. + chmod 755 "$TMP_BIN" + mv "$TMP_BIN" "$INSTALL_DIR/sandd" log_info "Installed to $INSTALL_DIR/sandd" + return + fi + + rm -f "$TMP_BIN" + log_warn "No prebuilt binary available at $DOWNLOAD_URL" + + if ! command -v cargo &> /dev/null; then + log_error "Cannot install sandd: no prebuilt binary for ${PLATFORM}/${ARCH} and cargo is not available." + log_error "Install Rust from https://rustup.rs and re-run, or build from source:" + log_error " git clone https://github.com/InftyAI/SandD && cd SandD && make daemon-release" + exit 1 + fi + + # --root keeps the binary out of root's ~/.cargo/bin, which is not on PATH + # for the sudo'd shell this script runs in. + log_info "Falling back to building from crates.io via cargo..." + if [[ "$SANDD_VERSION" == "latest" ]]; then + cargo install sandd --root "$(dirname "$INSTALL_DIR")" + else + cargo install sandd --version "${SANDD_VERSION#v}" --root "$(dirname "$INSTALL_DIR")" fi + + log_info "Installed to $INSTALL_DIR/sandd" } install_tailscale() { diff --git a/pyproject.toml b/pyproject.toml index 3c3c772..13cc981 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "maturin" [project] name = "sandd" -version = "0.0.0" +version = "0.0.1" description = "A lightweight sandbox daemon for secure agent execution in isolated environments." readme = {file = "README.md", content-type = "text/markdown"} requires-python = ">=3.8" diff --git a/sandd/Cargo.toml b/sandd/Cargo.toml index cbac446..697225e 100644 --- a/sandd/Cargo.toml +++ b/sandd/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sandd" -version = "0.0.0" +version = "0.0.1" edition = "2021" license = "MIT" description = "A lightweight sandbox daemon for secure agent execution in isolated environments." @@ -38,7 +38,9 @@ tracing-subscriber = { workspace = true } uuid = { workspace = true } # WebSocket client -tokio-tungstenite = { version = "0.24", features = ["native-tls"] } +# rustls rather than native-tls: keeps OpenSSL out of the dependency tree so the +# release binaries can be statically linked against musl and run on any Linux. +tokio-tungstenite = { version = "0.24", features = ["rustls-tls-native-roots"] } futures-util = "0.3" # Process execution From ac96a572e1e88d203a32aaed604effd419f4a213 Mon Sep 17 00:00:00 2001 From: kerthcet Date: Sat, 1 Aug 2026 08:39:55 +0100 Subject: [PATCH 2/2] fix lint Signed-off-by: kerthcet --- Makefile | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index c8b0c27..9e093ee 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,9 @@ RUFF := .venv/bin/ruff PYTEST := .venv/bin/pytest MATURIN := .venv/bin/maturin +# Pinned so lint results don't shift when ruff changes its default rule set. +RUFF_VERSION := ruff==0.15.15 + .PHONY: help build install dev test clean daemon-build daemon-release test-e2e docker-build docker-down help: @@ -74,15 +77,18 @@ docker-down: lint: $(RUFF) $(RUFF) check . +# `check --fix` exits non-zero when unfixable errors remain, which would stop +# make before the formatter runs -- hence the leading `-`. `make lint` is what +# gates on remaining errors. .PHONY: format format: $(RUFF) - $(RUFF) check --fix . + -$(RUFF) check --fix . $(RUFF) format . $(RUFF): @echo "Installing ruff..." @python3 -m venv .venv || true - @.venv/bin/pip install --quiet ruff + @.venv/bin/pip install --quiet '$(RUFF_VERSION)' @echo "Ruff installed successfully" $(PYTEST):