Skip to content

Commit 72bc3eb

Browse files
Copilothotlong
andcommitted
feat: add missing sys_team and sys_team_member objects, unify auth-schema-config to use SystemObjectName constants
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 272ed8f commit 72bc3eb

8 files changed

Lines changed: 155 additions & 11 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313
`ObjectSchema.create()` unless an explicit `tableName` is provided. This decouples the logical object name
1414
from the physical table name and enables unified routing, permissions, and discovery by domain.
1515
- **SystemObjectName constants** — Extended with all system objects: `ORGANIZATION`, `MEMBER`, `INVITATION`,
16-
`API_KEY`, `TWO_FACTOR`, `ROLE`, `PERMISSION_SET`, `AUDIT_LOG` (in addition to existing `USER`, `SESSION`,
17-
`ACCOUNT`, `VERIFICATION`, `METADATA`).
18-
- **plugin-auth system objects** — Added `SysOrganization`, `SysMember`, `SysInvitation`, `SysApiKey`,
19-
`SysTwoFactor` object definitions with `namespace: 'sys'`. Existing objects (`SysUser`, `SysSession`,
20-
`SysAccount`, `SysVerification`) migrated to use namespace convention.
16+
`TEAM`, `TEAM_MEMBER`, `API_KEY`, `TWO_FACTOR`, `ROLE`, `PERMISSION_SET`, `AUDIT_LOG` (in addition to
17+
existing `USER`, `SESSION`, `ACCOUNT`, `VERIFICATION`, `METADATA`).
18+
- **plugin-auth system objects** — Added `SysOrganization`, `SysMember`, `SysInvitation`, `SysTeam`,
19+
`SysTeamMember`, `SysApiKey`, `SysTwoFactor` object definitions with `namespace: 'sys'`. Existing objects
20+
(`SysUser`, `SysSession`, `SysAccount`, `SysVerification`) migrated to use namespace convention.
2121
- **plugin-security system objects** — Added `SysRole` and `SysPermissionSet` object definitions.
2222
- **plugin-audit** — New plugin package with `SysAuditLog` immutable audit trail object definition.
2323
- **StorageNameMapping.resolveTableName()** — Now supports namespace-aware auto-derivation

ROADMAP.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,8 @@ Objects now declare `namespace: 'sys'` and a short `name` (e.g., `name: 'user'`)
325325
| `SystemObjectName.ORGANIZATION` | `sys_organization` | plugin-auth | Authentication: organization (multi-org) |
326326
| `SystemObjectName.MEMBER` | `sys_member` | plugin-auth | Authentication: organization member |
327327
| `SystemObjectName.INVITATION` | `sys_invitation` | plugin-auth | Authentication: organization invitation |
328+
| `SystemObjectName.TEAM` | `sys_team` | plugin-auth | Authentication: team within an organization |
329+
| `SystemObjectName.TEAM_MEMBER` | `sys_team_member` | plugin-auth | Authentication: team membership |
328330
| `SystemObjectName.API_KEY` | `sys_api_key` | plugin-auth | Authentication: API key for programmatic access |
329331
| `SystemObjectName.TWO_FACTOR` | `sys_two_factor` | plugin-auth | Authentication: two-factor credentials |
330332
| `SystemObjectName.ROLE` | `sys_role` | plugin-security | Security: RBAC role definition |

packages/plugins/plugin-auth/src/auth-schema-config.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ export const AUTH_VERIFICATION_CONFIG = {
157157
* | updatedAt | updated_at |
158158
*/
159159
export const AUTH_ORGANIZATION_SCHEMA = {
160-
modelName: 'sys_organization',
160+
modelName: SystemObjectName.ORGANIZATION, // 'sys_organization'
161161
fields: {
162162
createdAt: 'created_at',
163163
updatedAt: 'updated_at',
@@ -178,7 +178,7 @@ export const AUTH_ORGANIZATION_SCHEMA = {
178178
* | createdAt | created_at |
179179
*/
180180
export const AUTH_MEMBER_SCHEMA = {
181-
modelName: 'sys_member',
181+
modelName: SystemObjectName.MEMBER, // 'sys_member'
182182
fields: {
183183
organizationId: 'organization_id',
184184
userId: 'user_id',
@@ -202,7 +202,7 @@ export const AUTH_MEMBER_SCHEMA = {
202202
* | teamId | team_id |
203203
*/
204204
export const AUTH_INVITATION_SCHEMA = {
205-
modelName: 'sys_invitation',
205+
modelName: SystemObjectName.INVITATION, // 'sys_invitation'
206206
fields: {
207207
organizationId: 'organization_id',
208208
inviterId: 'inviter_id',
@@ -240,7 +240,7 @@ export const AUTH_ORG_SESSION_FIELDS = {
240240
* | updatedAt | updated_at |
241241
*/
242242
export const AUTH_TEAM_SCHEMA = {
243-
modelName: 'sys_team',
243+
modelName: SystemObjectName.TEAM, // 'sys_team'
244244
fields: {
245245
organizationId: 'organization_id',
246246
createdAt: 'created_at',
@@ -262,7 +262,7 @@ export const AUTH_TEAM_SCHEMA = {
262262
* | createdAt | created_at |
263263
*/
264264
export const AUTH_TEAM_MEMBER_SCHEMA = {
265-
modelName: 'sys_team_member',
265+
modelName: SystemObjectName.TEAM_MEMBER, // 'sys_team_member'
266266
fields: {
267267
teamId: 'team_id',
268268
userId: 'user_id',
@@ -283,7 +283,7 @@ export const AUTH_TEAM_MEMBER_SCHEMA = {
283283
* | userId | user_id |
284284
*/
285285
export const AUTH_TWO_FACTOR_SCHEMA = {
286-
modelName: 'sys_two_factor',
286+
modelName: SystemObjectName.TWO_FACTOR, // 'sys_two_factor'
287287
fields: {
288288
backupCodes: 'backup_codes',
289289
userId: 'user_id',

packages/plugins/plugin-auth/src/objects/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ export { SysVerification } from './sys-verification.object.js';
2121
export { SysOrganization } from './sys-organization.object.js';
2222
export { SysMember } from './sys-member.object.js';
2323
export { SysInvitation } from './sys-invitation.object.js';
24+
export { SysTeam } from './sys-team.object.js';
25+
export { SysTeamMember } from './sys-team-member.object.js';
2426

2527
// ── Additional Auth Objects ────────────────────────────────────────────────
2628
export { SysApiKey } from './sys-api-key.object.js';
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
import { ObjectSchema, Field } from '@objectstack/spec/data';
4+
5+
/**
6+
* sys_team_member — System Team Member Object
7+
*
8+
* Links users to teams within organizations.
9+
* Backed by better-auth's organization plugin (teams feature).
10+
*
11+
* @namespace sys
12+
*/
13+
export const SysTeamMember = ObjectSchema.create({
14+
namespace: 'sys',
15+
name: 'team_member',
16+
label: 'Team Member',
17+
pluralLabel: 'Team Members',
18+
icon: 'user-plus',
19+
isSystem: true,
20+
description: 'Team membership records linking users to teams',
21+
titleFormat: '{user_id} in {team_id}',
22+
compactLayout: ['user_id', 'team_id', 'created_at'],
23+
24+
fields: {
25+
id: Field.text({
26+
label: 'Team Member ID',
27+
required: true,
28+
readonly: true,
29+
}),
30+
31+
created_at: Field.datetime({
32+
label: 'Created At',
33+
defaultValue: 'NOW()',
34+
readonly: true,
35+
}),
36+
37+
team_id: Field.text({
38+
label: 'Team ID',
39+
required: true,
40+
}),
41+
42+
user_id: Field.text({
43+
label: 'User ID',
44+
required: true,
45+
}),
46+
},
47+
48+
indexes: [
49+
{ fields: ['team_id', 'user_id'], unique: true },
50+
{ fields: ['user_id'] },
51+
],
52+
53+
enable: {
54+
trackHistory: true,
55+
searchable: false,
56+
apiEnabled: true,
57+
apiMethods: ['get', 'list', 'create', 'delete'],
58+
trash: false,
59+
mru: false,
60+
},
61+
});
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
import { ObjectSchema, Field } from '@objectstack/spec/data';
4+
5+
/**
6+
* sys_team — System Team Object
7+
*
8+
* Teams within an organization for fine-grained grouping.
9+
* Backed by better-auth's organization plugin (teams feature).
10+
*
11+
* @namespace sys
12+
*/
13+
export const SysTeam = ObjectSchema.create({
14+
namespace: 'sys',
15+
name: 'team',
16+
label: 'Team',
17+
pluralLabel: 'Teams',
18+
icon: 'users',
19+
isSystem: true,
20+
description: 'Teams within organizations for fine-grained grouping',
21+
titleFormat: '{name}',
22+
compactLayout: ['name', 'organization_id', 'created_at'],
23+
24+
fields: {
25+
id: Field.text({
26+
label: 'Team ID',
27+
required: true,
28+
readonly: true,
29+
}),
30+
31+
created_at: Field.datetime({
32+
label: 'Created At',
33+
defaultValue: 'NOW()',
34+
readonly: true,
35+
}),
36+
37+
updated_at: Field.datetime({
38+
label: 'Updated At',
39+
defaultValue: 'NOW()',
40+
readonly: true,
41+
}),
42+
43+
name: Field.text({
44+
label: 'Name',
45+
required: true,
46+
searchable: true,
47+
maxLength: 255,
48+
}),
49+
50+
organization_id: Field.text({
51+
label: 'Organization ID',
52+
required: true,
53+
}),
54+
},
55+
56+
indexes: [
57+
{ fields: ['organization_id'] },
58+
{ fields: ['name', 'organization_id'], unique: true },
59+
],
60+
61+
enable: {
62+
trackHistory: true,
63+
searchable: true,
64+
apiEnabled: true,
65+
apiMethods: ['get', 'list', 'create', 'update', 'delete'],
66+
trash: true,
67+
mru: false,
68+
},
69+
});

packages/spec/src/system/constants/system-names.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ describe('SystemObjectName', () => {
1818
expect(SystemObjectName.ORGANIZATION).toBe('sys_organization');
1919
expect(SystemObjectName.MEMBER).toBe('sys_member');
2020
expect(SystemObjectName.INVITATION).toBe('sys_invitation');
21+
expect(SystemObjectName.TEAM).toBe('sys_team');
22+
expect(SystemObjectName.TEAM_MEMBER).toBe('sys_team_member');
2123
expect(SystemObjectName.API_KEY).toBe('sys_api_key');
2224
expect(SystemObjectName.TWO_FACTOR).toBe('sys_two_factor');
2325
expect(SystemObjectName.ROLE).toBe('sys_role');
@@ -31,6 +33,8 @@ describe('SystemObjectName', () => {
3133
expect(names).toContain('sys_user');
3234
expect(names).toContain('sys_session');
3335
expect(names).toContain('sys_organization');
36+
expect(names).toContain('sys_team');
37+
expect(names).toContain('sys_team_member');
3438
expect(names).toContain('sys_role');
3539
expect(names).toContain('sys_audit_log');
3640
});
@@ -44,6 +48,8 @@ describe('SystemObjectName', () => {
4448
expect(keys).toContain('ORGANIZATION');
4549
expect(keys).toContain('MEMBER');
4650
expect(keys).toContain('INVITATION');
51+
expect(keys).toContain('TEAM');
52+
expect(keys).toContain('TEAM_MEMBER');
4753
expect(keys).toContain('API_KEY');
4854
expect(keys).toContain('TWO_FACTOR');
4955
expect(keys).toContain('ROLE');

packages/spec/src/system/constants/system-names.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ export const SystemObjectName = {
3434
MEMBER: 'sys_member',
3535
/** Authentication: organization invitation */
3636
INVITATION: 'sys_invitation',
37+
/** Authentication: team within an organization */
38+
TEAM: 'sys_team',
39+
/** Authentication: team membership */
40+
TEAM_MEMBER: 'sys_team_member',
3741
/** Authentication: API key for programmatic access */
3842
API_KEY: 'sys_api_key',
3943
/** Authentication: two-factor authentication credentials */

0 commit comments

Comments
 (0)