#!/usr/bin/env bash set -Eeuo pipefail readonly ROOT="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd -P)" readonly TEST_SCRIPT="$(readlink -f -- "${BASH_SOURCE[0]}")" readonly APPLY="$ROOT/scripts/bootstrap/apply-observability-access.sh" readonly ROLLBACK_ID=20260812T120000Z readonly INITIAL_PRODUCTION_SHA=79688d017d38eec9a6f100f8d0f784a5474e79802046ef1c2c11b30d170b0b0c readonly POST_PRODUCTION_SHA=b1c3049206a1a88165ee672ae9aceac7945673a3bb9c3cf3670b7f0d56c3f291 readonly INITIAL_TARGET_COUNT=21 readonly POST_TARGET_COUNT=30 readonly SUITE_WALL_BOUND_SECONDS=300 WORK='' declare -a METRIC_ROOTS=() ASSERTIONS=0 fail() { printf 'FAIL: %s\n' "$*" >&2 exit 1 } pass() { ASSERTIONS=$((ASSERTIONS + 1)) printf 'PASS: %s\n' "$1" } case_progress() { local case_name=$1 marker="CASE_BEGIN=$1" printf '%s\n' "$marker" printf '%s\n' "$marker" >>"$PROGRESS_LOG" } run_with_wall_bound() { local seconds=$1 shift [[ "$seconds" =~ ^[1-9][0-9]*$ && $# -gt 0 ]] || return 2 timeout --signal=TERM --kill-after=2s "${seconds}s" "$@" } cleanup() { trap - EXIT HUP INT TERM case "$WORK" in /tmp/platform-observability-access-test.*) rm -rf -- "$WORK" ;; esac local root for root in "${METRIC_ROOTS[@]}"; do case "$root" in /tmp/platform-observability-metrics.??????) rm -rf -- "$root" ;; esac done } trap cleanup EXIT trap 'exit 129' HUP trap 'exit 130' INT trap 'exit 143' TERM write_executable() { local path=$1 shift printf '%s\n' "$@" >"$path" chmod 0755 "$path" } make_fakes() { local fixture=$1 mkdir -m 0700 -p "$fixture/bin" "$fixture/state" chmod 0700 "$fixture/bin" "$fixture/state" : >"$fixture/commands.log" write_executable "$fixture/bin/sudo" \ '#!/usr/bin/env bash' \ 'printf '\''sudo'\'' >>"$PLATFORM_TEST_COMMAND_LOG"' \ 'printf '\'' %q'\'' "$@" >>"$PLATFORM_TEST_COMMAND_LOG"' \ 'printf '\''\n'\'' >>"$PLATFORM_TEST_COMMAND_LOG"' \ 'if [[ "${1:-}" == -v ]]; then : >"$PLATFORM_TEST_SUDO_REFRESHED"; exit 0; fi' \ '[[ -f "$PLATFORM_TEST_SUDO_REFRESHED" ]] || exit 92' \ 'if [[ "${1:-}" == -n ]]; then shift; fi' \ '(( $# > 0 )) || exit 0' \ 'if [[ "${PLATFORM_TEST_SUDO_FAIL_ACCEPTANCE:-0}" == 1 && " $* " == *" install "* && "$*" == *"acceptance.env"* ]]; then exit 81; fi' \ 'args=()' \ 'while (( $# > 0 )); do case "$1" in -o|-g) shift 2 ;; *) args+=("$1"); shift ;; esac; done' \ 'exec "${args[@]}"' write_executable "$fixture/bin/encryption" \ '#!/usr/bin/env bash' \ 'printf '\''encryption'\'' >>"$PLATFORM_TEST_COMMAND_LOG"; printf '\'' %q'\'' "$@" >>"$PLATFORM_TEST_COMMAND_LOG"; printf '\''\n'\'' >>"$PLATFORM_TEST_COMMAND_LOG"' \ 'count=0; [[ -f "$PLATFORM_TEST_ENCRYPTION_COUNT" ]] && read -r count <"$PLATFORM_TEST_ENCRYPTION_COUNT"' \ 'count=$((count + 1)); printf '\''%s\n'\'' "$count" >"$PLATFORM_TEST_ENCRYPTION_COUNT"' \ 'if [[ "$count" == 2 && -n "${PLATFORM_TEST_MUTATE_HANDOFF_ON_LAST_GATE:-}" ]]; then printf '\''# changed\n'\'' >>"$PLATFORM_TEST_MUTATE_HANDOFF_ON_LAST_GATE"; fi' \ 'action="${PLATFORM_TEST_MUTATE_INVENTORY_ON_LAST_GATE:-}"' \ 'if [[ "$count" == 2 && -n "$action" ]]; then' \ ' fixture_root="$(dirname -- "$PLATFORM_TEST_COMMAND_LOG")"; expected_root="$fixture_root/metrics"' \ ' [[ "$action" == raw-json || "$action" == rechecksum-count || "$action" == hardlink ]] || exit 73' \ ' [[ "$PLATFORM_TEST_INVENTORY_ROOT" == "$expected_root" && -d "$PLATFORM_TEST_INVENTORY_ROOT" && ! -L "$PLATFORM_TEST_INVENTORY_ROOT" && "$(readlink -f -- "$PLATFORM_TEST_INVENTORY_ROOT")" == "$expected_root" ]] || exit 74' \ ' inventory="$expected_root/target-initial/inventory.json"; checksum="$expected_root/target-initial/inventory.sha256"' \ ' case "$action" in' \ ' raw-json) printf '\'' \n'\'' >>"$inventory" ;;' \ ' rechecksum-count) jq -c '\''.targets |= .[:-1]'\'' "$inventory" >"$inventory.next"; chmod 0600 "$inventory.next"; mv -f -- "$inventory.next" "$inventory"; sha="$(sha256sum -- "$inventory" | awk '\''{print $1}'\'')"; printf '\''%s inventory.json\n'\'' "$sha" >"$checksum"; chmod 0600 "$checksum" ;;' \ ' hardlink) ln -- "$inventory" "$fixture_root/inventory-hardlink-control" ;;' \ ' esac' \ 'fi' \ 'if [[ "$count" == "${PLATFORM_TEST_ENCRYPTION_FAIL_AT:-0}" ]]; then exit 71; fi' write_executable "$fixture/bin/restore" \ '#!/usr/bin/env bash' \ 'printf '\''restore'\'' >>"$PLATFORM_TEST_COMMAND_LOG"; printf '\'' %q'\'' "$@" >>"$PLATFORM_TEST_COMMAND_LOG"; printf '\''\n'\'' >>"$PLATFORM_TEST_COMMAND_LOG"' \ 'count=0; [[ -f "$PLATFORM_TEST_RESTORE_COUNT" ]] && read -r count <"$PLATFORM_TEST_RESTORE_COUNT"' \ 'count=$((count + 1)); printf '\''%s\n'\'' "$count" >"$PLATFORM_TEST_RESTORE_COUNT"' \ 'if [[ "$count" == "${PLATFORM_TEST_RESTORE_FAIL_AT:-0}" ]]; then exit 72; fi' write_executable "$fixture/bin/recovery" \ '#!/usr/bin/env bash' \ 'printf '\''recovery'\'' >>"$PLATFORM_TEST_COMMAND_LOG"; printf '\'' %q'\'' "$@" >>"$PLATFORM_TEST_COMMAND_LOG"; printf '\''\n'\'' >>"$PLATFORM_TEST_COMMAND_LOG"' \ 'count=0; [[ -f "$PLATFORM_TEST_RECOVERY_COUNT" ]] && read -r count <"$PLATFORM_TEST_RECOVERY_COUNT"' \ 'count=$((count + 1)); printf '\''%s\n'\'' "$count" >"$PLATFORM_TEST_RECOVERY_COUNT"' \ 'response_var="PLATFORM_TEST_RECOVERY_OUTPUT_${count}"; response="${!response_var:-SLACK_DEPLOYMENT_GATE=RECOVERY\\n}"' \ 'rc_var="PLATFORM_TEST_RECOVERY_RC_${count}"; rc="${!rc_var:-${PLATFORM_TEST_RECOVERY_RC:-0}}"' \ 'printf '\''%b'\'' "$response"' \ 'exit "$rc"' cat >"$fixture/bin/kubectl" <<'PY' #!/usr/bin/env python3 import json import hashlib import os import pathlib import signal import socketserver import sys import time from http.server import BaseHTTPRequestHandler import yaml raw_args = sys.argv[1:] log = pathlib.Path(os.environ["PLATFORM_TEST_COMMAND_LOG"]) with log.open("a", encoding="utf-8") as stream: stream.write("kubectl " + " ".join(raw_args) + "\n") if not raw_args or raw_args[0] != "--request-timeout=10s": raise SystemExit(93) args = raw_args[1:] state = pathlib.Path(os.environ["PLATFORM_TEST_STATE"]) kind_alias = { "configmap": "ConfigMap", "configmaps": "ConfigMap", "prometheusrule": "PrometheusRule", "prometheusrules": "PrometheusRule", "alertmanagerconfig": "AlertmanagerConfig", "alertmanagerconfigs": "AlertmanagerConfig", "alertmanager": "Alertmanager", "alertmanagers": "Alertmanager", "networkpolicy": "NetworkPolicy", "networkpolicies": "NetworkPolicy", } def option(*names, default=None): for position, value in enumerate(args): if value in names and position + 1 < len(args): return args[position + 1] for name in names: if value.startswith(name + "="): return value.split("=", 1)[1] return default def state_path(kind, namespace, name): return state / f"{kind}__{namespace}__{name}.json" def load_documents(filename): with open(filename, encoding="utf-8") as stream: return [item for item in yaml.safe_load_all(stream) if item] if args == ["config", "current-context"]: print("default") raise SystemExit(0) if args[:2] == ["config", "view"]: print("https://127.0.0.1:6443", end="") raise SystemExit(0) if args[:2] == ["get", "node"]: print(json.dumps({ "metadata": {"name": "donghyeon-system-product-name", "uid": "node-uid"}, "status": {"conditions": [{"type": "Ready", "status": "True"}]}, })) raise SystemExit(0) if args[:3] == ["get", "secret", "alertmanager-slack-webhook"]: schema_count_path = pathlib.Path(os.environ["PLATFORM_TEST_SLACK_SCHEMA_COUNT"]) schema_count = int(schema_count_path.read_text()) if schema_count_path.exists() else 0 schema_count += 1 schema_count_path.write_text(str(schema_count)) extra_at = os.environ.get("PLATFORM_TEST_SLACK_EXTRA_KEY_AT", "0") extra = (os.environ.get("PLATFORM_TEST_SLACK_EXTRA_KEY", "0") == "1" or (extra_at.isdigit() and schema_count == int(extra_at))) keys = ["extra", "url"] if extra else ["url"] print(json.dumps({ "apiVersion": "v1", "kind": "Secret", "type": "Opaque", "metadata": {"name": "alertmanager-slack-webhook", "namespace": "observability"}, "data": {key: "cmVkYWN0ZWQ=" for key in keys}, })) raise SystemExit(0) if args[:2] == ["get", "probe"]: print(json.dumps({"items": [ {"metadata": {"name": "platform-private-edge"}}, {"metadata": {"name": "platform-private-internal"}}, {"metadata": {"name": "platform-public-edge"}}, ]})) raise SystemExit(0) if args[:3] == ["get", "servicemonitor", "aistor-bucket-usage"]: print("servicemonitor.monitoring.coreos.com/aistor-bucket-usage") raise SystemExit(0) if args[:3] == ["get", "podmonitor", "platform-postgres"]: print("podmonitor.monitoring.coreos.com/platform-postgres") raise SystemExit(0) if args and args[0] == "get" and option("--raw"): raw_path = option("--raw") pathlib.Path(os.environ["PLATFORM_TEST_POSTCHECK_REACHED"]).touch() if os.environ.get("PLATFORM_TEST_POSTCHECK_RC", "0") != "0": raise SystemExit(74) if raw_path.endswith("/proxy/-/ready") and "prometheus" in raw_path: print("Prometheus Server is Ready.") raise SystemExit(0) if raw_path.endswith("/proxy/-/ready") and "alertmanager" in raw_path: print("OK") raise SystemExit(0) if raw_path.endswith("/proxy/api/v1/rules"): groups = [] for path in sorted(state.glob("PrometheusRule__observability__*.json")): item = json.loads(path.read_text(encoding="utf-8")) for group in (item.get("spec") or {}).get("groups") or []: rules = [] for rule in group.get("rules") or []: rules.append({ "name": rule.get("alert") or rule.get("record"), "type": "alerting" if rule.get("alert") else "recording", "health": "ok", "lastError": "", "query": str(rule.get("expr", "")), }) groups.append({"name": group.get("name"), "rules": rules}) if os.environ.get("PLATFORM_TEST_PROMETHEUS_DROP_RULE", "0") == "1" and groups: groups[0]["rules"] = groups[0]["rules"][1:] print(json.dumps({"status": "success", "data": {"groups": groups}})) raise SystemExit(0) if raw_path.endswith("/proxy/api/v2/receivers"): mode = os.environ.get("PLATFORM_TEST_ALERTMANAGER_RECEIVER_MODE", "qualified") platform_null = "observability/platform-alertmanager/platform-null" platform_slack = "observability/platform-alertmanager/platform-slack" def receiver(name): return {"labels": {"name": name}, "name": name} receiver_cases = { "qualified": [receiver(platform_null), receiver(platform_slack)], "qualified-reversed": [receiver(platform_slack), receiver(platform_null)], "raw": [receiver("platform-null"), receiver("platform-slack")], "empty": [], "null": [None, receiver(platform_slack)], "duplicate": [receiver(platform_null), receiver(platform_null)], "extra": [receiver(platform_null), receiver(platform_slack), receiver("null")], "wrong-namespace": [receiver("other/platform-alertmanager/platform-null"), receiver(platform_slack)], "wrong-config": [receiver(platform_null), receiver("observability/other/platform-slack")], "wrong-local": [receiver(platform_null), receiver("observability/platform-alertmanager/other")], } if mode == "malformed": print('{"name":') elif mode in receiver_cases: print(json.dumps(receiver_cases[mode])) else: raise SystemExit(76) raise SystemExit(0) raise SystemExit(75) if args and args[0] == "get" and len(args) >= 3: kind = kind_alias.get(args[1].lower()) if not kind: raise SystemExit(44) name = args[2] namespace = option("-n", "--namespace", default="default") path = state_path(kind, namespace, name) if not path.exists(): if "--ignore-not-found" in args: raise SystemExit(0) raise SystemExit(1) item = json.loads(path.read_text()) drift = os.environ.get("PLATFORM_TEST_DRIFT_RESOURCE", "") reached = pathlib.Path(os.environ["PLATFORM_TEST_POSTCHECK_REACHED"]).exists() if reached and drift == f"{kind}/{name}": item["metadata"]["uid"] = "uid-drifted-by-other-owner" print(json.dumps(item)) raise SystemExit(0) if args and args[0] == "apply": filename = option("-f", "--filename") if not filename: raise SystemExit(45) if option("--dry-run") == "server" or "--dry-run=server" in args: raise SystemExit(0) counter = pathlib.Path(os.environ["PLATFORM_TEST_APPLY_COUNT"]) count = int(counter.read_text()) if counter.exists() else 0 for item in load_documents(filename): count += 1 counter.write_text(str(count)) if count == int(os.environ.get("PLATFORM_TEST_FAIL_APPLY_AT", "0")): raise SystemExit(73) metadata = item.setdefault("metadata", {}) namespace = metadata.get("namespace", "default") kind = item["kind"] path = state_path(kind, namespace, metadata["name"]) prior = json.loads(path.read_text()) if path.exists() else None metadata["uid"] = (prior or {}).get("metadata", {}).get("uid", f"uid-new-{kind}-{metadata['name']}") metadata["resourceVersion"] = str(1000 + count) metadata["generation"] = 2 path.write_text(json.dumps(item)) if count == int(os.environ.get("PLATFORM_TEST_FAIL_AFTER_APPLY_AT", "0")): raise SystemExit(73) raise SystemExit(0) if args and args[0] == "replace": filename = option("-f", "--filename") documents = load_documents(filename) if filename else [] if len(documents) != 1: raise SystemExit(47) item = documents[0] metadata = item.get("metadata") or {} namespace = metadata.get("namespace", "default") path = state_path(item["kind"], namespace, metadata["name"]) if not path.exists(): raise SystemExit(48) prior = json.loads(path.read_text()) prior_metadata = prior.get("metadata") or {} with log.open("a", encoding="utf-8") as stream: stream.write( f"replace-preconditions {item['kind']}/{metadata.get('name')} " f"uid={metadata.get('uid')} resourceVersion={metadata.get('resourceVersion')}\n" ) if (metadata.get("uid") != prior_metadata.get("uid") or metadata.get("resourceVersion") != prior_metadata.get("resourceVersion")): raise SystemExit(49) if os.environ.get("PLATFORM_TEST_REPLACE_CONFLICT", "0") == "1": raise SystemExit(409) metadata["resourceVersion"] = "replaced" path.write_text(json.dumps(item)) raise SystemExit(0) if args and args[0] == "exec": expected = { "grafana-dashboard-https-endpoints": "https-endpoints.json", "grafana-dashboard-kubernetes-node": "kubernetes-node.json", "grafana-dashboard-observability-backends": "observability-backends.json", "grafana-dashboard-platform-services": "platform-services.json", "grafana-dashboard-workload-health": "workload-health.json", } lines = [] for name, filename in expected.items(): item = json.loads(state_path("ConfigMap", "observability", name).read_text(encoding="utf-8")) data = item.get("data") or {} if set(data) != {filename}: raise SystemExit(76) digest = hashlib.sha256(data[filename].encode()).hexdigest() lines.append(f"{digest} /tmp/dashboards/{filename}") if os.environ.get("PLATFORM_TEST_GRAFANA_STALE_DASHBOARD", "0") == "1": lines[0] = "0" * 64 + " /tmp/dashboards/https-endpoints.json" print("\n".join(lines)) raise SystemExit(0) if args and args[0] == "proxy": socket_path = option("--unix-socket") if not socket_path: raise SystemExit(77) socket_file = pathlib.Path(socket_path) if socket_file.exists(): socket_file.unlink() api_prefixes = { "/api/v1/namespaces/observability/configmaps/": "ConfigMap", "/apis/monitoring.coreos.com/v1/namespaces/observability/prometheusrules/": "PrometheusRule", "/apis/monitoring.coreos.com/v1alpha1/namespaces/observability/alertmanagerconfigs/": "AlertmanagerConfig", "/apis/monitoring.coreos.com/v1/namespaces/observability/alertmanagers/": "Alertmanager", "/apis/networking.k8s.io/v1/namespaces/observability/networkpolicies/": "NetworkPolicy", } class Handler(BaseHTTPRequestHandler): def log_message(self, *_): return def reply(self, status, payload): encoded = json.dumps(payload, separators=(",", ":")).encode() self.send_response(status) self.send_header("Content-Type", "application/json") self.send_header("Content-Length", str(len(encoded))) self.end_headers() self.wfile.write(encoded) def do_DELETE(self): length = int(self.headers.get("Content-Length", "0")) try: delete_options = json.loads(self.rfile.read(length)) except Exception: self.reply(400, {"kind": "Status", "reason": "BadRequest"}) return kind = None name = None for prefix, candidate in api_prefixes.items(): if self.path.startswith(prefix): kind = candidate name = self.path[len(prefix):] break path = state_path(kind, "observability", name) if kind and name else None item = json.loads(path.read_text(encoding="utf-8")) if path and path.exists() else None expected_uid = ((item or {}).get("metadata") or {}).get("uid") supplied_uid = ((delete_options.get("preconditions") or {}).get("uid")) exact_options = ( delete_options == { "apiVersion": "v1", "kind": "DeleteOptions", "preconditions": {"uid": supplied_uid}, "propagationPolicy": "Background", } and isinstance(supplied_uid, str) and supplied_uid == expected_uid ) with log.open("a", encoding="utf-8") as stream: stream.write( f"raw-delete {self.path} uid={supplied_uid} " f"propagation={delete_options.get('propagationPolicy')} exact={str(exact_options).lower()}\n" ) if not item: self.reply(404, {"kind": "Status", "reason": "NotFound"}) return if not exact_options: self.reply(409, {"kind": "Status", "reason": "Conflict"}) return mode = os.environ.get("PLATFORM_TEST_DELETE_MODE", "success") count_file = pathlib.Path(os.environ["PLATFORM_TEST_DELETE_COUNT"]) delete_count = int(count_file.read_text()) if count_file.exists() else 0 delete_count += 1 count_file.write_text(str(delete_count)) active_mode = mode if delete_count == 1 else "success" if active_mode == "conflict": self.reply(409, {"kind": "Status", "reason": "Conflict"}) return if active_mode == "timeout": time.sleep(5) return path.unlink() if active_mode == "response-loss": self.close_connection = True return self.reply(200, {"kind": "Status", "status": "Success"}) with socketserver.UnixStreamServer(str(socket_file), Handler) as server: server.serve_forever() if args and args[0] == "delete": raise SystemExit(96) if args and args[0] in {"wait", "rollout"}: if "--timeout=60s" in args and os.environ.get("PLATFORM_TEST_PREFLIGHT_RC", "0") != "0": raise SystemExit(78) if "--timeout=10s" in args: pathlib.Path(os.environ["PLATFORM_TEST_POSTCHECK_REACHED"]).touch() delay = float(os.environ.get("PLATFORM_TEST_POSTCHECK_DELAY", "0")) if delay: time.sleep(delay) if os.environ.get("PLATFORM_TEST_POSTCHECK_RC", "0") != "0": raise SystemExit(79) raise SystemExit(0) raise SystemExit(46) PY chmod 0755 "$fixture/bin/kubectl" } write_inventory() { local root=$1 phase=$2 captured_at=$3 target_count=$4 sha [[ "$target_count" =~ ^[1-9][0-9]*$ ]] || fail "fixture target count is not a canonical positive decimal: $phase" mkdir -m 0700 -p -- "$root/$phase" jq -c -n \ --arg phase "$phase" \ --arg captured_at "$captured_at" \ --argjson target_count "$target_count" ' { schema: "platform-observability-metric-inventory/v1", phase: $phase, context: "default", api_server: "https://127.0.0.1:6443", captured_at_utc: $captured_at, targets: [range(0; $target_count) | { job: "fixture", health: "up", last_error: "", metrics: [{name: "up", label_names: ["job"]}] }] } ' >"$root/$phase/inventory.json" chmod 0600 "$root/$phase/inventory.json" jq -e --arg phase "$phase" --arg captured_at "$captured_at" --argjson target_count "$target_count" ' .schema == "platform-observability-metric-inventory/v1" and .phase == $phase and .context == "default" and .api_server == "https://127.0.0.1:6443" and .captured_at_utc == $captured_at and (.targets | type == "array" and length == $target_count) and all(.targets[]; .health == "up" and .last_error == "" and (.metrics | type == "array" and length > 0) and all(.metrics[]; (.name | type == "string" and length > 0) and (.label_names | type == "array") and all(.label_names[]; type == "string"))) ' "$root/$phase/inventory.json" >/dev/null || fail "fixture inventory generation was invalid: $phase" sha="$(sha256sum "$root/$phase/inventory.json" | awk '{print $1}')" printf '%s inventory.json\n' "$sha" >"$root/$phase/inventory.sha256" chmod 0600 "$root/$phase/inventory.sha256" printf '%s' "$sha" } refresh_inventory_checksum() { local root=$1 phase=$2 sha sha="$(sha256sum -- "$root/$phase/inventory.json" | awk '{print $1}')" printf '%s inventory.json\n' "$sha" >"$root/$phase/inventory.sha256" chmod 0600 "$root/$phase/inventory.sha256" printf '%s' "$sha" } rewrite_inventory_filter() { local root=$1 phase=$2 filter=$3 next next="$root/$phase/inventory.json.next" jq -c "$filter" "$root/$phase/inventory.json" >"$next" || fail "fixture inventory rewrite failed: $phase" chmod 0600 "$next" mv -f -- "$next" "$root/$phase/inventory.json" refresh_inventory_checksum "$root" "$phase" } rewrite_inventory_count() { local root=$1 phase=$2 target_count=$3 next next="$root/$phase/inventory.json.next" [[ "$target_count" =~ ^(0|[1-9][0-9]*)$ ]] || fail "fixture rewrite count is malformed: $phase" jq -c --argjson target_count "$target_count" ' .targets[0] as $target | .targets = [range(0; $target_count) | $target] ' "$root/$phase/inventory.json" >"$next" || fail "fixture count rewrite failed: $phase" chmod 0600 "$next" mv -f -- "$next" "$root/$phase/inventory.json" refresh_inventory_checksum "$root" "$phase" } write_handoff() { local root=$1 runbook=${2-https://git.learn.hyeonworks.com/platform/runbooks/observability.md} cat >"$root/dashboards.yaml" <<'YAML' apiVersion: v1 kind: ConfigMap metadata: {name: grafana-dashboard-https-endpoints, namespace: observability, labels: {grafana_dashboard: "1"}} data: {https-endpoints.json: '{"uid":"platform-https-endpoints","title":"Platform / HTTPS Endpoints"}'} --- apiVersion: v1 kind: ConfigMap metadata: {name: grafana-dashboard-kubernetes-node, namespace: observability, labels: {grafana_dashboard: "1"}} data: {kubernetes-node.json: '{"uid":"platform-kubernetes-node","title":"Platform / Kubernetes Node"}'} --- apiVersion: v1 kind: ConfigMap metadata: {name: grafana-dashboard-observability-backends, namespace: observability, labels: {grafana_dashboard: "1"}} data: {observability-backends.json: '{"uid":"platform-observability-backends","title":"Platform / Observability Backends"}'} --- apiVersion: v1 kind: ConfigMap metadata: {name: grafana-dashboard-platform-services, namespace: observability, labels: {grafana_dashboard: "1"}} data: {platform-services.json: '{"uid":"platform-services","title":"Platform / Services"}'} --- apiVersion: v1 kind: ConfigMap metadata: {name: grafana-dashboard-workload-health, namespace: observability, labels: {grafana_dashboard: "1"}} data: {workload-health.json: '{"uid":"platform-workload-health","title":"Platform / Workload Health"}'} YAML : >"$root/rules.yaml" local name alert while IFS='|' read -r name alert; do cat >>"$root/rules.yaml" <"$root/alertmanager.yaml" <<'YAML' apiVersion: monitoring.coreos.com/v1 kind: Alertmanager metadata: {name: observability-core-kube-pr-alertmanager, namespace: observability} spec: {alertmanagerConfiguration: {name: platform-alertmanager}} --- apiVersion: monitoring.coreos.com/v1alpha1 kind: AlertmanagerConfig metadata: name: platform-alertmanager namespace: observability labels: observability.hyeonworks.com/instance: home spec: route: receiver: platform-slack groupBy: - cluster - namespace - alertname - severity groupWait: 30s groupInterval: 5m repeatInterval: 4h routes: - receiver: platform-null matchers: - name: alertname matchType: "=" value: InfoInhibitor inhibitRules: - sourceMatch: - name: alertname matchType: "=" value: InfoInhibitor targetMatch: - name: severity matchType: "=" value: info equal: - namespace receivers: - name: platform-null - name: platform-slack slackConfigs: - apiURL: name: alertmanager-slack-webhook key: url sendResolved: true linkNames: false mrkdwnIn: - text - fields fallback: >- {{ if eq .Status "firing" }}FIRING{{ else }}RESOLVED{{ end }}: {{ if .CommonLabels.severity }}{{ .CommonLabels.severity | toUpper }}{{ else }}UNKNOWN{{ end }} · {{ .CommonLabels.alertname }} title: >- {{ if eq .Status "firing" }}[FIRING:{{ .Alerts.Firing | len }}]{{ else }}[RESOLVED]{{ end }} {{ if .CommonLabels.severity }}{{ .CommonLabels.severity | toUpper }}{{ else }}UNKNOWN{{ end }} · {{ .CommonLabels.alertname }} titleLink: https://grafana.learn.hyeonworks.com/ color: >- {{ if eq .Status "resolved" }}good{{ else if or (eq .CommonLabels.severity "emergency") (eq .CommonLabels.severity "critical") }}danger{{ else if eq .CommonLabels.severity "warning" }}warning{{ else }}#439FE0{{ end }} fields: - title: Status value: '{{ .Status | toUpper }}' short: true - title: Severity value: '{{ if .CommonLabels.severity }}{{ .CommonLabels.severity | toUpper }}{{ else }}UNKNOWN{{ end }}' short: true - title: Location value: '{{ if .CommonLabels.cluster }}{{ .CommonLabels.cluster }}{{ else }}unknown-cluster{{ end }} / {{ if .CommonLabels.namespace }}{{ .CommonLabels.namespace }}{{ else }}cluster-scoped{{ end }}' short: true - title: Alert count value: '{{ len .Alerts }}' short: true text: |- {{ range .Alerts }} *Alert status:* {{ .Status | toUpper }} *Target:* {{ $target := .Labels.Remove $.GroupLabels.Names }}{{ if $target }}{{ range $target.SortedPairs }}{{ .Name }}={{ .Value }} {{ end }}{{ else }}unknown{{ end }} *Summary:* {{ with .Annotations.summary }}{{ . }}{{ else }}No summary provided{{ end }} *Details:* {{ with .Annotations.description }}{{ . }}{{ else }}No description provided{{ end }} *Started:* {{ .StartsAt.Format "2006-01-02T15:04:05Z07:00" }} {{ if eq .Status "resolved" }}*Ended:* {{ .EndsAt.Format "2006-01-02T15:04:05Z07:00" }}{{ end }} {{ with .Annotations.runbook_url }}*Runbook:* <{{ . }}|대응 절차 열기>{{ end }} {{ end }} · footer: hyeonworks observability · Alertmanager --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: {name: observability-allow-alertmanager-public-https, namespace: observability} spec: podSelector: matchLabels: app.kubernetes.io/instance: observability-core-kube-pr-alertmanager app.kubernetes.io/name: alertmanager policyTypes: [Egress] egress: - to: - ipBlock: cidr: 0.0.0.0/0 except: [10.0.0.0/8, 100.64.0.0/10, 172.16.0.0/12, 192.168.0.0/16] ports: - {protocol: TCP, port: 443} YAML chmod 0600 "$root/dashboards.yaml" "$root/rules.yaml" "$root/alertmanager.yaml" } new_fixture() { local name=$1 runbook=${2-https://git.learn.hyeonworks.com/platform/runbooks/observability.md} local captured_at=${3-} initial_count=${4-$INITIAL_TARGET_COUNT} post_count=${5-$POST_TARGET_COUNT} local fixture metric initial_sha post_sha [[ -n "$captured_at" ]] || captured_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)" fixture="$WORK/$name" mkdir -m 0700 -- "$fixture" mkdir -m 0700 -- "$fixture/rollbacks" metric="$fixture/metrics" mkdir -m 0700 -- "$metric" mkdir -m 0700 -- "$fixture/rollbacks/observability-$ROLLBACK_ID" make_fakes "$fixture" initial_sha="$(write_inventory "$metric" target-initial "$captured_at" "$initial_count")" post_sha="$(write_inventory "$metric" post-substrate "$captured_at" "$post_count")" write_handoff "$metric" "$runbook" cat >"$fixture/state/Alertmanager__observability__observability-core-kube-pr-alertmanager.json" <<'JSON' {"apiVersion":"monitoring.coreos.com/v1","kind":"Alertmanager","metadata":{"name":"observability-core-kube-pr-alertmanager","namespace":"observability","uid":"uid-alertmanager-prior","resourceVersion":"88","generation":1,"creationTimestamp":"2026-08-01T00:00:00Z","managedFields":[{"manager":"operator"}],"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"remove"}},"spec":{"replicas":1},"status":{"availableReplicas":1}} JSON chmod 0700 "$fixture/rollbacks/observability-$ROLLBACK_ID" printf '%s|%s|%s|%s' "$fixture" "$metric" "$initial_sha" "$post_sha" } run_apply() { local fixture=$1 metric=$2 initial_sha=$3 post_sha=$4 shift 4 env \ PATH="$fixture/bin:$PATH" \ PLATFORM_OBSERVABILITY_ACCESS_TEST_MODE=1 \ PLATFORM_OBSERVABILITY_ACCESS_KUBECTL_BIN="$fixture/bin/kubectl" \ PLATFORM_OBSERVABILITY_ACCESS_SUDO_BIN="${PLATFORM_TEST_SUDO_BIN:-$fixture/bin/sudo}" \ PLATFORM_OBSERVABILITY_ACCESS_ENCRYPTION_SCRIPT="$fixture/bin/encryption" \ PLATFORM_OBSERVABILITY_ACCESS_RESTORE_SCRIPT="$fixture/bin/restore" \ PLATFORM_OBSERVABILITY_ACCESS_RECOVERY_SCRIPT="$fixture/bin/recovery" \ PLATFORM_OBSERVABILITY_ACCESS_ROLLBACK_BASE="$fixture/rollbacks" \ PLATFORM_TEST_EXPECTED_INITIAL_SHA="$initial_sha" \ PLATFORM_TEST_EXPECTED_POST_SHA="$post_sha" \ PLATFORM_OBSERVABILITY_ACCESS_CONFIRMATION=APPLY \ PLATFORM_OBSERVABILITY_ROLLBACK_ID="$ROLLBACK_ID" \ PLATFORM_TEST_COMMAND_LOG="$fixture/commands.log" \ PLATFORM_TEST_SUDO_REFRESHED="$fixture/sudo-refreshed" \ PLATFORM_TEST_ENCRYPTION_COUNT="$fixture/encryption-count" \ PLATFORM_TEST_RESTORE_COUNT="$fixture/restore-count" \ PLATFORM_TEST_RECOVERY_COUNT="$fixture/recovery-count" \ PLATFORM_TEST_SLACK_SCHEMA_COUNT="$fixture/slack-schema-count" \ PLATFORM_TEST_APPLY_COUNT="$fixture/apply-count" \ PLATFORM_TEST_DELETE_COUNT="$fixture/delete-count" \ PLATFORM_TEST_STATE="$fixture/state" \ PLATFORM_TEST_POSTCHECK_REACHED="$fixture/postcheck-reached" \ PLATFORM_TEST_ENCRYPTION_FAIL_AT="${PLATFORM_TEST_ENCRYPTION_FAIL_AT:-0}" \ PLATFORM_TEST_RESTORE_FAIL_AT="${PLATFORM_TEST_RESTORE_FAIL_AT:-0}" \ PLATFORM_TEST_RECOVERY_RC="${PLATFORM_TEST_RECOVERY_RC:-0}" \ PLATFORM_TEST_RECOVERY_RC_1="${PLATFORM_TEST_RECOVERY_RC_1:-}" \ PLATFORM_TEST_RECOVERY_RC_2="${PLATFORM_TEST_RECOVERY_RC_2:-}" \ PLATFORM_TEST_RECOVERY_OUTPUT_1="${PLATFORM_TEST_RECOVERY_OUTPUT_1:-}" \ PLATFORM_TEST_RECOVERY_OUTPUT_2="${PLATFORM_TEST_RECOVERY_OUTPUT_2:-}" \ PLATFORM_TEST_PREFLIGHT_RC="${PLATFORM_TEST_PREFLIGHT_RC:-0}" \ PLATFORM_TEST_POSTCHECK_RC="${PLATFORM_TEST_POSTCHECK_RC:-0}" \ PLATFORM_TEST_POSTCHECK_DELAY="${PLATFORM_TEST_POSTCHECK_DELAY:-0}" \ PLATFORM_TEST_PARENT_PID="$BASHPID" \ PLATFORM_TEST_FAIL_APPLY_AT="${PLATFORM_TEST_FAIL_APPLY_AT:-0}" \ PLATFORM_TEST_FAIL_AFTER_APPLY_AT="${PLATFORM_TEST_FAIL_AFTER_APPLY_AT:-0}" \ PLATFORM_TEST_SIGNAL_AT="${PLATFORM_TEST_SIGNAL_AT:-0}" \ PLATFORM_TEST_SLACK_EXTRA_KEY="${PLATFORM_TEST_SLACK_EXTRA_KEY:-0}" \ PLATFORM_TEST_SLACK_EXTRA_KEY_AT="${PLATFORM_TEST_SLACK_EXTRA_KEY_AT:-0}" \ PLATFORM_TEST_SUDO_FAIL_ACCEPTANCE="${PLATFORM_TEST_SUDO_FAIL_ACCEPTANCE:-0}" \ PLATFORM_TEST_DRIFT_RESOURCE="${PLATFORM_TEST_DRIFT_RESOURCE:-}" \ PLATFORM_TEST_DELETE_MODE="${PLATFORM_TEST_DELETE_MODE:-success}" \ PLATFORM_TEST_REPLACE_CONFLICT="${PLATFORM_TEST_REPLACE_CONFLICT:-0}" \ PLATFORM_TEST_PROMETHEUS_DROP_RULE="${PLATFORM_TEST_PROMETHEUS_DROP_RULE:-0}" \ PLATFORM_TEST_ALERTMANAGER_RECEIVER_MODE="${PLATFORM_TEST_ALERTMANAGER_RECEIVER_MODE-qualified}" \ PLATFORM_TEST_GRAFANA_STALE_DASHBOARD="${PLATFORM_TEST_GRAFANA_STALE_DASHBOARD:-0}" \ PLATFORM_TEST_MUTATE_HANDOFF_ON_LAST_GATE="${PLATFORM_TEST_MUTATE_HANDOFF_ON_LAST_GATE:-}" \ PLATFORM_TEST_MUTATE_INVENTORY_ON_LAST_GATE="${PLATFORM_TEST_MUTATE_INVENTORY_ON_LAST_GATE:-}" \ PLATFORM_TEST_INVENTORY_ROOT="$metric" \ bash "$APPLY" "$@" } run_inventory_validator() { local metric=$1 phase=$2 expected_sha=$3 expected_count=$4 env PLATFORM_OBSERVABILITY_ACCESS_TEST_MODE=1 bash -c ' source "$1" verified_output_dir=$2 validate_inventory_phase "$3" "$4" "$5" ' _ "$APPLY" "$metric" "$phase" "$expected_sha" "$expected_count" } assert_pre_prompt_rejection() { local fixture=$1 label=$2 ledger ledger="$fixture/rollbacks/observability-$ROLLBACK_ID/access-rules-alerts" [[ "$(<"$fixture/output")" != *'Type APPLY'* ]] || fail "$label reached confirmation" ! grep -Fq 'kubectl --request-timeout=10s apply --server-side --dry-run=server -f' "$fixture/commands.log" || fail "$label reached server dry-run" ! grep -Eq '^sudo .* install ' "$fixture/commands.log" || fail "$label installed rollback data" [[ ! -e "$ledger/objects.tsv" ]] || fail "$label created a rollback ledger" ! grep -Fq 'kubectl --request-timeout=10s apply -f' "$fixture/commands.log" || fail "$label reached Kubernetes apply" [[ ! -e "$ledger/acceptance.env" ]] || fail "$label wrote acceptance" } assert_post_confirmation_rejection() { local fixture=$1 label=$2 ledger ledger="$fixture/rollbacks/observability-$ROLLBACK_ID/access-rules-alerts" [[ -f "$ledger/objects.tsv" ]] || fail "$label did not preserve the durable rollback ledger" [[ ! -e "$fixture/apply-count" ]] || fail "$label reached an apply invocation" ! grep -Fq 'kubectl --request-timeout=10s apply -f' "$fixture/commands.log" || fail "$label reached Kubernetes apply" [[ ! -e "$ledger/acceptance.env" ]] || fail "$label wrote acceptance" } assert_reconcile_rollback() { local fixture=$1 label=$2 ledger prior ledger="$fixture/rollbacks/observability-$ROLLBACK_ID/access-rules-alerts" prior="$fixture/state/Alertmanager__observability__observability-core-kube-pr-alertmanager.json" [[ -e "$fixture/postcheck-reached" ]] || fail "$label did not reach reconciliation" grep -Fq 'OBSERVABILITY_ACCESS_RULES_ALERTS_ROLLBACK=PASS' "$fixture/output" || fail "$label did not roll back" [[ -f "$ledger/objects.tsv" ]] || fail "$label did not preserve the durable rollback ledger" [[ ! -e "$ledger/acceptance.env" ]] || fail "$label wrote acceptance" [[ -f "$prior" ]] || fail "$label did not restore the pre-existing Alertmanager" [[ "$(find "$fixture/state" -type f | wc -l | tr -d ' ')" == 1 ]] || fail "$label left newly-created fake state" } run_deployment_gate_helper() { local fixture=$1 first_output=$2 second_output=$3 expected_value=${4:-} env \ PLATFORM_OBSERVABILITY_ACCESS_TEST_MODE=1 \ PLATFORM_OBSERVABILITY_ACCESS_RECOVERY_SCRIPT="$fixture/bin/recovery" \ PLATFORM_TEST_COMMAND_LOG="$fixture/commands.log" \ PLATFORM_TEST_RECOVERY_COUNT="$fixture/recovery-count" \ PLATFORM_TEST_RECOVERY_OUTPUT_1="$first_output" \ PLATFORM_TEST_RECOVERY_OUTPUT_2="$second_output" \ bash -c ' source "$1" trap cleanup EXIT capture_slack_deployment_gate slack_deployment_gate_first helper-first capture_slack_deployment_gate slack_deployment_gate helper-second require_matching_slack_deployment_gates map_slack_deployment_gate_acceptance [[ "$slack_deployment_gate_value" == "$2" ]] cleanup ' _ "$APPLY" "$expected_value" } split_fixture() { local value=$1 IFS='|' read -r FIXTURE METRIC INITIAL_SHA POST_SHA <<<"$value" METRIC_ROOTS+=("$METRIC") } supervise_focused_suite() { (( $# == 0 )) || fail 'focused suite accepts no caller arguments' WORK="$(mktemp -d /tmp/platform-observability-access-test.XXXXXX)" chmod 0700 "$WORK" forged_root="$(mktemp -d /tmp/platform-observability-access-test.XXXXXX)" chmod 0700 "$forged_root" forged_attestation="$forged_root/worker.attestation" printf '%s\n' "$(stat -c '%d:%i' -- "$TEST_SCRIPT")" >"$forged_attestation" chmod 0600 "$forged_attestation" if run_with_wall_bound 2 bash "$TEST_SCRIPT" --internal-worker "$forged_root" "$forged_attestation" \ >"$WORK/forged-worker.out" 2>&1; then forged_rc=0 else forged_rc=$? fi case "$forged_root" in /tmp/platform-observability-access-test.??????) rm -rf -- "$forged_root" ;; esac (( forged_rc != 124 )) && ! grep -q '^PASS:' "$WORK/forged-worker.out" || fail 'direct forged internal worker bypassed the suite supervisor' printf 'SUPERVISOR_FORGED_WORKER_REJECTED=PASS\n' suite_started=$SECONDS if run_with_wall_bound "$SUITE_WALL_BOUND_SECONDS" \ /usr/bin/bash -c 'source "$1"; run_focused_suite_worker "$2"' \ _ "$TEST_SCRIPT" "$WORK"; then suite_rc=0 else suite_rc=$? fi suite_elapsed=$((SECONDS - suite_started)) mapfile -t suite_orphan_pids < <(pgrep -f -- "$WORK" || true) suite_orphan_count=${#suite_orphan_pids[@]} if (( suite_orphan_count > 0 )); then kill -TERM "${suite_orphan_pids[@]}" 2>/dev/null || true sleep 0.2 kill -KILL "${suite_orphan_pids[@]}" 2>/dev/null || true fi (( suite_rc != 124 )) || fail "focused suite exceeded its ${SUITE_WALL_BOUND_SECONDS}s hard wall-clock bound" (( suite_orphan_count == 0 )) || fail 'focused suite left a fixture-owned orphan process' (( suite_elapsed <= SUITE_WALL_BOUND_SECONDS + 2 )) || fail 'focused suite wall-clock accounting exceeded its hard bound' printf 'SUITE_WALL_SECONDS=%s\n' "$suite_elapsed" printf 'SUITE_WALL_BOUND_SECONDS=%s\n' "$SUITE_WALL_BOUND_SECONDS" printf 'SUITE_ORPHAN_PROCESSES=0\n' return "$suite_rc" } run_focused_suite_worker() { (( $# == 1 )) || fail 'invalid focused suite worker arity' WORK=$1 [[ "$WORK" =~ ^/tmp/platform-observability-access-test\.[A-Za-z0-9]{6}$ && -d "$WORK" && ! -L "$WORK" && "$(readlink -f -- "$WORK")" == "$WORK" && "$(stat -c '%u:%a' -- "$WORK")" == "$(id -u):700" ]] || fail 'focused suite supervisor work root is not exact, canonical, and private' PROGRESS_LOG="$WORK/suite-progress.log" : >"$PROGRESS_LOG" chmod 0600 "$PROGRESS_LOG" deadline_probe="platform-observability-deadline-probe-$BASHPID" if run_with_wall_bound 1 /usr/bin/bash -c 'exec -a "$1" /usr/bin/sleep 5' _ "$deadline_probe"; then deadline_probe_rc=0 else deadline_probe_rc=$? fi [[ "$deadline_probe_rc" == 124 ]] || fail 'suite wall-clock helper did not enforce its exact deadline' ! pgrep -f -- "$deadline_probe" >/dev/null || fail 'suite wall-clock helper left an orphan process' pass 'suite wall-clock helper terminates its process group without an orphan' # Break caught: production dry-run used to return before validating the # environment boundary, so a caller-controlled binary override silently # survived until a later execute invocation. if env PLATFORM_OBSERVABILITY_ACCESS_KUBECTL_BIN=/usr/bin/true \ bash "$APPLY" >"$WORK/production-override.out" 2>&1; then fail 'production dry-run accepted a test boundary override' fi pass 'production rejects every access boundary override before dry-run' # Break caught: TEST_MODE used to be an env-only switch. In particular the # real sudo binary was accepted because dry-run skipped fixture validation. split_fixture "$(new_fixture unsafe-real-sudo)" if PLATFORM_TEST_SUDO_BIN=/usr/bin/sudo \ run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ >"$FIXTURE/output" 2>&1; then fail 'test mode accepted the real sudo binary' fi grep -Fq 'test command boundary is unsafe' "$FIXTURE/output" || fail 'real sudo rejection did not identify the unsafe boundary' pass 'test mode rejects real sudo before dry-run' split_fixture "$(new_fixture dry-run)" output="$(run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA")" || fail 'dry-run failed' [[ "$output" == *'OBSERVABILITY_ACCESS_DRY_RUN=PASS'* ]] || fail 'dry-run PASS marker missing' [[ "$output" == *"TARGET_INITIAL_SHA256=$INITIAL_PRODUCTION_SHA"* ]] || fail 'dry-run did not show pinned initial hash' [[ "$output" == *"POST_SUBSTRATE_SHA256=$POST_PRODUCTION_SHA"* ]] || fail 'dry-run did not show pinned post hash' [[ ! -s "$FIXTURE/commands.log" ]] || fail 'dry-run invoked a system boundary' pass 'source-only dry-run prints pinned readiness without system access' split_fixture "$(new_fixture alertmanager-missing-title)" python3 - "$METRIC/alertmanager.yaml" <<'PY' import sys import yaml path = sys.argv[1] with open(path, encoding="utf-8") as stream: items = [item for item in yaml.safe_load_all(stream) if item is not None] config = next(item for item in items if item.get("kind") == "AlertmanagerConfig") receiver = next(item for item in config["spec"]["receivers"] if item["name"] == "platform-slack") receiver["slackConfigs"][0].pop("title") with open(path, "w", encoding="utf-8") as stream: yaml.safe_dump_all(items, stream, explicit_start=True, sort_keys=False) PY chmod 0600 "$METRIC/alertmanager.yaml" if run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail 'Alertmanager handoff without Slack title was accepted' fi assert_pre_prompt_rejection "$FIXTURE" 'Alertmanager handoff without Slack title' pass 'Alertmanager handoff without Slack title fails before prompt, ledger, server dry-run, and apply' # Break caught: the production receiver predicate treated the operator's # qualified receiver pair as absent, causing a valid rules-alerts transaction # to roll back after all resources had been applied. split_fixture "$(new_fixture qualified-receiver-pair)" if ! run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then assert_reconcile_rollback "$FIXTURE" 'qualified receiver pair' fail 'qualified receiver pair was rejected' fi grep -Fq 'OBSERVABILITY_ACCESS_RULES_ALERTS=PASS' "$FIXTURE/output" || fail 'qualified receiver pair omitted transaction success' pass 'qualified Alertmanager receiver pair is accepted exactly once' split_fixture "$(new_fixture qualified-receiver-pair-reversed)" if ! PLATFORM_TEST_ALERTMANAGER_RECEIVER_MODE=qualified-reversed \ run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then assert_reconcile_rollback "$FIXTURE" 'reversed qualified receiver pair' fail 'reversed qualified receiver pair was rejected' fi grep -Fq 'OBSERVABILITY_ACCESS_RULES_ALERTS=PASS' "$FIXTURE/output" || fail 'reversed qualified receiver pair omitted transaction success' pass 'reversed qualified Alertmanager receiver pair is accepted exactly once' # Break caught: exact source-pinned historical evidence older than the former # 24-hour ceiling was rejected even though age is not an authority signal. old_capture="$(date -u -d '49 hours ago' +%Y-%m-%dT%H:%M:%SZ)" split_fixture "$(new_fixture old-authoritative-pair \ https://git.learn.hyeonworks.com/platform/runbooks/observability.md "$old_capture")" if ! run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then [[ "$(<"$FIXTURE/output")" != *'Type APPLY'* ]] || fail 'rejected old authoritative pair unexpectedly reached confirmation' ! grep -Eq '^sudo .* install ' "$FIXTURE/commands.log" || fail 'rejected old authoritative pair unexpectedly invoked ledger install' ! grep -Fq 'kubectl --request-timeout=10s apply -f' "$FIXTURE/commands.log" || fail 'rejected old authoritative pair unexpectedly invoked Kubernetes apply' [[ ! -e "$FIXTURE/apply-count" ]] || fail 'rejected old authoritative pair unexpectedly mutated Kubernetes' [[ ! -e "$FIXTURE/rollbacks/observability-$ROLLBACK_ID/access-rules-alerts/objects.tsv" ]] || fail 'rejected old authoritative pair unexpectedly installed a rollback ledger' [[ ! -e "$FIXTURE/rollbacks/observability-$ROLLBACK_ID/access-rules-alerts/acceptance.env" ]] || fail 'rejected old authoritative pair unexpectedly wrote acceptance' fail 'old exact 21/30 authoritative pair was rejected' fi grep -Fq 'OBSERVABILITY_ACCESS_RULES_ALERTS=PASS' "$FIXTURE/output" || fail 'old exact 21/30 authoritative pair omitted transaction success' grep -Fq 'schema=platform-observability-rules-alerts-v2' \ "$FIXTURE/rollbacks/observability-$ROLLBACK_ID/access-rules-alerts/acceptance.env" || fail 'old exact 21/30 authoritative pair omitted v2 acceptance' pass 'old exact 21/30 source-pinned inventories remain authoritative' split_fixture "$(new_fixture valid-inventory-pair)" if ! env PLATFORM_OBSERVABILITY_ACCESS_TEST_MODE=1 \ PLATFORM_OBSERVABILITY_ACCESS_ROLLBACK_BASE="$FIXTURE/rollbacks" \ bash -c ' source "$1" verified_output_dir=$2 expected_initial_sha=$3 expected_post_sha=$4 validate_handoff_root verify_handoff_unchanged ' _ "$APPLY" "$METRIC" "$INITIAL_SHA" "$POST_SHA" >"$FIXTURE/output" 2>&1; then sed -n '1,160p' "$FIXTURE/output" >&2 fail 'valid exact 21/30 pair failed an initial or unchanged source-only gate' fi [[ ! -s "$FIXTURE/commands.log" ]] || fail 'source-only inventory pair control reached a system boundary' pass 'valid exact 21/30 pair passes both initial and unchanged source-only gates' for timestamp_case in malformed-utc invalid-calendar future-skew; do split_fixture "$(new_fixture "timestamp-$timestamp_case")" case "$timestamp_case" in malformed-utc) timestamp_value='not-a-utc-second' ;; invalid-calendar) timestamp_value='2026-02-30T12:00:00Z' ;; future-skew) timestamp_value="$(date -u -d '600 seconds' +%Y-%m-%dT%H:%M:%SZ)" ;; esac INITIAL_SHA="$(rewrite_inventory_filter "$METRIC" target-initial \ ".captured_at_utc = \"$timestamp_value\"")" if run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail "invalid inventory timestamp was accepted: $timestamp_case" fi assert_pre_prompt_rejection "$FIXTURE" "inventory timestamp $timestamp_case" pass "inventory timestamp $timestamp_case fails closed before confirmation" done for count_case in initial-20 initial-22 post-29 post-31; do split_fixture "$(new_fixture "count-$count_case")" case "$count_case" in initial-20) phase=target-initial; actual_count=20 ;; initial-22) phase=target-initial; actual_count=22 ;; post-29) phase=post-substrate; actual_count=29 ;; post-31) phase=post-substrate; actual_count=31 ;; esac changed_sha="$(rewrite_inventory_count "$METRIC" "$phase" "$actual_count")" if [[ "$phase" == target-initial ]]; then INITIAL_SHA=$changed_sha else POST_SHA=$changed_sha fi run_inventory_validator "$METRIC" "$phase" "$changed_sha" "$actual_count" \ >"$FIXTURE/source-control.out" 2>&1 || fail "source-only actual-count control failed: $count_case" if run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail "production expected target count accepted drift: $count_case" fi assert_pre_prompt_rejection "$FIXTURE" "inventory count $count_case" pass "inventory count $count_case is self-consistent but not production-authoritative" done split_fixture "$(new_fixture invalid-expected-count)" for invalid_expected_count in 0 01 x; do if run_inventory_validator "$METRIC" target-initial "$INITIAL_SHA" "$invalid_expected_count" \ >"$FIXTURE/expected-count-$invalid_expected_count.out" 2>&1; then fail "invalid expected count reached inventory validation: $invalid_expected_count" fi grep -Fq 'inventory expected target count is invalid' \ "$FIXTURE/expected-count-$invalid_expected_count.out" || fail "invalid expected count lacked its entry-gate error: $invalid_expected_count" done [[ ! -s "$FIXTURE/commands.log" ]] || fail 'invalid expected count reached a system boundary' pass 'expected count rejects 0, 01, and x at the source-only function entry' for semantic_case in schema phase context api health last-error empty-metrics metric-name label-type; do split_fixture "$(new_fixture "semantic-$semantic_case")" case "$semantic_case" in schema) filter='.schema = "platform-observability-metric-inventory/v2"' ;; phase) filter='.phase = "post-substrate"' ;; context) filter='.context = "other"' ;; api) filter='.api_server = "https://127.0.0.1:7443"' ;; health) filter='.targets[0].health = "down"' ;; last-error) filter='.targets[0].last_error = "failed"' ;; empty-metrics) filter='.targets[0].metrics = []' ;; metric-name) filter='.targets[0].metrics[0].name = 7' ;; label-type) filter='.targets[0].metrics[0].label_names[0] = 7' ;; esac INITIAL_SHA="$(rewrite_inventory_filter "$METRIC" target-initial "$filter")" if run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail "self-consistent inventory semantic drift was accepted: $semantic_case" fi assert_pre_prompt_rejection "$FIXTURE" "inventory semantic drift $semantic_case" done pass 'schema, phase, context, API, health, error, metrics, name, and label-type drift fail closed' for authority_case in wrong-production-pin one-good-phase swapped-phases; do split_fixture "$(new_fixture "authority-$authority_case")" case "$authority_case" in wrong-production-pin) expected_initial=$INITIAL_PRODUCTION_SHA; expected_post=$POST_PRODUCTION_SHA ;; one-good-phase) expected_initial=$INITIAL_SHA; expected_post=$POST_PRODUCTION_SHA ;; swapped-phases) expected_initial=$POST_SHA; expected_post=$INITIAL_SHA ;; esac if run_apply "$FIXTURE" "$METRIC" "$expected_initial" "$expected_post" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail "invalid source pin pair was accepted: $authority_case" fi assert_pre_prompt_rejection "$FIXTURE" "source pin $authority_case" done split_fixture "$(new_fixture mixed-generation-a)" mixed_fixture=$FIXTURE mixed_metric=$METRIC mixed_initial=$INITIAL_SHA mixed_post=$POST_SHA older_generation="$(date -u -d '2 hours ago' +%Y-%m-%dT%H:%M:%SZ)" split_fixture "$(new_fixture mixed-generation-b \ https://git.learn.hyeonworks.com/platform/runbooks/observability.md "$older_generation")" other_post=$POST_SHA FIXTURE=$mixed_fixture METRIC=$mixed_metric INITIAL_SHA=$mixed_initial POST_SHA=$mixed_post if run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$other_post" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail 'mixed-generation source pin pair was accepted' fi assert_pre_prompt_rejection "$FIXTURE" 'mixed-generation source pin pair' pass 'wrong, partial, swapped, and mixed-generation source pins fail closed' for integrity_case in stale-checksum wrong-checksum-grammar extra-phase-entry missing-phase-entry json-symlink checksum-symlink json-hardlink checksum-hardlink wrong-file-mode; do split_fixture "$(new_fixture "integrity-$integrity_case")" case "$integrity_case" in stale-checksum) printf ' \n' >>"$METRIC/target-initial/inventory.json" ;; wrong-checksum-grammar) printf 'not-a-sha inventory.json\n' >"$METRIC/target-initial/inventory.sha256" ;; extra-phase-entry) printf 'extra\n' >"$METRIC/target-initial/extra"; chmod 0600 "$METRIC/target-initial/extra" ;; missing-phase-entry) rm -- "$METRIC/target-initial/inventory.sha256" ;; json-symlink) mv "$METRIC/target-initial/inventory.json" "$FIXTURE/inventory-json-control"; ln -s "$FIXTURE/inventory-json-control" "$METRIC/target-initial/inventory.json" ;; checksum-symlink) mv "$METRIC/target-initial/inventory.sha256" "$FIXTURE/inventory-checksum-control"; ln -s "$FIXTURE/inventory-checksum-control" "$METRIC/target-initial/inventory.sha256" ;; json-hardlink) ln "$METRIC/target-initial/inventory.json" "$FIXTURE/inventory-json-control" ;; checksum-hardlink) ln "$METRIC/target-initial/inventory.sha256" "$FIXTURE/inventory-checksum-control" ;; wrong-file-mode) chmod 0644 "$METRIC/target-initial/inventory.json" ;; esac if run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail "inventory integrity drift was accepted: $integrity_case" fi assert_pre_prompt_rejection "$FIXTURE" "inventory integrity $integrity_case" done pass 'checksum, entry-set, symlink, hardlink, and mode drift fail closed' split_fixture "$(new_fixture wrong-owner)" write_executable "$FIXTURE/bin/id" \ '#!/usr/bin/env bash' \ 'if [[ "${1:-}" == -u ]]; then printf '\''999999\n'\''; else exec /usr/bin/id "$@"; fi' if PATH="$FIXTURE/bin:$PATH" run_inventory_validator \ "$METRIC" target-initial "$INITIAL_SHA" "$INITIAL_TARGET_COUNT" >"$FIXTURE/output" 2>&1; then fail 'inventory owner drift was accepted' fi grep -Fq 'inventory directory metadata changed' "$FIXTURE/output" || fail 'owner drift did not reach the ownership metadata gate' [[ ! -s "$FIXTURE/commands.log" ]] || fail 'owner drift reached a system boundary' pass 'inventory owner drift fails at the source-only metadata gate' argv_case=0 for args in \ '--execute' \ '--execute --rules-alerts' \ '--execute --verified-output-dir /tmp/example' \ '--execute --rules-alerts --substrate --verified-output-dir /tmp/example' \ '--execute --rules-alerts --verified-output-dir /tmp/example --verified-output-dir /tmp/example'; do argv_case=$((argv_case + 1)) split_fixture "$(new_fixture "argv-$argv_case")" read -r -a argv <<<"$args" if run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" "${argv[@]}" >"$FIXTURE/output" 2>&1; then fail "invalid argv was accepted: $args" fi [[ ! -s "$FIXTURE/commands.log" ]] || fail "invalid argv reached a system boundary: $args" done pass 'execute accepts only one exact rules-alerts mode and verified handoff argument' split_fixture "$(new_fixture unsafe-inventory-mode)" chmod 0755 "$METRIC/target-initial" if run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail 'unsafe inventory mode was accepted' fi [[ "$(<"$FIXTURE/output")" != *'Type APPLY'* ]] || fail 'unsafe inventory mode reached prompt' ! grep -q '^kubectl --request-timeout=10s apply -f ' "$FIXTURE/commands.log" || fail 'unsafe inventory mode reached mutation' pass 'inventory ownership, mode, link count, and exact hash gate precedes prompt' split_fixture "$(new_fixture extra-handoff-entry)" cp "$METRIC/dashboards.yaml" "$METRIC/grafana.yaml" chmod 0600 "$METRIC/grafana.yaml" if run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail 'extra renderer handoff entry was accepted' fi [[ "$(<"$FIXTURE/output")" != *'Type APPLY'* ]] || fail 'extra renderer handoff entry reached prompt' ! grep -q '^kubectl --request-timeout=10s apply -f ' "$FIXTURE/commands.log" || fail 'extra renderer handoff entry reached mutation' pass 'renderer handoff rejects Grafana and every entry outside three exact rules-alerts files' split_fixture "$(new_fixture missing-runbook '')" if run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail 'missing HTTPS runbook URL was accepted' fi grep -Fq 'OBSERVABILITY_ACCESS_RULES_ALERTS_READINESS=BLOCKED_RUNBOOK_URL' "$FIXTURE/output" || { sed -n '1,160p' "$FIXTURE/output" >&2; fail 'missing runbook blocker marker absent'; } ! grep -q '^kubectl --request-timeout=10s apply ' "$FIXTURE/commands.log" || fail 'missing runbook reached apply' ! grep -q '^sudo .*install ' "$FIXTURE/commands.log" || fail 'missing runbook wrote ledger' pass 'missing runbook URL blocks before prompt and mutation' split_fixture "$(new_fixture encryption-pre)" if PLATFORM_TEST_ENCRYPTION_FAIL_AT=1 run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail 'failed initial encryption gate was accepted' fi [[ "$(<"$FIXTURE/commands.log")" == $'sudo -v\nsudo -n true\nencryption --expect-reencrypted' ]] || fail 'initial encryption failure did not stop at exact first gate' pass 'initial encryption failure is zero mutation' split_fixture "$(new_fixture slack-schema)" if PLATFORM_TEST_SLACK_EXTRA_KEY=1 run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail 'Slack Secret with an extra key was accepted' fi ! grep -q '^kubectl --request-timeout=10s apply ' "$FIXTURE/commands.log" || fail 'Slack schema mismatch reached apply' [[ "$(<"$FIXTURE/output")" != *'Type APPLY'* ]] || fail 'Slack schema mismatch reached prompt' pass 'Slack Secret checks only the exact non-value schema before prompt' split_fixture "$(new_fixture recovery)" if PLATFORM_TEST_RECOVERY_RC=1 run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail 'missing Slack recovery marker was accepted' fi grep -Fqx 'recovery --check-slack-deployment-evidence' "$FIXTURE/commands.log" || fail 'Slack deployment checker argv is not exact' ! grep -q '^kubectl --request-timeout=10s apply ' "$FIXTURE/commands.log" || fail 'missing recovery marker reached apply' pass 'Slack deployment evidence is an exact pre-prompt gate' split_fixture "$(new_fixture second-gate-failure)" if PLATFORM_TEST_RECOVERY_RC_2=1 run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail 'second Slack deployment gate failure was accepted' fi [[ "$(<"$FIXTURE/recovery-count")" == 2 ]] || fail 'second gate failure did not invoke both exact deployment gates' [[ ! -e "$FIXTURE/apply-count" ]] || fail 'second gate failure reached cluster mutation' [[ -f "$FIXTURE/rollbacks/observability-$ROLLBACK_ID/access-rules-alerts/objects.tsv" ]] || fail 'second gate failure did not preserve the durable rollback ledger' [[ ! -e "$FIXTURE/rollbacks/observability-$ROLLBACK_ID/access-rules-alerts/acceptance.env" ]] || fail 'second gate failure wrote acceptance' pass 'second deployment gate failure preserves ledger and remains zero mutation' for gate_case in recovery-to-risk risk-to-recovery duplicate-output extra-output partial-output; do split_fixture "$(new_fixture "deployment-gate-$gate_case")" first='SLACK_DEPLOYMENT_GATE=RECOVERY\n' second='SLACK_DEPLOYMENT_GATE=RECOVERY\n' expected=RECOVERY case "$gate_case" in recovery-to-risk) second='SLACK_DEPLOYMENT_GATE=RISK_ACCEPTED\n' ;; risk-to-recovery) first='SLACK_DEPLOYMENT_GATE=RISK_ACCEPTED\n'; expected=RISK_ACCEPTED ;; duplicate-output) first='SLACK_DEPLOYMENT_GATE=RECOVERY\nSLACK_DEPLOYMENT_GATE=RECOVERY\n' ;; extra-output) first='SLACK_DEPLOYMENT_GATE=RECOVERY\nextra\n' ;; partial-output) first='SLACK_DEPLOYMENT_GATE=RECOVERY' ;; esac if run_deployment_gate_helper "$FIXTURE" "$first" "$second" "$expected" \ >"$FIXTURE/output" 2>&1; then fail "invalid Slack deployment gate was accepted: $gate_case" fi [[ ! -e "$FIXTURE/apply-count" && ! -e "$FIXTURE/rollbacks/observability-$ROLLBACK_ID/access-rules-alerts/acceptance.env" ]] || fail "invalid Slack deployment gate escaped the helper boundary: $gate_case" done pass 'verdict swaps and malformed deployment gate output fail closed before mutation' split_fixture "$(new_fixture last-secret-schema)" if PLATFORM_TEST_SLACK_EXTRA_KEY_AT=2 run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail 'last Slack Secret schema drift was accepted' fi [[ ! -e "$FIXTURE/apply-count" ]] || fail 'last Slack Secret schema drift reached mutation' [[ -f "$FIXTURE/rollbacks/observability-$ROLLBACK_ID/access-rules-alerts/objects.tsv" ]] || fail 'last Slack Secret schema drift did not preserve the durable ledger' pass 'last Slack Secret schema check precedes the second deployment gate and mutation' split_fixture "$(new_fixture production-preflight)" if PLATFORM_TEST_PREFLIGHT_RC=1 run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail 'failed production preflight was accepted' fi grep -Fq 'kubectl --request-timeout=10s wait --namespace observability --for=condition=Available deployment/grafana deployment/blackbox-exporter --timeout=60s' \ "$FIXTURE/commands.log" || fail 'focused failure did not execute the production preflight' [[ "$(<"$FIXTURE/output")" != *'Type APPLY'* ]] || fail 'failed production preflight reached prompt' ! grep -q '^kubectl --request-timeout=10s apply -f ' "$FIXTURE/commands.log" || fail 'failed production preflight reached mutation' pass 'production preflight is materially exercised and remains zero mutation on failure' split_fixture "$(new_fixture last-gate)" if PLATFORM_TEST_RESTORE_FAIL_AT=2 run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail 'failed last restore gate was accepted' fi [[ "$(grep -c '^encryption --expect-reencrypted$' "$FIXTURE/commands.log")" == 2 ]] || { sed -n '1,220p' "$FIXTURE/commands.log" >&2; sed -n '1,160p' "$FIXTURE/output" >&2; fail 'encryption gate did not run twice'; } [[ "$(grep -c '^restore --check$' "$FIXTURE/commands.log")" == 2 ]] || fail 'restore gate did not run twice' ! grep -q '^kubectl --request-timeout=10s apply -f ' "$FIXTURE/commands.log" || fail 'last restore failure reached apply' [[ -f "$FIXTURE/rollbacks/observability-$ROLLBACK_ID/access-rules-alerts/objects.tsv" ]] || fail 'last gate did not occur after immutable ledger capture' pass 'last encryption and restore gate failure remains zero cluster mutation' split_fixture "$(new_fixture handoff-race)" if PLATFORM_TEST_MUTATE_HANDOFF_ON_LAST_GATE="$METRIC/rules.yaml" \ run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail 'handoff mutation after confirmation was accepted' fi ! grep -q '^kubectl --request-timeout=10s apply -f ' "$FIXTURE/commands.log" || fail 'handoff race reached apply' pass 'verified renderer handoff hashes are rechecked after the last gate' for inventory_drift_case in raw-json rechecksum-count hardlink; do split_fixture "$(new_fixture "inventory-last-gate-$inventory_drift_case")" if PLATFORM_TEST_MUTATE_INVENTORY_ON_LAST_GATE="$inventory_drift_case" \ run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail "post-confirmation inventory drift was accepted: $inventory_drift_case" fi assert_post_confirmation_rejection "$FIXTURE" "post-confirmation inventory drift $inventory_drift_case" pass "post-confirmation inventory drift $inventory_drift_case stops before first apply" done split_fixture "$(new_fixture last-gate-count-wiring)" INITIAL_SHA="$(rewrite_inventory_count "$METRIC" target-initial 20)" run_inventory_validator "$METRIC" target-initial "$INITIAL_SHA" 20 \ >"$FIXTURE/source-control.out" 2>&1 || fail '20-target source-only positive control did not accept its matching expected count' if env PLATFORM_OBSERVABILITY_ACCESS_TEST_MODE=1 bash -c ' source "$1" verified_output_dir=$2 target_initial_sha=$3 post_substrate_sha=$4 verify_handoff_unchanged ' _ "$APPLY" "$METRIC" "$INITIAL_SHA" "$POST_SHA" >"$FIXTURE/output" 2>&1; then fail 'last inventory gate lost the production initial target count argument' fi grep -Fq 'inventory semantic contract changed: target-initial' "$FIXTURE/output" || fail 'last inventory count gate did not reject the self-consistent 20-target inventory' [[ ! -s "$FIXTURE/commands.log" ]] || fail 'last-gate count wiring control reached a system boundary' pass 'last inventory gate carries expected count 21 while direct expected count 20 remains a positive control' split_fixture "$(new_fixture symlinked-ledger-root)" mkdir -m 0700 "$FIXTURE/escaped-ledger" ln -s "$FIXTURE/escaped-ledger" \ "$FIXTURE/rollbacks/observability-$ROLLBACK_ID/access-rules-alerts" if run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail 'symlinked root ledger was followed' fi ! grep -q '^kubectl --request-timeout=10s apply -f ' "$FIXTURE/commands.log" || fail 'symlinked ledger root reached cluster mutation' [[ -z "$(find "$FIXTURE/escaped-ledger" -mindepth 1 -print -quit)" ]] || fail 'root ledger write escaped through symlink' pass 'root ledger lineage rejects symlink escape before cluster mutation' split_fixture "$(new_fixture success)" run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1 || { sed -n '1,260p' "$FIXTURE/output" >&2 fail 'rules-alerts transition failed' } grep -Fq 'OBSERVABILITY_ACCESS_RULES_ALERTS=PASS' "$FIXTURE/output" || fail 'success marker missing' grep -Fq 'Type APPLY default to apply only observability rules-alerts: APPLY' "$FIXTURE/output" || fail 'interactive prompt contract changed' expected_gate_trace='secret-schema-1 -> deployment-gate-1 -> preflight -> server-dry-run -> confirmation -> rollback-ledger -> encryption-last -> handoff/live-last -> secret-schema-2 -> deployment-gate-2 -> first-apply' mapfile -t gate_trace_parts < <(awk ' /get secret alertmanager-slack-webhook/ { secret++; if (secret == 1) print "secret-schema-1"; else if (secret == 2) print "secret-schema-2" } /^recovery --check-slack-deployment-evidence$/ { gate++; if (gate == 1) print "deployment-gate-1"; else if (gate == 2) print "deployment-gate-2" } /wait --namespace observability --for=condition=Available deployment\/grafana/ { print "preflight" } /apply --dry-run=server/ && !dry++ { print "server-dry-run" } /^sudo -n mv -T -- .*\/mutations.tsv.next-[0-9]+ .*\/mutations.tsv$/ && !ledger++ { print "rollback-ledger" } /^encryption --expect-reencrypted$/ && ++encryption == 2 { print "encryption-last" } /^restore --check$/ && ++restore == 2 { print "handoff/live-last" } /^kubectl --request-timeout=10s apply -f / && !apply++ { print "first-apply" } ' "$FIXTURE/commands.log") actual_gate_trace='' for gate_trace_part in "${gate_trace_parts[@]}"; do [[ -z "$actual_gate_trace" ]] || actual_gate_trace+=' -> ' actual_gate_trace+="$gate_trace_part" done actual_gate_trace="${actual_gate_trace/server-dry-run -> rollback-ledger/server-dry-run -> confirmation -> rollback-ledger}" [[ "$actual_gate_trace" == "$expected_gate_trace" ]] || fail "two Slack gates and first apply did not preserve the exact required order: $actual_gate_trace" pass 'second deployment gate preserves the required pre-prompt-to-first-apply order' # Break caught: the former test hook bypassed the production preflight and # reconcile path, so a focused PASS did not prove Prometheus or Grafana had # accepted the rendered rules and dashboards. grep -Fq 'kubectl --request-timeout=10s get probe --namespace observability --output=json' \ "$FIXTURE/commands.log" || fail 'focused success bypassed the production preflight path' grep -Fq 'kubectl --request-timeout=10s get --raw=/api/v1/namespaces/observability/services/http:observability-core-kube-pr-prometheus:9090/proxy/api/v1/rules' \ "$FIXTURE/commands.log" || fail 'focused success did not exercise Prometheus rule acceptance' grep -Fq 'kubectl --request-timeout=10s get --raw=/api/v1/namespaces/observability/services/http:observability-core-kube-pr-alertmanager:9093/proxy/api/v2/receivers' \ "$FIXTURE/commands.log" || fail 'focused success did not exercise the exact Alertmanager receiver API' grep -Fq 'kubectl --request-timeout=10s exec --namespace observability deployment/grafana --container grafana --' \ "$FIXTURE/commands.log" || fail 'focused success did not prove Grafana consumed the dashboard ConfigMaps' ! grep -Eq '^(preflight|postcheck)$' "$FIXTURE/commands.log" || fail 'focused success still used a test-only health hook' ledger="$FIXTURE/rollbacks/observability-$ROLLBACK_ID/access-rules-alerts/objects.tsv" [[ -f "$ledger" && ! -L "$ledger" && "$(stat -c %a "$ledger")" == 600 ]] || fail 'root ledger is unsafe' [[ "$(wc -l <"$ledger" | tr -d ' ')" == 13 ]] || fail 'ledger is not header plus exact twelve resources' awk -F '\t' ' NR == 1 { exit($0 != "phase\towner\tapiVersion\tkind\tnamespace\tname\texisted\trestore-mode\tpayload-file\tpayload-sha256") } NR > 1 { if (NF != 10 || $1 != "access-rules-alerts" || ($2 != "kube-prometheus-stack" && $2 != "platform-rules")) exit 1 } ' "$ledger" || fail 'ledger header, fields, phase, or owner is not exact' [[ "$(awk -F '\t' '$4=="ConfigMap"{n++} END{print n+0}' "$ledger")" == 5 ]] || fail 'dashboard ledger set is not exact' [[ "$(awk -F '\t' '$4=="PrometheusRule"{n++} END{print n+0}' "$ledger")" == 4 ]] || fail 'rule ledger set is not exact' [[ "$(awk -F '\t' '$4=="AlertmanagerConfig"{n++} END{print n+0}' "$ledger")" == 1 ]] || fail 'AlertmanagerConfig ledger set is not exact' [[ "$(awk -F '\t' '$4=="Alertmanager"{n++} END{print n+0}' "$ledger")" == 1 ]] || fail 'Alertmanager ledger set is not exact' [[ "$(awk -F '\t' '$4=="NetworkPolicy"{n++} END{print n+0}' "$ledger")" == 1 ]] || fail 'NetworkPolicy ledger set is not exact' ! grep -Eq $'\t(Secret|Probe|Ingress|Deployment|Service)\t' "$ledger" || fail 'forbidden substrate or Secret resource entered ledger' payload_rel="$(awk -F '\t' '$4=="Alertmanager"{print $9}' "$ledger")" payload="$FIXTURE/rollbacks/observability-$ROLLBACK_ID/access-rules-alerts/$payload_rel" python3 - "$payload" <<'PY' || fail 'prior Alertmanager payload is not sanitized' import json, sys item=json.load(open(sys.argv[1])) meta=item.get("metadata", {}) for key in ("uid","resourceVersion","generation","creationTimestamp","managedFields"): assert key not in meta assert "status" not in item assert "kubectl.kubernetes.io/last-applied-configuration" not in meta.get("annotations", {}) PY acceptance="$FIXTURE/rollbacks/observability-$ROLLBACK_ID/access-rules-alerts/acceptance.env" [[ -f "$acceptance" && "$(stat -c %a "$acceptance")" == 600 ]] || fail 'acceptance marker is unsafe' grep -Fqx 'schema=platform-observability-rules-alerts-v2' "$acceptance" || fail 'acceptance schema missing' grep -Fqx "rollback_id=$ROLLBACK_ID" "$acceptance" || fail 'acceptance rollback id missing' grep -Fqx "target_initial_sha256=$INITIAL_SHA" "$acceptance" || fail 'acceptance initial hash mismatch' grep -Fqx "post_substrate_sha256=$POST_SHA" "$acceptance" || fail 'acceptance post hash mismatch' grep -Fqx 'slack_deployment_gate=RECOVERY' "$acceptance" || fail 'acceptance deployment verdict missing' grep -Fqx 'slack_gate_approval_ref=strict-recovery-evidence-v1' "$acceptance" || fail 'recovery acceptance reference mismatch' grep -Fqx 'slack_gate_accepted_by_uid=not-applicable' "$acceptance" || fail 'recovery acceptance uid mismatch' grep -Fqx 'state=accepted' "$acceptance" || fail 'acceptance state missing' [[ "$(wc -l <"$acceptance" | tr -d ' ')" == 9 ]] || fail 'v2 acceptance field count is not exact' reconcile_last_line="$(awk ' /\/proxy\/api\/v1\/rules|\/proxy\/api\/v2\/receivers| exec --namespace observability deployment\/grafana / {line=NR} END {print line+0} ' "$FIXTURE/commands.log")" acceptance_install_line="$(awk '/^sudo -n install .*acceptance\.env/ {line=NR} END {print line+0}' "$FIXTURE/commands.log")" (( reconcile_last_line > 0 && acceptance_install_line > reconcile_last_line )) || fail 'acceptance marker was installed before all production acceptance evidence' [[ "$(grep -c '^kubectl --request-timeout=10s apply -f ' "$FIXTURE/commands.log")" == 12 ]] || fail 'apply was not one exact resource at a time' ! grep -Eqi '^kubectl --request-timeout=10s apply -f .*/(grafana|blackbox|targets|private-dns)\.yaml|^kubectl --request-timeout=10s delete (probe|ingress|deployment|service) ' "$FIXTURE/commands.log" || fail 'rules-alerts mode mutated a substrate, Probe, or Nginx resource' first_sudo="$(awk '/^sudo / {print; exit}' "$FIXTURE/commands.log")" [[ "$first_sudo" == 'sudo -v' ]] || fail 'sudo refresh did not precede root reads/writes' awk ' $0 == "encryption --expect-reencrypted" { encryption[++encryption_count]=NR } $0 == "restore --check" { restore[++restore_count]=NR } /^sudo -n mv -T -- .*\/mutations.tsv.next-[0-9]+ .*\/mutations.tsv$/ && !ledger { ledger=NR } /^kubectl --request-timeout=10s apply -f / && !mutation { mutation=NR } END { exit(!(encryption_count==2 && restore_count==2 && encryption[1] < restore[1] && restore[1] < ledger && ledger < encryption[2] && encryption[2] < restore[2] && restore[2] < mutation)) } ' "$FIXTURE/commands.log" || fail 'pre/last gate, ledger, and mutation order changed' pass 'current exact 21/30 success captures the sanitized ledger and applies only twelve rules-alerts resources' split_fixture "$(new_fixture risk-accepted-success)" PLATFORM_TEST_RECOVERY_OUTPUT_1='SLACK_DEPLOYMENT_GATE=RISK_ACCEPTED\n' \ PLATFORM_TEST_RECOVERY_OUTPUT_2='SLACK_DEPLOYMENT_GATE=RISK_ACCEPTED\n' \ run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1 || fail 'risk-accepted deployment gate success fixture failed' acceptance="$FIXTURE/rollbacks/observability-$ROLLBACK_ID/access-rules-alerts/acceptance.env" grep -Fqx 'slack_deployment_gate=RISK_ACCEPTED' "$acceptance" || fail 'risk acceptance verdict mismatch' grep -Fqx 'slack_gate_approval_ref=2026-08-14-observability-slack-recovery-risk-acceptance-design' "$acceptance" || fail 'risk acceptance reference mismatch' grep -Fqx 'slack_gate_accepted_by_uid=1000' "$acceptance" || fail 'risk acceptance uid mismatch' pass 'risk-accepted deployment verdict records the exact v2 acceptance mapping' split_fixture "$(new_fixture acceptance-write-failure)" if PLATFORM_TEST_SUDO_FAIL_ACCEPTANCE=1 \ run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail 'v2 acceptance write failure returned success' fi grep -Fq 'APPLIED_ACCEPTANCE_UNRECORDED' "$FIXTURE/output" || fail 'acceptance write failure did not identify missing acceptance' [[ ! -e "$FIXTURE/rollbacks/observability-$ROLLBACK_ID/access-rules-alerts/acceptance.env" ]] || fail 'acceptance write failure left an acceptance marker' pass 'v2 acceptance write failure remains unaccepted' for reconcile_case in prometheus-rule grafana-sidecar; do case_progress "reconcile-$reconcile_case" split_fixture "$(new_fixture "reconcile-$reconcile_case")" prometheus_drop=0 grafana_stale=0 case "$reconcile_case" in prometheus-rule) prometheus_drop=1 ;; grafana-sidecar) grafana_stale=1 ;; esac if PLATFORM_TEST_PROMETHEUS_DROP_RULE="$prometheus_drop" \ PLATFORM_TEST_GRAFANA_STALE_DASHBOARD="$grafana_stale" \ run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail "incomplete production acceptance was accepted: $reconcile_case" fi assert_reconcile_rollback "$FIXTURE" "incomplete production acceptance $reconcile_case" done for receiver_case in raw empty null duplicate extra wrong-namespace wrong-config wrong-local malformed; do case_progress "reconcile-alertmanager-receiver-$receiver_case" split_fixture "$(new_fixture "reconcile-alertmanager-receiver-$receiver_case")" if PLATFORM_TEST_ALERTMANAGER_RECEIVER_MODE="$receiver_case" \ run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail "invalid Alertmanager receiver was accepted: $receiver_case" fi assert_reconcile_rollback "$FIXTURE" "invalid Alertmanager receiver $receiver_case" done expected_reconcile_progress=$'CASE_BEGIN=reconcile-prometheus-rule\nCASE_BEGIN=reconcile-grafana-sidecar\nCASE_BEGIN=reconcile-alertmanager-receiver-raw\nCASE_BEGIN=reconcile-alertmanager-receiver-empty\nCASE_BEGIN=reconcile-alertmanager-receiver-null\nCASE_BEGIN=reconcile-alertmanager-receiver-duplicate\nCASE_BEGIN=reconcile-alertmanager-receiver-extra\nCASE_BEGIN=reconcile-alertmanager-receiver-wrong-namespace\nCASE_BEGIN=reconcile-alertmanager-receiver-wrong-config\nCASE_BEGIN=reconcile-alertmanager-receiver-wrong-local\nCASE_BEGIN=reconcile-alertmanager-receiver-malformed' [[ "$(<"$PROGRESS_LOG")" == "$expected_reconcile_progress" ]] || fail 'long reconciliation failure matrix did not emit exact per-case progress' pass 'Prometheus rules, exact Alertmanager receiver matrix, and Grafana sidecar evidence each fail closed before acceptance' split_fixture "$(new_fixture apply-outcome-unknown)" if PLATFORM_TEST_FAIL_APPLY_AT=5 run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail 'failed apply returned success' fi grep -Fq 'OBSERVABILITY_ACCESS_RULES_ALERTS_ROLLBACK=AMBIGUOUS' "$FIXTURE/output" || fail 'non-zero apply result was incorrectly reported as a certain no-op' grep -Fq 'MANUAL_RECOVERY_REQUIRED=YES' "$FIXTURE/output" || fail 'unknown apply outcome did not require manual recovery' [[ "$(find "$FIXTURE/state" -type f | wc -l | tr -d ' ')" == 1 ]] || fail 'recorded prefix was not rolled back after an ambiguous apply result' pass 'non-zero apply response is treated as an unknown outcome while owned prefix rolls back' split_fixture "$(new_fixture apply-response-loss)" if PLATFORM_TEST_FAIL_AFTER_APPLY_AT=5 run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail 'lost apply response returned success' fi grep -Fq 'OBSERVABILITY_ACCESS_RULES_ALERTS_ROLLBACK=AMBIGUOUS' "$FIXTURE/output" || fail 'lost apply response was reported as a certain rollback' grep -Fq 'MANUAL_RECOVERY_REQUIRED=YES' "$FIXTURE/output" || fail 'lost apply response omitted manual recovery' [[ ! -e "$FIXTURE/rollbacks/observability-$ROLLBACK_ID/access-rules-alerts/acceptance.env" ]] || fail 'lost apply response wrote acceptance' pass 'apply response loss preserves truthful ambiguity and no acceptance marker' split_fixture "$(new_fixture rollback)" if PLATFORM_TEST_POSTCHECK_RC=1 PLATFORM_TEST_POSTCHECK_DELAY=0 \ run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail 'failed reconcile returned success' fi grep -Fq 'OBSERVABILITY_ACCESS_RULES_ALERTS_ROLLBACK=PASS' "$FIXTURE/output" || fail 'rollback PASS marker missing' prior="$FIXTURE/state/Alertmanager__observability__observability-core-kube-pr-alertmanager.json" jq -e '.metadata.uid == "uid-alertmanager-prior" and .spec.replicas == 1' "$prior" >/dev/null || fail 'rollback did not restore the prior Alertmanager owner payload' [[ "$(find "$FIXTURE/state" -type f | wc -l | tr -d ' ')" == 1 ]] || fail 'rollback left newly-created objects' ! grep -Eq '^kubectl --request-timeout=10s (delete|apply).*(Secret|PersistentVolumeClaim|Probe)' "$FIXTURE/commands.log" || fail 'rollback touched a preserved or non-rules resource' delete_order="$(awk '$1=="raw-delete" {path=$2; sub(".*/","",path); print path}' "$FIXTURE/commands.log")" expected_delete_order=$'observability-allow-alertmanager-public-https\nplatform-alertmanager\nplatform-verified-services\nplatform-observability-core\nplatform-certificate-probes\nplatform-aistor-storage-quota\ngrafana-dashboard-workload-health\ngrafana-dashboard-platform-services\ngrafana-dashboard-observability-backends\ngrafana-dashboard-kubernetes-node\ngrafana-dashboard-https-endpoints' [[ "$delete_order" == "$expected_delete_order" ]] || fail 'rollback did not delete owned creations in exact reverse dependency order' [[ "$(grep -c '^raw-delete .* exact=true$' "$FIXTURE/commands.log")" == 11 ]] || fail 'rollback did not send exact UID-preconditioned DeleteOptions through the raw API' grep -Fq 'replace-preconditions Alertmanager/observability-core-kube-pr-alertmanager uid=uid-alertmanager-prior resourceVersion=' \ "$FIXTURE/commands.log" || fail 'rollback restore did not bind both UID and live resourceVersion' ! grep -Fq 'kubectl --request-timeout=10s delete ' "$FIXTURE/commands.log" || fail 'rollback used a plain kubectl delete branch' pass 'failed reconcile reverses only ledger-owned resources and restores exact prior owner' for delete_mode in response-loss conflict timeout; do split_fixture "$(new_fixture "delete-$delete_mode")" started_at="$(date +%s)" if PLATFORM_TEST_POSTCHECK_RC=1 PLATFORM_TEST_POSTCHECK_DELAY=0 PLATFORM_TEST_DELETE_MODE="$delete_mode" \ run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail "raw DELETE $delete_mode returned success" fi elapsed=$(( $(date +%s) - started_at )) (( elapsed <= 30 )) || fail "raw DELETE $delete_mode exceeded its bounded timeout" grep -Fq 'OBSERVABILITY_ACCESS_RULES_ALERTS_ROLLBACK=AMBIGUOUS' "$FIXTURE/output" || fail "raw DELETE $delete_mode was not reported truthfully" grep -Fq 'MANUAL_RECOVERY_REQUIRED=YES' "$FIXTURE/output" || fail "raw DELETE $delete_mode omitted manual recovery" grep -Eq '^raw-delete .* exact=true$' "$FIXTURE/commands.log" || fail "raw DELETE $delete_mode did not carry exact UID preconditions" [[ ! -e "$FIXTURE/rollbacks/observability-$ROLLBACK_ID/access-rules-alerts/acceptance.env" ]] || fail "raw DELETE $delete_mode wrote acceptance" done pass 'raw DELETE response loss, conflict, and timeout stay bounded and truthfully ambiguous' split_fixture "$(new_fixture replace-conflict)" if PLATFORM_TEST_POSTCHECK_RC=1 PLATFORM_TEST_POSTCHECK_DELAY=0 PLATFORM_TEST_REPLACE_CONFLICT=1 \ run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail 'UID/resourceVersion restore conflict returned success' fi grep -Fq 'replace-preconditions Alertmanager/observability-core-kube-pr-alertmanager uid=uid-alertmanager-prior resourceVersion=' \ "$FIXTURE/commands.log" || fail 'conflicted restore did not carry UID and resourceVersion' grep -Fq 'OBSERVABILITY_ACCESS_RULES_ALERTS_ROLLBACK=AMBIGUOUS' "$FIXTURE/output" || fail 'restore conflict did not remain ambiguous' grep -Fq 'MANUAL_RECOVERY_REQUIRED=YES' "$FIXTURE/output" || fail 'restore conflict omitted manual recovery' pass 'UID and resourceVersion restore conflict fails closed with manual recovery' split_fixture "$(new_fixture signal)" ( trap 'exit 143' TERM PLATFORM_TEST_POSTCHECK_RC=1 PLATFORM_TEST_POSTCHECK_DELAY=5 \ run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" ) >"$FIXTURE/output" 2>&1 & signal_pid=$! for ((signal_attempt=1; signal_attempt<=300; signal_attempt++)); do [[ -e "$FIXTURE/postcheck-reached" ]] && break kill -0 "$signal_pid" 2>/dev/null || break sleep 0.05 done [[ -e "$FIXTURE/postcheck-reached" ]] || fail 'signal fixture never reached a mutation-owned reconciliation boundary' apply_pid="$(pgrep -P "$signal_pid" -f "$APPLY" | head -n1)" [[ "$apply_pid" =~ ^[0-9]+$ ]] || fail 'signal fixture could not bind the apply process' kill -TERM "$apply_pid" if wait "$signal_pid"; then fail 'signal during mutation returned success' fi grep -Fq 'OBSERVABILITY_ACCESS_RULES_ALERTS_ROLLBACK=PASS' "$FIXTURE/output" || { sed -n '1,200p' "$FIXTURE/output" >&2; fail 'signal during reconciliation did not complete owned rollback'; } [[ ! -e "$FIXTURE/rollbacks/observability-$ROLLBACK_ID/access-rules-alerts/acceptance.env" ]] || fail 'signal during mutation wrote acceptance' pass 'signal during reconciliation invokes owned rollback and leaves no false acceptance' split_fixture "$(new_fixture uid-drift)" if PLATFORM_TEST_POSTCHECK_RC=1 PLATFORM_TEST_DRIFT_RESOURCE='ConfigMap/grafana-dashboard-workload-health' \ run_apply "$FIXTURE" "$METRIC" "$INITIAL_SHA" "$POST_SHA" \ --execute --rules-alerts --verified-output-dir "$METRIC" >"$FIXTURE/output" 2>&1; then fail 'UID-drifted rollback returned success' fi grep -Fq 'OBSERVABILITY_ACCESS_RULES_ALERTS_ROLLBACK=AMBIGUOUS' "$FIXTURE/output" || fail 'UID drift did not produce truthful ambiguity' grep -Fq 'MANUAL_RECOVERY_REQUIRED=YES' "$FIXTURE/output" || fail 'manual recovery marker missing' [[ -f "$FIXTURE/state/ConfigMap__observability__grafana-dashboard-workload-health.json" ]] || fail 'UID-drifted object was deleted without ownership' pass 'rollback refuses UID drift and reports manual recovery truthfully' printf 'Assertions: %d\n' "$ASSERTIONS" printf 'APPLY OBSERVABILITY ACCESS TEST PASS\n' } if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then supervise_focused_suite "$@" fi