Skip to content

Technical Debt Cleanup - Implementation Feedback

Overview

This document summarizes the implementation of high-priority technical debt items (Phases 5e through 5k) as defined in the prompt files.

Date: 2026-01-17
Phases Completed: 7 (5e, 5f, 5g, 5h, 5i, 5j, 5k)
Total Commits: 6


Phase 5e: Typed JSON Column Schemas (TD-003)

Implementation Summary

Created Zod schemas for all JSON columns in the database to provide runtime validation and TypeScript type inference.

Files Created

  • libs/domain/src/schemas/shipping-address.schema.ts
  • libs/domain/src/schemas/print-profile.schema.ts
  • libs/domain/src/schemas/event-metadata.schema.ts
  • libs/domain/src/schemas/webhook-payload.schema.ts
  • libs/domain/src/schemas/shipment-dimensions.schema.ts
  • libs/domain/src/schemas/index.ts
  • Tests for all schemas in libs/domain/src/schemas/__tests__/

Challenges Encountered

  1. Type Conflicts: After adding new schemas, existing entity files (order.ts, product-mapping.ts) had local interface definitions with identical names (ShippingAddress, PrintProfile). This caused TS2308 duplicate export errors.
  2. Resolution: Removed duplicate interfaces from entity files and updated imports to use schema-derived types.

  3. Test Assertions: Initial tests for EventMetadataSchema failed because the schema is a union type and { progress: 999 } was valid against BaseEventMetadataSchema.

  4. Resolution: Changed test to use a value that would actually fail validation.

Deviations from Prompt

  • None significant. All P1 and P2 schemas implemented as specified.

Phase 5f: Shared API Types (TD-004)

Implementation Summary

Created shared API request/response types in libs/domain-contracts to eliminate duplication between frontend and backend.

Files Created

  • libs/domain-contracts/src/api/common.types.ts - PaginatedResponse, ApiErrorResponse, etc.
  • libs/domain-contracts/src/api/order.api.ts
  • libs/domain-contracts/src/api/print-job.api.ts
  • libs/domain-contracts/src/api/dashboard.api.ts
  • libs/domain-contracts/src/api/product-mapping.api.ts
  • libs/domain-contracts/src/api/shipment.api.ts
  • libs/domain-contracts/src/api/event-log.api.ts
  • libs/domain-contracts/src/api/health.api.ts
  • libs/domain-contracts/src/api/index.ts

Challenges Encountered

  1. Enum Type Incompatibility: Prisma generates its own enum types (e.g., $Enums.OrderStatus) which are technically different types from the enums in @forma3d/domain, even though they have identical string values. This caused TS2345 errors throughout the codebase.
  2. Resolution: Introduced string union types (OrderStatusType, PrintJobStatusType, ShipmentStatusType) in libs/domain-contracts/src/lib/types.ts. This provides a flexible contract compatible with both Prisma enums and domain enums.

  3. Dependency Graph: @prisma/client was imported in domain-contracts, violating the domain boundary principle.

  4. Resolution: Replaced with @forma3d/domain dependency and refactored imports to use string unions.

Deviations from Prompt

  • Used string union types instead of importing domain enums to resolve cross-module enum compatibility issues.

Phase 5g: Structured Logging Cleanup (TD-005)

Implementation Summary

Replaced console.log statements with structured logging throughout the codebase.

Files Modified

  • apps/api/src/observability/instrument.ts - NestJS Logger
  • apps/web/src/observability/sentry.ts - devLog utility

Files Created

  • apps/web/src/lib/dev-logger.ts - Development-only logging utility

Challenges Encountered

  • None significant. The implementation was straightforward.

Deviations from Prompt

  • Did not add ESLint no-console rule. The prompt suggested this but the codebase already had minimal console.log usage and the structured logging patterns are now in place.

Phase 5h: Controller Test Coverage (TD-006)

Implementation Summary

Added unit tests for P1 and P3 priority controllers.

Files Created

  • apps/api/src/orders/__tests__/orders.controller.spec.ts
  • apps/api/src/print-jobs/__tests__/print-jobs.controller.spec.ts
  • apps/api/src/health/__tests__/health.controller.spec.ts

Test Coverage Added

  • OrdersController: findAll, findById, updateStatus, cancel
  • PrintJobsController: findAll, findByOrderId, findById, findActive, retry, cancel
  • HealthController: check, liveness, readiness

Challenges Encountered

  1. Mock Data Type Safety: TypeScript's strict typing required properly typed mock data that matched the repository/service return types. The PrintJobWithLineItem type required complete LineItem and Order structures.
  2. Resolution: Created factory functions (createMockPrintJob, createMockOrder) with type assertions to produce valid mock data.

Deviations from Prompt

  • Did not implement tests for all controllers (shopify, simplyprint-webhook, product-mappings, shipments, sendcloud, cancellation). Focused on P1/P3 priorities as specified.
  • Total tests increased from 391 to 414 (+23 tests).

Phase 5i: Domain Contract Cleanup (TD-007)

Implementation Summary

Verified that domain contracts don't leak Prisma types.

Outcome

Phase 5i was largely completed as part of Phase 5f work. Verification confirmed: - No @prisma/client imports in libs/domain/ - No @prisma/client imports in libs/domain-contracts/

Deviations from Prompt

  • No additional changes needed beyond Phase 5f work.

Phase 5j: Typed Error Hierarchy (TD-008)

Implementation Summary

Created a typed error hierarchy for consistent error handling across the application.

Files Created

  • libs/domain/src/errors/base.error.ts - DomainError base class
  • libs/domain/src/errors/common.errors.ts - NotFoundError, ValidationError, ConflictError, UnauthorizedError, ForbiddenError, ExternalServiceError, RateLimitError
  • libs/domain/src/errors/order.errors.ts - OrderNotFoundError, OrderStateError, OrderCancellationError, OrderNoPrintableItemsError
  • libs/domain/src/errors/print-job.errors.ts - PrintJobNotFoundError, PrintJobStateError, PrintJobRetryLimitError, PrintJobQueueError
  • libs/domain/src/errors/integration.errors.ts - SimplyPrintError, SendcloudError, ShopifyWebhookVerificationError, ShippingNotConfiguredError, ShipmentNotFoundError, ShippingLabelError
  • libs/domain/src/errors/index.ts

Key Features

  • Each error has a unique code for client-side handling
  • httpStatus for automatic HTTP response mapping
  • isOperational flag to distinguish expected vs unexpected errors
  • toResponse() method for consistent API error format

Deviations from Prompt

  • None significant. All error categories implemented as specified.

Phase 5k: Configuration Externalization (TD-009)

Implementation Summary

Externalized hardcoded configuration values into environment-based settings.

Files Modified

  • apps/api/src/config/configuration.ts - Added RetryQueueConfig, ApiTimeoutConfig, WebhookConfig interfaces
  • apps/api/src/retry-queue/retry-queue.service.ts - Now uses ConfigService for retry queue settings
  • apps/api/src/retry-queue/__tests__/retry-queue.service.spec.ts - Updated to mock ConfigService
  • .env.example - Added new configuration options with documentation

New Configuration Options

# Retry Queue
RETRY_QUEUE_MAX_RETRIES=5
RETRY_QUEUE_INITIAL_DELAY_MS=1000
RETRY_QUEUE_MAX_DELAY_MS=3600000
RETRY_QUEUE_BACKOFF_MULTIPLIER=2
RETRY_QUEUE_CLEANUP_RETENTION_DAYS=7

# API Timeouts
API_TIMEOUT_SIMPLYPRINT_MS=30000
API_TIMEOUT_SENDCLOUD_MS=30000
API_TIMEOUT_SHOPIFY_MS=30000

# Webhook
WEBHOOK_IDEMPOTENCY_RETENTION_HOURS=24

Deviations from Prompt

  • Did not update API clients (SimplyPrint, Sendcloud) to use centralized timeout config. The configuration interfaces are now in place for future adoption.

Summary Statistics

Metric Value
Files Created 24
Files Modified ~15
Lines of Code Added ~1,500
Test Count Before 391
Test Count After 414
New Test Files 7

Recommendations for Future Work

  1. Migrate API clients to use centralized timeout config: SimplyPrint and Sendcloud clients currently have hardcoded 30000ms timeout. Update to use ConfigService.get('apiTimeout.simplyPrint').

  2. Add ESLint no-console rule: To enforce structured logging, add "no-console": "error" with overrides for test files and dev-logger.ts.

  3. Implement remaining controller tests: shopify.controller, simplyprint-webhook.controller, product-mappings.controller, shipments.controller, sendcloud.controller, cancellation.controller.

  4. Use typed errors in services: The error hierarchy is now in place. Gradually migrate services to throw these typed errors instead of generic Error or NestJS exceptions.

  5. Consider Zod for DTO validation: The Zod schemas could be integrated with NestJS validation pipes for request body validation, replacing class-validator decorators.