C. Cross-Repo Gap Analysis
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 |