Skip to content

C. Cross-Repo Gap Analysis

← Back to README


Repository Comparison Table

Dimension reverb-backend reverb-react soreto-melissa soreto-zoe
Language JS (CJS) JS/JSX TypeScript ✓ TS + JS (mixed)
Node 14.17.3 ~10.15.3 ⛔ 22.0.0 ✓ 16.13.0
Node EOL Apr 2023 Dec 2020 Active ✓ Sep 2023
TypeScript No No v5.0 (strict) ✓ v5.4 (partial)
React N/A 17 + dom 16.5 ⛔ 18.2 ✓ N/A
React Router N/A 3.2.1 + dom 4.2.2 ⛔ N/A N/A
Express 4.17.1 4.16.2 N/A 4.16.4
ESLint v5 v4 v8 ✓ None
Prettier No No Yes ✓ No
Test framework Mocha Jest 23 Jest 30 None ⚠️
CI/CD Travis CI Travis CI (empty) None ⚠️ None ⚠️
Deploy Heroku Heroku Unknown Unknown
Lockfile npm npm npm npm (malformed)
Knex 0.95.7 N/A N/A 0.16.3 ⚠️
DB schema reverb N/A N/A zoe
Babel v7 v6 v7 (SWC) N/A

Dependency Version Fragmentation

Packages used by multiple repos at different versions — each divergence is a maintenance and debugging cost:

Package reverb-backend reverb-react soreto-melissa soreto-zoe
axios 0.27.2 0.18.0 1.7.3 ^1.3.4
moment 2.24.0 2.22.1 2.30.1 ^2.24.0
lodash 4.17.11 4.17.11 4.17.11
ejs 2.4.1 ^2.6.1 ^3.1.9
exceljs 4.3.0 ^4.3.0
mandrill-api 1.0.45 ^1.0.45
knex 0.95.7 0.16.3
primereact 1.5.1 10.2.1
eslint 5.15.1 4.18.2 8.35.0
elasticsearch 7.13.0 7.13.0
winston 3.1.0 3.2.1
express 4.17.1 4.16.2 4.16.4

Most critical drift: knex@0.16.3 (zoe) vs knex@0.95.7 (backend) — the same database is managed by tools 3 years apart. axios@0.18.0 (reverb-react, pre-v1) vs axios@1.7.3 (melissa) — different major API versions; reverb-react is also 3 major releases behind the current axios@1.16.1. primereact@1.5.1 (reverb-react) vs 10.2.1 (melissa) — 9 major versions apart, entirely incompatible APIs.


Hidden Coupling Map

The repos present as independent but operate as a single system:

┌─────────────────────────────────────────────────────────────────┐
│                    INTER-REPO COUPLING (Observed)               │
│                                                                 │
│  soreto-zoe                                                     │
│  └── local_modules/reverb/index.js                             │
│      └── HTTP POST /auth/login ──────────────────────────────► │
│          HTTP GET/POST /postreward/*, /notifications/*, etc. ──► reverb-backend │
│          (cookie: reverbToken)                                  │
│                                                                 │
│  soreto-melissa                                                 │
│  └── service/BaseService.tsx                                    │
│      └── axios + withCredentials ────────────────────────────► │
│          NEXT_PUBLIC_APP_API_URL = :5000/api/v1 ──────────────► reverb-backend │
│                                                                 │
│  reverb-react                                                   │
│  └── src/config/config.js                                       │
│      └── melissaPortalUrl = @@MELISSA_PORTAL_URL@@ ──────────► soreto-melissa │
│          { route: `${melissaPortalUrl}/client/dashboard` }      │
│                                                                 │
│  soreto-melissa                                                 │
│  └── shared/constants.ts                                        │
│      └── { link: process.env.NEXT_PUBLIC_LEGACY_PORTAL_URL } ─► reverb-react │
│          "Legacy Dashboard"                                     │
│                                                                 │
│  reverb-backend ──► PostgreSQL (schema: reverb)                │
│  soreto-zoe ──────► PostgreSQL (schema: zoe, same server)      │
│  soreto-zoe ──────► Redis (Bull queues)                        │
│  reverb-backend ──► Redis (sessions, cache)                    │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Conclusion: These are not four independent services. They are one platform deployed as four processes, with HTTP as the coupling mechanism rather than function calls. This is a distributed monolith — the worst architectural outcome, combining the complexity of microservices with the coupling of a monolith.


Domain Model Overlap

Several domain concepts appear in multiple repos without a shared definition:

Concept reverb-backend soreto-melissa soreto-zoe
User roles constants.js shared/constants.ts (ROLES enum) Implicit via reverb client
Campaign services/campaign.js service/CampaignService.ts processors/soreto/
Order services/order.js service/ (implicit) processors/soreto/postReward/
Reward services/reward.js service/RewardService.ts processors/soreto/postReward/reward.js
Affiliate networks services/affiliate.js service/AffiliateService.tsx processors/awin/, processors/rakuten/, etc.

The same domain concepts are defined independently in each repo. There is no canonical shared type definition — the source of truth is only the database schema, which is only visible in reverb-backend/migrations/.


Environment Management Fragmentation

Three different approaches to environment configuration across the ecosystem:

Repo Approach How values reach the app
reverb-backend config/config.js with process.env.VAR \|\| 'default' Env vars or inline defaults
reverb-react @@PLACEHOLDER@@ tokens in source code Replaced at webpack build time
soreto-melissa process.env.NEXT_PUBLIC_* Standard Next.js .env files
soreto-zoe config.js with dev()/prod() functions Env-specific JS function, selected by NODE_ENV

These four approaches are fundamentally incompatible. Moving to a monorepo requires choosing one approach — the recommended target is soreto-melissa's approach (standard .env + process.env), which is the most portable and conventional.


Accidental vs. Intentional Separation

Boundary Intentional? Evidence
reverb-backend ↔ soreto-melissa Intentional Different domains: API vs UI
reverb-backend ↔ soreto-zoe Intentional API vs job engine
reverb-react ↔ soreto-melissa Transitional Both exist simultaneously, cross-link
reverb-backend ↔ reverb-react Intentional (historical) SPA + API pattern
soreto-zoe local_modules/reverb Accidental Should be a typed package
Duplicate domain constants Accidental ROLES defined in melissa and backend

CI/CD Consistency Gap

Repo CI Provider Test Stage Deploy Stage
reverb-backend Travis CI ✓ Mocha tests Manual/Heroku
reverb-react Travis CI ⚠️ Build only (no tests run) Manual/Heroku
soreto-melissa None Unknown
soreto-zoe None Unknown

Two of four repos deploy to production with zero automated testing. The other two have CI, but reverb-react's CI doesn't validate correctness.


Infrastructure Inconsistencies

Concern reverb-backend soreto-zoe Notes
PostgreSQL Knex 0.95.7, schema: reverb Knex 0.16.3, schema: zoe Same server, different tools
Redis ioredis@4.14.0 (sessions + cache) ioredis (Bull queues) Likely same Redis instance
RabbitMQ Yes (Seneca AMQP) No Only reverb-backend uses it
Logging Winston 3.1.0 Winston 3.2.1 Compatible but not unified
Error handling Custom middleware Logger in BaseService Different patterns

Summary of Gaps

Gap Impact Resolution
No shared type definitions Silent API contract breaks @soreto/types package
4 different env management approaches Ops complexity Standardize on .env
2 repos with no CI Undetected regressions Add GitHub Actions
Knex version gap (zoe) DB upgrade risk Upgrade zoe's Knex first
local_modules/reverb untyped Runtime-only breakage @soreto/api-client package
3 different ESLint versions Inconsistent code quality @soreto/eslint-config