Closes#96
Replaces the per-field `json.dumps(value)` probe — which fully serialized
and discarded the result just to check serializability — with a type-check
fast path using `isinstance()`. The `_SERIALIZABLE_TYPES` tuple is defined
at module level so it's not recreated on every log call.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The production container has ambiguous timezone config — /etc/localtime
points to Etc/UTC but date reports CST. The transaction freeze/thaw task
used datetime.now() (naive, relying on OS timezone), causing scheduling
to fire at unpredictable wall-clock times.
- Add utils/timezone.py with centralized Chicago timezone helpers
- Fix tasks/transaction_freeze.py to use now_chicago() for scheduling
- Fix utils/logging.py timestamp to use proper UTC-aware datetime
- Add 14 timezone utility tests
- Update freeze task tests to mock now_chicago instead of datetime
Closes#43
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ContextualLogger methods forwarded all **kwargs as extra={} to Python's
standard logger. When callers passed exc_info=True, it landed in the
extra dict and Python's LogRecord raised KeyError("Attempt to overwrite
'exc_info' in LogRecord") since exc_info is a reserved attribute.
This caused /submit-scorecard to crash after game data was already
posted, masking the original error and preventing proper rollback.
Fix: Extract exc_info and stack_info from kwargs before passing as extra,
forwarding them as proper logging parameters instead. Also fix direct
callers in submit_scorecard.py and views/players.py to use error=e.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Complete rebuild of the Discord bot with modern architecture including:
- Modular API client with proper error handling
- Clean separation of models, services, and commands
- Comprehensive test coverage with pytest
- Structured logging and configuration management
- Organized command structure for scalability
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>