背景
准备发布 15.1 :framework 15.0.0 → 15.1.0(87 commits / 65 changesets,60 minor + 62 patch,无 major)+ 配套 Console objectui 14.0.0 → 14.1.0(94 commits,framework 已钉 b8967495be73,console dist 校验一致)。
本 issue 是发布前的完整测试清单,逐项验证后勾选。配套产物:
release docs 增补:content/docs/releases/v15.mdx 新增 "What's new in 15.1.0" 章节(分支 release/15.1-docs,待 PR)
测试计划长文:docs/plans/release-15.1-test-plan.md(同分支)
测试环境 :examples/app-showcase + objectstack dev --ui --seed-admin -p 3901 -d file:/tmp/showcase-rel151-3901/data.db,workspace 全量构建 71/71 绿,console dist == .objectui-sha。
图例:🖥 浏览器验证 · 🔌 API/CLI 验证 · 🤖 已有自动化钉死(CI)
A. 安全加固
A1 🔌🤖 静态 readonly UPDATE 强制:REST PATCH readonly 字段被 strip(security: 服务端 readonly 字段在 UPDATE 时未强制(可被用户上下文覆盖) #2948 /fix(security): enforce static readonly fields on the UPDATE write path (#2948) #2957 /安全:静态字段 readonly: true 仅 UI 层生效、服务端不强制 → 审批/状态/金额字段可被直接 PATCH 绕过写入(FLS 缺口) #3003 ,dogfood 已钉)
A2 🔌🤖 readonlyWhen 多行 UPDATE 强制,任一锁定行 → 整批丢弃该字段(安全:readonlyWhen 服务端剥离仅覆盖单条 update 路径,多行 updateMany 不强制(条件只读可被批量绕过) #3042 )
A3 🔌🤖 owner_id 锚点:insert 伪造/update 转移需 transfer grant;bulk insert 自动 stamp(安全:owner_id(属主锚点)客户端可写、服务端无守卫 → 非属主可伪造/转移记录属主 #3004 /fix(security): 守卫 owner_id 属主锚点 + bulk 写按属主收敛 (#3004, #2982) #3018 )
A4 🔌🤖 bulk write 按 owner/RLS write filter 收窄,fail-closed(Security: bulk (multi) update/delete skips OWD owner scoping on private objects — members can modify others' rows #2982 )
A5 🔌🤖 删用户 set_null 级联豁免 owner guard,级联不中断(属主守卫与级联 set_null 冲突:非特权删除 sys_user 时 owner_id 级联置空被 #3004 守卫拦截(级联中途失败) #3023 /fix(security): 级联 set_null 豁免属主转移守卫 (#3023) #3048 )
A6 🔌🤖 $expand 强制被引对象 RLS/FLS(Security: $expand bypasses RLS/FLS on the referenced object (data leak on lookups) #2850 /fix(security): enforce referenced-object RLS/FLS on $expand (#2850) #2961 )
A7 🖥🔌 public form 剥离 server-managed 锚点(owner_id/organization_id/audit 列)(安全:公开表单(publicFormGrant)提交绕过 owner_id 属主守卫 → 匿名可伪造属主 #3022 /fix(security): 公开表单不可再伪造服务端托管锚点(owner_id 等)(#3022) #3036 )
A8 🔌🤖 匿名 deny 统一:未登录 POST /graphql、raw /data → 401([security] Anonymous posture inconsistent across surfaces: dispatcher /graphql and raw hono /data bypass requireAuth (/meta now gated) #2567 系列)
A9 🔌 MCP run_action 需 ai.exposed,fail-closed + audit log(fix(security): gate the MCP action surface on ai.exposed, fail-closed (#2849) #2964 )
A10 🔌🤖 reports IDOR / 定时报表 RLS / RAG fall-open 三洞(Security: Reports surface ignores caller identity — cross-user/cross-tenant IDOR (read/delete any report) + scheduled reports bypass owner RLS #2980 /Security: Knowledge/RAG retrieval fall-opens to unfiltered corpus when ExecutionContext is missing or system — agent data ceiling escape #2981 /ADR-0096 (execution-surface identity admission) + fixes for the 3 confirmed-exploitable holes it surfaced (#2980, #2981, #2982) #2975 )
A11 🖥 OWD 保存门:packaged 对象只能收紧 sharingModel;external ≤ internal 保存时拒绝(OWD posture is lint-only at runtime: env can widen a packaged object's sharingModel via OS_METADATA_WRITABLE, and external≤internal (ADR-0090 D11) is never enforced on the write path #3050 + objectui#2508)
A12 🖥🔌🤖 附件访问链:读继承 parent、下载 401/403 + 短时效签名 URL、attach 需 parent EDIT([attachments] v1 follow-ups: sys_file orphan lifecycle + non-admin permission matrix dogfood #2755 /[attachments] v2 tracking: parent-visibility inheritance, authed downloads, remaining enforce-or-remove #2970 )
A13 🔌 sharing rule seed-not-clobber + capability scope seed-once(Audit sibling declared-metadata↔record two-store types (sys_position, sys_sharing_rule, sys_capability) per ADR-0094 addendum #2909 )
A14 🖥 better-auth 1.7.0-rc.1 登录链路正常(登录成功、后续请求 200)✅ 已验:admin 登录 + 全程会话正常
B. 声明式 Connector(ADR-0096/0097)
C. 附件 v1
D. Dashboard 全局筛选
E. Console 核心体验(objectui 14.1)
E1 🖥 Record 级 inline edit:共享 draft + 单次原子 Save ✅ 已验:双击进入 record 级编辑,highlight strip(负责人)+ 正文(税率)同时可编;两处改动 → 底部同一 Save 条 → 恰好一次 PATCH,响应含两处新值,updated_by 服务端 stamp;编辑中 header Edit 置灰
E2 🖥 多按钮 record header:≥3 动作并排,Delete/Share 进 ⋯(objectui#2574)
E3 🖥 related list 权限门控:无子对象 read 权限 → section 不渲染(objectui#2565,需非管理员用户)
E4 🖥 kanban:stageField 默认 lane + highlightFields 默认卡片字段(objectui#2596/chore: version packages #2541 )
E5 🖥 拼音搜索 ✅ 已验:⌘K zhangwei → 张伟(联系人);API search=zw → 张伟、lin → Faye Lin、王 → 王芳;记录 __search:"zhangwei zw" 伴随列已回填
E6 🖥 conditional tabs:page:tabs item visibleWhen,FALSE 时整 tab 消失(feat(spec): conditional tabs — page:tabs items accept a visibleWhen CEL predicate (#2606) #2967 + objectui#2516)
E7 🖥🤖 B3 级联选项:country→province 门控/过滤 + role-gated tier + server 拒绝越权提交(test(app-showcase): B3 cascading-select fixture — server-enforced dynamic options (#2559) #3006 ;进行中:表单 dependsOn 门控已见,「Select country first」;选 China 后 province 选项集待确认 )
E8 🖥 GB18030 CSV 导入:GBK 中文表头正常映射(objectui#2557)
E9 🖥 toast 不再因 error envelope 崩页(React Add i18n support for homepage (国际化官网首页) #31 )(objectui#2580)
E10 🖥 Studio/metadata-admin 跟随应用 locale,无混语言(objectui#2602)
E11 🖥 活动 feed/audit 摘要 workspace locale 本地化(fix(plugin-audit): localize activity summaries to the workspace locale (#3039) #3045 /feat(showcase+lint+audit): ADR-0085 #2548 follow-ups — console bump past PR4, detail-shapes e2e, shadowed-group lint, labeled feed summaries #3029 )
E12 🖥 Create User:param 可翻译 + 显式密码胜出不报 400(i18n: console action-dialog param labels are untranslatable — os i18n extract skips actions[].params #3030 /auth: create-user 400s when a password is typed while generatePassword keeps its default (true) #3031 )
E13 🖥🤖 action visible 三陷阱:record_more 进 ⋯ 菜单、os.user.* 别名、报错谓词 warn(objectui#2611)
F. Studio(设计期)
G. 平台 / 协议 / 部署(API·CLI)
回归门(发布前必须全绿)
已发现的观察项(非阻塞,待分诊)
发票列表 Owner id 列显示裸 FK id (he9M1IJv…)而非用户名——view 配置或 lookup display 解析,观感问题。
登录页/顶栏品牌仍为 "ObjectOS" ——15.1 已把 'ObjectOS' 从 spec 公开面退役(refactor(spec): retire 'ObjectOS' from the spec's public surface — Kernel naming #2963 ,ObjectOS 专指商业发行),OSS console 品牌是否要跟随改名需拍板。
E7 级联表单选 China 后 Province 仍显示 "Select country first" 占位——待确认是选项集未刷新还是占位文案未更新(功能本身有 live e2e 钉着)。
背景
准备发布 15.1:framework
15.0.0 → 15.1.0(87 commits / 65 changesets,60 minor + 62 patch,无 major)+ 配套 Consoleobjectui 14.0.0 → 14.1.0(94 commits,framework 已钉b8967495be73,console dist 校验一致)。本 issue 是发布前的完整测试清单,逐项验证后勾选。配套产物:
content/docs/releases/v15.mdx新增 "What's new in 15.1.0" 章节(分支release/15.1-docs,待 PR)docs/plans/release-15.1-test-plan.md(同分支)测试环境:
examples/app-showcase+objectstack dev --ui --seed-admin -p 3901 -d file:/tmp/showcase-rel151-3901/data.db,workspace 全量构建 71/71 绿,console dist ==.objectui-sha。图例:🖥 浏览器验证 · 🔌 API/CLI 验证 · 🤖 已有自动化钉死(CI)
A. 安全加固
readonlyUPDATE 强制:REST PATCH readonly 字段被 strip(security: 服务端 readonly 字段在 UPDATE 时未强制(可被用户上下文覆盖) #2948/fix(security): enforce static readonly fields on the UPDATE write path (#2948) #2957/安全:静态字段 readonly: true 仅 UI 层生效、服务端不强制 → 审批/状态/金额字段可被直接 PATCH 绕过写入(FLS 缺口) #3003,dogfood 已钉)readonlyWhen多行 UPDATE 强制,任一锁定行 → 整批丢弃该字段(安全:readonlyWhen 服务端剥离仅覆盖单条 update 路径,多行 updateMany 不强制(条件只读可被批量绕过) #3042)owner_id锚点:insert 伪造/update 转移需 transfer grant;bulk insert 自动 stamp(安全:owner_id(属主锚点)客户端可写、服务端无守卫 → 非属主可伪造/转移记录属主 #3004/fix(security): 守卫 owner_id 属主锚点 + bulk 写按属主收敛 (#3004, #2982) #3018)set_null级联豁免 owner guard,级联不中断(属主守卫与级联 set_null 冲突:非特权删除 sys_user 时 owner_id 级联置空被 #3004 守卫拦截(级联中途失败) #3023/fix(security): 级联 set_null 豁免属主转移守卫 (#3023) #3048)$expand强制被引对象 RLS/FLS(Security: $expand bypasses RLS/FLS on the referenced object (data leak on lookups) #2850/fix(security): enforce referenced-object RLS/FLS on $expand (#2850) #2961)POST /graphql、raw/data→ 401([security] Anonymous posture inconsistent across surfaces: dispatcher /graphql and raw hono /data bypass requireAuth (/meta now gated) #2567 系列)run_action需ai.exposed,fail-closed + audit log(fix(security): gate the MCP action surface onai.exposed, fail-closed (#2849) #2964)external ≤ internal保存时拒绝(OWD posture is lint-only at runtime: env can widen a packaged object's sharingModel via OS_METADATA_WRITABLE, and external≤internal (ADR-0090 D11) is never enforced on the write path #3050 + objectui#2508)B. 声明式 Connector(ADR-0096/0097)
GET /api/v1/automation/connectors见origin:'declarative'(feat(connectors): ADR-0096 — provider-bound declarative connector instances (#2977) #2994/feat(showcase): live provider:'mcp' declarative connector demo + CI-pinned dogfood proof (#3056) #3062)enabled:false静音(feat(automation,spec): descriptor-only contract + boot audit for declarative connectors (#2612) #2985)C. 附件 v1
D. Dashboard 全局筛选
{value,label}options 不再崩 dashboard,select 显示 label(objectui#2597)E. Console 核心体验(objectui 14.1)
updated_by服务端 stamp;编辑中 header Edit 置灰zhangwei→ 张伟(联系人);APIsearch=zw→ 张伟、lin→ Faye Lin、王→ 王芳;记录__search:"zhangwei zw"伴随列已回填visibleWhen,FALSE 时整 tab 消失(feat(spec): conditional tabs — page:tabs items accept a visibleWhen CEL predicate (#2606) #2967 + objectui#2516)os i18n extractskipsactions[].params#3030/auth: create-user 400s when a password is typed whilegeneratePasswordkeeps its default (true) #3031)record_more进 ⋯ 菜单、os.user.* 别名、报错谓词 warn(objectui#2611)F. Studio(设计期)
previous.补全 + did-you-mean(objectui#2571)?surface=owd:overview深链(objectui#2508)G. 平台 / 协议 / 部署(API·CLI)
aggregate_recordsMCP 工具(RLS 一致 + FLS 输入门)(feat(mcp): aggregate_records 工具 — GROUP BY 聚合走 engine 读路径(RLS/D10/FLS 全继承) #2976)actionrows execute but are invisible to MCP list_actions/run_action (declaration-surfacing gap) #3010/fix(runtime): surface standalone authored action rows on the MCP action bridge (#3010) #3020)overwritethrough packages.install for upgrade flows #3007)migrate meta --from 10(feat(protocol): complete ADR-0087 — load-seam handshake, chain backfill 12–15, release artifacts #2972)kernel:bootstrapped+app:seededmembership backfill(feat(kernel): kernel:bootstrapped anchor + fix everyone auto-bind ordering (#2926 follow-ups) #2989/fix(plugin-auth): re-run membership backfill when app seeding settles (#2996) #3000)strategy:残留 → 响亮 parse error + tombstone(feat(spec)!: 删除 tenancy.strategy + tenancy.crossTenantAccess — tenancy 块 strict 化 + tombstone(#2763) #2962)__search伴随列 boot backfill ✅ 已验:seed 存量行带__search,见 E5$参数 400(app-showcase 权限模型复测清单(07-15 对照 main 重评):1 项回归级重大缺陷(#2930 锚点写护栏被 A4 词表打穿)+ 2 项部分修复 + 3 项未修 + 1 项建议降级 + 2 项观察 #2926 ⑦⑩)回归门(发布前必须全绿)
pnpm build全绿(71/71,console dist ==.objectui-sha✅)pnpm test全绿(含全部 dogfood 套件)e2e/live/showcase-smoke.spec.tspnpm check:release-notesos validateexamples 三道门已发现的观察项(非阻塞,待分诊)
he9M1IJv…)而非用户名——view 配置或 lookup display 解析,观感问题。