- 21~26 Flutter 社区接入五单 + 字典 v3 白名单(flutter 286→502、api 325→334) - 27 收口总表:社区 demo 三页消亡、M3 四条验收标准逐条取证、 乐观更新与媒体链路端到端、实现期修正记录 - device-verification.md 的 M3 四项真机步骤已由各单收口补全 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
5.5 KiB
22 事件字典 v3 白名单扩充(T3-20 后端,ADR-020)
执行日期:2026-09-09
交付:EventDictionary v2 → v3(22 → 42 事件)+ 全套边界测试,patbond-api dev @ 8089c06
依据:06 号报告 §1.4/§1.5(事件与 props schema)、§1.2(feed_viewed 聚合裁定)、§1.3(隐私红线增量)、§6.1(pageName 页面族)
0. 概要
| 项 | 值 |
|---|---|
| 新增事件 | 20(06 号 §1.5 的 19 个 + experiment_exposed 已含其中,编号 22~40) |
| 字典总量 | 22 → 42 |
| 测试 | 325 → 334(+9:EventDictionaryTest +6、AnalyticsIntegrationTest +3),全绿 |
| openapi.yaml | 零变更——/api/v1/events 契约对事件名开放(键级校验在字典层),复核无需动 |
| check-secrets.sh --all | 通过(exit 0) |
改动仅限 patbond-user analytics 包三个文件:EventDictionary.java、EventDictionaryTest.java、AnalyticsIntegrationTest.java。
1. 新增事件与 06 号对照清单
props 键集与 06 号 §1.5「工单可直接抄」代码块逐键一致(原样落地,零偏差):
| # | 事件名 | props 白名单 | 06 号出处 |
|---|---|---|---|
| 22 | post_create_started |
entryPoint | §1.4 发布漏斗 |
| 23 | post_draft_saved |
trigger, mediaCount | §1.4 发布漏斗 |
| 24 | post_publish_succeeded |
durationMs, mediaCount, topicCount, textLengthBucket, fromDraft | §1.4 发布漏斗(漏斗事件) |
| 25 | post_publish_failed |
failureReason, errorCode, httpStatus, attemptSeq | §1.4 发布漏斗 |
| 26 | post_deleted |
(空集——单事件风格无专有属性) | §1.4 发布漏斗 |
| 27 | post_media_upload_started |
mediaType, sizeBucket | §1.4 媒体漏斗(逐文件) |
| 28 | post_media_upload_succeeded |
mediaType, sizeBucket, durationMs | §1.4 媒体漏斗(漏斗事件) |
| 29 | post_media_upload_failed |
mediaType, sizeBucket, failureReason, errorCode, httpStatus, attemptSeq | §1.4 媒体漏斗 |
| 30 | feed_viewed |
feedTab, durationMs, impressionCount, loadMoreCount, refreshCount | §1.2/§1.4 聚合曝光(首个高频事件) |
| 31 | feed_load_failed |
feedTab, loadType, failureReason, errorCode, httpStatus | §1.4 Feed 消费 |
| 32 | post_liked |
source | §1.4 互动 |
| 33 | post_unliked |
source | §1.4 互动 |
| 34 | post_favorited |
source | §1.4 互动 |
| 35 | post_unfavorited |
source | §1.4 互动 |
| 36 | comment_create_succeeded |
durationMs, isReply, textLengthBucket | §1.4 互动 |
| 37 | comment_create_failed |
failureReason, errorCode, httpStatus, attemptSeq | §1.4 互动 |
| 38 | user_followed |
source | §1.4 互动 |
| 39 | user_unfollowed |
source | §1.4 互动 |
| 40 | experiment_exposed |
experimentKey, variant | §1.4 实验基建(A/B 前置 #5,M4 启用字典先行) |
故意不进字典(测试侧同步锁死为 unknown):post_impression(§1.2 逐卡曝光否决)、post_viewed(§1.4 由 page_viewed(post_detail) 覆盖)、comment_create_started(短表单不设 started)、post_like_failed/user_follow_failed 等单点互动失败(靠服务端错误率观测)、topic_followed/unfollowed(§1.6 缺口 3,UI 定稿前挂起待拍板)。
2. pageName 页面族核对(§6.1)
字典侧 pageName 的登记处只有 EventDictionary 的 javadoc 注释(ingest 只校验 props 键,page_viewed 键集 pageName/referrer 不变)——已按 §6.1 同步为 v3 页面族:v2 九个 + 收编 4(create/pet_archive/services/post_detail)+ 新增 9(post_form/topic_list/topic_detail/user_profile/follower_list/following_list/favorite_list/draft_list)。与 §6.1「后端零改动提示」一致,无任何校验代码变更;值级枚举仍由客户端编译期 + 离线巡检兜底。
3. 测试增量(325 → 334)
EventDictionaryTest +6(沿既有 containsExactlyInAnyOrder 键集锁定模式):
v3PostPublishFunnelMatchesDictionary— 发布漏斗五事件,含 post_deleted 空集断言v3MediaUploadFunnelMatchesDictionary— 媒体三段漏斗v3FeedDomainMatchesDictionary— feed_viewed 聚合键集(无任何内容 ID 键)+ feed_load_failedv3InteractionEventsMatchDictionary— 互动八事件(分立事件名,无 action 属性)v3ExperimentExposedRegisteredAheadOfM4Use— experimentKey/variantv3DeliberatelyAbsentEventsStayUnknown— §1 末段七个故意不设事件
AnalyticsIntegrationTest +3(沿 v2 端到端先例):
acceptsV3FeedViewedAggregateEvent— feed_viewed 全键入库落表stripsContentIdPropsFromV3InteractionEvent— post_liked 混入白名单外postId被剥离(红线 2 的 ingest 侧兜底)rejectedPerCardImpressionStaysOutOfDictionary— post_impression 按 unknown_event_name 拒绝(§1.2 裁定锁死)
全套 ./mvnw clean test:334 测试 0 失败(user/auth/pet/community/common 五模块 BUILD SUCCESS)。
4. 边界与遗留
- 契约零变更:events 接口对事件名开放,openapi.yaml/契约快照均不需动,本工单未触碰。
- Flutter 半边未动:客户端强类型封装(post_analytics.dart / feed_analytics.dart / community_interaction_analytics.dart / analytics_page_name.dart 增量)属 T3-20 客户端半边,不在本工单。
- 待拍板项不预埋:
content_rejected失败枚举(审核环节待拍板)与topic_followed(UI 定稿)均未进字典,拍板后按 eventVersion 惯例增补。