# 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` 键集锁定模式): 1. `v3PostPublishFunnelMatchesDictionary` — 发布漏斗五事件,含 post_deleted 空集断言 2. `v3MediaUploadFunnelMatchesDictionary` — 媒体三段漏斗 3. `v3FeedDomainMatchesDictionary` — feed_viewed 聚合键集(无任何内容 ID 键)+ feed_load_failed 4. `v3InteractionEventsMatchDictionary` — 互动八事件(分立事件名,无 action 属性) 5. `v3ExperimentExposedRegisteredAheadOfM4Use` — experimentKey/variant 6. `v3DeliberatelyAbsentEventsStayUnknown` — §1 末段七个故意不设事件 **AnalyticsIntegrationTest +3**(沿 v2 端到端先例): 1. `acceptsV3FeedViewedAggregateEvent` — feed_viewed 全键入库落表 2. `stripsContentIdPropsFromV3InteractionEvent` — post_liked 混入白名单外 `postId` 被剥离(红线 2 的 ingest 侧兜底) 3. `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 惯例增补。