Skip to content

Service Catalog

Wenex Platform consists of 15 domain microservices plus 7 worker processes. All services are NestJS applications that expose a REST API and a gRPC server. Workers are event-driven consumers that do not expose a public REST API.


Architecture Summary


Standard Service Internals

Every microservice follows the same internal structure:

apps/services/<name>/src/
├── main.ts                    # Starts REST listener + gRPC server
├── app.module.ts              # Root module: DB connection, imported modules
├── app.service.ts             # Health checks, initialization
├── modules/
│   └── <entity>/
│       ├── <entity>.module.ts
│       ├── <entity>.controller.ts   # REST (also consumed by gateway via gRPC)
│       ├── <entity>.service.ts      # Business logic + gRPC handler
│       ├── <entity>.repository.ts   # Typegoose (MongoDB) queries
│       ├── <entity>.schema.ts       # Mongoose schema definition
│       └── dto/
│           ├── create-<entity>.dto.ts
│           ├── update-<entity>.dto.ts
│           └── <entity>.serializer.ts
└── protobuf/                  # Generated gRPC TypeScript stubs

Core Services

auth — Authentication & Authorization

Port: REST :3020 · gRPC :5020

Handles all authentication flows and token management. Unique in that it does not follow the standard CRUD pattern for its primary auth endpoint.

CollectionPathPurpose
Auths/authtoken, verify, logout, check, can
APTs/auth/aptsLong-lived Auth Personal Tokens (API keys)
Grants/auth/grantsOAuth permission grants

Key behaviors:

  • POST /auth/token is public (@IsPublic()) — no auth header required
  • APTs are revocable and scoped — create them with minimal permissions
  • POST /auth/can performs ABAC policy evaluation via the abacl library

domain — Tenant & OAuth Management

Port: REST :3030 · gRPC :5030

Manages tenant domains, OAuth applications, and client registrations.

CollectionPathPurpose
Apps/domain/appsOAuth application definitions
Clients/domain/clientsOAuth client credentials

context — Configuration & Settings

Port: REST :3040 · gRPC :5040

Stores application-wide and per-user configuration data.

CollectionPathPurpose
Configs/context/configsApplication configuration entries
Settings/context/settingsUser/tenant preference settings

Key behaviors:

  • context/configs is the registry for all CQRS webhook endpoints. Each client registers its own entry using key: ConfigKey.CQRS and eid: <client_id>:
typescript
await platform.context.configs.create({
  key: 'CQRS',                              // ConfigKey.CQRS
  eid: '68fc7a456e8fa60ae29c3d02',          // this client's MongoDB _id (= client_id in tokens)
  value: { webhook: 'http://localhost:8150/cqrs' },
});

The Platform's publisher worker reads these entries after every write to deliver webhook payloads to each client listed in a document's clients[] array.


essential — Saga Orchestration

Port: REST :3050 · gRPC :5050

Manages distributed saga transactions across multiple services. Workers use PostgreSQL-backed saga stages for durability.

CollectionPathPurpose
Sagas/essential/sagasDistributed saga instances
Saga Stages/essential/saga-stagesIndividual compensating steps

Key behaviors:

  • Sagas coordinate multi-service operations (e.g., order creation touching financial + logistic + conjoint)
  • PostgreSQL stores saga stage state for crash recovery
  • Workers (dispatcher, observer, preserver) drive saga execution

identity — Users, Profiles & Sessions

Port: REST :3080 · gRPC :5080

Core user management service. All other services reference users by MongoId.

CollectionPathPurpose
Users/identity/usersUser accounts
Profiles/identity/profilesExtended profile data
Sessions/identity/sessionsActive login sessions

Key behaviors:

  • User creation triggers Kafka events consumed by other services (e.g., wallet auto-creation in financial)
  • Sessions are soft-deleted on logout, hard-deleted by the cleaner worker

Business Services

financial — Billing & Payments

Port: REST :3060 · gRPC :5060

Manages the full financial lifecycle: accounts → wallets → invoices → transactions.

CollectionPathPurpose
Accounts/financial/accountsFinancial account records
Wallets/financial/walletsBalance-holding wallets
Invoices/financial/invoicesBilling documents
Transactions/financial/transactionsPayment / transfer records
Currencies/financial/currenciesSupported currency definitions

career — Business Operations

Port: REST :3140 · gRPC :5140

The largest domain service, managing all business-side entities.

CollectionPathPurpose
Businesses/career/businessesBusiness entity (top-level)
Branches/career/branchesPhysical/logical branches
Employees/career/employeesStaff records
Products/career/productsProduct catalog
Services/career/servicesOffered services
Stocks/career/stocksInventory per product/branch
Stores/career/storesRetail/online store fronts
Customers/career/customersCustomer records

special — Files & Statistics

Port: REST :3090 · gRPC :5090

Handles file uploads (via MinIO) and computed statistics.

CollectionPathPurpose
Files/special/filesFile metadata + MinIO reference
Stats/special/statsAggregated metrics / counters

Key behaviors:

  • File content is stored in MinIO; only metadata (filename, size, mime, url) is in MongoDB
  • The publisher worker processes file events for CDN propagation

touch — Notifications & Messaging

Port: REST :3100 · gRPC :5100

Records and dispatches all outbound communications.

CollectionPathPurpose
Emails/touch/emailsOutbound email records
Notices/touch/noticesIn-app notifications
Pushes/touch/pushesMobile push records
SMS/touch/smsSMS records
Histories/touch/historiesDelivery status history

Key behaviors:

  • Records are created first; actual delivery is handled by the publisher worker via EMQX/MQTT
  • histories tracks per-recipient delivery status

content — Notes, Posts & Support

Port: REST :3110 · gRPC :5110

Rich content management for user-facing documents.

CollectionPathPurpose
Notes/content/notesRich-text notes / documents
Posts/content/postsPublished articles / blog posts
Tickets/content/ticketsSupport ticket threads

logistic — Tracking & Delivery

Port: REST :3120 · gRPC :5120

Tracks physical assets and movements.

CollectionPathPurpose
Locations/logistic/locationsGeographic coordinates / addresses
Drivers/logistic/driversDriver profiles
Vehicles/logistic/vehiclesVehicle registry
Travels/logistic/travelsTrip / route records
Cargoes/logistic/cargoesShipment manifests

conjoint — Messaging & Channels

Port: REST :3130 · gRPC :5130

Real-time messaging infrastructure.

CollectionPathPurpose
Accounts/conjoint/accountsMessaging account (bot/user)
Channels/conjoint/channelsConversation channels
Contacts/conjoint/contactsContact directory
Members/conjoint/membersChannel membership records
Messages/conjoint/messagesIndividual messages

Key behaviors:

  • Message delivery uses EMQX/MQTT via the publisher worker
  • Channels support multiple account types (user, bot, business)

general — Cross-Cutting Entities

Port: REST :3070 · gRPC :5070

Shared entities used across domains.

CollectionPathPurpose
Activities/general/activitiesAudit activity log entries
Artifacts/general/artifactsGeneric binary references
Comments/general/commentsThreaded comment system
Events/general/eventsCalendar / system events
Workflows/general/workflowsProcess definitions

thing — IoT & Telemetry

Port: REST :3150 · gRPC :5150

Internet of Things device management and sensor telemetry.

CollectionPathPurpose
Devices/thing/devicesIoT device registry
Sensors/thing/sensorsSensor definitions per device
Metrics/thing/metricsSensor readings / time-series

Worker Processes

Workers are internal consumers — they have no public REST API. They expose only /status (health) and /metrics (Prometheus).

WorkerPortRole
dispatcher4010Main job queue: receives Kafka events, dispatches BullMQ jobs to other workers
observer4020Observes domain events: triggers notifications, audit logs
preserver4030Persistence worker: syncs Elasticsearch, snapshot creation
watcher4040Monitors saga execution, triggers compensations on timeout
publisher4050Outbound delivery: EMQX/MQTT push, email, SMS relay
logger4060Aggregates logs from all services, ships to Elasticsearch
cleaner4070Data retention: hard-deletes expired soft-deleted records

Worker Internal Structure

apps/workers/<name>/src/
├── main.ts              # Kafka consumer bootstrap + HTTP health server
├── app.module.ts        # Kafka, BullMQ, Mongo, Postgres imports
├── app.processor.ts     # @Process() — BullMQ job handler
├── app.task.ts          # @Cron() — scheduled maintenance tasks
├── app.service.ts       # Core business logic
├── app.controller.ts    # HTTP: /status, /metrics
└── entities/            # TypeORM entities (PostgreSQL)

Scope Naming Convention

Required scopes follow the pattern {action}:{service}:{collection}:

read:identity:users       → ReadIdentityUsers
write:financial:accounts  → WriteFinancialAccounts
manage:auth:apts          → ManageAuthApts

The manage: prefix grants all read, write, and destructive actions including destroy and bulk operations.


Health Checks

Every service and worker exposes GET /status with checks for its dependencies:

bash
curl http://localhost:3020/status    # auth
curl http://localhost:3080/status    # identity
curl http://localhost:4010/status    # dispatcher worker

Example response:

json
{
  "status": "ok",
  "info": {
    "mongodb": { "status": "up" },
    "redis": { "status": "up" },
    "kafka": { "status": "up" }
  }
}