Skip to content

B1. reverb-backend

← Current State Index · ← Audit README


Summary

reverb-backend is the core API platform for the entire Soreto ecosystem. It owns all business logic: auth, campaigns, rewards, orders, shared URLs, email queuing, marketplace, analytics, affiliate management, and user segmentation. All other repos depend on it, either directly (melissa, zoe) or indirectly (reverb-react via the same backend).


Key Facts

Property Value
Language JavaScript (CommonJS, no TypeScript)
Node version 14.17.3 — EOL April 2023
Framework Express 4.17.1
Database PostgreSQL via Knex 0.95.7 (schema: reverb)
Message Queue RabbitMQ via Seneca 3.23.3 + seneca-amqp-transport
Cache / Session Redis via ioredis@4.14.0, connect-redis@3.4.0
Search Elasticsearch 7.13.0
File Storage AWS S3 via aws-sdk@2.944.0
Payments Stripe 18.0.0
Auth Passport.js 0.3.2 (local, bearer, basic, OAuth2, Google, Facebook, Twitter)
Testing Mocha 9.0.2 + NYC (Istanbul) coverage
Build Webpack 5.44.0 + Babel 7
CI/CD Travis CI (.travis.yml) — Node 14, PostgreSQL, Redis, RabbitMQ
Deployment Heroku — 4-process Procfile
Lockfile package-lock.json (npm)

Process Architecture

The Procfile defines four separate processes:

web:               node app.js           — HTTP API server
service_meta:      node service_meta.js  — metadata/background tasks
service_api:       node service_api.js   — internal API service
service_email_queue: node service_email_queue.js — email queue consumer

This multi-process model on Heroku means the app has internal service communication. The seneca-amqp-transport library routes messages between processes via RabbitMQ. This is a significant operational dependency — RabbitMQ must be running for the email queue and meta services to function.


Service Inventory

The services/ directory contains 80+ files in a flat structure. Key domain groups:

Domain Services
Auth auth.js, authToken.js, socialAuth.js, passwordlessAuth.js, oauthCode.js, oauthToken.js
Campaign campaign.js, campaignVersion.js, abTest.js, abTestCampaignVersion.js, wizard.js
Reward reward.js, rewardPool.js, rewardPoolDynamic.js, rewardDiscountCode.js, postConversionReward.js
Order order.js, clientOrder.js, externalOrder.js, external_revenue.js
Sharing sharedUrl.js, sharedUrlAccessUserInfoService.js, socialApi.js, socialPost.js
User user.js, userManagement.js, userAccess.js, userBlacklist.js
Segmentation userSegmentation.js, userSegmentationPool.js, userSegmentationScore.js, userSegmentationResolver.js
Email emailQueue.js, emailTemplate.js, emailTemplateType.js
Marketplace marketPlace.js, mpBrands.js, mpOffers.js, mpBanners.js, mpImages.js
Analytics analytics.js, aggClientStats.js, byChannelStats.js
Affiliate affiliate.js, assocAffiliateMerchantClient.js

Observation: The flat service directory with no domain sub-grouping makes navigating the business logic difficult. There are no barrel files or internal module boundaries.


Route Structure

routes/
├── api/          ← REST API endpoints consumed by melissa, zoe, reverb-react
├── app/          ← App-level routes (possibly server-rendered pages)
├── partner/      ← Partner/merchant-facing routes
└── web_site/     ← Public website routes

There is no API versioning visible in the route structure. soreto-melissa calls /api/v1/ — the v1 prefix must be applied somewhere in the router or middleware.


Authentication

Passport.js with multiple strategies: - Local — username/password, session-less - Basic HTTP — used by internal services - Bearer token — OAuth2 bearer tokens - Google OAuth2 and Google Plus Token - Facebook and Facebook Token - Twitter and Twitter Token - Custom — for passwordless auth flow

Cookie: reverbToken (JWT, configured via config/config.js)


Environment Configuration

config/config.js loads environment variables with inline defaults:

SESSION_SECRET: process.env.SESSION_SECRET || 's0meSup3rC0mpleXPa$$w0rd',
TOKEN_SECRET:   process.env.TOKEN_SECRET   || 's0meSup3rC0mpleXPa$$w0rd',
COOKIE_SECRET:  process.env.COOKIE_SECRET  || 'eNboeOJQ6l$NiMM!VY2E#7bw735li$7a',

Risk: If any of these environment variables are unset in any environment, the application silently uses the default value. These defaults are now public (they are in this file). Any environment that relies on the default is using a compromised secret.

Analytics tokens are also hardcoded as defaults (Mixpanel token, GA tracking ID).


Local Module

local_modules/soreto-cookie-jam — a custom cookie packing library. Name: soreto-cookie-jam, author: Tiago Barroso. Only dependency: moment@^2.24.0.

This is a candidate for extraction to @soreto/auth-utils in the shared packages layer. See I — Shared Platform.


Travis CI Configuration

language: node_js
node_js: 14.17.3
services: [postgresql, rabbitmq, redis-server]
addons:
  postgresql: "9.5"
before_install: psql -U postgres -f db_pg_schema.sql
install: npm install && npm run build
before_script: node service_meta.js & node service_worker.js &
script: npm run test

Observation: CI requires PostgreSQL 9.5, RabbitMQ, and Redis. Tests run against a real database (no mocking at the infrastructure level). PostgreSQL 9.5 is itself EOL — the CI environment is running an older Postgres than production likely uses.


Deprecated & High-Risk Dependencies

Package Version Issue
universal-analytics 0.4.13 Google UA shut down July 2023. This sends to a dead API.
node-sass 8.0.0 Officially deprecated. Migrate to sass.
seneca 3.23.3 Effectively unmaintained. Core messaging risk.
seneca-amqp-transport 2.2.0 Same lineage, same risk.
passport 0.3.2 Three major versions behind (current: 0.7.x). Missing security fixes.
superagent 1.8.2 Released ~2015. Many breaking versions behind.
googleapis 12.1.0 Current is ~140. Massive version gap.
express-robots git+https://github.com/HofmT/express-robots.git Installed from GitHub URL with no pinned commit. Unstable.
uuid 2.0.1 Current is v11. API differences.
connect-redis 3.4.0 Breaking API changes in v6+. Blocks Redis upgrade.
async 1.5.2 Extremely old. Current is v3.

Risks Summary

Risk Severity
Node 14 EOL 🔴 HIGH
Hardcoded default secrets 🔴 HIGH
seneca.js unmaintained 🔴 HIGH
Google UA dead API 🟡 MEDIUM
node-sass deprecated 🟡 MEDIUM
No TypeScript — runtime-only type errors 🟡 MEDIUM
80+ flat service files, no domain structure 🟡 MEDIUM
No OpenAPI spec 🟡 MEDIUM
PostgreSQL 9.5 in CI 🟡 MEDIUM
GitHub-sourced dependency (express-robots) 🟡 MEDIUM