diff --git a/VERSION b/VERSION index 17fd0aed..e0d6b5ea 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.79.0 \ No newline at end of file +0.80.0 \ No newline at end of file diff --git a/frontend/src/lib/releaseNotes.ts b/frontend/src/lib/releaseNotes.ts index c68213a5..4be9bf6f 100644 --- a/frontend/src/lib/releaseNotes.ts +++ b/frontend/src/lib/releaseNotes.ts @@ -14,6 +14,34 @@ export interface ReleaseEntry { } export const RELEASE_NOTES: ReleaseEntry[] = [ + { + version: "0.80.0", + date: "2026-09-05", + summary: + "Getting into Siftlode used to take nine steps, three of which could quietly end in nothing — and one of which deleted the password you had just chosen. It is now one mail and one click in the usual case, every screen says which of the two gates you are actually waiting on, and the messages arrive in your own language.", + features: [ + "Siftlode's emails are now written in Hungarian or English, whichever you use. Every message — confirming your address, an approval, a password reset, a role change, an account closure — follows the language you signed up in or later chose in the app. Nothing else on the site changes: a mail arrives once, in whatever language it was written in, which is the one place you cannot simply switch and re-read.", + "Being approved usually takes one message now. If you have already signed up and your address is still unconfirmed, the approval mail carries the confirmation link itself and says so — you no longer have to find and open a second message that arrived hours earlier. When you have not signed up yet, it says a confirmation mail will follow, so its absence is something you would notice.", + "The two gates — confirming your email and being let in by an admin — no longer have to happen in a set order, and the screen names the one you are actually waiting on, with the exact address it has on file. If your address needs confirming, it offers to send a fresh link on the spot.", + 'Signed in with Google under a different address than the one you registered with? Settings and the account menu now show both, so the pill saying "Connected" also says who you are connected as. It only appears when the two differ.', + "Admins can see the people who signed up but still cannot get in, and which of the two gates each one is stuck behind. One click lets in someone whose address was approved before they registered, and a resend button gets a fresh confirmation link to anyone whose first one went astray — and says plainly if the instance has no working mail setup rather than reporting a send that never happened.", + "Whitelisting an address stays silent, as it always has, but telling that person is now its own button — with a dialog that picks the language to write them in, and warns you if you have already written to them.", + ], + fixes: [ + "The link in your confirmation email now works wherever you open it. In a browser already signed in to Siftlode it did nothing at all — the page loaded, the link was gone from the address bar, and nothing said whether it had worked; only a private window ever confirmed an address. Pasting the link into a tab that already had Siftlode open failed the same way.", + "Gmail addresses that differ only by dots or a +tag are one mailbox again, and Siftlode treats them as one person. Approving hartmann.peter1986@ no longer leaves the account registered as hartmannpeter1986@ locked out, and signing in with Google no longer quietly files a second access request for someone who was approved weeks ago.", + "The address you registered with is yours to keep. Signing in with Google used to overwrite it with the Google account's primary address, which cannot contain a +tag — so a me+siftlode@gmail.com sign-up lost its tag and could no longer sign in with the address it had chosen. Password resets and confirmation resends now reach you under any spelling of your mailbox, and the mail goes to the address on your account.", + 'An admin approving your account no longer deletes the password you chose at sign-up. Because approval usually happens before you read your mail, "your password was cleared for security" had become the normal experience rather than the rare one.', + 'Signing up again with an address that was already registered but never confirmed sends the confirmation link again. It used to answer with the same cheerful "check your inbox" and send nothing at all, which is the likeliest explanation for confirmation mails that "never arrived".', + 'Opening a password-reset link that has expired or was already used no longer draws the full "set a new password" form for you to fill in before telling you. It says the link is spent and offers a new one. The check is done without spending the link, so simply opening it costs you nothing.', + "A refused sign-in explains itself in your language instead of showing a raw English message, and the emails now say how long their links last and that they work only once.", + "The three messages you can be left waiting on now name the spam folder, because the first mail to a brand-new address is the one most likely to land there.", + ], + chores: [ + "E9.5, seven sprints. S1 removed the SEC-10 revoke from the admin-approval path (it stays on Google adoption, where ownership is attested). S2 moved verify-token consumption above App's signed-in/signed-out branch and snapshots the entry URL at import time, so no later URL writer can steal it; a hashchange listener covers fragment-only navigation, which UAT found on a plain-text mailed link. S3 added utils.canonical_email + a CanonicalEmailMixin deriving users/invites.email_canonical on every write (migration 0079), swept all eight matching sites, and kept the typed address for delivery; users.google_email (0080) surfaces the second address only when it differs. S4 gave every password_login refusal the {code, reason} shape and added a non-consuming password-reset/check. S5 added can_activate/count_pending_activations in core plus the admin surface and a badge that counts what actually waits on an admin. S6 branched the approval mail on what is left to do (7-day token) and recorded invites.invited_at (0081). S7 moved twelve mails into app/mailtext.py with a parity test over keys AND placeholders, resolved the language in the request handler rather than the background task, and captured invites.lang (0082) so a decision mail answers in the language the request was made in.", + "The closing review ran four rounds across seven dimensions and converged 12 → 4 → 3 → 2, every finding adversarially verified. It caught that clearEntryUrl had been blanking the whole query string on every load — which would have shipped a broken first-run setup — that the env allow-list still matched literally while invites had gone canonical, that invited_at recorded the intent rather than the send, and that three rewritten mailers never rendered in any test. It also refuted S1's own argument that the approval-time revoke was redundant, and then, in round 2, refuted the round-1 fix for that: \"the newest registration owns an unverified account\" is symmetric, so an attacker can simply register last, and it handed anonymous callers a write onto a real account's password — including the rows SEC-10 had deliberately left password-less. Reverted, with the attempt written into the roadmap so it is not tried again; the residual is SEC-16 and the owner's recourse remains password-reset.", + ], + }, { version: "0.79.0", date: "2026-09-03",