#!/bin/sh set -eu set -o pipefail # Shell syntax and static analysis cover the actual container shell scripts. shellcheck -s ash -x -S warning infra/local/scripts/dispatch.sh infra/local/scripts/test.sh shellcheck -x -S warning infra/local/tools.sh infra/local/scripts/start-service.sh infra/local/mongo/start.sh infra/local/nats/start.sh infra/local/vault/start.sh . infra/local/scripts/common.sh . infra/local/scripts/images.sh . infra/local/scripts/bootstrap.sh # Offline fixtures exercise stable selection, reject prereleases, and preserve pins. get() { case "$1" in */tags/latest) printf '{"digest":"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}';; *page_size*) cat <<'JSON' {"results":[{"name":"2.1.0","digest":"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},{"name":"2.2.0-rc1","digest":"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}]} JSON ;; *) return 1;; esac } [ "$(image hashicorp/vault latest)" = 'hashicorp/vault:2.1.0@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' ] || fail 'Stable release selection failed' get() { printf '{"digest":"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","results":[{"name":"3.0.0-rc1","digest":"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}]}'; } if image hashicorp/vault latest >/dev/null 2>&1; then fail 'Prerelease accepted'; fi # Isolate state from the developer stack during failure tests. STATE="$WORK/state"; mkdir "$STATE"; printf 'previous build' > "$STATE/images.env" get() { return 1; } if images >/dev/null 2>&1; then fail 'Offline resolution succeeded'; fi [ "$(cat "$STATE/images.env")" = 'previous build' ] || fail 'Failed resolution replaced pins' if printf '{"api_key":"","sender_address":"notifications@localhost.test"}' | email_valid; then fail 'Empty email accepted'; fi printf '{"api_key":"fixture-only","sender_address":"sender@example.test"}' | email_valid # Initialized Vault without matching local keys must fail without initializing it again. vault() { printf '{"initialized":true}'; } if (initialize) > "$WORK/initialize-error" 2>&1; then fail 'Missing local keys accepted'; fi grep -q 'Missing .local' "$WORK/initialize-error" for service in bff notifications; do if grep -Eq 'database/creds/|SXCHNGE_MONGO_URI' "infra/local/vault/$service.hcl"; then fail 'Database credentials trigger Agent restart'; fi done echo 'PASS: shell analysis, stable selection, failed-resolution preservation, email validation, missing-key protection and Agent contract' if command -v python >/dev/null 2>&1 || command -v python3 >/dev/null 2>&1; then fail 'Tool image unexpectedly contains Python'; fi # Migration never overwrites an independently provisioned destination. . infra/local/scripts/secrets.sh secret_moves() { echo 'email services/notifications/email/resend'; } archive_secret() { :; } kv() { case "$1" in email) printf '{"api_key":"existing-fixture"}';; *) cat "$WORK/destination";; esac } vault() { [ "$1" = kv/data/services/notifications/email/resend ] || fail 'Unexpected migration mutation' jq -e '.options.cas==0' >/dev/null printf '{"api_key":"existing-fixture"}' > "$WORK/destination" } printf 'null' > "$WORK/destination" migrate_secrets migrate_secrets printf '{"api_key":"different-fixture"}' > "$WORK/destination" if (migrate_secrets) >/dev/null 2>&1; then fail 'Migration overwrote conflicting destination'; fi jq -e '.api_key=="different-fixture"' "$WORK/destination" >/dev/null echo 'PASS: secret migration is repeatable and refuses conflicting destination values'