From e487618665f9be70ec2edc47a4fdb42b92a2e06b Mon Sep 17 00:00:00 2001 From: "anthropic-code-agent[bot]" <242468646+Claude@users.noreply.github.com> Date: Fri, 10 Apr 2026 04:04:34 +0000 Subject: [PATCH 1/2] Initial plan From 78ea54c272808476b3bf53f12ed119064d3821dc Mon Sep 17 00:00:00 2001 From: "anthropic-code-agent[bot]" <242468646+Claude@users.noreply.github.com> Date: Fri, 10 Apr 2026 04:10:26 +0000 Subject: [PATCH 2/2] Add SysUserPreference system object for user preferences storage - Create sys-user-preference.object.ts with complete schema definition - Add USER_PREFERENCE constant to SystemObjectName in spec - Register SysUserPreference in AuthPlugin with other auth objects - Update tests to validate new USER_PREFERENCE constant - Support user preferences layer in Config Resolution hierarchy Agent-Logs-Url: https://github.com/objectstack-ai/framework/sessions/9ec9dd2d-4fd7-4b98-9840-031868eb27d4 Co-authored-by: xuyushun441-sys <255036401+xuyushun441-sys@users.noreply.github.com> --- .../plugins/plugin-auth/src/auth-plugin.ts | 4 +- .../plugins/plugin-auth/src/objects/index.ts | 1 + .../src/objects/sys-user-preference.object.ts | 82 +++++++++++++++++++ .../src/system/constants/system-names.test.ts | 2 + .../spec/src/system/constants/system-names.ts | 2 + 5 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 packages/plugins/plugin-auth/src/objects/sys-user-preference.object.ts diff --git a/packages/plugins/plugin-auth/src/auth-plugin.ts b/packages/plugins/plugin-auth/src/auth-plugin.ts index 17e8da5b6..0ccf07fc2 100644 --- a/packages/plugins/plugin-auth/src/auth-plugin.ts +++ b/packages/plugins/plugin-auth/src/auth-plugin.ts @@ -7,7 +7,7 @@ import { SysUser, SysSession, SysAccount, SysVerification, SysOrganization, SysMember, SysInvitation, SysTeam, SysTeamMember, - SysApiKey, SysTwoFactor, + SysApiKey, SysTwoFactor, SysUserPreference, } from './objects/index.js'; /** @@ -107,7 +107,7 @@ export class AuthPlugin implements Plugin { SysUser, SysSession, SysAccount, SysVerification, SysOrganization, SysMember, SysInvitation, SysTeam, SysTeamMember, - SysApiKey, SysTwoFactor, + SysApiKey, SysTwoFactor, SysUserPreference, ], }); diff --git a/packages/plugins/plugin-auth/src/objects/index.ts b/packages/plugins/plugin-auth/src/objects/index.ts index b84cb452c..8575bf113 100644 --- a/packages/plugins/plugin-auth/src/objects/index.ts +++ b/packages/plugins/plugin-auth/src/objects/index.ts @@ -27,6 +27,7 @@ export { SysTeamMember } from './sys-team-member.object.js'; // ── Additional Auth Objects ──────────────────────────────────────────────── export { SysApiKey } from './sys-api-key.object.js'; export { SysTwoFactor } from './sys-two-factor.object.js'; +export { SysUserPreference } from './sys-user-preference.object.js'; // ── Backward Compatibility (deprecated) ──────────────────────────────────── /** @deprecated Use `SysUser` instead */ diff --git a/packages/plugins/plugin-auth/src/objects/sys-user-preference.object.ts b/packages/plugins/plugin-auth/src/objects/sys-user-preference.object.ts new file mode 100644 index 000000000..c1c9a7e7b --- /dev/null +++ b/packages/plugins/plugin-auth/src/objects/sys-user-preference.object.ts @@ -0,0 +1,82 @@ +// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license. + +import { ObjectSchema, Field } from '@objectstack/spec/data'; + +/** + * sys_user_preference — System User Preference Object + * + * Per-user key-value preferences for storing UI state, settings, and personalization. + * Supports the User Preferences layer in the Config Resolution hierarchy + * (Runtime > User Preferences > Tenant > Env). + * + * Common use cases: + * - UI preferences: theme, locale, timezone, sidebar state + * - Feature flags: plugin.ai.auto_save, plugin.dev.debug_mode + * - User-specific settings: default_view, notifications_enabled + * + * @namespace sys + */ +export const SysUserPreference = ObjectSchema.create({ + namespace: 'sys', + name: 'user_preference', + label: 'User Preference', + pluralLabel: 'User Preferences', + icon: 'settings', + isSystem: true, + description: 'Per-user key-value preferences (theme, locale, etc.)', + titleFormat: '{key}', + compactLayout: ['user_id', 'key'], + + fields: { + id: Field.text({ + label: 'Preference ID', + required: true, + readonly: true, + }), + + created_at: Field.datetime({ + label: 'Created At', + defaultValue: 'NOW()', + readonly: true, + }), + + updated_at: Field.datetime({ + label: 'Updated At', + defaultValue: 'NOW()', + readonly: true, + }), + + user_id: Field.text({ + label: 'User ID', + required: true, + maxLength: 255, + description: 'Owner user of this preference', + }), + + key: Field.text({ + label: 'Key', + required: true, + maxLength: 255, + description: 'Preference key (e.g., theme, locale, plugin.ai.auto_save)', + }), + + value: Field.json({ + label: 'Value', + description: 'Preference value (any JSON-serializable type)', + }), + }, + + indexes: [ + { fields: ['user_id', 'key'], unique: true }, + { fields: ['user_id'], unique: false }, + ], + + enable: { + trackHistory: false, + searchable: false, + apiEnabled: true, + apiMethods: ['get', 'list', 'create', 'update', 'delete'], + trash: false, + mru: false, + }, +}); diff --git a/packages/spec/src/system/constants/system-names.test.ts b/packages/spec/src/system/constants/system-names.test.ts index aa6804586..a662d1e49 100644 --- a/packages/spec/src/system/constants/system-names.test.ts +++ b/packages/spec/src/system/constants/system-names.test.ts @@ -22,6 +22,7 @@ describe('SystemObjectName', () => { expect(SystemObjectName.TEAM_MEMBER).toBe('sys_team_member'); expect(SystemObjectName.API_KEY).toBe('sys_api_key'); expect(SystemObjectName.TWO_FACTOR).toBe('sys_two_factor'); + expect(SystemObjectName.USER_PREFERENCE).toBe('sys_user_preference'); expect(SystemObjectName.ROLE).toBe('sys_role'); expect(SystemObjectName.PERMISSION_SET).toBe('sys_permission_set'); expect(SystemObjectName.AUDIT_LOG).toBe('sys_audit_log'); @@ -54,6 +55,7 @@ describe('SystemObjectName', () => { expect(keys).toContain('TEAM_MEMBER'); expect(keys).toContain('API_KEY'); expect(keys).toContain('TWO_FACTOR'); + expect(keys).toContain('USER_PREFERENCE'); expect(keys).toContain('ROLE'); expect(keys).toContain('PERMISSION_SET'); expect(keys).toContain('AUDIT_LOG'); diff --git a/packages/spec/src/system/constants/system-names.ts b/packages/spec/src/system/constants/system-names.ts index 5989b22b1..8ddf7030d 100644 --- a/packages/spec/src/system/constants/system-names.ts +++ b/packages/spec/src/system/constants/system-names.ts @@ -42,6 +42,8 @@ export const SystemObjectName = { API_KEY: 'sys_api_key', /** Authentication: two-factor authentication credentials */ TWO_FACTOR: 'sys_two_factor', + /** Authentication: user preferences (theme, locale, etc.) */ + USER_PREFERENCE: 'sys_user_preference', /** Security: role definition for RBAC */ ROLE: 'sys_role', /** Security: permission set grouping */