Files
codex-app-server/cloud/gates.py
T
host 41e8c98512 feat: cloud 门禁/超时/成本/沙箱收敛为单一判定源
- 新增标准库叶子层 timeouts/gates/quota/sandbox_policy:
  审批 3600 与单轮 600 各有名常量与环境覆盖层,已建项
  expires_at 永不重算;目录/控制/合并状态门禁统一判定,
  目录违规无任何覆盖参数;配额取数与比较唯一来源
  (USD 先于无价、命中均为 >=、无价只计 actual 行);
  /tmp 隔离矩阵与失联清理判定纯函数化。
- 调用点委托:server/worker/automations/auto_memory 的
  配额 SQL 与比较、server/tree/marker 的目录解析、
  marker 的控制门、sandbox 的任务容器名正则、两处 300 秒
  陈旧阈值默认值均收敛,别名与错误文案不变。
- 统一两个 P0 口径分歧:服务端无价计数由全部 usd IS NULL
  行改为 actual-only;显式不限额用户在服务端准入亦不受
  无价上限约束(与 worker 运行时一致)。
- 不新增门禁种类与 record 模式(主线无此实现);不改
  skill_seed/skills/SKILL.md;不改 v1.1 契约与分支保护。
- 新增 test_arch_converge.py 18 项。
2026-11-03 02:49:25 +00:00

126 lines
5.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""门禁层:调用方只传事实,本层只出决定。
收敛对象是主线上已经存在的硬门禁,不是新发明的门禁
种类。主线(origin/main)上不存在 merge_gate 的
record/enforce 模式、分支保护门禁与全自动门禁——那些只
在未合并的分支里;本轨不从分支搬功能、不新增门禁种类、
不把硬门禁降级为“只记录不阻断”(那会削弱安全语义,
不属于收敛)。本层收敛的是三类已有判定:
1. 目录门(resolve_inside):worktree 内相对路径的安全
解析。服务端 _safe_worktree_path、cloud/tree.py 的
resolve_tree_path、cloud/marker_tools.py 的
safe_worktree_path(worker 经 marker_tools 调用)此前
各写了一份 realpath + commonpath,仅在 commonpath
的 ValueError 处理上不一致(服务端不捕,另两处捕)。
现统一为本函数:绝对路径、.. 逃逸、符号链接逃逸、
跨盘符 ValueError 一律拒绝;空串返回原 worktree。
2. 控制门(decide_control):marker_tools.check_control_gate
的纯函数判定(cancel / retry 的目标状态与派生关系),
现为本层 canonical 实现,marker_tools 只保留同名薄壳
(调用点与测试 import 的名字不变)。
3. 合并状态门(merge_state_decision):服务端 _merge_task
的状态判定——只有 completed 可标记 merged,其它状态
一律拒绝(含已 merged 的重复调用)。权限判定
(approve_merge)仍在服务端,不进本层:本层只看事实
(任务状态),不查权限。
不可覆盖规则(冻结):
- 目录门的拒绝没有任何 confirm / override / bypass 参数。
本模块的函数签名里 deliberately 没有这类参数:显式
确认即使存在,也只能覆盖“保护类风险”,绝不能覆盖
目录违规——而主线上目录违规本来就没有确认通道,
任何调用方都不得以“用户已确认”为由绕过本层。
测试钉住:resolve_inside 与 decide_control 的签名中
不含 confirm / override / bypass 字样。
- 合并状态门同样没有覆盖参数:非 completed 任务不存在
“确认后合并”的路径,重复 merged 调用仍是拒绝。
返回形态沿用 codebase 的元组风格:(allowed, reason),
reason 为空表示放行;目录门另有 resolve_inside 直接
返回路径或 None(旧调用点的形态不变)。
"""
import os
TERMINAL_STATUSES = ("completed", "failed", "interrupted", "merged",
"merge-failed")
RETRYABLE_STATUSES = ("failed", "interrupted", "merge-failed")
def resolve_inside(base, rel):
"""worktree 内相对路径的安全解析:越界回 None。
空串返回 base 本身(旧三处行为一致);绝对路径、
.. 逃逸、符号链接逃逸、commonpath 跨盘符 ValueError
一律 None。目录内指回内部的符号链接放行到真实位置
(调用方仍只拿到 worktree 内的内容)。
"""
if not rel:
return base
if os.path.isabs(rel):
return None
real_base = os.path.realpath(base)
target = os.path.realpath(os.path.join(real_base, rel))
try:
if os.path.commonpath([real_base, target]) != real_base:
return None
except ValueError:
return None
return target
def is_goal_task(task):
"""goal 任务判定:verify_command 非空或 goal_mode 为真。
与 worker run_one 的 goal 分支同款;goal 字段本身是
goal_mode=1 时 prompt 的副本,不单独当判定条件。
"""
if not task:
return False
return bool(task.get("verify_command") or task.get("goal_mode"))
def decide_control(target, sender, relation, kind):
"""task-cancel / task-retry 的纯函数门禁,返回 (ok, reason)。
kind 只能是 "cancel" 或 "retry",其它值一律拒绝。
权限层不在这里:worker 侧另查 create_task /
approve_merge;本函数只管目标状态与关系,单测不需
AuthStore。goal 任务不可取消或重试(goal 循环自有轮次)。
"""
if kind not in ("cancel", "retry"):
return False, "未知的控制操作"
if target is None:
return False, "目标任务不存在"
if (target.get("project_id") is not None
and sender.get("project_id") is not None
and target.get("project_id") != sender.get("project_id")):
return False, "跨项目任务不可操作"
if target.get("id") == sender.get("id"):
return False, "不能操作自己"
if is_goal_task(target):
return False, "goal 任务不可取消或重试(goal 循环自有轮次)"
status = target.get("status")
if kind == "cancel":
if status in TERMINAL_STATUSES:
return False, "目标已终态(%s),不可取消" % status
else:
if status not in RETRYABLE_STATUSES:
return False, ("仅 failed / interrupted / merge-failed"
" 可重试,当前状态为 %s" % status)
if relation not in ("descendant", "same_creator"):
return False, "目标不在发送方派生链上且创建人不同"
return True, ""
def merge_state_decision(status):
"""合并标记的状态判定:仅 completed 放行,返回 (ok, reason)。
含已 merged 的重复调用在内,其它状态一律拒绝;文案与
服务端旧 409 错误一致。权限判定不在本层。
"""
if status == "completed":
return True, ""
return False, "only completed tasks can be marked merged"