Tags give the ability to mark specific points in history as being important
-
v2.5.0
protectedab376df0 · ·v2.5.0 Post templates move from the browser to the account, and the dialog they are edited from is usable on a phone (MR !181). Requires nexus-go v2.2.0 or later, which is deployed on both nodes. - Templates lived in localStorage under blurtPostTemplates-<user>, so they were per-browser and per-device, lost with site data, and absent from a private window. They are now rows in nexus-go, reached through five signed RPCs. Every operation is signed on its own and deliberately does not use the draft session grant: that grant is a bearer credential meant to spare a signature on each draft autosave, and template operations are rare enough to pay for themselves. - Writes fan out to every node and reads merge what every node returns, with last-write-wins and tombstones for deletes, exactly as drafts do. A list from zero reachable nodes is UNKNOWN rather than "you have none", so an outage never looks like data loss. - A modal asks once, before the editor stops reading the browser's copy, and clears that copy only after every template is confirmed stored. It was the only copy. - A /templates page, sibling of /drafts and beside it in the account menu, lists what the account holds, opens one into the editor, and deletes with a confirmation that says the delete cannot be undone -- because it cannot. Deleting used to sit in Advanced Settings as a second button identical to the one next to it and one click from Load. - The beneficiary row is no longer a twelve-column grid on a phone. Splitting those columns between a three-character percentage and an account name never worked at any share: the percentage clipped or the name was cramped. The percentage now takes exactly the width three digits need and the name takes the rest. Everything in the row centres against it, the @ box is transparent rather than Foundation's near-white, and Advanced Settings has a Cancel button at all -- its only way out was the corner X. - Adding a beneficiary over an unfinished row used to produce a second blank row and a duplicate-beneficiary error, because two blank rows cannot be told apart. Add is hidden while any row lacks a name or a percentage. - The template picker and the community role picker no longer hand the choice to the operating system's own picker, which cannot be styled and covers a dialog with a sheet that looks nothing like the site. - Below 640px a site-wide rule gives every table display:block so it can scroll, and a block box shrinks to its content -- so a narrow table stopped filling its card and read as one that had failed to load. The templates list and the community roles table use a wrapper that keeps the table a table. - Two i18n sections, post_template_selector_jsx and beneficiary_selector_jsx, existed only in English and rendered that way whatever the reader's language. Both are translated into the other eight locales. Add account and Remove now say Add beneficiary and Remove beneficiary; Sign in and Sign up, a letter apart and neither saying what it does, say Login and Register. Also in this release, with no effect on what users see: the repository gained a jest configuration and a green suite where twelve of its suites had been failing, a CI job that runs it on every merge request with the results and coverage shown there, and an npm install that survives a socket timeout instead of failing the pipeline before anything is tested (MRs !177, !178, !179, !180).
-
v2.4.1
protectedc501799f · ·v2.4.1 The editor's beneficiary shares, built and announced from one place (MR !176). - The editor announced beneficiary shares with arithmetic that disagreed with what it went on to broadcast: the dialog counted the form rows while the operation was assembled separately, so the two could drift. Across the configurations the validator accepts, the announced total was wrong in about one in five, and some announcements added up to more than 100%, which the chain cannot represent. The summary and the operation now come from a single buildBeneficiaries(), so what the author is shown is the list that is sent. - Automatic shares stay fixed. The community's and the referrer's 3% are never reduced, trimmed, or edited away. What the author adds is added on top, and when the total will not fit it is the author's own shares that yield, largest first. An account earning several shares becomes one entry with their sum, which is what the chain requires: it rejects a beneficiary listed twice. The convention is client-side and so unenforceable in the browser; the editor at least no longer offers the reduction itself. - The summary names each share's origin -- community, referrer, or set by the author -- on its own line, in place of the aggregate counter. The count corrected by !169 can no longer go wrong because nothing is counted any more: every share is listed with the amount it actually contributes. - validateBeneficiaries() now measures the author's shares against what is left, taking both the automatic percentages and the slots they occupy out of the budget, so validation and construction agree rather than each guessing. It also tolerates lists that reached it without passing through the form, which a hand-edited page can produce. - Applying a loaded template writes to the editor's store, not only to the dialog, so a template's beneficiaries survive being loaded.
-
v2.4.0
protected6a7b4b3f · ·v2.4.0 Security and availability fixes for the AI proxy and server-side rendering, plus the beneficiary lines in the editor (MRs !168, !170, !171, !172, !173, !174, !175). - Security: the AI proxy took the upstream endpoint from the request body and passed it to fetch unchecked, so anything the server could reach a caller could reach through it, with the response returned verbatim. Endpoints now go through a guard that allows https only, refuses addresses that are not publicly routable, and rejects redirects, checking the address inside the connection's DNS lookup so it covers the one actually connected to. The routes also require the same CSRF token the rest of the API does, which stops the proxy being usable as an open relay towards any public host. node-fetch becomes a direct dependency at 2.7.0: it was present only transitively at 1.7.3, which leaks the Authorization header on a cross-host redirect. - The AI proxy had never worked in a container. fetch was used but never imported, and the image runs Node 16, which has no global fetch, so every call answered 500. Fixing that alone would have armed the hole above, so both land together. - Rate limiting: rateLimitReq ignored its own limit argument, keyed on a header the client writes, and never expired its entries. It now takes a per-minute budget counted per route over a sliding window, identifies the visitor by CF-Connecting-IP where the deployment declares it is behind Cloudflare, and evicts the oldest entries at its ceiling rather than turning new callers away. - Availability: a failing remote document no longer kills a worker. The pinned posts, dapps and nsfw lists are fetched from raw URLs, and a redirect, an HTML error page or a rate-limited RPC each produced an uncaught exception or a promise that never settled. Fetching is now one helper that always settles, entries that cannot be read are skipped rather than failing the batch, each loader keeps its last good value, and an unhandled rejection is logged instead of ending the worker. - The AI model picker asks the provider which models the key may use instead of offering a list compiled into the client, which had gone stale to the point where every option failed. The model can always be typed. Upstream failures answer 400 with the provider's message rather than a status a CDN replaces with its own error page. - The AI chat now streams: the event stream was being gzipped, which held the answer back until it was complete. Reasoning models no longer print their chain of thought as the answer, the settings screen and the chat share one configuration store, and code spans are legible in the dark theme. - Logging out clears the assistant. Its conversation and the provider API key live in the browser, so both survived a logout and the next person at that machine could read the chat and spend the key. Expanding the chat window no longer hides its own toolbar behind the site header. - Editor: the beneficiary lines print a total when more than one automatic share applies and name the origin of each, instead of showing two identical lines that contradicted the counter. Translated into the remaining locales.
-
v2.3.4
protectedc6cb794f · ·v2.3.4 Two vote-reliability fixes (MRs !165, !166). - Vote: a broadcast error no longer erases the user's own vote unless the node contradicts it. blurtjs retries the same signed transaction, so a vote that was already applied comes back as "identical to this vote", and a timeout or a 5xx reply gives no verdict at all; both used to clear the optimistic vote, emptying the heart for a vote that was on chain and carrying that stale copy between views. The rollback now asks the node who voted before reverting, and never reverts when the node cannot answer. - RPC: failover now fires when a node is unreachable. transport.send() reported its failures only through its own callback, so error_count never reached failover_threshold and the client stayed pinned to a dead node. The retry budget is bounded too (it was the library default of 10, backing off to about 17 minutes), so the threshold is reached in seconds.
-
v2.3.3
protected2c2cd639 · ·v2.3.3 Two fixes to the reply flow. - A reply posted from a list card appeared above the post it answered. The list layout orders the card's children explicitly and the panel had no order of its own, so it sorted ahead of everything; it now sits past the footer at every breakpoint. - Opening a post that was not in the store yet showed the not-found page until the data arrived, most visibly through "view the full context", where the parent is never in the store. The page waits while the request is in flight and reports the post missing only once it has finished without producing it.
-
v2.3.2
protected5c841376 · ·v2.3.2 ESLint cleanup and the genuine errors it surfaced (MR !161). - Config: demote airbnb style rules to warnings (14,895 -> 0 errors); ignore vendored assets; declare jest/browser globals. CI-only, no runtime effect. - Fixes: latent bugs the linter had buried (undefined refs in FetchDataSaga, ChangePassword, Header, tape, SteemMarket, App, ...), all behavior-preserving.
-
v2.3.1
protected462cd54c · ·v2.3.1 Show the post-footer voters arrow whenever a post has votes. - The vote-count + voters arrow was gated on active_votes being pre-loaded in that copy of the post, so it appeared for some accounts/posts and not others. Gate it on total_votes instead; the modal already fetches the real voters on demand when opened (with reference-node fallbacks).
-
v2.3.0
protectedb1172501 · ·v2.3.0 Friendly, localized error handling; mobile and deploy improvements. - In-app error toasts now show calm, human, localized messages instead of raw chain assertions, mapping the common Blurt transaction errors (with a generic fallback) across all nine locales. - Fix long error messages overflowing the viewport on mobile. - Remove the obsolete out-of-bandwidth / Resource Credits modal, which does not apply to Blurt (transactions are gated by fees, not a resource-credit allowance). - Version the per-environment deploy config in the repo so the deploy jobs ship it. Classification: MINOR — user-facing features and fixes, no breaking changes.
-
v2.1.0
protected709bd43c · ·v2.1.0 - Server-side post drafts - Accept .mov / HEVC video uploads (by extension; no client-side rejection) - Drop the obsolete HEVC upload guidance - Logged-out navigation: keep Sign in / Sign up in the side menu, open login as an in-app modal, retire /login.html - Show the header Sign in / Sign up CTA only from 1200px (fix the iPad-landscape overlap with the primary nav) - Hide the Follow button for logged-out visitors - Correct the sign_in mistranslation (es, fr) - Centre the video play badge on iOS in the expanded list view