Appearance
Backend Layer
Overview
The PMN (Project Management Node) backend service is built using modern web technologies to provide a robust, scalable API for project management. The service follows a layered architecture pattern with clear separation of concerns and comprehensive error handling.
Technology Stack
Core Framework
- Hono: Lightweight, fast web framework for Node.js
- TypeScript: Full type safety and modern JavaScript features
- Node.js: Runtime environment (18+)
Database & ORM
- PostgreSQL: Primary relational database
- Prisma: Type-safe database client and ORM
- Redis: Caching and session storage
Authentication & Security
- Casdoor: Identity and access management
- JWT: JSON Web Token authentication
- Zod: Schema validation and type safety
Search & Analytics
- Elasticsearch: Full-text search capabilities
- Typesense: Vector search and recommendations
Additional Services
- BullMQ: Job queue management
- Novu: Notification service
- Sentry: Error tracking and monitoring
- AWS S3: File storage service
Architecture Layers
1. Presentation Layer (Routes)
Purpose: Handle HTTP requests and responses
Structure:
src/routes/
├── access.ts # Access control endpoints
├── addon.ts # Addon management
├── attachment.ts # File uploads
├── casdoor.ts # Authentication
├── comment.ts # Comment system
├── config.ts # Configuration management
├── eNode.ts # Project structure
├── excel.ts # Import/export
├── follower.ts # User following
├── history.ts # Change tracking
├── invite.ts # User invitations
├── issue.ts # Work item management
├── link.ts # Dependencies
├── marker.ts # Visual indicators
├── migrate_to.ts # Data migration
├── people.ts # User management
├── reminder.ts # Notifications
├── report.ts # Analytics
├── template.ts # Workflow templates
├── typesense.ts # Search integration
└── view.ts # Custom viewsKey Features:
- RESTful API design
- OpenAPI documentation
- Rate limiting
- CORS support
- Request validation
2. Business Logic Layer (Services)
Purpose: Implement core business logic and workflows
Structure:
src/services/
├── addonService.ts # Addon operations
├── commentService.ts # Comment management
├── eNodeService.ts # Project structure
├── excelService.ts # Import/export logic
├── historyService.ts # Change tracking
├── inviteService.ts # User invitations
├── issueService.ts # Work item logic
├── linkService.ts # Dependency management
├── markerService.ts # Visual indicators
├── peopleService.ts # User management
├── reminderService.ts # Notification logic
├── reportService.ts # Analytics generation
├── templateService.ts # Workflow templates
├── typesenseService.ts # Search operations
└── viewService.ts # Custom viewsKey Features:
- Business rule enforcement
- Data validation
- Workflow management
- Integration logic
- Error handling
3. Data Access Layer (Prisma)
Purpose: Database operations and data persistence
Structure:
prisma/
├── schema.prisma # Database schema
├── migrations/ # Database migrations
└── timescale/ # TimescaleDB schemaKey Features:
- Type-safe database queries
- Migration management
- Connection pooling
- Transaction support
- Query optimization
4. Infrastructure Layer
Purpose: Cross-cutting concerns and external services
Structure:
infra/
├── bootstrap/
│ └── init.ts # Application initialization
├── eventBus/
│ ├── EventBus.ts # Event system interface
│ ├── InMemoryEventBus.ts # In-memory implementation
│ └── NotifyNovu.ts # Notification service
├── prisma/
│ ├── prismaClient.ts # Database client
│ └── prismaFunction.ts # Database functions
└── services/
├── MqService.ts # Message queue
├── NotificationService.ts # Notifications
├── SyncerClient.ts # Data sync
├── WebsocketService.ts # Real-time
└── Worker.ts # Background jobsAPI Design Principles
RESTful Design
- Resource-based URLs:
/enodes,/issues,/people - HTTP Methods: GET, POST, PUT, DELETE, PATCH
- Status Codes: Proper HTTP response codes
- Content Types: JSON request/response format
Request Validation
typescript
// Example with Zod validation
const createIssueSchema = z.object({
title: z.string().min(1),
type: z.enum(['task', 'bug', 'story']),
enode_id: z.string().uuid(),
effort: z.number().positive().optional()
});
app.post('/issues', async (c) => {
const data = createIssueSchema.parse(await c.req.json());
// Process validated data
});Response Format
typescript
// Standard response structure
interface ApiResponse<T> {
success: boolean;
data?: T;
error?: string;
message?: string;
}Authentication & Authorization
Casdoor Integration
- Single Sign-On: Centralized authentication
- JWT Tokens: Secure session management
- Role-based Access: Granular permissions
- Multi-tenant: Organization isolation
Permission System
typescript
// Permission middleware example
app.use('/enodes/*', async (c, next) => {
const token = c.req.header('Authorization');
const user = await validateToken(token);
const permissions = await getUserPermissions(user.id, 'enode');
if (!hasPermission(permissions, c.req.method, c.req.path)) {
return c.json({ error: 'Insufficient permissions' }, 403);
}
await next();
});Data Synchronization
Real-time Updates
- WebSocket Service: Live collaboration
- Event Bus: Internal event system
- Syncer Integration: External data sync
- Notification Service: User alerts
Change Tracking
typescript
// History service example
export class HistoryService {
async trackChange(issueId: string, userId: string, changes: any) {
await this.prisma.history.create({
data: {
issue_id: issueId,
owner_id: userId,
patch: changes,
type: 'update',
type_event: 'issue_modified'
}
});
}
}Performance Optimization
Caching Strategy
- Redis Caching: Frequently accessed data
- Query Optimization: Database index usage
- Connection Pooling: Efficient database connections
- Background Processing: Async job handling
Rate Limiting
typescript
// Rate limiting middleware
app.use('*', rateLimiter({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
message: 'Too many requests from this IP'
}));Error Handling
Global Error Handler
typescript
app.onError((err, c) => {
console.error('Error:', err);
if (err instanceof Prisma.PrismaClientKnownRequestError) {
return c.json({ error: 'Database error', details: err.message }, 500);
}
if (err instanceof ZodError) {
return c.json({ error: 'Validation error', details: err.errors }, 400);
}
return c.json({ error: 'Internal server error' }, 500);
});Validation Errors
- Input Validation: Zod schema validation
- Business Rule Validation: Service layer validation
- Database Constraint Validation: Prisma error handling
- Custom Validation: Domain-specific rules
Monitoring & Observability
Logging
- Structured Logging: JSON format logs
- Log Levels: Debug, Info, Warn, Error
- Context Information: Request ID, user, timestamp
- Performance Metrics: Response time, throughput
Health Checks
typescript
app.get('/health', async (c) => {
try {
await prisma.$queryRaw`SELECT 1`;
return c.json({ status: 'healthy', timestamp: new Date().toISOString() });
} catch (error) {
return c.json({ status: 'unhealthy', error: error.message }, 500);
}
});Metrics Collection
- Response Times: API endpoint performance
- Error Rates: Failure monitoring
- Database Performance: Query execution times
- Resource Usage: Memory, CPU utilization
Security Features
Input Sanitization
- SQL Injection Prevention: Prisma ORM protection
- XSS Prevention: Output encoding
- CSRF Protection: Token validation
- Path Traversal: URL validation
Data Protection
- Encryption: Sensitive data encryption
- Access Logging: Complete audit trail
- Data Masking: PII protection
- Secure Headers: Security header implementation
Testing Strategy
Unit Testing
- Service Layer: Business logic testing
- Utility Functions: Helper function testing
- Validation: Schema validation testing
- Mocking: External service mocking
Integration Testing
- API Endpoints: End-to-end testing
- Database Operations: Data persistence testing
- Authentication: Security testing
- Performance: Load testing
Deployment & DevOps
Containerization
- Docker: Application containerization
- Docker Compose: Local development
- Multi-stage Builds: Production optimization
- Health Checks: Container health monitoring
Environment Management
- Configuration: Environment-specific settings
- Secrets: Secure credential management
- Feature Flags: Runtime configuration
- Monitoring: Production monitoring setup
Future Enhancements
Planned Features
- GraphQL API: Alternative query interface
- Event Sourcing: Enhanced audit capabilities
- Microservices: Service decomposition
- Kubernetes: Container orchestration
Performance Improvements
- Database Sharding: Horizontal scaling
- CDN Integration: Content delivery optimization
- Advanced Caching: Multi-level caching
- Load Balancing: Traffic distribution