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
12 changes: 12 additions & 0 deletions tandem/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

## Platform support

Tandem builds only on Linux. Its native C dependencies (nghttp2, c-ares,
mbedtls, cpucycles) are cross-compiled with `tools/build_native.sh`, which
invokes CMake + Ninja with a `zig cc -target <triple>` toolchain; the CMake
probe injects macOS-host-only flags (`-arch`, `-isysroot`) that zig cc rejects
for non-host targets. CI therefore builds and tests Tandem exclusively on
Linux runners (`zig build persistence-probe test -Dtarget=x86_64-linux-musl`).

On macOS hosts use `make` (which builds `sandboxd` and the Go binaries only)
and rely on CI for Tandem verification.
7 changes: 5 additions & 2 deletions tandem/src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,11 @@ fn startGrpcLite(allocator: std.mem.Allocator, pipeline: *PipelineServer, config
.tls = if (cert != null and key != null) .{
.certificate_chain_pem = cert.?,
.private_key_pem = key.?,
.ca_certificates_pem = ca,
.require_client_certificate = config.require_client_cert,
// v0.5.0 dropped the standalone require_client_certificate field:
// mTLS is now driven by whether client_ca_certificates_pem is
// non-null. Passing null disables client verification, which is
// exactly require_client_cert=false.
.client_ca_certificates_pem = if (config.require_client_cert) ca else null,
} else null,
};

Expand Down
54 changes: 39 additions & 15 deletions tandem/vendor/grpc-lite/.github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
persist-credentials: false

- name: Install mise tools
uses: jdx/mise-action@c2a87611a18de5b3828c5652fe268e992400cb5c # v4
uses: jdx/mise-action@2d8d4cafcbd33be2ea37d2b6f5ad595363d1f1ca # v5.1.1
with:
version: 2026.7.14

Expand Down Expand Up @@ -71,7 +71,7 @@ jobs:
persist-credentials: false

- name: Install mise tools
uses: jdx/mise-action@c2a87611a18de5b3828c5652fe268e992400cb5c # v4
uses: jdx/mise-action@2d8d4cafcbd33be2ea37d2b6f5ad595363d1f1ca # v5.1.1
with:
version: 2026.7.14

Expand All @@ -93,7 +93,7 @@ jobs:
persist-credentials: false

- name: Install mise tools
uses: jdx/mise-action@c2a87611a18de5b3828c5652fe268e992400cb5c # v4
uses: jdx/mise-action@2d8d4cafcbd33be2ea37d2b6f5ad595363d1f1ca # v5.1.1
with:
version: 2026.7.14

Expand All @@ -110,8 +110,20 @@ jobs:

generated-c-bundle:
name: Generated C bundle
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
include:
- arch: x86_64
runner: ubuntu-24.04
target: x86_64-linux-gnu
- arch: arm64
runner: ubuntu-24.04-arm
target: aarch64-linux-gnu
runs-on: ${{ matrix.runner }}
timeout-minutes: 30
env:
GRPC_LITE_TRANSPILED_C_TARGET: ${{ matrix.target }}
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand All @@ -120,17 +132,17 @@ jobs:
persist-credentials: false

- name: Install pinned mise and Zig
uses: jdx/mise-action@c2a87611a18de5b3828c5652fe268e992400cb5c # v4
uses: jdx/mise-action@2d8d4cafcbd33be2ea37d2b6f5ad595363d1f1ca # v5.1.1
with:
version: 2026.7.14

- name: Build reproducible bundle
run: mise run check-transpiled-c

- name: Upload verified bundle
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: grpc-lite-transpiled-c
name: grpc-lite-transpiled-c-${{ matrix.arch }}
path: .zig-cache/transpiled-c-dist/*
if-no-files-found: error
include-hidden-files: true
Expand All @@ -139,8 +151,20 @@ jobs:
generated-c-consumer:
name: Generated C bundle consumer — no Zig/no network
needs: generated-c-bundle
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
include:
- arch: x86_64
runner: ubuntu-24.04
target: x86_64-linux-gnu
- arch: arm64
runner: ubuntu-24.04-arm
target: aarch64-linux-gnu
runs-on: ${{ matrix.runner }}
timeout-minutes: 45
env:
GRPC_LITE_TRANSPILED_C_TARGET: ${{ matrix.target }}
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand All @@ -154,9 +178,9 @@ jobs:
docker version

- name: Download verified bundle
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: grpc-lite-transpiled-c
name: grpc-lite-transpiled-c-${{ matrix.arch }}
path: bundle-dist

- name: Consume bundle without Zig or network
Expand All @@ -179,7 +203,7 @@ jobs:
persist-credentials: false

- name: Install mise tools
uses: jdx/mise-action@c2a87611a18de5b3828c5652fe268e992400cb5c # v4
uses: jdx/mise-action@2d8d4cafcbd33be2ea37d2b6f5ad595363d1f1ca # v5.1.1
with:
version: 2026.7.14

Expand Down Expand Up @@ -207,7 +231,7 @@ jobs:
persist-credentials: false

- name: Install mise tools
uses: jdx/mise-action@c2a87611a18de5b3828c5652fe268e992400cb5c # v4
uses: jdx/mise-action@2d8d4cafcbd33be2ea37d2b6f5ad595363d1f1ca # v5.1.1
with:
version: 2026.7.14

Expand All @@ -234,7 +258,7 @@ jobs:
persist-credentials: false

- name: Install mise tools
uses: jdx/mise-action@c2a87611a18de5b3828c5652fe268e992400cb5c # v4
uses: jdx/mise-action@2d8d4cafcbd33be2ea37d2b6f5ad595363d1f1ca # v5.1.1
with:
version: 2026.7.14

Expand Down Expand Up @@ -263,7 +287,7 @@ jobs:
persist-credentials: false

- name: Install mise tools
uses: jdx/mise-action@c2a87611a18de5b3828c5652fe268e992400cb5c # v4
uses: jdx/mise-action@2d8d4cafcbd33be2ea37d2b6f5ad595363d1f1ca # v5.1.1
with:
version: 2026.7.14

Expand Down Expand Up @@ -292,7 +316,7 @@ jobs:
run: mise run interop-http2-edge

- name: Upload interop reports
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
if: always()
with:
name: interop-reports-${{ matrix.arch }}
Expand Down
4 changes: 2 additions & 2 deletions tandem/vendor/grpc-lite/.github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
persist-credentials: false

- name: Install mise tools
uses: jdx/mise-action@c2a87611a18de5b3828c5652fe268e992400cb5c # v4
uses: jdx/mise-action@2d8d4cafcbd33be2ea37d2b6f5ad595363d1f1ca # v5.1.1
with:
version: 2026.7.14

Expand All @@ -41,7 +41,7 @@ jobs:
run: mise run coverage

- name: Upload coverage to Codecov
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1
with:
disable_search: true
fail_ci_if_error: true
Expand Down
59 changes: 43 additions & 16 deletions tandem/vendor/grpc-lite/.github/workflows/release-transpiled-c.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,20 @@ jobs:
needs: full-validation
permissions:
contents: read
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
include:
- arch: x86_64
runner: ubuntu-24.04
target: x86_64-linux-gnu
- arch: arm64
runner: ubuntu-24.04-arm
target: aarch64-linux-gnu
runs-on: ${{ matrix.runner }}
timeout-minutes: 30
env:
GRPC_LITE_TRANSPILED_C_TARGET: ${{ matrix.target }}
steps:
- name: Checkout event commit
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand All @@ -47,7 +59,7 @@ jobs:
test "$version" = "$config"

- name: Install pinned mise and Zig
uses: jdx/mise-action@c2a87611a18de5b3828c5652fe268e992400cb5c # v4
uses: jdx/mise-action@2d8d4cafcbd33be2ea37d2b6f5ad595363d1f1ca # v5.1.1
with:
version: 2026.7.14

Expand All @@ -66,9 +78,9 @@ jobs:
test "$(jq -r .project_version "manifest-check/$root/manifest.json")" = "${GITHUB_REF_NAME#v}"

- name: Upload validated bundle
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: grpc-lite-transpiled-c-release
name: grpc-lite-transpiled-c-release-${{ matrix.arch }}
path: .zig-cache/transpiled-c-dist/*
if-no-files-found: error
include-hidden-files: true
Expand All @@ -79,8 +91,20 @@ jobs:
needs: package
permissions:
contents: read
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
include:
- arch: x86_64
runner: ubuntu-24.04
target: x86_64-linux-gnu
- arch: arm64
runner: ubuntu-24.04-arm
target: aarch64-linux-gnu
runs-on: ${{ matrix.runner }}
timeout-minutes: 45
env:
GRPC_LITE_TRANSPILED_C_TARGET: ${{ matrix.target }}
steps:
- name: Checkout event commit
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand All @@ -94,9 +118,9 @@ jobs:
docker version

- name: Download validated bundle
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: grpc-lite-transpiled-c-release
name: grpc-lite-transpiled-c-release-${{ matrix.arch }}
path: bundle-dist

- name: Test exact bundle
Expand All @@ -118,9 +142,10 @@ jobs:
timeout-minutes: 10
steps:
- name: Download validated bundle
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: grpc-lite-transpiled-c-release
pattern: grpc-lite-transpiled-c-release-*
merge-multiple: true
path: bundle-dist

- name: Create, verify, and publish workflow draft
Expand All @@ -132,12 +157,14 @@ jobs:
marker='<!-- grpc-lite-transpiled-c-workflow-owned -->'
tag=$GITHUB_REF_NAME
archives=(bundle-dist/*.tar.gz)
test "${#archives[@]}" -eq 1
archive=${archives[0]}
root=$(basename "$archive" .tar.gz)
manifest_commit=$(tar -xOf "$archive" "$root/manifest.json" | jq -r .source_commit)
test "$manifest_commit" = "$GITHUB_SHA"
(cd bundle-dist && sha256sum --check "$(basename "$archive").sha256")
test "${#archives[@]}" -eq 2
manifest_commit=$GITHUB_SHA
for arch in x86_64 arm64; do
archive="bundle-dist/grpc-lite-transpiled-c-${tag#v}-linux-$arch.tar.gz"
root=$(basename "$archive" .tar.gz)
test "$(tar -xOf "$archive" "$root/manifest.json" | jq -r .source_commit)" = "$manifest_commit"
(cd bundle-dist && sha256sum --check "$(basename "$archive").sha256")
done

require_current_tag() {
local object_json object_type object_sha
Expand All @@ -161,7 +188,7 @@ jobs:
require_current_tag
gh release create "$tag" --verify-tag --draft --title "$tag" \
--notes "$marker
Generated-only C bundle for insecure Linux x86_64."
Generated-only C bundle for insecure Linux x86_64 and ARM64."
release_json=$(gh release view "$tag" --json isDraft,body)
fi
is_draft=$(jq -r .isDraft <<<"$release_json")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
persist-credentials: false

- name: Install mise tools
uses: jdx/mise-action@c2a87611a18de5b3828c5652fe268e992400cb5c # v4
uses: jdx/mise-action@2d8d4cafcbd33be2ea37d2b6f5ad595363d1f1ca # v5.1.1
with:
version: 2026.7.14

Expand Down
4 changes: 2 additions & 2 deletions tandem/vendor/grpc-lite/.github/workflows/soak.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
persist-credentials: false

- name: Install mise tools
uses: jdx/mise-action@c2a87611a18de5b3828c5652fe268e992400cb5c # v4
uses: jdx/mise-action@2d8d4cafcbd33be2ea37d2b6f5ad595363d1f1ca # v5.1.1
with:
version: 2026.7.14

Expand All @@ -54,7 +54,7 @@ jobs:
run: mise run interop-official

- name: Upload soak logs
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
if: always()
with:
name: official-unary-soak
Expand Down
7 changes: 4 additions & 3 deletions tandem/vendor/grpc-lite/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ mise run gen-grpcpp
- gRPC payloads remain raw protobuf wire bytes.
- Generated protobuf sources live under `.zig-cache` and are not committed.
- The native Zig transport supports raw unary and full-duplex streaming over cleartext or TLS IPv4.
- The insecure Linux x86_64 transpiled-C release bundle supports cleartext transport only.
- The insecure Linux x86_64 and ARM64 transpiled-C release bundle supports cleartext transport only.
- c-ares resolves client hostnames to IPv4 candidates on the libxev loop.

Keep C types private to transport modules. Keep protobuf out of `src/root.zig` so the
Expand Down Expand Up @@ -79,8 +79,9 @@ authoritative: change it before implementing a feature with a different decision
| Graceful server drain | Selected | Stop admission, send GOAWAY, wait with timeout |
| Server resource limits | Selected | Aggregate connection cap, per-connection stream cap, absolute cleartext preface timeout, and idle timeout only while no inbound RPC streams are active |
| Native Zig TLS and ALPN | Selected | Optional mbedTLS; TLS 1.2+, mandatory `h2`, explicit PEM credentials |
| Transpiled-C release bundle TLS | Out of scope | The insecure Linux x86_64 bundle remains cleartext-only until TLS is separately selected |
| mTLS | Out of scope | Client certificates and server-side client verification are not required |
| Transpiled-C release bundles | Selected | Target-specific insecure Linux x86_64 and ARM64 packages; native CI packaging and no-Zig consumers |
| Transpiled-C release bundle TLS | Out of scope | The insecure Linux x86_64 and ARM64 bundles remain cleartext-only until TLS is separately selected |
| mTLS | Selected | Native Zig TLS only: optional client PEM identity and server-required client verification with explicit trusted CAs; no identity authorization or dynamic rotation |
| DNS | Selected | c-ares on Linux io_uring; client IPv4 hostnames only |
| IPv6 | Out of scope | No AAAA, Happy Eyeballs, or IPv6 listeners |
| Reflection and health services | Out of scope | Not part of the lite profile |
Expand Down
Loading
Loading