Skip to content

Frontend/cosmetology scaffold#1292

Merged
isabeleliassen merged 17 commits intocsg-org:mainfrom
InspiringApps:frontend/cosmo-scaffold
Feb 19, 2026
Merged

Frontend/cosmetology scaffold#1292
isabeleliassen merged 17 commits intocsg-org:mainfrom
InspiringApps:frontend/cosmo-scaffold

Conversation

@jsandoval81
Copy link
Collaborator

@jsandoval81 jsandoval81 commented Feb 11, 2026

Requirements List

  • New GitHub secrets (CSG)
    • DEV_WEBROOT_COGNITO_CLIENT_ID_STAFF_COSMO
      • The value will be from the CSG AWS test environment => Cognito Staff User Pool for Cosmetology => Oauth Client ID
  • New .env variables
    • VUE_APP_API_STATE_ROOT_COSMO
    • VUE_APP_API_LICENSE_ROOT_COSMO
    • VUE_APP_API_SEARCH_ROOT_COSMO
    • VUE_APP_API_USER_ROOT_COSMO
    • VUE_APP_COGNITO_AUTH_DOMAIN_STAFF_COSMO
    • VUE_APP_COGNITO_CLIENT_ID_STAFF_COSMO
    • IA frontend devs can get values from @jsandoval81
    • IA backend / CSG devs can use values from their sandbox

Description List

  • Updated store & top level components with an AppMode (JCC or COSMETOLOGY)
    • Existing app components can later evaluate this as needed to conditionally show / hide things
  • Updated network interceptors to evaluate the AppMode and change the outgoing request URI as needed
  • Updated PublicDashboard page based on new designs
  • Added temporary text to the nav menu that displays the current AppMode
    • Can be toggled in the browser console with ccModeToggle()
  • Updated the Public Dashboard with a new button for COSMO staff login
    • Better designs for this are WIP; may be part of this PR, may not
  • Compact & State Settings
    • Don't display the Authorize.net config for Cosmetology
    • Compact & State config card UI expectedly (& gracefully) show network errors currently for Cosmetology. The backend plans to add these endpoints at a later time pending some spec discussionsAdmin users
  • Removed the google recaptcha disclaimer text from recaptcha pages, per google's latest updates
  • Removed form subtext from state upload page (Remove subtext on compact data upload screen #1293)
  • Updated the backend CSP Lambda with new Cosmetology domains
  • Updated the backend deployment & distribution configs with new env variables

Testing List

  • yarn test:unit:all should run without errors or warnings
  • yarn serve should run without errors or warnings
  • yarn build should run without errors or warnings
  • /backend/compact-connect-ui-app bin/run_tests.sh -l all -no should run without errors or warnings
  • Code review
  • Testing
    • Make sure your frontend .env is updated
    • (IA) Coordinate getting a Cosmo Staff user created in IA Test
    • Smoke test new PublicDashboard page layout
    • Make sure Cosmetology license types don't show up in registration & MFA recovery forms
    • Make sure you can do the following for Cosmetology and JCC
      • Login as Staff
      • Perform licensee searches
      • Admin users
      • Basically anything JCC staff can do; except Compact & State settings management
        • Can confirm the Authorize.net config for Cosmetology is not displayed
        • Compact & State config cards UI expectedly (& gracefully) show network errors currently for Cosmetology. The backend plans to add these endpoints at a later time pending some spec discussions
      • If you ever are uncertain if the app is in the correct AppMode you can toggle the display of the app mode in the navigation bar by running this in browser console: ccModeToggle()

Closes #1281
Closes #1293

Summary by CodeRabbit

  • New Features

    • Added Cosmetology (COSMO) application mode with mode-aware login/logout flows, app-mode display/debug toggle, updated public dashboard/login UI, and network behavior that switches endpoints by mode.
    • Introduced Cosmetology & Esthetics compact and license types (EN/ES).
  • Bug Fixes

    • Updated Content-Security-Policy and runtime headers to allow COSMO endpoints.
  • Documentation

    • Expanded environment configuration and setup guidance for COSMO variables.
  • Other

    • Admin email login link updated to COSMO-specific bypass.

- Added the concept of an app-mode to track jcc vs. cosmo switching
- @todo: Get actual .env values for API & cognito & begin smoke testing
- @todo: Implement interceptors to evaluate which API to call
- @todo: Update mock data with cosmo data
- @todo: Update ChangePassword component (if needed)
- @todo: Add debug component to nav that displays app-mode
- Add debug component to nav that displays app-mode
- @todo: Get actual .env values for API & cognito & begin smoke testing
- @todo: Implement interceptors to evaluate which API to call
- @todo: Update mock data with cosmo data & to handle app mode
- @todo: Update ChangePassword component (if needed)
- Get actual .env values for API & cognito & begin smoke testing
- Implement initial interceptors switch
- @todo: Continue smoke testing
- @todo: Update mock data with cosmo data & to handle app mode
- @todo: Update ChangePassword component (if needed)
- Update axios dependency for dependabot alert
- Update mock data api with minimal support for cosm compact
- Continue smoke testing
- @todo: Update backend 'bypass' params to support cosm login passthrough
- @todo: Update CSP Lambda & related Python with new cosm domains
- @todo: Update ChangePassword component (if needed)
- Update backend lambda for the CSP header response
- Update backend 'bypass' param for cosmetology staff
- Updated frontend README with new .env vars
- Continue smoke testing
- @todo: Work with backend team to get ui stack configured with cosmetology SSM values
- @todo: Work with backend team to resolve issues with `/v1/compacts/cosm` endpoint
- @todo: Work with backend team to resolve cognito scopes for pw mgmt for JCC & Cosmo (may be separate PR?)
- @todo: Work with backend team to resolve ui_domain_name SSM param for cosmetology (if needed)
- @todo: Update ChangePassword UI component (if needed)
- @todo: Continue smoke testing
- Work with backend team to get ui stack configured with cosmetology SSM values
- Work with backend team to resolve plan for eventual `/v1/compacts/cosm` endpoint
- Work with backend team to resolve ui_domain_name SSM param for cosmetology
- Continue smoke testing
- @todo: Update ChangePassword UI component (if needed)
- @todo: Continue smoke testing
- Update backend test snapshots
- @todo: Update ChangePassword UI component (if needed)
- @todo: Continue smoke testing
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 11, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds Cosmetology (COSMO) support across frontend and backend: new AppModes and Cognito state types, COSMO environment variables, app-mode-aware login/token flows, network interceptors routing to COSMO APIs, CloudFront CSP updates to allow COSMO domains, locale/UI additions, and CDK/deployment changes to propagate COSMO config.

Changes

Cohort / File(s) Summary
CI / Build
.github/workflows/check-webroot.yml
Add COSMO VUE_APP_* and VUE_APP_COGNITO_*_COSMO env vars into job and build-step environments.
CDK stacks & deployment
backend/compact-connect-ui-app/stacks/.../__init__.py, backend/compact-connect-ui-app/stacks/.../deployment.py, backend/compact-connect-ui-app/stacks/.../distribution.py
Load cosmetology persistent SSM config, validate presence, forward cosmetology config into BucketDeployment and UIDistribution, inject COSMO env vars into bundle/CSP lambda generation.
CloudFront CSP Lambda & tests
backend/compact-connect-ui-app/lambdas/nodejs/cloudfront-csp/index.js, .../test/index.test.js, tests/resources/snapshots/*_DISTRIBUTION*.json, *_LAMBDA_FUNCTION*.json
Include COSMO env keys and add COSMO domains (dataApiCosmo, searchApiCosmo, s3UploadUrlStateCosmo, cognitoStaffCosmo) in CSP image/media/connect directives; update tests and snapshots.
Cosmetology backend email
backend/cosmetology-app/lambdas/nodejs/lib/email/cognito-email-service.ts, .../test.ts
Update admin-create-user email login link to use bypass=login-staff-cosmo and adjust tests.
Env & docs
webroot/.env.example, webroot/README.md
Add COSMO API root and Cognito env entries; document new env/CDK/SSM/deployment steps.
Env config plugin
webroot/src/plugins/EnvConfig/envConfig.plugin.ts
Expose apiUrlCosmo and cognitoCosmo fields and populate them from VUE_APP_*_COSMO vars.
App config & models
webroot/src/app.config.ts, webroot/src/models/Compact/Compact.model.ts
Add AppModes and CognitoStateTypes enums, add CompactType.COSMETOLOGY, add state to CognitoConfig, update getCognitoConfig/getHostedLoginUri signatures to accept appMode.
Auth flow / callbacks & pages
webroot/src/pages/AuthCallback/*, webroot/src/pages/PublicDashboard/*, webroot/src/pages/Logout/*, webroot/src/pages/MfaReset*/*
Refactor AuthCallback to handle STAFF_JCC/STAFF_COSMO/LICENSEE_JCC states with new token methods; set appMode on token success; add COSMO hosted URIs, bypass handlers, mock login flows.
Network layer & interceptors
webroot/src/network/*/data.api.ts, webroot/src/network/*/interceptors.ts, webroot/src/network/mocks/*
Change initInterceptors signatures to (router, store); interceptor factories accept store and conditionally set baseURL to COSMO endpoints when appMode === AppModes.COSMETOLOGY; update mocks and permissions.
Store: global & user
webroot/src/store/global/*, webroot/src/store/user/*
Add appMode and isAppModeDisplayed to state, mutations/actions (setAppMode/setAppModeDisplay), initialize appMode=JCC; user token refresh reads rootState.appMode to choose COSMO vs STAFF Cognito settings.
UI: App, nav, dashboard & settings
webroot/src/components/App/App.ts, .../CompactSelector.ts, .../PageMainNav.*, webroot/src/pages/PublicDashboard/*, webroot/src/pages/CompactSettings/*
Derive/persist app mode from selected compact, add developer toggle to show mode, display app mode in nav, present COSMO login options in dashboard, gate PaymentProcessorConfig to JCC, restructure PublicDashboard UI.
Locales
webroot/src/locales/en.json, webroot/src/locales/es.json
Add Cosmetology compact and license-types (Cosmetologist, Esthetician) and new navigation subtexts.
Misc (tests/entry/icons/styles)
webroot/src/main.ts, various tests, SVG/icon, less files
Pass store into initInterceptors, update tests for new signatures/app-mode behavior, small icon/template/style updates and removals of recaptcha terms blocks.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Client as Frontend
    participant Store as Vuex
    participant Router
    participant Cognito as CognitoIDP
    participant Auth as AuthCallback
    participant API as Backend/API

    User->>Client: Click "Login (Staff COSMO)"
    Client->>Store: dispatch setAppMode(AppModes.COSMETOLOGY)
    Client->>Router: navigate to hosted login (state=STAFF_COSMETOLOGY)
    Cognito->>User: Authenticate and redirect with code+state
    User->>Auth: Browser hits /auth/callback
    Auth->>Store: read state -> STAFF_COSMETOLOGY
    Auth->>Cognito: getTokensStaffCosmo(code)
    Cognito-->>Auth: tokens
    Auth->>Store: store tokens, ensure appMode=COSMETOLOGY
    Client->>API: Request (interceptor sees appMode COSMETOLOGY)
    API->>Backend: Use apiUrl*Cosmo endpoints
    Backend-->>Client: response
Loading
sequenceDiagram
    participant App as App Component
    participant Router
    participant Store
    participant CompactCfg as Compact Config

    App->>Router: await ready
    Router->>CompactCfg: parse route compact param -> expected AppModes
    Router->>Store: if mismatch -> dispatch setAppMode(expected)
    Store-->>App: appMode updated (mutation)
    App->>App: setAppModeFromCompact(...) and enable debugger
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Suggested reviewers

  • jlkravitz
  • ChiefStief
  • isabeleliassen
  • landonshumway-ia

"🐰
I hopped through code with nimble paws,
Added COSMO modes and learned the laws.
Tokens, CSP and envs aligned,
App modes set and routes refined.
Beauty APIs now hum — hooray! ✨"

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Frontend/cosmetology scaffold' is vague and does not clearly convey the specific technical changes being made to the codebase. Use a more descriptive title that captures the main changes, such as 'Add AppMode support for Cosmetology compact' or 'Implement multi-compact API routing with Cosmetology support'.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR addresses all primary coding requirements from #1281 (AppMode support, network interceptors, auth flows, compact routing) and #1293 (form subtext removal), with implementation spanning frontend store, components, network layers, and backend Lambda/deployment configs.
Out of Scope Changes check ✅ Passed All changes are within scope of the linked issues. Frontend changes support AppMode routing, network interceptors use AppMode to select correct APIs, Cosmetology license types are excluded from registration/MFA flows, state upload subtext is removed, and backend CSP/deployment configs are updated for Cosmetology domains.
Description check ✅ Passed The PR description provides comprehensive details covering requirements, descriptions, testing steps, and linked issue references.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
webroot/src/pages/MfaResetStartLicensee/MfaResetStartLicensee.ts (1)

109-122: ⚠️ Potential issue | 🟠 Major

Ensure the MFA reset backend endpoint supports the cosm compact value from cosmetology license types.

The licenseTypeOptions getter includes all entries from licensing.licenseTypes, which now includes Cosmetologist and Esthetician with compactKey: 'cosm'. When selected, getCompactFromlicenseType() (line 290) will resolve to 'cosm' and pass it to the backend via prepRequestData(). The frontend validates that a compact value exists (lines 324–325), but the backend must be able to handle the cosm compact gracefully to prevent opaque failures for cosmetology users.

webroot/src/network/licenseApi/data.api.ts (1)

535-548: ⚠️ Potential issue | 🟡 Minor

getLicenseeSsn bypasses interceptors and always uses the JCC license URL.

This method creates a standalone axios.get call with envConfig.apiUrlLicense hardcoded, bypassing the interceptor-based baseURL override. When appMode is COSMETOLOGY, this will still hit the JCC endpoint instead of envConfig.apiUrlLicenseCosmo.

If SSN retrieval is expected to work for Cosmetology licensees, this needs a similar conditional:

Proposed fix
     public async getLicenseeSsn(compact: string, licenseeId: string) {
         // This endpoint requires bypassing our regular error-handler interceptors.
         const authTokenStaff = authStorage.getItem(tokens.staff.AUTH_TOKEN);
         const authTokenStaffType = authStorage.getItem(tokens.staff.AUTH_TOKEN_TYPE);
-        const serverResponse: any = await axios.get(`${envConfig.apiUrlLicense}/v1/compacts/${compact}/providers/${licenseeId}/ssn`, {
+        const baseUrl = /* determine from store or other mechanism */ envConfig.apiUrlLicense;
+        const serverResponse: any = await axios.get(`${baseUrl}/v1/compacts/${compact}/providers/${licenseeId}/ssn`, {

Note: Since this method doesn't have access to the store (it's not passed through), you'd need to either pass the store/appMode into the method or find another way to resolve the correct base URL. This may be fine to defer if Cosmetology SSN retrieval isn't needed yet.

🤖 Fix all issues with AI agents
In `@webroot/README.md`:
- Around line 175-182: The README has inconsistent formatting for the
VUE_APP_COGNITO_CLIENT_ID_STAFF_COSMO entries: change the Beta value from plain
TODO to inline code by wrapping it in backticks (i.e., make it `TODO`) so it
matches the other TODO entries and the surrounding entries for
VUE_APP_COGNITO_CLIENT_ID_STAFF_COSMO.

In `@webroot/src/components/App/App.ts`:
- Around line 115-127: The guard in setAppModeFromCompact prevents re-evaluating
the route compact type because globalStore.appMode is never reset on logout;
update the logout/session-clear flow so appMode is cleared so
setAppModeFromCompact (and subsequent calls to
this.$store.dispatch('setAppMode', ...)) can re-run: either add appMode to the
STORE_RESET_GLOBAL mutation so it resets to null/undefined on logout, or
explicitly clear appMode in clearSessionStores during session teardown; ensure
CompactType and AppModes logic remains the same so route compact types are
honored on each new login.

In `@webroot/src/pages/AuthCallback/AuthCallback.ts`:
- Around line 81-107: The fallback token-fetching sequence (methods
getTokensStaffJcc, getTokensStaffCosmo, getTokensLicenseeJcc) never dispatches
setAppMode, so store.state.appMode remains default and interceptors use wrong
base URLs; after each successful token fetch in the fallback path, dispatch
setAppMode with the corresponding mode (e.g., JCC or COSMO) and update any
related state used by the interceptors so subsequent API calls use the correct
base URL, and ensure you only set isError = true if all token attempts fail.

In `@webroot/src/pages/PublicDashboard/PublicDashboard.vue`:
- Around line 89-100: The aria-label for the COSMO staff login button does not
match the visible text (visible includes "COSMO" but aria-label uses
$t('navigation.loginAsStaff')), violating label-in-name; update the accessible
name so it includes "COSMO" — either add a new i18n key like
navigation.loginAsStaffCosmo and use
:aria-label="$t('navigation.loginAsStaffCosmo')" for the element that uses
bypassToStaffLoginCosmo (and mirror this for the non-mock anchor that
concatenates COSMO), or concatenate the translated string with " COSMO" in the
aria-label so the aria-label matches the visible text while keeping the
click/keyup handlers (bypassToStaffLoginCosmo) and StaffUserIcon intact.

In `@webroot/src/store/global/global.state.ts`:
- Line 29: The boolean default for the debug flag isAppModeDisplayed should be
switched off for release: change its initializer from true to false in the
global state object (isAppModeDisplayed: false) and update the TODO comment to
indicate it is intentionally disabled for production; also scan for any code
that programmatically toggles isAppModeDisplayed on initialization (e.g., code
that reads from dev configs or env vars) and ensure those paths are guarded so
the debug display remains disabled by default.
🧹 Nitpick comments (8)
.github/workflows/check-webroot.yml (1)

57-66: Consider upgrading pinned GitHub Actions to current major versions.

actions/checkout@v2 and actions/setup-node@v1 are significantly outdated (current majors are v4). Older versions may lack security patches and features. This is pre-existing, so no need to address in this PR, but worth tracking.

webroot/src/pages/AuthCallback/AuthCallback.ts (1)

62-65: setAppMode dispatches are not awaited before proceeding to token fetch.

On lines 67, 72, and 77, this.$store.dispatch('setAppMode', ...) is called without await. If the interceptors or any downstream code reads appMode during the token fetch, it might see a stale value. Since getTokensStaffJcc/getTokensStaffCosmo/getTokensLicenseeJcc use axios.post directly (not the store-intercepted axios), this is likely fine in practice, but it's worth noting for consistency.

webroot/src/components/CompactSelector/CompactSelector.ts (1)

149-153: Minor: missing await on dispatch('setAppMode', ...).

Line 148 uses await on the preceding dispatch, but lines 150/152 fire-and-forget. For consistency and to ensure ordering, consider awaiting these as well.

♻️ Suggested fix
-            if (selectedCompactType === CompactType.COSMETOLOGY) {
-                this.$store.dispatch('setAppMode', AppModes.COSMETOLOGY);
-            } else {
-                this.$store.dispatch('setAppMode', AppModes.JCC);
-            }
+            if (selectedCompactType === CompactType.COSMETOLOGY) {
+                await this.$store.dispatch('setAppMode', AppModes.COSMETOLOGY);
+            } else {
+                await this.$store.dispatch('setAppMode', AppModes.JCC);
+            }
webroot/src/pages/Logout/Logout.ts (1)

46-46: Nit: getter name hostedLogoutUriStaff is now ambiguous.

Since this getter now handles both JCC and COSMO staff logout URIs, the name hostedLogoutUriStaff doesn't fully convey its dual-mode behavior. Consider renaming to something like hostedLogoutUriStaffByMode in a follow-up, purely for clarity.

webroot/src/network/mocks/mock.data.api.ts (1)

605-616: Remove or downgrade the debug console.log on Line 609.

console.log('deleting non-cosm staff user compacts') will emit noise in test output and dev console. Consider removing it or gating it behind a verbose/debug flag, consistent with the PR's own TODO to hide AppMode debug display by default.

Proposed fix
         if (mockStore?.state?.appMode === AppModes.COSMETOLOGY) {
-            console.log(`deleting non-cosm staff user compacts`);
             delete account.permissions.octp;
             delete account.permissions.aslp;
             delete account.permissions.coun;
         }
webroot/src/components/App/App.ts (1)

234-244: Debug hook on window — ensure it's excluded or guarded in production builds.

addAppModeDebugger() is called unconditionally in created(), attaching ccModeToggle to the global window object in all environments. While it only toggles a display flag (low risk), consider gating it behind a dev/non-production check to keep the production window surface clean.

💡 Optional: Guard behind environment check
 addAppModeDebugger(): void {
+    if (this.globalStore.appEnv === 'production') {
+        return;
+    }
     appWindow.ccModeToggle = () => {
webroot/src/pages/PublicDashboard/PublicDashboard.spec.ts (1)

62-81: Consider adding a test for hostedLoginUriStaffCosmo.

The new hostedLoginUriStaffCosmo computed property in PublicDashboard.ts is not covered by any test. Consider adding a test analogous to the existing staff URI test (lines 62-71) to verify the Cosmo staff hosted login URI includes the correct state (e.g., &state=staff-cosmetology or equivalent CognitoStateTypes.STAFF_COSMETOLOGY value), scope, and callback path.

webroot/src/pages/PublicDashboard/PublicDashboard.ts (1)

104-120: Consider extracting a shared bypassToStaffLogin with a mode parameter to reduce duplication.

bypassToStaffLogin() and bypassToStaffLoginCosmo() differ only in the AppModes value and hosted URI. A single method accepting the mode could serve both bypass cases. Fine to defer since this is scaffold work.

💡 Optional: Unified bypass method
-    bypassToStaffLogin(): void {
-        if (this.isUsingMockApi) {
-            this.mockStaffLogin(AppModes.JCC);
-        } else {
-            this.$store.dispatch('startLoading');
-            window.location.replace(this.hostedLoginUriStaff);
-        }
-    }
-
-    bypassToStaffLoginCosmo(): void {
-        if (this.isUsingMockApi) {
-            this.mockStaffLogin(AppModes.COSMETOLOGY);
-        } else {
-            this.$store.dispatch('startLoading');
-            window.location.replace(this.hostedLoginUriStaffCosmo);
-        }
-    }
+    bypassToStaffLogin(appMode: AppModes = AppModes.JCC): void {
+        if (this.isUsingMockApi) {
+            this.mockStaffLogin(appMode);
+        } else {
+            const uri = appMode === AppModes.COSMETOLOGY
+                ? this.hostedLoginUriStaffCosmo
+                : this.hostedLoginUriStaff;
+            this.$store.dispatch('startLoading');
+            window.location.replace(uri);
+        }
+    }

Then update bypassRedirect:

         case 'login-staff-cosmo':
-            this.bypassToStaffLoginCosmo();
+            this.bypassToStaffLogin(AppModes.COSMETOLOGY);
             break;

- Minor updates from backend workflow checks
- @todo: Update ChangePassword UI component (if needed)
- @todo: Continue smoke testing
- Set default state of app mode display to false
- PR review feedback
- @todo: Continue smoke testing
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@backend/cosmetology-app/lambdas/nodejs/package.json`:
- Around line 7-8: Remove the extra leading space before the "fast-xml-parser"
property in package.json so its indentation matches the preceding dependency
line ("@aws-sdk/client-sesv2") — update the line containing "fast-xml-parser":
"5.3.4" to have the same left alignment as the "@aws-sdk/client-sesv2" entry to
fix the whitespace inconsistency.
🧹 Nitpick comments (4)
webroot/src/store/global/global.spec.ts (1)

103-117: Consider also testing with AppModes.COSMO.

Both new mutation tests only exercise the JCC value (SET_APP_MODE) or true (SET_APP_MODE_DISPLAY). Since COSMO is the new mode being introduced, adding a case that sets AppModes.COSMO (and false for display) would strengthen coverage of the feature this PR adds.

webroot/src/pages/AuthCallback/AuthCallback.ts (2)

89-114: .then().catch() chaining means a rejected setAppMode dispatch would incorrectly increment errorCount.

If this.$store.dispatch('setAppMode', ...) inside .then() were to reject, the chained .catch() would catch that rejection and increment errorCount, even though the token fetch itself succeeded. This would cause the fallback to incorrectly attempt the next pool (or enter the error state) despite having valid tokens.

The risk is low since setAppMode is likely a simple synchronous mutation, but the control flow conflates token-fetch failures with post-fetch dispatch failures. Separating concerns makes the intent explicit:

Proposed fix: isolate setAppMode from the token-fetch error path
-            await this.getTokensStaffJcc()
-                .then(() => {
-                    this.$store.dispatch('setAppMode', AppModes.JCC);
-                })
-                .catch(() => {
-                    errorCount += 1;
-                });
+            await this.getTokensStaffJcc()
+                .catch(() => {
+                    errorCount += 1;
+                });
+
+            if (errorCount === 0) {
+                this.$store.dispatch('setAppMode', AppModes.JCC);
+            }

Apply the same pattern to the getTokensStaffCosmo and getTokensLicenseeJcc blocks below.


128-171: Three near-identical token-fetch methods — consider a shared helper.

getTokensStaffJcc, getTokensStaffCosmo, and getTokensLicenseeJcc differ only in which env-config keys they read and which AuthTypes value they dispatch. A single parameterized helper would eliminate the duplication and make adding future compacts (e.g., a Cosmetology licensee flow) a one-liner.

♻️ Example helper extraction
+    private async fetchTokens(
+        cognitoAuthDomain: string,
+        cognitoClientId: string,
+        authType: string,
+    ): Promise<void> {
+        const { domain } = this.$envConfig;
+        const params = new URLSearchParams();
+
+        params.append('grant_type', 'authorization_code');
+        params.append('client_id', cognitoClientId || '');
+        params.append('redirect_uri', `${domain}${this.$route.path}`);
+        params.append('code', this.authorizationCode);
+
+        const { data } = await axios.post(`${cognitoAuthDomain}/oauth2/token`, params);
+
+        await this.$store.dispatch('user/updateAuthTokens', { tokenResponse: data, authType });
+        await this.$store.dispatch('user/loginSuccess', authType);
+    }
+
     async getTokensStaffJcc(): Promise<void> {
-        const { domain, cognitoAuthDomainStaff, cognitoClientIdStaff } = this.$envConfig;
-        const params = new URLSearchParams();
-
-        params.append('grant_type', 'authorization_code');
-        params.append('client_id', cognitoClientIdStaff || '');
-        params.append('redirect_uri', `${domain}${this.$route.path}`);
-        params.append('code', this.authorizationCode);
-
-        const { data } = await axios.post(`${cognitoAuthDomainStaff}/oauth2/token`, params);
-
-        await this.$store.dispatch('user/updateAuthTokens', { tokenResponse: data, authType: AuthTypes.STAFF });
-        await this.$store.dispatch('user/loginSuccess', AuthTypes.STAFF);
+        const { cognitoAuthDomainStaff, cognitoClientIdStaff } = this.$envConfig;
+        return this.fetchTokens(cognitoAuthDomainStaff, cognitoClientIdStaff, AuthTypes.STAFF);
     }

Repeat for getTokensStaffCosmo and getTokensLicenseeJcc.

backend/compact-connect-ui-app/stacks/frontend_deployment_stack/distribution.py (1)

132-136: Consider using keyword arguments for clarity.

Two of the three parameters share the same type (PersistentStackFrontendAppConfigValues), so a positional mix-up would be silent. Named arguments make the mapping explicit and guard against accidental transposition.

♻️ Suggested change
         csp_function_code = generate_csp_lambda_code(
-            persistent_stack_frontend_app_config_values,
-            persistent_stack_frontend_app_config_values_cosmetology,
-            provider_users_stack_frontend_app_config_values
+            persistent_stack_values=persistent_stack_frontend_app_config_values,
+            persistent_stack_values_cosmetology=persistent_stack_frontend_app_config_values_cosmetology,
+            provider_users_stack_values=provider_users_stack_frontend_app_config_values,
         )

- PR review feedback
- @todo: Continue smoke testing
Copy link
Collaborator

@landonshumway-ia landonshumway-ia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, just one nit comment but doesn't hold up my approval

- Implement new public dashboard page
- Remove cosmetology license types from registration & mfa recovery screens
- Remove form subtext from state upload form (csg-org#1293)
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@webroot/src/pages/PublicDashboard/PublicDashboard.less`:
- Around line 40-50: The .lower modifier on the splash uses bottom: -5px which
can cause the SVG to overflow or clip; update the .lower rule (and related
.splash-image styling) to remove the negative offset — set bottom: 0 or replace
the negative offset with a non-destructive adjustment such as transform:
translateY( -5px ) on the inner SVG (or adjust stroke alignment/shape-rendering)
so the visual compensation doesn't push the element outside its container;
ensure container overflow handling remains correct if you keep any visual
offset.

In `@webroot/src/pages/PublicDashboard/PublicDashboard.vue`:
- Around line 12-33: The two decorative SVGs (the <svg> elements with class
"splash-image upper" and "splash-image lower" in the PublicDashboard.vue
template) should be marked as non‑interactive for assistive tech; add
aria-hidden="true" to each of those <svg> elements (the ones inside the divs
with class "splash-image-container upper" and "splash-image-container lower") so
screen readers ignore the path data.
🧹 Nitpick comments (2)
webroot/src/pages/RegisterLicensee/RegisterLicensee.ts (1)

88-102: Consider a denylist instead of an allowlist for future-proofing.

The hardcoded allowlist means any new compact added to CompactType in the future will be silently excluded from registration until a developer remembers to update this array. A denylist approach (e.g., filtering out CompactType.COSMETOLOGY) would automatically include future compacts, which is typically the safer default for a registration flow.

That said, the allowlist is more explicit and arguably safer during this scaffolding phase, so this is a minor consideration.

Alternative denylist approach
-        const enabledCompacts = [
-            CompactType.ASLP,
-            CompactType.OT,
-            CompactType.COUNSELING,
-        ];
-
-        licenseTypes
-            .filter((licenseType) => enabledCompacts.includes(licenseType.compactKey))
+        const disabledCompacts = [
+            CompactType.COSMETOLOGY,
+        ];
+
+        licenseTypes
+            .filter((licenseType) => !disabledCompacts.includes(licenseType.compactKey))
webroot/src/pages/PublicDashboard/PublicDashboard.vue (1)

92-169: Consider using v-for to reduce repetition in compact login buttons.

The four compact-type blocks (ASLP, OT, COUNSELING, COSMETOLOGY) share identical structure and only differ in the compact type and the login URI/handler (JCC vs COSMO). This could be driven by a computed array that maps each compact to its URI and handler, reducing ~75 lines of near-duplicate template code.

Understood this is WIP — deferrable if the designs may diverge per compact.

Copy link
Collaborator

@rmolinares rmolinares left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job! 🚀

@jsandoval81
Copy link
Collaborator Author

@jlkravitz This is ready for your review.

Copy link
Collaborator

@jlkravitz jlkravitz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

few small questions! I'd like to do a full deploy but I may wait for the 'sprint review' and do that in a couple of days (I'll have better internet :))

jlkravitz
jlkravitz previously approved these changes Feb 17, 2026
Copy link
Collaborator

@jlkravitz jlkravitz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, beautiful new home page design!

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
backend/compact-connect-ui-app/lambdas/nodejs/package.json (1)

34-36: Security fix via Yarn resolutions properly applied

The resolutions override pins fast-xml-parser to version 5.3.6, which addresses two active CVEs in entity expansion and numeric entity processing. Version 5.3.6 is confirmed as the latest release on npm. The yarn.lock file has been correctly regenerated with the pinned version.

Optional consideration: The exact version pin "5.3.6" will not automatically absorb future security patch releases. If the intent is to allow patch-level updates while maintaining the security fix, consider using ">=5.3.6" instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/compact-connect-ui-app/lambdas/nodejs/package.json` around lines 34 -
36, The package.json currently pins fast-xml-parser under the "resolutions"
field to the exact version "5.3.6"; if you want to allow future patch-level
security fixes while keeping the minimum safe version, change the resolution
value for "fast-xml-parser" from "5.3.6" to ">=5.3.6" and then regenerate your
lockfile (run yarn install / yarn set version && yarn install as appropriate) so
yarn.lock reflects the new range; the key symbols to update are the
"resolutions" object and the "fast-xml-parser" entry in package.json and then
commit the updated yarn.lock.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@backend/compact-connect-ui-app/lambdas/nodejs/package.json`:
- Around line 34-36: The package.json currently pins fast-xml-parser under the
"resolutions" field to the exact version "5.3.6"; if you want to allow future
patch-level security fixes while keeping the minimum safe version, change the
resolution value for "fast-xml-parser" from "5.3.6" to ">=5.3.6" and then
regenerate your lockfile (run yarn install / yarn set version && yarn install as
appropriate) so yarn.lock reflects the new range; the key symbols to update are
the "resolutions" object and the "fast-xml-parser" entry in package.json and
then commit the updated yarn.lock.

@jsandoval81
Copy link
Collaborator Author

@jlkravitz I just resolved merge conflicts + dependency alerts. This is ready for re-approval when you get a chance.

jlkravitz
jlkravitz previously approved these changes Feb 19, 2026
Copy link
Collaborator

@jlkravitz jlkravitz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@isabeleliassen Good to go!

@jsandoval81
Copy link
Collaborator Author

@jlkravitz More merge conflicts just resolved - this will need reapproval once the last check passes.

@isabeleliassen isabeleliassen merged commit ab2f945 into csg-org:main Feb 19, 2026
7 of 8 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Mar 3, 2026
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove subtext on compact data upload screen Frontend support for multiple compact APIs

5 participants