Set up Forgejo CI/CD policy

ober

7d5ee40dc091408cc01c89a5347cf343a29489be

diff --git a/.builds/ci.yml b/.builds/ci.yml
deleted file mode 100644
index 469ff56..0000000
--- a/.builds/ci.yml
+++ /dev/null
@@ -1,48 +0,0 @@
-image: debian/stable
-arch: amd64
-packages:
-- bash
-- build-essential
-- ca-certificates
-- curl
-- file
-- git
-- libncurses-dev
-- make
-- pkg-config
-- tar
-- libfuse-dev
-- libssl-dev
-- zlib1g-dev
-- liblz4-dev
-sources:
-- https://git.sr.ht/~lisp/jerboa
-- https://git.sr.ht/~lisp/jerboa-drive
-artifacts:
-- jerboa-drive/jerboa-drive-0.1.0.jpkg
-tasks:
-- build-jerboa: |
-    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"
-    make jerboa CHEZ_CONFIGURE_EXTRA=--disable-x11 JERBOA_NATIVE_FEATURES=tls JERBOA_CC_OPT=-O0
-    echo 'export PATH="$HOME/jerboa/dist:$PATH"' >> ~/.buildenv
-- package: |
-    umask 022
-    cd jerboa-drive
-    J="$HOME/jerboa/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-drive-0.1.0.jpkg"
-    "$J" pkg verify "$PWD/jerboa-drive-0.1.0.jpkg"
-    "$J" pkg verify --reproduce
-- verify: |
-    umask 022
-    cd jerboa-drive
-    PATH="$HOME/jerboa/dist:$PATH" JERBUILD="$HOME/jerboa/dist/jerbuild" make verify
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..04cf841
--- /dev/null
+++ b/.forgejo/workflows/ci.yaml
@@ -0,0 +1,68 @@
+name: required-ci
+
+on:
+  pull_request:
+    branches: [main]
+  push:
+    branches: [main]
+    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-drive
+        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: Fetch and build Jerboa
+        run: |
+          mkdir ../jerboa
+          git -C ../jerboa init
+          git -C ../jerboa remote add origin https://git.jerboa.sh/ober/jerboa.git
+          git -C ../jerboa fetch --depth 1 origin 6a5230800b3599147f04bd5b1493bc996047506a
+          git -C ../jerboa checkout --detach FETCH_HEAD
+          test "$(git -C ../jerboa rev-parse 'HEAD^{tree}')" = 6eb4710558222c4e2ef9b076491f7db5af5e3748
+          . "$HOME/.cargo/env"
+          CARGO_BUILD_JOBS=1 make -C ../jerboa jerboa \
+            CHEZ_CONFIGURE_EXTRA=--disable-x11 JERBOA_NATIVE_FEATURES=tls \
+            JERBOA_CC_OPT=-O0
+      - name: Build, test, and smoke-check
+        run: |
+          . "$HOME/.cargo/env"
+          PATH="$PWD/../jerboa/dist:$PATH" \
+          JERBUILD="$PWD/../jerboa/dist/jerbuild" \
+            sh .forgejo/ci-required.sh
+      - name: Verify and pack package
+        run: |
+          version=$(cat VERSION)
+          J="$PWD/../jerboa/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-drive-$version.jpkg"
+          "$J" pkg verify "$PWD/jerboa-drive-$version.jpkg"
+          "$J" pkg verify --reproduce
+      - name: Upload package
+        uses: https://code.forgejo.org/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3
+        with:
+          name: jerboa-drive-package
+          path: jerboa-drive-*.jpkg
+          if-no-files-found: error
diff --git a/.forgejo/workflows/version-policy.yaml b/.forgejo/workflows/version-policy.yaml
new file mode 100644
index 0000000..2ccc656
--- /dev/null
+++ b/.forgejo/workflows/version-policy.yaml
@@ -0,0 +1,23 @@
+name: version-policy
+
+on:
+  pull_request:
+    branches: [main]
+
+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..24a8f70
--- /dev/null
+++ b/.gitsafeignore
@@ -0,0 +1,5 @@
+.forgejo/workflows/ci.yaml:high-entropy-hex:25
+.forgejo/workflows/ci.yaml:high-entropy-hex:38
+.forgejo/workflows/ci.yaml:high-entropy-hex:40
+.forgejo/workflows/ci.yaml:high-entropy-hex:64
+.forgejo/workflows/version-policy.yaml:high-entropy-hex:18
diff --git a/AGENTS.md b/AGENTS.md
index 9b29031..8c65ec7 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: Editing `.ss`/`.sls` Files — Mandatory Rules
 
 These rules exist because local-model sessions have lost **hours** fighting
@@ -371,18 +389,17 @@ improved versions of the above.
 When working in a Jerboa project, **ONLY modify files in the current repo** unless the user explicitly names another path.
 
 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
@@ -392,7 +409,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 b82014f..9119c6c 100644
--- a/Makefile
+++ b/Makefile
@@ -238,7 +238,7 @@ security:
 	@bash scripts/package-security-test.sh
 	@test -f dependency-lock.tsv || { echo "missing dependency-lock.tsv" >&2; exit 1; }
 	@test -f support/fetch-locked-deps.sh || { echo "missing locked dependency fetcher" >&2; exit 1; }
-	@! grep -R -E 'uses:[[:space:]]*[^[:space:]]+@(v[0-9]+|main|master|stable)([[:space:]]|$$)' .github/workflows
+	@! grep -R -E 'uses:[[:space:]]*[^[:space:]]+@(v[0-9]+|main|master|stable)([[:space:]]|$$)' .forgejo/workflows
 	@! grep -R -F 'git clone --depth 1' .github support scripts
 	@awk -F '\t' 'NF != 4 || $$1 !~ /^[a-z0-9-]+$$/ || $$3 !~ /^[0-9a-f]{40}$$/ || $$4 !~ /^[0-9a-f]{40}$$/ { exit 1 } END { if (NR != 9) exit 1 }' dependency-lock.tsv
 	@grep -q 'sanitize-evidence' docs/release-evidence.md || { echo "missing release evidence sanitizer docs" >&2; exit 1; }
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..17e51c3
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+0.1.1
diff --git a/dependency-lock.tsv b/dependency-lock.tsv
index cc80679..a3e1688 100644
--- a/dependency-lock.tsv
+++ b/dependency-lock.tsv
@@ -1,9 +1,9 @@
-jerboa-aws	https://git.sr.ht/~lisp/jerboa-aws	c1e6296c2ca17ec1e3f100876d433b12f613e22a	5c17cc5fc069c06b7a3f40510c3ae05e2b9911f7
-jerboa-proton-bridge	https://git.sr.ht/~lisp/jerboa-proton-bridge	43035ebf6b7e679d160699469f7e9c66f922478c	dc1b1d495eaae53475376004862dd28fd38dc2b3
-jerboa-yubikey	https://git.sr.ht/~lisp/jerboa-yubikey	0091e16bfe2f5d96e7fb18ce016e5b1ce010edae	a1fb427573692992cf68fea8eb0aea984cce3bce
-jerboa-pgp	https://git.sr.ht/~lisp/jerboa-pgp	38c681f41abde4d8ae05fa922c4383035c5e90e6	60300c5757b4bdfe15fb85e24baa9b2053b01a1b
-jerboa-crypto	https://git.sr.ht/~lisp/jerboa-crypto	74675676105775de23c55df65da27d8d2ef4a1d7	a49d8a0ce63731081f7fb140e13eff8d3efb850e
-jerboa-fuse	https://git.sr.ht/~lisp/jerboa-fuse	020ab5f8872261142b4f4c8d9379945db42f59fc	7184ad9a92719af4a08850a5f7a9ce4263ababdb
-jerboa-mail	https://git.sr.ht/~lisp/jerboa-mail	5d6382371decb5ce93016b46a1710d65255401b0	48b15dbdb9e18749b6195f1cbbd7d2804c54b6a6
-jerboa-https	https://git.sr.ht/~lisp/jerboa-https	c3a4be506edcdddeed37c4b7723bdd226a8511c1	f979837172aff40da3108c365afe45616579176d
-jerboa-ssl	https://git.sr.ht/~lisp/jerboa-ssl	270b858534941baad6420e4906a26c279f4a8678	4d629174bbff9b1cd2ff1aa696be0cd33bf462e4
+jerboa-aws	https://git.jerboa.sh/ober/jerboa-aws	c1e6296c2ca17ec1e3f100876d433b12f613e22a	5c17cc5fc069c06b7a3f40510c3ae05e2b9911f7
+jerboa-proton-bridge	https://git.jerboa.sh/ober/jerboa-proton-bridge	43035ebf6b7e679d160699469f7e9c66f922478c	dc1b1d495eaae53475376004862dd28fd38dc2b3
+jerboa-yubikey	https://git.jerboa.sh/ober/jerboa-yubikey	0091e16bfe2f5d96e7fb18ce016e5b1ce010edae	a1fb427573692992cf68fea8eb0aea984cce3bce
+jerboa-pgp	https://git.jerboa.sh/ober/jerboa-pgp	38c681f41abde4d8ae05fa922c4383035c5e90e6	60300c5757b4bdfe15fb85e24baa9b2053b01a1b
+jerboa-crypto	https://git.jerboa.sh/ober/jerboa-crypto	74675676105775de23c55df65da27d8d2ef4a1d7	a49d8a0ce63731081f7fb140e13eff8d3efb850e
+jerboa-fuse	https://git.jerboa.sh/ober/jerboa-fuse	020ab5f8872261142b4f4c8d9379945db42f59fc	7184ad9a92719af4a08850a5f7a9ce4263ababdb
+jerboa-mail	https://git.jerboa.sh/ober/jerboa-mail	5d6382371decb5ce93016b46a1710d65255401b0	48b15dbdb9e18749b6195f1cbbd7d2804c54b6a6
+jerboa-https	https://git.jerboa.sh/ober/jerboa-https	c3a4be506edcdddeed37c4b7723bdd226a8511c1	f979837172aff40da3108c365afe45616579176d
+jerboa-ssl	https://git.jerboa.sh/ober/jerboa-ssl	270b858534941baad6420e4906a26c279f4a8678	4d629174bbff9b1cd2ff1aa696be0cd33bf462e4
diff --git a/docs/jerboa-drive-plan.md b/docs/jerboa-drive-plan.md
index 7062f1d..7e8f8c2 100644
--- a/docs/jerboa-drive-plan.md
+++ b/docs/jerboa-drive-plan.md
@@ -7,8 +7,8 @@ reviewing results.
 ## Current Starting State
 
 - Current local repo path: `/Users/user/mine/jerboa-drive`.
-- Current sourcehut remote: `git@git.sr.ht:~lisp/jerboa-drive`.
-- Sourcehut repo: `~lisp/jerboa-drive`, unlisted.
+- Current Forgejo remote: `ssh://git@git.jerboa.sh:2222/ober/jerboa-drive`.
+- Forgejo repo: `ober/jerboa-drive`.
 - Installed binary name remains `jdrive`.
 - Current repo has dirty work from Proton Drive work. Do not discard it.
 - `~/mine/jerboa-aws` already has basic S3 bucket/object APIs:
@@ -30,13 +30,12 @@ Status: complete as of the repo rename. Keep this section as audit/history.
    - inspect `git status --short`
    - commit only if verification requirements can be met; otherwise leave dirty
      work intact and document it in the handoff notes.
-3. Rename the sourcehut repo with `hut`:
-   - `hut git update jerboa-protonstorage --name jerboa-drive --visibility unlisted`
-   - verify with `hut git show jerboa-drive`
+3. Rename the repository in Forgejo and verify the canonical
+   `ober/jerboa-drive` project is reachable.
 4. Rename the local directory:
    - from parent dir: `mv ~/mine/jerboa-protonstorage ~/mine/jerboa-drive`
 5. Fix the git remote:
-   - `git remote set-url origin git@git.sr.ht:~lisp/jerboa-drive`
+   - `git remote set-url origin ssh://git@git.jerboa.sh:2222/ober/jerboa-drive`
    - verify with `git remote -v`
 6. Rename project metadata and docs:
    - `jerboa-protonstorage` -> `jerboa-drive`
@@ -46,7 +45,7 @@ Status: complete as of the repo rename. Keep this section as audit/history.
 Acceptance gate:
 - `pwd` is `/Users/user/mine/jerboa-drive`.
 - `git remote -v` points at `~lisp/jerboa-drive`.
-- `hut git show jerboa-drive` succeeds and shows unlisted visibility.
+- `git ls-remote https://git.jerboa.sh/ober/jerboa-drive.git` succeeds.
 - `jdrive --help` still works after reinstall.
 
 ## Phase 1: Define Product Boundary
diff --git a/jpkg.sexp b/jpkg.sexp
index 1ec5d77..ee821d1 100644
--- a/jpkg.sexp
+++ b/jpkg.sexp
@@ -1,6 +1,6 @@
 (package
   (name "@ober/jerboa-drive")
-  (version "0.1.0")
+  (version "0.1.1")
   (description "Cloud drive abstraction for Jerboa")
   (license "MIT")
   (source "https://git.jerboa.sh/ober/jerboa-drive")
diff --git a/support/ensure-jerboa.sh b/support/ensure-jerboa.sh
index 26620a5..83cbf9e 100755
--- a/support/ensure-jerboa.sh
+++ b/support/ensure-jerboa.sh
@@ -1,5 +1,5 @@
 #!/bin/sh
-# Bootstrap a project-local Jerboa toolchain from SourceHut release artifacts.
+# Bootstrap a project-local Jerboa toolchain from Forgejo release artifacts.
 #
 # Usage:
 #   support/ensure-jerboa.sh v0.2.3 .jerboa/bin
@@ -14,8 +14,8 @@ usage() {
 
 version=$1
 bindir=${2:-.jerboa/bin}
-repo=${JERBOA_RELEASE_REPO:-~lisp/jerboa}
-origin=${JERBOA_RELEASE_ORIGIN:-https://git.sr.ht}
+repo=${JERBOA_RELEASE_REPO:-ober/jerboa}
+origin=${JERBOA_RELEASE_ORIGIN:-https://git.jerboa.sh}
 
 if [ "${JERBOA_RELEASE_TARGET:-}" ]; then
     target=$JERBOA_RELEASE_TARGET
@@ -41,7 +41,7 @@ case "$target" in
 esac
 
 file="jerboa-${version}-${target}.tar.gz"
-base=${JERBOA_RELEASE_BASE:-${origin}/${repo}/refs/download/${version}}
+base=${JERBOA_RELEASE_BASE:-${origin}/${repo}/releases/download/${version}}
 url="${base%/}/${file}"
 sum_url="${url}.sha256"
 
diff --git a/support/fetch-locked-deps.sh b/support/fetch-locked-deps.sh
index 575992a..88ed62f 100644
--- a/support/fetch-locked-deps.sh
+++ b/support/fetch-locked-deps.sh
@@ -28,7 +28,7 @@ while IFS="$tab" read -r name repository commit tree extra; do
         *[!a-z0-9-]*|'') echo "ERROR: unsafe dependency name: $name" >&2; exit 1 ;;
     esac
     case "$repository" in
-        https://git.sr.ht/~lisp/jerboa-*) ;;
+        https://git.jerboa.sh/ober/jerboa-*) ;;
         *) echo "ERROR: unapproved dependency origin for $name" >&2; exit 1 ;;
     esac
     printf '%s\n' "$commit" | grep -Eq '^[0-9a-f]{40}$' || {