#3391 的独立 follow-up ①。
问题
权限集(packages/spec/src/security/permission.zod.ts,ObjectPermissionSchema)目前没有用户级 import/export 位。P1 的 export 派生自 list(export ⊆ list),意味着「任何能 list 的用户即可一键全表导出」——这与全球主流平台不符:Salesforce "Export Reports"、Dynamics "Export to Excel"、NetSuite "Export Lists"、SAP S_GUI 61 都有独立的导出权限轴。
方案
P1 已预留槽,接入即零契约变更:
影响
接上后,不再是「能 list 即能导出」;默认策略需设计(建议默认开、由权限集收紧,保持向后兼容)。
关联:#3391、#3498(预留 userExportAllowed)、objectui#2823。
#3553 落地后清单看起来齐了,但只做了可见的那一半:allowExport 位、/me/permissions 注解、前端隐藏 Export 按钮都在,服务端一行都没有拦。
因为 export ⊆ list,导出路由 GET /data/:object/export 经 findData 流式读,引擎中间件看到的是一次普通 find,只按 allowRead 放行 —— 全仓没有任何代码路径读过 allowExport。所以 allowExport: false 的用户直接 curl 仍能拉走整表,本 issue「不再是能 list 即能导出」的目标并未成立(AGENTS.md 铁律 #10 的 declared ≠ enforced)。
#3709 补上了调用点:evaluator 的 export 判定(读权限 ∧ 未被显式拒绝)、ISecurityService.canExport(fail closed)、导出路由在取第一个 chunk 之前返回 403 EXPORT_NOT_PERMITTED,以及 '*' 通配符回落对齐,消除客户端/服务端分歧。
遗留(不属于本 issue 范围): plugin-reports 的定时报表把 CSV 作为邮件附件发出,同样不经过本轴 —— allowExport:false 的用户仍可建报表定时发给自己。已开 #3710 单独跟进。
#3391 的独立 follow-up ①。
问题
权限集(
packages/spec/src/security/permission.zod.ts,ObjectPermissionSchema)目前没有用户级 import/export 位。P1 的 export 派生自list(export ⊆ list),意味着「任何能 list 的用户即可一键全表导出」——这与全球主流平台不符:Salesforce "Export Reports"、Dynamics "Export to Excel"、NetSuite "Export Lists"、SAPS_GUI61 都有独立的导出权限轴。方案
P1 已预留槽,接入即零契约变更:
@objectstack/spec/dataresolveEffectiveApiMethods(enable, { userExportAllowed })的ResolveApiOptions.userExportAllowed(本期恒true);export派生 =list ∧ userExportAllowed。/me/permissions时按用户权限计算userExportAllowed,传入 resolver;export随之从有效集里去留。(feat(spec,hono): user-level export permission axis (#3544) #3553)apiOperations(objectui#2823),无需再改前端契约。影响
接上后,不再是「能 list 即能导出」;默认策略需设计(建议默认开、由权限集收紧,保持向后兼容)。
关联:#3391、#3498(预留
userExportAllowed)、objectui#2823。补充:#3553 之后仍缺执法层,由 #3709 补齐
#3553 落地后清单看起来齐了,但只做了可见的那一半:
allowExport位、/me/permissions注解、前端隐藏 Export 按钮都在,服务端一行都没有拦。因为
export ⊆ list,导出路由GET /data/:object/export经findData流式读,引擎中间件看到的是一次普通find,只按allowRead放行 —— 全仓没有任何代码路径读过allowExport。所以allowExport: false的用户直接curl仍能拉走整表,本 issue「不再是能 list 即能导出」的目标并未成立(AGENTS.md 铁律 #10 的declared ≠ enforced)。#3709 补上了调用点:evaluator 的
export判定(读权限 ∧ 未被显式拒绝)、ISecurityService.canExport(fail closed)、导出路由在取第一个 chunk 之前返回 403EXPORT_NOT_PERMITTED,以及'*'通配符回落对齐,消除客户端/服务端分歧。遗留(不属于本 issue 范围):
plugin-reports的定时报表把 CSV 作为邮件附件发出,同样不经过本轴 ——allowExport:false的用户仍可建报表定时发给自己。已开 #3710 单独跟进。