Admin, Ops, System Config & Bulk Tooling¶
This document covers the operational backbone of the Mr. Mentor backend: the admin dashboard surface, dynamic runtime configuration (SystemConfig), the Excel/JSON bulk-upload pipeline for onboarding users, ad-hoc data cleanup of expired slots, low-level Redis inspection, the health-check endpoint, the Bull Board queue-monitoring UI, and unified issue/query reporting and triage. These are the tools the MAS operations and engineering teams use to run, observe, and repair the platform day to day.
Status: documented from source on this branch.
Overview¶
This domain is the "back office" of the backend. It does not belong to any single product (Mr. Mentor, Mr. Hire, MAS LMS, Sales CRM) — instead it provides cross-cutting operational capabilities that every product depends on:
- Admin dashboard operations — aggregate KPIs (connects, revenue, tokens, users, batch-wise breakdown) for the admin console, plus user/role management, meeting management, recordings, and query triage. Implemented in
src/controllers/admin.controller.ts+src/controllers/adminMas.controller.tsand mounted at/api/admin. - Dynamic system configuration — a key/value
SystemConfigtable that holds runtime config and feature flags read by this backend and, importantly, bymr-hire-backendon startup. Seesrc/services/SystemConfigService.ts. - Bulk upload tooling — a two-step Excel/JSON upload → preview/auto-map → validate → import pipeline for onboarding mentees and experts in bulk. See
src/services/BulkUploadService.tsandsrc/services/BulkUploadParserService.ts. - Data cleanup — manual and scheduled removal of expired, unbooked mentor slots and related housekeeping. See
src/controllers/cleanup.controller.ts+src/services/SlotCleanupService.ts. - Redis admin — raw key inspection and deletion for debugging. See
src/controllers/redis.controller.ts. - Health & monitoring — a liveness/readiness endpoint (
/api/health) plus the Bull Board UI at/admin/queuesfor inspecting BullMQ queues. - Issue/query reporting — a unified
Issuestable that captures bug reports, feedback, feature requests, and payment disputes from any product, with admin triage. Seesrc/services/IssuesService.ts.
Personas¶
| Persona | Role enum | What they do here |
|---|---|---|
| Platform admin | ADMIN, SUPERADMIN |
Dashboard, user management, bulk uploads, cleanup, config, issue triage |
| Operations / support | ADMIN |
Triage issues and payment queries, inspect Redis, run cleanup |
| DevOps / on-call engineer | (HTTP Basic for Bull Board) | Monitor queues, check /api/health |
| End user / student / mentor | USER, EXPERT (or anonymous) |
File issues via /api/issues; consume public config |
mr-hire-backend service |
service-to-service | Reads /api/system-config/:key on startup |
Key concepts & entities¶
| Concept | Meaning |
|---|---|
| SystemConfig | A single key/value row holding a runtime config value or feature flag. isActive acts as a soft on/off switch; getByKey only returns active rows. |
| Issue / Query | A user-submitted bug, feedback, feature request, "other", or payment dispute. "General queries" in the admin UI are all non-payment issues; "payment queries" are issueType = payment. Backed by the single Issues table. |
| Bulk upload field mapping | A { sourceField, targetField } pair that maps a spreadsheet column header to a known user/mentor field. Auto-suggested from header name heuristics, then confirmed by the admin. |
| Slot cleanup | Deletion of expired, unbooked mentor Slots rows and expiry of unaccepted meetings, run on a 15-minute schedule and triggerable manually. |
| Bull Board | A web UI bundled into the app at /admin/queues (HTTP Basic auth) that visualizes all BullMQ queues. |
| Warning | A student-discipline / risk record (warnings table). Mentioned here because it is an ops/admin-adjacent record, but it is owned primarily by the student-engagement domain. |
Main TypeORM entities¶
| Entity | File | Notes |
|---|---|---|
SystemConfig |
src/entities/SystemConfig.ts |
id (uuid PK), key (unique, indexed), value (text, nullable), label, description, isActive (default true), timestamps. |
Issues |
src/entities/Issues.ts |
id (int PK), optional userId FK → User, name, email, issueType enum, status enum, title, description, platform (default mr mentor), attachmentUrls (simple-array), imageUrl, payment fields (amount, paymentMethod enum, transactionId), notes, timestamps. |
Warning (mention) |
src/entities/Warning.ts |
id (uuid PK), studentId, type enum, severity enum, message, isActive, acknowledged, createdBy. Triage-adjacent but not owned by this domain. |
Bulk upload reads/writes User, Mentor, Token, and PromotionalToken rather than owning its own entity (see src/services/BulkUploadService.ts). Cleanup operates on Slots, RequestedSlot, and MeetingLogs via src/services/SlotCleanupService.ts.
Architecture¶
flowchart TD
subgraph Clients["Clients"]
FE["Admin Dashboard (mr-mentor-frontend)"]
USR["End user / student"]
HIRE["mr-hire-backend (service)"]
OPS["On-call engineer (browser)"]
end
subgraph Routes["Express routes"]
R_ADMIN["/api/admin/*"]
R_CFG["/api/system-config + /api/admin/system-config"]
R_BULK["/api/bulk-upload/*"]
R_CLEAN["/api/cleanup/*"]
R_REDIS["/api/redis/keys"]
R_HEALTH["/api/health"]
R_ISSUES["/api/issues"]
R_QUEUES["/admin/queues (Bull Board)"]
end
subgraph Controllers["Controllers"]
C_ADMIN["AdminController + AdminMasController"]
C_CFG["SystemConfigController"]
C_BULK["BulkUploadController"]
C_CLEAN["CleanupController"]
C_REDIS["RedisController"]
C_HEALTH["HealthController"]
C_ISSUES["IssuesController"]
end
subgraph Services["Services"]
S_DASH["AdminDashboardService"]
S_CFG["SystemConfigService"]
S_PARSE["BulkUploadParserService"]
S_BULK["BulkUploadService"]
S_CLEAN["SlotCleanupService"]
S_HEALTH["HealthService"]
S_ISSUES["IssuesService"]
S_QUEUE["QueueService (BullMQ)"]
end
subgraph Data["Data and infra"]
DB[("PostgreSQL via TypeORM")]
REDIS[("Redis")]
S3["AWS S3 (attachments)"]
end
FE --> R_ADMIN --> C_ADMIN --> S_DASH --> DB
FE --> R_CFG
USR --> R_ISSUES --> C_ISSUES --> S_ISSUES --> DB
HIRE --> R_CFG --> C_CFG --> S_CFG --> DB
C_CFG -->|"refresh-mr-hire"| HIRE
FE --> R_BULK --> C_BULK --> S_PARSE
C_BULK --> S_BULK --> DB
S_BULK -->|"onboarding email"| S_QUEUE
FE --> R_CLEAN --> C_CLEAN --> S_CLEAN --> DB
C_CLEAN -->|"schedule"| S_QUEUE --> REDIS
FE --> R_REDIS --> C_REDIS --> REDIS
OPS --> R_HEALTH --> C_HEALTH --> S_HEALTH
S_HEALTH --> DB
S_HEALTH --> REDIS
OPS --> R_QUEUES --> S_QUEUE --> REDIS
C_ISSUES -.->|"attachments"| S3
Data model¶
erDiagram
USER ||--o{ ISSUES : "files"
USER ||--o{ WARNING : "receives"
SYSTEM_CONFIG {
uuid id PK
varchar key UK
text value
varchar label
varchar description
boolean isActive
timestamp createdAt
timestamp updatedAt
}
ISSUES {
int id PK
uuid userId FK
varchar name
varchar email
enum issueType
enum status
varchar title
text description
varchar platform
text attachmentUrls
varchar imageUrl
decimal amount
enum paymentMethod
varchar transactionId
text notes
timestamp createdAt
timestamp updatedAt
}
WARNING {
uuid id PK
uuid studentId FK
enum type
enum severity
text message
boolean isActive
boolean acknowledged
uuid createdBy
timestamp createdAt
}
SystemConfig is standalone (no FKs). Bulk upload writes into User / Mentor / PromotionalToken (documented in the auth & token domains), not into a dedicated table.
Notable enums (src/entities/Issues.ts)¶
IssueType:bug,feedback,feature-request,other,paymentIssueStatus:open,in-progress,resolved,pending,paid,failedPaymentMethod:bank-transfer,upi,card,wallet
API surface¶
Paths below are the full mounted paths (mount prefix from src/routes/index.ts + path in the route file).
Issue reporting — src/routes/issues.routes.ts (mounted at /api)¶
| Method | Path | Auth/role | Purpose |
|---|---|---|---|
| GET | /api/issues |
none (public) | List issues (paginated). |
| GET | /api/issues/:id |
none (public) | Get one issue by id. |
| POST | /api/issues |
none (public) | Create an issue; platform taken from x-platform header. |
| PUT | /api/issues/:id |
none (public) | Update an issue. |
| DELETE | /api/issues/:id |
none (public) | Delete an issue. |
Issue triage via admin — src/routes/admin.routes.ts (mounted at /api/admin)¶
| Method | Path | Auth/role | Purpose |
|---|---|---|---|
| GET | /api/admin/issues |
auth + admin | List general (non-payment) queries, filtered/paginated. |
| GET | /api/admin/issues/:id |
auth + admin | Get one query. |
| POST | /api/admin/issues |
auth + admin | Create a general query. |
| PUT | /api/admin/issues/:id/status |
auth + admin | Update query status. |
| GET | /api/admin/queries/general |
auth + admin | Legacy alias of the issues list. |
| GET/POST/PUT | /api/admin/queries/general/* |
auth + admin | Legacy general-query aliases. |
| GET | /api/admin/queries/payment |
auth + admin | List payment-dispute issues. |
| GET | /api/admin/queries/payment/:id |
auth + admin | Get one payment query. |
| POST | /api/admin/queries/payment |
auth + admin | Create a payment query. |
| PUT | /api/admin/queries/payment/:id/status |
auth + admin | Update payment query status. |
Admin dashboard & user management — src/routes/admin.routes.ts (selected ops endpoints)¶
| Method | Path | Auth/role | Purpose |
|---|---|---|---|
| GET | /api/admin/dashboard |
auth + admin | Full aggregate dashboard payload (legacy single call). |
| GET | /api/admin/dashboard/connects |
auth + admin | Connects KPI panel. |
| GET | /api/admin/dashboard/revenue |
auth + admin | Revenue KPI panel. |
| GET | /api/admin/dashboard/tokens |
auth + admin | Token economy KPI panel. |
| GET | /api/admin/dashboard/users |
auth + admin | Users KPI panel. |
| GET | /api/admin/dashboard/batch-wise |
auth + admin | Batch-wise breakdown. |
| GET | /api/admin/dashboard/batch/:batchName/students |
auth + admin | Students in a batch. |
| POST | /api/admin/dashboard/refresh-kpi |
auth + admin | Force a KPI recompute. |
| GET | /api/admin/users |
auth + admin | List all users. |
| GET | /api/admin/users/by-email |
auth + admin | Lookup by exact email. |
| GET | /api/admin/users/search-by-email |
auth + admin | Search users by email. |
| GET | /api/admin/users/:id |
auth + admin | Get user by id. |
| PUT | /api/admin/users/:id |
auth + admin | Update user. |
| PUT | /api/admin/users/:id/role |
auth + admin | Change user role. |
| DELETE | /api/admin/users/:id |
auth + admin | Remove user. |
| POST | /api/admin/users/:id/block |
auth + admin | Block user. |
| POST | /api/admin/users/:id/unblock |
auth + admin | Unblock user. |
| POST | /api/admin/experts /admins /students /sales /sales-head /external-hrs /batch-leads /community-managers /super-mentors |
auth + admin | Create users of each role. |
The
/api/adminrouter also hosts large MAS-LMS, AI-classroom, WhatsApp-manager, notifications, course-plan, and LLM-gateway sub-trees. Those are documented in their own feature docs; only the operational subset is listed above.
System config — src/routes/systemConfig.routes.ts (mounted at /api)¶
| Method | Path | Auth/role | Purpose |
|---|---|---|---|
| GET | /api/system-config/enabled-call-providers |
none (public) | HR call-provider flags (specific route, declared before :key). |
| GET | /api/system-config/:key |
none (public) | Read one active config value (consumed by mr-hire-backend). |
| GET | /api/admin/system-config |
auth only | List all config rows. |
| POST | /api/admin/system-config |
auth only | Upsert a config by key. |
| PUT | /api/admin/system-config/:id |
auth only | Update a config row by id. |
| DELETE | /api/admin/system-config/:id |
auth only | Delete a config row. |
| POST | /api/admin/system-config/refresh-mr-hire |
auth only | Tell mr-hire-backend to refresh its call-provider cache. |
Bulk upload — src/routes/bulkUpload.routes.ts (mounted at /api/bulk-upload)¶
| Method | Path | Auth/role | Purpose |
|---|---|---|---|
| POST | /api/bulk-upload/preview |
auth + admin | Upload file, parse, return detected fields + suggested mappings + sample. |
| POST | /api/bulk-upload/process |
auth + admin | Re-upload file with mappings, validate, import users. |
| GET | /api/bulk-upload/fields |
auth + admin | List mappable fields for a userType. |
| GET | /api/bulk-upload/template |
auth + admin | Download a sample .xlsx or .json template. |
Cleanup — src/routes/cleanup.routes.ts (mounted at /api/cleanup)¶
| Method | Path | Auth/role | Purpose |
|---|---|---|---|
| DELETE | /api/cleanup/slots |
auth + admin | Run cleanup of expired unbooked slots synchronously. |
| GET | /api/cleanup/statistics |
auth + admin | Overall slot statistics. |
| GET | /api/cleanup/statistics/:mentorId |
auth + admin | Per-mentor slot statistics. |
| POST | /api/cleanup/schedule |
auth + admin | Enqueue a cleanup job onto the queue. |
| GET | /api/cleanup/slots/:filter |
auth + admin | List slots by filter (all, available, booked, future, expired, expiredUnbooked). |
Redis admin — src/routes/redis.routes.ts (mounted at /api/redis)¶
| Method | Path | Auth/role | Purpose |
|---|---|---|---|
| GET | /api/redis/keys |
none (see gotchas) | Dump all keys and values. |
| DELETE | /api/redis/keys/:key |
none (see gotchas) | Delete a key. |
Health — src/routes/health.routes.ts (mounted at /api)¶
| Method | Path | Auth/role | Purpose |
|---|---|---|---|
| GET | /api/health |
none (public) | Liveness/readiness: DB + Redis status, uptime, env. Returns 503 if unhealthy. |
Queue monitoring — src/routes/bullBoard.routes.ts (mounted at /)¶
| Method | Path | Auth/role | Purpose |
|---|---|---|---|
| ALL | /admin/queues |
HTTP Basic (BULL_BOARD_USERNAME / BULL_BOARD_PASSWORD) |
Bull Board UI for all BullMQ queues. |
User journeys¶
1. Bulk-upload mentees/experts (two-step preview → process)¶
The headline ops journey. An admin uploads a spreadsheet of mentees or experts. Step 1 parses the file and auto-suggests column mappings. The admin confirms/edits the mappings in the UI, then step 2 re-submits the same file plus the confirmed mappings to actually create the users. Each row is created in its own transaction; failures are collected per-row rather than aborting the batch.
sequenceDiagram
participant FE as Admin UI
participant API as BulkUploadController
participant Parse as BulkUploadParserService
participant Bulk as BulkUploadService
participant DB as PostgreSQL
participant Q as QueueService
Note over FE,API: Step 1 - preview
FE->>API: POST /api/bulk-upload/preview with file and userType
API->>API: multer validates type and size up to 10MB
API->>Parse: parseExcelFile or parseJsonFile
Parse-->>API: rows and headers
API->>Parse: generatePreview
Parse-->>API: detected fields, suggested mappings, sample rows
API-->>FE: preview payload
Note over FE,API: admin edits mappings then submits
FE->>API: POST /api/bulk-upload/process with file, userType, fieldMappings
API->>Parse: validateMappings requires email mapped
alt email not mapped
Parse-->>API: invalid
API-->>FE: 400 invalid field mappings
else valid
API->>Parse: applyMappings transforms rows
API->>API: apply defaultTokens to mentees when unset
API->>Bulk: validateBulkData
API->>Bulk: processBulkUpload userType and rows
loop each row
Bulk->>DB: check email exists
alt duplicate or missing required
Bulk->>Bulk: record row error and continue
else new
Bulk->>DB: insert User in a transaction
opt expert
Bulk->>DB: insert Mentor profile
Bulk->>Q: enqueue mentor-onboarding email after commit
end
opt mentee with meetTokens
Bulk->>DB: insert PromotionalToken
end
end
end
Bulk-->>API: successCount, failedCount, per-row errors
API-->>FE: result summary 200 or 400
end
Key details from src/services/BulkUploadService.ts:
- Passwords are hashed with bcrypt; if no password column is mapped, a random 12-char password is generated.
- Experts require company, role, and institute or the row fails validation.
- Expert onboarding emails are queued via QueueService.addEmailJob with a 2s delay, only after the transaction commits.
- Mentee meet-tokens are stored as a PromotionalToken (not a base Token), expiring 1 year out by default.
2. Dynamic system config — set a flag, then read it from another service¶
An admin writes a runtime config/feature flag through the admin endpoint. mr-hire-backend (or this backend) later reads it through the public :key endpoint. For call-provider settings the admin can also trigger a cache refresh in mr-hire-backend.
sequenceDiagram
participant FE as Admin UI
participant API as SystemConfigController
participant Svc as SystemConfigService
participant DB as PostgreSQL
participant Hire as mr-hire-backend
FE->>API: POST /api/admin/system-config key and value
API->>API: require key and value
API->>Svc: upsert key value label description
Svc->>DB: find by key
alt exists
Svc->>DB: update value
else new
Svc->>DB: insert row with label default key
end
Svc-->>API: saved config
API-->>FE: 200 config saved
opt refresh hire cache
FE->>API: POST /api/admin/system-config/refresh-mr-hire
API->>Hire: POST call-provider refresh timeout 5s
alt hire reachable
Hire-->>API: ok
API-->>FE: 200 cache refreshed
else hire down
API-->>FE: 200 saved, refresh failed non-critical
end
end
Note over Hire,DB: later, on its own startup
Hire->>API: GET /api/system-config/:key
API->>Svc: getByKey only active rows
Svc->>DB: find key and isActive true
alt found
Svc-->>API: config
API-->>Hire: 200 value
else missing or inactive
API-->>Hire: 404 config not found
end
3. Expired-slot cleanup — manual and scheduled¶
Mentor slots that expire without ever being booked accumulate noise. An admin can run cleanup synchronously, or enqueue it as a background job. The same logic runs automatically every 15 minutes via the scheduled cleanup queue.
sequenceDiagram
participant FE as Admin UI
participant API as CleanupController
participant Clean as SlotCleanupService
participant Q as QueueService
participant W as cleanup.worker
participant DB as PostgreSQL
alt run now
FE->>API: DELETE /api/cleanup/slots
API->>Clean: cleanupExpiredUnbookedSlots
Clean->>DB: delete expired unbooked Slots
Clean-->>API: deletedCount and details
API-->>FE: 200 result
else enqueue
FE->>API: POST /api/cleanup/schedule
API->>Q: addCleanupJob type cleanupExpiredSlots
Q-->>API: queued
API-->>FE: 200 job added
Q->>W: deliver job
W->>Clean: cleanupExpiredUnbookedSlots
Clean->>DB: delete expired unbooked Slots
end
Note over Q,W: also runs every 15 minutes from scheduleSlotCleanup on startup
Inspection helpers: GET /api/cleanup/statistics and /api/cleanup/slots/:filter let an admin preview what would be affected before deleting.
4. Issue reporting and admin triage¶
Any user (or anonymous visitor) files an issue. The x-platform header tags which product it came from. Admins later list, filter, and resolve issues; payment disputes are a special issueType.
sequenceDiagram
participant U as User or visitor
participant API as IssuesController
participant Svc as IssuesService
participant DB as PostgreSQL
participant Admin as Admin UI
participant AC as AdminController
U->>API: POST /api/issues name email issueType description
API->>API: set platform from x-platform header
alt missing required fields
API-->>U: 400 fields required
else ok
API->>Svc: createIssue
Svc->>DB: insert Issues row status open
Svc-->>API: saved issue
API-->>U: 201 created
end
Note over Admin,DB: triage
Admin->>AC: GET /api/admin/issues filters and pagination
AC->>Svc: getGeneralIssues excludes payment type
Svc->>DB: query with filters join user
Svc-->>AC: issues and total
AC-->>Admin: list
Admin->>AC: PUT /api/admin/issues/:id/status resolved
AC->>Svc: updateIssueStatus
Svc->>DB: save new status
Svc-->>AC: updated
AC-->>Admin: 200 updated
5. Health check and queue monitoring¶
On-call tooling and load balancers hit /api/health; engineers open Bull Board for queue depth and failed jobs.
sequenceDiagram
participant LB as Load balancer or on-call
participant API as HealthController
participant H as HealthService
participant DB as PostgreSQL
participant R as Redis
participant Ops as Engineer
participant BB as Bull Board
LB->>API: GET /api/health
API->>H: getHealthStatus
H->>DB: isConnected
H->>R: client status ready
H-->>API: status, uptime, env, db, redis
API->>H: isHealthy
alt healthy
API-->>LB: 200 data
else db or redis down
API-->>LB: 503 service unavailable
end
Ops->>BB: GET /admin/queues
BB->>BB: HTTP Basic auth check
alt bad credentials
BB-->>Ops: 401 authenticate
else ok
BB->>R: read BullMQ queue state
BB-->>Ops: queue dashboard
end
6. Redis inspection (debugging)¶
sequenceDiagram
participant Ops as Admin or engineer
participant API as RedisController
participant R as Redis
Ops->>API: GET /api/redis/keys
API->>R: getAllKeysAndValues
R-->>API: keys and values
API-->>Ops: 200 data
Ops->>API: DELETE /api/redis/keys/:key
API->>R: delete key
alt key existed
R-->>API: count 1
API-->>Ops: 200 deleted
else missing
R-->>API: count 0
API-->>Ops: 404 key not found
end
Background jobs & async¶
This domain both consumes and triggers BullMQ work. Queues are created by QueueService (singleton) and surfaced in Bull Board.
| Queue / worker | Trigger | Schedule | Source |
|---|---|---|---|
cleanupQueue → cleanup.worker |
POST /api/cleanup/schedule and startup scheduler |
scheduleSlotCleanup() runs every 15 minutes (src/index.ts) |
src/services/SlotCleanupService.ts |
kpiQueue → kpi.worker |
POST /api/admin/dashboard/refresh-kpi and startup scheduler |
scheduleKpiCalculation() every 15 minutes |
admin dashboard |
emailQueue → email.worker |
bulk-upload expert onboarding (addEmailJob, 2s delay) |
on demand | src/services/BulkUploadService.ts |
- Bull Board mounts the BullMQ adapters for every queue returned by
QueueService.getQueues()at/admin/queues, behind HTTP Basic auth. Board title and logo are configured insrc/routes/bullBoard.routes.ts. - There are no inbound webhooks or Socket.IO events specific to this domain; the bulk-upload
processstep is synchronous (it does not enqueue the user creation itself, only the follow-up email).
See Background jobs & queues for the full queue/worker catalog.
External integrations¶
| Integration | Where | Env vars | Failure / fallback |
|---|---|---|---|
mr-hire-backend |
SystemConfigController.refreshMrHireProvider POSTs to /call-provider/refresh |
MR_HIRE_BACKEND_URL (default http://localhost:8001) |
5s timeout; on failure responds 200 with a "refresh failed (non-critical)" message so the config save is never blocked. |
| AWS S3 | Issue attachmentUrls / imageUrl are pre-uploaded URLs |
AWS_* (see backend env) |
URLs stored as-is; no upload happens inside the issues flow. |
| Redis | Health check, Redis admin, BullMQ backing store | REDIS_HOST, REDIS_PORT |
Health returns 503 when Redis status is not ready. |
| PostgreSQL | All persistence | DB_* |
Health returns 503 when DB not connected. |
xlsx library |
Bulk parse + template generation | n/a | Parse errors surface as 500 with the parser message. |
Feature flags / runtime config¶
SystemConfig is the project's feature-flag and runtime-config mechanism. Flags are plain key/value rows; isActive=false hides a key from the public getByKey reader (a soft kill-switch). /api/system-config/enabled-call-providers is a specialised reader handled by HrCallConfigController and is intentionally declared before the :key route to avoid being shadowed.
Status lifecycles¶
Issue status¶
stateDiagram-v2
[*] --> open
open --> in_progress
in_progress --> resolved
open --> resolved
resolved --> [*]
state "payment issue track" as pay {
[*] --> pending
pending --> paid
pending --> failed
failed --> pending
}
IssueStatus is a single enum shared by both general issues (open → in-progress → resolved) and payment disputes (pending → paid / failed). The code does not enforce the transitions; updateGeneralQueryStatus only validates that the new value is a member of the enum.
SystemConfig active state¶
stateDiagram-v2
[*] --> active
active --> inactive : "set isActive false"
inactive --> active : "set isActive true"
active --> [*] : "delete by id"
inactive --> [*] : "delete by id"
note right of inactive
getByKey returns null
when not active
end note
Edge cases, limits & gotchas¶
- Hardening note (internal). A security/hardening observation for this area is tracked in the team's private notes (
internal/security-and-hardening-notes.md) and is intentionally not published on this site. - Hardening note (internal). A security/hardening observation for this area is tracked in the team's private notes (
internal/security-and-hardening-notes.md) and is intentionally not published on this site. - Hardening note (internal). A security/hardening observation for this area is tracked in the team's private notes (
internal/security-and-hardening-notes.md) and is intentionally not published on this site. - Bulk upload is two uploads, not one. Both
/previewand/processrequire the file in themultipart/form-databody;/processdoes not reuse the previously parsed file.fieldMappingsarrives as a JSON string (FormData) and is parsed server-side. - Per-row isolation, not all-or-nothing.
processBulkUploadruns each user creation in its ownqueryRunnertransaction; a duplicate email or missing required field fails that row only and is reported inerrors[]. The endpoint returns 200 if at least one row succeeded, else 400. - File limits. Multer caps uploads at 10 MB and accepts only
.xlsx,.xls,.json(by mimetype or extension). emailis the only mandatory mapping.validateMappingsonly requiresemail; expert-specific requirements (company,role,institute) are enforced later inBulkUploadService.createExpertand surface as row errors.graduationYearsanitation. Only accepted when it parses to an int between 1900 and 2100 (applyMappings); otherwise dropped silently.getIssueByIdcasts the id toNumber. TheIssuesPK is an int; passing a non-numeric id yields a NaN lookup (no match) rather than a validation error.- Multi-platform tagging. New issues default
platformto thex-platformheader value, falling back tomr mentor. Admin list endpoints can filter byplatform,userRole,status,type,resolution, date range, and free-text search. refresh-mr-hirenever fails loud. Even on a network error it returns HTTP 200 so the admin's config save is treated as successful.- Cleanup
DELETE /slotsis synchronous and destructive. It deletes rows immediately; useGET /slots/:filterfirst to preview. Scheduled cleanup runs the same logic every 15 minutes regardless. Warningis not owned here. It is referenced for completeness; its lifecycle (acknowledge/resolve) belongs to the student-engagement domain.
Related docs¶
- Background jobs & queues — BullMQ queues, workers, schedules.
- Observability & runbooks — health checks, Bull Board, on-call procedures.
- Auth & users — User entity, roles, and how bulk-created users log in.
- Token economy —
TokenandPromotionalTokencreated during bulk upload. - Mentorship & slots —
Slotsentity that cleanup operates on.