From 51af1ba90d15300fad353fefc6f60a95ad133403 Mon Sep 17 00:00:00 2001 From: 732642856 <732642856@qq.com> Date: Tue, 21 Jul 2026 16:06:26 +0800 Subject: [PATCH] feat: add commercial privacy artifact gate --- scripts/commercial_privacy_artifact_scan.py | 43 +++++++++++++++++++ .../test_commercial_privacy_artifact_scan.py | 31 +++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 scripts/commercial_privacy_artifact_scan.py create mode 100644 tests/test_commercial_privacy_artifact_scan.py diff --git a/scripts/commercial_privacy_artifact_scan.py b/scripts/commercial_privacy_artifact_scan.py new file mode 100644 index 00000000..0423b3f1 --- /dev/null +++ b/scripts/commercial_privacy_artifact_scan.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +"""Commercial privacy artifact gate. + +This is a thin commercial wrapper around the existing public release privacy +scanner. It exists so CI/product checks can call a business-named gate without +duplicating privacy logic. +""" +from __future__ import annotations + +import argparse +import json + +from public_release_privacy_scan import build_report + + +def commercial_report() -> dict[str, object]: + base = build_report() + return { + "scope": "commercial_privacy_artifact_scan", + "status": base["status"], + "finding_count": base["finding_count"], + "scanned_files": base["scanned_files"], + "privacy_boundary": "no_real_user_birth_data_private_cases_or_secret_values_in_public_artifacts", + "scanner_reuse": "scripts/public_release_privacy_scan.py", + "local_runtime_assets_not_committed": ["hip_main.dat", "hip_main.dat.download"], + "findings": base["findings"], + } + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--json", action="store_true", help="Emit JSON.") + args = parser.parse_args() + report = commercial_report() + if args.json: + print(json.dumps(report, ensure_ascii=False, indent=2, sort_keys=True)) + else: + print(f"{report['status']}: {report['finding_count']} findings") + return 0 if report["status"] == "pass" else 1 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tests/test_commercial_privacy_artifact_scan.py b/tests/test_commercial_privacy_artifact_scan.py new file mode 100644 index 00000000..807c3001 --- /dev/null +++ b/tests/test_commercial_privacy_artifact_scan.py @@ -0,0 +1,31 @@ +from __future__ import annotations + +import json +import subprocess +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] + + +def test_commercial_privacy_scan_reuses_public_release_scanner() -> None: + source = (ROOT / "scripts/commercial_privacy_artifact_scan.py").read_text() + assert "from public_release_privacy_scan import build_report" in source + assert "no_real_user_birth_data_private_cases_or_secret_values_in_public_artifacts" in source + assert "hip_main.dat" in source + + +def test_commercial_privacy_scan_json_contract_passes_current_tree() -> None: + completed = subprocess.run( + [sys.executable, "scripts/commercial_privacy_artifact_scan.py", "--json"], + cwd=ROOT, + text=True, + capture_output=True, + check=True, + ) + report = json.loads(completed.stdout) + assert report["scope"] == "commercial_privacy_artifact_scan" + assert report["scanner_reuse"] == "scripts/public_release_privacy_scan.py" + assert report["status"] == "pass" + assert report["finding_count"] == 0 + assert "hip_main.dat" in report["local_runtime_assets_not_committed"]