fix(assessment): establish independent release trust
Some checks failed
Dependency Audit / dependency-audit (push) Failing after 15s
Security Audit / security-audit (push) Failing after 13s

This commit is contained in:
2026-07-22 17:09:35 +02:00
parent 753dd2a3ee
commit ad8dd4f319
7 changed files with 577 additions and 102 deletions

View File

@@ -7,11 +7,12 @@ import json
from pathlib import Path
from urllib.error import HTTPError, URLError
from .http_fetch import fetch_http
from .http_fetch import DEFAULT_MAX_RESPONSE_BYTES, fetch_http
from .model import CatalogSnapshot
from .workspace import website_root
DEFAULT_PUBLIC_BASE_URL = "https://govoplan.add-ideas.de"
MAX_PUBLIC_JSON_RESPONSE_BYTES = DEFAULT_MAX_RESPONSE_BYTES
def collect_catalog_snapshot(
@@ -22,9 +23,13 @@ def collect_catalog_snapshot(
check_public: bool = False,
) -> CatalogSnapshot:
web_root = website_root(workspace_root)
catalog_path = web_root / "public" / "catalogs" / "v1" / "channels" / f"{channel}.json"
catalog_path = (
web_root / "public" / "catalogs" / "v1" / "channels" / f"{channel}.json"
)
keyring_path = web_root / "public" / "catalogs" / "v1" / "keyring.json"
public_catalog_url = f"{public_base_url.rstrip('/')}/catalogs/v1/channels/{channel}.json"
public_catalog_url = (
f"{public_base_url.rstrip('/')}/catalogs/v1/channels/{channel}.json"
)
public_keyring_url = f"{public_base_url.rstrip('/')}/catalogs/v1/keyring.json"
catalog_version: str | None = None
@@ -129,8 +134,12 @@ def collect_catalog_snapshot(
public_keyring_hash=public_keyring_hash,
public_catalog_error=public_catalog_error,
public_keyring_error=public_keyring_error,
catalog_matches_public=compare_hashes(local_catalog_hash, public_catalog_hash) if check_public else None,
keyring_matches_public=compare_hashes(local_keyring_hash, public_keyring_hash) if check_public else None,
catalog_matches_public=compare_hashes(local_catalog_hash, public_catalog_hash)
if check_public
else None,
keyring_matches_public=compare_hashes(local_keyring_hash, public_keyring_hash)
if check_public
else None,
)
@@ -149,7 +158,9 @@ def parse_catalog_payload(payload: object) -> dict[str, str | int | None]:
signatures = payload.get("signatures")
return {
"catalog_version": string_or_none(payload.get("catalog_version")),
"core_release_version": string_or_none(core_release.get("version")) if isinstance(core_release, dict) else None,
"core_release_version": string_or_none(core_release.get("version"))
if isinstance(core_release, dict)
else None,
"module_count": len(modules) if isinstance(modules, list) else 0,
"signature_count": len(signatures) if isinstance(signatures, list) else 0,
"generated_at": string_or_none(payload.get("generated_at")),
@@ -164,6 +175,7 @@ def fetch_json(url: str) -> dict[str, object]:
timeout=10,
label="Public release catalog URL",
headers={"User-Agent": "GovOPlaN release-console"},
max_response_bytes=MAX_PUBLIC_JSON_RESPONSE_BYTES,
)
return {"ok": True, "payload": json.loads(response.text())}
except (HTTPError, URLError, TimeoutError, ValueError, json.JSONDecodeError) as exc:
@@ -171,7 +183,9 @@ def fetch_json(url: str) -> dict[str, object]:
def canonical_hash(payload: object) -> str:
canonical = json.dumps(payload, sort_keys=True, separators=(",", ":"), ensure_ascii=True).encode("utf-8")
canonical = json.dumps(
payload, sort_keys=True, separators=(",", ":"), ensure_ascii=True
).encode("utf-8")
return hashlib.sha256(canonical).hexdigest()