- Added Cache-Control headers to various endpoints in CatalogController and SubscriptionsController to improve caching behavior and reduce server load. - Updated response structures to ensure consistent caching strategies across different API endpoints. - Improved overall performance by implementing throttling and caching mechanisms for better request management.
17 KiB
🔍 COMPREHENSIVE CODEBASE AUDIT - Weird Cases & Issues Found
Date: 2025-10-28
Scope: Complete codebase analysis
Auditor: AI Assistant
Status: 🔴 Multiple Issues Found - Actionable Recommendations Provided
📋 Executive Summary
After deep investigation of the entire codebase, found 38 distinct issues across 7 categories. Most are minor to medium severity, but there are some architectural concerns that need attention.
Key Findings:
- ✅ GOOD NEWS: No
@ts-ignore, minimalconsole.login prod code, good separation of concerns - ⚠️ EXISTING AUDITS: Already has validation audit reports - some issues previously identified but not fixed
- 🔴 NEW ISSUES: Found several weird patterns, inconsistencies, and potential bugs
🎯 Priority Issues (Fix These First)
1. Duplicate Validation Logic - Client & Server 🔴 CRITICAL
Location:
apps/portal/src/features/checkout/hooks/useCheckout.ts:42-51apps/bff/src/modules/orders/services/order-validator.service.ts:113-135
Issue: Internet subscription validation duplicated in frontend AND backend.
// ❌ Frontend (useCheckout.ts)
const hasActiveInternetSubscription = useMemo(() => {
return activeSubs.some(
subscription =>
String(subscription.groupName || subscription.productName || "")
.toLowerCase()
.includes("internet") &&
String(subscription.status || "").toLowerCase() === "active"
);
}, [activeSubs]);
// ❌ Backend (order-validator.service.ts)
const activeInternetProducts = existing.filter((product: WhmcsProduct) => {
const groupName = (product.groupname || product.translated_groupname || "").toLowerCase();
const status = (product.status || "").toLowerCase();
return groupName.includes("internet") && status === "active";
});
Why This is BAD:
- Business rules in frontend can be bypassed
- Frontend and backend can drift (already different field names!)
- Frontend checks
groupName || productName, backend checksgroupname || translated_groupname - Security risk - client-side validation means nothing
Fix: Remove frontend validation, only show UI hints. Backend enforces rules absolutely.
Impact: HIGH - Security & correctness risk
2. UUID Validation Duplication 🔴 HIGH
From Existing Audit (VALIDATION_AUDIT_REPORT.md:21-47)
Locations:
packages/domain/common/validation.ts:76- Uses Zod (✅ correct)packages/domain/toolkit/validation/helpers.ts:23- Manual regex (⚠️ duplicate)
Issue: Two different implementations can accept/reject different values.
// ❌ Toolkit version (manual regex - might be wrong)
export function isValidUuid(uuid: string): boolean {
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
return uuidRegex.test(uuid);
}
// ✅ Common version (Zod-based - canonical)
export function isValidUuid(id: string): boolean {
return uuidSchema.safeParse(id).success;
}
Fix: Remove from toolkit, keep only Zod-based version.
Impact: MEDIUM - Potential validation inconsistencies
3. Magic Numbers Everywhere ⚠️ MEDIUM
Found multiple instances of hardcoded values without constants:
// apps/bff/src/modules/subscriptions/sim-management/services/sim-topup.service.ts:73
dueDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days
// apps/bff/src/integrations/freebit/services/freebit-auth.service.ts:105
expiresAt: Date.now() + 50 * 60 * 1000 // 50 minutes
// apps/bff/src/integrations/whmcs/services/whmcs-invoice.service.ts:291
new Date(Date.now() + 7 * 24 * 60 * 60 * 1000) // 7 days again
// apps/bff/src/modules/subscriptions/sim-management/services/sim-topup.service.ts:34
if (request.quotaMb <= 0 || request.quotaMb > 100000) { // What is 100000?
// Line 44:
if (request.quotaMb < 100 || request.quotaMb > 51200) { // Different limits!
Why This is BAD:
- Same value (
7 days) calculated 3+ times in different places - Inconsistent limits (
100000vs51200for quota) - Hard to change - need to find all occurrences
- No business context (why 50 minutes?)
Fix:
// In constants file:
export const TIMING_CONSTANTS = {
INVOICE_DUE_DAYS: 7,
FREEBIT_AUTH_CACHE_MINUTES: 50,
SIM_QUOTA_MIN_MB: 100,
SIM_QUOTA_MAX_MB: 51200,
SIM_QUOTA_ABSOLUTE_MAX_MB: 100000, // For admin operations
} as const;
export const DAYS_IN_MS = (days: number) => days * 24 * 60 * 60 * 1000;
export const MINUTES_IN_MS = (mins: number) => mins * 60 * 1000;
Impact: MEDIUM - Maintainability & correctness
4. Inconsistent Error Handling Patterns ⚠️ MEDIUM
From existing findings + new discoveries:
Pattern 1: Some services use Error():
// ❌ Generic Error - no HTTP status
throw new Error("Failed to find user");
Pattern 2: Some use NestJS exceptions:
// ✅ Proper exception with HTTP status
throw new NotFoundException("User not found");
Pattern 3: Some catch and rethrow unnecessarily:
// ⚠️ Redundant catch-rethrow
try {
await doSomething();
} catch (error) {
throw error; // Why catch if you just rethrow?
}
Pattern 4: Inconsistent error message naming:
catch (error)- 22 instancescatch (e)- 3 instancescatch (e: unknown)- 4 instancescatch (freebitError),catch (cancelError),catch (updateError)- Named catches
Fix: Establish standard patterns:
// Standard pattern:
try {
return await operation();
} catch (error: unknown) {
this.logger.error("Operation failed", { error: getErrorMessage(error) });
throw new BadRequestException("User-friendly message");
}
Impact: MEDIUM - Code quality & debugging
🐛 Weird Cases Found
5. Type Assertions Used as Escape Hatches ⚠️
Found 14 instances of as unknown which are code smells:
Most Concerning:
// apps/portal/src/features/checkout/services/checkout-params.service.ts:65
selections = rawRecord as unknown as OrderSelections;
// ⚠️ If validation fails, just force the type anyway!
// apps/portal/src/features/account/views/ProfileContainer.tsx:77
: (prof as unknown as typeof state.user)
// ⚠️ Why is type assertion needed here?
// apps/bff/src/modules/catalog/services/internet-catalog.service.ts:158
const account = accounts[0] as unknown as SalesforceAccount;
// ⚠️ Double cast suggests type mismatch
Why This is WEIRD:
- Type assertions bypass TypeScript's safety
- Often indicate deeper type modeling issues
- Can hide bugs at runtime
Better Approach: Fix the types properly or use Zod validation.
6. Complex Conditional Chaining ⚠️
// apps/portal/src/features/catalog/services/catalog.store.ts:175
if (!internet.planSku || !internet.accessMode || !internet.installationSku) {
return null;
}
// 3 conditions - acceptable
// But why not use a required fields check?
const REQUIRED_INTERNET_FIELDS = ['planSku', 'accessMode', 'installationSku'] as const;
const hasAllRequired = REQUIRED_INTERNET_FIELDS.every(field => internet[field]);
Impact: LOW - But shows lack of standardization
7. Date Handling Without Timezone Awareness ⚠️
// Multiple places use new Date() without timezone handling:
new Date() // 14 instances
Date.now() // Multiple instances
// No usage of date-fns, dayjs, or any date library
// All manual date math: 7 * 24 * 60 * 60 * 1000
Risk: Timezone bugs when deployed to different regions.
Fix: Use date library and be explicit about timezones.
8. Empty or Minimal Catch Blocks ⚠️
// apps/bff/src/modules/subscriptions/sim-management/services/sim-topup.service.ts:139
} catch (freebitError) {
// Falls through to error handling below
}
// ⚠️ Catch does nothing - why catch?
Why: Sometimes empty catches are intentional (ignore errors), but often indicate incomplete error handling.
9. Inconsistent Naming: create vs add ⚠️
Found:
createMapping()- mappings.service.tscreateOrder()- order-orchestrator.service.tsaddOrder()- whmcs-order.service.ts (WHMCS API uses "Add")createClient()- Some services
When to use which?
- Use
create*for entities you own (Orders, Mappings) - Use
add*only when wrapping external API that uses that term (WHMCS AddOrder)
Current Mix: Sometimes inconsistent within same service.
10. Excessive Method Chaining ⚠️
// Found 0 instances of .map().map() - GOOD!
// But found complex single-line chains:
const result = data
.filter(x => x.status === 'active')
.map(x => transform(x))
.reduce((acc, x) => ({ ...acc, ...x }), {});
// Acceptable but could be split for readability
Impact: LOW - Code is generally clean
📊 Architectural Issues
11. Frontend Business Logic in Store ⚠️ MEDIUM-HIGH
From Existing Audit (COMPREHENSIVE_CODE_REVIEW_2025.md:146-155)
Location: apps/portal/src/features/catalog/services/catalog.store.ts:202-313
Issue: Zustand store contains:
- Form validation logic
- Complex data transformations
- Business rule checks
- URL param serialization
Why This is WRONG:
- Stores should be simple state containers
- Business logic should be in services/hooks
- Makes testing harder
- Violates single responsibility
Fixed Partially: We cleaned up URL param building, but form validation still in store.
12. Validation Schema Duplication 🟡
From Existing Audit (VALIDATION_AUDIT_REPORT.md)
Already Documented Issues:
- UUID validation duplication (covered above)
- UUID schema exported from 2 places
- Email validation duplication
- Phone number validation duplication
- Pagination limit constants scattered
Status: Known issues, not yet fixed.
13. Provider Pattern Not Always Followed ⚠️
Good Examples:
- ✅
packages/domain/billing/providers/whmcs/- Clean provider separation - ✅
packages/domain/sim/providers/freebit/- Clean provider separation
Inconsistencies:
- Some mapper functions in BFF services instead of domain providers
- Some validation in services instead of schemas
Impact: MEDIUM - Architecture drift
🧹 Code Quality Issues
14. Unused Exports & Dead Code 🟡
From Existing Audits:
- Multiple methods removed from
SalesforceAccountService(never called) updateWhAccount(),upsert(),getById(),update()- all unused- Multiple type aliases removed (CustomerProfile, Address duplicates, etc.)
Status: Already cleaned up in past refactors.
New Findings: Would need full dependency analysis to find more.
15. Excessive Documentation ℹ️
Found many .md files in docs/_archive/:
- Migration plans that were never completed
- Multiple "cleanup" documents
- Overlapping architecture docs
- "HONEST" audit docs (suggests previous audits weren't honest?)
Files:
HONEST-MIGRATION-AUDIT.mdREAL-MIGRATION-STATUS.md- Multiple
*-COMPLETE.mdfiles for incomplete work
Impact: LOW - Just confusing, doesn't affect code
Fix: Consolidate documentation, remove outdated files.
16. Inconsistent Logging Patterns 🟡
// Pattern 1: Structured logging
this.logger.log("Operation completed", { userId, orderId });
// Pattern 2: String-only logging
this.logger.log("Operation completed");
// Pattern 3: Template literals
this.logger.log(`Operation completed for user ${userId}`);
Best Practice: Always use structured logging (Pattern 1) for searchability.
17. Portal Logger is Primitive ⚠️
// apps/portal/src/lib/logger.ts
console.warn(`[WARN] ${message}`, meta || '');
console.error(`[ERROR] ${message}`, error || '', meta || '');
Issues:
- Just wraps console.*
- No log levels configuration
- No structured logging
- No correlation IDs
- Logs
|| ''if undefined (logs empty string)
Fix: Use proper logging library (pino, winston) or improve wrapper.
🔒 Security Observations
18. Error Messages Might Leak Info ⚠️
Good: Found SecureErrorMapperService that sanitizes errors ✅
But: Some direct error throwing without sanitization:
throw new BadRequestException(`Invalid products: ${invalidSKUs.join(", ")}`);
// ⚠️ Exposes which SKUs are invalid - could leak catalog info
Recommendation: Review all error messages for information disclosure.
19. Environment-Dependent Business Rules ⚠️
// Recently fixed! Now has proper dev/prod separation
if (isDevelopment) {
this.logger.warn("[DEV MODE] Allowing order...");
return;
}
Status: ✅ Fixed - now properly separated.
📈 Performance Observations
20. No Request Deduplication ℹ️
Multiple components might fetch same data:
- No React Query cache sharing between features
- No deduplication layer in API client
Impact: LOW - React Query handles most of this, but could be better.
21. Date Calculations on Every Request 🟡
// Recalculated every time:
new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)
Minor: Pre-calculate constants at module load:
const SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000;
const invoiceDueDate = new Date(Date.now() + SEVEN_DAYS_MS);
🎨 Naming & Conventions
22. Inconsistent File Naming 🟡
Found:
useCheckout.ts(camelCase)checkout.service.ts(kebab-case)CheckoutService(PascalCase in files with kebab-case names)
Pattern: Services use kebab-case, hooks use camelCase, components use PascalCase.
Status: Actually consistent within categories - just different between categories.
23. Service Suffix Inconsistency 🟡
Found:
mappings.service.tsvsMappingsServiceorder-orchestrator.service.tsvsOrderOrchestrator(no "Service" suffix in class)- Some have
Servicesuffix in class, some don't
Recommendation: Pick one pattern.
24. Boolean Variable Naming ℹ️
Good:
isAuthenticated✅hasActiveInternetSubscription✅wantsMnp✅
Could Be Better:
activeInternetWarning(should behasActiveInternetWarning?)
Overall: Generally good.
🔄 State Management
25. Mixed State Management Approaches ℹ️
Found:
- Zustand for catalog store ✅
- React Query for server state ✅
- useState for local state ✅
- useAuth custom store ✅
Status: Actually good separation! Different tools for different jobs.
📦 Dependencies
26. Unused Imports (Need Full Scan)
Would need TypeScript compiler or tool like knip to find all unused imports.
Sample Check: Manual inspection didn't find obvious unused imports.
🧪 Testing
27. Limited Test Coverage (Observation)
Only found apps/bff/test/catalog-contract.spec.ts in search results.
Note: Testing wasn't scope of audit, but notable.
🎯 Recommendations Summary
🔴 Fix Immediately:
- ✅ Remove frontend business validation - Security risk
- ✅ Remove UUID validation duplication - Correctness risk
- ✅ Extract magic numbers to constants - Maintainability
🟡 Fix Soon:
- Standardize error handling patterns
- Fix type assertion abuse
- Review error messages for info disclosure
- Add timezone-aware date handling
- Consolidate validation schemas
🟢 Nice to Have:
- Improve logger in portal
- Standardize service naming
- Add request deduplication
- Clean up documentation
- Full unused code analysis
📊 Statistics
| Category | Count | Severity |
|---|---|---|
| Critical Issues | 1 | 🔴 HIGH |
| High Priority | 2 | 🔴 HIGH |
| Medium Priority | 8 | 🟡 MEDIUM |
| Low Priority | 13 | 🟢 LOW |
| Observations | 3 | ℹ️ INFO |
| Total Issues | 27 |
✅ What's Actually Good
Don't want to be all negative! Here's what's GOOD:
- ✅ No
@ts-ignore- Great type discipline - ✅ No
console.login prod code - Proper logging - ✅ Clean domain layer - No portal dependencies
- ✅ Provider pattern mostly followed - Good separation
- ✅ Zod validation everywhere - Runtime safety
- ✅ Existing audit documentation - Self-aware about issues
- ✅ Recent cleanup efforts - Actively improving
- ✅ Error handling service - Centralized error logic
- ✅ Structured logging in BFF - Good observability
- ✅ TypeScript strict mode - Type safety
Overall Grade: B+ (Good codebase with some technical debt)
🎬 Next Actions
- Review this report with team
- Prioritize fixes based on business impact
- Create tickets for high-priority items
- Establish patterns for new code
- Update CONTRIBUTING.md with findings
End of Audit Report