#!/bin/sh # Copyright (C) 2026 Doan Luu Duc Tai # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . set -eu umask 077 ROOT=$(CDPATH= cd -- "$(dirname -- "$0")/../.." && pwd) for SCRIPT in "$ROOT/infra/guix/"*.sh; do sh -n "$SCRIPT" done sh "$ROOT/infra/guix/test-bootstrap.sh" sh "$ROOT/infra/guix/test-recovery.sh" STAGE=$(mktemp -d) trap 'find "$STAGE" -type d -exec chmod u+w {} +; rm -rf -- "$STAGE"' EXIT HUP INT TERM mkdir -p "$STAGE/source/infra/guix" "$STAGE/source/bin" "$STAGE/fake/bin" "$STAGE/toolbin" \ "$STAGE/fake/gnu/store/readonly" "$STAGE/sentinel" cp "$ROOT/infra/guix/"*.sh "$STAGE/source/infra/guix/" cp "$ROOT/infra/podman.conf" "$STAGE/source/infra/podman.conf" cp "$ROOT/infra/guix/containers.conf" "$STAGE/source/infra/guix/containers.conf" printf '%s\n' 'ciphertext fixture' > "$STAGE/backup.tar.gz.gpg" printf '%s\n' 'channels fixture' > "$STAGE/source/bin/guix-channels.scm" printf '%s\n' '#!/bin/sh' 'printf "%s\n" "${CONTAINERS_CONF:-}" > "$0.environment"' 'printf "%s\n" "$@"' > "$STAGE/source/bin/stack" chmod 700 "$STAGE/source/bin/stack" for TOOL in podman gpg; do printf '%s\n' '#!/bin/sh' 'exit 0' > "$STAGE/fake/bin/$TOOL" chmod 700 "$STAGE/fake/bin/$TOOL" done printf '%s\n' 'Immutable runtime content.' > "$STAGE/fake/gnu/store/readonly/value" printf '%s\n' 'Independent sentinel.' > "$STAGE/sentinel/value" ln -s "$STAGE/sentinel" "$STAGE/fake/gnu/store/readonly/outside" chmod 555 "$STAGE/sentinel" chmod 444 "$STAGE/sentinel/value" chmod 555 "$STAGE/fake/gnu/store" "$STAGE/fake/gnu/store/readonly" chmod 444 "$STAGE/fake/gnu/store/readonly/value" tar -czf "$STAGE/runtime.tar.gz" -C "$STAGE/fake" . chmod -R u+w "$STAGE/fake/gnu/store" cat > "$STAGE/toolbin/guix" <<'GUIX' #!/bin/sh set -eu case "$1" in describe) printf '%s\n' 'channels fixture' ;; time-machine) printf '%s\n' "$FAKE_PACK" ;; *) exit 1 ;; esac GUIX chmod 700 "$STAGE/toolbin/guix" FAKE_PACK="$STAGE/runtime.tar.gz" PATH="$STAGE/toolbin:$PATH" sh "$STAGE/source/infra/guix/build.sh" [ -z "$(find "$STAGE/source/bin" -maxdepth 1 -name '.guix-build.*' -print -quit)" ] || { echo 'Build left immutable staging directories.' >&2; exit 1; } [ "$(stat -c %a "$STAGE/sentinel")" = 555 ] [ "$(stat -c %a "$STAGE/sentinel/value")" = 444 ] cmp "$STAGE/runtime.tar.gz" "$STAGE/source/bin/guix-runtime.tar.gz" mkdir -p "$STAGE/release/stack/bin/chat" "$STAGE/release/stack/infra/guix" "$STAGE/release/stack/var" cp "$STAGE/source/bin/guix-runtime.tar.gz" "$STAGE/source/bin/guix-channels.scm" "$STAGE/release/stack/bin/" cp "$STAGE/source/infra/guix/"*.sh "$STAGE/release/stack/infra/guix/" cp "$ROOT/infra/guix/containers.conf" "$STAGE/release/stack/infra/guix/containers.conf" cp "$ROOT/LICENSE" "$STAGE/release/stack/LICENSE" printf '%s\n' 'services fixture' > "$STAGE/release/stack/infra/services.toml" printf '%s\n' 'image lock fixture' > "$STAGE/release/stack/var/image-lock.json" printf '%s\n' 'image export fixture' > "$STAGE/release/stack/var/images.tar" for ARTIFACT in server crypto.wasm SOURCE.tar.gz; do printf '%s\n' 'chat artifact fixture' > "$STAGE/release/stack/bin/chat/$ARTIFACT" done cat > "$STAGE/release/stack/bin/stack" <<'STACK' #!/bin/sh set -eu [ "$#" = 4 ] && [ "$1" = restore ] && [ "$2" = --release ] || exit 1 mkdir "$4" tar -xzf "$3" --strip-components=1 -C "$4" STACK chmod 700 "$STAGE/release/stack/bin/stack" tar -czf "$STAGE/release.tar.gz" -C "$STAGE/release" stack sh "$STAGE/source/infra/guix/bundle.sh" "$STAGE/backup.tar.gz.gpg" "$STAGE/release.tar.gz" "$STAGE/recovery.tar.gz" if sh "$STAGE/source/infra/guix/bundle.sh" "$STAGE/backup.tar.gz.gpg" "$STAGE/release.tar.gz" "$STAGE/recovery.tar.gz"; then echo 'Overwrote existing archive.' >&2; exit 1 fi tar -xzf "$STAGE/recovery.tar.gz" -C "$STAGE" [ -x "$STAGE/stack-recovery/bootstrap" ] || { echo 'Store bootstrap missing from capsule.' >&2; exit 1; } cmp "$ROOT/infra/guix/containers.conf" "$STAGE/stack-recovery/containers.conf" (cd "$STAGE/stack-recovery" && sha256sum --check --strict SHA256SUMS) cmp "$STAGE/backup.tar.gz.gpg" "$STAGE/stack-recovery/backup.tar.gz.gpg" cmp "$STAGE/release.tar.gz" "$STAGE/stack-recovery/release.tar.gz" cmp "$STAGE/release/stack/bin/stack" "$STAGE/stack-recovery/stack" cmp "$STAGE/release/stack/LICENSE" "$STAGE/stack-recovery/LICENSE" [ "$(stat -c %a "$STAGE/recovery.tar.gz")" = 600 ] if cmp -s "$STAGE/source/bin/stack" "$STAGE/stack-recovery/stack"; then echo 'Bundled source-tree executable instead of release executable.' >&2; exit 1 fi if "$STAGE/stack-recovery/restore" "$STAGE/source"; then echo 'Accepted existing restore destination.' >&2; exit 1 fi cp "$STAGE/source/infra/guix/run.sh" "$STAGE/source/bin/run" OUTPUT=$(sh "$STAGE/source/bin/run" status) EXPECTED=$(printf '%s\n' --root "$STAGE/source" status) [ "$OUTPUT" = "$EXPECTED" ] [ "$(cat "$STAGE/source/bin/stack.environment")" = "$STAGE/source/infra/guix/containers.conf" ] mv "$STAGE/source/bin/guix-runtime.tar.gz" "$STAGE/saved-runtime.tar.gz" OUTPUT=$(env -u CONTAINERS_CONF sh "$STAGE/source/bin/run" status) [ "$OUTPUT" = "$EXPECTED" ] [ "$(cat "$STAGE/source/bin/stack.environment")" = '' ] mv "$STAGE/saved-runtime.tar.gz" "$STAGE/source/bin/guix-runtime.tar.gz" find "$STAGE/source/var/guix" -name podman | read -r MATCH PUBLISHED=$(sha256sum "$STAGE/source/bin/guix-runtime.tar.gz") PUBLISHED=${PUBLISHED%% *} DIRECTORY_MODE=$(stat -c %a "$STAGE/source/var/guix/$PUBLISHED/gnu/store/readonly") FILE_MODE=$(stat -c %a "$STAGE/source/var/guix/$PUBLISHED/gnu/store/readonly/value") chmod -R a-w "$STAGE/fake/gnu/store" tar -czf "$STAGE/failed-runtime.tar.gz" -C "$STAGE/fake" bin/podman gnu chmod -R u+w "$STAGE/fake/gnu/store" cp "$STAGE/failed-runtime.tar.gz" "$STAGE/source/bin/guix-runtime.tar.gz" if sh "$STAGE/source/bin/run" status; then echo 'Accepted runtime missing GnuPG.' >&2; exit 1; fi [ -z "$(find "$STAGE/source/var/guix" -maxdepth 1 -name '.unpack.*' -print -quit)" ] || { echo 'Failed launcher left immutable staging directories.' >&2; exit 1; } [ -x "$STAGE/source/var/guix/$PUBLISHED/bin/gpg" ] [ "$(stat -c %a "$STAGE/source/var/guix/$PUBLISHED/gnu/store/readonly")" = "$DIRECTORY_MODE" ] [ "$(stat -c %a "$STAGE/source/var/guix/$PUBLISHED/gnu/store/readonly/value")" = "$FILE_MODE" ] [ "$(stat -c %a "$STAGE/sentinel")" = 555 ] [ "$(stat -c %a "$STAGE/sentinel/value")" = 444 ] cmp "$STAGE/runtime.tar.gz" "$STAGE/stack-recovery/runtime.tar.gz" cp "$STAGE/runtime.tar.gz" "$STAGE/source/bin/guix-runtime.tar.gz" printf 'tamper' >> "$STAGE/stack-recovery/backup.tar.gz.gpg" if (cd "$STAGE/stack-recovery" && sha256sum --check --strict SHA256SUMS); then echo 'Accepted changed ciphertext.' >&2; exit 1 fi rm "$STAGE/release/stack/bin/guix-channels.scm" tar -czf "$STAGE/missing.tar.gz" -C "$STAGE/release" stack if sh "$STAGE/source/infra/guix/bundle.sh" "$STAGE/backup.tar.gz.gpg" "$STAGE/missing.tar.gz" "$STAGE/other.tar.gz"; then echo 'Accepted missing provenance.' >&2; exit 1 fi cp "$STAGE/source/bin/guix-channels.scm" "$STAGE/release/stack/bin/guix-channels.scm" for ARTIFACT in image-lock.json images.tar; do mv "$STAGE/release/stack/var/$ARTIFACT" "$STAGE/$ARTIFACT" tar -czf "$STAGE/missing-image.tar.gz" -C "$STAGE/release" stack if sh "$STAGE/source/infra/guix/bundle.sh" "$STAGE/backup.tar.gz.gpg" "$STAGE/missing-image.tar.gz" "$STAGE/missing-image-output.tar.gz"; then echo 'Accepted release without complete saved images.' >&2; exit 1 fi [ ! -e "$STAGE/missing-image-output.tar.gz" ] mv "$STAGE/$ARTIFACT" "$STAGE/release/stack/var/$ARTIFACT" done for PRIVATE in .env var/data; do mkdir -p "$(dirname "$STAGE/release/stack/$PRIVATE")" printf '%s\n' 'private fixture' > "$STAGE/release/stack/$PRIVATE" tar -czf "$STAGE/private.tar.gz" -C "$STAGE/release" stack if sh "$STAGE/source/infra/guix/bundle.sh" "$STAGE/backup.tar.gz.gpg" "$STAGE/private.tar.gz" "$STAGE/private-output.tar.gz"; then echo 'Accepted private release contents.' >&2; exit 1 fi [ ! -e "$STAGE/private-output.tar.gz" ] rm "$STAGE/release/stack/$PRIVATE" done printf '%s\n' 'Bundle, immutable cleanup, integrity, overwrite, launcher, and missing-artifact checks passed.'