#!/usr/bin/env python3 """Validate the stable JSON contract returned by GET /health.""" import argparse import json import sys from datetime import datetime from pathlib import Path def validate(value): if not isinstance(value, dict): return "health response must be a JSON object" missing = sorted({"status", "timestamp", "uptime", "checks"} - value.keys()) if missing: return f"health response missing fields: {', '.join(missing)}" if value["status"] != "healthy": return f"unexpected health status: {value['status']}" try: datetime.fromisoformat(value["timestamp"].replace("Z", "+00:00")) except (AttributeError, ValueError): return "timestamp must be RFC3339" if not isinstance(value["uptime"], str) or not value["uptime"]: return "uptime must be a non-empty string" if not isinstance(value["checks"], dict) or value["checks"].get("database") != "healthy": return "database health check must be healthy" return None def main(argv=None): parser = argparse.ArgumentParser() parser.add_argument("path", nargs="?", help="JSON file; stdin when omitted") args = parser.parse_args(argv) try: raw = Path(args.path).read_text(encoding="utf-8") if args.path else sys.stdin.read() error = validate(json.loads(raw)) except (OSError, json.JSONDecodeError) as exc: error = f"invalid health JSON: {exc}" if error: print(error, file=sys.stderr) return 1 print("health JSON contract: ok") return 0 if __name__ == "__main__": sys.exit(main())