From bfbb2f160b285a576775f71ff9bcd99606fdd5f7 Mon Sep 17 00:00:00 2001 From: camillerev Date: Mon, 20 Jan 2025 18:19:06 +0100 Subject: [PATCH 1/6] add safe navigation operator on LoginHistory from authSession records --- .../log-management/classes/LogEntryEventHandler.cls | 6 +++--- .../logger-engine/classes/LogEntryEventBuilder.cls | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/nebula-logger/core/main/log-management/classes/LogEntryEventHandler.cls b/nebula-logger/core/main/log-management/classes/LogEntryEventHandler.cls index 6bc8a4c32..ae8bfbdbc 100644 --- a/nebula-logger/core/main/log-management/classes/LogEntryEventHandler.cls +++ b/nebula-logger/core/main/log-management/classes/LogEntryEventHandler.cls @@ -617,10 +617,10 @@ public without sharing class LogEntryEventHandler extends LoggerSObjectHandler { continue; } - log.LoginApplication__c = matchingAuthSessionProxy.LoginHistory.Application; - log.LoginBrowser__c = matchingAuthSessionProxy.LoginHistory.Browser; + log.LoginApplication__c = matchingAuthSessionProxy.LoginHistory?.Application; + log.LoginBrowser__c = matchingAuthSessionProxy.LoginHistory?.Browser; log.LoginHistoryId__c = matchingAuthSessionProxy.LoginHistoryId; - log.LoginPlatform__c = matchingAuthSessionProxy.LoginHistory.Platform; + log.LoginPlatform__c = matchingAuthSessionProxy.LoginHistory?.Platform; log.LoginType__c = matchingAuthSessionProxy.LoginType; log.LogoutUrl__c = matchingAuthSessionProxy.LogoutUrl; log.ParentSessionId__c = matchingAuthSessionProxy.ParentId; diff --git a/nebula-logger/core/main/logger-engine/classes/LogEntryEventBuilder.cls b/nebula-logger/core/main/logger-engine/classes/LogEntryEventBuilder.cls index 9f2039276..6ce3d072c 100644 --- a/nebula-logger/core/main/logger-engine/classes/LogEntryEventBuilder.cls +++ b/nebula-logger/core/main/logger-engine/classes/LogEntryEventBuilder.cls @@ -980,10 +980,10 @@ global with sharing class LogEntryEventBuilder { return; } - logEntryEvent.LoginApplication__c = CACHED_AUTH_SESSION_PROXY.LoginHistory.Application; - logEntryEvent.LoginBrowser__c = CACHED_AUTH_SESSION_PROXY.LoginHistory.Browser; - logEntryEvent.LoginHistoryId__c = CACHED_AUTH_SESSION_PROXY.LoginHistoryId; - logEntryEvent.LoginPlatform__c = CACHED_AUTH_SESSION_PROXY.LoginHistory.Platform; + logEntryEvent.LoginApplication__c = CACHED_AUTH_SESSION_PROXY.LoginHistory?.Application; + logEntryEvent.LoginBrowser__c = CACHED_AUTH_SESSION_PROXY.LoginHistory?.Browser; + logEntryEvent.LoginHistoryId__c = CACHED_AUTH_SESSION_PROXY?.LoginHistoryId; + logEntryEvent.LoginPlatform__c = CACHED_AUTH_SESSION_PROXY.LoginHistory?.Platform; logEntryEvent.LoginType__c = CACHED_AUTH_SESSION_PROXY.LoginType; logEntryEvent.LogoutUrl__c = CACHED_AUTH_SESSION_PROXY.LogoutUrl; logEntryEvent.ParentSessionId__c = CACHED_AUTH_SESSION_PROXY.ParentId; @@ -992,8 +992,8 @@ global with sharing class LogEntryEventBuilder { logEntryEvent.SessionType__c = CACHED_AUTH_SESSION_PROXY.SessionType; logEntryEvent.SourceIp__c = CACHED_AUTH_SESSION_PROXY.SourceIp; - if (CACHED_AUTH_SESSION_PROXY.LoginHistory.UserId != CURRENT_USER.Id) { - logEntryEvent.ImpersonatedById__c = CACHED_AUTH_SESSION_PROXY.LoginHistory.UserId; + if (CACHED_AUTH_SESSION_PROXY.LoginHistory?.UserId != CURRENT_USER.Id) { + logEntryEvent.ImpersonatedById__c = CACHED_AUTH_SESSION_PROXY.LoginHistory?.UserId; } } From 2d51545550194dbbc9fb2896fa1df5e1056ffa65 Mon Sep 17 00:00:00 2001 From: camillerev Date: Mon, 20 Jan 2025 18:46:22 +0100 Subject: [PATCH 2/6] remove a unuseful safe navigation operator --- .../core/main/logger-engine/classes/LogEntryEventBuilder.cls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nebula-logger/core/main/logger-engine/classes/LogEntryEventBuilder.cls b/nebula-logger/core/main/logger-engine/classes/LogEntryEventBuilder.cls index 6ce3d072c..1313eeb52 100644 --- a/nebula-logger/core/main/logger-engine/classes/LogEntryEventBuilder.cls +++ b/nebula-logger/core/main/logger-engine/classes/LogEntryEventBuilder.cls @@ -982,7 +982,7 @@ global with sharing class LogEntryEventBuilder { logEntryEvent.LoginApplication__c = CACHED_AUTH_SESSION_PROXY.LoginHistory?.Application; logEntryEvent.LoginBrowser__c = CACHED_AUTH_SESSION_PROXY.LoginHistory?.Browser; - logEntryEvent.LoginHistoryId__c = CACHED_AUTH_SESSION_PROXY?.LoginHistoryId; + logEntryEvent.LoginHistoryId__c = CACHED_AUTH_SESSION_PROXY.LoginHistoryId; logEntryEvent.LoginPlatform__c = CACHED_AUTH_SESSION_PROXY.LoginHistory?.Platform; logEntryEvent.LoginType__c = CACHED_AUTH_SESSION_PROXY.LoginType; logEntryEvent.LogoutUrl__c = CACHED_AUTH_SESSION_PROXY.LogoutUrl; From eb34e372836b77131ab4897ed38927f03127fb6c Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Mon, 20 Jan 2025 13:37:15 -0500 Subject: [PATCH 3/6] Added tests to validate that AuthSession with null LoginHistory is handled correctly --- .../classes/LogEntryEventHandler_Tests.cls | 56 +++++++++++++++++++ .../classes/LogEntryEventBuilder_Tests.cls | 36 ++++++++++++ 2 files changed, 92 insertions(+) diff --git a/nebula-logger/core/tests/log-management/classes/LogEntryEventHandler_Tests.cls b/nebula-logger/core/tests/log-management/classes/LogEntryEventHandler_Tests.cls index 747d68ce6..766fde130 100644 --- a/nebula-logger/core/tests/log-management/classes/LogEntryEventHandler_Tests.cls +++ b/nebula-logger/core/tests/log-management/classes/LogEntryEventHandler_Tests.cls @@ -680,6 +680,62 @@ private class LogEntryEventHandler_Tests { System.Assert.areEqual(mockAuthSessionProxy.SourceIp, log.SourceIp__c); } + @IsTest + static void it_should_query_and_handle_authSession_when_logingHistory_is_null() { + LoggerDataStore.setMock(LoggerMockDataStore.getEventBus()); + LoggerTestConfigurator.setupMockSObjectHandlerConfigurations(); + LoggerTestConfigurator.getSObjectHandlerConfiguration(Schema.LoggerScenario__c.SObjectType).IsEnabled__c = false; + LoggerTestConfigurator.getSObjectHandlerConfiguration(Schema.Log__c.SObjectType).IsEnabled__c = false; + LoggerTestConfigurator.getSObjectHandlerConfiguration(Schema.LogEntry__c.SObjectType).IsEnabled__c = false; + LogEntryEvent__e logEntryEvent = createLogEntryEvent(); + // The createLogEntryEvent() method sets all fields on LogEntryEvent__e, so clear the relevant fields to ensure + // that the values are only set based on the queried Schema.AuthSession record + logEntryEvent.LoginApplication__c = null; + logEntryEvent.LoginBrowser__c = null; + logEntryEvent.LoginHistoryId__c = null; + logEntryEvent.LoginPlatform__c = null; + logEntryEvent.LoginType__c = null; + logEntryEvent.LogoutUrl__c = null; + logEntryEvent.ParentSessionId__c = null; + logEntryEvent.SessionId__c = null; + logEntryEvent.SessionSecurityLevel__c = null; + logEntryEvent.SessionType__c = null; + logEntryEvent.SourceIp__c = null; + LoggerTestConfigurator.setMock(new LoggerParameter__mdt(DeveloperName = 'QueryAuthSessionDataSynchronously', Value__c = String.valueOf(false))); + System.Assert.isFalse(LoggerParameter.QUERY_AUTH_SESSION_DATA_SYNCHRONOUSLY); + MockLoggerEngineDataSelector mockSelector = new MockLoggerEngineDataSelector(); + LoggerEngineDataSelector.setMock(mockSelector); + LoggerSObjectProxy.AuthSession mockAuthSessionProxy = new LoggerSObjectProxy.AuthSession(); + mockAuthSessionProxy.Id = LoggerMockDataCreator.createId(Schema.AuthSession.SObjectType); + mockAuthSessionProxy.LoginHistory = null; + mockAuthSessionProxy.LoginHistoryId = null; + mockAuthSessionProxy.LoginType = 'LoginType'; + mockAuthSessionProxy.LogoutUrl = 'LogoutUrl'; + mockAuthSessionProxy.ParentId = LoggerMockDataCreator.createId(Schema.AuthSession.SObjectType); + mockAuthSessionProxy.SessionSecurityLevel = 'SessionSecurityLevel'; + mockAuthSessionProxy.SessionType = 'SessionType'; + mockAuthSessionProxy.SourceIp = 'SourceIp'; + mockAuthSessionProxy.UsersId = System.UserInfo.getUserId(); + mockSelector.setCachedAuthSessionProxy(mockAuthSessionProxy); + System.Assert.areEqual(0, mockSelector.getCachedAuthSessionQueryCount()); + + LoggerMockDataStore.getEventBus().publishRecord(logEntryEvent); + LoggerMockDataStore.getEventBus().deliver(new LogEntryEventHandler()); + + Log__c log = getLog(); + System.Assert.areEqual(mockAuthSessionProxy.Id, log.SessionId__c); + System.Assert.isNull(log.LoginApplication__c); + System.Assert.isNull(log.LoginBrowser__c); + System.Assert.isNull(log.LoginPlatform__c); + System.Assert.isNull(log.LoginHistoryId__c); + System.Assert.areEqual(mockAuthSessionProxy.LoginType, log.LoginType__c); + System.Assert.areEqual(mockAuthSessionProxy.LogoutUrl, log.LogoutUrl__c); + System.Assert.areEqual(mockAuthSessionProxy.ParentId, log.ParentSessionId__c); + System.Assert.areEqual(mockAuthSessionProxy.SessionSecurityLevel, log.SessionSecurityLevel__c); + System.Assert.areEqual(mockAuthSessionProxy.SessionType, log.SessionType__c); + System.Assert.areEqual(mockAuthSessionProxy.SourceIp, log.SourceIp__c); + } + @IsTest static void it_should_query_and_set_organization_data_when_synchronous_querying_is_disabled() { LoggerDataStore.setMock(LoggerMockDataStore.getEventBus()); diff --git a/nebula-logger/core/tests/logger-engine/classes/LogEntryEventBuilder_Tests.cls b/nebula-logger/core/tests/logger-engine/classes/LogEntryEventBuilder_Tests.cls index fc25a03fd..f81dce3ef 100644 --- a/nebula-logger/core/tests/logger-engine/classes/LogEntryEventBuilder_Tests.cls +++ b/nebula-logger/core/tests/logger-engine/classes/LogEntryEventBuilder_Tests.cls @@ -257,6 +257,42 @@ private class LogEntryEventBuilder_Tests { System.Assert.areEqual(mockAuthSessionProxy.SourceIp, logEntryEvent.SourceIp__c); } + @IsTest + static void it_should_query_and_handle_authSession_when_logingHistory_is_null() { + LoggerParameter.setMock(new LoggerParameter__mdt(DeveloperName = 'QueryAuthSessionDataSynchronously', Value__c = String.valueOf(true))); + System.Assert.isTrue(LoggerParameter.QUERY_AUTH_SESSION_DATA_SYNCHRONOUSLY); + MockLoggerEngineDataSelector mockSelector = new MockLoggerEngineDataSelector(); + LoggerEngineDataSelector.setMock(mockSelector); + LoggerSObjectProxy.AuthSession mockAuthSessionProxy = new LoggerSObjectProxy.AuthSession(); + mockAuthSessionProxy.Id = LoggerMockDataCreator.createId(Schema.AuthSession.SObjectType); + mockAuthSessionProxy.LoginHistory = null; + mockAuthSessionProxy.LoginHistoryId = null; + mockAuthSessionProxy.LoginType = 'LoginType'; + mockAuthSessionProxy.LogoutUrl = 'LogoutUrl'; + mockAuthSessionProxy.ParentId = LoggerMockDataCreator.createId(Schema.AuthSession.SObjectType); + mockAuthSessionProxy.SessionSecurityLevel = 'SessionSecurityLevel'; + mockAuthSessionProxy.SessionType = 'SessionType'; + mockAuthSessionProxy.SourceIp = 'SourceIp'; + mockAuthSessionProxy.UsersId = System.UserInfo.getUserId(); + mockSelector.setCachedAuthSessionProxy(mockAuthSessionProxy); + System.Assert.areEqual(0, mockSelector.getCachedAuthSessionQueryCount()); + + LogEntryEvent__e logEntryEvent = new LogEntryEventBuilder(getUserSettings(), System.LoggingLevel.INFO, true).setMessage('some message').getLogEntryEvent(); + + System.Assert.areEqual(1, mockSelector.getCachedAuthSessionQueryCount()); + System.Assert.isNull(logEntryEvent.LoginApplication__c); + System.Assert.isNull(logEntryEvent.LoginBrowser__c); + System.Assert.isNull(logEntryEvent.LoginPlatform__c); + System.Assert.isNull(logEntryEvent.LoginHistoryId__c); + System.Assert.areEqual(mockAuthSessionProxy.LoginType, logEntryEvent.LoginType__c); + System.Assert.areEqual(mockAuthSessionProxy.LogoutUrl, logEntryEvent.LogoutUrl__c); + System.Assert.areEqual(mockAuthSessionProxy.ParentId, logEntryEvent.ParentSessionId__c); + System.Assert.areEqual(mockAuthSessionProxy.Id, logEntryEvent.SessionId__c); + System.Assert.areEqual(mockAuthSessionProxy.SessionSecurityLevel, logEntryEvent.SessionSecurityLevel__c); + System.Assert.areEqual(mockAuthSessionProxy.SessionType, logEntryEvent.SessionType__c); + System.Assert.areEqual(mockAuthSessionProxy.SourceIp, logEntryEvent.SourceIp__c); + } + @IsTest static void it_should_not_run_organization_query_when_disabled_via_logger_parameter() { LoggerParameter.setMock(new LoggerParameter__mdt(DeveloperName = 'QueryOrganizationDataSynchronously', Value__c = String.valueOf(false))); From a0b81ce682ec043e3fbc50ea3aa3c80b2f7bfaa3 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Mon, 20 Jan 2025 13:48:38 -0500 Subject: [PATCH 4/6] Bumped package version number, name, and description --- README.md | 2 +- nebula-logger/core/main/logger-engine/classes/Logger.cls | 2 +- .../core/main/logger-engine/lwc/logger/loggerService.js | 2 +- package.json | 2 +- sfdx-project.json | 6 +++--- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 450f42ad9..956981ad9 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ The most robust observability solution for Salesforce experts. Built 100% natively on the platform, and designed to work seamlessly with Apex, Lightning Components, Flow, OmniStudio, and integrations. -## Unlocked Package - v4.15.4 +## Unlocked Package - v4.15.5 [![Install Unlocked Package in a Sandbox](./images/btn-install-unlocked-package-sandbox.png)](https://test.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000015oklQAA) [![Install Unlocked Package in Production](./images/btn-install-unlocked-package-production.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000015oklQAA) diff --git a/nebula-logger/core/main/logger-engine/classes/Logger.cls b/nebula-logger/core/main/logger-engine/classes/Logger.cls index 5bfce9495..536ef7c51 100644 --- a/nebula-logger/core/main/logger-engine/classes/Logger.cls +++ b/nebula-logger/core/main/logger-engine/classes/Logger.cls @@ -15,7 +15,7 @@ global with sharing class Logger { // There's no reliable way to get the version number dynamically in Apex @TestVisible - private static final String CURRENT_VERSION_NUMBER = 'v4.15.4'; + private static final String CURRENT_VERSION_NUMBER = 'v4.15.5'; private static final System.LoggingLevel FALLBACK_LOGGING_LEVEL = System.LoggingLevel.DEBUG; private static final List LOG_ENTRIES_BUFFER = new List(); private static final String MISSING_SCENARIO_ERROR_MESSAGE = 'No logger scenario specified. A scenario is required for logging in this org.'; diff --git a/nebula-logger/core/main/logger-engine/lwc/logger/loggerService.js b/nebula-logger/core/main/logger-engine/lwc/logger/loggerService.js index 4c7bd212a..9dab8fa80 100644 --- a/nebula-logger/core/main/logger-engine/lwc/logger/loggerService.js +++ b/nebula-logger/core/main/logger-engine/lwc/logger/loggerService.js @@ -10,7 +10,7 @@ import LoggerServiceTaskQueue from './loggerServiceTaskQueue'; import getSettings from '@salesforce/apex/ComponentLogger.getSettings'; import saveComponentLogEntries from '@salesforce/apex/ComponentLogger.saveComponentLogEntries'; -const CURRENT_VERSION_NUMBER = 'v4.15.4'; +const CURRENT_VERSION_NUMBER = 'v4.15.5'; const CONSOLE_OUTPUT_CONFIG = { messagePrefix: `%c Nebula Logger ${CURRENT_VERSION_NUMBER} `, diff --git a/package.json b/package.json index 3ff0f53ff..909d374e2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nebula-logger", - "version": "4.15.4", + "version": "4.15.5", "description": "The most robust logger for Salesforce. Works with Apex, Lightning Components, Flow, Process Builder & Integrations. Designed for Salesforce admins, developers & architects.", "author": "Jonathan Gillespie", "license": "MIT", diff --git a/sfdx-project.json b/sfdx-project.json index d1a5f14ae..22898be29 100644 --- a/sfdx-project.json +++ b/sfdx-project.json @@ -9,9 +9,9 @@ "path": "./nebula-logger/core", "definitionFile": "./config/scratch-orgs/base-scratch-def.json", "scopeProfiles": true, - "versionNumber": "4.15.4.NEXT", - "versionName": "FlowLogger exception message handling", - "versionDescription": "FlowLogger now properly truncates the LogEntryEvent__e.ExceptionMessage__c field", + "versionNumber": "4.15.5.NEXT", + "versionName": "Bugfix for AuthSession with null LoginHistory exception message handling", + "versionDescription": "Added safe navigation operator on LoginHistory from authSession records to avoid a NullPointerException", "postInstallUrl": "https://github.com/jongpie/NebulaLogger/wiki", "releaseNotesUrl": "https://github.com/jongpie/NebulaLogger/releases", "unpackagedMetadata": { From 62169ff48bc959a42c6c8e33d7497fe94430677d Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Mon, 3 Feb 2025 17:15:02 -0500 Subject: [PATCH 5/6] Fixed another related issue in LogEntryEventHandler where Log__c.ImpersonatedBy__c was not set when AuthSession data is queried async --- .../core/main/log-management/classes/LogEntryEventHandler.cls | 4 ++++ .../log-management/classes/LogEntryEventHandler_Tests.cls | 3 +++ 2 files changed, 7 insertions(+) diff --git a/nebula-logger/core/main/log-management/classes/LogEntryEventHandler.cls b/nebula-logger/core/main/log-management/classes/LogEntryEventHandler.cls index ae8bfbdbc..f7902c4f6 100644 --- a/nebula-logger/core/main/log-management/classes/LogEntryEventHandler.cls +++ b/nebula-logger/core/main/log-management/classes/LogEntryEventHandler.cls @@ -628,6 +628,10 @@ public without sharing class LogEntryEventHandler extends LoggerSObjectHandler { log.SessionSecurityLevel__c = matchingAuthSessionProxy.SessionSecurityLevel; log.SessionType__c = matchingAuthSessionProxy.SessionType; log.SourceIp__c = matchingAuthSessionProxy.SourceIp; + + if (matchingAuthSessionProxy.LoginHistory?.UserId != log.LoggedBy__c) { + log.ImpersonatedBy__c = matchingAuthSessionProxy.LoginHistory?.UserId; + } } } diff --git a/nebula-logger/core/tests/log-management/classes/LogEntryEventHandler_Tests.cls b/nebula-logger/core/tests/log-management/classes/LogEntryEventHandler_Tests.cls index 766fde130..e7f3afdc2 100644 --- a/nebula-logger/core/tests/log-management/classes/LogEntryEventHandler_Tests.cls +++ b/nebula-logger/core/tests/log-management/classes/LogEntryEventHandler_Tests.cls @@ -648,6 +648,9 @@ private class LogEntryEventHandler_Tests { mockLoginHistoryProxy.Application = 'Application'; mockLoginHistoryProxy.Browser = 'Browser'; mockLoginHistoryProxy.Platform = 'Platform'; + // TODO also test for when this UserId is a different user when an admin is impersonating another user + // This could be a bit tricky because creating a User in tests could fail in some orgs, and querying existing + // users in tests could fail in other orgs 🙃 mockLoginHistoryProxy.UserId = System.UserInfo.getUserId(); LoggerSObjectProxy.AuthSession mockAuthSessionProxy = new LoggerSObjectProxy.AuthSession(); mockAuthSessionProxy.Id = LoggerMockDataCreator.createId(Schema.AuthSession.SObjectType); From 56516ea5670d6cf1f2d87e2940e2808bc2009e84 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Tue, 4 Feb 2025 11:00:01 -0500 Subject: [PATCH 6/6] Created new core unlocked package version --- README.md | 6 +++--- sfdx-project.json | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 956981ad9..755186055 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,11 @@ The most robust observability solution for Salesforce experts. Built 100% native ## Unlocked Package - v4.15.5 -[![Install Unlocked Package in a Sandbox](./images/btn-install-unlocked-package-sandbox.png)](https://test.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000015oklQAA) -[![Install Unlocked Package in Production](./images/btn-install-unlocked-package-production.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000015oklQAA) +[![Install Unlocked Package in a Sandbox](./images/btn-install-unlocked-package-sandbox.png)](https://test.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000015p5jQAA) +[![Install Unlocked Package in Production](./images/btn-install-unlocked-package-production.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000015p5jQAA) [![View Documentation](./images/btn-view-documentation.png)](https://github.com/jongpie/NebulaLogger/wiki) -`sf package install --wait 20 --security-type AdminsOnly --package 04t5Y0000015oklQAA` +`sf package install --wait 20 --security-type AdminsOnly --package 04t5Y0000015p5jQAA` --- diff --git a/sfdx-project.json b/sfdx-project.json index 22898be29..c5db04378 100644 --- a/sfdx-project.json +++ b/sfdx-project.json @@ -209,6 +209,7 @@ "Nebula Logger - Core@4.15.2-added-support-for-logging-emptyrecylebinresult": "04t5Y0000015oifQAA", "Nebula Logger - Core@4.15.3-improved-testability-of-queries": "04t5Y0000015ok2QAA", "Nebula Logger - Core@4.15.4-flowlogger-exception-message-handling": "04t5Y0000015oklQAA", + "Nebula Logger - Core@4.15.5-bugfix-for-authsession-with-null-loginhistory-exception-message-handling": "04t5Y0000015p5jQAA", "Nebula Logger - Core Plugin - Async Failure Additions": "0Ho5Y000000blO4SAI", "Nebula Logger - Core Plugin - Async Failure Additions@1.0.0": "04t5Y0000015lhiQAA", "Nebula Logger - Core Plugin - Async Failure Additions@1.0.1": "04t5Y0000015lhsQAA",