DynamoDB 表关系图¶
Audit 历史
- 2026-04-26: 9 个 CDK stack deployed(StorageStack / SqsStack / IamStack / LambdaStack / CognitoStack / ContactsStack / MonitoringStack / EventBridgeStack / MessageSystemStack + 条件性 GitHubOidcStack)
- 2026-04-23: deep audit(AWS CLI 实查 + CDK 代码交叉验证)
- 2026-03-02: 上次全量 audit
call-analysis/call-events/LeadTracking-v2仍是 DDB-primary;calls/messages/leads已切换到 Neon-primary read(DDB 表保留作 backward-compat)
| 状态 | 含义 | 行动 |
|---|---|---|
| 🟢 ACTIVE | 有活跃代码引用,正在生产使用 | 正常维护 |
| 🟡 LEGACY | 功能已被新表替代,但仍有残留代码引用 | 排查引用后迁移 |
| 🔴 DEAD | 零活跃代码引用,业务读写接近零(≤16 RCU/7d) | 列入 Archive 候选。archive 前必须 CloudTrail 追踪 2-16 RCU/7d 的实际来源 |
Production (us-east-1) — 26 张表¶
全部 PAY_PER_REQUEST(按需计费)。16 个 CDK-managed + 6 个孤儿表 + 4 个 Legacy 表。
28 vs 26 — 为什么少了 2 张?
MessageStore 和 Conversations 已部署到 test (us-west-2),尚未部署到 prod。部署后 prod 将有 28 张。
CDK Stack 所有权(5 stacks · 4 repos)
| CDK Stack | Repo | 表数 | 表名前缀 |
|---|---|---|---|
CallAnalytics-Prod-Storage |
callytics-infrastructure |
3 | call-analytics-prod-* |
OrangeTheoryStack-prod |
studio-website-monorepo |
10 | orangetheory-* / studio-* |
RCSubscription-prod-Storage |
ringcentralSubscriptionService |
2 | rc-subscription-prod-* |
LeadTrackingStack |
lead-tracking |
1 | LeadTracking-v2-* |
(已删除) RingCentralOAuthStack-prod |
(已归档) ringcentralService |
6 | ConnectionService-*-prod |
Call Analytics — 通话分析 (3) CDK: CallAnalytics-Prod-Storage¶
Neon-primary read 已切换 (2026-04-26)
call-analysis 表仍接收 ai-analysis-processor 的 dual-write(legacy 兼容),但 Neon calls 已是 primary read source。studio-api 查询通话数据走 Neon SQL(含 store_id filter)。call-events 仍 DDB-primary(无 Neon 镜像)。call-analysis-config 仍 DDB-only(per-client AI 配置,operational table,不迁 Neon)。
| 表名 | 状态 | PK | GSI | 说明 |
|---|---|---|---|---|
call-analytics-prod-call-analysis-us-east-1 |
🟢 | telephonySessionId | 11 | AI 分析结果(最大表,Neon calls 是 primary read,DDB 仅 dual-write 兼容) |
call-analytics-prod-call-events-us-east-1 |
🟢 | telephonySessionId | 2 | 原始通话事件(DDB-only,无 Neon 镜像) |
call-analytics-prod-call-analysis-config-us-east-1 |
🟢 | client_id | 0 | 每客户分析配置(operational,不迁 Neon) |
call-analysis 11 个 GSI(全部 ProjectionType: ALL)
| GSI 名称 | Partition Key | Sort Key | 用途 |
|---|---|---|---|
franchise-callStartTime-index |
franchise | callStartTime | 按品牌查通话 |
franchise-siteId-index |
franchise | siteId | 按品牌+门店查 |
siteId-callStartTime-index |
siteId | callStartTime | 按门店查通话 |
fromPhoneNumber-callStartTime-index |
fromPhoneNumber | callStartTime | 按来电号码查 |
toPhoneNumber-callStartTime-index |
toPhoneNumber | callStartTime | 按被叫号码查 |
callDirection-callStartTime-index |
callDirection | callStartTime | 按方向查(呼入/呼出) |
staff_performance...name-callStartTime-index |
staff...name | callStartTime | 按员工姓名查 |
call_categorization...classification-callStartTime-index |
classification | callStartTime | 按主分类查 |
call_categorization.follow_up_type-callStartTime-index |
followuptype | callStartTime | 按跟进类型查 |
call_outcome.outcome_category-callStartTime-index |
outcome_category | callStartTime | 按结果类别查 |
transcriptionJobName-index |
transcriptionJobName | — | 转录任务关联 |
call-events 有 2 个 GSI:transcriptionJobName-index 和 sessionId-index(RC session 关联)。
⚠ 所有 11 个 GSI 均 ALL projection,写入成本 12 倍。其中 3 个 GSI 记录数为 0,建议排查后删除或改为 KEYS_ONLY。TODO:2026-03-02 审计未记录具体是哪 3 个 GSI。候选(按 feature status 推断,未 verify):call_outcome.outcome_category-callStartTime-index / call_categorization.follow_up_type-callStartTime-index / staff_performance...name-callStartTime-index。下次 audit 需 per-GSI scan --projection-expression 确认。
ConnectionService — 孤儿表 (6) ⚠ 全部 KMS + Deletion Protection¶
原 RingCentralOAuthStack-prod CDK stack 于 2025-12-29 删除,表因 RETAIN + DP 保留。功能已被 orangetheory-* 的 user+store-centric 模型替代。主应用无运行时依赖(USE_V2_CONFIG_LOADER=false,code path short-circuit),但 lib/stacks/lambda-stack.ts:440-447, 471-479 仍 hardcode CONFIG_TABLE_V2 / ORG_TABLE_V2 / CONN_TABLE_V2 3 个 env vars 到 AnalyticsGenerator + ForceRefresh 2 个 Lambda 的 env(值含 -test 硬后缀,指向在 us-west-2 不存在的 phantom 表)——未启用但未移除。追踪见 infra#658。
ConnectionService → orangetheory-* 新旧表映射
| ConnectionService (老) | orangetheory-* (新) | 说明 |
|---|---|---|
Organizations (orgId) |
StoresV2 (storeId) |
数据围墙从 org → store |
Connections (orgId+provider) |
UserConnections (userId+connectionId) |
RC 连接改为按用户 |
UserOrganizations (userId+orgId) |
UserStore (userId+storeId) |
成员权限改为按门店 |
OrgConfigurations (orgId) |
StoresV2.businessConfig |
配置合并到门店表 |
SubAccountLinks |
SubAccounts |
同样功能,不同 schema |
CallAnalysisConfigurations |
call-analysis-config |
直接替代(CDK 管理) |
| 表名 | 状态 | PK | SK | GSI | Streams | 说明 |
|---|---|---|---|---|---|---|
ConnectionService-CallAnalysisConfigurations-prod |
🟢 | client_id | — | 0 | ❌ | Legacy Lambda 仍在读(RCU ~450/7d) |
ConnectionService-Organizations-prod |
🟡 | orgId | — | 0 | ✅ NEWANDOLD | V2 loader 存在但 USE_V2_CONFIG_LOADER=false |
ConnectionService-Connections-prod |
🟡 | orgId | provider | 1 | ✅ NEWANDOLD | V2 loader 存在但未启用 |
ConnectionService-OrgConfigurations-prod |
🟡 | orgId | — | 0 | ✅ NEWANDOLD | V2 loader 存在但未启用 |
ConnectionService-UserOrganizations-prod |
🔴 | userId | orgId | 1 | ✅ NEWANDOLD | 零代码引用 |
ConnectionService-SubAccountLinks-prod |
🔴 | parentUserId | childUserId | 1 | ✅ NEWANDOLD | 零代码引用 |
Phone Management — 电话管理 (3) CDK: OrangeTheoryStack-prod¶
| 表名 | 状态 | PK | SK | GSI | 说明 |
|---|---|---|---|---|---|
orangetheory-UserConnections-prod |
🟢 | userId | connectionId | 4 | RC OAuth 连接(KMS 加密) |
orangetheory-PhoneNumbers-prod |
🟢 | providerAccountId | phoneNumber | 2 | RC 电话线路与分机 |
orangetheory-PhoneStoreAssignments-prod |
🟢 | storeId | phoneNumber | 1 | 电话→门店映射 |
Store & Operations — 门店运营 (7) CDK: OrangeTheoryStack-prod¶
| 表名 | 状态 | PK | SK | GSI | 说明 |
|---|---|---|---|---|---|
orangetheory-StoresV2-prod |
🟢 | storeId | — | 1 | 门店信息(GSI: userId-index) |
orangetheory-UserStore-prod |
🟢 | userId | storeId | 1 | 用户-门店权限 OWNER/EDITOR/VIEWER |
orangetheory-SubAccounts-prod |
🟢 | childUserId | — | 1 | 子账号关系 |
orangetheory-OAuthStates-prod |
🟢 | stateId | — | 0 | OAuth 瞬态(TTL: ttl) |
studio-Cache-prod |
🟢 | cacheKey | — | 0 | 通用缓存(TTL 30d: ttl) |
studio-BlackoutPeriods-prod |
🟢 | storeId | blackoutId | 1 | 禁呼时段 |
studio-OperatingHours-prod |
🟢 | storeId | sk | 0 | 营业时间(SK: SCHEDULE#date#ts / OVERRIDE#date) |
Lead Tracking — 线索追踪 (1) CDK: LeadTrackingStack¶
Neon-primary read 已切换 (2026-04-26)
LeadTracking-v2 仍接收 lead-tracking Lambda 的 dual-write(legacy 兼容),但 Neon leads 已是 primary read source,并已带 store_id(lead-tracking #88)。studio-api 查询线索数据走 Neon SQL。
| 表名 | 状态 | PK | GSI | 说明 |
|---|---|---|---|---|
LeadTracking-v2-us-east-1 |
🟢 | id | 4 | 线索记录(Neon leads 是 primary read,DDB 仅 dual-write 兼容) |
LeadTracking 4 个 GSI
| GSI 名称 | Partition Key | Sort Key | 用途 |
|---|---|---|---|
email-receivedAt-index |
leadEmail | receivedAt | 按客户邮箱查 |
emailFrom-receivedAt-index |
emailFrom | receivedAt | 按来源邮箱查 |
phone-receivedAt-index |
phone | receivedAt | 按电话号码查(E.164) |
forwardedOriginalFrom-receivedAt-index |
forwardedOriginalFrom | receivedAt | 按转发源查 |
RC Subscription — Webhook 订阅 (2) CDK: RCSubscription-prod-Storage¶
| 表名 | 状态 | PK | GSI | 说明 |
|---|---|---|---|---|
rc-subscription-prod-webhook-subscriptions |
🟢 | accountId | 1 | Webhook 订阅状态 |
rc-subscription-prod-idempotency |
🟢 | id | 0 | Lambda Powertools 幂等性去重(TTL: expiration) |
Legacy 遗留表 (4) Pre-CDK,仅 prod¶
| 表名 | 状态 | 说明 |
|---|---|---|
call-analysis |
🟡 | CDK 前旧表,production-resources.ts 仍引用 ARN |
call-events |
🟡 | CDK 前旧表,production-resources.ts 仍引用 ARN |
CallAnalysisMetadata |
🔴 | 更早期格式,零代码引用 |
client-configurations |
🔴 | 旧客户配置,零代码引用 |
Test (us-west-2) — 19 张表¶
Prod 的镜像子集。无 ConnectionService 孤儿表、无 Legacy 表、无 LeadTracking。另有 2 张 prod 尚未部署的新表。
| # | 表名 | CDK Stack | 备注 |
|---|---|---|---|
| 1 | call-analytics-test-call-analysis-us-west-2 |
CallAnalytics-Test-Storage | |
| 2 | call-analytics-test-call-events-us-west-2 |
CallAnalytics-Test-Storage | |
| 3 | call-analytics-test-call-analysis-config-us-west-2 |
CallAnalytics-Test-Storage | |
| 4 | call-analytics-test-message-store-us-west-2 |
MessageSystemStack | Prod 未部署 |
| 5 | call-analytics-test-conversations-us-west-2 |
MessageSystemStack | Prod 未部署 |
| 6 | orangetheory-UserConnections-test |
OrangeTheoryStack-test | |
| 7 | orangetheory-PhoneNumbers-test |
OrangeTheoryStack-test | |
| 8 | orangetheory-PhoneStoreAssignments-test |
OrangeTheoryStack-test | |
| 9 | orangetheory-StoresV2-test |
OrangeTheoryStack-test | |
| 10 | orangetheory-UserStore-test |
OrangeTheoryStack-test | |
| 11 | orangetheory-SubAccounts-test |
OrangeTheoryStack-test | |
| 12 | orangetheory-OAuthStates-test |
OrangeTheoryStack-test | |
| 13 | orangetheory-BlackoutPeriods-test |
OrangeTheoryStack-test | ⚠ 与 studio- 重复 |
| 14 | orangetheory-OperatingHours-test |
OrangeTheoryStack-test | ⚠ 与 studio- 重复 |
| 15 | studio-Cache-test |
OrangeTheoryStack-test | |
| 16 | studio-BlackoutPeriods-test |
OrangeTheoryStack-test | |
| 17 | studio-OperatingHours-test |
OrangeTheoryStack-test | |
| 18 | rc-subscription-test-webhook-subscriptions |
RCSubscription-test-Storage | |
| 19 | rc-subscription-test-idempotency |
RCSubscription-test-Storage |
Test 环境差异
- 无 Deletion Protection、无 PITR、全部
removalPolicy: DESTROY— test 环境允许随时重建 - BlackoutPeriods / OperatingHours 同时存在
orangetheory-*和studio-*两个版本。Prod 已清理仅保留studio-*,test 的orangetheory-*版本应在下次部署时清理。⚠️ 2026-04-23 live 发现:orangetheory-BlackoutPeriods-test有 29 items(2026-01-10 创建),studio-BlackoutPeriods-test只有 1 item——legacy 表的数据量反而更多。下次部署清理前必须先把 29 items 迁移到studio-*,否则丢数据。 - 缺少: LeadTracking(CDK 未部署到 test)、ConnectionService(孤儿表,从未创建)、Legacy 4 张(Pre-CDK 手动创建)
实体关系¶
全局关系图¶
完整的 DynamoDB 全量表关系图(21 张表 · 36 GSIs · 色彩分组 + 关系箭头),源文件:
diagrams/dynamodb.drawio
数据隔离模型¶
storeId 是数据围墙 — 每个门店只能看到自己电话号码关联的数据:
老板 (userId)
├── 门店 A (storeId-A)
│ ├── +1914265xxxx ──→ 门店 A 的 SMS / 通话 / 线索
│ └── +1914265xxxx ──→ 门店 A 的 SMS / 通话 / 线索
│
└── 门店 B (storeId-B)
├── +1978489xxxx ──→ 门店 B 的 SMS / 通话 / 线索
└── +1978489xxxx ──→ 门店 B 的 SMS / 通话 / 线索
❌ 门店 A 看不到门店 B 的数据
❌ 同一个客户在两家店 = 两条独立记录
✅ 老板可以切换门店分别查看
Phone Management 数据流¶
核心问题:哪个电话号码属于哪个门店?
graph LR
UC[UserConnections] -->|providerAccountId| PN[PhoneNumbers]
PN -->|phoneNumber| PSA[PhoneStoreAssignments]
PSA -->|storeId| ST[StoresV2]
注意事项¶
siteId ≠ storeId — 两个完全不同的字段!
call-analysis.siteId=providerAccountId(numeric,RingCentral 账号 ID,如277275028)StoresV2.storeId= UUID(如18a16bde-8f20-4442-9b95-35f9d144b0e7)- 两者不可互换! 要从通话记录关联到门店:
phoneNumber → PhoneStoreAssignments → storeId call-analysis.clientId=franchise-providerAccountId(如orangeTheory-277275028)call-analysis.franchise= 品牌名(如orangeTheory)—— GSIfranchise-callStartTime-index/franchise-siteId-index用此字段
⚠️ siteId / providerAccountId 即将 rename → accountId
siteId 已统一 rename 为 account_id(callytics-common 0.22.0,migration 0016,2026-04-25 完成)。GSI 索引名 franchise-siteId-index 等不会变(DDB 索引名不能改名),但 item 内字段名已切换。详见 identity-fields.md §1.3 + docs/archive/identity-naming-history.md 演变史。
表名前缀
| 前缀 | Repo | CDK Stack |
|---|---|---|
call-analytics-prod-* |
callytics-infrastructure |
CallAnalytics-Prod-Storage |
ConnectionService-*-prod |
(已归档) ringcentralService |
(已删除) ⚠ 孤儿表 |
orangetheory-*-prod |
studio-website-monorepo |
OrangeTheoryStack-prod(旧品牌前缀) |
studio-*-prod |
studio-website-monorepo |
OrangeTheoryStack-prod(新前缀,勿用 orangetheory-) |
LeadTracking-v2-* |
lead-tracking |
LeadTrackingStack |
rc-subscription-prod-* |
ringcentralSubscriptionService |
RCSubscription-prod-Storage |
PhoneNumbers 表的 extensionId 字段类型不一致:有分机的号码为 Number 类型,无分机的为空 String。代码需兼容两种类型。
Archive 候选清单¶
审计日期: 2026-04-23 · AWS CLI 实查 + CDK 代码引用 + 全仓库 grep 交叉验证 2026-03-02 首次 audit;2026-04-23 deep re-audit 发现 RCU 数据与前次结论的 drift(见各节 live 提示)。
🔴 DEAD — archive 前必须 CloudTrail 追踪读源¶
2026-04-23 live 发现:DEAD 表并非完全零读
aws cloudwatch get-metric-statistics --metric-name ConsumedReadCapacityUnits --period 604800 显示所有 4 张 DEAD 表在过去 7 天都有 2-16 RCU 的读取。读量极低,但 "零业务读写" 的旧结论已被证伪。archive 前必须用 CloudTrail 定位读源,否则冒 "删掉仍在 low-volume 被读的表" 风险。
另:client-configurations 经 aws lambda get-function-configuration RingCentralTokenRefresher-Multi-Tenant 验证,运行时 env var CLIENT_CONFIG_TABLE_V1=client-configurations 被设置(而非 doc 之前推断的空串)——这是 legacy Python Lambda,属于 ConnectionService-CallAnalysisConfigurations-prod 的同批退役范围。
| 表名 | 数据量 | DP | 7d RCU | 前置步骤 | 说明 |
|---|---|---|---|---|---|
CallAnalysisMetadata |
401 条 / 117KB | ❌ | 16 | CloudTrail 追源 → 确认后删除 | 更早期格式,零活跃引用 |
client-configurations |
2 条 / 1.5KB | ❌ | 2 | 退役 RingCentralTokenRefresher-Multi-Tenant(Python,非 CDK)后删除 |
运行时被 CLIENT_CONFIG_TABLE_V1 env var 引用 |
ConnectionService-UserOrganizations-prod |
62 条 | ✅ | 2.5 | CloudTrail 追源 → 关闭 DP → 删除 | 零活跃代码引用,新模型用 UserStore |
ConnectionService-SubAccountLinks-prod |
13 条 | ✅ | 2 | CloudTrail 追源 → 关闭 DP → 删除 | 零活跃代码引用,新模型用 SubAccounts |
🟡 LEGACY — 需完成前置步骤后 archive¶
ConnectionService 低活跃表(3 张) — 功能已被 orangetheory-* 替代。callytics-infrastructure 中有 V2 config loader 引用,但 USE_V2_CONFIG_LOADER=false(未启用)。
| 表名 | DP | 替代表 | 前置步骤 |
|---|---|---|---|
ConnectionService-Organizations-prod |
✅ | orangetheory-StoresV2-prod |
① 确认 V2 loader 不再需要 ② 关闭 DP |
ConnectionService-Connections-prod |
✅ | orangetheory-UserConnections-prod |
① 同上 ② 关闭 DP |
ConnectionService-OrgConfigurations-prod |
✅ | StoresV2.businessConfig |
① 同上 ② 关闭 DP |
ConnectionService-CallAnalysisConfigurations-prod(🟢 仍活跃)
| 属性 | 值 |
|---|---|
| DP | ✅ |
| 7d RCU | ~450 ← 仍有大量读取(2026-04-23 确认) |
| 替代表 | call-analytics-prod-call-analysis-config-us-east-1(8 条,CDK 管理) |
| 仍在读取的 Lambda | RingCentralTokenRefresher-Multi-Tenant(Legacy Python,非 CDK 管理),env var CONFIG_TABLE_NAME=ConnectionService-CallAnalysisConfigurations-prod |
| 关联 DEAD 读源 | 同一 Legacy Lambda env var CLIENT_CONFIG_TABLE_V1=client-configurations —— 同批退役 |
| 前置步骤 | ① 退役 Legacy Lambda(CDK 替代: orangetheory-token-refresh-prod,已在运行) ② 切换 USE_V2_CONFIG_LOADER 到新表 ③ 关闭 DP |
Legacy 通话表(2 张) — callytics-infrastructure/lib/config/production-resources.ts 中硬编码了 ARN(fromTableArn 引用)。
2026-04-23 live 发现:Legacy 表仍有显著读取流量
这两张表不是 quiet legacy —— 7 天 RCU Sum 分别为 call-analysis=3,482 和 call-events=8,819。"前置步骤 ②(确认零业务读写)" 目前不满足,archive 前必须 CloudTrail 追源并迁移 caller。
| 表名 | 数据量 | DP | 7d RCU | 前置步骤 |
|---|---|---|---|---|
call-analysis |
20,487 条 / 27MB | ✅ | 3,482 | ① 移除 production-resources.ts 中的 ARN 引用 ② CloudTrail 追源,迁移 caller 到 -prod- 新表 ③ 确认零业务读写 ④ 关闭 DP |
call-events |
24,550 条 / 69MB | ✅ | 8,819 | ① 同上 |
Test 环境重复表(2 张)
| 表名 | 环境 | 说明 |
|---|---|---|
orangetheory-BlackoutPeriods-test |
us-west-2 | 与 studio-BlackoutPeriods-test 重复 |
orangetheory-OperatingHours-test |
us-west-2 | 与 studio-OperatingHours-test 重复 |
Archive 优先级¶
Phase 1 (立即): CallAnalysisMetadata, client-configurations,
ConnectionService-UserOrganizations, ConnectionService-SubAccountLinks
→ 零引用零读写,风险最低
Phase 2 (退役 Legacy Lambda 后): ConnectionService-CallAnalysisConfigurations-prod
→ 需先退役 RingCentralTokenRefresher-Multi-Tenant
Phase 3 (清理 V2 loader 引用后): ConnectionService-Organizations/Connections/OrgConfigurations
→ 需确认 USE_V2_CONFIG_LOADER 代码路径可移除
Phase 4 (清理 production-resources.ts 后): call-analysis(legacy), call-events(legacy)
→ 需移除 callytics-infrastructure 中的 hardcoded ARN 引用
Phase 5 (Test 清理): orangetheory-BlackoutPeriods-test, orangetheory-OperatingHours-test
→ 下次 CDK deploy 时清理
删除操作步骤¶
# Step 1: 关闭 Deletion Protection(需要的表)
aws dynamodb update-table \
--table-name <TABLE_NAME> \
--no-deletion-protection \
--region us-east-1
# Step 2: 删除表
aws dynamodb delete-table \
--table-name <TABLE_NAME> \
--region us-east-1
删除前 checklist
- 确认 7 天 CloudWatch RCU/WCU = 0(或已确认来源并切换)
- grep 所有活跃代码仓库确认 0 引用
- 确认数据不需要归档(如需要,先导出到 S3)
- 在 test 环境先执行删除,观察 7 天无报错
- 最后在 prod 执行
安全现状¶
保护状态总览¶
每张 prod 持久表都有三层保护:DP(Deletion Protection,防 API/Console 误删)、RETAIN(removalPolicy,防 cdk destroy 误删)、PITR(Point-in-Time Recovery,防数据损坏,可恢复 35 天内任意时间点)。
⚠️ 2026-04-23 live 审计发现:Call Analytics 3 张 prod 表 DP + PITR 未启用
CDK code 中 lib/stacks/storage-stack.ts:131-138, 161-168, 279-286 intent 正确(deletionProtection: envConfig.environmentName === 'prod' + pointInTimeRecoverySpecification),但 CallAnalytics-Prod-Storage stack LastUpdatedTime = 2026-02-04,CDK 保护代码 2026-03-02 才 commit(SHA c129c1d)——从未 deploy 到 prod。52 天 risk window。
$ aws dynamodb describe-table --table-name call-analytics-prod-call-analysis-us-east-1 \
--region us-east-1 --query 'Table.DeletionProtectionEnabled'
false
$ aws dynamodb describe-continuous-backups --table-name call-analytics-prod-call-analysis-us-east-1 \
--region us-east-1 \
--query 'ContinuousBackupsDescription.PointInTimeRecoveryDescription.PointInTimeRecoveryStatus'
"DISABLED"
同样问题影响 call-analytics-prod-call-events-us-east-1 + call-analytics-prod-call-analysis-config-us-east-1。另:rc-subscription-prod-webhook-subscriptions DP 也是 False(PITR ✅,单项漂移)。
Ops 追踪见 infra#656 — 需要 out-of-band aws dynamodb update-table --deletion-protection-enabled + update-continuous-backups,然后 deploy-prod.yml 让 CF 模板对齐。Deploy cadence meta 追踪见 infra#659。
| 分组(表数) | Prod DP | Prod RETAIN | Prod PITR | Test DP | Test RETAIN | Test PITR |
|---|---|---|---|---|---|---|
| Call Analytics (3) | ⚠️ intent=✅ / live=❌ | ✅ | ⚠️ intent=✅ / live=❌ | ❌ | ❌ | ❌ |
| Studio 持久表 (8) | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
| LeadTracking (1) | ✅ | ✅ | ✅ | — | — | — |
| RC webhook-subscriptions (1) | ⚠️ intent=✅ / live=❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
| Message System (2) | — | — | — | ❌ | ❌ | ❌ |
| 瞬态表 (3: OAuthStates, Cache, idempotency) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
Prod: ⚠️ 4 张应 ✅✅✅ 的持久表实际 DP=False(3 张 Call Analytics + 1 张 webhook-subscriptions),pending ops 修复。Studio 持久表 + LeadTracking 验证 ✅✅✅。瞬态表(TTL 自动过期)无需保护。
Test: 全部 ❌❌❌,允许随时重建。— = 该环境无此表。
ConnectionService 孤儿表和 Legacy 表的保护状态见 Archive 候选。
其他配置¶
| 配置项 | 当前状态 | 备注 |
|---|---|---|
| 计费模式 | 全部 PAYPERREQUEST | 当前规模合适 |
| KMS 加密 | 仅 ConnectionService(6 张,共用 1 个 KMS key) | 含 PII 的表应启用 |
| DynamoDB Streams | ConnectionService 5 张表(NEW_AND_OLD_IMAGES) |
call-analysis 表待启用 NEW_IMAGE |
| TTL | OAuthStates (ttl)、Cache (ttl)、idempotency (expiration) = 3 张 |
瞬态数据表 |
| CDK Tags | callytics 3 + ConnectionService 6 + RC Subscription 2 = 11 张 | orangetheory-、studio-、LeadTracking 缺少 tags |