Services
The eTeamups Platform is composed of five in-repo microservices plus two frontend applications that live in separate repositories. Each service is a standalone Express application bootstrapped by the shared libs/server library.
Service Bootstrap Pattern
All HTTP services share the same startup flow:
libs/server/src/run.tsreads aserver.config.*.tsfile passed as a CLI argument.- It creates a
Serverinstance with the config (process name, port, middleware list). - The
Serverclass creates an Express app, registers a rate limiter (100 req / 15 min), JSON body parsing, and health-check endpoints (/_ping,/health). - It dynamically imports and instantiates each middleware listed in the config. Middleware classes extend
BasicMiddlewareand register their own Express routers. - The server starts listening on
0.0.0.0:<port>.
Auth Service
| Property | Value |
|---|---|
| Port | 9000 |
| Nginx path | /auth |
| Process name | Auth Server |
| Source | services/auth/ |
| GHCR image | ghcr.io/creativeaura/eteamups-platform-auth:latest |
Responsibilities
- Passwordless authentication using email-based OTP with PKCE.
- JWT access and refresh token generation.
- Token refresh endpoint.
- API version reporting.
Middleware Chain
| Middleware | Registered Routes |
|---|---|
AuthMiddleware |
Request timing logger on all routes, GET /version |
TokenMiddleware |
POST /token (refresh token exchange) |
VerifyMiddleware |
POST /verify (OTP + PKCE verification) |
Endpoints
POST /login
Initiates the authentication flow.
Request body (validated by Zod):
{
"emailAddress": "user@example.com",
"codeChallenge": "<base64url-encoded SHA-256 hash, 43-128 chars>"
}
Flow:
- Looks up an active account by email in MongoDB.
- Generates an 8-digit OTP and stores it with the code challenge.
- Enqueues an email job via
MessageQueueto deliver the OTP. - Returns JWT access token (15-day expiry) and refresh token (7-day expiry).
Response (200):
{
"accessToken": "<jwt>",
"refreshToken": "<jwt>"
}
POST /verify
Verifies the OTP and the PKCE code verifier.
Request body:
{
"otp": "12345678",
"codeVerifier": "<original code verifier string, 43-128 chars>"
}
Requires: Authorization: Bearer <accessToken> header (the token returned from /login).
Flow:
- Decodes the JWT to extract the email address.
- Looks up the account and a matching pending, non-expired OTP record.
- Verifies that
SHA256(codeVerifier)matches the storedcodeChallenge. - Marks the OTP as used and activates the account.
Response (200):
{
"error": false,
"message": "OTP verified successfully"
}
POST /token
Exchanges a valid refresh token for a new access/refresh token pair.
Requires: Authorization: Bearer <refreshToken> header.
Response (200):
{
"accessToken": "<jwt>",
"refreshToken": "<jwt>"
}
GET /version
Returns the current API version string.
Response (200): v0.0.1
Profile Service
| Property | Value |
|---|---|
| Port | 9100 |
| Nginx path | /profile |
| Process name | Profile Server |
| Source | services/profile/ |
| GHCR image | ghcr.io/creativeaura/eteamups-platform-profile:latest |
Responsibilities
- User profile management (the “me” endpoint).
- Team CRUD operations.
- Teammate CRUD operations within teams.
Middleware Chain
| Middleware | Registered Routes |
|---|---|
MeMiddleware |
GET /me, PUT /me (profile endpoints) |
TeamMiddleware |
POST /team, GET /team, GET /team/:id, PUT /team/:id, DELETE /team/:id |
TeammateMiddleware |
POST /teammate, GET /teammate, GET /teammate/:id, PUT /teammate/:id, DELETE /teammate/:id |
Endpoints
Me (User Profile)
| Method | Path | Description |
|---|---|---|
GET |
/me |
Retrieve the authenticated user’s profile |
Teams
| Method | Path | Description |
|---|---|---|
POST |
/team |
Create a new team |
GET |
/team |
List all teams |
GET |
/team/:id |
Get a single team by ID |
PUT |
/team/:id |
Update a team |
DELETE |
/team/:id |
Delete a team |
Teammates
| Method | Path | Description |
|---|---|---|
POST |
/teammate |
Add a teammate |
GET |
/teammate |
List all teammates |
GET |
/teammate/:id |
Get a single teammate by ID |
PUT |
/teammate/:id |
Update a teammate |
DELETE |
/teammate/:id |
Remove a teammate |
Organisation Service
| Property | Value |
|---|---|
| Port | 9107 |
| Nginx path | /organisation |
| Process name | Organisation Server |
| Source | services/organisation/ |
| GHCR image | ghcr.io/creativeaura/eteamups-platform-organisation:latest |
Responsibilities
- Organisation CRUD.
- Account management within organisations.
- Master data catalogues: countries, industries, functions, education levels, study majors, locations, skills.
Middleware Chain
| Middleware | Domain |
|---|---|
OrganisationMiddleware |
Organisation CRUD |
AccountMiddleware |
Account management |
CountryMiddleware |
Country catalogue |
EducationLevelMiddleware |
Education level catalogue |
FunctionMiddleware |
Function/role catalogue |
IndustryMiddleware |
Industry catalogue |
LocationMiddleware |
Location catalogue |
StudyMajorMiddleware |
Study major catalogue |
Endpoints
Each master data resource follows a standard CRUD pattern:
| Method | Path Pattern | Description |
|---|---|---|
POST |
/<resource> |
Create a new record |
GET |
/<resource> |
List all records |
GET |
/<resource>/:id |
Get a single record |
PUT |
/<resource>/:id |
Update a record |
DELETE |
/<resource>/:id |
Delete a record |
The available resources are:
| Resource Path | Collection |
|---|---|
/organisation |
organisations |
/account |
accounts |
/country |
countries |
/education-level |
educationlevels |
/function |
functions |
/industry |
industries |
/location |
locations |
/study-major |
studymajors |
/skill |
skills |
Media Service
| Property | Value |
|---|---|
| Port | 9102 |
| Nginx path | /media |
| Process name | Media Server |
| Source | services/media/ |
| GHCR image | ghcr.io/creativeaura/eteamups-platform-media:latest |
Responsibilities
- Serving media assets (images, files) to frontend clients.
- Media uploads are stored in a Docker volume (
media_uploadsmapped to/app/uploads). - Nginx is configured with a larger
client_max_body_size(100 MB) for the/mediapath.
Middleware Chain
| Middleware | Registered Routes |
|---|---|
MediaMiddleware |
GET /media/:id |
Endpoints
| Method | Path | Description |
|---|---|---|
GET |
/media/:id |
Retrieve a media asset by its identifier |
Message Queue Worker
| Property | Value |
|---|---|
| Port | None (not an HTTP service) |
| Source | libs/message-queue/run.ts |
| GHCR image | ghcr.io/creativeaura/eteamups-platform-message-queue:latest |
Responsibilities
- Processes jobs from the
email-queuein Redis. - Sends emails via the Resend API using
EmailClient.send_email_now(). - Handles graceful shutdown on
SIGTERMandSIGINT.
How It Works
The worker is a standalone Node.js process (not an Express server). It creates a BullMQ Worker instance that:
- Connects to Redis using the configured host and port.
- Listens for jobs on the
email-queue. - For each job, parses the job data and calls
EmailClient.send_email_now(body, to). - On success, marks the job complete. On failure, BullMQ retries with exponential backoff.
See Message Queue for full details.
Admin Portal (Separate Repository)
| Property | Value |
|---|---|
| Port | 3000 (frontend) / 9103 (API, if applicable) |
| Hostname | admin.zeswa.com |
| GHCR image | ghcr.io/creativeaura/eteamsup-admin-portal:latest |
The Admin Portal is a frontend application deployed as a Docker container alongside the platform services. It depends on all five backend services being healthy before starting. It is served through Nginx at admin.zeswa.com.
Zeswa Hub (Separate Repository)
| Property | Value |
|---|---|
| Port | 4000 |
| Hostname | zeswa.com / www.zeswa.com |
| GHCR image | ghcr.io/creativeaura/zeswa-hub:latest |
The Zeswa Hub is the public-facing frontend application. Like the Admin Portal, it runs in its own container and is proxied through Nginx. It also depends on all backend services being healthy.
Service Dependency Graph
Resource Limits (Docker)
Each container has configured CPU and memory limits:
| Service | CPU Limit | Memory Limit | CPU Reservation | Memory Reservation |
|---|---|---|---|---|
| MongoDB | 2.0 | 2 GB | 0.5 | 512 MB |
| Redis | 1.0 | 768 MB | 0.25 | 256 MB |
| Auth | 1.0 | 512 MB | 0.25 | 128 MB |
| Profile | 1.0 | 512 MB | 0.25 | 128 MB |
| Organisation | 1.0 | 512 MB | 0.25 | 128 MB |
| Media | 1.0 | 1 GB | 0.25 | 256 MB |
| Message Queue | 0.5 | 512 MB | 0.1 | 128 MB |
| Admin Portal | 1.0 | 512 MB | 0.25 | 128 MB |
| Zeswa Hub | 1.0 | 512 MB | 0.25 | 128 MB |
| Nginx | 0.5 | 256 MB | 0.1 | 64 MB |