Introduce a TasksSkeleton component to display animated placeholders while scheduled tasks are loading. Replace direct rendering of empty task rows with the skeleton when data is pending, enhancing perceived responsiveness and user experience in the admin tasks panel.
Introduce a document blob lease mechanism to prevent race conditions between document registration and orphaned blob cleanup. The new `document_blob_leases` table ensures that only one process can claim a document blob for mutation or deletion at a time. Update the orphan reaper to acquire a lease before deleting blobs and to re-check for ownership after acquiring the lease, avoiding accidental deletion of in-flight uploads.
Enhance scheduled task infrastructure with per-task fencing tokens to prevent stale runners from overwriting newer results, enforce runtime limits with abort signals, and expose scheduler mode and minimum interval to the admin panel and API. Adjust task handlers to accept a context with abort support, and update documentation and environment variable references for the new cron secret and scheduling behavior.
BREAKING CHANGE: Scheduled tasks now require a `document_blob_leases` table and updated handler signatures. Vercel deployments must set `CRON_SECRET` for scheduled maintenance.
Replace the bordered div layout in AdminTasksPanel with the Card component for
improved visual hierarchy. Add a dynamic running indicator using a custom
RunningDot component to clearly show active tasks. Update control alignment and
button states for better usability. Remove Badge-based status display in favor
of a more streamlined appearance.
Eliminate ffmpeg-static from the production node_modules during Docker image
assembly to streamline the deployment artifact and avoid bundling unused binaries.
Add database-level check constraints to ensure scheduled task intervals are always
positive for both Postgres and SQLite. Update admin API and UI to support sub-minute
intervals and stricter validation. Refactor scheduled task update logic to upsert
rows, ensuring tasks can be updated even if not yet present in the database.
Improve temporary upload cleanup to delete in paginated batches. Enhance tests to
cover new constraints and update behaviors.
Change cron schedule for /api/admin/tasks/tick from hourly to once daily at
midnight to reduce task frequency and align with updated operational
requirements.
Move Node.js-specific instrumentation logic to a dedicated file. Update
registration to dynamically import the node module only when running in a
Node.js environment. This separation clarifies environment-specific behavior
and improves maintainability.
Simplify user document transfer by consolidating storage and metadata handling. Remove inline deletion of shared blobs; only metadata is moved, and TTS segment transfer is controlled via options. Add `skipStorage` option for test scenarios to bypass storage operations. Update tests to reflect new transfer behavior.
Add a general-purpose scheduled task system with a persistent registry and status tracking, supporting background maintenance jobs such as orphaned blob reaping, expired upload cleanup, job event pruning, and TTS usage retention. Implement a new `scheduled_tasks` table, task engine, and handlers for each maintenance operation. Integrate an admin UI panel for monitoring, manual runs, and configuration of tasks. Update document and user data cleanup flows to delegate shared blob and preview deletion to the scheduled reaper. Add Vercel cron integration for serverless environments.
BREAKING CHANGE: Document and user storage cleanup now relies on background scheduled tasks for shared blob and preview deletion; immediate inline deletion is no longer performed.
Enhance error handling during document deletion by ensuring that failures
in restoring document ownership do not obscure the original error. Log
degraded events when ownership restoration fails after a deletion error,
providing additional context for debugging and monitoring. This change
improves reliability and traceability of document deletion operations.
Replace mutation-lock with document-lock to centralize document mutation
serialization and database transaction management. Introduce runInDbTransaction
utility to abstract SQLite/Postgres transaction differences. Update document
deletion, user data cleanup, and rate limiter logic to delegate transaction
handling and locking to shared helpers. Remove dialect-specific branching and
inline transaction logic for improved maintainability and testability.
BREAKING CHANGE: withDocumentMutationLock is removed in favor of withDocumentLock and runInDbTransaction
Enhance robustness of document deletion and TTS segment transfer by improving
error logging, partial rollback, and degraded state reporting. Add best-effort
cleanup and recovery mechanisms to prevent orphaned data and ensure diagnostic
information is captured for unexpected failures. Update user data cleanup to
log and swallow restoration errors without masking primary failures. Refine
claim logic to handle unmapped TTS audio keys safely.
Expand the anonymous data claim process to include document settings transfer and TTS segment S3 prefix copying. Remove foreign key constraints from user_tts_chars to allow non-user buckets. Update claim modal and onboarding flow to display claimed document settings. Refactor TTS char count transfer to merge all dates and fix upsert logic. Add S3 copy utility for TTS segments and corresponding tests. Update migrations and schema to reflect relaxed constraints.
Introduce `deleteOwnedDocument` utility to encapsulate all logic for removing a user's ownership of a document, including TTS segment cache cleanup, preview artifact removal, and S3 blob deletion for last-owner cases. Add `withDocumentMutationLock` to serialize concurrent mutations on the same document, using advisory locks in Postgres and a local queue fallback. Refactor all API routes and user data flows to use these utilities, ensuring transactional safety and preventing race conditions during document deletion or transfer. Update tests for new flows and add coverage for document cleanup sequencing and locking behavior.
Add tests for user data cleanup with shared document ownership and for TTS segment
variant export scenarios, including cases with duplicate audio keys and storage
disabled. Refactor cleanup logic to use document row types and transactional
ownership removal with last-owner checks. Update TTS segment cache clearing to
report deleted segment count by unique entry. Adjust export logic to always
include all TTS segment variants and conditionally export file buckets based on
storage availability. Update migration to use NOT VALID/VALIDATE for new
cascading constraints.
Revise user data cleanup logic to ensure proper cascading deletion of user-related
database rows and S3 objects, including shared document and preview artifacts.
Introduce explicit checks for last ownership before removing shared resources.
Add TTS segment cache and audio cleanup to document and user deletion flows.
Expand user data export to include TTS segment entries and audio, job events,
document settings, and linked auth sessions. Update schema with ON DELETE CASCADE
for userTtsChars and userJobEvents. Add new migration scripts and comprehensive
unit tests for cleanup and export scenarios.
Adjust language input resolution in TTS generation to ensure Replicate Kokoro
model receives the appropriate language code mapping even when the language
property is absent or falsy. Update tests to cover this scenario and verify
correct input construction.
Eliminate documentation of TTS and compute PDF parsing rate limiting options from the environment variables reference, as these are managed exclusively via runtime configuration in the admin UI and do not correspond to environment variables. This clarifies the distinction between environment-based and runtime-managed settings.
Update provider seeding logic and documentation to allow creation of admin/shared providers without requiring an API key. Adjust environment variable handling so that a blank or missing API_KEY is valid when API_BASE is set, enabling support for upstream TTS providers that do not require authentication. Remove defaulting to 'none' for API keys in API routes and ensure headers are omitted when no key is present. Add and update tests to verify correct handling of keyless providers.
BREAKING CHANGE: Providers can now be seeded without an API key; API_KEY is no longer required if API_BASE is set. Existing deployments relying on a non-empty API_KEY for seeding should review their environment configuration.
Update preference normalization logic to explicitly reject arrays when
validating record types, ensuring only plain objects are accepted. Adjust
ConfigProvider effect conditions for clarity and correctness. Add unit tests
verifying that arrays are not accepted as valid preference records or saved
voices.
Implement logic to resolve and inject Replicate Kokoro model-specific language
codes based on language tag and voice, using new mapping utilities. Update
`buildReplicateInput` to set `language_code` for the built-in Kokoro model.
Expand language utilities with code mapping and expose `resolveReplicateKokoroLanguageCode`.
Enhance tests to cover language code resolution and input mapping for Replicate
Kokoro, and verify language input key discovery for built-in models.
Move provider normalization logic into a dedicated module to ensure consistent
handling of provider defaults and user preference inheritance across client and
server. Update layout components to mount ConfigProvider only at the shared
layout level, preventing unnecessary remounts and hydration issues during
navigation. Adjust app config defaults so user provider settings are empty by
default, always inheriting the admin-configured provider unless explicitly set.
Add tests for normalization and sync logic to ensure robust provider resolution.
Add multilingual reader and TTS support
- Detect, normalize, persist, and expose document language across EPUB, PDF, HTML, TTS segment, and audiobook workflows.
- Forward supported language inputs to TTS providers, warn on voice/document language mismatches, and prevent incompatible Kokoro voice selections.
- Centralize Unicode-aware token alignment so EPUB, HTML, and PDF highlighting handles multilingual text, including Japanese matching.
- Standardize shared select, checkbox, button, input, menu, and popover primitives across reader, settings, admin, authentication, and public UI surfaces.
- Update README, introduction docs, and landing-page copy to describe multilingual narration and highlighting.
Remove internal selectedVoices state and use a memoized value based on the voice
prop to determine the selected voices. Avoid side effects on selection display,
ensuring that voice selection persists even when available voices are refetched.
This addresses issues where transient backend states could cause unwanted resets
to the first voice option.
Update introduction documentation and README to consistently refer to
OpenReader as "open-source" and highlight its multilingual capabilities.
Refine language segmentation example in multilingual sample text and
expand test coverage for language settings. Adjust TTS segment manifest
to normalize language tags, improve document language update logic, and
fix provider/model compatibility checks for instructions and language
input. Enhance reliability of language support detection for TTS
generation and Replicate provider integration.
Add a fast linear scan to resolve exact token sequence highlights before
falling back to the fuzzy window search, significantly improving
performance for large documents. Update unit tests to verify that
exact matches are found efficiently without invoking expensive
comparisons.
Expand README and introduction to highlight multilingual features,
including language-aware narration and highlighting. Update landing
page to reflect multilingual capabilities in descriptions, keywords,
and UI labels.
Eliminate the Playwright test matrix to run all browser projects in a single job.
Consolidate report artifact naming and streamline workflow configuration for
faster and more maintainable CI execution.
Move pdf.js worker and standard font resolution logic into dedicated
utility functions for improved maintainability and clarity. Replace
inline workerSrc setup with a reusable configurePdfjsNodeRuntime helper.
Update Next.js config to use a shared asset trace list for pdf.js runtime
files, reducing duplication and simplifying future updates.
Add 'pdfjs-dist' to serverExternalPackages in Next.js config to prevent bundling,
ensuring runtime resolution of on-disk assets like standard_fonts. Update
tracing includes for API preview route to explicitly cover worker and font
resources loaded dynamically.
Move encodeParserVersion to a dedicated module for unified access and remove local duplicates. Update all consumers to import from the new entrypoint. Tighten artifact readiness checks in both client and API route to ensure 'ready' is only reported when the artifact is accessible, with retries and stricter validation. Add tests for edge cases and operation state validation.
Standardize import of PDF_PARSER_VERSION across server modules to reference
@openreader/compute-core/api-contracts. This clarifies versioning boundaries
and improves maintainability by consolidating contract exports.
Eliminate parseState and parsedJsonKey columns from the documents table in both
Postgres and SQLite schemas, including related migration scripts and type
removal in document registration logic. This aligns the schema with the new
worker-based PDF parse model and reduces legacy field clutter.
Introduce new unit tests covering the PDF parse client lifecycle and worker-based
API routes. Tests verify client behavior for not-ready and ready parse states,
operation initiation, SSE event handling, and route validation. Also add
coverage for worker event proxy and worker flow routes. Remove all legacy
parseStatus and parsedJsonKey fields from document types, API, and gallery
view components to align with the new worker-owned PDF parse model.
This change removes legacy server-side PDF parse state management and transitions
to a fully worker-owned model for PDF parsing operations. Key updates include:
- Deletes all code related to server-managed parse state, including:
- parse-state.ts, parse-state-backfill.ts, parse-state-healing.ts,
parsed-pdf-reuse.ts, pdf-parse-operation.ts, and related job logic
- Removes the user-pdf-layout-job queue and associated job logic
- Refactors API routes for parsed PDF documents and events to use the new
worker-owned PDF parse operation flow under src/lib/server/pdf-parse/
- Updates S3 parsed PDF artifact keying to include parser version for
deduplication and compatibility
- Refactors client API and hooks to handle new error and progress reporting
- Removes all tests for the legacy parse state and job system, updating remaining
tests to mock the new worker-owned flow
BREAKING CHANGE: Server no longer manages per-user PDF parse state or jobs.
All PDF parsing is now managed by the compute worker and new artifact keying.
Legacy parse state and jobs are no longer supported. Existing parsed PDFs may
need to be reprocessed for compatibility with the new model.
Update folder tests to use an exported escapeRegExp helper when constructing
regex patterns for file name matching. This prevents false positives or errors
when file names contain special regex characters, improving test reliability.
## Summary by CodeRabbit
* **New Features**
* Expose PDF parser version system-wide; parser-version-aware parsing, reuse, and caching. Added tokenized temp upload flow, presign/finalize endpoints, and server-side DOCX→PDF conversion.
* Playback readiness propagated to TTS players/pages; unified upload/delete APIs and simplified uploader/sidebar UX.
* **Bug Fixes**
* Normalize stored parse state to current parser version to avoid stale readiness and improve reuse.
* Prevent premature playback starts and redundant preparation.
* **Tests**
* Added unit and E2E tests for parser-version handling, op-key inclusion, parse-state behavior, and canonical upload reuse.