1009 lines
37 KiB
Markdown
1009 lines
37 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project Overview
|
|
|
|
**Xpeditis** is a B2B SaaS maritime freight booking and management platform (maritime equivalent of WebCargo). The platform allows freight forwarders to search and compare real-time shipping rates, book containers online, and manage shipments from a centralized dashboard.
|
|
|
|
**Current Status**: Phase 4+ - Production-ready with security hardening, monitoring, comprehensive testing infrastructure, and active administration features development.
|
|
|
|
**Active Branch**: `administration` - Currently working on admin features, notifications system, and dashboard enhancements. Check `git status` for current feature branch.
|
|
|
|
**Recent Development**: Notifications system, dashboard improvements, pagination fixes, and admin user management features.
|
|
|
|
## Repository Structure
|
|
|
|
This is a **monorepo** containing both backend and frontend applications:
|
|
|
|
```
|
|
/Users/david/Documents/xpeditis/dev/xpeditis2.0/
|
|
├── apps/
|
|
│ ├── backend/ # NestJS API (Node.js 20+, TypeScript 5+)
|
|
│ │ ├── src/
|
|
│ │ │ ├── domain/ # Pure business logic (no framework deps)
|
|
│ │ │ ├── application/ # Controllers, DTOs, Guards
|
|
│ │ │ └── infrastructure/ # ORM, Cache, External APIs
|
|
│ │ ├── test/ # Integration & E2E tests
|
|
│ │ ├── load-tests/ # K6 load testing scripts
|
|
│ │ └── package.json # Backend dependencies
|
|
│ └── frontend/ # Next.js 14 App Router (React 18)
|
|
│ ├── app/ # Next.js App Router pages
|
|
│ ├── src/ # Components, hooks, utilities
|
|
│ ├── e2e/ # Playwright E2E tests
|
|
│ └── package.json # Frontend dependencies
|
|
├── infra/
|
|
│ └── postgres/ # PostgreSQL init scripts
|
|
├── docker/ # Docker build & deployment configs
|
|
├── docker-compose.yml # Local development infrastructure
|
|
├── package.json # Root monorepo package.json (workspace scripts)
|
|
├── .prettierrc # Prettier configuration (shared)
|
|
├── .github/workflows/ # GitHub Actions CI/CD pipelines
|
|
└── CLAUDE.md # This file (architecture guide)
|
|
```
|
|
|
|
**Workspace Management**:
|
|
- Root `package.json` contains monorepo-level scripts
|
|
- Each app has its own `package.json` with specific dependencies
|
|
- Use root-level commands (`npm run backend:dev`) for convenience
|
|
- Or navigate to specific app and run commands directly
|
|
|
|
## Development Commands
|
|
|
|
### Local Development Setup
|
|
|
|
```bash
|
|
# Install all dependencies (monorepo)
|
|
npm install
|
|
cd apps/backend && npm install
|
|
cd ../frontend && npm install
|
|
|
|
# Start infrastructure (PostgreSQL + Redis + MinIO)
|
|
docker-compose up -d
|
|
|
|
# Verify all services are running
|
|
docker-compose ps
|
|
# Expected: xpeditis-postgres, xpeditis-redis, xpeditis-minio
|
|
|
|
# Run database migrations
|
|
cd apps/backend
|
|
npm run migration:run
|
|
|
|
# Start backend development server (with hot reload)
|
|
npm run backend:dev # From root, or:
|
|
cd apps/backend && npm run dev
|
|
|
|
# Start frontend development server
|
|
npm run frontend:dev # From root, or:
|
|
cd apps/frontend && npm run dev
|
|
```
|
|
|
|
**Access Points**:
|
|
- Frontend: http://localhost:3000
|
|
- Backend API: http://localhost:4000
|
|
- API Docs (Swagger): http://localhost:4000/api/docs
|
|
- MinIO Console (local S3): http://localhost:9001 (minioadmin/minioadmin)
|
|
- Admin Dashboard: http://localhost:3000/dashboard/admin (ADMIN role required)
|
|
- Admin CSV Rates: http://localhost:3000/dashboard/admin/csv-rates
|
|
- Admin User Management: http://localhost:3000/dashboard/settings/users
|
|
- Notifications: http://localhost:3000/dashboard/notifications
|
|
|
|
### Monorepo Scripts (from root)
|
|
|
|
```bash
|
|
# Development
|
|
npm run backend:dev # Start backend dev server
|
|
npm run frontend:dev # Start frontend dev server
|
|
|
|
# Testing
|
|
npm run backend:test # Run backend unit tests
|
|
npm run frontend:test # Run frontend tests
|
|
npm run backend:lint # Lint backend code
|
|
npm run frontend:lint # Lint frontend code
|
|
|
|
# Code Quality
|
|
npm run format # Format all code (Prettier)
|
|
npm run format:check # Check formatting
|
|
|
|
# Build
|
|
npm run backend:build # Build backend for production
|
|
npm run frontend:build # Build frontend for production
|
|
|
|
# Utilities
|
|
npm run install:all # Install deps for all workspaces
|
|
npm run clean # Clean all node_modules and build artifacts
|
|
```
|
|
|
|
### Testing Commands
|
|
|
|
#### Backend Tests
|
|
|
|
```bash
|
|
cd apps/backend
|
|
|
|
# Unit tests (domain layer - no external dependencies)
|
|
npm test # Run all unit tests
|
|
npm run test:watch # Run in watch mode
|
|
npm run test:cov # With coverage report
|
|
|
|
# Integration tests (infrastructure layer with real DB/Redis)
|
|
npm run test:integration # Run all integration tests
|
|
npm run test:integration:watch # Run in watch mode
|
|
npm run test:integration:cov # With coverage report
|
|
|
|
# E2E tests (full API workflow)
|
|
npm run test:e2e # Run end-to-end tests
|
|
|
|
# Run a single test file
|
|
npm test -- booking.service.spec.ts
|
|
npm run test:integration -- redis-cache.adapter.spec.ts
|
|
npm run test:e2e -- carrier-portal.e2e-spec.ts
|
|
```
|
|
|
|
#### Load Testing (K6)
|
|
|
|
```bash
|
|
cd apps/backend
|
|
|
|
# Install k6 (macOS)
|
|
brew install k6
|
|
|
|
# Run rate search load test (100 virtual users)
|
|
k6 run load-tests/rate-search.test.js
|
|
|
|
# Run with custom parameters
|
|
k6 run --vus 50 --duration 60s load-tests/rate-search.test.js
|
|
```
|
|
|
|
#### E2E Testing (Playwright)
|
|
|
|
```bash
|
|
cd apps/frontend
|
|
|
|
# Install Playwright
|
|
npx playwright install
|
|
|
|
# Run E2E tests (booking workflow)
|
|
npx playwright test e2e/booking-workflow.spec.ts
|
|
|
|
# Run with UI mode
|
|
npx playwright test --ui
|
|
|
|
# Run specific browser
|
|
npx playwright test --project=chromium
|
|
```
|
|
|
|
#### API Testing (Postman/Newman)
|
|
|
|
```bash
|
|
# Install Newman globally
|
|
npm install -g newman
|
|
|
|
# Run Postman collection
|
|
newman run postman/Xpeditis_API.postman_collection.json
|
|
```
|
|
|
|
### Database Migrations
|
|
|
|
```bash
|
|
cd apps/backend
|
|
|
|
# Generate new migration (after changing ORM entities)
|
|
npm run migration:generate -- src/infrastructure/persistence/typeorm/migrations/MigrationName
|
|
|
|
# Run pending migrations
|
|
npm run migration:run
|
|
|
|
# Revert last migration
|
|
npm run migration:revert
|
|
|
|
# Check applied migrations (query database directly)
|
|
# Note: TypeORM doesn't have a built-in 'show' command
|
|
# Check the migrations table in the database to see applied migrations
|
|
```
|
|
|
|
**Important Migration Notes**:
|
|
- Migration files use Unix timestamp format: `1733185000000-DescriptiveName.ts`
|
|
- Always test migrations in development before running in production
|
|
- Migrations run automatically via TypeORM DataSource configuration
|
|
- Never modify existing migrations that have been applied to production
|
|
|
|
### Build & Production
|
|
|
|
```bash
|
|
# Backend build (uses tsc-alias to resolve path aliases)
|
|
cd apps/backend
|
|
npm run build # Compiles TypeScript and resolves @domain, @application, @infrastructure aliases
|
|
npm run start:prod # Runs the production build
|
|
|
|
# Frontend build
|
|
cd apps/frontend
|
|
npm run build # Next.js production build
|
|
npm start # Start production server
|
|
```
|
|
|
|
## Architecture
|
|
|
|
### Hexagonal Architecture (Ports & Adapters)
|
|
|
|
The backend follows strict hexagonal architecture with three isolated layers:
|
|
|
|
```
|
|
apps/backend/src/
|
|
├── domain/ # 🔵 CORE - Pure business logic (NO framework dependencies)
|
|
│ ├── entities/ # Business entities (Booking, RateQuote, User, CarrierProfile)
|
|
│ ├── value-objects/ # Immutable VOs (Money, Email, BookingNumber, Port)
|
|
│ ├── services/ # Domain services (pure TypeScript)
|
|
│ ├── ports/
|
|
│ │ ├── in/ # API Ports (use cases exposed by domain)
|
|
│ │ └── out/ # SPI Ports (interfaces required by domain)
|
|
│ └── exceptions/ # Domain exceptions
|
|
│
|
|
├── application/ # 🔌 Controllers & DTOs (depends ONLY on domain)
|
|
│ ├── auth/ # JWT authentication module
|
|
│ ├── rates/ # Rate search endpoints
|
|
│ ├── bookings/ # Booking management
|
|
│ ├── csv-bookings.module.ts # CSV booking imports
|
|
│ ├── controllers/ # REST endpoints
|
|
│ │ ├── health.controller.ts
|
|
│ │ ├── gdpr.controller.ts
|
|
│ │ └── index.ts
|
|
│ ├── dto/ # Data transfer objects with validation
|
|
│ │ ├── booking-*.dto.ts
|
|
│ │ ├── rate-*.dto.ts
|
|
│ │ └── csv-*.dto.ts
|
|
│ ├── services/ # Application services
|
|
│ │ ├── fuzzy-search.service.ts
|
|
│ │ ├── brute-force-protection.service.ts
|
|
│ │ ├── file-validation.service.ts
|
|
│ │ └── gdpr.service.ts
|
|
│ ├── guards/ # Auth guards, rate limiting, RBAC
|
|
│ │ ├── jwt-auth.guard.ts
|
|
│ │ └── throttle.guard.ts
|
|
│ ├── decorators/ # Custom decorators
|
|
│ │ ├── current-user.decorator.ts
|
|
│ │ ├── public.decorator.ts
|
|
│ │ └── roles.decorator.ts
|
|
│ ├── interceptors/ # Request/response interceptors
|
|
│ │ └── performance-monitoring.interceptor.ts
|
|
│ └── gdpr/ # GDPR compliance module
|
|
│ └── gdpr.module.ts
|
|
│
|
|
└── infrastructure/ # 🏗️ External integrations (depends ONLY on domain)
|
|
├── persistence/typeorm/ # PostgreSQL repositories
|
|
│ ├── entities/
|
|
│ │ ├── booking.orm-entity.ts
|
|
│ │ ├── carrier.orm-entity.ts
|
|
│ │ ├── csv-rate-config.orm-entity.ts
|
|
│ │ ├── notification.orm-entity.ts
|
|
│ │ ├── port.orm-entity.ts
|
|
│ │ ├── rate-quote.orm-entity.ts
|
|
│ │ └── audit-log.orm-entity.ts
|
|
│ ├── repositories/
|
|
│ ├── mappers/ # Domain ↔ ORM entity mappers
|
|
│ └── migrations/
|
|
├── cache/ # Redis adapter
|
|
├── carriers/ # Maersk, MSC, CMA CGM connectors
|
|
│ ├── carrier.module.ts
|
|
│ ├── csv-loader/ # CSV-based rate connector
|
|
│ │ └── csv-converter.service.ts
|
|
│ └── maersk/
|
|
│ └── maersk.types.ts
|
|
├── email/ # MJML email service (carrier notifications)
|
|
├── storage/ # S3 storage adapter
|
|
│ └── csv-storage/ # CSV rate files storage
|
|
│ └── rates/
|
|
├── monitoring/ # Monitoring and observability
|
|
│ └── sentry.config.ts
|
|
├── websocket/ # Real-time carrier updates
|
|
└── security/ # Helmet.js, rate limiting, CORS
|
|
```
|
|
|
|
**Critical Rules**:
|
|
1. **Domain layer**: No imports of NestJS, TypeORM, Redis, or any framework - pure TypeScript only
|
|
2. **Dependencies flow inward**: Infrastructure → Application → Domain (never the reverse)
|
|
3. **TypeScript path aliases**: Use `@domain/*`, `@application/*`, `@infrastructure/*`
|
|
4. **Testing**: Domain tests must run without NestJS TestingModule
|
|
5. **Mappers**: Use dedicated mapper classes for Domain ↔ ORM and Domain ↔ DTO conversions
|
|
|
|
**Example - Domain Entity Structure**:
|
|
```typescript
|
|
// apps/backend/src/domain/entities/booking.entity.ts
|
|
export class Booking {
|
|
private readonly props: BookingProps;
|
|
|
|
static create(props: Omit<BookingProps, 'bookingNumber' | 'status'>): Booking {
|
|
const bookingProps: BookingProps = {
|
|
...props,
|
|
bookingNumber: BookingNumber.generate(),
|
|
status: BookingStatus.create('draft'),
|
|
};
|
|
Booking.validate(bookingProps);
|
|
return new Booking(bookingProps);
|
|
}
|
|
|
|
updateStatus(newStatus: BookingStatus): Booking {
|
|
if (!this.status.canTransitionTo(newStatus)) {
|
|
throw new InvalidStatusTransitionException();
|
|
}
|
|
return new Booking({ ...this.props, status: newStatus });
|
|
}
|
|
}
|
|
```
|
|
|
|
### Frontend Architecture (Next.js 14 App Router)
|
|
|
|
```
|
|
apps/frontend/
|
|
├── app/ # Next.js 14 App Router (routing)
|
|
│ ├── page.tsx # Landing page
|
|
│ ├── layout.tsx # Root layout
|
|
│ ├── login/ # Auth pages
|
|
│ ├── register/
|
|
│ ├── forgot-password/
|
|
│ ├── reset-password/
|
|
│ ├── verify-email/
|
|
│ ├── dashboard/ # Protected dashboard routes
|
|
│ │ ├── page.tsx # Main dashboard
|
|
│ │ ├── layout.tsx # Dashboard layout with navigation
|
|
│ │ ├── search/ # Rate search
|
|
│ │ ├── search-advanced/ # Advanced search with results
|
|
│ │ ├── bookings/ # Booking management
|
|
│ │ │ ├── page.tsx # Bookings list
|
|
│ │ │ ├── [id]/page.tsx # Booking details
|
|
│ │ │ └── new/page.tsx # Create booking
|
|
│ │ ├── profile/ # User profile
|
|
│ │ ├── notifications/ # Notifications page
|
|
│ │ ├── settings/ # Settings pages
|
|
│ │ │ ├── users/page.tsx # User management (admin)
|
|
│ │ │ └── organization/page.tsx # Organization settings
|
|
│ │ └── admin/ # Admin features (ADMIN role only)
|
|
│ │ └── csv-rates/page.tsx # CSV rate management
|
|
│ ├── booking/ # Booking actions (public with token)
|
|
│ │ ├── confirm/[token]/page.tsx
|
|
│ │ └── reject/[token]/page.tsx
|
|
│ ├── carrier/ # Carrier portal routes
|
|
│ │ ├── accept/[token]/page.tsx
|
|
│ │ └── reject/[token]/page.tsx
|
|
│ ├── demo-carte/ # Map demo page
|
|
│ └── test-image/ # Image testing page
|
|
├── src/
|
|
│ ├── components/ # React components
|
|
│ │ ├── ui/ # shadcn/ui components (Button, Dialog, etc.)
|
|
│ │ ├── bookings/ # Booking components
|
|
│ │ └── admin/ # Admin components
|
|
│ ├── hooks/ # Custom React hooks
|
|
│ │ ├── useBookings.ts
|
|
│ │ ├── useCompanies.ts
|
|
│ │ └── useNotifications.ts
|
|
│ ├── lib/ # Utilities and API client
|
|
│ │ ├── api/ # API client modules
|
|
│ │ │ ├── auth.ts
|
|
│ │ │ ├── bookings.ts
|
|
│ │ │ ├── csv-rates.ts
|
|
│ │ │ └── dashboard.ts
|
|
│ │ ├── context/ # React contexts
|
|
│ │ └── providers/ # React Query and other providers
|
|
│ ├── types/ # TypeScript type definitions
|
|
│ │ ├── booking.ts
|
|
│ │ ├── carrier.ts
|
|
│ │ └── rates.ts
|
|
│ ├── utils/ # Helper functions
|
|
│ │ └── export.ts # Excel/CSV/PDF export utilities
|
|
│ └── pages/ # Legacy page components
|
|
└── public/ # Static assets (logos, images)
|
|
```
|
|
|
|
**Frontend Patterns**:
|
|
- Server Components by default, Client Components when needed (`"use client"`)
|
|
- React Hook Form + Zod for form validation
|
|
- TanStack Query for server state management
|
|
- Zustand for client state management
|
|
- shadcn/ui for accessible UI components
|
|
|
|
**TypeScript Path Aliases** (Frontend):
|
|
- `@/*` - Maps to `./src/*`
|
|
- `@/components/*` - Maps to `./src/components/*`
|
|
- `@/lib/*` - Maps to `./src/lib/*`
|
|
- `@/app/*` - Maps to `./app/*`
|
|
- `@/types/*` - Maps to `./src/types/*`
|
|
- `@/hooks/*` - Maps to `./src/hooks/*`
|
|
- `@/utils/*` - Maps to `./src/utils/*`
|
|
- `@/pages/*` - Maps to `./src/pages/*`
|
|
|
|
### Tech Stack
|
|
|
|
**Backend**:
|
|
- NestJS 10+ (framework)
|
|
- TypeScript 5+ (strict mode)
|
|
- PostgreSQL 15+ (database)
|
|
- TypeORM 0.3+ (ORM)
|
|
- Redis 7+ (cache, 15min TTL for rates)
|
|
- Passport + JWT (authentication)
|
|
- Argon2 (password hashing)
|
|
- Helmet.js (security headers)
|
|
- Pino (structured logging)
|
|
- Sentry (error tracking + APM)
|
|
|
|
**Frontend**:
|
|
- Next.js 14+ App Router
|
|
- TypeScript 5+
|
|
- React 18+
|
|
- TanStack Table (data grids)
|
|
- TanStack Query (server state)
|
|
- React Hook Form + Zod (forms)
|
|
- Socket.IO (real-time updates)
|
|
- Tailwind CSS + shadcn/ui
|
|
- Framer Motion (animations)
|
|
- Leaflet + React Leaflet (maps)
|
|
|
|
**Infrastructure**:
|
|
- Docker + Docker Compose
|
|
- GitHub Actions (CI/CD)
|
|
- AWS RDS (PostgreSQL)
|
|
- AWS ElastiCache (Redis)
|
|
- AWS S3 (document storage)
|
|
- MinIO (local S3-compatible storage for development)
|
|
|
|
## Testing Strategy
|
|
|
|
### Test Coverage Targets
|
|
- **Domain layer**: 90%+ (currently ~100% for value objects and entities)
|
|
- **Application layer**: 80%+
|
|
- **Infrastructure layer**: 70%+ (currently ~82% for Phase 3 services)
|
|
|
|
### Test File Locations
|
|
|
|
```
|
|
apps/backend/
|
|
├── src/
|
|
│ ├── application/
|
|
│ │ └── services/
|
|
│ │ ├── brute-force-protection.service.spec.ts
|
|
│ │ ├── file-validation.service.spec.ts
|
|
│ │ ├── fuzzy-search.service.spec.ts
|
|
│ │ └── gdpr.service.spec.ts
|
|
│ └── domain/
|
|
│ ├── entities/
|
|
│ │ ├── rate-quote.entity.spec.ts
|
|
│ │ ├── notification.entity.spec.ts
|
|
│ │ └── webhook.entity.spec.ts
|
|
│ └── value-objects/
|
|
│ ├── email.vo.spec.ts
|
|
│ └── money.vo.spec.ts
|
|
├── test/
|
|
│ ├── integration/
|
|
│ │ ├── booking.repository.spec.ts
|
|
│ │ ├── redis-cache.adapter.spec.ts
|
|
│ │ └── maersk.connector.spec.ts
|
|
│ ├── carrier-portal.e2e-spec.ts
|
|
│ ├── app.e2e-spec.ts
|
|
│ ├── jest-integration.json
|
|
│ ├── jest-e2e.json
|
|
│ └── setup-integration.ts
|
|
└── load-tests/
|
|
└── rate-search.test.js
|
|
|
|
apps/frontend/
|
|
└── e2e/
|
|
└── booking-workflow.spec.ts
|
|
```
|
|
|
|
### Running Tests in CI
|
|
|
|
Tests run automatically on GitHub Actions for all PRs:
|
|
- Linting & formatting check
|
|
- Backend unit tests
|
|
- Backend integration tests (with PostgreSQL + Redis services)
|
|
- Backend E2E tests
|
|
- Frontend tests
|
|
- Security scans
|
|
|
|
See [.github/workflows/ci.yml](.github/workflows/ci.yml) for full pipeline.
|
|
|
|
## Security Features (Phase 4)
|
|
|
|
**OWASP Top 10 Compliance**:
|
|
- ✅ Helmet.js security headers (CSP, HSTS, X-Frame-Options)
|
|
- ✅ Rate limiting (global: 100/min, auth: 5/min, search: 30/min)
|
|
- ✅ Brute-force protection (exponential backoff after 3 failed attempts)
|
|
- ✅ File upload validation (MIME, magic number, size limits)
|
|
- ✅ Password policy (12+ chars, complexity requirements, Argon2 hashing)
|
|
- ✅ CORS with strict origin validation
|
|
- ✅ SQL injection prevention (TypeORM parameterized queries)
|
|
- ✅ XSS protection (CSP headers + input sanitization)
|
|
|
|
**Monitoring & Observability**:
|
|
- Sentry error tracking + APM (10% trace sampling)
|
|
- Performance monitoring interceptor (slow request alerts)
|
|
- Structured JSON logging with Pino
|
|
- WebSocket real-time notifications (NotificationsGateway)
|
|
- WebSocket carrier status updates
|
|
|
|
## Database Schema
|
|
|
|
**Key Tables**:
|
|
- `organizations` - Freight forwarders and carriers (has `is_carrier` flag)
|
|
- `users` - User accounts with RBAC roles (Argon2 password hashing)
|
|
- `carriers` - Shipping line integrations (Maersk, MSC, CMA CGM, etc.)
|
|
- `carrier_profiles` - Carrier profile metadata and settings
|
|
- `carrier_activities` - Audit trail for carrier actions (accept/reject bookings, etc.)
|
|
- `ports` - 10k+ global ports (UN LOCODE)
|
|
- `rate_quotes` - Cached shipping rates (15min TTL)
|
|
- `bookings` - Container bookings (status workflow)
|
|
- `containers` - Container details (type, VGM, seal numbers)
|
|
- `shipments` - Real-time shipment tracking
|
|
- `audit_logs` - Compliance audit trail
|
|
- `csv_rates` - CSV-based rate data for offline/bulk rate loading
|
|
- `csv_bookings` - CSV-based booking imports (has `carrier_id` foreign key)
|
|
- `notifications` - User notifications (email, in-app)
|
|
- `webhooks` - Webhook configurations for external integrations
|
|
|
|
**Migrations**: Located in `apps/backend/src/infrastructure/persistence/typeorm/migrations/`
|
|
|
|
See [apps/backend/DATABASE-SCHEMA.md](apps/backend/DATABASE-SCHEMA.md) for complete schema documentation.
|
|
|
|
## Environment Variables
|
|
|
|
### Required Variables
|
|
|
|
**Backend** (`apps/backend/.env`):
|
|
```bash
|
|
NODE_ENV=development
|
|
PORT=4000
|
|
DATABASE_HOST=localhost
|
|
DATABASE_PORT=5432
|
|
DATABASE_USER=xpeditis
|
|
DATABASE_PASSWORD=xpeditis_dev_password
|
|
DATABASE_NAME=xpeditis_dev
|
|
REDIS_HOST=localhost
|
|
REDIS_PORT=6379
|
|
REDIS_PASSWORD=xpeditis_redis_password
|
|
JWT_SECRET=your-super-secret-jwt-key-change-this-in-production
|
|
JWT_ACCESS_EXPIRATION=15m
|
|
JWT_REFRESH_EXPIRATION=7d
|
|
|
|
# Email configuration (for carrier notifications)
|
|
EMAIL_HOST=smtp.example.com
|
|
EMAIL_PORT=587
|
|
EMAIL_USER=noreply@xpeditis.com
|
|
EMAIL_PASSWORD=your-email-password
|
|
EMAIL_FROM=noreply@xpeditis.com
|
|
```
|
|
|
|
**Frontend** (`apps/frontend/.env.local`):
|
|
```bash
|
|
NEXT_PUBLIC_API_URL=http://localhost:4000
|
|
NEXT_PUBLIC_WS_URL=ws://localhost:4000
|
|
```
|
|
|
|
See `apps/backend/.env.example` and `apps/frontend/.env.example` for all available variables.
|
|
|
|
## API Documentation
|
|
|
|
**OpenAPI/Swagger**: http://localhost:4000/api/docs (when backend running)
|
|
|
|
**Key Endpoints**:
|
|
|
|
### Client Portal
|
|
- `POST /api/v1/auth/login` - JWT authentication
|
|
- `POST /api/v1/auth/register` - User registration
|
|
- `POST /api/v1/rates/search` - Search shipping rates (cached 15min)
|
|
- `POST /api/v1/rates/csv-search` - Search rates from CSV data
|
|
- `POST /api/v1/bookings` - Create booking
|
|
- `GET /api/v1/bookings` - List bookings (paginated)
|
|
- `GET /api/v1/bookings/:id` - Get booking details
|
|
- `POST /api/v1/bookings/csv-import` - Bulk import bookings from CSV
|
|
|
|
### Admin Features
|
|
- `GET /api/v1/admin/users` - List users (ADMIN role)
|
|
- `POST /api/v1/admin/users` - Create user (ADMIN role)
|
|
- `PATCH /api/v1/admin/users/:id` - Update user (ADMIN role)
|
|
- `DELETE /api/v1/admin/users/:id` - Delete user (ADMIN role)
|
|
- `GET /api/v1/admin/csv-rates` - List CSV rate configs (ADMIN role)
|
|
- `POST /api/v1/admin/csv-rates/upload` - Upload CSV rates (ADMIN role)
|
|
|
|
### Notifications
|
|
- `GET /api/v1/notifications` - Get user notifications
|
|
- `PATCH /api/v1/notifications/:id/read` - Mark notification as read
|
|
- `DELETE /api/v1/notifications/:id` - Delete notification
|
|
- `WS /notifications` - WebSocket for real-time notifications
|
|
|
|
### GDPR Compliance
|
|
- `GET /api/v1/gdpr/export` - Export user data (GDPR compliance)
|
|
- `DELETE /api/v1/gdpr/delete` - Delete user data (GDPR right to be forgotten)
|
|
|
|
### Health Checks
|
|
- `GET /api/v1/health` - Health check endpoint
|
|
|
|
### Carrier Portal
|
|
- `POST /api/v1/carrier/auth/auto-login` - Auto-login via magic link token
|
|
- `POST /api/v1/carrier/auth/login` - Standard carrier login
|
|
- `GET /api/v1/carrier/dashboard/stats` - Carrier dashboard statistics
|
|
- `GET /api/v1/carrier/bookings` - List bookings assigned to carrier
|
|
- `GET /api/v1/carrier/bookings/:id` - Get booking details
|
|
- `PATCH /api/v1/carrier/bookings/:id/accept` - Accept booking request
|
|
- `PATCH /api/v1/carrier/bookings/:id/reject` - Reject booking request
|
|
- `GET /api/v1/carrier/profile` - Get carrier profile
|
|
- `PATCH /api/v1/carrier/profile` - Update carrier profile
|
|
|
|
### Common
|
|
- `GET /api/v1/carriers/:id/status` - Real-time carrier status
|
|
- `WS /carrier-status` - WebSocket for carrier status updates
|
|
|
|
See [apps/backend/docs/CARRIER_PORTAL_API.md](apps/backend/docs/CARRIER_PORTAL_API.md) for complete carrier portal API documentation.
|
|
|
|
## Business Rules
|
|
|
|
**Critical Constraints**:
|
|
- Rate quotes expire after 15 minutes (Redis TTL)
|
|
- Carrier API timeout: 5 seconds per carrier
|
|
- Booking workflow: Maximum 4 steps
|
|
- Session timeout: 2 hours inactivity
|
|
- Rate search: <2s response time (90% with cache)
|
|
- Booking number format: `WCM-YYYY-XXXXXX` (6 alphanumeric chars)
|
|
- Cache hit target: >90% for common routes
|
|
- Multi-currency support: USD, EUR
|
|
|
|
**RBAC Roles**:
|
|
- `ADMIN` - Full system access, user management, CSV rate uploads
|
|
- `MANAGER` - Manage organization bookings + users
|
|
- `USER` - Create and view own bookings
|
|
- `VIEWER` - Read-only access
|
|
- `CARRIER` - Carrier portal access (view assigned bookings, accept/reject)
|
|
|
|
**Carrier Portal Workflow**:
|
|
1. Admin creates CSV booking and assigns carrier
|
|
2. Email sent to carrier with magic link (auto-login token, valid 1 hour)
|
|
3. Carrier clicks link → auto-login → redirected to dashboard
|
|
4. Carrier can accept/reject booking, download documents
|
|
5. Activity logged in `carrier_activities` table
|
|
6. Client notified of carrier decision
|
|
|
|
## Real-Time Features (WebSocket)
|
|
|
|
The platform uses WebSocket connections for real-time updates:
|
|
|
|
**Notifications Gateway** (`application/gateways/notifications.gateway.ts`):
|
|
- Real-time user notifications (booking updates, system alerts)
|
|
- JWT-authenticated WebSocket connections
|
|
- Auto-reconnect with exponential backoff
|
|
- Connect to `ws://localhost:4000/notifications`
|
|
|
|
**Carrier Status Updates**:
|
|
- Real-time carrier API status monitoring
|
|
- Live shipment tracking updates
|
|
- Connection status: online/offline/degraded
|
|
- Connect to `ws://localhost:4000/carrier-status`
|
|
|
|
**Frontend Integration**:
|
|
- Socket.IO client for WebSocket connections
|
|
- Context providers in `lib/providers/`
|
|
- Real-time notification dropdown component
|
|
- Auto-refresh on status changes
|
|
|
|
## CSV Import/Export Features
|
|
|
|
The platform supports CSV-based operations for bulk data management:
|
|
|
|
**CSV Rate Search**:
|
|
- Upload CSV files with rate data for offline/bulk rate loading
|
|
- CSV-based carrier connectors in `infrastructure/carriers/csv-loader/`
|
|
- Stored in `csv_rates` table
|
|
- Accessible via admin dashboard at `/dashboard/admin/csv-rates`
|
|
- CSV files stored in `apps/backend/src/infrastructure/storage/csv-storage/rates/`
|
|
- Supported carriers: MSC, ECU Worldwide, NVO Consolidation, SSC Consolidation, TCC Logistics, Test Maritime Express
|
|
|
|
**CSV Booking Import**:
|
|
- Bulk import bookings from CSV files
|
|
- Validation and mapping to domain entities
|
|
- Stored in `csv_bookings` table
|
|
- CSV parsing with `csv-parse` library
|
|
- Automatic carrier assignment and email notification
|
|
|
|
**Export Features**:
|
|
- Export bookings to Excel (`.xlsx`) using `exceljs`
|
|
- Export to CSV format
|
|
- Export to PDF documents using `pdfkit`
|
|
- File downloads using `file-saver` on frontend
|
|
|
|
## Admin User Management
|
|
|
|
The platform includes a dedicated admin interface for user management:
|
|
|
|
**Admin Features** (Active on `administration` branch):
|
|
- User CRUD operations (Create, Read, Update, Delete)
|
|
- Organization management
|
|
- Role assignment and permissions
|
|
- Argon2 password hash generation for new users
|
|
- Accessible at `/dashboard/settings/users` (ADMIN role required)
|
|
- CSV rate management at `/dashboard/admin/csv-rates`
|
|
- Real-time notifications management
|
|
|
|
**Password Hashing Utility**:
|
|
- Use `apps/backend/generate-hash.js` to generate Argon2 password hashes
|
|
- Example: `node apps/backend/generate-hash.js mypassword`
|
|
|
|
## Deployment
|
|
|
|
### Docker Build
|
|
|
|
```bash
|
|
# Build backend image
|
|
docker build -t xpeditis-backend:latest -f apps/backend/Dockerfile .
|
|
|
|
# Build frontend image
|
|
docker build -t xpeditis-frontend:latest -f apps/frontend/Dockerfile .
|
|
|
|
# Run with Docker Compose (development)
|
|
docker-compose up -d
|
|
```
|
|
|
|
### Production Deployment (Portainer)
|
|
|
|
See [docker/PORTAINER_DEPLOYMENT_GUIDE.md](docker/PORTAINER_DEPLOYMENT_GUIDE.md) for complete instructions:
|
|
- Scaleway Container Registry (rg.fr-par.scw.cloud/weworkstudio)
|
|
- Docker Swarm stack deployment
|
|
- Traefik reverse proxy configuration
|
|
- Environment-specific configs (staging/production)
|
|
|
|
**CI/CD**: Automated via GitHub Actions
|
|
- Build and push Docker images to Scaleway Registry
|
|
- Deploy to staging/production via Portainer
|
|
- Run smoke tests post-deployment
|
|
|
|
**Deployment Scripts**:
|
|
- `docker/build-images.sh` - Build and tag Docker images
|
|
- `deploy-to-portainer.sh` - Automated deployment script
|
|
- `docker/portainer-stack.yml` - Production stack configuration
|
|
|
|
## Performance Targets
|
|
|
|
- Rate search: <2s for 90% of requests (with cache)
|
|
- Rate search: <5s for 90% of requests (cache miss)
|
|
- Dashboard load: <1s for up to 5k bookings
|
|
- Email confirmation: Send within 3s of booking
|
|
- Carrier email notification: Send within 5s of booking assignment
|
|
- Cache hit ratio: >90% for top 100 trade lanes
|
|
- Carrier API timeout: 5s (with circuit breaker)
|
|
|
|
## Naming Conventions
|
|
|
|
**TypeScript**:
|
|
- Entities: `Booking`, `RateQuote`, `CarrierProfile` (PascalCase)
|
|
- Value Objects: `Email`, `Money`, `BookingNumber`
|
|
- Services: `BookingService`, `RateSearchService`, `CarrierAuthService`
|
|
- Repositories: `BookingRepository`, `CarrierProfileRepository` (interface in domain)
|
|
- Repository Implementations: `TypeOrmBookingRepository`, `TypeOrmCarrierProfileRepository`
|
|
- DTOs: `CreateBookingDto`, `RateSearchRequestDto`, `CarrierAutoLoginDto`
|
|
- Ports: `SearchRatesPort`, `CarrierConnectorPort`
|
|
|
|
**Files**:
|
|
- Entities: `booking.entity.ts`
|
|
- Value Objects: `email.vo.ts`
|
|
- Services: `booking.service.ts`, `carrier-auth.service.ts`
|
|
- Tests: `booking.service.spec.ts`, `carrier-auth.service.spec.ts`
|
|
- ORM Entities: `booking.orm-entity.ts`, `carrier-profile.orm-entity.ts`
|
|
- Migrations: `1730000000001-CreateBookings.ts`, `1733185000000-CreateCarrierProfiles.ts`
|
|
|
|
## Key Architectural Patterns Used
|
|
|
|
### 1. Domain-Driven Design (DDD)
|
|
- **Entities**: Mutable objects with identity (e.g., `Booking`, `User`)
|
|
- **Value Objects**: Immutable, identity-less objects (e.g., `Money`, `Email`, `BookingNumber`)
|
|
- **Aggregates**: Cluster of entities/VOs treated as a unit (e.g., `Booking` with `Container` items)
|
|
- **Domain Services**: Stateless operations that don't belong to entities
|
|
- **Domain Events**: Not yet implemented (planned for Phase 5)
|
|
|
|
### 2. Repository Pattern
|
|
- **Interface in Domain**: `apps/backend/src/domain/ports/out/booking.repository.ts`
|
|
- **Implementation in Infrastructure**: `apps/backend/src/infrastructure/persistence/typeorm/repositories/typeorm-booking.repository.ts`
|
|
- **Mapper Pattern**: Separate mappers for Domain ↔ ORM entity conversion
|
|
|
|
### 3. DTO Pattern
|
|
- **Request DTOs**: Validate incoming API requests with `class-validator`
|
|
- **Response DTOs**: Control API response shape
|
|
- **Mappers**: Convert between DTOs and Domain entities in application layer
|
|
|
|
### 4. Circuit Breaker Pattern
|
|
- Used for external carrier API calls (Maersk, MSC, CMA CGM)
|
|
- Library: `opossum`
|
|
- Timeout: 5 seconds per carrier
|
|
- Location: `apps/backend/src/infrastructure/carriers/*/`
|
|
|
|
### 5. Caching Strategy
|
|
- **Redis for rate quotes**: 15-minute TTL
|
|
- **Cache-aside pattern**: Check cache first, fetch from carriers on miss
|
|
- **Cache key format**: `rate:{origin}:{destination}:{containerType}`
|
|
|
|
## Common Pitfalls to Avoid
|
|
|
|
❌ **DO NOT**:
|
|
- Import NestJS/TypeORM in domain layer
|
|
- Put business logic in controllers or repositories
|
|
- Use `any` type (strict mode enabled in backend)
|
|
- Skip writing tests (coverage targets enforced)
|
|
- Use `DATABASE_SYNC=true` in production (always use migrations)
|
|
- Commit `.env` files (use `.env.example` templates)
|
|
- Expose sensitive data in API responses (passwords, tokens, internal IDs)
|
|
- Skip rate limiting on public endpoints
|
|
- Use circular imports (leverage barrel exports with `index.ts`)
|
|
- Send emails without proper error handling
|
|
- Store plain text passwords (always use Argon2)
|
|
- Modify applied migrations (create new migration instead)
|
|
- Mix domain logic with framework code
|
|
|
|
✅ **DO**:
|
|
- Follow hexagonal architecture strictly (Infrastructure → Application → Domain)
|
|
- Write tests for all new features (domain 90%+, application 80%+)
|
|
- Use TypeScript path aliases (`@domain/*`, `@application/*`, `@infrastructure/*`)
|
|
- Validate all DTOs with `class-validator` decorators
|
|
- Implement circuit breakers for external APIs (carrier connectors)
|
|
- Cache frequently accessed data (Redis with TTL)
|
|
- Use structured logging (Pino JSON format)
|
|
- Document APIs with Swagger decorators (`@ApiOperation`, `@ApiResponse`)
|
|
- Run migrations before deployment (`npm run migration:run`)
|
|
- Test email sending in development with test accounts
|
|
- Use MJML for responsive email templates
|
|
- Create dedicated mappers for Domain ↔ ORM conversions
|
|
- Use Value Objects for domain concepts (Money, Email, etc.)
|
|
- Implement proper error handling with domain exceptions
|
|
- Use immutability in domain entities (return new instances on updates)
|
|
|
|
## Documentation
|
|
|
|
**Architecture & Planning**:
|
|
- [ARCHITECTURE.md](ARCHITECTURE.md) - System architecture (5,800 words)
|
|
- [DEPLOYMENT.md](DEPLOYMENT.md) - Deployment guide (4,500 words)
|
|
- [PRD.md](PRD.md) - Product requirements
|
|
- [TODO.md](TODO.md) - 30-week development roadmap
|
|
- [CARRIER_PORTAL_IMPLEMENTATION_PLAN.md](CARRIER_PORTAL_IMPLEMENTATION_PLAN.md) - Carrier portal implementation plan
|
|
|
|
**Implementation Summaries**:
|
|
- [PHASE4_SUMMARY.md](PHASE4_SUMMARY.md) - Security, monitoring, testing
|
|
- [PHASE3_COMPLETE.md](PHASE3_COMPLETE.md) - Booking workflow, exports
|
|
- [PHASE2_COMPLETE.md](PHASE2_COMPLETE.md) - Authentication, RBAC
|
|
- [PHASE-1-WEEK5-COMPLETE.md](PHASE-1-WEEK5-COMPLETE.md) - Rate search, cache
|
|
|
|
**API Documentation**:
|
|
- [apps/backend/docs/CARRIER_PORTAL_API.md](apps/backend/docs/CARRIER_PORTAL_API.md) - Carrier portal API reference
|
|
|
|
**Testing**:
|
|
- [TEST_EXECUTION_GUIDE.md](TEST_EXECUTION_GUIDE.md) - How to run all tests
|
|
- [TEST_COVERAGE_REPORT.md](TEST_COVERAGE_REPORT.md) - Coverage metrics
|
|
- [GUIDE_TESTS_POSTMAN.md](GUIDE_TESTS_POSTMAN.md) - Postman API tests
|
|
|
|
**Deployment**:
|
|
- [docker/PORTAINER_DEPLOYMENT_GUIDE.md](docker/PORTAINER_DEPLOYMENT_GUIDE.md) - Portainer setup
|
|
- [docker/DOCKER_BUILD_GUIDE.md](docker/DOCKER_BUILD_GUIDE.md) - Docker build instructions
|
|
- [DEPLOYMENT_CHECKLIST.md](DEPLOYMENT_CHECKLIST.md) - Pre-deployment checklist
|
|
|
|
## Quick Reference - Common Tasks
|
|
|
|
### Running a Single Test File
|
|
```bash
|
|
# Backend unit test
|
|
cd apps/backend
|
|
npm test -- booking.entity.spec.ts
|
|
|
|
# Backend integration test
|
|
npm run test:integration -- booking.repository.spec.ts
|
|
|
|
# Backend E2E test
|
|
npm run test:e2e -- carrier-portal.e2e-spec.ts
|
|
|
|
# Frontend test
|
|
cd apps/frontend
|
|
npm test -- BookingForm.test.tsx
|
|
```
|
|
|
|
### Debugging TypeScript Path Aliases
|
|
If imports like `@domain/*` don't resolve:
|
|
1. Check `apps/backend/tsconfig.json` has correct `paths` configuration
|
|
2. Verify VS Code is using workspace TypeScript version
|
|
3. Restart TypeScript server in VS Code: `Cmd+Shift+P` → "TypeScript: Restart TS Server"
|
|
|
|
### Common Environment Issues
|
|
|
|
**PostgreSQL connection fails**:
|
|
```bash
|
|
# Verify PostgreSQL container is running
|
|
docker ps | grep xpeditis-postgres
|
|
|
|
# Check PostgreSQL logs
|
|
docker logs xpeditis-postgres
|
|
|
|
# Restart PostgreSQL
|
|
docker-compose restart postgres
|
|
```
|
|
|
|
**Redis connection fails**:
|
|
```bash
|
|
# Verify Redis container is running
|
|
docker ps | grep xpeditis-redis
|
|
|
|
# Test Redis connection
|
|
docker exec -it xpeditis-redis redis-cli -a xpeditis_redis_password ping
|
|
# Expected: PONG
|
|
|
|
# Restart Redis
|
|
docker-compose restart redis
|
|
```
|
|
|
|
**Migrations fail**:
|
|
```bash
|
|
# Check migration status (query the database)
|
|
# The migrations are tracked in the 'migrations' table
|
|
|
|
# If stuck, revert and try again
|
|
npm run migration:revert
|
|
npm run migration:run
|
|
|
|
# Or connect to database to check manually
|
|
docker exec -it xpeditis-postgres psql -U xpeditis -d xpeditis_dev -c "SELECT * FROM migrations ORDER BY id DESC LIMIT 5;"
|
|
```
|
|
|
|
### Adding a New Feature (Step-by-Step)
|
|
|
|
1. **Create Domain Entity** (if needed):
|
|
- Location: `apps/backend/src/domain/entities/`
|
|
- Pure TypeScript, no framework imports
|
|
- Write unit tests: `*.entity.spec.ts`
|
|
|
|
2. **Create Value Objects** (if needed):
|
|
- Location: `apps/backend/src/domain/value-objects/`
|
|
- Immutable, validated in constructor
|
|
- Write unit tests: `*.vo.spec.ts`
|
|
|
|
3. **Define Domain Port Interface**:
|
|
- Location: `apps/backend/src/domain/ports/out/`
|
|
- Interface only, no implementation
|
|
|
|
4. **Create ORM Entity**:
|
|
- Location: `apps/backend/src/infrastructure/persistence/typeorm/entities/`
|
|
- File naming: `*.orm-entity.ts`
|
|
- Add `@Entity()` decorator
|
|
|
|
5. **Generate Migration**:
|
|
```bash
|
|
npm run migration:generate -- src/infrastructure/persistence/typeorm/migrations/CreateFeatureName
|
|
```
|
|
|
|
6. **Implement Repository**:
|
|
- Location: `apps/backend/src/infrastructure/persistence/typeorm/repositories/`
|
|
- Implements domain port interface
|
|
- Write integration tests
|
|
|
|
7. **Create DTOs**:
|
|
- Location: `apps/backend/src/application/dto/`
|
|
- Add `class-validator` decorators
|
|
|
|
8. **Create Controller**:
|
|
- Location: `apps/backend/src/application/controllers/`
|
|
- Add Swagger decorators
|
|
- Write E2E tests
|
|
|
|
9. **Create Application Module**:
|
|
- Location: `apps/backend/src/application/modules/`
|
|
- Register controllers, services, repositories
|
|
|
|
10. **Import Module in App.module.ts**
|
|
|
|
## Code Review Checklist
|
|
|
|
1. Hexagonal architecture principles followed
|
|
2. Domain layer has zero external dependencies
|
|
3. Unit tests written (90%+ coverage for domain)
|
|
4. Integration tests for infrastructure adapters
|
|
5. DTOs validated with class-validator
|
|
6. Swagger documentation updated
|
|
7. No secrets committed
|
|
8. TypeScript strict mode passes
|
|
9. Prettier formatting applied
|
|
10. ESLint passes with no warnings
|
|
11. Email templates tested in development
|
|
12. Carrier workflow tested end-to-end
|
|
13. Database migrations tested in development
|
|
14. ORM entities have corresponding domain entities
|
|
15. Mappers created for Domain ↔ ORM conversions
|