diff --git a/docs/developer/api/conflicts/bulk_dismiss_conflicts.md b/docs/developer/api/conflicts/bulk_dismiss_conflicts.md index 7bd6d26b..7b1058ba 100644 --- a/docs/developer/api/conflicts/bulk_dismiss_conflicts.md +++ b/docs/developer/api/conflicts/bulk_dismiss_conflicts.md @@ -1,3 +1,11 @@ +--- +method: POST +path: /api/conflicts/bulk-dismiss +auth: jwt +area: conflicts +--- + + # Bulk Dismiss Conflicts Dismiss multiple conflicts at once. @@ -14,7 +22,7 @@ Dismiss multiple conflicts at once. ### Example Request -```json +```json example-request { "conflict_ids": [ "550e8400-e29b-41d4-a716-446655440000", @@ -25,10 +33,12 @@ Dismiss multiple conflicts at once. ## Response (200 OK) -```json +```json example-response { - "message": "Conflicts dismissed successfully", - "dismissed_count": 2 + "results": [], + "total": 2, + "success": 2, + "failed": 0 } ``` diff --git a/docs/developer/api/conflicts/bulk_resolve_conflicts.md b/docs/developer/api/conflicts/bulk_resolve_conflicts.md index 6b094d67..61fcda9d 100644 --- a/docs/developer/api/conflicts/bulk_resolve_conflicts.md +++ b/docs/developer/api/conflicts/bulk_resolve_conflicts.md @@ -1,3 +1,11 @@ +--- +method: POST +path: /api/conflicts/bulk-resolve +auth: jwt +area: conflicts +--- + + # Bulk Resolve Conflicts Resolve multiple conflicts at once using a specified strategy. @@ -15,23 +23,24 @@ Resolve multiple conflicts at once using a specified strategy. ### Example Request -```json +```json example-request { "conflict_ids": [ "550e8400-e29b-41d4-a716-446655440000", "660e8400-e29b-41d4-a716-446655440001" ], - "resolution": "highest_progress" + "strategy": "highest_progress" } ``` ## Response (200 OK) -```json +```json example-response { - "message": "Conflicts resolved successfully", - "resolved_count": 2, - "failed_count": 0 + "results": [], + "total": 2, + "success": 2, + "failed": 0 } ``` diff --git a/docs/developer/api/conflicts/delete_conflict.md b/docs/developer/api/conflicts/delete_conflict.md index 5ddb4de1..472d2ec1 100644 --- a/docs/developer/api/conflicts/delete_conflict.md +++ b/docs/developer/api/conflicts/delete_conflict.md @@ -1,3 +1,11 @@ +--- +method: DELETE +path: /api/conflicts/:id +auth: jwt +area: conflicts +--- + + # Delete Conflict Delete a specific conflict record. diff --git a/docs/developer/api/conflicts/dismiss_all_resolved.md b/docs/developer/api/conflicts/dismiss_all_resolved.md index e2cba5d9..9a112520 100644 --- a/docs/developer/api/conflicts/dismiss_all_resolved.md +++ b/docs/developer/api/conflicts/dismiss_all_resolved.md @@ -1,3 +1,11 @@ +--- +method: POST +path: /api/conflicts/dismiss-all +auth: jwt +area: conflicts +--- + + # Dismiss All Resolved Dismiss all resolved conflicts. @@ -20,10 +28,9 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ## Response (200 OK) -```json +```json example-response { - "message": "All resolved conflicts dismissed", - "count": 15 + "deleted": 15 } ``` diff --git a/docs/developer/api/conflicts/get_conflict.md b/docs/developer/api/conflicts/get_conflict.md index 58914fb1..564b2c51 100644 --- a/docs/developer/api/conflicts/get_conflict.md +++ b/docs/developer/api/conflicts/get_conflict.md @@ -1,3 +1,11 @@ +--- +method: GET +path: /api/conflicts/:id +auth: jwt +area: conflicts +--- + + # Get Conflict Details Get detailed information about a specific conflict. @@ -26,43 +34,14 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ## Response (200 OK) -```json +```json example-response { "id": "uuid", - "media_item": { - "id": "book-uuid", - "title": "Sample Book", - "authors": ["Author Name"] - }, - "device_progress": { - "device_id": "device-uuid", - "device_name": "My Kobo", - "percentage": 75, - "position": 1234, - "page": 150, - "updated_at": "2026-02-08T10:00:00Z" - }, - "server_progress": { - "percentage": 50, - "position": 800, - "page": 100, - "updated_at": "2026-02-08T09:00:00Z" - }, - "device_bookmarks": [ - { - "position": 1234, - "text": "Interesting passage", - "created_at": "2026-02-08T10:00:00Z" - } - ], - "server_bookmarks": [ - { - "position": 800, - "text": "Another passage", - "created_at": "2026-02-07T15:00:00Z" - } - ], - "status": "active", + "media_item_id": "book-uuid", + "media_item_title": "Sample Book", + "conflict_type": "progress", + "conflict_data": {}, + "resolution_status": "unresolved", "created_at": "2026-02-08T10:00:00Z" } ``` diff --git a/docs/developer/api/conflicts/list_conflicts.md b/docs/developer/api/conflicts/list_conflicts.md index 2f5aa286..6b7aa369 100644 --- a/docs/developer/api/conflicts/list_conflicts.md +++ b/docs/developer/api/conflicts/list_conflicts.md @@ -1,3 +1,11 @@ +--- +method: GET +path: /api/conflicts +auth: jwt +area: conflicts +--- + + # List Conflicts List all sync conflicts for the current user. @@ -29,32 +37,21 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ## Response (200 OK) -```json +```json example-response { "conflicts": [ { "id": "uuid", "media_item_id": "book-uuid", "media_item_title": "Sample Book", - "device_progress": { - "device_id": "device-uuid", - "device_name": "My Kobo", - "percentage": 75, - "position": 1234, - "updated_at": "2026-02-08T10:00:00Z" - }, - "server_progress": { - "percentage": 50, - "position": 800, - "updated_at": "2026-02-08T09:00:00Z" - }, - "status": "active", + "conflict_type": "progress", + "conflict_data": {}, + "resolution_status": "unresolved", "created_at": "2026-02-08T10:00:00Z" } ], "total": 5, - "limit": 10, - "offset": 0 + "unresolved": 5 } ``` diff --git a/docs/developer/api/conflicts/resolve_conflict.md b/docs/developer/api/conflicts/resolve_conflict.md index d8078adf..372eb465 100644 --- a/docs/developer/api/conflicts/resolve_conflict.md +++ b/docs/developer/api/conflicts/resolve_conflict.md @@ -1,3 +1,11 @@ +--- +method: POST +path: /api/conflicts/:id/resolve +auth: jwt +area: conflicts +--- + + # Resolve Conflict Resolve a specific conflict by choosing which version to keep. @@ -20,19 +28,22 @@ Resolve a specific conflict by choosing which version to keep. ### Example Request -```json +```json example-request { - "resolution": "device" + "winner": "kobo" } ``` +`winner` is one of the conflict's source keys (e.g. `"kobo"`, `"koreader"`, +`"web"`) or `"manual"` — the latter requires `manual_data`. + ## Response (200 OK) -```json +```json example-response { - "message": "Conflict resolved successfully", - "conflict_id": "uuid", - "resolution": "device" + "conflict_resolved": true, + "applied_to": {}, + "devices_synced": [] } ``` diff --git a/docs/developer/api/queue/clear_device_queue.md b/docs/developer/api/queue/clear_device_queue.md index dd889765..282acdf2 100644 --- a/docs/developer/api/queue/clear_device_queue.md +++ b/docs/developer/api/queue/clear_device_queue.md @@ -1,3 +1,11 @@ +--- +method: DELETE +path: /api/queue/devices/:device_id/clear +auth: jwt +area: queue +--- + + # Clear Device Queue Clear all queue items for a specific device. @@ -24,9 +32,13 @@ DELETE /api/queue/devices/550e8400-e29b-41d4-a716-446655440000/clear Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ``` -## Response (204 No Content) +## Response (200 OK) -Device queue cleared successfully. +```json example-response +{ + "message": "queue cleared" +} +``` ## Error Responses diff --git a/docs/developer/api/queue/delete_queue_item.md b/docs/developer/api/queue/delete_queue_item.md index ef721b0e..d340047e 100644 --- a/docs/developer/api/queue/delete_queue_item.md +++ b/docs/developer/api/queue/delete_queue_item.md @@ -1,3 +1,11 @@ +--- +method: DELETE +path: /api/queue/items/:item_id +auth: jwt +area: queue +--- + + # Delete Queue Item Delete a specific queue item. diff --git a/docs/developer/api/queue/get_device_queue_stats.md b/docs/developer/api/queue/get_device_queue_stats.md index fc9ea211..a5e19c86 100644 --- a/docs/developer/api/queue/get_device_queue_stats.md +++ b/docs/developer/api/queue/get_device_queue_stats.md @@ -1,3 +1,11 @@ +--- +method: GET +path: /api/queue/devices/:device_id/stats +auth: jwt +area: queue +--- + + # Get Device Queue Statistics Get statistics for a specific device's sync queue. @@ -26,13 +34,13 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ## Response (200 OK) -```json +```json example-response { - "total_items": 15, - "pending_items": 8, - "processing_items": 2, - "completed_items": 4, - "failed_items": 1 + "pending_count": 8, + "processing_count": 2, + "failed_count": 1, + "completed_count": 4, + "total_count": 15 } ``` diff --git a/docs/developer/api/queue/list_all_queue_items.md b/docs/developer/api/queue/list_all_queue_items.md index 0cc2bb3d..f6ab8108 100644 --- a/docs/developer/api/queue/list_all_queue_items.md +++ b/docs/developer/api/queue/list_all_queue_items.md @@ -1,3 +1,11 @@ +--- +method: GET +path: /api/queue/items +auth: jwt+admin +area: queue +--- + + # List All Queue Items (Admin) List all queue items across all devices (admin only). @@ -29,24 +37,24 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ## Response (200 OK) -```json +```json example-response { "items": [ { "id": "uuid", "device_id": "device-uuid", "device_name": "My Kobo", - "media_item_id": "book-uuid", - "operation": "sync_progress", + "device_type": "kobo", + "user_email": "user@example.com", + "sync_type": "sync_progress", + "priority": 0, + "attempts": 0, + "max_attempts": 0, "status": "failed", - "error_message": "Connection timeout", - "created_at": "2026-02-08T10:00:00Z", - "updated_at": "2026-02-08T10:05:00Z" + "created_at": "2026-02-08T10:00:00Z" } ], - "total": 45, - "limit": 20, - "offset": 0 + "count": 45 } ``` diff --git a/docs/developer/api/queue/list_device_queue_items.md b/docs/developer/api/queue/list_device_queue_items.md index 1273e405..b12d7223 100644 --- a/docs/developer/api/queue/list_device_queue_items.md +++ b/docs/developer/api/queue/list_device_queue_items.md @@ -1,3 +1,11 @@ +--- +method: GET +path: /api/queue/devices/:device_id/items +auth: jwt +area: queue +--- + + # List Device Queue Items List all queue items for a specific device. @@ -34,22 +42,24 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ## Response (200 OK) -```json +```json example-response { "items": [ { "id": "uuid", "device_id": "device-uuid", - "media_item_id": "book-uuid", - "operation": "sync_progress", + "device_name": "My Kobo", + "device_type": "kobo", + "user_email": "user@example.com", + "sync_type": "sync_progress", + "priority": 0, + "attempts": 0, + "max_attempts": 0, "status": "pending", - "created_at": "2026-02-08T10:00:00Z", - "updated_at": "2026-02-08T10:00:00Z" + "created_at": "2026-02-08T10:00:00Z" } ], - "total": 8, - "limit": 10, - "offset": 0 + "count": 8 } ``` diff --git a/docs/developer/api/queue/retry_queue_item.md b/docs/developer/api/queue/retry_queue_item.md index 49ccae86..aca43e54 100644 --- a/docs/developer/api/queue/retry_queue_item.md +++ b/docs/developer/api/queue/retry_queue_item.md @@ -1,3 +1,11 @@ +--- +method: POST +path: /api/queue/items/:item_id/retry +auth: jwt +area: queue +--- + + # Retry Queue Item Retry a failed queue item. @@ -26,10 +34,13 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ## Response (200 OK) -```json +```json example-response { - "message": "Queue item retry initiated", - "item_id": "uuid" + "message": "item queued for retry", + "item_id": "uuid", + "status": "pending", + "attempts": 0, + "max_attempts": 0 } ``` diff --git a/internal/docs/schema.go b/internal/docs/schema.go index 6c6d84cd..e94cdb9d 100644 --- a/internal/docs/schema.go +++ b/internal/docs/schema.go @@ -324,4 +324,52 @@ var Schemas = map[string]Schema{ "name": "", "library_id": "", "books": [], "total": 0 }`), }, + + // --- Beam batch 2: conflicts + queue backfill --- + "GET /api/conflicts": { + Response: handlers.ConflictListResponse{}, + }, + "GET /api/conflicts/:id": { + Response: handlers.ConflictDetailResponse{}, + }, + "DELETE /api/conflicts/:id": {}, + "POST /api/conflicts/:id/resolve": { + Request: handlers.ConflictResolutionRequest{}, + Response: handlers.ConflictResolveResponse{}, + }, + "POST /api/conflicts/dismiss-all": { + // deleted is an INT count of dismissed rows. + Response: json.RawMessage(`{"deleted": 0}`), + }, + "POST /api/conflicts/bulk-resolve": { + Request: handlers.BulkResolveRequest{}, + Response: handlers.BulkResolveResponse{}, + }, + "POST /api/conflicts/bulk-dismiss": { + // Inline anonymous request struct {conflict_ids} — pinned by sample. + Request: json.RawMessage(`{"conflict_ids": []}`), + Response: handlers.BulkResolveResponse{}, + }, + + // NOTE: queue param names are :device_id / :item_id in the router — + // first registry draft used :id and the gate caught it. + "GET /api/queue/devices/:device_id/stats": { + Response: handlers.QueueStatsResponse{}, + }, + "GET /api/queue/devices/:device_id/items": { + Response: json.RawMessage(`{"items": [{}], "count": 0}`), + }, + "GET /api/queue/items": { + Response: json.RawMessage(`{"items": [{}], "count": 0}`), + }, + "POST /api/queue/items/:item_id/retry": { + Response: json.RawMessage(`{ + "message": "", "item_id": "", "status": "", + "attempts": 0, "max_attempts": 0 + }`), + }, + "DELETE /api/queue/items/:item_id": {}, + "DELETE /api/queue/devices/:device_id/clear": { + Response: json.RawMessage(`{"message": ""}`), + }, }