Set up Forgejo CI/CD policy

ober

4334221d9dc71ac0383f6f631aac4e60e7865b40

diff --git a/.builds/ci-freebsd.yml b/.builds/ci-freebsd.yml
deleted file mode 100644
index f26a052..0000000
--- a/.builds/ci-freebsd.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-image: freebsd/14.x
-arch: amd64
-packages:
-- bash
-- ca_root_nss
-- curl
-- git
-- gmake
-
-sources:
-- https://git.jerboa.sh/ober/jerboa
-
-tasks:
-- capsicum-platform-tests: |
-    cd jerboa
-    gmake build
-    .chez/bin/scheme --libdirs lib:vendor/jsqlite/src --script tests/test-capsicum.ss
-    .chez/bin/scheme --libdirs lib:vendor/jsqlite/src --script tests/test-seatbelt.ss
-    .chez/bin/scheme --libdirs lib:vendor/jsqlite/src --script tests/test-worker.ss
diff --git a/.builds/ci.yml b/.builds/ci.yml
deleted file mode 100644
index 35c418d..0000000
--- a/.builds/ci.yml
+++ /dev/null
@@ -1,30 +0,0 @@
-image: debian/stable
-arch: amd64
-packages:
-- bash
-- build-essential
-- ca-certificates
-- curl
-- file
-- git
-- libncurses-dev
-- pkg-config
-- tar
-sources:
-- https://git.jerboa.sh/ober/jerboa
-tasks:
-- build-and-test: |
-    umask 022
-    cd jerboa
-    sudo fallocate -l 4G /swapfile && sudo chmod 600 /swapfile && sudo mkswap /swapfile && sudo swapon /swapfile
-    export CARGO_BUILD_JOBS=1
-    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | \
-      sh -s -- -y --profile minimal --default-toolchain 1.94.1
-    source "$HOME/.cargo/env"
-    export CHEZ_CONFIGURE_EXTRA=--disable-x11
-    export JERBOA_NATIVE_FEATURES=tls
-    export JERBOA_CC_OPT=-O0
-    make security-hardware-smoke
-    make data-check
-    make test
-    make fuzz-smoke
diff --git a/.builds/release-freebsd-amd64.yml b/.builds/release-freebsd-amd64.yml
deleted file mode 100644
index 61e39e1..0000000
--- a/.builds/release-freebsd-amd64.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-image: freebsd/14.x
-arch: amd64
-packages:
-- bash
-- ca_root_nss
-- curl
-- git
-- gmake
-environment:
-  release_target: freebsd-amd64
-sources:
-- https://git.jerboa.sh/ober/jerboa
-tasks:
-- build: |
-    cd jerboa
-    case "${GIT_REF:-}" in
-      refs/tags/*) version=${GIT_REF#refs/tags/} ;;
-      *) version=v$(cat VERSION) ;;
-    esac
-    gmake jerboa
-    gmake release-artifact RELEASE_VERSION="$version" RELEASE_TARGET="$release_target"
-artifacts:
-- jerboa/dist/release/jerboa-freebsd-amd64.tar.gz
-- jerboa/dist/release/jerboa-freebsd-amd64.tar.gz.sha256
diff --git a/.builds/release-linux-amd64.yml b/.builds/release-linux-amd64.yml
deleted file mode 100644
index 0871189..0000000
--- a/.builds/release-linux-amd64.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-image: debian/stable
-arch: amd64
-packages:
-- bash
-- build-essential
-- ca-certificates
-- curl
-- file
-- git
-- tar
-environment:
-  release_target: linux-amd64
-sources:
-- https://git.jerboa.sh/ober/jerboa
-tasks:
-- build: |
-    cd jerboa
-    case "${GIT_REF:-}" in
-      refs/tags/*) version=${GIT_REF#refs/tags/} ;;
-      *) version=v$(cat VERSION) ;;
-    esac
-    make jerboa
-    make release-artifact RELEASE_VERSION="$version" RELEASE_TARGET="$release_target"
-artifacts:
-- jerboa/dist/release/jerboa-linux-amd64.tar.gz
-- jerboa/dist/release/jerboa-linux-amd64.tar.gz.sha256
diff --git a/.builds/release-linux-arm64.yml b/.builds/release-linux-arm64.yml
deleted file mode 100644
index eed31fb..0000000
--- a/.builds/release-linux-arm64.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-image: debian/stable
-arch: arm64
-packages:
-- bash
-- build-essential
-- ca-certificates
-- curl
-- file
-- git
-- tar
-environment:
-  release_target: linux-arm64
-sources:
-- https://git.jerboa.sh/ober/jerboa
-tasks:
-- build: |
-    cd jerboa
-    case "${GIT_REF:-}" in
-      refs/tags/*) version=${GIT_REF#refs/tags/} ;;
-      *) version=v$(cat VERSION) ;;
-    esac
-    make jerboa
-    make release-artifact RELEASE_VERSION="$version" RELEASE_TARGET="$release_target"
-artifacts:
-- jerboa/dist/release/jerboa-linux-arm64.tar.gz
-- jerboa/dist/release/jerboa-linux-arm64.tar.gz.sha256
diff --git a/.forgejo/ci-required.sh b/.forgejo/ci-required.sh
new file mode 100755
index 0000000..8496b8d
--- /dev/null
+++ b/.forgejo/ci-required.sh
@@ -0,0 +1,68 @@
+#!/bin/sh
+set -eu
+
+has_target() {
+  target=$1
+  [ -f Makefile ] && grep -Eq "^${target}[[:space:]]*:" Makefile
+}
+
+if has_target verify; then
+  make verify
+else
+  ran=0
+  for target in security test check build; do
+    if has_target "$target"; then
+      make "$target"
+      ran=1
+    fi
+  done
+  [ "$ran" = 1 ] || {
+    echo "ERROR: no verify, test, check, or build target is available" >&2
+    exit 1
+  }
+fi
+
+if ! has_target binary; then
+  echo "No standalone binary target; full repository verification passed."
+  exit 0
+fi
+
+make binary
+
+if has_target binary-smoke; then
+  make binary-smoke
+  exit 0
+fi
+if has_target smoke; then
+  make smoke
+  exit 0
+fi
+
+binary_list=$(mktemp)
+trap 'rm -f "$binary_list"' EXIT HUP INT TERM
+find . -maxdepth 2 -type f -perm -111 \
+  ! -path './.git/*' ! -path './.jerboa/*' ! -path './vendor/*' \
+  ! -path './test/*' ! -path './tests/*' \
+  -exec file {} \; |
+  awk -F: '/(ELF .*executable|Mach-O .*executable)/ { print $1 }' > "$binary_list"
+
+[ -s "$binary_list" ] || {
+  echo "ERROR: make binary succeeded but produced no runnable ELF executable" >&2
+  exit 1
+}
+
+while IFS= read -r binary; do
+  echo "Smoke-checking $binary"
+  if timeout 30 env QT_QPA_PLATFORM=offscreen \
+      QTWEBENGINE_CHROMIUM_FLAGS=--disable-gpu "$binary" --version >/dev/null 2>&1; then
+    continue
+  fi
+  if timeout 30 env QT_QPA_PLATFORM=offscreen \
+      QTWEBENGINE_CHROMIUM_FLAGS=--disable-gpu "$binary" --help >/dev/null 2>&1; then
+    continue
+  fi
+  echo "ERROR: $binary failed both --version and --help runtime smoke checks" >&2
+  exit 1
+done < "$binary_list"
+
+echo "Full verification, binary build, and runtime smoke checks passed."
diff --git a/.forgejo/require-version-bump.sh b/.forgejo/require-version-bump.sh
new file mode 100755
index 0000000..ec38872
--- /dev/null
+++ b/.forgejo/require-version-bump.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+set -eu
+
+version_file=${VERSION_FILE:-VERSION}
+test -f "$version_file" || {
+  echo "ERROR: $version_file is required" >&2
+  exit 1
+}
+
+new_version=$(tr -d '[:space:]' < "$version_file")
+printf '%s\n' "$new_version" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$' || {
+  echo "ERROR: VERSION must be semantic MAJOR.MINOR.PATCH, got: $new_version" >&2
+  exit 1
+}
+
+if [ -f jpkg.sexp ]; then
+  manifest_version=$(awk -F'"' '/\(version "/ { print $2; exit }' jpkg.sexp)
+  [ "$manifest_version" = "$new_version" ] || {
+    echo "ERROR: jpkg.sexp version $manifest_version must match VERSION $new_version" >&2
+    exit 1
+  }
+fi
+
+if [ "${FORGEJO_EVENT_NAME:-}" != pull_request ]; then
+  echo "VERSION $new_version is valid"
+  exit 0
+fi
+
+base_ref=${FORGEJO_BASE_REF:?FORGEJO_BASE_REF is required for pull requests}
+old_version=$(git show "origin/$base_ref:$version_file" 2>/dev/null | tr -d '[:space:]' || true)
+old_version=${old_version:-0.0.0}
+printf '%s\n' "$old_version" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$' || {
+  echo "ERROR: target branch VERSION is malformed: $old_version" >&2
+  exit 1
+}
+
+if ! awk -F. -v old="$old_version" -v new="$new_version" 'BEGIN {
+  split(old, o, ".")
+  split(new, n, ".")
+  for (i = 1; i <= 3; i++) {
+    if ((n[i] + 0) > (o[i] + 0)) exit 0
+    if ((n[i] + 0) < (o[i] + 0)) exit 1
+  }
+  exit 1
+}'; then
+  echo "ERROR: VERSION must advance beyond $old_version; got $new_version" >&2
+  exit 1
+fi
+
+echo "VERSION advances: $old_version -> $new_version"
diff --git a/.forgejo/workflows/ci.yaml b/.forgejo/workflows/ci.yaml
new file mode 100644
index 0000000..b3c5cf6
--- /dev/null
+++ b/.forgejo/workflows/ci.yaml
@@ -0,0 +1,56 @@
+name: required-ci
+
+on:
+  pull_request:
+    branches: [master]
+  push:
+    branches: [master]
+    tags: ['v*']
+  workflow_dispatch:
+
+jobs:
+  required:
+    runs-on: docker
+    container:
+      image: debian:stable
+    steps:
+      - name: Install system dependencies
+        run: |
+          apt-get update
+          DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
+            bash build-essential ca-certificates curl file git libfuse-dev \
+            libgl1-mesa-dev liblz4-dev libncurses-dev libqt5gui5 libssl-dev \
+            libx11-dev make pkg-config tar zlib1g-dev
+      - name: Check out jerboa
+        uses: https://code.forgejo.org/actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
+        with:
+          persist-credentials: false
+      - name: Install Rust
+        run: |
+          curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs |
+            sh -s -- -y --profile minimal --default-toolchain 1.94.1
+          echo "$HOME/.cargo/bin" >> "$FORGEJO_PATH"
+      - name: Build, test, and smoke-check
+        run: |
+          . "$HOME/.cargo/env"
+          CARGO_BUILD_JOBS=1 CHEZ_CONFIGURE_EXTRA=--disable-x11 \
+            JERBOA_NATIVE_FEATURES=tls JERBOA_CC_OPT=-O0 \
+            sh .forgejo/ci-required.sh
+      - name: Verify and pack package
+        run: |
+          version=$(cat VERSION)
+          J="$PWD/dist/jerboa"
+          mkdir -p "$HOME/.cache"
+          chmod -R go-w "$HOME/.cache"
+          "$J" pkg verify
+          "$J" pkg policy
+          "$J" pkg build
+          "$J" pkg pack --output "$PWD/jerboa-$version.jpkg"
+          "$J" pkg verify "$PWD/jerboa-$version.jpkg"
+          "$J" pkg verify --reproduce
+      - name: Upload package
+        uses: https://code.forgejo.org/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3
+        with:
+          name: jerboa-package
+          path: jerboa-*.jpkg
+          if-no-files-found: error
diff --git a/.forgejo/workflows/freebsd.yaml b/.forgejo/workflows/freebsd.yaml
new file mode 100644
index 0000000..ecbaa0d
--- /dev/null
+++ b/.forgejo/workflows/freebsd.yaml
@@ -0,0 +1,26 @@
+name: freebsd-required
+
+on:
+  pull_request:
+    branches: [master]
+  push:
+    branches: [master]
+  workflow_dispatch:
+
+jobs:
+  required:
+    runs-on: freebsd-amd64
+    steps:
+      - name: Install dependencies
+        run: pkg install -y bash ca_root_nss curl git gmake
+      - name: Check out Jerboa
+        uses: https://code.forgejo.org/actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
+        with:
+          persist-credentials: false
+      - name: Build binary and run platform tests
+        run: |
+          gmake build
+          bin/jerboa run tests/test-capsicum.ss
+          bin/jerboa run tests/test-seatbelt.ss
+          bin/jerboa run tests/test-worker.ss
+          bin/jerboa version
diff --git a/.forgejo/workflows/release.yaml b/.forgejo/workflows/release.yaml
new file mode 100644
index 0000000..f3bdd06
--- /dev/null
+++ b/.forgejo/workflows/release.yaml
@@ -0,0 +1,150 @@
+name: release
+
+on:
+  push:
+    tags: ['v*']
+  workflow_dispatch:
+
+jobs:
+  linux-amd64:
+    runs-on: docker
+    container:
+      image: debian:stable
+    steps:
+      - run: apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends bash build-essential ca-certificates curl file git tar
+      - uses: https://code.forgejo.org/actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
+        with:
+          fetch-depth: 0
+          persist-credentials: false
+      - name: Install Rust
+        run: |
+          curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs |
+            sh -s -- -y --profile minimal --default-toolchain 1.94.1
+          echo "$HOME/.cargo/bin" >> "$FORGEJO_PATH"
+      - name: Build, package, and run
+        run: |
+          . "$HOME/.cargo/env"
+          version="v$(cat VERSION)"
+          test "${FORGEJO_REF#refs/tags/}" = "$version"
+          make jerboa
+          make release-artifact RELEASE_VERSION="$version" RELEASE_TARGET=linux-amd64
+          archive=$(find dist/release -name '*linux-amd64.tar.gz' -type f)
+          tmp=$(mktemp -d)
+          tar -xzf "$archive" -C "$tmp"
+          binary=$(find "$tmp" -path '*/bin/jerboa' -type f)
+          "$binary" version
+      - uses: https://code.forgejo.org/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3
+        with:
+          name: release-linux-amd64
+          path: |
+            dist/release/*.tar.gz
+            dist/release/*.tar.gz.sha256
+          if-no-files-found: error
+
+  linux-arm64:
+    runs-on: docker-arm64
+    container:
+      image: debian:stable
+    steps:
+      - run: apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends bash build-essential ca-certificates curl file git tar
+      - uses: https://code.forgejo.org/actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
+        with:
+          fetch-depth: 0
+          persist-credentials: false
+      - name: Install Rust
+        run: |
+          curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs |
+            sh -s -- -y --profile minimal --default-toolchain 1.94.1
+          echo "$HOME/.cargo/bin" >> "$FORGEJO_PATH"
+      - name: Build, package, and run
+        run: |
+          . "$HOME/.cargo/env"
+          version="v$(cat VERSION)"
+          test "${FORGEJO_REF#refs/tags/}" = "$version"
+          make jerboa
+          make release-artifact RELEASE_VERSION="$version" RELEASE_TARGET=linux-arm64
+          archive=$(find dist/release -name '*linux-arm64.tar.gz' -type f)
+          tmp=$(mktemp -d)
+          tar -xzf "$archive" -C "$tmp"
+          binary=$(find "$tmp" -path '*/bin/jerboa' -type f)
+          "$binary" version
+      - uses: https://code.forgejo.org/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3
+        with:
+          name: release-linux-arm64
+          path: |
+            dist/release/*.tar.gz
+            dist/release/*.tar.gz.sha256
+          if-no-files-found: error
+
+  freebsd-amd64:
+    runs-on: freebsd-amd64
+    steps:
+      - run: pkg install -y bash ca_root_nss curl git gmake
+      - uses: https://code.forgejo.org/actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
+        with:
+          fetch-depth: 0
+          persist-credentials: false
+      - name: Build, package, and run
+        run: |
+          version="v$(cat VERSION)"
+          test "${FORGEJO_REF#refs/tags/}" = "$version"
+          gmake jerboa
+          gmake release-artifact RELEASE_VERSION="$version" RELEASE_TARGET=freebsd-amd64
+          archive=$(find dist/release -name '*freebsd-amd64.tar.gz' -type f)
+          tmp=$(mktemp -d)
+          tar -xzf "$archive" -C "$tmp"
+          binary=$(find "$tmp" -path '*/bin/jerboa' -type f)
+          "$binary" version
+      - uses: https://code.forgejo.org/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3
+        with:
+          name: release-freebsd-amd64
+          path: |
+            dist/release/*.tar.gz
+            dist/release/*.tar.gz.sha256
+          if-no-files-found: error
+
+  publish:
+    needs: [linux-amd64, linux-arm64, freebsd-amd64]
+    runs-on: docker
+    container:
+      image: debian:stable
+    steps:
+      - run: apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends ca-certificates curl git jq openssh-client
+      - uses: https://code.forgejo.org/actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
+        with:
+          fetch-depth: 0
+          persist-credentials: false
+      - uses: https://code.forgejo.org/actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3
+        with:
+          name: release-linux-amd64
+          path: dist/download/linux-amd64
+      - uses: https://code.forgejo.org/actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3
+        with:
+          name: release-linux-arm64
+          path: dist/download/linux-arm64
+      - uses: https://code.forgejo.org/actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3
+        with:
+          name: release-freebsd-amd64
+          path: dist/download/freebsd-amd64
+      - name: Sign, verify, and publish Forgejo release
+        env:
+          FORGEJO_TOKEN: ${{ forgejo.token }}
+          SIGNING_KEY_B64: ${{ secrets.JERBOA_RELEASE_SSH_SIGNING_KEY_B64 }}
+        run: |
+          mkdir -p dist/release
+          find dist/download -type f -exec cp {} dist/release/ \;
+          test -n "$SIGNING_KEY_B64" || {
+            echo "ERROR: JERBOA_RELEASE_SSH_SIGNING_KEY_B64 is required" >&2
+            exit 1
+          }
+          key=$(mktemp)
+          allowed=$(mktemp)
+          printf '%s' "$SIGNING_KEY_B64" | base64 -d > "$key"
+          chmod 0600 "$key"
+          printf 'jerboa %s\n' "$(ssh-keygen -y -f "$key")" > "$allowed"
+          export JERBOA_RELEASE_SIGNING_TOOL=ssh-keygen
+          export JERBOA_RELEASE_SSH_SIGNING_KEY="$key"
+          export JERBOA_RELEASE_SSH_ALLOWED_SIGNERS="$allowed"
+          export JERBOA_RELEASE_SSH_SIGNER_IDENTITY=jerboa
+          make sign-release-artifacts
+          make release-upload RELEASE_VERSION="v$(cat VERSION)"
diff --git a/.forgejo/workflows/version-policy.yaml b/.forgejo/workflows/version-policy.yaml
new file mode 100644
index 0000000..4d9f784
--- /dev/null
+++ b/.forgejo/workflows/version-policy.yaml
@@ -0,0 +1,23 @@
+name: version-policy
+
+on:
+  pull_request:
+    branches: [master]
+
+jobs:
+  required:
+    runs-on: docker
+    container:
+      image: debian:stable
+    steps:
+      - name: Install Git
+        run: |
+          apt-get update
+          DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends git ca-certificates
+      - name: Check out full history
+        uses: https://code.forgejo.org/actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
+        with:
+          fetch-depth: 0
+          persist-credentials: false
+      - name: Require semantic version advancement
+        run: sh .forgejo/require-version-bump.sh
diff --git a/.gitsafeignore b/.gitsafeignore
new file mode 100644
index 0000000..2681d0e
--- /dev/null
+++ b/.gitsafeignore
@@ -0,0 +1,14 @@
+.forgejo/workflows/ci.yaml:high-entropy-hex:25
+.forgejo/workflows/ci.yaml:high-entropy-hex:52
+.forgejo/workflows/freebsd.yaml:high-entropy-hex:17
+.forgejo/workflows/release.yaml:high-entropy-hex:113
+.forgejo/workflows/release.yaml:high-entropy-hex:117
+.forgejo/workflows/release.yaml:high-entropy-hex:121
+.forgejo/workflows/release.yaml:high-entropy-hex:125
+.forgejo/workflows/release.yaml:high-entropy-hex:15
+.forgejo/workflows/release.yaml:high-entropy-hex:36
+.forgejo/workflows/release.yaml:high-entropy-hex:50
+.forgejo/workflows/release.yaml:high-entropy-hex:71
+.forgejo/workflows/release.yaml:high-entropy-hex:83
+.forgejo/workflows/release.yaml:high-entropy-hex:98
+.forgejo/workflows/version-policy.yaml:high-entropy-hex:18
diff --git a/AGENTS.md b/AGENTS.md
index aeb7528..71876ec 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -1,3 +1,21 @@
+## STOP: Forgejo Pull Requests Are Mandatory
+
+Every change to this repository must use the Forgejo pull-request workflow.
+
+1. Start from the current remote default branch and create a dedicated feature, fix, or chore branch **before editing**.
+2. Make only the scoped changes on that branch.
+3. Run every repository-required test and build. If the repository produces binaries, build them and run a meaningful smoke check (such as the documented startup, `--help`, or `--version`). Do not commit while any required check fails.
+4. Commit the verified changes on the feature branch and push that branch to `origin`.
+5. Open a pull request on `git.jerboa.sh` targeting the default branch. A human must review, approve, and merge it.
+
+Absolute bans: never commit or push directly to `main` or `master`; never self-approve or self-merge; never bypass branch protection; and never leave completed changes only in a local branch. Release work and urgent fixes follow the same branch-and-PR process.
+
+### Every PR Must Advance the Version
+
+`VERSION` is the authoritative repository version. Every pull request must change it to a strictly greater semantic version (`MAJOR.MINOR.PATCH`). Use a patch increment for fixes and maintenance, a minor increment for backward-compatible features, and a major increment for breaking changes. Keep package manifests, generated version constants, release artifact names, and user-visible version output synchronized with `VERSION`.
+
+Forgejo CI compares the proposed `VERSION` with the target branch and rejects an unchanged, malformed, or lower version.
+
 ## STOP: Chez Scheme Is Off-Limits — Jerboa Only
 
 Absolute bans. They override every habit from Scheme training data and every
@@ -406,18 +424,17 @@ If delivery needs work, repair or configure the `git.jerboa.sh` release path.
 Do not reintroduce SourceHut or add a GitHub mirror.
 
 Common sibling repos that exist but must NOT be touched without explicit instruction:
-- `~/mine/jerboa-mcp` — Legacy node MCP, superseded. The active MCP server now lives in THIS repo at `mcp/` + `data/`. Don't modify the legacy repo unless told.
-- `~/mine/jerboa-shell` — Only modify when user explicitly says to work there.
-- `~/mine/gerbil-mcp` — **NEVER touch**. Deprecated.
-- `~/mine/gerbil-orig` — Read-only reference for upstream Gerbil. Never modify.
+- the legacy Jerboa MCP sibling checkout — Legacy node MCP, superseded. The active MCP server now lives in THIS repo at `mcp/` + `data/`. Don't modify the legacy repo unless told.
+- the Jerboa shell sibling checkout — Only modify when user explicitly says to work there.
+- the deprecated Gerbil MCP sibling checkout — **NEVER touch**. Deprecated.
+- the upstream Gerbil reference checkout — Read-only reference for upstream Gerbil. Never modify.
 
 If a user instruction mentions a file path, use EXACTLY that path. Do not substitute a similar-looking path from another repo.
 
 ### Never Reference Sibling Checkouts in Build Files
 
 Build files (Makefile, shell scripts, CI config) must **never** resolve a
-dependency via a relative sibling path (`../jerboa-foo`) or an absolute
-`~/mine/jerboa-foo` path. That layout is specific to this one machine —
+dependency via a relative sibling path (`..`-relative) or an absolute machine-specific sibling path. That layout is specific to this one machine —
 other users and CI do not have it. Always vendor instead: fetch/clone the
 dependency into `vendor/` (or this repo's equivalent) at build time, or use
 a pinned-release fetch script, so the build is reproducible without
@@ -427,7 +444,7 @@ A sibling-path fallback is not just a portability bug: it can silently
 substitute a full alternate source tree (build config, embedded data,
 secrets) for the vendored one, with no equivalent safety default, changing
 what actually gets built without any indication. If you find one
-(`grep -rn '\.\./jerboa\|~/mine/jerboa'` over Makefiles/scripts), remove it
+(for example, any sibling-checkout reference in Makefiles or scripts), remove it
 and vendor properly instead.
 
 ---
diff --git a/Makefile b/Makefile
index eb12d0a..be06e3c 100644
--- a/Makefile
+++ b/Makefile
@@ -60,7 +60,7 @@ CHEZ_INSTALL_FLAGS = \
 	--as-is \
 	$(CHEZ_TERMUX_CONFIGURE_VARS) \
 	$(CHEZ_CONFIGURE_EXTRA)
-LIBDIRS = $(JERBOA_HOME)/lib:$(JERBOA_HOME)/vendor/jsqlite/src
+LIBDIRS = $(JERBOA_HOME):$(JERBOA_HOME)/lib:$(JERBOA_HOME)/vendor/jsqlite/src
 SOURCE_BALANCE_RUNNER ?= $(SCHEME) --libdirs $(LIBDIRS) --script
 # Base directory for chez-* repos (legacy C FFI — see `make native` for Rust backend)
 JERBOA_EXT_DIR ?= $(HOME)/src
@@ -302,7 +302,7 @@ LLVM_BIN ?= $(shell if command -v llvm-as >/dev/null 2>&1; then dirname "$$(comm
 TYPED_WRAPPER_DIR ?= build/typed/jerboa
 .PHONY: typed-llvmir-focused-parity-suite typed-llvmir-bytes-parity typed-llvmir-for-parity typed-llvmir-list-parity typed-llvmir-map-parity typed-llvmir-pair-parity typed-llvmir-nullable-parity typed-llvmir-hashmap-empty-parity typed-llvmir-hashmap-single-parity typed-llvmir-hashmap-fold-parity typed-llvmir-hashmap-multi-parity typed-llvmir-regex-parity typed-llvmir-unicode-string-parity
 
-.PHONY: help chez static-supported-check chez-cross build binary binary-typed binary-typed-smoke binary-typed-uri-smoke binary-typed-json-smoke binary-cross native-cross pure-audit typecheck typed-rust typed-rust-focused-smoke-suite typed-rust-crate-metadata-smoke typed-rust-hashmap-smoke typed-rust-list-smoke typed-rust-map-smoke typed-rust-set-smoke typed-rust-mutable-list-smoke typed-rust-pair-smoke typed-rust-nullable-smoke typed-rust-string-ops-smoke typed-rust-jvm-helpers-smoke typed-rust-jvm-arrays-smoke typed-rust-jvm-json-smoke typed-rust-try-throw-smoke typed-rust-direct-throw-smoke typed-json-value-smoke typed-json-value-corpus-check typed-json-value-diff typed-json-value-diff-repro typed-json-value-bench typed-json-value-public-smoke typed-json-scan-corpus-check typed-bench typed-uri-pilot typed-uri-corpus-check typed-uri-diff typed-uri-diff-repro typed-uri-bench typed-uri-wrapper-smoke typed-uri-public-smoke typed-json-scan-diff typed-json-scan-bench typed-llvmir typed-llvmir-check typed-llvmir-leak-check typed-llvmir-leak-suite typed-llvmir-wasm-object-smoke typed-llvmir-wasm-runtime-smoke typed-llvmir-wasm-browser-smoke typed-llvmir-wasm-suite typed-llvmir-wasm-suite-release wasm-gc-release-gate typed-llvmir-smoke typed-llvmir-parity typed-llvmir-focused-parity-suite typed-llvmir-try-throw-parity typed-llvmir-bytes-parity typed-llvmir-list-parity typed-llvmir-mutable-list-parity typed-llvmir-set-parity typed-llvmir-map-parity typed-llvmir-jvm-arrays-parity typed-llvmir-pair-parity typed-llvmir-nullable-parity typed-llvmir-regex-parity typed-llvmir-unicode-string-parity typed-wrappers typed-build typed-wrapper-smoke typed-split-tree-smoke typed-test typed-clean test test-known-flaky test-reader test-core test-runtime test-try-debug test-stdlib test-ffi test-modules test-expanded test-contract test-ergo test-sqlite-robustness test-limits-primitives test-typed-core test-typed-parser test-typed-checker test-typed-rust test-typed-kotlin test-typed-llvmir test-typed-wrappers test-pure-audit test-features test-wrappers test-phase4a test-phase4b test-phase4c test-phase4d test-phase4e test-phase5 test-phase5e test-phase6 test-phase7 test-phase8 test-functional test-repl test-security test-security-profile test-native test-gaps native clean-native audit audit-native jpkg-audit vendor-jsqlite-security-check native-export-review-check tcb-drift-check import-policy-check source-balance restrict-closure-check security-audit clean security security-production security-profile security-hardware-smoke sbom reproducibility-report reproducibility-compare verify release-evidence fuzz fuzz-smoke fuzz-deep fuzz-reader-fuzz fuzz-json-fuzz fuzz-http2-fuzz fuzz-dns-fuzz fuzz-pregexp-fuzz fuzz-csv-fuzz fuzz-format-fuzz fuzz-uri-fuzz fuzz-base64-fuzz fuzz-hex-fuzz fuzz-router-fuzz fuzz-sandbox-fuzz test-rawstring test-regex test-rx test-peg test-regex-all check-docs check-docs-strict data-check podman podman-build podman-push lint
+.PHONY: help chez static-supported-check chez-cross build binary binary-smoke binary-typed binary-typed-smoke binary-typed-uri-smoke binary-typed-json-smoke binary-cross native-cross pure-audit typecheck typed-rust typed-rust-focused-smoke-suite typed-rust-crate-metadata-smoke typed-rust-hashmap-smoke typed-rust-list-smoke typed-rust-map-smoke typed-rust-set-smoke typed-rust-mutable-list-smoke typed-rust-pair-smoke typed-rust-nullable-smoke typed-rust-string-ops-smoke typed-rust-jvm-helpers-smoke typed-rust-jvm-arrays-smoke typed-rust-jvm-json-smoke typed-rust-try-throw-smoke typed-rust-direct-throw-smoke typed-json-value-smoke typed-json-value-corpus-check typed-json-value-diff typed-json-value-diff-repro typed-json-value-bench typed-json-value-public-smoke typed-json-scan-corpus-check typed-bench typed-uri-pilot typed-uri-corpus-check typed-uri-diff typed-uri-diff-repro typed-uri-bench typed-uri-wrapper-smoke typed-uri-public-smoke typed-json-scan-diff typed-json-scan-bench typed-llvmir typed-llvmir-check typed-llvmir-leak-check typed-llvmir-leak-suite typed-llvmir-wasm-object-smoke typed-llvmir-wasm-runtime-smoke typed-llvmir-wasm-browser-smoke typed-llvmir-wasm-suite typed-llvmir-wasm-suite-release wasm-gc-release-gate typed-llvmir-smoke typed-llvmir-parity typed-llvmir-focused-parity-suite typed-llvmir-try-throw-parity typed-llvmir-bytes-parity typed-llvmir-list-parity typed-llvmir-mutable-list-parity typed-llvmir-set-parity typed-llvmir-map-parity typed-llvmir-jvm-arrays-parity typed-llvmir-pair-parity typed-llvmir-nullable-parity typed-llvmir-regex-parity typed-llvmir-unicode-string-parity typed-wrappers typed-build typed-wrapper-smoke typed-split-tree-smoke typed-test typed-clean test test-known-flaky test-reader test-core test-runtime test-try-debug test-stdlib test-ffi test-modules test-expanded test-contract test-ergo test-sqlite-robustness test-limits-primitives test-typed-core test-typed-parser test-typed-checker test-typed-rust test-typed-kotlin test-typed-llvmir test-typed-wrappers test-pure-audit test-features test-wrappers test-phase4a test-phase4b test-phase4c test-phase4d test-phase4e test-phase5 test-phase5e test-phase6 test-phase7 test-phase8 test-functional test-repl test-security test-security-profile test-native test-gaps native clean-native audit audit-native jpkg-audit vendor-jsqlite-security-check native-export-review-check tcb-drift-check import-policy-check source-balance restrict-closure-check security-audit clean security security-production security-profile security-hardware-smoke sbom reproducibility-report reproducibility-compare verify release-evidence fuzz fuzz-smoke fuzz-deep fuzz-reader-fuzz fuzz-json-fuzz fuzz-http2-fuzz fuzz-dns-fuzz fuzz-pregexp-fuzz fuzz-csv-fuzz fuzz-format-fuzz fuzz-uri-fuzz fuzz-base64-fuzz fuzz-hex-fuzz fuzz-router-fuzz fuzz-sandbox-fuzz test-rawstring test-regex test-rx test-peg test-regex-all check-docs check-docs-strict data-check podman podman-build podman-push lint
 .PHONY: check-cross-tools fuzz-websocket-fuzz jlsp jlsp-freebsd-amd64 \
         jlsp-install jlsp-linux-amd64 jlsp-portable jmcp-freebsd-amd64 \
         jmcp-freebsd-arm64 jmcp-linux-amd64 jmcp-linux-arm64 \
@@ -590,6 +590,10 @@ BINARY_TYPED_SOURCES :=
 ifeq ($(BINARY_TYPED_URI),1)
 BINARY_TYPED_SOURCES += $(BINARY_TYPED_URI_SOURCES)
 endif
+
+binary-smoke: binary
+	@./$(BINARY_OUTPUT) --version | grep -F "jerboa-bin $(PROJECT_VERSION)"
+	@./$(BINARY_OUTPUT) --help >/dev/null
 ifeq ($(BINARY_TYPED_JSON),1)
 BINARY_TYPED_SOURCES += $(BINARY_TYPED_JSON_SOURCES)
 endif
@@ -602,9 +606,10 @@ ifneq ($(strip $(BINARY_TYPED_SOURCES)),)
 	@archive="$(BINARY_TYPED_RUST_DIR)/target/debug/libjerboa_typed_generated.a"; \
 	  test -f "$$archive" || { echo "ERROR: typed Rust .a not found at $$archive" >&2; exit 1; }; \
 	  JERBOA_TYPED_RUST_ARCHIVE="$$archive" \
+	  JERBOA_BUILD_VERSION="$(PROJECT_VERSION)" \
 	  SCHEME=$(SCHEME) JERBOA_CHEZ_PREFIX=$(CHEZ_PREFIX) BINARY_STATIC=$(STATIC) support/build-binary.sh $(BINARY_ENTRY) $(BINARY_OUTPUT)
 else
-	SCHEME=$(SCHEME) JERBOA_CHEZ_PREFIX=$(CHEZ_PREFIX) BINARY_STATIC=$(STATIC) support/build-binary.sh $(BINARY_ENTRY) $(BINARY_OUTPUT)
+	JERBOA_BUILD_VERSION="$(PROJECT_VERSION)" SCHEME=$(SCHEME) JERBOA_CHEZ_PREFIX=$(CHEZ_PREFIX) BINARY_STATIC=$(STATIC) support/build-binary.sh $(BINARY_ENTRY) $(BINARY_OUTPUT)
 endif
 
 # ── jerbuild standalone binary ───────────────────────────────────────────────
@@ -1520,8 +1525,16 @@ TEST_QUARANTINE_FILES := \
 	tests/test-wrapper-ssl.ss \
 	tests/test-wrapper-zlib.ss \
 	tests/test-wrappers.ss
-TEST_RUN_FILES := $(filter-out $(TEST_QUARANTINE_FILES),$(TEST_FILES))
-
+# These end-to-end programs consume binaries/wrappers produced by their
+# dedicated smoke targets.  release-evidence runs those targets with the
+# required generated artifacts and runtime environment.
+TEST_GENERATED_ARTIFACT_FILES := \
+	tests/test-typed-json-value-public-binary-e2e.ss \
+	tests/test-typed-uri-public-binary-e2e.ss \
+	tests/test-typed-uri-wrapper-e2e.ss
+TEST_RUN_FILES := $(filter-out $(TEST_QUARANTINE_FILES) $(TEST_GENERATED_ARTIFACT_FILES),$(TEST_FILES))
+
+test: JERBOA_NATIVE_FEATURES := full,sqlite
 test: native
 	@set -e; \
 	for t in $(TEST_RUN_FILES); do \
@@ -2546,6 +2559,7 @@ test-ergo:
 	@$(SCHEME) --libdirs $(LIBDIRS) --script tests/test-ergo.ss
 	@$(SCHEME) --libdirs $(LIBDIRS) --script tests/test-jerboa-prelude-ergo.ss
 
+test-sqlite-robustness: JERBOA_NATIVE_FEATURES := full,sqlite
 test-sqlite-robustness: native
 	@$(NATIVE_TEST_ENV) $(SCHEME) --libdirs $(LIBDIRS) --script tests/test-sqlite-robustness.ss
 
diff --git a/VERSION b/VERSION
index 1866a36..13dead7 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.2.9
+0.2.10
diff --git a/data/error-fixes.sexp b/data/error-fixes.sexp
index 5324be3..5b6bb53 100644
--- a/data/error-fixes.sexp
+++ b/data/error-fixes.sexp
@@ -2545,10 +2545,10 @@
     "packages:\n- build-essential\n- libncurses-dev\n\n# Alternative for no-curses builds:\n# vendor/ChezScheme/configure --disable-curses ...")
    ("explanation"
      .
-     "Chez Scheme bootquick links the bootstrap Scheme binary with -lncurses when curses support is enabled. Minimal Debian/SourceHut images can have runtime ncurses pieces but not the development symlink/library needed by the linker.")
+     "Chez Scheme bootquick links the bootstrap Scheme binary with -lncurses when curses support is enabled. Minimal Debian/Forgejo runner images can have runtime ncurses pieces but not the development symlink/library needed by the linker.")
    ("fix"
      .
-     "Install the ncurses development package in the build image, e.g. add libncurses-dev to .builds/ci.yml packages on Debian, or configure Chez with --disable-curses when curses support is intentionally omitted.")
+     "Install the ncurses development package in the build image, e.g. add libncurses-dev to .forgejo/workflows/ci.yaml packages on Debian, or configure Chez with --disable-curses when curses support is intentionally omitted.")
    ("id" . "chez-bootquick-missing-ncurses-dev")
    ("pattern"
      .
@@ -3418,4 +3418,12 @@
    ("pattern"
      .
      "Killed: 9.*(jerboa|jerbuild)|CODESIGNING.*Invalid Page|fatal 309")
+   ("type" . "runtime"))
+ (("fix"
+    .
+    "Do not weaken std/native path validation. Build or copy the executable and its native runtime into a private, non-group/world-writable directory (for example, a checkout below the user's home directory), then rerun the smoke test there. CI workspaces must likewise have trusted parent-directory permissions.")
+   ("id" . "native-runtime-rejects-world-writable-worktree")
+   ("pattern"
+    .
+    "native path component is group/world-writable")
    ("type" . "runtime")))
diff --git a/docs/jpkg-guide.md b/docs/jpkg-guide.md
index b5f13bb..6b082e5 100644
--- a/docs/jpkg-guide.md
+++ b/docs/jpkg-guide.md
@@ -218,7 +218,7 @@ Global: `jpkg --help`, `jpkg --version`. Every command also works as
 | Command | What it does |
 |---|---|
 | `jpkg init [NAME]` | Create `jpkg.sexp`, `jpkg.policy.sexp`, and an empty `jpkg.lock` (NAME defaults to `@local/<dir>`). |
-| `jpkg new NAME` | Scaffold a new package directory with manifest, strict policy, lockfile, `src/main.ss`, README, and `.build.yml`. |
+| `jpkg new NAME` | Scaffold a new package directory with manifest, strict policy, lockfile, `src/main.ss`, README, and `.forgejo/workflows/ci.yaml`. |
 | `jpkg add PKG[@VERSION]` | Add a dependency (range), resolve, write lock, install. |
 | `jpkg remove PKG` | Drop a dependency, re-resolve, prune the environment. |
 | `jpkg install [PKG[@VERSION]]` | Install a host-specific executable globally, or with no argument install **exactly** `jpkg.lock`. |
diff --git a/docs/kimi3-security-recommmendations.md b/docs/kimi3-security-recommmendations.md
index 1d616f3..0d66ad1 100644
--- a/docs/kimi3-security-recommmendations.md
+++ b/docs/kimi3-security-recommmendations.md
@@ -1055,7 +1055,7 @@ lockfile committed, and `jpkg audit` in their CI template. Update
 - **Status:** complete for generated jpkg projects. `jpkg init` now creates
   `jpkg.sexp`, strict `jpkg.policy.sexp` requiring signatures and provenance,
   and an empty `jpkg.lock` in the current directory. `jpkg new` scaffolds the
-  same policy/lock defaults plus `.build.yml` with `jpkg verify --strict`,
+  same policy/lock defaults plus `.forgejo/workflows/ci.yaml` with `jpkg verify --strict`,
   `jpkg audit`, and `jpkg build`. `docs/jpkg-guide.md` documents these
   defaults in the quickstart and command table.
 
diff --git a/docs/release-artifacts.md b/docs/release-artifacts.md
index c633d14..729fd09 100644
--- a/docs/release-artifacts.md
+++ b/docs/release-artifacts.md
@@ -481,14 +481,11 @@ supported split gate on hosts where remote automation has been enabled.
 
 ## Release builders
 
-The checked-in `.builds/release-*.yml` files are legacy build manifests. They
-describe the native Linux and FreeBSD release targets but are not an official
-artifact host:
+The checked-in Forgejo release workflow builds and runs the native Linux and
+FreeBSD artifacts before promotion:
 
 ```text
-.builds/release-linux-amd64.yml
-.builds/release-linux-arm64.yml
-.builds/release-freebsd-amd64.yml
+.forgejo/workflows/release.yaml
 ```
 
 The `macos-arm64` artifact is produced on an Apple Silicon macOS host with the
diff --git a/docs/reviews/2026-07-27-native-export-decisions.sexp b/docs/reviews/2026-07-27-native-export-decisions.sexp
index dac75b9..6b932bb 100644
--- a/docs/reviews/2026-07-27-native-export-decisions.sexp
+++ b/docs/reviews/2026-07-27-native-export-decisions.sexp
@@ -9,4 +9,39 @@
     (export (symbol "embed_encrypt") (decision retain-standalone-c-abi) (reason "binary embedding and encrypted-boot support API, intentionally consumed outside Scheme source"))
     (export (symbol "embed_pbkdf2_sha256") (decision retain-standalone-c-abi) (reason "binary embedding and encrypted-boot support API, intentionally consumed outside Scheme source"))
     (export (symbol "embed_random_bytes") (decision retain-standalone-c-abi) (reason "binary embedding and encrypted-boot support API, intentionally consumed outside Scheme source"))
-    (export (symbol "embed_read_passphrase") (decision retain-standalone-c-abi) (reason "binary embedding and encrypted-boot support API, intentionally consumed outside Scheme source"))))
+    (export (symbol "embed_read_passphrase") (decision retain-standalone-c-abi) (reason "binary embedding and encrypted-boot support API, intentionally consumed outside Scheme source"))
+    (export (symbol "jerboa_aproc_close") (decision retain-standalone-c-abi) (reason "consumed by sibling Jerboa static-binary symbol registries outside this repository"))
+    (export (symbol "jerboa_aproc_dup") (decision retain-standalone-c-abi) (reason "consumed by sibling Jerboa static-binary symbol registries outside this repository"))
+    (export (symbol "jerboa_freebsd_is_traced") (decision retain-standalone-c-abi) (reason "consumed by FreeBSD sibling applications and their static-binary symbol registries"))
+    (export (symbol "jerboa_freebsd_process_count") (decision retain-standalone-c-abi) (reason "consumed by FreeBSD sibling applications and their static-binary symbol registries"))
+    (export (symbol "jerboa_hkdf_sha256") (decision retain-standalone-c-abi) (reason "consumed by sibling cryptography modules and static-binary symbol registries"))
+    (export (symbol "jerboa_kill_probe") (decision retain-standalone-c-abi) (reason "consumed by sibling process-monitoring modules and static-binary symbol registries"))
+    (export (symbol "jerboa_md5") (decision retain-standalone-c-abi) (reason "consumed by sibling static-binary symbol registries and compatibility shims"))
+    (export (symbol "jerboa_mlockall") (decision retain-standalone-c-abi) (reason "consumed by sibling process-hardening modules and static-binary symbol registries"))
+    (export (symbol "jerboa_prctl_set_name") (decision retain-standalone-c-abi) (reason "consumed by sibling process-control modules and static-binary symbol registries"))
+    (export (symbol "jerboa_proc_self_exe") (decision retain-standalone-c-abi) (reason "consumed by sibling integrity modules and static-binary symbol registries"))
+    (export (symbol "jerboa_regex_compile_ex") (decision retain-standalone-c-abi) (reason "consumed by sibling static-binary symbol registries and native regex compatibility shims"))
+    (export (symbol "jerboa_setproctitle") (decision retain-standalone-c-abi) (reason "consumed by sibling process-control modules and static-binary symbol registries"))
+    (export (symbol "jerboa_sha256_ctx_final") (decision retain-standalone-c-abi) (reason "consumed by sibling incremental-hash static binaries outside this repository"))
+    (export (symbol "jerboa_sha256_ctx_free") (decision retain-standalone-c-abi) (reason "consumed by sibling incremental-hash static binaries outside this repository"))
+    (export (symbol "jerboa_sha256_ctx_new") (decision retain-standalone-c-abi) (reason "consumed by sibling incremental-hash static binaries outside this repository"))
+    (export (symbol "jerboa_sha256_ctx_update") (decision retain-standalone-c-abi) (reason "consumed by sibling incremental-hash static binaries outside this repository"))
+    (export (symbol "jerboa_sm_fuel_remaining") (decision retain-standalone-c-abi) (reason "consumed by sibling static-binary WASM runtime integrations outside this repository"))
+    (export (symbol "jerboa_sm_memory_read") (decision retain-standalone-c-abi) (reason "consumed by sibling static-binary WASM runtime integrations outside this repository"))
+    (export (symbol "jerboa_sm_memory_size") (decision retain-standalone-c-abi) (reason "consumed by sibling static-binary WASM runtime integrations outside this repository"))
+    (export (symbol "jerboa_sm_memory_write") (decision retain-standalone-c-abi) (reason "consumed by sibling static-binary WASM runtime integrations outside this repository"))
+    (export (symbol "jerboa_socks5_server_port") (decision retain-standalone-c-abi) (reason "consumed by sibling shell static binaries outside this repository"))
+    (export (symbol "jerboa_socks5_server_start") (decision retain-standalone-c-abi) (reason "consumed by sibling shell static binaries outside this repository"))
+    (export (symbol "jerboa_socks5_server_stats") (decision retain-standalone-c-abi) (reason "consumed by sibling shell static binaries outside this repository"))
+    (export (symbol "jerboa_socks5_server_stop") (decision retain-standalone-c-abi) (reason "consumed by sibling shell static binaries outside this repository"))
+    (export (symbol "jerboa_tls_connect_mtls_mem") (decision retain-standalone-c-abi) (reason "consumed by sibling shell and editor static binaries outside this repository"))
+    (export (symbol "jerboa_tls_connect_mtls_pem_ca") (decision retain-standalone-c-abi) (reason "consumed by sibling shell and editor static binaries outside this repository"))
+    (export (symbol "jerboa_tls_server_new_mtls_pem") (decision retain-standalone-c-abi) (reason "consumed by sibling shell and editor static binaries outside this repository"))
+    (export (symbol "jerboa_tls_server_new_pem") (decision retain-standalone-c-abi) (reason "consumed by sibling shell, editor, and code static binaries outside this repository"))
+    (export (symbol "jerboa_wasm_allow_cdb_dir") (decision retain-standalone-c-abi) (reason "consumed by sibling code and shell static-binary WASM integrations"))
+    (export (symbol "jerboa_wasm_set_socket") (decision retain-standalone-c-abi) (reason "consumed by sibling code and shell static-binary WASM integrations"))
+    (export (symbol "jerboa_x25519_diffie_hellman") (decision retain-standalone-c-abi) (reason "consumed by sibling cryptography modules and static binaries outside this repository"))
+    (export (symbol "jerboa_x25519_generate_keypair") (decision retain-standalone-c-abi) (reason "consumed by sibling cryptography modules and static binaries outside this repository"))
+    (export (symbol "jerboa_x25519_public_from_private") (decision retain-standalone-c-abi) (reason "consumed by sibling cryptography modules and static binaries outside this repository"))
+    (export (symbol "jerboa_x509_generate_self_signed_mem") (decision retain-standalone-c-abi) (reason "consumed by sibling shell, editor, and code static binaries outside this repository"))
+    (export (symbol "jerboa_x509_generate_signed_by_ca_mem") (decision retain-standalone-c-abi) (reason "consumed by sibling shell and editor static binaries outside this repository"))))
diff --git a/docs/reviews/2026-07-27-native-export-review.sexp b/docs/reviews/2026-07-27-native-export-review.sexp
index 139b1a7..e95a174 100644
--- a/docs/reviews/2026-07-27-native-export-review.sexp
+++ b/docs/reviews/2026-07-27-native-export-review.sexp
@@ -2,7 +2,7 @@
   (schema "jerboa.native-export-review/1")
   (generated-by "support/check-native-export-review.sh")
   (policy scheme-callers-or-documented)
-  (summary (exports 169) (scheme-referenced 162) (no-scheme-reference 7))
+  (summary (exports 204) (scheme-referenced 162) (no-scheme-reference 42))
   (exports
     (export (symbol "ed25519_derive_pubkey_standalone") (file "jerboa-native-rs/src/ed25519.rs") (line 50) (scheme-callers 0 (none)))
     (export (symbol "ed25519_sign_standalone") (file "jerboa-native-rs/src/ed25519.rs") (line 9) (scheme-callers 0 (none)))
@@ -11,23 +11,25 @@
     (export (symbol "embed_pbkdf2_sha256") (file "jerboa-native-rs/src/embed_crypto.rs") (line 19) (scheme-callers 0 (none)))
     (export (symbol "embed_random_bytes") (file "jerboa-native-rs/src/embed_crypto.rs") (line 188) (scheme-callers 0 (none)))
     (export (symbol "embed_read_passphrase") (file "jerboa-native-rs/src/embed_crypto.rs") (line 213) (scheme-callers 0 (none)))
-    (export (symbol "jerboa_aead_open") (file "jerboa-native-rs/src/crypto.rs") (line 431) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 214))))
-    (export (symbol "jerboa_aead_seal") (file "jerboa-native-rs/src/crypto.rs") (line 343) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 194))))
+    (export (symbol "jerboa_aead_open") (file "jerboa-native-rs/src/crypto.rs") (line 436) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 214))))
+    (export (symbol "jerboa_aead_seal") (file "jerboa-native-rs/src/crypto.rs") (line 348) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 194))))
     (export (symbol "jerboa_antidebug_check_all") (file "jerboa-native-rs/src/antidebug.rs") (line 157) (scheme-callers 1 (caller (file "lib/std/os/antidebug.ss") (line 46))))
     (export (symbol "jerboa_antidebug_check_breakpoint") (file "jerboa-native-rs/src/antidebug.rs") (line 105) (scheme-callers 1 (caller (file "lib/std/os/antidebug.ss") (line 42))))
     (export (symbol "jerboa_antidebug_check_ld_preload") (file "jerboa-native-rs/src/antidebug.rs") (line 67) (scheme-callers 1 (caller (file "lib/std/os/antidebug.ss") (line 40))))
     (export (symbol "jerboa_antidebug_check_tracer") (file "jerboa-native-rs/src/antidebug.rs") (line 37) (scheme-callers 1 (caller (file "lib/std/os/antidebug.ss") (line 38))))
     (export (symbol "jerboa_antidebug_ptrace") (file "jerboa-native-rs/src/antidebug.rs") (line 8) (scheme-callers 1 (caller (file "lib/std/os/antidebug.ss") (line 36))))
     (export (symbol "jerboa_antidebug_timing_check") (file "jerboa-native-rs/src/antidebug.rs") (line 129) (scheme-callers 1 (caller (file "lib/std/os/antidebug.ss") (line 44))))
-    (export (symbol "jerboa_aproc_killpg") (file "jerboa-native-rs/src/aproc.rs") (line 1083) (scheme-callers 1 (caller (file "lib/std/os/aproc.ss") (line 224))))
-    (export (symbol "jerboa_aproc_set_nonblock") (file "jerboa-native-rs/src/aproc.rs") (line 1053) (scheme-callers 1 (caller (file "lib/std/os/aproc.ss") (line 220))))
+    (export (symbol "jerboa_aproc_close") (file "jerboa-native-rs/src/aproc.rs") (line 1046) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_aproc_dup") (file "jerboa-native-rs/src/aproc.rs") (line 1028) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_aproc_killpg") (file "jerboa-native-rs/src/aproc.rs") (line 1085) (scheme-callers 1 (caller (file "lib/std/os/aproc.ss") (line 224))))
+    (export (symbol "jerboa_aproc_set_nonblock") (file "jerboa-native-rs/src/aproc.rs") (line 1055) (scheme-callers 1 (caller (file "lib/std/os/aproc.ss") (line 220))))
     (export (symbol "jerboa_aproc_spawn") (file "jerboa-native-rs/src/aproc.rs") (line 506) (scheme-callers 2 (caller (file "lib/std/os/aproc.ss") (line 195)) (caller (file "lib/std/os/aproc.ss") (line 214))))
     (export (symbol "jerboa_aproc_spawn_pty") (file "jerboa-native-rs/src/aproc.rs") (line 783) (scheme-callers 1 (caller (file "lib/std/os/aproc.ss") (line 214))))
-    (export (symbol "jerboa_aproc_wait4") (file "jerboa-native-rs/src/aproc.rs") (line 1099) (scheme-callers 1 (caller (file "lib/std/os/aproc.ss") (line 228))))
-    (export (symbol "jerboa_argon2id_hash") (file "jerboa-native-rs/src/crypto.rs") (line 814) (scheme-callers 2 (caller (file "lib/std/crypto/native-rust.ss") (line 330)) (caller (file "lib/std/crypto/password.ss") (line 35))))
-    (export (symbol "jerboa_argon2id_verify") (file "jerboa-native-rs/src/crypto.rs") (line 867) (scheme-callers 2 (caller (file "lib/std/crypto/native-rust.ss") (line 350)) (caller (file "lib/std/crypto/password.ss") (line 42))))
-    (export (symbol "jerboa_chacha20_open") (file "jerboa-native-rs/src/crypto.rs") (line 606) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 257))))
-    (export (symbol "jerboa_chacha20_seal") (file "jerboa-native-rs/src/crypto.rs") (line 519) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 236))))
+    (export (symbol "jerboa_aproc_wait4") (file "jerboa-native-rs/src/aproc.rs") (line 1101) (scheme-callers 1 (caller (file "lib/std/os/aproc.ss") (line 228))))
+    (export (symbol "jerboa_argon2id_hash") (file "jerboa-native-rs/src/crypto.rs") (line 819) (scheme-callers 2 (caller (file "lib/std/crypto/native-rust.ss") (line 330)) (caller (file "lib/std/crypto/password.ss") (line 35))))
+    (export (symbol "jerboa_argon2id_verify") (file "jerboa-native-rs/src/crypto.rs") (line 872) (scheme-callers 2 (caller (file "lib/std/crypto/native-rust.ss") (line 350)) (caller (file "lib/std/crypto/password.ss") (line 42))))
+    (export (symbol "jerboa_chacha20_open") (file "jerboa-native-rs/src/crypto.rs") (line 611) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 257))))
+    (export (symbol "jerboa_chacha20_seal") (file "jerboa-native-rs/src/crypto.rs") (line 524) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 236))))
     (export (symbol "jerboa_deflate") (file "jerboa-native-rs/src/compress.rs") (line 9) (scheme-callers 1 (caller (file "lib/std/compress/native-rust.ss") (line 61))))
     (export (symbol "jerboa_epoll_close") (file "jerboa-native-rs/src/epoll.rs") (line 106) (scheme-callers 1 (caller (file "lib/std/os/epoll-native.ss") (line 59))))
     (export (symbol "jerboa_epoll_create") (file "jerboa-native-rs/src/epoll.rs") (line 7) (scheme-callers 2 (caller (file "lib/std/os/epoll-native.ss") (line 30)) (caller (file "lib/std/os/epoll-native.ss") (line 50))))
@@ -36,10 +38,13 @@
     (export (symbol "jerboa_eventfd_create") (file "jerboa-native-rs/src/epoll.rs") (line 121) (scheme-callers 1 (caller (file "lib/std/os/epoll-native.ss") (line 293))))
     (export (symbol "jerboa_eventfd_drain") (file "jerboa-native-rs/src/epoll.rs") (line 155) (scheme-callers 1 (caller (file "lib/std/os/epoll-native.ss") (line 299))))
     (export (symbol "jerboa_eventfd_signal") (file "jerboa-native-rs/src/epoll.rs") (line 135) (scheme-callers 1 (caller (file "lib/std/os/epoll-native.ss") (line 296))))
+    (export (symbol "jerboa_freebsd_is_traced") (file "jerboa-native-rs/src/process_ctl.rs") (line 110) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_freebsd_process_count") (file "jerboa-native-rs/src/process_ctl.rs") (line 158) (scheme-callers 0 (none)))
     (export (symbol "jerboa_gunzip") (file "jerboa-native-rs/src/compress.rs") (line 162) (scheme-callers 1 (caller (file "lib/std/compress/native-rust.ss") (line 73))))
     (export (symbol "jerboa_gzip") (file "jerboa-native-rs/src/compress.rs") (line 116) (scheme-callers 1 (caller (file "lib/std/compress/native-rust.ss") (line 69))))
-    (export (symbol "jerboa_hmac_sha256") (file "jerboa-native-rs/src/crypto.rs") (line 206) (scheme-callers 2 (caller (file "lib/std/crypto/native-rust.ss") (line 157)) (caller (file "lib/std/crypto/native-rust.ss") (line 170))))
-    (export (symbol "jerboa_hmac_sha256_verify") (file "jerboa-native-rs/src/crypto.rs") (line 245) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 170))))
+    (export (symbol "jerboa_hkdf_sha256") (file "jerboa-native-rs/src/x25519.rs") (line 111) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_hmac_sha256") (file "jerboa-native-rs/src/crypto.rs") (line 211) (scheme-callers 2 (caller (file "lib/std/crypto/native-rust.ss") (line 157)) (caller (file "lib/std/crypto/native-rust.ss") (line 170))))
+    (export (symbol "jerboa_hmac_sha256_verify") (file "jerboa-native-rs/src/crypto.rs") (line 250) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 170))))
     (export (symbol "jerboa_http_parse") (file "jerboa-native-rs/src/http_parse.rs") (line 31) (scheme-callers 4 (caller (file "lib/std/net/fiber-httpd.ss") (line 78)) (caller (file "lib/std/net/fiber-httpd.ss") (line 81)) (caller (file "lib/std/net/httpsd.ss") (line 28)) (caller (file "lib/std/net/httpsd.ss") (line 71))))
     (export (symbol "jerboa_inflate") (file "jerboa-native-rs/src/compress.rs") (line 55) (scheme-callers 1 (caller (file "lib/std/compress/native-rust.ss") (line 65))))
     (export (symbol "jerboa_inotify_add_watch") (file "jerboa-native-rs/src/inotify_native.rs") (line 35) (scheme-callers 1 (caller (file "lib/std/os/inotify-native.ss") (line 65))))
@@ -52,14 +57,17 @@
     (export (symbol "jerboa_integrity_hash_self") (file "jerboa-native-rs/src/integrity.rs") (line 68) (scheme-callers 1 (caller (file "lib/std/os/integrity.ss") (line 53))))
     (export (symbol "jerboa_integrity_sign_verify") (file "jerboa-native-rs/src/integrity.rs") (line 141) (scheme-callers 1 (caller (file "lib/std/os/integrity.ss") (line 57))))
     (export (symbol "jerboa_integrity_verify_hash") (file "jerboa-native-rs/src/integrity.rs") (line 101) (scheme-callers 1 (caller (file "lib/std/os/integrity.ss") (line 55))))
+    (export (symbol "jerboa_kill_probe") (file "jerboa-native-rs/src/process_ctl.rs") (line 65) (scheme-callers 0 (none)))
     (export (symbol "jerboa_landlock_abi_version") (file "jerboa-native-rs/src/landlock.rs") (line 68) (scheme-callers 6 (caller (file "lib/std/os/landlock-native.ss") (line 78)) (caller (file "lib/std/os/landlock.ss") (line 12)) (caller (file "lib/std/os/landlock.ss") (line 56)) (caller (file "lib/std/os/landlock.ss") (line 57)) (caller (file "lib/std/os/limits/sandbox.ss") (line 455)) (caller (file "lib/std/os/sandbox.ss") (line 75))))
     (export (symbol "jerboa_landlock_add_net_rule") (file "jerboa-native-rs/src/landlock.rs") (line 234) (scheme-callers 1 (caller (file "lib/std/os/landlock-native.ss") (line 86))))
     (export (symbol "jerboa_landlock_add_path_rule") (file "jerboa-native-rs/src/landlock.rs") (line 129) (scheme-callers 1 (caller (file "lib/std/os/landlock-native.ss") (line 83))))
     (export (symbol "jerboa_landlock_create_ruleset") (file "jerboa-native-rs/src/landlock.rs") (line 97) (scheme-callers 1 (caller (file "lib/std/os/landlock-native.ss") (line 80))))
     (export (symbol "jerboa_landlock_enforce") (file "jerboa-native-rs/src/landlock.rs") (line 276) (scheme-callers 1 (caller (file "lib/std/os/landlock-native.ss") (line 89))))
     (export (symbol "jerboa_last_error") (file "jerboa-native-rs/src/panic.rs") (line 9) (scheme-callers 11 (caller (file "lib/std/compress/native-rust.ss") (line 76)) (caller (file "lib/std/crypto/native-rust.ss") (line 86)) (caller (file "lib/std/crypto/x509.ss") (line 24)) (caller (file "lib/std/native.ss") (line 56)) (caller (file "lib/std/net/tls-rustls.ss") (line 167)) (caller (file "lib/std/os/aproc.ss") (line 233)) (caller (file "lib/std/os/integrity.ss") (line 42)) (caller (file "lib/std/os/secure-output.ss") (line 47)) (caller (file "lib/std/pcap.ss") (line 66)) (caller (file "lib/std/regex-native.ss") (line 79)) (caller (file "lib/std/wasm/sandbox.ss") (line 196))))
-    (export (symbol "jerboa_pbkdf2_derive") (file "jerboa-native-rs/src/crypto.rs") (line 740) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 300))))
-    (export (symbol "jerboa_pbkdf2_verify") (file "jerboa-native-rs/src/crypto.rs") (line 773) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 315))))
+    (export (symbol "jerboa_md5") (file "jerboa-native-rs/src/crypto.rs") (line 59) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_mlockall") (file "jerboa-native-rs/src/process_ctl.rs") (line 41) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_pbkdf2_derive") (file "jerboa-native-rs/src/crypto.rs") (line 745) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 300))))
+    (export (symbol "jerboa_pbkdf2_verify") (file "jerboa-native-rs/src/crypto.rs") (line 778) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 315))))
     (export (symbol "jerboa_pcap_close") (file "jerboa-native-rs/src/pcap_capture.rs") (line 341) (scheme-callers 1 (caller (file "lib/std/pcap.ss") (line 58))))
     (export (symbol "jerboa_pcap_list_interfaces") (file "jerboa-native-rs/src/pcap_capture.rs") (line 371) (scheme-callers 1 (caller (file "lib/std/pcap.ss") (line 62))))
     (export (symbol "jerboa_pcap_next") (file "jerboa-native-rs/src/pcap_capture.rs") (line 269) (scheme-callers 1 (caller (file "lib/std/pcap.ss") (line 53))))
@@ -74,17 +82,20 @@
     (export (symbol "jerboa_pg_ncols") (file "jerboa-native-rs/src/postgres_native.rs") (line 236) (scheme-callers 1 (caller (file "lib/std/db/postgresql-native.ss") (line 34))))
     (export (symbol "jerboa_pg_nrows") (file "jerboa-native-rs/src/postgres_native.rs") (line 228) (scheme-callers 1 (caller (file "lib/std/db/postgresql-native.ss") (line 32))))
     (export (symbol "jerboa_pg_query") (file "jerboa-native-rs/src/postgres_native.rs") (line 182) (scheme-callers 1 (caller (file "lib/std/db/postgresql-native.ss") (line 30))))
-    (export (symbol "jerboa_random_bytes") (file "jerboa-native-rs/src/crypto.rs") (line 285) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 144))))
-    (export (symbol "jerboa_regex_captures") (file "jerboa-native-rs/src/regex_native.rs") (line 420) (scheme-callers 2 (caller (file "lib/std/regex-native.ss") (line 66)) (caller (file "lib/std/regex.ss") (line 110))))
+    (export (symbol "jerboa_prctl_set_name") (file "jerboa-native-rs/src/process_ctl.rs") (line 6) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_proc_self_exe") (file "jerboa-native-rs/src/process_ctl.rs") (line 251) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_random_bytes") (file "jerboa-native-rs/src/crypto.rs") (line 290) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 144))))
+    (export (symbol "jerboa_regex_captures") (file "jerboa-native-rs/src/regex_native.rs") (line 421) (scheme-callers 2 (caller (file "lib/std/regex-native.ss") (line 66)) (caller (file "lib/std/regex.ss") (line 110))))
     (export (symbol "jerboa_regex_compile") (file "jerboa-native-rs/src/regex_native.rs") (line 38) (scheme-callers 7 (caller (file "lib/jerboa/typed/llvmir.ss") (line 3179)) (caller (file "lib/jerboa/typed/llvmir.ss") (line 3193)) (caller (file "lib/std/regex-native.ss") (line 50)) (caller (file "lib/std/regex.ss") (line 81)) (caller (file "lib/std/regex.ss") (line 85)) (caller (file "tests/test-typed-llvmir.ss") (line 830)) (caller (file "tests/test-typed-llvmir.ss") (line 836))))
+    (export (symbol "jerboa_regex_compile_ex") (file "jerboa-native-rs/src/regex_native.rs") (line 299) (scheme-callers 0 (none)))
     (export (symbol "jerboa_regex_find") (file "jerboa-native-rs/src/regex_native.rs") (line 114) (scheme-callers 8 (caller (file "lib/jerboa/typed/llvmir.ss") (line 3181)) (caller (file "lib/jerboa/typed/llvmir.ss") (line 3235)) (caller (file "lib/std/regex-native.ss") (line 58)) (caller (file "lib/std/regex.ss") (line 91)) (caller (file "lib/std/regex.ss") (line 101)) (caller (file "lib/std/regex.ss") (line 709)) (caller (file "tests/test-typed-llvmir.ss") (line 832)) (caller (file "tests/test-typed-llvmir.ss") (line 838))))
-    (export (symbol "jerboa_regex_find_at") (file "jerboa-native-rs/src/regex_native.rs") (line 366) (scheme-callers 3 (caller (file "lib/std/regex-native.ss") (line 58)) (caller (file "lib/std/regex.ss") (line 101)) (caller (file "lib/std/regex.ss") (line 709))))
+    (export (symbol "jerboa_regex_find_at") (file "jerboa-native-rs/src/regex_native.rs") (line 367) (scheme-callers 3 (caller (file "lib/std/regex-native.ss") (line 58)) (caller (file "lib/std/regex.ss") (line 101)) (caller (file "lib/std/regex.ss") (line 709))))
     (export (symbol "jerboa_regex_free") (file "jerboa-native-rs/src/regex_native.rs") (line 282) (scheme-callers 6 (caller (file "lib/jerboa/typed/llvmir.ss") (line 3184)) (caller (file "lib/jerboa/typed/llvmir.ss") (line 3204)) (caller (file "lib/std/regex-native.ss") (line 76)) (caller (file "lib/std/regex.ss") (line 97)) (caller (file "tests/test-typed-llvmir.ss") (line 835)) (caller (file "tests/test-typed-llvmir.ss") (line 839))))
-    (export (symbol "jerboa_regex_group_count") (file "jerboa-native-rs/src/regex_native.rs") (line 494) (scheme-callers 2 (caller (file "lib/std/regex-native.ss") (line 63)) (caller (file "lib/std/regex.ss") (line 106))))
+    (export (symbol "jerboa_regex_group_count") (file "jerboa-native-rs/src/regex_native.rs") (line 495) (scheme-callers 2 (caller (file "lib/std/regex-native.ss") (line 63)) (caller (file "lib/std/regex.ss") (line 106))))
     (export (symbol "jerboa_regex_is_match") (file "jerboa-native-rs/src/regex_native.rs") (line 82) (scheme-callers 1 (caller (file "lib/std/regex-native.ss") (line 55))))
     (export (symbol "jerboa_regex_replace_all") (file "jerboa-native-rs/src/regex_native.rs") (line 159) (scheme-callers 5 (caller (file "lib/jerboa/typed/llvmir.ss") (line 3183)) (caller (file "lib/jerboa/typed/llvmir.ss") (line 3281)) (caller (file "lib/std/regex-native.ss") (line 71)) (caller (file "tests/test-typed-llvmir.ss") (line 834)) (caller (file "tests/test-typed-llvmir.ss") (line 837))))
     (export (symbol "jerboa_regex_replace_all_alloc") (file "jerboa-native-rs/src/regex_native.rs") (line 222) (scheme-callers 4 (caller (file "lib/jerboa/typed/llvmir.ss") (line 3183)) (caller (file "lib/jerboa/typed/llvmir.ss") (line 3281)) (caller (file "tests/test-typed-llvmir.ss") (line 834)) (caller (file "tests/test-typed-llvmir.ss") (line 837))))
-    (export (symbol "jerboa_scrypt") (file "jerboa-native-rs/src/crypto.rs") (line 694) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 280))))
+    (export (symbol "jerboa_scrypt") (file "jerboa-native-rs/src/crypto.rs") (line 699) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 280))))
     (export (symbol "jerboa_seccomp_available") (file "jerboa-native-rs/src/seccomp.rs") (line 284) (scheme-callers 1 (caller (file "lib/std/os/seccomp.ss") (line 32))))
     (export (symbol "jerboa_seccomp_lock") (file "jerboa-native-rs/src/seccomp.rs") (line 179) (scheme-callers 2 (caller (file "lib/std/os/seccomp.ss") (line 34)) (caller (file "lib/std/os/seccomp.ss") (line 36))))
     (export (symbol "jerboa_seccomp_lock_strict") (file "jerboa-native-rs/src/seccomp.rs") (line 196) (scheme-callers 1 (caller (file "lib/std/os/seccomp.ss") (line 36))))
@@ -104,18 +115,31 @@
     (export (symbol "jerboa_secure_random_fill") (file "jerboa-native-rs/src/secure_mem.rs") (line 199) (scheme-callers 1 (caller (file "lib/std/crypto/secure-mem.ss") (line 44))))
     (export (symbol "jerboa_secure_read_file") (file "jerboa-native-rs/src/secure_fs.rs") (line 723) (scheme-callers 1 (caller (file "lib/std/os/secure-output.ss") (line 65))))
     (export (symbol "jerboa_secure_wipe") (file "jerboa-native-rs/src/secure_mem.rs") (line 184) (scheme-callers 1 (caller (file "lib/std/crypto/secure-mem.ss") (line 41))))
-    (export (symbol "jerboa_sha1") (file "jerboa-native-rs/src/crypto.rs") (line 71) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 98))))
-    (export (symbol "jerboa_sha256") (file "jerboa-native-rs/src/crypto.rs") (line 87) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 109))))
-    (export (symbol "jerboa_sha384") (file "jerboa-native-rs/src/crypto.rs") (line 184) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 120))))
-    (export (symbol "jerboa_sha512") (file "jerboa-native-rs/src/crypto.rs") (line 194) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 131))))
-    (export (symbol "jerboa_sm_add_fuel") (file "jerboa-native-rs/src/wasm_sm.rs") (line 1152) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 186))))
+    (export (symbol "jerboa_setproctitle") (file "jerboa-native-rs/src/process_ctl.rs") (line 200) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_sha1") (file "jerboa-native-rs/src/crypto.rs") (line 72) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 98))))
+    (export (symbol "jerboa_sha256") (file "jerboa-native-rs/src/crypto.rs") (line 88) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 109))))
+    (export (symbol "jerboa_sha256_ctx_final") (file "jerboa-native-rs/src/crypto.rs") (line 159) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_sha256_ctx_free") (file "jerboa-native-rs/src/crypto.rs") (line 184) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_sha256_ctx_new") (file "jerboa-native-rs/src/crypto.rs") (line 118) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_sha256_ctx_update") (file "jerboa-native-rs/src/crypto.rs") (line 134) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_sha384") (file "jerboa-native-rs/src/crypto.rs") (line 189) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 120))))
+    (export (symbol "jerboa_sha512") (file "jerboa-native-rs/src/crypto.rs") (line 199) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 131))))
+    (export (symbol "jerboa_sm_add_fuel") (file "jerboa-native-rs/src/wasm_sm.rs") (line 1155) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 186))))
     (export (symbol "jerboa_sm_call") (file "jerboa-native-rs/src/wasm_sm.rs") (line 1008) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 168))))
-    (export (symbol "jerboa_sm_get_log") (file "jerboa-native-rs/src/wasm_sm.rs") (line 1165) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 180))))
+    (export (symbol "jerboa_sm_fuel_remaining") (file "jerboa-native-rs/src/wasm_sm.rs") (line 1160) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_sm_get_log") (file "jerboa-native-rs/src/wasm_sm.rs") (line 1169) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 180))))
     (export (symbol "jerboa_sm_instance_free") (file "jerboa-native-rs/src/wasm_sm.rs") (line 997) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 162))))
     (export (symbol "jerboa_sm_instance_new") (file "jerboa-native-rs/src/wasm_sm.rs") (line 987) (scheme-callers 2 (caller (file "lib/std/wasm/sandbox.ss") (line 156)) (caller (file "lib/std/wasm/sandbox.ss") (line 174))))
     (export (symbol "jerboa_sm_instance_new_hosted") (file "jerboa-native-rs/src/wasm_sm.rs") (line 992) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 174))))
+    (export (symbol "jerboa_sm_memory_read") (file "jerboa-native-rs/src/wasm_sm.rs") (line 1126) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_sm_memory_size") (file "jerboa-native-rs/src/wasm_sm.rs") (line 1146) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_sm_memory_write") (file "jerboa-native-rs/src/wasm_sm.rs") (line 1136) (scheme-callers 0 (none)))
     (export (symbol "jerboa_sm_module_free") (file "jerboa-native-rs/src/wasm_sm.rs") (line 937) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 150))))
     (export (symbol "jerboa_sm_module_new") (file "jerboa-native-rs/src/wasm_sm.rs") (line 849) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 144))))
+    (export (symbol "jerboa_socks5_server_port") (file "jerboa-native-rs/src/socks5_server.rs") (line 294) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_socks5_server_start") (file "jerboa-native-rs/src/socks5_server.rs") (line 122) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_socks5_server_stats") (file "jerboa-native-rs/src/socks5_server.rs") (line 316) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_socks5_server_stop") (file "jerboa-native-rs/src/socks5_server.rs") (line 265) (scheme-callers 0 (none)))
     (export (symbol "jerboa_sqlite_bind_blob") (file "jerboa-native-rs/src/sqlite.rs") (line 442) (scheme-callers 1 (caller (file "lib/std/db/sqlite-native.ss") (line 63))))
     (export (symbol "jerboa_sqlite_bind_double") (file "jerboa-native-rs/src/sqlite.rs") (line 372) (scheme-callers 1 (caller (file "lib/std/db/sqlite-native.ss") (line 59))))
     (export (symbol "jerboa_sqlite_bind_int") (file "jerboa-native-rs/src/sqlite.rs") (line 348) (scheme-callers 1 (caller (file "lib/std/db/sqlite-native.ss") (line 57))))
@@ -141,37 +165,48 @@
     (export (symbol "jerboa_string_filter_alnum_alloc") (file "jerboa-native-rs/src/string_native.rs") (line 85) (scheme-callers 3 (caller (file "lib/jerboa/typed/llvmir.ss") (line 3085)) (caller (file "tests/test-typed-llvmir.ss") (line 818)) (caller (file "tests/test-typed-llvmir.ss") (line 824))))
     (export (symbol "jerboa_string_lowercase_alloc") (file "jerboa-native-rs/src/string_native.rs") (line 51) (scheme-callers 3 (caller (file "lib/jerboa/typed/llvmir.ss") (line 3010)) (caller (file "tests/test-typed-llvmir.ss") (line 814)) (caller (file "tests/test-typed-llvmir.ss") (line 820))))
     (export (symbol "jerboa_string_uppercase_alloc") (file "jerboa-native-rs/src/string_native.rs") (line 68) (scheme-callers 3 (caller (file "lib/jerboa/typed/llvmir.ss") (line 3011)) (caller (file "tests/test-typed-llvmir.ss") (line 816)) (caller (file "tests/test-typed-llvmir.ss") (line 822))))
-    (export (symbol "jerboa_timing_safe_equal") (file "jerboa-native-rs/src/crypto.rs") (line 310) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 183))))
-    (export (symbol "jerboa_tls_accept") (file "jerboa-native-rs/src/tls.rs") (line 812) (scheme-callers 1 (caller (file "lib/std/net/tls-rustls.ss") (line 86))))
-    (export (symbol "jerboa_tls_close") (file "jerboa-native-rs/src/tls.rs") (line 1644) (scheme-callers 1 (caller (file "lib/std/net/tls-rustls.ss") (line 144))))
+    (export (symbol "jerboa_timing_safe_equal") (file "jerboa-native-rs/src/crypto.rs") (line 315) (scheme-callers 1 (caller (file "lib/std/crypto/native-rust.ss") (line 183))))
+    (export (symbol "jerboa_tls_accept") (file "jerboa-native-rs/src/tls.rs") (line 813) (scheme-callers 1 (caller (file "lib/std/net/tls-rustls.ss") (line 86))))
+    (export (symbol "jerboa_tls_close") (file "jerboa-native-rs/src/tls.rs") (line 1648) (scheme-callers 1 (caller (file "lib/std/net/tls-rustls.ss") (line 144))))
     (export (symbol "jerboa_tls_connect") (file "jerboa-native-rs/src/tls.rs") (line 199) (scheme-callers 5 (caller (file "lib/std/net/tls-rustls.ss") (line 92)) (caller (file "lib/std/net/tls-rustls.ss") (line 98)) (caller (file "lib/std/net/tls-rustls.ss") (line 107)) (caller (file "lib/std/net/tls-rustls.ss") (line 114)) (caller (file "lib/std/net/tls-rustls.ss") (line 121))))
     (export (symbol "jerboa_tls_connect_addr_timeout") (file "jerboa-native-rs/src/tls.rs") (line 330) (scheme-callers 1 (caller (file "lib/std/net/tls-rustls.ss") (line 107))))
-    (export (symbol "jerboa_tls_connect_mtls") (file "jerboa-native-rs/src/tls.rs") (line 1131) (scheme-callers 1 (caller (file "lib/std/net/tls-rustls.ss") (line 121))))
+    (export (symbol "jerboa_tls_connect_mtls") (file "jerboa-native-rs/src/tls.rs") (line 1133) (scheme-callers 1 (caller (file "lib/std/net/tls-rustls.ss") (line 121))))
+    (export (symbol "jerboa_tls_connect_mtls_mem") (file "jerboa-native-rs/src/tls.rs") (line 1424) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_tls_connect_mtls_pem_ca") (file "jerboa-native-rs/src/tls.rs") (line 1291) (scheme-callers 0 (none)))
     (export (symbol "jerboa_tls_connect_pinned") (file "jerboa-native-rs/src/tls.rs") (line 431) (scheme-callers 1 (caller (file "lib/std/net/tls-rustls.ss") (line 114))))
     (export (symbol "jerboa_tls_connect_timeout") (file "jerboa-native-rs/src/tls.rs") (line 206) (scheme-callers 1 (caller (file "lib/std/net/tls-rustls.ss") (line 98))))
-    (export (symbol "jerboa_tls_flush") (file "jerboa-native-rs/src/tls.rs") (line 1609) (scheme-callers 1 (caller (file "lib/std/net/tls-rustls.ss") (line 139))))
-    (export (symbol "jerboa_tls_get_fd") (file "jerboa-native-rs/src/tls.rs") (line 1735) (scheme-callers 1 (caller (file "lib/std/net/tls-rustls.ss") (line 161))))
-    (export (symbol "jerboa_tls_read") (file "jerboa-native-rs/src/tls.rs") (line 1545) (scheme-callers 1 (caller (file "lib/std/net/tls-rustls.ss") (line 129))))
-    (export (symbol "jerboa_tls_server_free") (file "jerboa-native-rs/src/tls.rs") (line 1659) (scheme-callers 1 (caller (file "lib/std/net/tls-rustls.ss") (line 80))))
-    (export (symbol "jerboa_tls_server_new") (file "jerboa-native-rs/src/tls.rs") (line 653) (scheme-callers 2 (caller (file "lib/std/net/tls-rustls.ss") (line 67)) (caller (file "lib/std/net/tls-rustls.ss") (line 74))))
-    (export (symbol "jerboa_tls_server_new_mtls") (file "jerboa-native-rs/src/tls.rs") (line 990) (scheme-callers 1 (caller (file "lib/std/net/tls-rustls.ss") (line 74))))
-    (export (symbol "jerboa_tls_set_nonblock") (file "jerboa-native-rs/src/tls.rs") (line 1666) (scheme-callers 1 (caller (file "lib/std/net/tls-rustls.ss") (line 150))))
-    (export (symbol "jerboa_tls_set_timeout") (file "jerboa-native-rs/src/tls.rs") (line 1691) (scheme-callers 1 (caller (file "lib/std/net/tls-rustls.ss") (line 155))))
-    (export (symbol "jerboa_tls_write") (file "jerboa-native-rs/src/tls.rs") (line 1578) (scheme-callers 1 (caller (file "lib/std/net/tls-rustls.ss") (line 134))))
-    (export (symbol "jerboa_wasm_add_fuel") (file "jerboa-native-rs/src/wasm.rs") (line 398) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 118))))
-    (export (symbol "jerboa_wasm_call") (file "jerboa-native-rs/src/wasm.rs") (line 452) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 94))))
-    (export (symbol "jerboa_wasm_fuel_remaining") (file "jerboa-native-rs/src/wasm.rs") (line 424) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 124))))
-    (export (symbol "jerboa_wasm_get_log") (file "jerboa-native-rs/src/wasm.rs") (line 734) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 136))))
+    (export (symbol "jerboa_tls_flush") (file "jerboa-native-rs/src/tls.rs") (line 1613) (scheme-callers 1 (caller (file "lib/std/net/tls-rustls.ss") (line 139))))
+    (export (symbol "jerboa_tls_get_fd") (file "jerboa-native-rs/src/tls.rs") (line 1739) (scheme-callers 1 (caller (file "lib/std/net/tls-rustls.ss") (line 161))))
+    (export (symbol "jerboa_tls_read") (file "jerboa-native-rs/src/tls.rs") (line 1549) (scheme-callers 1 (caller (file "lib/std/net/tls-rustls.ss") (line 129))))
+    (export (symbol "jerboa_tls_server_free") (file "jerboa-native-rs/src/tls.rs") (line 1663) (scheme-callers 1 (caller (file "lib/std/net/tls-rustls.ss") (line 80))))
+    (export (symbol "jerboa_tls_server_new") (file "jerboa-native-rs/src/tls.rs") (line 653) (scheme-callers 3 (caller (file "lib/std/net/tls-rustls.ss") (line 67)) (caller (file "lib/std/net/tls-rustls.ss") (line 74)) (caller (file "mcp/test/protocol-test.ss") (line 1242))))
+    (export (symbol "jerboa_tls_server_new_mtls") (file "jerboa-native-rs/src/tls.rs") (line 992) (scheme-callers 1 (caller (file "lib/std/net/tls-rustls.ss") (line 74))))
+    (export (symbol "jerboa_tls_server_new_mtls_pem") (file "jerboa-native-rs/src/tls.rs") (line 874) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_tls_server_new_pem") (file "jerboa-native-rs/src/tls.rs") (line 741) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_tls_set_nonblock") (file "jerboa-native-rs/src/tls.rs") (line 1670) (scheme-callers 1 (caller (file "lib/std/net/tls-rustls.ss") (line 150))))
+    (export (symbol "jerboa_tls_set_timeout") (file "jerboa-native-rs/src/tls.rs") (line 1695) (scheme-callers 1 (caller (file "lib/std/net/tls-rustls.ss") (line 155))))
+    (export (symbol "jerboa_tls_write") (file "jerboa-native-rs/src/tls.rs") (line 1582) (scheme-callers 1 (caller (file "lib/std/net/tls-rustls.ss") (line 134))))
+    (export (symbol "jerboa_wasm_add_fuel") (file "jerboa-native-rs/src/wasm.rs") (line 400) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 118))))
+    (export (symbol "jerboa_wasm_allow_cdb_dir") (file "jerboa-native-rs/src/wasm.rs") (line 352) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_wasm_call") (file "jerboa-native-rs/src/wasm.rs") (line 454) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 94))))
+    (export (symbol "jerboa_wasm_fuel_remaining") (file "jerboa-native-rs/src/wasm.rs") (line 426) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 124))))
+    (export (symbol "jerboa_wasm_get_log") (file "jerboa-native-rs/src/wasm.rs") (line 736) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 136))))
     (export (symbol "jerboa_wasm_instance_free") (file "jerboa-native-rs/src/wasm.rs") (line 296) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 88))))
     (export (symbol "jerboa_wasm_instance_new") (file "jerboa-native-rs/src/wasm.rs") (line 238) (scheme-callers 3 (caller (file "lib/std/wasm/sandbox.ss") (line 82)) (caller (file "lib/std/wasm/sandbox.ss") (line 130)) (caller (file "tests/test-wasm-sandbox.ss") (line 500))))
-    (export (symbol "jerboa_wasm_instance_new_hosted") (file "jerboa-native-rs/src/wasm.rs") (line 1300) (scheme-callers 2 (caller (file "lib/std/wasm/sandbox.ss") (line 130)) (caller (file "tests/test-wasm-sandbox.ss") (line 500))))
-    (export (symbol "jerboa_wasm_memory_read") (file "jerboa-native-rs/src/wasm.rs") (line 600) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 100))))
-    (export (symbol "jerboa_wasm_memory_size") (file "jerboa-native-rs/src/wasm.rs") (line 709) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 112))))
-    (export (symbol "jerboa_wasm_memory_write") (file "jerboa-native-rs/src/wasm.rs") (line 652) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 106))))
+    (export (symbol "jerboa_wasm_instance_new_hosted") (file "jerboa-native-rs/src/wasm.rs") (line 1302) (scheme-callers 2 (caller (file "lib/std/wasm/sandbox.ss") (line 130)) (caller (file "tests/test-wasm-sandbox.ss") (line 500))))
+    (export (symbol "jerboa_wasm_memory_read") (file "jerboa-native-rs/src/wasm.rs") (line 602) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 100))))
+    (export (symbol "jerboa_wasm_memory_size") (file "jerboa-native-rs/src/wasm.rs") (line 711) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 112))))
+    (export (symbol "jerboa_wasm_memory_write") (file "jerboa-native-rs/src/wasm.rs") (line 654) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 106))))
     (export (symbol "jerboa_wasm_module_free") (file "jerboa-native-rs/src/wasm.rs") (line 224) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 76))))
     (export (symbol "jerboa_wasm_module_new") (file "jerboa-native-rs/src/wasm.rs") (line 183) (scheme-callers 1 (caller (file "lib/std/wasm/sandbox.ss") (line 70))))
+    (export (symbol "jerboa_wasm_set_socket") (file "jerboa-native-rs/src/wasm.rs") (line 310) (scheme-callers 0 (none)))
     (export (symbol "jerboa_writev2") (file "jerboa-native-rs/src/http_parse.rs") (line 112) (scheme-callers 1 (caller (file "lib/std/net/io.ss") (line 81))))
-    (export (symbol "jerboa_x509_cert_fingerprint") (file "jerboa-native-rs/src/x509.rs") (line 607) (scheme-callers 1 (caller (file "lib/std/crypto/x509.ss") (line 31))))
+    (export (symbol "jerboa_x25519_diffie_hellman") (file "jerboa-native-rs/src/x25519.rs") (line 68) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_x25519_generate_keypair") (file "jerboa-native-rs/src/x25519.rs") (line 10) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_x25519_public_from_private") (file "jerboa-native-rs/src/x25519.rs") (line 38) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_x509_cert_fingerprint") (file "jerboa-native-rs/src/x509.rs") (line 609) (scheme-callers 1 (caller (file "lib/std/crypto/x509.ss") (line 31))))
     (export (symbol "jerboa_x509_generate_self_signed") (file "jerboa-native-rs/src/x509.rs") (line 234) (scheme-callers 1 (caller (file "lib/std/crypto/x509.ss") (line 27))))
+    (export (symbol "jerboa_x509_generate_self_signed_mem") (file "jerboa-native-rs/src/x509.rs") (line 354) (scheme-callers 0 (none)))
+    (export (symbol "jerboa_x509_generate_signed_by_ca_mem") (file "jerboa-native-rs/src/x509.rs") (line 462) (scheme-callers 0 (none)))
   )
 )
diff --git a/docs/unsafe-deserialize-allowlist.sexp b/docs/unsafe-deserialize-allowlist.sexp
index 3ee0ec9..110d96f 100644
--- a/docs/unsafe-deserialize-allowlist.sexp
+++ b/docs/unsafe-deserialize-allowlist.sexp
@@ -1,6 +1,6 @@
 (
- ("lib/jerboa/build.ss" 160 "bare-read-untrusted" "              (let ([form (read port)])" "trusted build-system source forms read from local project/build inputs")
- ("lib/jerboa/build.ss" 421 "bare-read-untrusted" "              (let ([form (read port)])" "trusted build-system source forms read from local project/build inputs")
+ ("lib/jerboa/build.ss" 168 "bare-read-untrusted" "              (let ([form (read port)])" "trusted build-system source forms read from local project/build inputs")
+ ("lib/jerboa/build.ss" 429 "bare-read-untrusted" "              (let ([form (read port)])" "trusted build-system source forms read from local project/build inputs")
  ("lib/jerboa/hot.ss" 108 "runtime-load-trusted" "                    (try (begin (load path)" "explicit hot-reload developer surface; caller selects local code path")
  ("lib/jerboa/wasm/gc-backend/driver.ss" 26 "bare-read-untrusted" "      (let ([form (read port)])" "trusted compiler driver input from the local build pipeline")
  ("lib/std/build.ss" 78 "bare-read-untrusted" "                         (let ([form (read port)])" "trusted build metadata/source forms under build-tool control")