@objectstack/platform-objects 0.1.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/apps/index.d.mts +16 -48
- package/dist/apps/index.d.ts +16 -48
- package/dist/apps/index.js +139 -215
- package/dist/apps/index.js.map +1 -1
- package/dist/apps/index.mjs +140 -210
- package/dist/apps/index.mjs.map +1 -1
- package/dist/audit/index.d.mts +40249 -150
- package/dist/audit/index.d.ts +40249 -150
- package/dist/audit/index.js +1428 -0
- package/dist/audit/index.js.map +1 -1
- package/dist/audit/index.mjs +1417 -1
- package/dist/audit/index.mjs.map +1 -1
- package/dist/identity/index.d.mts +18792 -2520
- package/dist/identity/index.d.ts +18792 -2520
- package/dist/identity/index.js +1107 -6
- package/dist/identity/index.js.map +1 -1
- package/dist/identity/index.mjs +1106 -7
- package/dist/identity/index.mjs.map +1 -1
- package/dist/index.d.mts +9 -7
- package/dist/index.d.ts +9 -7
- package/dist/index.js +3939 -1504
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3917 -1487
- package/dist/index.mjs.map +1 -1
- package/dist/integration/index.d.mts +2905 -0
- package/dist/integration/index.d.ts +2905 -0
- package/dist/integration/index.js +140 -0
- package/dist/integration/index.js.map +1 -0
- package/dist/integration/index.mjs +138 -0
- package/dist/integration/index.mjs.map +1 -0
- package/dist/metadata/index.d.mts +1426 -19092
- package/dist/metadata/index.d.ts +1426 -19092
- package/dist/metadata/index.js +29 -619
- package/dist/metadata/index.js.map +1 -1
- package/dist/metadata/index.mjs +30 -615
- package/dist/metadata/index.mjs.map +1 -1
- package/dist/security/index.d.mts +10759 -60
- package/dist/security/index.d.ts +10759 -60
- package/dist/security/index.js +786 -0
- package/dist/security/index.js.map +1 -1
- package/dist/security/index.mjs +782 -1
- package/dist/security/index.mjs.map +1 -1
- package/dist/system/index.d.mts +8409 -0
- package/dist/system/index.d.ts +8409 -0
- package/dist/system/index.js +395 -0
- package/dist/system/index.js.map +1 -0
- package/dist/system/index.mjs +391 -0
- package/dist/system/index.mjs.map +1 -0
- package/package.json +13 -8
- package/dist/tenant/index.d.mts +0 -16454
- package/dist/tenant/index.d.ts +0 -16454
- package/dist/tenant/index.js +0 -741
- package/dist/tenant/index.js.map +0 -1
- package/dist/tenant/index.mjs +0 -733
- package/dist/tenant/index.mjs.map +0 -1
- /package/dist/{state-machine.zod-BFg-VE0M.d-Ek3_yo9P.d.mts → state-machine.zod-BNanU03M.d-Ek3_yo9P.d.mts} +0 -0
- /package/dist/{state-machine.zod-BFg-VE0M.d-Ek3_yo9P.d.ts → state-machine.zod-BNanU03M.d-Ek3_yo9P.d.ts} +0 -0
package/dist/identity/index.mjs
CHANGED
|
@@ -7,10 +7,154 @@ var SysUser = ObjectSchema.create({
|
|
|
7
7
|
pluralLabel: "Users",
|
|
8
8
|
icon: "user",
|
|
9
9
|
isSystem: true,
|
|
10
|
+
managedBy: "better-auth",
|
|
10
11
|
description: "User accounts for authentication",
|
|
11
12
|
displayNameField: "name",
|
|
12
13
|
titleFormat: "{name}",
|
|
13
14
|
compactLayout: ["name", "email", "email_verified"],
|
|
15
|
+
// Custom actions — generic CRUD is suppressed because user accounts are
|
|
16
|
+
// managed by better-auth, but we still need first-class affordances for
|
|
17
|
+
// common operations. Each action delegates to a Console-side named script
|
|
18
|
+
// registered on the ActionRunner (see objectui `AppContent.tsx`). Adding
|
|
19
|
+
// new affordances (reset password, revoke session, …) is now a pure
|
|
20
|
+
// schema + script-registration change — no per-view code.
|
|
21
|
+
actions: [
|
|
22
|
+
{
|
|
23
|
+
name: "invite_user",
|
|
24
|
+
label: "Invite User",
|
|
25
|
+
icon: "user-plus",
|
|
26
|
+
variant: "primary",
|
|
27
|
+
locations: ["list_toolbar"],
|
|
28
|
+
type: "api",
|
|
29
|
+
target: "/api/v1/auth/organization/invite-member",
|
|
30
|
+
successMessage: "Invitation sent",
|
|
31
|
+
refreshAfter: true,
|
|
32
|
+
params: [
|
|
33
|
+
{ field: "email", required: true },
|
|
34
|
+
{ field: "role", objectOverride: "sys_member", required: true }
|
|
35
|
+
]
|
|
36
|
+
},
|
|
37
|
+
// ── Platform admin operations (require better-auth `admin` plugin) ─
|
|
38
|
+
//
|
|
39
|
+
// These actions hit /api/v1/auth/admin/* endpoints that are only
|
|
40
|
+
// wired when `auth.plugins.admin` is enabled. When the plugin is
|
|
41
|
+
// disabled the actions still render (schema is static) but server
|
|
42
|
+
// returns 404. UI surfaces them under the row menu so platform
|
|
43
|
+
// admins can manage accounts without dropping to SQL or
|
|
44
|
+
// a custom Setup wizard.
|
|
45
|
+
{
|
|
46
|
+
name: "ban_user",
|
|
47
|
+
label: "Ban User",
|
|
48
|
+
icon: "ban",
|
|
49
|
+
variant: "danger",
|
|
50
|
+
locations: ["list_item"],
|
|
51
|
+
type: "api",
|
|
52
|
+
target: "/api/v1/auth/admin/ban-user",
|
|
53
|
+
recordIdParam: "userId",
|
|
54
|
+
successMessage: "User banned",
|
|
55
|
+
refreshAfter: true,
|
|
56
|
+
confirmText: "Ban this user? They will be signed out and unable to sign in until unbanned.",
|
|
57
|
+
params: [
|
|
58
|
+
{ name: "banReason", label: "Ban Reason", type: "text", required: false }
|
|
59
|
+
]
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: "unban_user",
|
|
63
|
+
label: "Unban User",
|
|
64
|
+
icon: "check-circle-2",
|
|
65
|
+
variant: "secondary",
|
|
66
|
+
locations: ["list_item"],
|
|
67
|
+
type: "api",
|
|
68
|
+
target: "/api/v1/auth/admin/unban-user",
|
|
69
|
+
recordIdParam: "userId",
|
|
70
|
+
successMessage: "User unbanned",
|
|
71
|
+
refreshAfter: true
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
name: "set_user_password",
|
|
75
|
+
label: "Set Password",
|
|
76
|
+
icon: "key-round",
|
|
77
|
+
variant: "secondary",
|
|
78
|
+
locations: ["list_item"],
|
|
79
|
+
type: "api",
|
|
80
|
+
target: "/api/v1/auth/admin/set-user-password",
|
|
81
|
+
recordIdParam: "userId",
|
|
82
|
+
successMessage: "Password updated",
|
|
83
|
+
refreshAfter: false,
|
|
84
|
+
params: [
|
|
85
|
+
{ name: "newPassword", label: "New Password", type: "text", required: true }
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: "set_user_role",
|
|
90
|
+
label: "Set Platform Role",
|
|
91
|
+
icon: "shield-check",
|
|
92
|
+
variant: "secondary",
|
|
93
|
+
locations: ["list_item"],
|
|
94
|
+
type: "api",
|
|
95
|
+
target: "/api/v1/auth/admin/set-role",
|
|
96
|
+
recordIdParam: "userId",
|
|
97
|
+
successMessage: "Role updated",
|
|
98
|
+
refreshAfter: true,
|
|
99
|
+
params: [
|
|
100
|
+
{ name: "role", label: "Platform Role", type: "text", required: true }
|
|
101
|
+
]
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
name: "impersonate_user",
|
|
105
|
+
label: "Impersonate User",
|
|
106
|
+
icon: "user-cog",
|
|
107
|
+
variant: "secondary",
|
|
108
|
+
locations: ["list_item"],
|
|
109
|
+
type: "api",
|
|
110
|
+
target: "/api/v1/auth/admin/impersonate-user",
|
|
111
|
+
recordIdParam: "userId",
|
|
112
|
+
successMessage: "Now impersonating user",
|
|
113
|
+
refreshAfter: true,
|
|
114
|
+
confirmText: "Start an impersonation session for this user? Use only for legitimate support cases \u2014 actions will be logged."
|
|
115
|
+
}
|
|
116
|
+
],
|
|
117
|
+
listViews: {
|
|
118
|
+
all_users: {
|
|
119
|
+
type: "grid",
|
|
120
|
+
name: "all_users",
|
|
121
|
+
label: "All Users",
|
|
122
|
+
data: { provider: "object", object: "sys_user" },
|
|
123
|
+
columns: ["name", "email", "email_verified", "two_factor_enabled", "created_at"],
|
|
124
|
+
sort: [{ field: "name", order: "asc" }],
|
|
125
|
+
pagination: { pageSize: 50 }
|
|
126
|
+
},
|
|
127
|
+
unverified: {
|
|
128
|
+
type: "grid",
|
|
129
|
+
name: "unverified",
|
|
130
|
+
label: "Unverified",
|
|
131
|
+
data: { provider: "object", object: "sys_user" },
|
|
132
|
+
columns: ["name", "email", "created_at"],
|
|
133
|
+
filter: [{ field: "email_verified", operator: "equals", value: false }],
|
|
134
|
+
sort: [{ field: "created_at", order: "desc" }],
|
|
135
|
+
pagination: { pageSize: 50 }
|
|
136
|
+
},
|
|
137
|
+
two_factor: {
|
|
138
|
+
type: "grid",
|
|
139
|
+
name: "two_factor",
|
|
140
|
+
label: "2FA Enabled",
|
|
141
|
+
data: { provider: "object", object: "sys_user" },
|
|
142
|
+
columns: ["name", "email", "two_factor_enabled", "updated_at"],
|
|
143
|
+
filter: [{ field: "two_factor_enabled", operator: "equals", value: true }],
|
|
144
|
+
sort: [{ field: "name", order: "asc" }],
|
|
145
|
+
pagination: { pageSize: 50 }
|
|
146
|
+
},
|
|
147
|
+
banned: {
|
|
148
|
+
type: "grid",
|
|
149
|
+
name: "banned",
|
|
150
|
+
label: "Banned",
|
|
151
|
+
data: { provider: "object", object: "sys_user" },
|
|
152
|
+
columns: ["name", "email", "banned", "ban_reason", "ban_expires"],
|
|
153
|
+
filter: [{ field: "banned", operator: "equals", value: true }],
|
|
154
|
+
sort: [{ field: "updated_at", order: "desc" }],
|
|
155
|
+
pagination: { pageSize: 50 }
|
|
156
|
+
}
|
|
157
|
+
},
|
|
14
158
|
fields: {
|
|
15
159
|
// ── Identity (primary business fields) ───────────────────────
|
|
16
160
|
name: Field.text({
|
|
@@ -37,6 +181,32 @@ var SysUser = ObjectSchema.create({
|
|
|
37
181
|
group: "Identity",
|
|
38
182
|
description: "Whether two-factor authentication is enabled for this user. Maintained by the better-auth `twoFactor` plugin."
|
|
39
183
|
}),
|
|
184
|
+
// ── Admin (managed by better-auth `admin` plugin when enabled) ───
|
|
185
|
+
role: Field.text({
|
|
186
|
+
label: "Platform Role",
|
|
187
|
+
required: false,
|
|
188
|
+
maxLength: 64,
|
|
189
|
+
group: "Admin",
|
|
190
|
+
description: "Platform-level role (admin, user, \u2026). Set via the Set Platform Role action."
|
|
191
|
+
}),
|
|
192
|
+
banned: Field.boolean({
|
|
193
|
+
label: "Banned",
|
|
194
|
+
defaultValue: false,
|
|
195
|
+
group: "Admin",
|
|
196
|
+
description: "When true, the user cannot sign in. Toggle via Ban User / Unban User actions."
|
|
197
|
+
}),
|
|
198
|
+
ban_reason: Field.text({
|
|
199
|
+
label: "Ban Reason",
|
|
200
|
+
required: false,
|
|
201
|
+
maxLength: 255,
|
|
202
|
+
group: "Admin"
|
|
203
|
+
}),
|
|
204
|
+
ban_expires: Field.datetime({
|
|
205
|
+
label: "Ban Expires",
|
|
206
|
+
required: false,
|
|
207
|
+
group: "Admin",
|
|
208
|
+
description: "When set, the ban auto-clears at this time."
|
|
209
|
+
}),
|
|
40
210
|
// ── Profile ──────────────────────────────────────────────────
|
|
41
211
|
image: Field.url({
|
|
42
212
|
label: "Profile Image",
|
|
@@ -92,10 +262,67 @@ var SysSession = ObjectSchema.create({
|
|
|
92
262
|
pluralLabel: "Sessions",
|
|
93
263
|
icon: "key",
|
|
94
264
|
isSystem: true,
|
|
265
|
+
managedBy: "better-auth",
|
|
95
266
|
description: "Active user sessions",
|
|
96
267
|
displayNameField: "user_id",
|
|
97
268
|
titleFormat: "Session \u2014 {user_id}",
|
|
98
269
|
compactLayout: ["user_id", "ip_address", "expires_at"],
|
|
270
|
+
// Custom actions — sessions are managed by better-auth (generic CRUD
|
|
271
|
+
// suppressed). "Sign out other devices" is the high-value self-service
|
|
272
|
+
// affordance every IdP exposes. Maps to better-auth's
|
|
273
|
+
// `revoke-other-sessions` endpoint which terminates every session for
|
|
274
|
+
// the current user except the one making the request.
|
|
275
|
+
actions: [
|
|
276
|
+
{
|
|
277
|
+
name: "revoke_my_other_sessions",
|
|
278
|
+
label: "Sign out other devices",
|
|
279
|
+
icon: "log-out",
|
|
280
|
+
variant: "danger",
|
|
281
|
+
locations: ["list_toolbar"],
|
|
282
|
+
type: "api",
|
|
283
|
+
target: "/api/v1/auth/revoke-other-sessions",
|
|
284
|
+
confirmText: "Sign out of every other device where you're currently logged in? Your current session will remain active.",
|
|
285
|
+
successMessage: "All other sessions revoked",
|
|
286
|
+
refreshAfter: true
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
name: "revoke_session",
|
|
290
|
+
label: "Revoke Session",
|
|
291
|
+
icon: "log-out",
|
|
292
|
+
variant: "danger",
|
|
293
|
+
mode: "delete",
|
|
294
|
+
locations: ["list_item"],
|
|
295
|
+
type: "api",
|
|
296
|
+
target: "/api/v1/auth/revoke-session",
|
|
297
|
+
// better-auth `revoke-session` keys off the session token, not the id.
|
|
298
|
+
recordIdParam: "token",
|
|
299
|
+
recordIdField: "token",
|
|
300
|
+
confirmText: "Revoke this session? The user will be signed out from that device.",
|
|
301
|
+
successMessage: "Session revoked",
|
|
302
|
+
refreshAfter: true
|
|
303
|
+
}
|
|
304
|
+
],
|
|
305
|
+
listViews: {
|
|
306
|
+
mine: {
|
|
307
|
+
type: "grid",
|
|
308
|
+
name: "mine",
|
|
309
|
+
label: "My Sessions",
|
|
310
|
+
data: { provider: "object", object: "sys_session" },
|
|
311
|
+
columns: ["ip_address", "active_organization_id", "created_at", "expires_at"],
|
|
312
|
+
filter: [{ field: "user_id", operator: "equals", value: "{current_user_id}" }],
|
|
313
|
+
sort: [{ field: "created_at", order: "desc" }],
|
|
314
|
+
pagination: { pageSize: 50 }
|
|
315
|
+
},
|
|
316
|
+
all_sessions: {
|
|
317
|
+
type: "grid",
|
|
318
|
+
name: "all_sessions",
|
|
319
|
+
label: "All",
|
|
320
|
+
data: { provider: "object", object: "sys_session" },
|
|
321
|
+
columns: ["user_id", "ip_address", "active_organization_id", "created_at", "expires_at"],
|
|
322
|
+
sort: [{ field: "created_at", order: "desc" }],
|
|
323
|
+
pagination: { pageSize: 50 }
|
|
324
|
+
}
|
|
325
|
+
},
|
|
99
326
|
fields: {
|
|
100
327
|
// ── Session owner & expiry ──────────────────────────────────
|
|
101
328
|
user_id: Field.lookup("sys_user", {
|
|
@@ -133,6 +360,13 @@ var SysSession = ObjectSchema.create({
|
|
|
133
360
|
required: false,
|
|
134
361
|
group: "Client"
|
|
135
362
|
}),
|
|
363
|
+
// ── Admin (managed by better-auth `admin` plugin) ────────────
|
|
364
|
+
impersonated_by: Field.lookup("sys_user", {
|
|
365
|
+
label: "Impersonated By",
|
|
366
|
+
required: false,
|
|
367
|
+
group: "Admin",
|
|
368
|
+
description: "User id of the admin that started this impersonation session, if any."
|
|
369
|
+
}),
|
|
136
370
|
// ── Secret (hidden by default) ──────────────────────────────
|
|
137
371
|
token: Field.text({
|
|
138
372
|
label: "Session Token",
|
|
@@ -183,9 +417,41 @@ var SysAccount = ObjectSchema.create({
|
|
|
183
417
|
pluralLabel: "Accounts",
|
|
184
418
|
icon: "link",
|
|
185
419
|
isSystem: true,
|
|
420
|
+
managedBy: "better-auth",
|
|
186
421
|
description: "OAuth and authentication provider accounts",
|
|
187
422
|
titleFormat: "{provider_id} - {account_id}",
|
|
188
423
|
compactLayout: ["provider_id", "user_id", "account_id"],
|
|
424
|
+
listViews: {
|
|
425
|
+
mine: {
|
|
426
|
+
type: "grid",
|
|
427
|
+
name: "mine",
|
|
428
|
+
label: "My Links",
|
|
429
|
+
data: { provider: "object", object: "sys_account" },
|
|
430
|
+
columns: ["provider_id", "account_id", "created_at", "updated_at"],
|
|
431
|
+
filter: [{ field: "user_id", operator: "equals", value: "{current_user_id}" }],
|
|
432
|
+
sort: [{ field: "provider_id", order: "asc" }],
|
|
433
|
+
pagination: { pageSize: 50 }
|
|
434
|
+
},
|
|
435
|
+
by_provider: {
|
|
436
|
+
type: "grid",
|
|
437
|
+
name: "by_provider",
|
|
438
|
+
label: "By Provider",
|
|
439
|
+
data: { provider: "object", object: "sys_account" },
|
|
440
|
+
columns: ["provider_id", "user_id", "account_id", "created_at"],
|
|
441
|
+
sort: [{ field: "provider_id", order: "asc" }, { field: "created_at", order: "desc" }],
|
|
442
|
+
grouping: { fields: [{ field: "provider_id", order: "asc", collapsed: false }] },
|
|
443
|
+
pagination: { pageSize: 100 }
|
|
444
|
+
},
|
|
445
|
+
all_links: {
|
|
446
|
+
type: "grid",
|
|
447
|
+
name: "all_links",
|
|
448
|
+
label: "All",
|
|
449
|
+
data: { provider: "object", object: "sys_account" },
|
|
450
|
+
columns: ["provider_id", "user_id", "account_id", "created_at", "updated_at"],
|
|
451
|
+
sort: [{ field: "created_at", order: "desc" }],
|
|
452
|
+
pagination: { pageSize: 100 }
|
|
453
|
+
}
|
|
454
|
+
},
|
|
189
455
|
fields: {
|
|
190
456
|
id: Field.text({
|
|
191
457
|
label: "Account ID",
|
|
@@ -266,6 +532,7 @@ var SysVerification = ObjectSchema.create({
|
|
|
266
532
|
pluralLabel: "Verifications",
|
|
267
533
|
icon: "shield-check",
|
|
268
534
|
isSystem: true,
|
|
535
|
+
managedBy: "better-auth",
|
|
269
536
|
description: "Email and phone verification tokens",
|
|
270
537
|
titleFormat: "Verification for {identifier}",
|
|
271
538
|
compactLayout: ["identifier", "expires_at", "created_at"],
|
|
@@ -320,10 +587,109 @@ var SysOrganization = ObjectSchema.create({
|
|
|
320
587
|
pluralLabel: "Organizations",
|
|
321
588
|
icon: "building-2",
|
|
322
589
|
isSystem: true,
|
|
590
|
+
managedBy: "better-auth",
|
|
323
591
|
description: "Organizations for multi-tenant grouping",
|
|
324
592
|
displayNameField: "name",
|
|
325
593
|
titleFormat: "{name}",
|
|
326
594
|
compactLayout: ["name", "slug"],
|
|
595
|
+
// Custom actions — generic CRUD is suppressed (better-auth-managed),
|
|
596
|
+
// but admins still need to create new orgs from the Setup app.
|
|
597
|
+
actions: [
|
|
598
|
+
{
|
|
599
|
+
name: "create_organization",
|
|
600
|
+
label: "Create Organization",
|
|
601
|
+
icon: "plus",
|
|
602
|
+
variant: "primary",
|
|
603
|
+
locations: ["list_toolbar"],
|
|
604
|
+
type: "api",
|
|
605
|
+
target: "/api/v1/auth/organization/create",
|
|
606
|
+
successMessage: "Organization created",
|
|
607
|
+
refreshAfter: true,
|
|
608
|
+
params: [
|
|
609
|
+
{ field: "name", required: true },
|
|
610
|
+
{ field: "slug", required: true },
|
|
611
|
+
{ field: "logo" }
|
|
612
|
+
]
|
|
613
|
+
},
|
|
614
|
+
{
|
|
615
|
+
name: "update_organization",
|
|
616
|
+
label: "Edit Organization",
|
|
617
|
+
icon: "pencil",
|
|
618
|
+
mode: "edit",
|
|
619
|
+
locations: ["list_item"],
|
|
620
|
+
type: "api",
|
|
621
|
+
target: "/api/v1/auth/organization/update",
|
|
622
|
+
recordIdParam: "organizationId",
|
|
623
|
+
// better-auth `organization/update` nests editable fields under `data`.
|
|
624
|
+
bodyShape: { wrap: "data" },
|
|
625
|
+
successMessage: "Organization updated",
|
|
626
|
+
refreshAfter: true,
|
|
627
|
+
params: [
|
|
628
|
+
{ field: "name", required: true, defaultFromRow: true },
|
|
629
|
+
{ field: "slug", required: true, defaultFromRow: true },
|
|
630
|
+
{ field: "logo", defaultFromRow: true }
|
|
631
|
+
]
|
|
632
|
+
},
|
|
633
|
+
{
|
|
634
|
+
name: "delete_organization",
|
|
635
|
+
label: "Delete Organization",
|
|
636
|
+
icon: "trash-2",
|
|
637
|
+
variant: "danger",
|
|
638
|
+
mode: "delete",
|
|
639
|
+
locations: ["list_item"],
|
|
640
|
+
type: "api",
|
|
641
|
+
target: "/api/v1/auth/organization/delete",
|
|
642
|
+
recordIdParam: "organizationId",
|
|
643
|
+
confirmText: "Delete this organization? All members will lose access immediately. This cannot be undone.",
|
|
644
|
+
successMessage: "Organization deleted",
|
|
645
|
+
refreshAfter: true
|
|
646
|
+
},
|
|
647
|
+
{
|
|
648
|
+
// Switch the caller's active organization context. Standard
|
|
649
|
+
// better-auth endpoint; no extra params needed (org id ships as
|
|
650
|
+
// the row id). Used from the Setup list and the record header so
|
|
651
|
+
// admins can context-switch without leaving the page.
|
|
652
|
+
name: "set_active_organization",
|
|
653
|
+
label: "Set Active",
|
|
654
|
+
icon: "check-circle-2",
|
|
655
|
+
variant: "secondary",
|
|
656
|
+
mode: "custom",
|
|
657
|
+
locations: ["list_item", "record_header"],
|
|
658
|
+
type: "api",
|
|
659
|
+
target: "/api/v1/auth/organization/set-active",
|
|
660
|
+
recordIdParam: "organizationId",
|
|
661
|
+
successMessage: "Active organization switched",
|
|
662
|
+
refreshAfter: true
|
|
663
|
+
},
|
|
664
|
+
{
|
|
665
|
+
// Current user leaves the org. Distinct from `delete_organization`
|
|
666
|
+
// (admin-only, destroys the org) — `leave` only removes the caller's
|
|
667
|
+
// own membership. Better-auth: `organization/leave { organizationId }`.
|
|
668
|
+
name: "leave_organization",
|
|
669
|
+
label: "Leave Organization",
|
|
670
|
+
icon: "log-out",
|
|
671
|
+
variant: "danger",
|
|
672
|
+
mode: "custom",
|
|
673
|
+
locations: ["list_item", "record_header"],
|
|
674
|
+
type: "api",
|
|
675
|
+
target: "/api/v1/auth/organization/leave",
|
|
676
|
+
recordIdParam: "organizationId",
|
|
677
|
+
confirmText: "Leave this organization? You will lose access to all of its resources.",
|
|
678
|
+
successMessage: "You have left the organization",
|
|
679
|
+
refreshAfter: true
|
|
680
|
+
}
|
|
681
|
+
],
|
|
682
|
+
listViews: {
|
|
683
|
+
all_orgs: {
|
|
684
|
+
type: "grid",
|
|
685
|
+
name: "all_orgs",
|
|
686
|
+
label: "All",
|
|
687
|
+
data: { provider: "object", object: "sys_organization" },
|
|
688
|
+
columns: ["name", "slug", "created_at", "updated_at"],
|
|
689
|
+
sort: [{ field: "name", order: "asc" }],
|
|
690
|
+
pagination: { pageSize: 50 }
|
|
691
|
+
}
|
|
692
|
+
},
|
|
327
693
|
fields: {
|
|
328
694
|
// ── Identity ─────────────────────────────────────────────────
|
|
329
695
|
name: Field.text({
|
|
@@ -393,9 +759,67 @@ var SysMember = ObjectSchema.create({
|
|
|
393
759
|
pluralLabel: "Members",
|
|
394
760
|
icon: "user-check",
|
|
395
761
|
isSystem: true,
|
|
762
|
+
managedBy: "better-auth",
|
|
396
763
|
description: "Organization membership records",
|
|
397
764
|
titleFormat: "{user_id} in {organization_id}",
|
|
398
765
|
compactLayout: ["user_id", "organization_id", "role"],
|
|
766
|
+
// Row-level actions: better-auth `organization/update-member-role` and
|
|
767
|
+
// `organization/remove-member`. Generic CRUD is suppressed on better-auth
|
|
768
|
+
// managed tables, so these are the canonical edit/delete entry points.
|
|
769
|
+
// The `add_member` toolbar action covers the admin "attach an existing
|
|
770
|
+
// user directly without sending an invitation" flow.
|
|
771
|
+
actions: [
|
|
772
|
+
{
|
|
773
|
+
// Admin-only: directly attach an existing user to the active org,
|
|
774
|
+
// bypassing the invite-accept flow. Better-auth:
|
|
775
|
+
// `organization/add-member { userId, role, organizationId?, teamId? }`.
|
|
776
|
+
// organizationId/teamId default to the caller's active org/team when
|
|
777
|
+
// omitted, so we leave them as optional params.
|
|
778
|
+
name: "add_member",
|
|
779
|
+
label: "Add Member",
|
|
780
|
+
icon: "user-plus",
|
|
781
|
+
variant: "primary",
|
|
782
|
+
locations: ["list_toolbar"],
|
|
783
|
+
type: "api",
|
|
784
|
+
target: "/api/v1/auth/organization/add-member",
|
|
785
|
+
successMessage: "Member added",
|
|
786
|
+
refreshAfter: true,
|
|
787
|
+
params: [
|
|
788
|
+
{ name: "userId", field: "user_id", required: true },
|
|
789
|
+
{ field: "role", required: true },
|
|
790
|
+
{ name: "organizationId", field: "organization_id" }
|
|
791
|
+
]
|
|
792
|
+
},
|
|
793
|
+
{
|
|
794
|
+
name: "update_member_role",
|
|
795
|
+
label: "Change Role",
|
|
796
|
+
icon: "shield",
|
|
797
|
+
mode: "edit",
|
|
798
|
+
locations: ["list_item"],
|
|
799
|
+
type: "api",
|
|
800
|
+
target: "/api/v1/auth/organization/update-member-role",
|
|
801
|
+
recordIdParam: "memberId",
|
|
802
|
+
successMessage: "Member role updated",
|
|
803
|
+
refreshAfter: true,
|
|
804
|
+
params: [
|
|
805
|
+
{ field: "role", required: true, defaultFromRow: true }
|
|
806
|
+
]
|
|
807
|
+
},
|
|
808
|
+
{
|
|
809
|
+
name: "remove_member",
|
|
810
|
+
label: "Remove Member",
|
|
811
|
+
icon: "user-minus",
|
|
812
|
+
variant: "danger",
|
|
813
|
+
mode: "delete",
|
|
814
|
+
locations: ["list_item"],
|
|
815
|
+
type: "api",
|
|
816
|
+
target: "/api/v1/auth/organization/remove-member",
|
|
817
|
+
recordIdParam: "memberIdOrEmail",
|
|
818
|
+
confirmText: "Remove this member from the organization? They will lose access to all org resources.",
|
|
819
|
+
successMessage: "Member removed",
|
|
820
|
+
refreshAfter: true
|
|
821
|
+
}
|
|
822
|
+
],
|
|
399
823
|
fields: {
|
|
400
824
|
id: Field.text({
|
|
401
825
|
label: "Member ID",
|
|
@@ -415,11 +839,16 @@ var SysMember = ObjectSchema.create({
|
|
|
415
839
|
label: "User",
|
|
416
840
|
required: true
|
|
417
841
|
}),
|
|
418
|
-
role: Field.
|
|
842
|
+
role: Field.select({
|
|
419
843
|
label: "Role",
|
|
420
844
|
required: false,
|
|
421
|
-
description: "Member role within the organization
|
|
422
|
-
|
|
845
|
+
description: "Member role within the organization",
|
|
846
|
+
options: [
|
|
847
|
+
{ label: "Owner", value: "owner" },
|
|
848
|
+
{ label: "Admin", value: "admin" },
|
|
849
|
+
{ label: "Member", value: "member" }
|
|
850
|
+
],
|
|
851
|
+
defaultValue: "member"
|
|
423
852
|
})
|
|
424
853
|
},
|
|
425
854
|
indexes: [
|
|
@@ -441,9 +870,101 @@ var SysInvitation = ObjectSchema.create({
|
|
|
441
870
|
pluralLabel: "Invitations",
|
|
442
871
|
icon: "mail",
|
|
443
872
|
isSystem: true,
|
|
873
|
+
managedBy: "better-auth",
|
|
444
874
|
description: "Organization invitations for user onboarding",
|
|
445
875
|
titleFormat: "Invitation to {organization_id}",
|
|
446
876
|
compactLayout: ["email", "organization_id", "status"],
|
|
877
|
+
// Custom actions — generic CRUD is suppressed (better-auth-managed).
|
|
878
|
+
// Mirror the `invite_user` toolbar action from sys_user here so admins
|
|
879
|
+
// landing on the Invitations page get an obvious entry point.
|
|
880
|
+
actions: [
|
|
881
|
+
{
|
|
882
|
+
name: "invite_user",
|
|
883
|
+
label: "Invite User",
|
|
884
|
+
icon: "user-plus",
|
|
885
|
+
variant: "primary",
|
|
886
|
+
locations: ["list_toolbar"],
|
|
887
|
+
type: "api",
|
|
888
|
+
target: "/api/v1/auth/organization/invite-member",
|
|
889
|
+
successMessage: "Invitation sent",
|
|
890
|
+
refreshAfter: true,
|
|
891
|
+
params: [
|
|
892
|
+
{ field: "email", required: true },
|
|
893
|
+
{ field: "role", required: true }
|
|
894
|
+
]
|
|
895
|
+
},
|
|
896
|
+
{
|
|
897
|
+
name: "cancel_invitation",
|
|
898
|
+
label: "Cancel Invitation",
|
|
899
|
+
icon: "x-circle",
|
|
900
|
+
variant: "danger",
|
|
901
|
+
mode: "delete",
|
|
902
|
+
locations: ["list_item"],
|
|
903
|
+
type: "api",
|
|
904
|
+
target: "/api/v1/auth/organization/cancel-invitation",
|
|
905
|
+
recordIdParam: "invitationId",
|
|
906
|
+
confirmText: "Cancel this invitation? The recipient will no longer be able to accept it.",
|
|
907
|
+
successMessage: "Invitation canceled",
|
|
908
|
+
refreshAfter: true
|
|
909
|
+
},
|
|
910
|
+
{
|
|
911
|
+
name: "resend_invitation",
|
|
912
|
+
label: "Resend Invitation",
|
|
913
|
+
icon: "send",
|
|
914
|
+
variant: "secondary",
|
|
915
|
+
locations: ["list_item"],
|
|
916
|
+
type: "api",
|
|
917
|
+
target: "/api/v1/auth/organization/invite-member",
|
|
918
|
+
bodyExtra: { resend: true },
|
|
919
|
+
successMessage: "Invitation resent",
|
|
920
|
+
refreshAfter: true,
|
|
921
|
+
params: [
|
|
922
|
+
{ field: "email", required: true, defaultFromRow: true },
|
|
923
|
+
{ field: "role", required: true, defaultFromRow: true }
|
|
924
|
+
]
|
|
925
|
+
}
|
|
926
|
+
],
|
|
927
|
+
listViews: {
|
|
928
|
+
pending: {
|
|
929
|
+
type: "grid",
|
|
930
|
+
name: "pending",
|
|
931
|
+
label: "Pending",
|
|
932
|
+
data: { provider: "object", object: "sys_invitation" },
|
|
933
|
+
columns: ["email", "role", "organization_id", "inviter_id", "expires_at"],
|
|
934
|
+
filter: [{ field: "status", operator: "equals", value: "pending" }],
|
|
935
|
+
sort: [{ field: "expires_at", order: "asc" }],
|
|
936
|
+
pagination: { pageSize: 50 }
|
|
937
|
+
},
|
|
938
|
+
accepted: {
|
|
939
|
+
type: "grid",
|
|
940
|
+
name: "accepted",
|
|
941
|
+
label: "Accepted",
|
|
942
|
+
data: { provider: "object", object: "sys_invitation" },
|
|
943
|
+
columns: ["email", "role", "organization_id", "inviter_id", "created_at"],
|
|
944
|
+
filter: [{ field: "status", operator: "equals", value: "accepted" }],
|
|
945
|
+
sort: [{ field: "created_at", order: "desc" }],
|
|
946
|
+
pagination: { pageSize: 50 }
|
|
947
|
+
},
|
|
948
|
+
expired: {
|
|
949
|
+
type: "grid",
|
|
950
|
+
name: "expired",
|
|
951
|
+
label: "Expired / Canceled",
|
|
952
|
+
data: { provider: "object", object: "sys_invitation" },
|
|
953
|
+
columns: ["email", "status", "organization_id", "expires_at"],
|
|
954
|
+
filter: [{ field: "status", operator: "in", value: ["expired", "rejected", "canceled"] }],
|
|
955
|
+
sort: [{ field: "expires_at", order: "desc" }],
|
|
956
|
+
pagination: { pageSize: 50 }
|
|
957
|
+
},
|
|
958
|
+
all_invitations: {
|
|
959
|
+
type: "grid",
|
|
960
|
+
name: "all_invitations",
|
|
961
|
+
label: "All",
|
|
962
|
+
data: { provider: "object", object: "sys_invitation" },
|
|
963
|
+
columns: ["email", "status", "role", "organization_id", "inviter_id", "created_at"],
|
|
964
|
+
sort: [{ field: "created_at", order: "desc" }],
|
|
965
|
+
pagination: { pageSize: 50 }
|
|
966
|
+
}
|
|
967
|
+
},
|
|
447
968
|
fields: {
|
|
448
969
|
id: Field.text({
|
|
449
970
|
label: "Invitation ID",
|
|
@@ -464,11 +985,16 @@ var SysInvitation = ObjectSchema.create({
|
|
|
464
985
|
required: true,
|
|
465
986
|
description: "Email address of the invited user"
|
|
466
987
|
}),
|
|
467
|
-
role: Field.
|
|
988
|
+
role: Field.select({
|
|
468
989
|
label: "Role",
|
|
469
990
|
required: false,
|
|
470
|
-
|
|
471
|
-
|
|
991
|
+
description: "Role to assign upon acceptance",
|
|
992
|
+
options: [
|
|
993
|
+
{ label: "Owner", value: "owner" },
|
|
994
|
+
{ label: "Admin", value: "admin" },
|
|
995
|
+
{ label: "Member", value: "member" }
|
|
996
|
+
],
|
|
997
|
+
defaultValue: "member"
|
|
472
998
|
}),
|
|
473
999
|
status: Field.select(["pending", "accepted", "rejected", "expired", "canceled"], {
|
|
474
1000
|
label: "Status",
|
|
@@ -510,10 +1036,89 @@ var SysTeam = ObjectSchema.create({
|
|
|
510
1036
|
pluralLabel: "Teams",
|
|
511
1037
|
icon: "users",
|
|
512
1038
|
isSystem: true,
|
|
1039
|
+
managedBy: "better-auth",
|
|
513
1040
|
description: "Teams within organizations for fine-grained grouping",
|
|
514
1041
|
displayNameField: "name",
|
|
515
1042
|
titleFormat: "{name}",
|
|
516
1043
|
compactLayout: ["name", "organization_id"],
|
|
1044
|
+
// Custom actions calling better-auth's team endpoints. Generic CRUD is
|
|
1045
|
+
// suppressed (managedBy: 'better-auth'), so these are the canonical
|
|
1046
|
+
// entry points for create/update/delete.
|
|
1047
|
+
actions: [
|
|
1048
|
+
{
|
|
1049
|
+
// Better-auth: `organization/create-team { name, organizationId? }`.
|
|
1050
|
+
// organizationId defaults to the caller's active org when omitted.
|
|
1051
|
+
name: "create_team",
|
|
1052
|
+
label: "Create Team",
|
|
1053
|
+
icon: "plus",
|
|
1054
|
+
variant: "primary",
|
|
1055
|
+
locations: ["list_toolbar"],
|
|
1056
|
+
type: "api",
|
|
1057
|
+
target: "/api/v1/auth/organization/create-team",
|
|
1058
|
+
successMessage: "Team created",
|
|
1059
|
+
refreshAfter: true,
|
|
1060
|
+
params: [
|
|
1061
|
+
{ field: "name", required: true },
|
|
1062
|
+
{ name: "organizationId", field: "organization_id" }
|
|
1063
|
+
]
|
|
1064
|
+
},
|
|
1065
|
+
{
|
|
1066
|
+
// Better-auth: `organization/update-team { teamId, data: { name } }`.
|
|
1067
|
+
// teamId stays flat (top-level); the user-editable params nest under
|
|
1068
|
+
// `data` via bodyShape.
|
|
1069
|
+
name: "update_team",
|
|
1070
|
+
label: "Edit Team",
|
|
1071
|
+
icon: "pencil",
|
|
1072
|
+
mode: "edit",
|
|
1073
|
+
locations: ["list_item"],
|
|
1074
|
+
type: "api",
|
|
1075
|
+
target: "/api/v1/auth/organization/update-team",
|
|
1076
|
+
recordIdParam: "teamId",
|
|
1077
|
+
bodyShape: { wrap: "data" },
|
|
1078
|
+
successMessage: "Team updated",
|
|
1079
|
+
refreshAfter: true,
|
|
1080
|
+
params: [
|
|
1081
|
+
{ field: "name", required: true, defaultFromRow: true }
|
|
1082
|
+
]
|
|
1083
|
+
},
|
|
1084
|
+
{
|
|
1085
|
+
// Better-auth: `organization/remove-team { teamId, organizationId? }`.
|
|
1086
|
+
// organizationId defaults to the caller's active org when omitted.
|
|
1087
|
+
name: "remove_team",
|
|
1088
|
+
label: "Delete Team",
|
|
1089
|
+
icon: "trash-2",
|
|
1090
|
+
variant: "danger",
|
|
1091
|
+
mode: "delete",
|
|
1092
|
+
locations: ["list_item"],
|
|
1093
|
+
type: "api",
|
|
1094
|
+
target: "/api/v1/auth/organization/remove-team",
|
|
1095
|
+
recordIdParam: "teamId",
|
|
1096
|
+
confirmText: "Delete this team? Members will lose any team-scoped access. This cannot be undone.",
|
|
1097
|
+
successMessage: "Team deleted",
|
|
1098
|
+
refreshAfter: true
|
|
1099
|
+
}
|
|
1100
|
+
],
|
|
1101
|
+
listViews: {
|
|
1102
|
+
by_org: {
|
|
1103
|
+
type: "grid",
|
|
1104
|
+
name: "by_org",
|
|
1105
|
+
label: "By Organization",
|
|
1106
|
+
data: { provider: "object", object: "sys_team" },
|
|
1107
|
+
columns: ["organization_id", "name", "created_at", "updated_at"],
|
|
1108
|
+
sort: [{ field: "organization_id", order: "asc" }, { field: "name", order: "asc" }],
|
|
1109
|
+
grouping: { fields: [{ field: "organization_id", order: "asc", collapsed: false }] },
|
|
1110
|
+
pagination: { pageSize: 100 }
|
|
1111
|
+
},
|
|
1112
|
+
all_teams: {
|
|
1113
|
+
type: "grid",
|
|
1114
|
+
name: "all_teams",
|
|
1115
|
+
label: "All",
|
|
1116
|
+
data: { provider: "object", object: "sys_team" },
|
|
1117
|
+
columns: ["name", "organization_id", "created_at", "updated_at"],
|
|
1118
|
+
sort: [{ field: "name", order: "asc" }],
|
|
1119
|
+
pagination: { pageSize: 50 }
|
|
1120
|
+
}
|
|
1121
|
+
},
|
|
517
1122
|
fields: {
|
|
518
1123
|
// ── Identity ─────────────────────────────────────────────────
|
|
519
1124
|
name: Field.text({
|
|
@@ -568,9 +1173,52 @@ var SysTeamMember = ObjectSchema.create({
|
|
|
568
1173
|
pluralLabel: "Team Members",
|
|
569
1174
|
icon: "user-plus",
|
|
570
1175
|
isSystem: true,
|
|
1176
|
+
managedBy: "better-auth",
|
|
571
1177
|
description: "Team membership records linking users to teams",
|
|
572
1178
|
titleFormat: "{user_id} in {team_id}",
|
|
573
1179
|
compactLayout: ["user_id", "team_id", "created_at"],
|
|
1180
|
+
// Custom actions calling better-auth's team-member endpoints. Generic
|
|
1181
|
+
// CRUD is suppressed (managedBy: 'better-auth') so these are the
|
|
1182
|
+
// canonical add/remove entry points.
|
|
1183
|
+
actions: [
|
|
1184
|
+
{
|
|
1185
|
+
// Better-auth: `organization/add-team-member { teamId, userId }`.
|
|
1186
|
+
name: "add_team_member",
|
|
1187
|
+
label: "Add Member",
|
|
1188
|
+
icon: "user-plus",
|
|
1189
|
+
variant: "primary",
|
|
1190
|
+
locations: ["list_toolbar"],
|
|
1191
|
+
type: "api",
|
|
1192
|
+
target: "/api/v1/auth/organization/add-team-member",
|
|
1193
|
+
successMessage: "Team member added",
|
|
1194
|
+
refreshAfter: true,
|
|
1195
|
+
params: [
|
|
1196
|
+
{ name: "teamId", field: "team_id", required: true },
|
|
1197
|
+
{ name: "userId", field: "user_id", required: true }
|
|
1198
|
+
]
|
|
1199
|
+
},
|
|
1200
|
+
{
|
|
1201
|
+
// Better-auth: `organization/remove-team-member { teamId, userId }`.
|
|
1202
|
+
// The endpoint identifies the membership by the (teamId, userId)
|
|
1203
|
+
// pair rather than the join-row id, so we pull both from the row
|
|
1204
|
+
// via `defaultFromRow` instead of using `recordIdParam`.
|
|
1205
|
+
name: "remove_team_member",
|
|
1206
|
+
label: "Remove from Team",
|
|
1207
|
+
icon: "user-minus",
|
|
1208
|
+
variant: "danger",
|
|
1209
|
+
mode: "delete",
|
|
1210
|
+
locations: ["list_item"],
|
|
1211
|
+
type: "api",
|
|
1212
|
+
target: "/api/v1/auth/organization/remove-team-member",
|
|
1213
|
+
confirmText: "Remove this user from the team? They will lose any team-scoped access.",
|
|
1214
|
+
successMessage: "Team member removed",
|
|
1215
|
+
refreshAfter: true,
|
|
1216
|
+
params: [
|
|
1217
|
+
{ name: "teamId", field: "team_id", required: true, defaultFromRow: true },
|
|
1218
|
+
{ name: "userId", field: "user_id", required: true, defaultFromRow: true }
|
|
1219
|
+
]
|
|
1220
|
+
}
|
|
1221
|
+
],
|
|
574
1222
|
fields: {
|
|
575
1223
|
id: Field.text({
|
|
576
1224
|
label: "Team Member ID",
|
|
@@ -604,16 +1252,338 @@ var SysTeamMember = ObjectSchema.create({
|
|
|
604
1252
|
mru: false
|
|
605
1253
|
}
|
|
606
1254
|
});
|
|
1255
|
+
var SysDepartment = ObjectSchema.create({
|
|
1256
|
+
name: "sys_department",
|
|
1257
|
+
label: "Department",
|
|
1258
|
+
pluralLabel: "Departments",
|
|
1259
|
+
icon: "building",
|
|
1260
|
+
isSystem: true,
|
|
1261
|
+
managedBy: "platform",
|
|
1262
|
+
description: "Hierarchical org-skeleton node (department / division / business unit / office).",
|
|
1263
|
+
displayNameField: "name",
|
|
1264
|
+
titleFormat: "{name}",
|
|
1265
|
+
compactLayout: ["name", "kind", "parent_department_id", "manager_user_id"],
|
|
1266
|
+
listViews: {
|
|
1267
|
+
active: {
|
|
1268
|
+
type: "grid",
|
|
1269
|
+
name: "active",
|
|
1270
|
+
label: "Active",
|
|
1271
|
+
data: { provider: "object", object: "sys_department" },
|
|
1272
|
+
columns: ["name", "code", "kind", "parent_department_id", "manager_user_id", "effective_from"],
|
|
1273
|
+
filter: [{ field: "active", operator: "equals", value: true }],
|
|
1274
|
+
sort: [{ field: "name", order: "asc" }],
|
|
1275
|
+
pagination: { pageSize: 100 }
|
|
1276
|
+
},
|
|
1277
|
+
inactive: {
|
|
1278
|
+
type: "grid",
|
|
1279
|
+
name: "inactive",
|
|
1280
|
+
label: "Inactive",
|
|
1281
|
+
data: { provider: "object", object: "sys_department" },
|
|
1282
|
+
columns: ["name", "code", "kind", "effective_to"],
|
|
1283
|
+
filter: [{ field: "active", operator: "equals", value: false }],
|
|
1284
|
+
sort: [{ field: "effective_to", order: "desc" }],
|
|
1285
|
+
pagination: { pageSize: 50 }
|
|
1286
|
+
},
|
|
1287
|
+
by_kind: {
|
|
1288
|
+
type: "grid",
|
|
1289
|
+
name: "by_kind",
|
|
1290
|
+
label: "By Kind",
|
|
1291
|
+
data: { provider: "object", object: "sys_department" },
|
|
1292
|
+
columns: ["kind", "name", "code", "parent_department_id", "manager_user_id", "active"],
|
|
1293
|
+
sort: [{ field: "kind", order: "asc" }, { field: "name", order: "asc" }],
|
|
1294
|
+
grouping: { fields: [{ field: "kind", order: "asc", collapsed: false }] },
|
|
1295
|
+
pagination: { pageSize: 100 }
|
|
1296
|
+
},
|
|
1297
|
+
all_departments: {
|
|
1298
|
+
type: "grid",
|
|
1299
|
+
name: "all_departments",
|
|
1300
|
+
label: "All",
|
|
1301
|
+
data: { provider: "object", object: "sys_department" },
|
|
1302
|
+
columns: ["name", "code", "kind", "parent_department_id", "manager_user_id", "active"],
|
|
1303
|
+
sort: [{ field: "name", order: "asc" }],
|
|
1304
|
+
pagination: { pageSize: 100 }
|
|
1305
|
+
}
|
|
1306
|
+
},
|
|
1307
|
+
fields: {
|
|
1308
|
+
// ── Identity ─────────────────────────────────────────────────
|
|
1309
|
+
name: Field.text({
|
|
1310
|
+
label: "Name",
|
|
1311
|
+
required: true,
|
|
1312
|
+
searchable: true,
|
|
1313
|
+
maxLength: 255,
|
|
1314
|
+
group: "Identity"
|
|
1315
|
+
}),
|
|
1316
|
+
code: Field.text({
|
|
1317
|
+
label: "Code",
|
|
1318
|
+
required: false,
|
|
1319
|
+
searchable: true,
|
|
1320
|
+
maxLength: 64,
|
|
1321
|
+
description: "Short stable code (e.g. EMEA-SALES). Unique within tenant.",
|
|
1322
|
+
group: "Identity"
|
|
1323
|
+
}),
|
|
1324
|
+
kind: Field.select(
|
|
1325
|
+
["company", "division", "department", "team", "office", "cost_center"],
|
|
1326
|
+
{
|
|
1327
|
+
label: "Kind",
|
|
1328
|
+
required: true,
|
|
1329
|
+
defaultValue: "department",
|
|
1330
|
+
description: "Categorisation hint \u2014 does not change graph semantics.",
|
|
1331
|
+
group: "Identity"
|
|
1332
|
+
}
|
|
1333
|
+
),
|
|
1334
|
+
// ── Hierarchy ────────────────────────────────────────────────
|
|
1335
|
+
parent_department_id: Field.lookup("sys_department", {
|
|
1336
|
+
label: "Parent Department",
|
|
1337
|
+
required: false,
|
|
1338
|
+
description: "Self-reference for the org tree. Null = root of tenant.",
|
|
1339
|
+
group: "Hierarchy"
|
|
1340
|
+
}),
|
|
1341
|
+
organization_id: Field.lookup("sys_organization", {
|
|
1342
|
+
label: "Organization",
|
|
1343
|
+
required: true,
|
|
1344
|
+
description: "Tenant scope.",
|
|
1345
|
+
group: "Hierarchy"
|
|
1346
|
+
}),
|
|
1347
|
+
// ── Leadership ───────────────────────────────────────────────
|
|
1348
|
+
manager_user_id: Field.lookup("sys_user", {
|
|
1349
|
+
label: "Department Head",
|
|
1350
|
+
required: false,
|
|
1351
|
+
description: "User responsible for this org unit (department head / lead).",
|
|
1352
|
+
group: "Leadership"
|
|
1353
|
+
}),
|
|
1354
|
+
// ── Lifecycle ────────────────────────────────────────────────
|
|
1355
|
+
active: Field.boolean({
|
|
1356
|
+
label: "Active",
|
|
1357
|
+
required: false,
|
|
1358
|
+
defaultValue: true,
|
|
1359
|
+
description: "When false, members are not expanded by graph queries.",
|
|
1360
|
+
group: "Lifecycle"
|
|
1361
|
+
}),
|
|
1362
|
+
effective_from: Field.datetime({
|
|
1363
|
+
label: "Effective From",
|
|
1364
|
+
required: false,
|
|
1365
|
+
description: "When this department came into existence (HRIS sync).",
|
|
1366
|
+
group: "Lifecycle"
|
|
1367
|
+
}),
|
|
1368
|
+
effective_to: Field.datetime({
|
|
1369
|
+
label: "Effective To",
|
|
1370
|
+
required: false,
|
|
1371
|
+
description: "When this department was retired (HRIS sync).",
|
|
1372
|
+
group: "Lifecycle"
|
|
1373
|
+
}),
|
|
1374
|
+
external_ref: Field.text({
|
|
1375
|
+
label: "External Reference",
|
|
1376
|
+
required: false,
|
|
1377
|
+
maxLength: 200,
|
|
1378
|
+
description: "ID in upstream HRIS (Workday / SAP HR / \u5317\u68EE).",
|
|
1379
|
+
group: "Lifecycle"
|
|
1380
|
+
}),
|
|
1381
|
+
// ── System ───────────────────────────────────────────────────
|
|
1382
|
+
id: Field.text({
|
|
1383
|
+
label: "Department ID",
|
|
1384
|
+
required: true,
|
|
1385
|
+
readonly: true,
|
|
1386
|
+
group: "System"
|
|
1387
|
+
}),
|
|
1388
|
+
created_at: Field.datetime({
|
|
1389
|
+
label: "Created At",
|
|
1390
|
+
defaultValue: "NOW()",
|
|
1391
|
+
readonly: true,
|
|
1392
|
+
group: "System"
|
|
1393
|
+
}),
|
|
1394
|
+
updated_at: Field.datetime({
|
|
1395
|
+
label: "Updated At",
|
|
1396
|
+
defaultValue: "NOW()",
|
|
1397
|
+
readonly: true,
|
|
1398
|
+
group: "System"
|
|
1399
|
+
})
|
|
1400
|
+
},
|
|
1401
|
+
indexes: [
|
|
1402
|
+
{ fields: ["organization_id"] },
|
|
1403
|
+
{ fields: ["parent_department_id"] },
|
|
1404
|
+
{ fields: ["code", "organization_id"], unique: true },
|
|
1405
|
+
{ fields: ["active"] }
|
|
1406
|
+
],
|
|
1407
|
+
enable: {
|
|
1408
|
+
trackHistory: true,
|
|
1409
|
+
searchable: true,
|
|
1410
|
+
apiEnabled: true,
|
|
1411
|
+
apiMethods: ["get", "list", "create", "update", "delete"],
|
|
1412
|
+
trash: true,
|
|
1413
|
+
mru: false
|
|
1414
|
+
}
|
|
1415
|
+
});
|
|
1416
|
+
var SysDepartmentMember = ObjectSchema.create({
|
|
1417
|
+
name: "sys_department_member",
|
|
1418
|
+
label: "Department Member",
|
|
1419
|
+
pluralLabel: "Department Members",
|
|
1420
|
+
icon: "user-cog",
|
|
1421
|
+
isSystem: true,
|
|
1422
|
+
managedBy: "platform",
|
|
1423
|
+
description: "User assignment to a department (matrix-org friendly, effective-dated).",
|
|
1424
|
+
titleFormat: "{user_id} in {department_id}",
|
|
1425
|
+
compactLayout: ["user_id", "department_id", "role_in_department", "is_primary"],
|
|
1426
|
+
fields: {
|
|
1427
|
+
id: Field.text({
|
|
1428
|
+
label: "Member ID",
|
|
1429
|
+
required: true,
|
|
1430
|
+
readonly: true,
|
|
1431
|
+
group: "System"
|
|
1432
|
+
}),
|
|
1433
|
+
department_id: Field.lookup("sys_department", {
|
|
1434
|
+
label: "Department",
|
|
1435
|
+
required: true,
|
|
1436
|
+
group: "Assignment"
|
|
1437
|
+
}),
|
|
1438
|
+
user_id: Field.lookup("sys_user", {
|
|
1439
|
+
label: "User",
|
|
1440
|
+
required: true,
|
|
1441
|
+
group: "Assignment"
|
|
1442
|
+
}),
|
|
1443
|
+
role_in_department: Field.select(
|
|
1444
|
+
["member", "lead", "deputy"],
|
|
1445
|
+
{
|
|
1446
|
+
label: "Role in Department",
|
|
1447
|
+
required: false,
|
|
1448
|
+
defaultValue: "member",
|
|
1449
|
+
description: "`lead` is the day-to-day head; `deputy` may stand in for the lead in approval routing.",
|
|
1450
|
+
group: "Assignment"
|
|
1451
|
+
}
|
|
1452
|
+
),
|
|
1453
|
+
is_primary: Field.boolean({
|
|
1454
|
+
label: "Primary Assignment",
|
|
1455
|
+
required: false,
|
|
1456
|
+
defaultValue: true,
|
|
1457
|
+
description: "When the user is in multiple departments, this marks the canonical one for reporting.",
|
|
1458
|
+
group: "Assignment"
|
|
1459
|
+
}),
|
|
1460
|
+
effective_from: Field.datetime({
|
|
1461
|
+
label: "Effective From",
|
|
1462
|
+
required: false,
|
|
1463
|
+
group: "Lifecycle"
|
|
1464
|
+
}),
|
|
1465
|
+
effective_to: Field.datetime({
|
|
1466
|
+
label: "Effective To",
|
|
1467
|
+
required: false,
|
|
1468
|
+
group: "Lifecycle"
|
|
1469
|
+
}),
|
|
1470
|
+
created_at: Field.datetime({
|
|
1471
|
+
label: "Created At",
|
|
1472
|
+
defaultValue: "NOW()",
|
|
1473
|
+
readonly: true,
|
|
1474
|
+
group: "System"
|
|
1475
|
+
}),
|
|
1476
|
+
updated_at: Field.datetime({
|
|
1477
|
+
label: "Updated At",
|
|
1478
|
+
defaultValue: "NOW()",
|
|
1479
|
+
readonly: true,
|
|
1480
|
+
group: "System"
|
|
1481
|
+
})
|
|
1482
|
+
},
|
|
1483
|
+
indexes: [
|
|
1484
|
+
{ fields: ["department_id", "user_id"], unique: true },
|
|
1485
|
+
{ fields: ["user_id"] },
|
|
1486
|
+
{ fields: ["is_primary"] }
|
|
1487
|
+
],
|
|
1488
|
+
enable: {
|
|
1489
|
+
trackHistory: true,
|
|
1490
|
+
searchable: true,
|
|
1491
|
+
apiEnabled: true,
|
|
1492
|
+
apiMethods: ["get", "list", "create", "update", "delete"],
|
|
1493
|
+
trash: true,
|
|
1494
|
+
mru: false
|
|
1495
|
+
}
|
|
1496
|
+
});
|
|
607
1497
|
var SysApiKey = ObjectSchema.create({
|
|
608
1498
|
name: "sys_api_key",
|
|
609
1499
|
label: "API Key",
|
|
610
1500
|
pluralLabel: "API Keys",
|
|
611
1501
|
icon: "key-round",
|
|
612
1502
|
isSystem: true,
|
|
1503
|
+
managedBy: "better-auth",
|
|
613
1504
|
description: "API keys for programmatic access",
|
|
614
1505
|
displayNameField: "name",
|
|
615
1506
|
titleFormat: "{name}",
|
|
616
1507
|
compactLayout: ["name", "prefix", "user_id", "expires_at", "revoked"],
|
|
1508
|
+
// Custom actions — sys_api_key is managed-by 'better-auth' but the
|
|
1509
|
+
// `revoked` boolean is a column we control via the data API. These row
|
|
1510
|
+
// actions use the generic PATCH /api/v1/sys_api_key/{id} endpoint with
|
|
1511
|
+
// `bodyExtra` to set the `revoked` flag explicitly.
|
|
1512
|
+
actions: [
|
|
1513
|
+
{
|
|
1514
|
+
name: "revoke_api_key",
|
|
1515
|
+
label: "Revoke API Key",
|
|
1516
|
+
icon: "shield-off",
|
|
1517
|
+
variant: "danger",
|
|
1518
|
+
mode: "custom",
|
|
1519
|
+
locations: ["list_item"],
|
|
1520
|
+
type: "api",
|
|
1521
|
+
method: "PATCH",
|
|
1522
|
+
target: "/api/v1/data/sys_api_key/{id}",
|
|
1523
|
+
bodyExtra: { revoked: true },
|
|
1524
|
+
confirmText: "Revoke this API key? Any clients using it will immediately lose access.",
|
|
1525
|
+
successMessage: "API key revoked",
|
|
1526
|
+
refreshAfter: true
|
|
1527
|
+
},
|
|
1528
|
+
{
|
|
1529
|
+
name: "restore_api_key",
|
|
1530
|
+
label: "Restore API Key",
|
|
1531
|
+
icon: "shield-check",
|
|
1532
|
+
variant: "secondary",
|
|
1533
|
+
mode: "custom",
|
|
1534
|
+
locations: ["list_item"],
|
|
1535
|
+
type: "api",
|
|
1536
|
+
method: "PATCH",
|
|
1537
|
+
target: "/api/v1/data/sys_api_key/{id}",
|
|
1538
|
+
bodyExtra: { revoked: false },
|
|
1539
|
+
confirmText: "Restore this revoked API key? Existing clients holding the key will regain access.",
|
|
1540
|
+
successMessage: "API key restored",
|
|
1541
|
+
refreshAfter: true
|
|
1542
|
+
}
|
|
1543
|
+
],
|
|
1544
|
+
listViews: {
|
|
1545
|
+
mine: {
|
|
1546
|
+
type: "grid",
|
|
1547
|
+
name: "mine",
|
|
1548
|
+
label: "My Keys",
|
|
1549
|
+
data: { provider: "object", object: "sys_api_key" },
|
|
1550
|
+
columns: ["name", "prefix", "expires_at", "last_used_at", "revoked"],
|
|
1551
|
+
filter: [
|
|
1552
|
+
{ field: "user_id", operator: "equals", value: "{current_user_id}" }
|
|
1553
|
+
],
|
|
1554
|
+
sort: [{ field: "created_at", order: "desc" }],
|
|
1555
|
+
pagination: { pageSize: 50 }
|
|
1556
|
+
},
|
|
1557
|
+
active: {
|
|
1558
|
+
type: "grid",
|
|
1559
|
+
name: "active",
|
|
1560
|
+
label: "Active",
|
|
1561
|
+
data: { provider: "object", object: "sys_api_key" },
|
|
1562
|
+
columns: ["name", "prefix", "user_id", "expires_at", "last_used_at"],
|
|
1563
|
+
filter: [{ field: "revoked", operator: "equals", value: false }],
|
|
1564
|
+
sort: [{ field: "last_used_at", order: "desc" }],
|
|
1565
|
+
pagination: { pageSize: 50 }
|
|
1566
|
+
},
|
|
1567
|
+
revoked: {
|
|
1568
|
+
type: "grid",
|
|
1569
|
+
name: "revoked",
|
|
1570
|
+
label: "Revoked",
|
|
1571
|
+
data: { provider: "object", object: "sys_api_key" },
|
|
1572
|
+
columns: ["name", "prefix", "user_id", "expires_at", "updated_at"],
|
|
1573
|
+
filter: [{ field: "revoked", operator: "equals", value: true }],
|
|
1574
|
+
sort: [{ field: "updated_at", order: "desc" }],
|
|
1575
|
+
pagination: { pageSize: 50 }
|
|
1576
|
+
},
|
|
1577
|
+
all_keys: {
|
|
1578
|
+
type: "grid",
|
|
1579
|
+
name: "all_keys",
|
|
1580
|
+
label: "All",
|
|
1581
|
+
data: { provider: "object", object: "sys_api_key" },
|
|
1582
|
+
columns: ["name", "prefix", "user_id", "expires_at", "last_used_at", "revoked"],
|
|
1583
|
+
sort: [{ field: "created_at", order: "desc" }],
|
|
1584
|
+
pagination: { pageSize: 50 }
|
|
1585
|
+
}
|
|
1586
|
+
},
|
|
617
1587
|
fields: {
|
|
618
1588
|
// ── Identity ─────────────────────────────────────────────────
|
|
619
1589
|
name: Field.text({
|
|
@@ -712,9 +1682,66 @@ var SysTwoFactor = ObjectSchema.create({
|
|
|
712
1682
|
pluralLabel: "Two Factor Credentials",
|
|
713
1683
|
icon: "smartphone",
|
|
714
1684
|
isSystem: true,
|
|
1685
|
+
managedBy: "better-auth",
|
|
715
1686
|
description: "Two-factor authentication credentials",
|
|
716
1687
|
titleFormat: "Two-factor for {user_id}",
|
|
717
1688
|
compactLayout: ["user_id", "created_at"],
|
|
1689
|
+
listViews: {
|
|
1690
|
+
mine: {
|
|
1691
|
+
type: "grid",
|
|
1692
|
+
name: "mine",
|
|
1693
|
+
label: "My Enrollment",
|
|
1694
|
+
data: { provider: "object", object: "sys_two_factor" },
|
|
1695
|
+
columns: ["created_at", "updated_at"],
|
|
1696
|
+
filter: [{ field: "user_id", operator: "equals", value: "{current_user_id}" }],
|
|
1697
|
+
sort: [{ field: "created_at", order: "desc" }],
|
|
1698
|
+
pagination: { pageSize: 50 }
|
|
1699
|
+
},
|
|
1700
|
+
all_enrollments: {
|
|
1701
|
+
type: "grid",
|
|
1702
|
+
name: "all_enrollments",
|
|
1703
|
+
label: "All",
|
|
1704
|
+
data: { provider: "object", object: "sys_two_factor" },
|
|
1705
|
+
columns: ["user_id", "created_at", "updated_at"],
|
|
1706
|
+
sort: [{ field: "created_at", order: "desc" }],
|
|
1707
|
+
pagination: { pageSize: 50 }
|
|
1708
|
+
}
|
|
1709
|
+
},
|
|
1710
|
+
// Toolbar actions for self-service 2FA enrollment. The actual TOTP secret
|
|
1711
|
+
// and backup codes returned by better-auth must be shown in the response
|
|
1712
|
+
// toast / dialog — the action runner surfaces successMessage; the raw
|
|
1713
|
+
// payload is logged client-side for now (TODO: dedicated 2FA setup wizard).
|
|
1714
|
+
actions: [
|
|
1715
|
+
{
|
|
1716
|
+
name: "enable_two_factor",
|
|
1717
|
+
label: "Enable 2FA",
|
|
1718
|
+
icon: "shield-check",
|
|
1719
|
+
variant: "primary",
|
|
1720
|
+
locations: ["list_toolbar"],
|
|
1721
|
+
type: "api",
|
|
1722
|
+
target: "/api/v1/auth/two-factor/enable",
|
|
1723
|
+
successMessage: "2FA enrollment started \u2014 check response for TOTP URI and backup codes",
|
|
1724
|
+
refreshAfter: true,
|
|
1725
|
+
params: [
|
|
1726
|
+
{ name: "password", label: "Current Password", type: "text", required: true }
|
|
1727
|
+
]
|
|
1728
|
+
},
|
|
1729
|
+
{
|
|
1730
|
+
name: "disable_two_factor",
|
|
1731
|
+
label: "Disable 2FA",
|
|
1732
|
+
icon: "shield-off",
|
|
1733
|
+
variant: "danger",
|
|
1734
|
+
locations: ["list_toolbar"],
|
|
1735
|
+
type: "api",
|
|
1736
|
+
target: "/api/v1/auth/two-factor/disable",
|
|
1737
|
+
confirmText: "Disable two-factor authentication on your account?",
|
|
1738
|
+
successMessage: "2FA disabled",
|
|
1739
|
+
refreshAfter: true,
|
|
1740
|
+
params: [
|
|
1741
|
+
{ name: "password", label: "Current Password", type: "text", required: true }
|
|
1742
|
+
]
|
|
1743
|
+
}
|
|
1744
|
+
],
|
|
718
1745
|
fields: {
|
|
719
1746
|
id: Field.text({
|
|
720
1747
|
label: "Two Factor ID",
|
|
@@ -764,6 +1791,7 @@ var SysDeviceCode = ObjectSchema.create({
|
|
|
764
1791
|
pluralLabel: "Device Codes",
|
|
765
1792
|
icon: "key-round",
|
|
766
1793
|
isSystem: true,
|
|
1794
|
+
managedBy: "better-auth",
|
|
767
1795
|
description: "OAuth 2.0 Device Authorization Grant (RFC 8628) pending requests",
|
|
768
1796
|
titleFormat: "{user_code}",
|
|
769
1797
|
compactLayout: ["user_code", "status", "client_id", "expires_at"],
|
|
@@ -853,9 +1881,44 @@ var SysUserPreference = ObjectSchema.create({
|
|
|
853
1881
|
pluralLabel: "User Preferences",
|
|
854
1882
|
icon: "settings",
|
|
855
1883
|
isSystem: true,
|
|
1884
|
+
// managedBy: 'system' — preferences are per-user state authored from
|
|
1885
|
+
// the user's own settings page, never created by an admin. The list
|
|
1886
|
+
// surface in Setup is a support/diagnostic view only.
|
|
1887
|
+
managedBy: "system",
|
|
856
1888
|
description: "Per-user key-value preferences (theme, locale, etc.)",
|
|
857
1889
|
titleFormat: "{key}",
|
|
858
1890
|
compactLayout: ["user_id", "key"],
|
|
1891
|
+
listViews: {
|
|
1892
|
+
mine: {
|
|
1893
|
+
type: "grid",
|
|
1894
|
+
name: "mine",
|
|
1895
|
+
label: "My Preferences",
|
|
1896
|
+
data: { provider: "object", object: "sys_user_preference" },
|
|
1897
|
+
columns: ["key", "updated_at"],
|
|
1898
|
+
filter: [{ field: "user_id", operator: "equals", value: "{current_user_id}" }],
|
|
1899
|
+
sort: [{ field: "key", order: "asc" }],
|
|
1900
|
+
pagination: { pageSize: 100 }
|
|
1901
|
+
},
|
|
1902
|
+
by_user: {
|
|
1903
|
+
type: "grid",
|
|
1904
|
+
name: "by_user",
|
|
1905
|
+
label: "By User",
|
|
1906
|
+
data: { provider: "object", object: "sys_user_preference" },
|
|
1907
|
+
columns: ["user_id", "key", "updated_at"],
|
|
1908
|
+
sort: [{ field: "user_id", order: "asc" }, { field: "key", order: "asc" }],
|
|
1909
|
+
grouping: { fields: [{ field: "user_id", order: "asc", collapsed: true }] },
|
|
1910
|
+
pagination: { pageSize: 200 }
|
|
1911
|
+
},
|
|
1912
|
+
all_preferences: {
|
|
1913
|
+
type: "grid",
|
|
1914
|
+
name: "all_preferences",
|
|
1915
|
+
label: "All",
|
|
1916
|
+
data: { provider: "object", object: "sys_user_preference" },
|
|
1917
|
+
columns: ["user_id", "key", "created_at", "updated_at"],
|
|
1918
|
+
sort: [{ field: "updated_at", order: "desc" }],
|
|
1919
|
+
pagination: { pageSize: 100 }
|
|
1920
|
+
}
|
|
1921
|
+
},
|
|
859
1922
|
fields: {
|
|
860
1923
|
id: Field.text({
|
|
861
1924
|
label: "Preference ID",
|
|
@@ -907,10 +1970,42 @@ var SysOauthApplication = ObjectSchema.create({
|
|
|
907
1970
|
pluralLabel: "OAuth Applications",
|
|
908
1971
|
icon: "key-round",
|
|
909
1972
|
isSystem: true,
|
|
1973
|
+
managedBy: "better-auth",
|
|
910
1974
|
description: "Registered OAuth/OIDC client applications",
|
|
911
1975
|
displayNameField: "name",
|
|
912
1976
|
titleFormat: "{name}",
|
|
913
1977
|
compactLayout: ["name", "client_id", "type", "disabled"],
|
|
1978
|
+
listViews: {
|
|
1979
|
+
active: {
|
|
1980
|
+
type: "grid",
|
|
1981
|
+
name: "active",
|
|
1982
|
+
label: "Active",
|
|
1983
|
+
data: { provider: "object", object: "sys_oauth_application" },
|
|
1984
|
+
columns: ["name", "client_id", "type", "updated_at"],
|
|
1985
|
+
filter: [{ field: "disabled", operator: "equals", value: false }],
|
|
1986
|
+
sort: [{ field: "name", order: "asc" }],
|
|
1987
|
+
pagination: { pageSize: 50 }
|
|
1988
|
+
},
|
|
1989
|
+
disabled_apps: {
|
|
1990
|
+
type: "grid",
|
|
1991
|
+
name: "disabled_apps",
|
|
1992
|
+
label: "Disabled",
|
|
1993
|
+
data: { provider: "object", object: "sys_oauth_application" },
|
|
1994
|
+
columns: ["name", "client_id", "type", "updated_at"],
|
|
1995
|
+
filter: [{ field: "disabled", operator: "equals", value: true }],
|
|
1996
|
+
sort: [{ field: "updated_at", order: "desc" }],
|
|
1997
|
+
pagination: { pageSize: 50 }
|
|
1998
|
+
},
|
|
1999
|
+
all_apps: {
|
|
2000
|
+
type: "grid",
|
|
2001
|
+
name: "all_apps",
|
|
2002
|
+
label: "All",
|
|
2003
|
+
data: { provider: "object", object: "sys_oauth_application" },
|
|
2004
|
+
columns: ["name", "client_id", "type", "disabled", "created_at"],
|
|
2005
|
+
sort: [{ field: "name", order: "asc" }],
|
|
2006
|
+
pagination: { pageSize: 50 }
|
|
2007
|
+
}
|
|
2008
|
+
},
|
|
914
2009
|
fields: {
|
|
915
2010
|
// ── Identity ─────────────────────────────────────────────────
|
|
916
2011
|
id: Field.text({
|
|
@@ -1122,6 +2217,7 @@ var SysOauthAccessToken = ObjectSchema.create({
|
|
|
1122
2217
|
pluralLabel: "OAuth Access Tokens",
|
|
1123
2218
|
icon: "ticket",
|
|
1124
2219
|
isSystem: true,
|
|
2220
|
+
managedBy: "better-auth",
|
|
1125
2221
|
description: "Opaque OAuth access tokens issued to client applications",
|
|
1126
2222
|
compactLayout: ["client_id", "user_id", "expires_at"],
|
|
1127
2223
|
fields: {
|
|
@@ -1199,6 +2295,7 @@ var SysOauthRefreshToken = ObjectSchema.create({
|
|
|
1199
2295
|
pluralLabel: "OAuth Refresh Tokens",
|
|
1200
2296
|
icon: "refresh-cw",
|
|
1201
2297
|
isSystem: true,
|
|
2298
|
+
managedBy: "better-auth",
|
|
1202
2299
|
description: "Opaque OAuth refresh tokens (linked to a session)",
|
|
1203
2300
|
compactLayout: ["client_id", "user_id", "expires_at"],
|
|
1204
2301
|
fields: {
|
|
@@ -1280,6 +2377,7 @@ var SysOauthConsent = ObjectSchema.create({
|
|
|
1280
2377
|
pluralLabel: "OAuth Consents",
|
|
1281
2378
|
icon: "shield-check",
|
|
1282
2379
|
isSystem: true,
|
|
2380
|
+
managedBy: "better-auth",
|
|
1283
2381
|
description: "User consent records for OAuth client applications",
|
|
1284
2382
|
compactLayout: ["client_id", "user_id", "scopes"],
|
|
1285
2383
|
fields: {
|
|
@@ -1339,6 +2437,7 @@ var SysJwks = ObjectSchema.create({
|
|
|
1339
2437
|
pluralLabel: "JWKS Keys",
|
|
1340
2438
|
icon: "key",
|
|
1341
2439
|
isSystem: true,
|
|
2440
|
+
managedBy: "better-auth",
|
|
1342
2441
|
description: "Asymmetric key pairs used to sign and verify issued JWTs",
|
|
1343
2442
|
compactLayout: ["id", "created_at", "expires_at"],
|
|
1344
2443
|
fields: {
|
|
@@ -1380,6 +2479,6 @@ var SysJwks = ObjectSchema.create({
|
|
|
1380
2479
|
}
|
|
1381
2480
|
});
|
|
1382
2481
|
|
|
1383
|
-
export { SysAccount, SysApiKey, SysDeviceCode, SysInvitation, SysJwks, SysMember, SysOauthAccessToken, SysOauthApplication, SysOauthConsent, SysOauthRefreshToken, SysOrganization, SysSession, SysTeam, SysTeamMember, SysTwoFactor, SysUser, SysUserPreference, SysVerification };
|
|
2482
|
+
export { SysAccount, SysApiKey, SysDepartment, SysDepartmentMember, SysDeviceCode, SysInvitation, SysJwks, SysMember, SysOauthAccessToken, SysOauthApplication, SysOauthConsent, SysOauthRefreshToken, SysOrganization, SysSession, SysTeam, SysTeamMember, SysTwoFactor, SysUser, SysUserPreference, SysVerification };
|
|
1384
2483
|
//# sourceMappingURL=index.mjs.map
|
|
1385
2484
|
//# sourceMappingURL=index.mjs.map
|