merge: 合入本地 Ops 扩展与 origin/main(ECR-009–016)

保留远程用户侧 ECR-009–016 与本地 Ops 目录/RBAC/CMS/危机等能力;文档标注分叉期间 ECR 编号冲突。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
jackyu66git
2026-08-13 01:45:53 +08:00
co-authored by Cursor
593 changed files with 21918 additions and 328 deletions
+6 -1
View File
@@ -3,5 +3,10 @@
| File | Purpose |
|---|---|
| [../domain.md](../domain.md) | Tech ↔ 用户名 |
| [domain-map.md](domain-map.md) | Bounded contexts冻结 |
| [domain-map.md](domain-map.md) | Bounded contextsP1 冻结 + Ops Wave 0 Draft |
| [erd.md](erd.md) | P1 表结构草案(冻结) |
| [boundary-rules.md](boundary-rules.md) | BC owns / allowed / forbidden**P0** · Wave 0 |
| [glossary.yaml](glossary.yaml) | 工程/API 唯一词(与 lexicon 双轨) |
| [entity-catalog.md](entity-catalog.md) | 概念级实体目录(无 migration |
Ops Contract-First 归档:`docs/WAVE0/`
+239
View File
@@ -0,0 +1,239 @@
# Bounded Context Boundary Rules
> Wave 0 · **P0 资产** · AI / Engineer 只读;变更须 Architect + Human
> 运行时权威副本:`.ai/domain/boundary-rules.md`
Status: `Draft`Human Review 后 Frozen
---
## 如何读
- **owns**:该 BC **唯一写权威**(修改入口)。
- **does_not_own**:明示禁止「顺手改」。
- **allowed**:允许的依赖(多为读或经门面)。
- **forbidden**:禁止的依赖(含跨 BC 写支付/会员等)。
违反本文件 = Reviewer **BLOCK**(架构回归)。
---
## Admin_Auth_Audit
```yaml
Admin_Auth_Audit:
owns:
- AdminAccount
- AdminSession
- AuditLog
does_not_own:
- UserStatus
- MembershipPlan
- Entitlement
allowed:
- Admin_RBAC.read
forbidden:
- Payment.write
- C端业务聚合根的隐式写入
```
## Admin_RBAC
```yaml
Admin_RBAC:
owns:
- AdminRole
- AdminPermission
does_not_own:
- User
- Profile
- Membership
allowed:
- Admin_Auth_Audit.write_audit
forbidden:
- Payment
- Membership.write
- DeviceAuth.user_token_issue
```
## Identity_Profile
```yaml
Identity_Profile:
owns:
- User
- Profile
- DeviceIdentity
- UserStatus
- BehaviorSnapshot
- PsychologicalTagSet
does_not_own:
- MembershipPlan
- Entitlement
- Order
- Payment
- RedemptionCode
allowed:
- Analytics_OpsB.read
forbidden:
- Payment
- Membership.write
```
## Membership_Orders
```yaml
Membership_Orders:
owns:
- MembershipPlan
- Entitlement
- Membership
- Order
- DeepAccess
- RedemptionCode
- Payment # mock 今;真支付适配器后置,仍归本 BC
does_not_own:
- UserStatus
- AdminRole
- FilterRule
allowed:
- Identity_Profile.read
forbidden:
- Ask_Ops.write_prompt
- Content_Safety.rule_mutate_via_order
```
## Analytics_OpsB
```yaml
Analytics_OpsB:
owns:
- AnalyticsSession
- AnalyticsEvent
does_not_own:
- User
- Membership
allowed:
- Identity_Profile.read_ids_only
forbidden:
- Payment
- 采集 PII 正文(生日/问答全文等)
```
## Ops_Content
```yaml
Ops_Content:
owns:
- HomeTool
- ScalePublishState
does_not_own:
- Scale 题目正文编辑器(未开 ECR 前禁止扩张)
allowed:
- Explore_Reports.publish_gate
forbidden:
- Community
- Payment
```
## Account_Risk
```yaml
Account_Risk:
owns:
- RiskFlag
- BanRecord
does_not_own:
- MembershipPlan
allowed:
- Identity_Profile.UserStatus.transition # 经明确应用服务
- Admin_Auth_Audit.write_audit
forbidden:
- Payment.refund_silent
```
## Content_Safety
```yaml
Content_Safety:
owns:
- FilterRule
- ModerationCase
- BlockPolicy
- CrisisEvent
- CrisisPolicy
does_not_own:
- Membership
- Payment
- AdminRole
allowed:
- Identity_Profile.read
- Ask_Ops.read_session_meta
forbidden:
- Membership.write
- Payment
```
## Ask_Ops
```yaml
Ask_Ops:
owns:
- AskSessionView
- QualityFeedback
- HandoffCase
- SystemPrompt
- KnowledgeSource
- KnowledgeChunk
- ToolDefinition
does_not_own:
- Payment
- MembershipPlan
- UserStatus
allowed:
- Identity_Profile.read
- Content_Safety.evaluate
forbidden:
- Payment
- Membership.write
- Admin_RBAC.write
```
## Ops_CMS_NoUGC
```yaml
Ops_CMS_NoUGC:
owns:
- Banner
- FeedSlot
- ScheduledPublication
does_not_own:
- UGC Post
- CommentGraph
- TrustScore
allowed:
- Admin_RBAC.check
forbidden:
- Community
- 用户生成内容入库为主路径
```
## Community
```yaml
Community:
status: Forbidden
owns: []
note: feature-map UGC 广场 [No];开启须 L3 ADR + 新 Capability
```
---
## 反模式(禁止)
```text
AskService → load User → update Membership → charge Payment
UserService.updateMembership()
Content_Safety 直接改 Entitlement
Ops_CMS 引入「用户帖子」表却声称 NoUGC
```
+20
View File
@@ -23,6 +23,26 @@
---
## Ops Platform Bounded ContextsWave 0 Draft
> 详细 owns/forbidden[`boundary-rules.md`](boundary-rules.md) · 词表:[`glossary.yaml`](glossary.yaml) · 实体:[`entity-catalog.md`](entity-catalog.md)
> 归档:`docs/WAVE0/domain/` · Capability`docs/WAVE0/capability/ops-capability-map.md`
> **不修改**上方 P1 不变量;Ops BC 实现须独立 ECR。
| Context | Capability | Status |
|---|---|---|
| Admin_Auth_Audit | AdminGovernance | Shipped Ops-A |
| Admin_RBAC | AdminGovernance | Draft → ECR-013A |
| Analytics_OpsB | GrowthInsights / UserIntelligence(read) | Shipped Ops-B |
| Ops_Content | ExploreConfig (partial) | Shipped Ops-C |
| Account_Risk | AccountLifecycle | Spec via ECR-013BIdentity_Profile owns UserStatus |
| Content_Safety | ContentSafety · CrisisCare | ContentSafety **ECR-019**CrisisCare **ECR-022**CrisisPolicy 只读) |
| Ask_Ops | AskOperations · AICoreConfig | AskOperations **ECR-017/020**AICoreConfig **ECR-021**SystemPrompt 只读) |
| Ops_CMS_NoUGC | OpsCMS | Draft |
| Community | — | **Forbidden** |
---
## Context diagram
```
+43
View File
@@ -0,0 +1,43 @@
# Entity CatalogWave 0 · 概念级)
> 仅登记名称、归属 BC、Capability、生命周期备注。**不建表、不写 migration。**
> 与 [`glossary.yaml`](glossary.yaml) · [`boundary-rules.md`](boundary-rules.md) 一致。
Status: `Draft`
| Entity | BC | Capability | Notes |
|--------|----|------------|-------|
| AdminAccount | Admin_Auth_Audit | AdminGovernance | 已存在 Ops-A |
| AdminSession | Admin_Auth_Audit | AdminGovernance | 已存在 |
| AuditLog | Admin_Auth_Audit | AdminGovernance | 已存在;只追加 |
| AdminRole | Admin_RBAC | AdminGovernance | **ECR-013A** |
| AdminPermission | Admin_RBAC | AdminGovernance | **ECR-013A** |
| User | Identity_Profile | AccountLifecycle | 已存在 |
| Profile | Identity_Profile | UserIntelligence | 已存在 |
| UserStatus | Identity_Profile | AccountLifecycle | **ECR-013B** 状态机 |
| AccountStateTransition | Identity_Profile | AccountLifecycle | **ECR-013B** |
| BehaviorSnapshot | Identity_Profile | UserIntelligence | **ECR-016** 读模型(analytics 聚合) |
| PsychologicalTagSet | Identity_Profile | UserIntelligence | **ECR-016** 由报告 type 派生 |
| MembershipPlan | Membership_Orders | CommerceEntitlement | **ECR-014 Closed** |
| Entitlement | Membership_Orders | CommerceEntitlement | **ECR-018** 读模型(MembershipDeepAccess |
| RedemptionCode | Membership_Orders | CommerceEntitlement | **ECR-015 Closed** |
| Membership | Membership_Orders | CommerceEntitlement | 已存在 |
| Order | Membership_Orders | CommerceEntitlement | 已存在 |
| DeepAccess | Membership_Orders | CommerceEntitlement | 已存在 |
| Payment | Membership_Orders | CommerceEntitlement | mock;真支付最后 |
| HomeTool | Ops_Content | ExploreConfig | 已存在 Ops-C |
| ScalePublishState | Ops_Content | ExploreConfig | 已存在 |
| AnalyticsSession / Event | Analytics_OpsB | GrowthInsights | 已存在 Ops-B |
| FilterRule | Content_Safety | ContentSafety | **ECR-019** 只读 + evaluate |
| ModerationCase | Content_Safety | ContentSafety | 后置 |
| CrisisEvent / CrisisPolicy | Content_Safety | CrisisCare | **ECR-022** CrisisPolicy 只读;CrisisEvent 后置 |
| SystemPrompt / Knowledge* / ToolDefinition | Ask_Ops | AICoreConfig | **ECR-021** SystemPrompt 只读;Knowledge/Tools 后置 |
| AskSessionView / QualityFeedback | Ask_Ops | AskOperations | **ECR-017** AskSessionView**ECR-020** QualityFeedback |
| Banner / FeedSlot | Ops_CMS_NoUGC | OpsCMS | 后置 |
| UGC* | Community | — | **Forbidden** |
## 状态机(ECR-013B · 契约已开)
`UserStatus`: 见 `.ai/product/feature-spec/ops-account-lifecycle.md`
`deleted` soft-delete **不在 013B**(另开)。
实现轮前:**禁止** migration / DeviceAuth 改动。
+116
View File
@@ -0,0 +1,116 @@
# domain glossary — engineering / API unique terms
# Wave 0 Draft. Runtime copy: .ai/domain/glossary.yaml
# User-facing copy stays in .ai/product/lexicon.md
# Conflict: Architect + Human resolve; do not invent synonyms in code.
version: "0.1.0"
status: draft
terms:
AdminRole:
zh: 管理员角色
bc: Admin_RBAC
forbidden: [admin_group, privilege_group]
AdminPermission:
zh: 管理员权限点
bc: Admin_RBAC
forbidden: [acl_flag, authz_bit]
AuditLog:
zh: 操作审计日志
bc: Admin_Auth_Audit
forbidden: [admin_history]
UserStatus:
zh: 用户账户状态
bc: Identity_Profile
values: [active, disabled, banned, suspended]
forbidden: [user_flag, account_level]
AccountStateTransition:
zh: 账户状态迁移
bc: Identity_Profile
forbidden: [status_patch_log]
MembershipPlan:
zh: 会员套餐
bc: Membership_Orders
forbidden: [package, vip_level, 订阅档, sku_vip]
Entitlement:
zh: 权益
bc: Membership_Orders
forbidden: [privilege_pack, benefit_bundle]
RedemptionCode:
zh: 兑换码
bc: Membership_Orders
forbidden: [gift_card, activation_key_alias]
DeepAccess:
zh: 深度版
bc: Membership_Orders
forbidden: [Unlock, unlock_report]
BehaviorSnapshot:
zh: 行为快照
bc: Identity_Profile
forbidden: [user_track_dump]
PsychologicalTagSet:
zh: 心理标签集
bc: Identity_Profile
forbidden: [psy_labels_raw]
FilterRule:
zh: 过滤规则
bc: Content_Safety
forbidden: [badword_only]
ModerationCase:
zh: 审核工单
bc: Content_Safety
forbidden: [review_ticket_ugc]
CrisisEvent:
zh: 危机事件
bc: Content_Safety
forbidden: [suicide_flag_public]
CrisisPolicy:
zh: 危机策略
bc: Content_Safety
forbidden: [kill_switch_generic]
SystemPrompt:
zh: 系统提示词
bc: Ask_Ops
forbidden: [god_prompt]
KnowledgeSource:
zh: 知识源
bc: Ask_Ops
forbidden: [rag_file]
KnowledgeChunk:
zh: 知识块
bc: Ask_Ops
forbidden: [embedding_row_ui]
ToolDefinition:
zh: 工具定义
bc: Ask_Ops
forbidden: [function_call_config_loose]
Banner:
zh: 运营横幅
bc: Ops_CMS_NoUGC
forbidden: [story_feed_ugc]
Community:
zh: (禁止能力)
bc: Community
status: forbidden
forbidden: [ugc_plaza, 社区广场]
+11 -9
View File
@@ -227,16 +227,18 @@ UI **不出现「塔罗」**。禁止神谕吉凶、恐吓话术。
## 7. 运营后台(内部 · 非 C 端 Tab)
详见 Spec[feature-spec/ops-admin.md](feature-spec/ops-admin.md) · ECR-006
详见 Spec[feature-spec/ops-admin.md](feature-spec/ops-admin.md) · ECR-006
**演进规范(Wave 0):** [`docs/WAVE0/`](../../docs/WAVE0/) · Capability Map · boundary-rules · Contract-First(禁止 Feature 堆砌进实现)
| 分期 | 内容 |
|---|---|
| Phase A `[Ops]` | 登录 · 用户/订单查询 · 会员授予 · 审计 · `apps/admin-h5`ECR-006 Closed |
| Phase B `[Ops]` | 行为分析:自有埋点 + 管理端「数据」看板(**ECR-007 Implemented** · Spec `ops-analytics.md` |
| Phase C `[Ops]` | 内容:首页宫格 CRUD · 测评上下架(**ECR-008 Implemented** · Spec `ops-content.md` |
| Phase B `[Ops]` | 行为分析:自有埋点 + 管理端「数据」看板(**ECR-007** · Spec `ops-analytics.md` |
| Phase C `[Ops]` | 内容:首页宫格 CRUD · 测评上下架(**ECR-008** · Spec `ops-content.md` |
| Phase D `[Ops]` | 商业加深:订单筛选 · 展示价 · 退款只读(**ECR-009** · Spec `ops-commerce.md` |
| Phase E `[Ops]` | 系统:RBAC · 封禁 · 推送占位(**ECR-010** · Spec `ops-system.md` |
| Phase F+ | 封禁细策略 · 真推送通道 · 更细权限矩阵(各开独立 ECR) |
| Phase D+ Contract | **Contract-First** 扩展目录:**ECR-013A…040**RBAC/兑换码/问答运营/安全/危机/CMS/ExploreConfig 等)。见 `docs/WAVE0/` |
| Phase F+ | 封禁细策略 · 真推送通道 · 更细权限矩阵;**UGC 仍 `[No]`**;真支付最后 |
不计入 P1 Complete;不进入五 Tab。
@@ -258,11 +260,11 @@ UI **不出现「塔罗」**。禁止神谕吉凶、恐吓话术。
| `/scales/:slug` | 探索测试作答 | |
| `/reports` | 成长报告列表 | |
| `/reports/:id` | 成长报告详情 | |
| `/star` | 星座 | P2 |
| `/synastry` | 合盘 | P2 |
| `/synastry/invite/:token` | 合盘邀请 | P2 |
| `/rhythm` | 身心节律 | P2 |
| `/cards` | 意象卡片 | P2 |
| `/star` | 星座 | P2 Complete |
| `/synastry` | 合盘 | P2 Complete |
| `/synastry/invite/:token` | 合盘邀请 | P2 Complete |
| `/rhythm` | 身心节律 | P2 Complete |
| `/cards` | 意象卡片 | P2 Complete |
兼容重定向:`/decode``/portrait`(仅技术兼容,UI 不出现 decode 文案)。
+29 -2
View File
@@ -21,11 +21,38 @@
| [life-rhythm.md](life-rhythm.md) | 身心节律 | §2.7 | `/rhythm` | P2 Complete |
| [image-card.md](image-card.md) | 意象卡片 | §2.8 | `/cards` | P2 Complete |
| [ops-admin.md](ops-admin.md) | 运营后台 | §7 | `admin-h5` `/` `/users/:id` … | Ops-A |
| [ops-analytics.md](ops-analytics.md) | 运营行为分析(埋点+数据看板) | §7 | `admin-h5` `/analytics` · H5 track | Ops-B · ECR-007 Implemented |
| [ops-content.md](ops-content.md) | 运营内容(宫格+测评上下架) | §7 | `admin-h5` `/content` · `GET /home/tools` | Ops-C · ECR-008 Implemented |
| [ops-analytics.md](ops-analytics.md) | 运营行为分析(埋点+数据看板) | §7 | `admin-h5` `/analytics` · H5 track | Ops-B · ECR-007 |
| [ops-content.md](ops-content.md) | 运营内容(宫格+测评上下架) | §7 | `admin-h5` `/content` · `GET /home/tools` | Ops-C · ECR-008 |
| [ops-commerce.md](ops-commerce.md) | 运营商业加深(订单筛选+展示价+退款只读) | §7 | `admin-h5` `/orders` `/pricing` | Ops-D · ECR-009 |
| [ops-system.md](ops-system.md) | 运营系统(RBAC+封禁+推送占位) | §7 | `admin-h5` `/push` `/admins` | Ops-E · ECR-010 |
| [input-compliance.md](input-compliance.md) | 用户文字输入合规 | 横切 · 安全 | 各写接口 · code 40060 | P2 · ECR-012 |
| [ops-rbac.md](ops-rbac.md) | 运营 RBAC | §7 | `admin-h5` `/me` permissions · `/admin/roles*` | Ops · **ECR-013A** |
| [ops-redemption-code.md](ops-redemption-code.md) | 兑换码 RedemptionCode | §7 | `admin-h5` `/codes` · `POST /membership/redeem` | Ops · **ECR-015(local)** |
| [ops-user-intelligence.md](ops-user-intelligence.md) | 用户洞察 UserIntelligence | §7 | `admin-h5` 用户详情「洞察」 | Ops · **ECR-016(local)** |
| [ops-ask-operations.md](ops-ask-operations.md) | 问答运营 AskOperations | §7 | `admin-h5` `/ask` | Ops · **ECR-017** |
| [ops-entitlement.md](ops-entitlement.md) | 用户权益 Entitlement | §7 | `admin-h5` 用户详情「权益」 | Ops · **ECR-018** |
| [ops-content-safety.md](ops-content-safety.md) | 内容安全 ContentSafety | §7 | `admin-h5` `/safety` | Ops · **ECR-019** |
| [ops-quality-feedback.md](ops-quality-feedback.md) | 问答质量反馈 QualityFeedback | §7 | `admin-h5` `/ask` | Ops · **ECR-020** |
| [ops-ai-core-config.md](ops-ai-core-config.md) | AI 核心配置 AICoreConfig | §7 | `admin-h5` `/ai` | Ops · **ECR-021** |
| [ops-crisis-care.md](ops-crisis-care.md) | 危机关怀 CrisisCare | §7 | `admin-h5` `/crisis` | Ops · **ECR-022** |
| [ops-knowledge-source.md](ops-knowledge-source.md) | AI 知识源 KnowledgeSource | §7 | `admin-h5` `/ai` | Ops · **ECR-023** |
| [ops-banner.md](ops-banner.md) | OpsCMS Banner | §7 | `admin-h5` `/cms` | Ops · **ECR-024** |
| [ops-feed-slot.md](ops-feed-slot.md) | OpsCMS FeedSlot | §7 | `admin-h5` `/cms` | Ops · **ECR-025** |
| [ops-scheduled-publication.md](ops-scheduled-publication.md) | OpsCMS ScheduledPublication | §7 | `/admin/cms/publications*` | Ops · **ECR-026** |
| [ops-knowledge-chunk.md](ops-knowledge-chunk.md) | AICoreConfig KnowledgeChunk | §7 | `/admin/ai/knowledge-chunks*` | Ops · **ECR-027** |
| [ops-tool-definition.md](ops-tool-definition.md) | AICoreConfig ToolDefinition | §7 | `/admin/ai/tools*` | Ops · **ECR-028** |
| [ops-block-policy.md](ops-block-policy.md) | ContentSafety BlockPolicy | §7 | `/admin/content-safety/block-policies*` | Ops · **ECR-029** |
| [ops-moderation-case.md](ops-moderation-case.md) | ContentSafety ModerationCase | §7 | `/admin/content-safety/cases*` | Ops · **ECR-030** |
| [ops-crisis-event.md](ops-crisis-event.md) | CrisisCare CrisisEvent | §7 | `/admin/crisis/events*` | Ops · **ECR-031** |
| [ops-intervention-outcome.md](ops-intervention-outcome.md) | CrisisCare InterventionOutcome | §7 | `/admin/crisis/interventions*` | Ops · **ECR-032** |
| [ops-handoff-case.md](ops-handoff-case.md) | AskOperations HandoffCase | §7 | `/admin/ask/handoffs*` | Ops · **ECR-033** |
| [ops-privacy-request.md](ops-privacy-request.md) | AdminGovernance PrivacyRequest | §7 | `/admin/privacy/requests*` | Ops · **ECR-034** |
| [ops-star-config.md](ops-star-config.md) | ExploreConfig StarConfig | §7 | `/admin/explore/star-configs*` | Ops · **ECR-035** |
| [ops-rhythm-config.md](ops-rhythm-config.md) | ExploreConfig RhythmConfig | §7 | `/admin/explore/rhythm-configs*` | Ops · **ECR-036** |
| [ops-image-card-deck.md](ops-image-card-deck.md) | ExploreConfig ImageCardDeck | §7 | `/admin/explore/image-card-decks*` | Ops · **ECR-037** |
| [ops-report-template.md](ops-report-template.md) | GrowthInsights ReportTemplate | §7 | `/admin/growth/report-templates*` | Ops · **ECR-038** |
| [ops-funnel-definition.md](ops-funnel-definition.md) | GrowthInsights FunnelDefinition | §7 | `/admin/analytics/funnel-definitions*` | Ops · **ECR-039** |
| [ops-scale-definition.md](ops-scale-definition.md) | ExploreConfig ScaleDefinition | §7 | `/admin/explore/scales*` | Ops · **ECR-040** |
新功能:复制 `_TEMPLATE.md` → 填满 → 在本表登记 → 再编码。
@@ -0,0 +1,156 @@
# Feature Spec: 账户生命周期 / UserStatusOps · ECR-013B
> Status: `Active`**Closed** · Feature Complete)· Map: `§7 运营后台` · Phase: `Ops-D`
> Parent: **WAVE0-FROZEN** (`27f27a1`) · Predecessor: **ECR-013A Closed**
> ESS: `docs/ECR/ECR-013B-account-lifecycle.md`**Closed**
> Capability: `AccountLifecycle` · BC: `Identity_Profile`
> 模板:`docs/WAVE0/contracts/OPS-CONTRACT-TEMPLATE.md`
---
## ESS 门禁
1. Change Level = **L2** → 已 Approved + Coding auth + Implemented + **Closed**
2. ~~Contract Definition only~~ — 已完成
3. 实现证据:`docs/TEST_REPORT/ECR-013B.md` · `docs/CODE_REVIEW/ECR-013B.md`
---
## L0 Capability
| 字段 | 内容 |
|------|------|
| Capability ID | `AccountLifecycle` |
| Purpose | 以可审计状态机管理 C 端用户账户启停与封禁,阻断违规会话 |
| Why now | `users.status` 字段已存在但无运营迁移与强制拒绝;013A 权限面就绪后可挂状态写权限 |
| Non-goals | soft-delete / `deleted`;UGC 社区封禁;真支付;Admin 账号启停(已有 admin.status);推送通知 |
---
## L1 Bounded Context
| 字段 | 内容 |
|------|------|
| Primary BC | `Identity_Profile` |
| owns | `User` · `UserStatus` · `AccountStateTransition` |
| does_not_own | `AdminRole` · `Membership` · `Payment` · `BanRecord`Account_Risk 后置加深) |
| allowed | `Admin_Auth_Audit.write_audit`(经 admin 调用) |
| forbidden | `Payment` · `Membership.write` · soft-delete User |
权威:`.ai/domain/boundary-rules.md` · `Account_Risk` 仅允许经明确服务触发 `UserStatus.transition`
---
## 1. 功能定义
| 字段 | 内容 |
|------|------|
| Name | Account Lifecycle / UserStatus |
| Purpose | 运营可迁移用户状态;非 active 会话在 C 端被拒绝 |
| Business Goal | 风险处置最小闭环,不引入社区/UGC |
| In | Out |
|---|---|
| 状态机 `active/disabled/banned/suspended` | soft-delete / GDPR 擦除 |
| Admin 迁移 API + AuditLog + Transition 记录 | 站内推送 / 短信 |
| DeviceAuth / Bearer 对非 active 拒绝 | AdminAccount.status013A 外) |
| 权限码 `admin.users.status.write` | 行级数据 ACL |
---
## L2 Domain
| Entity | 不变式 / 状态机 |
|--------|----------------|
| `UserStatus` | 取值冻结:`active` · `disabled` · `banned` · `suspended`;非法值拒写 |
| `User.status` | 与 `UserStatus` 同值;默认 `active`(已有列) |
| `AccountStateTransition` | 只追加;记录 from→to · admin_id · reason · created_at |
### 合法迁移
```text
active → disabled | banned | suspended
disabled → active | banned
suspended → active | banned | disabled
banned → active | disabled
```
其它边 → **400**。同状态写 → **400**(幂等拒绝,避免空审计噪音)。
### C 端效应
| Status | DeviceAuth / 已登录 Bearer |
|--------|------------------------------|
| `active` | 放行 |
| `disabled` / `banned` / `suspended` | **401**(或 403 统一码,实现轮定一)+ 不可发新 session |
---
## L3 API Contract(意图 · 实现轮同步 OpenAPI)
前缀:`/api/v1/admin` · AdminAuth · 信封 `{code,message,data}`
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| POST | `/users/:id/status` | `admin.users.status.write` | 迁移 UserStatus;写 Transition + AuditLog |
| GET | `/users/:id/status-transitions` | `admin.users.read` | 最近迁移列表(limit |
既有 `GET /users` · `GET /users/:id` 已暴露 `status` — 保持;实现轮确认枚举文档化。
`contract_diff``docs/CONTRACT_DIFF/ECR-013B.yaml`
RBAC catalog **additive**`admin.users.status.write` → 种子写入 `super_admin`migration)。
---
## L4 Acceptance Criteria
### Functional
| ID | Given | When | Then |
|----|-------|------|------|
| AC-F-01 | 用户 `active` | POST status=`banned` + reason | 200GET user.status=`banned` |
| AC-F-02 | 用户 `banned` | POST status=`active` | 200;可再次 DeviceAuth |
| AC-F-03 | 非法边(如 `active``active` | POST | **400** |
| AC-F-04 | GET status-transitions | — | 含最近 from/to/admin/reason |
### Security
| ID | Given | When | Then |
|----|-------|------|------|
| AC-S-01 | Admin 无 `admin.users.status.write` | POST status | **403** + deny audit |
| AC-S-02 | 用户 `banned` | C 端带原 Bearer 访问受保护 API | **401/403** |
| AC-S-03 | 仅 DeviceAuth 无 Admin | POST `/admin/users/:id/status` | **401** |
| AC-S-04 | 无 Admin session | GET transitions | **401** |
### Performance
| ID | Given | When | Then |
|----|-------|------|------|
| AC-P-01 | transitions ≤1000 行/用户 | GET transitions limit=50 | 本机 P95 **&lt; 500ms** |
### Observability
| ID | Given | When | Then |
|----|-------|------|------|
| AC-O-01 | 迁移成功 | — | AuditLog action=`users.status.transition` |
| AC-O-02 | 迁移成功 | — | `account_state_transitions` 有对应行 |
---
## Forbidden(本切片)
- soft-delete / `deleted` 状态
- 真支付 · UGC · Prompt · 兑换码 · Crisis 深化
- 改 Admin RBAC 模型(仅 **additive** 一枚 permission
- 自动开下一 ECR
---
## Implementation Notes(实现轮才执行)
| 项 | 内容 |
|----|------|
| Migration | YEStransitions 表;permission 种子;必要时 CHECK/注释枚举) |
| Packages | service account/lifecycle · DeviceAuth/session 拒绝 · admin handler · admin-h5 用户详情最小 CTA |
| Depends | ECR-013A Closedpermission middleware |
+15 -3
View File
@@ -208,7 +208,19 @@ Phase A 可先 `console`/本地;不挡验收。
| Phase | 内容 |
|---|---|
| **A(本 ECR** | 登录 · 用户 · 订单 · 授予会员 · 审计 · admin-h5 壳 |
| **BECR-007** | 自有埋点 · 管理端「数据」看板 — Spec `ops-analytics.md` |
| **CECR-008** | 首页宫格 CRUD · 测评上下架 — Spec `ops-content.md`Approved |
| **BECR-007 Closed** | 自有埋点 · 管理端「数据」看板 — Spec `ops-analytics.md` |
| **CECR-008 Closed** | 首页宫格 CRUD · 测评上下架 — Spec `ops-content.md` |
| **EECR-013A Closed** | Admin RBAC — Spec `ops-rbac.md` · Parent WAVE0-FROZEN |
| **FECR-013B Closed** | AccountLifecycle — Spec `ops-account-lifecycle.md` |
| **GECR-014 Closed** | MembershipPlan — Spec `ops-membership-plan.md` |
| **HECR-015 Closed** | RedemptionCode — Spec `ops-redemption-code.md` |
| **IECR-016 Closed** | UserIntelligence — Spec `ops-user-intelligence.md` |
| **JECR-017 Closed** | AskOperations — Spec `ops-ask-operations.md` |
| **KECR-018 Closed** | Entitlement — Spec `ops-entitlement.md` |
| **LECR-019 Closed** | ContentSafety FilterRule — Spec `ops-content-safety.md` |
| **MECR-020 Closed** | QualityFeedback — Spec `ops-quality-feedback.md` |
| **NECR-021 Closed** | AICoreConfig SystemPrompt — Spec `ops-ai-core-config.md` |
| **OECR-022 Closed** | CrisisCare CrisisPolicy — Spec `ops-crisis-care.md` |
| 后置 | Knowledge·Tools 写面 / CrisisEvent / 真支付(Loop 续跑) |
| D | 订单筛选 · 展示价 · 退款只读(另开 ECR) |
| E | RBAC · 封禁 · 推送占位(另开 ECR) |
| 后置 | 封禁加深(Account_Risk)· 推送占位 |
@@ -0,0 +1,41 @@
# Feature Spec: AICoreConfig · SystemPromptOps · ECR-021
> Status: `Active`Loop continuous · **ECR-021 Closed**
> Parent: WAVE0-FROZEN · Predecessor: ECR-020 Closed
> Capability: `AICoreConfig` · BC: `Ask_Ops`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
Prompt 在线编辑/发布 · KnowledgeSource/Chunk · ToolDefinition · 切换运行时引擎 · UGC · 真支付
## L2 Domain
| 概念 | 语义 |
|------|------|
| `SystemPrompt` | code 唯一;body 为模板文本;active/system;本切片只读 |
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/ai/system-prompts` | `admin.ai_config.read` | 列表 |
| GET | `/admin/ai/system-prompts/:id` | 同上 | 详情(含 body |
## Migration
`000022``system_prompts` + 种子 `ask_default` + 授予权限
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | list 含 ask_default |
| AC-F-02 | get 返回 body 非空 |
| AC-F-03 | 未知 id → 404 |
| AC-S-01 | 无 Admin → 401 |
| AC-S-02 | 无 ai_config.read → 403 |
| AC-P-01 | list &lt; 500ms |
| AC-O-01 | N/A 只读 |
contract_diff: `docs/CONTRACT_DIFF/ECR-021.yaml`
+1 -1
View File
@@ -1,7 +1,7 @@
# Feature Spec: 运营行为分析(Ops-B
> Status: `Active` · Map: `§7 运营后台` · Phase: `Ops-B`
> ESS`docs/ECR/ECR-007-ops-analytics.md`Approved · L2)· BD-2026-007 Approved
> ESS`docs/ECR/ECR-007-ops-analytics.md`**Closed** · L2)· BD-2026-007 Approved
> 关联:[ops-admin.md](ops-admin.md) · [analytics.md](analytics.md) · [cece-frontend-re/complete-design/40-ops-commerce.md](cece-frontend-re/complete-design/40-ops-commerce.md)
---
@@ -0,0 +1,41 @@
# Feature Spec: AskOperationsOps · ECR-017
> Status: `Active`Loop continuous · **ECR-017 Closed**
> Parent: WAVE0-FROZEN · Predecessor: ECR-016 Closed
> Capability: `AskOperations` · BC: `Ask_Ops`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
改写/删除消息正文 · SystemPrompt/Knowledge 配置 · QualityFeedback 写回 · AICoreConfig · 真支付 · UGC
## L2 读模型
| 概念 | 语义 |
|------|------|
| `AskSessionView` | 线程元数据 + message_count(列表) |
| 会话详情 | 只读消息序列(role/content/created_at |
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/ask/threads` | `admin.ask.read` | 列表(可选 `user_id` |
| GET | `/admin/ask/threads/:id` | `admin.ask.read` | 详情含消息 |
## Migration
`000019`:为 `super_admin` 授予 `admin.ask.read`(无新业务表)
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | 有消息线程 → list 含该 thread · message_count≥1 |
| AC-F-02 | detail 返回 user+assistant 消息 |
| AC-S-01 | 无 Admin → 401 |
| AC-S-02 | 无 ask.read → 403 |
| AC-P-01 | list &lt; 500ms 本机 |
| AC-O-01 | N/A 只读(无写审计强制) |
contract_diff: `docs/CONTRACT_DIFF/ECR-017.yaml`
+41
View File
@@ -0,0 +1,41 @@
# Feature Spec: OpsCMS · BannerOps · ECR-024
> Status: `Active`Loop continuous · **ECR-024 Closed**
> Parent: WAVE0-FROZEN · Predecessor: ECR-023 Closed
> Capability: `OpsCMS` · BC: `Ops_CMS_NoUGC`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
Banner 写发布 · FeedSlot · ScheduledPublication · UGC · 真支付
## L2 Domain
| 概念 | 语义 |
|------|------|
| `Banner` | code 唯一;placement ∈ {home,explore,ask}active/system;本切片只读 |
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/cms/banners` | `admin.cms.read` | 只读 |
| GET | `/admin/cms/banners/{id}` | `admin.cms.read` | 只读 |
## Migration
`000025`:表 + 种子(若有) + 授予 admin.cms.read
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | list 含种子或空列表合法 |
| AC-F-02 | 已知 id get 200 |
| AC-F-03 | 未知 id → 404 |
| AC-S-01 | 无 Admin → 401 |
| AC-S-02 | 无权限 → 403 |
| AC-P-01 | list &lt; 500ms |
| AC-O-01 | N/A 只读 |
contract_diff: `docs/CONTRACT_DIFF/ECR-024.yaml`
@@ -0,0 +1,41 @@
# Feature Spec: ContentSafety · BlockPolicyOps · ECR-029
> Status: `Active`Loop continuous · **ECR-029 Closed**
> Parent: WAVE0-FROZEN · Predecessor: ECR-028 Closed
> Capability: `ContentSafety` · BC: `Content_Safety`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
策略写发布 · 用户侧硬拦截上线 · UGC · 真支付
## L2 Domain
| 概念 | 语义 |
|------|------|
| `BlockPolicy` | 本切片只读目录;code 唯一(若适用) |
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/content-safety/block-policies` | `admin.content_safety.read` | 只读 |
| GET | `/admin/content-safety/block-policies/{id}` | `admin.content_safety.read` | 只读 |
## Migration
`000030`:表 + 种子(若有)(权限复用)
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | list 含种子或空列表合法 |
| AC-F-02 | 已知 id get 200 |
| AC-F-03 | 未知 id → 404 |
| AC-S-01 | 无 Admin → 401 |
| AC-S-02 | 无权限 → 403 |
| AC-P-01 | list &lt; 500ms |
| AC-O-01 | N/A 只读 |
contract_diff: `docs/CONTRACT_DIFF/ECR-029.yaml`
@@ -0,0 +1,42 @@
# Feature Spec: ContentSafety · FilterRuleOps · ECR-019
> Status: `Active`Loop continuous · **ECR-019 Closed**
> Parent: WAVE0-FROZEN · Predecessor: ECR-018 Closed
> Capability: `ContentSafety` · BC: `Content_Safety`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
ModerationCase 写回 · CrisisPolicy 配置 · 真 NLP/厂商审核 · UGC · 真支付 · 用户侧硬拦截上线(本切片仅运营只读 + 试匹配)
## L2 Domain
| 概念 | 语义 |
|------|------|
| `FilterRule` | code 唯一;category ∈ {crisis,abuse,spam,pii}action ∈ {flag,block,escalate}system 种子不可本切片删除 |
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/content-safety/filter-rules` | `admin.content_safety.read` | 列表 |
| GET | `/admin/content-safety/filter-rules/:id` | 同上 | 详情 |
| POST | `/admin/content-safety/evaluate` | 同上 | 试匹配(不写工单) |
## Migration
`000020``filter_rules` + 种子规则 + 授予 `admin.content_safety.read`
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | list 含 system 种子 ≥1 |
| AC-F-02 | evaluate 命中种子 pattern → matches 非空 |
| AC-F-03 | get 未知 id → 404 |
| AC-S-01 | 无 Admin → 401 |
| AC-S-02 | 无 content_safety.read → 403 |
| AC-P-01 | list &lt; 500ms |
| AC-O-01 | evaluate 不写 Audit(只读试匹配) |
contract_diff: `docs/CONTRACT_DIFF/ECR-019.yaml`
+1 -1
View File
@@ -1,7 +1,7 @@
# Feature Spec: 运营内容配置(Ops-C
> Status: `Active` · Map: `§7 运营后台` · Phase: `Ops-C`
> ESS`docs/ECR/ECR-008-ops-content.md`Approved · L2)· BD-2026-008 Approved
> ESS`docs/ECR/ECR-008-ops-content.md`**Closed** · L2)· BD-2026-008 Approved
> 关联:[ops-admin.md](ops-admin.md) · [ops-analytics.md](ops-analytics.md) · [home.md](home.md) · [explore-test.md](explore-test.md)
---
@@ -0,0 +1,42 @@
# Feature Spec: CrisisCare · CrisisPolicyOps · ECR-022
> Status: `Active`Loop continuous · **ECR-022 Closed**
> Parent: WAVE0-FROZEN · Predecessor: ECR-021 Closed
> Capability: `CrisisCare` · BC: `Content_Safety`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
CrisisEvent 入库工单 · InterventionOutcome · 策略在线编辑 · 医疗诊断结论 · UGC · 真支付 · 用户侧硬熔断上线
## L2 Domain
| 概念 | 语义 |
|------|------|
| `CrisisPolicy` | code 唯一;severity ∈ {high,critical}action ∈ {escalate,block,show_helpline}helpline_text 可选;本切片只读 |
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/crisis/policies` | `admin.crisis.read` | 列表 |
| GET | `/admin/crisis/policies/:id` | 同上 | 详情 |
| POST | `/admin/crisis/evaluate` | 同上 | 试匹配(不写 CrisisEvent |
## Migration
`000023``crisis_policies` + 种子 + 授予权限
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | list 含 system 种子 ≥1 |
| AC-F-02 | evaluate 命中 pattern → matches 非空 |
| AC-F-03 | 未知 id → 404 |
| AC-S-01 | 无 Admin → 401 |
| AC-S-02 | 无 crisis.read → 403 |
| AC-P-01 | list &lt; 500ms |
| AC-O-01 | evaluate 不写 Audit/Event |
contract_diff: `docs/CONTRACT_DIFF/ECR-022.yaml`
@@ -0,0 +1,41 @@
# Feature Spec: CrisisCare · CrisisEventOps · ECR-031
> Status: `Active`Loop continuous · **ECR-031 Closed**
> Parent: WAVE0-FROZEN · Predecessor: ECR-030 Closed
> Capability: `CrisisCare` · BC: `Content_Safety`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
事件写入工单流 · 医疗诊断 · UGC · 真支付
## L2 Domain
| 概念 | 语义 |
|------|------|
| `CrisisEvent` | 本切片只读目录;code 唯一(若适用) |
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/crisis/events` | `admin.crisis.read` | 只读 |
| GET | `/admin/crisis/events/{id}` | `admin.crisis.read` | 只读 |
## Migration
`000032`:表 + 种子(若有)(权限复用)
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | list 含种子或空列表合法 |
| AC-F-02 | 已知 id get 200 |
| AC-F-03 | 未知 id → 404 |
| AC-S-01 | 无 Admin → 401 |
| AC-S-02 | 无权限 → 403 |
| AC-P-01 | list &lt; 500ms |
| AC-O-01 | N/A 只读 |
contract_diff: `docs/CONTRACT_DIFF/ECR-031.yaml`
@@ -0,0 +1,36 @@
# Feature Spec: EntitlementOps · ECR-018
> Status: `Active`Loop continuous · **ECR-018 Closed**
> Parent: WAVE0-FROZEN · Predecessor: ECR-017 Closed
> Capability: `CommerceEntitlement` · BC: `Membership_Orders`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
真支付 · 改订单/退款 · 新建权益矩阵表 · UGC · 改报告正文 · ask_pack SKU
## L2 读模型(无 migration
| 概念 | 来源 |
|------|------|
| `Entitlement` | Membership + DeepAccess 列表 + ask_paid_quota 聚合 |
| flags | `report_detail_via_membership` · `deep_access_count` |
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/users/:id/entitlements` | `admin.users.read` | 用户权益只读视图 |
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | 授予会员后 flags.report_detail_via_membership=true |
| AC-F-02 | 有 deep_access 时 deep_accesses 非空或 count≥1 |
| AC-F-03 | 无会员无深度 → membership.active=false 且 count=0 仍 200 |
| AC-S-01 | 无 Admin → 401 |
| AC-P-01 | GET &lt; 500ms 本机 |
| AC-O-01 | N/A 只读 |
contract_diff: `docs/CONTRACT_DIFF/ECR-018.yaml`
+41
View File
@@ -0,0 +1,41 @@
# Feature Spec: OpsCMS · FeedSlotOps · ECR-025
> Status: `Active`Loop continuous · **ECR-025 Closed**
> Parent: WAVE0-FROZEN · Predecessor: ECR-024 Closed
> Capability: `OpsCMS` · BC: `Ops_CMS_NoUGC`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
FeedSlot 写发布 · ScheduledPublication · UGC · 真支付 · Banner 写
## L2 Domain
| 概念 | 语义 |
|------|------|
| `FeedSlot` | 本切片只读目录;code 唯一(若适用) |
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/cms/feed-slots` | `admin.cms.read` | 只读 |
| GET | `/admin/cms/feed-slots/{id}` | `admin.cms.read` | 只读 |
## Migration
`000026`:表 + 种子(若有)(权限复用)
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | list 含种子或空列表合法 |
| AC-F-02 | 已知 id get 200 |
| AC-F-03 | 未知 id → 404 |
| AC-S-01 | 无 Admin → 401 |
| AC-S-02 | 无权限 → 403 |
| AC-P-01 | list &lt; 500ms |
| AC-O-01 | N/A 只读 |
contract_diff: `docs/CONTRACT_DIFF/ECR-025.yaml`
@@ -0,0 +1,41 @@
# Feature Spec: GrowthInsights · FunnelDefinitionOps · ECR-039
> Status: `Active`Loop continuous · **ECR-039 Closed**
> Parent: WAVE0-FROZEN · Predecessor: ECR-038 Closed
> Capability: `GrowthInsights` · BC: `Analytics_OpsB`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
漏斗写配置 · UGC · 真支付
## L2 Domain
| 概念 | 语义 |
|------|------|
| `FunnelDefinition` | 本切片只读目录;code 唯一(若适用) |
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/analytics/funnel-definitions` | `admin.analytics.read` | 只读 |
| GET | `/admin/analytics/funnel-definitions/{id}` | `admin.analytics.read` | 只读 |
## Migration
`000040`:表 + 种子(若有)(权限复用)
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | list 含种子或空列表合法 |
| AC-F-02 | 已知 id get 200 |
| AC-F-03 | 未知 id → 404 |
| AC-S-01 | 无 Admin → 401 |
| AC-S-02 | 无权限 → 403 |
| AC-P-01 | list &lt; 500ms |
| AC-O-01 | N/A 只读 |
contract_diff: `docs/CONTRACT_DIFF/ECR-039.yaml`
@@ -0,0 +1,41 @@
# Feature Spec: AskOperations · HandoffCaseOps · ECR-033
> Status: `Active`Loop continuous · **ECR-033 Closed**
> Parent: WAVE0-FROZEN · Predecessor: ECR-032 Closed
> Capability: `AskOperations` · BC: `Ask_Ops`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
转人工写流 · 顾问执业 · UGC · 真支付
## L2 Domain
| 概念 | 语义 |
|------|------|
| `HandoffCase` | 本切片只读目录;code 唯一(若适用) |
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/ask/handoffs` | `admin.ask.read` | 只读 |
| GET | `/admin/ask/handoffs/{id}` | `admin.ask.read` | 只读 |
## Migration
`000034`:表 + 种子(若有)(权限复用)
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | list 含种子或空列表合法 |
| AC-F-02 | 已知 id get 200 |
| AC-F-03 | 未知 id → 404 |
| AC-S-01 | 无 Admin → 401 |
| AC-S-02 | 无权限 → 403 |
| AC-P-01 | list &lt; 500ms |
| AC-O-01 | N/A 只读 |
contract_diff: `docs/CONTRACT_DIFF/ECR-033.yaml`
@@ -0,0 +1,41 @@
# Feature Spec: ExploreConfig · ImageCardDeckOps · ECR-037
> Status: `Active`Loop continuous · **ECR-037 Closed**
> Parent: WAVE0-FROZEN · Predecessor: ECR-036 Closed
> Capability: `ExploreConfig` · BC: `Explore_Reports`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
牌组写发布 · UGC · 真支付
## L2 Domain
| 概念 | 语义 |
|------|------|
| `ImageCardDeck` | 本切片只读目录;code 唯一(若适用) |
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/explore/image-card-decks` | `admin.explore.read` | 只读 |
| GET | `/admin/explore/image-card-decks/{id}` | `admin.explore.read` | 只读 |
## Migration
`000038`:表 + 种子(若有)(权限复用)
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | list 含种子或空列表合法 |
| AC-F-02 | 已知 id get 200 |
| AC-F-03 | 未知 id → 404 |
| AC-S-01 | 无 Admin → 401 |
| AC-S-02 | 无权限 → 403 |
| AC-P-01 | list &lt; 500ms |
| AC-O-01 | N/A 只读 |
contract_diff: `docs/CONTRACT_DIFF/ECR-037.yaml`
@@ -0,0 +1,41 @@
# Feature Spec: CrisisCare · InterventionOutcomeOps · ECR-032
> Status: `Active`Loop continuous · **ECR-032 Closed**
> Parent: WAVE0-FROZEN · Predecessor: ECR-031 Closed
> Capability: `CrisisCare` · BC: `Content_Safety`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
干预写回 · 医疗诊断 · UGC · 真支付
## L2 Domain
| 概念 | 语义 |
|------|------|
| `InterventionOutcome` | 本切片只读目录;code 唯一(若适用) |
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/crisis/interventions` | `admin.crisis.read` | 只读 |
| GET | `/admin/crisis/interventions/{id}` | `admin.crisis.read` | 只读 |
## Migration
`000033`:表 + 种子(若有)(权限复用)
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | list 含种子或空列表合法 |
| AC-F-02 | 已知 id get 200 |
| AC-F-03 | 未知 id → 404 |
| AC-S-01 | 无 Admin → 401 |
| AC-S-02 | 无权限 → 403 |
| AC-P-01 | list &lt; 500ms |
| AC-O-01 | N/A 只读 |
contract_diff: `docs/CONTRACT_DIFF/ECR-032.yaml`
@@ -0,0 +1,41 @@
# Feature Spec: AICoreConfig · KnowledgeChunkOps · ECR-027
> Status: `Active`Loop continuous · **ECR-027 Closed**
> Parent: WAVE0-FROZEN · Predecessor: ECR-026 Closed
> Capability: `AICoreConfig` · BC: `Ask_Ops`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
Embedding · 上传切块 · 运行时 RAG 接线 · UGC · 真支付
## L2 Domain
| 概念 | 语义 |
|------|------|
| `KnowledgeChunk` | 本切片只读目录;code 唯一(若适用) |
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/ai/knowledge-chunks` | `admin.ai_config.read` | 只读 |
| GET | `/admin/ai/knowledge-chunks/{id}` | `admin.ai_config.read` | 只读 |
## Migration
`000028`:表 + 种子(若有)(权限复用)
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | list 含种子或空列表合法 |
| AC-F-02 | 已知 id get 200 |
| AC-F-03 | 未知 id → 404 |
| AC-S-01 | 无 Admin → 401 |
| AC-S-02 | 无权限 → 403 |
| AC-P-01 | list &lt; 500ms |
| AC-O-01 | N/A 只读 |
contract_diff: `docs/CONTRACT_DIFF/ECR-027.yaml`
@@ -0,0 +1,41 @@
# Feature Spec: AICoreConfig · KnowledgeSourceOps · ECR-023
> Status: `Active`Loop continuous · **ECR-023 Closed**
> Parent: WAVE0-FROZEN · Predecessor: ECR-022 Closed
> Capability: `AICoreConfig` · BC: `Ask_Ops`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
KnowledgeChunk / Embedding · 源文件上传 · 在线编辑发布 · ToolDefinition · 运行时 RAG 接线 · UGC · 真支付
## L2 Domain
| 概念 | 语义 |
|------|------|
| `KnowledgeSource` | code 唯一;source_kind ∈ {faq,policy,guide}active/system;本切片只读目录,不含 Chunk |
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/ai/knowledge-sources` | `admin.ai_config.read` | 列表 |
| GET | `/admin/ai/knowledge-sources/:id` | 同上 | 详情 |
## Migration
`000024``knowledge_sources` + 种子 `ask_grounding`(权限已由 000022 授予)
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | list 含 ask_grounding |
| AC-F-02 | get 返回 source_kind 合法 |
| AC-F-03 | 未知 id → 404 |
| AC-S-01 | 无 Admin → 401 |
| AC-S-02 | 无 ai_config.read → 403 |
| AC-P-01 | list &lt; 500ms |
| AC-O-01 | N/A 只读 |
contract_diff: `docs/CONTRACT_DIFF/ECR-023.yaml`
@@ -0,0 +1,77 @@
# Feature Spec: 会员套餐 MembershipPlanOps · ECR-014
> Status: `Active`Loop continuous · Approved · coding)· Map: `§7` · Phase: `Ops-D`
> Parent: **WAVE0-FROZEN** · Predecessor: **ECR-013B Closed**
> ESS: `docs/ECR/ECR-014-membership-plan.md`
> Capability: `CommerceEntitlement` · BC: `Membership_Orders`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
---
## ESS 门禁
1. L2 · Loop continuous:契约齐 → 自动 Approve + coding
2. **不含** 真支付 · 兑换码 · Entitlement 矩阵 · ask_pack 价目表
---
## L0 Capability
| 字段 | 内容 |
|------|------|
| Capability ID | `CommerceEntitlement` |
| Purpose | 运营可配置成长会员套餐时长与标价(mock 履约仍用既有支付) |
| Why now | planDays/金额硬编码;013B 完成后进入 Commerce 配置面最小切片 |
| Non-goals | 真支付网关 · RedemptionCode · Entitlement 细权 · ask_pack |
---
## L1 Bounded Context
| Primary BC | `Membership_Orders` |
| owns | `MembershipPlan` |
| does_not_own | `UserStatus` · `Payment` 适配器 · `AdminRole` |
| allowed | `Admin_Auth_Audit.write_audit` |
| forbidden | 真支付 · UGC |
---
## L2 Domain
| Entity | 不变式 |
|--------|--------|
| `MembershipPlan` | `code` ∈ {month,quarter,year} 本切片冻结;`duration_days`>0`amount_cents`≥0`active` 布尔 |
---
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/membership-plans` | `admin.membership.plans.read` | 列表 |
| GET | `/admin/membership-plans/:code` | `admin.membership.plans.read` | 详情 |
| PUT | `/admin/membership-plans/:code` | `admin.membership.plans.write` | 更新 title/days/amount/active + AuditLog |
履约:`GrantMembership` / membership `CreateOrder` 读表(缺行回退旧硬编码)。
`contract_diff``docs/CONTRACT_DIFF/ECR-014.yaml`
---
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | GET plans 含 month/quarter/year |
| AC-F-02 | PUT month days/amount → GET 一致 |
| AC-F-03 | GrantMembership 使用表内 duration_days |
| AC-S-01 | 无 write 权限 PUT → 403 |
| AC-S-02 | 无 Admin → 401 |
| AC-P-01 | GET list P95 &lt; 500ms 本机 |
| AC-O-01 | PUT 成功 → AuditLog `membership.plans.update` |
---
## Implementation Notes
Migration `membership_plans` + RBAC additive permissions · admin-h5 最小列表编辑页
@@ -0,0 +1,41 @@
# Feature Spec: ContentSafety · ModerationCaseOps · ECR-030
> Status: `Active`Loop continuous · **ECR-030 Closed**
> Parent: WAVE0-FROZEN · Predecessor: ECR-029 Closed
> Capability: `ContentSafety` · BC: `Content_Safety`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
审核写回 · 真 NLP 厂商 · UGC · 真支付
## L2 Domain
| 概念 | 语义 |
|------|------|
| `ModerationCase` | 本切片只读目录;code 唯一(若适用) |
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/content-safety/cases` | `admin.content_safety.read` | 只读 |
| GET | `/admin/content-safety/cases/{id}` | `admin.content_safety.read` | 只读 |
## Migration
`000031`:表 + 种子(若有)(权限复用)
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | list 含种子或空列表合法 |
| AC-F-02 | 已知 id get 200 |
| AC-F-03 | 未知 id → 404 |
| AC-S-01 | 无 Admin → 401 |
| AC-S-02 | 无权限 → 403 |
| AC-P-01 | list &lt; 500ms |
| AC-O-01 | N/A 只读 |
contract_diff: `docs/CONTRACT_DIFF/ECR-030.yaml`
@@ -0,0 +1,41 @@
# Feature Spec: AdminGovernance · PrivacyRequestOps · ECR-034
> Status: `Active`Loop continuous · **ECR-034 Closed**
> Parent: WAVE0-FROZEN · Predecessor: ECR-033 Closed
> Capability: `AdminGovernance` · BC: `Admin_Auth_Audit`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
隐私请求履约写 · soft-delete · UGC · 真支付
## L2 Domain
| 概念 | 语义 |
|------|------|
| `PrivacyRequest` | 本切片只读目录;code 唯一(若适用) |
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/privacy/requests` | `admin.privacy.read` | 只读 |
| GET | `/admin/privacy/requests/{id}` | `admin.privacy.read` | 只读 |
## Migration
`000035`:表 + 种子(若有) + 授予 admin.privacy.read
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | list 含种子或空列表合法 |
| AC-F-02 | 已知 id get 200 |
| AC-F-03 | 未知 id → 404 |
| AC-S-01 | 无 Admin → 401 |
| AC-S-02 | 无权限 → 403 |
| AC-P-01 | list &lt; 500ms |
| AC-O-01 | N/A 只读 |
contract_diff: `docs/CONTRACT_DIFF/ECR-034.yaml`
@@ -0,0 +1,42 @@
# Feature Spec: QualityFeedbackOps · ECR-020
> Status: `Active`Loop continuous · **ECR-020 Closed**
> Parent: WAVE0-FROZEN · Predecessor: ECR-019 Closed
> Capability: `AskOperations` · BC: `Ask_Ops`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
改写消息正文 · SystemPrompt/Knowledge · HandoffCase 全量 · AICoreConfig · UGC 广场 · 真支付
## L2 Domain
| 概念 | 语义 |
|------|------|
| `QualityFeedback` | 绑定 thread(可选 message);rating 15tag ∈ {helpful,off_topic,unsafe,other}source ∈ {admin,user} |
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/ask/feedback` | `admin.ask.read` | 列表 |
| POST | `/admin/ask/threads/:id/feedback` | `admin.ask.feedback.write` | 运营提交 |
| POST | `/ask/threads/:id/feedback` | DeviceAuth 用户 | C 端评分 |
## Migration
`000021``ask_quality_feedback` + 授予 `admin.ask.feedback.write`
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | admin POST feedback → 200 · list 可见 |
| AC-F-02 | user POST feedback → 200 |
| AC-F-03 | 无效 rating → 400 |
| AC-S-01 | 无 Admin → admin list 401 |
| AC-S-02 | 无 feedback.write → admin POST 403 |
| AC-P-01 | list &lt; 500ms |
| AC-O-01 | admin 提交写 AuditLog `ask.feedback.create` |
contract_diff: `docs/CONTRACT_DIFF/ECR-020.yaml`
+151
View File
@@ -0,0 +1,151 @@
# Feature Spec: 运营后台 RBACOps · ECR-013A
> Status: `Active`**Closed** · Feature Complete)· Map: `§7 运营后台` · Phase: `Ops-D`
> Parent: **WAVE0-FROZEN** (`27f27a1`)
> ESS: `docs/ECR/ECR-013A-admin-rbac.md`**Closed**
> Capability: `AdminGovernance` · BC: `Admin_RBAC`
> 模板:`docs/WAVE0/contracts/OPS-CONTRACT-TEMPLATE.md`
---
## ESS 门禁
1. Change Level = **L2** → 已 Approved + Coding auth + Implemented + **Closed**
2. ~~Contract Definition only~~ — 已完成
3. 实现证据:`docs/TEST_REPORT/ECR-013A.md` · `docs/CODE_REVIEW/ECR-013A.md`
---
## L0 Capability
| 字段 | 内容 |
|------|------|
| Capability ID | `AdminGovernance` |
| Purpose | 以最小权限原则约束管理员可执行的运营动作 |
| Why now | Ops-A 全员等价权限;进入 M1+ 前必须有权限面,否则越权不可治理 |
| Non-goals | 用户账户启停(ECR-013B);兑换码;CMSAsk Prompt;真支付;UGC |
---
## L1 Bounded Context
| 字段 | 内容 |
|------|------|
| Primary BC | `Admin_RBAC` |
| owns | `AdminRole` · `AdminPermission` |
| does_not_own | `User` · `Profile` · `UserStatus` · `Membership` · `Payment` |
| allowed | `Admin_Auth_Audit.write_audit` |
| forbidden | `Payment` · `Membership.write` · `DeviceAuth.user_token_issue` |
权威:`.ai/domain/boundary-rules.md`
---
## 1. 功能定义
| 字段 | 内容 |
|------|------|
| Name | Admin RBAC |
| Purpose | 角色与权限点绑定;API 级强制鉴权;变更可审计 |
| Business Goal | 支撑多运营角色,而不扩大 C 端攻击面 |
| In | Out |
|---|---|
| Role CRUD(最小:list/get/update permissions | UserStatus / 封禁(013B |
| `GET /admin/me` 返回 permissions | 细粒度数据行级 ACL |
| 既有 admin 写操作挂 permission 检查 | 新业务模块权限爆炸式新增(另 ECR) |
---
## L2 Domain
| Entity | 不变式 |
|--------|--------|
| `AdminRole` | `name` 唯一;系统角色 `super_admin` 不可删除 |
| `AdminPermission` | 稳定字符串码(见下表);只增不改语义 |
| `AdminAccount.role_id` | 每个账号恰好一个角色(本切片);无角色视为拒绝写操作 |
### Permission catalog(本切片冻结)
| Code | 覆盖既有能力 |
|------|----------------|
| `admin.users.read` | GET users / users/:id / stats |
| `admin.users.membership.grant` | POST membership/grant |
| `admin.users.ask_quota.grant` | POST ask-quota/grant |
| `admin.orders.read` | GET orders |
| `admin.audit.read` | GET audit-logs |
| `admin.analytics.read` | GET analytics/*Ops-B |
| `admin.content.write` | home tools / scales publishOps-C |
| `admin.roles.read` | GET roles |
| `admin.roles.write` | 变更角色权限 |
`super_admin` 种子拥有上表全部。
---
## L3 API Contract(意图 · 实现轮同步 OpenAPI)
前缀:`/api/v1/admin` · AdminAuth · 信封 `{code,message,data}`
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/roles` | `admin.roles.read` | 角色列表 |
| GET | `/roles/:id` | `admin.roles.read` | 角色 + permissions[] |
| PUT | `/roles/:id/permissions` | `admin.roles.write` | 全量替换权限集;写 AuditLog |
| GET | `/me` | (已登录) | **扩展**返回 `role` + `permissions[]` |
既有写接口:在实现轮挂上表 permission;缺权 → **403** + AuditLog(尝试记录)。
`contract_diff``docs/CONTRACT_DIFF/ECR-013A.yaml`
---
## L4 Acceptance Criteria
### Functional
| ID | Given | When | Then |
|----|-------|------|------|
| AC-F-01 | super_admin 已登录 | GET `/roles` | 200,含 `super_admin` |
| AC-F-02 | 角色存在 | PUT permissions 合法集合 | 200;再次 GET 一致 |
| AC-F-03 | GET `/me` | — | data 含 `permissions` 数组 |
### Security
| ID | Given | When | Then |
|----|-------|------|------|
| AC-S-01 | Admin 无 `admin.roles.write` | PUT `/roles/:id/permissions` | **403**;AuditLog 有拒绝或尝试记录 |
| AC-S-02 | Admin 无 `admin.users.membership.grant` | POST membership/grant | **403** |
| AC-S-03 | 仅 DeviceAuth | 访问 `/admin/roles` | **401** |
| AC-S-04 | 删除 `super_admin` 角色 | 任意 API | **拒绝**4xx |
### Performance
| ID | Given | When | Then |
|----|-------|------|------|
| AC-P-01 | 角色数 N≤100 | GET `/roles` | 本机 integration 环境下 P95 **&lt; 500ms** |
### Observability
| ID | Given | When | Then |
|----|-------|------|------|
| AC-O-01 | PUT permissions 成功 | — | AuditLog action 含 `roles.permissions.update` |
| AC-O-02 | AC-S-01 触发 | — | AuditLog 可追溯 admin_id + path |
---
## Forbidden(本切片)
- UserStatus / AccountLifecycle**ECR-013B**
- 真支付 · UGC · Prompt/RAG · 兑换码 · CMS Banner 新表
- 改 DeviceAuth / C 端五 Tab
---
## Implementation Notes(实现轮才执行)
| 项 | 内容 |
|----|------|
| Migration | YESroles / permissions 关联;accounts.role_id;种子 super_admin |
| Packages | `service/admin` · repo · middleware permission check · admin-h5 只读展示权限(最小) |
| Parent | WAVE0-FROZEN |
@@ -0,0 +1,43 @@
# Feature Spec: 兑换码 RedemptionCodeOps · ECR-015
> Status: `Active`Loop continuous · Approved · coding
> Parent: WAVE0-FROZEN · Predecessor: ECR-014 Closed
> Capability: `CommerceEntitlement` · BC: `Membership_Orders`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
真支付 · Entitlement 细权 · ask_pack 兑换 · UGC
## L2
| Entity | 不变式 |
|--------|--------|
| `RedemptionBatch` | label · plan_code∈membership_plans · quantity 1..100 |
| `RedemptionCode` | code 唯一;status unused→redeemed\|disabledredeemed 不可再兑 |
## L3 API
| Method | Path | Auth | 语义 |
|--------|------|------|------|
| POST | `/admin/redemption-batches` | `admin.membership.codes.write` | 批量生成 |
| GET | `/admin/redemption-batches` | `admin.membership.codes.read` | 批次列表 |
| GET | `/admin/redemption-batches/:id/codes` | `admin.membership.codes.read` | 码列表 |
| POST | `/admin/redemption-codes/:id/disable` | `admin.membership.codes.write` | 作废 unused |
| POST | `/membership/redeem` | DeviceAuth+已注册 | 兑码→延长会员 |
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | POST batch quantity=3 → 3 unused codes |
| AC-F-02 | C端 redeem → membership active;码=redeemed |
| AC-F-03 | 再兑同一码 → 400 |
| AC-F-04 | disable unused → status=disabled;兑 → 400 |
| AC-S-01 | 无 write → POST batch 403 |
| AC-S-02 | 未登录兑码 → 401 |
| AC-P-01 | GET batches &lt; 500ms |
| AC-O-01 | 生成 AuditLog `redemption.batch.create` |
| AC-O-02 | 兑换可追溯 redeemed_by |
contract_diff: `docs/CONTRACT_DIFF/ECR-015.yaml`
@@ -0,0 +1,41 @@
# Feature Spec: GrowthInsights · ReportTemplateOps · ECR-038
> Status: `Active`Loop continuous · **ECR-038 Closed**
> Parent: WAVE0-FROZEN · Predecessor: ECR-037 Closed
> Capability: `GrowthInsights` · BC: `Explore_Reports`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
模板写发布 · 广告投放 · UGC · 真支付
## L2 Domain
| 概念 | 语义 |
|------|------|
| `ReportTemplate` | 本切片只读目录;code 唯一(若适用) |
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/growth/report-templates` | `admin.growth.read` | 只读 |
| GET | `/admin/growth/report-templates/{id}` | `admin.growth.read` | 只读 |
## Migration
`000039`:表 + 种子(若有) + 授予 admin.growth.read
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | list 含种子或空列表合法 |
| AC-F-02 | 已知 id get 200 |
| AC-F-03 | 未知 id → 404 |
| AC-S-01 | 无 Admin → 401 |
| AC-S-02 | 无权限 → 403 |
| AC-P-01 | list &lt; 500ms |
| AC-O-01 | N/A 只读 |
contract_diff: `docs/CONTRACT_DIFF/ECR-038.yaml`
@@ -0,0 +1,41 @@
# Feature Spec: ExploreConfig · RhythmConfigOps · ECR-036
> Status: `Active`Loop continuous · **ECR-036 Closed**
> Parent: WAVE0-FROZEN · Predecessor: ECR-035 Closed
> Capability: `ExploreConfig` · BC: `Explore_Reports`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
配置写发布 · UGC · 真支付
## L2 Domain
| 概念 | 语义 |
|------|------|
| `RhythmConfig` | 本切片只读目录;code 唯一(若适用) |
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/explore/rhythm-configs` | `admin.explore.read` | 只读 |
| GET | `/admin/explore/rhythm-configs/{id}` | `admin.explore.read` | 只读 |
## Migration
`000037`:表 + 种子(若有)(权限复用)
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | list 含种子或空列表合法 |
| AC-F-02 | 已知 id get 200 |
| AC-F-03 | 未知 id → 404 |
| AC-S-01 | 无 Admin → 401 |
| AC-S-02 | 无权限 → 403 |
| AC-P-01 | list &lt; 500ms |
| AC-O-01 | N/A 只读 |
contract_diff: `docs/CONTRACT_DIFF/ECR-036.yaml`
@@ -0,0 +1,41 @@
# Feature Spec: ExploreConfig · ScaleDefinitionOps · ECR-040
> Status: `Active`Loop continuous · **ECR-040 Closed**
> Parent: WAVE0-FROZEN · Predecessor: ECR-039 Closed
> Capability: `ExploreConfig` · BC: `Explore_Reports`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
PATCH status(已有 content.write)· 题干编辑 · UGC · 真支付
## L2 Domain
| 概念 | 语义 |
|------|------|
| `ScaleDefinition` | 本切片只读目录;code 唯一(若适用) |
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/explore/scales` | `admin.explore.read` | 只读 |
| GET | `/admin/explore/scales/{id}` | `admin.explore.read` | 只读 |
## Migration
Migration NO:复用 `scales` 表只读投影
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | list 含种子或空列表合法 |
| AC-F-02 | 已知 id get 200 |
| AC-F-03 | 未知 id → 404 |
| AC-S-01 | 无 Admin → 401 |
| AC-S-02 | 无权限 → 403 |
| AC-P-01 | list &lt; 500ms |
| AC-O-01 | N/A 只读 |
contract_diff: `docs/CONTRACT_DIFF/ECR-040.yaml`
@@ -0,0 +1,41 @@
# Feature Spec: OpsCMS · ScheduledPublicationOps · ECR-026
> Status: `Active`Loop continuous · **ECR-026 Closed**
> Parent: WAVE0-FROZEN · Predecessor: ECR-025 Closed
> Capability: `OpsCMS` · BC: `Ops_CMS_NoUGC`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
定时发布写操作 · UGC · 真支付 · Banner/FeedSlot 写
## L2 Domain
| 概念 | 语义 |
|------|------|
| `ScheduledPublication` | 本切片只读目录;code 唯一(若适用) |
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/cms/publications` | `admin.cms.read` | 只读 |
| GET | `/admin/cms/publications/{id}` | `admin.cms.read` | 只读 |
## Migration
`000027`:表 + 种子(若有)(权限复用)
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | list 含种子或空列表合法 |
| AC-F-02 | 已知 id get 200 |
| AC-F-03 | 未知 id → 404 |
| AC-S-01 | 无 Admin → 401 |
| AC-S-02 | 无权限 → 403 |
| AC-P-01 | list &lt; 500ms |
| AC-O-01 | N/A 只读 |
contract_diff: `docs/CONTRACT_DIFF/ECR-026.yaml`
@@ -0,0 +1,41 @@
# Feature Spec: ExploreConfig · StarConfigOps · ECR-035
> Status: `Active`Loop continuous · **ECR-035 Closed**
> Parent: WAVE0-FROZEN · Predecessor: ECR-034 Closed
> Capability: `ExploreConfig` · BC: `Explore_Reports`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
配置写发布 · 引擎改分层 · UGC · 真支付
## L2 Domain
| 概念 | 语义 |
|------|------|
| `StarConfig` | 本切片只读目录;code 唯一(若适用) |
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/explore/star-configs` | `admin.explore.read` | 只读 |
| GET | `/admin/explore/star-configs/{id}` | `admin.explore.read` | 只读 |
## Migration
`000036`:表 + 种子(若有) + 授予 admin.explore.read
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | list 含种子或空列表合法 |
| AC-F-02 | 已知 id get 200 |
| AC-F-03 | 未知 id → 404 |
| AC-S-01 | 无 Admin → 401 |
| AC-S-02 | 无权限 → 403 |
| AC-P-01 | list &lt; 500ms |
| AC-O-01 | N/A 只读 |
contract_diff: `docs/CONTRACT_DIFF/ECR-035.yaml`
@@ -0,0 +1,41 @@
# Feature Spec: AICoreConfig · ToolDefinitionOps · ECR-028
> Status: `Active`Loop continuous · **ECR-028 Closed**
> Parent: WAVE0-FROZEN · Predecessor: ECR-027 Closed
> Capability: `AICoreConfig` · BC: `Ask_Ops`
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
工具在线编辑 · 运行时绑定 · UGC · 真支付
## L2 Domain
| 概念 | 语义 |
|------|------|
| `ToolDefinition` | 本切片只读目录;code 唯一(若适用) |
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/ai/tools` | `admin.ai_config.read` | 只读 |
| GET | `/admin/ai/tools/{id}` | `admin.ai_config.read` | 只读 |
## Migration
`000029`:表 + 种子(若有)(权限复用)
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | list 含种子或空列表合法 |
| AC-F-02 | 已知 id get 200 |
| AC-F-03 | 未知 id → 404 |
| AC-S-01 | 无 Admin → 401 |
| AC-S-02 | 无权限 → 403 |
| AC-P-01 | list &lt; 500ms |
| AC-O-01 | N/A 只读 |
contract_diff: `docs/CONTRACT_DIFF/ECR-028.yaml`
@@ -0,0 +1,39 @@
# Feature Spec: 用户洞察 UserIntelligenceOps · ECR-016
> Status: `Active`Loop continuous · **ECR-016 Closed**
> Parent: WAVE0-FROZEN · Predecessor: ECR-015 Closed
> Capability: `UserIntelligence` · BC: `Identity_Profile`(读)+ `Analytics_OpsB`(读)
> 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md`
## Non-goals
写标签 · 改报告正文 · Ask 全文运营编辑 · UGC · 真支付 · 新表(本切片纯读模型聚合)
## L2 读模型(无 migration
| 概念 | 来源 |
|------|------|
| `UserProfileView` | profiles 摘要(已有 detail |
| `InsightReport` | growth_reports 类型计数 + 最近列表 |
| `PsychologicalTagSet` | 由报告 type 派生的稳定标签(非 NLP) |
| `BehaviorSnapshot` | analytics_events 最近页面/事件(若有) |
## L3 API
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| GET | `/admin/users/:id/insight` | `admin.users.read` | 聚合洞察只读 |
## L4 AC
| ID | Then |
|----|------|
| AC-F-01 | 有报告用户 → insight.reports_by_type 非空或 reports 列表 |
| AC-F-02 | tags 含报告类型映射标签 |
| AC-F-03 | 无埋点时 behavior.events=[] 仍 200 |
| AC-S-01 | 无 Admin → 401 |
| AC-S-02 | 无 users.read → 403 |
| AC-P-01 | GET insight &lt; 500ms 本机 |
| AC-O-01 | N/A 只读(无写审计) |
contract_diff: `docs/CONTRACT_DIFF/ECR-016.yaml`
+3 -1
View File
@@ -169,7 +169,7 @@
**Given** Self 有生日
**When** 生成星座报告
**Then** 展示轮盘、太阳/月亮/上升、相位速览、fortune 日运与行运;无「占卜」「算命」恐吓
**Then** 展示轮盘、太阳/月亮/上升、相位速览、outlook 日/周/月/年/一生与行运;无「占卜」「算命」恐吓
**Given** 两份档案
**When** POST synastry
@@ -214,3 +214,5 @@
| Packages | `internal/star` · `ephemeris` · `natal` · `fortune` · `synastry` |
| 星历 | Swiss EphemerisCGO,默认 Moshier);热带 + Whole Sign |
| 实现 | `POST /reports/star` · `POST /reports/synastry` · nearby/invites · H5 `/star` · `/synastry` · invite |
| Gaps | ECR-012 收口:报告页复用 StarFortunePanel;分享 type=starfortuneBundle 仅读 outlook 且剥离 luckye2e mock 含 outlook |
| ESS | `docs/ECR/ECR-012-star-alignment.md`**Approved** · L2)· BD-2026-012 Approved |