fix: close remaining Z39 slug isolation gaps

Bind preview rows and published API base paths to the active module slug so cloned or stale state cannot address another module.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
whm
2026-08-07 17:34:15 +08:00
parent 473113682f
commit 154f849f57
5 changed files with 13 additions and 11 deletions

View File

@@ -186,9 +186,8 @@ func (l *PublishLogic) Publish(slug string, req *types.PublishReq) (*types.Publi
if slug != "" && slug != incoming.Meta.Slug { if slug != "" && slug != incoming.Meta.Slug {
incoming.Meta.Slug = slug incoming.Meta.Slug = slug
} }
if incoming.Apis.BasePath == "" || strings.Contains(incoming.Apis.BasePath, "-") { // Z39API 地址只由本次发布路径 slug 决定,禁止克隆蓝图沿用旧模块 base_path
incoming.Apis.BasePath = "/api/v1/apps/" + slug incoming.Apis.BasePath = "/api/v1/apps/" + slug
}
mode := strings.ToLower(strings.TrimSpace(req.Mode)) mode := strings.ToLower(strings.TrimSpace(req.Mode))
if mode == "" { if mode == "" {
@@ -568,9 +567,7 @@ func (l *PublishLogic) publishHostMetaOnly(
bp := existing.Blueprint bp := existing.Blueprint
bp.Meta.Name = moduleName bp.Meta.Name = moduleName
bp.Meta.Slug = slug bp.Meta.Slug = slug
if bp.Apis.BasePath == "" { bp.Apis.BasePath = "/api/v1/apps/" + slug
bp.Apis.BasePath = "/api/v1/apps/" + slug
}
rec := existing rec := existing
rec.Name = moduleName rec.Name = moduleName

File diff suppressed because one or more lines are too long

2
web/dist/index.html vendored
View File

@@ -7,7 +7,7 @@
<link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,600;9..144,700&family=Manrope:wght@400;500;600;700&display=swap" rel="stylesheet" /> <link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,600;9..144,700&family=Manrope:wght@400;500;600;700&display=swap" rel="stylesheet" />
<script type="module" crossorigin src="/assets/index-Pe8anoMp.js"></script> <script type="module" crossorigin src="/assets/index-D2ZGs_V_.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-CtqUfnO-.css"> <link rel="stylesheet" crossorigin href="/assets/index-CtqUfnO-.css">
</head> </head>
<body> <body>

View File

@@ -386,7 +386,12 @@ export async function listRows(
: `${PLATFORM}/api/v1/public/apps/${slug}/${resource}?${qs}`; : `${PLATFORM}/api/v1/public/apps/${slug}/${resource}?${qs}`;
// 草稿预览:优先用预览包内嵌行数据(未发布也可出图) // 草稿预览:优先用预览包内嵌行数据(未发布也可出图)
const prev = getActivePreview(); const prev = getActivePreview();
if (prev && (!resource || resource === prev.resource || !prev.resource)) { const previewSlug = String(prev?.blueprint?.meta?.slug || "");
if (
prev &&
previewSlug === slug &&
(!resource || resource === prev.resource || !prev.resource)
) {
let items = prev.rows || []; let items = prev.rows || [];
if (filters) { if (filters) {
items = items.filter((row) => items = items.filter((row) =>

View File

@@ -1285,10 +1285,10 @@ POST /api/v1/agent/sync/channels/{id}/pull
1. **根因修复**:智能体绑定的 `database_name` 是多模块共享库;旧逻辑却强制 `database_per_app/public`,导致不同 slug 的同名实体表复用。现改为共享库内 `schema_per_app`,每个模块使用独立 `app_t{tenant}_{slug}`;旧 `public` 模块重发时升级到独立 Schema随后由双向同步重新灌入所属数据。 1. **根因修复**:智能体绑定的 `database_name` 是多模块共享库;旧逻辑却强制 `database_per_app/public`,导致不同 slug 的同名实体表复用。现改为共享库内 `schema_per_app`,每个模块使用独立 `app_t{tenant}_{slug}`;旧 `public` 模块重发时升级到独立 Schema随后由双向同步重新灌入所属数据。
2. **标识符防碰撞**Schema/独立库名超过 48 字符时保留可读前缀并附加 slug 内容哈希,不再直接截断造成长 slug 碰撞。 2. **标识符防碰撞**Schema/独立库名超过 48 字符时保留可读前缀并附加 slug 内容哈希,不再直接截断造成长 slug 碰撞。
3. **页面防串包**hash 路由加载增加请求序号,快速切换模块时旧请求不得覆盖新蓝图;加载期间卸载旧模块,且校验返回蓝图 `meta.slug` 必须等于 URL slug。蓝图/数据 GET 使用 `no-store` 3. **页面防串包**hash 路由加载增加请求序号,快速切换模块时旧请求不得覆盖新蓝图;加载期间卸载旧模块,且校验返回蓝图 `meta.slug` 必须等于 URL slug。预览行缓存同时校验 slug+resource蓝图/数据 GET 使用 `no-store`
4. **回执与 capsule 可核对**publish 增加 `blueprint_revision``resource_tables`agent-capsule 增加 `app_slug``schema_name`、revision 和各资源物理 table。 4. **回执与 capsule 可核对**publish 增加 `blueprint_revision``resource_tables`agent-capsule 增加 `app_slug``schema_name`、revision 和各资源物理 table。
5. **诊断与拒绝回退**CRUD 解析后强校验 requested slug 与 resolved app 一致、Schema/table 非空;日志记录 tenant、requested slug、resource、resolved Schema/table、revision。现有 Meta 查询仍严格按 `tenant_id + slug`,不存在默认模块回退。 5. **诊断与拒绝回退**CRUD 解析后强校验 requested slug 与 resolved app 一致、Schema/table 非空;日志记录 tenant、requested slug、resource、resolved Schema/table、revision。现有 Meta 查询仍严格按 `tenant_id + slug`,不存在默认模块回退。
6. **缓存说明**:当前仓无按页面结构复用的构建产物缓存;以 tenant+slug 定位元数据并以蓝图 revision 作为诊断/响应标识HTTP 明确 `no-store`,避免旧运行时配置被复用 6. **缓存与路径说明**:当前仓无按页面结构复用的构建产物缓存;以 tenant+slug 定位元数据并以蓝图 revision 作为诊断/响应标识HTTP 明确 `no-store`。发布(含仅改 host_meta无条件把 `apis.base_path` 重写为当前 slug禁止克隆蓝图沿用旧模块路径
#### 宇恒改(须) #### 宇恒改(须)