dubs-server 1.0.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 (304) hide show
  1. package/.claude/settings.local.json +280 -0
  2. package/CLAUDE.md +46 -0
  3. package/CONNECT4_PRODUCTION_DEPLOY.md +155 -0
  4. package/CURRENT_SESSION.md +171 -0
  5. package/CURRENT_SESSION_DRAW.md +516 -0
  6. package/MARCH_MADNESS_SURVIVOR.md +254 -0
  7. package/PANDA.md +166 -0
  8. package/Procfile +4 -0
  9. package/README.md +476 -0
  10. package/controllers/livescoresController.js +376 -0
  11. package/controllers/pickemController.js +554 -0
  12. package/controllers/survivorAdminController.js +887 -0
  13. package/controllers/survivorController.js +623 -0
  14. package/cron/oracleMonitor.js +77 -0
  15. package/cron/pickemOracleMonitor.js +73 -0
  16. package/data/jackpot-history.json +952 -0
  17. package/data/ncaaTeams.js +406 -0
  18. package/documentation/API_SECURITY_GUIDE.md +327 -0
  19. package/documentation/ARCADE_API.md +593 -0
  20. package/documentation/ARCADE_IMPLEMENTATION_SUMMARY.md +399 -0
  21. package/documentation/ARCADE_QUICKSTART.md +242 -0
  22. package/documentation/AUTOMATIC_MODE_ORACLE.md +321 -0
  23. package/documentation/BUG_FIX_COHORT_DATE_DISPLAY.md +171 -0
  24. package/documentation/CLAIM_MIGRATION_INSTRUCTIONS.md +52 -0
  25. package/documentation/CLAIM_STATUS_FIX.md +67 -0
  26. package/documentation/CLI_TOOL_GUIDE.md +372 -0
  27. package/documentation/COHORT_RETENTION_ANALYSIS.md +295 -0
  28. package/documentation/COHORT_RETENTION_IMPLEMENTATION_COMPLETE.md +461 -0
  29. package/documentation/COHORT_RETENTION_SUMMARY.md +204 -0
  30. package/documentation/COMPLETE_PROJECT_SUMMARY.md +490 -0
  31. package/documentation/DATABASE_QUERIES.md +269 -0
  32. package/documentation/DATABASE_RETENTION_POLICY.md +390 -0
  33. package/documentation/DATABASE_SETUP_GUIDE.md +361 -0
  34. package/documentation/DATABASE_SETUP_SUMMARY.md +247 -0
  35. package/documentation/DEMO_API_CURL_COMMANDS.md +656 -0
  36. package/documentation/DEPLOYMENT_SUMMARY.txt +100 -0
  37. package/documentation/DUPLICATE_NOTIFICATIONS_FIXED.md +201 -0
  38. package/documentation/EXCHANGE_RATES_INTEGRATION.md +371 -0
  39. package/documentation/FINAL_API_PROTECTION_TABLE.md +175 -0
  40. package/documentation/GAME_START_NOTIFICATIONS_DEPLOYMENT.md +256 -0
  41. package/documentation/GAME_START_NOTIFICATIONS_INTEGRATION.md +275 -0
  42. package/documentation/HEROKU_DEPLOYMENT.md +134 -0
  43. package/documentation/HEROKU_SCHEDULER_SETUP.md +271 -0
  44. package/documentation/JACKPOT_API.md +521 -0
  45. package/documentation/JACKPOT_DEPLOYMENT_GUIDE.md +362 -0
  46. package/documentation/JWT_IMPLEMENTATION_SUMMARY.md +373 -0
  47. package/documentation/JWT_QUICK_SETUP.md +268 -0
  48. package/documentation/JWT_TESTING_GUIDE.md +404 -0
  49. package/documentation/KEEPER_RECOVERY_GUIDE.md +381 -0
  50. package/documentation/KEEPER_SETUP.md +206 -0
  51. package/documentation/KEEPER_STATE_MACHINE.md +423 -0
  52. package/documentation/LATEST_PRODUCTION_SETUP.md +387 -0
  53. package/documentation/LOCAL_VOTING_TEST.md +279 -0
  54. package/documentation/ORACLE_FIXES_SUMMARY.md +188 -0
  55. package/documentation/ORACLE_POSTGRESQL_UPDATE.md +202 -0
  56. package/documentation/PAYMENT_DEPLOYMENT.md +209 -0
  57. package/documentation/PNL_TRACKING_SETUP.md +189 -0
  58. package/documentation/PREVENTING_LOCKUP_ERRORS.md +472 -0
  59. package/documentation/PRODUCTION_READY_SUMMARY.md +227 -0
  60. package/documentation/PUBLIC_VS_PRIVATE_ENDPOINTS.md +278 -0
  61. package/documentation/QUICK_AUTH_SETUP.md +99 -0
  62. package/documentation/QUICK_DEPLOY.md +224 -0
  63. package/documentation/QUICK_FIX.md +114 -0
  64. package/documentation/QUICK_START.md +152 -0
  65. package/documentation/REFEREE_MODE_GUIDE.md +392 -0
  66. package/documentation/RETENTION_CORE_ACTION_UPDATE.md +313 -0
  67. package/documentation/RETENTION_UPDATE_SUMMARY.md +108 -0
  68. package/documentation/RUN_MIGRATION_NOW.md +39 -0
  69. package/documentation/SCRIPTS_UPDATE_SUMMARY.md +251 -0
  70. package/documentation/SETUP_GUIDE.md +184 -0
  71. package/documentation/STATE_MACHINE_IMPLEMENTATION.md +250 -0
  72. package/documentation/TELEGRAM_NOTIFICATIONS_DIAGNOSIS.md +361 -0
  73. package/documentation/UNIFIED_ARCHITECTURE.md +231 -0
  74. package/documentation/VOTING_DEPLOYMENT_SUMMARY.md +392 -0
  75. package/documentation/WEBSOCKET_ARCHITECTURE.md +881 -0
  76. package/documentation/WHAT_WE_BUILT_TODAY.md +369 -0
  77. package/documentation/latest/LATEST_PRODUCTION_SETUP.md +865 -0
  78. package/ecosystem.config.js +65 -0
  79. package/env.template +125 -0
  80. package/middleware/apiKeyAuth.js +136 -0
  81. package/middleware/authenticate.js +214 -0
  82. package/middleware/developerUserAuth.js +76 -0
  83. package/middleware/socketAuth.js +69 -0
  84. package/package.json +49 -0
  85. package/postman/Dubs-API-v1-With-Voting.postman_collection.json +555 -0
  86. package/postman/Dubs-API-v1.postman_collection.json +205 -0
  87. package/postman/Dubs_Developer_API.postman_collection.json +662 -0
  88. package/postman/QUICKSTART.md +118 -0
  89. package/postman/QUICK_REFERENCE.md +246 -0
  90. package/postman/README.md +71 -0
  91. package/postman/VOTING_API_GUIDE.md +426 -0
  92. package/refactor/Animations.md +148 -0
  93. package/refactor/Chat.md +252 -0
  94. package/routes/actionsRoutes.js +699 -0
  95. package/routes/adminRoutes.js +370 -0
  96. package/routes/analyticsRoutes.js +1262 -0
  97. package/routes/arcadeRoutes.js +557 -0
  98. package/routes/authRoutes.js +2310 -0
  99. package/routes/avatarRoutes.js +85 -0
  100. package/routes/botRoutes.js +211 -0
  101. package/routes/chatRoutes.js +377 -0
  102. package/routes/cryptoPriceRoutes.js +105 -0
  103. package/routes/developerRoutes.js +4201 -0
  104. package/routes/deviceRoutes.js +214 -0
  105. package/routes/dmRoutes.js +167 -0
  106. package/routes/esportsRoutes.js +806 -0
  107. package/routes/exchangeRateRoutes.js +233 -0
  108. package/routes/gamesRoutes.js +3028 -0
  109. package/routes/jackpotRoutes.js +754 -0
  110. package/routes/keeperMonitoringRoutes.js +156 -0
  111. package/routes/keeperWebhookRoutes.js +466 -0
  112. package/routes/livescoresRoutes.js +31 -0
  113. package/routes/pickemAdminRoutes.js +199 -0
  114. package/routes/pickemRoutes.js +231 -0
  115. package/routes/playerStatsRoutes.js +147 -0
  116. package/routes/portfolioRoutes.js +217 -0
  117. package/routes/promoRoutes.js +418 -0
  118. package/routes/referralEarningsRoutes.js +392 -0
  119. package/routes/socialRoutes.js +459 -0
  120. package/routes/sportsRoutes.js +1271 -0
  121. package/routes/survivorAdminRoutes.js +345 -0
  122. package/routes/survivorRoutes.js +756 -0
  123. package/routes/uploadRoutes.js +256 -0
  124. package/routes/userProfileRoutes.js +244 -0
  125. package/routes/whatsNewRoutes.js +331 -0
  126. package/scripts/.claude/settings.local.json +15 -0
  127. package/scripts/README.md +170 -0
  128. package/scripts/RESTART_EVERYTHING.sh +104 -0
  129. package/scripts/add-claim-columns.sql +48 -0
  130. package/scripts/add-crypto-prices-cache.sql +27 -0
  131. package/scripts/add-exchange-rates-cache.sql +40 -0
  132. package/scripts/add-game-invite-column.sql +23 -0
  133. package/scripts/add-game-invite-notification.sql +33 -0
  134. package/scripts/add-game-invite-telegram-pref.sql +16 -0
  135. package/scripts/add-game-joined-notification.sql +16 -0
  136. package/scripts/add-game-joined-pref.js +40 -0
  137. package/scripts/add-game-joined-preference.sql +6 -0
  138. package/scripts/add-game-start-notifications.sql +41 -0
  139. package/scripts/add-notification-flags-to-games.sql +55 -0
  140. package/scripts/add-pending-game-dismissals.sql +19 -0
  141. package/scripts/add-preferred-currency.sql +34 -0
  142. package/scripts/add-winner-columns.js +61 -0
  143. package/scripts/add_mention_system.sql +53 -0
  144. package/scripts/add_payment_system.sql +96 -0
  145. package/scripts/add_sports_event_id_column.sql +22 -0
  146. package/scripts/analyze-cohort-data-heroku.js +276 -0
  147. package/scripts/analyze-cohort-data.js +295 -0
  148. package/scripts/analyze-prod-cohorts.sh +10 -0
  149. package/scripts/backfill-matchup-images.js +245 -0
  150. package/scripts/backfill-missing-signatures.js +175 -0
  151. package/scripts/backfill-referral-earnings.js +202 -0
  152. package/scripts/check-chat-schema.js +130 -0
  153. package/scripts/check-db.sh +14 -0
  154. package/scripts/check_oracle_in_game.js +54 -0
  155. package/scripts/cleanup-database.js +193 -0
  156. package/scripts/clear-notification-cache.js +85 -0
  157. package/scripts/convert-mnemonic.js +50 -0
  158. package/scripts/create-users-table.sql +44 -0
  159. package/scripts/debug-cohort-counts.js +248 -0
  160. package/scripts/debug-winner-calc.js +84 -0
  161. package/scripts/deploy-payment-system.sh +118 -0
  162. package/scripts/deploy-to-heroku.sh +63 -0
  163. package/scripts/diagnose-locked-round.js +143 -0
  164. package/scripts/dubs-cli.js +720 -0
  165. package/scripts/dump-account.js +65 -0
  166. package/scripts/find-vrf-offset.js +48 -0
  167. package/scripts/fix-chat-notifications-constraint.sql +122 -0
  168. package/scripts/fix-claim-columns.js +124 -0
  169. package/scripts/fix-constraint-now.js +44 -0
  170. package/scripts/fix-lock-timestamps.js +96 -0
  171. package/scripts/fix-locked-round.sh +126 -0
  172. package/scripts/fix-missing-badges.sql +91 -0
  173. package/scripts/fix-payment-notifications.sql +41 -0
  174. package/scripts/force-new-round.js +55 -0
  175. package/scripts/force-resolve-and-claim.js +278 -0
  176. package/scripts/important/README.md +115 -0
  177. package/scripts/important/authority-force-lock.js +197 -0
  178. package/scripts/important/authority-resolve-game.js +267 -0
  179. package/scripts/important/check-game-status.js +373 -0
  180. package/scripts/important/list-pending-games-by-version.js +270 -0
  181. package/scripts/important/reconcile-v1-v2-payouts.js +270 -0
  182. package/scripts/initialize-jackpot.js +111 -0
  183. package/scripts/jackpot/.claude/settings.local.json +10 -0
  184. package/scripts/jackpot/force-reset.js +84 -0
  185. package/scripts/jackpot/initialize-mainnet.js +100 -0
  186. package/scripts/jackpot/keeper.js +742 -0
  187. package/scripts/jackpot/status.js +107 -0
  188. package/scripts/jackpot/update-round-duration.js +143 -0
  189. package/scripts/keeper-bot.js +112 -0
  190. package/scripts/list-pending-games.js +131 -0
  191. package/scripts/migrate-chat-v2.js +127 -0
  192. package/scripts/migrate-chat-winners.js +84 -0
  193. package/scripts/migrate-chat.sh +17 -0
  194. package/scripts/migrate-game-invite.js +83 -0
  195. package/scripts/migrate-heroku-game-notifications.sh +159 -0
  196. package/scripts/migrations/001_analytics_tables.sql +422 -0
  197. package/scripts/migrations/002_add_matchup_image_url.sql +14 -0
  198. package/scripts/migrations/003_referral_earnings.sql +208 -0
  199. package/scripts/migrations/004_add_whats_new_notification_type.sql +62 -0
  200. package/scripts/migrations/005_add_connect4_your_turn_notification.sql +61 -0
  201. package/scripts/migrations/005_push_notifications.sql +55 -0
  202. package/scripts/migrations/006_add_draw_team_players.sql +28 -0
  203. package/scripts/migrations/006_add_game_cancelled_notification.sql +62 -0
  204. package/scripts/migrations/007_add_gif_url.sql +8 -0
  205. package/scripts/migrations/008_add_connect4_columns.sql +139 -0
  206. package/scripts/migrations/008_add_pool_tracking.sql +22 -0
  207. package/scripts/migrations/009_create_survivor_pool_tables.sql +174 -0
  208. package/scripts/migrations/010_add_survivor_pool_outcome.sql +28 -0
  209. package/scripts/migrations/011_create_developer_tables.sql +67 -0
  210. package/scripts/migrations/011_fix_keeper_tables.sql +85 -0
  211. package/scripts/migrations/012_create_developer_webhooks.sql +31 -0
  212. package/scripts/migrations/013_add_network_mode.sql +18 -0
  213. package/scripts/migrations/014_create_developer_app_users.sql +19 -0
  214. package/scripts/migrations/015_add_ui_config.sql +4 -0
  215. package/scripts/migrations/016_add_resolution_secret.sql +4 -0
  216. package/scripts/migrations/017_add_external_game_id.sql +3 -0
  217. package/scripts/migrations/018_create_pickem_tables.sql +115 -0
  218. package/scripts/migrations/019_expo_push_tokens.sql +19 -0
  219. package/scripts/migrations/create_whats_new_tables.sql +88 -0
  220. package/scripts/migrations/drop_live_games_tables.sql +34 -0
  221. package/scripts/open-jackpot-round.js +85 -0
  222. package/scripts/purge-all-data.sh +329 -0
  223. package/scripts/purge-all-data.sql +142 -0
  224. package/scripts/purge-heroku-data.sh +149 -0
  225. package/scripts/purge-heroku-data.sql +62 -0
  226. package/scripts/rebuild-heroku-database.sh +113 -0
  227. package/scripts/recover-funds.js +357 -0
  228. package/scripts/regenerate-epl-images.js +278 -0
  229. package/scripts/resize-s3-matchup-images.js +374 -0
  230. package/scripts/resolve-direct.js +88 -0
  231. package/scripts/resolve-mock-game.js +124 -0
  232. package/scripts/resolve-pickem-game.js +55 -0
  233. package/scripts/resolve-round-manual.js +83 -0
  234. package/scripts/resolve-stuck-game.js +382 -0
  235. package/scripts/resolve-stuck-round.js +42 -0
  236. package/scripts/run-connect4-migration.sh +16 -0
  237. package/scripts/run-mention-migration.sh +32 -0
  238. package/scripts/run-payment-migration.sh +51 -0
  239. package/scripts/run-preferred-currency-migration.sh +31 -0
  240. package/scripts/run-referral-earnings-migration.sh +32 -0
  241. package/scripts/run-survivor-outcome-migration.sh +16 -0
  242. package/scripts/seed-test-users.js +346 -0
  243. package/scripts/setup-auth-tables.js +78 -0
  244. package/scripts/setup-complete-database.sql +992 -0
  245. package/scripts/setup-database-fresh.sh +359 -0
  246. package/scripts/setup-heroku-keeper.sh +48 -0
  247. package/scripts/setup-keeper-database.js +83 -0
  248. package/scripts/setup-keeper-state-db.sql +110 -0
  249. package/scripts/setup-oracle.sh +39 -0
  250. package/scripts/setup-pnl-tracking.js +111 -0
  251. package/scripts/start-devnet.sh +14 -0
  252. package/scripts/test-arcade-devnet.sh +160 -0
  253. package/scripts/test-arcade-match.sh +109 -0
  254. package/scripts/test-automatic-mode.sh +239 -0
  255. package/scripts/test-connect4-cancel-claim.js +370 -0
  256. package/scripts/test-connect4-e2e.js +369 -0
  257. package/scripts/test-connect4-resolve.js +369 -0
  258. package/scripts/test-game-state-endpoint.js +136 -0
  259. package/scripts/test-invite-notification.js +86 -0
  260. package/scripts/test-jackpot-api.sh +71 -0
  261. package/scripts/test-poll-confirmation.js +267 -0
  262. package/scripts/test-resolve-game.js +271 -0
  263. package/scripts/test-resolve-signature.js +223 -0
  264. package/scripts/test-signature-preservation.js +124 -0
  265. package/scripts/test-state-machine.js +291 -0
  266. package/scripts/test-webhook-receiver.js +60 -0
  267. package/scripts/update-notification-constraint.js +52 -0
  268. package/scripts/verify-account-layout.js +145 -0
  269. package/scripts/verify-winner-algorithm.js +278 -0
  270. package/server.js +5259 -0
  271. package/services/arcadeMatchService.js +763 -0
  272. package/services/automaticGameOracle.js +1596 -0
  273. package/services/chatService.js +1612 -0
  274. package/services/connect4GameService.js +1049 -0
  275. package/services/connect4NotificationService.js +374 -0
  276. package/services/cryptoPriceService.js +223 -0
  277. package/services/customGameResolver.js +260 -0
  278. package/services/db.js +79 -0
  279. package/services/directMessageService.js +389 -0
  280. package/services/discordNotifications.js +160 -0
  281. package/services/exchangeRateService.js +289 -0
  282. package/services/expoPushService.js +314 -0
  283. package/services/gamesCacheService.js +539 -0
  284. package/services/jackpotHistory.js +331 -0
  285. package/services/jackpotService.js +856 -0
  286. package/services/keeperStateService.js +355 -0
  287. package/services/matchupImageService.js +591 -0
  288. package/services/notificationCacheService.js +407 -0
  289. package/services/pickemOracle.js +440 -0
  290. package/services/playerStatsService.js +389 -0
  291. package/services/portfolioService.js +555 -0
  292. package/services/promoService.js +757 -0
  293. package/services/promoTreasuryService.js +239 -0
  294. package/services/pushNotifications.js +353 -0
  295. package/services/redisService.js +422 -0
  296. package/services/referralEarningsService.js +728 -0
  297. package/services/s3Service.js +396 -0
  298. package/services/socialService.js +1202 -0
  299. package/services/survivorOracle.js +469 -0
  300. package/services/survivorSimulator.js +475 -0
  301. package/services/telegramNotifications.js +461 -0
  302. package/services/userProfileStatsService.js +1185 -0
  303. package/services/whatsNewService.js +388 -0
  304. package/utils/urlHelper.js +95 -0
@@ -0,0 +1,269 @@
1
+ # ๐Ÿ“Š Heroku Database Quick Reference
2
+
3
+ ## ๐Ÿ”— Connect to Database
4
+
5
+ ### Interactive psql Shell:
6
+ ```bash
7
+ heroku pg:psql -a dubs-server-dev
8
+ ```
9
+
10
+ ### Run Single Query:
11
+ ```bash
12
+ heroku pg:psql -a dubs-server-dev -c "YOUR QUERY HERE"
13
+ ```
14
+
15
+ ### Get Database Info:
16
+ ```bash
17
+ heroku pg:info -a dubs-server-dev
18
+ ```
19
+
20
+ ---
21
+
22
+ ## ๐ŸŽฏ Useful Queries
23
+
24
+ ### 1. View Recent Rounds
25
+ ```sql
26
+ SELECT round_id, status, entry_count, retry_count,
27
+ locked_at, revealed_at, resolved_at
28
+ FROM keeper_rounds
29
+ ORDER BY round_id DESC
30
+ LIMIT 10;
31
+ ```
32
+
33
+ ### 2. View Rounds with Full Verification Data
34
+ ```sql
35
+ SELECT r.round_id, r.winner, r.win_amount, r.total_pot,
36
+ r.server_seed_hash, r.oracle_seed, r.signature
37
+ FROM jackpot_rounds r
38
+ WHERE r.server_seed_hash IS NOT NULL
39
+ AND r.oracle_seed IS NOT NULL
40
+ ORDER BY r.timestamp DESC
41
+ LIMIT 10;
42
+ ```
43
+
44
+ ### 3. Check Action Log for a Round
45
+ ```sql
46
+ SELECT action, success, duration_ms, timestamp, error_message
47
+ FROM keeper_actions
48
+ WHERE round_id = 551
49
+ ORDER BY timestamp ASC;
50
+ ```
51
+
52
+ ### 4. See Stuck Rounds (View)
53
+ ```sql
54
+ SELECT * FROM stuck_rounds;
55
+ ```
56
+
57
+ ### 5. Overall Health Summary (View)
58
+ ```sql
59
+ SELECT * FROM keeper_health_summary;
60
+ ```
61
+
62
+ ### 6. Recent Keeper Health Snapshots
63
+ ```sql
64
+ SELECT rounds_completed, consecutive_failures,
65
+ last_success_round, uptime_seconds, timestamp
66
+ FROM keeper_health
67
+ ORDER BY timestamp DESC
68
+ LIMIT 10;
69
+ ```
70
+
71
+ ### 7. Success Rate Analysis
72
+ ```sql
73
+ SELECT
74
+ action,
75
+ COUNT(*) as total_attempts,
76
+ SUM(CASE WHEN success THEN 1 ELSE 0 END) as successes,
77
+ ROUND(100.0 * SUM(CASE WHEN success THEN 1 ELSE 0 END) / COUNT(*), 2) as success_rate_pct,
78
+ AVG(duration_ms) as avg_duration_ms
79
+ FROM keeper_actions
80
+ GROUP BY action
81
+ ORDER BY action;
82
+ ```
83
+
84
+ ### 8. Find Slow Operations
85
+ ```sql
86
+ SELECT round_id, action, duration_ms, timestamp
87
+ FROM keeper_actions
88
+ WHERE duration_ms > 2000 -- Slower than 2 seconds
89
+ ORDER BY duration_ms DESC
90
+ LIMIT 10;
91
+ ```
92
+
93
+ ### 9. Find Rounds with Errors
94
+ ```sql
95
+ SELECT DISTINCT round_id, status, retry_count, last_error
96
+ FROM keeper_rounds
97
+ WHERE retry_count > 0
98
+ ORDER BY round_id DESC
99
+ LIMIT 10;
100
+ ```
101
+
102
+ ### 10. Rounds Completed in Last Hour
103
+ ```sql
104
+ SELECT round_id,
105
+ EXTRACT(EPOCH FROM (resolved_at - locked_at)) as completion_seconds
106
+ FROM keeper_rounds
107
+ WHERE resolved_at > NOW() - INTERVAL '1 hour'
108
+ ORDER BY resolved_at DESC;
109
+ ```
110
+
111
+ ---
112
+
113
+ ## ๐Ÿ” Debugging Queries
114
+
115
+ ### Find What Round is Currently Processing:
116
+ ```sql
117
+ SELECT round_id, status,
118
+ EXTRACT(EPOCH FROM (NOW() - updated_at)) as seconds_since_update
119
+ FROM keeper_rounds
120
+ WHERE status NOT IN ('resolved', 'open')
121
+ ORDER BY updated_at DESC
122
+ LIMIT 5;
123
+ ```
124
+
125
+ ### See Complete Round Lifecycle:
126
+ ```sql
127
+ -- Detailed timeline for round 551
128
+ SELECT
129
+ 'Created' as phase, created_at as timestamp FROM keeper_rounds WHERE round_id = 551
130
+ UNION ALL
131
+ SELECT 'Locked', locked_at FROM keeper_rounds WHERE round_id = 551
132
+ UNION ALL
133
+ SELECT 'Revealed', revealed_at FROM keeper_rounds WHERE round_id = 551
134
+ UNION ALL
135
+ SELECT 'Resolved', resolved_at FROM keeper_rounds WHERE round_id = 551
136
+ UNION ALL
137
+ SELECT 'Reset', reset_at FROM keeper_rounds WHERE round_id = 551
138
+ ORDER BY timestamp;
139
+ ```
140
+
141
+ ### Find Longest Round Completion:
142
+ ```sql
143
+ SELECT round_id,
144
+ EXTRACT(EPOCH FROM (resolved_at - locked_at)) as seconds_to_complete
145
+ FROM keeper_rounds
146
+ WHERE resolved_at IS NOT NULL
147
+ ORDER BY seconds_to_complete DESC
148
+ LIMIT 10;
149
+ ```
150
+
151
+ ---
152
+
153
+ ## ๐Ÿ“Š Monitoring Queries (Run Periodically)
154
+
155
+ ### Check System Health:
156
+ ```bash
157
+ heroku pg:psql -a dubs-server-dev -c "
158
+ SELECT
159
+ (SELECT COUNT(*) FROM stuck_rounds) as stuck_count,
160
+ (SELECT COUNT(*) FROM keeper_rounds WHERE status = 'resolved') as resolved_count,
161
+ (SELECT AVG(EXTRACT(EPOCH FROM (resolved_at - locked_at)))
162
+ FROM keeper_rounds
163
+ WHERE resolved_at IS NOT NULL) as avg_completion_seconds;
164
+ "
165
+ ```
166
+
167
+ ### Recent Activity:
168
+ ```bash
169
+ heroku pg:psql -a dubs-server-dev -c "
170
+ SELECT action, success, COUNT(*) as count, AVG(duration_ms) as avg_ms
171
+ FROM keeper_actions
172
+ WHERE timestamp > NOW() - INTERVAL '1 hour'
173
+ GROUP BY action, success
174
+ ORDER BY action, success DESC;
175
+ "
176
+ ```
177
+
178
+ ---
179
+
180
+ ## ๐Ÿ› ๏ธ Maintenance Queries
181
+
182
+ ### Clear Old Action Logs (Keep last 1000):
183
+ ```sql
184
+ DELETE FROM keeper_actions
185
+ WHERE id NOT IN (
186
+ SELECT id FROM keeper_actions
187
+ ORDER BY timestamp DESC
188
+ LIMIT 1000
189
+ );
190
+ ```
191
+
192
+ ### Mark Stuck Round as Resolved (Manual Override):
193
+ ```sql
194
+ UPDATE keeper_rounds
195
+ SET status = 'resolved', resolved_at = NOW()
196
+ WHERE round_id = 999;
197
+ ```
198
+
199
+ ### Reset Retry Counter:
200
+ ```sql
201
+ UPDATE keeper_rounds
202
+ SET retry_count = 0, last_error = NULL
203
+ WHERE round_id = 999;
204
+ ```
205
+
206
+ ---
207
+
208
+ ## ๐Ÿš€ Quick Commands You'll Use Often
209
+
210
+ **See what keeper is doing right now:**
211
+ ```bash
212
+ heroku pg:psql -a dubs-server-dev -c "SELECT round_id, status, EXTRACT(EPOCH FROM (NOW() - updated_at)) as secs_ago FROM keeper_rounds ORDER BY updated_at DESC LIMIT 5;"
213
+ ```
214
+
215
+ **Check if any rounds are stuck:**
216
+ ```bash
217
+ heroku pg:psql -a dubs-server-dev -c "SELECT * FROM stuck_rounds;"
218
+ ```
219
+
220
+ **See recent completions:**
221
+ ```bash
222
+ heroku pg:psql -a dubs-server-dev -c "SELECT round_id, status, entry_count FROM keeper_rounds WHERE status = 'resolved' ORDER BY resolved_at DESC LIMIT 5;"
223
+ ```
224
+
225
+ **Full dashboard view:**
226
+ ```bash
227
+ curl -s https://dubs-server-dev-55d1fba09a97.herokuapp.com/api/keeper/dashboard | jq .
228
+ ```
229
+
230
+ ---
231
+
232
+ ## ๐Ÿ’ก Pro Tips
233
+
234
+ 1. **Watch Live Updates:**
235
+ ```bash
236
+ watch -n 2 'heroku pg:psql -a dubs-server-dev -c "SELECT round_id, status FROM keeper_rounds ORDER BY round_id DESC LIMIT 5"'
237
+ ```
238
+
239
+ 2. **Export to CSV:**
240
+ ```bash
241
+ heroku pg:psql -a dubs-server-dev -c "COPY (SELECT * FROM keeper_rounds ORDER BY round_id DESC LIMIT 100) TO STDOUT WITH CSV HEADER" > rounds.csv
242
+ ```
243
+
244
+ 3. **Backup Important Data:**
245
+ ```bash
246
+ heroku pg:backups:capture -a dubs-server-dev
247
+ heroku pg:backups:download -a dubs-server-dev
248
+ ```
249
+
250
+ ---
251
+
252
+ ## ๐Ÿ“ฑ Access from Any Tool
253
+
254
+ **Get DATABASE_URL:**
255
+ ```bash
256
+ heroku config:get DATABASE_URL -a dubs-server-dev
257
+ ```
258
+
259
+ Then use with any Postgres client:
260
+ - TablePlus
261
+ - pgAdmin
262
+ - DBeaver
263
+ - psql locally
264
+
265
+ **Quick connect string format:**
266
+ ```
267
+ postgresql://username:password@host:5432/database?sslmode=require
268
+ ```
269
+
@@ -0,0 +1,390 @@
1
+ # ๐Ÿ“ฆ Database Retention & Cleanup Policy
2
+
3
+ **Last Updated:** November 18, 2025
4
+ **Purpose:** Prevent unbounded database growth while preserving audit trail
5
+
6
+ ---
7
+
8
+ ## ๐ŸŽฏ Retention Policies
9
+
10
+ ### **Forever (Never Delete):**
11
+
12
+ 1. **`jackpot_rounds`** - Historical winners
13
+ - **Why:** Users need to verify ANY past round
14
+ - **Size:** ~500 bytes per round
15
+ - **Growth:** ~50 rounds/day = 25 KB/day = 9 MB/year
16
+ - **Acceptable:** Plenty of room on Heroku Postgres
17
+
18
+ 2. **`keeper_rounds` (resolved status)** - Completed rounds
19
+ - **Why:** Audit trail for completed rounds
20
+ - **Size:** ~300 bytes per round
21
+ - **Growth:** ~50 rounds/day = 15 KB/day = 5.5 MB/year
22
+ - **Acceptable:** Essential audit data
23
+
24
+ ### **30 Days Retention:**
25
+
26
+ 3. **`keeper_actions`** - Detailed action logs
27
+ - **Why:** Recent debugging, older logs less useful
28
+ - **Size:** ~200 bytes per action
29
+ - **Growth:** ~200 actions/day = 40 KB/day
30
+ - **Cleanup:** Delete actions older than 30 days
31
+ - **Impact:** Keeps last ~6,000 actions (~1.2 MB)
32
+
33
+ 4. **`keeper_rounds` (incomplete)** - Stuck/failed rounds
34
+ - **Why:** Old stuck rounds aren't relevant
35
+ - **Size:** ~300 bytes per round
36
+ - **Growth:** Should be 0 (no stuck rounds!)
37
+ - **Cleanup:** Delete incomplete rounds older than 30 days
38
+
39
+ ### **90 Days Retention:**
40
+
41
+ 5. **`keeper_health`** - Health snapshots
42
+ - **Why:** Long-term trend analysis
43
+ - **Size:** ~150 bytes per snapshot
44
+ - **Growth:** ~1,440 snapshots/day (every minute) = 216 KB/day
45
+ - **Cleanup:** Delete snapshots older than 90 days
46
+ - **Impact:** Keeps ~130,000 snapshots (~19.5 MB)
47
+
48
+ ---
49
+
50
+ ## ๐Ÿ“Š Growth Projections
51
+
52
+ ### **Without Cleanup:**
53
+
54
+ | Table | Per Day | Per Month | Per Year |
55
+ |-------|---------|-----------|----------|
56
+ | jackpot_rounds | 25 KB | 750 KB | 9 MB |
57
+ | keeper_rounds | 15 KB | 450 KB | 5.5 MB |
58
+ | keeper_actions | 40 KB | 1.2 MB | **14.6 MB** |
59
+ | keeper_health | 216 KB | 6.5 MB | **78.8 MB** |
60
+ | **TOTAL** | **296 KB** | **8.9 MB** | **108 MB** |
61
+
62
+ **Conclusion:** Without cleanup, ~108 MB/year. Heroku has 1 GB limit. Would take **9+ years** to fill up!
63
+
64
+ ### **With Cleanup:**
65
+
66
+ | Table | Max Size (Steady State) |
67
+ |-------|-------------------------|
68
+ | jackpot_rounds | ~9 MB/year (grows forever) |
69
+ | keeper_rounds | ~5.5 MB/year (grows forever) |
70
+ | keeper_actions | ~1.2 MB (capped at 30 days) |
71
+ | keeper_health | ~19.5 MB (capped at 90 days) |
72
+ | **TOTAL** | **~35 MB steady state** |
73
+
74
+ **Conclusion:** With cleanup, stays under 50 MB indefinitely. **No storage concerns for years.**
75
+
76
+ ---
77
+
78
+ ## ๐Ÿ”„ Automated Cleanup (Heroku Scheduler)
79
+
80
+ ### **Setup Once:**
81
+
82
+ ```bash
83
+ # Add Heroku Scheduler addon (free!)
84
+ heroku addons:create scheduler:standard -a dubs-server-dev
85
+
86
+ # Open scheduler dashboard
87
+ heroku addons:open scheduler -a dubs-server-dev
88
+ ```
89
+
90
+ ### **Add Daily Job:**
91
+
92
+ **In Heroku Scheduler Dashboard:**
93
+ - **Command:** `node scripts/cleanup-database.js`
94
+ - **Frequency:** Daily
95
+ - **Time:** 3:00 AM UTC (off-peak)
96
+ - **Dyno Size:** Standard-1X
97
+
98
+ **Or via CLI:**
99
+ ```bash
100
+ heroku addons:create scheduler:standard -a dubs-server-dev
101
+ # Then configure in dashboard
102
+ ```
103
+
104
+ ---
105
+
106
+ ## ๐Ÿ› ๏ธ Manual Cleanup
107
+
108
+ ### **Run Cleanup Now:**
109
+
110
+ ```bash
111
+ # On Heroku
112
+ heroku run node scripts/cleanup-database.js -a dubs-server-dev
113
+
114
+ # Locally (if DATABASE_URL set)
115
+ node scripts/cleanup-database.js
116
+ ```
117
+
118
+ ### **Check Space Usage:**
119
+
120
+ ```bash
121
+ heroku pg:info -a dubs-server-dev
122
+ ```
123
+
124
+ Look for:
125
+ ```
126
+ Data Size: 7.93 MB / 1 GB (0.77%)
127
+ ```
128
+
129
+ **When to worry:** > 500 MB (50%) โ†’ Increase cleanup frequency
130
+
131
+ ---
132
+
133
+ ## ๐Ÿ” What Gets Cleaned
134
+
135
+ ### **keeper_actions** (30 days)
136
+
137
+ **Keeps:**
138
+ - Last 30 days of action logs
139
+ - ~6,000 recent actions
140
+ - All recent debugging data
141
+
142
+ **Deletes:**
143
+ - Actions older than 30 days
144
+ - Old success logs (not needed)
145
+ - Old error logs (already investigated)
146
+
147
+ **Example:** Round 100 completed 35 days ago โ†’ action logs deleted, but round data kept
148
+
149
+ ### **keeper_health** (90 days)
150
+
151
+ **Keeps:**
152
+ - Last 90 days of health snapshots
153
+ - ~130,000 data points
154
+ - Enough for trend analysis
155
+
156
+ **Deletes:**
157
+ - Snapshots older than 90 days
158
+ - Ancient performance data
159
+
160
+ ### **keeper_rounds incomplete** (30 days)
161
+
162
+ **Keeps:**
163
+ - All resolved rounds (forever)
164
+ - Recent stuck rounds (for debugging)
165
+
166
+ **Deletes:**
167
+ - Stuck rounds older than 30 days
168
+ - Failed rounds that never completed
169
+
170
+ **Why:** If round stuck for 30 days, it's never completing!
171
+
172
+ ---
173
+
174
+ ## ๐Ÿ“ˆ Monitoring Cleanup
175
+
176
+ ### **Check if Cleanup is Running:**
177
+
178
+ ```bash
179
+ # View scheduler logs
180
+ heroku logs --ps scheduler -a dubs-server-dev
181
+
182
+ # Check last cleanup time
183
+ heroku pg:psql -a dubs-server-dev -c "
184
+ SELECT MAX(timestamp) as last_cleanup
185
+ FROM keeper_actions
186
+ WHERE action = 'cleanup';
187
+ "
188
+ ```
189
+
190
+ ### **See What Would Be Deleted (Dry Run):**
191
+
192
+ ```bash
193
+ heroku pg:psql -a dubs-server-dev -c "
194
+ SELECT
195
+ 'keeper_actions' as table_name,
196
+ COUNT(*) as rows_to_delete
197
+ FROM keeper_actions
198
+ WHERE timestamp < NOW() - INTERVAL '30 days'
199
+
200
+ UNION ALL
201
+
202
+ SELECT
203
+ 'keeper_health',
204
+ COUNT(*)
205
+ FROM keeper_health
206
+ WHERE timestamp < NOW() - INTERVAL '90 days'
207
+
208
+ UNION ALL
209
+
210
+ SELECT
211
+ 'keeper_rounds (incomplete)',
212
+ COUNT(*)
213
+ FROM keeper_rounds
214
+ WHERE status NOT IN ('resolved', 'open')
215
+ AND updated_at < NOW() - INTERVAL '30 days';
216
+ "
217
+ ```
218
+
219
+ ---
220
+
221
+ ## ๐Ÿšจ Emergency: Database Full
222
+
223
+ **If you somehow reach 90%+ capacity:**
224
+
225
+ ### **Option 1: Aggressive Cleanup**
226
+
227
+ ```bash
228
+ # Delete actions older than 7 days instead of 30
229
+ heroku pg:psql -a dubs-server-dev -c "
230
+ DELETE FROM keeper_actions
231
+ WHERE timestamp < NOW() - INTERVAL '7 days';
232
+ "
233
+
234
+ # Delete health older than 30 days instead of 90
235
+ heroku pg:psql -a dubs-server-dev -c "
236
+ DELETE FROM keeper_health
237
+ WHERE timestamp < NOW() - INTERVAL '30 days';
238
+ "
239
+
240
+ # Vacuum to reclaim space
241
+ heroku pg:psql -a dubs-server-dev -c "VACUUM FULL;"
242
+ ```
243
+
244
+ ### **Option 2: Export & Archive**
245
+
246
+ ```bash
247
+ # Export old data to CSV
248
+ heroku pg:psql -a dubs-server-dev -c "
249
+ COPY (
250
+ SELECT * FROM keeper_actions
251
+ WHERE timestamp < NOW() - INTERVAL '90 days'
252
+ ) TO STDOUT WITH CSV HEADER
253
+ " > keeper_actions_archive_$(date +%Y%m%d).csv
254
+
255
+ # Store in S3, Google Cloud Storage, or local
256
+
257
+ # Then delete from database
258
+ heroku pg:psql -a dubs-server-dev -c "
259
+ DELETE FROM keeper_actions
260
+ WHERE timestamp < NOW() - INTERVAL '90 days';
261
+ "
262
+ ```
263
+
264
+ ### **Option 3: Upgrade Database**
265
+
266
+ ```bash
267
+ # Upgrade to larger plan
268
+ heroku addons:upgrade postgresql-colorful-22525:standard-0 -a dubs-server-dev
269
+
270
+ # Plans:
271
+ # essential-0: 1 GB (current, $5/month)
272
+ # essential-1: 10 GB ($50/month)
273
+ # standard-0: 64 GB ($200/month)
274
+ ```
275
+
276
+ ---
277
+
278
+ ## ๐ŸŽฏ Recommended Strategy
279
+
280
+ ### **For Devnet/Testing:**
281
+
282
+ Run cleanup **weekly**:
283
+ ```bash
284
+ # Add to Heroku Scheduler
285
+ node scripts/cleanup-database.js
286
+ # Frequency: Daily
287
+ ```
288
+
289
+ **Why:** Development generates lots of test data, clean it aggressively
290
+
291
+ ### **For Production/Mainnet:**
292
+
293
+ Run cleanup **daily** with current policies:
294
+ - keeper_actions: 30 days
295
+ - keeper_health: 90 days
296
+ - keeper_rounds: Keep resolved forever
297
+
298
+ **Why:** Balance between audit trail and storage
299
+
300
+ ### **For High Volume (1000+ rounds/day):**
301
+
302
+ **Option A:** More aggressive retention
303
+ - keeper_actions: 14 days
304
+ - keeper_health: 30 days
305
+ - Consider archiving to S3
306
+
307
+ **Option B:** Upgrade database
308
+ - Move to 10 GB plan ($50/month)
309
+ - Keep longer retention
310
+
311
+ ---
312
+
313
+ ## ๐Ÿ“Š Cost Analysis
314
+
315
+ ### **Storage Costs:**
316
+
317
+ **Heroku Postgres Essential-0 (1 GB):**
318
+ - Cost: $5/month
319
+ - Capacity: 1 GB
320
+ - Expected usage with cleanup: <50 MB
321
+ - **Verdict:** Plenty of room โœ…
322
+
323
+ **Upgrade triggers:**
324
+ - > 500 MB used โ†’ Consider cleanup tuning
325
+ - > 800 MB used โ†’ Upgrade to Essential-1 (10 GB, $50/mo)
326
+
327
+ ### **Cleanup Costs:**
328
+
329
+ **Heroku Scheduler:**
330
+ - Cost: FREE (included)
331
+ - Runs: Daily at 3am
332
+ - Duration: ~30 seconds
333
+ - Dyno hours: ~0.5 hours/month
334
+ - **Verdict:** Free tier covers it โœ…
335
+
336
+ ---
337
+
338
+ ## ๐Ÿงช Test Cleanup Locally
339
+
340
+ ```bash
341
+ # Set DATABASE_URL to local Postgres
342
+ export DATABASE_URL="postgresql://localhost/dubs_test"
343
+
344
+ # Run cleanup
345
+ node scripts/cleanup-database.js
346
+
347
+ # Expected output:
348
+ # ๐Ÿงน DATABASE CLEANUP STARTING
349
+ # ๐Ÿ“Š Before Cleanup: ...
350
+ # ๐Ÿงน Cleaning keeper_actions...
351
+ # Deleted 0 old action logs
352
+ # โœ… CLEANUP COMPLETE
353
+ ```
354
+
355
+ ---
356
+
357
+ ## ๐Ÿ“‹ Cleanup Checklist
358
+
359
+ **Initial Setup (One Time):**
360
+ - [ ] Deploy cleanup script: `git push heroku-dev main`
361
+ - [ ] Add Heroku Scheduler addon
362
+ - [ ] Configure daily job at 3am
363
+ - [ ] Test run: `heroku run node scripts/cleanup-database.js -a dubs-server-dev`
364
+
365
+ **Monthly Monitoring:**
366
+ - [ ] Check database size: `heroku pg:info -a dubs-server-dev`
367
+ - [ ] Verify cleanup runs: `heroku logs --ps scheduler -a dubs-server-dev`
368
+ - [ ] Review retention policies (adjust if needed)
369
+
370
+ **Yearly Review:**
371
+ - [ ] Analyze growth trends
372
+ - [ ] Adjust retention policies
373
+ - [ ] Consider database upgrade
374
+ - [ ] Archive old data if needed
375
+
376
+ ---
377
+
378
+ ## ๐ŸŽฏ Current Recommendation
379
+
380
+ **For your devnet testing:**
381
+
382
+ โœ… **Run cleanup weekly** (daily is overkill for low volume)
383
+ โœ… **Keep current retention policies** (30/90 days)
384
+ โœ… **Monitor size monthly**
385
+ โœ… **Don't worry about storage** (you have 1000x headroom)
386
+
387
+ **The database will NOT fill up.** Even at 1000 rounds/day, you have years before hitting limits.
388
+
389
+ But having automated cleanup is good practice and prevents surprises! ๐ŸŽฏ
390
+