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:

  1. libs/server/src/run.ts reads a server.config.*.ts file passed as a CLI argument.
  2. It creates a Server instance with the config (process name, port, middleware list).
  3. The Server class creates an Express app, registers a rate limiter (100 req / 15 min), JSON body parsing, and health-check endpoints (/_ping, /health).
  4. It dynamically imports and instantiates each middleware listed in the config. Middleware classes extend BasicMiddleware and register their own Express routers.
  5. 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:

  1. Looks up an active account by email in MongoDB.
  2. Generates an 8-digit OTP and stores it with the code challenge.
  3. Enqueues an email job via MessageQueue to deliver the OTP.
  4. 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:

  1. Decodes the JWT to extract the email address.
  2. Looks up the account and a matching pending, non-expired OTP record.
  3. Verifies that SHA256(codeVerifier) matches the stored codeChallenge.
  4. 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_uploads mapped to /app/uploads).
  • Nginx is configured with a larger client_max_body_size (100 MB) for the /media path.

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-queue in Redis.
  • Sends emails via the Resend API using EmailClient.send_email_now().
  • Handles graceful shutdown on SIGTERM and SIGINT.

How It Works

The worker is a standalone Node.js process (not an Express server). It creates a BullMQ Worker instance that:

  1. Connects to Redis using the configured host and port.
  2. Listens for jobs on the email-queue.
  3. For each job, parses the job data and calls EmailClient.send_email_now(body, to).
  4. 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

graph TD NGINX["Nginx"] AUTH["Auth Service"] PROFILE["Profile Service"] ORG["Organisation Service"] MEDIA["Media Service"] MQ["Message Queue Worker"] ADMIN["Admin Portal"] HUB["Zeswa Hub"] MONGO[("MongoDB")] REDIS[("Redis")] NGINX --> AUTH NGINX --> PROFILE NGINX --> ORG NGINX --> MEDIA NGINX --> ADMIN NGINX --> HUB AUTH --> MONGO AUTH --> REDIS PROFILE --> MONGO ORG --> MONGO MEDIA --> MONGO MQ --> MONGO MQ --> REDIS ADMIN --> AUTH ADMIN --> PROFILE ADMIN --> ORG ADMIN --> MEDIA ADMIN --> MQ HUB --> AUTH HUB --> PROFILE HUB --> ORG HUB --> MEDIA HUB --> MQ

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