diff --git a/scripts/unified-deployment-smoke.sh b/scripts/unified-deployment-smoke.sh index ced2e280..6c490687 100755 --- a/scripts/unified-deployment-smoke.sh +++ b/scripts/unified-deployment-smoke.sh @@ -991,6 +991,15 @@ task13_server_tht() { sudo -n -- "$TASK13_THT" --installation "$TASK13_INSTALLATION" "$@" } +task13_server_checkpoint_leftover() { + [[ "${TASK13_PROFILE:-local}" == server \ + && -n "${TASK13_CONTROL_DIR:-}" \ + && "$TASK13_CONTROL_DIR" == "$TASK13_ROOT/.tht/$TASK13_PROJECT" \ + && "$TASK13_PROJECT" =~ ^thothii-[0-9a-f]{12}$ ]] \ + || task13_fail "refusing to inspect an unexpected server control path" + sudo -n -- find "$TASK13_CONTROL_DIR" -maxdepth 1 -name 'restore-checkpoint-*.zip' -print -quit +} + task13_prepare_local_auth_runtime() { local owner_label owner_label="$(docker volume inspect --format '{{ index .Labels "io.thothii.task13.run" }}' \ @@ -1417,9 +1426,9 @@ task13_assert_server_oidc_restore_verification() { || grep -Fq "$TASK13_AUTHENTIK_API_TOKEN" "$rollback_output"; then task13_fail "failed server restore exposed fake-provider custody values" fi - [[ "$(cat "$rollback_sentinel")" == current-state ]] \ + [[ "$(sudo -n -- cat -- "$rollback_sentinel")" == current-state ]] \ || task13_fail "failed server restore did not roll back the server data bind" - checkpoint_leftover="$(find "$TASK13_CONTROL_DIR" -maxdepth 1 -name 'restore-checkpoint-*.zip' -print -quit)" + checkpoint_leftover="$(task13_server_checkpoint_leftover)" [[ -z "$checkpoint_leftover" ]] || task13_fail "failed server restore retained its private recovery checkpoint" task13_compose_logged "verify failed restore cleared authentication runtime" \ run --rm --no-deps --no-TTY core sh -ceu ' @@ -1475,7 +1484,7 @@ task13_assert_server_oidc_restore_verification() { task13_sanitize <"$restore_output" | tail -n 8 >&2 return "$restore_rc" fi - checkpoint_leftover="$(find "$TASK13_CONTROL_DIR" -maxdepth 1 -name 'restore-checkpoint-*.zip' -print -quit)" + checkpoint_leftover="$(task13_server_checkpoint_leftover)" [[ -z "$checkpoint_leftover" ]] || task13_fail "successful server restore retained its private recovery checkpoint" task13_compose_start_logged "start restored server stack" up --detach --wait --wait-timeout 120 core frontend frontend="$(task13_frontend_address)" @@ -1965,10 +1974,14 @@ task13_reclaim_server_fixture_ownership() { [[ "${TASK13_TMP%/*}" == "${TASK13_TMP_PARENT:-}" \ && "${TASK13_TMP##*/}" == thothii-task13.* ]] \ || task13_fail "refusing to reclaim an unexpected server fixture path" + [[ -n "${TASK13_CONTROL_DIR:-}" \ + && "$TASK13_CONTROL_DIR" == "$TASK13_ROOT/.tht/$TASK13_PROJECT" \ + && "$TASK13_PROJECT" =~ ^thothii-[0-9a-f]{12}$ ]] \ + || task13_fail "refusing to reclaim an unexpected server control path" host_uid="$(id -u)" host_gid="$(id -g)" task13_bounded "$TASK13_CLEANUP_TIMEOUT" "reclaim server fixture ownership" \ - sudo -n -- chown -hR "$host_uid:$host_gid" "$TASK13_TMP" + sudo -n -- chown -hR "$host_uid:$host_gid" "$TASK13_TMP" "$TASK13_CONTROL_DIR" } task13_cleanup() { @@ -1994,21 +2007,20 @@ task13_cleanup() { if [[ -n "${TASK13_PROJECT:-}" && -n "${TASK13_ROOT:-}" && -f "${TASK13_OVERRIDE:-}" ]]; then if task13_assert_project_ownership >>"${TASK13_LOG:-/dev/null}" 2>&1; then task13_compose_files - if task13_bounded "$TASK13_CLEANUP_TIMEOUT" "stop owned Compose project" \ + if ! task13_bounded "$TASK13_CLEANUP_TIMEOUT" "stop owned Compose project" \ "${TASK13_COMPOSE[@]}" down --volumes --remove-orphans --timeout 10 \ >>"${TASK13_LOG:-/dev/null}" 2>&1; then - if ! { - task13_reclaim_server_fixture_ownership - } >>"${TASK13_LOG:-/dev/null}" 2>&1; then - cleanup_rc=1 - fi - else cleanup_rc=1 fi else cleanup_rc=1 fi fi + if ! { + task13_reclaim_server_fixture_ownership + } >>"${TASK13_LOG:-/dev/null}" 2>&1; then + cleanup_rc=1 + fi if [[ -f "${TASK13_UPDATE_STATE:-}" ]]; then transaction="$(sed -n 's/.*"transaction": "\([^"]*\)".*/\1/p' "$TASK13_UPDATE_STATE" | head -n 1)" fi @@ -2570,6 +2582,8 @@ task13_self_test_source_contract() { local server_fixture_reclamation server_runtime_config_probe server_workspace_config_permission local server_runtime_selector_probe server_runtime_generation_probe server_runtime_direct_file_probe local server_runtime_projection_status_contract + local server_rollback_sentinel_read server_control_dir_reclamation + local server_checkpoint_lookup local server_secret_source_owner server_secret_source_preparation server_tht_wrapper root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)" workflow="$root/.github/workflows/deployment.yml" @@ -2606,6 +2620,9 @@ task13_self_test_source_contract() { server_runtime_generation_probe='check_readable "/run/thothii-auth/generations/$projection_generation/''auth.yaml"' server_runtime_direct_file_probe='check_readable /run/thothii-auth/''auth.yaml' server_runtime_projection_status_contract='value.state!=="''ready"||value.equal!==true' + server_rollback_sentinel_read='sudo -n -- cat -- "$rollback_''sentinel"' + server_control_dir_reclamation='"$TASK13_TMP" "$TASK13_CONTROL_''DIR"' + server_checkpoint_lookup='task13_server_checkpoint_''leftover' server_secret_source_preparation='task13_prepare_server_secret_''sources' server_secret_source_owner='chown 10001:''10001 -- "$TASK13_SECRETS" "$TASK13_PI_AUTH"' server_tht_wrapper='task13_server_''tht' @@ -2695,6 +2712,13 @@ task13_self_test_source_contract() { || task13_fail "the server runtime preconditions must not require the forbidden direct-file fallback" grep -Fq -- "$server_runtime_projection_status_contract" "$root/scripts/unified-deployment-smoke.sh" \ || task13_fail "the server status assertion must validate projection readiness" + grep -Fq -- "$server_rollback_sentinel_read" "$root/scripts/unified-deployment-smoke.sh" \ + || task13_fail "the server rollback sentinel must be read through the privileged host surface" + grep -Fq -- "$server_control_dir_reclamation" "$root/scripts/unified-deployment-smoke.sh" \ + || task13_fail "server cleanup must reclaim both temporary and control roots" + [[ "$(grep -Ec "^${server_checkpoint_lookup}\\(\\)|${server_checkpoint_lookup}" \ + "$root/scripts/unified-deployment-smoke.sh")" -eq 3 ]] \ + || task13_fail "server restore must inspect root-owned checkpoints through one privileged helper" grep -Fq -- "$server_workspace_config_permission" "$root/scripts/unified-deployment-smoke.sh" \ || task13_fail "the server workspace fixture must be readable by the container UID" [[ "$(grep -Ec "^${server_secret_source_preparation}\\(\\)|^[[:space:]]+${server_secret_source_preparation}$" \