Help us shape the future of Go! Take the 2026 Go Developer Survey

policy

package
v0.12.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 23, 2026 License: MIT Imports: 11 Imported by: 3

Documentation

Overview

Package policy 操作审计门:多种会话执行策略模式(confirm/auto/plan/full)下的 统一操作裁决——每个操作必过、三值裁决、全程留痕。模式改变的是裁决策略,不是移除 审计点;红线(变异工具拒绝、高危恒人审)在矩阵层硬编码,任何模式不可绕过。

裁决分层:例外规则(Policy.Rules,首个命中即胜)→ 模式×风险矩阵 → 兜底 need_human (未知形态 fail-safe)。灰区可挂 Arbiter 仲裁插件,失败/非法输出一律 fail-safe 升人审 ——「只升不降」在 fail-safe 方向恒成立。工具调用面的装饰器见 AuditGate。

沉淀自 bianque engine/policy(v0.9.6):领域包 yaml 路径约定改为显式入参 (LoadOverrides path),其余原样。

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AuditGate

func AuditGate(g *Gate, op Op, onAudit func(Op, Decision), t tool.InvokableTool) tool.InvokableTool

AuditGate 给工具套操作审计门;gate 为 nil 原样返回(未装配审计门=存量行为)。

func Disposition added in v0.12.3

func Disposition(err error) toolfail.Class

Disposition 一次失败的处置类别——调用点该调的那一个。

判定顺序:

  1. 宿主已用 toolfail 显式归类(*Failure / 哨兵 / 自报可重试)→ 以那份为准: 那是产出它的那一层已经做完的判断,比协议层事实更具体。
  2. 宿主自报「不可重试」→ ClassUnknown:不得回落到协议层映射,否则会把宿主 已经否决的失败重新判成可重试。
  3. 否则按协议层事实机械映射(FailureClass)。

第 2 步单独存在的原因:toolfail 的自报分支把「自报不可重试」也归成 ClassUnknown, 从返回值上与「什么都没判出来」不可分。此处补一次判别,把这两种情形分开。

func FailureClass added in v0.12.3

func FailureClass(kind mcp.ErrorKind) toolfail.Class

FailureClass 协议层分类 → 处置层类别。

这是**唯一**的映射入口:下游不要各写各的映射表。

未登记的分类(含零值与越界值)一律回落 ClassUnknown——不可分类 = 不可重试, 不给「查不到就乐观」留口子。

func Stage added in v0.6.1

func Stage(g *Gate, op Op, onDecision func(Decision)) invoke.Stage

Stage 把操作审计门接成 invoke 链上的一环。

为什么要这个适配器

AuditGate 是**装饰器**:宿主忘了包一层,这次调用就没有审计门——而且不报错、 不告警,事后从日志里也看不出这次调用没走门。invoke 链不存在这个形态: 拿到链就只能走 Do,绕过代码写不出来(见 invoke 包头)。

故两者并存:AuditGate 保留以兼容既有调用点,**新代码的审计门走这里**。

Op 的取法

op 是**模板**:Type / Mode / Risk / Mutating 在装配期固化(它们按调用点是静态可判的), Tool 每次由链上的实际调用覆盖。这样一个 stage 能服务同一调用点下的多个工具, 不必为每个工具各装配一次。

裁决到放行/拒绝的映射

VerdictAuto      放行
VerdictDeny      拒绝,不可重试(策略否定;重试不会让策略变松)
VerdictNeedHuman 拒绝,**不可重试**:重试会立刻得到同样的结果,
                人工审批是带外动作,不该由退避重试去撞
VerdictPlanOnly  拒绝(执行被降级为仅提审),不可重试
VerdictUnknown   拒绝(fail-closed),不可重试

需要人工介入的情形一律不可重试:把「需要人」翻译成「多试几次」是退避语义 最常见的误用,重试风暴会一直撞同一堵墙,且把真正的阻塞点埋在日志里。

func ValidMode

func ValidMode(s string) bool

ValidMode API 入参严格校验(空串返回 false,由调用方走缺省档)。

Types

type Arbiter

type Arbiter interface {
	Arbitrate(ctx context.Context, op Op) (Verdict, string, error)
}

Arbiter 灰区仲裁插件(可选)。契约:只允许返回 auto_proceed/need_human/deny; 失败或非法输出由 Gate fail-safe 升人审——「只升不降」在 fail-safe 方向恒成立。

type Decider

type Decider string

Decider 裁决者(审计「这次放行是谁裁的」):human 仅审批闸固有语义,gate 不产生。

const (
	DeciderRule   Decider = "rule"          // 规则/矩阵
	DeciderLLM    Decider = "llm"           // 灰区仲裁插件
	DeciderHuman  Decider = "human"         // 人工审批
	DeciderSystem Decider = "system_policy" // 策略代批(审批单 decided_by 同值)
)

type Decision

type Decision struct {
	Verdict Verdict
	Decider Decider
	RuleID  string
	Reason  string
}

Decision 裁决结果(审计事件 payload 的语义源)。

type Gate

type Gate struct {
	// contains filtered or unexported fields
}

Gate 操作审计门。Decide 只读 policy,并发安全,可放工具调用热路径。

func NewGate

func NewGate(p *Policy, a Arbiter) *Gate

NewGate 构造;p 为 nil 用内置基座。

func (*Gate) Decide

func (g *Gate) Decide(ctx context.Context, op Op) Decision

Decide 裁决:例外规则 → 矩阵层 → 兜底 need_human(未知形态 fail-safe)。

type Mode

type Mode string

Mode 会话执行策略模式。

const (
	ModeConfirm Mode = "confirm" // 变更前确认(缺省;=存量行为)
	ModeAuto    Mode = "auto"    // 低风险(≤auto_max_risk)系统代批
	ModePlan    Mode = "plan"    // 计划模式:方案只审不执行
	ModeFull    Mode = "full"    // 完全访问:≤full_max_risk 代批(最高危恒人工双确认)
)

func Normalize

func Normalize(s string) Mode

Normalize 归一:空/非法一律回落 confirm。非法值在 API 入口已被 400 拦截 (ValidMode),这里是纵深兜底——审计门不允许因模式脏值放大权限。

type Op

type Op struct {
	Type     OpType
	Mode     Mode
	Tool     string // 工具名(tool_call/execute_step)
	Risk     int    // 1-4(plan_submit);0=未评级
	Mutating bool   // 工具名命中变异动词段(agentrun.IsMutatingTool)
}

Op 一次待裁决操作。

type OpType

type OpType string

OpType 操作类型:工具调用面 / 确定性执行面 / 方案提审面。

const (
	OpToolCall    OpType = "tool_call"    // LLM ReAct 采集面单次工具调用
	OpExecuteStep OpType = "execute_step" // 已批准方案的确定性执行步骤(审批上游把关,审计复读)
	OpPlanSubmit  OpType = "plan_submit"  // 执行类方案提审(风险等级驱动)
)

type Policy

type Policy struct {
	AutoMaxRisk int    `yaml:"auto_max_risk"`
	FullMaxRisk int    `yaml:"full_max_risk"`
	Rules       []Rule `yaml:"rules"`
}

Policy 策略表:代批阈值 + 例外规则。yaml 外置(LoadOverrides,缺文件用 DefaultPolicy 基座;解析失败 fail-fast)。

func DefaultPolicy

func DefaultPolicy() *Policy

DefaultPolicy 内置基座:auto 代批至 L2、full 代批至 L3(L4 恒人工双确认)。

func LoadOverrides

func LoadOverrides(fsys fs.FS, path string) (*Policy, error)

LoadOverrides 读 <fsys>/<path> 外置策略文件(yaml 根键 operation_policy)。 缺文件 → 内置基座(nil error);读取/解析失败 → error(fail-fast,启动即败, 宁拒不启动不带错跑)。阈值 clamp 到基座——外置文件只能调低不能调高 (调高=扩权,须改基座走评审)。path 由宿主传入(如领域包布局约定 "_shared/operation_policy.yaml")。

type Rule

type Rule struct {
	ID       string   `yaml:"id"`
	OpTypes  []string `yaml:"op_types"` // 空=全部操作类型
	Tools    []string `yaml:"tools"`    // 工具名精确匹配;空=不限
	MinRisk  int      `yaml:"min_risk"` // 含(对 plan_submit 的 Risk 生效;0=不限)
	MaxRisk  int      `yaml:"max_risk"` // 含;0=不限
	Mutating *bool    `yaml:"mutating"` // nil=不限
	Verdict  Verdict  `yaml:"verdict"`  // auto_proceed|need_human|deny|unknown
	Reason   string   `yaml:"reason"`
}

Rule 例外规则(首个命中即裁决,优先于矩阵层)。

type Verdict

type Verdict string

Verdict 裁决值:三值裁决 + 两个过程值(plan_only=计划模式只审不执行; unknown=灰区待仲裁,仅例外规则可产出)。

const (
	VerdictAuto      Verdict = "auto_proceed"
	VerdictNeedHuman Verdict = "need_human"
	VerdictDeny      Verdict = "deny"
	VerdictPlanOnly  Verdict = "plan_only"
	VerdictUnknown   Verdict = "unknown"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL