Technical Debt Register¶
The consolidated debt register for Prism. This is the single source of truth for known structural, reliability and security debt. Each item is grounded in a real file. Severity: P0 (fix now / active risk), P1 (fix this quarter), P2 (opportunistic).
Validation legend: ✅ verified · 📄 inferred · ♻️ duplication · ⚰️ dead/disabled · ⚠️ risk
1. Debt table¶
| # | Item | Location | Impact | Suggested fix | Severity |
|---|---|---|---|---|---|
| D1 | Dual ingestion writers to crm_queue ♻️ |
prism-services orders-consumer λ and commonOrderIngestion.js / uengageOrderIngestion.js / petpoojaOrderIngestion.js |
duplicate/inconsistent orders, unclear source-of-truth, race conditions | pick one authoritative writer; add idempotent upsert key; dedup on ingest | P0 |
| D2 | Non-atomic loyalty points (Mongo + MySQL) ⚠️ | commonFunctions/handleWalletPointsFlow.js, crmPointsAllocationQueueCron.js |
balance drift → bug E1.10 (Total ≠ Used+Available+Expired) | idempotency flag on order; saga/compensation; single ledger source | P0 |
| D3 | Duplicate queue implementations ♻️ | commonFunctions/automatedCampaignQueue.js (legacy) vs automatedCampaignQueueNew.js |
divergent behavior, double maintenance | consolidate to one versioned module; delete legacy | P1 |
| D4 | Dual dashboards ♻️ | controllers/dashboardController.js (legacy) vs dashboardControllerNew.js |
cross-widget mismatches (A4.4), double maintenance | finish migration to New; deprecate legacy | P1 |
| D5 | Three campaign pipelines ♻️ | campaignController.js + campaignControllerDynamic.js + automatedCampaignController.js |
no clear routing/priority; regressions on merge (A2.1) | define orchestration contract → Central Marketing Hub | P1 |
| D6 | Dual loyalty points queues ♻️ | MongoDB loyalty_points_allocate (pointAllocation.js) vs MySQL crm_points_allocation_queue |
two code paths, drift risk | deprecate Mongo queue; full migration to MySQL+retry | P1 |
| D7 | 91 crons in the web process ⚠️ | index.js:40-124 |
cron load couples to API latency; restart re-registers all | extract crons to a separate worker/process | P1 |
| D8 | Stubbed WhatsApp consumers ⚰️ | prism-services/.../consumers/send.js, receipts.js (log-only) |
receipts never persisted → bug E1.3 (volume mismatch) | implement DB writes; add delivery-receipt processor | P0 |
| D9 | No Kafka DLQ / retry ⚠️ | serverless YMLs; orders-consumer |
poison message crashes batch; lost/duplicated msgs | add DLQ topic + per-message try/catch + retry policy | P0 |
| D10 | Hardcoded secrets ⚠️ | serverless-orders.yml:51, serverless-whatsapp.yml:67,89; jwtMiddleware.js:5; jwtWhatsappMiddleware.js:5; injestion_middleware.js:8; thirdPartyMiddleware.js:6; newrelic.js:16; utilities/redis.js |
prod Mongo/JWT exposed in VCS | move to Secrets Manager/SSM/env; rotate all | P0 |
| D11 | Committed .env.dev ⚠️ |
/.env.dev in repo |
plaintext dev creds in VCS | gitignore + purge from history; keep only .env.prod.example |
P1 |
| D12 | Open CORS + no rate limit ⚠️ | index.js CORS origin:"*", socket.js:12-16; no limiter |
CSRF/abuse, provider throttle-ban | restrict origins; add rate limiter (per-IP + per-business) | P1 |
| D13 | APM disabled ⚰️ | index.js:1-13 (Elastic commented); newrelic.js inactive |
no distributed tracing; logs are only signal | enable one APM; wire trace_id through |
P1 |
| D14 | Dead code ⚰️ | testController.js, oldCustomerCron.js, oldFcmCron.js, uengageloyaltyController.js (empty), parseFcmTokenController.js; commented crons index.js:69,77,105,118,… |
confusion, load-time cost, attack surface | delete; archive intentional stubs with a note | P2 |
| D15 | Missing indexes 📄 | high-write collections (crm_queue, whatsapp_queue_*, customers) & MySQL wallet tables |
slow polling scans, pool saturation | add indexes on {status}, {process_status}, tenant keys, execution_time |
P1 |
| D16 | No TTL on dump collections ⚠️ | customer_injestion_dump, fcm_injestion_dump, dated *_queue_* collections |
unbounded growth; manual cleanup only (deleteCrmQueue.js) |
TTL indexes or scheduled archival | P1 |
| D17 | Firebase app per message ⚠️ | commonFunctions/processNotiQueue.js (initializeApp(..., name+Date.now())) |
memory leak under batch load | cache one app per parent_business_id |
P2 |
| D18 | No WhatsApp send rate limiting ⚠️ | sendWhatsappMessageCron.js, sendWhatsappTransactionalCron.js |
Gupshup/Meta throttle-ban | per-business rate caps + backoff | P1 |
| D19 | Status-field inconsistency 📄 | SMS/Push processed (bool), WhatsApp process_status (int), MySQL status (str) |
error-prone queue code | unify to a shared enum convention | P2 |
| D20 | Reward/milestone logic scattered 📄 | handleWalletPointsFlow.js, handleMilestoneUpgrade.js, rewardHelper.js, helpers.js |
hard to reason about loyalty correctness | consolidate into loyaltyEngine.js |
P2 |
| D21 | Polling-only queues ⚠️ | all queue crons (1s-5m polls) | thundering herd, wasted DB queries | task queue (Bull/SQS) for SMS/Push | P2 |
| D22 | No stuck-cron auto-recovery ⚠️ | *_cron_status guards; only email alert (dedupCustomers has 4h force-close) |
manual intervention to unstick | circuit breaker + auto force-close threshold | P1 |
| D23 | Redis failure non-fatal but silent ⚠️ | index.js startRedis() logs, doesn't exit |
cache-dependent features degrade silently | health check + explicit degraded mode | P2 |
2. Debt clusters (how the items relate)¶
mindmap
root((Prism Debt))
Ingestion
D1 dual writers
D9 no DLQ/retry
D8 stubbed WA consumers
Loyalty
D2 non-atomic points
D6 dual points queues
D20 scattered logic
Duplication
D3 dup queues
D4 dual dashboards
D5 three campaign pipelines
Platform
D7 91 crons in web
D21 polling queues
D22 no auto-recovery
D13 APM off
Security
D10 hardcoded secrets
D11 committed env
D12 CORS/rate limit
Data hygiene
D15 missing indexes
D16 no TTL
D14 dead code
3. Improvement Suggestions — prioritized roadmap¶
Phase 1 — Stop the bleeding (P0, active data/security risk)¶
- D10 + D11 rotate & vault all secrets; purge
.env.devfrom history. (security) - D2 add order-level idempotency flag + reconcile loyalty ledger → closes E1.10.
- D1 designate one authoritative
crm_queuewriter; dedup key. - D8 + D9 implement WhatsApp receipt persistence + Kafka DLQ/retry → closes E1.3.
Phase 2 — De-duplicate & harden (P1, this quarter)¶
- D4/D5 finish dashboard + campaign consolidation (aligns with roadmap A2.1, A4.4/A4.5).
- D3/D6 collapse duplicate queue/points implementations.
- D7 move crons to a dedicated worker process; D22 add stuck-cron auto-recovery.
- D15/D16 add indexes + TTL/archival on high-write & dump collections.
- D12 lock CORS + add rate limiting; D13 enable one APM.
- D18 per-business WhatsApp rate caps.
Phase 3 — Polish (P2, opportunistic)¶
- D14 delete dead code; D19 unify queue status enums.
- D17 cache Firebase apps; D20 extract
loyaltyEngine.js; D21 evaluate a real task queue; D23 Redis health checks.
Acceptance bar for any dashboard/analytics work: the roadmap A4 Data Validation Protocol (logic, composition, sync-time, cross-widget integrity). See Roadmap §A.