Download sibyl-memory-client/scripts/check_release_keys.py from SibylLabsLLC/Sibyl-Memory: direct link, hf CLI and curl.
- Browser
- Download file 3.08 kB
-
https://huggingface.co/SibylLabsLLC/Sibyl-Memory/resolve/main/sibyl-memory-client/scripts/check_release_keys.py
- Command line
-
hf download hf://SibylLabsLLC/Sibyl-Memory/sibyl-memory-client/scripts/check_release_keys.py
-
curl -L -o check_release_keys.py https://huggingface.co/SibylLabsLLC/Sibyl-Memory/resolve/main/sibyl-memory-client/scripts/check_release_keys.py
3.08 kB
| #!/usr/bin/env python3 | |
| """Release gate for the pinned entitlement keys (spec account-gated 2.4, 7.1 step 10). | |
| Fails (exit 1) while any kid in sibyl_memory_client._entitlement_keys.TRUSTED_KEYS | |
| is a PLACEHOLDER, while a pinned key is malformed (not 32 bytes, kid does not | |
| match sha256(raw)[:16]), or, when --expect-kids is given, while the pinned kid | |
| set differs from the kids the operator read from production | |
| /api/plugin/health `entitlement_public_keys`. No network: the expected kids | |
| are an argument. | |
| python scripts/check_release_keys.py --expect-kids 3f9a1c2b7e4d6a80 | |
| python scripts/check_release_keys.py --src path/to/src # check a tree, not the install | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import hashlib | |
| import importlib.util | |
| import sys | |
| from pathlib import Path | |
| def _load_keys_module(src: str | None): | |
| if src: | |
| path = Path(src) / "sibyl_memory_client" / "_entitlement_keys.py" | |
| spec = importlib.util.spec_from_file_location("_pinned_keys_under_check", path) | |
| mod = importlib.util.module_from_spec(spec) | |
| assert spec and spec.loader | |
| spec.loader.exec_module(mod) | |
| return mod | |
| from sibyl_memory_client import _entitlement_keys | |
| return _entitlement_keys | |
| def check(src: str | None, expect: set[str] | None) -> list[str]: | |
| mod = _load_keys_module(src) | |
| keys = dict(mod.TRUSTED_KEYS) | |
| placeholders = set(getattr(mod, "PLACEHOLDER_KIDS", frozenset())) | |
| problems: list[str] = [] | |
| if not keys: | |
| problems.append("TRUSTED_KEYS is empty") | |
| if not 1 <= len(keys) <= 2: | |
| problems.append(f"TRUSTED_KEYS holds {len(keys)} keys (expected 1, or 2 during a rotation)") | |
| for kid, raw in keys.items(): | |
| if kid in placeholders: | |
| problems.append(f"kid {kid} is a PLACEHOLDER key; replace it with the production public key") | |
| if not isinstance(raw, (bytes, bytearray)) or len(raw) != 32: | |
| problems.append(f"kid {kid}: public key is not 32 raw bytes") | |
| elif hashlib.sha256(bytes(raw)).hexdigest()[:16] != kid: | |
| problems.append(f"kid {kid}: does not equal sha256(raw public key)[:16]") | |
| if expect is not None and set(keys) != expect: | |
| problems.append(f"pinned kids {sorted(keys)} != production kids {sorted(expect)}") | |
| return problems | |
| def main(argv: list[str] | None = None) -> int: | |
| ap = argparse.ArgumentParser(description=__doc__.splitlines()[0]) | |
| ap.add_argument("--expect-kids", default=None, | |
| help="comma-separated kids from production /api/plugin/health") | |
| ap.add_argument("--src", default=None, help="check this source tree instead of the installed package") | |
| args = ap.parse_args(argv) | |
| expect = None | |
| if args.expect_kids is not None: | |
| expect = {k.strip() for k in args.expect_kids.split(",") if k.strip()} | |
| problems = check(args.src, expect) | |
| if problems: | |
| for p in problems: | |
| print(f"RELEASE BLOCKED: {p}") | |
| return 1 | |
| print("pinned entitlement keys OK") | |
| return 0 | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |