Files
go-sip/docs/evidence/20260919-phone-call-business-log.md
T

3.0 KiB
Raw Blame History

按手机号关联的外呼业务日志(2026-09-19)

实现

已在 Agent RPC 执行/事实回报边界增加文件型结构化业务日志:

  • internal/calllog/log.goJSONL 追加器;每条记录 0600,父目录 0700,写入后 Sync
  • internal/rpc/server.goExecute 记录 execution.preparedReportExecutionEvent 记录 call status/finished、录音事实和 attempt summary。
  • cmd/sip-go-agent/main.goAgent 配置 CallLogger;未指定路径时写入 Agent spool 的 call-business.jsonl
  • internal/config/config.go:支持 AGENT_CALL_BUSINESS_LOGAGENT_CALL_PHONE_LOG_KEY

脱敏边界

  • 原始 callee 只在进程内用于生成身份,永不序列化到日志。
  • phone_ref 是使用受控注入密钥计算的 HMAC-SHA256,可跨任务关联同一号码;phone_mask 只保留末四位(短号码全部掩码)。
  • 不写入凭据、SIP URI/服务端地址、音频、转写文本、prompt、变量或 OSS 本地路径。
  • 日志 key 不得写入代码、配置样例、日志或证据;建议通过受控环境/secret 文件注入,长度至少 16 字节。key 轮换会产生新的手机号引用,轮换应作为单独运维动作登记。

记录字段

每条记录包含 schema_versionevent_idoccurred_atevent_typephone_refphone_mask,并按实际事实填充:

  • 业务关联:tenant_idtrace_idtask_idtask_item_idtask_revisionexecution_idattempt_idcall_id
  • 线路和节点:route_policy_idcaller_profile_idtrunk_idcell_idagent_id
  • SIP/状态:sip_stagesip_status_codesip_reasoncall_stateattempt_statestatusresultreason_code
  • 录音/结果:recording_idrecording_staterecording_size_bytesrecording_duration_msrecording_sha256duration_ms

ReportExecutionEvent 只从 allow-list 字段解析事实 payload,不把任意 payload 或 transcript 文本复制到业务日志;call.finishedattempt_summary 会拆成独立 call.attempt 记录。

配置

# 可选路径;只配置 key 时默认落到 $AGENT_SPOOL_ROOT/call-business.jsonl
AGENT_CALL_BUSINESS_LOG=/var/lib/sip-go-agent/call-business.jsonl
AGENT_CALL_PHONE_LOG_KEY=<受控注入的至少16字节密钥>

设置路径时必须同时设置 key;只设置 key 时使用 spool fallback。未设置 key 时不会创建日志文件,避免退回明文手机号。

本地验证

已通过:

go test -race ./internal/calllog ./internal/rpc
go test -race ./...
go vet ./...

覆盖场景:同一手机号跨事件稳定关联、原始号码不出现在 JSONL、SIP 阶段/状态码/线路/执行与呼叫 ID/录音/结果字段、attempt summary 拆分、文件权限、非法身份拒绝和并发追加。

该日志是 Agent 本地业务审计材料,不替代 SaaS 的最终业务事件、MQ 应用收讫、OSS verified→MQ 回执或生产观测系统;本地测试通过也不代表真实 SIP/AI/OSS/P1 验收通过。