Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -120,14 +120,17 @@ jobs:
with:
node-version: 24
cache: pnpm
cache-dependency-path: frontend/pnpm-lock.yaml
cache-dependency-path: |
frontend/pnpm-lock.yaml
release-site/pnpm-lock.yaml
- uses: astral-sh/setup-uv@v5
- run: uv sync
- run: bash scripts/generate-settings.sh
- run: bash scripts/prepare-install-test-assets.sh
- run: bash scripts/materialize-config.sh
- run: cd frontend && pnpm install --frozen-lockfile
- run: cd frontend && pnpm run build
- run: cd release-site && pnpm install --frozen-lockfile

- name: Dependency audit
run: |
Expand Down
103 changes: 95 additions & 8 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -353,9 +353,20 @@ jobs:
set -euo pipefail
VERSION="${RELEASE_TAG#v}"
sudo /usr/sbin/installer -pkg "packages/Capsem-$VERSION.pkg" -target /
test -d "/Applications/Capsem.app"
test -x "/Applications/Capsem.app/Contents/MacOS/capsem-app"
test -x "$HOME/.capsem/bin/capsem"
"$HOME/.capsem/bin/capsem" --version | grep -F "$VERSION"
"$HOME/.capsem/bin/capsem" status
for bin in capsem capsem-admin capsem-gateway capsem-mcp capsem-mcp-aggregator capsem-mcp-builtin capsem-process capsem-service capsem-tray capsem-tui; do
test -x "$HOME/.capsem/bin/$bin"
"$HOME/.capsem/bin/$bin" --version | grep -F "$VERSION"
done
"$HOME/.capsem/bin/capsem" status | tee /tmp/capsem-status.txt
grep -F "Installed: true" /tmp/capsem-status.txt
grep -F "Running: true" /tmp/capsem-status.txt
grep -F "Service: ok" /tmp/capsem-status.txt
grep -F "Gateway: ok" /tmp/capsem-status.txt
pgrep -x capsem-tray

- name: Collect macOS artifacts
run: |
Expand Down Expand Up @@ -474,14 +485,45 @@ jobs:
echo "=== Verify companion binaries in deb ==="
dpkg-deb --contents target/release/bundle/deb/*.deb | grep -E "capsem-service|capsem-tui|capsem-mcp-aggregator|capsem-mcp-builtin|capsem-gateway|capsem-tray|capsem-admin"

- name: Enable KVM for exact-package VM proof
if: matrix.arch == 'x86_64'
run: |
sudo modprobe kvm
sudo chmod 0666 /dev/kvm
sudo modprobe vhost_vsock
sudo chmod 0666 /dev/vhost-vsock
test -r /dev/kvm -a -w /dev/kvm
test -r /dev/vhost-vsock -a -w /dev/vhost-vsock

- name: Install exact release deb
run: |
set -euo pipefail
VERSION="${RELEASE_TAG#v}"
sudo dpkg -i target/release/bundle/deb/*.deb || sudo apt-get install -f -y
test -x /usr/bin/capsem
/usr/bin/capsem --version | grep -F "$VERSION"
/usr/bin/capsem status
dpkg-query -W -f='${Version}' capsem | grep -Fx "$VERSION"
for bin in capsem capsem-admin capsem-app capsem-gateway capsem-mcp capsem-mcp-aggregator capsem-mcp-builtin capsem-process capsem-service capsem-tray capsem-tui; do
test -x "/usr/bin/$bin"
if [ "$bin" != "capsem-app" ]; then
"/usr/bin/$bin" --version | grep -F "$VERSION"
fi
done
/usr/bin/capsem status | tee /tmp/capsem-status.txt
grep -F "Installed: true" /tmp/capsem-status.txt
grep -F "Running: true" /tmp/capsem-status.txt
grep -F "Service: ok" /tmp/capsem-status.txt
grep -F "Gateway: ok" /tmp/capsem-status.txt

- name: Prove exact-package guest shell execution
if: matrix.arch == 'x86_64'
run: |
set -euo pipefail
python3 scripts/prove-installed-shell.py \
--capsem /usr/bin/capsem \
--marker CAPSEM_EXACT_PACKAGE_SHELL_OK \
--session-name release-exact-shell-x86_64 \
--timeout 300

- name: Collect Linux artifacts
run: |
Expand Down Expand Up @@ -877,18 +919,63 @@ jobs:
")
[ "$fail" = 0 ] || { echo '::error::one or more asset URLs are unreachable or hash-mismatched'; exit 1; }

- name: Glow-up verify public install, channel switch, and upgrade
- name: Verify public release packages and installer contract
run: |
set -euo pipefail
echo "Docker smoke: curl -fsSL https://capsem.org/install.sh | sh"
uv run python3 scripts/check-public-binary-release.py \
--channel "$RELEASE_CHANNEL" \
--manifest-url "$ASSET_MANIFEST_URL" \
--stable-manifest-url https://release.capsem.org/assets/stable/manifest.json \
--nightly-manifest-url https://release.capsem.org/assets/nightly/manifest.json \
--install-script-url https://capsem.org/install.sh \
--site-url https://capsem.org/ \
--work-dir /tmp/public-binary-release \
--docker-linux-install \
--docker-channel-switch \
--docker-upgrade
--work-dir /tmp/public-binary-release

- name: Enable KVM for live public-install VM proof
run: |
set -euo pipefail
sudo modprobe kvm
sudo chmod 0666 /dev/kvm
sudo modprobe vhost_vsock
sudo chmod 0666 /dev/vhost-vsock
test -r /dev/kvm -a -w /dev/kvm
test -r /dev/vhost-vsock -a -w /dev/vhost-vsock

- name: Install live public Linux release and prove guest shell execution
run: |
set -euo pipefail
EXPECTED_VERSION="$(python3 - <<'PY'
import json

manifest = json.load(open('/tmp/verify/manifest.json'))
matches = [
package
for package in manifest.get('packages', [])
if package.get('platform') == 'linux'
and package.get('architecture') == 'x86_64'
]
if len(matches) != 1 or not isinstance(matches[0].get('version'), str):
raise SystemExit('manifest must contain exactly one versioned linux/x86_64 package')
print(matches[0]['version'])
PY
)"
curl -fsSL https://capsem.org/install.sh | CAPSEM_CHANNEL="$RELEASE_CHANNEL" sh
test -x "$HOME/.capsem/bin/capsem"
test -x /usr/bin/capsem-app
"$HOME/.capsem/bin/capsem" --version | grep -F "$EXPECTED_VERSION"
dpkg-query -W -f='${Version}' capsem | grep -Fx "$EXPECTED_VERSION"
for bin in capsem capsem-admin capsem-gateway capsem-mcp capsem-mcp-aggregator capsem-mcp-builtin capsem-process capsem-service capsem-tray capsem-tui; do
test -x "$HOME/.capsem/bin/$bin"
"$HOME/.capsem/bin/$bin" --version | grep -F "$EXPECTED_VERSION"
done
grep -F "$ASSET_MANIFEST_URL" "$HOME/.capsem/assets/manifest-origin.json"
"$HOME/.capsem/bin/capsem" status | tee /tmp/capsem-live-status.txt
grep -F "Installed: true" /tmp/capsem-live-status.txt
grep -F "Running: true" /tmp/capsem-live-status.txt
grep -F "Service: ok" /tmp/capsem-live-status.txt
grep -F "Gateway: ok" /tmp/capsem-live-status.txt
python3 scripts/prove-installed-shell.py \
--capsem "$HOME/.capsem/bin/capsem" \
--marker CAPSEM_LIVE_PUBLIC_INSTALL_SHELL_OK \
--session-name release-live-public-shell-x86_64 \
--timeout 300
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Fixed
- Made the public macOS curl installer synchronously apply the downloaded
package with `/usr/sbin/installer`, so the command completes a real install
instead of handing the package to a generic `open` action.
- Made both macOS and Linux public installers reject package downloads whose
byte size or SHA-256 does not match the release manifest before elevation.
- Strengthened release CI to verify exact installed package versions, complete
binary cohorts, service readiness, and PTY-driven `capsem shell` execution
inside a KVM-backed guest on Linux.
- Made Debian-package SBOM inspection parse the package archive directly, so
release acceptance tests work with both BSD and GNU host toolchains.
- Pinned the clean-build SSE stream dependency to its supported patch API so
untracked local resolution state cannot mask release CI compilation drift.
- Made macOS CI install the release-site lockfile before integration tests so
cached local Node modules cannot mask clean-runner release-contract failures.

## [1.5.1783894498] - 2026-07-12

### Changed
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ futures = "0.3"
tokio-stream = { version = "0.1", features = ["net"] }
async-compression = { version = "0.4", features = ["tokio", "gzip"] }
tokio-util = { version = "0.7", features = ["io"] }
sse-stream = "0.2"
sse-stream = "=0.2.4"
base64 = "0.22"
bytes = "1"
regex = "1"
Expand Down
2 changes: 1 addition & 1 deletion crates/capsem-core/src/hypervisor/fuse/inode_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ mod tests {
let dir = std::env::temp_dir().join("capsem-fuse-test").join(name);
let _ = std::fs::remove_dir_all(&dir);
std::fs::create_dir_all(&dir).unwrap();
dir
dir.canonicalize().unwrap()
}

// Inode table operations
Expand Down
Loading
Loading