保留工具桥和验证证据错误
保留图片证据读取和哈希底层原因 补充 Direct 工具错误展示约定
This commit is contained in:
@@ -1053,15 +1053,15 @@ fn bridge_resource_request_fingerprint(input: &DirectResourceGenerationInput) ->
|
||||
fn bridge_png_content(root: &Path, path: &Path) -> Result<String, String> {
|
||||
let root = root
|
||||
.canonicalize()
|
||||
.map_err(|_| "工具桥项目根无法安全解析".to_string())?;
|
||||
.map_err(|error| format!("工具桥项目根无法安全解析:{error}"))?;
|
||||
let path = path
|
||||
.canonicalize()
|
||||
.map_err(|_| "工具桥图片不存在".to_string())?;
|
||||
.map_err(|error| format!("工具桥图片不存在或无法解析:{error}"))?;
|
||||
if !path.starts_with(&root) {
|
||||
return Err("工具桥图片越出当前项目边界".to_string());
|
||||
}
|
||||
let metadata =
|
||||
std::fs::symlink_metadata(&path).map_err(|_| "读取工具桥图片失败".to_string())?;
|
||||
std::fs::symlink_metadata(&path).map_err(|error| format!("读取工具桥图片失败:{error}"))?;
|
||||
if metadata.file_type().is_symlink()
|
||||
|| !metadata.is_file()
|
||||
|| metadata.len() > DIRECT_TOOL_BRIDGE_MAX_IMAGE_BYTES
|
||||
@@ -1071,7 +1071,7 @@ fn bridge_png_content(root: &Path, path: &Path) -> Result<String, String> {
|
||||
let (mut file, _) = open_project_snapshot_regular_file(&path, "工具桥图片")?;
|
||||
let mut bytes = Vec::new();
|
||||
file.read_to_end(&mut bytes)
|
||||
.map_err(|_| "读取工具桥图片失败".to_string())?;
|
||||
.map_err(|error| format!("读取工具桥图片失败:{error}"))?;
|
||||
if !bytes.starts_with(b"\x89PNG\r\n\x1a\n") {
|
||||
return Err("工具桥图片不是有效 PNG".to_string());
|
||||
}
|
||||
|
||||
@@ -104,17 +104,17 @@ fn evidence_hashes(root: &Path, result: &Value) -> Result<Value, String> {
|
||||
return Err("validation-evidence: 证据不属于受控验证目录".into());
|
||||
}
|
||||
let path = resolve_local_project_path(root, relative)?;
|
||||
let meta =
|
||||
std::fs::symlink_metadata(&path).map_err(|_| "validation-evidence: 证据文件丢失")?;
|
||||
let meta = std::fs::symlink_metadata(&path)
|
||||
.map_err(|error| format!("validation-evidence: 证据文件丢失:{error}"))?;
|
||||
if !meta.is_file() || meta.file_type().is_symlink() || meta.len() > 16 * 1024 * 1024 {
|
||||
return Err("validation-evidence: 证据类型或大小无效".into());
|
||||
}
|
||||
let mut bytes = Vec::new();
|
||||
std::fs::File::open(path)
|
||||
.map_err(|_| "validation-evidence: 无法读取证据")?
|
||||
.map_err(|error| format!("validation-evidence: 无法读取证据:{error}"))?
|
||||
.take(16 * 1024 * 1024 + 1)
|
||||
.read_to_end(&mut bytes)
|
||||
.map_err(|_| "validation-evidence: 无法读取证据")?;
|
||||
.map_err(|error| format!("validation-evidence: 无法读取证据:{error}"))?;
|
||||
if bytes.len() > 16 * 1024 * 1024 {
|
||||
return Err("validation-evidence: 证据文件在读取时超限".into());
|
||||
}
|
||||
@@ -234,14 +234,15 @@ fn fingerprint(root: &Path, include_outputs: bool) -> Result<String, String> {
|
||||
let mut bytes = 0u64;
|
||||
let mut visited = 0usize;
|
||||
while let Some(directory) = directories.pop() {
|
||||
for entry in
|
||||
std::fs::read_dir(&directory).map_err(|_| "validation-fingerprint: 读取项目失败")?
|
||||
for entry in std::fs::read_dir(&directory)
|
||||
.map_err(|error| format!("validation-fingerprint: 读取项目失败:{error}"))?
|
||||
{
|
||||
visited += 1;
|
||||
if visited > 20_000 {
|
||||
return Err("validation-fingerprint: 项目文件数超限".into());
|
||||
}
|
||||
let entry = entry.map_err(|_| "validation-fingerprint: 读取目录项失败")?;
|
||||
let entry = entry
|
||||
.map_err(|error| format!("validation-fingerprint: 读取目录项失败:{error}"))?;
|
||||
let name = entry.file_name().to_string_lossy().to_ascii_lowercase();
|
||||
if matches!(
|
||||
name.as_str(),
|
||||
@@ -264,7 +265,7 @@ fn fingerprint(root: &Path, include_outputs: bool) -> Result<String, String> {
|
||||
}
|
||||
let ty = entry
|
||||
.file_type()
|
||||
.map_err(|_| "validation-fingerprint: 读取类型失败")?;
|
||||
.map_err(|error| format!("validation-fingerprint: 读取类型失败:{error}"))?;
|
||||
let path = entry.path();
|
||||
if !include_outputs
|
||||
&& name == "dist"
|
||||
@@ -300,14 +301,14 @@ fn fingerprint(root: &Path, include_outputs: bool) -> Result<String, String> {
|
||||
if name.starts_with("game-creator.config") {
|
||||
continue;
|
||||
}
|
||||
let mut file =
|
||||
std::fs::File::open(&path).map_err(|_| "validation-fingerprint: 打开输入失败")?;
|
||||
let mut file = std::fs::File::open(&path)
|
||||
.map_err(|error| format!("validation-fingerprint: 打开输入失败:{error}"))?;
|
||||
let mut digest = Sha256::new();
|
||||
let mut buffer = [0u8; 64 * 1024];
|
||||
loop {
|
||||
let read = file
|
||||
.read(&mut buffer)
|
||||
.map_err(|_| "validation-fingerprint: 读取输入失败")?;
|
||||
.map_err(|error| format!("validation-fingerprint: 读取输入失败:{error}"))?;
|
||||
if read == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -117,6 +117,7 @@ DirectProject 已经解决过同一类问题([`【ADR】DirectProject命令接
|
||||
- Codex Provider proxy 的请求体读取/JSON 改写、上游请求、响应构造和 SSE 传输错误也必须把 serde、join、reqwest 或流错误写入返回正文,不能只回 `provider upstream unavailable`。
|
||||
- 浏览器健康检查的发现、临时目录、配置、DevTools 版本请求和清理失败保留底层错误/超时阶段;稳定浏览器码用于分类,但不能覆盖诊断正文。
|
||||
- WebView 普通错误出口遇到 Tauri 的结构化对象时,优先展示 `message/detail/reason/code`,再有界序列化对象;不得把对象转成 `[object Object]` 后回落“未提供具体错误正文”。
|
||||
- Direct 工具桥图片读取和真实试玩验证证据的 OS 读取/哈希错误保留底层原因;路径越界、私有路径和安全拒绝仍使用稳定安全码。
|
||||
- 浏览器启动/DevTools 握手与 Codex model-catalog 子进程失败保留 stderr、退出状态、解析错误和阶段;稳定机器码仍用于分类,但不能单独成为用户可见正文。
|
||||
- Node/npm 环境探测和 Web scaffold 构建持续排空并保存有界 stdout/stderr 尾部,失败返回退出状态、超时阶段和脱敏正文;环境预检回执同时下发 `code` 与 `diagnostic`。
|
||||
- HTTP 409 只有明确包含泥点不足事实时才映射为 `paidCreditsInsufficient`;Claude Code 的普通 409 冲突保留为 `upstreamFailed`。
|
||||
|
||||
@@ -20,6 +20,7 @@ DirectProject 回合失败在确认不是客户端内部不可归类故障时,
|
||||
- Codex Provider proxy 的请求体改写、上游发送、响应构造和 SSE 错误保留底层正文,避免代理层再次把具体网络/解析故障压成单一 unavailable。
|
||||
- 浏览器健康检查不再把发现、配置、DevTools 版本和清理失败只返回机器码;阶段码保留,同时带底层错误或明确的超时预算。
|
||||
- WebView 结构化对象错误保留 `message/detail/reason/code` 或有界 JSON 正文,避免 `[object Object]` 触发普通错误兜底。
|
||||
- Direct 工具桥图片与真实试玩证据读取/哈希错误保留 OS 正文,安全边界拒绝继续使用稳定码。
|
||||
- Transport / Stream / IPC / host process / memory exhaustion 的回归测试与错误事件证据。
|
||||
|
||||
## 不做
|
||||
|
||||
Reference in New Issue
Block a user