- Add BountyService for room bounty operations (group and personal)
- Add TrackingService for tracking bounty operations
- Uses RoomStorage and TrackingStorage ports
- PermissionError raised when non-creator edits/deletes
- ValueError raised when bounty not found in tracking
Tests with SimpleRoomStorage and SimpleTrackingStorage (without ensure_*)
show that add_bounty() and track_bounty() work fine without explicit
ensure methods - they create rooms/tracking internally.
This simplifies the Protocol to only essential methods.
- Removed PersonalStorage (redundant - RoomStorage handles both via room_id)
- Added ensure_room() and ensure_tracking() methods for explicit creation
- Added @runtime_checkable to Protocols for isinstance checks
- Added tests/test_ports.py with 11 unit tests for storage protocols
- Bounty.created_by_user_id is now non-optional (always required)
- Removed is_group from RoomData (negative room_id is self-documenting)
- Added room_id to TrackedBounty to track which room bounty was tracked from
- Added clarifying docstrings explaining TrackingData vs TrackedBounty
- Updated tests to match new model structure
- Remove GroupBounty/PersonalBounty subclasses, use Bounty with optional created_by_user_id
- Combine UserData/GroupData into RoomData with room_id and is_group fields
- Add group_id field to TrackingData (supports negative Telegram group IDs)
- Add test_bounty_comparison_not_equal for verifying different bounties are not equal
- Update core/__init__.py exports