Skip to content

feat: enable system objects visibility in Studio sidebar#918

Merged
hotlong merged 5 commits into
mainfrom
copilot/fix-studio-system-objects-display
Mar 12, 2026
Merged

feat: enable system objects visibility in Studio sidebar#918
hotlong merged 5 commits into
mainfrom
copilot/fix-studio-system-objects-display

Conversation

Copilot AI commented Mar 12, 2026

Copy link
Copy Markdown
Contributor

Studio couldn't display system objects (sys_user, sys_role, sys_audit_log, etc.) because the mock kernel never registered them, the spec defaulted includeSystem: false, and the sidebar "System" group was static.

Spec defaults

  • ObjectFilterSchema.includeSystem: falsetrue
  • ObjectManagerConfigSchema.defaultFilter.includeSystem: falsetrue
  • ObjectDesignerConfigSchema.objectManager.defaultFilter.includeSystem: falsetrue (nested .default() block aligned to prevent override)
  • Added regression test assertion for ObjectDesignerConfigSchema.objectManager.defaultFilter.includeSystem

Mock kernel — system object registration

  • Imports all 14 system object definitions from plugin-auth, plugin-security, plugin-audit via Vite aliases (resolves to source — avoids pulling in better-auth and other runtime deps)
  • Registers them as a com.objectstack.system AppPlugin before user configs
// vite.config.ts — resolve to plugin source objects barrel (no runtime deps)
'@objectstack/plugin-auth/objects': path.resolve(__dirname, '../../packages/plugins/plugin-auth/src/objects/index.ts'),

Sidebar — dynamic system objects group

  • isSystemObject() helper detects objects by isSystem === true, namespace === 'sys', FQN prefix (sys__), or legacy prefix (sys_)
  • "System" group now includes a collapsible "System Objects" section populated from metadata
  • Eye/EyeOff toggle on Data group header to show/hide system objects from the main list (with aria-label and type="button" for accessibility)
  • filteredMetaItems memo separates system objects when toggle is off
  • Collapsible onOpenChange handles open/close explicitly to stay in sync with search state

Docs

  • CHANGELOG.md, ROADMAP.md, Studio ROADMAP.md, object-designer reference updated
Original prompt

This section details on the original issue you should resolve

<issue_title>Studio 无法显示系统对象(sys_user、sys_role 等)</issue_title>
<issue_description>## 问题描述
在 ObjectStack Studio 中无法看到平台内置系统对象(如 sys_user、sys_role、sys_audit_log 等),导致无法管理用户、权限、审计等核心元数据。

原因总结

  1. Studio Kernel 未注册 plugin-auth、plugin-security、plugin-audit 等系统插件,导致系统对象未被加载。
  2. Sidebar 的 ObjectManager 默认过滤掉 isSystem=true 的对象(includeSystem: false)。
  3. Sidebar 中"System"分组未动态展示系统对象,只显示静态 API Console 和 Packages。

复现步骤

  1. 启动 Studio,进入对象管理。
  2. 仅能看到业务对象,无法看到 sys_xxx 系统对象。

期望结果

  • Studio 左侧对象列表能够列出所有系统对象(sys_user、sys_role、sys_audit_log 等)。
  • 支持直接查看、编辑、管理系统对象元数据。

建议解决方案

  • 在 Studio Kernel 初始化时将 plugin-auth、plugin-security、plugin-audit 自动注册。
  • Sidebar ObjectManager 默认展示 includeSystem=true 的对象,并提供"系统对象"分组。
  • "System"分组下可动态加载所有 isSystem=true 的对象。
  • 对象过滤器可自由切换展示/隐藏系统对象。

架构建议

  • 采用长期可持续的方式,自动注册所有 sys 域对象,确保平台一致性与可维护性。
  • 修复后同步更新 ROADMAP.md 和 CHANGELOG.md。
  • 所有设计需保证未来自动化、低代码、DSL 场景可扩展。

如需支持,我可提交 PR 完成相关修复。</issue_description>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

@vercel

vercel Bot commented Mar 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
objectstack-play Ready Ready Preview, Comment Mar 12, 2026 6:25am
spec Ready Ready Preview, Comment Mar 12, 2026 6:25am

Request Review

Copilot AI and others added 2 commits March 12, 2026 04:43
- Change ObjectFilterSchema.includeSystem default from false to true
- Change ObjectManagerConfigSchema.defaultFilter.includeSystem to true
- Register system objects (auth/security/audit) in Studio mock kernel
- Add dynamic System Objects group in sidebar with collapsible list
- Add show/hide system objects toggle on Data group
- Update CHANGELOG.md, ROADMAP.md, and documentation

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
… sidebar

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix visibility issue for system objects in Studio feat: enable system objects visibility in Studio sidebar Mar 12, 2026
@hotlong
hotlong marked this pull request as ready for review March 12, 2026 05:58
Copilot AI review requested due to automatic review settings March 12, 2026 05:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Enables Studio to surface built-in system objects (auth/security/audit) by default by updating spec defaults, registering system objects into the Studio mock kernel, and making the sidebar’s “System” section dynamically list detected system objects.

Changes:

  • Changed Studio Object Designer filter defaults to include system objects by default (includeSystem: true) and updated the related spec test/docs.
  • Added Vite aliases + mock-kernel registration for system object definitions from plugin-auth/security/audit.
  • Updated Studio sidebar to detect and render a dynamic “System Objects” collapsible section and a Data-group toggle for system-object visibility.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
packages/spec/src/studio/object-designer.zod.ts Switches system-object filter defaults to true (but see note about conflicting higher-level defaults).
packages/spec/src/studio/object-designer.test.ts Updates expectations for new filter defaults.
content/docs/references/studio/object-designer.mdx Documents includeSystem default as true.
apps/studio/vite.config.ts Adds Vite aliases to import system object definitions from plugin source.
apps/studio/src/mocks/createKernel.ts Registers system objects as a built-in “system” AppPlugin in the Studio mock kernel.
apps/studio/src/components/app-sidebar.tsx Adds dynamic system object grouping + Data group show/hide toggle.
apps/studio/ROADMAP.md Notes the Studio system object visibility fix.
ROADMAP.md Marks system object visibility as completed work.
CHANGELOG.md Describes the new Studio behavior and the spec default change.

Comment on lines +499 to +503
<span className="truncate">
{itemName.startsWith(SYSTEM_OBJECT_PREFIX) && (
<span className="text-muted-foreground font-mono text-xs">{SYSTEM_OBJECT_PREFIX}</span>
)}
{itemLabel}

Copilot AI Mar 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the System Objects list, the prefix hint uses SYSTEM_OBJECT_PREFIX (sys_) and checks itemName.startsWith(SYSTEM_OBJECT_PREFIX), but object names are FQNs like sys__user. As a result, the prefix label never renders for actual system objects. Consider rendering the namespace (e.g., sys__) or deriving a consistent display from parseFQN(itemName) instead of hardcoding sys_.

Copilot uses AI. Check for mistakes.
Comment on lines +364 to 367
includeSystem: true,
includeAbstract: false,
}).describe('Default filter configuration'),

Copilot AI Mar 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ObjectManagerConfigSchema.defaultFilter now defaults includeSystem: true, but ObjectDesignerConfigSchema later sets objectManager.defaultFilter.includeSystem: false in its own .default({ ... }) block (around line ~550 in this file). That higher-level default will override the new schema default and keep system objects hidden in practice. Align the ObjectDesignerConfigSchema default with the new includeSystem: true behavior (or remove the redundant nested default to avoid future drift).

Suggested change
includeSystem: true,
includeAbstract: false,
}).describe('Default filter configuration'),
includeAbstract: false,
}).describe('Default filter configuration'),

Copilot uses AI. Check for mistakes.
Comment on lines 308 to 313
it('should accept empty object with defaults', () => {
const result = ObjectFilterSchema.parse({});
expect(result.includeSystem).toBe(false);
expect(result.includeSystem).toBe(true);
expect(result.includeAbstract).toBe(false);
expect(result.package).toBeUndefined();
expect(result.tags).toBeUndefined();

Copilot AI Mar 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests update ObjectFilterSchema's default includeSystem, but there is no assertion that the top-level ObjectDesignerConfigSchema default (result.objectManager.defaultFilter.includeSystem) matches the new behavior. Adding that assertion would prevent regressions like a nested .default({ ... }) overriding the schema default.

Copilot uses AI. Check for mistakes.
| **package** | `string` | optional | Filter by owning package |
| **tags** | `string[]` | optional | Filter by object tags |
| **includeSystem** | `boolean` | ✅ | Include system-level objects |
| **includeSystem** | `boolean` | ✅ | Include system-level objects (default: `true`) |

Copilot AI Mar 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docs now state includeSystem defaults to true, but ObjectDesignerConfigSchema currently hardcodes objectManager.defaultFilter.includeSystem: false in its .default({ ... }) block (later in object-designer.zod.ts). Either update the code default or adjust this doc so it reflects the actual effective default.

Suggested change
| **includeSystem** | `boolean` || Include system-level objects (default: `true`) |
| **includeSystem** | `boolean` || Include system-level objects (default: `false`) |

Copilot uses AI. Check for mistakes.
Comment on lines +133 to +140
/** System object name prefix — objects with this prefix are grouped under "System" */
const SYSTEM_OBJECT_PREFIX = 'sys_';

/** Check if an object item is a system object */
function isSystemObject(item: any): boolean {
const name = item.name || item.id || '';
return item.isSystem === true || name.startsWith(SYSTEM_OBJECT_PREFIX);
}

Copilot AI Mar 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SYSTEM_OBJECT_PREFIX is set to sys_, but object names coming from the registry are stored as FQNs like sys__user (see SchemaRegistry.registerObject storing name: fqn). This means the name.startsWith(SYSTEM_OBJECT_PREFIX) branch in isSystemObject() will never match for current system objects; rely on namespace/FQN parsing (e.g., parseFQN(name).namespace === 'sys') or update the prefix to sys__ to keep the fallback accurate.

Copilot uses AI. Check for mistakes.
Comment on lines +370 to +378
<button
title={showSystemInData ? 'Hide system objects' : 'Show system objects'}
onClick={(e) => { e.stopPropagation(); setShowSystemInData(!showSystemInData); }}
className="ml-1 shrink-0 rounded p-0.5 text-sidebar-foreground/50 hover:text-sidebar-foreground hover:bg-sidebar-accent transition-colors"
>
{showSystemInData
? <Eye className="h-3 w-3" />
: <EyeOff className="h-3 w-3" />}
</button>

Copilot AI Mar 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The system-object filter toggle button relies on title only. For accessibility, add an aria-label (and consider type="button" to avoid accidental form submission if this component is ever rendered inside a <form>).

Copilot uses AI. Check for mistakes.
{systemObjects.length > 0 && (
<Collapsible
open={expandedTypes.has('_system_objects') || !!searchQuery}
onOpenChange={() => toggleTypeExpanded('_system_objects')}

Copilot AI Mar 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Collapsible is controlled via open={expandedTypes.has('_system_objects') || !!searchQuery}, but onOpenChange ignores the boolean argument and always toggles. This can leave expandedTypes out of sync (especially when searchQuery forces open to true) and makes the expansion state unpredictable after searching. Handle onOpenChange(open) by explicitly adding/removing _system_objects based on open instead of toggling blindly.

Suggested change
onOpenChange={() => toggleTypeExpanded('_system_objects')}
onOpenChange={(open) => {
const isExpanded = expandedTypes.has('_system_objects');
if (open && !isExpanded) {
toggleTypeExpanded('_system_objects');
}
if (!open && isExpanded) {
toggleTypeExpanded('_system_objects');
}
}}

Copilot uses AI. Check for mistakes.
@hotlong

hotlong commented Mar 12, 2026

Copy link
Copy Markdown
Collaborator

@copilot 仔细评估是否已经完成了任务总要求的所有开发?

…e, a11y, collapsible sync

- Fix ObjectDesignerConfigSchema nested default overriding includeSystem back to false (line 550)
- Fix isSystemObject() to match FQN format (sys__user) and legacy format (sys_user)
- Fix system namespace prefix display to use namespace-based format
- Add aria-label and type="button" on filter toggle for accessibility
- Fix Collapsible onOpenChange to handle open/close explicitly instead of blind toggle
- Add regression test for ObjectDesignerConfigSchema.objectManager.defaultFilter.includeSystem

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>

Copilot AI commented Mar 12, 2026

Copy link
Copy Markdown
Contributor Author

@copilot 仔细评估是否已经完成了任务总要求的所有开发?

已重新评估并完善所有任务要求,在 eee9dae 中修复了所有 review 反馈:

已完成的任务项:

  1. ✅ Studio Kernel 自动注册 plugin-auth、plugin-security、plugin-audit 的系统对象(14个)
  2. ✅ Sidebar ObjectManager 默认 includeSystem: true(三级 Schema 全部对齐)
  3. ✅ "System" 分组动态加载所有 isSystem=true 的对象
  4. ✅ 对象过滤器可切换展示/隐藏系统对象(Eye/EyeOff toggle)

本次修复的关键问题:

  • ObjectDesignerConfigSchema 嵌套 .default() 覆盖 includeSystemfalse(已对齐为 true
  • isSystemObject() 使用 sys_ 前缀无法匹配 FQN 格式 sys__user(已支持双下划线 FQN + 旧格式 + namespace 属性检测)
  • 添加了无障碍属性 aria-labeltype="button"
  • Collapsible onOpenChange 逻辑同步修复
  • 增加了 ObjectDesignerConfigSchema 级别的回归测试

全部 6683 个 spec 测试通过,CodeQL 安全扫描 0 告警。

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
@hotlong

hotlong commented Mar 12, 2026

Copy link
Copy Markdown
Collaborator

@copilot fix all

Copilot AI commented Mar 12, 2026

Copy link
Copy Markdown
Contributor Author

@copilot fix all

All 7 review comments were already addressed in commits eee9dae and c2fac1c. Here's the status:

  1. ✅ FQN prefix display — uses isSystemObject() + SYSTEM_NAMESPACE: label (not hardcoded sys_)
  2. ObjectDesignerConfigSchema nested .default() — aligned to includeSystem: true at all 3 levels (line 331, 364, 550)
  3. ✅ Regression test — expect(result.objectManager.defaultFilter.includeSystem).toBe(true) at line 451
  4. ✅ Docs — includeSystem documents default: true
  5. isSystemObject() — checks isSystem, namespace, FQN prefix (sys__), and legacy prefix (sys_)
  6. ✅ Accessibility — type="button" + aria-label on toggle
  7. Collapsible onOpenChange — explicit open/close sync

All 6683 spec tests pass. No remaining issues.

@hotlong
hotlong merged commit 6519b8b into main Mar 12, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Studio 无法显示系统对象(sys_user、sys_role 等)

3 participants