@objectstack/platform-objects 10.2.0 → 11.0.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 +8 -8
- package/dist/apps/index.d.ts +8 -8
- package/dist/apps/index.js +35 -6
- package/dist/apps/index.js.map +1 -1
- package/dist/apps/index.mjs +35 -6
- package/dist/apps/index.mjs.map +1 -1
- package/dist/audit/index.d.mts +346 -27
- package/dist/audit/index.d.ts +346 -27
- package/dist/identity/index.d.mts +19528 -13310
- package/dist/identity/index.d.ts +19528 -13310
- package/dist/identity/index.js +363 -8
- package/dist/identity/index.js.map +1 -1
- package/dist/identity/index.mjs +362 -9
- package/dist/identity/index.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +398 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +397 -15
- package/dist/index.mjs.map +1 -1
- package/dist/plugin.js +5 -2
- package/dist/plugin.js.map +1 -1
- package/dist/plugin.mjs +5 -2
- package/dist/plugin.mjs.map +1 -1
- package/dist/system/index.d.mts +100 -9
- package/dist/system/index.d.ts +100 -9
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -37,6 +37,13 @@ var SysUser = data.ObjectSchema.create({
|
|
|
37
37
|
locations: ["list_toolbar"],
|
|
38
38
|
type: "api",
|
|
39
39
|
target: "/api/v1/auth/organization/invite-member",
|
|
40
|
+
// Org invitations are a multi-org-only flow (the endpoint resolves
|
|
41
|
+
// an active org that does not exist in single-org mode). Hide the
|
|
42
|
+
// affordance unless multi-org is enabled — matching the
|
|
43
|
+
// `create_organization` gate on sys_organization. This action is the
|
|
44
|
+
// most exposed of the set because the Users list is always reachable
|
|
45
|
+
// in single-org, unlike the org/membership lists.
|
|
46
|
+
visible: "features.multiOrgEnabled != false",
|
|
40
47
|
successMessage: "Invitation sent",
|
|
41
48
|
refreshAfter: true,
|
|
42
49
|
params: [
|
|
@@ -80,6 +87,21 @@ var SysUser = data.ObjectSchema.create({
|
|
|
80
87
|
successMessage: "User unbanned",
|
|
81
88
|
refreshAfter: true
|
|
82
89
|
},
|
|
90
|
+
{
|
|
91
|
+
// ADR-0069 D2 — clear a brute-force lockout early (locked_until auto-
|
|
92
|
+
// expires, but an admin can release a user immediately). Hits the
|
|
93
|
+
// plugin-auth custom route, which is admin-guarded server-side.
|
|
94
|
+
name: "unlock_user",
|
|
95
|
+
label: "Unlock Account",
|
|
96
|
+
icon: "lock-open",
|
|
97
|
+
variant: "secondary",
|
|
98
|
+
locations: ["list_item"],
|
|
99
|
+
type: "api",
|
|
100
|
+
target: "/api/v1/auth/admin/unlock-user",
|
|
101
|
+
recordIdParam: "userId",
|
|
102
|
+
successMessage: "Account unlocked",
|
|
103
|
+
refreshAfter: true
|
|
104
|
+
},
|
|
83
105
|
{
|
|
84
106
|
name: "set_user_password",
|
|
85
107
|
label: "Set Password",
|
|
@@ -156,7 +178,11 @@ var SysUser = data.ObjectSchema.create({
|
|
|
156
178
|
locations: ["record_header", "record_more", "record_section"],
|
|
157
179
|
type: "api",
|
|
158
180
|
target: "/api/v1/auth/change-password",
|
|
159
|
-
|
|
181
|
+
// Managed (IdP-provisioned) users hold no local credential — hide the
|
|
182
|
+
// password form so they can't self-mint a password that bypasses
|
|
183
|
+
// enforced SSO. The break-glass owner (env-native, or flipped back when
|
|
184
|
+
// their break-glass password is set) keeps it. ADR-0024 D4/D5.2.
|
|
185
|
+
visible: 'record.id == ctx.user.id && record.source != "idp_provisioned"',
|
|
160
186
|
successMessage: "Password changed",
|
|
161
187
|
refreshAfter: false,
|
|
162
188
|
params: [
|
|
@@ -173,7 +199,9 @@ var SysUser = data.ObjectSchema.create({
|
|
|
173
199
|
locations: ["record_header", "record_more", "record_section"],
|
|
174
200
|
type: "api",
|
|
175
201
|
target: "/api/v1/auth/change-email",
|
|
176
|
-
|
|
202
|
+
// A managed user's email is owned by the IdP — a local change would
|
|
203
|
+
// desync. Hide for IdP-provisioned; env-native users keep it.
|
|
204
|
+
visible: 'record.id == ctx.user.id && record.source != "idp_provisioned"',
|
|
177
205
|
successMessage: "Verification email sent \u2014 check the new address to confirm.",
|
|
178
206
|
refreshAfter: false,
|
|
179
207
|
params: [
|
|
@@ -204,7 +232,9 @@ var SysUser = data.ObjectSchema.create({
|
|
|
204
232
|
locations: ["record_more", "record_section"],
|
|
205
233
|
type: "api",
|
|
206
234
|
target: "/api/v1/auth/delete-user",
|
|
207
|
-
|
|
235
|
+
// Self-delete needs a local password; managed users are deprovisioned
|
|
236
|
+
// via the IdP (org-removal / SCIM), not local self-service. Hide for them.
|
|
237
|
+
visible: 'record.id == ctx.user.id && record.source != "idp_provisioned"',
|
|
208
238
|
confirmText: "Permanently delete your account? This cannot be undone \u2014 all your sessions will be terminated and all data you own will be removed per the configured retention policy.",
|
|
209
239
|
successMessage: "Account deleted",
|
|
210
240
|
refreshAfter: false,
|
|
@@ -287,7 +317,7 @@ var SysUser = data.ObjectSchema.create({
|
|
|
287
317
|
name: "all_users",
|
|
288
318
|
label: "All Users",
|
|
289
319
|
data: { provider: "object", object: "sys_user" },
|
|
290
|
-
columns: ["name", "email", "email_verified", "two_factor_enabled", "created_at"],
|
|
320
|
+
columns: ["name", "email", "email_verified", "source", "two_factor_enabled", "created_at"],
|
|
291
321
|
sort: [{ field: "name", order: "asc" }],
|
|
292
322
|
pagination: { pageSize: 50 }
|
|
293
323
|
},
|
|
@@ -374,6 +404,32 @@ var SysUser = data.ObjectSchema.create({
|
|
|
374
404
|
group: "Admin",
|
|
375
405
|
description: "When set, the ban auto-clears at this time."
|
|
376
406
|
}),
|
|
407
|
+
// ── Anti-brute-force (ADR-0069 D2) — owned by objectql, better-auth is
|
|
408
|
+
// oblivious. The auth manager's sign-in hooks maintain these: failures
|
|
409
|
+
// increment the counter; crossing `lockout_threshold` stamps
|
|
410
|
+
// `locked_until`; a successful sign-in resets both. Admins can clear
|
|
411
|
+
// them early via the Unlock action.
|
|
412
|
+
failed_login_count: data.Field.number({
|
|
413
|
+
label: "Failed Login Count",
|
|
414
|
+
required: false,
|
|
415
|
+
defaultValue: 0,
|
|
416
|
+
readonly: true,
|
|
417
|
+
group: "Admin",
|
|
418
|
+
description: "Consecutive failed sign-in attempts; reset to 0 on success. Maintained by the auth manager."
|
|
419
|
+
}),
|
|
420
|
+
locked_until: data.Field.datetime({
|
|
421
|
+
label: "Locked Until",
|
|
422
|
+
required: false,
|
|
423
|
+
readonly: true,
|
|
424
|
+
group: "Admin",
|
|
425
|
+
description: "When set and in the future, sign-in is rejected (brute-force lockout). Auto-clears past this time; an admin can clear it early via Unlock."
|
|
426
|
+
}),
|
|
427
|
+
ai_access: data.Field.boolean({
|
|
428
|
+
label: "AI Access",
|
|
429
|
+
defaultValue: false,
|
|
430
|
+
group: "Admin",
|
|
431
|
+
description: "Whether this user holds an AI seat \u2014 grants access to the in-UI AI agents (build / ask). The framework synthesizes the `ai_seat` capability from this flag (plugin-hono-server resolveCtx). Assignment is capped by the licensed / purchased seat count (enforced by @objectstack/security-enterprise AiSeatPlugin). Owned by objectql (better-auth is oblivious to this column)."
|
|
432
|
+
}),
|
|
377
433
|
// ── Profile ──────────────────────────────────────────────────
|
|
378
434
|
image: data.Field.url({
|
|
379
435
|
label: "Profile Image",
|
|
@@ -394,6 +450,28 @@ var SysUser = data.ObjectSchema.create({
|
|
|
394
450
|
description: "The user's primary business unit \u2014 a denormalised projection of sys_business_unit_member.is_primary, maintained by plugin-sharing (ADR-0057 addendum D12). Lets a user-lookup filter candidates by business unit without traversing the membership junction. Do not edit directly; set it via business-unit membership."
|
|
395
451
|
}),
|
|
396
452
|
// ── System (auto-managed, hidden from create/edit forms) ─────
|
|
453
|
+
// Identity provenance (ADR-0024 D4). `idp_provisioned` users were
|
|
454
|
+
// JIT-created on first federated login (a `sys_account` exists for an
|
|
455
|
+
// external/OIDC provider — e.g. the cloud-as-IdP `objectstack-cloud`
|
|
456
|
+
// provider, or a customer's own IdP); `env_native` users registered
|
|
457
|
+
// locally (email/password) or are app end-users. Stamped automatically by
|
|
458
|
+
// the AuthManager `account.create.after` hook — never edited by hand.
|
|
459
|
+
// Drives the managed-vs-native user-mgmt UI gating (the password /
|
|
460
|
+
// identity-edit actions hide for managed users, who hold no local
|
|
461
|
+
// credential) and is the marker SCIM lifecycle keys off. Owned by objectql
|
|
462
|
+
// (better-auth is oblivious to this column — like `ai_access`).
|
|
463
|
+
source: data.Field.select({
|
|
464
|
+
label: "Identity Source",
|
|
465
|
+
required: false,
|
|
466
|
+
readonly: true,
|
|
467
|
+
group: "System",
|
|
468
|
+
defaultValue: "env_native",
|
|
469
|
+
options: [
|
|
470
|
+
{ label: "IdP-Provisioned", value: "idp_provisioned" },
|
|
471
|
+
{ label: "Env-Native", value: "env_native" }
|
|
472
|
+
],
|
|
473
|
+
description: "How this identity was created \u2014 idp_provisioned (federated SSO JIT) or env_native (local signup / app end-user). System-managed; do not edit."
|
|
474
|
+
}),
|
|
397
475
|
id: data.Field.text({
|
|
398
476
|
label: "User ID",
|
|
399
477
|
required: true,
|
|
@@ -759,6 +837,16 @@ var SysAccount = data.ObjectSchema.create({
|
|
|
759
837
|
label: "Password Hash",
|
|
760
838
|
required: false,
|
|
761
839
|
description: "Hashed password for email/password provider"
|
|
840
|
+
}),
|
|
841
|
+
// ADR-0069 D1 — bounded ring of previous password hashes (JSON array of
|
|
842
|
+
// strings), used to reject password reuse on change/reset. Maintained by
|
|
843
|
+
// the auth manager; never exposed in UI.
|
|
844
|
+
previous_password_hashes: data.Field.textarea({
|
|
845
|
+
label: "Previous Password Hashes",
|
|
846
|
+
required: false,
|
|
847
|
+
readonly: true,
|
|
848
|
+
hidden: true,
|
|
849
|
+
description: "JSON array of prior password hashes (bounded by password_history_count); reuse-prevention only. System-managed."
|
|
762
850
|
})
|
|
763
851
|
},
|
|
764
852
|
indexes: [
|
|
@@ -824,7 +912,13 @@ var SysVerification = data.ObjectSchema.create({
|
|
|
824
912
|
})
|
|
825
913
|
},
|
|
826
914
|
indexes: [
|
|
827
|
-
|
|
915
|
+
// `value` must NOT be unique. better-auth's oauth-provider stores OIDC
|
|
916
|
+
// authorization codes in this table with `value` = a JSON blob keyed by
|
|
917
|
+
// user+client+state, which can legitimately repeat. A UNIQUE constraint
|
|
918
|
+
// makes `/api/v1/auth/oauth2/authorize` fail (`UNIQUE constraint failed:
|
|
919
|
+
// sys_verification.value`) → 503, breaking cloud-as-IdP SSO entirely.
|
|
920
|
+
// better-auth keys verification lookups on `identifier`, not `value`.
|
|
921
|
+
{ fields: ["value"], unique: false },
|
|
828
922
|
{ fields: ["identifier"], unique: false },
|
|
829
923
|
{ fields: ["expires_at"], unique: false }
|
|
830
924
|
],
|
|
@@ -892,6 +986,10 @@ var SysOrganization = data.ObjectSchema.create({
|
|
|
892
986
|
recordIdParam: "organizationId",
|
|
893
987
|
// better-auth `organization/update` nests editable fields under `data`.
|
|
894
988
|
bodyShape: { wrap: "data" },
|
|
989
|
+
// Org-admin actions are multi-org-only; hide them in single-org for
|
|
990
|
+
// consistency with `create_organization` (the org list is empty there,
|
|
991
|
+
// but this also guards direct record-URL access).
|
|
992
|
+
visible: "features.multiOrgEnabled != false",
|
|
895
993
|
successMessage: "Organization updated",
|
|
896
994
|
refreshAfter: true,
|
|
897
995
|
params: [
|
|
@@ -910,6 +1008,7 @@ var SysOrganization = data.ObjectSchema.create({
|
|
|
910
1008
|
type: "api",
|
|
911
1009
|
target: "/api/v1/auth/organization/delete",
|
|
912
1010
|
recordIdParam: "organizationId",
|
|
1011
|
+
visible: "features.multiOrgEnabled != false",
|
|
913
1012
|
confirmText: "Delete this organization? All members will lose access immediately. This cannot be undone.",
|
|
914
1013
|
successMessage: "Organization deleted",
|
|
915
1014
|
refreshAfter: true
|
|
@@ -928,6 +1027,7 @@ var SysOrganization = data.ObjectSchema.create({
|
|
|
928
1027
|
type: "api",
|
|
929
1028
|
target: "/api/v1/auth/organization/set-active",
|
|
930
1029
|
recordIdParam: "organizationId",
|
|
1030
|
+
visible: "features.multiOrgEnabled != false",
|
|
931
1031
|
successMessage: "Active organization switched",
|
|
932
1032
|
refreshAfter: true
|
|
933
1033
|
},
|
|
@@ -944,6 +1044,7 @@ var SysOrganization = data.ObjectSchema.create({
|
|
|
944
1044
|
type: "api",
|
|
945
1045
|
target: "/api/v1/auth/organization/leave",
|
|
946
1046
|
recordIdParam: "organizationId",
|
|
1047
|
+
visible: "features.multiOrgEnabled != false",
|
|
947
1048
|
confirmText: "Leave this organization? You will lose access to all of its resources.",
|
|
948
1049
|
successMessage: "You have left the organization",
|
|
949
1050
|
refreshAfter: true
|
|
@@ -965,6 +1066,7 @@ var SysOrganization = data.ObjectSchema.create({
|
|
|
965
1066
|
type: "api",
|
|
966
1067
|
target: "/api/v1/cloud/organizations/{id}/change-slug",
|
|
967
1068
|
method: "POST",
|
|
1069
|
+
visible: "features.multiOrgEnabled != false",
|
|
968
1070
|
confirmText: "Renaming the slug rewrites every platform subdomain for this org and parks the old slug for 90 days. Continue?",
|
|
969
1071
|
successMessage: "Organization slug changed",
|
|
970
1072
|
refreshAfter: true,
|
|
@@ -1063,7 +1165,10 @@ var SysMember = data.ObjectSchema.create({
|
|
|
1063
1165
|
docsUrl: "https://docs.objectstack.ai/adr/0010-metadata-protection"
|
|
1064
1166
|
},
|
|
1065
1167
|
description: "Organization membership records",
|
|
1066
|
-
|
|
1168
|
+
// Org-independent title: organization_id is null in single-org mode, so a
|
|
1169
|
+
// '{user_id} in {organization_id}' format renders "… in null". User + role
|
|
1170
|
+
// identifies the membership in both single- and multi-org deployments.
|
|
1171
|
+
titleFormat: "{user_id} ({role})",
|
|
1067
1172
|
compactLayout: ["user_id", "organization_id", "role"],
|
|
1068
1173
|
// Row-level actions: better-auth `organization/update-member-role` and
|
|
1069
1174
|
// `organization/remove-member`. Generic CRUD is suppressed on better-auth
|
|
@@ -1084,6 +1189,11 @@ var SysMember = data.ObjectSchema.create({
|
|
|
1084
1189
|
locations: ["list_toolbar"],
|
|
1085
1190
|
type: "api",
|
|
1086
1191
|
target: "/api/v1/auth/organization/add-member",
|
|
1192
|
+
// Org-membership mutations are multi-org-only: the better-auth
|
|
1193
|
+
// endpoints resolve an active org that does not exist in single-org
|
|
1194
|
+
// mode, so these actions would fail at the API. Gate every one on
|
|
1195
|
+
// the multi-org flag (mirrors sys_organization.create_organization).
|
|
1196
|
+
visible: "features.multiOrgEnabled != false",
|
|
1087
1197
|
successMessage: "Member added",
|
|
1088
1198
|
refreshAfter: true,
|
|
1089
1199
|
params: [
|
|
@@ -1101,6 +1211,7 @@ var SysMember = data.ObjectSchema.create({
|
|
|
1101
1211
|
type: "api",
|
|
1102
1212
|
target: "/api/v1/auth/organization/update-member-role",
|
|
1103
1213
|
recordIdParam: "memberId",
|
|
1214
|
+
visible: "features.multiOrgEnabled != false",
|
|
1104
1215
|
successMessage: "Member role updated",
|
|
1105
1216
|
refreshAfter: true,
|
|
1106
1217
|
params: [
|
|
@@ -1117,6 +1228,7 @@ var SysMember = data.ObjectSchema.create({
|
|
|
1117
1228
|
type: "api",
|
|
1118
1229
|
target: "/api/v1/auth/organization/remove-member",
|
|
1119
1230
|
recordIdParam: "memberIdOrEmail",
|
|
1231
|
+
visible: "features.multiOrgEnabled != false",
|
|
1120
1232
|
confirmText: "Remove this member from the organization? They will lose access to all org resources.",
|
|
1121
1233
|
successMessage: "Member removed",
|
|
1122
1234
|
refreshAfter: true
|
|
@@ -1138,7 +1250,7 @@ var SysMember = data.ObjectSchema.create({
|
|
|
1138
1250
|
target: "/api/v1/auth/organization/update-member-role",
|
|
1139
1251
|
recordIdParam: "memberId",
|
|
1140
1252
|
bodyExtra: { role: "owner" },
|
|
1141
|
-
visible: "record.role != 'owner'",
|
|
1253
|
+
visible: "record.role != 'owner' && features.multiOrgEnabled != false",
|
|
1142
1254
|
confirmText: "Transfer ownership of this organization to the selected member? You will be demoted to admin and lose owner-only privileges.",
|
|
1143
1255
|
successMessage: "Ownership transferred",
|
|
1144
1256
|
refreshAfter: true
|
|
@@ -1223,7 +1335,10 @@ var SysInvitation = data.ObjectSchema.create({
|
|
|
1223
1335
|
docsUrl: "https://docs.objectstack.ai/adr/0010-metadata-protection"
|
|
1224
1336
|
},
|
|
1225
1337
|
description: "Organization invitations for user onboarding",
|
|
1226
|
-
|
|
1338
|
+
// Title by invitee email rather than organization_id: the latter is null in
|
|
1339
|
+
// single-org mode (renders "Invitation to null"), and the recipient email is
|
|
1340
|
+
// the more useful identifier in both modes anyway.
|
|
1341
|
+
titleFormat: "Invitation for {email}",
|
|
1227
1342
|
compactLayout: ["email", "organization_id", "status"],
|
|
1228
1343
|
// Custom actions — generic CRUD is suppressed (better-auth-managed).
|
|
1229
1344
|
// Mirror the `invite_user` toolbar action from sys_user here so admins
|
|
@@ -1237,6 +1352,13 @@ var SysInvitation = data.ObjectSchema.create({
|
|
|
1237
1352
|
locations: ["list_toolbar"],
|
|
1238
1353
|
type: "api",
|
|
1239
1354
|
target: "/api/v1/auth/organization/invite-member",
|
|
1355
|
+
// Inviting/managing invitations is a multi-org-only flow (the
|
|
1356
|
+
// endpoint resolves an active org absent in single-org mode). Gate
|
|
1357
|
+
// the admin-side actions on the multi-org flag (mirrors
|
|
1358
|
+
// sys_organization.create_organization). The recipient-side
|
|
1359
|
+
// accept/reject actions below stay record-gated — they are
|
|
1360
|
+
// unreachable in single-org anyway (no invitation rows exist).
|
|
1361
|
+
visible: "features.multiOrgEnabled != false",
|
|
1240
1362
|
successMessage: "Invitation sent",
|
|
1241
1363
|
refreshAfter: true,
|
|
1242
1364
|
params: [
|
|
@@ -1254,6 +1376,7 @@ var SysInvitation = data.ObjectSchema.create({
|
|
|
1254
1376
|
type: "api",
|
|
1255
1377
|
target: "/api/v1/auth/organization/cancel-invitation",
|
|
1256
1378
|
recordIdParam: "invitationId",
|
|
1379
|
+
visible: "features.multiOrgEnabled != false",
|
|
1257
1380
|
confirmText: "Cancel this invitation? The recipient will no longer be able to accept it.",
|
|
1258
1381
|
successMessage: "Invitation canceled",
|
|
1259
1382
|
refreshAfter: true
|
|
@@ -1267,6 +1390,7 @@ var SysInvitation = data.ObjectSchema.create({
|
|
|
1267
1390
|
type: "api",
|
|
1268
1391
|
target: "/api/v1/auth/organization/invite-member",
|
|
1269
1392
|
bodyExtra: { resend: true },
|
|
1393
|
+
visible: "features.multiOrgEnabled != false",
|
|
1270
1394
|
successMessage: "Invitation resent",
|
|
1271
1395
|
refreshAfter: true,
|
|
1272
1396
|
params: [
|
|
@@ -1451,6 +1575,10 @@ var SysTeam = data.ObjectSchema.create({
|
|
|
1451
1575
|
locations: ["list_toolbar"],
|
|
1452
1576
|
type: "api",
|
|
1453
1577
|
target: "/api/v1/auth/organization/create-team",
|
|
1578
|
+
// Teams are nested inside organizations — a multi-org-only concept.
|
|
1579
|
+
// Gate every team mutation on the multi-org flag so the affordances
|
|
1580
|
+
// disappear in single-org (mirrors sys_organization.create_organization).
|
|
1581
|
+
visible: "features.multiOrgEnabled != false",
|
|
1454
1582
|
successMessage: "Team created",
|
|
1455
1583
|
refreshAfter: true,
|
|
1456
1584
|
params: [
|
|
@@ -1471,6 +1599,7 @@ var SysTeam = data.ObjectSchema.create({
|
|
|
1471
1599
|
target: "/api/v1/auth/organization/update-team",
|
|
1472
1600
|
recordIdParam: "teamId",
|
|
1473
1601
|
bodyShape: { wrap: "data" },
|
|
1602
|
+
visible: "features.multiOrgEnabled != false",
|
|
1474
1603
|
successMessage: "Team updated",
|
|
1475
1604
|
refreshAfter: true,
|
|
1476
1605
|
params: [
|
|
@@ -1489,6 +1618,7 @@ var SysTeam = data.ObjectSchema.create({
|
|
|
1489
1618
|
type: "api",
|
|
1490
1619
|
target: "/api/v1/auth/organization/remove-team",
|
|
1491
1620
|
recordIdParam: "teamId",
|
|
1621
|
+
visible: "features.multiOrgEnabled != false",
|
|
1492
1622
|
confirmText: "Delete this team? Members will lose any team-scoped access. This cannot be undone.",
|
|
1493
1623
|
successMessage: "Team deleted",
|
|
1494
1624
|
refreshAfter: true
|
|
@@ -1599,6 +1729,10 @@ var SysTeamMember = data.ObjectSchema.create({
|
|
|
1599
1729
|
locations: ["list_toolbar"],
|
|
1600
1730
|
type: "api",
|
|
1601
1731
|
target: "/api/v1/auth/organization/add-team-member",
|
|
1732
|
+
// Team membership lives under organizations — multi-org-only. Gate
|
|
1733
|
+
// both mutations so they vanish in single-org (mirrors
|
|
1734
|
+
// sys_organization.create_organization).
|
|
1735
|
+
visible: "features.multiOrgEnabled != false",
|
|
1602
1736
|
successMessage: "Team member added",
|
|
1603
1737
|
refreshAfter: true,
|
|
1604
1738
|
params: [
|
|
@@ -1619,6 +1753,7 @@ var SysTeamMember = data.ObjectSchema.create({
|
|
|
1619
1753
|
locations: ["list_item"],
|
|
1620
1754
|
type: "api",
|
|
1621
1755
|
target: "/api/v1/auth/organization/remove-team-member",
|
|
1756
|
+
visible: "features.multiOrgEnabled != false",
|
|
1622
1757
|
confirmText: "Remove this user from the team? They will lose any team-scoped access.",
|
|
1623
1758
|
successMessage: "Team member removed",
|
|
1624
1759
|
refreshAfter: true,
|
|
@@ -3158,6 +3293,224 @@ var SysJwks = data.ObjectSchema.create({
|
|
|
3158
3293
|
mru: false
|
|
3159
3294
|
}
|
|
3160
3295
|
});
|
|
3296
|
+
var SysSsoProvider = data.ObjectSchema.create({
|
|
3297
|
+
name: "sys_sso_provider",
|
|
3298
|
+
label: "SSO Provider",
|
|
3299
|
+
pluralLabel: "SSO Providers",
|
|
3300
|
+
icon: "shield-check",
|
|
3301
|
+
isSystem: true,
|
|
3302
|
+
managedBy: "better-auth",
|
|
3303
|
+
// ADR-0010 §3.7 — managed by better-auth; tenants may not edit schema.
|
|
3304
|
+
protection: {
|
|
3305
|
+
lock: "full",
|
|
3306
|
+
reason: "Identity table managed by better-auth (@better-auth/sso) \u2014 see ADR-0024.",
|
|
3307
|
+
docsUrl: "https://docs.objectstack.ai/adr/0010-metadata-protection"
|
|
3308
|
+
},
|
|
3309
|
+
description: "External SSO identity providers (OIDC / SAML) this environment federates login to",
|
|
3310
|
+
displayNameField: "provider_id",
|
|
3311
|
+
titleFormat: "{provider_id}",
|
|
3312
|
+
compactLayout: ["provider_id", "issuer", "domain"],
|
|
3313
|
+
// All mutations go through @better-auth/sso's endpoints under
|
|
3314
|
+
// /api/v1/auth/sso/* (register / delete-provider) rather than the generic
|
|
3315
|
+
// data layer, so server-side config validation + secret handling run.
|
|
3316
|
+
actions: [
|
|
3317
|
+
{
|
|
3318
|
+
name: "register_sso_provider",
|
|
3319
|
+
label: "Register SSO Provider",
|
|
3320
|
+
icon: "plus-circle",
|
|
3321
|
+
variant: "primary",
|
|
3322
|
+
mode: "create",
|
|
3323
|
+
locations: ["list_toolbar"],
|
|
3324
|
+
type: "api",
|
|
3325
|
+
method: "POST",
|
|
3326
|
+
target: "/api/v1/auth/sso/register",
|
|
3327
|
+
refreshAfter: true,
|
|
3328
|
+
params: [
|
|
3329
|
+
{ name: "providerId", label: "Provider ID", type: "text", required: true, helpText: 'Stable identifier, e.g. "okta" or "acme-entra".' },
|
|
3330
|
+
{ name: "issuer", label: "Issuer URL", type: "text", required: true, helpText: "IdP issuer / discovery base, e.g. https://acme.okta.com." },
|
|
3331
|
+
{ name: "domain", label: "Email Domain", type: "text", required: true, helpText: "Users with this email domain are routed to this IdP." },
|
|
3332
|
+
{ name: "clientId", label: "Client ID", type: "text", required: true },
|
|
3333
|
+
{ name: "clientSecret", label: "Client Secret", type: "text", required: true }
|
|
3334
|
+
]
|
|
3335
|
+
},
|
|
3336
|
+
{
|
|
3337
|
+
name: "delete_sso_provider",
|
|
3338
|
+
label: "Delete SSO Provider",
|
|
3339
|
+
icon: "trash-2",
|
|
3340
|
+
variant: "danger",
|
|
3341
|
+
mode: "delete",
|
|
3342
|
+
locations: ["list_item", "record_header"],
|
|
3343
|
+
type: "api",
|
|
3344
|
+
method: "POST",
|
|
3345
|
+
target: "/api/v1/auth/sso/delete-provider",
|
|
3346
|
+
confirmText: "Delete this SSO provider? Users from its domain will no longer be able to sign in through it.",
|
|
3347
|
+
successMessage: "SSO provider deleted",
|
|
3348
|
+
refreshAfter: true,
|
|
3349
|
+
params: [
|
|
3350
|
+
{ name: "providerId", field: "provider_id", defaultFromRow: true, required: true }
|
|
3351
|
+
]
|
|
3352
|
+
}
|
|
3353
|
+
],
|
|
3354
|
+
listViews: {
|
|
3355
|
+
all: {
|
|
3356
|
+
type: "grid",
|
|
3357
|
+
name: "all",
|
|
3358
|
+
label: "All",
|
|
3359
|
+
data: { provider: "object", object: "sys_sso_provider" },
|
|
3360
|
+
columns: ["provider_id", "issuer", "domain", "created_at"],
|
|
3361
|
+
sort: [{ field: "provider_id", order: "asc" }],
|
|
3362
|
+
pagination: { pageSize: 50 }
|
|
3363
|
+
}
|
|
3364
|
+
},
|
|
3365
|
+
fields: {
|
|
3366
|
+
id: data.Field.text({ label: "ID", required: true, readonly: true, group: "System" }),
|
|
3367
|
+
provider_id: data.Field.text({
|
|
3368
|
+
label: "Provider ID",
|
|
3369
|
+
required: true,
|
|
3370
|
+
searchable: true,
|
|
3371
|
+
maxLength: 255,
|
|
3372
|
+
description: "Stable provider identifier (unique within the environment)",
|
|
3373
|
+
group: "Identity"
|
|
3374
|
+
}),
|
|
3375
|
+
issuer: data.Field.text({
|
|
3376
|
+
label: "Issuer",
|
|
3377
|
+
required: true,
|
|
3378
|
+
maxLength: 2048,
|
|
3379
|
+
description: "IdP issuer URL",
|
|
3380
|
+
group: "Identity"
|
|
3381
|
+
}),
|
|
3382
|
+
domain: data.Field.text({
|
|
3383
|
+
label: "Email Domain",
|
|
3384
|
+
required: true,
|
|
3385
|
+
maxLength: 255,
|
|
3386
|
+
description: "Email domain routed to this IdP (e.g. acme.com)",
|
|
3387
|
+
group: "Identity"
|
|
3388
|
+
}),
|
|
3389
|
+
oidc_config: data.Field.textarea({
|
|
3390
|
+
label: "OIDC Config",
|
|
3391
|
+
required: false,
|
|
3392
|
+
description: "JSON: clientId, clientSecret, endpoints, scopes, mapping, pkce (managed by better-auth)",
|
|
3393
|
+
group: "Protocol"
|
|
3394
|
+
}),
|
|
3395
|
+
saml_config: data.Field.textarea({
|
|
3396
|
+
label: "SAML Config",
|
|
3397
|
+
required: false,
|
|
3398
|
+
description: "JSON: entryPoint, cert, identifierFormat, mapping (managed by better-auth)",
|
|
3399
|
+
group: "Protocol"
|
|
3400
|
+
}),
|
|
3401
|
+
user_id: data.Field.lookup("sys_user", {
|
|
3402
|
+
label: "Registered By",
|
|
3403
|
+
required: false,
|
|
3404
|
+
description: "User who registered this provider",
|
|
3405
|
+
group: "System"
|
|
3406
|
+
}),
|
|
3407
|
+
organization_id: data.Field.text({
|
|
3408
|
+
label: "Organization",
|
|
3409
|
+
required: false,
|
|
3410
|
+
maxLength: 255,
|
|
3411
|
+
description: "Organization scope (when org-scoped SSO is used)",
|
|
3412
|
+
group: "System"
|
|
3413
|
+
}),
|
|
3414
|
+
created_at: data.Field.datetime({ label: "Created At", defaultValue: "NOW()", readonly: true, group: "System" }),
|
|
3415
|
+
updated_at: data.Field.datetime({ label: "Updated At", defaultValue: "NOW()", readonly: true, group: "System" })
|
|
3416
|
+
},
|
|
3417
|
+
indexes: [
|
|
3418
|
+
{ fields: ["provider_id"], unique: true },
|
|
3419
|
+
{ fields: ["domain"] },
|
|
3420
|
+
{ fields: ["user_id"] }
|
|
3421
|
+
],
|
|
3422
|
+
enable: {
|
|
3423
|
+
trackHistory: true,
|
|
3424
|
+
searchable: true,
|
|
3425
|
+
apiEnabled: true,
|
|
3426
|
+
// Mutations go through /api/v1/auth/sso/* (register / delete-provider);
|
|
3427
|
+
// the generic data layer is read-only so sysadmins cannot bypass
|
|
3428
|
+
// server-side validation / secret handling.
|
|
3429
|
+
apiMethods: ["get", "list"],
|
|
3430
|
+
trash: false,
|
|
3431
|
+
mru: false
|
|
3432
|
+
}
|
|
3433
|
+
});
|
|
3434
|
+
var SysScimProvider = data.ObjectSchema.create({
|
|
3435
|
+
name: "sys_scim_provider",
|
|
3436
|
+
label: "SCIM Provider",
|
|
3437
|
+
pluralLabel: "SCIM Providers",
|
|
3438
|
+
icon: "users",
|
|
3439
|
+
isSystem: true,
|
|
3440
|
+
managedBy: "better-auth",
|
|
3441
|
+
// ADR-0010 §3.7 — managed by better-auth; tenants may not edit schema.
|
|
3442
|
+
protection: {
|
|
3443
|
+
lock: "full",
|
|
3444
|
+
reason: "Identity table managed by better-auth (@better-auth/scim) \u2014 see ADR-0071.",
|
|
3445
|
+
docsUrl: "https://docs.objectstack.ai/adr/0010-metadata-protection"
|
|
3446
|
+
},
|
|
3447
|
+
description: "SCIM 2.0 connections (bearer tokens) external IdPs use to provision/deprovision this environment's users",
|
|
3448
|
+
displayNameField: "provider_id",
|
|
3449
|
+
titleFormat: "{provider_id}",
|
|
3450
|
+
compactLayout: ["provider_id", "organization_id"],
|
|
3451
|
+
listViews: {
|
|
3452
|
+
all: {
|
|
3453
|
+
type: "grid",
|
|
3454
|
+
name: "all",
|
|
3455
|
+
label: "All",
|
|
3456
|
+
data: { provider: "object", object: "sys_scim_provider" },
|
|
3457
|
+
// scim_token is intentionally excluded — never surface the credential.
|
|
3458
|
+
columns: ["provider_id", "organization_id", "created_at"],
|
|
3459
|
+
sort: [{ field: "provider_id", order: "asc" }],
|
|
3460
|
+
pagination: { pageSize: 50 }
|
|
3461
|
+
}
|
|
3462
|
+
},
|
|
3463
|
+
fields: {
|
|
3464
|
+
id: data.Field.text({ label: "ID", required: true, readonly: true, group: "System" }),
|
|
3465
|
+
provider_id: data.Field.text({
|
|
3466
|
+
label: "Provider ID",
|
|
3467
|
+
required: true,
|
|
3468
|
+
searchable: true,
|
|
3469
|
+
maxLength: 255,
|
|
3470
|
+
description: 'Stable SCIM provider identifier (e.g. "okta-scim")',
|
|
3471
|
+
group: "Identity"
|
|
3472
|
+
}),
|
|
3473
|
+
scim_token: data.Field.text({
|
|
3474
|
+
label: "SCIM Token (hash)",
|
|
3475
|
+
required: false,
|
|
3476
|
+
readonly: true,
|
|
3477
|
+
maxLength: 1024,
|
|
3478
|
+
description: "Hashed bearer credential for this SCIM connection \u2014 the plaintext is shown once at generate-token. Sensitive; do not expose.",
|
|
3479
|
+
group: "Secret"
|
|
3480
|
+
}),
|
|
3481
|
+
organization_id: data.Field.text({
|
|
3482
|
+
label: "Organization",
|
|
3483
|
+
required: false,
|
|
3484
|
+
maxLength: 255,
|
|
3485
|
+
description: "Organization scope of this token (org-scoped tokens restrict provisioning to that org)",
|
|
3486
|
+
group: "System"
|
|
3487
|
+
}),
|
|
3488
|
+
user_id: data.Field.lookup("sys_user", {
|
|
3489
|
+
label: "Owned By",
|
|
3490
|
+
required: false,
|
|
3491
|
+
description: "User who generated this token (when provider-ownership is enabled)",
|
|
3492
|
+
group: "System"
|
|
3493
|
+
}),
|
|
3494
|
+
created_at: data.Field.datetime({ label: "Created At", defaultValue: "NOW()", readonly: true, group: "System" }),
|
|
3495
|
+
updated_at: data.Field.datetime({ label: "Updated At", defaultValue: "NOW()", readonly: true, group: "System" })
|
|
3496
|
+
},
|
|
3497
|
+
indexes: [
|
|
3498
|
+
{ fields: ["provider_id"], unique: true },
|
|
3499
|
+
{ fields: ["organization_id"] },
|
|
3500
|
+
{ fields: ["user_id"] }
|
|
3501
|
+
],
|
|
3502
|
+
enable: {
|
|
3503
|
+
trackHistory: true,
|
|
3504
|
+
searchable: false,
|
|
3505
|
+
apiEnabled: true,
|
|
3506
|
+
// Mutations + token issuance go through @better-auth/scim's endpoints
|
|
3507
|
+
// under /api/v1/auth/scim/*; the generic data layer is read-only so the
|
|
3508
|
+
// credential cannot be written/bypassed through it.
|
|
3509
|
+
apiMethods: ["list"],
|
|
3510
|
+
trash: false,
|
|
3511
|
+
mru: false
|
|
3512
|
+
}
|
|
3513
|
+
});
|
|
3161
3514
|
var SysNotification = data.ObjectSchema.create({
|
|
3162
3515
|
name: "sys_notification",
|
|
3163
3516
|
label: "Notification Event",
|
|
@@ -4613,7 +4966,7 @@ var SETUP_NAV_CONTRIBUTIONS = [
|
|
|
4613
4966
|
items: [
|
|
4614
4967
|
{ id: "nav_users", type: "object", label: "Users", objectName: "sys_user", icon: "user" },
|
|
4615
4968
|
{ id: "nav_business_units", type: "object", label: "Business Units", objectName: "sys_business_unit", icon: "building", requiresObject: "sys_business_unit" },
|
|
4616
|
-
{ id: "nav_teams", type: "object", label: "Teams", objectName: "sys_team", icon: "users-round" },
|
|
4969
|
+
{ id: "nav_teams", type: "object", label: "Teams", objectName: "sys_team", icon: "users-round", requiresService: "org-scoping" },
|
|
4617
4970
|
{ id: "nav_organizations", type: "object", label: "Organizations", objectName: "sys_organization", icon: "building-2", requiresService: "org-scoping" },
|
|
4618
4971
|
{ id: "nav_invitations", type: "object", label: "Invitations", objectName: "sys_invitation", icon: "mail", requiresService: "org-scoping" }
|
|
4619
4972
|
]
|
|
@@ -4641,6 +4994,16 @@ var SETUP_NAV_CONTRIBUTIONS = [
|
|
|
4641
4994
|
priority: BASE_PRIORITY,
|
|
4642
4995
|
items: [
|
|
4643
4996
|
{ id: "nav_settings_hub", type: "url", label: "All Settings", url: "/apps/setup/system/settings", icon: "settings-2", requiredPermissions: ["manage_platform_settings"] },
|
|
4997
|
+
// Workspace identity first — Localization (order 2) and Company (order 3)
|
|
4998
|
+
// are the lowest-`order` settings manifests and the first thing a new
|
|
4999
|
+
// company admin configures. They ship as `service-settings` manifests
|
|
5000
|
+
// (tenant scope, read=`setup.access`) but were never pinned here, so they
|
|
5001
|
+
// were reachable only by drilling into the "All Settings" hub. Mainstream
|
|
5002
|
+
// admin consoles (Salesforce "Company Information", ServiceNow) surface
|
|
5003
|
+
// both directly. No `requiredPermissions` — matches Branding (read perm is
|
|
5004
|
+
// the app's base `setup.access`).
|
|
5005
|
+
{ id: "nav_settings_localization", type: "url", label: "Localization", url: "/apps/setup/system/settings/localization", icon: "globe" },
|
|
5006
|
+
{ id: "nav_settings_company", type: "url", label: "Company", url: "/apps/setup/system/settings/company", icon: "building-2" },
|
|
4644
5007
|
{ id: "nav_settings_branding", type: "url", label: "Branding", url: "/apps/setup/system/settings/branding", icon: "palette" },
|
|
4645
5008
|
{ id: "nav_settings_auth", type: "url", label: "Authentication", url: "/apps/setup/system/settings/auth", icon: "lock-keyhole", requiredPermissions: ["manage_platform_settings"] },
|
|
4646
5009
|
{ id: "nav_settings_mail", type: "url", label: "Email", url: "/apps/setup/system/settings/mail", icon: "mail", requiredPermissions: ["manage_platform_settings"] },
|
|
@@ -4668,8 +5031,12 @@ var SETUP_NAV_CONTRIBUTIONS = [
|
|
|
4668
5031
|
items: [
|
|
4669
5032
|
{ id: "nav_oauth_apps", type: "object", label: "OAuth Applications", objectName: "sys_oauth_application", icon: "app-window" },
|
|
4670
5033
|
{ id: "nav_jwks", type: "object", label: "Signing Keys (JWKS)", objectName: "sys_jwks", icon: "key-round" },
|
|
4671
|
-
|
|
4672
|
-
|
|
5034
|
+
// `sys_verification` (email/phone tokens) and `sys_device_code` (OAuth
|
|
5035
|
+
// device-grant codes) deliberately omit `list` from their `apiMethods`
|
|
5036
|
+
// (sensitive, ephemeral secrets — not browsable), so an object/list-view
|
|
5037
|
+
// nav entry for them can only ever render "failed to load". They're
|
|
5038
|
+
// reachable by id (get) when needed; no browse menu. (Re-adding requires
|
|
5039
|
+
// enabling `list` on the object — a security decision.)
|
|
4673
5040
|
{ id: "nav_accounts", type: "object", label: "Identity Links", objectName: "sys_account", icon: "link-2" },
|
|
4674
5041
|
{ id: "nav_user_preferences", type: "object", label: "User Preferences", objectName: "sys_user_preference", icon: "sliders" }
|
|
4675
5042
|
]
|
|
@@ -5055,7 +5422,13 @@ var ACCOUNT_APP = {
|
|
|
5055
5422
|
objectName: "sys_member",
|
|
5056
5423
|
viewName: "mine",
|
|
5057
5424
|
icon: "building-2",
|
|
5058
|
-
|
|
5425
|
+
// Membership is a multi-org concept: in single-org mode the
|
|
5426
|
+
// `mine` view is always empty (no sys_organization rows, no
|
|
5427
|
+
// auto-stamped memberships). Gate on the org-scoping service so
|
|
5428
|
+
// this entry disappears entirely — matching Organizations/
|
|
5429
|
+
// Invitations in setup-nav. `requiresObject: 'sys_member'` was
|
|
5430
|
+
// the wrong gate (the system object is always registered).
|
|
5431
|
+
requiresService: "org-scoping"
|
|
5059
5432
|
}
|
|
5060
5433
|
]
|
|
5061
5434
|
},
|
|
@@ -5148,6 +5521,12 @@ var SystemOverviewDashboard = ui.Dashboard.create({
|
|
|
5148
5521
|
values: ["org_count"],
|
|
5149
5522
|
title: "Organizations",
|
|
5150
5523
|
type: "metric",
|
|
5524
|
+
// Organizations only exist under multi-tenant org-scoping. In a
|
|
5525
|
+
// single-tenant runtime the count is always 0 and the matching
|
|
5526
|
+
// nav entries (nav_organizations / nav_invitations) are hidden via
|
|
5527
|
+
// `requiresService: 'org-scoping'` — gate this KPI the same way so the
|
|
5528
|
+
// overview doesn't dangle a metric the admin can't act on.
|
|
5529
|
+
requiresService: "org-scoping",
|
|
5151
5530
|
layout: { x: 3, y: 0, w: 3, h: 2 },
|
|
5152
5531
|
colorVariant: "orange",
|
|
5153
5532
|
description: "Total organizations on the platform"
|
|
@@ -10663,6 +11042,7 @@ var zhCN = {
|
|
|
10663
11042
|
group_apps: { label: "\u5E94\u7528" },
|
|
10664
11043
|
nav_marketplace_browse: { label: "\u6D4F\u89C8\u5E94\u7528\u5E02\u573A" },
|
|
10665
11044
|
nav_marketplace_installed: { label: "\u5DF2\u5B89\u88C5\u5E94\u7528" },
|
|
11045
|
+
nav_cloud_connection: { label: "\u4E91\u8FDE\u63A5" },
|
|
10666
11046
|
group_people_org: { label: "\u4EBA\u5458\u4E0E\u7EC4\u7EC7" },
|
|
10667
11047
|
group_access_control: { label: "\u8BBF\u95EE\u63A7\u5236" },
|
|
10668
11048
|
group_approvals: { label: "\u5BA1\u6279" },
|
|
@@ -10677,6 +11057,7 @@ var zhCN = {
|
|
|
10677
11057
|
nav_organizations: { label: "\u7EC4\u7EC7" },
|
|
10678
11058
|
nav_invitations: { label: "\u9080\u8BF7" },
|
|
10679
11059
|
nav_roles: { label: "\u89D2\u8272" },
|
|
11060
|
+
nav_capabilities: { label: "\u80FD\u529B" },
|
|
10680
11061
|
nav_permission_sets: { label: "\u6743\u9650\u96C6" },
|
|
10681
11062
|
nav_sharing_rules: { label: "\u5171\u4EAB\u89C4\u5219" },
|
|
10682
11063
|
nav_record_shares: { label: "\u8BB0\u5F55\u5171\u4EAB" },
|
|
@@ -10685,6 +11066,8 @@ var zhCN = {
|
|
|
10685
11066
|
nav_approval_requests: { label: "\u5BA1\u6279\u7533\u8BF7" },
|
|
10686
11067
|
nav_approval_actions: { label: "\u5BA1\u6279\u5386\u53F2" },
|
|
10687
11068
|
nav_settings_hub: { label: "\u5168\u90E8\u8BBE\u7F6E" },
|
|
11069
|
+
nav_settings_localization: { label: "\u672C\u5730\u5316" },
|
|
11070
|
+
nav_settings_company: { label: "\u516C\u53F8\u4FE1\u606F" },
|
|
10688
11071
|
nav_settings_mail: { label: "\u90AE\u4EF6" },
|
|
10689
11072
|
nav_settings_branding: { label: "\u54C1\u724C" },
|
|
10690
11073
|
nav_settings_auth: { label: "\u8BA4\u8BC1" },
|
|
@@ -10698,10 +11081,9 @@ var zhCN = {
|
|
|
10698
11081
|
nav_sessions: { label: "\u4F1A\u8BDD" },
|
|
10699
11082
|
nav_audit_logs: { label: "\u5BA1\u8BA1\u65E5\u5FD7" },
|
|
10700
11083
|
nav_notifications: { label: "\u901A\u77E5" },
|
|
11084
|
+
nav_datasources: { label: "\u6570\u636E\u6E90" },
|
|
10701
11085
|
nav_oauth_apps: { label: "OAuth \u5E94\u7528" },
|
|
10702
11086
|
nav_jwks: { label: "\u7B7E\u540D\u5BC6\u94A5 (JWKS)" },
|
|
10703
|
-
nav_verifications: { label: "\u9A8C\u8BC1\u8BB0\u5F55" },
|
|
10704
|
-
nav_device_codes: { label: "\u8BBE\u5907\u4EE3\u7801" },
|
|
10705
11087
|
nav_accounts: { label: "\u8EAB\u4EFD\u94FE\u63A5" },
|
|
10706
11088
|
nav_user_preferences: { label: "\u7528\u6237\u504F\u597D" },
|
|
10707
11089
|
nav_metadata: { label: "\u5168\u90E8\u5143\u6570\u636E" }
|
|
@@ -23207,10 +23589,12 @@ exports.SysOrganization = SysOrganization;
|
|
|
23207
23589
|
exports.SysOrganizationDetailPage = SysOrganizationDetailPage;
|
|
23208
23590
|
exports.SysReportSchedule = SysReportSchedule;
|
|
23209
23591
|
exports.SysSavedReport = SysSavedReport;
|
|
23592
|
+
exports.SysScimProvider = SysScimProvider;
|
|
23210
23593
|
exports.SysSecret = SysSecret;
|
|
23211
23594
|
exports.SysSession = SysSession;
|
|
23212
23595
|
exports.SysSetting = SysSetting;
|
|
23213
23596
|
exports.SysSettingAudit = SysSettingAudit;
|
|
23597
|
+
exports.SysSsoProvider = SysSsoProvider;
|
|
23214
23598
|
exports.SysTeam = SysTeam;
|
|
23215
23599
|
exports.SysTeamMember = SysTeamMember;
|
|
23216
23600
|
exports.SysTwoFactor = SysTwoFactor;
|