Assist_Design/ARCHITECTURE-CLEANUP-ANALYSIS.md

10 KiB

Architecture Cleanup Analysis

Date: October 8, 2025
Status: Plan Mostly Implemented - Minor Cleanup Needed

Executive Summary

The refactoring plan in \d.plan.md has been ~85% implemented. The major architectural improvements have been completed:

Completed:

  • Centralized DB mappers in apps/bff/src/infra/mappers/
  • Deleted FreebitMapperService
  • Moved Freebit utilities to domain layer
  • WHMCS services now use domain mappers directly
  • All redundant wrapper services removed

Remaining Issues:

  1. Pub/Sub event types still in BFF (should be in domain)
  2. Empty transformer directories (should be deleted)
  3. Business error codes in BFF (should be in domain)

Detailed Findings

1. DB Mappers Centralization - COMPLETE

Status: Fully Implemented

Location: apps/bff/src/infra/mappers/

apps/bff/src/infra/mappers/
├── index.ts              ✅
├── user.mapper.ts        ✅
└── mapping.mapper.ts     ✅

Evidence:

  • mapPrismaUserToDomain() properly maps Prisma → Domain
  • mapPrismaMappingToDomain() properly maps Prisma → Domain
  • Old user-mapper.util.ts has been deleted
  • Services are using centralized mappers

This is production-ready and follows clean architecture.


2. Freebit Integration - COMPLETE

Status: Fully Implemented

What was done:

  1. Deleted apps/bff/src/integrations/freebit/services/freebit-mapper.service.ts
  2. Created packages/domain/sim/providers/freebit/utils.ts with:
    • normalizeAccount()
    • validateAccount()
    • formatDateForApi()
    • parseDateFromApi()
  3. Exported utilities from packages/domain/sim/providers/freebit/index.ts
  4. Services now use domain mappers directly:
    • Freebit.transformFreebitAccountDetails()
    • Freebit.transformFreebitTrafficInfo()
    • Freebit.normalizeAccount()

This is production-ready and follows clean architecture.


3. WHMCS Services Using Domain Mappers - COMPLETE

Status: Fully Implemented

Evidence from apps/bff/src/integrations/whmcs/services/whmcs-invoice.service.ts:

// Line 213: Using domain mappers directly
const defaultCurrency = this.currencyService.getDefaultCurrency();
const transformed = Providers.Whmcs.transformWhmcsInvoice(whmcsInvoice, {
  defaultCurrencyCode: defaultCurrency.code,
  defaultCurrencySymbol: defaultCurrency.prefix || defaultCurrency.suffix,
});

Evidence from whmcs-payment.service.ts:

import { Providers } from "@customer-portal/domain/payments";
// Using domain mappers directly

Services are correctly using domain mappers with currency context.


4. Pub/Sub Event Types Still in BFF - NEEDS MIGRATION

Status: Not Implemented

Current Location: apps/bff/src/integrations/salesforce/types/pubsub-events.types.ts

Problem: These are provider-specific raw types for Salesforce Platform Events, but they're still in the BFF layer.

Current types:

// In apps/bff/src/integrations/salesforce/types/pubsub-events.types.ts

export interface SalesforcePubSubSubscription {
  topicName: string;
}

export interface SalesforcePubSubEventPayload {
  OrderId__c?: string;
  OrderId?: string;
  [key: string]: unknown;
}

export interface SalesforcePubSubEvent {
  payload: SalesforcePubSubEventPayload;
  replayId?: number;
}

export interface SalesforcePubSubError {
  details?: string;
  metadata?: SalesforcePubSubErrorMetadata;
  [key: string]: unknown;
}

export type SalesforcePubSubCallbackType = "data" | "event" | "grpcstatus" | "end" | "error";

🔴 RECOMMENDATION:

These are Salesforce provider types and should be moved to the domain layer:

New Location: packages/domain/orders/providers/salesforce/pubsub.types.ts

Rationale:

  • These are raw provider types (like WhmcsInvoice, FreebitAccountDetailsRaw)
  • They represent Salesforce Platform Events structure
  • Domain layer already has packages/domain/orders/providers/salesforce/
  • They're used for order provisioning events

Migration Path:

1. Create: packages/domain/orders/providers/salesforce/pubsub.types.ts
2. Move types from BFF
3. Export from: packages/domain/orders/providers/salesforce/index.ts
4. Update imports in: apps/bff/src/integrations/salesforce/events/pubsub.subscriber.ts

⚠️ 5. Empty WHMCS Transformers Directory - CLEANUP NEEDED

Status: ⚠️ Partially Cleaned

Current State: The directory exists but is empty

apps/bff/src/integrations/whmcs/transformers/
├── services/     (empty)
├── utils/        (empty)
└── validators/   (empty)

Evidence:

  • Transformer services deleted
  • Not referenced in whmcs.module.ts
  • Not imported anywhere
  • But directory still exists

🟡 RECOMMENDATION:

Delete the entire transformers/ directory:

rm -rf apps/bff/src/integrations/whmcs/transformers/

Impact: Zero - nothing uses it anymore.


6. Business Error Codes in BFF - NEEDS MIGRATION

Status: Not Implemented

Current Location: apps/bff/src/modules/orders/services/order-fulfillment-error.service.ts

Problem: Business error codes are defined in BFF:

export enum OrderFulfillmentErrorCode {
  PAYMENT_METHOD_MISSING = "PAYMENT_METHOD_MISSING",
  ORDER_NOT_FOUND = "ORDER_NOT_FOUND",
  WHMCS_ERROR = "WHMCS_ERROR",
  MAPPING_ERROR = "MAPPING_ERROR",
  VALIDATION_ERROR = "VALIDATION_ERROR",
  SALESFORCE_ERROR = "SALESFORCE_ERROR",
  PROVISIONING_ERROR = "PROVISIONING_ERROR",
}

🔴 RECOMMENDATION:

Move to domain layer as these are business error codes:

New Location: packages/domain/orders/constants.ts or packages/domain/orders/errors.ts

Rationale:

  • These represent business-level error categories
  • Not infrastructure concerns
  • Could be useful for other consumers (frontend, webhooks, etc.)
  • Part of the domain's error vocabulary

7. Infrastructure-Specific Types - CORRECTLY PLACED

Status: Correct

Some types in BFF modules are correctly placed as they are infrastructure concerns:

Example: apps/bff/src/modules/invoices/types/invoice-service.types.ts:

export interface InvoiceServiceStats {
  totalInvoicesRetrieved: number;
  totalPaymentLinksCreated: number;
  totalSsoLinksCreated: number;
  averageResponseTime: number;
  lastRequestTime?: Date;
  lastErrorTime?: Date;
}

export interface InvoiceHealthStatus {
  status: "healthy" | "unhealthy";
  details: {
    whmcsApi?: string;
    mappingsService?: string;
    error?: string;
    timestamp: string;
  };
}

These are BFF-specific monitoring/health check types and belong in BFF.


Summary of Remaining Work

High Priority

Issue Location Action Effort
Pub/Sub Types apps/bff/src/integrations/salesforce/types/pubsub-events.types.ts Move to packages/domain/orders/providers/salesforce/ 15 min
Error Codes apps/bff/src/modules/orders/services/order-fulfillment-error.service.ts Move enum to packages/domain/orders/errors.ts 10 min

Low Priority (Cleanup)

Issue Location Action Effort
Empty Transformers apps/bff/src/integrations/whmcs/transformers/ Delete directory 1 min

Architecture Score

Before Refactoring: 60/100

  • Redundant wrapper services everywhere
  • Scattered DB mappers
  • Unclear boundaries

Current State: 85/100

  • Centralized DB mappers
  • Direct domain mapper usage
  • Clean integration layer
  • No redundant wrappers
  • ⚠️ Minor cleanup needed

Target State: 100/100

  • All business types in domain
  • All provider types in domain
  • Clean BFF focusing on orchestration

Immediate (30 minutes)

  1. Move Pub/Sub Types to Domain

    # Create new file
    mkdir -p packages/domain/orders/providers/salesforce
    
    # Move types
    mv apps/bff/src/integrations/salesforce/types/pubsub-events.types.ts \
       packages/domain/orders/providers/salesforce/pubsub.types.ts
    
    # Update exports and imports
    
  2. Move Order Error Codes to Domain

    // Create: packages/domain/orders/errors.ts
    export const ORDER_FULFILLMENT_ERROR_CODE = {
      PAYMENT_METHOD_MISSING: "PAYMENT_METHOD_MISSING",
      ORDER_NOT_FOUND: "ORDER_NOT_FOUND",
      WHMCS_ERROR: "WHMCS_ERROR",
      MAPPING_ERROR: "MAPPING_ERROR",
      VALIDATION_ERROR: "VALIDATION_ERROR",
      SALESFORCE_ERROR: "SALESFORCE_ERROR",
      PROVISIONING_ERROR: "PROVISIONING_ERROR",
    } as const;
    
    export type OrderFulfillmentErrorCode = 
      typeof ORDER_FULFILLMENT_ERROR_CODE[keyof typeof ORDER_FULFILLMENT_ERROR_CODE];
    
  3. Delete Empty Transformers Directory

    rm -rf apps/bff/src/integrations/whmcs/transformers/
    

Documentation (10 minutes)

  1. Update Success Criteria in \d.plan.md
    • Mark completed items as done
    • Document remaining work

Conclusion

The refactoring plan has been successfully implemented with only minor cleanup needed:

🎉 Achievements:

  • Clean architecture boundaries established
  • Domain layer is the single source of truth for business logic
  • BFF layer focuses on orchestration and infrastructure
  • No redundant wrapper services
  • Centralized DB mappers

🔧 Final Touch-ups Needed:

  • Move pub/sub types to domain (15 min)
  • Move error codes to domain (10 min)
  • Delete empty directories (1 min)

Total remaining effort: ~30 minutes to achieve 100% cleanliness.


Files to Check

Already Clean

  • apps/bff/src/infra/mappers/ - Centralized DB mappers
  • apps/bff/src/integrations/freebit/services/ - Using domain mappers
  • apps/bff/src/integrations/whmcs/services/ - Using domain mappers
  • packages/domain/sim/providers/freebit/ - Contains utilities and mappers

Needs Attention

  • apps/bff/src/integrations/salesforce/types/pubsub-events.types.ts - Move to domain
  • apps/bff/src/modules/orders/services/order-fulfillment-error.service.ts - Move enum to domain
  • apps/bff/src/integrations/whmcs/transformers/ - Delete empty directory