Files
mdrs-client-python/CHANGELOG.md
T
orrisroot 0cac30ccf8 fix(auth): serialise the token refresh across processes
The login cache is shared by every mdrs process, but the refresh was
guarded by a lock that only reaches inside one. Concurrent runs each
sent the same refresh token, and a provider that rotates them accepts
the first and refuses the rest.

- hold a lock that spans processes across the whole read-refresh-
  write, checking cheaply first so ordinary requests never take it
- write the cache through a temporary file: opening it for writing
  truncates it, and a reader landing in that window found it empty
  and threw the session away
- take the lock for every write, not just the refresh, so a login
  running beside one cannot be silently reverted
- wait for a busy lock on Windows rather than giving up after the ten
  attempts msvcrt allows, and retry the rename it refuses while a
  reader still holds the file open
- bound the refresh request on its own, so a provider that goes quiet
  cannot hold the lock indefinitely
- accept bare hostnames such as localhost, store URLs without the
  trailing slash, and join download paths through one helper
2026-08-14 16:36:50 +09:00

156 lines
4.8 KiB
Markdown

# Changelog
All notable changes to this project will be documented in this file.
## [Unreleased]
### Fixed
- Serialised the token refresh across processes. Concurrent `mdrs` invocations shared one refresh token and each sent it, so a provider that rotates refresh tokens accepted the first and refused the rest.
- Wrote the login cache through a temporary file so a reader can no longer catch it mid-truncation and discard the session.
- Joined the base URL and the API's relative path correctly in `ls --json` output, which produced a doubled separator when the configured URL ended with one.
### Changed
- Accepted bare hostnames such as `localhost` in `config create`/`config update`, and stored the URL without its trailing slash, matching the Rust client so both can share `config.ini`.
- Bounded the token refresh request with its own timeout, so a provider that stops answering cannot hold the cross-process lock indefinitely.
- **Breaking for embedders:** `CacheInterface` now requires `lock()` and `reload()`. A cache passed to `MdrsClient.from_remote(..., cache=...)` must provide both; `InMemoryCache` implements them as no-ops.
## [1.3.18] - 2026-07-02
### Added
- Added a comprehensive unit test suite in `tests/test_commands.py` checking registration, parsing, and execution flow of all 16 commands.
### Refactored
- Abstracted configuration storage (introducing `ConfigInterface`, `InMemoryConfig`, and updating `ConfigFile`) to enable dependency injection.
- Modularized transfer operations (upload and download) to decouple them from the service layer.
- Decoupled commands from direct file system configurations and migrated all subcommands to use abstract config classes.
### Changed
- Upgraded dependencies including `pydantic-settings` to `2.14.2` and `pyright` to `1.1.411`.
### Fixed
- Fixed duplicate `__all__` definitions in package initialization file `mdrsclient/__init__.py` that caused `__version__` export to be overwritten.
## [1.3.17] - 2026-07-02
### Refactored
- Decoupled core logic from CLI interface and introduced `MdrsClient` service layer to improve library portability.
- Migrated all CLI commands to utilize `MdrsClient` for execution.
### Added
- Abstract authentication state using `CacheInterface` and `InMemoryCache`.
## [1.3.16] - 2026-06-12
### Fixed
- Retrieve the full `Folder` object from `FoldersApi` instead of using the `FolderSimple` returned by `find_sub_folder` when resolving DOI subfolders. This fixes a type checker error under the upgraded pyright and avoids a potential AttributeError at runtime due to `FolderSimple` lacking the `path` attribute.
### Changed
- Upgraded dependencies and bumped version to 1.3.16 in pyproject.toml.
## [1.3.15] - 2026-05-01
### Fixed
- Apply NFC normalization to filenames and folder names sent to the server.
## [1.3.14] - 2026-04-17
### Changed
- Simplified `config list` command (removed `-l`/`--long` option, always display URL).
- Renamed `--quick` option to `--quiet` for `ls` subcommand.
### Added
- Added subcommand aliases for config commands (e.g. `ls` alias for list, `rm` alias for delete).
- Added `version` command.
## [1.3.13] - 2025-07-02
### Fixed
- Fixed pagination logic for the `file.list` API.
## [1.3.12] - 2025-05-20
### Fixed
- Fixed bug where file downloading was skipped incorrectly when `-s`/`--skip-if-file-exists` option was present.
## [1.3.11] - 2025-01-21
### Fixed
- Follow-up fixes for User API specification changes.
## [1.3.10] - 2024-12-23
### Added
- Delete broken files and show a summary when a file download fails.
### Changed
- Updated dependency libraries.
## [1.3.9] - 2024-10-23
### Fixed
- Fixed compatibility with Python 3.10.
## [1.3.8] - 2024-09-18
### Added
- Implemented `-s`/`--skip-if-file-exists` option for `download` command.
### Fixed
- Added exception handling for unexpected responses from the server.
## [1.3.7] - 2024-07-22
### Added
- Implemented `--exclude` argument for download subcommand.
## [1.3.6] - 2024-07-08
### Added
- Support cancelling recursive downloads if downloading some files fails.
## [1.3.5] - 2024-07-08
### Added
- Added authorization token validation checks for file download operations.
### Removed
- Removed unnecessary debug code.
## [1.3.4] - 2024-07-04
### Added
- Added some aliases for config sub command.
### Fixed
- Fixed bug when uploading large files.
## [1.3.3] - 2024-02-13
### Added
- Implemented `-s`/`--skip-if-file-exists` option for `upload` command.
## [1.3.2] - 2024-02-09
### Added
- Added `-u` and `-p` options to login command.
## [1.3.1] - 2023-12-20
### Fixed
- Fixed bug to resolve local files for recursive file upload.
## [1.3.0] - 2023-12-18
### Changed
- Removed debug comments.
## [1.2.0] - 2023-10-04
### Changed
- Follow-up recent specification changes about folder access level.
## [1.1.1] - 2023-07-26
### Changed
- Set destination folder name using name attribute of folder copy API.