Skip to content

Instantly share code, notes, and snippets.

@jeje-andal
Created February 24, 2026 07:12
Show Gist options
  • Select an option

  • Save jeje-andal/e72b5689da7e6eb790463f66cbead4e8 to your computer and use it in GitHub Desktop.

Select an option

Save jeje-andal/e72b5689da7e6eb790463f66cbead4e8 to your computer and use it in GitHub Desktop.
PR Review: PR #20 - PMS AuthLink Fix & KPI Strategy Pattern (MVP 1 - Sprint 6 - PMS)

PR Review Metadata

Field Value
File C:\Documents\Notes\AI Answer\PR-Review-Gitea-AK.Web.Gen2-20-20260224.md
PR https://git.andalsoftware.com/Andal.Kharisma/AK.Web.Gen2/pulls/20
Decision CONDITIONAL APPROVAL
Files 37 changed
Risk MEDIUM-HIGH

Use this path for next step: C:\Documents\Notes\AI Answer\PR-Review-Gitea-AK.Web.Gen2-20-20260224.md


PR Review Report: PR #20 - AK.Web.Gen2

Executive Summary

This PR implements critical authentication fixes for the PMS micro-frontend, introducing a dynamic AuthLink Apollo middleware to resolve stale JWT token issues. It also adds identity bootstrapping for fresh logins and implements a Strategy pattern for KPI data loading. While the core changes are architecturally sound and address real security concerns, there are test hygiene issues and commented-out code that need resolution before merge.

Overall Assessment: The AuthLink implementation is a critical security fix that addresses a fundamental flaw where static context was evaluated once at startup before token exchange completed. The Strategy pattern implementation for KPI data loading demonstrates good separation of concerns.


Stack Analysis

Affected Micro-Frontends

Micro-Frontend Files Changed Impact Level
PMS (Performance Management System) 35 files HIGH
shared-lib Indirect (via auth patterns) LOW

Technology Stack

  • Framework: Angular v20 with standalone components
  • State Management: RxJS BehaviorSubjects
  • GraphQL: Apollo Client with custom Link chain
  • UI Components: DevExtreme Angular
  • Testing: Karma/Jasmine

Critical Findings

CRITICAL: AuthLink Implementation - Security Fix

File: projects/pms/src/app/core/interceptors/auth-link.ts (NEW)

The Problem Being Fixed: The previous implementation used defaultOptions.context which was evaluated once at config time before the token exchange completed. This resulted in stale/empty Authorization headers on GraphQL requests after fresh login.

The Solution:

// AuthLink reads token dynamically from localStorage on EACH request
export class AuthLink extends ApolloLink {
    private static request(operation: Operation, forward?: NextLink) {
        const accessToken = AuthLink.getAccessToken(); // Fresh read every time
        if (accessToken) {
            operation.setContext({
                headers: {
                    ...operation.getContext()['headers'],
                    Authorization: `Bearer ${accessToken}`,
                },
            });
        }
        return forward ? forward(operation) : null;
    }
}

Applied To All Apollo Clients:

  • Default client (PMS GraphQL)
  • Named clients: pms, hrms, dpt, orchestrator

Security Considerations:

  • Properly guards against SSR (typeof window === 'undefined')
  • Handles private browsing mode gracefully (try/catch around localStorage)
  • Uses ACCESS_TOKEN_KEY constant for consistent key naming

Recommendation: APPROVED - This is a critical security fix that resolves authentication race conditions.


HIGH: Identity Service Bootstrap

File: projects/pms/src/app/core/services/identity.service.ts

Changes:

  1. Added identityReady$ BehaviorSubject to signal when identity context is initialized
  2. Implements bootstrapIdentityForFreshLogin() method
  3. Dashboard component now waits for identityReady$ before loading data

Code Pattern:

// DRR-2026-02-20: Bootstrap identity on fresh login
if (!this.targetIdentityContext$.value) {
    this.bootstrapIdentityForFreshLogin();
} else {
    this.identityReadySubject$.next(true);
}

Impact: Prevents "not authorized" errors on fresh login by ensuring identity context is established before API calls.

Recommendation: APPROVED - Properly handles the identity initialization race condition.


MEDIUM: Strategy Pattern for KPI Data Loading

New Files:

  • projects/pms/src/app/features/setting-kpi/strategies/kpi-data-loading.strategy.ts
  • projects/pms/src/app/features/setting-kpi/strategies/settings-kpi.strategy.ts
  • projects/pms/src/app/features/setting-kpi/strategies/review-kpi.strategy.ts
  • projects/pms/src/app/features/setting-kpi/strategies/monitoring-kpi.strategy.ts

Implementation: Abstract strategy class with three concrete implementations:

Strategy Behavior
SettingsKPIStrategy Returns empty array if no job position, else fetches by hierarchy
ReviewKPIStrategy Same as Settings - returns empty array if no job position
MonitoringKPIStrategy Always fetches ALL KPIs (admin/HR only) using new kpiDetailsForMonitoringAll query

New GraphQL Query:

query KpiDetailsForMonitoringAll {
    kpiDetailsForMonitoringAll { ... }
}

Recommendation: APPROVED - Clean separation of concerns, properly documented with DRR reference.


WARNING: Test File Hygiene Issues

Issue 1: Commented-Out Test Code (Do Not Merge)

File: projects/pms/src/app/core/services/auth-logout-integration.service.spec.ts

afterEach(() => {
    // Restore window.location
    // window.location = originalWindowLocation;  // <-- COMMENTED OUT
});

File: projects/pms/src/app/features/competency/components/assessment/self-assessment/self-assessment.component.spec.ts

it('should hide dialog', () => {
    component.showConfirmDialog = true;
    // component.cancelSubmission();  // <-- COMMENTED OUT
    expect(component.showConfirmDialog).toBeFalse();
});

Recommendation: Either restore the code or delete the test. Commented-out code should not be committed.

Issue 2: Integration Test Deletion

Deleted Files:

  • projects/pms/src/app/features/kpi-approval/tests/index.ts
  • projects/pms/src/app/features/kpi-approval/tests/integration-test-utils.ts
  • projects/pms/src/app/features/kpi-approval/tests/kpi-approval.integration.spec.ts
  • projects/pms/src/app/features/kpi-approval/tests/test-config.ts

Impact: Integration test coverage removed. Verify this is intentional and that E2E tests (Playwright) provide adequate coverage.

Issue 3: Multiple Spec Files Deleted

Deleted Spec Files:

  • kpi-approval.service.spec.ts
  • kpi-monitoring.component.spec.ts
  • kpi-review-history.component.spec.ts
  • kpi-settings.component.spec.ts
  • kpi-submission-history.component.spec.ts
  • kpi.service.spec.ts

Recommendation: Verify these deletions are intentional. If tests were failing and removed rather than fixed, this reduces test coverage.


WARNING: Service Bug Fix

File: projects/pms/src/app/features/kpi-approval/services/kpi-approval.service.ts

Fix: Added null check for approverId to avoid GraphQL validation errors:

// Return empty array if no current employee (avoids GraphQL validation error)
if (!approverId) {
    this.pendingApprovalsSubject$.next([]);
    return new BehaviorSubject<ApprovalStatus[]>([]).asObservable();
}

Also added error propagation:

catchError(error => {
    const errorMessage = this.extractError(error);
    this.errorSubject$.next(errorMessage);  // <-- Now propagates to error$
    return throwError(() => errorMessage);
})

Recommendation: APPROVED - Proper defensive programming.


INFO: Duplicate Test Code Fixed

File: projects/pms/src/app/features/settings/components/workflow-configuration/status-color-mapping.service.spec.ts

Issue: Multiple duplicate lines removed:

// Before (duplicate):
const op = controller.expectOne(UPSERT_GENERAL_SETTINGS);
const op = controller.expectOne(UPSERT_GENERAL_SETTINGS);  // Duplicate removed

// Before (duplicate test definition):
it('should return value string on successful save', done => { ... });
it('should return value string on successful save', done => { ... });  // Duplicate removed

Recommendation: APPROVED - Code cleanup.


Code Quality Assessment

Positive Patterns

  1. DRR Comments: Design Rationale Records included (DRR-2026-02-20)
  2. JSDoc Documentation: Comprehensive comments on AuthLink and strategies
  3. Error Handling: Proper try/catch around localStorage access
  4. RxJS Patterns: Proper use of BehaviorSubject, takeUntilDestroyed
  5. Dependency Injection: Modern inject() function used instead of constructor injection

Areas for Improvement

  1. Test Coverage: Significant test file deletions need justification
  2. Commented Code: Two instances of commented-out test code should be resolved
  3. GraphQL Context: AuthLink removes need for authService.getAuthContext() in defaultOptions but it's still used in getAllKPIsForMonitoring() - verify consistency

Architecture Compliance

Principle Status Notes
Feature-Based Architecture PASS Changes confined to features/ directory
Standalone Components PASS No NgModule changes detected
Strategy Pattern PASS Proper abstraction for KPI loading
Apollo Link Chain PASS AuthLink -> CustomerIdLink -> TargetIdentityLink -> HttpLink
Barrel Exports PASS strategies/index.ts properly exports all strategies

Security Review

Check Status Notes
Token Storage PASS Uses localStorage with proper guards
SSR Safety PASS Checks typeof window before localStorage access
Private Mode PASS try/catch handles localStorage unavailability
Authorization Header PASS Proper Bearer ${token} format
Token Refresh N/A Not in scope - handled by token exchange initializer

Performance Implications

  1. AuthLink Overhead: Minimal - localStorage read is synchronous and fast
  2. Identity Bootstrap: One-time cost on fresh login, prevents subsequent auth errors
  3. Strategy Pattern: No runtime overhead - DI resolves strategy at component creation
  4. Monitoring Query: New kpiDetailsForMonitoringAll fetches all KPIs - ensure pagination or filtering on large datasets

Test Coverage Impact

Metric Before After Change
Spec Files 37+ ~28 -9 files
Integration Tests 1 suite 0 -1 suite

Recommendation: Verify that E2E tests (Playwright) provide adequate coverage for the removed integration tests.


Prioritized Recommendations

Before Merge (Blocking)

  1. Resolve commented-out test code in:

    • auth-logout-integration.service.spec.ts (line 235)
    • self-assessment.component.spec.ts (line 314)
  2. Document test deletions - Add PR description explaining why integration tests and spec files were removed

After Merge (Non-blocking)

  1. Consider adding unit tests for AuthLink class
  2. Verify getAllKPIsForMonitoring() still needs manual authService.getAuthContext() or if AuthLink handles it
  3. Monitor error rates for "not authorized" errors post-deployment

Quality Metrics Dashboard

Category Score Weight Weighted
Code Quality 85/100 25% 21.25
Security 95/100 25% 23.75
Architecture 90/100 20% 18.00
Test Coverage 60/100 20% 12.00
Documentation 90/100 10% 9.00
Overall 84.0/100

Score Interpretation: 84/100 = Good with minor issues


Action Items

  • Remove or restore commented-out test code
  • Add PR description documenting test file deletions
  • Verify E2E test coverage compensates for removed integration tests
  • Confirm getAllKPIsForMonitoring auth context handling is intentional
  • Run full test suite: npm test (PMS project)
  • Run lint check: npm run quality:pms

Cross-Stack Impact

Stack Impact Notes
PMS HIGH Core auth and identity changes
Recruitment NONE No files changed
Andalkharisma NONE No files changed
shared-lib INDIRECT Auth patterns may need replication

Breaking Changes: None detected - all changes are internal to PMS.


Final Decision

CONDITIONAL APPROVAL

This PR addresses critical authentication issues with the AuthLink implementation and improves architecture with the Strategy pattern. However, the commented-out test code must be resolved before merge. The test file deletions should be documented in the PR description.

Merge Criteria:

  1. Remove commented-out code OR restore with explanation
  2. Document rationale for test file deletions
  3. Verify CI passes with npm run quality:pms

Review generated by Claude Code - Multi-Stack PR Orchestrator v5.0 Date: 2026-02-24 Files Analyzed: 37 changed files across PMS micro-frontend

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment