产物地址只允许公网主机,回环与内网段一律拒收

- platform-tripo:`TripoUrl::parse` 在协议与 userinfo 检查之后,再加一道主机检查——回环、内网、链路本地、组播与保留段(含云元数据 169.254.169.254)全部拒收;`localhost` 及其子域同样拒收;IPv4-mapped 的 IPv6 地址按内嵌的 IPv4 判定,`::ffff:127.0.0.1` 绕不过去
- 保留段按 IANA 特殊用途表逐段列出(0/8、100.64/10、192.0.0/24、198.18/15、240/4),因为 `Ipv4Addr::is_reserved` 与 `is_global` 在当前工具链上仍是 nightly
- 新增用例覆盖 17 个拒收地址与 5 个放行地址;产物下载用例本来就跑在 127.0.0.1 的本地 mock 上,改用 `parse_unchecked_for_test` 构造
- docs/technical:写明这条主机规则与「域名解析结果在这一层看不见」的已知限制
This commit is contained in:
2026-09-24 20:36:57 +08:00
parent a6409d79dc
commit a08e3bf262
3 changed files with 128 additions and 3 deletions
@@ -16,7 +16,7 @@
`platform-tripo` 是唯一接触 `tripo3d-sdk` 的边界。它返回自己的 provider DTO,不让 SDK 类型穿透到未来的 `api-server`。Tripo 的 `success` 映射为 `completed`;`failed`/`banned` 映射为 `failed`;`cancelled` 和 `expired` 保留为独立终态;未知状态返回结构化错误。
provider task 结果与产品资源结果分离。provider adapter 不生成 `resourceId` 或 `assetId`;未来应用层在资源持久化后再构造带资源 ID 的产品 DTO。模型 URL 被视为临时 provider 引用,下载由显式方法完成。`TripoUrl` 的 `Debug` 与 `redacted()` 只输出 scheme、host 与 path,隐藏可能带签名的 query 与 fragment,并保留命中的分隔符(`?` 或 `#`),不把 fragment 显示成 query;带 userinfo 的地址在解析阶段直接拒绝。完整 URL 仅通过 `as_str()` 显式读取;`TripoUrl` 不实现 `Display`,避免 `{}` 这类通用格式化把带签名的完整地址写进日志,冒烟示例同样只打印脱敏后的地址。
provider task 结果与产品资源结果分离。provider adapter 不生成 `resourceId` 或 `assetId`;未来应用层在资源持久化后再构造带资源 ID 的产品 DTO。模型 URL 被视为临时 provider 引用,下载由显式方法完成。`TripoUrl` 的 `Debug` 与 `redacted()` 只输出 scheme、host 与 path,隐藏可能带签名的 query 与 fragment,并保留命中的分隔符(`?` 或 `#`),不把 fragment 显示成 query;带 userinfo 的地址在解析阶段直接拒绝;主机必须是公网地址,回环、内网、链路本地、组播与保留段(含云元数据地址 `169.254.169.254`)一律拒收,域名层面拦住 `localhost` 及其子域。域名解析出的真实地址在这一层看不见,域名指向内网的情况要靠连接层处理,属已知限制。完整 URL 仅通过 `as_str()` 显式读取;`TripoUrl` 不实现 `Display`,避免 `{}` 这类通用格式化把带签名的完整地址写进日志,冒烟示例同样只打印脱敏后的地址。
task 尚未完成时 `output` 为空;完成后 `output` 必须是与 task type 一致的 enum variant,不使用把不同 endpoint 字段揉在一起的通用可选字段结构。真实 provider smoke 确认:text-to-model 结果固定包含 `model_url`、`rendered_image_url`、`generated_image_url`;image-to-model 和 multiview-to-model 结果固定包含 `model_url`、`rendered_image_url`。这些字段在各自结果 struct 中均为必填 `TripoUrl`;缺失、URL 非法或 task type 不受支持时返回 `TripoError::OutputSchema`。