Files
platform-core/scripts/validate/test-observability-smoke.sh
T

1112 lines
69 KiB
Bash

#!/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" <<EOF
trace-ascii = "$TEST_WORK/hostile-curl.trace"
header = "X-Ambient-Curlrc: forbidden"
EOF
chmod 0600 "$TEST_WORK/curl-home/.curlrc"
HOME="$TEST_WORK/curl-home" CURL_HOME="$TEST_WORK/curl-home" \
http_status 'file:///etc/hosts' >/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"