feat: complete phase2 baseline cdr quality rbac
This commit is contained in:
+290
-4
@@ -4,10 +4,11 @@
|
||||
|
||||
## 当前状态
|
||||
|
||||
- 当前任务:需求修改/二期变更:号码库第 6、7 步本地实现并提交 Git
|
||||
- 总体状态:S30 已完成;本地 KVM 开发环境 V2 闭环原冻结 release 为 `s28-v2-20260621220924`,当前 B release 仍为 `s33-active-calls-20260623094000`,已在该 release 上覆盖发布 s41 用户/角色删除小改;A `/etc/opensips/opensips.cfg` 已将 `fr_inv_timeout` 从 30 临时调为 95 并重启;T 已新增 `/opt/lisglosips-s40/lisglosips-s40-virtual-calls.py` 并启动 10 路虚拟呼叫场景;号码库第 1-7 步已完成本地代码基线,尚未发布到 B/A、尚未执行 MySQL migration、尚未导入真实 80 万号段;阿里云迁移前需按 S30 Runbook 重新演练
|
||||
- 最后更新:2026-06-24 11:41 +08:00
|
||||
- 当前阻塞:无。遗留风险为 Redis 恢复后 OpenSIPS 热路径可能需要重启 `opensips` 才恢复,已纳入 S30 Runbook;本次发现并补齐 B `config-publisher.env`,当前 `lisglosips@config-publisher` 已 active。
|
||||
- 当前任务:需求修改/二期变更:权限驱动导航和按钮
|
||||
- 本次变更摘要:已完成登录/刷新响应透出 `user.permissions`,前端新增统一 `can(permission)` 权限封装;菜单按页面权限裁剪,核心真实 API 页面操作按钮按 manage/play 权限裁剪,无权限页面提供明确提示,并避免无权限启动时批量请求导致 403。
|
||||
- 总体状态:S30 已完成;本地 KVM 开发环境 V2 闭环原冻结 release 为 `s28-v2-20260621220924`;B 已切换并冻结到 `s42-phase2-business-prefix-20260624140000` 作为二期业务前缀小样本联调基线,MySQL 已补齐号码库 migration `20260624095000_number_library` 与业务前缀 migration `20260624121000_business_prefix_gateway_rewrite`,Prisma status 为 up to date,config-publisher 当前 active 配置版本为 `1782286812696`,上一版本为 `1782286145681`,B preflight 直接执行通过;A 已加载业务前缀 Lua SHA `0b7ee595cdcad2f38a670dd8ff3553387820039e`,OpenSIPS 配置 SHA-256 为 `ae1544e9a39d2db114e6981babac042c2ab6d399d59ba597a52b85d597aa5aa5`,最终 `dlg_list` 已清空;T 已完成冻结验收实呼 `s28-1782288889943-ckv83lce@lisglosips-t`,B CDR 入库并计费成功;当前仍未导入真实 80 万手机号段;阿里云迁移前需按 S30 Runbook 重新演练
|
||||
- 最后更新:2026-06-24 17:50 +08:00
|
||||
- 当前阻塞:无阻塞。遗留问题:真实 80 万手机号段尚未导入;OpenSIPS dialog 在测试呼叫结束后可能残留,冻结前已通过重启清空,后续应单独分析 dialog 生命周期和 `dlg_end_dlg Operation failed` 根因;本次权限裁剪使用本地 mock API 完成只读账号浏览器冒烟,真实 B 服务器浏览器登录态逐页按钮、真实录音文件播放和 Nginx/X-Accel 链路仍需后续人工复测。
|
||||
- 当前环境:A/B/T 为本地 KVM 开发服务器,通过 Tailscale 联调;开发完成后再迁移阿里云
|
||||
- 私密访问资料:`.codex-private/SERVER_ACCESS.md`,只在实际连接时读取,禁止回显
|
||||
|
||||
@@ -89,6 +90,291 @@
|
||||
|
||||
## 交接记录
|
||||
|
||||
### 2026-06-24 17:50 - 需求修改/二期变更:权限驱动导航和按钮
|
||||
|
||||
- 状态:已完成
|
||||
- 操作服务器:本地
|
||||
- 完成内容:
|
||||
- 后端登录/刷新响应新增 `user.permissions`,从用户启用角色的 `role_permissions` 汇总去重并排序后返回;保留原 `roles` 字段。
|
||||
- 前端新增 `apps/web/src/permissions.js`,提供页面权限表、`permissionSet`、`can`、`canAll`、`canAny`。
|
||||
- `App.jsx` 根据权限裁剪菜单;启动和手动刷新时只请求当前用户有权限的全局 API,避免无权限接口产生批量 403;无权限页面显示明确“无权限访问”提示。
|
||||
- 核心页面按钮按后端真实权限 key 裁剪:当前通话挂断、客户/供应商管理、充值、客户网关、业务前缀、落地网关、落地线路组、号码库导入、话单录音播放、质检录音播放/评分/抽检规则、用户管理、角色管理。
|
||||
- 修正角色权限页 dev fixture 的权限 key,使其与后端 `RequirePermissions` 使用的真实 key 保持一致。
|
||||
- 修改文件:`apps/api/src/modules/auth/auth.types.ts`、`apps/api/src/modules/auth/auth.repository.ts`、`apps/api/src/modules/auth/auth.service.ts`、`apps/api/src/modules/auth/auth.service.spec.ts`、`apps/api/src/modules/auth/auth.e2e.spec.ts`、`apps/web/src/permissions.js`、`apps/web/src/App.jsx`、`apps/web/src/fixtures/devFixtures.js`、`apps/web/src/pages/*.jsx`、`IMPLEMENTATION_STATUS.md`
|
||||
- 安装软件及固定版本:未安装新软件。
|
||||
- 执行的关键命令:`corepack pnpm@10.33.0 typecheck`、`corepack pnpm@10.33.0 lint`、`corepack pnpm@10.33.0 build`、`corepack pnpm@10.33.0 exec vitest run apps/api/src/modules/auth/auth.service.spec.ts apps/api/src/modules/auth/auth.e2e.spec.ts --hookTimeout=60000 --maxWorkers=1`、`corepack pnpm@10.33.0 exec vitest run --hookTimeout=60000 --maxWorkers=1`、`corepack pnpm@10.33.0 --filter @lisglosips/web dev -- --host 127.0.0.1`
|
||||
- 验证结果:
|
||||
- typecheck/lint/build 均通过。
|
||||
- Auth 定向测试 2 files / 6 tests 通过,确认 login/refresh 均返回 permissions。
|
||||
- 全量 Vitest 25 files / 88 tests 通过。
|
||||
- 使用本地临时 mock API 与 in-app Browser 验证只读账号仅含 `dashboard.view/customers.view`:侧边栏只显示“概览 Dashboard”“客户管理”;“供应商管理”“质检中心”等菜单不可见;客户页可查看客户列表,但无“新增客户”“编辑”“充值”“删除”按钮;无 Vite overlay,无应用 console error/warn。
|
||||
- 回滚方式:回滚上述后端 auth 文件、前端权限/页面文件和本状态文件即可;本次未修改 Prisma schema、未执行数据库迁移、未连服务器、未重启服务。
|
||||
- 未解决问题:当前按钮级裁剪覆盖真实 API 核心页面;费率与计费、SIP 运维、监控告警、系统设置仍属于待设计/演示页面,后续接真实 API 时需继续补权限 key 和按钮裁剪。真实 B 登录态逐页按钮仍需后续人工复测。
|
||||
- 下一任务:等待用户指定。
|
||||
|
||||
### 2026-06-24 17:30 - 需求修改/二期变更:前端拆分与信息架构整理
|
||||
|
||||
- 状态:已完成
|
||||
- 操作服务器:本地
|
||||
- 完成内容:
|
||||
- 将 `App.jsx` 中的页面组件拆到 `apps/web/src/pages/`:`CdrPage.jsx`、`QualityPage.jsx`、`ActiveCallsPage.jsx`、`CustomersPage.jsx`、`CustomerGatewaysPage.jsx`、`VendorsPage.jsx`、`VendorGatewaysPage.jsx`、`VendorLineGroupsPage.jsx`、`BusinessPrefixesPage.jsx`、`NumberLibraryPage.jsx`、`RechargeRecordsPage.jsx`、`RoutesPage.jsx`、`BillingPage.jsx`、`SipOpsPage.jsx`、`MonitoringPage.jsx`、`SettingsPage.jsx`、`UsersPage.jsx`、`RolesPage.jsx`、`OperationLogsPage.jsx`。
|
||||
- 将页面共享布局组件拆到 `apps/web/src/components/layout.jsx`,包含 `Icon`、`PageTitle`、`Panel`、`ApiNotice`、`Drawer`、`Modal`、`SimpleTable`、`KeyValue` 等。
|
||||
- 将格式化和 API 归一化函数拆到 `apps/web/src/utils/formatters.js`,供 App 数据刷新和页面组件复用。
|
||||
- 将残留静态演示/mock 数据集中到 `apps/web/src/fixtures/devFixtures.js`,避免继续散落在 `App.jsx`;未把这些旧 fixture 接入生产 API 流程。
|
||||
- `App.jsx` 保留应用入口、登录、导航、全局 API 刷新与页面 props 分发,体积从约 237 KB 降到约 20 KB。
|
||||
- 修改文件:`apps/web/src/App.jsx`、`apps/web/src/components/layout.jsx`、`apps/web/src/utils/formatters.js`、`apps/web/src/fixtures/devFixtures.js`、`apps/web/src/pages/*.jsx`、`IMPLEMENTATION_STATUS.md`
|
||||
- 安装软件及固定版本:未安装新软件。
|
||||
- 执行的关键命令:`corepack pnpm@10.33.0 lint`、`corepack pnpm@10.33.0 typecheck`、`corepack pnpm@10.33.0 build`、`corepack pnpm@10.33.0 exec vitest run --hookTimeout=60000 --maxWorkers=1`、`corepack pnpm@10.33.0 --filter @lisglosips/web dev -- --host 127.0.0.1`
|
||||
- 验证结果:
|
||||
- lint/typecheck/build 均通过。
|
||||
- 全量 Vitest 25 files / 88 tests 通过。
|
||||
- 使用本地临时 mock API 与 in-app Browser 验证 `http://127.0.0.1:5173/`:登录后可切换“当前通话”“话单中心”“质检中心”“客户管理”,对应页面 `h1` 正确、root 正常挂载、无 Vite overlay、无应用 console error/warn。
|
||||
- 拆分过程中发现并修复两个运行时拆分问题:`App.jsx` 主壳补回 `Badge` 导入;`emptySamplingRuleForm` 从 `CdrPage.jsx` 挪回 `QualityPage.jsx`。
|
||||
- 回滚方式:回滚上述前端拆分文件和本状态文件即可;本次未修改 Prisma schema、未执行数据库迁移、未连服务器、未重启服务。
|
||||
- 未解决问题:`fixtures/devFixtures.js` 仍承载费率、路由、监控、系统设置等未接真实 API 的旧演示数据;后续应按页面逐步接真实 API 或加 dev-only 开关彻底隔离。真实 B 服务器浏览器登录态逐页按钮仍需后续人工复测。
|
||||
- 下一任务:等待用户指定。
|
||||
|
||||
### 2026-06-24 17:10 - 需求修改/二期变更:质检中心接真实 API
|
||||
|
||||
- 状态:已完成
|
||||
- 操作服务器:本地
|
||||
- 完成内容:
|
||||
- 录音列表从静态数据切换为 `api.recordings()`,接入 `GET /recordings`,支持待质检/已质检/全部筛选、条数筛选、加载中、错误提示与空状态。
|
||||
- 录音详情接入 `GET /recordings/:id`,详情抽屉展示客户、被叫、业务、录音时长、抽样状态、命中规则与既有质检结果。
|
||||
- 录音播放接入 `GET /recordings/:id/play`,以 blob URL 驱动页面内 `<audio controls>`,支持播放/暂停、进度、播放失败提示和自动播放下一条。
|
||||
- 质检评分保存接入 `PUT /recordings/:id/review`,提交结果、评分、问题标签和备注;保存后刷新录音列表与当前详情,避免“看似保存但未刷新”。
|
||||
- 抽检规则接入 `/quality/rules`,支持新增、编辑、启用、禁用、删除;规则表单使用真实客户与落地线路组选项,并支持全部客户/全部线路。
|
||||
- 修改文件:`apps/web/src/App.jsx`、`apps/web/src/api.js`、`IMPLEMENTATION_STATUS.md`
|
||||
- 安装软件及固定版本:未安装新软件。
|
||||
- 执行的关键命令:`corepack pnpm@10.33.0 lint`、`corepack pnpm@10.33.0 typecheck`、`corepack pnpm@10.33.0 build`、`corepack pnpm@10.33.0 exec vitest run --hookTimeout=60000 --maxWorkers=1`、`corepack pnpm@10.33.0 --filter @lisglosips/web dev -- --host 127.0.0.1`
|
||||
- 验证结果:
|
||||
- lint/typecheck/build 均通过。
|
||||
- 全量 Vitest 25 files / 88 tests 通过。
|
||||
- 使用本地临时 mock API 与 in-app Browser 验证质检中心主流程:进入质检中心、打开录音详情、读取 `/recordings/:id/play` blob、填写标签/备注/评分并保存,页面出现保存反馈且刷新详情与列表;无应用 console error/warn。
|
||||
- 定向验证录音播放:详情抽屉内 `<audio>` 存在,`src` 为 blob URL,抽样状态与质检控件可见。
|
||||
- 定向验证抽检规则 CRUD:新增 `QA 保留验证规则` 成功,禁用后状态刷新为禁用,删除后列表移除;无应用 console error/warn。
|
||||
- 回滚方式:回滚上述 2 个前端文件和本状态文件即可;本次未修改 Prisma schema、未执行数据库迁移、未连服务器、未重启服务。
|
||||
- 未解决问题:真实 B 服务器浏览器登录态逐页按钮仍需后续人工复测;真实录音文件的播放、Range/Nginx X-Accel 链路仍需在 B 上用实际文件复测;话单信令入口仍是 CDR payload/Call-ID 索引展示,未接独立 HEP/SIP trace 检索接口;CSV 导出仍未实现。
|
||||
- 下一任务:等待用户指定。
|
||||
|
||||
### 2026-06-24 16:55 - 需求修改/二期变更:话单中心前端接真实 API
|
||||
|
||||
- 状态:已完成
|
||||
- 操作服务器:本地
|
||||
- 完成内容:
|
||||
- 替换话单中心静态 `cdrs/ratedCdrs` 数据,页面改为调用 `api.cdrs()` 查询真实列表,并调用 `api.cdrDetail()` 按需读取详情。
|
||||
- 新增话单查询条件:主叫、被叫、客户网关、落地网关、地级市代码、运营商、开始时间、结束时间、每页条数;查询时重置到第一页。
|
||||
- 新增分页状态:展示当前范围、总数、上一页、下一页,并使用后端 `meta.total/take/skip/hasMore`。
|
||||
- 详情抽屉改为真实契约展示,包含链路信息、关联对象、计费结果、时间轴、录音与信令;信令入口展示 Call-ID、eventId、网关、配置版本和 payload 索引。
|
||||
- 新增录音播放接线:`api.recordingPlayback()` 拉取 `/recordings/:id/play` blob,详情抽屉内使用 `<audio controls>` 播放;无录音或读取失败时给出禁用/错误状态。
|
||||
- 保留导出 CSV 入口但禁用,避免误导为已实现导出。
|
||||
- 修改文件:`apps/web/src/App.jsx`、`apps/web/src/api.js`、`apps/web/src/styles.css`、`IMPLEMENTATION_STATUS.md`
|
||||
- 安装软件及固定版本:未安装新软件。
|
||||
- 执行的关键命令:`corepack pnpm@10.33.0 lint`、`corepack pnpm@10.33.0 build`、`corepack pnpm@10.33.0 typecheck`、`corepack pnpm@10.33.0 exec vitest run --hookTimeout=60000 --maxWorkers=1`、`corepack pnpm@10.33.0 --filter @lisglosips/web dev -- --host 127.0.0.1`
|
||||
- 验证结果:
|
||||
- lint/typecheck/build 均通过。
|
||||
- 全量 Vitest 25 files / 88 tests 通过。
|
||||
- in-app Browser 验证 `http://127.0.0.1:5173/` 应用壳可加载,标题为 `LisgloSIPS - 聆界SIP管理平台`,无 Vite overlay,无 console error/warn。
|
||||
- 使用本地临时 mock API 验证登录后话单中心:查询主叫 `1001` 后列表过滤为 1 条;详情抽屉打开成功;计费结果、信令索引、录音 `<audio>` 控件可见;查询不存在主叫 `999999` 后出现空状态且总数为 0;console error/warn 为 0。
|
||||
- 回滚方式:回滚上述 3 个前端文件和本状态文件即可;本次未修改 Prisma schema、未执行数据库迁移、未连服务器、未重启服务。
|
||||
- 未解决问题:真实 B 服务器浏览器登录态逐页按钮仍需后续人工复测;信令入口当前展示 CDR payload/Call-ID 索引,未接独立 HEP/SIP trace 检索接口;CSV 导出仍未实现。
|
||||
- 下一任务:等待用户指定。
|
||||
|
||||
### 2026-06-24 16:28 - 需求修改/二期变更:CDR/话单后端 API 补强
|
||||
|
||||
- 状态:已完成
|
||||
- 操作服务器:本地
|
||||
- 完成内容:
|
||||
- 在现有 `CdrsModule` 上补强话单后端能力,保持路由 `GET /cdrs` 与 `GET /cdrs/:id` 不变。
|
||||
- 列表筛选新增 `startedFrom/startedTo`,并兼容 `from/to`、`startTime/endTime`;保留主叫、被叫、客户网关、落地网关、归属地城市、运营商、`take/skip` 分页。
|
||||
- 列表返回新增 `meta: { total, take, skip, hasMore }`,并补充业务前缀、原始被叫、落地主被叫、录音摘要字段。
|
||||
- 详情返回整理为前端可直接展示的稳定契约,关联 raw CDR、rated CDR、recording、customer、vendor、customer gateway、vendor gateway、line group、business prefix、customer gateway policy,并保留 payload、receivedAt、createdAt。
|
||||
- 修改文件:`apps/api/src/modules/cdrs/cdrs.repository.ts`、`apps/api/src/modules/cdrs/cdrs.service.ts`、`apps/api/src/modules/cdrs/cdrs.service.spec.ts`、`IMPLEMENTATION_STATUS.md`
|
||||
- 安装软件及固定版本:未安装新软件。
|
||||
- 执行的关键命令:`corepack pnpm@10.33.0 exec vitest run apps/api/src/modules/cdrs/cdrs.service.spec.ts --hookTimeout=60000`、`corepack pnpm@10.33.0 typecheck`、`corepack pnpm@10.33.0 lint`、`corepack pnpm@10.33.0 build`、`corepack pnpm@10.33.0 exec vitest run --hookTimeout=60000 --maxWorkers=1`
|
||||
- 验证结果:CDR service spec 3 tests 通过;typecheck/lint/build 均通过;全量 Vitest 25 files / 88 tests 通过。
|
||||
- 回滚方式:回滚上述 3 个 CDR 模块文件和本状态文件即可;本次未修改 Prisma schema、未执行数据库迁移、未连服务器、未重启服务。
|
||||
- 未解决问题:前端话单列表/详情页尚未接入新契约;如未来要按客户、供应商、落地线路组、SIP 状态码等更多条件筛选,可在当前 `CdrQuery` 上继续扩展。
|
||||
- 下一任务:等待用户指定。
|
||||
|
||||
### 2026-06-24 16:16 - 需求修改/二期变更:S42 二期业务前缀基线冻结
|
||||
|
||||
- 状态:已完成
|
||||
- 操作服务器:A、B、T、本地
|
||||
- 完成内容:基于当前文档、代码和服务器状态对 `s42-phase2-business-prefix-20260624140000` 执行冻结前收口。补齐 B 当前 release 中 `infra/server-b/s30/lisglosips-release-preflight.sh` 执行权限为 `0755`,直接执行 preflight 通过;确认 B current、API/CDR/Recording/Config Publisher/Nginx/MySQL/Redis/HEP/Prometheus/Grafana active,API ready 正常,Prisma 4 条 migration up to date,Redis active/previous 配置版本为 `1782286812696`/`1782286145681`,最新 MySQL/Redis 备份 `/data/backups/*/20260624T055810Z` SHA256 校验通过。抽样确认 Redis `stream:cdr_deadletter` 26 条为早期修复前历史死信,冻结验收呼叫未新增 deadletter。A 侧历史 4 条 dialog 使用 `dlg_end_dlg` 仍返回 `Operation failed` 且未消失,已先执行 `opensips -C` 再重启 OpenSIPS 清空;冻结验收实呼后新增 1 条测试 dialog 残留,再次语法检查并重启 OpenSIPS,最终 `dlg_list` 为空。新增正式冻结报告 `docs/S42_PHASE2_FREEZE_REPORT.md`。
|
||||
- 修改文件:`docs/S42_PHASE2_FREEZE_REPORT.md`、`IMPLEMENTATION_STATUS.md`;B 当前 release 脚本权限已修正为 `0755`。
|
||||
- 安装软件及固定版本:未安装新软件。
|
||||
- 执行的关键命令:本地 `corepack pnpm@10.33.0 typecheck`、`corepack pnpm@10.33.0 lint`、`corepack pnpm@10.33.0 build`、`corepack pnpm@10.33.0 exec vitest run --hookTimeout=60000 --maxWorkers=1`;B `lisglosips-release-preflight.sh`、Prisma migrate status、Redis `MGET cfg:active_version cfg:previous_version`、备份 `sha256sum -c SHA256SUMS`、deadletter 抽样;A `opensips -C -f /etc/opensips/opensips.cfg`、`systemctl restart opensips`、`lisglosips-call-control dlg_list`;T `python3 /opt/lisglosips-s28/lisglosips-s28-sip.py invite --host 100.90.90.90 --port 15060 --bind-host 100.93.185.30 --contact-host 100.93.185.30 --caller s28-ip-1001 --callee 13800138000 --hold 3 --timeout 20`。
|
||||
- 验证结果:本地 typecheck/lint/build 均通过;全量 Vitest 在 `--hookTimeout=60000` 下 25 个测试文件、87 条测试通过;B preflight 直接执行通过,API ready 正常,Prisma up to date,最新 MySQL/Redis 备份哈希通过;T 冻结验收实呼 Call-ID `s28-1782288889943-ckv83lce@lisglosips-t` 收到 `100 Giving it a try`、`200 OK`、BYE `200 OK`;B raw CDR `raw_d5732df32b8d496686512870fb087232` 入库,`caller=s28-ip-1001`、`callee=13800138000`、`raw_callee=13800138000`、`business_prefix=NULL`、`landing_caller=s28-ip-1001`、`landing_callee=13800138000`、`sip_code=200`、`rating_status=RATED`,客户费用和供应商成本均为 `0.012000`;CDR Worker 日志 `processed=1 deadlettered=0`;A 最终 `dlg_list` 为空。
|
||||
- 回滚方式:B 应用可执行 `/opt/lisglosips/current/infra/server-b/s30/lisglosips-release-rollback.sh /opt/lisglosips/releases/s33-active-calls-20260623094000`;Redis 可从当前 `1782286812696` 切回上一版本 `1782286145681`,不删除 Stream/deadletter;A 可从最近 `/var/backups/lisglosips-phase2/` 备份恢复 `opensips.cfg` 与 `lisglosips_hotpath.lua`,先 `opensips -C` 再重启;数据库如必须恢复,使用 `/data/backups/mysql/20260624T055810Z` 先在隔离库验证后进入维护窗口处理。
|
||||
- 未解决问题:真实 80 万手机号段尚未导入;浏览器登录态逐页按钮未做完整人工复测;OpenSIPS dialog 在测试呼叫结束后可能残留,冻结前已通过重启清空,后续应单独分析 dialog 生命周期和 `dlg_end_dlg Operation failed` 根因;当前仍为本地 KVM/Tailscale 冻结,不进入阿里云生产迁移。
|
||||
|
||||
### 2026-06-24 15:42 - 需求修改/二期变更:业务前缀重构第 10 步 A/B/T 端到端验收
|
||||
|
||||
- 状态:已完成
|
||||
- 操作服务器:A、B、T、本地
|
||||
- 完成内容:复核 B 当前 release `/opt/lisglosips/releases/s42-phase2-business-prefix-20260624140000`,A OpenSIPS 与 Redis AUTH 代理 active,热路径 Lua SHA `0b7ee595cdcad2f38a670dd8ff3553387820039e`,T UAS `100.93.185.30:50620` 监听正常。临时写入 Step 10 验收数据:业务前缀 `671`、S28 客户网关业务前缀匹配、北京/移动号码段、S28 第一落地网关屏蔽北京、同线路组第二落地网关、落地被叫前缀 `88`、指定主叫 `02160010001`。发布临时配置版本 `1782286145681` 后从 T 发起组合实呼 `s28-1782286191063-ig215mpx@lisglosips-t`,A 热路径选择第二落地网关 `vgw_91379ef9dc254ab29039d4b77197`,B CDR 入库 `raw_callee=67113800138000`、`callee=13800138000`、`business_prefix=671`、`callee_city_code=110100`、`callee_operator=MOBILE`、`landing_caller=02160010001`、`landing_callee=8813800138000`、`rating_status=RATED`。随后通过 `/api/v2/active-calls` 验证当前通话列表包含 `callerIp` 与 `landingIp`,并通过 `/api/v2/active-calls/:id/hangup` 对 `bae.39c14471` 发起强制挂断,返回 `HANGUP_IN_PROGRESS` 且目标进入 state `5`。
|
||||
- 修改文件:`IMPLEMENTATION_STATUS.md`
|
||||
- 验证结果:B `lisglosips@api`、`lisglosips@cdr-worker`、`lisglosips@config-publisher` active;A `opensips`、`lisglosips-redis-auth-proxy` active;T UAS 监听正常;组合实呼 SIP `100/200/BYE 200`;A OpenSIPS 日志记录热路径 allow 与 CDR XADD;B CDR Worker `processed=1 deadlettered=0`;当前通话 API 返回 6 条 dialog 并包含呼叫方 IP/落地 IP;强制挂断 API 返回 `HANGUP_IN_PROGRESS`。
|
||||
- 回滚方式:已执行回滚 SQL:S28 客户网关 `callee_match_mode` 恢复 `ANY`,删除临时客户网关业务前缀绑定、临时线路组成员、屏蔽地区、指定主叫池、号码段和运营商规则;第二落地网关 `landing_callee_prefix` 恢复 `NULL`;临时业务前缀 `bp_p2e2e_671` 软删除以保留 CDR 引用;回滚配置已发布为 `1782286812696`,manifest 回到 `customerGatewayBusinessPrefixCount=0`、`callerRewriteCount=0`、`phoneSegmentCount=0`、`carrierPrefixRuleCount=0`、`blockedRegionCount=0`。
|
||||
- 未解决问题:A `dlg_list` 仍有历史测试 dialog 残留,包括旧 S28 呼叫;强制挂断 OpenSIPS MI 对部分 dialog 仍可能返回 `Operation failed` 但会推进终止态;本次验证使用 API 级当前通话/挂断,未在浏览器登录态逐页点击 Web 按钮;真实 80 万手机号段尚未导入。
|
||||
|
||||
### 2026-06-24 15:00 - 需求修改/二期变更:业务前缀重构第 9 步 A/B/T 验收续跑与 CDR 修复
|
||||
|
||||
- 状态:已完成第 9 步主链路验收;仍有历史 dialog 清理和 Web 登录态页面按钮复测遗留
|
||||
- 操作服务器:A、B、T、本地
|
||||
- 完成内容:按用户要求先 ping B,`100.90.90.91` 4 次 ping 0% 丢包,SSH 可达,B current 为 `s42-phase2-business-prefix-20260624140000`,API/CDR/Recording/Config Publisher 均 active。重新上传 A/B 候选 Lua/配置,发现直接 `redis-cli SCRIPT LOAD "$(cat file)"` 会丢失末尾换行导致 SHA 为 `e1a853...`,已改用 `redis-cli -x SCRIPT LOAD < file`,Redis 中确认 `SCRIPT EXISTS 0b7ee595cdcad2f38a670dd8ff3553387820039e` 返回 1。A 侧首次重启时误将 B 本机 `REDIS_URL` 写入 OpenSIPS,导致 cachedb 连接 `127.0.0.1:6379` 失败;根据 S20 Runbook 修正为 OpenSIPS cachedb URL `redis:s20://127.0.0.1:6380/`,通过 A 本地 `lisglosips-redis-auth-proxy` 连接 B Redis,重新 `opensips -C` 并重启 OpenSIPS,日志显示连接 `127.0.0.1:6380`,无新增 Redis connection refused。T 发起 S28 实呼 `s28-1782283559224-yo6iqlqg@lisglosips-t` 成功,但 B CDR Worker 将事件投 deadletter;定位为二期热路径写 `customer_gateway_policy_id=single_gateway` 占位值,而 `raw_cdrs.customer_gateway_policy_id` 仍有外键。修复 `apps/worker-cdr/src/rating.ts` 的 nullable ID 归一化,将 `single_gateway` 与 `no_policy_match` 一并转 `null`,补充单元测试,构建并仅重启 B `lisglosips@cdr-worker`。再次发起实呼 `s28-1782283796126-nx2488rc@lisglosips-t`,SIP 100/200/BYE 200 成功,A 日志显示 hotpath allow 和 CDR XADD,B CDR Worker `processed=1 deadlettered=0`,`raw_cdrs` 入库 `customer_gateway_policy_id=NULL`、`business_prefix_id=NULL`、`landing_caller=s28-ip-1001`、`landing_callee=13800138000`、`rating_status=RATED`。随后发起长呼 `s28-1782283960806-f6ct79b4@lisglosips-t` 验证当前通话/强制挂断控制面,A `dlg_list` 可见目标 dialog `03a.af0b33d6`,包含呼叫方 SDP/IP 与落地侧 SDP/IP;执行 `dlg_end_dlg 03a.af0b33d6` 返回 MI `Operation failed`,但目标 dialog 状态进入 `5` 且 `timeout=0`,二次检查目标 Call-ID/ID 已不可见,T 测试脚本收到平台侧 BYE 形式结束。该行为与 API 现有兼容逻辑一致:Operation failed 后若 dialog 消失则视为 `HANGUP_CONFIRMED`,若 state=5 则视为 `HANGUP_IN_PROGRESS`。
|
||||
- 修改文件:`apps/worker-cdr/src/rating.ts`、`apps/worker-cdr/src/rating.spec.ts`、`IMPLEMENTATION_STATUS.md`
|
||||
- 安装软件及固定版本:未安装新软件。
|
||||
- 执行的关键命令:`ping 100.90.90.91 -n 4`、B SSH 服务状态检查、B Redis `SCRIPT LOAD`/`SCRIPT EXISTS`、A `lisglosips-redis-load-hotpath`、A `opensips -C -f /etc/opensips/opensips.cfg`、A `systemctl restart opensips`、T `python3 /opt/lisglosips-s28/lisglosips-s28-sip.py invite`、A `/usr/local/sbin/lisglosips-call-control dlg_list`、A `/usr/local/sbin/lisglosips-call-control dlg_end_dlg 03a.af0b33d6`、B `raw_cdrs` 查询、`node_modules\.bin\vitest.cmd run apps/worker-cdr/src/rating.spec.ts`、`node_modules\.bin\tsc.cmd -p apps/worker-cdr/tsconfig.json`
|
||||
- 验证结果:B ping 0% 丢包,SSH 可达;A OpenSIPS 与 Redis proxy active;A OpenSIPS 新配置语法检查通过并重启成功,日志显示 cachedb 连接 `127.0.0.1:6380`;B API ready 正常,config-publisher 仍为 schemaVersion 2 配置版本 `1782282403866`;Worker 定向测试 4 条通过;CDR Worker 修复后实呼入库并计费,`deadlettered=0`;强制挂断控制面对目标 dialog 生效,目标二次检查不可见。
|
||||
- 回滚方式:A 可恢复 `/var/backups/lisglosips-phase2/20260624144208` 中的 `opensips.cfg` 与 `lisglosips_hotpath.lua` 后 `opensips -C` 并重启。B 可切回 `/opt/lisglosips/releases/s33-active-calls-20260623094000` 并重启 API/CDR/Recording/Config Publisher;数据库如需回滚,使用 `/data/backups/mysql/20260624T055810Z` 先在隔离环境验证。CDR Worker 单点修复可恢复上一 release 的 `apps/worker-cdr/dist` 并重启 `lisglosips@cdr-worker`。
|
||||
- 未解决问题:A `dlg_list` 仍显示几条历史 S28 测试 dialog 残留,需要单独清理或确认 dialog timeout;Web 页面级“当前通话”列表和按钮因缺少登录态未通过浏览器/API 直接复测,本次以底层 MI 和实呼验证为准;真实 80 万手机号段仍未导入,号码归属地为 UNKNOWN。
|
||||
- 下一任务:清理历史 dialog 后,在网页登录态下复测“当前通话”页面展示呼叫方 IP/落地 IP 与强制挂断按钮;随后按需导入真实号码库数据并做业务前缀命中场景测试。
|
||||
|
||||
### 2026-06-24 14:40 - 需求修改/二期变更:业务前缀重构第 9 步 B 侧发布与 A 侧发布阻塞
|
||||
|
||||
- 状态:部分完成;B 侧数据库 migration、release 切换、API/Worker 重启、Redis 配置发布和 preflight 已完成;A 侧 OpenSIPS 未重启到新热路径,A/B/T 实呼验收未完成;当前因 B 再次不可达阻塞
|
||||
- 操作服务器:B、A、本地;T 未执行实呼
|
||||
- 完成内容:B 开机恢复后完成 S30 备份,MySQL 备份 `/data/backups/mysql/20260624T055810Z` 与 Redis 备份 `/data/backups/redis/20260624T055810Z` 哈希校验通过。创建 B 新 release `/opt/lisglosips/releases/s42-phase2-business-prefix-20260624140000`,从旧 current 复制基底并覆盖本地构建产物、Prisma schema/migration、业务前缀模块、迁移脚本与 Web dist。执行 Prisma generate 后,发现不能用应用账号跑 DDL,改用 `/etc/lisglosips/secrets/mysql-migrate.env` 迁移账号。号码库 migration `20260624095000_number_library` 先因应用账号无 CREATE 权限失败,随后又暴露 `vendor_gateway_blocked_regions_vendor_gateway_id_region_scope_province_code_city_code_key` 索引名过长;已修正本地 migration 为短名 `vgb_regions_gateway_scope_region_key`,并在 B 上补齐部分落地后的剩余 DDL,再 `prisma migrate resolve --applied`。业务前缀 migration `20260624121000_business_prefix_gateway_rewrite` 暴露 `customer_gateway_business_prefixes_gateway_id_business_prefix_id_key` 索引名过长;已修正为 `cgbp_gateway_business_prefix_key`,在 B 上幂等补齐客户网关新字段、多 IP 表、业务前缀绑定表、主叫前缀表、落地主叫池、CDR 新字段及索引/外键,再标记 applied。Prisma status 显示 4 条 migration 全部 up to date。旧客户网关迁移脚本 dry-run 显示 2 个 safe、0 blockers;apply 成功,更新 2 个客户网关,新增 1 条主叫前缀,写入 1 条 outbox。B current 已切换到 `s42-phase2-business-prefix-20260624140000`,`lisglosips@api`、`lisglosips@cdr-worker`、`lisglosips@recording-worker`、`lisglosips@config-publisher` 重启后均 active。API live/ready 和 HTTPS ready 通过,config-publisher 发布 schemaVersion 2 配置版本 `1782282403866`,B preflight 通过。A 侧候选 `opensips.cfg` 与 `lisglosips_hotpath.lua` 已上传到 `/tmp` 并安装到 `/etc/opensips` 后 `opensips -C` 通过,备份目录为 `/var/backups/lisglosips-phase2/20260624142935`;但发现本地模板 `cachedb_url` 占位符仍未替换,且 B 随后再次不可达,无法安全读取 Redis URL、加载 Redis Lua 或重启 A OpenSIPS。为避免 A 半发布,已将 A `/etc/opensips/opensips.cfg` 与 `/etc/opensips/lisglosips_hotpath.lua` 恢复到该备份,恢复后 `opensips -C` 通过且 `opensips` 服务 active。
|
||||
- 修改文件:`prisma/migrations/20260624095000_number_library/migration.sql`、`prisma/migrations/20260624121000_business_prefix_gateway_rewrite/migration.sql`、`IMPLEMENTATION_STATUS.md`
|
||||
- 安装软件及固定版本:未安装新软件。
|
||||
- 执行的关键命令:B `systemctl start lisglosips-backup.service`、备份目录内 `sha256sum -c SHA256SUMS`、创建 release 并覆盖构建产物、`prisma generate`、`prisma migrate resolve --rolled-back 20260624095000_number_library`、迁移账号执行补齐 DDL、`prisma migrate resolve --applied 20260624095000_number_library`、`prisma migrate resolve --applied 20260624121000_business_prefix_gateway_rewrite`、`prisma migrate status`、`node scripts/phase2-gateway-migration.mjs --json`、`node scripts/phase2-gateway-migration.mjs --apply --json`、`systemctl restart lisglosips@api lisglosips@cdr-worker lisglosips@recording-worker lisglosips@config-publisher`、B `lisglosips-release-preflight.sh`;A `opensips -C -f /etc/opensips/opensips.cfg`、恢复 A phase2 备份。
|
||||
- 验证结果:本地 `prisma validate` 使用占位 `DATABASE_URL` 通过;B MySQL/Redis 备份哈希通过;B Prisma status 为 `Database schema is up to date!`;B API live/ready 与 HTTPS ready 返回 `ok`;config-publisher 日志显示 schemaVersion 2 快照发布成功,manifest 包含 `businessPrefixCount`、`customerGatewayIpCount`、`customerGatewayCallerPrefixCount`、号码库与屏蔽地区统计;B preflight ok。A 候选配置语法检查曾通过;A 恢复备份后语法检查通过,OpenSIPS active。B 在最后阶段再次 ping/SSH 超时,A/B/T 实呼未执行。
|
||||
- 回滚方式:B 应用可执行 `infra/server-b/s30/lisglosips-release-rollback.sh /opt/lisglosips/releases/s33-active-calls-20260623094000` 或手动将 `/opt/lisglosips/current` 指回该 release 并重启 API/CDR/Recording/Config Publisher。数据库已执行向前兼容新增表/列,优先用新页面/API 修正配置;如必须恢复,使用 `/data/backups/mysql/20260624T055810Z` 在隔离环境验证后恢复。Redis 可切回上一配置版本。A 侧已恢复到 `/var/backups/lisglosips-phase2/20260624142935`,未重启进入新热路径。
|
||||
- 未解决问题:B Tailscale/主机网络不稳定,发布后再次不可达;A Redis URL 占位符问题需在后续发布脚本中修正,不能直接部署模板;尚未将 Lua SHA 加载到 Redis;A OpenSIPS 未重启到新热路径;A/B/T 端到端呼叫、强制挂断、话单详情字段验证未执行;真实 80 万手机号段仍未导入。
|
||||
- 下一任务:先恢复并稳定 B 连通性;确认 B current、服务、Redis 配置版本仍正常;读取受控 Redis URL 并安全替换 A cfg 占位符,加载 Lua SCRIPT 到 Redis,`opensips -C` 通过后重启 A OpenSIPS;再执行 T 实呼和当前通话/话单验收。
|
||||
|
||||
### 2026-06-24 13:40 - 需求修改/二期变更:业务前缀重构第 9 步三机发布前验收
|
||||
|
||||
- 状态:已阻塞;未执行数据库迁移,未部署 release,未发布 Redis,未替换 A OpenSIPS,未重启服务
|
||||
- 操作服务器:本地、A、T 只读探测;B 未连通
|
||||
- 完成内容:按第 9 步 Runbook 先复核影响、风险与回滚点;确认本步骤会涉及 B MySQL/Redis 备份、Prisma migration、旧客户网关迁移 dry-run/apply、Redis 配置发布、A OpenSIPS/Lua 语法检查和 A/B/T 实呼验收。执行三机连通性检查时,A `100.90.90.90` 与 T `100.93.185.30` SSH 可达且 OpenSIPS active;B `100.90.90.91` 从开发机 SSH 超时,开发机 `Test-NetConnection` 显示 Ping 与 TCP 22 失败;从 A、T 到 B 的 ping 也 100% 丢包,`nc -vz 100.90.90.91 22` 超时。由于 B 是数据库、Redis、API/Worker 与 release 目标机,未满足安全发布前提,停止执行。
|
||||
- 修改文件:`IMPLEMENTATION_STATUS.md`
|
||||
- 安装软件及固定版本:未安装新软件。
|
||||
- 执行的关键命令:`ssh -F .codex-private/ssh/config lisglosips-a "hostname; whoami; systemctl is-active opensips || true"`、`ssh -F .codex-private/ssh/config lisglosips-t "hostname; whoami; systemctl is-active opensips || true"`、`Test-NetConnection 100.90.90.91 -Port 22`、`ping 100.90.90.91 -n 4`、从 A/T 执行 `ping -c 2 -W 2 100.90.90.91` 与 `nc -vz -w 3 100.90.90.91 22`
|
||||
- 验证结果:A/T SSH 与 OpenSIPS 状态正常;B 当前不可达,无法记录 B current release、无法执行 S30 备份、无法执行 Prisma migration dry-run、无法做 Redis 配置发布与 A/B/T 端到端验收。
|
||||
- 回滚方式:本次未对服务器做写操作,无需远端回滚。恢复 B 连通后,从第 9 步开头重新执行:先记录 B release/migration/Redis 版本,再执行 S30 MySQL/Redis 备份和恢复校验,然后部署新 release 到独立目录并 dry-run 迁移。
|
||||
- 未解决问题:需要恢复 B 的 Tailscale/主机网络/SSH 可达性;恢复后需确认 B 上 `lisglosips@api`、`lisglosips@cdr-worker`、`lisglosips@recording-worker`、`lisglosips@config-publisher`、MySQL、Redis 状态,再继续第 9 步。
|
||||
- 下一任务:恢复 B 可达性后重新执行第 9 步发布前验收;如需现场处理 B,优先通过 KVM/控制台检查电源、Tailscale、nftables、sshd 与系统状态。
|
||||
|
||||
### 2026-06-24 13:25 - 需求修改/二期变更:业务前缀重构第 8 步旧数据迁移与发布前验收准备
|
||||
|
||||
- 状态:已完成本地代码与 Runbook;未执行数据库迁移,未连接服务器,未发布 A/B,未重启服务
|
||||
- 操作服务器:本地
|
||||
- 完成内容:新增 `scripts/phase2-gateway-migration.mjs`,用于审计和安全回填旧客户网关数据。脚本默认 dry-run,不写库;只有显式 `--apply` 才写入。自动迁移仅允许“每个客户网关恰好 1 条启用旧策略、被叫任意、主叫任意或主叫前缀”的安全场景;多旧策略、无启用策略、旧被叫等值/前缀、旧主叫等值、新旧线路组冲突均列为人工 blockers。apply 时会写入 `customer_gateways.line_group_id/caller_match_mode/callee_match_mode`、补齐 `customer_gateway_ips` 与 `customer_gateway_caller_prefixes`,并写 `customer_gateway_config` outbox 触发配置发布。新增 `docs/PHASE2_BUSINESS_PREFIX_GATEWAY_MIGRATION_RUNBOOK.md`,覆盖 B migration、dry-run/apply、Redis 发布、A OpenSIPS 备份/语法检查/重启、A/B/T 实呼验收和回滚。
|
||||
- 修改文件:`scripts/phase2-gateway-migration.mjs`、`docs/PHASE2_BUSINESS_PREFIX_GATEWAY_MIGRATION_RUNBOOK.md`、`IMPLEMENTATION_STATUS.md`
|
||||
- 安装软件及固定版本:未安装新软件。
|
||||
- 执行的关键命令:`node --check scripts/phase2-gateway-migration.mjs`、`node_modules\.bin\tsc.cmd -b tsconfig.build.json --pretty`、`node_modules\.bin\eslint.cmd .`、`node_modules\.bin\vitest.cmd run`、逐包 `node_modules\.bin\tsc.cmd -p ...`、`apps\web\node_modules\.bin\vite.CMD build`
|
||||
- 验证结果:迁移脚本语法检查通过;typecheck 通过;lint 通过;全量 test 通过,25 个测试文件、86 条测试通过;所有 TypeScript package 构建通过;Web 使用 `apps/web` 自身 Vite 5 构建通过。
|
||||
- 回滚方式:本地回滚可删除上述脚本/Runbook 并恢复状态文件。若未来在 B 执行 `--apply` 后需回滚,优先通过客户网关 API/页面修正新字段并重新发布 Redis;若必须恢复数据库,使用执行前 MySQL 备份在隔离环境验证后恢复。Redis 可切回上一 `cfg:previous_version`;A OpenSIPS 可恢复发布前 cfg/Lua 备份并重新 `opensips -C` 后重启。
|
||||
- 未解决问题:尚未在 B 执行 Prisma migration 和 dry-run;真实 blockers 数量未知;A 侧 `opensips -C` 和 `uac_replace_from` 实呼行为尚未验证;客户侧计费仍未切换到客户网关费率;业务前缀绑定仍需按真实客户号码规则人工配置。
|
||||
- 下一任务:第 9 步本地/三机发布前总验收:先在 B 执行 dry-run 审计并处理 blockers,再按 Runbook 执行 migration、配置发布、A OpenSIPS 语法检查和 A/B/T 实呼验收;执行前必须再次确认备份和维护窗口。
|
||||
|
||||
### 2026-06-24 13:15 - 需求修改/二期变更:业务前缀重构第 7 步 CDR Stream 与入库链路
|
||||
|
||||
- 状态:已完成本地代码;未执行数据库迁移,未发布服务器,未重启服务
|
||||
- 操作服务器:本地
|
||||
- 完成内容:CDR Redis Stream 事件契约新增 `raw_callee`、`business_prefix_id`、`business_prefix`、`landing_caller`、`landing_callee`、`normalized_callee`,发布端可显式写入这些字段,解析端兼容旧消息缺字段。CDR Worker 创建 `raw_cdrs` 时写入 `rawCallee`、`businessPrefixId`、`businessPrefix`、`landingCaller`、`landingCallee`,并将 `normalized_callee` 保留在 payload 中。话单 API DTO 透出原始被叫、业务前缀、落地主叫、落地被叫;Web 话单详情弹窗的链路信息区展示这些字段,列表列宽不增加。
|
||||
- 修改文件:`packages/redis/src/cdr-stream.ts`、`packages/redis/src/cdr-stream.spec.ts`、`apps/worker-cdr/src/rating.ts`、`apps/worker-cdr/src/rating.spec.ts`、`apps/api/src/modules/cdrs/cdrs.repository.ts`、`apps/api/src/modules/cdrs/cdrs.service.spec.ts`、`apps/web/src/App.jsx`、`IMPLEMENTATION_STATUS.md`
|
||||
- 安装软件及固定版本:未安装新软件。
|
||||
- 执行的关键命令:`node_modules\.bin\vitest.cmd run packages/redis/src/cdr-stream.spec.ts apps/worker-cdr/src/rating.spec.ts apps/api/src/modules/cdrs/cdrs.service.spec.ts`、`node_modules\.bin\tsc.cmd -b tsconfig.build.json --pretty`、`node_modules\.bin\eslint.cmd .`、`node_modules\.bin\vitest.cmd run`、逐包 `node_modules\.bin\tsc.cmd -p ...`、`apps\web\node_modules\.bin\vite.CMD build`
|
||||
- 验证结果:定向测试通过,3 个测试文件、13 条测试通过;typecheck 通过;lint 通过;全量 test 通过,25 个测试文件、86 条测试通过;所有 TypeScript package 构建通过;Web 使用 `apps/web` 自身 Vite 5 构建通过。
|
||||
- 回滚方式:恢复上述 Stream/Worker/CDR API/Web/状态文件即可;若未来已发布并产生新字段 CDR,回滚旧 Worker 前需确认旧版本能忽略 Stream 中额外字段,或先停止 A 侧新 Lua XADD;数据库已含兼容 nullable 字段,本次无额外 migration。
|
||||
- 未解决问题:真实 B 环境仍需执行第 1 步 migration 后才能写入新 `raw_cdrs` 字段;A/B/T 尚未发布验收;客户侧计费仍未切换到客户网关费率;旧客户网关策略迁移脚本仍待实现;OpenSIPS `uac_replace_from` 行为仍需实呼验证。
|
||||
- 下一任务:第 8 步旧数据迁移与发布前验收准备:迁移现有客户网关单 IP/旧策略到新表和单线路组字段,准备 B migration、配置发布、A OpenSIPS 语法检查与 A/B/T 实呼验收脚本。
|
||||
|
||||
### 2026-06-24 13:05 - 需求修改/二期变更:业务前缀重构第 6 步 OpenSIPS/Lua 热路径本地改造
|
||||
|
||||
- 状态:已完成本地代码;未连接服务器,未发布 A/B,未重启 OpenSIPS,未执行 `opensips -C`
|
||||
- 操作服务器:本地
|
||||
- 完成内容:重写 S28 热路径 Lua,使其优先读取 `auth:ip:{source}:gateways` 候选客户网关列表,兼容旧 `auth:ip:{source}` 单网关;按客户网关状态、客户状态、主叫前缀规则、被叫业务前缀规则匹配客户网关;被叫命中业务前缀时剥离前缀并输出真实被叫,同时保留原始被叫、业务前缀 ID/值、号码库归一化号码。线路组选择继续按同组落地网关优先级和地区屏蔽跳过逻辑执行;落地网关命中后按 `landingCalleePrefix` 生成落地被叫,按 `callerRewritePool` 权重和 Call-ID 确定性哈希选择落地指定主叫。保留旧 `customer_gateway_policies` 兼容分支,供未迁移客户网关继续路由。OpenSIPS S28 模板加载 `uac.so`,更新 Lua SHA,接收 24 个热路径返回字段,转发前改写 `$ru` 为落地被叫,并在需要时通过 `uac_replace_from` 改写 From;成功/失败 CDR XADD 追加 `raw_callee`、`business_prefix_id`、`business_prefix`、`landing_caller`、`landing_callee`、`normalized_callee`。
|
||||
- 修改文件:`infra/server-a/s28/lisglosips_hotpath.lua`、`infra/server-a/s28/opensips.cfg`、`IMPLEMENTATION_STATUS.md`
|
||||
- 安装软件及固定版本:未安装新软件。
|
||||
- 执行的关键命令:`node_modules\.bin\tsc.cmd -b tsconfig.build.json --pretty`、`node_modules\.bin\eslint.cmd .`、`node_modules\.bin\vitest.cmd run`、逐包 `node_modules\.bin\tsc.cmd -p ...`、`apps\web\node_modules\.bin\vite.CMD build`、Node 静态校验 Lua SHA 与 OpenSIPS AVP 索引。
|
||||
- 验证结果:typecheck 通过;lint 通过;全量 test 通过,25 个测试文件、86 条测试通过;所有 TypeScript package 构建通过;Web 使用 `apps/web` 自身 Vite 5 构建通过;静态校验确认 `opensips.cfg` 中 EVALSHA 与当前 Lua SHA `0b7ee595cdcad2f38a670dd8ff3553387820039e` 一致,`s28_hotpath` AVP 映射覆盖 0-23。当前本地无 OpenSIPS/Lua 运行时,尚未执行 `opensips -C -f /etc/opensips/opensips.cfg`,发布到 A 前必须补做。
|
||||
- 回滚方式:本地回滚可恢复 `infra/server-a/s28/lisglosips_hotpath.lua`、`infra/server-a/s28/opensips.cfg` 与状态文件。若未来已发布到 A,回滚前先停止变更窗口,恢复发布前备份的 `/etc/opensips/opensips.cfg` 与 `/etc/opensips/lisglosips_hotpath.lua`,重新加载旧 Lua SHA,执行 `opensips -C -f /etc/opensips/opensips.cfg` 通过后重启 OpenSIPS;B 侧 Redis 可切回上一配置版本。
|
||||
- 未解决问题:真实 A 机语法检查和重启验收尚未执行;`uac_replace_from` 的最终行为需在 A/B/T 呼叫中确认;CDR Worker 目前仍未解析并入库 `raw_callee`、`business_prefix_id`、`business_prefix`、`landing_caller`、`landing_callee`、`normalized_callee` 新字段;客户侧计费仍未切换到客户网关费率;旧客户网关策略迁移脚本仍待实现。
|
||||
- 下一任务:第 7 步改造 CDR Stream/Worker 入库链路,解析并写入业务前缀与落地主被叫字段,同时准备 A/B/T 端到端验收脚本。
|
||||
|
||||
### 2026-06-24 12:55 - 需求修改/二期变更:业务前缀重构第 5 步 Redis 配置发布结构
|
||||
|
||||
- 状态:已完成本地代码;未执行数据库迁移,未发布服务器,未重启服务,未写真实 Redis
|
||||
- 操作服务器:本地
|
||||
- 完成内容:`worker-config-publisher` 快照清单升级为 `schemaVersion: 2`,新增业务前缀数量、客户网关 IP 数、客户网关业务前缀数、客户网关主叫前缀数、落地指定主叫池数量等统计;配置快照新增 `businessPrefixes`,客户网关快照新增多 IP、单线路组、客户侧计费、主叫前缀规则、被叫业务前缀规则,落地网关快照新增 `landingCalleePrefix` 与 `callerRewritePool`。Redis 写入新增 `business_prefix:*`、`business_prefix_value:*`、`business_prefixes`、`auth:ip:*:gateways`、`customer_gateway:*:caller_prefixes`、`customer_gateway:*:business_prefixes`、`customer_gateway:*:line_group`、`vendor_gateway:*:caller_rewrite_pool` 等热路径 key,同时保留旧 `auth:ip:*`、旧客户策略列表和旧落地前缀规则兼容输出。业务前缀 CRUD 增删改启停时新增 `business_prefix_config` outbox,发布器纳入该 aggregate type。
|
||||
- 修改文件:`apps/worker-config-publisher/src/publisher.ts`、`apps/worker-config-publisher/src/publisher.spec.ts`、`apps/api/src/modules/business-prefixes/business-prefixes.repository.ts`、`IMPLEMENTATION_STATUS.md`
|
||||
- 安装软件及固定版本:未安装新软件;执行 `prisma generate` 重新生成本地 Prisma Client。
|
||||
- 执行的关键命令:`node_modules\.bin\prisma.cmd format`、`node_modules\.bin\prisma.cmd generate`、`node_modules\.bin\vitest.cmd run apps/worker-config-publisher/src/publisher.spec.ts`、`node_modules\.bin\tsc.cmd -b tsconfig.build.json --pretty`、`node_modules\.bin\eslint.cmd .`、`node_modules\.bin\vitest.cmd run`、逐包 `node_modules\.bin\tsc.cmd -p ...`、`apps\web\node_modules\.bin\vite.CMD build`
|
||||
- 验证结果:Prisma format/generate 通过;发布器定向测试通过,1 条测试通过;typecheck 通过;lint 通过;全量 test 通过,25 个测试文件、86 条测试通过;所有 TypeScript package 构建通过;Web 使用 `apps/web` 自身 Vite 5 构建通过。根级 `node scripts/pnpm-run.mjs typecheck/build` 因当前 shell 找不到 `pnpm` 报 `spawnSync pnpm ENOENT`,已用本地 `.cmd` 可执行文件完成等效验证。
|
||||
- 回滚方式:恢复上述发布器、业务前缀仓储和状态文件即可;若未来已经发布到 B 并产生 `business_prefix_config` outbox,可停止 config-publisher 后将相关 outbox 标为已处理或恢复发布前数据库备份,再切回旧 release。Redis 活跃配置可通过 `CONFIG_PREVIOUS_VERSION_KEY` 回滚到上一版本;本次未对服务器 Redis 进行写入。
|
||||
- 未解决问题:真实 B 环境仍需先执行第 1 步 migration 后才能运行新发布器;OpenSIPS/Lua 尚未读取新 Redis key,尚未完成业务前缀剥离、客户网关候选匹配、客户侧计费、落地被叫加前缀和指定主叫权重选择;CDR 写入 raw callee/business prefix/landing caller/landing callee 与 A/B/T 验收仍待后续步骤。
|
||||
- 下一任务:第 6 步改造 OpenSIPS/Lua 热路径:按 IP 候选客户网关、主叫前缀和被叫业务前缀匹配客户网关,并输出剥离后的真实被叫号码。
|
||||
|
||||
### 2026-06-24 12:50 - 需求修改/二期变更:业务前缀重构第 4 步落地网关新改写字段
|
||||
|
||||
- 状态:已完成本地代码;未执行数据库迁移,未发布服务器,未重启服务
|
||||
- 操作服务器:本地
|
||||
- 完成内容:落地网关 API 增加 `landingCalleePrefix` 和 `callerRewritePool`;创建/更新时写入 `vendor_gateways.landing_callee_prefix` 与 `vendor_gateway_caller_rewrite_pool`,并继续保留旧 `vendor_gateway_prefix_rules` 表作为兼容字段。落地被叫前缀支持空值或英文/数字;指定主叫号码池支持多个号码、权重和启停状态,并校验重复号码。前端落地网关编辑页将旧“被叫前缀转换/主叫前缀转换”替换为“落地要求被叫前缀”和“落地要求指定主叫”,列表新增落地被叫前缀与指定主叫数展示;保存时调用真实 `PATCH /api/v2/vendor-gateways/:id`。顺带修正落地网关子表 ID 生成长度,避免 `vgfp_...`、`vgcr_...` 超过 32 字符字段长度。
|
||||
- 修改文件:`apps/api/src/modules/vendor-gateways/vendor-gateways.repository.ts`、`apps/api/src/modules/vendor-gateways/vendor-gateways.service.ts`、`apps/api/src/modules/vendor-gateways/vendor-gateways.e2e.spec.ts`、`apps/web/src/api.js`、`apps/web/src/App.jsx`、`IMPLEMENTATION_STATUS.md`
|
||||
- 安装软件及固定版本:未安装新软件;执行 `prisma generate` 重新生成本地 Prisma Client。
|
||||
- 执行的关键命令:`node_modules\.bin\prisma.cmd generate`、`node_modules\.bin\tsc.cmd -b tsconfig.build.json --pretty false`、`node_modules\.bin\vitest.cmd run apps/api/src/modules/vendor-gateways/vendor-gateways.e2e.spec.ts`、`corepack pnpm@10.33.0 lint`、`corepack pnpm@10.33.0 build`、`corepack pnpm@10.33.0 test`
|
||||
- 验证结果:Prisma generate 通过;typecheck 通过;落地网关 e2e 通过,4 条测试通过;lint 通过;workspace build 通过;全量 test 通过,25 个测试文件、86 条测试通过。
|
||||
- 回滚方式:恢复上述落地网关 API/Web 文件和 `IMPLEMENTATION_STATUS.md` 即可;若只回滚第 4 步,可保留第 1-3 步。若未来已执行 migration 且已录入新落地改写数据,回滚前需导出 `vendor_gateways.landing_callee_prefix` 与 `vendor_gateway_caller_rewrite_pool`,确认没有生产配置依赖后再删列/删表或恢复备份。
|
||||
- 未解决问题:当前前端仍只完善落地网关编辑路径,新增按钮仍是占位;真实 B 环境必须先执行第 1 步 migration 后才能使用本页面新字段;Redis 发布结构、OpenSIPS/Lua 热路径落地被叫加前缀/主叫按权重改写、CDR 写入 landing caller/callee 和 A/B/T 验收仍待后续步骤。
|
||||
- 下一任务:第 5 步改造 Redis 配置发布与 Worker/热路径配置结构,先在本地生成新配置快照契约,再安排 OpenSIPS/Lua 处理顺序。
|
||||
|
||||
### 2026-06-24 12:35 - 需求修改/二期变更:业务前缀重构第 3 步客户网关新模型
|
||||
|
||||
- 状态:已完成本地代码;未执行数据库迁移,未发布服务器,未重启服务
|
||||
- 操作服务器:本地
|
||||
- 完成内容:客户网关 API 扩展为多 IP、单落地线路组、客户侧计费周期/周期费率、主叫匹配模式与前缀列表、被叫匹配模式与业务前缀多选;创建/更新时写入 `customer_gateway_ips`、`customer_gateway_caller_prefixes`、`customer_gateway_business_prefixes`,同时保留旧 `source_ip` 为首个 IP 兼容字段,旧 `customer_gateway_policies` 表和模块未删除。前端客户网关页面新增客户选择、多个 IP、SIP 域、落地线路组、客户费率、主叫规则和业务前缀多选;列表展示落地线路组、客户费率、主叫规则和被叫规则;旧“策略配置”入口已从客户网关列表隐藏。客户网关新增/编辑已接入真实 API。
|
||||
- 修改文件:`apps/api/src/modules/customer-gateways/customer-gateways.repository.ts`、`apps/api/src/modules/customer-gateways/customer-gateways.service.ts`、`apps/api/src/modules/customer-gateways/customer-gateways.e2e.spec.ts`、`apps/web/src/api.js`、`apps/web/src/App.jsx`、`IMPLEMENTATION_STATUS.md`
|
||||
- 安装软件及固定版本:未安装新软件;执行 `prisma generate` 重新生成本地 Prisma Client。
|
||||
- 执行的关键命令:`node_modules\.bin\prisma.cmd generate`、`node_modules\.bin\tsc.cmd -b tsconfig.build.json --pretty false`、`node_modules\.bin\vitest.cmd run apps/api/src/modules/customer-gateways/customer-gateways.e2e.spec.ts`、`corepack pnpm@10.33.0 lint`、`corepack pnpm@10.33.0 build`、`corepack pnpm@10.33.0 test`
|
||||
- 验证结果:Prisma generate 通过;typecheck 通过;客户网关 e2e 通过,5 条测试通过;lint 通过;workspace build 通过;全量 test 通过,25 个测试文件、86 条测试通过。
|
||||
- 回滚方式:恢复上述客户网关 API/Web 文件和 `IMPLEMENTATION_STATUS.md` 即可;若只回滚第 3 步,可保留第 1 步 Schema 与第 2 步业务前缀管理。本次未连接服务器、未执行 MySQL migration、未写 Redis、未重启 OpenSIPS/RTPEngine/Worker/Web。
|
||||
- 未解决问题:真实 B 环境必须先执行第 1 步 migration 后才能使用本页面新字段;旧客户网关策略数据尚未迁移到 `customer_gateways.line_group_id` 与新匹配表;落地网关“落地要求被叫前缀/指定主叫池”、Redis 发布结构、OpenSIPS/Lua 热路径号码剥离与落地改写、CDR 写入链路和 A/B/T 验收仍待后续步骤。
|
||||
- 下一任务:第 4 步改造落地网关 API/Web:用 `landing_callee_prefix` 和 `vendor_gateway_caller_rewrite_pool` 替代旧主被叫前缀转换规则。
|
||||
|
||||
### 2026-06-24 12:20 - 需求修改/二期变更:业务前缀重构第 2 步 API 与 Web 菜单
|
||||
|
||||
- 状态:已完成本地代码;未执行数据库迁移,未发布服务器,未重启服务
|
||||
- 操作服务器:本地
|
||||
- 完成内容:新增 `BusinessPrefixesModule`,提供 `GET/POST/PATCH/DELETE /api/v2/business-prefixes` 以及启用/禁用接口;权限复用 `customer_gateways.view/manage`,审计模块记录 business-prefixes 创建、修改、启停、删除。前端新增“业务前缀管理”菜单和页面,支持关键字/状态筛选、新增、编辑、启用/禁用确认、删除确认,删除按钮使用红色警示色;前端 API Client 增加业务前缀相关方法和错误文案。业务前缀删除时若已被客户网关引用会返回 `BUSINESS_PREFIX_IN_USE`。
|
||||
- 修改文件:`apps/api/src/modules/business-prefixes/`、`apps/api/src/modules/app.module.ts`、`apps/web/src/api.js`、`apps/web/src/App.jsx`、`IMPLEMENTATION_STATUS.md`
|
||||
- 安装软件及固定版本:未安装新软件;执行 `prisma generate` 重新生成本地 Prisma Client。
|
||||
- 执行的关键命令:`node_modules\.bin\prisma.cmd generate`、`node_modules\.bin\tsc.cmd -b tsconfig.build.json --pretty false`、`corepack pnpm@10.33.0 lint`、`node_modules\.bin\vitest.cmd run packages/database/src/schema-contract.spec.ts`、`corepack pnpm@10.33.0 build`、`corepack pnpm@10.33.0 test`
|
||||
- 验证结果:Prisma generate 通过;typecheck 通过;lint 通过;database contract 定向测试通过;workspace build 通过;全量 test 通过,25 个测试文件、86 条测试通过。
|
||||
- 回滚方式:恢复 `apps/api/src/modules/business-prefixes/`、`apps/api/src/modules/app.module.ts`、`apps/web/src/api.js`、`apps/web/src/App.jsx`、`IMPLEMENTATION_STATUS.md`,并保留/恢复第 1 步 Schema 取决于是否继续二期;本次未连接服务器、未执行 MySQL migration、未写 Redis、未重启 OpenSIPS/RTPEngine/Worker/Web。
|
||||
- 未解决问题:当前业务前缀页面依赖第 1 步 migration 实际执行后才可在真实 B API 使用;客户网关多 IP、单线路组、客户侧费率、业务前缀多选、主叫前缀规则、落地网关新改写字段、Redis 发布结构、OpenSIPS/Lua 热路径和 A/B/T 验收仍待后续步骤。
|
||||
- 下一任务:第 3 步改造客户网关 API/Web:支持多 IP、单落地线路组、客户侧费率、业务前缀多选和主叫前缀规则,同时设计旧策略兼容/迁移方式。
|
||||
|
||||
### 2026-06-24 12:05 - 需求修改/二期变更:业务前缀重构第 1 步本地数据模型
|
||||
|
||||
- 状态:已完成本地代码;未执行数据库迁移,未发布服务器,未重启服务
|
||||
- 操作服务器:本地
|
||||
- 完成内容:按兼容迁移方式新增业务前缀、客户网关多 IP、客户网关单落地线路组、客户侧计费周期/费率、客户网关主叫/被叫匹配模式、客户网关业务前缀关联、客户网关主叫前缀列表、落地网关“落地要求被叫前缀”、落地网关指定主叫号码池和权重、话单 raw callee/business prefix/landing caller/landing callee 等二期字段。保留旧 `customer_gateway_policies` 与 `vendor_gateway_prefix_rules`,用于后续 API/Web/OpenSIPS 分阶段切换。
|
||||
- 修改文件:`prisma/schema.prisma`、`prisma/migrations/20260624121000_business_prefix_gateway_rewrite/migration.sql`、`packages/database/src/schema-contract.spec.ts`、`IMPLEMENTATION_STATUS.md`
|
||||
- 安装软件及固定版本:未安装新软件;继续使用本地仓库依赖中的 Prisma `6.19.0`、Vitest `4.0.14`。
|
||||
- 执行的关键命令:`node_modules\.bin\prisma.cmd format`、`$env:DATABASE_URL='mysql://lisglosips_app@127.0.0.1:3306/lisglosips'; node_modules\.bin\prisma.cmd validate`、`node_modules\.bin\vitest.cmd run packages/database/src/schema-contract.spec.ts`
|
||||
- 验证结果:Prisma format 通过;Prisma validate 通过;数据库 contract 定向测试通过,1 个测试文件、6 条测试通过。全量 lint/typecheck/test/build 尚未运行,因为本步只改 Schema、迁移与 contract,下一步 API/Web 改动后再跑全量验证。
|
||||
- 回滚方式:恢复 `prisma/schema.prisma`、删除 `prisma/migrations/20260624121000_business_prefix_gateway_rewrite/` 并恢复 `packages/database/src/schema-contract.spec.ts`、`IMPLEMENTATION_STATUS.md` 即可;本次未连接服务器、未执行 MySQL migration、未写 Redis、未重启 OpenSIPS/RTPEngine/Worker/Web。
|
||||
- 未解决问题:业务前缀管理 API/Web、客户网关新表单与新 API、旧策略迁移脚本、落地网关新字段 API/Web、Redis 发布结构、OpenSIPS/Lua 热路径号码剥离与落地改写、CDR 写入链路、A/B/T 端到端验收仍待后续步骤实施。
|
||||
- 下一任务:第 2 步实现“业务前缀管理” API 与 Web 菜单,继续保持本地开发,不直接执行 B MySQL migration。
|
||||
|
||||
### 2026-06-24 11:58 - 需求修改/二期变更:业务前缀、客户网关匹配和落地号码改写重构需求评估
|
||||
|
||||
- 状态:已完成需求文档更新;未改代码,未执行数据库迁移,未发布服务器
|
||||
- 操作服务器:本地
|
||||
- 完成内容:将新增“业务前缀管理”菜单、客户网关多 IP、客户网关单线路组、客户网关客户侧费率、主叫前缀/被叫业务前缀匹配规则、真实被叫号码语义、落地要求被叫前缀、落地要求指定主叫号码池和权重选择等需求写入 `SOFTSWITCH_PLATFORM_DESIGN_V2.md`。明确该需求会替代旧客户网关多路由策略模型和旧落地网关主被叫前缀转换规则,必须分阶段迁移,不能两套热路径并存。补充数据模型建议、Redis 热路径结构、OpenSIPS/Lua 处理顺序、CDR 字段、失败原因、风险约束和 10 步实施拆分。
|
||||
- 修改文件:`SOFTSWITCH_PLATFORM_DESIGN_V2.md`、`IMPLEMENTATION_STATUS.md`
|
||||
- 安装软件及固定版本:未安装新软件。
|
||||
- 执行的关键命令:`rg` 检查现有客户网关策略、落地前缀转换、号码库、OpenSIPS 热路径和文档位置;文档更新后用关键字复核“业务前缀管理”“customer_gateway_ips”“landing_callee_prefix”“vendor_gateway_caller_rewrite_pool”“BUSINESS_PREFIX_NOT_MATCHED”等条目。
|
||||
- 验证结果:本次为 Markdown 需求文档更新,未运行 typecheck/lint/test/build;未连接服务器,未执行 Prisma migration,未写 Redis,未重启 OpenSIPS。
|
||||
- 回滚方式:恢复 `SOFTSWITCH_PLATFORM_DESIGN_V2.md` 和 `IMPLEMENTATION_STATUS.md` 本次文档改动即可;不涉及 B release、MySQL、Redis、OpenSIPS、RTPEngine、Worker 或 Web 回滚。
|
||||
- 未解决问题:实施前仍需确认业务前缀允许字符和长度、是否全局唯一、同一 IP 下多个客户网关规则冲突策略、客户侧费率是否立即替代 S23 最小计费逻辑、旧客户网关多策略如何迁移、落地指定主叫权重选择是否要求严格随机或按 Call-ID 可复现。
|
||||
- 下一任务:建议先做第 1 步“需求冻结与冲突口径确认”,随后单独开数据库建模/migration,不要直接改 OpenSIPS 热路径。
|
||||
|
||||
### 2026-06-24 11:41 - 需求修改/二期变更:号码库第 6、7 步本地实现
|
||||
|
||||
- 状态:已完成本地代码;准备提交 Git;未发布到 B/A,未执行数据库迁移,未重启服务
|
||||
|
||||
Reference in New Issue
Block a user