mega-framework 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (322) hide show
  1. package/.env +127 -0
  2. package/.env.example +186 -0
  3. package/.prettierrc.json +8 -0
  4. package/CHANGELOG.md +259 -0
  5. package/LICENSE +21 -0
  6. package/README.md +153 -0
  7. package/bin/mega-ws-hub.js +15 -0
  8. package/bin/mega.js +38 -0
  9. package/docker-compose.yml +201 -0
  10. package/eslint.config.js +57 -0
  11. package/infra/otel-collector-config.yaml +43 -0
  12. package/jsconfig.json +18 -0
  13. package/package.json +121 -0
  14. package/sample/crud/.env +18 -0
  15. package/sample/crud/.env.example +50 -0
  16. package/sample/crud/README.md +85 -0
  17. package/sample/crud/apps/main/app.config.js +114 -0
  18. package/sample/crud/apps/main/channels/chat-bus.js +115 -0
  19. package/sample/crud/apps/main/channels/chat-channel.js +145 -0
  20. package/sample/crud/apps/main/controllers/auth-controller.js +144 -0
  21. package/sample/crud/apps/main/controllers/cron-controller.js +34 -0
  22. package/sample/crud/apps/main/controllers/guide-controller.js +37 -0
  23. package/sample/crud/apps/main/controllers/jobs-controller.js +43 -0
  24. package/sample/crud/apps/main/controllers/logs-controller.js +35 -0
  25. package/sample/crud/apps/main/controllers/metrics-controller.js +22 -0
  26. package/sample/crud/apps/main/controllers/note-controller.js +116 -0
  27. package/sample/crud/apps/main/controllers/perf-controller.js +38 -0
  28. package/sample/crud/apps/main/controllers/redis-controller.js +36 -0
  29. package/sample/crud/apps/main/controllers/tracing-controller.js +43 -0
  30. package/sample/crud/apps/main/controllers/upload-controller.js +98 -0
  31. package/sample/crud/apps/main/controllers/user-controller.js +34 -0
  32. package/sample/crud/apps/main/controllers/web-controller.js +137 -0
  33. package/sample/crud/apps/main/controllers/worker-controller.js +57 -0
  34. package/sample/crud/apps/main/controllers/ws-controller.js +29 -0
  35. package/sample/crud/apps/main/jobs/email-job.js +72 -0
  36. package/sample/crud/apps/main/locales/client/en.json +3 -0
  37. package/sample/crud/apps/main/locales/client/ko.json +3 -0
  38. package/sample/crud/apps/main/locales/server/en.json +316 -0
  39. package/sample/crud/apps/main/locales/server/ko.json +316 -0
  40. package/sample/crud/apps/main/middleware/web-auth.js +40 -0
  41. package/sample/crud/apps/main/middleware/ws-auth.js +48 -0
  42. package/sample/crud/apps/main/migrations/20260606000001-create-users.js +27 -0
  43. package/sample/crud/apps/main/migrations/20260606000002-add-auth-to-users.js +30 -0
  44. package/sample/crud/apps/main/models/note.js +71 -0
  45. package/sample/crud/apps/main/models/user.js +86 -0
  46. package/sample/crud/apps/main/public/css/app.css +101 -0
  47. package/sample/crud/apps/main/public/css/guide.css +137 -0
  48. package/sample/crud/apps/main/public/js/app.js +54 -0
  49. package/sample/crud/apps/main/public/js/perf.js +129 -0
  50. package/sample/crud/apps/main/public/js/theme-init.js +12 -0
  51. package/sample/crud/apps/main/public/js/upload-demo.js +63 -0
  52. package/sample/crud/apps/main/public/js/worker-demo.js +92 -0
  53. package/sample/crud/apps/main/public/js/ws-chat.js +161 -0
  54. package/sample/crud/apps/main/public/vendor/bootstrap/bootstrap.bundle.min.js +7 -0
  55. package/sample/crud/apps/main/public/vendor/bootstrap/bootstrap.min.css +6 -0
  56. package/sample/crud/apps/main/public/vendor/highlight/github-dark.css +109 -0
  57. package/sample/crud/apps/main/public/vendor/highlight/github.css +118 -0
  58. package/sample/crud/apps/main/public/vendor/mega-client-wasm/README.md +19 -0
  59. package/sample/crud/apps/main/public/vendor/mega-client-wasm/mega_client_wasm.d.ts +196 -0
  60. package/sample/crud/apps/main/public/vendor/mega-client-wasm/mega_client_wasm.js +1187 -0
  61. package/sample/crud/apps/main/public/vendor/mega-client-wasm/mega_client_wasm_bg.wasm +0 -0
  62. package/sample/crud/apps/main/routes/auth.js +15 -0
  63. package/sample/crud/apps/main/routes/cron.js +14 -0
  64. package/sample/crud/apps/main/routes/guide.js +25 -0
  65. package/sample/crud/apps/main/routes/jobs.js +14 -0
  66. package/sample/crud/apps/main/routes/logs.js +28 -0
  67. package/sample/crud/apps/main/routes/metrics.js +13 -0
  68. package/sample/crud/apps/main/routes/notes.js +19 -0
  69. package/sample/crud/apps/main/routes/perf.js +47 -0
  70. package/sample/crud/apps/main/routes/redis.js +14 -0
  71. package/sample/crud/apps/main/routes/tracing.js +14 -0
  72. package/sample/crud/apps/main/routes/upload.js +16 -0
  73. package/sample/crud/apps/main/routes/users.js +54 -0
  74. package/sample/crud/apps/main/routes/web.js +23 -0
  75. package/sample/crud/apps/main/routes/worker.js +15 -0
  76. package/sample/crud/apps/main/routes/ws.js +30 -0
  77. package/sample/crud/apps/main/schedules/cron-counter-schedule.js +30 -0
  78. package/sample/crud/apps/main/services/auth-service.js +74 -0
  79. package/sample/crud/apps/main/services/cron-demo-service.js +66 -0
  80. package/sample/crud/apps/main/services/guide-service.js +145 -0
  81. package/sample/crud/apps/main/services/jobs-demo-service.js +83 -0
  82. package/sample/crud/apps/main/services/logs-demo-service.js +59 -0
  83. package/sample/crud/apps/main/services/metrics-demo-service.js +144 -0
  84. package/sample/crud/apps/main/services/note-service.js +75 -0
  85. package/sample/crud/apps/main/services/perf-service.js +302 -0
  86. package/sample/crud/apps/main/services/redis-demo-service.js +75 -0
  87. package/sample/crud/apps/main/services/tracing-demo-service.js +69 -0
  88. package/sample/crud/apps/main/services/upload-demo-service.js +48 -0
  89. package/sample/crud/apps/main/services/user-service.js +65 -0
  90. package/sample/crud/apps/main/views/auth/login.ejs +57 -0
  91. package/sample/crud/apps/main/views/auth/register.ejs +71 -0
  92. package/sample/crud/apps/main/views/cron/index.ejs +92 -0
  93. package/sample/crud/apps/main/views/guide/index.ejs +24 -0
  94. package/sample/crud/apps/main/views/guide/page.ejs +64 -0
  95. package/sample/crud/apps/main/views/home.ejs +82 -0
  96. package/sample/crud/apps/main/views/jobs/index.ejs +113 -0
  97. package/sample/crud/apps/main/views/layouts/main.ejs +112 -0
  98. package/sample/crud/apps/main/views/logs/index.ejs +80 -0
  99. package/sample/crud/apps/main/views/metrics/index.ejs +123 -0
  100. package/sample/crud/apps/main/views/notes/edit.ejs +45 -0
  101. package/sample/crud/apps/main/views/notes/list.ejs +74 -0
  102. package/sample/crud/apps/main/views/notes/new.ejs +45 -0
  103. package/sample/crud/apps/main/views/perf/index.ejs +90 -0
  104. package/sample/crud/apps/main/views/redis/index.ejs +65 -0
  105. package/sample/crud/apps/main/views/tracing/index.ejs +106 -0
  106. package/sample/crud/apps/main/views/upload/index.ejs +79 -0
  107. package/sample/crud/apps/main/views/users/edit.ejs +48 -0
  108. package/sample/crud/apps/main/views/users/list.ejs +81 -0
  109. package/sample/crud/apps/main/views/users/new.ejs +48 -0
  110. package/sample/crud/apps/main/views/worker/index.ejs +70 -0
  111. package/sample/crud/apps/main/views/ws/index.ejs +62 -0
  112. package/sample/crud/apps/main/workers/hash-worker.js +17 -0
  113. package/sample/crud/apps/main/workers/hash.task.js +22 -0
  114. package/sample/crud/ecosystem.config.cjs +9 -0
  115. package/sample/crud/mega.config.js +105 -0
  116. package/sample/crud/package-lock.json +5665 -0
  117. package/sample/crud/package.json +28 -0
  118. package/sample/crud/test/apps/main/auth-flow.integration.test.js +177 -0
  119. package/sample/crud/test/apps/main/auth-service.test.js +93 -0
  120. package/sample/crud/test/apps/main/chat-bus.test.js +101 -0
  121. package/sample/crud/test/apps/main/chat-channel.test.js +144 -0
  122. package/sample/crud/test/apps/main/cron-demo-service.test.js +93 -0
  123. package/sample/crud/test/apps/main/demo-flow.integration.test.js +386 -0
  124. package/sample/crud/test/apps/main/email-job.test.js +76 -0
  125. package/sample/crud/test/apps/main/guide-service.test.js +68 -0
  126. package/sample/crud/test/apps/main/hash-task.test.js +30 -0
  127. package/sample/crud/test/apps/main/jobs-demo-service.test.js +88 -0
  128. package/sample/crud/test/apps/main/logs-demo-service.test.js +85 -0
  129. package/sample/crud/test/apps/main/metrics-demo-service.test.js +90 -0
  130. package/sample/crud/test/apps/main/note-service.test.js +68 -0
  131. package/sample/crud/test/apps/main/perf-service.test.js +121 -0
  132. package/sample/crud/test/apps/main/perf.integration.test.js +202 -0
  133. package/sample/crud/test/apps/main/redis-demo-service.test.js +98 -0
  134. package/sample/crud/test/apps/main/tracing-demo-service.test.js +90 -0
  135. package/sample/crud/test/apps/main/upload-demo-service.test.js +61 -0
  136. package/sample/crud/test/apps/main/user-service.test.js +65 -0
  137. package/sample/crud/test/apps/main/ws-chat.integration.test.js +232 -0
  138. package/sample/crud/vitest.config.js +8 -0
  139. package/sample/crud/yarn.lock +2142 -0
  140. package/sample/simple/.env.example +15 -0
  141. package/sample/simple/README.md +52 -0
  142. package/sample/simple/apps/main/app.config.js +35 -0
  143. package/sample/simple/apps/main/controllers/pages-controller.js +22 -0
  144. package/sample/simple/apps/main/locales/client/en.json +3 -0
  145. package/sample/simple/apps/main/locales/client/ko.json +3 -0
  146. package/sample/simple/apps/main/locales/server/en.json +23 -0
  147. package/sample/simple/apps/main/locales/server/ko.json +23 -0
  148. package/sample/simple/apps/main/public/css/app.css +101 -0
  149. package/sample/simple/apps/main/public/hello.txt +1 -0
  150. package/sample/simple/apps/main/public/js/app.js +54 -0
  151. package/sample/simple/apps/main/public/js/theme-init.js +12 -0
  152. package/sample/simple/apps/main/public/vendor/bootstrap/bootstrap.bundle.min.js +7 -0
  153. package/sample/simple/apps/main/public/vendor/bootstrap/bootstrap.min.css +6 -0
  154. package/sample/simple/apps/main/routes/index.js +9 -0
  155. package/sample/simple/apps/main/routes/pages.js +12 -0
  156. package/sample/simple/apps/main/views/index.ejs +56 -0
  157. package/sample/simple/apps/main/views/layouts/main.ejs +74 -0
  158. package/sample/simple/ecosystem.config.cjs +10 -0
  159. package/sample/simple/mega.config.js +27 -0
  160. package/sample/simple/package-lock.json +1851 -0
  161. package/sample/simple/package.json +25 -0
  162. package/sample/simple/test/apps/main/index.test.js +13 -0
  163. package/sample/simple/vitest.config.js +8 -0
  164. package/src/adapters/adapter-manager.js +305 -0
  165. package/src/adapters/adapter-options.js +208 -0
  166. package/src/adapters/file-adapter.js +350 -0
  167. package/src/adapters/file-session-adapter.js +363 -0
  168. package/src/adapters/index.js +38 -0
  169. package/src/adapters/maria-adapter.js +425 -0
  170. package/src/adapters/mega-adapter.js +511 -0
  171. package/src/adapters/mega-bus-adapter.js +81 -0
  172. package/src/adapters/mega-cache-adapter.js +94 -0
  173. package/src/adapters/mega-db-adapter.js +72 -0
  174. package/src/adapters/mega-lock-adapter.js +118 -0
  175. package/src/adapters/mega-log-sink-adapter.js +46 -0
  176. package/src/adapters/mega-session-adapter.js +72 -0
  177. package/src/adapters/mongo-adapter.js +396 -0
  178. package/src/adapters/nats-adapter.js +370 -0
  179. package/src/adapters/postgres-adapter.js +341 -0
  180. package/src/adapters/redis-adapter.js +331 -0
  181. package/src/adapters/redis-session-adapter.js +261 -0
  182. package/src/adapters/redlock-adapter.js +385 -0
  183. package/src/adapters/registry.js +157 -0
  184. package/src/adapters/sqlite-adapter.js +309 -0
  185. package/src/auth/index.js +103 -0
  186. package/src/cli/commands/console-cmd.js +56 -0
  187. package/src/cli/commands/new.js +101 -0
  188. package/src/cli/commands/routes.js +107 -0
  189. package/src/cli/commands/scaffold.js +120 -0
  190. package/src/cli/commands/test-cmd.js +45 -0
  191. package/src/cli/generators/index.js +368 -0
  192. package/src/cli/index.js +472 -0
  193. package/src/cli/template-engine.js +72 -0
  194. package/src/cli/ws-hub.js +582 -0
  195. package/src/core/ajv-mapper.js +80 -0
  196. package/src/core/boot.js +323 -0
  197. package/src/core/cluster-metrics.js +278 -0
  198. package/src/core/config-loader.js +115 -0
  199. package/src/core/config-validator.js +322 -0
  200. package/src/core/ctx-builder.js +253 -0
  201. package/src/core/envelope.js +88 -0
  202. package/src/core/error-mapper.js +116 -0
  203. package/src/core/formbody.js +69 -0
  204. package/src/core/hub-link.js +552 -0
  205. package/src/core/i18n.js +525 -0
  206. package/src/core/index.js +63 -0
  207. package/src/core/mega-app.js +1138 -0
  208. package/src/core/mega-cluster.js +232 -0
  209. package/src/core/mega-server.js +176 -0
  210. package/src/core/mega-service.js +41 -0
  211. package/src/core/migration-runner.js +196 -0
  212. package/src/core/multipart.js +282 -0
  213. package/src/core/openapi.js +114 -0
  214. package/src/core/router.js +388 -0
  215. package/src/core/routes-loader.js +57 -0
  216. package/src/core/scope-registry.js +53 -0
  217. package/src/core/security.js +275 -0
  218. package/src/core/services-loader.js +98 -0
  219. package/src/core/session-cleanup-schedule.js +57 -0
  220. package/src/core/session-store.js +55 -0
  221. package/src/core/session.js +414 -0
  222. package/src/core/static-assets.js +126 -0
  223. package/src/core/template.js +294 -0
  224. package/src/core/workers-manager.js +193 -0
  225. package/src/core/ws-compression.js +112 -0
  226. package/src/core/ws-controller.js +109 -0
  227. package/src/core/ws-message.js +176 -0
  228. package/src/core/ws-upgrade.js +445 -0
  229. package/src/errors/config-error.js +16 -0
  230. package/src/errors/http-errors.js +130 -0
  231. package/src/errors/index.js +19 -0
  232. package/src/errors/mega-error.js +34 -0
  233. package/src/eslint-plugin/index.js +15 -0
  234. package/src/eslint-plugin/no-direct-model-import.js +113 -0
  235. package/src/index.js +131 -0
  236. package/src/lib/asp/config.js +83 -0
  237. package/src/lib/asp/crypto.js +145 -0
  238. package/src/lib/asp/errors.js +49 -0
  239. package/src/lib/asp/nonce-cache.js +94 -0
  240. package/src/lib/asp/plugin.js +263 -0
  241. package/src/lib/asp/ws-terminator.js +101 -0
  242. package/src/lib/env-mapper.js +222 -0
  243. package/src/lib/hub-protocol.js +322 -0
  244. package/src/lib/index.js +42 -0
  245. package/src/lib/logger/telegram-core.js +150 -0
  246. package/src/lib/logger/telegram-transport.js +126 -0
  247. package/src/lib/mega-brute-force.js +225 -0
  248. package/src/lib/mega-circuit-breaker.js +412 -0
  249. package/src/lib/mega-cron.js +169 -0
  250. package/src/lib/mega-hash.js +179 -0
  251. package/src/lib/mega-health.js +91 -0
  252. package/src/lib/mega-job-queue.js +600 -0
  253. package/src/lib/mega-job-worker.js +295 -0
  254. package/src/lib/mega-job.js +140 -0
  255. package/src/lib/mega-logger.js +128 -0
  256. package/src/lib/mega-metrics.js +661 -0
  257. package/src/lib/mega-plugin.js +650 -0
  258. package/src/lib/mega-retry.js +95 -0
  259. package/src/lib/mega-schedule.js +507 -0
  260. package/src/lib/mega-shutdown.js +176 -0
  261. package/src/lib/mega-tracing.js +715 -0
  262. package/src/lib/mega-worker.js +653 -0
  263. package/src/lib/worker-runner/process-entry.js +30 -0
  264. package/src/lib/worker-runner/task-dispatch.js +72 -0
  265. package/src/lib/worker-runner/thread-entry.js +26 -0
  266. package/src/models/index.js +7 -0
  267. package/src/models/mega-model.js +151 -0
  268. package/src/test/index.js +288 -0
  269. package/templates/adapter/code.tpl +40 -0
  270. package/templates/adapter/test.tpl +13 -0
  271. package/templates/app/app.config.tpl +10 -0
  272. package/templates/app/route.tpl +10 -0
  273. package/templates/app/test.tpl +13 -0
  274. package/templates/channel/code.tpl +38 -0
  275. package/templates/channel/test.tpl +19 -0
  276. package/templates/controller/code.tpl +16 -0
  277. package/templates/controller/route.tpl +9 -0
  278. package/templates/controller/test.tpl +14 -0
  279. package/templates/job/code.tpl +23 -0
  280. package/templates/job/test.tpl +17 -0
  281. package/templates/locale/code.tpl +3 -0
  282. package/templates/locale/test.tpl +13 -0
  283. package/templates/middleware/code.tpl +13 -0
  284. package/templates/middleware/test.tpl +11 -0
  285. package/templates/migration/code.tpl +20 -0
  286. package/templates/migration/test.tpl +14 -0
  287. package/templates/model/code.tpl +21 -0
  288. package/templates/model/test.tpl +29 -0
  289. package/templates/project/app.config.tpl +8 -0
  290. package/templates/project/app.config.views.tpl +37 -0
  291. package/templates/project/ecosystem.config.tpl +10 -0
  292. package/templates/project/env.tpl +12 -0
  293. package/templates/project/gitignore.tpl +8 -0
  294. package/templates/project/locales/client/en.json.tpl +3 -0
  295. package/templates/project/locales/client/ko.json.tpl +3 -0
  296. package/templates/project/locales/server/en.json.tpl +17 -0
  297. package/templates/project/locales/server/ko.json.tpl +17 -0
  298. package/templates/project/mega.config.tpl +11 -0
  299. package/templates/project/package.tpl +25 -0
  300. package/templates/project/public/css/app.css +101 -0
  301. package/templates/project/public/js/app.js +54 -0
  302. package/templates/project/public/js/theme-init.js +12 -0
  303. package/templates/project/public/vendor/bootstrap/bootstrap.bundle.min.js +7 -0
  304. package/templates/project/public/vendor/bootstrap/bootstrap.min.css +6 -0
  305. package/templates/project/readme.tpl +48 -0
  306. package/templates/project/route.test.tpl +13 -0
  307. package/templates/project/route.test.views.tpl +15 -0
  308. package/templates/project/route.tpl +10 -0
  309. package/templates/project/route.views.tpl +10 -0
  310. package/templates/project/views/index.ejs.tpl +58 -0
  311. package/templates/project/views/layout.ejs.tpl +73 -0
  312. package/templates/project/vitest.config.tpl +8 -0
  313. package/templates/route/code.tpl +11 -0
  314. package/templates/route/test.tpl +26 -0
  315. package/templates/schedule/code.tpl +19 -0
  316. package/templates/schedule/test.tpl +17 -0
  317. package/templates/service/code.tpl +18 -0
  318. package/templates/service/test.tpl +17 -0
  319. package/templates/worker/code.tpl +14 -0
  320. package/templates/worker/task.tpl +13 -0
  321. package/templates/worker/test.tpl +18 -0
  322. package/vitest.config.js +33 -0
package/.env ADDED
@@ -0,0 +1,127 @@
1
+ # Environment
2
+ NODE_ENV=development
3
+
4
+ # Server
5
+ # 세션 쿠키 HMAC 키 — ≥32자 필수(config-validator M-1). dev/test 전용. ⚠️ 운영은 별도 시크릿으로 교체.
6
+ SESSION_SECRET=Zz4VoSzf0sYMEoqASu8G_wx5l3uKi2MlHsxDK3MSkoE
7
+ # cluster 워커 프로세스 수(ADR-154) — 정수 N 또는 max(CPU 코어 수). 미설정/1=단일 프로세스.
8
+ # MEGA_CLUSTER_WORKERS=max
9
+
10
+ # ─────────────────────────────────────────────────────────────────────
11
+ # Docker 통합 테스트 인프라 제어 (ADR-103) — docker-compose.yml 이 읽음
12
+ # 모두 dev/test 전용. ⚠️ 운영 환경 사용 금지.
13
+ # 미설정 시 docker-compose.yml 의 인라인 디폴트가 그대로 적용됨.
14
+ # 네이밍: MEGA_<SERVICE>_<FIELD> (코드의 MEGA_WSHUB_* 패턴과 정합)
15
+ # ─────────────────────────────────────────────────────────────────────
16
+ # Postgres (Step 4)
17
+ MEGA_PG_PORT=5432
18
+ MEGA_PG_USER=mega
19
+ MEGA_PG_PASSWORD=dkTkqkfl12
20
+ MEGA_PG_DB=mega_test
21
+ # MariaDB (Step 4)
22
+ MEGA_MARIA_PORT=3306
23
+ MEGA_MARIA_ROOT_PASSWORD=dkTkqkfl12
24
+ MEGA_MARIA_USER=mega
25
+ MEGA_MARIA_PASSWORD=dkTkqkfl12
26
+ MEGA_MARIA_DB=mega_test
27
+ # MongoDB (Step 5)
28
+ MEGA_MONGO_PORT=27017
29
+ MEGA_MONGO_USER=mega
30
+ MEGA_MONGO_PASSWORD=dkTkqkfl12
31
+ MEGA_MONGO_DB=mega_test
32
+ # Redis (Step 6)
33
+ MEGA_REDIS_PORT=6379
34
+ MEGA_REDIS_PASSWORD=dkTkqkfl12
35
+ # NATS (Step 6)
36
+ MEGA_NATS_PORT=4222
37
+ MEGA_NATS_MONITOR_PORT=8222
38
+ # 컨테이너 restart 정책: 개발=unless-stopped / CI 일회성=no
39
+ MEGA_INFRA_RESTART=unless-stopped
40
+
41
+ # ─────────────────────────────────────────────────────────────────────
42
+ # 연결 문자열 (services config 가 읽음) — 위 docker 디폴트와 정합
43
+ # 네이밍: <SERVICE>_URL (prefix 없는 services-키 패턴)
44
+ # ─────────────────────────────────────────────────────────────────────
45
+ # Database (services.databases.*)
46
+ PG_URL=postgres://mega:dkTkqkfl12@localhost:5432/mega_test
47
+ MARIA_URL=mariadb://mega:dkTkqkfl12@localhost:3306/mega_test
48
+ MONGO_URL=mongodb://mega:dkTkqkfl12@localhost:27017/mega_test?authSource=admin
49
+
50
+ # Redis (services.caches.*)
51
+ REDIS_SESSION_URL=redis://:dkTkqkfl12@localhost:6379/0
52
+ REDIS_CACHE_URL=redis://:dkTkqkfl12@localhost:6379/1
53
+ REDIS_RATE_URL=redis://:dkTkqkfl12@localhost:6379/2
54
+
55
+ # NATS (services.buses.*)
56
+ NATS_EVENTS_URL=nats://localhost:4222
57
+ NATS_JOBS_URL=nats://localhost:4222
58
+
59
+ # ─────────────────────────────────────────────────────────────────────
60
+ # 어댑터 옵션 자동 매핑 (ADR-109, 12-factor) — services.<domain>.<key>.envPrefix 지정 시
61
+ # MegaAdapterManager 가 buildAdapterEnvConfig 로 읽어 어댑터 옵션에 병합(env 우선).
62
+ # grammar: MEGA_<SERVICE>_<KEY>
63
+ # URL → url
64
+ # HOST/PORT/USER/PASSWORD → 연결필드 (PORT 만 정수, 나머지 항상 문자열)
65
+ # DATABASE | DB → database / DBNAME → dbName (Mongo)
66
+ # POOL_<X> → pool.{camelCase(X)} (driver 무관 공통 풀 인터페이스, 값 자동 타입변환)
67
+ # OPTIONS_<X> → options.{driver별 키} (driver-aware, 아래 표 — 값 자동 타입변환)
68
+ # ⚠️ 위 MEGA_<SERVICE>_PORT/USER/PASSWORD/DB 는 docker-compose(ADR-103)와 namespace 공유.
69
+ # grammar 불일치 키(예: MEGA_MARIA_ROOT_PASSWORD)는 어댑터 매핑에서 무시됨.
70
+ # # OPTIONS_* driver별 키 표기 (ADR-109 보강, Step 6 QA H-1 — .env 는 UPPER_SNAKE 로 통일해 적되
71
+ # # driver 가 인식하는 표기로 자동 변환됨):
72
+ # # redis/nats/mongodb/mariadb = camelCase (KEY_PREFIX→keyPrefix, MAX_RECONNECT_ATTEMPTS→maxReconnectAttempts,
73
+ # # SERVER_SELECTION_TIMEOUT_MS→serverSelectionTimeoutMS[MS 보존])
74
+ # # postgres/sqlite/file = snake_case (STATEMENT_TIMEOUT→statement_timeout)
75
+ # ─────────────────────────────────────────────────────────────────────
76
+ # 공통 풀 인터페이스 (드라이버 키로 자동 매핑 — 단위: idleTimeoutMs/acquireTimeoutMs/maxLifetimeMs=ms)
77
+ # MEGA_PG_POOL_MIN=0
78
+ # MEGA_PG_POOL_MAX=10
79
+ # MEGA_PG_POOL_IDLE_TIMEOUT_MS=10000
80
+ # MEGA_PG_POOL_ACQUIRE_TIMEOUT_MS=0
81
+ # MEGA_PG_POOL_MAX_LIFETIME_MS=0 # pg 전용 (maria/mongo 미지원→throw)
82
+ # 드라이버 특화 옵션 (passthrough — driver별 키 변환)
83
+ # MEGA_PG_OPTIONS_SSL=true # → options.ssl (pg=snake_case)
84
+ # MEGA_PG_OPTIONS_STATEMENT_TIMEOUT=30000 # → options.statement_timeout
85
+ # MEGA_MARIA_OPTIONS_BIG_INT_STRATEGY=number # → options.bigIntStrategy (maria=camel) 'number'(디폴트,2^53 초과 정밀도 손실)|'bigint'|'string'
86
+ # MEGA_MARIA_OPTIONS_CHARSET=utf8mb4 # → options.charset
87
+ # MEGA_MARIA_OPTIONS_MULTIPLE_STATEMENTS=false # → options.multipleStatements (camel 변환)
88
+ # MEGA_MONGO_DBNAME=mega_test # Mongo dbName (url path 로도 가능)
89
+ # MEGA_MONGO_OPTIONS_AUTH_SOURCE=admin # → options.authSource (mongo=camel)
90
+ # MEGA_MONGO_OPTIONS_SERVER_SELECTION_TIMEOUT_MS=5000 # → options.serverSelectionTimeoutMS (MS 대문자 보존, 이제 env 로 가능)
91
+
92
+ # WS Hub (mega ws-hub CLI — src/cli/ws-hub.js, runWsHubCli)
93
+ # 코드가 읽는 키는 MEGA_WSHUB_* (언더스코어 없는 단일 service 토큰). TOKENS 만 필수.
94
+ # 비밀 토큰은 운영에서 교체. hub 는 `mega ws-hub` 실행 시에만 기동(자동 기동 없음).
95
+ MEGA_WSHUB_TOKENS=change-me
96
+ MEGA_WSHUB_PORT=3100
97
+ MEGA_WSHUB_HOST=0.0.0.0
98
+ MEGA_WSHUB_HEARTBEAT_MS=25000
99
+ MEGA_WSHUB_MAX_PAYLOAD=1048576
100
+ # 압축(ADR-078) — 'true' 일 때만 ON. THRESHOLD 는 압축 ON 시에만 적용(byte).
101
+ MEGA_WSHUB_COMPRESSION=false
102
+ MEGA_WSHUB_COMPRESSION_THRESHOLD=1024
103
+
104
+ # Telegram (옵션 — 로거 sink)
105
+ # TG_BOT_TOKEN= ← 실토큰은 .env.local 에. npm publish 노출 방지로 .env 에선 비움(2026-06-08).
106
+ # TG_CHAT_ID=
107
+
108
+ # OpenTelemetry 분산 트레이싱 (옵션 — Phase 3 Step 8 / Phase 5 Step 1, MegaTracing)
109
+ # MegaTracing.fromEnv() 가 읽는 런타임 키(ADR-114/126). 옵트인 OFF(디폴트)면 0 비용.
110
+ # ⚠️ 구 OTEL_ENABLED/OTEL_ENDPOINT(prefix 없는)는 코드가 안 읽는 죽은 키라 제거 — 반드시 MEGA_OTEL_*.
111
+ MEGA_OTEL_ENABLED=false
112
+ MEGA_OTEL_SERVICE_NAME=mega-app
113
+ MEGA_OTEL_ENDPOINT=http://localhost:4318/v1/traces
114
+ MEGA_OTEL_EXPORTER=otlp
115
+ MEGA_OTEL_SAMPLING_RATIO=1.0
116
+ MEGA_OTEL_VERSION=
117
+ MEGA_OTEL_ENVIRONMENT=
118
+
119
+ # ── 실 OTel collector + Zipkin docker 백엔드 (ADR-128) — 통합 테스트(tracing E2E)가 읽음 ──
120
+ # docker-compose 의 otel-collector(:4318 OTLP HTTP)·zipkin(:9411) 가동 시 실 OTLP→collector→zipkin 검증.
121
+ # 미설정 시 tracing E2E(otel-collector-e2e)만 자동 skip(CI 일관성). OTLP HTTP traces path 는 /v1/traces.
122
+ MEGA_OTEL_OTLP_ENDPOINT=http://localhost:4318/v1/traces
123
+ MEGA_OTEL_ZIPKIN_API=http://localhost:9411/api/v2
124
+ MEGA_OTEL_HEALTH_URL=http://localhost:13133
125
+
126
+ # Log level
127
+ LOG_LEVEL=info
package/.env.example ADDED
@@ -0,0 +1,186 @@
1
+ # ─────────────────────────────────────────────────────────────────────
2
+ # MEGA-FRAMEWORK 환경변수 전수 레퍼런스 (.env.example)
3
+ # 복사해서 `.env` 로 쓰고 실제 값을 채운다. `.env` 는 개발 기간 한정 git 추적(공개 전 rotate, .gitignore 참조).
4
+ # 범위 = framework 자체(통합 테스트 인프라 + 관측성) + framework 가 직접 읽는 키. 앱(sample/*) 전용 키는
5
+ # 각 sample 의 .env.example 참조(sample/simple, sample/crud).
6
+ # 표기: 주석 해제(앞 `#` 제거) 시 활성. 값이 적힌 줄 = 디폴트로 채워진 활성 키. `#KEY=` = 선택(필요 시 해제).
7
+ # ─────────────────────────────────────────────────────────────────────
8
+
9
+ # Environment
10
+ # 'development' | 'production' | 'test'. 다수 길목의 게이팅 기준(템플릿 캐시·정적자산·OpenAPI 노출·
11
+ # i18n saveMissing(ADR-164, dev 만)·metrics resource environment). 미설정 시 일부는 production 으로 간주.
12
+ NODE_ENV=development
13
+
14
+ # ─────────────────────────────────────────────────────────────────────
15
+ # Server / Cluster (framework 직접 읽음)
16
+ # ─────────────────────────────────────────────────────────────────────
17
+ # 세션 쿠키 HMAC 서명 키 — ≥32자 필수(config-validator M-1). dev/test 전용. ⚠️ 운영은 별도 시크릿으로 교체.
18
+ # 앱 mega.config.js 의 server.sessionSecret 이 `process.env.SESSION_SECRET` 로 읽는 관례.
19
+ SESSION_SECRET=change-me-in-production
20
+ # cluster 워커 프로세스 수(ADR-154) — 정수 N 또는 max(CPU 코어 수). 미설정/1=단일 프로세스.
21
+ # 우선순위: `mega start --cluster` > MEGA_CLUSTER_WORKERS > mega.config.js 의 server.cluster.
22
+ # MEGA_CLUSTER_WORKERS=max
23
+
24
+ # ─────────────────────────────────────────────────────────────────────
25
+ # Docker 통합 테스트 인프라 제어 (ADR-103) — docker-compose.yml 이 읽음
26
+ # 모두 dev/test 전용. ⚠️ 운영 환경 사용 금지.
27
+ # 미설정 시 docker-compose.yml 의 인라인 디폴트가 그대로 적용됨.
28
+ # 네이밍: MEGA_<SERVICE>_<FIELD> (코드의 MEGA_WSHUB_* 패턴과 정합)
29
+ # ─────────────────────────────────────────────────────────────────────
30
+ # Postgres (Step 4)
31
+ MEGA_PG_PORT=5432
32
+ MEGA_PG_USER=mega
33
+ MEGA_PG_PASSWORD=mega-dev-only
34
+ MEGA_PG_DB=mega_test
35
+ # MariaDB (Step 4)
36
+ MEGA_MARIA_PORT=3306
37
+ MEGA_MARIA_ROOT_PASSWORD=mega-dev-only
38
+ MEGA_MARIA_USER=mega
39
+ MEGA_MARIA_PASSWORD=mega-dev-only
40
+ MEGA_MARIA_DB=mega_test
41
+ # MongoDB (Step 5)
42
+ MEGA_MONGO_PORT=27017
43
+ MEGA_MONGO_USER=mega
44
+ MEGA_MONGO_PASSWORD=mega-dev-only
45
+ MEGA_MONGO_DB=mega_test
46
+ # Redis (Step 6)
47
+ MEGA_REDIS_PORT=6379
48
+ MEGA_REDIS_PASSWORD=mega-dev-only
49
+ # NATS (Step 6)
50
+ MEGA_NATS_PORT=4222
51
+ MEGA_NATS_MONITOR_PORT=8222
52
+ # 컨테이너 restart 정책: 개발=unless-stopped / CI 일회성=no
53
+ MEGA_INFRA_RESTART=unless-stopped
54
+ # OTel collector + Zipkin 트레이싱 백엔드 컨테이너 포트 (ADR-128) — docker-compose.yml 이 읽음.
55
+ # 위 MEGA_OTEL_OTLP_ENDPOINT/ZIPKIN_API(아래 OpenTelemetry 섹션) 와 포트가 정합해야 함.
56
+ MEGA_ZIPKIN_PORT=9411
57
+ MEGA_OTEL_OTLP_GRPC_PORT=4317
58
+ MEGA_OTEL_OTLP_HTTP_PORT=4318
59
+ MEGA_OTEL_HEALTH_PORT=13133
60
+
61
+ # ─────────────────────────────────────────────────────────────────────
62
+ # 연결 문자열 (services config 가 읽음) — 위 docker 디폴트와 정합
63
+ # 네이밍: <SERVICE>_URL (prefix 없는 services-키 패턴)
64
+ # ─────────────────────────────────────────────────────────────────────
65
+ # Database (services.databases.*)
66
+ PG_URL=postgres://mega:mega-dev-only@localhost:5432/mega_test
67
+ MARIA_URL=mariadb://mega:mega-dev-only@localhost:3306/mega_test
68
+ MONGO_URL=mongodb://mega:mega-dev-only@localhost:27017/mega_test?authSource=admin
69
+
70
+ # Redis (services.caches.*)
71
+ REDIS_SESSION_URL=redis://:mega-dev-only@localhost:6379/0
72
+ REDIS_CACHE_URL=redis://:mega-dev-only@localhost:6379/1
73
+ REDIS_RATE_URL=redis://:mega-dev-only@localhost:6379/2
74
+
75
+ # NATS (services.buses.*)
76
+ NATS_EVENTS_URL=nats://localhost:4222
77
+ NATS_JOBS_URL=nats://localhost:4222
78
+
79
+ # ─────────────────────────────────────────────────────────────────────
80
+ # 어댑터 옵션 자동 매핑 (ADR-109, 12-factor) — services.<domain>.<key>.envPrefix 지정 시
81
+ # MegaAdapterManager 가 buildAdapterEnvConfig 로 읽어 어댑터 옵션에 병합(env 우선).
82
+ # grammar: MEGA_<SERVICE>_<KEY>
83
+ # URL → url
84
+ # HOST/PORT/USER/PASSWORD → 연결필드 (PORT 만 정수, 나머지 항상 문자열)
85
+ # DATABASE | DB → database / DBNAME → dbName (Mongo)
86
+ # POOL_<X> → pool.{camelCase(X)} (driver 무관 공통 풀 인터페이스, 값 자동 타입변환)
87
+ # OPTIONS_<X> → options.{driver별 키} (driver-aware, 아래 표 — 값 자동 타입변환)
88
+ # ⚠️ 위 MEGA_<SERVICE>_PORT/USER/PASSWORD/DB 는 docker-compose(ADR-103)와 namespace 공유.
89
+ # grammar 불일치 키(예: MEGA_MARIA_ROOT_PASSWORD)는 어댑터 매핑에서 무시됨.
90
+ # # OPTIONS_* driver별 키 표기 (ADR-109 보강, Step 6 QA H-1 — .env 는 UPPER_SNAKE 로 통일해 적되
91
+ # # driver 가 인식하는 표기로 자동 변환됨):
92
+ # # redis/nats/mongodb/mariadb = camelCase (KEY_PREFIX→keyPrefix, MAX_RECONNECT_ATTEMPTS→maxReconnectAttempts,
93
+ # # SERVER_SELECTION_TIMEOUT_MS→serverSelectionTimeoutMS[MS 보존])
94
+ # # postgres/sqlite/file = snake_case (STATEMENT_TIMEOUT→statement_timeout)
95
+ # ─────────────────────────────────────────────────────────────────────
96
+ # 공통 풀 인터페이스 (드라이버 키로 자동 매핑 — 단위: idleTimeoutMs/acquireTimeoutMs/maxLifetimeMs=ms)
97
+ # MEGA_PG_POOL_MIN=0
98
+ # MEGA_PG_POOL_MAX=10
99
+ # MEGA_PG_POOL_IDLE_TIMEOUT_MS=10000
100
+ # MEGA_PG_POOL_ACQUIRE_TIMEOUT_MS=0
101
+ # MEGA_PG_POOL_MAX_LIFETIME_MS=0 # pg 전용 (maria/mongo 미지원→throw)
102
+ # 드라이버 특화 옵션 (passthrough — driver별 키 변환)
103
+ # MEGA_PG_OPTIONS_SSL=true # → options.ssl (pg=snake_case)
104
+ # MEGA_PG_OPTIONS_STATEMENT_TIMEOUT=30000 # → options.statement_timeout
105
+ # MEGA_MARIA_OPTIONS_BIG_INT_STRATEGY=number # → options.bigIntStrategy (maria=camel) 'number'(디폴트,2^53 초과 정밀도 손실)|'bigint'|'string'
106
+ # MEGA_MARIA_OPTIONS_CHARSET=utf8mb4 # → options.charset
107
+ # MEGA_MARIA_OPTIONS_MULTIPLE_STATEMENTS=false # → options.multipleStatements (camel 변환)
108
+ # MEGA_MONGO_DBNAME=mega_test # Mongo dbName (url path 로도 가능)
109
+ # MEGA_MONGO_OPTIONS_AUTH_SOURCE=admin # → options.authSource (mongo=camel)
110
+ # MEGA_MONGO_OPTIONS_SERVER_SELECTION_TIMEOUT_MS=5000 # → options.serverSelectionTimeoutMS (MS 대문자 보존, 이제 env 로 가능)
111
+ # Step 6 비-DB 어댑터 (Redis cache / File cache / NATS bus) — pool 미지원(지정 시 throw)
112
+ # MEGA_REDIS_URL=redis://:pw@localhost:6379/1 # 또는 HOST/PORT/USER/PASSWORD discrete
113
+ # MEGA_REDIS_DB=1 # → db:1 (정수, 논리 DB 번호 0~15, connection 과 별개 축. url path 의 db 보다 우선)
114
+ # MEGA_REDIS_OPTIONS_KEY_PREFIX=app: # → options.keyPrefix (redis=camel 변환)
115
+ # MEGA_REDIS_OPTIONS_COMMAND_TIMEOUT=5000 # → options.commandTimeout
116
+ # MEGA_NATS_URL=nats://localhost:4222 # 또는 HOST/PORT (+ TOKEN 또는 USER/PASSWORD)
117
+ # MEGA_NATS_OPTIONS_NAME=mega # → options.name (nats=camel 변환)
118
+ # MEGA_NATS_OPTIONS_MAX_RECONNECT_ATTEMPTS=-1 # → options.maxReconnectAttempts
119
+ # # File 캐시는 url 없이 basePath 필수 — config 파일에 { driver:'file', basePath:'/var/cache/mega' }
120
+ # Step 7 분산 락 (redlock) — 연결을 직접 열지 않고 services.caches 의 Redis 어댑터 key 를 참조한다
121
+ # # config 파일: services.locks.<key> = { driver:'redlock', redis:'<cache-key>', options:{...} }
122
+ # # 'redis' 는 url/host 가 아니라 어댑터 참조라 env 매핑 대상 아님 — config 파일에 명시.
123
+ # MEGA_LOCK_OPTIONS_RETRY_COUNT=10 # → options.retryCount (redlock=camel 변환)
124
+ # MEGA_LOCK_OPTIONS_RETRY_DELAY=200 # → options.retryDelay (ms)
125
+ # MEGA_LOCK_OPTIONS_RETRY_JITTER=200 # → options.retryJitter (ms)
126
+ # MEGA_LOCK_OPTIONS_AUTOMATIC_EXTENSION_THRESHOLD=500 # → options.automaticExtensionThreshold (ms, using 자동 연장 임계)
127
+ # # driftFactor(0~1 소수)는 env 정수 변환과 안 맞아 config 파일에 직접: options:{ driftFactor:0.01 }
128
+
129
+ # ─────────────────────────────────────────────────────────────────────
130
+ # WS Hub (mega ws-hub CLI — src/cli/ws-hub.js, runWsHubCli)
131
+ # 코드가 읽는 키는 MEGA_WSHUB_* (언더스코어 없는 단일 service 토큰). TOKENS 만 필수.
132
+ # 비밀 토큰은 운영에서 교체. hub 는 `mega ws-hub` 실행 시에만 기동(자동 기동 없음).
133
+ # ─────────────────────────────────────────────────────────────────────
134
+ MEGA_WSHUB_TOKENS=change-me
135
+ MEGA_WSHUB_PORT=3100
136
+ MEGA_WSHUB_HOST=0.0.0.0
137
+ MEGA_WSHUB_HEARTBEAT_MS=25000
138
+ MEGA_WSHUB_MAX_PAYLOAD=1048576
139
+ # 압축(ADR-078) — 'true' 일 때만 ON. THRESHOLD 는 압축 ON 시에만 적용(byte).
140
+ MEGA_WSHUB_COMPRESSION=false
141
+ MEGA_WSHUB_COMPRESSION_THRESHOLD=1024
142
+
143
+ # ─────────────────────────────────────────────────────────────────────
144
+ # OpenTelemetry 분산 트레이싱 (옵션 — Phase 3 Step 8 / Phase 5, MegaTracing, ADR-114/126/163)
145
+ # 런타임 키. boot 이 MegaTracing.fromEnv() 로 읽는다(src/core/boot.js). 옵트인 OFF(디폴트)면
146
+ # 어댑터에 hook 리스너가 안 붙어 0 비용. ⚠️ prefix 없는 OTEL_ENABLED/OTEL_ENDPOINT 는 죽은 키 — 반드시 MEGA_OTEL_*.
147
+ # ─────────────────────────────────────────────────────────────────────
148
+ MEGA_OTEL_ENABLED=false # true 일 때만 트레이싱 활성(serviceName 필수)
149
+ MEGA_OTEL_SERVICE_NAME=mega-app # service.name (활성 시 필수)
150
+ MEGA_OTEL_ENDPOINT=http://localhost:4318/v1/traces # exporter endpoint (otlp: /v1/traces, zipkin: http://localhost:9411/api/v2/spans)
151
+ MEGA_OTEL_EXPORTER=otlp # otlp | zipkin | console | inmemory
152
+ MEGA_OTEL_SAMPLING_RATIO=1.0 # 0~1 비율, 또는 always_on / always_off
153
+ MEGA_OTEL_VERSION= # service.version (옵션)
154
+ MEGA_OTEL_ENVIRONMENT= # deployment.environment.name (옵션, 예: production)
155
+
156
+ # 실 OTel collector + Zipkin docker 백엔드 (ADR-128) — 통합 테스트(tracing E2E)가 읽는다.
157
+ # docker-compose 의 otel-collector(:4318)·zipkin(:9411) 가동 시 실 OTLP→collector→zipkin 경로를 검증.
158
+ # 미설정 시 해당 E2E 만 자동 skip(CI 일관성). 운영 배포에선 collector endpoint 로 교체.
159
+ MEGA_OTEL_OTLP_ENDPOINT=http://localhost:4318/v1/traces # 앱 OTLP HTTP traces 전송 대상(collector receiver)
160
+ MEGA_OTEL_ZIPKIN_API=http://localhost:9411/api/v2 # 테스트가 span 도달을 폴링 조회(/traces, /spans)
161
+ MEGA_OTEL_HEALTH_URL=http://localhost:13133 # collector health_check extension(준비 폴링용)
162
+
163
+ # ─────────────────────────────────────────────────────────────────────
164
+ # Prometheus 메트릭 (옵션 — Phase 5, MegaMetrics, ADR-072/131, docs/INFRA.md §7)
165
+ # 메트릭 옵트인은 config(mega.config.js 의 health.exposeMetrics:true)로 켠다. 아래 METRICS_ENABLED 는
166
+ # 그 config 가 `exposeMetrics: process.env.METRICS_ENABLED === 'true'` 로 읽는 관례(docs/INFRA §7).
167
+ # 표준 boot 경로의 serviceName 은 health.serviceName → MEGA_OTEL_SERVICE_NAME 폴백, environment 는 NODE_ENV,
168
+ # version 은 server.version 을 쓴다. MEGA_METRICS_* 는 MegaMetrics.fromEnv()(public API) 전용 키로,
169
+ # boot 은 fromEnv 를 호출하지 않으므로 직접 fromEnv 를 쓸 때만 적용된다.
170
+ # ─────────────────────────────────────────────────────────────────────
171
+ # METRICS_ENABLED=true # 또는 MEGA_METRICS_ENABLED=true — config 에서 exposeMetrics 로 와이어
172
+ # MEGA_METRICS_SERVICE_NAME=mega # 없으면 MEGA_OTEL_SERVICE_NAME 폴백 (MegaMetrics.fromEnv 전용)
173
+ # MEGA_METRICS_VERSION= # resource service.version (MegaMetrics.fromEnv 전용)
174
+ # MEGA_METRICS_ENVIRONMENT=prod # resource deployment.environment (MegaMetrics.fromEnv 전용)
175
+
176
+ # ─────────────────────────────────────────────────────────────────────
177
+ # 로깅 / Telegram sink (mega-logger, ADR-023/141)
178
+ # ⚠️ 로그 레벨·sink 는 .env 가 아니라 mega.config.js 의 logger 블록에서 설정한다 — framework 는
179
+ # LOG_LEVEL / TG_BOT_TOKEN / TG_CHAT_ID 를 process.env 로 읽지 않는다(아래는 config 와이어링용 관례 키).
180
+ # ─────────────────────────────────────────────────────────────────────
181
+ # 로그 레벨 — mega.config.js 의 logger.level('info'/'debug'/...)에서 설정. (LOG_LEVEL env 는 코드가 안 읽음)
182
+ # LOG_LEVEL=info
183
+ # Telegram sink(옵션) — 토큰/챗ID. mega.config.js 의 logger.sinks 에
184
+ # { type:'telegram', botToken: process.env.TG_BOT_TOKEN, chatId: process.env.TG_CHAT_ID } 로 직접 와이어해야 적용.
185
+ # TG_BOT_TOKEN=
186
+ # TG_CHAT_ID=
@@ -0,0 +1,8 @@
1
+ {
2
+ "semi": false,
3
+ "singleQuote": true,
4
+ "trailingComma": "all",
5
+ "printWidth": 100,
6
+ "tabWidth": 2,
7
+ "arrowParens": "always"
8
+ }
package/CHANGELOG.md ADDED
@@ -0,0 +1,259 @@
1
+ # Changelog
2
+
3
+ 이 프로젝트의 주요 변경 사항을 기록한다. 형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/),
4
+ 버전 체계는 [Semantic Versioning](https://semver.org/lang/ko/) 을 따른다.
5
+
6
+ ## [Unreleased]
7
+
8
+ > **Phase 7.5 — E2E 검증 + 정본 결함 교정 (종합 마무리)**: `sample/simple`·`sample/crud` 를 실제로 끝까지
9
+ > 굴려 문서-코드 일치를 E2E 로 증명하고, 드러난 정본 배선 공백 8건(H)·계약 위반 5건(M)을 근본 교정([ADR-146](docs/09-decisions-and-open-questions.md)~164)
10
+ > + 핵심 모듈 로직 정확성 audit([ADR-165](docs/09-decisions-and-open-questions.md)~172). 게이트 `npm test` 1634→1817 그린/3 skip,
11
+ > typecheck 0, lint 0, 신규 dep 0(샘플은 전부 내장 부품 조립). 상세: [`docs/phase-7-5-summary.md`](docs/phase-7-5-summary.md).
12
+
13
+ ### Added
14
+
15
+ - **`sample/crud` 성능 벤치마크(`/perf`, ADR-174)** — 프레임워크 주요 표면(HTTP 직렬화·암호화·DB·캐시·세션)의 처리량/지연을 sample 앱에서 직접 재는 `/perf` 뷰어(시나리오 선택·실행 폼 + 결과 표) + `POST /perf/run`(AJAX, JSON) 추가. 측정은 Node 내장 `perf_hooks` 자체 구현(autocannon/k6 등 **외부 부하도구 X — 신규 dep 0**), 통계는 정렬+nearest-rank 백분위(p50/p90/p95/p99·min·max·avg·rps). 시나리오 9종: `http.echo`·`http.jsonSmall`·`http.jsonLarge`·`crypto.hash`(scrypt)·`crypto.aspRoundtrip`(`MegaAspCrypto` 공개 표면 AES-256-GCM)·`db.pg.insertSelect`·`db.mongo.insertFind`·`cache.redis.setGet`·`session.createRead`. DB 는 sample 정본 배선(postgres·mongo)만 — maria/sqlite 는 미배선이라 P7 결정으로 제외. 시나리오별 유효 상한(`crypto.hash` 는 ≈32 MiB/호출이라 반복 500·동시성 4 로 clamp — 자기-DoS/OOM 방어)으로 묶고 clamp 는 응답·로그로 가시화(조용한 절삭 X). DB 시나리오는 `run_id` 격리 + `try/finally` teardown(잔여 0). 두 라우트 `webRequireAuth` 보호, JSON POST 는 CSRF 토큰 면제+Origin 검증(ADR-051). navbar 성능 메뉴 + ko/en i18n. 단위 +12·통합 +10, sample `mega test` 그린(회귀 0), 라이브 실측 9종 0 실패(http.echo 330만 rps·crypto.hash avg 48.8 ms·db.pg p95 2.2 ms 등).
16
+ - **`sample/crud` 가이드 뷰어(`/guide`, ADR-173)** — `docs/guide/*.md` 8개 사용 가이드를 sample 앱에서 읽는 `/guide` 인덱스(카드 그리드) + `/guide/:slug` 단일 페이지(좌측 목차 + 우측 본문)를 추가. 마크다운→HTML 과 코드 하이라이트를 **전부 서버에서** 끝낸다(`marked`·`highlight.js`) — 브라우저 JS 추가 0 으로 sample 의 helmet CSP(`script-src 'self' 'wasm-unsafe-eval'`) 무수정 준수(라이브 CSP 위반 0). 하이라이트 테마는 light(github) + dark(`[data-bs-theme="dark"]` 스코프) vendored 라 테마 토글과 함께 코드블록 색 전환. 헤딩 id 는 github-slugger 규칙으로 달아 가이드 내 목차 점프 동작. slug 화이트리스트 + 형식검증으로 경로조작 차단, 두 라우트 `webRequireAuth` 보호. 신규 의존성은 **런타임 import** 이라 `dependencies`(devDep 아님) — sample/crud 한정, 프레임워크 코어 무변경, audit 0. navbar 가이드 메뉴 + ko/en i18n. 단위 +6, sample `mega test` 97 그린(회귀 0), 라이브 브라우저 검증(사이드바·표·하이라이트·offcanvas).
17
+ - **샘플 prod 기본 부팅(`sample/crud`·`sample/simple`, ADR-164)** — `package.json` 의 `start` 를
18
+ `NODE_ENV=production mega start`, `dev`(및 `dev:all`)를 `NODE_ENV=development mega start` 로 명시. 라이브
19
+ `npm start` 가 프로덕션 기본이라 i18n `saveMissing`(누락 키 관측)이 꺼져 ko/en locale 파일을 오염시키지 않는다
20
+ (ADR-163 유령서버 함정 근본 대책). 개발 모드는 `npm run dev`. 프레임워크 정본 무변경(외부 사용자 영향 0), POSIX
21
+ env prefix 라 신규 dep 0.
22
+ - **클러스터 메트릭 집계 — `collectCluster()` / `mergeExposition()` (ADR-154/163)** — `mega start` 클러스터에서 워커별로 흩어진 Prometheus 메트릭을 마스터 IPC 로 합산한다(prom-client AggregatorRegistry 패턴을 OpenTelemetry 에 적용). `/metrics`·`/demo/metrics` 가 워커 라운드로빈으로 들쭉날쭉하던 문제 해소 — 한 응답에 전 워커 누적이 일관되게 나온다. 신규 `src/core/cluster-metrics.js`(merge=counter/histogram/gauge 합산·info 메타 비합산·HELP/TYPE dedupe, 단일 프로세스/timeout 시 로컬 폴백). 단위 7 + spawn 통합 1(2워커 /api/ping 10회 → /metrics 합 10 일관). 라이브 8워커 검증.
23
+ - **업로드 파일 다운로드 + 저장 위치 설정화(`sample/crud`, ADR-163)** — `/demo/upload/file/:name`(인증 필요)이 정적 서빙이 아니라 소스에서 `createReadStream` 으로 읽어 전송(경로탐색 차단 + attachment). 저장 위치를 `.env DEMO_UPLOAD_DIR`(기본 `var/uploads`)로 설정화 + 데모에 저장 경로·다운로드 링크 표시.
24
+ - **`sample/crud` 관측 데모(`/demo/metrics`·`/docs`·`/demo/tracing`·`/demo/logs`·`/demo/upload`)** — Phase 5 의 관측성 부품(MegaMetrics·OpenAPI/Swagger·MegaTracing·pino·multipart)을 시연(신규 dep 0). **`/demo/metrics`**: `MegaMetrics.collect()`(Prometheus 텍스트)를 파싱해 HTTP(상태클래스/라우트)·잡·WS·process 카드 + raw `/metrics` 링크. **`/docs`**: `openapi` 옵트인 + `users` 라우트 schema/메타 보강 → OpenAPI 3.0 자동 생성, `webRequireAuth` 가드. **`/demo/tracing`**: 현재 `trace_id`(+ `x-trace-id` 헤더) + 최근 trace(redis) + Zipkin 딥링크, "trace 생성"은 `ctx.tracer.span` + DB 핑으로 다층 span. **`/demo/logs`**: `ctx.log` 로 실제 emit — `redact` 가 `token`/`password` 를 `[Redacted]` 마스킹 + trace_id 자동 첨부(안전 메타만 redis 표시). **`/demo/upload`**: `req.saveUploads()` 로 임시 디렉터리 저장(MIME/크기/개수 게이트) — multipart CSRF 는 `csrf-token` **헤더**로(스트리밍 body 미파싱 회피, fetch+FormData). navbar 5개 + ko/en i18n(86키), `.env.example` OTEL 섹션. 라이브 5데모 + Zipkin trace 검증, sample `mega test` 91(+23). (ADR-163)
25
+ - **`sample/crud` 스케줄러·잡 큐·CPU 워커 데모(`/demo/cron`·`/demo/jobs`·`/demo/worker`)** — Phase 4 의 잡·스케줄·워커 3종 추상을 실제 멀티프로세스로 시연(신규 dep 0 — 정본 부품 조립만). **`/demo/cron`**: `CronCounterSchedule`(`mega scheduler` 프로세스)이 30초마다 redis 카운터 INCR + 이력, **클러스터 중복방지는 `static lock`(redlock leader election)** — 2 scheduler 경쟁에서 tick 당 1회만 실행 실증. 수동 실행 버튼 + 다음 실행 시각(MegaCron). **`/demo/jobs`**: 웹이 `EmailJob` 을 NATS JetStream 에 enqueue → `mega worker` 프로세스(instances:2) 소비, 3모드(`ok`/`flaky`=재시도후성공/`fail`=DLQ 격리), 처리 타임라인(redis) + **DLQ 스트림 직접 조회**로 격리분 표시. **`/demo/worker`**: `HashWorker`(worker_threads 풀)로 SHA-256 N회 반복 CPU 작업, **1초 하트비트 ping 으로 메인 스레드 non-block 시연**(15M 라운드 6.5초 실행 중 ping 2–13ms 유지). 배선: global `services.buses.jobs`/`caches.lock`/`locks.main` + `schedules`/`jobs`/`workers`, 앱 `buses` 별명 + `rateLimit` 상향(하트비트 폴링 수용). navbar/home 링크 + ko/en i18n. 라이브 3프로세스 + 브라우저 검증, sample `mega test` 68(+13). (ADR-162)
26
+ - **`sample/crud` 실시간 채팅(WebSocket) + ASP + redis pub/sub cluster broadcast** — `MegaWebSocketController`·
27
+ ASP·cluster-wide 전파를 프레임워크 내장 부품 조립으로 추가(신규 dep 0). `/demo/ws` 는 로그인 채팅 —
28
+ `ChatChannel` 이 onConnect/chat.send/onDisconnect 를 처리하고, **cluster-wide 전파는 redis pub/sub**
29
+ (`chat-bus.js`: PUBLISH `ws:chat:bcast` + 워커마다 ioredis `duplicate()` 구독자 SUBSCRIBE→로컬 전달)로 hub
30
+ 프로세스 없이 워커 간 fanout. **접속자 명단도 cluster-wide**(redis HASH `ws:chat:roster`). WS upgrade 인증은
31
+ 신규 `readSession`(ADR-159)로 세션 쿠키 확인(비로그인 401, fail-closed). 브라우저 ASP 는 정본 WASM
32
+ `MegaSocket` 을 `protocol:'envelope'`(ADR-160)로 써서 E:(AES-256-GCM) 프레임을 브라우저에서 직접 암복호화 —
33
+ pkg 는 git 추적(ADR-161) + sample `public/vendor/` 서빙, 데모 secret(`ASP_MASTER_SECRET`)을 data 속성 주입,
34
+ helmet CSP `'wasm-unsafe-eval'`. 사용자 본문은 `textContent` 로만 렌더(XSS 방지), navbar/home 링크 + ko/en
35
+ i18n. 라이브 2워커 클러스터에서 cross-worker broadcast(워커 A↔B) + cluster-wide roster 실증. (ADR-158)
36
+ - **WASM `pkg/` git 추적(외부 사용자 즉시 실행)** — `@mega-framework/client-wasm` 빌드 산출물
37
+ `packages/mega-client-wasm/pkg/` 를 git 추적(`target/` 는 계속 ignore). root `.gitignore` 정정 + wasm-pack 이
38
+ 만드는 `pkg/.gitignore`(`*`)를 `build:wasm` 스크립트가 제거(재빌드해도 추적 유지). (ADR-161)
39
+ - **`readSession(req, { store, secret })` + `Router#app`** — WS upgrade(`before(req)`)는 Fastify 밖이라
40
+ `req.session` 이 없다. `core/session.js` 에 읽기 전용 세션 복원 helper 추가(쿠키 → HMAC 서명검증 → 세션스토어
41
+ 로드, rolling/쿠키발급 없음, 위조·만료는 null fail-closed). 라우트 모듈이 앱에 닿도록 `router.app` getter 노출
42
+ (WS `before` 가 `router.app.sessionStore` 를 클로저로 주입). (ADR-159)
43
+ - **WASM `MegaSocket` envelope 프로토콜 모드(opt-in)** — `@mega-framework/client-wasm` 의 WS 와이어가
44
+ `{type,data}` 라 프레임워크 WS envelope `{v,id,type,ts,payload}`(ADR-015)과 비호환이던 deferred 정합 과제를
45
+ 해소. 생성자 opt `protocol: 'envelope'`(기본 `'event'` 하위호환)이면 송신은 정본 envelope(`id`=UUID v4,
46
+ `ts`=정수 ms), 수신은 `payload` 를 핸들러에 전달, ping 은 `mega.ping`(유효 type). ASP 암복호화 계층 불변
47
+ (envelope 은 암호화 전 평문 JSON 양식 변경). `cargo test` 37 + `wasm-pack test --node` 7(신규 3). (ADR-160)
48
+ - **`sample/crud` MongoDB(`notes`) + Redis 데모 페이지** — Document DB 어댑터(ADR-108)와 Redis 캐시 표면
49
+ (ADR-110)을 직접 쓰는 데모를 프레임워크 내장 부품 조립으로 추가(신규 dep 0). `/demo/notes` 는 mongo
50
+ `notes` 컬렉션 CRUD(MPA + Bootstrap 5 카드 + CSRF) — `Note extends MegaModel`(`this.db.collection(...)`
51
+ 도큐먼트 API, 식별자는 자체 UUID `id` 라 `mongodb`/ObjectId import 불요). `/demo/redis` 는 방문 카운터
52
+ (`.native` 원자적 INCR/EXPIRE — 누적 + 일자별 TTL 2일)와 쿼리 결과 캐시(표준 get/set 으로 `User.count()`를
53
+ 30초 캐싱, hit/miss + 남은 TTL 표시, DEL 로 비우기)를 한 페이지에서 시연. `services.databases.mongo`
54
+ (`MONGO_URL`) + `services.caches.demo`(`REDIS_DEMO_URL`, db1) 설정, `/demo/**` 는 `webRequireAuth` 보호,
55
+ navbar/home 데모 링크 + ko/en i18n + 다크모드. (ADR-157)
56
+ - **`sample/crud` 인증(로그인·로그아웃·회원가입) + redis 세션 + brute-force** — 세션 기반 인증을 프레임워크
57
+ 내장 부품 조립으로 얹음(신규 dep 0). 비밀번호는 `MegaHash`(scrypt, ADR-130), 세션은 redis store + 쿠키
58
+ HMAC 서명 + rolling TTL(`SESSION_SECRET`·`REDIS_SESSION_URL`), 반복 시도 잠금은 `ctx.bruteForce`(redis
59
+ `rate` 캐시, subject=`IP:email`로 account-lockout DoS 회피). 로그인 성공 시 `session.regenerate()`로 세션
60
+ 고정 공격 방지. `/auth/login`·`/auth/logout`·`/register`(보호 영역 밖, POST+CSRF), `/admin/**`은 비로그인
61
+ 리다이렉트(웹 `webRequireAuth`), JSON API `/users`는 `requireAuth`(401 envelope)로 보호. Bootstrap 5 로그인/
62
+ 회원가입 카드 + navbar 로그인 상태 + ko/en i18n. `mega g migration`으로 `password_hash`·`last_login_at`
63
+ 컬럼 추가. (ADR-155)
64
+ - **`mega start` 클러스터 모드 + `MEGA_CLUSTER_WORKERS` env** — `MegaCluster`(fork·respawn·graceful)는
65
+ 구현돼 있었으나 `mega start` 가 단일 프로세스(`bootApp`)만 띄워 `server.cluster` 가 죽어 있던 배선 공백을
66
+ 메움. 워커 수는 `--cluster <N|max>` > `MEGA_CLUSTER_WORKERS` env > `server.cluster` config 순으로 해석
67
+ (정수 N 또는 `max`=CPU 코어 수, 미설정/1=단일 프로세스, 0·음수·소수·문자열은 부팅 fail-fast). 마스터가
68
+ 워커 N개를 fork·respawn·graceful 협응하고 각 워커가 `bootApp`+listen(Node cluster 가 공유 소켓 분배,
69
+ `SO_REUSEPORT` 불필요). SIGTERM → 워커 drain → 마스터 exit 0. (ADR-154)
70
+ - **Bootstrap 5 뷰 디자인** — `mega new --views` 골격 · `sample/simple` · `sample/crud` 를 Bootstrap 5.3.8
71
+ (vendored, `public/vendor/bootstrap/` 에 dist min 커밋 — 신규 npm dep 아님)로 일관 디자인. navbar(브랜드 +
72
+ nav + 다크모드 토글 + 언어 메뉴) + hero/카드/테이블/폼, 다크모드(`data-bs-theme` + `localStorage`), 브랜드
73
+ CSS 변수 커스텀, i18n ko/en 토글(쿠키). `--views` 는 이제 GET / 를 뷰 렌더 라우트로 만들고 ko/en 로케일 +
74
+ i18n·staticAssets config 를 함께 생성한다. (ADR-151)
75
+ - **HTML 폼 바디 파싱 `@fastify/formbody`** — 서버사이드 뷰(`views.dir`)를 켠 앱은 폼 제출
76
+ (`application/x-www-form-urlencoded`)을 `req.body` 로 자동 파싱(MPA). JSON 전용 앱은 미등록(기존 JSON/text
77
+ 파싱 유지). 그동안 서버 뷰는 지원하나 폼 제출은 못 받던 코어 공백을 공식 플러그인으로 메움. (ADR-151)
78
+ - **`sample/crud` 관리 UI(MPA)** — JSON REST(`/users`)는 유지하고, Bootstrap 5 서버사이드 렌더 UI 를
79
+ `/admin/users*`(목록/신규/수정/삭제, PRG + CSRF 토큰 + 검증/충돌 폼 피드백)에 추가. (ADR-151)
80
+ - **마이그레이션 러너 `mega migrate`** — 그동안 generator 가 `apps/<app>/migrations/<ts>-<name>.js`(up/down)
81
+ 스텁만 만들고 실행 주체가 없던 갭(roadmap §267)을 메움. `mega migrate`(pending 일괄 up) ·
82
+ `mega migrate:down`(마지막 1개 롤백) · `mega migrate:status`(목록). 대상 DB 는 `services.databases`
83
+ globalKey(`--db`, 미지정 시 유일 db 또는 `primary`), 적용 이력은 대상 DB 의 `mega_migrations` 테이블,
84
+ 각 마이그레이션은 트랜잭션으로 감싸 원자 적용. SQL 어댑터(postgres/maria/sqlite) 대상. (ADR-149)
85
+ - **`ctx.services.<name>` 자동 서비스 DI** — 부팅 시 `apps/<app>/services/*.js` 를 자동 로드해 라우트
86
+ 핸들러·다른 서비스가 `ctx.services.<name>` / `this.services.<name>` 로 **요청별 lazy 인스턴스**(첫 접근 시
87
+ 생성·요청 내 캐시)를 받는다. 서비스 간 합성은 동일 인스턴스 공유, 생성 중 순환은 fail-fast 차단,
88
+ 미등록 이름은 `service.not_registered`. 이름 도출 `user-service.js`→`user`. 그동안 문서가 표준 CRUD
89
+ 패턴으로 기술했으나 런타임 미구현이던 갭을 메움(OQ-010 해결). Phase 7.5 `sample/crud` 진입 정독에서
90
+ 발견. (ADR-148)
91
+
92
+ ### Fixed
93
+
94
+ - **`sample/crud` `.gitignore` `logs/` 앵커 누락 → `views/logs/index.ejs` 추적 누락 정정 + 관측/가이드/perf 뷰 i18n fallback(ADR-175)** — `sample/crud/.gitignore` 의 `logs/` 가 leading slash 없이 작성돼 런타임 로그 디렉터리뿐 아니라 **`apps/main/views/logs/`(view 소스)까지 매칭**, logs 관측 데모 뷰가 git 에 한 번도 추적되지 않아 신선한 clone 에선 `GET /demo/logs` 가 500 이 되던 선재 결함을 발견·정정. 패턴을 `/logs/` 로 **앵커링**(루트 런타임 로그 무시 의도 보존 + view 소스 추적 복구, `git check-ignore` 양방향 재검증). 영향 source 는 이 뷰 1개뿐(전수 조사 확인). 동반으로 guide·perf·metrics·tracing·logs 뷰(6개) + 컨트롤러(5개)의 `t('key')` 호출에 **한국어 fallback 104개**를 채움(i18next 네이티브 **위치 인자** 형식 `t('key', '한국어')` — `i18n.js` 시그니처 + 같은 배치 sibling E-task 와 동일 컨벤션, 값은 정본 `locales/server/ko.json` 그대로 — ko.json 무변경, 동적 키는 fallback 인자를 표현식으로). 키가 이미 ko.json 에 있어 런타임 출력 불변 — fallback 은 키 누락 시 한국어로 떨어지는 안전망. sample `mega test` 125 그린(회귀 0, 편집 6뷰 전부 통합 테스트가 실제 렌더), 컨트롤러 eslint clean, framework src 무변경, 신규 dep 0.
95
+ - **세션 regenerate 구 sid 정리 silent catch 정정(ADR-172, P4)** — `src/core/session.js` 의
96
+ `regenerate()` 가 새 sid 저장 후 옛 sid 를 `store.destroy(oldSid).catch(() => {})` 로 정리하던
97
+ **빈 catch(silent 묵살)**를 `try/catch` + `logger.warn` 으로 교정(CLAUDE.md P4 — silent catch 금지).
98
+ 옛 sid 삭제 실패는 비치명적(새 sid 저장은 이미 성공, 옛 키는 TTL 만료/cleanup 이 회수)이라 응답은 막지
99
+ 않되 무로그 묵살은 금지 — 같은 파일 onSend rolling touch 실패와 동일한 best-effort+warn 패턴으로 가시화
100
+ (sid 는 hashSid 해시로 원본 비노출). 공개 계약 무변경, 신규 dep 0, 회귀 단위 +3.
101
+ - **세션/콘솔/트레이싱/멀티앱서버 로직 정확성 audit — `MegaServer.mount` 부분상태 원자화 + 3영역 결함 0(ADR-171)** —
102
+ `redis-session-adapter.js`·`console-cmd.js`·`mega-tracing.js`·`mega-server.js` 를 정본([ADR-129](docs/09-decisions-and-open-questions.md)/046·167·114/126·067)·형제 어댑터·호출부와 한 줄씩 대조. **[L] 1건 교정**: `MegaServer.mount` 가 host 충돌 throw 시 일부 host 만 `#hostMap` 에 박혀 부분 상태가 남던 것을 **2-pass(전체 충돌 사전검증 후에만 등록)**로 원자화 — 공개 계약(`config.host_collision` throw) 무변경, 내부 불변식만 강화. 나머지 3영역(redis-session·console-cmd·mega-tracing)은 정독 결과 **로직 결함 0**(redis-session 은 audit 된 cache 형제와 동일 connect/ping 전략, console 은 ADR-167 정정 정확, tracing 은 shutdown 멱등·run() 격리 정확). 결함 0 영역은 **계약 회귀가드**만 신설(redis-session fail-loud 에러경로 + mega-tracing 옵트인 OFF no-op 안전계약). 신규 단위 15·정본/외부 동작 무변경·신규 dep 0.
103
+ - **클러스터 메트릭/부팅 로직 정확성 audit — IPC 집계 프로토콜 무결성 확인 + 진단성 보강(ADR-170)** —
104
+ `cluster-metrics.js`·`boot.js` 를 한 줄씩 정독해 master↔worker IPC 집계(요청자 자기 포함·전원 회신 완료·죽은
105
+ 워커 제외·timeout 부분 합산·멱등 finishRound·로컬 폴백)와 부팅 시퀀스에 **로직 결함이 없음을 in-process 단위로
106
+ 확증**(결함 0). 진단성 보강 2건: `installPrimaryAggregator` 의 죽은 워커 send 실패를 silent skip 에서
107
+ `console.warn` surface(P4/P5), `formatValue` 사문화 분기 제거(동작 불변). fork/IPC 가 부모 v8 커버리지로
108
+ 측정 불가하던 공백은 `cluster`/`process` 주입 seam(ADR-165 패턴, 프로덕션 호출부 무변경) + boot 관측성 옵트인
109
+ 회귀 가드로 해소. 신규 단위 20·정본/외부 동작 무변경·신규 dep 0.
110
+ - **CLI 스캐폴드 E2E §345 색상 의존 회귀 — 실 터미널에서 그린인데 fail(ADR-169)** — `scaffold-e2e`
111
+ §345(생성물 vitest 그린 검증)가 자식 vitest 출력을 `/Test Files\s+\d+ passed/` 로 매칭하는데, vitest 4 는
112
+ `std-env isAgent` 가 false 인 환경(실 터미널)에서 색상을 켜 요약이 `Test Files \x1b[..m14 passed` 가 된다.
113
+ 그러면 정규식의 `\s+\d+` 가 숫자 앞 ANSI escape 에서 끊겨 **테스트는 통과(exit 0)했는데 매칭만 실패**했다(Claude
114
+ Code 세션은 `isAgent=true` 라 vitest 가 색을 꺼 plain → 통과, 그래서 잠복). 자식 spawn 에 표준 `NO_COLOR=1`
115
+ (no-color.org) 을 주입해 출력을 환경 독립 plain 으로 고정. 테스트 인프라만 수정·정본 무변경, 신규 dep 0.
116
+ - **CLI 진입점 로직 정확성 — `mega start --port`/`--host` fail-open 파싱 교정(ADR-168)** — `mega start` 가
117
+ `--port` 값을 `Number(flags.port)` 로 무검증 강등하던 결함을 fail-closed `resolvePort` 로 교정. 베어
118
+ `--port`(값 없음)는 `Number(true)=1` 로 **특권포트에 silent 시도**, `--port=`(빈 값)은 `Number('')=0` 으로 **OS
119
+ 랜덤포트에 silent bind**, `--port abc` 는 `NaN` 이 어댑터 connect 까지 부팅한 뒤 Node 가 `ERR_SOCKET_BAD_PORT`
120
+ 로 **늦게 cryptic throw** 하던 것을, 부팅 전 0~65535 정수 검증으로 즉시 명확히 throw(명시적 `--port 0` 랜덤포트는
121
+ 허용). `--host` 도 베어/빈 값을 `resolveHost` 로 fail-closed(빈 호스트가 Node `::` 전 인터페이스에 silent
122
+ bind 하던 것 차단). `resolveClusterWorkers`(ADR-154) 와 동형 패턴. 정본(ADR-123/146) 무변경·구현 결함 수정만,
123
+ 신규 단위 +13, 신규 dep 0.
124
+ - **CLI 명령 로직 정확성 — `mega test` 시그널 종료 오판·`mega routes` async 누락·`mega console` 종료 행 수정(ADR-167)** —
125
+ `mega test` 가 vitest 를 **시그널로 죽으면**(SIGKILL/OOM/timeout-kill) close code=null 을 `?? 0` 으로 받아 **테스트
126
+ 실패를 통과로 보고**하던 fail-closed 위반을 `128+signo`(bash 관례) 반환으로 교정. `mega routes` 는 `mod.default()` 를
127
+ await 하지 않아 **async 라우트 모듈**(`export default async (router) => {...}`)의 라우트가 출력에서 조용히 누락되던
128
+ 결함을 `await` 로 교정(실 loader 동형) + recording router 에 `app:null`·`statSync isFile` 가드 추가(`.js` 디렉토리
129
+ import 크래시 방지). `mega console` 은 REPL 종료(.exit/Ctrl-D) 시 graceful shutdown 이 없어 **어댑터/wsHub 열린
130
+ 핸들로 프로세스가 행**하고 어댑터가 미정리되던 결함을, `setupSignals(['SIGTERM'])` + REPL `'exit'` 이벤트→graceful
131
+ shutdown wiring 으로 교정(SIGINT 은 REPL 소유 유지). `src/cli/commands` 커버리지 branches 58.9%→87.95%·funcs
132
+ 60%→89.65%, 신규/보강 단위 +27. 정본(ADR-142) 무변경·구현 결함 수정만, 신규 dep 0.
133
+ - **텔레그램 sink 로직 정확성 — 메시지 유실 race·전송 행·worker 크래시 위험 수정(ADR-166)** — `RetryQueue.drain()`
134
+ 이 `readFile`→`writeFile('')` 로 큐를 비워 두 await 사이 끼어든 `append` 가 통째로 지워지던 **데이터 유실
135
+ race**(정본 "유실 0" 위반, 주석의 "원자적 truncate" 도 거짓)를 `rename` 단일 syscall claim 으로 교정(가로챈 뒤
136
+ 들어온 append 는 새 파일에 보존, 동시 drain 은 ENOENT→빈 배열, ENOENT 외 에러는 fail-loud). `httpsPost` 에
137
+ **요청 타임아웃**(무응답 연결이 retry 루프를 영구 정지시키던 결함) + **응답 스트림 error 핸들러**(unhandled 로
138
+ worker thread 가 죽던 위험) 추가. 더해 `telegramTransport` 에 `httpsRequest` 주입 seam(ADR-165 동일 패턴, 기본
139
+ `httpsPost` 라 프로덕션 무변경)을 둬 stream glue 를 worker thread 없이 단위 검증 — `src/lib/logger` 커버리지
140
+ 50.58%→99%(line 100%), 신규/보강 단위 +21. 로직 계약(ADR-141/023) 무변경·버그 수정만, 신규 dep 0.
141
+ - **업로드 다운로드 404 키 `upload.not_found` 의 locale 정리(`sample/crud`, ADR-163)** — dev `saveMissing`
142
+ ([ADR-037](docs/09-decisions-and-open-questions.md#adr-037-i18n--i18next--savemissing-axion-패턴))이 라이브 검증
143
+ 중 방치된 서버에서 `upload.not_found` 를 ko.json 에 영어값+테스트 파일명(`File 'itest-*.txt' not found.`)으로
144
+ 자동 기입한 오염을 ko 한국어값(`파일을 찾을 수 없습니다.`)으로 교정 + **en.json 에 누락돼 있던 `not_found`
145
+ parity 추가**(키 존재로 재오염 차단, `unsupported_media_type`·`too_large` 와 동일 패턴).
146
+ - **분산 트레이싱이 프로덕션 부팅에서 활성화되지 않던 결함** — `src/core/boot.js prepareRuntime` 가 메트릭
147
+ SDK(`MegaMetrics.init`)는 초기화하면서 **트레이싱 SDK(`MegaTracing.fromEnv`)는 어디서도 호출하지 않아**,
148
+ `MEGA_OTEL_ENABLED=true` 라도 `MegaTracing.isEnabled()`=false → mega-app 의 HTTP/WS 루트 span(ADR-126)이
149
+ 전부 스킵됐다(테스트만 수동 `init`). `prepareRuntime` 에 메트릭과 대칭으로 `MegaTracing.fromEnv()` +
150
+ `attachToManager`(어댑터 자동 span) + shutdown 등록을 추가(신규 dep 0). 라이브로 Zipkin 에 trace 전달
151
+ + `x-trace-id` 응답 헤더 실증. (ADR-163)
152
+ - **라우트 `before: [requireAuth]` 가 부팅 시 등록 거부되던 결함** — Fastify 는 async `preHandler` 의 arity 가
153
+ 3 이상이면 3번째를 콜백 `done` 으로 간주해 거부하는데, 인증 가드 `requireAuth`/`requireRole` 은
154
+ `(req, reply, ctx)` 로 arity 3 라 ADR-143 이 문서화한 라우트-레벨 `{ before: [requireAuth] }` 가 실제로는
155
+ 깨져 있었다(`transform`/`after` 는 래핑되나 `before` 만 raw 전달). 라우터가 각 `before` 를 arity-2 async
156
+ 래퍼 `(req, reply) => fn(req, reply)` 로 감싸 Fastify 계약에 맞춘다 — 순서·reply 단락 의미 불변. (ADR-156)
157
+ - **`sample/crud` 삭제 시 "생성 화면"이 뜨던 결함 (CSP 가 인라인 스크립트 차단)** — helmet 기본 CSP
158
+ (`script-src 'self'`)가 `list.ejs` 의 인라인 삭제-모달 wiring 스크립트 실행을 막아, `deleteForm` 의 action 이
159
+ 설정되지 않고 현재 URL(`/admin/users`)로 POST → `POST /admin/users`(생성)로 가 신규 폼이 검증 오류로
160
+ 재렌더됐다. 같은 이유로 다크모드도 새로고침 후 유지 안 됨. CSP 를 약화하지 않고 클라 JS 를 외부 파일로
161
+ 분리: 모달 wiring 은 `app.js`(트리거 버튼 `data-action`/`data-name`), 테마 초기화는 `theme-init.js`(<head>).
162
+ crud/simple/templates + `mega new --views` 생성물에 적용. 삭제 정상 동작·다크모드 유지 브라우저 검증. (ADR-153)
163
+ - **`mega` CLI 가 프로젝트 `.env` 를 로드하지 않던 결함** — `mega start`/`worker`/`scheduler`/`migrate` 등이
164
+ `.env` 를 `process.env` 로 올리지 않아, `mega.config.js` 의 `process.env.DATABASE_URL` 류가 비어 부팅이
165
+ 실패했다(`cp .env.example .env && npm start` 워크플로가 깨짐). CLI 가 프로젝트 루트(`--root`/cwd)의 `.env` 를
166
+ Node 내장 `process.loadEnvFile`(dep 0)로 자동 로드하도록 수정 — config 로드 전, 런타임 명령에 한해. 이미 설정된
167
+ 실 환경변수는 덮어쓰지 않음(실 env 우선). `engines.node`>=20.6.0. `yarn mega start` 실패 보고에서 발견. (ADR-152)
168
+ - **`sample/crud` 의 이메일 중복 수정이 500 으로 뭉개지던 결함** — `UserService.update()` 가 `create()` 와
169
+ 달리 postgres unique_violation(`23505`)을 매핑하지 않아, 이미 쓰인 이메일로 수정 시(JSON `PUT /users/:id` ·
170
+ 관리 UI 모두) raw DB 에러가 500 으로 떨어졌다. `create()` 처럼 `MegaConflictError(409, user.email_taken)` 로
171
+ 매핑하도록 보강. MPA UI 진입(ADR-151) 검증에서 발견. (ADR-151)
172
+ - **CLI 런타임 부팅이 빌트인 어댑터 driver 를 등록하지 못하던 결함** — `mega start`/`worker`/
173
+ `scheduler`/`migrate` 가 빌트인 DB(postgres 등)를 쓰면 `Unknown adapter driver "postgres"` 로 실패했다.
174
+ 빌트인 어댑터는 `src/adapters/index.js` 배럴 import 시 자기등록(ADR-044)하는데, CLI 부팅 경로가 그
175
+ 배럴을 import 하지 않아 `buildFromGlobalConfig` 시점에 driver 가 미등록이었다. `boot.js` 가 배럴을
176
+ side-effect import 하도록 수정. Phase 7.5 `sample/crud` E2E 에서 발견. (ADR-150)
177
+ - **스캐폴드 라우트 핸들러 예시의 envelope `ok` 중복** — `mega new` 생성 핸들러가
178
+ `{ ok: true, message }` 를 반환해 자동 envelope(ADR-018)이 한 번 더 감싸며
179
+ `{ ok:true, data:{ ok:true, message }, meta }` 로 `ok` 가 이중 노출됐다. 핸들러는 도메인 데이터만
180
+ 반환하도록 정정(`{ message }`) → 응답이 단일 `ok` 의 `{ ok:true, data:{ message }, meta }` 로 복구.
181
+ 외부 사용자 첫 예시가 올바른 패턴(핸들러=raw data, envelope=framework 책임)을 가르친다.
182
+ Phase 7.5 `sample/simple` E2E 에서 발견. 이중 wrap 회귀 가드 추가. (ADR-147)
183
+ - **`mega start` 가 `server.port`/`server.host` 정본 config 를 무시하던 결함** — `bootApp` 이
184
+ `global.server.{port,host}` 를 listen 배선에 반영하지 않아 `PORT` 환경변수·`mega.config.js` 의
185
+ `server.port` 가 죽고 `--port` 플래그만 동작했다. CLI 인자 우선 + config 폴백으로 정본
186
+ ([04-data-models §183](docs/04-data-models.md)) 계약 복구. Phase 7.5 `sample/simple` E2E 에서 발견. (ADR-146)
187
+
188
+ ### Changed
189
+
190
+ - **`MegaCluster` 커버리지 33%→100% — cluster/process 주입 seam + in-process 단위 테스트(ADR-165)** —
191
+ `src/core/mega-cluster.js` 의 낮은 커버리지(라인 35%·함수 47%·분기 40%)의 원인은 테스트 부족이 아니라
192
+ **fork 자식 프로세스가 vitest coverage-v8(부모 프로세스만 instrument)에 안 잡히는 측정 한계**였다(마스터/워커
193
+ 로직은 이미 6개 fork 통합 테스트가 실제 `child_process` 로 검증). 생성자에 `_cluster`(기본 `node:cluster`)·
194
+ `_proc`(기본 전역 `process`) 주입 seam 을 추가해 fork 루프·워커 exit 핸들러·respawn backoff·워커 message
195
+ 핸들러를 fake 주입으로 부모 프로세스 안에서 단위 검증한다. 기본값=실 모듈 → 런타임·기존 통합 테스트 동작 무변경.
196
+ 결과: mega-cluster.js **라인 100%·함수 100%·분기 93.47%**, 신규 단위 13건(`npm test` 1705→1718). 신규 dep 0.
197
+ - **`.env.example` 전수 정비(root)** — framework 가 직접 읽는 키 + docker-compose 인프라 + 관측성 키를
198
+ 누락 없이 정리하고 정본(ADR/docs) cross-ref 를 붙였다. 신규: docker 트레이싱 백엔드 포트(`MEGA_ZIPKIN_PORT`·
199
+ `MEGA_OTEL_OTLP_GRPC_PORT`·`MEGA_OTEL_OTLP_HTTP_PORT`·`MEGA_OTEL_HEALTH_PORT`, ADR-128) + Prometheus
200
+ 메트릭 섹션(`METRICS_ENABLED`/`MEGA_METRICS_*`, ADR-072/131·docs/INFRA §7). 정정: `LOG_LEVEL`·
201
+ `TG_BOT_TOKEN`·`TG_CHAT_ID` 는 framework 가 `process.env` 로 읽지 않는 키라(로그 레벨·sink 는
202
+ `mega.config.js` 의 `logger` 블록에서 설정) 주석 처리 + 와이어링 노트로 정정 — 오해 소지 제거. sample 의
203
+ `.env.example`(simple·crud)은 각 sample 이 실제 쓰는 키를 이미 전부 담고 있어 무변경. framework 정본
204
+ 코드 무변경(문서 전용), 신규 dep 0.
205
+ - **i18n `saveMissing` 누락 키를 모든 available 언어에 자동 생성 + 언어 간 키 parity 보정(ADR-164)** — dev 에서
206
+ 미존재 키를 부르면 과거엔 **현재 언어에만**(`saveMissingTo:'current'`) 기입해 나머지 언어엔 키가 없어 매 요청
207
+ 재트리거되며 ko.json 이 무한 재오염됐다(ADR-163 함정). 이제 `missingKeyHandler` 가 **설정된 모든 `cfg.available`
208
+ 언어**(예: ko·en) 파일에 그 키를 자동 생성한다 — 값은 `defaultValue`, **없으면 키 이름**. 또한 init 시
209
+ `reconcileLocaleKeys` 가 **한 언어에만 있는 키**(예: en 에만 있고 ko 없음 — i18next 가 fallback 으로 찾아
210
+ missingKeyHandler 가 안 터지던 공백)를 나머지 언어에 **fallback 값 우선**으로 채운다(nested 포함). 키가 전 언어에
211
+ 존재해 재트리거(재오염 루프)가 끊긴다. **자동 기입은 `NODE_ENV==='development'` 에서만**(기존 `!=='production'`
212
+ 은 test/CI/미설정에서도 켜져 `mega test` 가 추적 locale 파일을 디스크 기입·손상시키던 함정 — dev 로 좁힘). 통합
213
+ 2건 보강, `npm test` 1705/3skip, sample 실행 후 locale 오염 0.
214
+ - **프로젝트 템플릿 `vitest` `^2.0.0` → `^4.0.0`** — `mega new` 생성물이 프레임워크(ADR-145, 4.1.8)와
215
+ 정합되도록 갱신. 생성 직후 `npm audit` 취약점(구 vitest 2.x 체인) 해소. (ADR-146)
216
+
217
+ ### Security
218
+
219
+ - **`vitest` 2.1.9 → 4.1.8 major bump** — `npm audit` 6건(critical 2 + moderate 4,
220
+ `vitest`/`vite`/`esbuild` dev 전용 체인) 전부 해소(audit 0). 회귀 0(1634 그린 / 3 skip
221
+ 유지), typecheck·lint 0. (ADR-145)
222
+
223
+ ### Changed
224
+
225
+ - **`package.json` `repository` 필드 추가** — npm publish 시 repository 링크 노출. (B2)
226
+
227
+ ## [0.1.0] - 2026-06-06
228
+
229
+ 첫 공개 릴리즈. Phase 0~6 의 산출물 — 멀티앱 HTTP/WS 런타임, 데이터 어댑터, 잡/스케줄러/워커, 세션·보안·
230
+ i18n·트레이싱·메트릭, 그리고 **CLI 스캐폴드 + 코드 generator** 를 포함한다.
231
+
232
+ ### Added
233
+
234
+ - **CLI 스캐폴드 (`mega new`)** — 빈 폴더에서 멀티앱 hello world 까지 한 명령. 기본 앱 `main`,
235
+ `*.localhost` 호스트, `package.json`(scripts + `concurrently` + PM2 `ecosystem.config.cjs`),
236
+ `README` · `.env.example` · `.gitignore` · `vitest.config.js` 생성. `--views` 로 EJS + ejs-mate
237
+ 뷰 골격 옵트인(대화형 prompts 지원). (ADR-142)
238
+ - **코드 generator 13종 (`mega g <kind> <name>`)** — app · controller · channel · service · model ·
239
+ middleware · route · schedule · job · worker · locale · adapter · migration. **코드 + 테스트 동시
240
+ 생성**(ADR-012), 멀티앱 인지(`--app`, 기본 main), `mega g controller --version=v2`(ADR-069),
241
+ `mega g adapter --kind=db|cache|bus|session|log`. 생성물은 즉시 ESLint 통과 + vitest 그린. (ADR-142)
242
+ - **CLI 명령 추가** — `mega routes`(라우트 트리 출력) · `mega test`(vitest 래퍼) · `mega console`
243
+ (앱 컨텍스트 REPL). (ADR-142)
244
+ - **`mega-framework/auth`** — 세션 기반 인증 가드 `requireAuth` / `requireRole`. (ADR-143)
245
+ - **`mega-framework/test`** — 단위 테스트 fixture 헬퍼 `MegaTest`(`makeHttp` / `makeWs` /
246
+ `mockBus` / `mockCache`). (ADR-144)
247
+ - **`package.json` exports 맵** — `mega-framework` · `/lib` · `/errors` · `/auth` · `/test` ·
248
+ `/eslint-plugin` 서브패스 공개(ADR-080 계약 실행).
249
+ - `ctx.user` — 인증 가드가 채우는 요청 사용자(canonical ctx 필드).
250
+
251
+ ### Changed
252
+
253
+ - CLI 파서로 `commander`, 대화형 입력으로 `prompts` 채택(scaffold/dev 명령군). 런타임 명령
254
+ (start/worker/scheduler/plugin)은 기존 zero-dep 파싱(ADR-123) 유지. (ADR-142 — ADR-123 의
255
+ zero-dep CLI 결정 개정)
256
+ - `version` 0.0.1 → 0.1.0.
257
+
258
+ [Unreleased]: https://git.example.com/mega-framework/compare/v0.1.0...HEAD
259
+ [0.1.0]: https://git.example.com/mega-framework/releases/tag/v0.1.0