A production-ready, open-source messaging backend API with end-to-end encryption support. Built with Node.js, TypeScript, Express, PostgreSQL, Redis, and Socket.io.
Developed and Designed by Yaduraj Singh
- π End-to-End Encryption - Signal Protocol implementation for secure messaging
- π¬ Real-time Messaging - WebSocket support with Socket.io
- π₯ User Management - Firebase authentication, user profiles, friend requests
- π Security First - JWT authentication, rate limiting, input validation, CORS
- β‘ High Performance - Optimized queries, connection pooling, Redis caching
- π Production Ready - Comprehensive logging, error handling, health checks
- π RESTful API - Clean, well-documented REST endpoints
- π WebSocket Events - Real-time notifications and updates
- Node.js >= 18.0.0
- npm >= 9.0.0
- Docker & Docker Compose (recommended) OR PostgreSQL 15+ and Redis 7+
- Clone the repository
git clone https://github.com/yourusername/plasticworld-backend.git
cd plasticworld-backend- Install dependencies
npm install- Set up environment variables
cp .env.example .envEdit .env with your configuration (see .env.example for all options).
- Set up databases with Docker Compose (recommended)
# Start PostgreSQL and Redis
docker-compose up -d
# Verify containers are running
docker-compose ps- Run database migrations
npm run db:migrate- Build TypeScript
npm run build- Start the server
# Development (with hot reload)
npm run dev
# Production
npm startThe API will be available at http://localhost:3000
The project includes docker-compose.yml for easy local development with PostgreSQL and Redis.
# Start PostgreSQL and Redis
docker-compose up -d
# View logs
docker-compose logs -f
# Stop services
docker-compose down
# Stop and remove volumes (clean slate)
docker-compose down -vThe docker-compose.yml uses environment variables from your .env file:
DB_NAME,DB_USER,DB_PASSWORD- PostgreSQL configurationREDIS_PASSWORD- Redis password (optional)
The project includes a production-ready Dockerfile with multi-stage build:
# Build the Docker image
docker build -t plasticworld-backend .
# Run the container
docker run -p 3000:3000 --env-file .env plasticworld-backend- Multi-stage build for optimized image size
- Non-root user for security
- Health check endpoint
- Proper signal handling with dumb-init
- Production dependencies only
You can extend docker-compose.yml to include the backend API:
services:
api:
build: .
ports:
- "3000:3000"
env_file:
- .env
depends_on:
- postgres
- redis
networks:
- plasticworld-networkThen run:
docker-compose up --build- Development:
http://localhost:3000/api/v1 - Production:
https://your-domain.com/api/v1
- Development:
ws://localhost:3000 - Production:
wss://your-domain.com
POST /auth/google-signin- Sign in with Google (Firebase)POST /auth/refresh- Refresh access tokenPOST /auth/logout- Logout and invalidate sessionPOST /auth/profile-complete- Complete user profile after first sign-in
GET /users/me- Get current user profilePUT /users/me- Update current user profileGET /users/search- Search users by username/emailGET /users/:userId- Get public user profile
GET /friends- Get friends listPOST /friends/request- Send friend requestPOST /friends/:friendshipId/accept- Accept friend requestPOST /friends/:friendshipId/reject- Reject friend requestDELETE /friends/:friendshipId- Remove friendPOST /friends/:userId/block- Block userDELETE /friends/:userId/block- Unblock user
POST /messages- Send a messageGET /messages- Get messages (with pagination)GET /messages/:messageId- Get specific messagePUT /messages/:messageId- Edit messageDELETE /messages/:messageId- Delete messagePOST /messages/:messageId/delivered- Mark message as deliveredPOST /messages/:messageId/read- Mark message as readPOST /messages/read- Mark multiple messages as read
GET /encryption/keys/prekey-bundle/:userId/:deviceId- Get prekey bundle for key exchangePOST /encryption/session/establish- Establish encryption sessionGET /encryption/keys- Get current user's encryption keys
GET /health- Health check endpoint
For detailed API documentation, see API_DOCUMENTATION.md
message:send- Send a messagetyping:start- Start typing indicatortyping:stop- Stop typing indicatorstatus:update- Update user status
message:received- New message receivedmessage:delivered- Message delivered to recipientmessage:read- Message read by recipienttyping:start- User started typingtyping:stop- User stopped typinguser:online- User came onlineuser:offline- User went offlinefriend:request:received- New friend requestfriend:request:accepted- Friend request accepted
- Runtime: Node.js with TypeScript
- Framework: Express.js
- Database: PostgreSQL
- Cache: Redis
- WebSocket: Socket.io
- Authentication: Firebase Admin SDK + JWT
- Encryption: Signal Protocol (X3DH + Double Ratchet)
- Logging: Winston
plasticworld-backend/
βββ src/
β βββ config/ # Configuration (database, redis, firebase, socket)
β βββ middleware/ # Express middleware (auth, error handling)
β βββ routes/ # API route handlers
β βββ services/ # Business logic services
β βββ migrations/ # Database migrations
β βββ utils/ # Utilities (logger, validation)
β βββ app.ts # Express app setup
β βββ server.ts # Server entry point
βββ dist/ # Compiled JavaScript (generated)
βββ logs/ # Log files (generated)
βββ docker-compose.yml # Docker setup for local development
βββ Dockerfile # Production Docker image
βββ package.json
graph TB
subgraph "Client Layer"
iOS[iOS App<br/>Swift/SwiftUI]
Android[Android App<br/>Kotlin/Compose]
Web[Web App<br/>React/Next.js]
end
subgraph "Network Layer"
CF[Cloudflare Tunnel<br/>CDN & DDoS Protection]
LB[Load Balancer<br/>PM2 Cluster]
end
subgraph "Application Layer"
API[REST API<br/>Express.js + TypeScript]
WS[WebSocket Server<br/>Socket.io]
end
subgraph "Business Logic Layer"
Auth[Authentication Service<br/>Firebase + JWT]
User[User Service<br/>Profile Management]
Friend[Friendship Service<br/>Friend Requests]
Message[Messaging Service<br/>Real-time Chat]
Encrypt[Encryption Service<br/>Signal Protocol]
end
subgraph "Data Layer"
PG[(PostgreSQL<br/>Primary Database)]
Redis[(Redis<br/>Cache & Sessions)]
Firebase[Firebase Auth<br/>OAuth Provider]
end
subgraph "Infrastructure"
Docker[Docker Containers<br/>PostgreSQL & Redis]
PM2[PM2 Process Manager<br/>Auto-restart & Clustering]
Logs[Winston Logger<br/>Structured Logging]
end
iOS --> CF
Android --> CF
Web --> CF
CF --> LB
LB --> API
LB --> WS
API --> Auth
API --> User
API --> Friend
API --> Message
API --> Encrypt
WS --> Message
WS --> User
Auth --> Firebase
Auth --> Redis
User --> PG
Friend --> PG
Message --> PG
Encrypt --> PG
Encrypt --> Redis
API --> Redis
WS --> Redis
Docker --> PG
Docker --> Redis
PM2 --> API
PM2 --> WS
API --> Logs
WS --> Logs
style iOS fill:#007AFF
style Android fill:#3DDC84
style Web fill:#61DAFB
style CF fill:#F38020
style API fill:#339933
style WS fill:#010101
style PG fill:#336791
style Redis fill:#DC382D
style Firebase fill:#FFCA28
sequenceDiagram
participant Client
participant Firebase
participant Backend
participant PostgreSQL
participant Redis
Client->>Firebase: Sign in with Google
Firebase-->>Client: Firebase ID Token
Client->>Backend: POST /auth/google-signin<br/>{idToken, deviceInfo}
Backend->>Firebase: Verify ID Token
Firebase-->>Backend: User Info (email, name, photo)
Backend->>PostgreSQL: Check if user exists<br/>(by Firebase UID or email)
PostgreSQL-->>Backend: User data (or null)
alt User doesn't exist
Backend->>PostgreSQL: Create new user<br/>Generate username
PostgreSQL-->>Backend: User created
else User exists but inactive
Backend->>PostgreSQL: Reactivate user<br/>Update Firebase UID
PostgreSQL-->>Backend: User reactivated
end
Backend->>PostgreSQL: Create/update device record
PostgreSQL-->>Backend: Device created
Backend->>Backend: Generate JWT tokens<br/>(access + refresh)
Backend->>Redis: Store session<br/>{userId, deviceId, refreshToken}
Redis-->>Backend: Session stored
Backend-->>Client: {accessToken, refreshToken, user, device}
Client->>Client: Store tokens securely<br/>(Keychain/SecureStorage)
sequenceDiagram
participant Sender
participant Backend
participant PostgreSQL
participant Redis
participant WebSocket
participant Recipient
Sender->>Sender: Encrypt message<br/>(Signal Protocol)
Sender->>Backend: POST /messages<br/>{recipientId, encryptedContent, encryptedKey}
Backend->>PostgreSQL: Check friendship<br/>& block status
PostgreSQL-->>Backend: Friendship status
alt Not friends or blocked
Backend-->>Sender: 403 Forbidden<br/>{code: "NOT_FRIENDS"}
else Valid
Backend->>PostgreSQL: Insert message<br/>{senderId, recipientId, encryptedContent, status: "sent"}
PostgreSQL-->>Backend: Message created
Backend->>Redis: Check if recipient online
Redis-->>Backend: Online status
Backend-->>Sender: 201 Created<br/>{message}
alt Recipient online
Backend->>WebSocket: Emit to recipient<br/>"message:received"
WebSocket->>Recipient: Real-time notification<br/>{message}
Recipient->>Recipient: Show notification<br/>Update UI
else Recipient offline
Backend->>PostgreSQL: Queue for delivery<br/>(message status: "sent")
end
Sender->>Sender: Update UI<br/>Show "sent" status
end
sequenceDiagram
participant Alice
participant Backend
participant PostgreSQL
participant Redis
participant Bob
Note over Alice: First message to Bob
Alice->>Backend: GET /encryption/keys/prekey-bundle/:bobId/:deviceId
Backend->>PostgreSQL: Get Bob's keys<br/>{identityKey, signedPreKey, oneTimePreKey}
PostgreSQL-->>Backend: Prekey bundle
Backend-->>Alice: Prekey bundle
Alice->>Alice: Perform X3DH key exchange<br/>Generate shared secret (root key)
Alice->>Backend: POST /encryption/session/establish<br/>{recipientUserId, recipientDeviceId}
Backend->>Backend: Perform X3DH<br/>(server-side validation)
Backend->>Redis: Store session<br/>{sessionId, rootKey, chainKeys}
Redis-->>Backend: Session stored
Backend-->>Alice: Session established
Alice->>Alice: Initialize Double Ratchet<br/>{rootKey, chainKeys}
Note over Alice: Encrypt message
Alice->>Alice: Encrypt with Double Ratchet<br/>{plaintext β ciphertext + nonce}
Alice->>Backend: POST /messages<br/>{encryptedContent, encryptedKey}
Backend->>PostgreSQL: Store encrypted message<br/>(server never sees plaintext)
PostgreSQL-->>Backend: Message stored
Backend->>Bob: Deliver via WebSocket<br/>{encryptedContent, encryptedKey}
Bob->>Bob: Decrypt with Double Ratchet<br/>{ciphertext + nonce β plaintext}
Note over Alice,Bob: Subsequent messages use<br/>Double Ratchet only<br/>(no X3DH needed)
erDiagram
USERS ||--o{ DEVICES : has
USERS ||--o{ SESSIONS : has
USERS ||--o{ FRIENDSHIPS : "requester/recipient"
USERS ||--o{ BLOCKS : "blocker/blocked"
USERS ||--o{ MESSAGES : "sender/recipient"
USERS ||--o{ ENCRYPTION_KEYS : has
DEVICES ||--o{ SESSIONS : has
DEVICES ||--o{ ENCRYPTION_KEYS : has
FRIENDSHIPS ||--o{ MESSAGES : enables
MESSAGES ||--o{ MESSAGE_RECEIPTS : has
MESSAGES ||--o{ MESSAGE_MEDIA : has
MESSAGES ||--o{ MESSAGES : "replies to"
USERS {
uuid id PK
varchar firebase_uid UK
varchar username UK
varchar email UK
varchar name
text profile_picture_url
enum status
timestamp last_seen
boolean is_active
timestamp created_at
timestamp updated_at
}
DEVICES {
uuid id PK
uuid user_id FK
varchar device_name
enum device_type
boolean is_active
timestamp created_at
timestamp updated_at
}
SESSIONS {
uuid id PK
uuid user_id FK
uuid device_id FK
varchar refresh_token_hash
timestamp expires_at
boolean is_active
timestamp created_at
}
FRIENDSHIPS {
uuid id PK
uuid requester_id FK
uuid recipient_id FK
enum status
timestamp requested_at
timestamp responded_at
}
MESSAGES {
uuid id PK
uuid sender_id FK
uuid recipient_id FK
text encrypted_content
text encrypted_key
enum message_type
enum status
timestamp sent_at
timestamp delivered_at
timestamp read_at
}
ENCRYPTION_KEYS {
uuid id PK
uuid user_id FK
uuid device_id FK
text identity_key_public
text signed_prekey_public
integer prekey_count
boolean is_active
}
graph LR
subgraph "Client"
Request[API Request]
Response[API Response]
end
subgraph "Middleware Layer"
CORS[CORS Middleware]
RateLimit[Rate Limiting]
Auth[Auth Middleware]
Validation[Validation Middleware]
ErrorHandler[Error Handler]
end
subgraph "Route Handler"
Controller[Route Controller]
end
subgraph "Service Layer"
Service[Business Logic Service]
end
subgraph "Data Layer"
DB[(PostgreSQL)]
Cache[(Redis)]
end
Request --> CORS
CORS --> RateLimit
RateLimit --> Auth
Auth --> Validation
Validation --> Controller
Controller --> Service
Service --> DB
Service --> Cache
DB --> Service
Cache --> Service
Service --> Controller
Controller --> ErrorHandler
ErrorHandler --> Response
style Request fill:#4CAF50
style Response fill:#2196F3
style Auth fill:#FF9800
style Service fill:#9C27B0
style DB fill:#336791
style Cache fill:#DC382D
sequenceDiagram
participant Client
participant Backend
participant Redis
participant PostgreSQL
Client->>Backend: API Request<br/>Authorization: Bearer <expired-token>
Backend->>Backend: Verify JWT token
Backend-->>Client: 401 Unauthorized<br/>{code: "TOKEN_EXPIRED"}
Client->>Backend: POST /auth/refresh<br/>{refreshToken}
Backend->>Backend: Verify refresh token<br/>(JWT signature)
Backend->>Redis: Get session<br/>{userId, deviceId}
Redis-->>Backend: Session data
alt Session valid
Backend->>PostgreSQL: Verify device exists<br/>& user is active
PostgreSQL-->>Backend: Device & user valid
Backend->>Backend: Generate new token pair
Backend->>Redis: Update session<br/>{newRefreshToken}
Redis-->>Backend: Session updated
Backend-->>Client: {newAccessToken, newRefreshToken}
Client->>Client: Update stored tokens
Client->>Backend: Retry original request<br/>with new access token
Backend-->>Client: Original response
else Session invalid
Backend-->>Client: 401 Unauthorized<br/>{code: "SESSION_INVALID"}
Client->>Client: Redirect to login
end
sequenceDiagram
participant Sender
participant Backend
participant PostgreSQL
participant WebSocket
participant Recipient
Note over Recipient: Message received<br/>(via WebSocket or polling)
Recipient->>Backend: POST /messages/:id/delivered
Backend->>PostgreSQL: Update message<br/>{deliveredAt, status: "delivered"}
PostgreSQL-->>Backend: Updated
Backend->>WebSocket: Emit to sender<br/>"message:delivered"
WebSocket->>Sender: Delivery notification<br/>{messageId}
Sender->>Sender: Update UI<br/>Show "delivered" status
Note over Recipient: User opens message<br/>& reads content
Recipient->>Backend: POST /messages/:id/read<br/>or POST /messages/read (bulk)
Backend->>PostgreSQL: Update message(s)<br/>{readAt, status: "read"}
PostgreSQL-->>Backend: Updated
Backend->>PostgreSQL: Update unread count<br/>(decrement)
PostgreSQL-->>Backend: Count updated
Backend->>WebSocket: Emit to sender<br/>"message:read"
WebSocket->>Sender: Read receipt<br/>{messageId}
Sender->>Sender: Update UI<br/>Show "read" status
sequenceDiagram
participant UserA
participant Backend
participant PostgreSQL
participant WebSocket
participant UserB
UserA->>Backend: POST /friends/request<br/>{userId: UserB}
Backend->>PostgreSQL: Check if already friends<br/>or blocked
PostgreSQL-->>Backend: Status check
alt Already friends
Backend-->>UserA: 409 Conflict<br/>{code: "ALREADY_FRIENDS"}
else Blocked
Backend-->>UserA: 403 Forbidden<br/>{code: "BLOCKED"}
else Valid request
Backend->>PostgreSQL: Create friendship<br/>{requesterId: UserA, status: "pending"}
PostgreSQL-->>Backend: Friendship created
Backend->>Redis: Check if UserB online
Redis-->>Backend: Online status
Backend-->>UserA: 201 Created<br/>{friendship}
alt UserB online
Backend->>WebSocket: Emit to UserB<br/>"friend:request:received"
WebSocket->>UserB: Notification<br/>{friendship, requester}
UserB->>UserB: Show notification<br/>"New friend request"
end
end
Note over UserB: UserB sees request<br/>& decides to accept
UserB->>Backend: POST /friends/:friendshipId/accept
Backend->>PostgreSQL: Update friendship<br/>{status: "accepted", respondedAt}
PostgreSQL-->>Backend: Updated
Backend->>WebSocket: Emit to UserA<br/>"friend:request:accepted"
WebSocket->>UserA: Notification<br/>{friendship}
Backend-->>UserB: 200 OK<br/>{friendship}
UserA->>UserA: Update UI<br/>Show UserB as friend
UserB->>UserB: Update UI<br/>Show UserA as friend
stateDiagram-v2
[*] --> Disconnected
Disconnected --> Connecting: Client connects with access token
Connecting --> Authenticating: Socket.io connection established
Authenticating --> Authenticated: Token validated, User & device verified
Authenticating --> Disconnected: Authentication failed (invalid token)
Authenticated --> Connected: Join user room, Set online status
Connected --> ReceivingEvents: Listen for events
ReceivingEvents --> ReceivingEvents: message:received, typing:start/stop, user:online/offline, status:update
Connected --> SendingEvents: Emit events
SendingEvents --> SendingEvents: message:send, typing:start/stop, status:update, message:read
ReceivingEvents --> Connected
SendingEvents --> Connected
Connected --> Disconnected: Client disconnects<br/>or error
Disconnected --> [*]
sequenceDiagram
participant UserA
participant WebSocket
participant Backend
participant Redis
participant UserB
UserA->>UserA: User starts typing
UserA->>WebSocket: Emit "typing:start"<br/>{recipientId: UserB}
WebSocket->>Backend: Handle typing event
Backend->>Redis: Store typing indicator<br/>{userId: UserA, recipientId: UserB, timestamp}
Redis-->>Backend: Stored
Backend->>Redis: Check if UserB online
Redis-->>Backend: Online status
alt UserB online
Backend->>WebSocket: Emit to UserB<br/>"typing:start"
WebSocket->>UserB: Real-time event<br/>{userId: UserA, name: "User A"}
UserB->>UserB: Show typing indicator<br/>"User A is typing..."
end
Note over UserA: User stops typing<br/>(after 3 seconds timeout)
UserA->>WebSocket: Emit "typing:stop"<br/>{recipientId: UserB}
WebSocket->>Backend: Handle stop event
Backend->>Redis: Remove typing indicator
Redis-->>Backend: Removed
Backend->>WebSocket: Emit to UserB<br/>"typing:stop"
WebSocket->>UserB: Real-time event<br/>{userId: UserA}
UserB->>UserB: Hide typing indicator
stateDiagram-v2
[*] --> Draft: User composes message
Draft --> Encrypting: User sends message
Encrypting --> Encrypted: Signal Protocol encryption (client-side)
Encrypted --> Sending: POST /messages API call
Sending --> Sent: Message stored in database
Sent --> Delivering: Recipient device receives
Delivering --> Delivered: Message delivered
Delivered --> Reading: Recipient opens message
Reading --> Read: Message read
Read --> [*]: Message lifecycle complete
Sent --> Editing: User edits message (within 15 minutes)
Editing --> Sent: PUT /messages/:id
Sent --> Deleting: User deletes message
Deleting --> Deleted: DELETE /messages/:id, soft delete (deleted_at)
Deleted --> [*]
note right of Encrypting
Client-side encryption
Server never sees plaintext
end note
note right of Sent
Real-time delivery
via WebSocket if online
end note
sequenceDiagram
participant Device1
participant Backend
participant PostgreSQL
participant Redis
participant Device2
Note over Device1: User signs in on Device 1
Device1->>Backend: POST /auth/google-signin<br/>{deviceInfo: Device1}
Backend->>PostgreSQL: Create device record<br/>{deviceId: D1, deviceType: "ios"}
PostgreSQL-->>Backend: Device created
Backend-->>Device1: {accessToken, device: D1}
Note over Device2: User signs in on Device 2
Device2->>Backend: POST /auth/google-signin<br/>{deviceInfo: Device2}
Backend->>PostgreSQL: Create device record<br/>{deviceId: D2, deviceType: "android"}
PostgreSQL-->>Backend: Device created
Backend-->>Device2: {accessToken, device: D2}
Note over Device1: User sends message from Device 1
Device1->>Backend: POST /messages<br/>{recipientId, encryptedContent}
Backend->>PostgreSQL: Store message
Backend->>Redis: Check recipient online devices
Redis-->>Backend: [Device3, Device4]
Backend->>Backend: Broadcast to all recipient devices<br/>(via WebSocket)
Backend->>Device2: Message notification<br/>(if Device2 is recipient)
Note over Device2: User reads message on Device 2
Device2->>Backend: POST /messages/:id/read
Backend->>PostgreSQL: Update message status
Backend->>Redis: Update unread count
Backend->>Backend: Broadcast read receipt<br/>to all sender devices
Backend->>Device1: Read receipt notification<br/>{messageId, readAt}
Device1->>Device1: Update UI<br/>Show "read" status
graph TB
subgraph "Caching Strategy"
RedisCache[Redis Cache<br/>User Profiles, Sessions]
QueryCache[Query Result Cache<br/>Friends Lists, Conversations]
SessionCache[Session Cache<br/>Active Sessions]
end
subgraph "Database Optimization"
Indexes[Database Indexes<br/>User Lookups, Message Queries]
ConnectionPool[Connection Pooling<br/>PostgreSQL Pool]
QueryOptimization[Query Optimization<br/>Efficient Joins]
end
subgraph "API Optimization"
Pagination[Pagination<br/>Limit/Offset]
LazyLoading[Lazy Loading<br/>On-Demand Data]
Compression[Response Compression<br/>Gzip]
end
subgraph "Real-Time Optimization"
WebSocketPool[WebSocket Connection Pool<br/>Reuse Connections]
EventBatching[Event Batching<br/>Group Updates]
Debouncing[Debouncing<br/>Typing Indicators]
end
RedisCache --> Indexes
QueryCache --> ConnectionPool
SessionCache --> QueryOptimization
Indexes --> Pagination
ConnectionPool --> LazyLoading
QueryOptimization --> Compression
Pagination --> WebSocketPool
LazyLoading --> EventBatching
Compression --> Debouncing
style RedisCache fill:#DC382D
style Indexes fill:#336791
style Pagination fill:#4CAF50
style WebSocketPool fill:#010101
graph TB
subgraph "Client Security"
SecureStorage[Secure Token Storage<br/>Keychain/SecureStorage]
ClientEncrypt[Client-Side Encryption<br/>Signal Protocol]
end
subgraph "Network Security"
HTTPS[HTTPS/TLS<br/>Encrypted Transport]
CFProtection[Cloudflare Protection<br/>DDoS, WAF, Rate Limiting]
end
subgraph "Application Security"
JWTAuth[JWT Authentication<br/>Signed & Verified]
RateLimit[Rate Limiting<br/>100 req/15min]
CORS[CORS Policy<br/>Whitelisted Origins]
Helmet[Security Headers<br/>Helmet.js]
Validation[Input Validation<br/>Zod Schemas]
end
subgraph "Data Security"
E2EEncrypt[End-to-End Encryption<br/>Signal Protocol]
DBEncrypt[Database Encryption<br/>Encrypted Fields]
SessionSecure[Secure Sessions<br/>Redis with TTL]
end
subgraph "Infrastructure Security"
Firewall[Firewall Rules<br/>Port Restrictions]
Secrets[Secret Management<br/>Environment Variables]
Logging[Audit Logging<br/>Winston Logger]
end
SecureStorage --> HTTPS
ClientEncrypt --> HTTPS
HTTPS --> CFProtection
CFProtection --> JWTAuth
JWTAuth --> RateLimit
RateLimit --> CORS
CORS --> Helmet
Helmet --> Validation
Validation --> E2EEncrypt
E2EEncrypt --> DBEncrypt
DBEncrypt --> SessionSecure
SessionSecure --> Firewall
Firewall --> Secrets
Secrets --> Logging
style SecureStorage fill:#4CAF50
style ClientEncrypt fill:#4CAF50
style HTTPS fill:#2196F3
style CFProtection fill:#F38020
style JWTAuth fill:#FF9800
style E2EEncrypt fill:#9C27B0
style DBEncrypt fill:#336791
For more detailed architecture diagrams, see ARCHITECTURE_DIAGRAMS.md
- Authentication: Firebase OAuth + JWT tokens
- Authorization: Role-based access control
- Encryption: End-to-end encryption with Signal Protocol
- Rate Limiting: 100 requests per 15 minutes per IP
- CORS: Configurable origin whitelist
- Input Validation: Zod schema validation
- SQL Injection Prevention: Parameterized queries
- Security Headers: Helmet.js
# Run tests
npm test
# Run tests in watch mode
npm run test:watch
# Run tests with coverage
npm run test:coverage# Lint code
npm run lint
# Fix linting issues
npm run lint:fix
# Format code
npm run format
# Type check
npm run typecheck# Run migrations
npm run db:migrate
# Create new migration (manual)
# Create file in src/migrations/XXX_description.sql- Logging: Winston with daily rotation
- Health Checks:
/healthendpoint - Error Tracking: Structured error logging
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow TypeScript best practices
- Write tests for new features
- Update documentation
- Follow the existing code style
- Add JSDoc comments for public APIs
See CONTRIBUTING.md for detailed guidelines.
This project is licensed under the MIT License - see the LICENSE file for details.
- Signal Protocol for encryption algorithms
- Firebase for authentication
- Express.js community
- All contributors
Yaduraj Singh
- Email: yadurajsingham@gmail.com
- GitHub: @YadurajManu
- Project: PlasticWorld Backend
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Made with β€οΈ for secure, real-time messaging
Developed and Designed by Yaduraj Singh