|
| 1 | +# Central Communication Server (CCS) - Detailed Design |
| 2 | + |
| 3 | +## 1. Introduction |
| 4 | + |
| 5 | +This document outlines the detailed design for the Central Communication Server (CCS). The CCS is a core component responsible for managing real-time communication, user authentication, presence, and message persistence. |
| 6 | + |
| 7 | +## 2. Technology Stack |
| 8 | + |
| 9 | +* **Programming Language:** Python 3.9+ |
| 10 | +* **Web Framework:** FastAPI |
| 11 | +* **Asynchronous Server Gateway Interface (ASGI):** Uvicorn |
| 12 | +* **Real-time Communication Protocol:** WebSockets |
| 13 | +* **Database:** PostgreSQL |
| 14 | +* **Authentication:** JSON Web Tokens (JWT) |
| 15 | +* **Caching (Optional, for future scalability):** Redis (e.g., for presence status, session management) |
| 16 | + |
| 17 | +## 3. System Architecture Overview |
| 18 | + |
| 19 | +The CCS will expose WebSocket endpoints for real-time communication and HTTP endpoints for authentication and user management. It will interact with the PostgreSQL database for persistent storage. |
| 20 | + |
| 21 | +``` |
| 22 | ++-------------------+ +------------------------+ +-------------------+ |
| 23 | +| Clients |<---->| CCS |<---->| PostgreSQL | |
| 24 | +| (Web, Mobile, CLI)| | (FastAPI, WebSockets) | | Database | |
| 25 | ++-------------------+ +------------------------+ +-------------------+ |
| 26 | + | |
| 27 | + | (Future Enhancement) |
| 28 | + | |
| 29 | + v |
| 30 | + +-------+ |
| 31 | + | Redis | |
| 32 | + +-------+ |
| 33 | +``` |
| 34 | + |
| 35 | +## 4. Module Structure |
| 36 | + |
| 37 | +The CCS will be organized into the following primary modules: |
| 38 | + |
| 39 | +* **`main.py`**: Entry point of the application. Initializes FastAPI app, database connections, and routes. |
| 40 | +* **`auth/`**: Handles user authentication and JWT management. |
| 41 | + * `auth_service.py`: Logic for user registration, login, password hashing, JWT generation and validation. |
| 42 | + * `auth_routes.py`: HTTP API endpoints for `/register`, `/login`. |
| 43 | +* **`users/`**: Manages user profiles and presence. |
| 44 | + * `user_models.py`: Pydantic models for user data. |
| 45 | + * `user_service.py`: Logic for fetching user details, updating profiles. |
| 46 | + * `presence_service.py`: Manages user online/offline status and broadcasts updates. |
| 47 | +* **`messaging/`**: Handles real-time message routing and persistence. |
| 48 | + * `connection_manager.py`: Manages active WebSocket connections. Stores connections per user or per group. |
| 49 | + * `message_router.py`: Routes incoming messages to appropriate recipients (one-to-one, group). |
| 50 | + * `message_service.py`: Handles storage and retrieval of messages from the database. |
| 51 | + * `websocket_routes.py`: WebSocket endpoints for establishing connections and message exchange. |
| 52 | +* **`database/`**: Manages database interactions. |
| 53 | + * `db_config.py`: Database connection settings. |
| 54 | + * `db_models.py`: SQLAlchemy ORM models for database tables. |
| 55 | + * `crud.py`: Create, Read, Update, Delete operations for database models. |
| 56 | +* **`core/`**: Core utilities and configurations. |
| 57 | + * `config.py`: Application settings (e.g., JWT secret, database URL). |
| 58 | + * `security.py`: Password hashing utilities. |
| 59 | +* **`tests/`**: Unit and integration tests for all modules. |
| 60 | + |
| 61 | +## 5. Key Classes and Functions |
| 62 | + |
| 63 | +### 5.1. `auth/auth_service.py` |
| 64 | + |
| 65 | +* `class AuthService`: |
| 66 | + * `async def register_user(user_data: UserCreateSchema) -> UserSchema`: Registers a new user. Hashes password. Stores in DB. |
| 67 | + * `async def authenticate_user(username: str, password: str) -> Optional[UserSchema]`: Authenticates a user. |
| 68 | + * `def create_access_token(data: dict, expires_delta: Optional[timedelta] = None) -> str`: Creates a JWT. |
| 69 | + * `async def get_current_user(token: str = Depends(oauth2_scheme)) -> UserSchema`: Decodes JWT and retrieves user. |
| 70 | + |
| 71 | +### 5.2. `users/presence_service.py` |
| 72 | + |
| 73 | +* `class PresenceService`: |
| 74 | + * `active_users: set[str] = set()`: Stores user IDs of currently online users. |
| 75 | + * `async def user_connected(user_id: str)`: Marks user as online, broadcasts presence. |
| 76 | + * `async def user_disconnected(user_id: str)`: Marks user as offline, broadcasts presence. |
| 77 | + * `async def broadcast_presence_update(user_id: str, status: str)` |
| 78 | + |
| 79 | +### 5.3. `messaging/connection_manager.py` |
| 80 | + |
| 81 | +* `class ConnectionManager`: |
| 82 | + * `active_connections: dict[str, WebSocket] = {}`: Maps user_id to WebSocket connection. |
| 83 | + * `async def connect(user_id: str, websocket: WebSocket)`: Accepts and stores a new connection. |
| 84 | + * `def disconnect(user_id: str)`: Removes a connection. |
| 85 | + * `async def send_personal_message(message: str, user_id: str)` |
| 86 | + * `async def broadcast(message: str)`: Sends a message to all connected clients (e.g., for system-wide announcements or group chats if not handled separately). |
| 87 | + * `async def send_to_group(group_id: str, message: str)`: (If group chat is implemented) Sends message to all members of a group. |
| 88 | + |
| 89 | +### 5.4. `messaging/message_router.py` |
| 90 | + |
| 91 | +* `class MessageRouter`: |
| 92 | + * `def __init__(self, connection_manager: ConnectionManager, message_service: MessageService)` |
| 93 | + * `async def route_message(sender_id: str, raw_message: dict)`: Parses message type (e.g., one-to-one, group, system), validates, and forwards to `ConnectionManager` or `MessageService`. |
| 94 | + |
| 95 | +### 5.5. `messaging/message_service.py` |
| 96 | + |
| 97 | +* `class MessageService`: |
| 98 | + * `async def store_message(sender_id: str, recipient_id: str, content: str, timestamp: datetime) -> MessageSchema`: Stores a message in the database. |
| 99 | + * `async def get_message_history(user_id1: str, user_id2: str, limit: int = 100, offset: int = 0) -> list[MessageSchema]`: Retrieves chat history between two users. |
| 100 | + * `async def get_group_message_history(group_id: str, limit: int = 100, offset: int = 0) -> list[MessageSchema]`: Retrieves group message history. |
| 101 | + |
| 102 | +## 6. Database Schema (PostgreSQL) |
| 103 | + |
| 104 | +* **`users` table:** |
| 105 | + * `id`: SERIAL PRIMARY KEY |
| 106 | + * `username`: VARCHAR(50) UNIQUE NOT NULL |
| 107 | + * `email`: VARCHAR(100) UNIQUE NOT NULL |
| 108 | + * `hashed_password`: VARCHAR(255) NOT NULL |
| 109 | + * `full_name`: VARCHAR(100) |
| 110 | + * `created_at`: TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP |
| 111 | + * `last_login_at`: TIMESTAMP WITH TIME ZONE |
| 112 | + |
| 113 | +* **`messages` table:** |
| 114 | + * `id`: SERIAL PRIMARY KEY |
| 115 | + * `sender_id`: INTEGER REFERENCES `users`(`id`) NOT NULL |
| 116 | + * `recipient_id`: INTEGER REFERENCES `users`(`id`) NULL (for one-to-one messages) |
| 117 | + * `group_id`: INTEGER REFERENCES `groups`(`id`) NULL (for group messages) |
| 118 | + * `content`: TEXT NOT NULL |
| 119 | + * `sent_at`: TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP |
| 120 | + * `is_read`: BOOLEAN DEFAULT FALSE |
| 121 | + |
| 122 | +* **`groups` table:** (For group chat functionality) |
| 123 | + * `id`: SERIAL PRIMARY KEY |
| 124 | + * `name`: VARCHAR(100) NOT NULL |
| 125 | + * `description`: TEXT |
| 126 | + * `created_by`: INTEGER REFERENCES `users`(`id`) NOT NULL |
| 127 | + * `created_at`: TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP |
| 128 | + |
| 129 | +* **`group_members` table:** (Many-to-many relationship between users and groups) |
| 130 | + * `id`: SERIAL PRIMARY KEY |
| 131 | + * `user_id`: INTEGER REFERENCES `users`(`id`) NOT NULL |
| 132 | + * `group_id`: INTEGER REFERENCES `groups`(`id`) NOT NULL |
| 133 | + * `joined_at`: TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP |
| 134 | + * UNIQUE (`user_id`, `group_id`) |
| 135 | + |
| 136 | +* **Constraints/Indexes:** |
| 137 | + * Indexes on `users.username`, `users.email`. |
| 138 | + * Indexes on `messages.sender_id`, `messages.recipient_id`, `messages.group_id`, `messages.sent_at`. |
| 139 | + * Indexes on `groups.name`. |
| 140 | + * Foreign key constraints as defined above. |
| 141 | + |
| 142 | +## 7. Error Handling Strategy |
| 143 | + |
| 144 | +* **HTTP API Endpoints:** |
| 145 | + * Use standard HTTP status codes (e.g., 200 OK, 201 Created, 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 500 Internal Server Error). |
| 146 | + * FastAPI's `HTTPException` will be used for standard error responses. |
| 147 | + * Response body for errors: `{"detail": "Error message or description"}`. |
| 148 | +* **WebSocket Communication:** |
| 149 | + * Define a standard message format for errors, e.g., `{"type": "error", "payload": {"code": <error_code>, "message": "<description>"}}`. |
| 150 | + * `1xxx` series WebSocket close codes will be used where appropriate. |
| 151 | + * Examples of error codes: |
| 152 | + * `1001`: Authentication failed |
| 153 | + * `1002`: Invalid message format |
| 154 | + * `1003`: Target user offline (if not queuing messages) |
| 155 | + * `1004`: Rate limit exceeded |
| 156 | +* **Server-Side Errors:** |
| 157 | + * All unexpected errors will be caught at a global level and logged. |
| 158 | + * A generic error message will be sent to the client to avoid exposing sensitive details. |
| 159 | + |
| 160 | +## 8. Logging Strategy |
| 161 | + |
| 162 | +* **Library:** Standard Python `logging` module, configured by FastAPI/Uvicorn. |
| 163 | +* **Log Levels:** |
| 164 | + * `DEBUG`: Detailed information, typically of interest only when diagnosing problems. (e.g., raw incoming/outgoing messages, connection attempts). |
| 165 | + * `INFO`: Confirmation that things are working as expected. (e.g., user login, message sent, server startup). |
| 166 | + * `WARNING`: An indication that something unexpected happened, or indicative of some problem in the near future (e.g., 'disk space low'). (e.g., failed login attempt, message delivery retry). |
| 167 | + * `ERROR`: Due to a more serious problem, the software has not been able to perform some function. (e.g., database connection failure, unhandled exception in a request). |
| 168 | + * `CRITICAL`: A serious error, indicating that the program itself may be unable to continue running. |
| 169 | +* **Log Format:** |
| 170 | + * `%(asctime)s - %(name)s - %(levelname)s - %(module)s.%(funcName)s:%(lineno)d - %(message)s` |
| 171 | + * Example: `2023-10-27 10:00:00,000 - uvicorn.access - INFO - main.handle_request:123 - GET /users/me HTTP/1.1 200 OK` |
| 172 | +* **Log Output:** |
| 173 | + * Console (stdout/stderr) during development. |
| 174 | + * File-based logging in production (e.g., `/var/log/ccs/ccs.log`) with log rotation. |
| 175 | +* **Key Information to Log:** |
| 176 | + * Application startup and shutdown. |
| 177 | + * Incoming requests (HTTP and WebSocket connections) with relevant metadata (IP, user_id if authenticated). |
| 178 | + * Authentication successes and failures. |
| 179 | + * Message processing details (sender, receiver/group, timestamp) - potentially at DEBUG level for content. |
| 180 | + * Database queries (optional, can be verbose, usually enabled at DEBUG level). |
| 181 | + * All errors and exceptions with stack traces. |
| 182 | + * Presence updates (user connected/disconnected). |
| 183 | + |
| 184 | +## 9. Security Considerations (Initial Thoughts) |
| 185 | + |
| 186 | +* **Input Validation:** All incoming data (HTTP request bodies, WebSocket messages) will be strictly validated using Pydantic models. |
| 187 | +* **Password Hashing:** `passlib` library with a strong hashing algorithm (e.g., bcrypt, Argon2). |
| 188 | +* **JWT Security:** |
| 189 | + * Use HTTPS for all communication. |
| 190 | + * Strong, secret key for JWT signing. |
| 191 | + * Short-lived access tokens, implement refresh token mechanism if needed. |
| 192 | +* **WebSocket Security:** |
| 193 | + * `wss://` (WebSocket Secure) in production. |
| 194 | + * Authenticate WebSocket connections promptly after establishment. |
| 195 | +* **Rate Limiting:** Consider implementing rate limiting on API endpoints and WebSocket messages to prevent abuse. |
| 196 | +* **Dependency Management:** Keep dependencies up-to-date to patch known vulnerabilities. |
| 197 | + |
| 198 | +## 10. Scalability Considerations (Initial Thoughts) |
| 199 | + |
| 200 | +* **Statelessness:** Design services to be as stateless as possible to allow horizontal scaling. User session/connection info might need a shared store (e.g., Redis) if scaling beyond one server instance. |
| 201 | +* **Asynchronous Operations:** Leverage Python's `asyncio` and FastAPI's async capabilities to handle many concurrent connections efficiently. |
| 202 | +* **Database Optimization:** Proper indexing, connection pooling. Consider read replicas for the database in the future. |
| 203 | +* **Load Balancing:** A load balancer will be needed if deploying multiple CCS instances. |
| 204 | +* **Message Queues (Advanced):** For very high throughput or to decouple services further, a message queue (e.g., RabbitMQ, Kafka) could be introduced between message reception and processing/delivery. |
| 205 | + |
| 206 | +This document provides a foundational design. Further details will be elaborated during the implementation phase of each module. |
0 commit comments