@open-mercato/enterprise 0.6.6-develop.6465.1.019f0fb26f → 0.6.6-develop.6472.1.1673e7e66b
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/modules/record_locks/subscribers/conflict-detected-notification.js +3 -1
- package/dist/modules/record_locks/subscribers/conflict-detected-notification.js.map +2 -2
- package/dist/modules/record_locks/subscribers/conflict-resolved-notification.js +3 -1
- package/dist/modules/record_locks/subscribers/conflict-resolved-notification.js.map +2 -2
- package/dist/modules/record_locks/subscribers/lock-contended-notification.js +3 -1
- package/dist/modules/record_locks/subscribers/lock-contended-notification.js.map +2 -2
- package/dist/modules/record_locks/subscribers/lock-force-released-notification.js +3 -1
- package/dist/modules/record_locks/subscribers/lock-force-released-notification.js.map +2 -2
- package/dist/modules/record_locks/widgets/injection/record-locking/widget.client.js +4 -2
- package/dist/modules/record_locks/widgets/injection/record-locking/widget.client.js.map +2 -2
- package/dist/modules/security/api/enforcement/_shared.js +3 -1
- package/dist/modules/security/api/enforcement/_shared.js.map +2 -2
- package/dist/modules/security/api/mfa/_shared.js +3 -1
- package/dist/modules/security/api/mfa/_shared.js.map +2 -2
- package/dist/modules/security/api/profile/password/route.js +3 -1
- package/dist/modules/security/api/profile/password/route.js.map +2 -2
- package/dist/modules/security/api/sudo/_shared.js +3 -1
- package/dist/modules/security/api/sudo/_shared.js.map +2 -2
- package/dist/modules/security/api/users/_shared.js +3 -1
- package/dist/modules/security/api/users/_shared.js.map +2 -2
- package/dist/modules/sso/api/callback/oidc/route.js +5 -3
- package/dist/modules/sso/api/callback/oidc/route.js.map +2 -2
- package/dist/modules/sso/api/error-handler.js +4 -2
- package/dist/modules/sso/api/error-handler.js.map +2 -2
- package/dist/modules/sso/api/hrd/route.js +3 -1
- package/dist/modules/sso/api/hrd/route.js.map +2 -2
- package/dist/modules/sso/api/initiate/route.js +4 -2
- package/dist/modules/sso/api/initiate/route.js.map +2 -2
- package/dist/modules/sso/backend/sso/config/[id]/page.js +2 -2
- package/dist/modules/sso/backend/sso/config/[id]/page.js.map +2 -2
- package/dist/modules/sso/i18n/de.json +2 -2
- package/dist/modules/sso/i18n/en.json +2 -2
- package/dist/modules/sso/i18n/es.json +2 -2
- package/dist/modules/sso/i18n/pl.json +2 -2
- package/dist/modules/sso/services/accountLinkingService.js +9 -46
- package/dist/modules/sso/services/accountLinkingService.js.map +2 -2
- package/dist/modules/sso/services/ssoConfigService.js +9 -7
- package/dist/modules/sso/services/ssoConfigService.js.map +2 -2
- package/dist/modules/sso/services/ssoService.js +4 -2
- package/dist/modules/sso/services/ssoService.js.map +2 -2
- package/dist/modules/system_status_overlays/subscribers/application-bootstrap-enterprise-warning.js +4 -2
- package/dist/modules/system_status_overlays/subscribers/application-bootstrap-enterprise-warning.js.map +2 -2
- package/package.json +5 -5
- package/src/modules/record_locks/subscribers/conflict-detected-notification.ts +4 -1
- package/src/modules/record_locks/subscribers/conflict-resolved-notification.ts +4 -1
- package/src/modules/record_locks/subscribers/lock-contended-notification.ts +4 -1
- package/src/modules/record_locks/subscribers/lock-force-released-notification.ts +4 -1
- package/src/modules/record_locks/widgets/injection/record-locking/widget.client.tsx +5 -2
- package/src/modules/security/api/enforcement/_shared.ts +4 -1
- package/src/modules/security/api/mfa/_shared.ts +4 -1
- package/src/modules/security/api/profile/password/route.ts +4 -1
- package/src/modules/security/api/sudo/_shared.ts +4 -1
- package/src/modules/security/api/users/_shared.ts +4 -1
- package/src/modules/sso/api/callback/oidc/route.ts +6 -3
- package/src/modules/sso/api/error-handler.ts +5 -2
- package/src/modules/sso/api/hrd/route.ts +4 -1
- package/src/modules/sso/api/initiate/route.ts +5 -2
- package/src/modules/sso/backend/sso/config/[id]/page.tsx +2 -2
- package/src/modules/sso/i18n/de.json +2 -2
- package/src/modules/sso/i18n/en.json +2 -2
- package/src/modules/sso/i18n/es.json +2 -2
- package/src/modules/sso/i18n/pl.json +2 -2
- package/src/modules/sso/services/accountLinkingService.ts +10 -52
- package/src/modules/sso/services/ssoConfigService.ts +10 -7
- package/src/modules/sso/services/ssoService.ts +5 -2
- package/src/modules/system_status_overlays/subscribers/application-bootstrap-enterprise-warning.ts +6 -2
|
@@ -5,6 +5,9 @@ import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
|
|
|
5
5
|
import { SsoService } from '../../services/ssoService'
|
|
6
6
|
import { ssoInitiateSchema } from '../../data/validators'
|
|
7
7
|
import { emitSsoEvent } from '../../events'
|
|
8
|
+
import { createLogger } from '@open-mercato/shared/lib/logger'
|
|
9
|
+
|
|
10
|
+
const logger = createLogger('sso').child({ component: 'initiate' })
|
|
8
11
|
|
|
9
12
|
export const metadata = {
|
|
10
13
|
GET: { requireAuth: false },
|
|
@@ -50,10 +53,10 @@ export async function GET(req: Request) {
|
|
|
50
53
|
})
|
|
51
54
|
return res
|
|
52
55
|
} catch (err) {
|
|
53
|
-
|
|
56
|
+
logger.error('SSO initiate error', { err })
|
|
54
57
|
void emitSsoEvent('sso.login.failed', {
|
|
55
58
|
reason: err instanceof Error ? err.message : 'initiate_failed',
|
|
56
|
-
}).catch((
|
|
59
|
+
}).catch((eventError) => logger.error('SSO event emit failed', { err: eventError }))
|
|
57
60
|
return NextResponse.redirect(toAbsoluteUrl(req, '/login?error=sso_failed'))
|
|
58
61
|
}
|
|
59
62
|
}
|
|
@@ -647,7 +647,7 @@ function RoleMappingsTab({
|
|
|
647
647
|
return (
|
|
648
648
|
<div>
|
|
649
649
|
<p className="text-sm text-muted-foreground mb-4">
|
|
650
|
-
{t('sso.admin.roles.description', 'Map IdP app role names to local roles.
|
|
650
|
+
{t('sso.admin.roles.description', 'Map IdP app role names to local roles. Only explicitly mapped IdP roles grant local roles; on each SSO login, SSO-sourced roles are synced while manually-assigned roles are preserved.')}
|
|
651
651
|
</p>
|
|
652
652
|
<div className="flex items-end gap-2 mb-4">
|
|
653
653
|
<div className="flex-1">
|
|
@@ -696,7 +696,7 @@ function RoleMappingsTab({
|
|
|
696
696
|
</div>
|
|
697
697
|
) : (
|
|
698
698
|
<p className="text-sm text-muted-foreground py-4 text-center mb-4">
|
|
699
|
-
{t('sso.admin.roles.empty', 'No role mappings configured. IdP role
|
|
699
|
+
{t('sso.admin.roles.empty', 'No role mappings configured. Users will not receive SSO-sourced roles until an IdP role is explicitly mapped to a local role.')}
|
|
700
700
|
</p>
|
|
701
701
|
)}
|
|
702
702
|
|
|
@@ -72,8 +72,8 @@
|
|
|
72
72
|
"sso.admin.field.secretRequired": "Client-Geheimnis eingeben",
|
|
73
73
|
"sso.admin.field.secretSet": "Client-Geheimnis ist konfiguriert",
|
|
74
74
|
"sso.admin.new": "Neue SSO-Konfiguration",
|
|
75
|
-
"sso.admin.roles.description": "Ordnen Sie IdP-App-Rollennamen lokalen Rollen zu.
|
|
76
|
-
"sso.admin.roles.empty": "Keine Rollenzuordnungen konfiguriert. IdP-
|
|
75
|
+
"sso.admin.roles.description": "Ordnen Sie IdP-App-Rollennamen lokalen Rollen zu. Nur ausdrücklich zugeordnete IdP-Rollen vergeben lokale Rollen; bei jeder SSO-Anmeldung werden SSO-basierte Rollen synchronisiert, während manuell zugewiesene Rollen erhalten bleiben.",
|
|
76
|
+
"sso.admin.roles.empty": "Keine Rollenzuordnungen konfiguriert. Benutzer erhalten keine SSO-basierten Rollen, bis eine IdP-Rolle ausdrücklich einer lokalen Rolle zugeordnet ist.",
|
|
77
77
|
"sso.admin.roles.error.duplicate": "Diese IdP-Rolle ist bereits zugeordnet",
|
|
78
78
|
"sso.admin.roles.error.emptyIdpRole": "IdP-Rollenname ist erforderlich",
|
|
79
79
|
"sso.admin.roles.error.emptyLocalRole": "Wählen Sie eine lokale Rolle",
|
|
@@ -72,8 +72,8 @@
|
|
|
72
72
|
"sso.admin.field.secretRequired": "Enter client secret",
|
|
73
73
|
"sso.admin.field.secretSet": "Client secret is configured",
|
|
74
74
|
"sso.admin.new": "New SSO Config",
|
|
75
|
-
"sso.admin.roles.description": "Map IdP app role names to local roles.
|
|
76
|
-
"sso.admin.roles.empty": "No role mappings configured. IdP role
|
|
75
|
+
"sso.admin.roles.description": "Map IdP app role names to local roles. Only explicitly mapped IdP roles grant local roles; on each SSO login, SSO-sourced roles are synced while manually-assigned roles are preserved.",
|
|
76
|
+
"sso.admin.roles.empty": "No role mappings configured. Users will not receive SSO-sourced roles until an IdP role is explicitly mapped to a local role.",
|
|
77
77
|
"sso.admin.roles.error.duplicate": "This IdP role is already mapped",
|
|
78
78
|
"sso.admin.roles.error.emptyIdpRole": "IdP role name is required",
|
|
79
79
|
"sso.admin.roles.error.emptyLocalRole": "Select a local role",
|
|
@@ -72,8 +72,8 @@
|
|
|
72
72
|
"sso.admin.field.secretRequired": "Ingrese el secreto de cliente",
|
|
73
73
|
"sso.admin.field.secretSet": "El secreto de cliente está configurado",
|
|
74
74
|
"sso.admin.new": "Nueva configuración SSO",
|
|
75
|
-
"sso.admin.roles.description": "Asigne nombres de roles de aplicación IdP a roles locales.
|
|
76
|
-
"sso.admin.roles.empty": "No hay asignaciones de roles configuradas. Los
|
|
75
|
+
"sso.admin.roles.description": "Asigne nombres de roles de aplicación IdP a roles locales. Solo los roles de IdP asignados explícitamente conceden roles locales; en cada inicio de sesión SSO, los roles de origen SSO se sincronizan mientras se conservan los roles asignados manualmente.",
|
|
76
|
+
"sso.admin.roles.empty": "No hay asignaciones de roles configuradas. Los usuarios no recibirán roles de origen SSO hasta que un rol de IdP se asigne explícitamente a un rol local.",
|
|
77
77
|
"sso.admin.roles.error.duplicate": "Este rol de IdP ya está asignado",
|
|
78
78
|
"sso.admin.roles.error.emptyIdpRole": "El nombre del rol de IdP es obligatorio",
|
|
79
79
|
"sso.admin.roles.error.emptyLocalRole": "Seleccione un rol local",
|
|
@@ -72,8 +72,8 @@
|
|
|
72
72
|
"sso.admin.field.secretRequired": "Wprowadź client secret",
|
|
73
73
|
"sso.admin.field.secretSet": "Client secret jest skonfigurowany",
|
|
74
74
|
"sso.admin.new": "Nowa konfiguracja SSO",
|
|
75
|
-
"sso.admin.roles.description": "Mapuj nazwy ról IdP na lokalne role.
|
|
76
|
-
"sso.admin.roles.empty": "Brak skonfigurowanych mapowań ról.
|
|
75
|
+
"sso.admin.roles.description": "Mapuj nazwy ról IdP na lokalne role. Tylko jawnie zmapowane role IdP nadają lokalne role; przy każdym logowaniu SSO role źródłowe SSO są synchronizowane, a role przypisane ręcznie pozostają zachowane.",
|
|
76
|
+
"sso.admin.roles.empty": "Brak skonfigurowanych mapowań ról. Użytkownicy nie otrzymają ról źródłowych SSO, dopóki rola IdP nie zostanie jawnie zmapowana na lokalną rolę.",
|
|
77
77
|
"sso.admin.roles.error.duplicate": "Ta rola IdP jest już zmapowana",
|
|
78
78
|
"sso.admin.roles.error.emptyIdpRole": "Nazwa roli IdP jest wymagana",
|
|
79
79
|
"sso.admin.roles.error.emptyLocalRole": "Wybierz lokalną rolę",
|
|
@@ -6,6 +6,9 @@ import { SsoConfig, SsoIdentity, SsoRoleGrant, ScimToken } from '../data/entitie
|
|
|
6
6
|
import { emitSsoEvent } from '../events'
|
|
7
7
|
import { EmailNotVerifiedError } from '../lib/errors'
|
|
8
8
|
import type { SsoIdentityPayload } from '../lib/types'
|
|
9
|
+
import { createLogger } from '@open-mercato/shared/lib/logger'
|
|
10
|
+
|
|
11
|
+
const logger = createLogger('sso').child({ component: 'account-linking' })
|
|
9
12
|
|
|
10
13
|
export class AccountLinkingService {
|
|
11
14
|
constructor(private em: EntityManager) {}
|
|
@@ -127,7 +130,7 @@ export class AccountLinkingService {
|
|
|
127
130
|
id: identity.id,
|
|
128
131
|
tenantId,
|
|
129
132
|
organizationId: config.organizationId,
|
|
130
|
-
}).catch((
|
|
133
|
+
}).catch((eventError) => logger.error('SSO event emit failed', { err: eventError }))
|
|
131
134
|
|
|
132
135
|
return { user, identity }
|
|
133
136
|
}
|
|
@@ -174,7 +177,7 @@ export class AccountLinkingService {
|
|
|
174
177
|
id: identity.id,
|
|
175
178
|
tenantId,
|
|
176
179
|
organizationId: config.organizationId,
|
|
177
|
-
}).catch((
|
|
180
|
+
}).catch((eventError) => logger.error('SSO event emit failed', { err: eventError }))
|
|
178
181
|
|
|
179
182
|
return { user, identity }
|
|
180
183
|
})
|
|
@@ -311,73 +314,28 @@ function resolveRoleNamesFromIdpGroups(
|
|
|
311
314
|
|
|
312
315
|
for (const group of normalizedGroups) {
|
|
313
316
|
const mapped = mergedMappings.get(group)
|
|
314
|
-
if (mapped?.length)
|
|
315
|
-
for (const role of mapped) roleNames.add(role)
|
|
316
|
-
continue
|
|
317
|
-
}
|
|
317
|
+
if (!mapped?.length) continue
|
|
318
318
|
|
|
319
|
-
roleNames.add(
|
|
320
|
-
const segmented = group.split(/[\\/:]/).map((part) => normalizeToken(part)).filter((part): part is string => part !== null)
|
|
321
|
-
for (const candidate of segmented) {
|
|
322
|
-
roleNames.add(candidate)
|
|
323
|
-
}
|
|
319
|
+
for (const role of mapped) roleNames.add(role)
|
|
324
320
|
}
|
|
325
321
|
|
|
326
322
|
return Array.from(roleNames)
|
|
327
323
|
}
|
|
328
324
|
|
|
329
325
|
function loadMergedMappings(configMappings?: Record<string, string>): Map<string, string[]> {
|
|
330
|
-
const
|
|
326
|
+
const mappings = new Map<string, string[]>()
|
|
331
327
|
|
|
332
|
-
// Per-config mappings take precedence over env var
|
|
333
328
|
if (configMappings && Object.keys(configMappings).length > 0) {
|
|
334
329
|
for (const [group, roleName] of Object.entries(configMappings)) {
|
|
335
330
|
const normalizedGroup = normalizeToken(group)
|
|
336
331
|
if (!normalizedGroup) continue
|
|
337
332
|
const normalizedRole = normalizeToken(roleName)
|
|
338
333
|
if (!normalizedRole) continue
|
|
339
|
-
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
return envMappings
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
function loadGroupRoleMappingsFromEnv(): Map<string, string[]> {
|
|
347
|
-
const raw = process.env.SSO_GROUP_ROLE_MAP
|
|
348
|
-
if (!raw) return new Map()
|
|
349
|
-
|
|
350
|
-
try {
|
|
351
|
-
const parsed = JSON.parse(raw) as Record<string, unknown>
|
|
352
|
-
const out = new Map<string, string[]>()
|
|
353
|
-
for (const [group, roleValue] of Object.entries(parsed)) {
|
|
354
|
-
const normalizedGroup = normalizeToken(group)
|
|
355
|
-
if (!normalizedGroup) continue
|
|
356
|
-
const roles = normalizeRoleList(roleValue)
|
|
357
|
-
if (roles.length > 0) out.set(normalizedGroup, roles)
|
|
358
|
-
}
|
|
359
|
-
return out
|
|
360
|
-
} catch {
|
|
361
|
-
return new Map()
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
function normalizeRoleList(value: unknown): string[] {
|
|
366
|
-
if (typeof value === 'string') {
|
|
367
|
-
const token = normalizeToken(value)
|
|
368
|
-
return token ? [token] : []
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
if (Array.isArray(value)) {
|
|
372
|
-
const out = new Set<string>()
|
|
373
|
-
for (const entry of value) {
|
|
374
|
-
const token = normalizeToken(entry)
|
|
375
|
-
if (token) out.add(token)
|
|
334
|
+
mappings.set(normalizedGroup, [normalizedRole])
|
|
376
335
|
}
|
|
377
|
-
return Array.from(out)
|
|
378
336
|
}
|
|
379
337
|
|
|
380
|
-
return
|
|
338
|
+
return mappings
|
|
381
339
|
}
|
|
382
340
|
|
|
383
341
|
function normalizeToken(value: unknown): string | null {
|
|
@@ -8,6 +8,9 @@ import type { SsoConfigAdminCreateInput, SsoConfigAdminUpdateInput, SsoConfigLis
|
|
|
8
8
|
import { emitSsoEvent } from '../events'
|
|
9
9
|
import { validateDomain, normalizeDomain, uniqueDomains, checkDomainLimit } from '../lib/domains'
|
|
10
10
|
import type { SsoProviderRegistry } from '../lib/registry'
|
|
11
|
+
import { createLogger } from '@open-mercato/shared/lib/logger'
|
|
12
|
+
|
|
13
|
+
const logger = createLogger('sso').child({ component: 'config' })
|
|
11
14
|
|
|
12
15
|
export interface SsoAdminScope {
|
|
13
16
|
isSuperAdmin: boolean
|
|
@@ -138,7 +141,7 @@ export class SsoConfigService {
|
|
|
138
141
|
id: config.id,
|
|
139
142
|
tenantId: config.tenantId,
|
|
140
143
|
organizationId: config.organizationId,
|
|
141
|
-
}).catch((
|
|
144
|
+
}).catch((eventError) => logger.error('SSO event emit failed', { err: eventError }))
|
|
142
145
|
|
|
143
146
|
return this.toPublic(config)
|
|
144
147
|
}
|
|
@@ -178,7 +181,7 @@ export class SsoConfigService {
|
|
|
178
181
|
id: config.id,
|
|
179
182
|
tenantId: config.tenantId,
|
|
180
183
|
organizationId: config.organizationId,
|
|
181
|
-
}).catch((
|
|
184
|
+
}).catch((eventError) => logger.error('SSO event emit failed', { err: eventError }))
|
|
182
185
|
|
|
183
186
|
return this.toPublic(config)
|
|
184
187
|
}
|
|
@@ -197,7 +200,7 @@ export class SsoConfigService {
|
|
|
197
200
|
id: config.id,
|
|
198
201
|
tenantId: config.tenantId,
|
|
199
202
|
organizationId: config.organizationId,
|
|
200
|
-
}).catch((
|
|
203
|
+
}).catch((eventError) => logger.error('SSO event emit failed', { err: eventError }))
|
|
201
204
|
}
|
|
202
205
|
|
|
203
206
|
async activate(scope: SsoAdminScope, id: string, active: boolean): Promise<SsoConfigPublic> {
|
|
@@ -229,13 +232,13 @@ export class SsoConfigService {
|
|
|
229
232
|
id: config.id,
|
|
230
233
|
tenantId: config.tenantId,
|
|
231
234
|
organizationId: config.organizationId,
|
|
232
|
-
}).catch((
|
|
235
|
+
}).catch((eventError) => logger.error('SSO event emit failed', { err: eventError }))
|
|
233
236
|
} else if (!active && wasActive) {
|
|
234
237
|
void emitSsoEvent('sso.config.deactivated', {
|
|
235
238
|
id: config.id,
|
|
236
239
|
tenantId: config.tenantId,
|
|
237
240
|
organizationId: config.organizationId,
|
|
238
|
-
}).catch((
|
|
241
|
+
}).catch((eventError) => logger.error('SSO event emit failed', { err: eventError }))
|
|
239
242
|
}
|
|
240
243
|
|
|
241
244
|
return this.toPublic(config)
|
|
@@ -276,7 +279,7 @@ export class SsoConfigService {
|
|
|
276
279
|
tenantId: config.tenantId,
|
|
277
280
|
organizationId: config.organizationId,
|
|
278
281
|
domain: normalized,
|
|
279
|
-
}).catch((
|
|
282
|
+
}).catch((eventError) => logger.error('SSO event emit failed', { err: eventError }))
|
|
280
283
|
|
|
281
284
|
return this.toPublic(config)
|
|
282
285
|
})
|
|
@@ -294,7 +297,7 @@ export class SsoConfigService {
|
|
|
294
297
|
tenantId: config.tenantId,
|
|
295
298
|
organizationId: config.organizationId,
|
|
296
299
|
domain: normalized,
|
|
297
|
-
}).catch((
|
|
300
|
+
}).catch((eventError) => logger.error('SSO event emit failed', { err: eventError }))
|
|
298
301
|
|
|
299
302
|
return this.toPublic(config)
|
|
300
303
|
}
|
|
@@ -10,6 +10,9 @@ import type { AccountLinkingService } from './accountLinkingService'
|
|
|
10
10
|
import { encryptStateCookie, decryptStateCookie, createFlowState } from '../lib/state-cookie'
|
|
11
11
|
import { emitSsoEvent } from '../events'
|
|
12
12
|
import type { TenantDataEncryptionService } from '@open-mercato/shared/lib/encryption/tenantDataEncryptionService'
|
|
13
|
+
import { createLogger } from '@open-mercato/shared/lib/logger'
|
|
14
|
+
|
|
15
|
+
const logger = createLogger('sso').child({ component: 'service' })
|
|
13
16
|
|
|
14
17
|
export class SsoService {
|
|
15
18
|
constructor(
|
|
@@ -60,7 +63,7 @@ export class SsoService {
|
|
|
60
63
|
void emitSsoEvent('sso.login.initiated', {
|
|
61
64
|
tenantId: config.tenantId,
|
|
62
65
|
organizationId: config.organizationId,
|
|
63
|
-
}).catch((
|
|
66
|
+
}).catch((eventError) => logger.error('SSO event emit failed', { err: eventError }))
|
|
64
67
|
|
|
65
68
|
const authUrl = await provider.buildAuthUrl(config, {
|
|
66
69
|
state: state.state,
|
|
@@ -144,7 +147,7 @@ export class SsoService {
|
|
|
144
147
|
id: String(user.id),
|
|
145
148
|
tenantId: config.tenantId,
|
|
146
149
|
organizationId: config.organizationId,
|
|
147
|
-
}).catch((
|
|
150
|
+
}).catch((eventError) => logger.error('SSO event emit failed', { err: eventError }))
|
|
148
151
|
|
|
149
152
|
return {
|
|
150
153
|
token,
|
package/src/modules/system_status_overlays/subscribers/application-bootstrap-enterprise-warning.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { createLogger } from '@open-mercato/shared/lib/logger'
|
|
2
|
+
|
|
3
|
+
const logger = createLogger('system_status_overlays')
|
|
4
|
+
|
|
1
5
|
const APP_BOOTSTRAP_EVENT = 'application.bootstrap.completed'
|
|
2
6
|
const ENTERPRISE_WARNING_GLOBAL_KEY = '__openMercatoEnterpriseLicenseWarningShown__'
|
|
3
7
|
|
|
@@ -11,7 +15,7 @@ export default async function handle() {
|
|
|
11
15
|
if ((globalThis as Record<string, unknown>)[ENTERPRISE_WARNING_GLOBAL_KEY] === true) return
|
|
12
16
|
|
|
13
17
|
;(globalThis as Record<string, unknown>)[ENTERPRISE_WARNING_GLOBAL_KEY] = true
|
|
14
|
-
|
|
15
|
-
'
|
|
18
|
+
logger.warn(
|
|
19
|
+
'Enterprise modules are enabled. Developer preview is free, but production usage requires a commercial enterprise license. See: https://github.com/open-mercato/open-mercato/blob/main/packages/enterprise/README.md',
|
|
16
20
|
)
|
|
17
21
|
}
|