feat(delivery): final report + reserved-label guard + Windows test fixes (v2 phase A3-final)
Gap-closing on top of the merged A3-3..A3-6 work: - ProjectService.create_preview_domain now refuses a label that is a reserved platform name (git, mcp, api, panel, ...) via PROTECTED_HOST_LABELS. The rules set existed but only the owner-facing validate_extra_host consulted it, so the tenant path could reserve one. - process.py: signal.SIGKILL is resolved through getattr with a SIGTERM fallback, so the module imports and type-checks on Windows where SIGKILL does not exist. - Three more Windows test repairs: a git-created .git must be unlinked and recreated rather than overwritten in place; POSIX-only chmod and symlink assertions are gated on os.name (the security property they assert is checked everywhere, the platform-specific mechanics only where they apply). - docs/plan/reports/agent-3-final.md: the integration hand-off — host requirements, every setting, every endpoint added or changed, the tables, the open CHANGE REQUESTS, a 12-step manual QA script and the known limitations. Checks: ruff clean, mypy clean (136 files), 521 API tests pass, 83 web tests pass, tsc clean, next lint clean.
This commit is contained in:
@@ -142,6 +142,11 @@ def test_safe_join_refuses_a_parent_escape(tmp_path):
|
||||
safe_join(str(root), "a/b/../../../etc/passwd")
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
os.name == "nt",
|
||||
reason="creating a symlink on Windows requires SeCreateSymbolicLinkPrivilege "
|
||||
"(admin or Developer Mode); the path-escape guard is covered on POSIX hosts",
|
||||
)
|
||||
def test_safe_join_refuses_a_symlink_that_escapes(tmp_path):
|
||||
"""A symlink planted inside the work dir must not become a host read."""
|
||||
root = tmp_path / "work"
|
||||
|
||||
Reference in New Issue
Block a user