| 45 | |
| 46 | |
| 47 | def validate_item(item: dict, file_name: str, idx: int) -> None: |
| 48 | prefix = f"{file_name}[{idx}] ({item.get('id', '???')})" |
| 49 | |
| 50 | required_fields = [ |
| 51 | "id", "framework", "category", "title", "summary", |
| 52 | "source_url", "source_name", "published_date", "importance", "status", |
| 53 | ] |
| 54 | for f in required_fields: |
| 55 | if f not in item: |
| 56 | errors.append(f"{prefix}: missing required field '{f}'") |
| 57 | |
| 58 | fw = item.get("framework", "") |
| 59 | if fw not in VALID_FRAMEWORKS: |
| 60 | errors.append(f"{prefix}: invalid framework '{fw}'") |
| 61 | |
| 62 | cat = item.get("category", "") |
| 63 | if cat not in VALID_CATEGORIES: |
| 64 | errors.append(f"{prefix}: invalid category '{cat}'") |
| 65 | |
| 66 | imp = item.get("importance", "") |
| 67 | if imp not in VALID_IMPORTANCES: |
| 68 | errors.append(f"{prefix}: invalid importance '{imp}'") |
| 69 | |
| 70 | st = item.get("status", "") |
| 71 | if st not in VALID_STATUSES: |
| 72 | errors.append(f"{prefix}: invalid status '{st}'") |
| 73 | |
| 74 | title = item.get("title", {}) |
| 75 | if not isinstance(title, dict) or not title.get("en"): |
| 76 | errors.append(f"{prefix}: title must have 'en' key with non-empty value") |
| 77 | |
| 78 | summary = item.get("summary", {}) |
| 79 | if not isinstance(summary, dict) or not summary.get("en"): |
| 80 | errors.append(f"{prefix}: summary must have 'en' key with non-empty value") |
| 81 | |
| 82 | url = item.get("source_url", "") |
| 83 | if url: |
| 84 | from urllib.parse import urlparse |
| 85 | parsed = urlparse(url) |
| 86 | if parsed.scheme not in ("http", "https"): |
| 87 | errors.append(f"{prefix}: source_url must use http/https scheme") |
| 88 | domain = parsed.hostname or "" |
| 89 | is_official = ( |
| 90 | domain in OFFICIAL_DOMAINS |
| 91 | or any(domain.endswith(s) for s in GOV_DOMAIN_SUFFIXES) |
| 92 | ) |
| 93 | if not is_official: |
| 94 | errors.append( |
| 95 | f"{prefix}: source_url domain '{domain}' is not an official " |
| 96 | f"government/standards body domain" |
| 97 | ) |
| 98 | |
| 99 | tags = item.get("tags", []) |
| 100 | if not isinstance(tags, list): |
| 101 | errors.append(f"{prefix}: tags must be a list") |
| 102 | |
| 103 | pub_date = item.get("published_date", "") |
| 104 | if pub_date: |