set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
default_session="${CUA_SANDBOX_SESSION:-}"
default_db="${AVEN_SANDBOX_DB:-$HOME/.local/state/aven/marketing-screenshot.sqlite}"
global_sandbox="${CUA_SANDBOX_COMMAND:-$(command -v cua-sandbox || true)}"
usage() {
cat <<'USAGE'
Usage: scripts/cua-sandbox <command> [arguments]
Aven command:
db-bootstrap <session> [source] [--force]
Snapshot a host aven database into a session
Global commands:
setup Install the CLI and build the persistent image
start <session> Start an isolated CuaBot server in the foreground
stop <session> Stop a named CuaBot server
status <session> Show a named CuaBot server's status
list List discoverable CuaBot sessions
cua <session> [args...] Pass arguments to a named CuaBot server
container <session> Print the Docker container name
Environment:
CUA_SANDBOX_COMMAND Global command override
CUA_SANDBOX_SESSION Session fallback when an argument is omitted
AVEN_SANDBOX_DB Database source for db-bootstrap
USAGE
}
require_command() {
if ! command -v "$1" >/dev/null 2>&1; then
printf 'missing required command: %s\n' "$1" >&2
exit 1
fi
}
require_global_sandbox() {
if [[ -z "$global_sandbox" || ! -x "$global_sandbox" ]]; then
echo "Global cua-sandbox command is missing from PATH." >&2
exit 1
fi
}
resolve_session() {
local requested="${1:-$default_session}"
if [[ -z "$requested" ]]; then
echo "a session name is required" >&2
echo "Pass one explicitly or set CUA_SANDBOX_SESSION." >&2
exit 1
fi
if [[ ! "$requested" =~ ^[a-zA-Z0-9][a-zA-Z0-9._-]*$ ]]; then
echo "invalid session name: $requested" >&2
exit 1
fi
printf '%s\n' "$requested"
}
bootstrap_database() (
local session="$1"
local source="$2"
local force="$3"
local container="cuabot-xpra-$session"
local destination="/home/user/aven-run/aven.db"
local binary="/home/user/aven-run/aven"
require_command docker
require_command sqlite3
if [[ ! -f "$source" ]]; then
echo "database source does not exist: $source" >&2
exit 1
fi
if [[ "$(docker inspect --format '{{.State.Status}}' "$container" 2>/dev/null || true)" != "running" ]]; then
echo "sandbox container is not running: $container" >&2
exit 1
fi
if docker exec "$container" pgrep -f 'aven tui' >/dev/null 2>&1; then
echo "aven is running in session '$session'; stop it before replacing its database" >&2
exit 1
fi
if ! docker exec -u user "$container" test -x "$binary"; then
echo "sandbox aven binary is missing: $binary" >&2
echo "Deploy the branch build before bootstrapping its database." >&2
exit 1
fi
if [[ "$force" != "true" ]] \
&& docker exec -u user "$container" test -e "$destination"
then
echo "sandbox database already exists: $destination"
echo "Pass --force to replace it."
exit 0
fi
local temp_dir snapshot remote
temp_dir="$(mktemp -d)"
trap 'rm -rf "$temp_dir"' EXIT
snapshot="$temp_dir/aven.sqlite"
remote="/home/user/aven-run/.aven-bootstrap-$session-$$.sqlite"
sqlite3 "$source" ".backup '$snapshot'"
local version migration
local -a normalized=()
while IFS= read -r version; do
if [[ ! "$version" =~ ^[0-9]+$ ]]; then
echo "database contains an invalid migration version: $version" >&2
exit 1
fi
migration="$(compgen -G "$repo_root/crates/aven-core/migrations/${version}_*.sql" || true)"
if [[ -z "$migration" ]]; then
sqlite3 "$snapshot" "DELETE FROM _sqlx_migrations WHERE version = $version;"
normalized+=("$version")
fi
done < <(sqlite3 "$snapshot" 'SELECT version FROM _sqlx_migrations ORDER BY version;')
if [[ "$(sqlite3 "$snapshot" 'PRAGMA quick_check;')" != "ok" ]]; then
echo "database snapshot failed its integrity check" >&2
exit 1
fi
chmod 0644 "$snapshot"
docker exec -u user "$container" mkdir -p /home/user/aven-run
docker cp "$snapshot" "$container:$remote"
docker exec -u user "$container" sh -lc "
set -eu
cp '$remote' '$destination.bootstrap'
"
docker exec "$container" rm -f "$remote"
if ! docker exec -u user -e AVEN_DB="$destination.bootstrap" \
"$container" "$binary" list --all --limit 1 >/dev/null
then
docker exec -u user "$container" rm -f "$destination.bootstrap"
echo "sandbox aven could not open the database snapshot" >&2
exit 1
fi
docker exec -u user "$container" \
rm -f "$destination-wal" "$destination-shm"
docker exec -u user "$container" mv "$destination.bootstrap" "$destination"
echo "Bootstrapped $destination"
echo "Source: $source"
echo "Session: $session"
if [[ "${#normalized[@]}" -gt 0 ]]; then
printf 'Ignored source-only migrations:'
printf ' %s' "${normalized[@]}"
printf '\n'
fi
)
command="${1:-}"
case "$command" in
db-bootstrap)
session="$(resolve_session "${2:-}")"
source="${3:-$default_db}"
force="false"
if [[ "$source" == "--force" ]]; then
source="$default_db"
force="true"
elif [[ "${4:-}" == "--force" ]]; then
force="true"
elif [[ -n "${4:-}" ]]; then
echo "unexpected argument: ${4}" >&2
exit 1
fi
bootstrap_database "$session" "$source" "$force"
;;
help|-h|--help|'')
usage
;;
*)
require_global_sandbox
exec "$global_sandbox" "$@"
;;
esac