#!/usr/bin/env bash

# The packslip backend installs a release from its vendor's signed manifest.
# jdx/packslip publishes one for its own releases, signed keylessly by its
# release workflow, which is the identity the project name pins.

# Every release carrying a packslip is recent; do not let the default
# minimum release age hide them all.
export MISE_MINIMUM_RELEASE_AGE=0

# The backend needs no setting turned on to be used.
assert_contains "env -u MISE_EXPERIMENTAL mise ls-remote packslip:github.com/jdx/packslip" "0.2.0"

# The registry supplies the canonical project and pins each publishing workflow
# separately so CI signing jobs cannot authorize either bundles or the index.
mkdir canonical
pushd canonical >/dev/null
cat >mise.toml <<'EOF'
[tools]
packslip = "latest"
EOF
# Latest resolves and verifies the vendor recommendation without installing it.
latest=$(mise latest packslip) || exit 1
[[ -n $latest ]] || exit 1
assert_contains "mise ls-remote packslip" "$latest"
# The quickstart works with no explicit signer options in the user's config.
MISE_GLOBAL_CONFIG_FILE="$PWD/global.toml" mise use -g packslip
assert_contains "cat global.toml" 'packslip ='
assert_contains "mise exec -- packslip version" "packslip $latest"
canonical_install_path="$(mise where packslip)"
assert_contains "cat $canonical_install_path/.mise-packslip.json" '"project": "packslip.dev"'
# Changing a list policy must not reuse the accepted versions from the warm cache.
assert_fail_contains "mise ls-remote 'packslip[list_identity_prefix=https://github.com/jdx/packslip/.github/workflows/ci.yml@]'" "verifying the release list"
# A trusted index does not authorize its signer (or CI) to sign release bundles.
assert_fail_contains "mise latest 'packslip[identity_prefix=https://github.com/jdx/packslip/.github/workflows/packslip-releases.yml@]'" "expected an identity starting with"
assert_fail_contains "mise latest 'packslip[identity_prefix=https://github.com/jdx/packslip/.github/workflows/ci.yml@]'" "expected an identity starting with"
mise packslip forget packslip.dev
popd >/dev/null

# A warm accepted-version cache must not hide changed stamper policy.
mkdir stamp-policy
pushd stamp-policy >/dev/null
cat >mise.toml <<'EOF'
[settings.packslip]
stampers = ["invalid"]
EOF
assert_fail_contains "mise ls-remote packslip:github.com/jdx/packslip" "has no pin"
popd >/dev/null

mise use packslip:github.com/jdx/packslip@0.2.0
assert_contains "$MISE_DATA_DIR/shims/packslip version" "packslip 0.2.0"

# github.com is implied for owner/repo.
assert_contains "mise x packslip:jdx/packslip@0.2.0 -- packslip version" "packslip 0.2.0"

# The verified statement is kept beside the install, and the lockfile
# entry carries the URL and digest the statement signed.
install_path="$(mise where packslip:github.com/jdx/packslip@0.2.0)"
assert_contains "cat $install_path/.mise-packslip.json" '"project": "github.com/jdx/packslip"'
assert_contains "mise tool packslip:github.com/jdx/packslip" "packslip"

# The signer is pinned, the way SSH remembers a host, and can be forgotten.
assert_contains "mise packslip pins" "https://github.com/jdx/packslip/.github/workflows/release.yml"
assert_contains "mise packslip forget jdx/packslip" "forgot the pinned signer"
assert_contains "mise packslip pins" "no packslip signers pinned"

# This release's packslip lists no completion, and mise says so rather
# than guessing at one; a tool mise does not know has no packslip at all.
assert_fail_contains "mise completion zsh --tool packslip" "declares no zsh completion"
assert_fail_contains "mise completion zsh --tool nope" "not an active, installed tool"

# This release declares no skill either, and sync links nothing.
assert_contains "mise skills ls" "no skills declared"
assert "mise skills ls --json" "[]"
assert_contains "mise skills sync --dir skills" "nothing to link"
assert_directory_not_exists skills
assert_contains "env MISE_SKILLS_DIR=agents/skills mise skills sync" "nothing to link"
assert_directory_not_exists agents

# A lockfile records who signed, so the project commits to that signer.
export MISE_LOCKFILE=1
mkdir -p locked && cd locked
touch mise.lock
cat <<EOF >mise.toml
[tools]
"packslip:github.com/jdx/packslip" = "0.2.0"
EOF
mise uninstall packslip:github.com/jdx/packslip@0.2.0
mise install
assert_contains "cat mise.lock" 'signer = "sigstore-oidc:https://github.com/jdx/packslip/.github/workflows/release.yml"'
# A lockfile is an already-reviewed selection. A later release-age policy must
# not make that committed install unreproducible.
mise uninstall packslip:github.com/jdx/packslip@0.2.0
MISE_MINIMUM_RELEASE_AGE=2000-01-01 mise install
cd ..
unset MISE_LOCKFILE

# Naming one release is itself the selection release age governs, so a config
# that pins an exact version installs during the cooling window with no
# lockfile, and locking records the same selection.
mkdir -p pinned && cd pinned
cat <<EOF >mise.toml
[tools]
"packslip:github.com/jdx/packslip" = "0.2.0"
EOF
mise uninstall packslip:github.com/jdx/packslip@0.2.0
MISE_MINIMUM_RELEASE_AGE=2000-01-01 mise install
assert_contains "mise x -- packslip version" "packslip 0.2.0"
MISE_MINIMUM_RELEASE_AGE=2000-01-01 mise lock
assert_contains "cat mise.lock" 'version = "0.2.0"'
cd ..

# A release that carries no packslip is refused rather than guessed at.
assert_fail_contains "mise install packslip:jdx/mise-test-fixtures@1.0.0" "no release"
