* Initial plan
* Add comprehensive testing plan and start test infrastructure
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Fix test failures: update LiveQuery tests to use snake_case and remove unused imports
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Fix database migrations: fix UNSIGNED keyword, duplicate timestamps, reserved keywords, and type mismatches
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Add comprehensive test results summary documenting all fixes and test coverage
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Add comprehensive e2e integration tests covering auth, permissions, streaming, and error handling
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Change JWT from RS256 (RSA keys) to HS256 (secret)
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Add JWT migration documentation
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Fix config loading, OAuth2 registry, settings column, and HLS routes
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Fix UserRole/UserStatus database type encoding/decoding
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Add comprehensive API test suite with results documentation
- Comprehensive test script covering 13 API categories (24+ endpoints)
- Tests health, auth, user, room, media, playback, provider, notification, OAuth2 endpoints
- 15/24 tests passing (62.5% success rate)
- Detailed documentation of test results and known issues
- Multi-user testing with JWT authentication
- Automated test script with color-coded output
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Fix API endpoints: notifications, room list queries, and proto serialization
- Fix notification read-all endpoint to accept optional JSON body
- Fix RoomStatus database queries to use numeric values instead of strings
- Fix room list endpoint proto serialization (remove json!() wrapper)
- Add comprehensive API test suite and results documentation
- 10/17 endpoints now passing (58% success rate)
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Fix proto generation: regenerate Room struct with missing fields
Root cause: Room proto definition in client.proto had description (field 8) and
updated_at (field 9) but the generated Rust code was stale and only had fields
up to member_count (field 7). This caused room creation to fail with
"invalid type: null, expected u64" error when room_to_proto_basic() tried to
set non-existent fields.
Solution: Regenerate proto Rust code by rebuilding synctv-proto package with
protoc installed. This properly generates the Room struct with all 9 fields.
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Fix room creation: proto generation, RoomSettings deserialization, and status encoding
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Fix room status encoding and add nanoid PostgreSQL function
- Created nanoid() PostgreSQL function for ID generation in triggers
- Fixed RoomRepository to use i16 encoding/decoding for status column
- Added i16_to_status() helper method
- Updated row_to_room(), update(), and update_status() to use i16 instead of string
- Fixed create_root_playlist trigger to use NEW.created_by (not creator_id)
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Fix room_member repository: correct column references and status types
- Fixed SQL query to use rooms.id instead of incorrect rooms.room_id
- Fixed room status check to use i16 (1=Active) instead of string comparison
- Improved error handling for invalid room status
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Fix RoomRole and MemberStatus encoding in room_member repository
- Removed .to_string() calls on role and status bindings
- Allow sqlx custom encoders to handle i16 conversion
- Fixes "column role is of type smallint but expression is of type text" error
- Applied to add(), add_with_transaction(), update_role(), and update_status() methods
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Fix RoomRole and MemberStatus encoding in room_member repository
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Fix missing admin_*_permissions columns in SELECT queries
Fixed 4 SELECT queries in room_member.rs that were missing admin_added_permissions and admin_removed_permissions columns:
- get() method (line 203)
- get_any() method (line 225)
- list_by_room() method (line 247)
- list_by_room_with_online() method (line 273)
This was causing "no column found for name: admin_added_permissions" errors when permission checks tried to decode the RoomMember from query results.
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Fix database trigger and missing columns in room member queries
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Delete generated markdown files
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Remove SQL nanoid function and move root playlist creation to Rust
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Delete nanoid SQL files directly instead of creating drop migration
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Refactor: rename streaming → livestream throughout codebase
- Renamed synctv-stream directory to synctv-livestream
- Renamed src/streaming to src/livestream
- Updated config files: streaming → livestream
- Updated all code references throughout
- Updated Cargo.toml workspace config
- Updated test files
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Fix remaining streaming → livestream references
- Fixed module path in rtmp.rs
- Fixed imports in api/livestream.rs
- Fixed imports in protocols/hls/server.rs
- Build now passes successfully
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
---------
Co-authored-by: anthropic-code-agent[bot] <242468646+Claude@users.noreply.github.com>
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Initial plan
* Integrate SFU manager into ClientApiImpl for network quality monitoring
- Add synctv-sfu workspace dependency and wire it through API layer
- Add sfu_manager field to ClientApiImpl, ClientServiceImpl, ClientServiceConfig
- Implement get_network_quality() using SfuManager::get_room_network_quality()
- Convert NetworkStats to PeerNetworkQuality proto messages
- Pass sfu_manager from server.rs through HTTP and gRPC initialization
- Compiles with zero warnings and zero errors
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Address code review: restore const fn, extract network_stats_to_proto helper
- Restore const fn qualifier on ClientApiImpl::new
- Extract network_stats_to_proto() conversion function to eliminate duplication
- Both HTTP and gRPC handlers now use the shared helper
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Remove accidentally committed test binary
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Fix production-readiness issues: OAuth2 list_providers, server.rs unwrap, gRPC error codes
- Implement OAuth2Service::list_available_instances() to list configured OAuth2 providers
- Update HTTP list_providers handler to return actual provider instances instead of empty vec
- Replace bare unwrap() calls in server.rs with proper anyhow error handling
- Fix incorrect Status::unimplemented to Status::failed_precondition for settings registry
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Address code review: improve documentation for OAuth2 list_providers
- Add response format documentation to list_providers HTTP handler
- Clarify list_available_instances returns empty vec and has no guaranteed order
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Replace production unwrap() calls with proper error handling
- resilience.rs: Use unwrap_or_else(|e| e.into_inner()) on Mutex locks to
recover from poisoned mutexes instead of panicking
- room_settings/mod.rs: Same pattern for RwLock on static registry
- validation.rs: Use if-let pattern for first char check, pre-compile email
regex with LazyLock, use swap_remove instead of iterator unwrap
- OAuth2 providers (github/google/logto/oidc): Return Result from create()
methods instead of unwrapping user-provided redirect URLs
- sfu/peer.rs: Use unwrap_or(now) for checked_sub on Instant
- rtmp_server.rs: Use expect() with context on constant address parse
- repository/room.rs: Use if-let pattern instead of bool guard + unwrap
- provider/alist.rs: Use unwrap_or_default() for SystemTime
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Address code review feedback on validation and OAuth2 comment
- Use pop() instead of swap_remove(0) for single-element Vec
- Fix comment to say 'expect is safe' instead of 'safe to unwrap'
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Fix critical SQL bugs and remove dead database code
- user.rs: Fix RETURNING clauses in update_password() and
update_email_verified() that referenced non-existent 'permissions'
column instead of 'role, status' — would cause runtime SQL errors
- user.rs: Remove duplicate row_to_user_with_email_verified() method
(identical to row_to_user which already handles email_verified)
- room.rs: Fix broken list() method with invalid '$' placeholders
and unbound parameters — would cause runtime SQL errors
- room.rs: Fix list_by_creator() referencing non-existent 'settings'
column in SELECT
- room_member.rs: Add missing admin_added_permissions and
admin_removed_permissions to 6 RETURNING clauses that were
inconsistent with the row_to_member() mapper
- Remove dead room_optimized.rs and user_optimized.rs files that
were never connected to the module system
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Add description field to Room across all layers
- SQL: Add description TEXT column to rooms table in original migration
- Model: Add description field to Room, CreateRoomRequest, UpdateRoomRequest
- Repository: Update all SQL queries (INSERT, SELECT, UPDATE, RETURNING)
to include description column; search now matches both name and description
- Service: Update create_room() to accept description with 500 char limit;
add update_room_description() method
- Proto: Add description field to Room (client.proto) and AdminRoom (admin.proto)
and CreateRoomRequest
- gRPC: Update all Room/AdminRoom proto constructions in client_service.rs
and admin_service.rs
- HTTP: Update create_room handler to accept description field
- Impls: Update room_to_proto_basic and admin_room_to_proto helpers
- OpenAPI: Update RoomSchema and CreateRoomRequestSchema with description
- Tests: Update RoomFixture to include description field
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Use strict try_get for description column instead of unwrap_or_default
Per code review: since description is NOT NULL in the schema, use
try_get()? to surface schema mismatches early rather than silently
falling back to empty string.
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Complete API field gaps: User email_verified, Room updated_at, ListRooms search
- Proto: Add email_verified (field 7) to User message in client.proto
- Proto: Add updated_at (field 9) to Room message in client.proto
- Proto: Add search (field 3) to ListRoomsRequest for public room search
- gRPC: Update all User proto constructions (4) to include email_verified
- gRPC: Update all Room proto constructions (12) to include updated_at
- gRPC: Wire search field through to RoomListQuery in list_rooms handler
- HTTP: Update list_rooms to accept page/page_size/search query params
- Impls: Update user_to_proto and room_to_proto_basic helpers
- OpenAPI: Update UserSchema (add role, status, email_verified; remove
outdated permissions) and RoomSchema (add updated_at)
- Remove 260+ lines of commented-out dead code in admin_service.rs
(replaced by working implementations at bottom of file)
- Remove 150+ lines of commented-out dead code in client_service.rs
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Fix all test compilation errors across the codebase
- Fix ClusterEvent::ChatMessage missing color/position fields in 7 test sites
- Fix resilience.rs test imports: add TimeoutConfig, RetryConfig, CircuitBreaker, etc.
- Fix ChatMessageFixture: remove non-existent username field from builder
- Fix STUN tests: properly unwrap nested decode Result, use iterator directly
instead of .iter() on impl Iterator
- Fix StreamRegistryTrait mock in integration test: update to current trait API
with register_publisher, try_register_publisher, refresh_publisher_ttl, etc.
- Fix streaming_integration_test: create PullStreamManager for infrastructure
- Add serde_urlencoded dev-dependency to synctv-stream and synctv-api
- Remove broken test_create_live_router and test_path_format_matches_go_version
tests that used non-existent axum 0.7 Router::routes() method
- Add chrono::Utc import to registry_trait.rs for mock timestamps
- Fix unused warnings in test_helpers.rs and integration test imports
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Fix all test failures across entire codebase - 342 tests now pass
Test compilation fixes:
- Fix ClusterEvent::ChatMessage missing color/position in 7 test sites
- Fix resilience.rs test imports (TimeoutConfig, RetryConfig, etc.)
- Fix ChatMessageFixture: remove non-existent username field
- Fix STUN tests: properly unwrap nested Result, use iterator directly
- Fix StreamRegistryTrait mock: update to current 7-method trait API
- Fix streaming_integration_test: create PullStreamManager for infra
- Add serde_urlencoded dev-dependency to synctv-stream and synctv-api
- Add chrono::Utc import to registry_trait.rs for mock timestamps
Test logic fixes:
- Fix LiveQuery deserialization: add #[serde(rename = "roomId")]
- Fix path segment index assertions (off-by-one in 4 tests)
- Fix path segment count assertions (8 not 7, 10 not 9)
- Fix retry delay test expectations to match 1-based implementation
- Fix PartitionHealth test JSON (Vec<String> not Vec<Object>)
- Fix dedup tests: use #[tokio::test] (DedupFilter spawns tasks)
- Add #[ignore] to 7 Redis-dependent StreamRegistry tests
Code quality:
- Remove broken axum Router::routes() introspection tests
- Mark 12 incomplete doc-test examples as ```ignore
- Fix unused import warnings in test files
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
* Standardize JSON field naming: remove camelCase rename on LiveQuery.room_id
Remove #[serde(rename = "roomId")] from LiveQuery struct so the query
parameter uses standard snake_case "room_id" format. This was the only
instance of non-standard JSON naming in our own API layer.
All third-party provider types (bilibili, emby, alist) correctly retain
their serde renames to match external API formats.
Update test to use room_id= instead of roomId= in query strings.
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: zijiren233 <84728412+zijiren233@users.noreply.github.com>