55 lines
1.7 KiB
Python
55 lines
1.7 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""Install the branded PWA manifest only over the exact pinned upstream file."""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import hashlib
|
||
|
|
import json
|
||
|
|
import os
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
|
||
|
|
ROOT = Path(os.environ.get("HERMES_WEBUI_PATCH_ROOT", "/opt/hermes-webui"))
|
||
|
|
SOURCE = Path(
|
||
|
|
os.environ.get(
|
||
|
|
"HERMES_WEBUI_MANIFEST_SOURCE", "/tmp/hermes-webui-manifest.json"
|
||
|
|
)
|
||
|
|
)
|
||
|
|
UPSTREAM_SHA256 = "da3e24d84ae91fba3f8ba51f48d51d277b4f6d443506e888a178ac7d1fed1c6a"
|
||
|
|
|
||
|
|
|
||
|
|
manifest_path = ROOT / "static/manifest.json"
|
||
|
|
upstream = manifest_path.read_bytes()
|
||
|
|
if hashlib.sha256(upstream).hexdigest() != UPSTREAM_SHA256:
|
||
|
|
raise SystemExit(
|
||
|
|
"Hermes manifest patch context changed in "
|
||
|
|
f"{manifest_path}: pinned upstream SHA-256 mismatch"
|
||
|
|
)
|
||
|
|
|
||
|
|
branded = SOURCE.read_bytes()
|
||
|
|
try:
|
||
|
|
payload = json.loads(branded)
|
||
|
|
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
|
||
|
|
raise SystemExit("Tracked Hermes manifest is not valid UTF-8 JSON") from exc
|
||
|
|
|
||
|
|
expected_icons = {
|
||
|
|
("static/hermes-agent-192.png", "192x192", "image/png"),
|
||
|
|
("static/hermes-agent-512.png", "512x512", "image/png"),
|
||
|
|
}
|
||
|
|
actual_icons = {
|
||
|
|
(icon.get("src"), icon.get("sizes"), icon.get("type"))
|
||
|
|
for icon in payload.get("icons", [])
|
||
|
|
if isinstance(icon, dict)
|
||
|
|
}
|
||
|
|
if (
|
||
|
|
payload.get("name") != "Hermes Chat"
|
||
|
|
or payload.get("short_name") != "Hermes"
|
||
|
|
or actual_icons != expected_icons
|
||
|
|
):
|
||
|
|
raise SystemExit("Tracked Hermes manifest identity contract changed")
|
||
|
|
|
||
|
|
# Write once, and only after both the installed upstream context and replacement
|
||
|
|
# contract have passed. This prevents an upstream pin drift from being hidden by
|
||
|
|
# a wholesale COPY over the served manifest.
|
||
|
|
manifest_path.write_bytes(branded)
|