From ad2525d9e621a3f69f023cbeea98f7e87517c9f5 Mon Sep 17 00:00:00 2001 From: dev9-bb Date: Tue, 20 Oct 2026 23:44:07 +0800 Subject: [PATCH 1/2] docs: register the native share-qualification seam CfShareGrantFunc is the second, explicitly separate seam for permissions that exist without a library grant. Record why the tightening chain cannot express one (it starts from a native grant and ends at NULL), what it may answer (r/rw at an exact path, never admin), how it is gated, and which entry points it deliberately does not cover -- sync and web upload keep their library-level gate, because their cache key has no room for a path. --- docs/EXTENSION-POINTS.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/EXTENSION-POINTS.md b/docs/EXTENSION-POINTS.md index 46ce3e2c..e29bff33 100644 --- a/docs/EXTENSION-POINTS.md +++ b/docs/EXTENSION-POINTS.md @@ -76,6 +76,7 @@ seasearch、Elasticsearch、企业自有检索服务都可以是同一个 kind | 扩展点 | 上游调用点 | 基线行为 | |---|---|---| | `CfPermFunc` | `rpc-service.c` 的 `check_permission_by_path` | 透传原生权限 | +| `CfShareGrantFunc` | `rpc-service.c` 的 `check_permission_by_path`,**仅当原生库权限为空** | 不注册 → 原生拒绝照旧 | | `CfDirentFilterFunc` | `rpc-service.c` 的目录列举 RPC 出口 | 不过滤 | | `CfRestrictedFunc` | `cf_find_restricted_path` RPC → 同步 / 打包下载 | 返回 NULL(子树全可达) | | `CfFileOpPrepareFunc` | `repo-op.c` 全部 19 个写入口;Go 写入口经 `cf_fileop_prepare` RPC | 放行 | @@ -107,6 +108,23 @@ provider 无法把它放宽回来(`:106-107`)。所以这条 Hook **结构 core 依据适用的目录 ACL/共享授予资格(`server/cloudfile-policy.h:48-56`)。给 `cf_ext_check_permission` 补 SQL 字段永远得不到这个效果——它在第一步就已经返回了。 +**同一件事在原生写入口上另有一条缝:`CfShareGrantFunc`(2026-10-20)。** +`cf_ext_check_permission` 的链救不了写侧是有原因的,把它掰过来代价更大: +链的语义是"从原生权限出发收紧",而非成员的共享是"从零开始给资格",两者混在一起 +就没法再断言"每个 provider 只收紧"。所以写侧用一条**明说的、单独的**缝: + +- `seafile_check_permission_by_path()` 在原生库权限为空时(且**不是** RPC 失败)才问 + `cf_ext_share_grant()`,它返回该**精确路径**上的 `r`/`rw`,永不返回 `admin`; +- 库根与任何未共享路径一律不放行,答案由 `cf_v2_share.c` 向 Hub 的 + `/cloudfile/acl/check/` 求证(同 Go fileserver 用的那个内部 JWT 通道,见 + `cf_v2_acl_check_json()`),响应里的 `permissions` 逐检查项给出级别; +- C/Go 的终判不变:Go 写入口仍走 `cfACLPath`/`cfACLFinal`,C 仍走提交事务内的检查。 + +这条缝**只覆盖 API 写入口**(上传链接、新建目录、重命名、移动、删除、seafdav)。 +同步协议与 Web 直传走 `http-server.c` / `sync_api.go` 的库级 `check_permission` 及其 +按 repo+user+op 缓存——那里没有可携带路径的缓存键,也沿用"同步协议按库拒绝"的既有 +结论,非成员仍不进入这两条协议。 + 完整契约(谁判、判到什么范围、哪些入口不得当终判)见 [权限终判契约](permission-adjudication-contract.md)。 From bb180b7b888aef7db3f8df8a31be89a9a0e50c08 Mon Sep 17 00:00:00 2001 From: servicememeai Date: Wed, 21 Oct 2026 01:16:20 +0900 Subject: [PATCH 2/2] docs: align native share registration with standard V2 schema --- docs/EXTENSION-POINTS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/EXTENSION-POINTS.md b/docs/EXTENSION-POINTS.md index e29bff33..3bd0a204 100644 --- a/docs/EXTENSION-POINTS.md +++ b/docs/EXTENSION-POINTS.md @@ -118,6 +118,7 @@ core 依据适用的目录 ACL/共享授予资格(`server/cloudfile-policy.h:4 - 库根与任何未共享路径一律不放行,答案由 `cf_v2_share.c` 向 Hub 的 `/cloudfile/acl/check/` 求证(同 Go fileserver 用的那个内部 JWT 通道,见 `cf_v2_acl_check_json()`),响应里的 `permissions` 逐检查项给出级别; +- 注册仅检查标准 V2 三表 `cf_library_storage`、`cf_dir_acl`、`cf_sso_group_map` 与内部 Hub 通道;不依赖已退役的 `cf_managed_library` 或新增功能开关。未安装 V2、表不齐或通道不可用时保留原生拒绝;实际路径授权仍由 Hub 判定。 - C/Go 的终判不变:Go 写入口仍走 `cfACLPath`/`cfACLFinal`,C 仍走提交事务内的检查。 这条缝**只覆盖 API 写入口**(上传链接、新建目录、重命名、移动、删除、seafdav)。