"""Bounded package metadata and conservative direct-Node test discovery.""" from __future__ import annotations from pathlib import Path import re import shlex from .common import digest, read_json, redact_argv, reject_symlinks MAX_PACKAGE_BYTES = 1024 * 1024 MAX_SCRIPTS = 512 CORE_COMPONENT_SUITES = ( "data-grid-actions", "dialog-focus", "explorer-tree", "icon-button", "layout-primitives", "mail-components", "metric-card", "page-layout", "workspace-layout", "people-picker", "password-field", "resource-access", "action-blocker", "documentation-help", "selection-list", "wysiwyg-editor", ) CORE_RUNNER = "scripts/run-component-tests.mjs" def read_package(path: Path) -> dict: try: package = read_json(path, max_bytes=MAX_PACKAGE_BYTES) except (OSError, ValueError) as exc: raise ValueError(f"Cannot safely read package metadata: {path}") from exc if not isinstance(package, dict): raise ValueError(f"Package metadata must be an object: {path}") scripts = package.get("scripts", {}) if not isinstance(scripts, dict) or len(scripts) > MAX_SCRIPTS: raise ValueError(f"Package scripts must be a bounded object: {path}") for name, command in scripts.items(): if ( not isinstance(name, str) or not 1 <= len(name) <= 128 or any(char in name for char in "\0\r\n") ): raise ValueError(f"Package script names must be bounded strings: {path}") if ( not isinstance(command, str) or not 1 <= len(command) <= 8192 or "\0" in command ): raise ValueError( f"Package script commands must be bounded nonempty strings: {path}" ) return package def core_component_alias( repo_name: str, name: str, command: str, package_path: Path ) -> str | None: if repo_name != "govoplan-core" or package_path.parent.name != "webui": return None if name == "test:components" and command == f"node {CORE_RUNNER}": return "all" for suite in CORE_COMPONENT_SUITES: if name == "test:" + suite and command == f"node {CORE_RUNNER} {suite}": return suite return None def direct_node(command: str, package_path: Path) -> tuple[list[str] | None, str]: try: parts = shlex.split(command) except ValueError: return None, "Malformed command quoting; no command was guessed or executed." if not parts or parts[0] != "node": return ( None, "Not a direct Node source test; use its explicitly reviewed owning workflow.", ) offset = 2 if len(parts) > 1 and parts[1] == "--test" else 1 if len(parts) != offset + 1 or not re.fullmatch( r"(?:scripts|tests)/[A-Za-z0-9_.-]+\.mjs", parts[offset] ): return ( None, "Compound command, flags or arguments are unsupported by scoped source discovery.", ) if parts[offset] == CORE_RUNNER: return ( None, "Only exact known Core component aliases belong to the shared UI batch.", ) target = package_path.parent / parts[offset] try: reject_symlinks(target) if not target.is_file() or not target.resolve().is_relative_to( package_path.parent.resolve() ): return None, "Declared test target is missing or escapes its package." except (OSError, ValueError): return None, "Declared test target is not a safe regular package file." return [ "{node}", *parts[1:offset], str(target), ], "Direct package-owned source test." def declared_tests(repo, package_path: Path) -> list[dict]: package = read_package(package_path) result = [] for name, command in sorted(package.get("scripts", {}).items()): if name != "test" and not name.startswith("test:"): continue component = core_component_alias(repo.name, name, command, package_path) argv, reason = ( direct_node(command, package_path) if component is None else (None, "Exact known Core component alias.") ) result.append( { "repo": repo.name, "package_path": str(package_path), "name": name, "command_sha256": digest(command), "argv": redact_argv(argv) if argv else None, "component_suite": component, "reason": reason, "_argv": argv, } ) return result def discovered_sources(repo) -> list[dict]: webui = repo.path / "webui" found = {} for folder in ("scripts", "tests"): for pattern in ("test-interface-pattern*.mjs", "*structure*.mjs"): for target in (webui / folder).glob(pattern): command = ( "node " + ("--test " if target.name.endswith(".test.mjs") else "") + target.relative_to(webui).as_posix() ) argv, reason = direct_node(command, webui / "package.json") found[str(target)] = { "repo": repo.name, "package_path": str(webui / "package.json"), "name": "file:" + target.relative_to(webui).as_posix(), "discovered": True, "command_sha256": digest(command), "argv": redact_argv(argv) if argv else None, "component_suite": None, "reason": reason, "_argv": argv, } if len(found) > MAX_SCRIPTS: raise ValueError( f"Too many discovered source checks in {repo.name}" ) return [found[key] for key in sorted(found)] def source_stage_id(repo_name: str, argv: list[str]) -> str: stem = Path(argv[-1]).stem return f"{repo_name}.{stem}"[:110] + "." + digest(argv)[:12]