Repository: bcgov/business-ui
Pull request #116: 27067 - Fixed LD targetting + wrong user reporting
Author: login: JazzarKarim
Created: 2025-04-30T17:53:23Z | Merged: 2025-05-01T20:20:09Z

https://github.com/bcgov/entity/issues/27067

OK, here's a bit of info what I did here:

First and foremost, I moved the LD store out of the nuxt daxiom shared package. The store used to be here:
`business-ui\business-registry-dashboard\node_modules\@daxiom\nuxt-core-layer-test\app\stores`

Now, I don't know if Thor will like this but I needed to do that in order to make my own changes. The changes being correctly reporting the context to LD when an org/user is changed. 

- I added some additional `console.info` to see what's going on
- The context is updated and sent to LD on user/org change.

Here's how I tested:
I logged in as BCREG0020 which defaults to resd right. The contexts in LD are:
<img width="1106" alt="image" src="https://github.com/user-attachments/assets/233210a2-bdb5-4882-83f8-65d6fd27ee34" />
You can see up top 668 which is the org id for resd. 

Now, let's change the account to mine: 
<img width="312" alt="image" src="https://github.com/user-attachments/assets/0f299408-98ac-4da7-9848-b417d724a9e3" />

The event now is passed (previously this doesn't happen):
<img width="776" alt="image" src="https://github.com/user-attachments/assets/92af6685-6184-4ea1-9131-db651db43125" />

Now checking in LD after waiting a bit:
<img width="1074" alt="image" src="https://github.com/user-attachments/assets/ce0dfc9e-6b75-4022-a6a8-762adbf8a8fe" />

As you can see, this org ID resembles my dev account in BCREG0020 that I just switched to.

Now finally, to test this, what I did is I enabled targeting for my org ID:
<img width="913" alt="image" src="https://github.com/user-attachments/assets/3eb8c1fd-6f91-4152-8063-7a93e8799076" />

And it works! You can see the pagination controls below.
<img width="1066" alt="image" src="https://github.com/user-attachments/assets/c89cd505-a972-419d-8cf7-f62c6b6994bc" />
 
### NOTE: An Ad blocker prevents the app from relaying the contexts to LD. This is why we see sometimes anonymous in LD. Sev, Mihai had this issue at one point if you remember and we were wondering why. This might've been it. The ad blocker MUST be disabled to report back correctly to LD.


Diff:
diff --git a/business-registry-dashboard/app/stores/connect-launchdarkly.ts b/business-registry-dashboard/app/stores/connect-launchdarkly.ts
new file mode 100644
index 000000000..755843915
--- /dev/null
+++ b/business-registry-dashboard/app/stores/connect-launchdarkly.ts
@@ -0,0 +1,155 @@
+import { initialize } from 'launchdarkly-js-client-sdk'
+import type { LDClient, LDFlagSet, LDOptions, LDMultiKindContext } from 'launchdarkly-js-client-sdk'
+import { defineStore } from 'pinia'
+import { useKeycloak, useConnectAccountStore } from '#imports'
+
+export const useConnectLaunchdarklyStore = defineStore('brd-connect-ld-store', () => {
+  const keycloak = reactive(useKeycloak())
+  const accountStore = useConnectAccountStore()
+  const ldClient: Ref<LDClient | null> = ref(null)
+  const ldContext = ref({
+    kind: 'multi',
+    org: { key: 'anonymous' },
+    user: { key: 'anonymous' }
+  } as LDMultiKindContext)
+  const ldFlagSet: Ref<LDFlagSet> = ref({})
+  const ldInitialized = ref(false)
+  const isInitializing = ref(false)
+  const isAppLoaded = ref(false)
+
+  // Only initialize LaunchDarkly after app is fully loaded and user is authenticated
+  watch([() => keycloak.isAuthenticated, () => isAppLoaded.value], ([isAuthenticated, isLoaded]) => {
+    if (isAuthenticated && isLoaded && !ldInitialized.value && !isInitializing.value) {
+      init()
+    } else if (isAuthenticated && isLoaded && ldInitialized.value) {
+      // If the context has changed but we're already initialized, update the context
+      updateUserContext()
+    }
+  })
+
+  // Watch for account changes to update LaunchDarkly org context
+  watch(() => accountStore.currentAccount.id, (accountId) => {
+    if (accountId && ldInitialized.value) {
+      updateUserContext()
+    }
+  })
+
+  // Create the user and org context objects for LaunchDarkly
+  function createLdContext () {
+    const appName = useRuntimeConfig().public.appName
+
+    // Create user context
+    const user = {
+      key: keycloak.kcUser.keycloakGuid,
+      firstName: keycloak.kcUser.firstName,
+      lastName: keycloak.kcUser.lastName,
+      email: keycloak.kcUser.email,
+      roles: keycloak.kcUser.roles,
+      loginSource: keycloak.kcUser.loginSource,
+      appSource: appName
+    }
+
+    // Default org to user key if no account
+    let org = { key: user.key, appSource: appName }
+
+    // Use account info if available
+    if (accountStore.currentAccount.id) {
+      org = {
+        key: accountStore.currentAccount.id,
+        accountType: accountStore.currentAccount.accountType,
+        accountStatus: accountStore.currentAccount.accountStatus,
+        type: accountStore.currentAccount.type,
+        label: accountStore.currentAccount.label,
+        appSource: appName
+      }
+    }
+
+    return { kind: 'multi', org, user } as LDMultiKindContext
+  }
+
+  function updateUserContext () {
+    if (!ldClient.value) { return }
+
+    // Create new context using shared function
+    const newContext = createLdContext()
+    ldContext.value = newContext
+
+    // Update the LaunchDarkly context
+    ldClient.value.identify(newContext).then(() => {
+      // Update flag values after context change
+      ldFlagSet.value = ldClient.value?.allFlags() || {}
+    }).catch((error) => {
+      console.error('LaunchDarkly context update error:', error)
+    })
+  }
+
+  function init () {
+    if (ldInitialized.value || isInitializing.value) {
+      return
+    }
+
+    // Skip initialization if user is not authenticated
+    if (!keycloak.isAuthenticated || !keycloak.kcUser?.keycloakGuid) {
+      return
+    }
+
+    isInitializing.value = true
+    const ldClientId = useRuntimeConfig().public.ldClientId
+    if (!ldClientId) {
+      isInitializing.value = false
+      return
+    }
+
+    // Create context using shared function
+    ldContext.value = createLdContext()
+    const options: LDOptions = {
+      streaming: false,
+      useReport: false,
+      diagnosticOptOut: true
+    }
+
+    try {
+      ldClient.value = initialize(ldClientId, ldContext.value, options)
+      ldClient.value.on('initialized', () => {
+        ldFlagSet.value = ldClient.value?.allFlags() || {}
+        ldInitialized.value = true
+        isInitializing.value = false
+        console.info('LaunchDarkly initialization complete.')
+      })
+
+      // Handle initialization failure
+      ldClient.value.on('error', (error) => {
+        console.error('LaunchDarkly initialization error:', error)
+        isInitializing.value = false
+      })
+    } catch (error) {
+      console.error('LaunchDarkly failed to initialize:', error)
+      isInitializing.value = false
+    }
+  }
+
+  function getFeatureFlag (name: string): any {
+    return ldClient.value ? ldClient.value.variation(name) : null
+  }
+
+  function getStoredFlag (name: string): any {
+    if (!ldInitialized) {
+      console.warn('Accessing ldarkly stored flag, but ldarkly is not initialized.')
+    }
+    return ldFlagSet.value[name]
+  }
+
+  function $reset () {
+    ldInitialized.value = false
+    isInitializing.value = false
+    ldClient.value = null
+    ldFlagSet.value = {}
+  }
+
+  return {
+    init,
+    getFeatureFlag,
+    getStoredFlag,
+    $reset
+  }
+})
diff --git a/business-registry-dashboard/package.json b/business-registry-dashboard/package.json
index be72b9f7a..a81b3593a 100644
--- a/business-registry-dashboard/package.json
+++ b/business-registry-dashboard/package.json
@@ -2,7 +2,7 @@
   "name": "business-registry-dashboard",
   "private": true,
   "type": "module",
-  "version": "1.0.43",
+  "version": "1.0.44",
   "scripts": {
     "build-check": "nuxt build",
     "build": "nuxt generate",


Reviews:
user: login: severinbeauvais
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-30T20:19:59Z
user: login: severinbeauvais
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-30T20:21:39Z
user: login: severinbeauvais
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-30T20:23:28Z
user: login: severinbeauvais
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-30T20:25:04Z
user: login: JazzarKarim
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-01T19:19:07Z
user: login: JazzarKarim
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-01T19:19:16Z
user: login: JazzarKarim
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-01T19:19:33Z
user: login: JazzarKarim
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-01T19:19:50Z
user: login: severinbeauvais
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-01T19:27:10Z
user: login: bobdev-94
body: LGTM
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-01T19:48:59Z
user: login: TVWerdal
body: Looks good
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-05-01T19:51:11Z
user: login: meawong
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-05-01T19:54:20Z
user: login: ArwenQin
body: Looks good!
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-01T19:55:18Z

Review comments:
diff_hunk: @@ -0,0 +1,195 @@
+import { initialize } from 'launchdarkly-js-client-sdk'
+import type { LDClient, LDFlagSet, LDOptions, LDMultiKindContext } from 'launchdarkly-js-client-sdk'
+import { defineStore } from 'pinia'
+import { useKeycloak, useConnectAccountStore } from '#imports'
+
+export const useConnectLaunchdarklyStore = defineStore('brd-connect-ld-store', () => {
+  const keycloak = reactive(useKeycloak())
+  const accountStore = useConnectAccountStore()
+  const ldClient: Ref<LDClient | null> = ref(null)
+  const ldContext = ref({
+    kind: 'multi',
+    org: { key: 'anonymous' },
+    user: { key: 'anonymous' }
+  } as LDMultiKindContext)
+  const ldFlagSet: Ref<LDFlagSet> = ref({})
+  const ldInitialized = ref(false)
+  const isInitializing = ref(false)
+  const isAppLoaded = ref(false)
+
+  // Only initialize LaunchDarkly after app is fully loaded and user is authenticated
+  watch([() => keycloak.isAuthenticated, () => isAppLoaded.value], ([isAuthenticated, isLoaded]) => {
+    if (isAuthenticated && isLoaded && !ldInitialized.value && !isInitializing.value) {
+      init()
+    } else if (isAuthenticated && isLoaded && ldInitialized.value) {
+      // If the context has changed but we're already initialized, update the context
+      updateUserContext()
+    }
+  })
+
+  // Watch for account changes to update LaunchDarkly org context
+  watch(() => accountStore.currentAccount.id, (accountId) => {
+    if (accountId && ldInitialized.value) {
+      updateUserContext()
+    }
+  })
+
+  function updateUserContext () {
+    if (!ldClient.value) { return }
+
+    // Only update context if user is authenticated
+    if (!keycloak.isAuthenticated || !keycloak.kcUser?.keycloakGuid) {
+      console.info('Not updating LaunchDarkly context - user not authenticated')
+      return
+    }
+
+    const appName = useRuntimeConfig().public.appName
+    const user = {
+      key: keycloak.kcUser.keycloakGuid,
+      firstName: keycloak.kcUser.firstName,
+      lastName: keycloak.kcUser.lastName,
+      email: keycloak.kcUser.email || 'unknown@example.com', // Ensure email is never undefined
+      roles: keycloak.kcUser.roles,
+      loginSource: keycloak.kcUser.loginSource,
+      appSource: appName
+    }
+
+    let org = { key: user.key, appSource: appName } // Default to user key if no account
+
+    if (accountStore.currentAccount.id) {
+      org = {
+        key: accountStore.currentAccount.id,
+        accountType: accountStore.currentAccount.accountType,
+        accountStatus: accountStore.currentAccount.accountStatus,
+        type: accountStore.currentAccount.type,
+        label: accountStore.currentAccount.label,
+        appSource: appName
+      }
+    }
+
+    const newContext = { kind: 'multi', org, user } as LDMultiKindContext
+    ldContext.value = newContext
+
+    // Update the LaunchDarkly context
+    ldClient.value.identify(newContext).then(() => {
+      // Update flag values after context change
+      ldFlagSet.value = ldClient.value?.allFlags() || {}
+      console.info('LaunchDarkly context updated successfully')
+    }).catch((error) => {
+      console.error('LaunchDarkly context update error:', error)
+    })
+  }
+
+  function init () {
+    console.info('Initializing LaunchDarkly')
+    if (ldInitialized.value) {
+      console.info('LaunchDarkly already initialized.')
+      return
+    }
+
+    // Prevent multiple initialization attempts
+    if (isInitializing.value) {
+      console.info('LaunchDarkly initialization already in progress.')
+      return
+    }
+
+    // Skip initialization if user is not authenticated
+    if (!keycloak.isAuthenticated || !keycloak.kcUser?.keycloakGuid) {
+      console.info('Not initializing LaunchDarkly - user not authenticated')
+      return
+    }
+
+    isInitializing.value = true
+
+    const ldClientId = useRuntimeConfig().public.ldClientId
+    if (!ldClientId) {
+      console.info('No LaunchDarkly SDK variable set. Aborting LaunchDarkly setup.')
+      isInitializing.value = false
+      return
+    }
+
+    const appName = useRuntimeConfig().public.appName
path: business-registry-dashboard/app/stores/connect-launchdarkly.ts
user: login: severinbeauvais
body: This code (and below) looks like a duplicate of the code above on line 46.
created_at: 2025-04-30T20:19:59Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,195 @@
+import { initialize } from 'launchdarkly-js-client-sdk'
+import type { LDClient, LDFlagSet, LDOptions, LDMultiKindContext } from 'launchdarkly-js-client-sdk'
+import { defineStore } from 'pinia'
+import { useKeycloak, useConnectAccountStore } from '#imports'
+
+export const useConnectLaunchdarklyStore = defineStore('brd-connect-ld-store', () => {
+  const keycloak = reactive(useKeycloak())
+  const accountStore = useConnectAccountStore()
+  const ldClient: Ref<LDClient | null> = ref(null)
+  const ldContext = ref({
+    kind: 'multi',
+    org: { key: 'anonymous' },
+    user: { key: 'anonymous' }
+  } as LDMultiKindContext)
+  const ldFlagSet: Ref<LDFlagSet> = ref({})
+  const ldInitialized = ref(false)
+  const isInitializing = ref(false)
+  const isAppLoaded = ref(false)
+
+  // Only initialize LaunchDarkly after app is fully loaded and user is authenticated
+  watch([() => keycloak.isAuthenticated, () => isAppLoaded.value], ([isAuthenticated, isLoaded]) => {
+    if (isAuthenticated && isLoaded && !ldInitialized.value && !isInitializing.value) {
+      init()
+    } else if (isAuthenticated && isLoaded && ldInitialized.value) {
+      // If the context has changed but we're already initialized, update the context
+      updateUserContext()
+    }
+  })
+
+  // Watch for account changes to update LaunchDarkly org context
+  watch(() => accountStore.currentAccount.id, (accountId) => {
+    if (accountId && ldInitialized.value) {
+      updateUserContext()
+    }
+  })
+
+  function updateUserContext () {
+    if (!ldClient.value) { return }
+
+    // Only update context if user is authenticated
+    if (!keycloak.isAuthenticated || !keycloak.kcUser?.keycloakGuid) {
+      console.info('Not updating LaunchDarkly context - user not authenticated')
+      return
+    }
+
+    const appName = useRuntimeConfig().public.appName
+    const user = {
+      key: keycloak.kcUser.keycloakGuid,
+      firstName: keycloak.kcUser.firstName,
+      lastName: keycloak.kcUser.lastName,
+      email: keycloak.kcUser.email || 'unknown@example.com', // Ensure email is never undefined
+      roles: keycloak.kcUser.roles,
+      loginSource: keycloak.kcUser.loginSource,
+      appSource: appName
+    }
+
+    let org = { key: user.key, appSource: appName } // Default to user key if no account
+
+    if (accountStore.currentAccount.id) {
+      org = {
+        key: accountStore.currentAccount.id,
+        accountType: accountStore.currentAccount.accountType,
+        accountStatus: accountStore.currentAccount.accountStatus,
+        type: accountStore.currentAccount.type,
+        label: accountStore.currentAccount.label,
+        appSource: appName
+      }
+    }
+
+    const newContext = { kind: 'multi', org, user } as LDMultiKindContext
+    ldContext.value = newContext
+
+    // Update the LaunchDarkly context
+    ldClient.value.identify(newContext).then(() => {
+      // Update flag values after context change
+      ldFlagSet.value = ldClient.value?.allFlags() || {}
+      console.info('LaunchDarkly context updated successfully')
+    }).catch((error) => {
+      console.error('LaunchDarkly context update error:', error)
+    })
+  }
+
+  function init () {
+    console.info('Initializing LaunchDarkly')
+    if (ldInitialized.value) {
+      console.info('LaunchDarkly already initialized.')
+      return
+    }
+
+    // Prevent multiple initialization attempts
+    if (isInitializing.value) {
+      console.info('LaunchDarkly initialization already in progress.')
+      return
+    }
+
+    // Skip initialization if user is not authenticated
+    if (!keycloak.isAuthenticated || !keycloak.kcUser?.keycloakGuid) {
+      console.info('Not initializing LaunchDarkly - user not authenticated')
+      return
+    }
+
+    isInitializing.value = true
+
+    const ldClientId = useRuntimeConfig().public.ldClientId
+    if (!ldClientId) {
+      console.info('No LaunchDarkly SDK variable set. Aborting LaunchDarkly setup.')
+      isInitializing.value = false
+      return
+    }
+
+    const appName = useRuntimeConfig().public.appName
+
+    // Only initialize with authenticated user context
+    const user = {
+      key: keycloak.kcUser.keycloakGuid,
+      firstName: keycloak.kcUser.firstName,
+      lastName: keycloak.kcUser.lastName,
+      email: keycloak.kcUser.email || 'unknown@example.com', // Ensure email is never undefined
+      roles: keycloak.kcUser.roles,
+      loginSource: keycloak.kcUser.loginSource,
+      appSource: appName
+    }
+
+    // Default org to user key if no account selected
+    let org = { key: user.key, appSource: appName }
+
+    if (accountStore.currentAccount.id) {
+      org = {
+        key: accountStore.currentAccount.id,
+        accountType: accountStore.currentAccount.accountType,
+        accountStatus: accountStore.currentAccount.accountStatus,
+        type: accountStore.currentAccount.type,
+        label: accountStore.currentAccount.label,
+        appSource: appName
+      }
+    }
+
+    ldContext.value = { kind: 'multi', org, user }
+    const options: LDOptions = {
+      streaming: false,
+      useReport: false,
+      diagnosticOptOut: true
+    }
+
+    try {
+      ldClient.value = initialize(ldClientId, ldContext.value, options)
+
+      ldClient.value.on('initialized', () => {
+        ldFlagSet.value = ldClient.value?.allFlags() || {}
+        ldInitialized.value = true
+        isInitializing.value = false
+        console.info('LaunchDarkly initialization complete.')
+      })
+
+      // Handle initialization failure
+      ldClient.value.on('error', (error) => {
+        console.error('LaunchDarkly initialization error:', error)
+        isInitializing.value = false
+      })
+    } catch (error) {
+      console.error('LaunchDarkly failed to initialize:', error)
+      isInitializing.value = false
+    }
+  }
+
+  function getFeatureFlag (name: string): any {
+    return ldClient.value ? ldClient.value.variation(name) : null
+  }
+
+  function getStoredFlag (name: string): any {
+    if (!ldInitialized.value) {
+      console.warn('Accessing LaunchDarkly stored flag, but LaunchDarkly is not initialized.')
+    }
+    return ldFlagSet.value[name]
+  }
+
+  function $reset () {
+    ldInitialized.value = false
+    isInitializing.value = false
+    ldClient.value = null
+    ldFlagSet.value = {}
+  }
+
+  return {
+    ldClient,
+    ldContext,
+    ldFlagSet,
+    ldInitialized,
+    init,
+    getFeatureFlag,
+    getStoredFlag,
+    updateUserContext,
+    $reset
+  }
path: business-registry-dashboard/app/stores/connect-launchdarkly.ts
user: login: severinbeauvais
body: Are all of these needed outside of this module? Or could this interface be cleaned up to just 1 or 2 items?
created_at: 2025-04-30T20:21:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,195 @@
+import { initialize } from 'launchdarkly-js-client-sdk'
+import type { LDClient, LDFlagSet, LDOptions, LDMultiKindContext } from 'launchdarkly-js-client-sdk'
+import { defineStore } from 'pinia'
+import { useKeycloak, useConnectAccountStore } from '#imports'
+
+export const useConnectLaunchdarklyStore = defineStore('brd-connect-ld-store', () => {
+  const keycloak = reactive(useKeycloak())
+  const accountStore = useConnectAccountStore()
+  const ldClient: Ref<LDClient | null> = ref(null)
+  const ldContext = ref({
+    kind: 'multi',
+    org: { key: 'anonymous' },
+    user: { key: 'anonymous' }
+  } as LDMultiKindContext)
+  const ldFlagSet: Ref<LDFlagSet> = ref({})
+  const ldInitialized = ref(false)
+  const isInitializing = ref(false)
+  const isAppLoaded = ref(false)
+
+  // Only initialize LaunchDarkly after app is fully loaded and user is authenticated
+  watch([() => keycloak.isAuthenticated, () => isAppLoaded.value], ([isAuthenticated, isLoaded]) => {
+    if (isAuthenticated && isLoaded && !ldInitialized.value && !isInitializing.value) {
+      init()
+    } else if (isAuthenticated && isLoaded && ldInitialized.value) {
+      // If the context has changed but we're already initialized, update the context
+      updateUserContext()
+    }
+  })
+
+  // Watch for account changes to update LaunchDarkly org context
+  watch(() => accountStore.currentAccount.id, (accountId) => {
+    if (accountId && ldInitialized.value) {
+      updateUserContext()
+    }
+  })
+
+  function updateUserContext () {
+    if (!ldClient.value) { return }
+
+    // Only update context if user is authenticated
+    if (!keycloak.isAuthenticated || !keycloak.kcUser?.keycloakGuid) {
path: business-registry-dashboard/app/stores/connect-launchdarkly.ts
user: login: severinbeauvais
body: Can this ever happen?

Does this automatically recover, or is this a real error?
created_at: 2025-04-30T20:23:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,195 @@
+import { initialize } from 'launchdarkly-js-client-sdk'
+import type { LDClient, LDFlagSet, LDOptions, LDMultiKindContext } from 'launchdarkly-js-client-sdk'
+import { defineStore } from 'pinia'
+import { useKeycloak, useConnectAccountStore } from '#imports'
+
+export const useConnectLaunchdarklyStore = defineStore('brd-connect-ld-store', () => {
+  const keycloak = reactive(useKeycloak())
+  const accountStore = useConnectAccountStore()
+  const ldClient: Ref<LDClient | null> = ref(null)
+  const ldContext = ref({
+    kind: 'multi',
+    org: { key: 'anonymous' },
+    user: { key: 'anonymous' }
+  } as LDMultiKindContext)
+  const ldFlagSet: Ref<LDFlagSet> = ref({})
+  const ldInitialized = ref(false)
+  const isInitializing = ref(false)
+  const isAppLoaded = ref(false)
+
+  // Only initialize LaunchDarkly after app is fully loaded and user is authenticated
+  watch([() => keycloak.isAuthenticated, () => isAppLoaded.value], ([isAuthenticated, isLoaded]) => {
+    if (isAuthenticated && isLoaded && !ldInitialized.value && !isInitializing.value) {
+      init()
+    } else if (isAuthenticated && isLoaded && ldInitialized.value) {
+      // If the context has changed but we're already initialized, update the context
+      updateUserContext()
+    }
+  })
+
+  // Watch for account changes to update LaunchDarkly org context
+  watch(() => accountStore.currentAccount.id, (accountId) => {
+    if (accountId && ldInitialized.value) {
+      updateUserContext()
+    }
+  })
+
+  function updateUserContext () {
+    if (!ldClient.value) { return }
+
+    // Only update context if user is authenticated
+    if (!keycloak.isAuthenticated || !keycloak.kcUser?.keycloakGuid) {
+      console.info('Not updating LaunchDarkly context - user not authenticated')
+      return
+    }
+
+    const appName = useRuntimeConfig().public.appName
+    const user = {
+      key: keycloak.kcUser.keycloakGuid,
+      firstName: keycloak.kcUser.firstName,
+      lastName: keycloak.kcUser.lastName,
+      email: keycloak.kcUser.email || 'unknown@example.com', // Ensure email is never undefined
+      roles: keycloak.kcUser.roles,
+      loginSource: keycloak.kcUser.loginSource,
+      appSource: appName
+    }
+
+    let org = { key: user.key, appSource: appName } // Default to user key if no account
+
+    if (accountStore.currentAccount.id) {
+      org = {
+        key: accountStore.currentAccount.id,
+        accountType: accountStore.currentAccount.accountType,
+        accountStatus: accountStore.currentAccount.accountStatus,
+        type: accountStore.currentAccount.type,
+        label: accountStore.currentAccount.label,
+        appSource: appName
+      }
+    }
+
+    const newContext = { kind: 'multi', org, user } as LDMultiKindContext
+    ldContext.value = newContext
+
+    // Update the LaunchDarkly context
+    ldClient.value.identify(newContext).then(() => {
+      // Update flag values after context change
+      ldFlagSet.value = ldClient.value?.allFlags() || {}
+      console.info('LaunchDarkly context updated successfully')
+    }).catch((error) => {
+      console.error('LaunchDarkly context update error:', error)
+    })
+  }
+
+  function init () {
+    console.info('Initializing LaunchDarkly')
path: business-registry-dashboard/app/stores/connect-launchdarkly.ts
user: login: severinbeauvais
body: It would be nice to minimize LD-related console output. What do you think about just 1 success/fail message? I'm not stuck on this one.
created_at: 2025-04-30T20:25:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,195 @@
+import { initialize } from 'launchdarkly-js-client-sdk'
+import type { LDClient, LDFlagSet, LDOptions, LDMultiKindContext } from 'launchdarkly-js-client-sdk'
+import { defineStore } from 'pinia'
+import { useKeycloak, useConnectAccountStore } from '#imports'
+
+export const useConnectLaunchdarklyStore = defineStore('brd-connect-ld-store', () => {
+  const keycloak = reactive(useKeycloak())
+  const accountStore = useConnectAccountStore()
+  const ldClient: Ref<LDClient | null> = ref(null)
+  const ldContext = ref({
+    kind: 'multi',
+    org: { key: 'anonymous' },
+    user: { key: 'anonymous' }
+  } as LDMultiKindContext)
+  const ldFlagSet: Ref<LDFlagSet> = ref({})
+  const ldInitialized = ref(false)
+  const isInitializing = ref(false)
+  const isAppLoaded = ref(false)
+
+  // Only initialize LaunchDarkly after app is fully loaded and user is authenticated
+  watch([() => keycloak.isAuthenticated, () => isAppLoaded.value], ([isAuthenticated, isLoaded]) => {
+    if (isAuthenticated && isLoaded && !ldInitialized.value && !isInitializing.value) {
+      init()
+    } else if (isAuthenticated && isLoaded && ldInitialized.value) {
+      // If the context has changed but we're already initialized, update the context
+      updateUserContext()
+    }
+  })
+
+  // Watch for account changes to update LaunchDarkly org context
+  watch(() => accountStore.currentAccount.id, (accountId) => {
+    if (accountId && ldInitialized.value) {
+      updateUserContext()
+    }
+  })
+
+  function updateUserContext () {
+    if (!ldClient.value) { return }
+
+    // Only update context if user is authenticated
+    if (!keycloak.isAuthenticated || !keycloak.kcUser?.keycloakGuid) {
+      console.info('Not updating LaunchDarkly context - user not authenticated')
+      return
+    }
+
+    const appName = useRuntimeConfig().public.appName
+    const user = {
+      key: keycloak.kcUser.keycloakGuid,
+      firstName: keycloak.kcUser.firstName,
+      lastName: keycloak.kcUser.lastName,
+      email: keycloak.kcUser.email || 'unknown@example.com', // Ensure email is never undefined
+      roles: keycloak.kcUser.roles,
+      loginSource: keycloak.kcUser.loginSource,
+      appSource: appName
+    }
+
+    let org = { key: user.key, appSource: appName } // Default to user key if no account
+
+    if (accountStore.currentAccount.id) {
+      org = {
+        key: accountStore.currentAccount.id,
+        accountType: accountStore.currentAccount.accountType,
+        accountStatus: accountStore.currentAccount.accountStatus,
+        type: accountStore.currentAccount.type,
+        label: accountStore.currentAccount.label,
+        appSource: appName
+      }
+    }
+
+    const newContext = { kind: 'multi', org, user } as LDMultiKindContext
+    ldContext.value = newContext
+
+    // Update the LaunchDarkly context
+    ldClient.value.identify(newContext).then(() => {
+      // Update flag values after context change
+      ldFlagSet.value = ldClient.value?.allFlags() || {}
+      console.info('LaunchDarkly context updated successfully')
+    }).catch((error) => {
+      console.error('LaunchDarkly context update error:', error)
+    })
+  }
+
+  function init () {
+    console.info('Initializing LaunchDarkly')
+    if (ldInitialized.value) {
+      console.info('LaunchDarkly already initialized.')
+      return
+    }
+
+    // Prevent multiple initialization attempts
+    if (isInitializing.value) {
+      console.info('LaunchDarkly initialization already in progress.')
+      return
+    }
+
+    // Skip initialization if user is not authenticated
+    if (!keycloak.isAuthenticated || !keycloak.kcUser?.keycloakGuid) {
+      console.info('Not initializing LaunchDarkly - user not authenticated')
+      return
+    }
+
+    isInitializing.value = true
+
+    const ldClientId = useRuntimeConfig().public.ldClientId
+    if (!ldClientId) {
+      console.info('No LaunchDarkly SDK variable set. Aborting LaunchDarkly setup.')
+      isInitializing.value = false
+      return
+    }
+
+    const appName = useRuntimeConfig().public.appName
path: business-registry-dashboard/app/stores/connect-launchdarkly.ts
user: login: JazzarKarim
body: Minimized code duplication in latest code. 
created_at: 2025-05-01T19:19:07Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,195 @@
+import { initialize } from 'launchdarkly-js-client-sdk'
+import type { LDClient, LDFlagSet, LDOptions, LDMultiKindContext } from 'launchdarkly-js-client-sdk'
+import { defineStore } from 'pinia'
+import { useKeycloak, useConnectAccountStore } from '#imports'
+
+export const useConnectLaunchdarklyStore = defineStore('brd-connect-ld-store', () => {
+  const keycloak = reactive(useKeycloak())
+  const accountStore = useConnectAccountStore()
+  const ldClient: Ref<LDClient | null> = ref(null)
+  const ldContext = ref({
+    kind: 'multi',
+    org: { key: 'anonymous' },
+    user: { key: 'anonymous' }
+  } as LDMultiKindContext)
+  const ldFlagSet: Ref<LDFlagSet> = ref({})
+  const ldInitialized = ref(false)
+  const isInitializing = ref(false)
+  const isAppLoaded = ref(false)
+
+  // Only initialize LaunchDarkly after app is fully loaded and user is authenticated
+  watch([() => keycloak.isAuthenticated, () => isAppLoaded.value], ([isAuthenticated, isLoaded]) => {
+    if (isAuthenticated && isLoaded && !ldInitialized.value && !isInitializing.value) {
+      init()
+    } else if (isAuthenticated && isLoaded && ldInitialized.value) {
+      // If the context has changed but we're already initialized, update the context
+      updateUserContext()
+    }
+  })
+
+  // Watch for account changes to update LaunchDarkly org context
+  watch(() => accountStore.currentAccount.id, (accountId) => {
+    if (accountId && ldInitialized.value) {
+      updateUserContext()
+    }
+  })
+
+  function updateUserContext () {
+    if (!ldClient.value) { return }
+
+    // Only update context if user is authenticated
+    if (!keycloak.isAuthenticated || !keycloak.kcUser?.keycloakGuid) {
+      console.info('Not updating LaunchDarkly context - user not authenticated')
+      return
+    }
+
+    const appName = useRuntimeConfig().public.appName
+    const user = {
+      key: keycloak.kcUser.keycloakGuid,
+      firstName: keycloak.kcUser.firstName,
+      lastName: keycloak.kcUser.lastName,
+      email: keycloak.kcUser.email || 'unknown@example.com', // Ensure email is never undefined
+      roles: keycloak.kcUser.roles,
+      loginSource: keycloak.kcUser.loginSource,
+      appSource: appName
+    }
+
+    let org = { key: user.key, appSource: appName } // Default to user key if no account
+
+    if (accountStore.currentAccount.id) {
+      org = {
+        key: accountStore.currentAccount.id,
+        accountType: accountStore.currentAccount.accountType,
+        accountStatus: accountStore.currentAccount.accountStatus,
+        type: accountStore.currentAccount.type,
+        label: accountStore.currentAccount.label,
+        appSource: appName
+      }
+    }
+
+    const newContext = { kind: 'multi', org, user } as LDMultiKindContext
+    ldContext.value = newContext
+
+    // Update the LaunchDarkly context
+    ldClient.value.identify(newContext).then(() => {
+      // Update flag values after context change
+      ldFlagSet.value = ldClient.value?.allFlags() || {}
+      console.info('LaunchDarkly context updated successfully')
+    }).catch((error) => {
+      console.error('LaunchDarkly context update error:', error)
+    })
+  }
+
+  function init () {
+    console.info('Initializing LaunchDarkly')
+    if (ldInitialized.value) {
+      console.info('LaunchDarkly already initialized.')
+      return
+    }
+
+    // Prevent multiple initialization attempts
+    if (isInitializing.value) {
+      console.info('LaunchDarkly initialization already in progress.')
+      return
+    }
+
+    // Skip initialization if user is not authenticated
+    if (!keycloak.isAuthenticated || !keycloak.kcUser?.keycloakGuid) {
+      console.info('Not initializing LaunchDarkly - user not authenticated')
+      return
+    }
+
+    isInitializing.value = true
+
+    const ldClientId = useRuntimeConfig().public.ldClientId
+    if (!ldClientId) {
+      console.info('No LaunchDarkly SDK variable set. Aborting LaunchDarkly setup.')
+      isInitializing.value = false
+      return
+    }
+
+    const appName = useRuntimeConfig().public.appName
+
+    // Only initialize with authenticated user context
+    const user = {
+      key: keycloak.kcUser.keycloakGuid,
+      firstName: keycloak.kcUser.firstName,
+      lastName: keycloak.kcUser.lastName,
+      email: keycloak.kcUser.email || 'unknown@example.com', // Ensure email is never undefined
+      roles: keycloak.kcUser.roles,
+      loginSource: keycloak.kcUser.loginSource,
+      appSource: appName
+    }
+
+    // Default org to user key if no account selected
+    let org = { key: user.key, appSource: appName }
+
+    if (accountStore.currentAccount.id) {
+      org = {
+        key: accountStore.currentAccount.id,
+        accountType: accountStore.currentAccount.accountType,
+        accountStatus: accountStore.currentAccount.accountStatus,
+        type: accountStore.currentAccount.type,
+        label: accountStore.currentAccount.label,
+        appSource: appName
+      }
+    }
+
+    ldContext.value = { kind: 'multi', org, user }
+    const options: LDOptions = {
+      streaming: false,
+      useReport: false,
+      diagnosticOptOut: true
+    }
+
+    try {
+      ldClient.value = initialize(ldClientId, ldContext.value, options)
+
+      ldClient.value.on('initialized', () => {
+        ldFlagSet.value = ldClient.value?.allFlags() || {}
+        ldInitialized.value = true
+        isInitializing.value = false
+        console.info('LaunchDarkly initialization complete.')
+      })
+
+      // Handle initialization failure
+      ldClient.value.on('error', (error) => {
+        console.error('LaunchDarkly initialization error:', error)
+        isInitializing.value = false
+      })
+    } catch (error) {
+      console.error('LaunchDarkly failed to initialize:', error)
+      isInitializing.value = false
+    }
+  }
+
+  function getFeatureFlag (name: string): any {
+    return ldClient.value ? ldClient.value.variation(name) : null
+  }
+
+  function getStoredFlag (name: string): any {
+    if (!ldInitialized.value) {
+      console.warn('Accessing LaunchDarkly stored flag, but LaunchDarkly is not initialized.')
+    }
+    return ldFlagSet.value[name]
+  }
+
+  function $reset () {
+    ldInitialized.value = false
+    isInitializing.value = false
+    ldClient.value = null
+    ldFlagSet.value = {}
+  }
+
+  return {
+    ldClient,
+    ldContext,
+    ldFlagSet,
+    ldInitialized,
+    init,
+    getFeatureFlag,
+    getStoredFlag,
+    updateUserContext,
+    $reset
+  }
path: business-registry-dashboard/app/stores/connect-launchdarkly.ts
user: login: JazzarKarim
body: Agreed, done. 
created_at: 2025-05-01T19:19:16Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,195 @@
+import { initialize } from 'launchdarkly-js-client-sdk'
+import type { LDClient, LDFlagSet, LDOptions, LDMultiKindContext } from 'launchdarkly-js-client-sdk'
+import { defineStore } from 'pinia'
+import { useKeycloak, useConnectAccountStore } from '#imports'
+
+export const useConnectLaunchdarklyStore = defineStore('brd-connect-ld-store', () => {
+  const keycloak = reactive(useKeycloak())
+  const accountStore = useConnectAccountStore()
+  const ldClient: Ref<LDClient | null> = ref(null)
+  const ldContext = ref({
+    kind: 'multi',
+    org: { key: 'anonymous' },
+    user: { key: 'anonymous' }
+  } as LDMultiKindContext)
+  const ldFlagSet: Ref<LDFlagSet> = ref({})
+  const ldInitialized = ref(false)
+  const isInitializing = ref(false)
+  const isAppLoaded = ref(false)
+
+  // Only initialize LaunchDarkly after app is fully loaded and user is authenticated
+  watch([() => keycloak.isAuthenticated, () => isAppLoaded.value], ([isAuthenticated, isLoaded]) => {
+    if (isAuthenticated && isLoaded && !ldInitialized.value && !isInitializing.value) {
+      init()
+    } else if (isAuthenticated && isLoaded && ldInitialized.value) {
+      // If the context has changed but we're already initialized, update the context
+      updateUserContext()
+    }
+  })
+
+  // Watch for account changes to update LaunchDarkly org context
+  watch(() => accountStore.currentAccount.id, (accountId) => {
+    if (accountId && ldInitialized.value) {
+      updateUserContext()
+    }
+  })
+
+  function updateUserContext () {
+    if (!ldClient.value) { return }
+
+    // Only update context if user is authenticated
+    if (!keycloak.isAuthenticated || !keycloak.kcUser?.keycloakGuid) {
path: business-registry-dashboard/app/stores/connect-launchdarkly.ts
user: login: JazzarKarim
body: No, this is theoretically won't happen. I removed. 
created_at: 2025-05-01T19:19:32Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,195 @@
+import { initialize } from 'launchdarkly-js-client-sdk'
+import type { LDClient, LDFlagSet, LDOptions, LDMultiKindContext } from 'launchdarkly-js-client-sdk'
+import { defineStore } from 'pinia'
+import { useKeycloak, useConnectAccountStore } from '#imports'
+
+export const useConnectLaunchdarklyStore = defineStore('brd-connect-ld-store', () => {
+  const keycloak = reactive(useKeycloak())
+  const accountStore = useConnectAccountStore()
+  const ldClient: Ref<LDClient | null> = ref(null)
+  const ldContext = ref({
+    kind: 'multi',
+    org: { key: 'anonymous' },
+    user: { key: 'anonymous' }
+  } as LDMultiKindContext)
+  const ldFlagSet: Ref<LDFlagSet> = ref({})
+  const ldInitialized = ref(false)
+  const isInitializing = ref(false)
+  const isAppLoaded = ref(false)
+
+  // Only initialize LaunchDarkly after app is fully loaded and user is authenticated
+  watch([() => keycloak.isAuthenticated, () => isAppLoaded.value], ([isAuthenticated, isLoaded]) => {
+    if (isAuthenticated && isLoaded && !ldInitialized.value && !isInitializing.value) {
+      init()
+    } else if (isAuthenticated && isLoaded && ldInitialized.value) {
+      // If the context has changed but we're already initialized, update the context
+      updateUserContext()
+    }
+  })
+
+  // Watch for account changes to update LaunchDarkly org context
+  watch(() => accountStore.currentAccount.id, (accountId) => {
+    if (accountId && ldInitialized.value) {
+      updateUserContext()
+    }
+  })
+
+  function updateUserContext () {
+    if (!ldClient.value) { return }
+
+    // Only update context if user is authenticated
+    if (!keycloak.isAuthenticated || !keycloak.kcUser?.keycloakGuid) {
+      console.info('Not updating LaunchDarkly context - user not authenticated')
+      return
+    }
+
+    const appName = useRuntimeConfig().public.appName
+    const user = {
+      key: keycloak.kcUser.keycloakGuid,
+      firstName: keycloak.kcUser.firstName,
+      lastName: keycloak.kcUser.lastName,
+      email: keycloak.kcUser.email || 'unknown@example.com', // Ensure email is never undefined
+      roles: keycloak.kcUser.roles,
+      loginSource: keycloak.kcUser.loginSource,
+      appSource: appName
+    }
+
+    let org = { key: user.key, appSource: appName } // Default to user key if no account
+
+    if (accountStore.currentAccount.id) {
+      org = {
+        key: accountStore.currentAccount.id,
+        accountType: accountStore.currentAccount.accountType,
+        accountStatus: accountStore.currentAccount.accountStatus,
+        type: accountStore.currentAccount.type,
+        label: accountStore.currentAccount.label,
+        appSource: appName
+      }
+    }
+
+    const newContext = { kind: 'multi', org, user } as LDMultiKindContext
+    ldContext.value = newContext
+
+    // Update the LaunchDarkly context
+    ldClient.value.identify(newContext).then(() => {
+      // Update flag values after context change
+      ldFlagSet.value = ldClient.value?.allFlags() || {}
+      console.info('LaunchDarkly context updated successfully')
+    }).catch((error) => {
+      console.error('LaunchDarkly context update error:', error)
+    })
+  }
+
+  function init () {
+    console.info('Initializing LaunchDarkly')
path: business-registry-dashboard/app/stores/connect-launchdarkly.ts
user: login: JazzarKarim
body: Agreed, I put only the ones that are important. 
created_at: 2025-05-01T19:19:50Z
author_association: COLLABORATOR

PR comments:
user: login: JazzarKarim
created_at: 2025-04-30T18:03:15Z
body: /gcbrun
author_association: COLLABORATOR
user: login: bcregistry-sre
created_at: 2025-04-30T18:06:50Z
body: Temporary Url for review: https://business-registry-dev--pr-116-bew54xjh.web.app
author_association: COLLABORATOR
user: login: severinbeauvais
created_at: 2025-04-30T20:29:33Z
body: > ### NOTE: An Ad blocker prevents the app from relaying the contexts to LD. This is why we see sometimes anonymous in LD. Sev, Mihai had this issue at one point if you remember and we were wondering why. This might've been it. The ad blocker MUST be disabled to report back correctly to LD.

I'm a bit surprised by this. Please do a bit of research on this, in case there's a workaround.

I guess using the default context will not cause any Prod issues, since only specific accounts will need targeting. I'm assuming the default LD config is fine for everyone except the exceptions.
author_association: CONTRIBUTOR
user: login: JazzarKarim
created_at: 2025-05-01T19:20:47Z
body: > > ### NOTE: An Ad blocker prevents the app from relaying the contexts to LD. This is why we see sometimes anonymous in LD. Sev, Mihai had this issue at one point if you remember and we were wondering why. This might've been it. The ad blocker MUST be disabled to report back correctly to LD.
> 
> I'm a bit surprised by this. Please do a bit of research on this, in case there's a workaround.
> 
> I guess using the default context will not cause any Prod issues, since only specific accounts will need targeting. I'm assuming the default LD config is fine for everyone except the exceptions.

I'll look into a workaround. Default context won't cause any problems as you mentioned. This will only cause problems to targeted accounts or orgs. 
author_association: COLLABORATOR
user: login: JazzarKarim
created_at: 2025-05-01T19:24:29Z
body: @severinbeauvais Sev, if you select only the last commit, you can see the differences between the one in daxiom package and mine. 
author_association: COLLABORATOR
user: login: JazzarKarim
created_at: 2025-05-01T19:24:38Z
body: /gcbrun
author_association: COLLABORATOR
user: login: bcregistry-sre
created_at: 2025-05-01T19:28:27Z
body: Temporary Url for review: https://business-registry-dev--pr-116-bew54xjh.web.app
author_association: COLLABORATOR