5643d89236
- Added `businessPricing.service.js` to handle business customer pricing logic. - Introduced `money.js` for money parsing, formatting, and calculations. - Created `pricing.service.js` to manage variant quoting and promotion application. - Updated validation schemas in `catalogue.schemas.js` and `inventoryMerchandising.schemas.js` for new pricing and inventory features. - Implemented cron job for inventory reservation expiry in `inventoryReservationExpiry.cron.js`. - Created database migrations for catalogue and inventory structures. - Added unit tests for catalogue localization, validation, and inventory merchandising functionalities.
417 lines
48 KiB
Markdown
417 lines
48 KiB
Markdown
# ZUMRI Current Backend Status
|
|
|
|
## Phase 4 Completion Update
|
|
|
|
Completion date: 2026-09-03. Module 03 (product catalogue) is approximately 84%; Module 04 (multi-language content) is approximately 82%. Phase 4 adds 18 catalogue models covering brands, hierarchical localized categories, products/translations/multi-category joins, DECIMAL-price variants, configurable options and attributes, owned media, scheduled localized collections, structured size guides, explicit relations, and moderated reviews.
|
|
|
|
Public APIs now provide active/public product lists and slug detail, safe search/filter/sort/pagination, locale fallback, categories, brands, current collections, signed media DTOs, price ranges, and approved review summaries. Permission-gated admin APIs cover product lifecycle, variants/options/media/relations, brands, cycle-safe categories, collections, size guides, and review moderation. No inventory quantity, wholesale pricing, promotion, or shopping behavior was introduced.
|
|
|
|
The mocked regression suite passes 15 suites/78 tests and syntax validation covers 204 JavaScript files. The Phase 4 migration is forward-only and was not executed. Restored-staging migration checks, permission seeding, real MySQL query/concurrency testing, and signed-media volume validation remain required before Phase 5. See `Documentation/PHASE_4_CATALOGUE_CONTENT.md` and `Documentation/API_CATALOGUE.md`.
|
|
|
|
## Phase 3 Completion Update
|
|
|
|
Completion date: 2026-09-03. Module 02 (customer profile/address management) is now approximately 88%; Module 13 (business accounts) is approximately 78%. Customer profile/preferences, structured owned addresses with transactional defaults, secure self-deactivation, business applications, permission-gated transactional approval, immutable partner identity, business profiles/contacts/addresses, domain status, DECIMAL credit configuration, and settlement-term primitives are implemented.
|
|
|
|
Security impact: all customer resource identity is derived from Phase 1 authentication; mutation schemas are strict; profile media is owner-validated; address/application IDOR is constrained in queries; approval/deactivation revoke sessions after identity-boundary changes; and business financial/review fields are excluded from self-service. Six models were added and two existing models extended. Customer/business and admin APIs are documented in `Documentation/API_CUSTOMER_BUSINESS.md`.
|
|
|
|
The complete mocked regression suite passes 12 suites/57 tests, and syntax validation passes 171 JavaScript files. The Phase 3 migration is forward-only and was not executed. Staging must resolve legacy business/profile/address pre-checks, seed/grant permissions, and validate MySQL concurrency plus Redis/S3/SMTP flows before Phase 4. See `Documentation/PHASE_3_CUSTOMER_BUSINESS_FOUNDATIONS.md`.
|
|
|
|
## Phase 2 Completion Update
|
|
|
|
Completion date: 2026-09-03. Phase 2 hardens the existing shared-service foundation without adding commerce domains. Module 14 (notifications) is now approximately 72%; Module 19 (file/media) 82%; Module 20 (audit/config/logging) 68%; and Module 21 (background jobs) 78%. The document subsystem is approximately 82%.
|
|
|
|
Storage now has a reusable S3/S3-compatible boundary, actual-content validation, controlled keys, checksums, owner/status metadata, compensation, and authorization-safe signed URLs. Email is routed through BullMQ with delivery status and final-failure persistence. Notifications have fixed aliases, unique assignment migration, self-only inbox/read operations, announcement support, and preference policy. Queue defaults, idempotent job IDs, Bull Board registration, safe failure handling, stronger append-only activity records, and structured redacted logs are in place. Documents now have ownership, controlled registry validation, persisted generation lifecycle, safe status, and non-destructive signed download.
|
|
|
|
The full mocked suite contains 10 suites/40 tests and passes; syntax checks cover 153 JavaScript files. The new migration was not executed. Remaining work is staging migration/data pre-checks plus real MySQL, Redis, S3-compatible, SMTP, PDF/browser, retention-volume, and concurrency validation. After those operational checks and permission seeding, it is safe to begin Phase 3. See `Documentation/PHASE_2_CROSS_CUTTING_SERVICES.md` and `Documentation/API_CROSS_CUTTING_SERVICES.md`.
|
|
|
|
Audit date: 2026-09-03
|
|
Scope: repository source, configuration, lockfile, existing documentation, safe syntax/test/dependency checks. No database, Redis, S3, email, or other external service was mutated.
|
|
|
|
## 1. Executive Summary
|
|
|
|
This repository is an early modular-monolith foundation, not yet an e-commerce backend. It contains working-shaped user registration/email verification, OTP login, basic profiles, RBAC tables/controllers, notifications, activity logging, S3 upload plumbing, document generation, Redis/BullMQ workers, and one cron. Important pieces are incomplete or broken in integration. The estimated completion against the 25-module ZUMRI target is **about 12%**.
|
|
|
|
No original development-plan day is fully complete. Day 1 is approximately 55%: Express, Sequelize/MySQL, Redis/BullMQ, a Dockerfile, and a health route exist, but Swagger, robust health checks, Node 22 alignment, production bootstrap/error handling, Compose/Nginx, migrations, and tests do not. Day 2 is approximately 38%; Day 3 approximately 18%; notification/job/file/document/audit foundations from later days were built early.
|
|
|
|
The code still carries prior-project terminology (`Oceanic Titan`, `oceanic-db`, Oceanic demo URL) and role names that conflict with the actual user ENUM. Future work should preserve usable primitives, but first complete and secure foundation/authentication.
|
|
|
|
Status terms: **COMPLETE** = end-to-end implementation is credible from source; **PARTIAL** = meaningful code exists but requirements/integration are incomplete; **STUB** = structure only; **MISSING** = no implementation; **BROKEN** = known source/integration defect.
|
|
|
|
## 2. Current Architecture
|
|
|
|
- `server.js` loads `.env`, imports `app.js`, and listens on `0.0.0.0:${PORT|3070}`.
|
|
- `app.js` authenticates Sequelize and calls unrestricted `sequelize.sync()` in an unawaited startup IIFE, then starts cron jobs. The HTTP listener starts independently, so requests can arrive before database readiness, and DB failure does not stop the process.
|
|
- Middleware order is cookie parser, CORS, JSON parser, Morgan, `/health`, `/api`, static documentation, then Bull Board. There is no URL-encoded parser, request ID, Helmet, compression, rate limiting, global 404 handler, or global error handler.
|
|
- API base path is `/api` (not versioned). Routes delegate mostly directly to Sequelize-backed controllers; there is only a permission service and activity service.
|
|
- Redis connections are created at module import. One shared client is used by queues/workers, while password reset and S3 utilities create additional clients.
|
|
- Workers are a separate `npm run worker` process. The server does not start them. Activity, log, and document consumers exist.
|
|
- Cron runs in every API process after DB sync; there is no distributed lock, so multi-instance deployments duplicate scheduling.
|
|
- Sequelize models are registered centrally and their `associate` functions are invoked. No migrations are present.
|
|
- Environment keys exist locally; `.env` is ignored/untracked. `.env.sample` is tracked. No actual secret values are reproduced here.
|
|
|
|
### Bootstrap and operational findings
|
|
|
|
| Concern | Status | Evidence / impact |
|
|
|---|---|---|
|
|
| Express start and base path | Partial | `server.js`, `app.js`; `/api` and `/health` |
|
|
| JSON / cookies / CORS / logging | Partial | JSON, cookies, single-origin credentialed CORS, Morgan `dev`; no body-size configuration or URL-encoded parser |
|
|
| Security middleware | Missing | No Helmet or API rate limiter |
|
|
| 404/global errors | Missing | Errors depend on individual controllers; unmatched routes use Express defaults |
|
|
| Database readiness | Broken | Listener is not gated on authenticate/sync; failure is logged only |
|
|
| Redis readiness | Partial | Event logging exists; health endpoint never checks Redis |
|
|
| BullMQ/workers | Partial | Separate process required and undocumented operationally; retries only on document jobs |
|
|
| Cron initialization | Partial | Starts after DB sync, once per server process, with no leader lock |
|
|
| Health check | Broken | Sends response before asynchronous DB authentication completes and hardcodes mail/Redis as OK |
|
|
| Graceful shutdown | Missing | No SIGTERM/SIGINT cleanup for server, Sequelize, Redis, workers, or cron |
|
|
| Process errors | Missing | No `unhandledRejection`/`uncaughtException` policy |
|
|
|
|
## 3. Existing Infrastructure
|
|
|
|
| Component | Status | Files | Notes |
|
|
|---|---|---|---|
|
|
| Express API | Partial | `server.js`, `app.js`, `app/routes/*` | Express 5; no versioning/global errors/security middleware |
|
|
| MySQL/Sequelize | Partial | `app/config/db.config.js`, `app/models/index.js` | Pool configured; runtime `sync()`, no migrations |
|
|
| Redis | Partial | `redis.config.js`, `redisClient.js` | Functional client pattern; excessive clients, no shutdown/readiness |
|
|
| BullMQ | Partial | `app/queues/*`, `app/workers/*` | Three queues and matching consumers; only document jobs have attempts/backoff/retention |
|
|
| Bull Board | Broken/unsafe | `bullBoard.config.js`, `app.js` | Only activity queue shown; `/admin/queues` has no authentication |
|
|
| Cron | Partial | `cron/*` | Transactional notification deletion; no distributed lock or retention-age policy |
|
|
| Email | Partial | `mail.config.js`, `mail.util.js`, templates | SMTP/template sender exists; verifies on import, sends inline, no queue/retry/escaping |
|
|
| S3 storage | Broken | `s3.config.js`, `s3Upload.utill.js` | S3 client is entirely commented out, so `s3.send` fails |
|
|
| Uploads | Broken | upload middleware/controller/model | MIME/size checks exist; account guard is incompatible; no magic-byte validation/cleanup/ownership |
|
|
| Documents | Partial/broken | document controller, logic, templates, queue/worker | PDF/Excel framework is substantive; S3 breaks completion; access is overly broad and role guards mismatch |
|
|
| Notifications | Partial | notification models/controller/cron | In-app records only; no assignment API/service, email/FCM/preferences/delivery tracking |
|
|
| Activity/audit | Partial | activity service/model/queue/worker/controller | Async append-only-shaped records; no actor/IP/change metadata, integrity/retention, or broad coverage |
|
|
| Logging | Partial | console utility/log queue/worker | Local daily files; may receive sensitive payloads; no rotation/structured sink |
|
|
| API docs | Partial | `Documentation/*`, docs routes | Handwritten Markdown/HTML, not Swagger/OpenAPI; docs auth is forgeable |
|
|
| Tests | Missing | package script only | Jest finds zero tests; Supertest is not installed |
|
|
| Docker | Partial | `Dockerfile` | Uses Node 20 instead of target Node 22; API image only; no healthcheck/non-root user |
|
|
| Nginx/Compose/CI/CD | Missing | none | No reverse proxy, service orchestration, or pipeline files |
|
|
| Payments/FCM/OpenAI | Missing | none | No dependencies, config, models, or consumers |
|
|
|
|
Queue behavior: `document-generation` has 3 exponential attempts (2s base), completed retention, and retained failures. `activity-queue` and `logQueue` have consumers but no explicit retry/backoff/retention/dead-letter policy and are not idempotent. Re-delivery can duplicate activity rows or log lines. Queue event listeners attached to `Queue` are not a reliable substitute for `QueueEvents` for all lifecycle events. Worker failures are logged only. Document status is not reconciled on job failure/success.
|
|
|
|
## 4. Existing Database Models
|
|
|
|
All models use timestamps and none uses `paranoid`. Aside from the unique flags noted below, explicit indexes are absent.
|
|
|
|
| Model / table | Key and important fields | Purpose | Important relations | Status |
|
|
|---|---|---|---|---|
|
|
| User / `users` | PK string `id`; names, unique email, password, accountType ENUM, accountStatus ENUM, emailVerifiedAt | Identity/account | hasOne Profile; hasMany UserPermission | Partial; no role FK/`roleID` despite service/controller use, no sessions/tokenVersion/social IDs |
|
|
| Profile / `profiles` | PK `profile_id`; unique `user_id`; theme, notificationsEnabled, image IDs, DOB, phone | Basic preferences/profile | belongsTo User | Partial; no gender/language/address; image IDs lack FKs |
|
|
| UserActivity / `UserActivity` | integer PK; user/name/description/type/module/date/time | Activity trail | None | Partial; user FK absent, redundant time fields, no indexes |
|
|
| Upload / `uploads` | integer PK; S3 path/type/size/name/use/uploaded_by | Media metadata | None | Partial; uploader/user and ownership FKs absent |
|
|
| Permission / `permission` | PK `permission_id`; name/page/module/action | Permission definition | hasMany role/user grants | Partial |
|
|
| Role / `roles` | PK `role_id`; name/description | Named role | hasMany role grants | Partial; User has no role association |
|
|
| RolePermission / `rolePermission` | PK `rp_id`; role_id, permission_id | Role grant | belongsTo Role/Permission | Partial; no composite unique constraint |
|
|
| UserPermission / `userPermission` | integer PK; user_id, permission_id | Direct additive grant | belongsTo User/Permission | Partial; no composite unique; cannot deny/expire grants |
|
|
| Document / `Document` | PK `doc_id`; reference_no, doc_type, JSON data, status | Saved business documents | None | Partial; status/type unconstrained, no creator/owner/FKs/indexes |
|
|
| DocumentType / `DocumentType` | integer PK; nullable name, JSON description | Document registry metadata | None | Partial; name is neither required nor unique |
|
|
| ReferenceNumber / `referenceNumbers` | PK string; unique sequence_key, integer counter, last value | Atomic sequence generation | None | Reusable; transaction/row locking implemented by utility |
|
|
| Notification / `notification` | PK string; headline/body, USER/ANNOUNCEMENT ENUM, active/date | In-app notification content | hasMany UserNotification as `users` | Partial |
|
|
| UserNotification / `user_notification` | integer PK; user_id, notification_id, isRead | Per-user notification state | belongsTo User; belongsTo Notification | Partial; constraints disabled, no composite unique/index; include alias is inconsistent (controller asks `notification`, association defines no alias) |
|
|
|
|
Association registration does execute. However, User's `roleID` is not a declared attribute or FK, notifications deliberately disable FK constraints, activities/uploads/documents have no user association, and join-table uniqueness is not enforced. `sequelize.sync()` masks the absence of schema migrations and makes production schema evolution unsafe.
|
|
|
|
## 5. Existing API Endpoints
|
|
|
|
All paths below are derived from actual mounting. “Self-or-admin” is not implemented anywhere; parameterized user endpoints generally trust the requested ID after coarse account-type checks.
|
|
|
|
| Method | Endpoint | Auth | Permission / guard | Status | Notes |
|
|
|---|---|---|---|---|---|
|
|
| GET | `/health` | No | None | Broken | Returns before DB check; Redis/mail are hardcoded OK |
|
|
| GET | `/api/auth/me` | Yes | None | Partial | Returns token payload plus effective permissions |
|
|
| POST | `/api/auth/req-otp` | No | None | Partial/unsafe | Password + in-memory OTP; logs OTP; enumeration; no attempts/rate limit/status check |
|
|
| POST | `/api/auth/login` | No | None | Partial/unsafe | OTP to one-day access cookie; no refresh/session/rotation/status check |
|
|
| POST | `/api/auth/logout` | No | None | Partial | Clears cookie only; bearer tokens remain valid |
|
|
| POST | `/api/user` | No | None | Partial/bug | Registration + profile + verification; activity uses undefined `req.user` after commit |
|
|
| POST | `/api/user/verify-email` | No | None | Partial | Redis one-use hashed token; no resend endpoint |
|
|
| GET | `/api/user` | Yes | accountType `admin` | Partial | Paginated list |
|
|
| GET | `/api/user/:id` | Yes | listed legacy types | Broken/IDOR | Most listed types cannot exist; no ownership enforcement |
|
|
| PATCH | `/api/user/:id` | Yes | listed legacy types | Broken/privilege escalation | Mass updates accountType/undeclared role fields; no ownership/field validation; early returns leak transaction |
|
|
| DELETE | `/api/user/:id` | Yes | `admin` | Partial | Hard delete; related profile handling depends on DB state; early return leaks transaction |
|
|
| GET | `/api/activity` | Yes | `admin` | Partial | Full audit list, no pagination |
|
|
| GET | `/api/activity/user/:userId` | Yes | `admin` | Partial | No paging/index |
|
|
| POST | `/api/upload` | Yes | `admin` or nonexistent `staff` | Broken | S3 client undefined; DB requires `use_for`; upload not transactional |
|
|
| GET | `/api/upload/signed-url/:id` | Yes | `admin` or nonexistent `staff` | Broken | S3 undefined; catch sends no response; no ownership check |
|
|
| GET | `/api/document/types` | Yes | admin or nonexistent legacy types | Partial | Effectively admin-only under current ENUM |
|
|
| POST | `/api/document/saved` | Yes | same | Partial | Body filter on a read operation; no owner/pagination; Sequelize `exclude` placed incorrectly |
|
|
| POST | `/api/document/generate` | Yes | same | Broken | Queues correctly, but worker S3 upload fails; validation shallow |
|
|
| POST | `/api/document/draft` | Yes | same | Partial | Saves arbitrary JSON; no ownership/validation |
|
|
| GET | `/api/document/reference-number/:documentType` | Yes | same | Partial | Consumes sequence on GET |
|
|
| GET | `/api/document/job/:jobId/status` | Yes | same | Partial/IDOR | Exposes stacktrace and any job by ID |
|
|
| GET | `/api/document/download/:uuid` | Yes | same | Broken/unsafe | S3 undefined; deletes shared object after response; no ownership |
|
|
| DELETE | `/api/document/job/:jobId` | Yes | same | Partial/IDOR | Any allowed user can remove any removable job |
|
|
| GET | `/api/document/:docId` | Yes | same | Partial/IDOR | Arbitrary document access |
|
|
| POST | `/api/docs/login` | No | Static credentials | Unsafe | Sets unsigned boolean cookie; no expiry/rate limiting |
|
|
| POST | `/api/docs/logout` | No | None | Partial | Clears cookie |
|
|
| GET | `/api/docs/markdown-files` | docs cookie | `docsAuth === "true"` | Unsafe | Cookie can be forged by client |
|
|
| GET | `/api/docs/view/:file` | docs cookie | same | Partial | Extension/path checks; auth is weak |
|
|
| POST | `/api/profile/req-reset-password` | No | None | Partial/unsafe logging | Enumeration-resistant response; raw reset token is logged |
|
|
| POST | `/api/profile/reset-password` | No | None | Partial | Hashed one-use Redis token; new password is not policy-validated |
|
|
| POST | `/api/profile/change-password` | Yes | legacy account types | Broken/partial | Effectively admin-only; no new-password validation/session revocation |
|
|
| GET | `/api/profile/avatar/:userId` | Yes | legacy account types | Broken | S3 undefined, missing upload null check, wrong `profile.userId` property, IDOR |
|
|
| GET | `/api/profile/background/:userId` | Yes | legacy account types | Broken | Same issues |
|
|
| POST | `/api/notification` | Yes | admin or nonexistent `management` | Partial | Creates content only; no user assignment |
|
|
| GET | `/api/notification/announcements` | Yes | legacy account types | Partial | Effectively admin-only |
|
|
| GET | `/api/notification/user/:userId` | Yes | legacy account types | Broken/IDOR | Include alias mismatch likely throws; no ownership |
|
|
| PATCH | `/api/notification/user/:userId/notification/:notificationId/read` | Yes | legacy account types | Broken/IDOR | No ownership; effectively admin-only |
|
|
| ALL | `/admin/queues/*` | No | None | Unsafe | Bull Board exposed; only activity queue registered |
|
|
| GET | `/Documentation/*` | No | Blocks `.md` only | Partial | Static HTML documentation is public |
|
|
|
|
### Defined but unreachable permission routes
|
|
|
|
`app/routes/permission.routes.js` defines 18 endpoints under the intended permission router (permission CRUD/bulk; role CRUD and grants; user grants CRUD/bulk), but `app/routes/index.js` imports `permissionRoutes` and never calls `router.use(...)`. Therefore none has an actual URL and all are **BROKEN/unreachable**. If mounted as `/permission`, their paths would be `/`, `/bulk`, `/:permissionId`, `/roles`, `/roles/:roleId`, `/roles/:roleId/permissions`, `/roles/permissions/bulk`, `/users/:userId/permissions`, `/users/permissions`, `/users/permissions/bulk`, and `/users/permissions/:upId` with the methods declared in that file. Read endpoints require authentication; mutations require accountType exactly `admin`. Controllers are substantial CRUD logic, but integration, uniqueness, cache invalidation, validation, and transactions are inconsistent.
|
|
|
|
## 6. Development Plan Status
|
|
|
|
| Module | Completion | Status | Evidence | Remaining Work |
|
|
|---|---:|---|---|---|
|
|
| 01 Authentication & Authorization | 38% | Partial | Password hashing, register/verify, OTP access JWT, middleware, RBAC structures | Refresh/session lifecycle, OAuth/Apple, durable OTP/limits, status enforcement, role linkage, mount/fix RBAC |
|
|
| 02 Customer Profile & Address Management | 22% | Foundation | User/Profile with phone, DOB, images/preferences | Self-service ownership, addresses/default, gender/language, deactivation, robust image flow |
|
|
| 03 Product Catalogue Management | 0% | Missing | No models/routes | Full catalogue/category/variant/review/SEO model and APIs |
|
|
| 04 Multi-Language Content | 0% | Missing | No content translation system | Locale strategy and translated content |
|
|
| 05 Inventory Management | 0% | Missing | No inventory entities | Stock, reservations, warehouses, adjustments |
|
|
| 06 Cart & Wishlist | 0% | Missing | None | Entire module |
|
|
| 07 Promotions, Coupons & Banners | 0% | Missing | None | Entire module |
|
|
| 08 Checkout | 0% | Missing | None | Pricing/shipping/tax/transaction orchestration |
|
|
| 09 Order Management | 0% | Missing | Document names are not commerce orders | Full order state machine and returns |
|
|
| 10 Payment Management | 0% | Missing | No provider code/dependencies | PayHere/Stripe, webhooks, idempotency, refunds |
|
|
| 11 Delivery & Rider Management | 2% | Foundation only | `rider` account ENUM; document templates named delivery/dispatch | Rider profiles, assignments, tracking, zones/rates |
|
|
| 12 Loyalty, Reward Points & Membership | 0% | Missing | None | Ledger, tiers, generic earn rules, rewards/vouchers |
|
|
| 13 Wholesale / Business Accounts | 2% | Foundation only | `business_customer` ENUM only | Approval/profile/pricing/MOQ/tiers/credit/settlements/invoices/analytics |
|
|
| 14 Notification System | 28% | Partial | Notification/user join models, CRUD/read endpoints, cleanup cron, mail utility | Fix aliases/ownership; assignment and preferences; FCM/email jobs/templates/status |
|
|
| 15 Support Ticket System | 0% | Missing | None | Tickets, messages, SLA/escalation/help center |
|
|
| 16 AI Customer Support Chatbot | 0% | Missing | No OpenAI integration | Conversations, tools, safety, human escalation |
|
|
| 17 Product Recommendations | 0% | Missing | None | Events and recommendation service |
|
|
| 18 Admin Dashboard & Analytics | 1% | Foundation | Admin user type and raw activity endpoint | Metrics, aggregation, secured dashboard APIs |
|
|
| 19 File & Media Management | 25% | Broken foundation | Multer, Upload model, S3/presigned utilities | Restore/configure client, ownership, object validation/lifecycle, media transformations |
|
|
| 20 Audit Logging & System Configuration | 22% | Partial | Async activity records/log queue | Full audit schema/coverage, immutability, config models, secure structured logging |
|
|
| 21 Background Jobs & Queues | 35% | Partial | Redis, 3 queues/consumers, worker entry, document retry | Idempotency, policies for every queue, monitoring auth, graceful shutdown, scheduler topology |
|
|
| 22 Security | 15% | Weak foundation | bcrypt, JWT verification, HttpOnly cookie, basic MIME limits | Findings in §10; headers, throttles, validation, authorization, secrets/token discipline |
|
|
| 23 Testing & Quality Assurance | 2% | Missing | Jest dependency/script only | Tests, Supertest, fixtures, lint/type/static checks, CI |
|
|
| 24 API Documentation | 18% | Partial | Handwritten endpoint Markdown/HTML | OpenAPI/Swagger, synchronization, schemas/security/error contracts |
|
|
| 25 Deployment & Infrastructure | 18% | Partial | Dockerfile | Node 22, Compose, Nginx, healthcheck, non-root, migrations, CI/CD, observability |
|
|
|
|
## 7. Original 15-Day Plan Status
|
|
|
|
| Day | Intended Scope | Completion | Notes |
|
|
|---|---|---:|---|
|
|
| 1 | Foundation | 55% | Express/Sequelize/MySQL/Redis/BullMQ/Docker present; health broken; Swagger/Compose/migrations/production lifecycle missing |
|
|
| 2 | Authentication | 38% | Basic verified registration and OTP access JWT; core session/OAuth/security requirements incomplete |
|
|
| 3 | Customer + business accounts | 18% | Basic user/profile and enum only; no addresses/business domain |
|
|
| 4 | Products/categories/variants | 0% | Missing |
|
|
| 5 | Inventory/admin products | 0% | Missing |
|
|
| 6 | Cart/wishlist | 0% | Missing |
|
|
| 7 | Promotions/checkout | 0% | Missing |
|
|
| 8 | Orders | 0% | Missing |
|
|
| 9 | Payments | 0% | Missing |
|
|
| 10 | Delivery/rider | 2% | Rider enum and unrelated document templates only |
|
|
| 11 | Loyalty | 0% | Missing |
|
|
| 12 | Notifications/support | 16% | Partial in-app notification foundation; support absent |
|
|
| 13 | AI/recommendations | 0% | Missing |
|
|
| 14 | Analytics/security | 8% | Raw activities and scattered security controls only |
|
|
| 15 | QA/production | 5% | Dockerfile only; no tests/CI/Nginx/production hardening |
|
|
|
|
**Last genuinely complete day: none.** Development reached partway through Day 1 and Day 2, with selected infrastructure from Days 12, 14, and 15 implemented early.
|
|
|
|
## 8. Demo Website Requirement Gaps
|
|
|
|
| Feature | Present on Demo | Present Backend | Original Plan | Action Needed |
|
|
|---|---|---|---|---|
|
|
| Email/password login | Yes | Partial (password then email OTP) | Auth | Clarify desired login flow; secure OTP/session lifecycle |
|
|
| Remember me | Yes | No | Auth | Add session-specific lifetime safely |
|
|
| Forgot/reset password | Yes | Partial | Auth | Stop token logging, validate password, revoke sessions |
|
|
| Google sign-in | Yes | No | Auth | Add provider verification/linking |
|
|
| Apple sign-in | Yes | No | Potential added requirement | Add to auth scope explicitly |
|
|
| Account overview/recent orders/counts | Yes | No | Customer/orders | Aggregate dashboard endpoint after domain models |
|
|
| Points/vouchers/membership/progress | Yes | No | Loyalty | Ledger, tier/rule/reward architecture |
|
|
| Default address/profile/addresses | Yes | Profile partial; addresses absent | Customer | Ownership-safe profile and address CRUD/default constraint |
|
|
| Wishlist/order history/sign out | Yes | Sign-out cookie only; rest absent | Cart/orders/auth | Implement modules and true session revocation |
|
|
| Silver/Gold/Platinum tiers/benefits | Yes | No | Loyalty | Configurable tiers; do not hardcode demo examples |
|
|
| Point transaction history | Yes | No | Loyalty | Immutable ledger |
|
|
| Purchases/reviews/referrals/birthdays earning | Yes | No | Loyalty/reviews | Generic earn-source rules with idempotency |
|
|
| Reward redemption/vouchers/shipping rewards | Yes | No | Loyalty/promotions | Reward definitions, redemption transaction, vouchers |
|
|
| Business approval/Partner ID/tier | Yes | Account enum only | Wholesale | Business profile and approval workflow |
|
|
| Monthly/history/discount/top buyers/orders | Yes | No | Wholesale/analytics | Wholesale aggregates and reporting |
|
|
| Credit limit/available/utilization | Yes | No | Wholesale | Credit account/ledger and authorization rules |
|
|
| Settlement terms/dates/invoices | Yes | No | Wholesale/payment | Terms, statements, invoice/payment lifecycle |
|
|
| Wholesale catalogue/MOQ/pricing tiers/bulk | Yes | No | Wholesale/catalogue | Customer-segment pricing and volume tiers |
|
|
| Featured inventory/reorder | Yes | No | Inventory/wholesale | Stock and reorder workflows |
|
|
| Shipping thresholds/methods/zones/fees | Yes | No | Checkout/delivery | Configurable rate engine |
|
|
| International shipping/duties display | Yes | No | Delivery/checkout | Destination rules and duty estimate representation |
|
|
| Order tracking | Yes | No | Orders/delivery | Shipment event timeline |
|
|
| 30-day return/eligibility/reason/status | Yes | No | Orders (gap detail) | Configurable returns/RMA state machine |
|
|
| Pickup/refund/exchange | Yes | No | Delivery/payment/orders | Integrate RMA, courier, payment refund, exchange order |
|
|
| Help center/FAQs/sizing/payment help | Yes | No | Support/content | CMS/help content APIs |
|
|
| Email support/tickets | Yes | No | Support | Ticket/conversation/SLA module |
|
|
| AI Style Assistant/human escalation | Yes | No | AI/support | AI conversation with ticket/advisor handoff |
|
|
| Newsletter consent lifecycle | Yes | No | Demo gap | Dedicated subscriber consent/status/source/language model; not profile notification preference |
|
|
| New/featured/sale products | Yes | No | Catalogue/promotions | Merchandising fields/rules |
|
|
| Category/editorial collections | Yes | No | Catalogue/content | Collections and ordered merchandising |
|
|
| Related products | Yes | No | Recommendations/catalogue | Explicit and computed relations |
|
|
| Reviews/verified purchase reviews | Yes | No | Catalogue/recommendations | Review moderation and verified-order link |
|
|
| Size guides | Yes | No | Catalogue/content | Structured, category/product-linked guides |
|
|
| Product SEO | Yes | No | Catalogue | Slugs/meta/canonical data |
|
|
| Banners | Yes | No | Promotions | Placement, locale, schedule, targeting |
|
|
| Multiple languages | Yes | No | Multi-language | Localized product/content model |
|
|
|
|
Current order/delivery architecture cannot support shipping or returns: no commerce Order, OrderItem, Shipment, Address, Return, Refund, or state-transition entities exist. The similarly named generated documents are generic JSON documents and should not be treated as domain substitutes.
|
|
|
|
## 9. Technical Debt
|
|
|
|
### CRITICAL
|
|
|
|
- Restore a valid S3 client before any upload/document endpoint can work.
|
|
- Align authorization vocabulary and enforce ownership; current legacy guards, IDORs, and accountType mutation enable denial of access or privilege escalation.
|
|
- Remove raw OTP/reset-token and decoded-auth logging; rotate any credentials if operational logs captured them.
|
|
- Replace production `sequelize.sync()` with migrations and gate server readiness on required services.
|
|
- Implement a real access/refresh session model with rotation, revocation, account-status enforcement, and secure logout.
|
|
|
|
### HIGH
|
|
|
|
- Mount and repair permission routes; add User-role linkage and grant uniqueness/cache invalidation.
|
|
- Add validation schemas and centralized error handling; prevent arbitrary field updates.
|
|
- Protect Bull Board and documentation sessions.
|
|
- Fix notification association alias and user ownership checks.
|
|
- Add rate limits for login, OTP, verification, reset, docs login, and general API traffic.
|
|
- Add tests for auth/authorization, transactions, uploads/jobs, and failure paths.
|
|
- Fix transaction leaks on early returns in user update/delete.
|
|
|
|
### MEDIUM
|
|
|
|
- Standardize response/error formats and status codes; stop returning internal error messages/stack traces.
|
|
- Consolidate Redis connections and add lifecycle/readiness handling.
|
|
- Make jobs idempotent and add retry/backoff/retention/dead-letter/alert policies.
|
|
- Move email to a job and add retry/delivery tracking and safe template escaping.
|
|
- Add pagination/indexes to activity, notification, document, and user queries.
|
|
- Remove legacy Oceanic naming and reconcile API versioning.
|
|
|
|
### LOW
|
|
|
|
- Correct mojibake in source/log messages, inconsistent singular/plural table names, and `*.utill.js` spelling.
|
|
- Remove unused imports/constants and dead/commented code.
|
|
- Split giant permission controller and move business logic into services after behavior is tested.
|
|
|
|
## 10. Security Findings
|
|
|
|
- No tracked `.env` was detected. `.env.sample` is tracked. Potential secret-bearing configuration exists in local `.env`; values were not inspected/reproduced. If this file has ever been shared or committed elsewhere, rotate credentials.
|
|
- JWT falls back to a public placeholder secret if configuration is missing. There is no issuer/audience/session ID/tokenVersion or refresh-token revocation.
|
|
- Login OTP uses `Math.random`, process memory, and no attempt/rate limit; it fails across instances/restarts and is logged in plaintext.
|
|
- Password reset token is logged in plaintext. Reset/change paths do not validate the new password policy or revoke existing access tokens.
|
|
- Login does not reject pending, suspended, or deactivated accounts.
|
|
- User update allows coarse-authorized callers to target arbitrary IDs and set `accountType`, a privilege-escalation and IDOR risk. Many profile/notification/document endpoints have the same ownership defect.
|
|
- Bull Board is public. Docs protection is an unsigned client cookie equal to `true`; credentials are brute-forceable without rate limiting.
|
|
- CORS is a single credentialed origin and cookie flags are reasonable for cross-site production, but CSRF protection/origin validation is absent for cookie-authenticated mutations.
|
|
- Multer limits size and declared MIME, but image wildcard acceptance lacks content sniffing, image decompression safeguards, antivirus scanning, extension normalization policy, and object lifecycle cleanup.
|
|
- S3 `PutObject` sets no ACL (good default if bucket blocks public access), but actual bucket policy/encryption cannot be verified. Signed URLs are cached; authorization is checked only before URL issuance and ownership is not checked.
|
|
- Controllers expose `error.message`; job status exposes stack traces. Production Sequelize logging is inverted to `true`, which can leak query data.
|
|
- Request validation is handwritten and sparse; mass assignment exists in user update. Sequelize query values are generally parameterized, so no direct raw-SQL injection was found.
|
|
- Foreign-key constraints are disabled for notification joins; missing uniqueness and transactions create races/duplicates in grants and notifications.
|
|
- No Helmet, API rate limiting, CSRF strategy, audit integrity, session revocation, or centralized security error policy exists.
|
|
|
|
## 11. Broken / Suspicious Implementations
|
|
|
|
- `app/config/s3.config.js`: the entire client/export is commented; every S3 caller receives `{}`.
|
|
- `app/routes/index.js`: imports `permissionRoutes` but never mounts it.
|
|
- `app/utils/documentJob.util.js`: requires nonexistent `../queues/pdf.queue`; currently appears orphaned.
|
|
- `app/services/permission.service.js#getEffectivePermissions`: queries `user.roleID`, which is not a User model attribute; role grants cannot reliably apply.
|
|
- `app/routes/{user,profile,document,notification}.routes.js`: guards use `management`, `team_head`, `user`, or `staff`, none of which is in the User ENUM. Valid `manager`, `customer`, `business_customer`, `rider`, `support_agent`, and `superadmin` are largely excluded.
|
|
- `user.controller#createNewUser`: calls `logActivity({user: req.user})` on a public route, causing a post-commit exception after the account has been created; client may receive 500 and retry.
|
|
- `user.controller#updateUser`: accepts accountType and undeclared role/department fields; does not update email despite destructuring it; opens transaction before lookups and does not roll back early 404 responses.
|
|
- `user.controller#deleteUser`: early 404 does not roll back; hard delete may conflict with Profile because cascade is unspecified.
|
|
- `profile.controller#getProfileAvatar/getProfileBackgroundImage`: assumes upload exists, uses wrong `profile.userId` response property, lacks ownership, and reaches broken S3.
|
|
- `upload.controller#getFileUrl`: empty catch block can leave requests hanging.
|
|
- `notification.controller#getUserNotifications`: requests association alias `notification`, but `belongsTo` defines no alias; likely Sequelize eager-loading error.
|
|
- `notification.controller`: USER notifications are created but never assigned to users through an endpoint/service.
|
|
- `app.js#/health`: asynchronous DB result races with response; reports `N/A`/hardcoded OK rather than real readiness.
|
|
- `app.js` bootstrap: server listens before DB boot finishes; DB errors are swallowed; each instance starts cron.
|
|
- `app/middleware/permission.middleware.js`: unused `hasPermission`; admin bypass only recognizes `admin`, not `superadmin`; wildcard logic differs between helper and actual check.
|
|
- `docsSession.middleware.js`: trusts an unsigned, client-set boolean cookie.
|
|
- `document.controller#getSavedDocuments`: `exclude` is not nested under `attributes`, so JSON data may still be fetched; filter is in POST body despite message saying query parameter.
|
|
- `document.controller#downloadDocument`: destructive read deletes the object after delivery and lacks job/user ownership.
|
|
- `app/logic/documents/registry.js`: catches module load failure but still registers undefined functions, deferring failure to runtime.
|
|
- `consoleLog.utill.js` and auth/reset utilities: log pipelines may persist secrets and full error objects.
|
|
- Production DB logging is enabled while non-production logging is disabled, likely inverted.
|
|
|
|
Orphaned or unused-looking code includes `documentJob.util.js`, `notification.utill.js` (empty), `logic/documents/engine/pdf.engine.js` (generation uses `pdfGenerator.js`), several Excel/id/vendor/calendar/basis utilities not referenced by mounted features, `Assets` in upload controller (unregistered), imported `PERMISSIONS`/`checkPermission` in routes where checks are absent/commented, and unused dependencies likely including `pdfmake` and `nodeman`. `nodemon` is incorrectly a production dependency. Static analysis cannot prove every dynamic/template use; confirm before removal.
|
|
|
|
## 12. Reusable Existing Components
|
|
|
|
- Sequelize model registry/association convention can be extended after migrations replace runtime sync.
|
|
- User/Profile registration transaction, bcrypt utility, hashed one-use email verification token, and hashed password-reset-token concepts are sound foundations once error/logging/session issues are fixed.
|
|
- Cookie-or-Bearer authentication middleware structure is reusable after it loads current user/session/status and applies token claims.
|
|
- Permission, role, role-grant, and user-grant models/controllers/service are worth repairing rather than rebuilding; add role linkage, constraints, mounting, validation, and cache invalidation.
|
|
- Shared Redis factory/client and permission/user cache helpers can be consolidated and retained.
|
|
- Activity queue/service/worker is a useful async audit foundation; extend its schema and coverage.
|
|
- BullMQ worker entry pattern and document queue retry/backoff settings are reusable; standardize them across queues.
|
|
- Upload metadata model, Multer memory-storage limits, S3 key generation, and presigned URL caching are reusable after the S3 client and authorization/content validation are fixed.
|
|
- Document registry, PDF/Excel generators, templates, queue/worker, Document/DocumentType models, and atomic reference-number generator are substantive reusable subsystems. They are auxiliary business-document infrastructure, not order/payment replacements.
|
|
- Notification/UserNotification models, read-state concept, announcement query, and transactional cleanup cron can be repaired and extended for channel delivery.
|
|
- Email transport/template system and existing verification/reset/welcome templates can be moved behind an email queue.
|
|
|
|
## 13. Recommended Next Development Phase
|
|
|
|
Continue with a **Foundation, security, and authentication completion phase** before starting catalogue work.
|
|
|
|
First make startup deterministic and production-safe: Node 22 alignment, validated environment configuration, migrations, real readiness/liveness checks, global 404/errors, Helmet/rate limits, protected operations dashboards, graceful shutdown, and a test harness. Then complete identity: Redis-backed cryptographic OTP with limits, account-status checks, access/refresh sessions with rotation/revocation, secure logout/reset, validation, ownership rules, and a repaired/mounted role-permission system. Repair S3 only as part of restoring already-promised profile/media/document behavior.
|
|
|
|
After that baseline passes integration tests, finish customer/business profile and address primitives, reusing User/Profile, auth middleware, Redis, permission service, upload system, activity logger, email templates, queues, and reference-number utility. Only then begin catalogue/product models.
|
|
|
|
## 14. Recommended Updated Roadmap
|
|
|
|
1. **Phase 0 — Stabilize foundation:** Node 22, env validation, migrations, startup/readiness, global errors/security middleware, graceful shutdown, protected Bull Board, baseline Jest/Supertest and CI.
|
|
2. **Phase 1 — Complete identity and authorization:** OTP/session/refresh rotation, status checks, logout/revocation, password recovery hardening, OAuth Google/Apple, ownership rules, repaired roles/permissions.
|
|
3. **Phase 2 — Repair existing cross-cutting services:** S3/media, email jobs, notification aliases/assignment, queue reliability/idempotency, audit schema, document ownership and job lifecycle.
|
|
4. **Phase 3 — Customer and business foundations:** Profile completion, addresses/defaults, preferences/deactivation, business approval/partner identity/credit and settlement primitives.
|
|
5. **Phase 4 — Catalogue/content:** Categories, products, variants, media, localized content, SEO, size guides, collections, reviews.
|
|
6. **Phase 5 — Inventory and merchandising:** Warehouses/stock/reservations, wholesale pricing/MOQ/volume tiers, banners/promotions/coupons.
|
|
7. **Phase 6 — Shopping and checkout:** Cart, wishlist, pricing, shipping zones/rates/duties, checkout transactions.
|
|
8. **Phase 7 — Orders/payments:** Order state machine, PayHere/Stripe webhook idempotency, invoices, refunds, returns/exchanges.
|
|
9. **Phase 8 — Delivery/rider:** Assignments, tracking events, pickup/return logistics.
|
|
10. **Phase 9 — Loyalty and wholesale completion:** Generic earn ledger, tiers, rewards/vouchers/referrals; credit utilization/settlements/analytics.
|
|
11. **Phase 10 — Support/AI/recommendations:** Help content, tickets/SLA, advisor escalation, AI assistant, recommendation events/services.
|
|
12. **Phase 11 — Analytics and production QA:** Dashboards, security testing, load/integration/e2e tests, observability, Nginx/Compose/deployment/runbooks.
|
|
|
|
## 15. Do Not Rebuild List
|
|
|
|
Preserve and extend these concepts/files after adding tests: centralized Sequelize registration; User/Profile base tables; bcrypt helper; Redis connection/cache helpers; email verification/password-reset token hashing; auth middleware extraction of cookie/Bearer tokens; RBAC model/controller foundation; activity queue/service/worker; document registry/generators/templates/queue/worker; reference-number sequencing; Upload metadata/Multer limits/S3 utility interface; Notification/UserNotification read-state model; cleanup cron transaction; mail templates/transport interface; Docker Chromium setup for Puppeteer.
|
|
|
|
## Verification and Dependency Audit
|
|
|
|
- `node --check` passed for every repository JavaScript file.
|
|
- `npm test -- --runInBand` failed because Jest found **0 tests**.
|
|
- `npm ls --depth=0` completed without reporting missing installed top-level packages.
|
|
- `npm audit --omit=dev` reported **28 production dependency vulnerabilities**: 19 high, 8 moderate, 1 low, 0 critical. Dependency upgrades were intentionally not performed.
|
|
- Broken local import scan found active-looking `documentJob.util.js -> ../queues/pdf.queue`; the commented future `email.worker` reference is not an active defect.
|
|
- Targeted dependency observations: Supertest, Swagger/OpenAPI tooling, Helmet, rate limiting, FCM, payment SDKs, and OpenAI SDK are missing. `nodemon` should be dev-only; `nodeman` and `pdfmake` appear unused. Confirm with runtime coverage before removal.
|
|
|
|
## Phase 0 Completion Update
|
|
|
|
**Date:** 2026-09-03
|
|
**Revised Day 1 completion:** approximately **92%**.
|
|
|
|
Phase 0 stabilized the existing foundation without adding commerce modules. Node/Docker now target Node 22; Zod validates required startup configuration and feature-gated mail/S3 configuration; unsafe JWT secret fallbacks are removed. Express construction is independent from listening, and `server.js` waits for successful MySQL authentication and Redis connectivity before accepting traffic. Runtime `sequelize.sync()` was removed and Sequelize CLI plus a non-destructive current-model baseline migration were added.
|
|
|
|
New `/health/live` and `/health/ready` routes provide real liveness/readiness behavior, while `/health` remains a liveness compatibility alias. Request IDs, Helmet, explicit body limits, general and sensitive rate limits, centralized 404/error handling, safer production request logging, configurable cron startup, and API/worker graceful shutdown are now present. Bull Board requires an authenticated `admin` or `superadmin` and displays all three existing queues. The existing router is available on both `/api` and `/api/v1`.
|
|
|
|
Deployment additions include a hardened Node 22/Chromium/non-root Dockerfile with healthcheck, API/worker/MySQL/Redis Compose configuration, an Nginx reverse-proxy example, and a Gitea Actions CI baseline. Jest/Supertest tests now cover environment validation, liveness/readiness, errors/404, protected routes, Bull Board denial, and request correlation. The first test run exposed incompatible ESM-only `uuid@13`; it was safely pinned to CommonJS-compatible v11. `nodemon` moved to devDependencies.
|
|
|
|
Remaining foundation-adjacent work is intentionally deferred: production database baseline verification, distributed cron locking, full queue policy/idempotency, stronger documentation sessions, permission-router/role integration, and the Phase 1 authentication/ownership/security issues. The original audit above remains the historical baseline; statements such as “missing tests/Helmet/migrations” are superseded by this update and `Documentation/PHASE_0_FOUNDATION_STABILIZATION.md`.
|
|
|
|
## Phase 1 Completion Update
|
|
|
|
**Date:** 2026-09-03
|
|
**Authentication completion:** approximately **91%**.
|
|
**Revised Day 2 completion:** approximately **90%**.
|
|
|
|
Phase 1 replaced process-memory OTP and refresh sessions with Redis hash-only login challenges and durable MySQL auth-session families. OTP now uses `crypto.randomInt`, challenge UUIDs, TTL, atomic verification, bounded attempts, and no plaintext logging. Refresh tokens are opaque random values stored only by SHA-256 hash; row-locked transaction rotation detects replay and revokes the family. Access JWTs are short-lived, issuer/audience/algorithm constrained, and bound to `sub`, live session ID, and User token version. Middleware enforces current account state and session revocation.
|
|
|
|
New `auth_sessions`, `user_identities`, and `user_roles` models/tables support devices, Remember Me, Google/Apple stable subjects, and configurable roles. The User security migration adds token version/last login, expands canonical account types, and adds RBAC unique indexes. Permission routes are mounted behind SUPER_ADMIN, permission resolution now uses UserRole, and cache invalidation covers assignments/grants. Customer self-service update is allowlisted and ID-based mutation is privileged, closing the audited identity IDOR/mass-assignment path.
|
|
|
|
Auth endpoints now cover customer registration, verification/resend, password-to-OTP challenge, OTP completion, refresh rotation, current/all-device logout, forgot/reset/change password, Google, Apple, `/me`, and shared admin/rider compatibility flows. Both `/api` and `/api/v1` remain. Security-focused unit/integration tests were added without real providers/email/database/Redis.
|
|
|
|
Remaining identity work is operational: validate/deduplicate deployed RBAC data before migration, run staging MySQL/Redis concurrency tests, seed initial privileged assignments securely, configure provider audiences/mail, and design manual privileged OAuth linking and email change if required. Module 01 is now approximately 91%; migration/staging validation prevents claiming 100% production completion.
|
|
## Phase 5 Completion Update
|
|
|
|
Date: 2026-09-03. Inventory/reservation foundations, business pricing, promotions/coupons, and localized scheduled banners are implemented behind new permissions and a forward-only migration. Phase 5 adds 13 models, secured administration routes, public availability/banner projections, audit calls, a bounded expiry reconciliation cron, and Phase 6 pricing/reservation service boundaries. Module 05 is 85%, Module 07 is 78%, and Module 13 is 75%. Inventory is 90%, reservations 90%, business pricing 82%, promotions/coupons 78%, and banners 82%. Automated verification: 18 suites and 89 tests passed; syntax passed for 232 JavaScript files. Migration was not executed. Staging must precheck legacy stock/pricing/promotion/banner data, apply the migration, seed permissions/default warehouse, and test genuine MySQL locking plus cron behavior before Phase 6 production use.
|