# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). > Version en espanol: [CHANGELOG.md](CHANGELOG.md) ## [Unreleased] ### Maintenance - Removed the discontinued agent runner and its exclusive development dependencies. - Removed internal audit reports and execution plans from the public source tree; Git and Docker exclusions now cover local automation artifacts and worktrees. - Removed completed implementation plans and the redundant README alias; updated the contribution guide for the current TypeScript codebase. - Limited the Docker build context to required inputs and the final application's files to compiled code. Excluded local runtime data, caches and development backups from Git. - Removed the unreachable legacy Radar enrichment implementation, along with its exclusive state, contracts and tests. The active Wantlist update workflow is preserved. - Corrected Radar's domain documentation to describe its current Wantlist management and local preferences, without automatic price review. ## [0.4.1] - 2026-09-30 Backend maintenance release focused on data integrity, authentication, cancellation and verified upgrades. ### Fixed - **Import identity** — imports resolve collection copies by consistent instance/release identifiers and reject ambiguous or conflicting rows, including duplicate identity columns. - **Durable imported edits** — pending ratings and notes survive restarts, partial failures and incoming synchronization. Revision checks and serialized writes keep older retries from replacing newer edits. Authenticated clients can retry with `POST /api/import/retry`; import status includes durable `pending` and `pendingFailed` field counts. - **Session revocation** — password changes and administrative resets invalidate earlier sessions; deleted accounts cannot continue using an old cookie. Login rechecks account state after password verification. - **Concurrent login limiting** — attempts reserve account, client and concurrent verification capacity before password verification, closing the parallel-request bypass. - **Cancelled job ownership** — stopped or reset account jobs cannot publish late results, repopulate cleared data or release a replacement run's lock. - **Sync completion** — a Discogs sync run remains active through inventory and cover warmup, and follow-up failures are reported instead of marking the run successful early. - **Wantlist snapshots** — malformed, duplicate or incomplete paginated responses cannot mark valid Radar records as missing. - **Inventory snapshots** — listing state is preserved until a complete, coherent inventory has been received, including accounts with several listings for the same release. - **Collection snapshots** — incomplete pagination cannot prune local copies or partially replace their data; separate instances of the same release remain valid. - **Discogs request deadlines** — bounded quota waits, requests, body reads and rate-limit retries honor cancellation. Retry delays are capped and response resources are released. - **Cover download deadlines** — cover downloads and body reads honor account/job cancellation and a 30-second deadline, including the authenticated media proxy and sync warmup. - **Docker Compose ports** — a custom host `PORT` keeps the container listener and health check on port 3800. - **Collection filter performance** — bounded facet caching avoids rescanning unchanged collections, remains valid across session writes and detects collection changes from other SQLite connections without retaining rolled-back values. - **Data boundaries** — reject malformed collection/inventory metadata before reconciliation, and normalize stored JSON array shapes on read so exports and statistics do not fail on malformed stored values. ### Changed - Restore TypeScript checking across the backend with explicit database, request and external-data contracts; remove the remaining backend `@ts-nocheck` directives. - Replace copied import-header, inventory and migration test algorithms with tests of production behavior. The complete Database schema lifecycle runs in one transaction so failed migrations roll back together. ### Upgrade notes - Existing databases migrate automatically. Sessions created before this release require a fresh login. - The durable import queue covers edits confirmed with this version; it cannot reconstruct previously lost in-memory failures. Retrying pending edits is an explicit backend API operation. [0.4.1]: https://github.com/SimonBlancoE/discographic/compare/v0.4.0...v0.4.1 ## [0.4.0] - 2026-09-29 Release with an interface redesign, new Discogs-powered features, a full stack upgrade and production hardening. ### Added - **Rarity & demand** - Discogs community data (have / want / average rating) with most wanted, coveted and rarest rankings. - **Media and sleeve condition** - grade filters, editing from the release page and a condition breakdown on the dashboard. - **Discogs folders** - folder filter and moving records between folders. - **Other pressings** - every version of the same master, flagging the ones you own and the ones in your Wantlist. - **Value according to Discogs** - collection minimum, median and maximum, with history saved on every sync. - **Suggested price by condition** - Discogs suggested price per grade, highlighting your copy (requires Discogs seller settings). - **Interface redesign** - sidebar and mobile tab bar, cover grid view, filter chips and collection state in the URL. - **Quieter design** - warm palette with a single gold accent, single-hue charts, and a welcome panel with real shortcuts instead of the dashboard carousel. - **Narrow screens** - figures and cards adapt to their panel width (container queries), with no overflow from 360 px phones to vertical monitors. - **README** - rewritten with fresh English and Spanish screenshots. ### Changed - **Stack** - Node 24 LTS, React 19, React Router 7, Recharts 3, Express 5, Vite 8, Tailwind CSS 4, TypeScript 7 and better-sqlite3 13. - **Radar** - the unsaved-changes warning now also covers the browser Back button. - **Security** - persistent random session secret when none is configured, `TRUST_PROXY` for proxy/Cloudflare deployments, login attempt limiting, session regeneration on login, security headers and a Docker `HEALTHCHECK`. - **Docker** - native modules are compiled in the build stage; the runtime image only ships production dependencies. ### Fixed - Editing notes could overwrite media or sleeve condition on Discogs. - Cover route vulnerable to path traversal. - An empty Discogs response could wipe the local collection. - Races in the price review and in the Discogs request limiter. - `xlsx` upgraded to 0.20.3 (CVE-2023-30533, CVE-2024-22363). - `sharp` upgraded to 0.35.4 and `qs` to 6.16.0 for known vulnerabilities. - Excel export downloaded a CSV, and format filters emptied the export. - Edits Discogs accepts are kept even if a later step fails, and two quick edits to the same release no longer overwrite each other. - Overly broad genre/style filters, country wiped on every sync, preferences lost on account change, formulas in exports, time-zone-shifted dates, broken Radar links and the print catalog capped at 100 records. [0.4.0]: https://github.com/SimonBlancoE/discographic/compare/v0.3.4...v0.4.0 ## [0.3.4] - 2026-07-04 Maintenance and robustness release fixing functional bugs and optimizing collection exports. ### Fixed - **ECB Exchange Rates Outages** - the application now falls back to static default rates instead of throwing an HTTP 500 error when the ECB API is offline. - **Discogs details page tolerance** - errors from Discogs API when retrieving details no longer crash the details page; the system falls back safely to local database entries. - **Cover Cache in CollectionTable** - the collection table now uses the local cover proxy endpoint instead of remote hotlinking. - **Performance optimization in export** - currency conversions are performed synchronously in batch, eliminating thousands of redundant async promises. - **Race condition in imports** - resolves a potential TypeError if a release is deleted concurrently during the import workflow. [0.3.4]: https://github.com/SimonBlancoE/discographic/compare/v0.3.3...v0.3.4 ## [0.3.3] - 2026-05-10 Documentation and metadata cleanup release. ### Changed - **Public repository references corrected** - README clone instructions, package metadata, contribution guidance, planning docs, and guardrail tests now point only to the public GitHub repository. - **Private development details removed** - repo-facing documentation no longer mentions private remotes, private upstream naming, or downstream publication wording. [0.3.3]: https://github.com/SimonBlancoE/discographic/compare/v0.3.2...v0.3.3 ## [0.3.2] - 2026-05-10 Documentation release for clearer project guidance. ### Changed - **README project intro clarified** - the opening section is now titled "What is Discographic?" and asks Discogs users, especially sellers, to share feedback because seller workflows need input from people who use them. - **Manual test instance separated** - the ephemeral QA instance instructions are now shown as a callout so they are not confused with normal setup. - **Contribution expectations clarified** - the README now says direct contributions are not accepted as a standing policy, while feedback, issues, and pull requests remain welcome and appreciated. [0.3.2]: https://github.com/SimonBlancoE/discographic/compare/v0.3.1...v0.3.2 ## [0.3.1] - 2026-05-08 Maintenance release with two improvements on top of 0.3.0: listing price on release details and polished Spanish translations. ### Fixed - **Listing price on release details** - the detail view now shows the listing price when available. - **Spanish translations polished** - the ES copy was normalized in imports, achievements, and repo metadata for more natural wording. ### Tests - Release verification focused on the version bump, changelog, and repository synchronization. [0.3.1]: https://github.com/SimonBlancoE/discographic/compare/v0.3.0...v0.3.1 ## [0.3.0] - 2026-05-02 Release focused on the full TypeScript migration, shared frontend/backend contracts, and upgrade verification for existing self-hosted installs. ### Added - **TypeScript-only source tree** - frontend, backend, shared modules, tests, scripts, and supported config migrated to `.ts`/`.tsx` or non-JS formats. - **Typed shared contracts** - account, release, marketplace, sync status, dashboard stats, and collection views now have explicit types and normalizers under `shared/contracts/`. - **Single verification pipeline** - `npm run verify` runs the JavaScript source scan, typecheck, tests, build, and upgrade smoke. - **Upgrade smoke from `v0.2.2`** - exercises compiled runtime and Docker against a legacy fixture to verify data, configuration, and startup paths. - **Compiled backend runtime** - production starts from `dist/server/start.js`; development runs TypeScript directly through `tsx`. - **Saved collection views** - filters, sort, and columns can be saved as reusable collection views. - **Implementation planning support** - runner, prompts, and working standards for implementation slices. ### Changed - **Split app/server build** - `npm run build` compiles Vite first, then the backend with `tsc -p tsconfig.server.json`. - **Route code splitting** - main bundles are smaller by loading pages on demand. - **Collection table rendering stabilized** - handlers, visible columns, and sort props keep stable references to avoid preventable renders. - **README and repository metadata** - public repository metadata and release guidance were documented alongside the migration scope. - **Contribution documentation** - `CONTRIBUTING.md`, PRD, and ADRs document the TypeScript-only rules, untrusted-boundary normalization, and verification. ### Fixed - **Marketplace states preserved** - unknown and failed states no longer collapse to zero, and legacy zero values are cleaned explicitly. - **Marketplace errors normalized** - failed responses expose consistent states to the frontend. - **Label filter** - long options no longer truncate prematurely. - **Docker lockfile** - lockfile synced with current dependencies. ### Tests - Suite migrated to TypeScript with coverage for shared contracts, runtime paths, TypeScript-only guardrails, code splitting, upgrade smoke, and vinyl badge behavior. Current verification: 183 tests. [0.3.0]: https://github.com/SimonBlancoE/discographic/compare/v0.2.2...v0.3.0 ## [0.2.2] - 2026-04-22 Visual patch for the feature carousel. ### Fixed - **Next slide bled through on the right edge** — the viewport padding introduced in 0.2.1 pushed the track off the area clipped by `overflow: hidden`, leaving part of the adjacent slide visible on the right. Padding moved into each slide with `box-sizing: border-box`. The viewport is now a pure overflow container again. [0.2.2]: https://github.com/SimonBlancoE/discographic/compare/v0.2.1...v0.2.2 ## [0.2.1] - 2026-04-22 Patch with fixes to the dashboard feature carousel and the header logo badge. ### Fixed - **Carousel buttons did not respond** — the drag pointer handler was capturing the whole container and intercepting clicks on arrows and dots. Pointer is now scoped to the viewport only. - **Autoplay cycled too fast** — raised from 9s to 14s; manual-interaction resume delay raised from 3s to 5s. - **Spanish translations** — rewritten in neutral Castilian Spanish. Dropped DJ jargon ("maleta", "pick", "cavando", "Spin the Crate", "tapete"). English copy trimmed to match: plainer, more direct phrasing. - **Hover caused elements to move** — removed the mouse-parallax on hero chips and orbs. Hover interaction is now a subtle cyan border glow on the carousel viewport, with no element movement. ### Changed - **"Next up" indicator removed** — the ticker is gone entirely. - **Header logo badge enlarged** — from 3.2rem to 5.25rem (record disc from 2.35rem to 4.2rem). Hover still accelerates the spin animation, but no longer surfaces the genre caption. [0.2.1]: https://github.com/SimonBlancoE/discographic/compare/v0.2.0...v0.2.1 ## [0.2.0] - 2026-04-22 Release focused on dashboard and wall performance, sync robustness, import and media localization, plus a broad refactor that lifts shared logic into reusable modules. ### Added - **Dashboard Hero Carousel** — animated feature carousel with autoplay, pointer and keyboard navigation, and `prefers-reduced-motion` support. - **VinylBadge** — spinning badge surfacing the collection's top genres, animation paused under `prefers-reduced-motion`. - **DashboardStatsContext** — shared provider that centralizes dashboard stats loading and removes duplicate fetches across consumers. - **Stats contract** — `shared/contracts/dashboardStats.js` normalizes backend payloads into a stable shape for the frontend. - **Cover wall virtualization** — `WindowedCoverWallGrid` renders only visible rows; large collections scroll without jank. - **Post-sync reconciliation** — full syncs prune release rows that no longer exist in the user's collection and clean up cached covers for them. - **Import and media fallback localization** — import messages and cover fallback strings now honor the user's locale. - **Shared notes service** — `server/services/notes.js` unifies note normalization, serialization, and cleanup across sync, import, and export. - **Cover media service** — `server/services/coverMedia.js` centralizes cover caching, variants (wall/poster), and cleanup. - **Shared release filters** — `server/services/releaseFilters.js` and `shared/collectionFilters.js` consolidate filters used by stats, collection, and export. - **Import sync** — `server/services/importSync.js` + `src/lib/importSync.js` push imported notes and ratings back to Discogs with progress state. - **Typed contracts under `shared/contracts/`** — first step toward an explicit frontend/backend contract surface. - **Tests** — new coverage for collection filters, reconciliation, cover media, export parity, import progress, notes normalization, wall metrics, stats contract, badge genres, marketplace_status migration, and marketplace value fetch. Total: 217 tests. ### Fixed - **`marketplace_status` migration re-running every boot** — backfill now runs only when the column is first added, preserving existing statuses on re-runs. - **Silent marketplace fetch errors** — `fetchMarketplaceValue` now logs `releaseId` and `error.message` before returning `FAILED`. - **Unnecessary re-renders in dashboard consumers** — `refresh` wrapped in `useCallback`, `badgeGenres` memoized, and `getDashboardBadgeGenres` reduced to a pure slice with no re-normalization. - **Export/import parity** — notes and derived fields round-trip without losing metadata. - **Import notes sync** — imported notes now sync back to Discogs correctly. ### Changed - **Shared helper refactor** — collection, cover, and filter helpers no longer duplicated across routes and services. - **Dashboard.jsx** — consumes the shared context instead of managing its own stats fetch. - **Enrichment condition** — centralized in `server/services/enrichmentQueue.js` with `MARKETPLACE_STATUS` constants for explicit state. ### Removed - **Unused components** — `CompletionRing`, `StatSparkline`, `CountryChart`, `useAnimatedNumber` hook, and the unused `/api/value` route. [0.2.0]: https://github.com/SimonBlancoE/discographic/compare/v0.1.0...v0.2.0 ## [0.1.0] - 2026-04-10 First tagged release. Discographic is a self-hosted Discogs collection manager for vinyl collectors, featuring sync, enrichment, export/import, and a dashboard with charts and achievements. ### Added - **Dynamic currency conversion** — prices stored in EUR, converted in real-time via ECB exchange rates with 6-hour caching, yesterday-date fallback, and concurrent-fetch deduplication. Currency selector in collection header (EUR/USD/GBP) with persistent user preference. - **Togglable columns** — column registry as single source of truth, ColumnToggle popover (rendered via portal), per-user column visibility preferences saved to the database. - **Marketplace listings** — inventory sync fetches user's own Discogs listings, picks best per release (prefers "For Sale" over "Draft", lowest price), stores original price + EUR conversion. Two new columns: listing status and listing price. - **Localized exports** — CSV/XLSX column headers use i18n keys in both Spanish and English. Cross-locale import tolerance so files exported in one locale can be imported in the other. - **Ephemeral test instance** — `docker-compose.test.yml` with tmpfs storage, `scripts/test-instance.sh` for automated bootstrap and user seeding, npm scripts `test:instance:start` / `test:instance:stop`. - **Password management** — admin can reset user passwords, users can change their own password. - **Achievement system** — collection milestones and secret unlocks with confetti animations. - **Test suite** — 77 tests across 9 files covering currency conversion, inventory sync, DB migrations, export serialization, i18n columns, preferences storage, and enrichment progress. ### Fixed - **Infinite enrichment loop** — removed `country` from enrichment pending condition; releases where Discogs has no country data no longer re-trigger enrichment indefinitely. - **Silent inventory sync failures** — errors now reported via sync state instead of only logged to console. - **Collection column menu overlay** — ColumnToggle popover rendered via React portal, eliminating fragile z-index layering. - **Dockerfile missing shared/ directory** — added COPY for shared/ in the runtime stage. ### Changed - **Preferences API** — restricted to a whitelist of known keys (`collection_visible_columns`, `currency`) instead of permissive regex. - **Column preference save** — debounced with 500ms delay to coalesce rapid toggles into a single API call. - **Sort reset notification** — toast message when sort resets to artist after hiding the currently sorted column. - **Vite dev proxy** — target port configurable via `VITE_API_PORT` env variable, defaults to 3800. - **Currency defaults** — replaced hardcoded `'EUR'` strings in AuthContext and Collection with shared `DEFAULT_CURRENCY` constant. [0.1.0]: https://github.com/SimonBlancoE/discographic/releases/tag/v0.1.0