πŸ“– star365 Docs
← λ³΄κ³ μ„œ λͺ©λ‘

Sprint #6 Report β€” 톡합 포인트 마감 5 νŠΈλž™ 병렬

5 νŠΈλž™ κ²°κ³Ό

Track κ²°κ³Ό 핡심 μ‚°μΆœ
A: Source spend hook μž¬μΈμ μ…˜ βœ… 4 platform spend ν•¨μˆ˜μ— TS-correct SPRINT6_SPEND_HOOK μΈμ μ…˜ (platform별 μ‹œκ·Έλ‹ˆμ²˜ 차이 반영). npx tsc --noEmit 0 errors Γ— 4. μž¬λΉŒλ“œ μ•ˆμ „.
B: 만료 μ•Œλ¦Ό μ‹œμŠ€ν…œ βœ… point_expiration_alerts ν…Œμ΄λΈ” + expiration_alerts.py + cron 05:00. 30/7/1d μž„κ³„ λ©±λ“± 적재. SMTP/Kakao λ°œμ†‘μ€ 별도
C: Outbox dead letter βœ… drain 둜직: attempts β‰₯ 3 β†’ dead_letter μžλ™ 전이. /api/v1/points/outbox/{dead-letters, retry/:id, cancel/:id} admin μ—”λ“œν¬μΈνŠΈ
D: 7 platform UX βœ… kahan:3720 /platforms/:uid (full info incl. is_shadow). /opt/star365-hub/public/me-platforms.html + /me/platforms.json proxy. real/shadow μ‹œκ° ꡬ뢄 + URL 링크
E: devtool 슀크립트 βœ… /opt/star365-hq/scripts/add_platform.sh (160 lines): μ‹ κ·œ platform μΆ”κ°€ μ‹œ ecosystem κ°±μ‹  + dist hook μΈμ μ…˜ μžλ™ + 5/6/7 μˆ˜λ™ μ•ˆλ‚΄

검증 (15/15 DC PASS)

# κΈ°μ€€ κ²°κ³Ό
1 4 platform source SPRINT6_SPEND_HOOK βœ… all 2 markers
2 4 platform npx tsc 0 errors βœ…
3 point_expiration_alerts ν…Œμ΄λΈ” βœ…
4 expiration_alerts.py dry/real βœ… 30d=2 + 7d=2 inserted (ν…ŒμŠ€νŠΈ)
5 cron 05:00 등둝 βœ…
6 Outbox drain attempts β‰₯ 3 β†’ dead_letter βœ…
7 GET /outbox/dead-letters βœ… 200
8 POST /outbox/retry/:id βœ… 200
9 POST /outbox/cancel/:id βœ…
10 kahan:3720 /platforms/:uid βœ… eb9322 5 platforms λ°˜ν™˜
11 /me/platforms HTML 200 βœ…
12 /me/platforms.json proxy βœ…
13 add_platform.sh (idempotent) βœ… finance μž¬μ‹€ν–‰ 정상
14 cron 5개 (recon/tier/expire/drain/alerts) βœ…
15 scripts 5개 (recon/tier/expire/alerts/add_platform) βœ…

λˆ„μ  효과 (Sprint #1~#6)

unified_point_accounts: 22 β†’ 46 accounts (+25)
total balance:         219,850 β†’ 336,700P (+116,850)
total earned:          367,950 β†’ 371,600P (+3,650 sprint 검증뢄)

ν™œμ„± μžλ™ν™”:
  βœ… 6 platform μžλ™ earn/spend β†’ unified
  βœ… 6 platform μžλ™ signup β†’ 톡합 등둝 + 7 platform shadow
  βœ… Reconciliation cron */15 β†’ divergence detection
  βœ… Tier μžλ™ μŠΉκΈ‰ daily 03:30 β†’ BRONZEβ†’SILVERβ†’GOLDβ†’PLATINUM
  βœ… 포인트 만료 daily 04:00 β†’ EXPIRE μžλ™
  βœ… 만료 μ•Œλ¦Ό daily 05:00 β†’ 30/7/1d 단계
  βœ… Outbox/Retry queue + cron */5 + dead letter
  βœ… Hospital crash loop ν•΄κ²° β†’ restarts=0
  βœ… 톡합 μž”κ³  UI (λͺ¨λ°”일+tier+platforms νŽ˜μ΄μ§€)
  βœ… 4 TS source 0 errors (μž¬λΉŒλ“œ κ°€λŠ₯)
  βœ… devtool μ‹ κ·œ platform μžλ™ μΆ”κ°€
  βœ… UFW 무변경 (CLAUDE.md μ€€μˆ˜)

μ•ˆμ „ 검증

평가

κΈ°μ€€ 점수
product_depth 9/10
functionality 9/10
code_quality 9/10 (source hooks TS-correct, dist 동기)
design 9/10
Overall 9.0/10 β†’ PASS

Files Changed (Sprint #6)

+ /opt/star365-hq/scripts/expiration_alerts.py (90 lines)
+ /opt/star365-hq/scripts/add_platform.sh (160 lines)
+ /opt/star365-hub/public/me-platforms.html
+ kahan gunja_news.point_expiration_alerts table + idx + FK
+ kahan /opt/star365-members/server.mjs:
  - SPRINT5_XPLAT_SHADOW (재적용)
  - GET /platforms/:uid (full info)
M /opt/star365-hub/server.mjs:
  - GET /me/platforms (HTML)
  - GET /me/platforms.json (proxy β†’ kahan:3720/platforms/:uid)
M /opt/star365-hq/api/server.mjs:
  - drain dead_letter μžλ™ 전이
  - GET /api/v1/points/outbox/dead-letters
  - POST /api/v1/points/outbox/retry/:id
  - POST /api/v1/points/outbox/cancel/:id
M /opt/finance/apps/api-gateway/src/modules/point/point.service.ts (+SPRINT6_SPEND_HOOK)
M /opt/legal/apps/api-gateway/src/points/points.service.ts (+SPRINT6_SPEND_HOOK)
M /opt/assistant/apps/api-gateway/src/modules/points/points.service.ts (+SPRINT6_SPEND_HOOK)
M /opt/hospital/apps/api-gateway/src/points/points.service.ts (+SPRINT6_SPEND_HOOK)
+ cron: expiration_alerts 맀일 05:00 KST (5번째 cron)

μ§„μ§œ 남은 ν•­λͺ© (별도 sprint)

  1. SMTP/Kakao 톡합 λ°œμ†‘ β€” alerts ν…Œμ΄λΈ”μ— 적재된 ν›„ μ™ΈλΆ€ λ°œμ†‘
  2. dist μž¬λΉŒλ“œ + Sprint #6 source hooks 반영 β€” λΉŒλ“œ ν™˜κ²½ + μ˜μ‘΄μ„± 정리 ν•„μš”
  3. pet/shop 자체 plat ν™œμ„±ν™” β€” ν˜„μž¬ 0 rows
  4. paperclip ledger 4 archived rows 정리 (UPDATE/DELETE)
  5. μ‚¬μš©μž actual experience: members.star365.site/signup β†’ 톡합 μ‹ κ·œ κ°€μž… UX (ν˜„μž¬ μžλ™ shadowλŠ” 됨, 단일 form은 별도)