# 数据、内容与隐私契约 > 状态:结构已定义,内容来源与授权仍为发布阻塞项 > 适用范围:卦库 assets、Room、DataStore、导入脚本和内容审核 ## 1. 数据分类 | 数据 | 来源 | 默认位置 | 敏感性 | 是否参与起卦 | |---|---|---|---|---| | 三轮币面/六爻结果 | 用户输入/本地计算 | 会话状态,可选 Room | 低至中 | 是 | | 用户问题 | 用户输入 | 会话状态,可选 Room | 高 | 否 | | 64 卦与爻辞 | 经审核的内容包 | assets 或预置 Room | 低,关注版权 | 仅用于查表 | | 本地解释 | 编辑内容 | assets | 低,关注版权 | 否 | | AI 请求与回复 | 用户主动请求 | 内存,可选 Room | 高 | 否 | | 偏好与同意版本 | 用户设置 | 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 ActionNoteEntity - sessionId: foreign key - actionText: nullable - timeboxText: nullable - completedState: NOT_SET | PLANNED | DONE | ABANDONED ``` 约束: - 数据库存储原始 18 枚币面和确定结果,读取时可重新计算并进行一致性检查。 - `questionText` 默认可为空;用户不保存问题时不能偷偷复制到其他表。 - 删除 session 应级联删除解释和行动记录。 - enum 使用稳定字符串或显式转换,不依赖 Kotlin ordinal。 - 每次 schema 迁移必须有 migration test;禁止发布构建使用 destructive migration。 ## 6. DataStore 范围 DataStore 仅保存少量偏好: - onboarding 版本是否已读; - 主题:系统/浅色/深色; - 减少应用内非必要动画; - AI 同意文本版本和同意时间; - 默认解释方式; - 是否允许保存问题原文。 不要把六爻历史、完整内容包或 AI 长文本塞入 DataStore。 ## 7. 隐私规则 - 问题文本被视为敏感用户内容。 - 本地核心流程不需要网络权限之外的危险权限。 - 未点击 AI 解读时,问题和卦象不得离开设备。 - AI 请求前展示准确的数据清单和服务方类别。 - 日志、分析、崩溃报告、截图测试夹具不得使用真实用户问题。 - 调试日志使用固定脱敏样例;发布构建关闭网络 body logging。 - 历史导出、云备份和 Android Auto Backup 策略在实现前必须单独决策。 ## 8. 数据生命周期 ```text 草稿问题/未完成投币:SavedStateHandle + 内存 ↓ 用户完成 不可变 CastResult:结果页内存 ↓ 用户明确保存 Room 历史快照 AI 请求:请求期间内存 → 服务端按已披露策略处理 AI 回复:结果页内存 → 用户保存后可进入 Room ``` 会话中止后是否保留草稿由产品设置决定;无论如何都不能把草稿作为遥测发送。 ## 9. 内容变更规则 - 修正文案:提升 `contentVersion`,记录来源和审校人。 - 修改 schema:提升 `schemaVersion`,提供向后兼容或明确迁移。 - 修改领域算法:提升 `methodVersion`,不得通过内容版本掩盖。 - 历史页必须按记录中的内容/方法版本解释旧结果,或明确提示当前展示使用了新版内容;不能静默伪装成原始解释。 Android 存储选择参考:[数据与文件概览](https://developer.android.com/training/data-storage/)、[Room 预置数据库](https://developer.android.com/training/data-storage/room/prepopulate)。