| Field | Value |
|---|---|
| File | C:\Documents\Notes\AI Answer\PR-Review-Gitea-AKWebGen2-PR10-20250210.md |
| PR | git.andalsoftware.com/Andal.Kharisma/AK.Web.Gen2/pulls/10 |
| Decision | REQUEST CHANGES |
| Files Changed | 50+ files |
| Risk Level | MEDIUM-HIGH |
Use this path for next step: C:\Documents\Notes\AI Answer\PR-Review-Gitea-AKWebGen2-PR10-20250210.md
Repository: git.andalsoftware.com/Andal.Kharisma/AK.Web.Gen2 PR Number: 10 Feature: Identity Delegation with Cross-Stack Integration Stacks Affected: DevOps/Infrastructure, E2E Testing (Playwright), Frontend (Angular)
This PR introduces a comprehensive identity delegation feature allowing users to act on behalf of others within the PMS module. The implementation spans CI/CD pipelines, Kubernetes infrastructure, E2E testing infrastructure, and Angular frontend code with cross-project dependencies.
Overall Assessment: The feature is well-architected with good separation of concerns, but has critical security issues (hardcoded credentials) and high-priority concerns (CI/CD security, production logging) that must be addressed before merge.
Top 3 Critical Recommendations:
- [SECURITY]: Remove hardcoded test credentials from E2E fixtures - Risk of production exposure
- [SECURITY]: Add checksum verification for kubectl download in CI/CD pipeline
- [QUALITY]: Remove console.log statements from production auth code
- [N/A] No database changes in this PR
- E2E tests for delegation identity flow
- Unit tests for dashboard components
- Auth service integration tests
- Missing: API contract tests for GraphQL mutations
- Missing: Load testing for delegation queries
- Input validation in auth forms
- CRITICAL: Hardcoded credentials in test files
- JWT token handling
- HIGH: Kubectl download without checksum verification
- MEDIUM: No rate limiting on ingress
- MEDIUM: console.log in production code
.gitea/workflows/ci-pms.yml(new)manifests/pms.yaml(new)angular.json(modified)
Strengths:
- Uses Gitea Actions secrets for registry authentication
- Timeout configured (15 minutes) for build job
- Sparse checkout reduces repository download size
- Multi-stage pipeline (generate-tag -> build -> deploy)
Security Concerns:
| Severity | Issue | Location | Recommendation |
|---|---|---|---|
| HIGH | Kubectl download without checksum | ci-pms.yml:66 | Add SHA256 checksum verification |
| HIGH | KUBE_CONFIG in environment variable | ci-pms.yml:70 | Use Gitea secrets with masking |
| MEDIUM | Sed pattern matching for image replacement | ci-pms.yml:73 | Use yq or kustomize for manifest updates |
| LOW | No resource limits on deploy job | ci-pms.yml:56 | Add resource constraints |
Code Quality Issues:
# Line 66-67 - UNSAFE: No checksum verification
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
# RECOMMENDATION:
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
# Verify checksum
echo "$(curl -s https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl.sha256) kubectl" | sha256sum --check
chmod +x kubectlStrengths:
- Uses cert-manager for TLS (letsencrypt-prod)
- Security headers configured (server_tokens off, cache control)
- Health probes implemented (liveness/readiness)
- Infisical integration for secrets management
- Resource limits for memory (1Gi limit, 256Mi request)
Security Concerns:
| Severity | Issue | Location | Recommendation |
|---|---|---|---|
| MEDIUM | No CPU limits/requests | pms.yaml:179-183 | Add CPU constraints |
| MEDIUM | No pod security context | pms.yaml:166-206 | Add runAsNonRoot, readOnlyRootFilesystem |
| MEDIUM | No network policies | - | Implement network segmentation |
| LOW | Placeholder image tag pattern | pms.yaml:175 | Use kustomize or helm for templating |
| LOW | No rate limiting on ingress | pms.yaml:105-134 | Add nginx rate limit annotations |
Recommended Security Context Addition:
spec:
template:
spec:
securityContext:
runAsNonRoot: true
runAsUser: 101 # nginx user
fsGroup: 101
containers:
- name: pms
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALLprojects/andalkharisma-e2e/(new directory - 20+ files)projects/pms-e2e/(new fixtures and page objects)
Strengths:
- Well-structured Page Object Model (POM) pattern
- Command pattern for reusable actions
- Fixture-based test data management
- Comprehensive accessibility testing utilities (@axe-core/playwright)
- Strong TypeScript typing throughout
Test Organization:
projects/andalkharisma-e2e/
├── commands/ # Reusable action commands
├── fixtures/ # Test data and auth fixtures
├── page-objects/ # POM implementations
├── shared/utils/ # Test utilities
└── tests/ # Test specifications
Hardcoded Credentials:
| File | Credential | Risk |
|---|---|---|
fixtures/users.json:676-677 |
t001@mailinator.com / P@ssw0rd | Production exposure risk |
fixtures/users.json:692-693 |
sijr01@mailinator.com / G_O1-?wi | Production exposure risk |
fixtures/users.json:701-702 |
sisr01@mailinator.com / 3O%@Eg!6 | Production exposure risk |
fixtures/auth.fixture.ts:536-546 |
Same credentials with fallbacks | Fallback to hardcoded values |
commands/login.commands.ts:339-345 |
Credentials in command file | Code duplication |
Problematic Pattern:
// fixtures/auth.fixture.ts:536-547
const USERS: Record<UserType, UserCredentials> = {
noDelegation: {
email: process.env.TEST_USER_NO_DELEGATION || 'sisr01@mailinator.com',
password: process.env.TEST_USER_NO_DELEGATION_PASSWORD || '3O%@Eg!6',
// ...
},
withDelegation: {
email: process.env.TEST_USER_WITH_DELEGATION || 'sijr01@mailinator.com',
password: process.env.TEST_USER_WITH_DELEGATION_PASSWORD || 'G_O1-?wi',
// ...
},
};Recommendation: Remove fallback values. Fail fast if environment variables are not set:
const getRequiredEnv = (name: string): string => {
const value = process.env[name];
if (!value) throw new Error(`Required environment variable ${name} not set`);
return value;
};| Issue | Location | Recommendation |
|---|---|---|
| Fixed timeouts | delegation-identity.spec.ts:2140 |
Use proper wait conditions instead of waitForTimeout |
| Hardcoded ports | Multiple files | Extract to configuration |
| Duplicate user definitions | auth.fixture.ts, users.json, login.commands.ts | Centralize in single source of truth |
Covered:
- Identity selection modal display
- Main account vs delegated identity selection
- Session storage state verification
- Cross-application navigation
Gaps:
- No negative test cases for invalid delegation states
- No network failure scenarios
- No concurrent user testing
projects/andalkharisma/src/app/core/interceptors/auth-context-link.ts(new)projects/andalkharisma/src/app/shared/components/dashboard/(modified)projects/andalkharisma/src/app/app.config.ts(modified)projects/andalkharisma/src/app/shared/services/auth.service.ts(modified)
Strengths:
- Proper Apollo Link middleware implementation
- Reads tokens fresh from storage on each request
- Handles both localStorage and sessionStorage
- Adds CustomerId header for multi-tenant schema switching
- Comprehensive error handling
Issues:
| Severity | Issue | Line | Recommendation |
|---|---|---|---|
| HIGH | console.log in production | 2661, 2663 | Remove or use proper logging service |
| MEDIUM | No token expiration check | - | Validate token before adding to headers |
Problematic Code:
// Lines 2661-2664
if (customerId && customerId !== 'null') {
headers['CustomerId'] = customerId;
console.log('AuthContextLink: Adding CustomerId header:', customerId); // REMOVE
} else {
console.log('AuthContextLink: No CustomerId found in storage'); // REMOVE
}Strengths:
- Proper delegation check before redirect
- Error handling with user feedback
- Modal state management with RxJS subscriptions
- Proper cleanup in ngOnDestroy
Issues:
| Severity | Issue | Recommendation |
|---|---|---|
| MEDIUM | Direct window.location.href manipulation | Use Angular Router with navigation extras |
| LOW | Hardcoded sessionStorage key | Use IDENTITY_SESSION_KEY constant consistently |
Cross-Project Dependency Risk:
// dashboard.component.ts:3337-3341
// Imports from PMS project - TIGHT COUPLING
import { IdentityService } from '../../../../../../pms/src/app/core/services/identity.service';
import { OnBehalfDelegation } from '../../../../../../pms/src/app/core/models/delegation.types';
import { IDENTITY_SESSION_KEY } from '../../../../../../pms/src/app/core/constants/delegation.constants';
import { SelectIdentityModalComponent } from '../../../../../../pms/src/app/components/delegation/select-identity-modal/select-identity-modal.component';Risk: Changes to PMS project structure or exports will break AndalKharisma.
Recommendation: Extract shared types and services to shared-lib project.
Breaking Changes:
logIn(email, password, rememberMe)->logIn(email, password)storeTokens(tokenResponse, rememberMe)->storeTokens(tokenResponse)- Removed
rememberMeproperty fromLoginFormComponent
Impact: Any code calling these methods with the old signature will fail.
Strengths:
- Simplified token storage (always localStorage)
- Added
getAuthContext()for Apollo integration - Better cross-tab persistence
Issues:
| Severity | Issue | Recommendation |
|---|---|---|
| MEDIUM | console.log in getCustomerId() | Remove or use debug logger |
| LOW | customerId optional in TokenResponseDto | Document when it's optional |
Strengths:
- Comprehensive unit tests for dashboard delegation flows
- Tests for conditional redirect, modal trigger, post-modal navigation
- Performance tests (<50ms execution time assertions)
Issues:
- Tests use jasmine spies extensively - may mask integration issues
- Mocking window.location.href instead of testing Router navigation
AndalKharisma (Frontend)
├── imports IdentityService from PMS (TIGHT COUPLING)
├── imports SelectIdentityModalComponent from PMS
├── imports delegation types from PMS
└── E2E tests validate integration
PMS (Micro-frontend)
├── deployed by CI/CD pipeline
├── K8s manifests define infrastructure
└── receives auth tokens from AndalKharisma
E2E Tests
├── depend on both apps running
├── validate cross-app delegation flow
└── test auth context propagation
| Component | Change | Impact |
|---|---|---|
| AuthService.logIn() | Removed rememberMe parameter | Any caller with 3 args breaks |
| AuthService.storeTokens() | Removed rememberMe parameter | Internal only - low risk |
| LoginFormComponent | Removed rememberMe property | Template bindings may break |
| URL format | Changed /#? to /? |
External bookmarks may break |
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| PMS changes break AndalKharisma | High | High | Extract shared code to library |
| Hardcoded credentials leak | Medium | Critical | Remove fallbacks immediately |
| CI/CD pipeline compromised | Low | High | Add checksum verification |
| E2E tests flaky | Medium | Medium | Replace fixed timeouts |
-
Remove Hardcoded Credentials
// BEFORE: email: process.env.TEST_USER_NO_DELEGATION || 'sisr01@mailinator.com', // AFTER: email: getRequiredEnv('TEST_USER_NO_DELEGATION'),
-
Add Kubectl Checksum Verification
- name: Install kubectl with verification run: | KUBECTL_VERSION=$(curl -L -s https://dl.k8s.io/release/stable.txt) curl -LO "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl" curl -LO "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl.sha256" echo "$(cat kubectl.sha256) kubectl" | sha256sum --check chmod +x kubectl
-
Remove console.log from Production Code
auth-context-link.tslines 2661, 2663auth.service.tsline 4394
-
Add Kubernetes Security Context
securityContext: runAsNonRoot: true runAsUser: 101 readOnlyRootFilesystem: true
-
Extract Cross-Project Imports to Shared Library
- Move IdentityService, delegation types to
shared-lib - Prevents tight coupling between projects
- Move IdentityService, delegation types to
-
Add CPU Limits to K8s Manifests
resources: limits: cpu: 500m memory: 1Gi requests: cpu: 100m memory: 256Mi
-
Replace Fixed Timeouts in E2E Tests
// BEFORE: await page.waitForTimeout(3000); // AFTER: await page.waitForSelector('.modal', { state: 'hidden' });
- Add rate limiting to ingress
- Use kustomize/helm for manifest templating
- Add network policies for pod-to-pod communication
| Metric | Score | Notes |
|---|---|---|
| Code Quality | 75/100 | Good structure, some production logging |
| Test Coverage | 80/100 | Comprehensive E2E and unit tests |
| Security | 60/100 | Critical credential issue, CI/CD concerns |
| Documentation | 70/100 | Good inline comments, missing architecture docs |
| Cross-Stack Integration | 65/100 | Tight coupling between projects |
Overall Quality Score: 70/100
- Remove hardcoded credentials from E2E fixtures
- Add kubectl checksum verification to CI/CD
- Remove console.log statements from production code
- Add Kubernetes security contexts
- Verify environment variable configuration in CI/CD
- Test delegation flow in staging environment
- Verify breaking changes don't affect other micro-frontends
- Monitor E2E test stability
- Set up alerting for CI/CD pipeline failures
- Plan extraction of shared code to library
| Stack | Files Added | Files Modified | Total |
|---|---|---|---|
| DevOps | 2 | 1 | 3 |
| E2E Tests | 25+ | 0 | 25+ |
| Frontend | 10+ | 15+ | 25+ |
| Total | 37+ | 16+ | 53+ |
Review saved to: C:\Documents\Notes\AI Answer\PR-Review-Gitea-AKWebGen2-PR10-20250210.md