#!/usr/bin/env bash # Focused tests for the observability acceptance state machine. The production # artifact is executed for CLI behavior and sourced for pure validators and # lifecycle orchestration; no live command, sudo, Secret, or mutation is used. set -Eeuo pipefail set +x umask 077 readonly TEST_ROOT="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd -P)" readonly SMOKE="$TEST_ROOT/scripts/validate/observability-smoke.sh" TEST_WORK='' RAW_DELETE_WORK='' ASSERTIONS=0 fail() { printf 'OBSERVABILITY SMOKE TEST FAILURE: %s\n' "$*" >&2; exit 1; } pass() { ASSERTIONS=$((ASSERTIONS + 1)); printf 'PASS: %s\n' "$1"; } assert_eq() { [[ "$1" == "$2" ]] || fail "$3: expected=[$1] actual=[$2]"; } assert_contains() { [[ "$1" == *"$2"* ]] || fail "$3"; } assert_not_contains() { [[ "$1" != *"$2"* ]] || fail "$3"; } expect_failure() { local rc=0; "$@" >/dev/null 2>&1 || rc=$?; (( rc != 0 )) || fail "expected failure: $*"; } cleanup() { trap - EXIT HUP INT TERM case "$RAW_DELETE_WORK" in /tmp/platform-observability-smoke.????????) rm -rf -- "$RAW_DELETE_WORK" ;; esac case "$TEST_WORK" in /tmp/platform-observability-smoke-test.??????) rm -rf -- "$TEST_WORK" ;; esac } trap cleanup EXIT trap 'exit 129' HUP trap 'exit 130' INT trap 'exit 143' TERM [[ -f "$SMOKE" && ! -L "$SMOKE" ]] || fail 'production smoke is missing (RED: create observability-smoke.sh)' TEST_WORK="$(mktemp -d /tmp/platform-observability-smoke-test.XXXXXX)" chmod 0700 "$TEST_WORK" readonly EXPECTED_DRY_RUN=$'OBSERVABILITY_SMOKE_DRY_RUN=PASS\nCHECK_01=Grafana public/private DNS exactness\nCHECK_02=Grafana certificate chain,hostname,one-SAN,expiry\nCHECK_03=LAN,Tailscale,denied-source,public-edge HTTPS status\nCHECK_04=Gitea,Grafana,Keycloak public metrics denial\nCHECK_05=unknown-SNI and Traefik NodePort boundary\nCHECK_06=exact Prometheus target allowlist and health\nCHECK_07=Gitea,Keycloak,CNPG,AIStor,Traefik metric contracts\nCHECK_08=untrusted-Pod AIStor and blackbox denial\nCHECK_09=public,private,internal,TLS blackbox series\nCHECK_10=Grafana datasource health and Loki-to-Tempo trace link\nCHECK_11=AIStor quota and recording-rule series\nCHECK_12=Grafana,Alertmanager restart persistence\nCHECK_13=Certbot dry-run deploy-hook and Nginx health\nHUMAN_OIDC=admin,viewer,denied,break-glass,session-revoke,relogin-denied\nHUMAN_SLACK=firing,resolved\nHUMAN_EXTERNAL_CLIENT=required\nTEMPORARY_OBJECTS=NetworkPolicy,Pod,AlertmanagerSilence,PrometheusRule\nPRESERVE=Secret,PVC,preexisting-Keycloak-membership\nMUTATION=NOT_REQUESTED' # Mutation caught: moving a command check or external read before the no-arg # branch makes the command trace non-empty and breaks the exact output. mkdir -m 0700 "$TEST_WORK/bin" for command_name in dirname kubectl curl dig openssl nc sudo; do printf '#!/usr/bin/env bash\nprintf %s\\n "%s" >>"%s"\nexit 97\n' \ "'%s'" "$command_name" "$TEST_WORK/external.log" >"$TEST_WORK/bin/$command_name" chmod 0755 "$TEST_WORK/bin/$command_name" done : >"$TEST_WORK/external.log" dry_output="$(PATH="$TEST_WORK/bin:/usr/bin:/bin" bash "$SMOKE")" assert_eq "$EXPECTED_DRY_RUN" "$dry_output" 'default exact plan' [[ ! -s "$TEST_WORK/external.log" ]] || fail 'default invocation touched an external boundary' pass 'default invocation is exact and no-contact' # Mutation caught: accepting an extra/duplicated flag could accidentally enter # an execute path the operator did not request. for argument in --wrong --execute=1 --context default; do rc=0; PATH="$TEST_WORK/bin:/usr/bin:/bin" bash "$SMOKE" $argument >/dev/null 2>&1 || rc=$? assert_eq 1 "$rc" "unsupported argument status: $argument" done [[ ! -s "$TEST_WORK/external.log" ]] || fail 'bad CLI touched an external boundary' pass 'CLI rejects every non-contract argument before contact' override_rc=0 override_output="$(PLATFORM_OBSERVABILITY_SMOKE_KUBECTL=/tmp/not-kubectl bash "$SMOKE" 2>&1)" || override_rc=$? assert_eq 1 "$override_rc" 'production override status' assert_contains "$override_output" 'production boundary override is forbidden' 'production override message' source_only_rc=0 source_only_output="$(PLATFORM_OBSERVABILITY_SMOKE_SOURCE_ONLY=1 bash "$SMOKE" 2>&1)" || source_only_rc=$? assert_eq 1 "$source_only_rc" 'source-only environment bypass status' assert_contains "$source_only_output" 'production boundary override is forbidden' 'source-only environment bypass message' pass 'production invocation rejects test seams' # Source-only mode exposes pure validators without running main. PLATFORM_OBSERVABILITY_SMOKE_SOURCE_ONLY=1 source "$SMOKE" # Production command constants must themselves satisfy the non-symlink # executable boundary used by execute preflight on this host. declare -F validate_command_boundaries >/dev/null || fail 'command-boundary validator is missing' validate_command_boundaries pass 'production command boundaries resolve to fixed regular executables' mkdir -m 0700 "$TEST_WORK/hostile-bin" cat >"$TEST_WORK/hostile-bin/stat" <<'SH' #!/usr/bin/env bash printf 'hostile-stat\n' >>"${OBS_SMOKE_HOSTILE_PATH_LOG:?}" exec /usr/bin/stat "$@" SH chmod 0755 "$TEST_WORK/hostile-bin/stat" : >"$TEST_WORK/hostile-path.log" RAW_DELETE_WORK="$(mktemp -d /tmp/platform-observability-smoke.XXXXXXXX)" chmod 0700 "$RAW_DELETE_WORK" : >"$RAW_DELETE_WORK/file"; chmod 0600 "$RAW_DELETE_WORK/file" ( WORK="$RAW_DELETE_WORK" PATH="$TEST_WORK/hostile-bin:/usr/bin:/bin" OBS_SMOKE_HOSTILE_PATH_LOG="$TEST_WORK/hostile-path.log" \ safe_work_file "$WORK/file" ) || fail 'fixed utility boundary setup' [[ ! -s "$TEST_WORK/hostile-path.log" ]] || fail 'security utility resolved through hostile PATH' rm -rf -- "$RAW_DELETE_WORK"; RAW_DELETE_WORK='' pass 'security utility boundaries ignore hostile PATH' # A signal after the long-lived API proxy PID is assigned but before its # process-start identity is captured must be deferred. Otherwise EXIT cleanup # cannot prove ownership and the proxy is leaked. cat >"$TEST_WORK/bin/kubectl-proxy-signal" <<'SH' #!/usr/bin/env bash trap 'exit 0' TERM INT while :; do /usr/bin/sleep 1; done SH chmod 0755 "$TEST_WORK/bin/kubectl-proxy-signal" RAW_DELETE_WORK="$(mktemp -d /tmp/platform-observability-smoke.XXXXXXXX)" chmod 0700 "$RAW_DELETE_WORK" rm -f -- "$TEST_WORK/proxy-signal.marker" "$TEST_WORK/proxy-signal.pid" proxy_signal_rc=0 ( WORK="$RAW_DELETE_WORK"; KUBECTL_BIN="$TEST_WORK/bin/kubectl-proxy-signal" API_PROXY_PID=''; API_PROXY_START=''; API_PROXY_SOCKET='' MUTATION_CRITICAL_DEPTH=0; DEFERRED_SIGNAL_RC=0 OBS_SMOKE_PROXY_SIGNAL_TARGET=$BASHPID OBS_SMOKE_PROXY_SIGNAL_MARKER="$TEST_WORK/proxy-signal.marker" export OBS_SMOKE_PROXY_SIGNAL_TARGET OBS_SMOKE_PROXY_SIGNAL_MARKER process_start_time() { if [[ ! -e "$OBS_SMOKE_PROXY_SIGNAL_MARKER" ]]; then : >"$OBS_SMOKE_PROXY_SIGNAL_MARKER" /bin/kill -INT "$OBS_SMOKE_PROXY_SIGNAL_TARGET" fi printf '12345' } trap on_exit EXIT trap 'handle_termination_signal 130' INT start_api_proxy ) || proxy_signal_rc=$? assert_eq 130 "$proxy_signal_rc" 'API proxy deferred signal status' [[ -f "$TEST_WORK/proxy-signal.marker" ]] || fail 'API proxy signal fixture did not reach identity capture' proxy_pid="$(pgrep -f "^bash $TEST_WORK/bin/kubectl-proxy-signal" | head -n1 || true)" if [[ -n "$proxy_pid" ]] && /bin/kill -0 "$proxy_pid" 2>/dev/null; then /bin/kill -KILL "$proxy_pid" 2>/dev/null || true fail 'API proxy process leaked across the signal ownership window' fi RAW_DELETE_WORK='' pass 'API proxy signal window closes after PID start-time ownership capture' declare -F validate_commit_environment >/dev/null || fail 'full repeat commit environment gate is missing' ( EXPECTED_NODE_UID='' NODE_FIXTURE_UID='node-uid-one' validate_command_boundaries() { printf 'commands\n' >>"$TEST_WORK/commit-gate.log"; } kubectl_bounded() { printf '%q ' "$@" >>"$TEST_WORK/commit-gate.log"; printf '\n' >>"$TEST_WORK/commit-gate.log" case "$1 $2" in 'config current-context') printf 'default' ;; 'config view') printf 'https://127.0.0.1:6443' ;; 'get --raw=/readyz') : ;; 'get node') jq -n --arg name "$EXPECTED_NODE" --arg uid "$NODE_FIXTURE_UID" '{metadata:{name:$name,uid:$uid},status:{conditions:[{type:"Ready",status:"True"}]}}' ;; 'auth can-i') printf 'yes' ;; *) return 91 ;; esac } : >"$TEST_WORK/commit-gate.log" validate_commit_environment validate_commit_environment NODE_FIXTURE_UID='node-uid-replacement' expect_failure validate_commit_environment ) || fail 'full repeat commit environment gate flow' assert_eq 3 "$(grep -c '^commands$' "$TEST_WORK/commit-gate.log")" 'command boundary repeat count' [[ "$(grep -c '^auth can-i ' "$TEST_WORK/commit-gate.log")" -gt 20 ]] || fail 'authority set was not repeated' pass 'commit gate repeats commands, context, node identity, API and authority' declare -F kubectl_wait_90_bounded >/dev/null || fail '90-second Kubernetes convergence wrapper is missing' declare -F kubectl_wait_180_bounded >/dev/null || fail '180-second Kubernetes convergence wrapper is missing' cat >"$TEST_WORK/bin/kubectl-convergence" <<'SH' #!/usr/bin/env bash set -Eeuo pipefail /usr/bin/tr '\0' ' ' <"/proc/$PPID/cmdline" >>"${OBS_SMOKE_CONVERGENCE_LOG:?}" printf '\n' >>"$OBS_SMOKE_CONVERGENCE_LOG" printf '%q ' "$@" >>"$OBS_SMOKE_CONVERGENCE_LOG"; printf '\n' >>"$OBS_SMOKE_CONVERGENCE_LOG" SH chmod 0755 "$TEST_WORK/bin/kubectl-convergence" : >"$TEST_WORK/convergence.log" KUBECTL_BIN="$TEST_WORK/bin/kubectl-convergence" OBS_SMOKE_CONVERGENCE_LOG="$TEST_WORK/convergence.log" \ kubectl_wait_90_bounded -n observability wait --timeout=90s pod/example KUBECTL_BIN="$TEST_WORK/bin/kubectl-convergence" OBS_SMOKE_CONVERGENCE_LOG="$TEST_WORK/convergence.log" \ kubectl_wait_180_bounded -n observability rollout status deployment/grafana --timeout=180s convergence_log="$(<"$TEST_WORK/convergence.log")" assert_contains "$convergence_log" '--kill-after=2s 100s' '90-second outer convergence deadline' assert_contains "$convergence_log" '--request-timeout=95s -n observability wait --timeout=90s pod/example' '90-second request deadline' assert_contains "$convergence_log" '--kill-after=2s 190s' '180-second outer convergence deadline' assert_contains "$convergence_log" '--request-timeout=185s -n observability rollout status deployment/grafana --timeout=180s' '180-second request deadline' KUBECTL_BIN="$KUBECTL_DEFAULT" pass 'Kubernetes convergence honors declared waits within fixed outer deadlines' # A second-resolution timestamp cannot identify ownership under concurrent # runs. Production must add a cryptographically random, non-secret nonce. declare -F new_smoke_run_id >/dev/null || fail 'unique smoke run-id generator is missing' run_id_one="$(new_smoke_run_id network)" run_id_two="$(new_smoke_run_id network)" [[ "$run_id_one" =~ ^network-[0-9]{8}t[0-9]{6}z-[0-9a-f]{32}$ ]] || fail 'first smoke run ID is not exact' [[ "$run_id_two" =~ ^network-[0-9]{8}t[0-9]{6}z-[0-9a-f]{32}$ ]] || fail 'second smoke run ID is not exact' [[ "$run_id_one" != "$run_id_two" ]] || fail 'concurrent smoke run IDs collided' pass 'temporary object identity uses a unique non-secret nonce' # The full run ID is safe as a label value but, when prefixed again, exceeds # Kubernetes' 63-character DNS label limit. Resource names must retain the # full 128-bit nonce while remaining valid exact DNS labels. declare -F kubernetes_smoke_name >/dev/null || fail 'bounded Kubernetes smoke-name helper is missing' kubernetes_name="$(kubernetes_smoke_name "$run_id_one")" [[ "$kubernetes_name" =~ ^observability-smoke-[0-9a-f]{32}$ ]] || fail 'Kubernetes smoke name is not nonce-bound' (( ${#kubernetes_name} <= 63 )) || fail 'Kubernetes smoke name exceeds DNS label length' expect_failure kubernetes_smoke_name 'network-20260812t091011z-not-a-nonce' pass 'temporary Kubernetes names retain ownership entropy within DNS limits' # Mutation caught: accepting public/private DNS drift or more than one SAN. validate_dns_contract '' '' 192.168.0.107 '' 100.92.240.34 '' 192.168.0.107 '' expect_failure validate_dns_contract 203.0.113.10 '' 192.168.0.107 '' 100.92.240.34 '' 192.168.0.107 '' expect_failure validate_dns_contract '' '' 192.168.0.108 '' 100.92.240.34 '' 192.168.0.107 '' validate_certificate_contract $'DNS:grafana.learn.hyeonworks.com' 0 0 expect_failure validate_certificate_contract $'DNS:grafana.learn.hyeonworks.com\nDNS:extra.example' 0 0 expect_failure validate_certificate_contract 'DNS:grafana.learn.hyeonworks.com' 1 0 expect_failure validate_certificate_contract 'DNS:grafana.learn.hyeonworks.com' 0 1 declare -F validate_certificate_extension_contract >/dev/null || fail 'full certificate GeneralNames validator is missing' validate_certificate_extension_contract \ $'X509v3 Subject Alternative Name:\n DNS:grafana.learn.hyeonworks.com' 0 0 for extra_name in \ 'IP Address:192.168.0.107' \ 'email:admin@learn.hyeonworks.com' \ 'URI:https://grafana.learn.hyeonworks.com/' \ 'othername: UPN::grafana'; do expect_failure validate_certificate_extension_contract \ "X509v3 Subject Alternative Name: DNS:grafana.learn.hyeonworks.com, $extra_name" 0 0 done pass 'DNS and certificate validators reject drift' # Production machine leaf: exercise its real bounded dig argv construction, # normalization, and response-to-contract flow at the command boundary. cat >"$TEST_WORK/bin/dig-leaf" <<'SH' #!/usr/bin/env bash set -Eeuo pipefail printf '%q ' "$@" >>"${OBS_SMOKE_LEAF_LOG:?}" printf '\n' >>"${OBS_SMOKE_LEAF_LOG:?}" [[ "$1" == +time=2 && "$2" == +tries=1 && "$3" == +short && "$6" == grafana.learn.hyeonworks.com ]] resolver=${4#@}; record=$5 if [[ "${OBS_SMOKE_LEAF_DRIFT:-0}" == 1 && "$resolver" == 192.168.0.107 && "$record" == A ]]; then printf '192.168.0.108\n' elif [[ "$resolver" == 192.168.0.107 && "$record" == A ]]; then printf '\n192.168.0.107\n192.168.0.107\n' elif [[ "$resolver" == 100.92.240.34 && "$record" == A ]]; then printf '100.92.240.34\n' fi SH chmod 0755 "$TEST_WORK/bin/dig-leaf" : >"$TEST_WORK/dig-leaf.log" DIG_BIN="$TEST_WORK/bin/dig-leaf" OBS_SMOKE_LEAF_LOG="$TEST_WORK/dig-leaf.log" check_dns_host >/dev/null assert_eq 6 "$(wc -l <"$TEST_WORK/dig-leaf.log" | tr -d '[:space:]')" 'DNS leaf command count' assert_contains "$(<"$TEST_WORK/dig-leaf.log")" '+time=2 +tries=1 +short @1.1.1.1 A grafana.learn.hyeonworks.com' 'public A argv contract' assert_contains "$(<"$TEST_WORK/dig-leaf.log")" '+time=2 +tries=1 +short @192.168.0.107 AAAA grafana.learn.hyeonworks.com' 'LAN AAAA argv contract' assert_contains "$(<"$TEST_WORK/dig-leaf.log")" '+time=2 +tries=1 +short @100.92.240.34 A grafana.learn.hyeonworks.com' 'Tailscale A argv contract' expect_failure env OBS_SMOKE_LEAF_LOG="$TEST_WORK/dig-leaf.log" OBS_SMOKE_LEAF_DRIFT=1 \ bash -c 'PLATFORM_OBSERVABILITY_SMOKE_SOURCE_ONLY=1 source "$1"; DIG_BIN="$2"; check_dns_host' \ bash "$SMOKE" "$TEST_WORK/bin/dig-leaf" DIG_BIN="$DIG_DEFAULT" pass 'production DNS leaf uses bounded exact argv and rejects parsed drift' cat >"$TEST_WORK/traefik-service.json" <<'JSON' {"apiVersion":"v1","kind":"Service","metadata":{"name":"traefik","namespace":"kube-system","uid":"traefik-service-uid"},"spec":{"type":"NodePort","externalTrafficPolicy":"Cluster","selector":{"app.kubernetes.io/name":"traefik","app.kubernetes.io/instance":"traefik-kube-system"},"ports":[{"name":"web","port":80,"protocol":"TCP","targetPort":"web","nodePort":30080},{"name":"websecure","port":443,"protocol":"TCP","targetPort":"websecure","nodePort":30443}]}} JSON chmod 0600 "$TEST_WORK/traefik-service.json" declare -F check_nodeport_identity >/dev/null || fail 'Traefik NodePort identity leaf is missing' ( WORK="$TEST_WORK" kubectl_bounded() { cat -- "$TEST_WORK/traefik-service.json"; } http_status() { printf '%q ' "$@" >"$TEST_WORK/nodeport-http.argv" printf '404' } check_nodeport_identity >/dev/null ) || fail 'exact Traefik NodePort identity flow' assert_contains "$(<"$TEST_WORK/nodeport-http.argv")" '--header Host:\ observability-smoke.invalid http://127.0.0.1:30080/' 'NodePort exact HTTP argv' expect_failure bash -c ' PLATFORM_OBSERVABILITY_SMOKE_SOURCE_ONLY=1 source "$1" WORK="$(dirname -- "$2")" SERVICE_FIXTURE=$2 kubectl_bounded() { cat -- "$SERVICE_FIXTURE"; } http_status() { printf 200; } check_nodeport_identity ' bash "$SMOKE" "$TEST_WORK/traefik-service.json" jq '.spec.selector["app.kubernetes.io/name"]="foreign"' "$TEST_WORK/traefik-service.json" >"$TEST_WORK/traefik-service-foreign.json" expect_failure bash -c ' PLATFORM_OBSERVABILITY_SMOKE_SOURCE_ONLY=1 source "$1" WORK="$(dirname -- "$2")" SERVICE_FIXTURE=$2 kubectl_bounded() { cat -- "$SERVICE_FIXTURE"; } http_status() { printf 404; } check_nodeport_identity ' bash "$SMOKE" "$TEST_WORK/traefik-service-foreign.json" pass 'loopback NodePort proves exact Traefik Service and HTTP response' # A hostile ambient curlrc must not influence either public HTTPS calls or the # private Unix-socket API client. `--disable` has to be curl's first argument. mkdir -m 0700 "$TEST_WORK/curl-home" cat >"$TEST_WORK/curl-home/.curlrc" </dev/null [[ ! -e "$TEST_WORK/hostile-curl.trace" ]] || fail 'http_status loaded hostile curlrc' RAW_DELETE_WORK="$(mktemp -d /tmp/platform-observability-smoke.XXXXXXXX)" chmod 0700 "$RAW_DELETE_WORK" proxy_rc=0 ( WORK="$RAW_DELETE_WORK" API_PROXY_SOCKET="$WORK/nonexistent.sock" HOME="$TEST_WORK/curl-home" CURL_HOME="$TEST_WORK/curl-home" \ proxy_request GET '/api/v1/namespaces/observability/pods' "$WORK/output.json" ) >/dev/null 2>&1 || proxy_rc=$? assert_eq 1 "$proxy_rc" 'failed-socket proxy status' [[ ! -e "$TEST_WORK/hostile-curl.trace" ]] || fail 'proxy_request loaded hostile curlrc' rm -rf -- "$RAW_DELETE_WORK" RAW_DELETE_WORK='' pass 'curl boundaries ignore hostile ambient curlrc' cat >"$TEST_WORK/targets.json" <<'JSON' {"status":"success","data":{"activeTargets":[ {"scrapePool":"podMonitor/platform-data/platform-postgres/0","health":"up"}, {"scrapePool":"probe/observability/platform-private-edge","health":"up"}, {"scrapePool":"probe/observability/platform-private-edge","health":"up"}, {"scrapePool":"probe/observability/platform-private-edge","health":"up"}, {"scrapePool":"probe/observability/platform-private-internal","health":"up"}, {"scrapePool":"probe/observability/platform-private-internal","health":"up"}, {"scrapePool":"probe/observability/platform-private-internal","health":"up"}, {"scrapePool":"probe/observability/platform-public-edge","health":"up"}, {"scrapePool":"probe/observability/platform-public-edge","health":"up"}, {"scrapePool":"serviceMonitor/gitea/gitea/0","health":"up"}, {"scrapePool":"serviceMonitor/keycloak/keycloak/0","health":"up"}, {"scrapePool":"serviceMonitor/kube-system/traefik/0","health":"up"}, {"scrapePool":"serviceMonitor/object-storage/aistor-bucket-usage/0","health":"up"}, {"scrapePool":"serviceMonitor/observability-agent/alloy/0","health":"up"}, {"scrapePool":"serviceMonitor/observability-agent/node-exporter/0","health":"up"}, {"scrapePool":"serviceMonitor/observability/blackbox-exporter/0","health":"up"}, {"scrapePool":"serviceMonitor/observability/grafana/0","health":"up"}, {"scrapePool":"serviceMonitor/observability/loki/0","health":"up"}, {"scrapePool":"serviceMonitor/observability/observability-core-kube-pr-alertmanager/0","health":"up"}, {"scrapePool":"serviceMonitor/observability/observability-core-kube-pr-alertmanager/1","health":"up"}, {"scrapePool":"serviceMonitor/observability/observability-core-kube-pr-apiserver/0","health":"up"}, {"scrapePool":"serviceMonitor/observability/observability-core-kube-pr-coredns/0","health":"up"}, {"scrapePool":"serviceMonitor/observability/observability-core-kube-pr-kubelet/0","health":"up"}, {"scrapePool":"serviceMonitor/observability/observability-core-kube-pr-kubelet/1","health":"up"}, {"scrapePool":"serviceMonitor/observability/observability-core-kube-pr-kubelet/2","health":"up"}, {"scrapePool":"serviceMonitor/observability/observability-core-kube-pr-operator/0","health":"up"}, {"scrapePool":"serviceMonitor/observability/observability-core-kube-pr-prometheus/0","health":"up"}, {"scrapePool":"serviceMonitor/observability/observability-core-kube-pr-prometheus/1","health":"up"}, {"scrapePool":"serviceMonitor/observability/observability-core-kube-state-metrics/0","health":"up"}, {"scrapePool":"serviceMonitor/observability/tempo/0","health":"up"} ]}} JSON python3 -I -S - "$TEST_WORK/targets.json" <<'PY' import json,pathlib,sys path=pathlib.Path(sys.argv[1]); item=json.loads(path.read_text()) urls={ 'podMonitor/platform-data/platform-postgres/0':'http://10.42.0.10:9187/metrics', 'serviceMonitor/gitea/gitea/0':'http://10.42.0.11:3000/metrics', 'serviceMonitor/keycloak/keycloak/0':'http://10.42.0.12:9000/metrics', 'serviceMonitor/kube-system/traefik/0':'http://10.42.0.13:9100/metrics', 'serviceMonitor/object-storage/aistor-bucket-usage/0':'http://10.42.0.14:9000/minio/metrics/v3/cluster/usage/buckets', 'serviceMonitor/observability-agent/alloy/0':'http://10.42.0.21:12345/metrics', 'serviceMonitor/observability-agent/node-exporter/0':'http://192.168.0.107:9100/metrics', 'serviceMonitor/observability/blackbox-exporter/0':'http://10.42.0.22:9115/metrics', 'serviceMonitor/observability/grafana/0':'http://10.42.0.23:3000/metrics', 'serviceMonitor/observability/loki/0':'http://10.42.0.24:3100/metrics', 'serviceMonitor/observability/observability-core-kube-pr-alertmanager/0':'http://10.42.0.25:9093/metrics', 'serviceMonitor/observability/observability-core-kube-pr-alertmanager/1':'http://10.42.0.25:8080/metrics', 'serviceMonitor/observability/observability-core-kube-pr-apiserver/0':'https://192.168.0.107:6443/metrics', 'serviceMonitor/observability/observability-core-kube-pr-coredns/0':'http://10.42.0.26:9153/metrics', 'serviceMonitor/observability/observability-core-kube-pr-kubelet/0':'https://192.168.0.107:10250/metrics', 'serviceMonitor/observability/observability-core-kube-pr-kubelet/1':'https://192.168.0.107:10250/metrics/cadvisor', 'serviceMonitor/observability/observability-core-kube-pr-kubelet/2':'https://192.168.0.107:10250/metrics/probes', 'serviceMonitor/observability/observability-core-kube-pr-operator/0':'http://10.42.0.27:8080/metrics', 'serviceMonitor/observability/observability-core-kube-pr-prometheus/0':'http://10.42.0.28:9090/metrics', 'serviceMonitor/observability/observability-core-kube-pr-prometheus/1':'http://10.42.0.28:8080/metrics', 'serviceMonitor/observability/observability-core-kube-state-metrics/0':'http://10.42.0.29:8080/metrics', 'serviceMonitor/observability/tempo/0':'http://10.42.0.30:3200/metrics', } jobs={ 'podMonitor/platform-data/platform-postgres/0':'platform-postgres', 'serviceMonitor/gitea/gitea/0':'gitea', 'serviceMonitor/keycloak/keycloak/0':'keycloak-service', 'serviceMonitor/kube-system/traefik/0':'traefik', 'serviceMonitor/object-storage/aistor-bucket-usage/0':'minio-aistor', 'serviceMonitor/observability-agent/alloy/0':'alloy', 'serviceMonitor/observability-agent/node-exporter/0':'prometheus-node-exporter', 'serviceMonitor/observability/blackbox-exporter/0':'blackbox-exporter', 'serviceMonitor/observability/grafana/0':'grafana', 'serviceMonitor/observability/loki/0':'observability/loki', 'serviceMonitor/observability/observability-core-kube-pr-alertmanager/0':'observability-core-kube-pr-alertmanager', 'serviceMonitor/observability/observability-core-kube-pr-alertmanager/1':'observability-core-kube-pr-alertmanager', 'serviceMonitor/observability/observability-core-kube-pr-apiserver/0':'apiserver', 'serviceMonitor/observability/observability-core-kube-pr-coredns/0':'coredns', 'serviceMonitor/observability/observability-core-kube-pr-kubelet/0':'kubelet', 'serviceMonitor/observability/observability-core-kube-pr-kubelet/1':'kubelet', 'serviceMonitor/observability/observability-core-kube-pr-kubelet/2':'kubelet', 'serviceMonitor/observability/observability-core-kube-pr-operator/0':'observability-core-kube-pr-operator', 'serviceMonitor/observability/observability-core-kube-pr-prometheus/0':'observability-core-kube-pr-prometheus', 'serviceMonitor/observability/observability-core-kube-pr-prometheus/1':'observability-core-kube-pr-prometheus', 'serviceMonitor/observability/observability-core-kube-state-metrics/0':'kube-state-metrics', 'serviceMonitor/observability/tempo/0':'tempo', } namespaces={pool:pool.split('/')[1] for pool in urls} namespaces.update({ 'serviceMonitor/observability/observability-core-kube-pr-apiserver/0':'default', 'serviceMonitor/observability/observability-core-kube-pr-coredns/0':'kube-system', 'serviceMonitor/observability/observability-core-kube-pr-kubelet/0':'kube-system', 'serviceMonitor/observability/observability-core-kube-pr-kubelet/1':'kube-system', 'serviceMonitor/observability/observability-core-kube-pr-kubelet/2':'kube-system', }) probe_targets={ 'probe/observability/platform-private-edge':iter([ ('https://db-admin.learn.hyeonworks.com/','http://blackbox-exporter.observability.svc.cluster.local:9115/probe?module=http_private_edge_403&target=https%3A%2F%2Fdb-admin.learn.hyeonworks.com%2F','blackbox-private-edge','private-edge'), ('https://grafana.learn.hyeonworks.com/','http://blackbox-exporter.observability.svc.cluster.local:9115/probe?module=http_private_edge_403&target=https%3A%2F%2Fgrafana.learn.hyeonworks.com%2F','blackbox-private-edge','private-edge'), ('https://storage-admin.learn.hyeonworks.com/','http://blackbox-exporter.observability.svc.cluster.local:9115/probe?module=http_private_edge_403&target=https%3A%2F%2Fstorage-admin.learn.hyeonworks.com%2F','blackbox-private-edge','private-edge')]), 'probe/observability/platform-private-internal':iter([ ('http://pgadmin.platform-admin.svc.cluster.local/misc/ping','http://blackbox-exporter.observability.svc.cluster.local:9115/probe?hostname=db-admin.learn.hyeonworks.com&module=http_private_internal_200&target=http%3A%2F%2Fpgadmin.platform-admin.svc.cluster.local%2Fmisc%2Fping','blackbox-private-internal','private-internal'), ('http://grafana.observability.svc.cluster.local/api/health','http://blackbox-exporter.observability.svc.cluster.local:9115/probe?hostname=grafana.learn.hyeonworks.com&module=http_private_internal_200&target=http%3A%2F%2Fgrafana.observability.svc.cluster.local%2Fapi%2Fhealth','blackbox-private-internal','private-internal'), ('http://minio-aistor-console.object-storage.svc.cluster.local:9090/','http://blackbox-exporter.observability.svc.cluster.local:9115/probe?hostname=storage-admin.learn.hyeonworks.com&module=http_private_internal_200&target=http%3A%2F%2Fminio-aistor-console.object-storage.svc.cluster.local%3A9090%2F','blackbox-private-internal','private-internal')]), 'probe/observability/platform-public-edge':iter([ ('https://git.learn.hyeonworks.com/api/healthz','http://blackbox-exporter.observability.svc.cluster.local:9115/probe?module=http_2xx&target=https%3A%2F%2Fgit.learn.hyeonworks.com%2Fapi%2Fhealthz','blackbox-public-edge','public-edge'), ('https://id.learn.hyeonworks.com/realms/hyeonworks/.well-known/openid-configuration','http://blackbox-exporter.observability.svc.cluster.local:9115/probe?module=http_2xx&target=https%3A%2F%2Fid.learn.hyeonworks.com%2Frealms%2Fhyeonworks%2F.well-known%2Fopenid-configuration','blackbox-public-edge','public-edge')]), } for target in item['data']['activeTargets']: pool=target['scrapePool'] if pool.startswith('probe/'): instance,url,job,group=next(probe_targets[pool]) target['scrapeUrl']=url target['labels']={'instance':instance,'job':job,'namespace':'observability','observability.hyeonworks.com/probe-group':group} else: from urllib.parse import urlsplit target['scrapeUrl']=target['globalUrl']=urls[pool] parsed=urlsplit(target['scrapeUrl']) target['discoveredLabels']={'__address__':parsed.netloc,'__scheme__':parsed.scheme,'__metrics_path__':parsed.path} target['labels']={'instance':parsed.netloc,'job':jobs[pool],'namespace':namespaces[pool]} path.write_text(json.dumps(item,separators=(',',':'))+'\n') PY chmod 0600 "$TEST_WORK/targets.json" validate_target_contract "$TEST_WORK/targets.json" jq '(.data.activeTargets[0].health)="down"' "$TEST_WORK/targets.json" >"$TEST_WORK/targets-down.json" expect_failure validate_target_contract "$TEST_WORK/targets-down.json" jq '.data.activeTargets += [{"scrapePool":"serviceMonitor/kube-system/kube-scheduler/0","health":"up"}]' "$TEST_WORK/targets.json" >"$TEST_WORK/targets-extra.json" expect_failure validate_target_contract "$TEST_WORK/targets-extra.json" jq '(.data.activeTargets[]|select(.scrapePool=="serviceMonitor/keycloak/keycloak/0").scrapeUrl)="http://10.42.0.12:8080/metrics"' "$TEST_WORK/targets.json" >"$TEST_WORK/targets-wrong-port.json" expect_failure validate_target_contract "$TEST_WORK/targets-wrong-port.json" jq '(.data.activeTargets[]|select(.scrapePool=="serviceMonitor/observability/grafana/0").scrapeUrl)="http://10.42.0.99:9998/metrics"' "$TEST_WORK/targets.json" >"$TEST_WORK/targets-core-wrong-port.json" expect_failure validate_target_contract "$TEST_WORK/targets-core-wrong-port.json" jq '(.data.activeTargets[]|select(.scrapePool=="serviceMonitor/observability/grafana/0")) |= (.scrapeUrl="http://10.42.0.99:3000/metrics" | .globalUrl=.scrapeUrl | .discoveredLabels.__address__="10.42.0.99:3000")' "$TEST_WORK/targets.json" >"$TEST_WORK/targets-same-port-substitution.json" expect_failure validate_target_contract "$TEST_WORK/targets-same-port-substitution.json" jq '(.data.activeTargets[]|select(.scrapePool=="probe/observability/platform-public-edge").labels.instance)="https://git.learn.hyeonworks.com/api/healthz"' "$TEST_WORK/targets.json" >"$TEST_WORK/targets-substituted-instance.json" expect_failure validate_target_contract "$TEST_WORK/targets-substituted-instance.json" pass 'target validator enforces exact 30-target/25-pool allowlist' cat >"$TEST_WORK/series.json" <<'JSON' {"status":"success","data":{"resultType":"vector","result":[ {"metric":{"bucket":"loki","job":"minio-aistor","namespace":"object-storage","instance":"10.42.0.4:9000"},"value":[1,"1"]}, {"metric":{"bucket":"tempo","job":"minio-aistor","namespace":"object-storage","instance":"10.42.0.4:9000"},"value":[1,"1"]} ]}} JSON chmod 0600 "$TEST_WORK/series.json" validate_series_contract "$TEST_WORK/series.json" 2 'bucket,instance,job,namespace' 'loki,tempo' bucket expect_failure validate_series_contract "$TEST_WORK/series.json" 1 'bucket,instance,job,namespace' 'loki,tempo' bucket jq 'del(.data.result[0].metric.instance)' "$TEST_WORK/series.json" >"$TEST_WORK/series-bad.json" expect_failure validate_series_contract "$TEST_WORK/series-bad.json" 2 'bucket,instance,job,namespace' 'loki,tempo' bucket declare -F validate_series_identity_contract >/dev/null || fail 'exact series identity validator is missing' validate_series_identity_contract "$TEST_WORK/series.json" \ '[{"bucket":"loki","job":"minio-aistor","namespace":"object-storage"},{"bucket":"tempo","job":"minio-aistor","namespace":"object-storage"}]' \ '^([0-9]{1,3}[.]){3}[0-9]{1,3}:9000$' jq '(.data.result[0].metric.job)="wrong"' "$TEST_WORK/series.json" >"$TEST_WORK/series-wrong-job.json" expect_failure validate_series_identity_contract "$TEST_WORK/series-wrong-job.json" \ '[{"bucket":"loki","job":"minio-aistor","namespace":"object-storage"},{"bucket":"tempo","job":"minio-aistor","namespace":"object-storage"}]' \ '^([0-9]{1,3}[.]){3}[0-9]{1,3}:9000$' pass 'metric-series validator enforces count, labels, and exact values' : >"$TEST_WORK/metric-query-contract.log" ( check_one_query() { printf '%s\037' "$@" >>"$TEST_WORK/metric-query-contract.log"; printf '\n' >>"$TEST_WORK/metric-query-contract.log"; } check_metric_contracts >/dev/null ) || fail 'metric query contract renderer' cnpg_contract="$(grep '^cnpg' "$TEST_WORK/metric-query-contract.log")" keycloak_contract="$(grep '^keycloak' "$TEST_WORK/metric-query-contract.log")" assert_contains "$keycloak_contract" 'process_uptime_seconds{job="keycloak-service",namespace="keycloak"}' 'Keycloak query live job identity' assert_contains "$keycloak_contract" '[{"job":"keycloak-service","namespace":"keycloak"}]' 'Keycloak result live job identity' assert_contains "$cnpg_contract" 'cnpg_collector_up{job="platform-postgres",namespace="platform-data",cluster="platform-postgres"}' 'CNPG query cluster identity' assert_contains "$cnpg_contract" '[{"cluster":"platform-postgres","job":"platform-postgres","namespace":"platform-data"}]' 'CNPG result cluster identity' pass 'CNPG metric query binds the exact cluster identity' cat >"$TEST_WORK/datasources.json" <<'JSON' {"prometheus":{"status":"OK"},"loki":{"status":"OK"},"tempo":{"status":"OK"}, "loki_config":{"uid":"loki","jsonData":{"derivedFields":[{"name":"trace_id","datasourceUid":"tempo","url":"${__value.raw}"}]}}, "tempo_config":{"uid":"tempo","jsonData":{"tracesToLogsV2":{"datasourceUid":"loki","filterByTraceID":true}}}, "selected_trace":"0123456789abcdef0123456789abcdef", "tempo_search":{"traces":[{"traceID":"0123456789abcdef0123456789abcdef","rootServiceName":"platform-smoke"}]}, "loki_query":{"status":"success","data":{"result":[{"values":[["1","{\"trace_id\":\"0123456789abcdef0123456789abcdef\"}"]]}]}}, "tempo_query":{"batches":[{"resource":{"attributes":[{"key":"service.name","value":{"stringValue":"platform-smoke"}}]},"scopeSpans":[{"spans":[{"traceId":"ASNFZ4mrze8BI0VniavN7w=="}]}]}]}} JSON chmod 0600 "$TEST_WORK/datasources.json" validate_datasource_contract "$TEST_WORK/datasources.json" jq '.tempo.status="ERROR"' "$TEST_WORK/datasources.json" >"$TEST_WORK/datasources-bad.json" expect_failure validate_datasource_contract "$TEST_WORK/datasources-bad.json" jq '.loki_query.data.result=[]' "$TEST_WORK/datasources.json" >"$TEST_WORK/datasources-no-link.json" expect_failure validate_datasource_contract "$TEST_WORK/datasources-no-link.json" declare -F synthetic_loki_query >/dev/null || fail 'core synthetic Loki selector builder is missing' assert_eq '{cluster="home",namespace="observability"} | json | trace_id="0123456789abcdef0123456789abcdef"' \ "$(synthetic_loki_query 0123456789abcdef0123456789abcdef)" 'core synthetic Loki selector' expect_failure synthetic_loki_query 'bad"trace' jq '(.tempo_query.batches[0].resource.attributes[0].value.stringValue)="wrong-service"' \ "$TEST_WORK/datasources.json" >"$TEST_WORK/datasources-wrong-synthetic.json" expect_failure validate_datasource_contract "$TEST_WORK/datasources-wrong-synthetic.json" pass 'datasource validator requires health and a live Loki-to-Tempo link' # Mutation caught: incomplete human evidence must never produce full PASS. complete_tokens=$'OIDC_ADMIN_CONFIRMED\nOIDC_VIEWER_CONFIRMED\nOIDC_DENIED_CONFIRMED\nBREAK_GLASS_CONFIRMED\nREMOVAL_VIEWER_CONFIRMED\nSESSION_REVOKED\nRELOGIN_DENIED\nFIRING\nRESOLVED\nEXTERNAL_CLIENT_VERIFIED' validate_human_tokens <<<"$complete_tokens" expect_failure bash -c 'PLATFORM_OBSERVABILITY_SMOKE_SOURCE_ONLY=1 source "$1"; validate_human_tokens' bash "$SMOKE" <<<"${complete_tokens%$'\nEXTERNAL_CLIENT_VERIFIED'}" pass 'human acceptance requires every exact token' declare -F external_attestation_token >/dev/null || fail 'external-client bound attestation token is missing' assert_eq 'EXTERNAL_CLIENT_VERIFIED public_ip=203.0.113.10 status=403 source=outside-lan-tailscale proxy=disabled' \ "$(external_attestation_token 203.0.113.10)" 'external attestation fields' expect_failure external_attestation_token '203.0.113.10;touch /tmp/no' external_instructions="$(render_external_attestation 203.0.113.10)" assert_contains "$external_instructions" "--resolve $GRAFANA_HOST:443:203.0.113.10" 'external exact resolve command' assert_contains "$external_instructions" 'Expected exact result: HTTP 403' 'external exact expected result' assert_contains "$external_instructions" 'outside both LAN and Tailscale' 'external source requirement' pass 'external-client evidence binds exact command, source and result fields' declare -F confirmation_remaining_seconds >/dev/null || fail 'shared confirmation deadline calculator is missing' assert_eq 300 "$(confirmation_remaining_seconds 1300 1000)" 'shared deadline initial window' assert_eq 1 "$(confirmation_remaining_seconds 1300 1299)" 'shared deadline last second' expect_failure confirmation_remaining_seconds 1300 1300 expect_failure confirmation_remaining_seconds 1300 1301 pass 'session revoke and relogin confirmations share one five-minute deadline' declare -F capture_keycloak_absent_baseline >/dev/null || fail 'stable full Keycloak membership baseline helper is missing' declare -F add_keycloak_viewer_membership >/dev/null || fail 'response-safe Keycloak membership add helper is missing' ( WORK="$TEST_WORK"; KEYCLOAK_USER_ID='user-owned-id'; KEYCLOAK_VIEWER_GROUP_ID='viewer-owned-id' KEYCLOAK_MEMBERSHIP_BEFORE="$TEST_WORK/keycloak-full-baseline.json" : >"$TEST_WORK/keycloak-pagination.log" keycloak_request() { local output=$3 first printf '%s\n' "$2" >>"$TEST_WORK/keycloak-pagination.log" first="$(sed -n 's/.*[?&]first=\([0-9]*\).*/\1/p' <<<"$2")" if [[ "$first" == 0 ]]; then jq -n '[range(0;100)|{id:("group-"+tostring),name:("group-"+tostring),path:("/group-"+tostring)}]' >"$output" else jq -n '[{id:"viewer-owned-id",name:"platform-observability-viewers",path:"/platform-observability-viewers"}]' >"$output" fi chmod 0600 -- "$output"; printf 200 } expect_failure capture_keycloak_absent_baseline admin-owned-id [[ "$(wc -l <"$TEST_WORK/keycloak-pagination.log" | tr -d '[:space:]')" -ge 2 ]] ) || fail 'full Keycloak pagination detects a viewer membership after page one' keycloak_signal_rc=0 ( WORK="$TEST_WORK"; KEYCLOAK_USER_ID='user-owned-id'; KEYCLOAK_VIEWER_GROUP_ID='viewer-owned-id' KEYCLOAK_MEMBERSHIP_BEFORE="$TEST_WORK/keycloak-signal-baseline.json" printf '[]\n' >"$KEYCLOAK_MEMBERSHIP_BEFORE"; chmod 0600 -- "$KEYCLOAK_MEMBERSHIP_BEFORE" KEYCLOAK_TEST_ADDED=false; KEYCLOAK_MEMBERSHIP_PENDING=false; KEYCLOAK_MEMBERSHIP_REMOVED=false MUTATION_CRITICAL_DEPTH=0; DEFERRED_SIGNAL_RC=0; SIGNAL_TARGET=$BASHPID trap 'handle_termination_signal 130' INT trap 'printf "%s|%s\n" "$KEYCLOAK_TEST_ADDED" "$KEYCLOAK_MEMBERSHIP_PENDING" >"$TEST_WORK/keycloak-signal.capture"' EXIT keycloak_request() { local method=$1 output=$3 if [[ "$method" == PUT ]]; then : >"$output"; chmod 0600 -- "$output"; /bin/kill -INT "$SIGNAL_TARGET"; return 28 fi return 91 } keycloak_memberships() { jq -n '[{id:"viewer-owned-id",name:"platform-observability-viewers",path:"/platform-observability-viewers"}]' >"$1" chmod 0600 -- "$1" } add_keycloak_viewer_membership ) || keycloak_signal_rc=$? assert_eq 130 "$keycloak_signal_rc" 'deferred Keycloak membership signal status' assert_eq 'true|false' "$(<"$TEST_WORK/keycloak-signal.capture")" 'signal-safe Keycloak membership ownership capture' pass 'Keycloak membership add uses full baseline and response-safe ownership capture' # Production Keycloak cleanup leaf: a preexisting membership is never touched; # a test-added membership is removed by exact user/group IDs and verified # absent even when the DELETE response was lost. ( WORK="$TEST_WORK" KEYCLOAK_USER_ID='user-owned-id'; KEYCLOAK_VIEWER_GROUP_ID='viewer-owned-id' KEYCLOAK_MEMBERSHIP_BEFORE="$TEST_WORK/keycloak-cleanup-baseline.json" printf '[]\n' >"$KEYCLOAK_MEMBERSHIP_BEFORE"; chmod 0600 -- "$KEYCLOAK_MEMBERSHIP_BEFORE" KEYCLOAK_TEST_ADDED=false; KEYCLOAK_MEMBERSHIP_PENDING=false; KEYCLOAK_MEMBERSHIP_REMOVED=false keycloak_request() { printf 'unexpected\n' >>"$TEST_WORK/keycloak-cleanup.log"; return 1; } : >"$TEST_WORK/keycloak-cleanup.log" cleanup_keycloak_membership [[ ! -s "$TEST_WORK/keycloak-cleanup.log" ]] KEYCLOAK_TEST_ADDED=true rm -f -- "$TEST_WORK/keycloak-deleted.marker" keycloak_request() { printf '%s|%s\n' "$1" "$2" >>"$TEST_WORK/keycloak-cleanup.log" : >"$TEST_WORK/keycloak-deleted.marker" return 28 } keycloak_memberships() { if [[ ! -e "$TEST_WORK/keycloak-deleted.marker" ]]; then jq -n '[{id:"viewer-owned-id",name:"platform-observability-viewers",path:"/platform-observability-viewers"}]' >"$1" else printf '[]\n' >"$1" fi chmod 0600 -- "$1" } cleanup_keycloak_membership [[ "$KEYCLOAK_MEMBERSHIP_REMOVED" == true ]] ) || fail 'test-added Keycloak membership cleanup flow' assert_eq 'DELETE|/admin/realms/hyeonworks/users/user-owned-id/groups/viewer-owned-id' \ "$(<"$TEST_WORK/keycloak-cleanup.log")" 'exact Keycloak membership cleanup path' pass 'Keycloak cleanup touches only test-added exact membership' # Production Slack lifecycle/render leaf: firing proof precedes confirmation, # exact owned rule cleanup precedes resolved confirmation, and the alert carries # every grouping/runbook label without a webhook payload. cat >"$TEST_WORK/bin/date-slack" <<'SH' #!/usr/bin/env bash set -Eeuo pipefail [[ " $* " == *' +%Y%m%dT%H%M%SZ '* ]] printf '20260812T091011Z\n' SH chmod 0755 "$TEST_WORK/bin/date-slack" ( WORK="$TEST_WORK"; DATE_BIN="$TEST_WORK/bin/date-slack" new_smoke_run_id() { printf 'alert-20260812t091011z-00000000000000000000000000000001'; } CONFIRMATION_QUEUE=(FIRING RESOLVED); CONFIRMATION_INDEX=0; TEST_MODE=true create_owned_from_file() { cp -- "$1" "$TEST_WORK/slack-rule.capture"; printf 'create\n' >>"$TEST_WORK/slack-order.log"; } wait_for_smoke_alert() { printf 'wait-%s\n' "$2" >>"$TEST_WORK/slack-order.log"; } require_confirmation() { printf 'confirm-%s\n' "$1" >>"$TEST_WORK/slack-order.log"; [[ "${CONFIRMATION_QUEUE[$CONFIRMATION_INDEX]}" == "$1" ]] && CONFIRMATION_INDEX=$((CONFIRMATION_INDEX + 1)); } cleanup_owned_objects() { printf 'cleanup\n' >>"$TEST_WORK/slack-order.log"; } : >"$TEST_WORK/slack-order.log" run_slack_acceptance >"$TEST_WORK/slack-output.capture" ) || fail 'Slack lifecycle render flow' assert_eq $'create\nwait-present\nconfirm-FIRING\ncleanup\nconfirm-RESOLVED\nwait-absent' \ "$(<"$TEST_WORK/slack-order.log")" 'Slack lifecycle order' jq -e --arg runbook "$RUNBOOK_URL" ' .kind=="PrometheusRule" and .metadata.name=="observability-smoke-00000000000000000000000000000001" and .metadata.namespace=="observability" and .metadata.labels["platform.hyeonworks.com/smoke-run"]=="alert-20260812t091011z-00000000000000000000000000000001" and (.spec.groups|length)==1 and (.spec.groups[0].rules|length)==1 and .spec.groups[0].rules[0].alert=="PlatformObservabilitySmoke" and .spec.groups[0].rules[0].expr=="vector(1)" and .spec.groups[0].rules[0].labels=={"cluster":"home","namespace":"observability","instance":"alert-20260812t091011z-00000000000000000000000000000001","severity":"info"} and .spec.groups[0].rules[0].annotations.runbook_url==$runbook ' "$TEST_WORK/slack-rule.capture" >/dev/null || fail 'Slack rule exact payload contract' pass 'Slack lifecycle renders and cleans only one exact temporary rule' # Production network transaction leaf: first prove the exact deployed ingress # policies, then explicitly allow the test Pod's egress to both targets. A # failed connect can no longer be manufactured by a test-owned egress deny. cat >"$TEST_WORK/fixture-aistor-ingress-policy.json" <<'JSON' {"apiVersion":"networking.k8s.io/v1","kind":"NetworkPolicy","metadata":{"name":"object-storage-allow-prometheus-metrics","namespace":"object-storage","uid":"aistor-policy-uid","resourceVersion":"11"},"spec":{"podSelector":{"matchLabels":{"aistor.min.io/objectStore":"minio-aistor"}},"policyTypes":["Ingress"],"ingress":[{"from":[{"namespaceSelector":{"matchLabels":{"kubernetes.io/metadata.name":"observability"}},"podSelector":{"matchLabels":{"app.kubernetes.io/name":"prometheus","app.kubernetes.io/instance":"observability-core-kube-pr-prometheus"}}}],"ports":[{"protocol":"TCP","port":9000}]}]}} JSON cat >"$TEST_WORK/fixture-blackbox-ingress-policy.json" <<'JSON' {"apiVersion":"networking.k8s.io/v1","kind":"NetworkPolicy","metadata":{"name":"observability-allow-prometheus-to-blackbox","namespace":"observability","uid":"blackbox-policy-uid","resourceVersion":"12"},"spec":{"podSelector":{"matchLabels":{"app.kubernetes.io/name":"prometheus-blackbox-exporter","app.kubernetes.io/instance":"blackbox-exporter"}},"policyTypes":["Ingress"],"ingress":[{"from":[{"podSelector":{"matchLabels":{"app.kubernetes.io/name":"prometheus","app.kubernetes.io/instance":"observability-core-kube-pr-prometheus"}}}],"ports":[{"protocol":"TCP","port":9115}]}]}} JSON chmod 0600 "$TEST_WORK/fixture-aistor-ingress-policy.json" "$TEST_WORK/fixture-blackbox-ingress-policy.json" declare -F validate_deployed_ingress_policy_contracts >/dev/null || fail 'deployed ingress policy exact validator is missing' validate_deployed_ingress_policy_contracts "$TEST_WORK/fixture-aistor-ingress-policy.json" "$TEST_WORK/fixture-blackbox-ingress-policy.json" jq '.spec.ingress[0].from[0].podSelector.matchLabels["app.kubernetes.io/name"]="foreign"' \ "$TEST_WORK/fixture-aistor-ingress-policy.json" >"$TEST_WORK/aistor-ingress-policy-drift.json" expect_failure validate_deployed_ingress_policy_contracts \ "$TEST_WORK/aistor-ingress-policy-drift.json" "$TEST_WORK/fixture-blackbox-ingress-policy.json" ( WORK="$TEST_WORK"; DATE_BIN="$TEST_WORK/bin/date-slack" new_smoke_run_id() { printf 'network-20260812t091011z-00000000000000000000000000000001'; } kubectl_bounded() { if [[ "$1 $2 $3 $4 $5" == '-n object-storage get networkpolicy object-storage-allow-prometheus-metrics' ]]; then printf 'precondition-aistor\n' >>"$TEST_WORK/network-order.log"; cat -- "$TEST_WORK/fixture-aistor-ingress-policy.json"; return 0 fi if [[ "$1 $2 $3 $4 $5" == '-n observability get networkpolicy observability-allow-prometheus-to-blackbox' ]]; then printf 'precondition-blackbox\n' >>"$TEST_WORK/network-order.log"; cat -- "$TEST_WORK/fixture-blackbox-ingress-policy.json"; return 0 fi if [[ "$1 $2 $3 $4" == '-n object-storage get service' && "$5" == minio ]]; then printf '10.43.0.41'; return 0; fi if [[ "$1 $2 $3 $4" == '-n observability get service' && "$5" == blackbox-exporter ]]; then printf '10.43.0.42'; return 0; fi if [[ "$1 $2" == '-n observability' && "$3" == wait ]]; then printf 'wait\n' >>"$TEST_WORK/network-order.log"; return 0; fi if [[ "$1 $2" == '-n observability' && "$3" == logs ]]; then printf 'OBSERVABILITY_NETWORK_BOUNDARY_PASS\n'; return 0; fi return 91 } kubectl_wait_90_bounded() { kubectl_bounded "$@"; } create_owned_from_file() { case "$2" in NetworkPolicy) cp -- "$1" "$TEST_WORK/network-policy.capture" ;; Pod) cp -- "$1" "$TEST_WORK/network-pod.capture" ;; esac printf 'create-%s\n' "$2" >>"$TEST_WORK/network-order.log" } cleanup_owned_objects() { printf 'cleanup\n' >>"$TEST_WORK/network-order.log"; } : >"$TEST_WORK/network-order.log" run_network_boundary_transaction >"$TEST_WORK/network-output.capture" ) || fail "network transaction render flow: $(<"$TEST_WORK/network-order.log")" assert_eq $'precondition-aistor\nprecondition-blackbox\ncreate-NetworkPolicy\ncreate-Pod\nwait\ncleanup' "$(<"$TEST_WORK/network-order.log")" 'network transaction order' jq -e ' .kind=="NetworkPolicy" and .metadata.namespace=="observability" and .spec.policyTypes==["Egress"] and (.spec.egress|length)==3 and .spec.egress[0].ports==[{"protocol":"UDP","port":53},{"protocol":"TCP","port":53}] and (.spec.egress[0].to|length)==1 and .spec.egress[0].to[0].namespaceSelector.matchLabels["kubernetes.io/metadata.name"]=="kube-system" and .spec.egress[0].to[0].podSelector.matchLabels["k8s-app"]=="kube-dns" and .spec.egress[1]=={"to":[{"namespaceSelector":{"matchLabels":{"kubernetes.io/metadata.name":"object-storage"}},"podSelector":{"matchLabels":{"aistor.min.io/objectStore":"minio-aistor"}}}],"ports":[{"protocol":"TCP","port":9000}]} and .spec.egress[2]=={"to":[{"namespaceSelector":{"matchLabels":{"kubernetes.io/metadata.name":"observability"}},"podSelector":{"matchLabels":{"app.kubernetes.io/name":"prometheus-blackbox-exporter","app.kubernetes.io/instance":"blackbox-exporter"}}}],"ports":[{"protocol":"TCP","port":9115}]} ' "$TEST_WORK/network-policy.capture" >/dev/null || fail 'network-policy explicit target egress contract' jq -e --arg image "$BUSYBOX_IMAGE" ' .kind=="Pod" and .spec.automountServiceAccountToken==false and .spec.restartPolicy=="Never" and (.spec.containers|length)==1 and .spec.containers[0].image==$image and .spec.containers[0].securityContext.allowPrivilegeEscalation==false and .spec.containers[0].securityContext.readOnlyRootFilesystem==true and .spec.containers[0].securityContext.capabilities.drop==["ALL"] and (.spec.containers[0].command[2]|contains("nc -z -w 4 10.43.0.41 9000")) and (.spec.containers[0].command[2]|contains("nc -z -w 4 10.43.0.42 9115")) ' "$TEST_WORK/network-pod.capture" >/dev/null || fail 'network Pod exact restriction contract' pass 'network transaction proves deployed ingress denial with explicit test egress' unbounded_timeout_lines="$(rg -n '\"\$TIMEOUT_BIN\"(?!.*--kill-after)' "$SMOKE" --pcre2 | grep -v '\"\$SUDO_BIN\".*\"\$DATE_BIN\"' || true)" [[ -z "$unbounded_timeout_lines" ]] || fail "timeout without kill-after remains: $unbounded_timeout_lines" raw_silence_date_lines="$(rg -n 'start=\"\$\(\"\$DATE_BIN\"|end=\"\$\(\"\$DATE_BIN\"' "$SMOKE" || true)" [[ -z "$raw_silence_date_lines" ]] || fail "raw silence date subprocess remains: $raw_silence_date_lines" pass 'all fixed subprocess boundaries include terminal kill deadlines' # Production Certbot leaf: exact bounded dry-run includes deploy hooks and only # succeeds when Nginx remains active. cat >"$TEST_WORK/bin/sudo-certbot" <<'SH' #!/usr/bin/env bash set -Eeuo pipefail printf '%q ' "$@" >>"${OBS_SMOKE_CERTBOT_LOG:?}"; printf '\n' >>"${OBS_SMOKE_CERTBOT_LOG:?}" [[ "${1:-}" == -v ]] && exit 0 if [[ "${1:-}" == -n && "${2:-}" == /usr/bin/true ]]; then exit 0; fi if [[ "${1:-}" == -n && "${2:-}" == /usr/bin/systemctl && "${3:-}" == is-active && "${4:-}" == nginx ]]; then printf 'active\n'; exit 0; fi [[ " $* " == *' /snap/bin/certbot renew --dry-run --run-deploy-hooks '* ]] SH chmod 0755 "$TEST_WORK/bin/sudo-certbot" : >"$TEST_WORK/certbot.log" SUDO_BIN="$TEST_WORK/bin/sudo-certbot" OBS_SMOKE_CERTBOT_LOG="$TEST_WORK/certbot.log" run_certbot_acceptance >/dev/null assert_contains "$(<"$TEST_WORK/certbot.log")" '-n /usr/bin/timeout --signal=TERM --kill-after=5s 600s /snap/bin/certbot renew --dry-run --run-deploy-hooks' 'Certbot bounded deploy-hook argv' SUDO_BIN="$SUDO_DEFAULT" pass 'Certbot leaf runs exact dry-run deploy-hook and Nginx health gate' cat >"$TEST_WORK/bin/sudo-stall-unless-bounded" <<'SH' #!/usr/bin/env bash set -Eeuo pipefail parent="$(/usr/bin/tr '\0' ' ' <"/proc/$PPID/cmdline")" if [[ "$parent" == *'/usr/bin/timeout'* ]]; then exit 17; fi /usr/bin/sleep 5 SH chmod 0755 "$TEST_WORK/bin/sudo-stall-unless-bounded" stall_rc=0 /usr/bin/timeout --signal=TERM --kill-after=1s 1s bash -c ' PLATFORM_OBSERVABILITY_SMOKE_SOURCE_ONLY=1 source "$1" SUDO_BIN="$2" run_certbot_acceptance ' bash "$SMOKE" "$TEST_WORK/bin/sudo-stall-unless-bounded" >/dev/null 2>&1 || stall_rc=$? [[ "$stall_rc" != 124 ]] || fail 'privileged subprocess escaped its internal timeout' pass 'privileged Certbot and systemd subprocesses are internally bounded' # Regression RED: silence create/delete is response-outcome safe. A lost create # response is recovered only from one exact unique-run silence; a false 204 # cannot clear ownership while that exact silence remains. cat >"$TEST_WORK/bin/date-silence" <<'SH' #!/usr/bin/env bash set -Eeuo pipefail case " $* " in *' +%Y%m%dT%H%M%SZ '*) printf '20260812T091011Z\n' ;; *" -d +20 minutes +%Y-%m-%dT%H:%M:%SZ "*) printf '2026-08-12T09:30:11Z\n' ;; *' +%Y-%m-%dT%H:%M:%SZ '*) printf '2026-08-12T09:10:11Z\n' ;; *) exit 91 ;; esac SH chmod 0755 "$TEST_WORK/bin/date-silence" ( WORK="$TEST_WORK"; DATE_BIN="$TEST_WORK/bin/date-silence" new_smoke_run_id() { printf 'persistence-20260812t091011z-00000000000000000000000000000001'; } SILENCE_ID=''; SILENCE_RUN=''; SILENCE_POLL_ATTEMPTS=2; SILENCE_POLL_DELAY=0 MANUAL_RECOVERY=false rm -f -- "$TEST_WORK/silence-post-attempted" proxy_request() { local method=$1 output=$3 case "$method" in POST) cp -- "$4" "$TEST_WORK/silence-create-body.capture" : >"$output"; chmod 0600 -- "$output" : >"$TEST_WORK/silence-post-attempted" return 28 ;; GET) if [[ ! -f "$TEST_WORK/silence-post-attempted" ]]; then printf '[]\n' >"$output"; else jq -n --arg run 'persistence-20260812t091011z-00000000000000000000000000000001' '[{ id:"silence-owned-id",status:{state:"active"},createdBy:"platform-observability-smoke", comment:("Temporary restart-persistence acceptance "+$run), matchers:[ {name:"alertname",value:"PlatformObservabilityPersistenceSmoke",isRegex:false,isEqual:true}, {name:"instance",value:$run,isRegex:false,isEqual:true} ] }]' >"$output"; fi chmod 0600 -- "$output"; printf '200' ;; esac } create_persistence_silence printf '%s|%s\n' "$SILENCE_ID" "$SILENCE_RUN" >"$TEST_WORK/silence-create-recovered.capture" ) || fail 'lost-response silence create was not reconciled' assert_eq 'silence-owned-id|persistence-20260812t091011z-00000000000000000000000000000001' "$(<"$TEST_WORK/silence-create-recovered.capture")" 'recovered silence identity' jq -e ' .createdBy=="platform-observability-smoke" and .comment=="Temporary restart-persistence acceptance persistence-20260812t091011z-00000000000000000000000000000001" and ([.matchers[]|select(.name=="instance" and .value=="persistence-20260812t091011z-00000000000000000000000000000001" and .isRegex==false and .isEqual==true)]|length)==1 ' "$TEST_WORK/silence-create-body.capture" >/dev/null || fail 'unique silence create payload' false_delete_rc=0 ( WORK="$TEST_WORK"; SILENCE_ID='silence-owned-id'; SILENCE_RUN='persistence-20260812t091011z-00000000000000000000000000000001' SILENCE_POLL_ATTEMPTS=2; SILENCE_POLL_DELAY=0; MANUAL_RECOVERY=false emit_manual_recovery() { printf 'manual\n' >"$TEST_WORK/silence-delete-manual.capture"; MANUAL_RECOVERY=true; } proxy_request() { local method=$1 output=$3 if [[ "$method" == DELETE ]]; then : >"$output"; chmod 0600 -- "$output"; printf '204'; return 0; fi jq -n --arg run "$SILENCE_RUN" '[{ id:"silence-owned-id",status:{state:"active"},createdBy:"platform-observability-smoke", comment:("Temporary restart-persistence acceptance "+$run), matchers:[{name:"alertname",value:"PlatformObservabilityPersistenceSmoke",isRegex:false,isEqual:true},{name:"instance",value:$run,isRegex:false,isEqual:true}] }]' >"$output"; chmod 0600 -- "$output"; printf '200' } delete_persistence_silence ) || false_delete_rc=$? assert_eq 1 "$false_delete_rc" 'false-204 silence delete status' [[ -f "$TEST_WORK/silence-delete-manual.capture" ]] || fail 'false-204 silence delete omitted manual recovery' expired_delete_rc=0 ( WORK="$TEST_WORK"; SILENCE_ID='silence-owned-id'; SILENCE_RUN='persistence-20260812t091011z-00000000000000000000000000000001' SILENCE_POLL_ATTEMPTS=2; SILENCE_POLL_DELAY=0; MANUAL_RECOVERY=false proxy_request() { local method=$1 output=$3 if [[ "$method" == DELETE ]]; then : >"$output"; chmod 0600 -- "$output"; printf '204'; return 0; fi jq -n --arg run "$SILENCE_RUN" '[{ id:"silence-owned-id",status:{state:"expired"},createdBy:"platform-observability-smoke", comment:("Temporary restart-persistence acceptance "+$run), matchers:[{name:"alertname",value:"PlatformObservabilityPersistenceSmoke",isRegex:false,isEqual:true},{name:"instance",value:$run,isRegex:false,isEqual:true}] }]' >"$output"; chmod 0600 -- "$output"; printf '200' } delete_persistence_silence ) || expired_delete_rc=$? assert_eq 0 "$expired_delete_rc" 'stable expired silence delete outcome' pass 'silence lifecycle reconciles response loss and rejects false delete success' signal_silence_rc=0 ( WORK="$TEST_WORK"; DATE_BIN="$TEST_WORK/bin/date-silence" new_smoke_run_id() { printf 'persistence-20260812t091011z-00000000000000000000000000000002'; } SILENCE_ID=''; SILENCE_RUN=''; SILENCE_POLL_ATTEMPTS=2; SILENCE_POLL_DELAY=0 MUTATION_CRITICAL_DEPTH=0; DEFERRED_SIGNAL_RC=0 SIGNAL_TARGET=$BASHPID trap 'handle_termination_signal 130' INT trap 'printf "%s|%s\n" "$SILENCE_ID" "$SILENCE_RUN" >"$TEST_WORK/signal-silence.capture"' EXIT rm -f -- "$TEST_WORK/signal-silence-posted" proxy_request() { local method=$1 output=$3 case "$method" in POST) : >"$output"; chmod 0600 -- "$output" : >"$TEST_WORK/signal-silence-posted" /bin/kill -INT "$SIGNAL_TARGET" return 28 ;; GET) if [[ ! -f "$TEST_WORK/signal-silence-posted" ]]; then printf '[]\n' >"$output" else jq -n --arg run "$SILENCE_RUN" '[{id:"silence-signal-id",status:{state:"active"},createdBy:"platform-observability-smoke",comment:("Temporary restart-persistence acceptance "+$run),matchers:[{name:"alertname",value:"PlatformObservabilityPersistenceSmoke",isRegex:false,isEqual:true},{name:"instance",value:$run,isRegex:false,isEqual:true}]}]' >"$output" fi chmod 0600 -- "$output"; printf '200' ;; esac } create_persistence_silence ) || signal_silence_rc=$? assert_eq 130 "$signal_silence_rc" 'deferred silence signal status' assert_eq 'silence-signal-id|persistence-20260812t091011z-00000000000000000000000000000002' \ "$(<"$TEST_WORK/signal-silence.capture")" 'signal-safe silence ownership capture' pass 'silence signal window closes only after exact ownership capture' # Production raw delete leaf: keep its real API-path and UID DeleteOptions # builder while replacing only transport and post-delete reads. Transport loss # is success only after stable absence; a foreign replacement fails closed. RAW_DELETE_WORK="$(mktemp -d /tmp/platform-observability-smoke.XXXXXXXX)" chmod 0700 "$RAW_DELETE_WORK" ( WORK="$RAW_DELETE_WORK" proxy_request() { printf '%s|%s\n' "$1" "$2" >"$WORK/raw-delete-call" cp -- "$4" "$WORK/raw-delete-body" : >"$3" printf '200' } owned_object_state() { return 1; } delete_owned_uid Pod observability smoke-pod uid-pod ) assert_eq 'DELETE|/api/v1/namespaces/observability/pods/smoke-pod' "$(<"$RAW_DELETE_WORK/raw-delete-call")" 'raw delete API path' jq -e '.apiVersion=="meta.k8s.io/v1" and .kind=="DeleteOptions" and .propagationPolicy=="Background" and .preconditions=={"uid":"uid-pod"}' "$RAW_DELETE_WORK/raw-delete-body" >/dev/null || fail 'raw UID DeleteOptions contract' ambiguity_rc=0 ( WORK="$RAW_DELETE_WORK" proxy_request() { return 28; } owned_object_state() { return 1; } delete_owned_uid PrometheusRule observability smoke-rule uid-rule ) || ambiguity_rc=$? assert_eq 0 "$ambiguity_rc" 'transport ambiguity followed by absence' foreign_rc=0 ( WORK="$RAW_DELETE_WORK" proxy_request() { return 28; } owned_object_state() { printf '%s\n' 'foreign-uid|foreign-run'; return 0; } delete_owned_uid PrometheusRule observability smoke-rule uid-rule ) || foreign_rc=$? assert_eq 1 "$foreign_rc" 'foreign replacement raw delete status' rm -rf -- "$RAW_DELETE_WORK" RAW_DELETE_WORK='' pass 'production raw UID delete reconciles ambiguity and preserves replacement' # Regression RED: an ambiguous create may be followed by an unrelated object # with copied name/labels. Server defaults are allowed, but every desired field # and the exact standalone-container boundary must match before ownership. cat >"$TEST_WORK/owned-desired.json" <<'JSON' {"apiVersion":"v1","kind":"Pod","metadata":{"name":"smoke-pod","namespace":"observability","labels":{"app.kubernetes.io/managed-by":"platform-observability-smoke","platform.hyeonworks.com/smoke-run":"run-1"}},"spec":{"automountServiceAccountToken":false,"restartPolicy":"Never","containers":[{"name":"network-smoke","image":"busybox@sha256:fixture","command":["sh","-ec","true"],"securityContext":{"allowPrivilegeEscalation":false,"readOnlyRootFilesystem":true,"capabilities":{"drop":["ALL"]}}}]}} JSON jq '.metadata.uid="uid-pod" | .metadata.resourceVersion="7" | .spec.dnsPolicy="ClusterFirst" | .spec.containers[0].terminationMessagePolicy="File" | .status={"phase":"Pending"}' \ "$TEST_WORK/owned-desired.json" >"$TEST_WORK/owned-live-defaulted.json" chmod 0600 "$TEST_WORK/owned-desired.json" "$TEST_WORK/owned-live-defaulted.json" declare -F validate_live_matches_desired >/dev/null || fail 'ambiguous-create desired/live ownership validator is missing' validate_live_matches_desired "$TEST_WORK/owned-desired.json" "$TEST_WORK/owned-live-defaulted.json" jq '.spec.containers += [{"name":"foreign","image":"busybox:latest"}]' \ "$TEST_WORK/owned-live-defaulted.json" >"$TEST_WORK/owned-live-sidecar.json" expect_failure validate_live_matches_desired "$TEST_WORK/owned-desired.json" "$TEST_WORK/owned-live-sidecar.json" jq '.spec.containers[0].command=["sh","-ec","exfiltrate"]' \ "$TEST_WORK/owned-live-defaulted.json" >"$TEST_WORK/owned-live-drift.json" expect_failure validate_live_matches_desired "$TEST_WORK/owned-desired.json" "$TEST_WORK/owned-live-drift.json" pass 'ambiguous create ownership requires desired spec, not copied labels' # Production create leaf: exercise server dry-run, successful identity capture, # transport-ambiguous re-read, and a copied-label foreign-spec rejection. RAW_DELETE_WORK="$(mktemp -d /tmp/platform-observability-smoke.XXXXXXXX)" chmod 0700 "$RAW_DELETE_WORK" ( WORK="$RAW_DELETE_WORK" scenario=success owned_object_state() { return 1; } kubectl_bounded() { if [[ "$1" == create && "$2" == --dry-run=server ]]; then return 0; fi if [[ "$1" == create ]]; then cat -- "$TEST_WORK/owned-live-defaulted.json" [[ "$scenario" == success ]] && return 0 return 28 fi if [[ "$1" == -n && "$3" == get ]]; then if [[ "$scenario" == foreign ]]; then cat -- "$TEST_WORK/owned-live-sidecar.json"; else cat -- "$TEST_WORK/owned-live-defaulted.json"; fi return 0 fi return 91 } OWNED_KIND=(); OWNED_NAMESPACE=(); OWNED_NAME=(); OWNED_UID=(); OWNED_RUN=() create_owned_from_file "$TEST_WORK/owned-desired.json" Pod observability smoke-pod run-1 printf '%s|%s|%s|%s|%s\n' "${OWNED_KIND[0]}" "${OWNED_NAMESPACE[0]}" "${OWNED_NAME[0]}" "${OWNED_UID[0]}" "${OWNED_RUN[0]}" >"$TEST_WORK/create-success.capture" OWNED_KIND=(); OWNED_NAMESPACE=(); OWNED_NAME=(); OWNED_UID=(); OWNED_RUN=(); scenario=ambiguous ambiguous_create_rc=0 create_owned_from_file "$TEST_WORK/owned-desired.json" Pod observability smoke-pod run-1 || ambiguous_create_rc=$? printf '%s|%s|%s\n' "$ambiguous_create_rc" "${#OWNED_UID[@]}" "${OWNED_UID[0]:-}" >"$TEST_WORK/create-ambiguous.capture" OWNED_KIND=(); OWNED_NAMESPACE=(); OWNED_NAME=(); OWNED_UID=(); OWNED_RUN=(); scenario=foreign foreign_create_rc=0 emit_manual_recovery() { printf 'manual\n' >"$TEST_WORK/create-foreign-manual.capture"; } create_owned_from_file "$TEST_WORK/owned-desired.json" Pod observability smoke-pod run-1 || foreign_create_rc=$? printf '%s|%s\n' "$foreign_create_rc" "${#OWNED_UID[@]}" >"$TEST_WORK/create-foreign.capture" ) assert_eq 'Pod|observability|smoke-pod|uid-pod|run-1' "$(<"$TEST_WORK/create-success.capture")" 'successful create ownership capture' assert_eq '1|1|uid-pod' "$(<"$TEST_WORK/create-ambiguous.capture")" 'ambiguous create owned-state capture' assert_eq '1|0' "$(<"$TEST_WORK/create-foreign.capture")" 'foreign create ownership rejection' [[ -f "$TEST_WORK/create-foreign-manual.capture" ]] || fail 'foreign ambiguous create omitted manual-recovery evidence' rm -rf -- "$RAW_DELETE_WORK" RAW_DELETE_WORK='' pass 'production create leaf fails closed and records only exact owned state' # A signal delivered after the API commits but before the response is recorded # must be deferred until the exact created UID is in the cleanup ledger. declare -F handle_termination_signal >/dev/null || fail 'mutation signal deferral is missing' RAW_DELETE_WORK="$(mktemp -d /tmp/platform-observability-smoke.XXXXXXXX)" chmod 0700 "$RAW_DELETE_WORK" signal_create_rc=0 ( WORK="$RAW_DELETE_WORK" trap 'handle_termination_signal 130' INT trap 'printf "%s|%s\n" "${#OWNED_UID[@]}" "${OWNED_UID[0]:-}" >"$TEST_WORK/signal-create.capture"' EXIT owned_object_state() { return 1; } kubectl_bounded() { if [[ "$1" == create && "$2" == --dry-run=server ]]; then return 0; fi if [[ "$1" == create ]]; then /bin/kill -INT "$BASHPID" cat -- "$TEST_WORK/owned-live-defaulted.json" return 0 fi return 91 } OWNED_KIND=(); OWNED_NAMESPACE=(); OWNED_NAME=(); OWNED_UID=(); OWNED_RUN=() create_owned_from_file "$TEST_WORK/owned-desired.json" Pod observability smoke-pod run-1 ) || signal_create_rc=$? assert_eq 130 "$signal_create_rc" 'deferred create signal status' assert_eq '1|uid-pod' "$(<"$TEST_WORK/signal-create.capture")" 'signal-safe UID registration' rm -rf -- "$RAW_DELETE_WORK" RAW_DELETE_WORK='' pass 'create signal window closes only after exact UID registration' # Mutation caught: cleanup by name or without a matching UID could delete a # replacement. The fixture exercises owned, absent, and foreign identities. OWNED_KIND=(Pod NetworkPolicy PrometheusRule) OWNED_NAMESPACE=(observability observability observability) OWNED_NAME=(smoke-pod smoke-policy smoke-rule) OWNED_UID=(uid-pod uid-policy uid-rule) OWNED_RUN=(run-1 run-1 run-1) declare -a cleanup_calls=() owned_object_state() { case "$3" in smoke-pod) return 1 ;; smoke-policy) printf '%s\n' 'uid-policy|run-1'; return 0 ;; smoke-rule) printf '%s\n' 'foreign-uid|foreign-run'; return 0 ;; esac } delete_owned_uid() { cleanup_calls+=("$1|$2|$3|$4"); [[ "$3" != smoke-rule ]]; } cleanup_rc=0 cleanup_owned_objects || cleanup_rc=$? assert_eq 1 "$cleanup_rc" 'foreign cleanup status' assert_eq 'NetworkPolicy|observability|smoke-policy|uid-policy' "${cleanup_calls[0]}" 'exact UID cleanup call' assert_eq 1 "${#cleanup_calls[@]}" 'foreign object must not be deleted' pass 'cleanup preserves absent and foreign objects and UID-deletes only owned state' # Regression RED: an execute preflight may create the private work/proxy and # fail halfway. EXIT cleanup must already be armed before that first allocation. preflight_cleanup_marker="$TEST_WORK/preflight-cleanup.marker" preflight_rc=0 ( TEST_MODE=true require_execute_environment() { WORK='/tmp/platform-observability-smoke.fixture00'; return 1; } cleanup_all() { printf 'cleanup\n' >"$preflight_cleanup_marker"; } main --execute ) >/dev/null 2>&1 || preflight_rc=$? assert_eq 1 "$preflight_rc" 'partial preflight failure status' [[ -f "$preflight_cleanup_marker" ]] || fail 'partial execute preflight was not cleanup-armed' pass 'execute cleanup is armed before preflight allocation' # The main execute orchestration is tested with all external work replaced at # function boundaries. Wrong APPLY stops before mutation; missing external # evidence returns PARTIAL=2; success performs cleanup and reaches final PASS. run_orchestration_fixture() { local confirmations=$1 ( TEST_MODE=true PUBLIC_EDGE_IP='203.0.113.10' TEST_CONFIRMATIONS="$confirmations" mapfile -t CONFIRMATION_QUEUE <<<"$TEST_CONFIRMATIONS" CONFIRMATION_INDEX=0 require_execute_environment() { :; } run_read_only_machine_checks() { printf 'machine\n' >>"${ORCHESTRATION_LOG:-/dev/null}"; printf 'READ_ONLY_FIXTURE=PASS\n'; } repeat_commit_gate() { printf 'commit-gate\n' >>"${ORCHESTRATION_LOG:-/dev/null}"; } run_network_boundary_transaction() { printf 'network\n' >>"${ORCHESTRATION_LOG:-/dev/null}"; OWNED_KIND+=(Pod); OWNED_NAMESPACE+=(observability); OWNED_NAME+=(fixture-pod); OWNED_UID+=(fixture-uid); OWNED_RUN+=(fixture-run); } run_restart_persistence_transaction() { printf 'restart\n' >>"${ORCHESTRATION_LOG:-/dev/null}"; } run_certbot_acceptance() { printf 'certbot\n' >>"${ORCHESTRATION_LOG:-/dev/null}"; } run_oidc_acceptance() { require_confirmation OIDC_ADMIN_CONFIRMED; require_confirmation OIDC_VIEWER_CONFIRMED; require_confirmation OIDC_DENIED_CONFIRMED; require_confirmation BREAK_GLASS_CONFIRMED; require_confirmation REMOVAL_VIEWER_CONFIRMED; require_confirmation SESSION_REVOKED; require_confirmation RELOGIN_DENIED; printf 'OBSERVABILITY_OIDC_ACCEPTANCE=PASS\n'; } run_slack_acceptance() { require_confirmation FIRING; require_confirmation RESOLVED; printf 'OBSERVABILITY_SLACK_ACCEPTANCE=PASS\n'; } owned_object_state() { return 1; } delete_owned_uid() { :; } main --execute ) } wrong_rc=0 wrong_output="$(run_orchestration_fixture 'WRONG' 2>&1)" || wrong_rc=$? assert_eq 1 "$wrong_rc" 'wrong APPLY orchestration status' assert_not_contains "$wrong_output" 'OBSERVABILITY_MACHINE_ACCEPTANCE=PASS' 'wrong APPLY reached mutation' partial_confirmations=$'APPLY default\nOIDC_ADMIN_CONFIRMED\nOIDC_VIEWER_CONFIRMED\nOIDC_DENIED_CONFIRMED\nBREAK_GLASS_CONFIRMED\nREMOVAL_VIEWER_CONFIRMED\nSESSION_REVOKED\nRELOGIN_DENIED\nFIRING\nRESOLVED' partial_rc=0 partial_output="$(run_orchestration_fixture "$partial_confirmations" 2>&1)" || partial_rc=$? assert_eq 2 "$partial_rc" 'external partial orchestration status' assert_contains "$partial_output" 'OBSERVABILITY_EXTERNAL_BOUNDARY=PARTIAL' 'external partial marker' assert_not_contains "$partial_output" 'OBSERVABILITY_SMOKE=PASS' 'partial acceptance falsely passed' full_confirmations="$partial_confirmations"$'\nEXTERNAL_CLIENT_VERIFIED public_ip=203.0.113.10 status=403 source=outside-lan-tailscale proxy=disabled' : >"$TEST_WORK/orchestration-order.log" full_output="$(ORCHESTRATION_LOG="$TEST_WORK/orchestration-order.log" run_orchestration_fixture "$full_confirmations")" assert_contains "$full_output" 'OBSERVABILITY_MACHINE_ACCEPTANCE=PASS' 'machine acceptance marker' assert_contains "$full_output" 'OBSERVABILITY_SMOKE=PASS' 'full acceptance marker' assert_eq $'machine\ncommit-gate\nnetwork\nrestart\ncertbot\ncommit-gate\nmachine' \ "$(<"$TEST_WORK/orchestration-order.log")" 'post-mutation full machine revalidation order' pass 'execute orchestration is gated and cannot turn partial into PASS' bash -n "$SMOKE" bash -n "$TEST_ROOT/scripts/validate/test-observability-smoke.sh" printf 'OBSERVABILITY SMOKE TEST PASS (%d assertions)\n' "$ASSERTIONS"