Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,9 @@ V2 内置 ACL、CE 原生 Tag 和已安装 Guard 的 Checkout 不应重新受旧
**纯文档变更不编译、不跑测试、不构建镜像,也不部署。** 小范围代码改动优先检查受影响路径、复用已验证的证据;全量 C/Go/前端构建、三仓联验及镜像发布只在明确必要的阶段或发布任务开展。不要因一次文档提交自动要求全仓编译。

不要提交 `deploy/compose/.env`、任何真实凭据、密钥、持久数据卷或镜像构建产物。文档中文,代码和 commit message 英文;上游既有风格优先。

## 开发期数据库变更(2026-10-21)

- 新版当前只明确新增四张业务表:`cf_library_storage`、`cf_dir_acl`、`cf_sso_group_map`、`cf_edit_guard`。历史表仅作备份或迁移输入,不属于新版运行库及运行依赖;增加业务表须先确认,历史数据单独归档,不直接删除。
- 开发期建表、升级及数据迁移通过 Docker 仓 `database/` 下独立、人工执行的 SQL 交付,DEV 验证与 PROD 发布复用固定脚本及校验和。启动/重启仅校验,不自动执行扩展 DDL、旧迁移链或兼容补丁。
- 仅明确审核的成熟版本之间才考虑自动升级;须定义精确源/目标范围和数据/中断恢复验证。不得根据 dev 分支、表名存在或旧台账自动推断升级路径,不自动回滚。
31 changes: 31 additions & 0 deletions database/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# CloudFile 开发期数据库交付

2026-10-21 决策:CloudFile 仍处于开发阶段,数据库结构升级和数据迁移使用**独立、人工执行的 SQL**。DEV 验证与 PROD 发布使用同一份固定 SQL 包;成熟版本之间才允许另行设计、审核自动升级机制。开发分支、构建成功或标签变化都不自动取得迁移资格。

## 唯一新增业务表清单

截至本次决策,新版只明确新增四张表:

| 表 | 作用 |
| --- | --- |
| `cf_library_storage` | 库与存储绑定 |
| `cf_dir_acl` | 目录权限及分享属性 |
| `cf_sso_group_map` | 外部身份与原生组映射 |
| `cf_edit_guard` | 编辑 Guard;普通上传下载不创建 Checkout/Checkin |

其它 `cf_*` 名称属于历史实现或待确认依赖,仅用于备份或数据迁移,不属于新版运行库或运行依赖。不得因旧源码、JSON 迁移、旧开关或当前数据库存在便将其带入新版。不得将旧迁移链、`cloudfile.sql` 或 Django 的自动迁移直接作为新版初始化入口,也不据此删除现有表和数据。增加第五张业务表必须先单独确认设计。SQL 的候选表、归档表使用 `stage_`/`backup_` 前缀,属于受控运维产物,不能作为新业务模型。

## SQL 包与执行规则

当前包:[20261021-four-table-baseline](v2/20261021-four-table-baseline/README.md)。每个包说明源结构、目标结构、适用的 Server/Hub/Docker 提交、数据转换限制、执行顺序、验收与故障处理,并固定 SQL SHA256。

- 新安装执行独立建表 SQL;已有实例按精确源结构选择升级 SQL。发现缺表、未知结构或非空 Guard 时停止并审查,不自动猜测映射。
- 应用启动/重启检查运行库不混入历史 CloudFile 表;基础三表必须匹配,Guard 仅在显式启用 Checkout 时检查,不执行 CloudFile 开发期 DDL、数据回填或旧兼容修复;不使用开发期开关恢复自动升级。结构不匹配就停止并给出手动 SQL 提示。
- 发布前备份、停止所有写入者;DEV 验证后将同一份 SQL 及校验和用于对应源结构的 PROD,不能把 DEV 业务数据覆盖 PROD。两环境结构不同则另写并审核迁移。
- 数据库结构与业务数据迁移分别写清,禁止静默截断、猜测身份、重置真实锁 generation 或依赖 HTTP 200 作为落盘证明。业务对象引用须可核验。
- 默认不自动回滚。MySQL/MariaDB DDL 可能隐式提交,中断后先查看候选表、归档表及数据;停止写入后由人工决定修复或恢复。不能仅因脚本失败就重跑或删除备份。
- 已交付并执行的 SQL 不改写;后续修正用新包记录。以脚本校验和、实际表结构和执行记录为依据,不伪造旧 `cf_schema_migration` 的成功状态。

成熟版本自动升级必须另外给出明确的源/目标版本范围、完整依赖表清单、并发/停机边界、备份与中断恢复证据、全量数据转换验收以及发布审批;不能默认遍历历史迁移目录。上游成熟 Seafile 版本的原有升级流程与 CloudFile 开发期扩展 SQL 分开管理。

历史 `cloudfile-directory-schema.py`、`SchemaRunner.apply()` 与 `tools/repair-v2-four-tables.py` 保留用于追溯,不作为新版开发期发布入口。已运行的容器仍使用旧启动代码,代码变更须随匹配版本发布后才能生效;此次规范和 SQL 交付不意味着已经替换 DEV 镜像或执行 PROD 升级。
83 changes: 83 additions & 0 deletions database/v2/20261021-four-table-baseline/00-create.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
-- New installation only. Select the native Seafile database explicitly.
-- Do not use IF NOT EXISTS: a colliding old layout must stop installation.
-- CloudFile V2 fresh schema. Native CE tables remain the authoritative facts.
-- This file is independent of cloudfile.sql and the legacy migration chain.

CREATE TABLE cf_library_storage (
repo_key VARCHAR(80) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
repo_id CHAR(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
state VARCHAR(8) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
PRIMARY KEY (repo_key),
UNIQUE KEY library_storage_repo (repo_id),
CONSTRAINT library_storage_state CHECK (state IN ('reserved','active','retired'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

CREATE TABLE cf_sso_group_map (
provider VARCHAR(32) COLLATE utf8mb4_bin NOT NULL,
subject_type VARCHAR(4) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
namespace VARCHAR(128) COLLATE utf8mb4_bin NOT NULL,
external_id VARCHAR(225) COLLATE utf8mb4_bin NOT NULL,
group_id BIGINT NOT NULL,
PRIMARY KEY (provider,subject_type,namespace,external_id),
UNIQUE KEY sso_native_group (group_id),
CONSTRAINT sso_group_type CHECK (subject_type IN ('org','role')),
CONSTRAINT sso_group_id CHECK (group_id > 0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

CREATE TABLE cf_dir_acl (
repo_id CHAR(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
path_hash BINARY(32) NOT NULL,
path VARCHAR(4096) COLLATE utf8mb4_bin NOT NULL,
subject_type VARCHAR(4) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
provider VARCHAR(32) COLLATE utf8mb4_bin NOT NULL,
namespace VARCHAR(128) COLLATE utf8mb4_bin NOT NULL,
external_id VARCHAR(225) COLLATE utf8mb4_bin NOT NULL,
permission VARCHAR(9) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
inherit TINYINT NOT NULL,
share_mode TINYINT NOT NULL,
revision CHAR(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
PRIMARY KEY (repo_id,path_hash,subject_type,provider,namespace,external_id),
KEY acl_shared_subject (provider,subject_type,namespace,external_id,share_mode,repo_id),
CONSTRAINT acl_subject_type CHECK (subject_type IN ('user','org','role')),
CONSTRAINT acl_permission CHECK (permission IN ('r','rw','invisible')),
CONSTRAINT acl_inherit CHECK (inherit IN (0,1)),
CONSTRAINT acl_share CHECK (share_mode IN (0,1) AND
(share_mode=0 OR (permission IN ('r','rw') AND path <> '/')))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

-- CloudFile V2 optional Rust local editing. Fresh isolated CF-EDIT installations ONLY.
-- The three-table V2 MVP remains unchanged unless editing is explicitly enabled.
-- There is NO server-side Intent or editing Session table. Seafile keeps native
-- File/Block/Commit/Branch versions; Agent Rust keeps its local pending Journal.
-- One row per physical file path preserves generation across Checkout cycles.
CREATE TABLE cf_edit_guard (
repo_id CHAR(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
path_hash BINARY(32) NOT NULL,
path VARCHAR(4096) COLLATE utf8mb4_bin NOT NULL,
guard_id CHAR(36) CHARACTER SET ascii COLLATE ascii_bin NULL,
generation BIGINT UNSIGNED NOT NULL DEFAULT 0,
owner_uid VARCHAR(225) COLLATE utf8mb4_bin NULL,
owner_native_user VARCHAR(255) COLLATE utf8mb4_bin NULL,
terminal_type VARCHAR(16) CHARACTER SET ascii COLLATE ascii_bin NULL,
terminal_name VARCHAR(128) COLLATE utf8mb4_bin NULL,
checkout_ip VARCHAR(45) CHARACTER SET ascii COLLATE ascii_bin NULL,
proof_digest CHAR(64) CHARACTER SET ascii COLLATE ascii_bin NULL,
base_file_id CHAR(40) CHARACTER SET ascii COLLATE ascii_bin NULL,
lease_expires_at DATETIME(6) NULL,
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
PRIMARY KEY (repo_id, path_hash),
UNIQUE KEY cf_edit_guard_id (guard_id),
KEY cf_edit_guard_active (repo_id, guard_id),
KEY cf_edit_guard_owner (owner_uid, guard_id),
CONSTRAINT cf_edit_terminal_type CHECK (
terminal_type IS NULL OR terminal_type IN ('windows','macos','linux','other')
),
CONSTRAINT cf_edit_active_shape CHECK (
(guard_id IS NULL AND owner_uid IS NULL AND owner_native_user IS NULL
AND proof_digest IS NULL AND base_file_id IS NULL AND lease_expires_at IS NULL)
OR
(guard_id IS NOT NULL AND owner_uid IS NOT NULL AND owner_native_user IS NOT NULL
AND proof_digest IS NOT NULL AND base_file_id IS NOT NULL AND lease_expires_at IS NOT NULL)
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
18 changes: 18 additions & 0 deletions database/v2/20261021-four-table-baseline/01-preflight.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
-- Read-only inspection, usable before/after the four-table conversion.
-- Select the native Seafile database. Output metadata and aggregates only.
SELECT DATABASE() AS database_name, VERSION() AS engine_version;
SELECT TABLE_NAME,ENGINE,TABLE_COLLATION FROM information_schema.TABLES
WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME IN
('cf_library_storage','cf_dir_acl','cf_sso_group_map','cf_edit_guard') ORDER BY TABLE_NAME;
SELECT TABLE_NAME,COLUMN_NAME,COLUMN_TYPE,IS_NULLABLE,COLUMN_DEFAULT,COLLATION_NAME
FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME IN
('cf_library_storage','cf_dir_acl','cf_sso_group_map','cf_edit_guard') ORDER BY TABLE_NAME,ORDINAL_POSITION;
SELECT TABLE_NAME,INDEX_NAME,NON_UNIQUE,SEQ_IN_INDEX,COLUMN_NAME,SUB_PART
FROM information_schema.STATISTICS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME IN
('cf_library_storage','cf_dir_acl','cf_sso_group_map','cf_edit_guard') ORDER BY TABLE_NAME,INDEX_NAME,SEQ_IN_INDEX;
SELECT 'cf_library_storage' AS table_name,COUNT(*) AS row_count FROM cf_library_storage
UNION ALL SELECT 'cf_dir_acl',COUNT(*) FROM cf_dir_acl
UNION ALL SELECT 'cf_sso_group_map',COUNT(*) FROM cf_sso_group_map
UNION ALL SELECT 'cf_edit_guard',COUNT(*) FROM cf_edit_guard;
SELECT COUNT(*) AS guard_rows,SUM(guard_id IS NOT NULL) AS occupied_guard_rows,
SUM(generation>0) AS rows_with_generation FROM cf_edit_guard;
18 changes: 18 additions & 0 deletions database/v2/20261021-four-table-baseline/05-archive-legacy.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
-- Read-only archive plan. Historical tables must not remain in V2 runtime.
-- Select the runtime DB and set @cf_upgrade_archive_database to a separately
-- backed-up archive DB. Review the generated statements and dependencies,
-- stop all writers, then execute the reviewed RENAME statements explicitly.
-- This file itself never moves or deletes data; FK/views require DBA review.
SELECT TABLE_NAME,TABLE_TYPE,ENGINE
FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE()
AND LOWER(LEFT(TABLE_NAME,2))='cf'
AND TABLE_NAME NOT IN ('cf_library_storage','cf_dir_acl','cf_sso_group_map','cf_edit_guard')
ORDER BY TABLE_NAME;
SELECT CONCAT('RENAME TABLE `',REPLACE(TABLE_SCHEMA,'`','``'),'`.`',REPLACE(TABLE_NAME,'`','``'),
'` TO `',REPLACE(@cf_upgrade_archive_database,'`','``'),'`.`',REPLACE(TABLE_NAME,'`','``'),'`;')
AS reviewed_archive_sql
FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_TYPE='BASE TABLE'
AND @cf_upgrade_archive_database IS NOT NULL AND @cf_upgrade_archive_database<>DATABASE()
AND LOWER(LEFT(TABLE_NAME,2))='cf'
AND TABLE_NAME NOT IN ('cf_library_storage','cf_dir_acl','cf_sso_group_map','cf_edit_guard')
ORDER BY TABLE_NAME;
Loading
Loading