Document and configure private nonproduction HEP mirror

This commit is contained in:
2026-10-05 21:59:56 +08:00
parent 95eeee8400
commit 7241511f1b
6 changed files with 71 additions and 4 deletions
+2 -1
View File
@@ -80,7 +80,7 @@
- P01–P08 及 K01–K16 已完成**项目内隔离 Mock** 核验;本轮把分散的人类可读契约、文档与第三方对接合为唯一当前规范,不重审已确认规则。若未来另获启动开发/审查子 Agent 授权,必须按使用者指定的 `gpt-5.6-luna`、`max` 思考和 `fast: true` 逐项核验并显式配置,不静默换模型、降档或关闭 fast。
- 唯一现行 SaaS↔Dispatcher 业务规范是 [`docs/thirds/saas-dispatcher.md`](docs/thirds/saas-dispatcher.md);当前项目内 Schema、拓扑、正反例及来源/hash 在 [`contracts/local/`](contracts/local/);内部 Agent RPC 在 [`proto/agent/agent.proto`](proto/agent/agent.proto)。本地验收与外部缺口见 [`docs/evidence/saas-dispatcher-p08-acceptance.md`](docs/evidence/saas-dispatcher-p08-acceptance.md)。Markdown 不代替机器合同或外部签收,也不另外维护一份平行字段定义。
- 已由当前合同来源清单固定哈希的历史提案与计划保留**原字节**于 [`docs/archive/sources/`](docs/archive/sources/README.md),使用者原有未提交的两份旧对接文档也按原字节归档;旧上游 v1 在 [`docs/archive/upstream/`](docs/archive/upstream/README.md) 可离线校验,但不嵌入运行合同。旧 F/W 工作包、旧 MQ-only 合同及归档不作为当前运行入口。固定 MQ `v1`、HTTP `/internal/v1/dispatcher/...` 和业务 revision 是现行通信规则,不是自有实现代次;不得为历史路径新建兼容或回退。
- 当前业务范围仍仅**单节点、单 Dispatcher、单 Agent、单 Cell、单租户**。根命令只接受显式 `agent`/`dispatcher`;`mixed` 和裸 `real` 仍拒绝;隔离 `mock`、只读 `sip-only` 和需完整非生产证据/正式获批指令的 `nonprod-real` 为彼此独立的入口。新增非生产真实入口尚未在测试机完成全链路核验;2026-10-04 获批的同一数企/号码两次单次试拨操作均未观测到 SIP 包或最终结果,第二次已有 Dispatcher 派发回执而 Agent 错误根因未知。第二次派发回执经使用者授权后已私密持久化并确认 MQ,最终结果仍缺失;版本 `d2c4a99` 已通过来源/哈希、非呼出时段不拨号抓包预检与版本级只读主机核验并安装;SaaS、Dispatcher、Agent 在测试机已启动,但没有投递新呼叫,Asterisk 仍为零活动通话。SaaS 测试服务已从获批的新私有快照经 HTTPS 提供租户额度 2/revision 2;2026-10-04 旧事件 `call-669f8829-a111-476d-88c7-3de604bf6dc6` 经使用者单独确认,仅在原始 SQLite 备份、只读通道/抓包核实及操作者证据先私密落盘后,人工标记 Dispatcher inbox 为 `finished` 并释放占用(现为 0),Agent 原 `unknown` 幂等日记、派发回执及原始证据均保留;没有 Agent 签发终结事实或最终结果,不能据此声称真实呼叫成功。不得自动重拨、清理未知执行或以编译/本机 Mock 通过宣称真实通话可用。另有严格隔离的 `--mode sip-only`:只允许 Dispatcher 读完整 SIP、持久接纳归属 `sip.config`、经已激活双向 TLS Agent 会话将完整快照应用到原生 Asterisk,并从运行态核对版本;不发现任务、不启动业务呼叫、不开放准入、不处理其他业务控制。测试机已凭使用者批准,将三条历史登记地址以**测试快照显式声明的** UDP/IP 鉴权、无需 REGISTER 配置写入并核对 Asterisk 运行态;供应商尚未确认这些实际线路是否满足上述参数,至今没有观察到真实 SIP 拨号,不证明线路可用或生产签收。没有真实 SaaS、management、真实通话或生产签收;真实百炼 LLM 与 OSS 已各做一次**不拨号、独立的最小连接/写入诊断**(见 [`docs/evidence/real-ai-oss-one-shot-20261003.md`](docs/evidence/real-ai-oss-one-shot-20261003.md)),这不是获批任务的 ASR/LLM/TTS、录音和上传全链路签收。生产发布包仍为 `production_approval=false`。任何本机 Mock 或 SIP-only 核验均不授权真实呼叫。
- 当前业务范围仍仅**单节点、单 Dispatcher、单 Agent、单 Cell、单租户**。根命令只接受显式 `agent`/`dispatcher`;`mixed` 和裸 `real` 仍拒绝;隔离 `mock`、只读 `sip-only` 和需完整非生产证据/正式获批指令的 `nonprod-real` 为彼此独立的入口。2026-10-05 正式 SaaS Mock 已驱动真实 Agent/Asterisk 发出五通 SIP INVITE,均由线路返回 480,已证实终结并提交结果但均未接通、未见 LLM 应答;数企→15003164745 受当日 3/3 门禁限制尚未在修复版完成试拨,不能声称六组通过。2026-10-04 获批的同一数企/号码两次单次试拨操作均未观测到 SIP 包或最终结果,第二次已有 Dispatcher 派发回执而 Agent 错误根因未知。第二次派发回执经使用者授权后已私密持久化并确认 MQ,最终结果仍缺失;版本 `d2c4a99` 已通过来源/哈希、非呼出时段不拨号抓包预检与版本级只读主机核验并安装;SaaS、Dispatcher、Agent 在测试机已启动,但没有投递新呼叫,Asterisk 仍为零活动通话。SaaS 测试服务已从获批的新私有快照经 HTTPS 提供租户额度 2/revision 2;2026-10-04 旧事件 `call-669f8829-a111-476d-88c7-3de604bf6dc6` 经使用者单独确认,仅在原始 SQLite 备份、只读通道/抓包核实及操作者证据先私密落盘后,人工标记 Dispatcher inbox 为 `finished` 并释放占用(现为 0),Agent 原 `unknown` 幂等日记、派发回执及原始证据均保留;没有 Agent 签发终结事实或最终结果,不能据此声称真实呼叫成功。不得自动重拨、清理未知执行或以编译/本机 Mock 通过宣称真实通话可用。另有严格隔离的 `--mode sip-only`:只允许 Dispatcher 读完整 SIP、持久接纳归属 `sip.config`、经已激活双向 TLS Agent 会话将完整快照应用到原生 Asterisk,并从运行态核对版本;不发现任务、不启动业务呼叫、不开放准入、不处理其他业务控制。测试机已凭使用者批准,将三条历史登记地址以**测试快照显式声明的** UDP/IP 鉴权、无需 REGISTER 配置写入并核对 Asterisk 运行态;供应商尚未确认这些实际线路是否满足上述参数,虽已观察到 SIP 480,但尚未证实线路可接通或完成生产签收。没有真实 SaaS、management、真实通话或生产签收;真实百炼 LLM 与 OSS 已各做一次**不拨号、独立的最小连接/写入诊断**(见 [`docs/evidence/real-ai-oss-one-shot-20261003.md`](docs/evidence/real-ai-oss-one-shot-20261003.md)),这不是获批任务的 ASR/LLM/TTS、录音和上传全链路签收。生产发布包仍为 `production_approval=false`。任何本机 Mock 或 SIP-only 核验均不授权真实呼叫。
- 使用者批准独立的测试专用 `deploys/test/saas-mock/` 仅模拟缺失的 SaaS:从 0600 的静态快照提供五类正式 HTTP 配置,在专用 RabbitMQ vhost 中由模拟 SaaS 预建现行拓扑;不在 Dispatcher 内注入快照;默认不发布外呼消息,只有受限脚本已为同一 `event_id`/线路/原始号码启动抓包后,才可显式单次 MQ 投递;不替代 Agent/Asterisk/AI/OSS。测试用正式入口必须同时具备只读配置、专用 MQ、真实 Agent/Asterisk/AI/录音/OSS、逐通确认和拨号前活跃抓包证据,缺一项不得试拨。此模拟不构成真实 SaaS 签收。
- 开发按 TDD 分批,小步提交;不得覆盖使用者现存修改/未跟踪文件,不自动清理、迁移或覆盖任何现存 SQLite、spool、outbox 和 Agent 恢复文件。旧 `.executions` 及恢复根目录中旧 `.uploads`、`.upload-locks`、逐执行 `state.json` 的发现须只读失败关闭,现存未交付事实由使用者确认处置。真实云账号、EIP、线路、拨号、生产部署和共享数据操作分别需要明确授权。
@@ -91,6 +91,7 @@
- `call.execute` 只带获批 `task_id/callee`,调用线路、主叫、AI 和时限由该任务快照固定;`task.control` 的 start/pause/resume/stop 无旧 CAS/版本字段,控制回 task/action/status 处理结果,stop 不可恢复。任务启动/重启完整读取列表,运行中不定时轮询任务列表;新建任务由 start 读取任务配置和租户额度,暂停后修改的任务由 resume 重读;全局 AI 服务商列表每次启动只读取一次,本进程全部任务复用,变更须重启后才生效;没有 edit 事件。启动时全量读取并核验 SIP,运行中只由 `sip.config` 通知触发全量 SIP 读取,无常规定时 SIP 轮询;任务 start/resume 使用已生效 SIP 快照,不自行拉取或向 Agent 核验 SIP。SIP 修订变化待旧呼叫结束且 Agent 已加载后,仅在本地重新绑定任务快照,不重读任务列表;待处理期间新准入关闭。发现分页同快照先全部校验后提交,MQ 控制持久状态高于偶发 HTTP 状态;冲突关准入、resume 须重新核验。历史命令不因消息年龄过期,但实际呼出前仍检查任务/白名单/时段/授权/额度和有效通话上限;任务结束不删未确认结果、恢复、幂等或未知占用。
- 独立 Dispatcher 的 SQLite 是任务、额度、inbox/outbox 的权威数据;Agent 无业务数据库,录音、执行与上传恢复只写受控私有文件。额度包含未知占用,新 boot/租约到期不得自动清除未知执行;明确 Agent 在拨号前拒绝时须持久拒绝并释放,已接纳但证实 ARI originate 从未提交的失败由原 Agent 经正式终结回执释放,RPC 交付未知时仍占用。2026-10-04 修复版 `d2c4a99` 已安装并通过非呼出时段主机诊断,新隔离测试租户额度 2/revision 2 已启用并由 Dispatcher 只读拉取;原快照保留;该条旧执行仅按前述经使用者授权的人工核实记录解除 Dispatcher 占用,绝非新 boot 或超时自动清除未知执行。仅 Agent 用机器可读标记证实本次未发起的拒绝可自动释放;旧执行的同错误码不算证明。不实现双活数据库、自动跨机热备、多 D 共享额度或第二租户公平。本轮不借本机 D1/D2 隔离夹具宣称多 D 运行。不得建立旧表/旧消息/旧 HTTP 执行兼容通道。
- Dispatcher↔Agent 复用 Unary gRPC 和受控 Endpoint;Agent 预绑定 D UUID 与服务端证书指纹,激活/会话代际、peer mTLS/SAN/SNI 和已签发期限须核对,新 boot 不清未知占用。Agent 不自行向 SaaS 取任务/AI/OSS 授权;Dispatcher 只用已经核验的 Agent `GetLoadedSIP` revision 开执行准入。本机 Mock 的加载回报不证明 Asterisk 已实际加载;仅隔离 SIP-only Agent 在配置原子写入、PJSIP reload 和运行态 endpoint/AOR/UDP transport 一致后持久标记 revision,每次加载查询重新核验。只支持明确的 UDP、IP/none 鉴权、无需 REGISTER 的 IPv4/PCMA 线路;未知字段和其他传输/鉴权/注册方式拒绝,不热更静态 transport。SIP 配置的唯一编辑/审批面仍是 management。
- 非生产真实 Agent 的 Asterisk `res_hep`/`res_hep_pjsip` 仅镜像至本机 UDP:在 ARI Dial 前读取本次 SIP Call-ID 并绑定执行,按 Call-ID 和原始 INVITE transaction 只采集真实最终响应的状态码、状态行与完整 `raw`;丢失/无法关联以 `sip_capture_error` 显式报告,不从 ARI、号码或挂断原因推测。镜像缺失不阻止已证实终结的额度释放;未经确认的占用仍保留。配置及回滚见 [`deploys/cell/README.md`](deploys/cell/README.md),不得将完整 SIP 报文写入普通日志、提交或聊天;本地测试通过不等于测试机已部署 HEP 或真实接通。
- AI 使用任务内不可变授权快照:仅经获批准百炼/火山 ASR、OpenAI 兼容 LLM、百炼 TTS(`qwen3-tts-flash`/`Cherry`/`Chinese`)能表达的参数进入每通话实例;ASR-only 不启动 LLM/TTS,完整 AI 不借旧语音测试的授权或参数。只有最终用户 ASR 文本的明确字面关键词可触发拒联/挂断;不由 SDK 默认值、环境、CLI、metadata 或宽松 Schema 改写业务参数,不因 SDK 重试产生第二次发起/收费或重播。日志只存脱敏版本/摘要/计数,不存密钥、prompt、完整对话或音频。
- **私有配置位置(本机路径相对本仓库根目录,只读,绝不提交)**:`.local/provider-ai.env` 是 `0600` 的 `KEY=VALUE` 文件;字段名为 `BAILIAN_API_KEY`、`BAILIAN_BASE_URL`、`BAILIAN_WSS_BASE_URL`、`BAILIAN_TTS_VOICE`、`VOLC_ASR_APP_NAME`、`VOLC_ASR_APP_KEY`、`VOLCENGINE_ACCESS_KEY`、`VOLCENGINE_SECRET_KEY`、`VOLCENGINE_REGION`、`VOLCENGINE_DISABLE_SSL`。根目录 `aliyun-oss.env` 也是 `0600`,**不是 shell env 文件**;它以冒号分隔,字段名准确为 `bucket`、`Endpoint`、`Region`,以及 `RAM` 下的 `username`、`accessKeyId`、`accessKeySecret`(大小写须保持原样)。测试机 `rogee` 用户的现行 ARI 文件位于 `~/.config/go-sip-asterisk/{ari.conf,http.conf,ari-secret}`,不是旧 `.local/asterisk-*/ari.conf`;访问测试机前先核对已登记的 SSH 主机指纹,不展示 `ari-secret`。
- **下次安全读取步骤**:先确认工作目录是本仓库,用 `stat` 仅检查本机两份文件是否存在、所有者与权限 `0600`;不满足即停止。按各自格式在受限本机进程中解析所需字段到内存,不执行 `source`、不打印全文/字段值、不写临时明文副本,不把密钥、签名 URL、音频或完整对话带入聊天、日志、提交及长期证据。AI 的历史文件只可作为**获准凭据来源**,模型/voice/速度等仍由当前获批的 task/providers 快照固定,不能用环境变量覆盖。OSS 历史文件也不能直接传给 `DISPATCHER_OSS_CONFIG_FILE`:该运行配置要求私有 JSON、`dispatcher_id` 和 `oss` 字段,并以环境变量**名称引用**密钥;需按现行合同构造并核验授权后才能使用。普通构建和测试不读取这些私有文件;真实服务测试必须显式启用对应 opt-in 并受现行门禁约束。
+17 -2
View File
@@ -26,8 +26,23 @@ ARI and RTP configuration must be supplied separately. For the isolated
nonproduction user service only, `configure-asterisk-user-ari.sh` creates
private `ari.conf`, loopback-only `http.conf` and an owner-only `ari-secret`
without printing credentials, overwriting existing files or restarting the
service. Restart the user service only after separately verifying zero active
calls, then read back ARI HTTP and both `enabled`/`active` state. Do not treat
service. For the same nonproduction user-level service, enable the native
HEP SIP mirror with `configure-asterisk-user-hep.sh 127.0.0.1:<port>` after
verifying the Agent's `AGENT_HEP_LISTEN_ADDR` uses that **same** loopback UDP
address and port. This one-time helper refuses existing `hep.conf` and does
not restart or overwrite Asterisk. Its config enables `res_hep` and
`res_hep_pjsip`, sets `uuid_type = call-id`, and uses no capture password.
The pinned native package contains both modules; no Homer server is needed.
Only after separately verifying zero active calls, restart the user service,
check `module show like res_hep` for both modules, read back ARI HTTP and both
`enabled`/`active` state, and check that the Agent's UDP listener is bound.
A missing listener prevents Agent startup; an absent or broken SIP mirror is
reported as `sip_capture_error`, never guessed as a SIP status. To roll back,
first stop new admission and verify zero active calls, stop the Agent, remove
only the explicitly installed private `hep.conf`, restart Asterisk and verify
its modules/status, then restore the previously approved Agent version and
config. Do not clear existing call occupancy, outbox, or Agent recovery files.
Do not treat
this local test setup as a management-approved production configuration.
The bundled stage has no live SIP trunk or dialing authorization; verify loaded endpoints and contacts
before any call. Do not substitute another Asterisk version or a container image.
@@ -0,0 +1,15 @@
#!/usr/bin/env bash
# Install only the local Asterisk HEP mirror config; restart separately after confirming zero calls.
set -euo pipefail
[[ $# == 1 && $1 =~ ^127\.0\.0\.1:([1-9][0-9]{0,4})$ ]] || { echo 'usage: configure-asterisk-user-hep.sh 127.0.0.1:<port>' >&2; exit 2; }
port=${BASH_REMATCH[1]}
(( 10#$port <= 65535 )) || { echo 'invalid HEP port' >&2; exit 2; }
config="$HOME/.config/go-sip-asterisk"
[[ -d $config && -r $config/asterisk.conf ]] || { echo 'user Asterisk config missing; fail-closed' >&2; exit 1; }
[[ ! -e $config/hep.conf && ! -L $config/hep.conf ]] || { echo 'HEP config already exists; refuse to overwrite' >&2; exit 1; }
umask 077
stage=$(mktemp "$config/.hep.XXXXXXXX")
trap 'rm -f -- "$stage"' EXIT
printf '[general]\nenabled = yes\ncapture_address = %s\ncapture_id = 1234\nuuid_type = call-id\n' "$1" >"$stage"
ln -- "$stage" "$config/hep.conf" || { echo 'cannot create HEP config without overwriting another file' >&2; exit 1; }
echo 'Asterisk local HEP mirror configured; service not restarted'
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
set -euo pipefail
script="$(dirname "$0")/configure-asterisk-user-hep.sh"
root=$(mktemp -d)
trap 'rm -rf -- "$root"' EXIT
mkdir -p "$root/.config/go-sip-asterisk"
printf '[directories]\n' >"$root/.config/go-sip-asterisk/asterisk.conf"
for addr in 0.0.0.0:19060 localhost:19060 127.0.0.1:0 127.0.0.1:abc; do
if HOME="$root" bash "$script" "$addr" >/dev/null 2>&1; then
echo "unexpected HEP address admitted: $addr" >&2; exit 1
fi
done
[[ ! -e "$root/.config/go-sip-asterisk/hep.conf" ]]
HOME="$root" bash "$script" 127.0.0.1:19060
conf="$root/.config/go-sip-asterisk/hep.conf"
grep -qx 'enabled = yes' "$conf"
grep -qx 'capture_address = 127.0.0.1:19060' "$conf"
grep -qx 'uuid_type = call-id' "$conf"
[[ $(stat -c '%a' "$conf") == 600 ]]
if HOME="$root" bash "$script" 127.0.0.1:19060 >/dev/null 2>&1; then
echo 'existing HEP config was overwritten' >&2; exit 1
fi
printf 'HEP config: passed\n'
+1 -1
View File
@@ -1,6 +1,6 @@
# Physical production deployment
This is the **target host layout**, not an approved deployment of the current binary. The current business commands are isolated Mock-only and reject mixed/real before opening resources; the local release manifest has `production_approval=false`. Neither the steps below nor a local package/check authorize real services or calls. Native Asterisk loading and required non-production diagnostics still need separate evidence.
This is the **target host layout**, not an approved production deployment of the current binary. The explicit `nonprod-real` Agent/Dispatcher path requires separately approved host, task, evidence, credentials and calling window; mixed/production are not thereby approved. The local release manifest has `production_approval=false`. Neither the steps below nor a local package/check authorize real calls. Native Asterisk loading and required non-production diagnostics need separate evidence.
Debian 12 amd64 is supported only for explicitly marked non-production test hosts.
Build the native Asterisk archive **on Debian 12** with `NONPROD=1`; the
+13
View File
@@ -50,6 +50,19 @@ the user journal. Missing settings or status fail closed; it neither skips
the installed-artifact checksum/capture requirements nor proves reboot
persistence when lingering is disabled. The default remains system scope.
For nonproduction real calls, additionally configure the on-host Asterisk HEP
mirror as described in [`cell/README.md`](../cell/README.md), with
`AGENT_HEP_LISTEN_ADDR=127.0.0.1:<port>` matching `capture_address` in the
private `hep.conf`. Confirm `res_hep` and `res_hep_pjsip` are running and the
Agent's UDP listener is bound before any explicitly authorized trial. The
capture-first wrapper remains mandatory; HEP is not a replacement for pcap,
PJSIP logger, call-window checks, or caller approval. Verify the same
`call.execute.result` is present in Dispatcher outbox and the SaaS Mock's
restricted result store; inspect full `raw` only there and do not place it in
logs, source, chat, or long-term evidence. A missing mirror produces a clear
`sip_capture_error` but does not undo a proven call end or release. This setup
by itself neither places a real call nor establishes that one was answered.
The offline OSS environment file is a fixture for isolated tests only. It
contains no real credentials or production approval. The former
`ai-dental-meiba-v1.json` is archived at