Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog,
and this project adheres to Semantic Versioning.
[v2.0.1] - 2025-07-15
Configuration & Logging
- ⚙️ Configuration System: Added support for CONFIG_PATH environment variable for Docker deployments
- Fixed issue where application wasn't reading CONFIG_PATH for Docker configuration
- Improved documentation in help output
[v2.0.0] - Major Rewrite
MAJOR UPDATE: This release represents a comprehensive rewrite of the application with significant architectural changes, performance improvements, and new features. Users should review the migration guide for important upgrade information.
Architecture Overhaul
- 🌐 Complete GraphQL Client Rewrite: Entirely rebuilt the Hardcover client using GraphQL for more efficient and precise API interactions
- 💾 State Management: Introduced a robust state management system for tracking sync progress and book status across sessions
- 🔒 Rate Limiting: Implemented token bucket rate limiting with improved concurrency control and deadlock prevention
- 📈 Memory Optimization: Drastically reduced memory usage with optimized data structures and garbage collection
- 🔄 Concurrency Model: Redesigned concurrency approach with proper context handling and cancellation support
Major New Features
- 🔄 Incremental Sync Engine: Built a sophisticated incremental synchronization system that only processes changed books
- New state persistence layer between syncs for tracking changes
- Smart detection of relevant changes to minimize unnecessary API calls
- Configurable change thresholds for fine-tuning sync behavior
- 🏷️ Edition Management: Complete rewrite of edition handling with new tools and improved matching
- Better book matching algorithms that prioritize relevant results and filter out summaries
- Enhanced edition information extraction and normalization
- Improved mismatch detection and resolution
- 📦 Docker Support: Comprehensive Docker implementation with optimized container builds
- Multi-arch support for various platforms
- Environment-based configuration with sensible defaults
- Volume mounting for persistent data
- 📊 Advanced Progress Tracking: Completely rebuilt progress tracking system
- More accurate progress calculation and persistence
- Support for both percentage and seconds-based progress tracking
- Better handling of finished status and completion events
- 🔍 Ownership Sync: Added support for syncing ownership status between platforms
Configuration & Logging
- ⚙️ Configuration System: Completely redesigned configuration with improved validation
- More sensible defaults and clearer documentation
- Better environment variable support and overriding
- Hierarchical configuration with proper merging of options
- 📝 Logging Framework: Rebuilt logging system with structured logging
- Request ID tracking across operations
- Configurable log levels and formats (JSON/text)
- Improved context in log messages
- Better error reporting and debug information
Tools & Utilities
- 📱 New CLI Tools: Added suite of command-line tools for advanced operations
- Edition management tools for creating and updating editions
- Image tools for managing cover images
- Hardcover lookup utilities for data verification
- Mismatch handling and resolution tools
- 🐛 Error Handling: Introduced BookError type and comprehensive error handling
- Detailed error classification and reporting
- Better recovery from transient failures
- More informative user feedback
Critical Fixes & Improvements
- 🚨 Data Integrity:
- Prevented data loss in user_book_read updates
- Fixed race conditions in concurrent operations
- Improved transaction handling and atomicity
- Better handling of API response failures
- 🔧 Progress & Status:
- Fixed progress_seconds handling for accurate time tracking
- Enhanced finished status detection and updates
- Prevented duplicate read statuses in Hardcover
- Improved progress update logic with better error handling
- 🔍 Mismatch Handling:
- Improved edition information and format handling
- Removed "Audiobookshelf." prefix from edition information
- Set more meaningful edition formats based on publisher (e.g., "Audible Audio", "libro.fm")
- Better detection and recording of book mismatches
- 🚀 Performance:
- Optimized API request batching and caching
- Reduced memory allocations in hot paths
- Improved concurrency control and resource usage
- Enhanced rate limiting with token bucket algorithm
Removed & Deprecated
- ⚡ Legacy Components: Removed several deprecated components and systems:
- Removed old rate limiting system using delays (
sync_delay
andHARDCOVER_SYNC_DELAY_MS
) - Eliminated legacy matching modes and configuration options
- Removed outdated mismatch handling code and fixed-path configurations
- Deprecated non-GraphQL API endpoints usage
- Removed old rate limiting system using delays (
Developer Experience
- 🛠️ CI/CD: Enhanced CI/CD pipeline with improved workflows
- Better Docker image building and tagging
- Comprehensive test coverage with race detection
- Automated release processes
- Improved build artifacts and versioning
- 📝 Documentation: Completely rewrote documentation
- Better API documentation and examples
- More comprehensive configuration guides
- Improved troubleshooting information
- Migration guides for upgrading from previous versions
[1.6.1] - 2025-06-12
Fixed
- 🚨 CRITICAL: Complete Data Loss Prevention: Comprehensive fix for GraphQL partial update data loss
- Root Cause: Hardcover's GraphQL
update_user_book_read
mutation sets unmentioned fields to NULL - Solution: Enhanced
checkExistingUserBookRead()
to retrieve ALL existing fields before updates - Protected Fields:
progress_seconds
,started_at
,finished_at
,edition_id
,reading_format_id
- Comprehensive Preservation: All existing data is now preserved during progress updates
- Enhanced Data Structure: New
ExistingUserBookReadData
struct for complete field management - Updated Queries: GraphQL queries now include
edition_id
andreading_format_id
fields - Fallback Protection: Both primary and fallback queries enhanced with complete field selection
- Test Coverage: Comprehensive tests verify no data loss during updates
- Impact: Prevents critical reading history and metadata loss that was affecting user accounts
- Root Cause: Hardcover's GraphQL
[1.6.0] - 2025-06-12
Security
- 🔒 Go Security Update: Upgraded Go base image from
golang:1.24.2-alpine
togolang:1.24.4-alpine
- Resolves CVE-2025-4673 (Proxy-Authorization headers issue)
- Resolves CVE-2025-0913 (O_CREATE|O_EXCL handling inconsistency)
- Resolves CVE-2025-22874 (VerifyOptions.KeyUsages issue)
- Zero HIGH/CRITICAL vulnerabilities in Trivy security scan
Added
-
🧠 Intelligent Caching System: Revolutionary performance improvement with smart author/narrator lookup caching
- PersonCache: In-memory cache with configurable TTL (default: 1 hour)
- Smart Search: Caches author and narrator search results to avoid repeated API calls
- Cross-Role Lookup: Authors found as narrators are cached for author searches and vice versa
- Publisher Support: Extended caching to publisher lookups for complete metadata coverage
- Cache Statistics: Built-in metrics for hit rates, misses, and performance monitoring
- Automatic Cleanup: Expired entries are automatically cleaned up to manage memory
- Significant Performance: Reduces API calls by 70-90% for libraries with repeated author/narrator names
- Configurable:
CACHE_TTL_MINUTES
environment variable (default: 60 minutes)
-
📊 Enhanced Progress Detection System: Advanced audiobook progress tracking with multiple fallback mechanisms
- Multi-Endpoint Support: Uses both
/api/me
and/api/me/listening-sessions
for comprehensive coverage - Manually Finished Books: Proper detection of books marked as "finished" with
isFinished
flag - Smart Fallbacks: Automatic fallback between different AudiobookShelf API endpoints
- Progress Validation: Cross-validation between multiple data sources for accuracy
- Debug Logging: Comprehensive logging for troubleshooting progress detection issues
- API Compatibility: Works with different AudiobookShelf versions and configurations
- Multi-Endpoint Support: Uses both
-
🏗️ Complete Local Image Upload System: Full implementation for AudiobookShelf cover image handling
- Local URL Detection: Automatically detects AudiobookShelf server images vs external URLs
- Multi-Stage Upload: Creates edition first, then uploads local images with proper association
- Edition Linking: Automatically links uploaded images to newly created editions
- Error Handling: Graceful degradation when image uploads fail (edition still created)
- URL Validation: Smart detection of local vs external image URLs for proper processing
Fixed
-
🔧 CRITICAL: Edition Field NULL Fix: Fixed critical bug where
edition
field becamenull
inuser_book_read
entries- Root Cause: Missing
edition_id
field inDatesReadInput
objects for GraphQL mutations - Data Loss Prevention: Ensures reading entries maintain proper edition context
- Comprehensive Solution: Updated both insert and update mutations with edition ID validation
- Diagnostic Tools: Added troubleshooting functions and enhanced logging
- Root Cause: Missing
-
🔧 Book ID Deduplication Fix: Fixed handling of deduped books with canonical IDs in Hardcover
- Smart Detection: Automatically uses
canonical_id
whenbook_status_id = 4
(deduped) - GraphQL Enhancement: Added
book_status_id
andcanonical_id
fields to all book queries - Real-World Testing: Verified with "The Third Gilmore Girl" case and other deduped books
- Seamless Handling: Transparent redirection to canonical book without user intervention
- Smart Detection: Automatically uses
-
🔧 RE-READ Detection Fix: Fixed incorrect RE-READ detection for manually finished books
- Enhanced Logic: Uses
/api/me
endpoint for accurate finished book detection - False Positive Prevention: Checks
isBookFinished
status before treating as re-read - Conservative Approach: Added safeguards for books with finished reads but 0% API progress
- URL Support: Fixed AudiobookShelf URL handling for reverse proxy configurations
- Enhanced Logic: Uses
-
🔧 Status Update Bug Fix: Fixed missing user book status mutations in Hardcover
- Complete Implementation: Added proper status update GraphQL mutations
- Want to Read Fix: Prevents finished books from being incorrectly marked as "Want to Read"
- Status Consistency: Ensures status changes are properly reflected in Hardcover
-
🔧 GraphQL Mutation Issues: Fixed various GraphQL operation problems
- URL Handling: Fixed mutations failing with local AudiobookShelf cover URLs
- Mutation Structure: Corrected GraphQL mutation syntax and variable handling
- Error Recovery: Improved error handling and fallback mechanisms
Changed
- 🔧 ASIN Enhancement Logic: Completely redesigned Audible ASIN reference system
- Honest Implementation: Removed misleading "enhanced with external metadata" claims
- ASIN Reference Only: Simple, reliable ASIN reference without false enhancement promises
- Transparent Markers: Clear "ASIN: {value}" markers in mismatch JSON files
- Source Attribution: Uses
"hardcover+asin"
for ASIN reference tracking
Removed
- ❌ Non-functional API Integrations: Cleaned up misleading external API integration code
- Audible API: Removed non-functional Audible API integration attempts
- Web Scraping: Removed blocked web scraping implementations
- False Claims: Eliminated code that claimed external metadata enhancement capabilities
- Configuration Cleanup: Removed non-functional environment variables
Refactoring
- 📁 Project Structure: Organized project structure for better maintainability
- Scripts Directory: Moved build and deployment scripts to
scripts/
folder - Documentation: Consolidated feature documentation in
docs/
directory - Test Organization: Better organization of test files by feature area
- Dockerfile Updates: Updated paths for reorganized structure
- Scripts Directory: Moved build and deployment scripts to
Performance
- ⚡ Massive Performance Improvements: Multiple optimizations for large libraries
- Cache System: 70-90% reduction in API calls through intelligent caching
- Smart Detection: Reduced redundant API operations through better detection logic
- Efficient Queries: Optimized GraphQL queries to fetch only necessary data
- Memory Management: Automatic cache cleanup and memory optimization
Fixed
- 🔧 CRITICAL: Edition Field NULL Fix: Fixed critical bug where
edition
field becamenull
inuser_book_read
entries- Root Cause:
insertUserBookRead()
andupdate_user_book_read
mutations were missingedition_id
field inDatesReadInput
objects - Data Loss Prevention: Without
edition_id
, Hardcover couldn't link reading entries to specific editions, causingedition
field to becomenull
- Function Enhancement: Modified
insertUserBookRead()
signature to accepteditionID
parameter - Mutation Updates: Added
edition_id
field to both insert and updateDatesReadInput
objects with validation - Sync Logic: Updated sync.go to pass
existingEditionId
fromcheckExistingUserBook()
context - Debug Features: Added diagnostic logging and
diagnoseNullEdition()
calls for troubleshooting - Data Integrity: Preserves edition information in all user reading entries, preventing loss of audiobook edition context
- Test Coverage: Comprehensive test suite in
edition_field_fix_test.go
with 100% pass rate - Impact: Critical fix for maintaining reading history integrity with proper edition tracking
- Root Cause:
- 🎯 Honest Enhancement Markers: Simplified mismatch enhancement to accurately reflect actual capabilities
- Issue: Previous markers claimed "enhanced with external metadata" when only ASIN was added
- Fix: Replaced with honest "ASIN: {value}" reference markers when ASIN is available
- Source: Uses
"hardcover+asin"
source attribution for ASIN reference only
Removed
- ❌ Non-functional API Integrations: Removed misleading external API integration code
- Reason: Audible has no public API available, and web scraping is blocked by anti-bot measures
- Cleanup: Removed
audible.go
,openlibrary.go
, and related non-functional integration files - Honest Implementation:
enhanceWithExternalData()
now only adds ASIN reference without false enhancement claims - Configuration: Removed non-functional environment variables (
AUDIBLE_API_ENABLED
,AUDIBLE_API_TOKEN
,AUDIBLE_API_TIMEOUT
) - Documentation: Updated to reflect actual capabilities instead of theoretical integrations
Fixed
- 🔧 RE-READ Detection Fix: Fixed incorrect RE-READ detection for manually finished books
- Root Cause: Books marked as "Finished" in AudiobookShelf but showing 0% progress due to API detection issues were incorrectly treated as re-read scenarios
- Enhanced API Integration: Now uses
/api/me
endpoint for accurate finished book detection withisFinished
flags - Smart Logic: Modified RE-READ detection to check
isBookFinished
status before treating as re-read scenario - Conservative Skip Logic: Added safeguards for books with finished reads in Hardcover but 0% progress in AudiobookShelf
- URL Fix: Updated AudiobookShelf URL handling to support reverse proxy with
/audiobookshelf
path prefix - Type Corrections: Fixed API response type definitions to match actual
/api/me
endpoint structure - False Positive Prevention: Eliminates incorrect duplicate read entries for books like "If I Was Your Girl" and "Earth Afire"
- Backward Compatible: Maintains compatibility with existing API responses and configurations
- 🔧 1000x Progress Multiplication Error: Fixed critical bug where progress values were being multiplied by 1000
- Root Cause: AudiobookShelf API sometimes returns
currentTime
in milliseconds whiletotalDuration
is in seconds - Unit Conversion: Added automatic detection and conversion of millisecond values to seconds
- Smart Detection:
convertTimeUnits()
function intelligently identifies when conversion is needed - Comprehensive Fix: Applied unit conversion throughout all progress calculation paths
- Progress Calculation: Updated
calculateProgressWithConversion()
to handle mixed units - API Response Debugging: Added
debugAPIResponse()
function to identify unit mismatches - Backward Compatible: Maintains compatibility with correctly formatted API responses
- Test Coverage: Added comprehensive tests including reproduction of original bug scenario
- Real-world Impact: Prevents progress values like 500.0 or 1000.0 being sent to Hardcover instead of 0.5 or 1.0
- Root Cause: AudiobookShelf API sometimes returns
[v1.5.0] - 2025-06-08
Added
- 📚 Owned Books Query Functions: Added proper owned books querying capabilities
OwnedBook
struct: Data structure for representing owned books with complete metadatagetOwnedBooks()
function: Retrieves all books from user's "Owned" list using correct GraphQL queryisBookOwnedDirect()
function: Checks if a specific book is owned by querying the lists table- Key Discovery: Hardcover stores ownership in the "Owned" list, not the
user_books.owned
field - Correct API Usage: Uses
lists
table approach instead of faultyuser_books.owned
field - Well-Documented: Functions include comments explaining the correct ownership model
- Future-Ready: Core functions available for implementing owned books sync features
Fixed
- 📚 Owned Flag Auto-Fix: Fixed and enhanced owned flag handling for books that are skipped during sync
- Modified
checkExistingUserBook()
to return both owned status and edition_id from Hardcover - Updated sync logic to automatically mark books as owned using
edition_owned
mutation when needed - Added comprehensive owned flag checking even when status/progress are up-to-date
- Integrated
markBookAsOwned()
function to actually fix missing owned flags (not just detect them) - Enhanced logging for all owned flag operations and edge cases
- Created comprehensive test coverage for owned flag scenarios
- Key improvement: Books that should be owned are now automatically marked as owned during sync
- Modified
[v1.4.1] - 2025-06-07
Fixed
- 🌍 Container Timezone Support: Fixed timezone handling in Docker containers
- Issue: Container logs showed UTC timestamps regardless of
TZ
environment variable - Solution: Added
tzdata
package to Alpine base image and timezone configuration in Go application - Functionality: Container now properly respects
TZ
environment variable (e.g.,TZ=Europe/Vienna
) - Compatibility: Maintains backward compatibility - works with or without
TZ
variable - Logging: Application now logs timezone confirmation when
TZ
is set - Technical: Go application sets
time.Local
based onTZ
environment variable
- Issue: Container logs showed UTC timestamps regardless of
[v1.4.0] - 2025-06-07
Added
- 🏠 Owned Books Marking: New feature to mark synced books as "owned" in Hardcover
- Environment Variable:
SYNC_OWNED=true
(enabled by default) - Functionality: Automatically marks synced books as "owned" to distinguish from wishlist items
- Integration: Added to
insert_user_book
GraphQL mutation when creating new user books - Configuration: Can be disabled with
SYNC_OWNED=false
if ownership tracking not desired
- Environment Variable:
- 🧪 Comprehensive Test Coverage: Added
owned_test.go
with 12 test cases- Tests environment variable parsing with various boolean values
- Validates default behavior (enabled by default)
- Ensures proper handling of edge cases and invalid values
- 📖 Documentation: Updated README.md with owned books sync section
- Added
SYNC_OWNED
to environment variables table - Created dedicated "Owned Books Sync" configuration section
- Updated features list to highlight ownership tracking capability
- Added
Changed
- 📚 User Book Creation: Enhanced sync logic to include ownership information
- Modified
userBookInput
map to include"owned": true
whengetSyncOwned()
returns true - Only affects newly created books; existing books in Hardcover remain unchanged
- Ownership status is independent of reading status (Want to Read, Currently Reading, Read)
- Modified
Technical Details
- Config Function: Added
getSyncOwned()
function following same pattern asgetSyncWantToRead()
- Default Behavior: Enabled by default to provide better library organization out of the box
- API Integration: Seamlessly integrates with existing Hardcover GraphQL mutations
- Testing: 100% test coverage for the new functionality with comprehensive edge case handling
[v1.3.2] - 2025-06-05
Changed
- 🎯 DEFAULT BEHAVIOR: "Want to Read" sync is now enabled by default
- Breaking Change:
SYNC_WANT_TO_READ
now defaults totrue
instead offalse
- User Impact: Unstarted books (0% progress) will automatically sync to Hardcover as "Want to Read" status
- Migration: Users who prefer the old behavior can set
SYNC_WANT_TO_READ=false
to disable - Logic Update: Changed from opt-in (
"true"
) to opt-out (!= "false", "0", "no"
)
- Breaking Change:
Added
- 📖 "Want to Read" Feature Documentation: Comprehensive documentation for the "Want to Read" sync feature
- Added detailed "Want to Read Sync" section to README.md with use cases and examples
- Updated environment variables table to reflect new default behavior
- Added configuration examples and migration guidance
- 🧪 Comprehensive Test Suite: Created
want_to_read_test.go
with 17 tests- 12 environment variable tests covering default behavior and edge cases
- 5 status logic tests validating status determination for different progress levels
- 100% test coverage for the "Want to Read" feature
Fixed
- 📚 Book Filtering Logic: Enhanced book filtering to properly include 0% progress books when "Want to Read" sync is enabled
- Updated
runSync()
to check both progress threshold and "Want to Read" configuration - Added debug logging for books included via "Want to Read" sync
- Updated
- 🎛️ Configuration Logic: Improved
getSyncWantToRead()
function with robust default handling- Defaults to
true
for better out-of-the-box experience - Handles edge cases like empty values, invalid strings, and case variations
- Maintains backward compatibility while improving user experience
- Defaults to
Technical Details
- Status Mapping: 0% progress → "Want to Read" (status_id=1) when enabled, "Currently Reading" (status_id=2) when disabled
- Environment Variable:
SYNC_WANT_TO_READ=true
(default), set tofalse
/0
/no
to disable - Performance: No performance impact as filtering logic is optimized
[v1.3.1] - 2025-06-05
Fixed
- 🚨 CRITICAL: Fixed reading history being wiped out when updating existing
user_book_read
entries- Issue: When updating progress on existing reads,
started_at: null
was being preserved, removing reading history - Root Cause:
update_user_book_read
mutation was only sendingprogress_seconds
without ensuringstarted_at
is set - Fix: Always set
started_at
to current date when updating existing reads to prevent null values - Impact: Prevents loss of reading start dates and maintains proper reading history
- Also ensures
finished_at
is properly set when books reach 99%+ completion - Added comprehensive test coverage for the reading history fix
- Issue: When updating progress on existing reads,
[v1.3.0] - 2025-06-05
Added
- 🚀 Incremental/Delta Sync: Major performance improvement with timestamp-based incremental syncing
- Added persistent sync state management with
sync_state.json
file - Only processes books with changes since last sync using AudiobookShelf listening session timestamps
- Automatic fallback to full sync when incremental data is unavailable or on first run
- Configurable sync modes:
enabled
(default),disabled
, orauto
- Smart full sync scheduling: automatically performs full sync after 7 days or when forced
- New environment variables:
INCREMENTAL_SYNC_MODE
: Control incremental sync behaviorSYNC_STATE_FILE
: Custom path for sync state storage (default:sync_state.json
)FORCE_FULL_SYNC
: Force full sync on next run (automatically resets after use)
- Comprehensive logging to show sync mode and progress
- Reduces API calls significantly for large libraries with minimal changes
- Added persistent sync state management with
Fixed
- LibraryItemID Field Reference: Fixed incorrect field access in incremental sync filtering
- Changed from
book.Metadata.LibraryItemID
tobook.ID
to match actual data structure - Ensures proper book filtering in incremental sync mode
- Changed from
- Duplicate User Book Reads: Fixed issue where multiple
user_book_reads
entries were created for the same book when reading across different days- Modified
checkExistingUserBookRead()
to check for any unfinished reads instead of date-specific reads - Changed GraphQL query from
started_at: { _eq: $targetDate }
tofinished_at: { _is_null: true }
- Added ordering by
started_at desc
to get the most recent unfinished read - Prevents duplicate read tracking entries when continuing books on different days
- Modified
- Panic Fix: Fixed runtime panic when Hardcover returns
user_book_reads
with nullstarted_at
values- Added nil check for
userBookRead.StartedAt
before dereferencing in debug logs - Use "null" string when
StartedAt
is nil instead of causing application crash - Prevents
invalid memory address or nil pointer dereference
error
- Added nil check for
Changed
- Performance Optimization: Reduced
getCurrentUser()
API calls from 3 per book to 1 per sync run- Added caching mechanism for current user authentication
- Cache is cleared at start of each sync run to ensure fresh authentication
- Significantly reduces API load and improves sync performance for large libraries
- For 100 books: reduces from 300 API calls to 1 per sync session
Technical Details
- Added
incremental.go
with sync state management functions - Enhanced
fetchRecentListeningSessions()
to query AudiobookShelf sessions API with timestamp filtering - Modified
runSync()
to integrate incremental sync logic with existing sync workflow - Added comprehensive test coverage for incremental sync functionality
- Backward compatible: existing setups continue to work without configuration changes
[v1.2.4] - 2025-06-04
Added
- Enhanced Formatting: Improved readability of duration and date displays in mismatch reports
- Added
formatDuration()
function to convert decimal hours to human-readable "Xh Ym Zs" format - Added
formatReleaseDate()
function with support for multiple date formats (YYYY-MM-DD, MM/DD/YYYY, etc.) - Enhanced mismatch collection to use new formatting functions for better user experience
- Comprehensive test coverage for new formatting functions with example outputs
- Added
- Build Improvements: Added test binaries to .gitignore to keep repository clean
Technical
- Refactored mismatch metadata handling to use centralized formatting functions
- Added support for parsing various date formats including partial dates (year/month only)
- Improved duration display consistency across all mismatch reporting
[v1.2.3] - 2025-06-04
Fixed
- API Fix: Corrected Hardcover GraphQL API URL in
checkExistingFinishedRead()
function fromhttps://hardcover.app/api/graphql
tohttps://api.hardcover.app/v1/graphql
- Resolved: 404 error warning "Failed to check existing finished reads" that was appearing in production logs
- Cleanup: Removed empty test files that were causing build issues
[v1.2.2] - 2025-06-04
Fixed
- Runtime Fix: Fixed JSON unmarshaling error in
getCurrentUser()
function where Hardcover'sme
query returns an array instead of expected object - Added: Debug logging for
getCurrentUser()
response to aid troubleshooting - Added: Validation for empty user data response in
getCurrentUser()
- Note: This patch enables the security features introduced in v1.2.1 to work properly
[v1.2.1] - 2025-06-04
Security
- CRITICAL: Fixed GraphQL security vulnerability where API returned data from other users
- Fixed: GraphQL variable type mismatch (
String!
vscitext!
) causing query failures - Added: Explicit user filtering to all GraphQL queries to prevent cross-user data leakage
- Added:
getCurrentUser()
function for authenticated user validation - Enhanced: Defense-in-depth security with relationship-based filtering in
user_book_reads
queries - Fixed: Enhanced query strategy with user-scoped fallback queries
Technical
- Updated
checkExistingUserBook()
with proper user filtering and improved ordering - Added user validation to
checkExistingUserBookRead()
andcheckExistingFinishedRead()
- Changed GraphQL ordering from invalid
created_at
to validstarted_at
field - All queries now include
user: { username: { _eq: $username } }
filtering
[v1.2.0] - 2025-06-03
Added
- Enhanced Mismatch Collection: Upgraded book mismatch tracking system with rich metadata
- Added detailed metadata fields: subtitle, narrator, publisher, published year/date, duration
- Duration display in human-readable hours format (e.g., "18.1 hours")
- Enhanced
Audiobook
struct to carry full metadata through sync process - Comprehensive mismatch summaries with all available book information
- Improved manual review process with better identification data
- Backward Compatibility: Preserved original
addBookMismatch()
function for existing integrations
Technical
- Extended
BookMismatch
struct with 7 additional metadata fields - Created
addBookMismatchWithMetadata()
function with metadata processing - Updated sync process to use enhanced metadata collection at all mismatch points
- Added metadata flow from
fetchAudiobookShelfStats()
through to mismatch collection
[v1.1.0] - 2025-06-02
Added
- Book Matching Mismatch Collection: New comprehensive system to track and report books that may need manual verification
- Collects three types of mismatches: complete lookup failures, audiobook edition failures, and fallback matches
- Provides detailed summaries after sync with actionable recommendations
- Helps users identify books requiring manual review
- Configurable Audiobook Edition Matching: New
AUDIOBOOK_MATCH_MODE
environment variablecontinue
(default): Log warning and sync with available book dataskip
: Skip problematic books to avoid wrong edition syncsfail
: Stop sync immediately when audiobook edition cannot be verified
- Conditional Sync Logic: Smart API usage to avoid unnecessary Hardcover API calls
- Checks existing read status before making changes
- Only syncs when progress has actually changed
- Reduces API load and improves performance
- Version Injection: Build system now properly injects version information
- Comprehensive Documentation: Organized feature docs in
docs/
folder
Fixed
- Critical: Duplicate user_book_read entries spam in Hardcover feed
- Critical: Progress data mapping bug in AudioBookShelf sync
- Critical: Detection of manually finished books in AudiobookShelf
- Critical: Include 100% completed books in sync process (was excluding them)
- Critical:
getMinimumProgressThreshold()
returning 0.0 instead of correct default 0.01 - GraphQL mutation errors with user_book_read operations
- GraphQL query syntax issues in book lookup functions
- Improved _ilike to _eq for more precise GraphQL queries
- Enhanced response validation for GraphQL mutations
- Input validation for configuration threshold values
Changed
- Major Code Refactoring: Extracted sync functionality into separate modules for improved maintainability
- Split monolithic
main.go
(~774 lines) into focused modules - Created
sync.go
(630 lines) for core sync logic - Created
audiobookshelf.go
for AudiobookShelf API interactions - Created
hardcover.go
for Hardcover API interactions - Created
config.go
for configuration management - Created
types.go
for data structure definitions - Created
utils.go
for utility functions - Created
mismatch.go
for book matching mismatch handling - Reduced
main.go
to 144 lines (startup, HTTP endpoints, lifecycle management)
- Split monolithic
Technical Improvements
- Better separation of concerns between application lifecycle and business logic
- Improved code organization and modularity
- Enhanced maintainability for future development
- Easier testing of individual components
- Multi-architecture Docker builds (amd64, arm64)
- Build reproducibility and cache optimization
- All existing functionality preserved and tested
Notes
- This is a major feature and refactoring release with no breaking changes
- All existing features and API compatibility maintained
- No configuration changes required for existing users
- New environment variables are optional with sensible defaults
[v1.0.0] - Previous Release
- Initial stable release with full sync functionality between AudiobookShelf and Hardcover