# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 """Sphinx extension that generates tables from a sandbox policy YAML file. Usage in MyST markdown:: ```{policy-table} path/to/sandbox-policy.yaml ``` The directive reads the YAML relative to the repo root and emits: 1. A "Filesystem, Landlock, and Process" table. 2. One subsection per ``network_policies`` block with endpoint and binary tables. """ from __future__ import annotations from pathlib import Path from typing import Any import yaml from docutils import nodes from docutils.statemachine import StringList from sphinx.application import Sphinx from sphinx.util.docutils import SphinxDirective def _tls_display(ep: dict[str, Any]) -> str: tls = ep.get("tls") return tls if tls else "\u2014" def _access_display(ep: dict[str, Any]) -> str: if "rules" in ep: rules = ep["rules"] parts = [] for r in rules: allow = r.get("allow", {}) parts.append(f"``{allow.get('method', '*')} {allow.get('path', '/**')}``") return ", ".join(parts) access = ep.get("access") if access: return access return "L4 passthrough" def _binaries_line(binaries: list[dict[str, str]]) -> str: paths = [f"``{b['path']}``" for b in binaries] return ", ".join(paths) BLOCK_INFO: dict[str, dict[str, str]] = { "claude_code": { "title": "Anthropic API and Telemetry", "description": ( "Allows Claude Code to reach its API, feature-flagging " "(Statsig), error reporting (Sentry), release notes, and " "the Claude platform dashboard." ), }, "github_ssh_over_https": { "title": "Git Clone and Fetch", "description": ( "Allows ``git clone``, ``git fetch``, and ``git pull`` over " "HTTPS via Git Smart HTTP. Push (``git-receive-pack``) is " "disabled by default." ), }, "nvidia_inference": { "title": "NVIDIA API Catalog", "description": ( "Allows outbound calls to the NVIDIA hosted inference API. " "Used by agents that route LLM requests through " "``integrate.api.nvidia.com``." ), }, "github_rest_api": { "title": "GitHub API (Read-Only)", "description": ( "Grants read-only access to the GitHub REST API. Enables " "issue reads, PR listing, and repository metadata lookups " "without allowing mutations." ), }, "pypi": { "title": "Python Package Installation", "description": ( "Allows ``pip install`` and ``uv pip install`` to reach PyPI, " "python-build-standalone releases on GitHub, and " "``downloads.python.org``." ), }, "vscode": { "title": "VS Code Remote and Marketplace", "description": ( "Allows VS Code Server, Remote Containers, and extension " "marketplace traffic so remote development sessions can " "download updates and extensions." ), }, "gitlab": { "title": "GitLab", "description": ( "Allows the ``glab`` CLI to reach ``gitlab.com`` for " "repository and merge-request operations." ), }, } def _block_title(key: str, name: str) -> str: info = BLOCK_INFO.get(key) return info["title"] if info else name def _block_description(key: str) -> str | None: info = BLOCK_INFO.get(key) return info["description"] if info else None class PolicyTableDirective(SphinxDirective): """Render sandbox policy YAML as tables.""" required_arguments = 1 has_content = False def run(self) -> list[nodes.Node]: repo_root = Path(self.env.srcdir).parent yaml_path = repo_root / self.arguments[0] self.env.note_dependency(str(yaml_path)) if not yaml_path.exists(): msg = self.state_machine.reporter.warning( f"Policy YAML not found: {yaml_path}", line=self.lineno, ) return [msg] policy = yaml.safe_load(yaml_path.read_text()) lines: list[str] = [] fs = policy.get("filesystem_policy", {}) landlock = policy.get("landlock", {}) proc = policy.get("process", {}) lines.append("(default-policy-fs-landlock-process)=") lines.append("