--- sidebar_position: 6 title: Data Model and State Machines sidebar_label: Data Model description: MindSpace tables, constraints, indexes, lifecycle states, and consistency rules --- # 数据模型与状态机 ## 通用约定 - 主键使用 UUID、ULID 或其他不可枚举标识。 - 时间使用 UTC 保存,客户端按用户时区展示。 - 所有业务表包含 `created_at` 和 `updated_at`。 - 需要软删除的表包含 `deleted_at`。 - JSON 仅用于扩展详情,不代替可查询的核心字段。 - 密码、token 和敏感值只保存哈希或加密值。 - 所有多租户查询必须包含 `user_id` 或通过明确 join 校验所有权。 ## 1. users | 字段 | 说明 | | --- | --- | | id | 用户主键 | | username | 登录名,唯一 | | slug | 主页 slug,唯一或全局保留 | | email | 邮箱,规范化后唯一 | | phone | 可选,加密保存 | | password_hash | 强密码哈希 | | avatar_asset_id | 头像资产 | | plan_type | free/growth/pro/enterprise | | status | pending/active/frozen/disabled/deleted | | email_verified_at | 邮箱验证时间 | | last_login_at | 最近登录 | 索引: - unique username - unique slug - unique normalized email - status ## 2. user_spaces | 字段 | 说明 | | --- | --- | | id | Space ID | | user_id | 所有者,首期一对一唯一 | | space_name | 展示名 | | quota_bytes | 总容量 | | used_bytes | 已确认占用 | | reserved_bytes | 上传中预留 | | status | active/locked/deleted | | storage_namespace | 内部存储命名空间 | 约束: - `used_bytes >= 0` - `reserved_bytes >= 0` - `used_bytes + reserved_bytes <= quota_bytes`,管理员超配场景需显式处理。 ## 3. space_categories | 字段 | 说明 | | --- | --- | | id | 分类 ID | | user_id | 所有者 | | space_id | 所属空间 | | category_code | oa/private/public/draft/archive | | category_name | 展示名 | | visibility_policy | 默认可见性 | | ai_access_policy | Agent 默认策略 | | publish_policy | 发布策略 | | is_system | 是否内置分类 | | sort_order | 排序 | 唯一约束:`space_id + category_code`。 ## 4. assets | 字段 | 说明 | | --- | --- | | id | 资产 ID | | user_id | 所有者 | | space_id | 所属空间 | | category_id | 逻辑分类 | | parent_id | 可选逻辑父目录 | | asset_type | file/folder/image/html/markdown/pdf/excel/word/ppt/page_bundle | | mime_type | 服务端检测值 | | original_filename | 原始文件名 | | display_name | 展示名 | | logical_path | 逻辑路径,不用于物理访问 | | current_version_id | 当前版本 | | size_bytes | 当前版本大小 | | checksum | 当前版本校验值 | | risk_level | 最新风险等级 | | visibility | private/internal/public_candidate | | status | uploaded/processing/ready/quarantined/archived/deleted | | source_type | upload/chat/agent/template/generated | 索引: - `user_id + category_id + updated_at` - `user_id + parent_id` - checksum,可用于用户内去重 - status ## 5. asset_versions | 字段 | 说明 | | --- | --- | | id | 版本 ID | | asset_id | 资产 | | version_no | 递增版本号 | | storage_key | 内部对象 key | | size_bytes | 版本大小 | | checksum | 内容校验值 | | mime_type | 该版本类型 | | created_by | 用户或系统主体 | | change_note | 变更说明 | | scan_status | pending/passed/warned/blocked | 唯一约束:`asset_id + version_no`。 版本删除需要先检查页面、发布和审计引用。 ## 6. page_records | 字段 | 说明 | | --- | --- | | id | Page ID | | user_id | 所有者 | | space_id | 所属空间 | | source_session_id | 来源会话 | | source_message_id | 来源消息 | | source_asset_id | 来源资产 | | title | 标题 | | summary | 摘要 | | cover_image_asset_id | 封面 | | page_type | 页面类型 | | template_id | 模板 | | draft_content_ref | 草稿内容引用 | | current_version_id | 最新保存版本 | | current_publish_id | 当前发布记录 | | status | 页面状态 | | visibility | 私有展示策略 | ## 7. page_versions | 字段 | 说明 | | --- | --- | | id | 页面版本 | | page_id | Page ID | | version_no | 递增版本 | | content_asset_id | 页面内容资产 | | bundle_asset_id | 构建后的页面包 | | source_snapshot_json | 来源摘要和追溯信息 | | security_scan_id | 对应扫描 | | created_by | 创建主体 | | change_note | 版本说明 | | immutable | 发布版本必须为 true | ## 8. publish_records | 字段 | 说明 | | --- | --- | | id | 发布 ID | | user_id | 所有者 | | page_id | 页面 | | page_version_id | 不可变版本 | | publish_type | page/share | | url_slug | 长期页面 slug | | public_url | 可派生或缓存 | | access_mode | public/password/private_link/time_limited/login_required/owner_only | | password_hash | 密码模式 | | token_hash | 分享 token 哈希 | | token_prefix | 支持运维定位的短前缀 | | expires_at | 过期时间 | | published_at | 发布时间 | | offline_at | 下线时间 | | status | draft/online/expired/offline/blocked | | view_count | 聚合浏览量 | | security_scan_id | 发布扫描 | 唯一约束: - 在线长期页:`user_id + url_slug` - token hash 唯一 ## 9. publication_events 用于保存发布历史,而不是覆盖旧记录: - id - publish_id - event_type - actor_id - old_page_version_id - new_page_version_id - access_mode - detail_json - created_at 事件包括 `published`、`republished`、`settings_changed`、`expired`、`offlined`、`blocked`。 ## 10. security_scans | 字段 | 说明 | | --- | --- | | id | 扫描 ID | | user_id | 所有者 | | target_type | asset/page_version/publication_bundle | | target_id | 目标 | | scanner_version | 扫描器和规则版本 | | status | queued/running/passed/warned/blocked/failed | | risk_level | none/low/medium/high/critical | | findings_count | 命中数量 | | summary_json | 分类统计 | | started_at | 开始 | | completed_at | 完成 | ## 11. security_findings - id - scan_id - finding_type - severity - location_json - masked_sample - recommended_action - resolution - resolved_by - resolved_at `masked_sample` 不能保存完整敏感原文。 ## 12. desensitization_rules - id - owner_type:system/user/organization - owner_id - scope - rule_name - rule_type - pattern_encrypted - replacement - strategy - enabled - priority - version - created_at - updated_at 规则类型: - phone - email - id_card - bank_card - address - person_name - company_name - amount - contract_number - medical_record_number - student_number - employee_number - custom_regex ## 13. desensitization_runs - id - user_id - source_asset_id - source_version_id - output_asset_id - output_version_id - scan_id_before - scan_id_after - applied_rules_json - status - confirmed_by - created_at ## 14. audit_logs - id - actor_type - actor_id - user_id - action - target_type - target_id - request_id - ip_hash 或按合规策略保存 IP - user_agent_summary - risk_level - result - detail_json - created_at 动作至少包括: - upload_file - delete_file - read_private_file - download_file - agent_access - generate_page - publish_page - republish_page - offline_page - share_link_created - share_link_accessed - desensitize_content - admin_freeze_user - admin_offline_publication ## 15. agent_jobs - id - user_id - session_id - job_type - instruction - permission_scope - output_category_id - status - idempotency_key - progress - result_page_id - result_asset_id - error_code - error_message - queued_at - started_at - completed_at - expires_at ## 16. agent_job_assets - id - job_id - asset_id - asset_version_id - permission:read/write/create_derivative - created_at Agent 不通过目录授权读取所有资产。 ## 17. upload_sessions - id - user_id - space_id - category_id - filename - expected_size - reserved_bytes - temporary_storage_key - status - expires_at - checksum - created_at - completed_at ## 18. templates - id - owner_type - owner_id - name - category - page_type - description - cover_asset_id - manifest_json - input_schema_json - version - status - health_disclaimer - created_at - updated_at ## 19. usage_records - id - user_id - metric_type - quantity - period_key - source_type - source_id - created_at 指标包括存储、AI 次数、公开页面数和页面访问量。 ## 20. page_view_events - id - publish_id - occurred_at - visitor_hash - session_hash - referrer_domain - device_type - country_code - is_bot 原始事件按保留策略清理,聚合结果长期保存。 ## 资产状态机 ```text uploaded -> processing -> ready \-> quarantined ready -> archived -> ready ready -> deleted quarantined -> processing quarantined -> deleted ``` ## 页面状态机 ```text draft -> processing -> reviewing reviewing -> risk_found reviewing -> ready risk_found -> draft ready -> published published -> draft # 继续编辑产生新草稿 published -> protected published/protected -> expired published/protected -> offline offline -> published # 必须重新检查并产生事件 any non-deleted -> deleted # 发布中的页面先下线 ``` 数据库中可以拆分 `status` 与 `access_mode`,避免把 protected 同时当状态和访问模式。 ## Agent job 状态机 ```text queued -> running -> succeeded queued -> cancelled running -> cancelled running -> failed -> queued # 允许重试 running -> timed_out ``` ## 并发控制 - 页面保存携带 `version` 或 `updated_at` 做乐观锁。 - 重新发布锁定 Page 或 Publication,避免两个版本同时切换。 - 配额使用数据库原子更新。 - 幂等请求复用原结果,不重复扣费或创建资产。 - 删除资产前校验引用关系,并在事务中更新配额。 ## 数据保留 - 软删除资产进入回收期,回收期内仍计入或不计入配额必须产品化配置。 - 分享 token 下线后保留哈希用于审计,不可恢复原 token。 - 审计日志保留期不得低于平台安全要求。 - 原始访问事件按隐私策略短期保留。 - 已发布版本应保留到发布记录和审计保留期结束。