diff --git a/CHANGELOG.md b/CHANGELOG.md index 02bf397..8e76a8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,41 +5,32 @@ All notable changes to this project are 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). -## [2.1.0] - Unreleased +## [2.1.0] - 2026-09-16 ### Added -- A password generator for share passwords. With "Password protect" on, the upload page offers Generate and Copy under the password field. On the next page the password is offered once more beside the link — masked, with a copy button at the end of the field like the link's. It is passed along encrypted in the session and never stored. -- A "Share Passwords" card in Admin settings controls the generator: - - Mode: off, on request (the Generate button) or prefilled as soon as protection is switched on. - - Kind: random characters (length 12–64; uppercase, lowercase, numbers and symbols; look-alike characters left out if chosen) or a passphrase (4–10 words from EFF's large word list, with a chosen separator). - - An example with its estimated entropy shows before saving. - - Defaults: on request, 20 letters and numbers without look-alikes. -- `AUTO_HTTPS` for the Docker image: with `AUTO_HTTPS: "true"` and `SERVER_NAME` set to the domain, the container fetches a Let's Encrypt certificate, serves HTTPS on port 443 and redirects port 80. Without it the container serves plain HTTP on port 80, as before, for a reverse proxy in front. -- `UPLOAD_CHUNK_SIZE_MB` (default 16) sets the size of each encrypted chunk the browser sends. +- A password generator for share passwords, with a copy button. The password is shown once more beside the new link. Admins can turn it off, or switch between random characters and a passphrase, in Admin settings. +- `AUTO_HTTPS` for the Docker image: set it to `"true"` with `SERVER_NAME` to get a Let's Encrypt certificate and serve HTTPS. Without it the container serves plain HTTP on port 80, as before. +- `UPLOAD_CHUNK_SIZE_MB` sets the size of each upload chunk (default 16). ### Changed -- **Breaking: uploads need HTTPS.** Files are now encrypted in the uploader's browser with WebCrypto, which browsers only offer over HTTPS or on `localhost`. Over plain HTTP the upload page says so and takes no files; downloads keep working. Serve SealShare with `AUTO_HTTPS` or behind a reverse proxy that terminates TLS. -- Uploads are encrypted in the browser and sent in chunks of 16 MB, each written to disk once, already encrypted. A large file no longer waits on "Processing files..." or on "Create Share Link": before, the server wrote every upload three times (PHP's temporary file, Livewire's temporary copy, the encrypted file). The server checks every chunk as it arrives. A chunk that fails is retried automatically, then the file offers Retry; each file in the list shows its progress. -- A share's files are encrypted with a random key of its own; with a share password, that key is wrapped with a key derived from the password with Argon2id instead of PBKDF2. Shares created before keep working as they are. -- PHP's upload limits no longer cap a share's file size: "Max file size" in Admin settings can be set beyond them, and `PHP_UPLOAD_MAX_FILESIZE` / `PHP_POST_MAX_SIZE` default to `64M` (they only apply to the logo upload). `LIVEWIRE_MAX_UPLOAD_TIME` is no longer needed. -- Files still uploading count towards the storage quota. An upload no chunk reached for 4 hours is deleted by the hourly cleanup. -- The interface moves to [Livewire Material](https://gitea.nonameweb.ch/noNameWEB/livewire-material) 2.0.0, which aligns every component with Material 3 Expressive as Google documents it. SealShare keeps the pages, the arrangement and the flow it had — rebuilt on the new components — and no longer ships Tailwind CSS. -- The colour scheme is regenerated with Material 3's 2025 colour rules, at all three contrast levels. The colour profile an admin chose, and each visitor's light or dark setting, carry over unchanged. -- The settings pages — Profile, Update password, Two Factor Authentication and Appearance — are shown as cards, the way Admin settings already were. Deleting the account and the two-factor recovery codes each sit in a card of their own beside the page's. -- A form field now fills the card that holds it instead of stopping short of its edge. -- Every page shares one layout, the one the share pages already had: a centred heading over one column of cards, the same width on every page. To fit it, the admin dashboard lists its shares instead of a table: each share's token opens it, its files, size, downloads and expiry sit underneath, and a "Sort by" select replaces the column headers. The sign-in, password reset, two-factor, setup and system password pages lose their separate tinted card: they are headed by the site's logo, title and description, like the upload and download pages, with the form in a card below. +- **Breaking: uploads need HTTPS.** Files are now encrypted in the browser and uploaded in chunks, which browsers only allow over HTTPS or on `localhost`. Over plain HTTP downloads still work, but uploads don't. Use `AUTO_HTTPS` or a reverse proxy that terminates TLS. +- Large uploads are much faster: each chunk is written to disk once, already encrypted, and a failed chunk is retried. +- Each share has its own random key; with a share password it is protected with Argon2id instead of PBKDF2. Existing shares keep working. +- PHP's upload limits no longer cap the share file size. `PHP_UPLOAD_MAX_FILESIZE` and `PHP_POST_MAX_SIZE` default to `64M`, and `LIVEWIRE_MAX_UPLOAD_TIME` is no longer needed. +- Unfinished uploads count towards the storage quota and are deleted after 4 hours. +- The interface moves to [Livewire Material](https://gitea.nonameweb.ch/noNameWEB/livewire-material) 2.1.0 and no longer ships Tailwind CSS. Every page uses the same single-column layout of cards, and the admin dashboard lists shares instead of a table. Colour profiles and light/dark choices carry over. ### Fixed -- "Download all" works for large shares: the ZIP is streamed as it is built, file by file, instead of every file being decrypted into memory and the archive written unencrypted to a temporary file. -- Unencrypted copies of uploads no longer stay behind in Livewire's temporary folder after a share is created; the hourly cleanup also removes those left by earlier versions. -- The Docker image's `docker/Caddyfile` was never used and is removed; `SERVER_NAME` now only matters with `AUTO_HTTPS`. +- "Download all" works for large shares: the ZIP is streamed instead of being built in memory and written unencrypted to a temporary file. +- Unencrypted copies of uploads no longer stay behind in Livewire's temporary folder; the hourly cleanup removes old ones. +- Removed the unused `docker/Caddyfile`. ### Security -- An encrypted file whose trailing chunks were cut off, or whose chunks were reordered, now fails to decrypt: each chunk's nonce carries its index and whether it is the last one. +- An encrypted file with missing or reordered chunks now fails to decrypt. ## [2.0.1] - 2026-09-13 @@ -147,6 +138,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Dark themed UI built with Livewire, Alpine.js, Tailwind CSS and DaisyUI. - Docker images published to `ghcr.io/surtic86/sealshare`, served by FrankenPHP via Laravel Octane. -[2.1.0]: https://gitea.nonameweb.ch/noNameWEB/SealShare/compare/v2.0.1...main +[2.1.0]: https://gitea.nonameweb.ch/noNameWEB/SealShare/compare/v2.0.1...v2.1.0 [2.0.1]: https://gitea.nonameweb.ch/noNameWEB/SealShare/compare/v2.0.0...v2.0.1 [2.0.0]: https://gitea.nonameweb.ch/noNameWEB/SealShare/releases/tag/v2.0.0