feat(ops): ECR-007 行为分析与 ECR-008 内容运营后台
落地埋点 ingest/数据看板、首页宫格 CMS 与测评上下架;含账号引导、问答流式与免责声明去重,以及 review P1 审计同事务修复。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
# Backend Design: ECR-007 运营行为分析 Ops-B
|
||||
|
||||
> Architect 产出;Engineer 只消费本文件。
|
||||
> 实现纪律:`$ESS_ROOT/technology-governance/BACKEND_STANDARD.md`
|
||||
> 项目分层权威:`.ai/architecture.md` · Handler → Service → Repository
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| ID | BD-2026-007 |
|
||||
| ECR | ECR-007 |
|
||||
| Change Level | L2 |
|
||||
| Status | Approved(2026-08-07 Human) |
|
||||
| Author | Architect |
|
||||
| Date | 2026-08-07 |
|
||||
| Risk | Medium |
|
||||
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
- 问题 / 目标:缺自有行为数据与运营看板;需页停留、退出页、点击、会话级指标。
|
||||
- 非目标:CMS/RBAC/OLAP/热力图;见 ECR Forbidden。
|
||||
- 相关 Spec:`ops-analytics.md`;无新 ADR(Postgres 足够,栈不变)。
|
||||
|
||||
## Architecture Change
|
||||
|
||||
- 是否改变分层边界:No
|
||||
- 受影响层:API · Application(`service/analytics` + admin 扩展)· Infrastructure(repo + migration)· UI(user-h5 analytics · admin-h5 数据页)
|
||||
|
||||
## Module Changes
|
||||
|
||||
| Module | Layer | Change | Must NOT |
|
||||
|--------|-------|--------|----------|
|
||||
| `handler` analytics ingest | API | bind、DeviceAuth、调 service | SQL;业务规则堆 handler |
|
||||
| `service/analytics` | Application | 校验批量、截断、写 session/event | 直连 gin |
|
||||
| `repository/analytics_repo.go` | Infrastructure | SQL ingest + 聚合 | 泄漏到 UI |
|
||||
| `handler/admin` analytics GET | API | AdminAuth | Device 用户可访问 |
|
||||
| `user-h5/lib/analytics.ts` | UI | 队列上报 | 直打 DB;传 PII |
|
||||
| `admin-h5` 数据页 | UI | 展示聚合 | 裸拼绝对 API URL |
|
||||
|
||||
## Data Flow
|
||||
|
||||
```text
|
||||
user-h5 analytics queue
|
||||
→ POST /api/v1/analytics/events (X-Device-Key [+ Bearer])
|
||||
→ service/analytics → AnalyticsRepo
|
||||
→ analytics_events / analytics_sessions
|
||||
|
||||
admin-h5 「数据」
|
||||
→ GET /api/v1/admin/analytics/* (Admin Bearer)
|
||||
→ service/admin 或 service/analytics 只读聚合
|
||||
→ SQL group by day / page_path / element_id / funnel names
|
||||
```
|
||||
|
||||
## API Changes
|
||||
|
||||
- 契约:`proto/openapi.yaml` 增补
|
||||
- 兼容:纯新增路径
|
||||
- 信封:`{code,message,data}`
|
||||
|
||||
### Ingest(示意)
|
||||
|
||||
`POST /api/v1/analytics/events`
|
||||
Body: `{ items: [{ name, session_id, page_path?, client_ts, props? }] }`
|
||||
上限:≤100/请求;超限 400。
|
||||
|
||||
### Admin 聚合
|
||||
|
||||
| Path | data 要点 |
|
||||
|------|-----------|
|
||||
| `/admin/analytics/overview?from&to` | dau, new_users, sessions, avg_session_ms |
|
||||
| `/admin/analytics/pages` | page_path, pv, uv, avg_dwell_ms, exit_count |
|
||||
| `/admin/analytics/exits` | exit_page, count |
|
||||
| `/admin/analytics/clicks` | element_id, count |
|
||||
| `/admin/analytics/funnel` | steps[] name+count |
|
||||
|
||||
## Database Changes
|
||||
|
||||
- `analytics_sessions` · `analytics_events`
|
||||
- 可选 `analytics_daily_page`(实现期若查询慢再加,仍属本 ECR 允许)
|
||||
- Migration:`000013_analytics_ops.up.sql` / `.down.sql`
|
||||
- Immutable:events 只追加;不提供删除 API
|
||||
|
||||
## Migration Plan
|
||||
|
||||
- Required:YES
|
||||
- 步骤:expand 建表 → 部署 API → 开 H5 上报 → admin 看板
|
||||
- 回滚:关上报 + 下线路由 + down migration(非生产可)
|
||||
|
||||
## Failure Handling
|
||||
|
||||
- ingest 部分非法条目:整批 400 或跳过非法并计 dropped(选定一种写进实现注释,默认整批 400)
|
||||
- 未鉴权 Device:401
|
||||
- Admin 无 token:401
|
||||
- DB 错:500;客户端 track 吞错
|
||||
|
||||
## Test Plan
|
||||
|
||||
- Unit:props 截断、dwell 非负
|
||||
- Integration:login device → post events → admin overview/pages/exits
|
||||
- H5:analytics 队列 flush mock
|
||||
|
||||
## Rollback Plan
|
||||
|
||||
见 ECR Rollback。
|
||||
|
||||
---
|
||||
|
||||
## Backend Change Boundary(mandatory)
|
||||
|
||||
```text
|
||||
Change Level: L2
|
||||
Change: 自有 analytics ingest + admin 聚合看板
|
||||
|
||||
Affected:
|
||||
Domain:
|
||||
- AnalyticsSession / AnalyticsEvent
|
||||
Application:
|
||||
- service/analytics · admin analytics reads
|
||||
Infrastructure:
|
||||
- AnalyticsRepo · migration 000013
|
||||
API:
|
||||
- POST /api/v1/analytics/events
|
||||
- GET /api/v1/admin/analytics/*
|
||||
Migration: Required
|
||||
Tests:
|
||||
- ingest + admin aggregate path
|
||||
Risk: Medium
|
||||
```
|
||||
|
||||
## Architecture Regression Check
|
||||
|
||||
- [ ] 无 Handler 直连 DB
|
||||
- [ ] 无绕过 Service
|
||||
- [ ] Admin / Device 鉴权面隔离
|
||||
- [ ] 未引入非默认中间件
|
||||
- [ ] 未简化分层
|
||||
@@ -0,0 +1,128 @@
|
||||
# Backend Design: ECR-008 运营内容 Ops-C
|
||||
|
||||
> Architect 产出;Engineer 只消费本文件。
|
||||
> 项目分层:Handler → Service → Repository
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| ID | BD-2026-008 |
|
||||
| ECR | ECR-008 |
|
||||
| Change Level | L2 |
|
||||
| Status | Approved(2026-08-07 Human) |
|
||||
| Author | Architect |
|
||||
| Date | 2026-08-07 |
|
||||
| Risk | Medium |
|
||||
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
- 目标:首页宫格可运营配置;scales 可上下架。
|
||||
- 非目标:Feeds CMS、题目编辑器、外链图标、RBAC。
|
||||
- 无新 ADR。
|
||||
|
||||
## Architecture Change
|
||||
|
||||
- 分层边界:No
|
||||
- 层:API · Application · Infrastructure · UI(user-h5 home · admin-h5 内容)
|
||||
|
||||
## Module Changes
|
||||
|
||||
| Module | Layer | Change | Must NOT |
|
||||
|--------|-------|--------|----------|
|
||||
| `repository/home_tools` | Infra | CRUD / ReplaceAll | 泄漏到 UI |
|
||||
| `repository/scale` | Infra | ListAll · UpdateStatus | |
|
||||
| `service/home` 或 content | App | 白名单校验 · 事务替换 | 直连 gin |
|
||||
| `handler` home + admin | API | 绑定鉴权 | SQL |
|
||||
| `user-h5` useHomePage | UI | GET tools | 直写 DB |
|
||||
| `admin-h5` ContentPage | UI | 编辑保存 | 裸绝对 URL |
|
||||
|
||||
## Data Flow
|
||||
|
||||
```text
|
||||
admin-h5 内容页
|
||||
→ PUT /admin/home/tools → service → ReplaceAll + audit
|
||||
→ PATCH /admin/scales/:id → UpdateStatus + audit
|
||||
|
||||
user-h5 首页
|
||||
→ GET /home/tools → enabled 列表 → HomeToolGrid
|
||||
失败 → homeCatalog.ts 静态回退
|
||||
|
||||
C 端测评
|
||||
→ GET /scales(既有 ListPublished)
|
||||
```
|
||||
|
||||
## API Changes
|
||||
|
||||
- `GET /api/v1/home/tools` → `{ items: [{ id, row_index, sort_order, path, icon, label, badge?, badge_tone? }] }`
|
||||
- `GET /api/v1/admin/home/tools` → 含 `enabled`
|
||||
- `PUT /api/v1/admin/home/tools` body `{ items: [...] }` 整表替换
|
||||
- `GET /api/v1/admin/scales` → 全量含 status
|
||||
- `PATCH /api/v1/admin/scales/{id}` body `{ status: published|draft }`
|
||||
|
||||
## Database
|
||||
|
||||
```sql
|
||||
home_tools (
|
||||
id uuid PK,
|
||||
row_index smallint NOT NULL, -- 1 or 2
|
||||
sort_order int NOT NULL,
|
||||
path text NOT NULL,
|
||||
icon varchar(32) NOT NULL,
|
||||
label varchar(32) NOT NULL,
|
||||
badge varchar(8) NULL,
|
||||
badge_tone varchar(8) NULL,
|
||||
enabled boolean NOT NULL DEFAULT true,
|
||||
updated_at timestamptz NOT NULL DEFAULT now()
|
||||
)
|
||||
```
|
||||
|
||||
Migration:`000014_ops_content.up.sql` / `.down.sql`
|
||||
|
||||
## Validation
|
||||
|
||||
- icon ∈ 既有 HomeToolIcon 名集合
|
||||
- path 匹配 `^/[a-zA-Z0-9_./-]{1,120}$` 且不含 `..`
|
||||
- row_index ∈ {1,2};label 1–16 字;items ≤ 24
|
||||
- status ∈ {published, draft}
|
||||
- 非法整批 400
|
||||
|
||||
## Failure Handling
|
||||
|
||||
- Admin 无 token:401
|
||||
- scale 不存在:404
|
||||
- DB:500;H5 拉 tools 失败静默回退静态
|
||||
|
||||
## Test Plan
|
||||
|
||||
- Unit:path/icon 校验
|
||||
- Integration:seed → PUT 改 enabled → GET home 少一项;PATCH draft → ListPublished
|
||||
|
||||
## Rollback
|
||||
|
||||
见 ECR。
|
||||
|
||||
---
|
||||
|
||||
## Backend Change Boundary
|
||||
|
||||
```text
|
||||
Change Level: L2
|
||||
Change: home_tools CMS + scales status admin
|
||||
|
||||
Affected:
|
||||
Domain: HomeTool
|
||||
Application: service/home · admin scales
|
||||
Infrastructure: HomeToolsRepo · ScaleRepo · 000014
|
||||
API: /home/tools · /admin/home/tools · /admin/scales
|
||||
Migration: Required
|
||||
Tests: integration content ops
|
||||
Risk: Medium
|
||||
```
|
||||
|
||||
## Architecture Regression Check
|
||||
|
||||
- [ ] 无 Handler 直连 DB
|
||||
- [ ] Admin / Device 鉴权隔离
|
||||
- [ ] 未引入非默认中间件
|
||||
- [ ] 未简化分层
|
||||
Reference in New Issue
Block a user