2026-08-04 17:09:52 +08:00
|
|
|
|
# 数据、内容与隐私契约
|
|
|
|
|
|
|
|
|
|
|
|
> 状态:结构已定义,内容来源与授权仍为发布阻塞项
|
|
|
|
|
|
> 适用范围:卦库 assets、Room、DataStore、导入脚本和内容审核
|
|
|
|
|
|
|
|
|
|
|
|
## 1. 数据分类
|
|
|
|
|
|
|
|
|
|
|
|
| 数据 | 来源 | 默认位置 | 敏感性 | 是否参与起卦 |
|
|
|
|
|
|
|---|---|---|---|---|
|
2026-08-04 23:00:05 +08:00
|
|
|
|
| 十八枚币面/六爻结果 | 用户输入/本地计算 | 会话状态;结果锁定后默认 Room | 低至中 | 是 |
|
|
|
|
|
|
| 用户问题 | 用户输入 | 会话状态;按默认开启的设置进入 Room | 高 | 否 |
|
2026-08-04 17:09:52 +08:00
|
|
|
|
| 64 卦与爻辞 | 经审核的内容包 | assets 或预置 Room | 低,关注版权 | 仅用于查表 |
|
|
|
|
|
|
| 本地解释 | 编辑内容 | assets | 低,关注版权 | 否 |
|
2026-08-04 23:00:05 +08:00
|
|
|
|
| AI 请求与回复 | 用户主动请求 | 请求在内存;回复按默认开启的设置进入 Room | 高 | 否 |
|
2026-08-04 17:09:52 +08:00
|
|
|
|
| 偏好与同意版本 | 用户设置 | DataStore | 中 | 否 |
|
|
|
|
|
|
|
|
|
|
|
|
任何“否”的数据都不能成为 `CastEngine` 输入。
|
|
|
|
|
|
|
|
|
|
|
|
## 2. 本地内容包
|
|
|
|
|
|
|
|
|
|
|
|
建议使用带清单的版本化 JSON:
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"schemaVersion": 1,
|
|
|
|
|
|
"contentVersion": "zh-Hans-2026.1",
|
|
|
|
|
|
"sources": [
|
|
|
|
|
|
{
|
|
|
|
|
|
"id": "source-id",
|
|
|
|
|
|
"title": "来源名称",
|
|
|
|
|
|
"edition": "版本说明",
|
|
|
|
|
|
"license": "许可证或公版依据",
|
|
|
|
|
|
"url": "https://example.invalid"
|
|
|
|
|
|
}
|
|
|
|
|
|
],
|
|
|
|
|
|
"hexagrams": [
|
|
|
|
|
|
{
|
|
|
|
|
|
"kingWenNumber": 1,
|
|
|
|
|
|
"name": "乾",
|
|
|
|
|
|
"symbol": "䷀",
|
|
|
|
|
|
"lowerTrigram": "QIAN",
|
|
|
|
|
|
"upperTrigram": "QIAN",
|
|
|
|
|
|
"patternBottomUp": ["YANG", "YANG", "YANG", "YANG", "YANG", "YANG"],
|
|
|
|
|
|
"judgmentOriginal": "…",
|
|
|
|
|
|
"judgmentPlain": "…",
|
|
|
|
|
|
"lineTextsBottomUp": ["…", "…", "…", "…", "…", "…"],
|
|
|
|
|
|
"linePlainBottomUp": ["…", "…", "…", "…", "…", "…"],
|
|
|
|
|
|
"specialUsageText": "…",
|
|
|
|
|
|
"sourceRefs": ["source-id"]
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
示例中的省略号不是可发布内容。禁止由 AI 在构建时临时补齐缺失卦辞或爻辞。
|
|
|
|
|
|
|
|
|
|
|
|
## 3. 内容完整性门禁
|
|
|
|
|
|
|
|
|
|
|
|
内容包进入应用前必须自动验证:
|
|
|
|
|
|
|
|
|
|
|
|
- `schemaVersion` 为客户端支持值;
|
|
|
|
|
|
- 64 个条目数量准确;
|
|
|
|
|
|
- 文王卦号 1–64 各出现且只出现一次;
|
|
|
|
|
|
- 64 个 `patternBottomUp` 各不重复,且与上下卦一致;
|
|
|
|
|
|
- 每卦恰有六条 bottom-up 爻辞;
|
|
|
|
|
|
- 名称、卦辞、来源引用和许可证字段非空;
|
|
|
|
|
|
- 乾、坤特殊文本是否存在与内容版本声明一致;
|
|
|
|
|
|
- 所有文本为有效 UTF-8,无 HTML/Markdown 脚本或不可见控制字符;
|
|
|
|
|
|
- 生成内容校验摘要,便于安装包与内容版本对应。
|
|
|
|
|
|
|
|
|
|
|
|
运行时若内容包校验失败,应用应显示数据完整性错误并禁用结果查表,不能使用错误卦、相邻数组项或 AI 猜测作为降级。
|
|
|
|
|
|
|
|
|
|
|
|
## 4. 来源与授权
|
|
|
|
|
|
|
|
|
|
|
|
- 古代原文、公版翻译、现代译注和编辑改写必须分栏记录,不能把“古籍公版”错误外推到现代译本。
|
|
|
|
|
|
- 每段可发布文本必须能追踪到 `sourceRefs` 和授权依据。
|
|
|
|
|
|
- 现代白话建议由项目自行撰写并审核,或使用明确允许再分发和修改的来源。
|
|
|
|
|
|
- 字体、纹理、插画和音效同样进入许可证清单。
|
|
|
|
|
|
- 发布包内提供“内容来源”页面;用户能查看版本和来源。
|
|
|
|
|
|
|
|
|
|
|
|
内容负责人确认来源前,64 卦内容任务不可标记完成。
|
|
|
|
|
|
|
|
|
|
|
|
## 5. Room 数据模型提案
|
|
|
|
|
|
|
|
|
|
|
|
历史记录不是起卦事实源,但应保存可复核的快照:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
CastingSessionEntity
|
|
|
|
|
|
- id: UUID string, primary key
|
|
|
|
|
|
- createdAt: Instant/epoch millis
|
|
|
|
|
|
- methodVersion: string
|
|
|
|
|
|
- contentVersion: string
|
|
|
|
|
|
- coinConvention: enum string
|
|
|
|
|
|
- roundsJson: validated JSON
|
|
|
|
|
|
- lineValues: compact validated representation
|
|
|
|
|
|
- primaryHexagramId: 1..64
|
|
|
|
|
|
- transformedHexagramId: 1..64
|
|
|
|
|
|
- movingPositions: validated representation
|
|
|
|
|
|
- questionText: nullable
|
|
|
|
|
|
- questionSaved: boolean
|
|
|
|
|
|
|
|
|
|
|
|
ExplanationEntity
|
|
|
|
|
|
- id: UUID string, primary key
|
|
|
|
|
|
- sessionId: foreign key
|
|
|
|
|
|
- source: LOCAL | AI
|
|
|
|
|
|
- contractVersion: string
|
|
|
|
|
|
- content: validated structured JSON
|
|
|
|
|
|
- createdAt
|
2026-08-04 23:00:05 +08:00
|
|
|
|
- supersedesExplanationId: nullable foreign key
|
2026-08-04 17:09:52 +08:00
|
|
|
|
|
|
|
|
|
|
ActionNoteEntity
|
|
|
|
|
|
- sessionId: foreign key
|
|
|
|
|
|
- actionText: nullable
|
|
|
|
|
|
- timeboxText: nullable
|
|
|
|
|
|
- completedState: NOT_SET | PLANNED | DONE | ABANDONED
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
约束:
|
|
|
|
|
|
|
|
|
|
|
|
- 数据库存储原始 18 枚币面和确定结果,读取时可重新计算并进行一致性检查。
|
|
|
|
|
|
- `questionText` 默认可为空;用户不保存问题时不能偷偷复制到其他表。
|
2026-08-04 23:00:05 +08:00
|
|
|
|
- 第六爻锁定时读取一次 `HistorySavePolicy` 快照;总开关开启时,在单个事务中创建 `CastingSessionEntity`,并按默认开启的内容开关写入 `questionText`。关闭总开关或选择“本次不保存”时不得产生长期记录。
|
|
|
|
|
|
- 同一流程随后生成的本地或 AI 解读按策略写入关联的 `ExplanationEntity`;重新解读新增实体并通过 `supersedesExplanationId` 保留版本关系,不得静默覆写旧正文。
|
|
|
|
|
|
- 行动记录按策略关联到同一 session;没有实际行动内容时不创建空 `ActionNoteEntity`。
|
2026-08-04 17:09:52 +08:00
|
|
|
|
- 删除 session 应级联删除解释和行动记录。
|
|
|
|
|
|
- enum 使用稳定字符串或显式转换,不依赖 Kotlin ordinal。
|
|
|
|
|
|
- 每次 schema 迁移必须有 migration test;禁止发布构建使用 destructive migration。
|
|
|
|
|
|
|
|
|
|
|
|
## 6. DataStore 范围
|
|
|
|
|
|
|
|
|
|
|
|
DataStore 仅保存少量偏好:
|
|
|
|
|
|
|
|
|
|
|
|
- onboarding 版本是否已读;
|
|
|
|
|
|
- 主题:系统/浅色/深色;
|
|
|
|
|
|
- 减少应用内非必要动画;
|
|
|
|
|
|
- AI 同意文本版本和同意时间;
|
|
|
|
|
|
- 默认解释方式;
|
2026-08-04 23:00:05 +08:00
|
|
|
|
- `autoSaveHistory`:默认 `true`;
|
|
|
|
|
|
- `saveQuestionText`:默认 `true`;
|
|
|
|
|
|
- `saveExplanationContent`:默认 `true`;
|
|
|
|
|
|
- `saveActionNote`:默认 `true`。
|
|
|
|
|
|
|
|
|
|
|
|
总开关关闭时,后三项不参与自动写入,但保留用户上次选择;再次开启后恢复。DataStore 中的本地保存偏好与 AI 同意版本是独立字段,不得相互推导。
|
2026-08-04 17:09:52 +08:00
|
|
|
|
|
|
|
|
|
|
不要把六爻历史、完整内容包或 AI 长文本塞入 DataStore。
|
|
|
|
|
|
|
|
|
|
|
|
## 7. 隐私规则
|
|
|
|
|
|
|
|
|
|
|
|
- 问题文本被视为敏感用户内容。
|
|
|
|
|
|
- 本地核心流程不需要网络权限之外的危险权限。
|
|
|
|
|
|
- 未点击 AI 解读时,问题和卦象不得离开设备。
|
|
|
|
|
|
- AI 请求前展示准确的数据清单和服务方类别。
|
|
|
|
|
|
- 日志、分析、崩溃报告、截图测试夹具不得使用真实用户问题。
|
|
|
|
|
|
- 调试日志使用固定脱敏样例;发布构建关闭网络 body logging。
|
2026-08-04 23:00:05 +08:00
|
|
|
|
- `CastingSessionEntity`、`ExplanationEntity`、`ActionNoteEntity` 所在的 Room 数据库及其 `-wal`、`-shm` 等辅助文件必须通过 Android backup/data-extraction 规则排除,不参与 Auto Backup、设备到设备迁移或厂商云备份。
|
|
|
|
|
|
- MVP 不提供历史导出、账号或云同步。未来任何导出、备份或同步都必须新增决策、展示准确范围并取得单独的明确选择。
|
2026-08-04 17:09:52 +08:00
|
|
|
|
|
|
|
|
|
|
## 8. 数据生命周期
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
草稿问题/未完成投币:SavedStateHandle + 内存
|
2026-08-04 23:00:05 +08:00
|
|
|
|
↓ 第六爻确认并锁定
|
2026-08-04 17:09:52 +08:00
|
|
|
|
不可变 CastResult:结果页内存
|
2026-08-04 23:00:05 +08:00
|
|
|
|
├─ autoSaveHistory=true → Room 会话快照 + 按设置保存问题
|
|
|
|
|
|
└─ autoSaveHistory=false → 不写 Room,可由用户选择“保存本次”
|
2026-08-04 17:09:52 +08:00
|
|
|
|
|
|
|
|
|
|
AI 请求:请求期间内存 → 服务端按已披露策略处理
|
2026-08-04 23:00:05 +08:00
|
|
|
|
本地/AI 回复:结果页内存 → 按设置关联到同一 Room 会话
|
|
|
|
|
|
└─ 会话不存在或解释保存关闭 → 不长期保存,可由用户选择保存本次
|
2026-08-04 17:09:52 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-08-04 23:00:05 +08:00
|
|
|
|
“最近一次”不是独立复制的数据,而是按 `createdAt` 从 Room 查询得到的最新已保存会话。首页不得缓存另一份问题或解释正文;删除该会话后,最近记录区域必须随查询结果一起更新为空态或下一条记录。
|
|
|
|
|
|
|
|
|
|
|
|
中止的未完成草稿只按 SavedState 恢复策略存在,不进入问卦簿;无论如何都不能把草稿作为遥测发送。用户选择“本次不保存/删除本次记录”后,应删除已经自动创建的 session 及其关联内容,但不改写全局设置。
|
2026-08-04 17:09:52 +08:00
|
|
|
|
|
|
|
|
|
|
## 9. 内容变更规则
|
|
|
|
|
|
|
|
|
|
|
|
- 修正文案:提升 `contentVersion`,记录来源和审校人。
|
|
|
|
|
|
- 修改 schema:提升 `schemaVersion`,提供向后兼容或明确迁移。
|
|
|
|
|
|
- 修改领域算法:提升 `methodVersion`,不得通过内容版本掩盖。
|
|
|
|
|
|
- 历史页必须按记录中的内容/方法版本解释旧结果,或明确提示当前展示使用了新版内容;不能静默伪装成原始解释。
|
|
|
|
|
|
|
|
|
|
|
|
Android 存储选择参考:[数据与文件概览](https://developer.android.com/training/data-storage/)、[Room 预置数据库](https://developer.android.com/training/data-storage/room/prepopulate)。
|