Skip to content

Job-Scheduler-API · Repository map + Cron catalog (branch: prod)

job-scheduler-api เป็น NestJS 9 headless cron runner — มี business logic จริงแค่ 1 job: ทุกวัน 17:00 น. เรียก POST {INCIDENT_SERVER}incident-management-api/crontab/summary

ชื่อ service + .env (BASE_PATH=benefit-api/, DB_NAME=benefit) เป็น copy-paste จาก benefit-api — ไม่สะท้อนหน้าที่จริง


Identity

ItemValue
Canonical branchprod (31 tracked files)
StackNestJS 9 + @nestjs/schedule + axios + Passport JWT (unused)
Port9900
TimezoneAsia/Bangkok (Docker volume)
HTTP surfaceว่างAppController ไม่มี route

Module map

AppModule
├── ConfigModule.forRoot
├── ScheduleModule.forRoot()     ← enables @Cron
├── IncidentsModule
│   └── IncidentsService         ← sole business logic
├── AppController                ← EMPTY
├── AppService                   ← EMPTY
└── JwtStrategy                  ← template residue

IncidentsModule ไม่มี controller — cron-only


Cron catalog (authoritative)

JobScheduleMeaningFile:lineAction
incidentSummaryCronExpression.EVERY_DAY_AT_5PM0 17 * * *Daily 17:00 Bangkokincidents.service.ts:16-30POST {INCIDENT_SERVER}incident-management-api/crontab/summary — no body, no auth

History: commit เคยใช้ @Cron('* * 17 * * *') (ทุกนาทีในชั่วโมง 17) + GET — แก้เป็น daily 5PM + POST

Unmerged — branch origin/add-cronjob-meeting only

JobScheduleAction
meeting()0 */15 * * * * (every 15 min)GET {meetingServer}meeting/secure/corn-email

ยังไม่ merge เข้า prod


Full trace — incidentSummary

17:00 Bangkok
  → IncidentsService.incidentSummary()
  → config.get('incidentServer')  // INCIDENT_SERVER=https://vtrcapi.redcross.or.th/
  → axios.post(`${url}incident-management-api/crontab/summary`)  // NO auth headers
  → vtrc-api nginx proxies /incident-management-api/ → localhost:7201
  → I3GatewayLogger.info(response.data) → ./logs/{DD-MM-YYYY}.log
  → on error: throw BadRequestException (unusual for background cron)

Evidence — job-scheduler-api/src/modules/incidents/incidents.service.ts:16-30 (branch: prod)

Downstream: incident-management-api repo ไม่อยู่ใน workspace — ยืนยันได้แค่ nginx upstream ที่ vtrc-api/nginx/default.conf:116-123


Dead DB wiring

LayerStatus
.env DB_* (MSSQL, DB_NAME=benefit)Configured แต่ never consumed
configuration.ts db.*Loaded into ConfigService แต่ไม่มี config.get('db.*')
TypeOrmModuleImported ใน app.module.ts:6 แต่ ไม่อยู่ใน imports array
Commit 82cab98 "remove db"เคยมี TypeOrmModule.forRootAsync (mysql + synchronize:true) — ลบแล้ว
npm deps typeorm, mysql2Zero runtime usage
Dead importsInjectEntityManager, EntityManager ใน incidents.service.ts:3-4

Also unused env: VTRC_SERVER, VTRC_COMMON_SERVER


Auth / HTTP surface

SurfaceBehavior
HTTP routesNone — empty AppController
Global JwtAuthGuardApplied (main.ts:27) — irrelevant today
@Public()Defined แต่ไม่เคยใช้
Outbound cron POSTNo auth — bare axios
Swagger{BASE_PATH}docs = benefit-api/docs (misleading)

Security findings

SEC-JOBSCHED-01 · .env tracked in git with secrets

ที่: job-scheduler-api/.env (committed) — MSSQL sa password + SECRET_KEY

Impact: anyone with repo read access ได้ production DB credentials

Remediation: rotate + .gitignore + git filter-repo


SEC-JOBSCHED-02 · Unauthenticated outbound cron POST

ที่: incidents.service.ts:20-21

Impact: endpoint /crontab/summary ถูกเรียกโดยไม่มี auth — ถ้า network เปิด ใครก็ trigger ได้

Remediation: เพิ่ม shared secret header หรือ mTLS; ฝั่ง incident-management-api ต้อง verify


Other findings

IDSeverityFinding
SEC-JOBSCHED-03🟡CORS origin: '*' (main.ts:29-33)
SEC-JOBSCHED-04🟡JwtAuthGuard logs full user payload
QUAL-JOBSCHED-01🟢Committed log file logs/30-01-2023.log
QUAL-JOBSCHED-02🟢Broken e2e expects Hello World!
OBS-JOBSCHED-01🟢Dockerfile EXPOSE 3000 vs port 9900

Health Scorecard

Dimensionสถานะเหตุผล
Job correctness🟡1 job ทำงาน; history ของ schedule bug
Secrets🔴.env committed
Outbound auth🔴Cron POST ไม่มี auth
Dead code🔴TypeORM/JWT/empty controller ทั้งหมด
Naming identity🔴benefit-api copy-paste
Observability🟡File log มี; ไม่มี health/metrics
Test coverage🔴Smoke only + broken e2e

คะแนนรวม: 0 🟢 / 2 🟡 / 5 🔴


Modernization priority

  1. Rotate secrets + ลบ .env จาก git
  2. เพิ่ม auth ให้ outbound cron + ฝั่ง receiver
  3. ลบ TypeORM/mysql2/JWT dead deps
  4. แก้ identity (BASE_PATH, project name)
  5. เพิ่ม /health @Public() endpoint
  6. ตัดสินใจ merge meeting cron จาก add-cronjob-meeting หรือปิด branch

กลับไป index