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.tslibs/domain/src/schemas/print-profile.schema.tslibs/domain/src/schemas/event-metadata.schema.tslibs/domain/src/schemas/webhook-payload.schema.tslibs/domain/src/schemas/shipment-dimensions.schema.tslibs/domain/src/schemas/index.ts- Tests for all schemas in
libs/domain/src/schemas/__tests__/
Challenges Encountered¶
- 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. -
Resolution: Removed duplicate interfaces from entity files and updated imports to use schema-derived types.
-
Test Assertions: Initial tests for
EventMetadataSchemafailed because the schema is a union type and{ progress: 999 }was valid againstBaseEventMetadataSchema. - 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.tslibs/domain-contracts/src/api/print-job.api.tslibs/domain-contracts/src/api/dashboard.api.tslibs/domain-contracts/src/api/product-mapping.api.tslibs/domain-contracts/src/api/shipment.api.tslibs/domain-contracts/src/api/event-log.api.tslibs/domain-contracts/src/api/health.api.tslibs/domain-contracts/src/api/index.ts
Challenges Encountered¶
- 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. -
Resolution: Introduced string union types (
OrderStatusType,PrintJobStatusType,ShipmentStatusType) inlibs/domain-contracts/src/lib/types.ts. This provides a flexible contract compatible with both Prisma enums and domain enums. -
Dependency Graph:
@prisma/clientwas imported indomain-contracts, violating the domain boundary principle. - Resolution: Replaced with
@forma3d/domaindependency 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 Loggerapps/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-consolerule. 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.tsapps/api/src/print-jobs/__tests__/print-jobs.controller.spec.tsapps/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¶
- Mock Data Type Safety: TypeScript's strict typing required properly typed mock data that matched the repository/service return types. The
PrintJobWithLineItemtype required completeLineItemandOrderstructures. - 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 classlibs/domain/src/errors/common.errors.ts- NotFoundError, ValidationError, ConflictError, UnauthorizedError, ForbiddenError, ExternalServiceError, RateLimitErrorlibs/domain/src/errors/order.errors.ts- OrderNotFoundError, OrderStateError, OrderCancellationError, OrderNoPrintableItemsErrorlibs/domain/src/errors/print-job.errors.ts- PrintJobNotFoundError, PrintJobStateError, PrintJobRetryLimitError, PrintJobQueueErrorlibs/domain/src/errors/integration.errors.ts- SimplyPrintError, SendcloudError, ShopifyWebhookVerificationError, ShippingNotConfiguredError, ShipmentNotFoundError, ShippingLabelErrorlibs/domain/src/errors/index.ts
Key Features¶
- Each error has a unique
codefor client-side handling httpStatusfor automatic HTTP response mappingisOperationalflag to distinguish expected vs unexpected errorstoResponse()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 interfacesapps/api/src/retry-queue/retry-queue.service.ts- Now uses ConfigService for retry queue settingsapps/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¶
-
Migrate API clients to use centralized timeout config: SimplyPrint and Sendcloud clients currently have hardcoded 30000ms timeout. Update to use
ConfigService.get('apiTimeout.simplyPrint'). -
Add ESLint no-console rule: To enforce structured logging, add
"no-console": "error"with overrides for test files and dev-logger.ts. -
Implement remaining controller tests: shopify.controller, simplyprint-webhook.controller, product-mappings.controller, shipments.controller, sendcloud.controller, cancellation.controller.
-
Use typed errors in services: The error hierarchy is now in place. Gradually migrate services to throw these typed errors instead of generic
Erroror NestJS exceptions. -
Consider Zod for DTO validation: The Zod schemas could be integrated with NestJS validation pipes for request body validation, replacing class-validator decorators.