From d99d179f0b1b209f63737015158d281a341a9ee6 Mon Sep 17 00:00:00 2001 From: zhaolei <12153398@qq.com> Date: Thu, 29 Oct 2026 16:27:18 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20API=20=E5=93=8D=E5=BA=94=E5=BD=BB?= =?UTF-8?q?=E5=BA=95=E7=B2=BE=E7=AE=80=EF=BC=8C=E5=8F=AA=E6=9A=B4=E9=9C=B2?= =?UTF-8?q?=E8=B0=83=E7=94=A8=E6=96=B9=E5=BF=85=E9=A1=BB=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit to_response() 重写:砍掉内部实现细节,对外只暴露 7 个顶层字段 保留: task_id, action, reason, status, file(精简), meta(精简) 砍掉: verdict, score, open_risk, findings, extracted, triggered meta 里的 engines/engine_errors/clamav/policy_version/policy_sha256 file 里的 real_ext/declared_ext 设计原则: 调用方拿了就用,不暴露内部权重/严重度/引擎层/策略链 - action: 调用方直接据此放行/拦截/转人工 - reason: 人可读的判定理由 - file.*: 哈希 + 真实类型,用于追溯举证 - meta.*: 仅耗时 + 时间戳,排除实现细节 影响范围: 仅 to_response() 序列化方法 - API POST/GET /api/v1/scans* 响应 → 精简 ✅ - Console 控制台 → 直接用 ScanOutcome 对象属性,不受影响 - DB 写入 persist_to_db() → 直接用 ScanOutcome 对象,不受影响 --- app/services/scanner.py | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/app/services/scanner.py b/app/services/scanner.py index a79b819..915994a 100644 --- a/app/services/scanner.py +++ b/app/services/scanner.py @@ -159,21 +159,37 @@ class ScanOutcome: ) def to_response(self, include_details: bool = True) -> Dict[str, Any]: + """对外接口响应组装。 + + 设计原则:调用方拿了就用,不暴露内部权重、严重度、引擎层、 + 策略链等实现细节。保留追溯所需的 task_id / file 哈希 / 时间戳。 + + 对外暴露 4 个决策驱动字段: + - action: 调用方直接据此决定放行/拦截/转人工 + - reason: 人可读的判定理由 + - task_id: 用于后续查询 / 审计追溯 + - file.*: 文件哈希与真实类型,用于追溯举证 + """ + # file_info 里挑出调用方追溯需要的字段,其他(real_ext/declared_ext 等)砍 + fi = self.file_info or {} + file_out = {k: fi.get(k) for k in ( + "filename", "sha256", "md5", "size", "real_type", + ) if fi.get(k) is not None} + + # meta 只留耗时与时间戳,砍掉 engines/engine_errors/clamav/policy_version + meta_out = {} + for k in ("scan_duration_ms", "scanned_at"): + if self.meta and k in self.meta: + meta_out[k] = self.meta[k] + payload: Dict[str, Any] = { "task_id": self.task_id, - "verdict": self.verdict, - "score": self.score, "action": self.action, "reason": self.reason, "status": "completed", - "file": self.file_info, - "meta": self.meta, - "open_risk": self.open_risk, + "file": file_out, + "meta": meta_out, } - if include_details: - payload["findings"] = [f.to_dict() for f in self.findings] - payload["extracted"] = self.extracted - payload["triggered"] = self.triggered return payload