avoigt1121
Claude Opus 5.5
docs: name no institution in the public repo (the client's Tech Transfer rule)
081f1c7 Download scripts/render_host_table.py from anne-voigt/pdac-knowledge-agent-dev: direct link, hf CLI and curl.
- Browser
- Download file 3.13 kB
-
https://huggingface.co/spaces/anne-voigt/pdac-knowledge-agent-dev/resolve/main/scripts/render_host_table.py
- Command line
-
hf download hf://spaces/anne-voigt/pdac-knowledge-agent-dev/scripts/render_host_table.py
-
curl -L -o render_host_table.py https://huggingface.co/spaces/anne-voigt/pdac-knowledge-agent-dev/resolve/main/scripts/render_host_table.py
3.13 kB
| """Render the security addendum's host table from config, so the addendum cannot drift from the code. | |
| The table between the ``host-table`` markers in ``docs/security/addendum-knowledge-specialist.md`` is | |
| generated from ``config/sources.yaml`` (hosts, licences) and ``config/tools_allowlist.yaml`` (which | |
| endpoints call which source). ``tests/test_sources_hosts.py`` already proves every host a loaded tool | |
| can reach is in ``sources.yaml``; this script carries that same list into the document the client's security reviewers read. | |
| python scripts/render_host_table.py # rewrite the block in place | |
| python scripts/render_host_table.py --check # exit 1 if the committed block is stale | |
| """ | |
| from __future__ import annotations | |
| import sys | |
| from pathlib import Path | |
| ROOT = Path(__file__).resolve().parent.parent | |
| sys.path.insert(0, str(ROOT)) | |
| from src import config | |
| ADDENDUM = ROOT / "docs" / "security" / "addendum-knowledge-specialist.md" | |
| START = "<!-- host-table:start (generated by scripts/render_host_table.py; do not edit by hand) -->" | |
| END = "<!-- host-table:end -->" | |
| def endpoints_by_source() -> dict[str, list[str]]: | |
| used: dict[str, set[str]] = {} | |
| for tool in config.allowlist()["tools"].values(): | |
| used.setdefault(tool["source"], set()).update(tool["endpoints"]) | |
| return {sid: [e for e in config.ENDPOINTS if e in eps] for sid, eps in used.items()} | |
| def render() -> str: | |
| by_source = endpoints_by_source() | |
| rows = [ | |
| "| Source | Hosts called | Licence carried on every row | Called in Phase 1 by | Key needed |", | |
| "|---|---|---|---|---|", | |
| ] | |
| for sid, src in config.sources().items(): | |
| eps = by_source.get(sid) or [] | |
| called = ", ".join(f"`{e}`" for e in eps) if eps else "not called (declared ahead of use)" | |
| hosts = ", ".join(f"`{h}`" for h in src["hosts"]) | |
| rows.append(f"| {src['name']} | {hosts} | {src['licence']} | {called} | none |") | |
| n_hosts = sum(len(s["hosts"]) for s in config.sources().values()) | |
| n_called = sum(len(s["hosts"]) for sid, s in config.sources().items() if by_source.get(sid)) | |
| rows.append("") | |
| rows.append( | |
| f"{n_hosts} hosts in all; {n_called} are called by a Phase 1 endpoint. Source of truth: " | |
| "`config/sources.yaml`, checked against the installed ToolUniverse by " | |
| "`tests/test_sources_hosts.py`." | |
| ) | |
| return "\n".join([START, *rows, END]) | |
| def main(argv: list[str]) -> int: | |
| text = ADDENDUM.read_text(encoding="utf-8") | |
| if START not in text or END not in text: | |
| print(f"{ADDENDUM.name}: host-table markers missing", file=sys.stderr) | |
| return 2 | |
| before, rest = text.split(START, 1) | |
| _, after = rest.split(END, 1) | |
| updated = before + render() + after | |
| if "--check" in argv: | |
| if updated != text: | |
| print( | |
| f"{ADDENDUM.name}: host table is stale; run scripts/render_host_table.py", | |
| file=sys.stderr, | |
| ) | |
| return 1 | |
| return 0 | |
| ADDENDUM.write_text(updated, encoding="utf-8") | |
| return 0 | |
| if __name__ == "__main__": | |
| raise SystemExit(main(sys.argv[1:])) | |