Improvement Plan
Ecosistema completo para organización y gestión de contenido con interfaces espaciales
Security Library - Improvement Plan
Date: 2025-09-29 Library: @libs-core/security Status: Analysis Complete - Ready for Implementation Priority: High - Core security library
Executive Summary
The security library is well-structured and functional, but requires improvements to align with project standards defined in CLAUDE.md. This document outlines specific violations, technical debt, and a prioritized action plan.
Current State
- ✅ Angular 20 standalone components and signals
- ✅ Multi-tenancy support with context isolation
- ✅ JWT authentication with refresh tokens
- ✅ RBAC implementation
- ✅ Integration with log-system, event-system, shared-models
- ⚠️ 3 failing tests (CSRFTokenService injection issues)
- ❌ Multiple violations of project standards
Critical Violations (Must Fix)
1. Timer Usage - NO SETIMEOUTS Rule Violation
Location: libs/core/security/src/lib/auth/token.service.ts:116
// ❌ VIOLATION: Using timer for periodic checks
this.autoRefreshSubscription = timer(0, 30000) // verificar cada 30 segundos
.pipe(
filter(() => this.shouldRefresh()),
switchMap(() => this.refreshAccessToken()),
catchError((error) => {
console.error('Error en auto-refresh:', error);
return EMPTY;
})
)
.subscribe();
Impact: Violates core principle "do not use setTimeouts"
Solution: Implement event-driven token refresh
- Use token expiration date to calculate exact refresh time
- Subscribe to authentication state changes
- Use Angular's zone-aware observables
- Trigger refresh on HTTP 401 responses
Priority: 🔴 Critical
2. Console Usage - Missing LoggerService Integration
Locations: Multiple files use console.error/log instead of LoggerService
Files affected:
- token.service.ts:100
- token.service.ts:106
- token.service.ts:122
- token.service.ts:244
- token.service.ts:291
- token.service.ts:303
- auth.service.ts:182
- auth.service.ts:198
- auth.service.ts:209
- auth.service.ts:538
- auth.service.ts:601
- auth.service.ts:620
- auth.service.ts:642
Impact: Missing centralized logging, debugging, and monitoring capabilities
Solution:
- Inject LoggerService from @libs-core/log-system
- Use appropriate log levels (trace, debug, info, warn, error, critical)
- Add correlation IDs for multi-tenant tracking
- Use @loggable and @logError decorators where applicable
Priority: 🔴 Critical
3. Promises Instead of RxJS
Location: libs/core/security/src/lib/utils/crypto.utils.ts
Problem: Functions encryptForStorage and decryptFromStorage use async/await with Promises
// ❌ VIOLATION: Using Promises
export async function encryptForStorage(
data: string,
password: string
): Promise<{ encrypted: string; salt: string; iv: string }> {
// ... async/await code
}
Impact: Violates "Always use rxJS, never use promises"
Solution: Convert to Observable-based API
export function encryptForStorage(
data: string,
password: string
): Observable<{ encrypted: string; salt: string; iv: string }> {
return from(performEncryption(data, password));
}
Priority: 🔴 Critical
High Priority Issues
4. Test Failures - CSRFTokenService Injection
Test Results:
❌ CSRFTokenService > token management > should get token for specific tenant
→ NG0203: The `LoggerService2` token injection failed. inject() must be called from an injection context
❌ CSRFTokenService > token management > should clear all tokens
→ NG0203: The `LoggerService2` token injection failed. inject() must be called from an injection context
❌ CSRFTokenService > token management > should clear token for specific tenant
→ NG0203: The `LoggerService2` token injection failed. inject() must be called from an injection context
Root Cause: CSRFTokenService tries to inject LoggerService outside of Angular injection context
Solution:
- Ensure TestBed properly provides LoggerService
- Use
runInInjectionContextfor service instantiation in tests - Review CSRFTokenService constructor injection
Priority: 🟡 High
5. Missing Input/Output Signal Usage
Current State: Most directives still use @Input() and @Output() decorators
Affected Files:
- All directive files in
src/lib/directives/
Solution: Migrate to Angular 20 signal inputs/outputs
// ❌ Current
@Input() permission!: string;
@Output() accessDenied = new EventEmitter<void>();
// ✅ Preferred
permission = input.required<string>();
accessDenied = output<void>();
Priority: 🟡 High
Medium Priority Improvements
6. Enhance SOLID Principles
Single Responsibility Violations:
AuthService (883 lines) handles too many responsibilities:
- Authentication (login, logout)
- Token management
- Context selection/switching
- Permission checking
- Role checking
- Event emission
Recommendation: Split into smaller, focused services:
AuthenticationService: Login/logout operationsAuthorizationService: Permission/role checksTenantContextService: Context selection/switching (may exist as ContextService)
Priority: 🟠 Medium
7. Improve Error Handling
Current Issues:
- Generic error messages
- Inconsistent error types
- Limited error context
Example:
// ❌ Current
catch (error) {
console.error('Error inicializando tokens:', error);
return this.clearTokens();
}
// ✅ Improved
catch (error) {
this.logger.error('Token initialization failed', {
error,
operation: 'token_init',
tenantId: this.contextService.getCurrentTenantId(),
correlationId: this.generateCorrelationId()
});
throw new TokenInitializationError(
'Failed to initialize authentication tokens',
{ cause: error, recoverable: true }
);
}
Priority: 🟠 Medium
8. Add Performance Decorators
Current State: No performance monitoring on critical methods
Solution: Use @performance decorator from log-system
@performance({ threshold: 100, level: 'warn' })
login(credentials: LoginCredentials): Observable<LoginResult> {
// ...
}
@performance({ threshold: 50 })
refreshAuthentication(): Observable<void> {
// ...
}
Priority: 🟠 Medium
9. Improve Change Detection Strategy
Current State: Not all directives explicitly declare OnPush
Solution: Ensure all directives use OnPush
@Directive({
selector: '[hasPermission]',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush // Add this
})
Priority: 🟠 Medium
Low Priority Enhancements
10. Documentation Improvements
Missing Documentation:
- Complex authentication flows
- Multi-tenant context switching
- Token refresh mechanism
- CSRF protection details
Priority: 🟢 Low
11. Add More Unit Tests
Current Coverage: Good, but could be improved
Areas needing more tests:
- Edge cases in token expiration
- Complex permission scenarios
- Multi-tenant context switching
- Error recovery flows
Priority: 🟢 Low
12. TypeScript Strict Mode Compliance
Current Issues: Some any types still exist
Solution: Replace with proper types or SafeAny from utilities
Priority: 🟢 Low
Implementation Roadmap
Phase 1: Critical Fixes (Week 1)
Goal: Fix all critical violations
- ✅ Create improvement plan document
- ⬜ Remove timer-based auto-refresh in TokenService
- ⬜ Replace all console.* with LoggerService
- ⬜ Convert crypto.utils Promises to Observables
- ⬜ Fix CSRFTokenService test failures
- ⬜ Run full test suite and ensure all pass
Success Criteria:
- No timer/setTimeout usage
- No console.* usage
- All tests passing
- 100% Observable usage
Phase 2: High Priority Improvements (Week 2)
Goal: Modernize to Angular 20 standards
- ⬜ Migrate directives to signal inputs/outputs
- ⬜ Add @performance decorators to critical methods
- ⬜ Improve error handling with proper error classes
- ⬜ Enhance logging with correlation IDs
- ⬜ Add OnPush change detection to all directives
Success Criteria:
- All directives use signal inputs/outputs
- Performance monitoring in place
- Rich error context
- Consistent change detection
Phase 3: Architecture Improvements (Week 3)
Goal: Enhance SOLID principles and maintainability
- ⬜ Evaluate AuthService split (SRP)
- ⬜ Implement extracted services if needed
- ⬜ Add integration tests for complex flows
- ⬜ Document authentication flows
- ⬜ Add architectural decision records (ADRs)
Success Criteria:
- Services follow SRP
- Complex flows documented
- Integration test coverage >80%
Phase 4: Polish & Documentation (Week 4)
Goal: Complete documentation and add remaining tests
- ⬜ Complete API documentation
- ⬜ Add usage examples
- ⬜ Create migration guide (if breaking changes)
- ⬜ Add edge case tests
- ⬜ Final code review and cleanup
Success Criteria:
- Complete documentation
- Test coverage >90%
- All TypeScript strict mode compliant
Risk Assessment
Breaking Changes Risk: Medium
Potential breaking changes:
- Crypto utilities API change (Promise → Observable)
- Possible AuthService split
- Signal inputs/outputs in directives
Mitigation:
- Provide backwards compatibility layer
- Clear migration guide
- Gradual deprecation warnings
Performance Impact: Low
Changes unlikely to affect performance:
- Event-driven token refresh is more efficient than polling
- LoggerService has minimal overhead
- Signal inputs/outputs improve performance
Testing Effort: Medium
Testing requirements:
- Unit tests for all changed code
- Integration tests for authentication flows
- E2E tests for critical paths
Success Metrics
Code Quality
- 0 timer/setTimeout usage
- 0 console.* usage
- 100% Observable usage (no Promises)
- Test coverage >90%
- All tests passing
- 0 TypeScript
anytypes
Architecture
- Services follow SOLID principles
- Clear separation of concerns
- Proper error handling with context
- Performance monitoring in place
Documentation
- Complete API documentation
- Usage examples
- Architecture diagrams
- Migration guides (if needed)
Dependencies & Coordination
Internal Dependencies
- ✅ @libs-core/log-system (already integrated)
- ✅ @libs-core/event-system (already integrated)
- ✅ @libs-core/shared-models (already integrated)
- ✅ @gograb-space/utilities (already integrated)
External Dependencies
- Angular 20.x
- RxJS 7.x
- Web Crypto API (browser)
Coordination Required
- Module integrator team (for breaking changes)
- UI framework team (for directive changes)
- User management module (for authentication changes)
Next Steps
- Review this plan with team/stakeholders
- Prioritize items based on project timeline
- Create Nx tasks for each phase
- Start Phase 1 - Critical fixes
- Track progress using TodoWrite tool
Appendix A: File-by-File Analysis
Authentication Services
AuthService
- File:
src/lib/auth/auth.service.ts - Lines: 883
- Issues:
- 6 console.error usages
- SRP violation (too many responsibilities)
- Missing @performance decorators
- Priority: High
TokenService
- File:
src/lib/auth/token.service.ts - Lines: 375
- Issues:
- timer(0, 30000) usage (critical)
- 6 console.error usages
- Missing @performance decorators
- Priority: Critical
SessionService
- File:
src/lib/auth/session.service.ts - Status: Not reviewed yet
- Priority: Medium
Utilities
crypto.utils
- File:
src/lib/utils/crypto.utils.ts - Lines: 255
- Issues:
- async/await with Promises (critical)
- encryptForStorage function
- decryptFromStorage function
- Priority: Critical
jwt.utils
- File:
src/lib/utils/jwt.utils.ts - Status: ✅ Appears clean
- Priority: Low
Interceptors
context.interceptor
- File:
src/lib/interceptors/context.interceptor.ts - Status: ✅ Good implementation with LoggerService
- Priority: Low
csrf.interceptor
- File:
src/lib/interceptors/csrf.interceptor.ts - Issues: 3 test failures
- Priority: High
Directives
All directive files need:
- Migration to signal inputs/outputs
- OnPush change detection
Files:
has-permission.directive.tshas-any-permission.directive.tshas-all-permissions.directive.tshas-role.directive.tshas-any-role.directive.tshas-minimum-role.directive.tsis-admin.directive.tssecure-content.directive.ts
Priority: High
Appendix B: Code Examples
Example 1: Token Refresh (Event-Driven)
Current (timer-based):
private setupAutoRefresh(): void {
this.autoRefreshSubscription = timer(0, 30000) // ❌ Poll every 30 seconds
.pipe(
filter(() => this.shouldRefresh()),
switchMap(() => this.refreshAccessToken()),
catchError((error) => {
console.error('Error en auto-refresh:', error);
return EMPTY;
})
)
.subscribe();
}
Proposed (event-driven):
private setupAutoRefresh(): void {
// Calculate exact time to refresh
const timeToRefresh$ = this.accessToken.pipe(
filter(token => token !== null),
map(token => {
const expiryTime = getJWTTimeToExpiry(token!);
const refreshTime = expiryTime * 0.8; // Refresh at 80% lifetime
return Math.max(0, refreshTime * 1000);
}),
distinctUntilChanged()
);
// Schedule refresh at exact time
this.autoRefreshSubscription = timeToRefresh$.pipe(
switchMap(delayMs => timer(delayMs)),
switchMap(() => this.refreshAccessToken()),
tap(() => this.logger.debug('Token refreshed automatically', {
operation: 'token_auto_refresh'
})),
catchError(error => {
this.logger.error('Token auto-refresh failed', {
error,
operation: 'token_auto_refresh',
recoverable: true
});
return EMPTY;
}),
repeat() // Restart the cycle after each refresh
).subscribe();
}
Example 2: LoggerService Integration
Current:
catch (error) {
console.error('Error inicializando tokens:', error);
return this.clearTokens();
}
Proposed:
catch (error) {
this.logger.error('Token initialization failed', {
error,
operation: 'token_initialization',
tenantId: this.contextService.getCurrentTenantId(),
correlationId: this.sessionService.getCorrelationId(),
recoverable: true
});
return this.clearTokens().pipe(
tap(() => this.logger.info('Tokens cleared after initialization failure', {
operation: 'token_cleanup'
}))
);
}
Example 3: Signal Inputs/Outputs
Current:
@Directive({
selector: '[hasPermission]',
standalone: true
})
export class HasPermissionDirective {
@Input() permission!: string;
@Output() accessDenied = new EventEmitter<void>();
// ...
}
Proposed:
@Directive({
selector: '[hasPermission]',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class HasPermissionDirective {
permission = input.required<string>();
accessDenied = output<void>();
// Computed signals for reactive logic
hasAccess = computed(() =>
this.authService.hasPermission(this.permission())
);
// ...
}
Appendix C: Testing Strategy
Unit Tests
- All services: 100% coverage of public methods
- All utilities: 100% coverage including edge cases
- All directives: Test with various input combinations
Integration Tests
- Complete authentication flow
- Context switching flow
- Token refresh flow
- Permission checking flow
E2E Tests
- User login and navigation
- Session timeout and recovery
- Multi-tenant switching
- Unauthorized access handling
Conclusion
The security library is fundamentally solid but requires targeted improvements to align with project standards. The most critical issues (timer usage, console logging, Promise usage) can be fixed within a week. Following the phased roadmap will result in a production-ready, maintainable, and standards-compliant security library.
Estimated Total Effort: 3-4 weeks Risk Level: Medium (some breaking changes possible) Business Value: High (core security improvements)
Document Version: 1.0 Last Updated: 2025-09-29 Next Review: After Phase 1 completion