Repository navigation
Release v2.90.0 - #2334
Merged
Merged
Release v2.90.0#2334
Conversation
_ExpiresWhenStale told a new result from the one before it by how much time it had left. Two fresh results each have the whole four seconds left when they are drawn on the clock tick they finished in, so after the first had expired the second found the slot already expired and stayed hidden. It now resets on the announcement's identity as well. In the app every result follows a running state, which resets the slot, so this needed a sync to start and finish within one frame. It is what made "a second result that reads the same is shown again" flaky: on Windows' coarse clock both results sometimes landed on one tick. The summary's remaining time now reads clock.now() rather than DateTime.now(): the same time in the app, and in a widget test the clock its timers run on, so the test fails every time without the fix rather than now and then. clock moves from a transitive to a direct dependency (same version). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y4dehHVpH2fFgzitCz1yJ6
Staging showed "Create snapshot" and "Publish Drive State" side by side, both promising a faster drive, and the Snapshots tab listed only one of them. Users now see one term. - every "Create snapshot" goes through promptToCreateSnapshot, which makes a drive state artifact wherever publishing one is offered for the drive (createsDriveStateSnapshot, the same gate the nudge used) and the older snapshot everywhere else, as before - the separate "Publish Drive State" items in the New menu and the drive menu are gone - the creation modal, its refusals and failures say snapshot rather than artifact, drive state or publish; two em dashes in them are gone too - the Snapshots tab lists the drive's artifacts beside its older snapshots, newest first, wherever the build reads or publishes them; a pending artifact shows as pending - a published artifact is announced to the tab as pending straight away, even if its modal was closed during the upload Production is unchanged: publishing and reading are off there, so every "Create snapshot" still makes the older snapshot and the tab lists only those. Spec and code keep the term drive state. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y4dehHVpH2fFgzitCz1yJ6
GraphQL queries go out with their fragments written out (8 s to 0.2 s per old-range query)
Drive state none-found log names the block it searched from
A second sync result is shown even when it reads like the first
…nings
- costs show 4 decimal places, like the balances beside them ("0.0079 AR",
not "0.007935750989 AR"); a cost too small for that reads "< 0.0001"
- the payment line reads "Wallet balance, 1.0619 AR available" or
"Turbo Credits, 2.0370 available" instead of "Payment Method: Wallet
Balance: 1.0619 AR"; cost and payment lines are localized
- the upload flow's buttons and titles use title case, as most of the app's
dialogs do (Upload, Cancel, Skip, Replace, OK, Warning)
- the problem dialog's title, text and buttons are localized; "Do Not Fix"
is now "Close"; closing with wallet-paid files unfinished asks first,
since they may be paid for; the file list fits its files instead of
leaving a large empty space
- the inline warning box fills its width in every dialog
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZiqyGae4T1gJLGGB29pR9
Drive state spec and comments match the published format
Drive state artifacts are snapshots to the user
Two pushes to dev in quick succession each ran their own deploy, and whichever run finished last owned gh-pages. On 2026-10-16 the #2270 merge (04be6f2) finished its tests two minutes after the #2271 merge (08bc4e3) and overwrote it, so staging ran dev without #2271. - staging.yaml: one concurrency group for the workflow with cancel-in-progress, so a newer push cancels the older run still in progress and the newest commit is the one deployed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y4dehHVpH2fFgzitCz1yJ6
The upload sheet picked the payment method from a dropdown that showed
only the selected method's cost. It now shows both ways to pay as option
cards, in the style the Turbo top-up uses to choose how to pay.
- each card has a radio dot, the method, its balance, and on the right
what this upload costs with it
- a balance that can't pay says so on its card ("Not enough AR, 1.0619
available"), in the error colour on the selected card; the separate
"Insufficient AR balance" line is no longer repeated under the cards
- the keep-this-tab-open warning is hidden while the wallet can't pay,
since there is no upload to keep the tab open for
- the new strings are localized; the dropdown and its two strings are
removed, and useDropdown is renamed useOptionCards
- tests for the cards, and the credits-notice tests now run against them
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZiqyGae4T1gJLGGB29pR9
When neither Turbo Credits nor the wallet's AR could pay for an upload, the sheet said "add Turbo credits to your profile or use AR". It now says "You don't have enough Credits or AR for this upload. Add Credits to upload.", with the second sentence opening the top-up as before. Both strings are localized. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019ZiqyGae4T1gJLGGB29pR9
The concurrency group orders runs by when they were queued, not by commit, so re-running an older dev run would still publish its build over a newer one. - deploy-web checks dev's head through the API before publishing and skips the download and deploy steps, with a notice, when this run's commit is no longer the head. Manual runs on other refs are left as they were. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y4dehHVpH2fFgzitCz1yJ6
ui: choose how to pay for an upload from two option cards
With a workflow-level group that cancelled in progress, re-running an older run cancelled the run for dev's head, and the older run then skipped publishing as stale, so nothing published dev's head. - the staging-deploy group moves from the workflow to deploy-web, with cancel-in-progress off. Tests and builds run in parallel as before; only publishing is one at a time, and the dev-head check decides which run publishes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y4dehHVpH2fFgzitCz1yJ6
The dispatcher keeps each direct-to-network upload's signed data items until it succeeds, so a retry resends the same transaction. A cancelled upload is never retried (the cancelled screen offers only OK), so its entry is now removed when the cancel makes send fail. Other failures still keep theirs for Re-Upload. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019ZiqyGae4T1gJLGGB29pR9
- ArweaveFS.md: a Drive State section beside Snapshot, with its tags and envelope, pointing to the published spec in ar-io-docs and to the schema a reader compares - DRIVE_STATE_ARTIFACT.md §3.3 described the JSON payload D12 replaced: "serialise rows", seven sections with a rows array, and a JSON coverage example with version 1.0. It now describes the SQLite file, its nine tables and the meta row - §6 records an open question: the read gate requires the exact frozen schema, so a 1.x minor that adds a table needs the gate to accept unknown tables - DELIVERY_PLAN.md: status as of 2026-10-17. #2197 merged, the OPFS worker built, the first upload done by a human, staging rollout steps, and spec items 2.2 to 2.7 in review as ar-io/docs #192 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y4dehHVpH2fFgzitCz1yJ6
fix: a staging deploy can't be overwritten by an older one
ui: tidy the upload dialogs' amounts, buttons, problem dialog and warnings
docs: drive state docs match the shipped format and the published spec
Conflict in sync_repository.dart: dev removed syncDriveById (no callers, and it would have reset a drive's watermark to zero), which this branch's second commit had given the name repair. The removal is kept; the repair still runs at the two entry points that remain, syncAllDrives and syncSingleDrive. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y4dehHVpH2fFgzitCz1yJ6
… block the drive list kept the first drive entity transaction the gateway listed for each drive, on each page. HEIGHT_DESC does not order transactions inside one block, so a rename and a hide in the same block could come back in either order, and the rename's isHidden: false brought the drive back. - keep one transaction per drive across every page - the newer one wins: higher block, pending above mined, then the later Unix-Time, the order sync already uses within a block - a missing or malformed Unix-Time loses a tie instead of throwing - correct two comments that described the per-page duplicates fixes #2245 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ksUKnnC1PGwNoUh6JNwZt
A guide and tools for testing a production web build the way a user does: headless Chromium, logged in with the team's test wallet, clicking through dialogs, uploading, and checking screenshots and a network log. - docs/WEB_E2E_TESTING.md: rules, one-time setup, the run steps, test recipes (free and blocked Turbo uploads, wallet-paid uploads through a fake gateway, injected failures, ar-io.dev dry-run) and known quirks - tool/web_e2e/launch.js: keeps the browser running behind a spend guard. Wallet-paid uploads go to a local fake gateway (or to ar-io.dev only while it answers as dry-run); Turbo uploads over the free 105 KiB, and all top-ups, are refused. File choosers are answered from a queue, and the keyfile is handed over only to the login - login.js logs in from a new profile or unlocks an existing one; the keyfile goes in by path and the password is typed from a local file, neither printed - step.js runs one step and screenshots it - chaos_gateway.py checks every chunk's proof as a node does; chaos_report.py says whether every header got all its bytes - CLAUDE.md points agents at the guide The keyfile and password are read from ~/.config/ardrive-e2e/env and are never in the repo. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019ZiqyGae4T1gJLGGB29pR9
…rive list getCommitTime throws a RangeError, not a FormatException, for a value DateTime cannot hold, and that escaped getUniqueUserDriveEntityTxs and failed discovery for every drive in the wallet. - catch RangeError as well as FormatException - test a missing, non-numeric and out-of-range Unix-Time, in both orders - reword three comments that still said the list holds several revisions per drive Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ksUKnnC1PGwNoUh6JNwZt
the drive page skipped a tick whose folder contents matched what was drawn, and ignored the drive row that came with it. rename drive writes only the drive row, so the breadcrumb kept the old name. rename drive also leaves the root folder's own name as it was, in this app and in core-js, so a zip of the drive or of its root folder named its top folder after the drive's old name while the zip file itself carried the new one. - compare the drive row as well as the contents before skipping a tick - name a root folder after its drive when it goes into a zip - give the shared test folder a parent, since a folder without one is now treated as a root fixes #2246 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ksUKnnC1PGwNoUh6JNwZt
on web an out-of-range DateTime throws a plain ArgumentError, not the RangeError the vm throws, so the previous commit's guard still let it escape and fail the drive list in the build users run. - catch ArgumentError, which RangeError extends, so both platforms are covered - run the same cases in chrome through a browser-only wrapper, since ci runs only @teston('browser') files in a browser - reword the last comment that still described duplicate drive ids Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ksUKnnC1PGwNoUh6JNwZt
- the no-op check's comment claimed it skips only when nothing visible changed; a watermark write or a re-encrypted private key now redraws once, and the comment says so - pin that cost with a test: a watermark write redraws once, and the same write again redraws nothing - the root folder branch in the zip conversion is a guard, since the explorer does not normally pass a root folder as a folder item; say so in the comment and the test name Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ksUKnnC1PGwNoUh6JNwZt
"Your successfuly created a snapshot of {driveName}!" becomes "You created
a snapshot of {driveName}.", and the string's description loses its
"sucessfuly". english only; the other locales read correctly.
fixes #2247
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ksUKnnC1PGwNoUh6JNwZt
…ls closed - the guarded Turbo hosts are read from assets/config: those of every flavor except development. PR previews (development config) use testnet Turbo services, which are free and wiped after a few days, so they are let through; launch.js prints both lists at start - a guard that throws now refuses the request instead of letting it pass - the guide says which build to test (PR preview, staging, local), what testnet means for payment testing (free up to 5 MiB, so the payment choice needs a bigger file; the test wallet has no testnet credits), and adds the duplicate-name dialog to the known quirks Tested on #2274's preview: login from an empty profile, sync, a 300 KB testnet Turbo upload going through, and the payment cards for a 6 MB file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019ZiqyGae4T1gJLGGB29pR9
- "What to test" in the guide:
- a change is tested from a plan written from its diff (normal path,
each state the code distinguishes, light and dark mode, plus the
checklist journeys in the same area)
- a 13-journey release checklist runs on staging before a production
release
- each bug that reaches users adds a journey to the checklist
- .claude/skills/web-e2e: `/web-e2e <PR>` tests a PR's preview and
`/web-e2e release` runs the checklist; it checks you can run, picks
the build, writes the plan, runs it, and reports in a fixed format
with the spending check
- .gitignore keeps .claude/ ignored except .claude/skills/, so project
skills are shared
- CLAUDE.md points at the skill
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZiqyGae4T1gJLGGB29pR9
Found by a browser test of the payment cards on the PR preview. - with the wallet card selected (the default with no credits) and neither balance enough, the "Add Credits to upload." link never showed: the AR-short branch returned first. It now gives way to the both-short message under the cards - with Turbo selected and the credits short, the cards still showed the hard-coded "Insufficient Credit balance for purchase. Add Credits to use Turbo.", repeating the Turbo card. They now show only the localized "Add Credits to upload." link. The radio list is unchanged Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019ZiqyGae4T1gJLGGB29pR9
…e review fixes An extension wallet whose earlier credits reading was none or zero, with AR paid directly, lost the "Refresh credits used" button and the "as of" note. The AR-only tile now carries both. Also: a clock that moved backward is stale, not current; the AR count is re-checked after a minute, not half an hour, for ten minutes after this app spends; an open no longer joins a read that began before the last spend; and both writers to local storage check for a logout after the store opens. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ksUKnnC1PGwNoUh6JNwZt
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ksUKnnC1PGwNoUh6JNwZt
39 of the 395 Dart files changed since 2.89.0 were not dart format clean (CI doesn't check formatting). This formats exactly those 39 and nothing else: whitespace, wrapping and trailing newlines only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019ZiqyGae4T1gJLGGB29pR9
…ches up - the save-dialog stand-in sends the bytes as requests launch.js routes, not through an exposed binding: every client attached over CDP hears a binding call, and step.js answered it with "not exposed", so the app showed "File download failed" though every byte was saved - the guide: the sync split button on a new profile, how to turn on the semantics tree for labels(), journey 7 at rate 1.0 then 0.3, the duplicate-file dialog's buttons, and copying assets/config for a WSL copy Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019ZiqyGae4T1gJLGGB29pR9
Keep the refresh for extension wallets, and the other permanence cache review fixes
style: dart format the files this release touched
fix: e2e downloads finish while a step is attached
A visitor with a drive link or a Drive ID opens that drive from the landing card. No wallet, no account, no second step. Public drives need nothing else; a private drive opens with the drive key it was shared with. Signing in later keeps the drive. - landing card: one link, "Open it without signing in", opening a dialog that takes a Drive ID or any ArDrive link (including file links) through the route parser, looks the drive up, asks for a key when it is private, writes the drive row with no profile key and hands off to the router - router: openDriveAsVisitor starts the drive's sync as the explorer builds (from the cubit factory and the route-link follower), signInKeepingDrive keeps the drive across login, and a private drive whose key is not in memory is prompted for once; cancelling lands on sign in - carry-over: ProfileCubit awaits DriveDao.persistInMemoryDriveKeys before announcing the login, so a private drive opened as a visitor survives - visitor strip above the explorer with Sign in; the top bar's Log in keeps the drive instead of logging out; the New button offers Open another drive - visitor leaks closed: Create snapshot (desktop menu, Snapshots tab), License add/update, Your drives in the sync menu, the create-drive cards, private thumbnails, mobile share-to-app, new-window preview on private drives - two pre-existing causes of a "Drive not synced" flash on a freshly opened drive: DriveDetailCubit's folder-not-found path emitted the unsynced state without the running-sync gate, and SyncCubit.syncMetadataOnly emitted idle over a running single-drive sync for a visitor - ActivityCubit.performUninterruptableActivity is typed Future<void> and releases the flag in a finally Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A minor: 79 PRs since 2.89.0, all compatible. The web database moves to SQLite on OPFS in a worker (each user's data is migrated once, on first load, and the old store is kept), previews show progress and wait to be asked for large files, search answers as you type, the upload dialog is shorter, wallet-paid uploads retry and never pay twice, shared links open where they point, and manifests are called deployments. Drive state artifacts ship switched off in production. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019ZiqyGae4T1gJLGGB29pR9
Keeps 2.90.0 in pubspec.yaml over master's 2.89.0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019ZiqyGae4T1gJLGGB29pR9
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
- prod.json: enableSyncFromDriveState and enableDriveStatePublishing on, as staging has run them since 2026-10-16 - configVersion 3 -> 4, so users who already ran the app take the new config; without the bump their stored config keeps both off - the flag rail test now expects staging and prod on, dev off Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y4dehHVpH2fFgzitCz1yJ6
feat: turn drive state reading and publishing on in production
- the sync menu's build keeps its @OverRide; the helper above it is not one - the drives cubit import is covered by blocs.dart now - const preferences in the visitor metadata sync test Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…thing behind From an adversarial review of this branch. Keys and sessions: - a link's drive key is tied to the drive the link named: selecting another drive drops it, and before it goes into memory it is checked against the drive, so a reload on drive A's link then a click on drive C no longer stores A's key on C's row at sign-in - a key typed into the open-drive dialog is never written to the address bar (and so never into browser history); a reload asks for it once - a start with no profile clears what an earlier visitor's session wrote: drive rows and their decrypted folder and file names no longer pass to the next visitor, or to whoever signs in next on that browser - licensing in the details panel needs a signed-in owner; search builds its items as owned whatever the drive Flow: - a drive opened while another sync runs waits for it and syncs after, instead of staying unsynced - the key prompt asks again after a new route, and a prompt that could not open does not use up its one try - the dialog turns Open off the moment the drive id or key changes, keeps "doesn't look like a link" once said, and words a transaction link as a transaction, not a file UX: - one way to sign in: the visitor strip is gone, and the top bar's button is a red "Log in" (was an outlined "Login" beside a "Sign in" strip) - a visitor's New menu says "Attach drive", as a signed-in user's does - copy: "drive ID" mid-sentence, "without logging in"; unused strings and a duplicate key hint removed - the landing link takes keyboard focus; its click is the only one counted as a landing-page click Housekeeping: the analyzer issues that failed CI, sorted imports, comments that narrated history, an unwrapped future, "Drive not synced" wording. Tests: sign-in stores a visitor's key before ProfileLoggedIn, a start with no profile clears visitor rows, a link key is dropped for another drive, a typed key stays out of the url, and the dialog's three timing fixes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019ZiqyGae4T1gJLGGB29pR9
The details panel built the revision menu without its drive, so the "public drives only" gate for Preview read an unknown drive as public and a private revision still opened the transaction's encrypted bytes. The menu now gets the drive, and Preview needs a drive known to be public. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- "Open a drive without logging in" on its own; the question above it said the same thing twice, and the unused string goes with it - the link's semantics say it is a button - clearing the drive key mid-check also ends the check, so the progress bar does not stay on for a key that is gone Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
feat: open a drive from the sign-in screen without signing in
Journey 15 covers the sign-in screen's "Open a drive without logging in": a public drive by ID, a private drive by a keyed share link through the New menu, and logging in from the explorer. It runs before journey 1, on the fresh profile, because that is the state a visitor has. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
docs: the release checklist opens a drive without logging in
The dialog it opens is titled "Open a drive" and the sign-in screen says "Open a drive without logging in"; "Attach drive" is the signed-in word for adding a drive to your own list, and stays there. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
ux: a visitor's New menu says "Open another drive"
This was referenced Oct 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release v2.90.0
dev→master. Version2.90.0(pubspec.yaml). On staging since152041bb0. 85 PRs since 2.89.0 (#2187–#2337, five of them dependabot bumps). A minor: nothing breaks for users, and links already in the wild keep resolving.What's new
Snapshots are now drive state artifacts, on in production. Create snapshot publishes a drive's state as one SQLite file, and a sync reads a drive's newest one before replaying its history: one discovery query per drive, and any failure falls back to the normal sync. Snapshots made by CLI 5.0.0 and core-js are readable here too. Staging has run it since 2026-10-16.
configVersiongoes 3 → 4 so every install picks the switches up; that reset also puts a user's chosen gateway and their auto-sync, thumbnail and snapshot-sync toggles back to the defaults, as the bump in #2200 did. (#2187, #2188, #2197, #2264, #2268, #2270, #2271, #2281, #2296, #2303, #2306, #2324, #2335)A faster, sturdier database in the browser. The web app's local database moves from sql.js to SQLite on the browser's private file system (OPFS), run in a background worker. Each user's existing data is copied over once, on the first load after the upgrade. Reopening takes 0.08 s instead of 3.5 s, and large writes no longer freeze the page. One tab owns the database at a time, so two tabs no longer overwrite each other's saves. Browsers without OPFS fall back to IndexedDB. The old store is left in place, untouched, as the way back. Schema 29 → 30 adds one nullable column. (#2197)
Open a drive without logging in. A link on the sign-in screen takes a drive link or a drive ID, asks for the drive key if the drive is private (filled in when the link carried it), and one press opens the explorer and syncs the drive. Browsing, previews, downloads and share links work as for a shared link; anything that needs a wallet is not offered. Logging in from the top bar keeps the drive, and a private drive opened this way keeps its key after login. A typed drive key never reaches the address bar, so a reload asks for it once. A visitor's New menu says "Open another drive"; "Attach drive" stays the signed-in word. (#2333, #2337)
Previews that show their progress. A preview downloads once and streams, instead of once per refresh. It says how far it has got ("18.2 MB of 47 MB", then "Decrypting…"), and a failed download offers Try again. PDFs, private media and images over 25 MiB wait for a Preview press; public video and audio still play straight away. Closing a preview stops its download. A playing private video no longer restarts when the drive syncs. (#2238, #2242, #2243)
Search as you type. Results drop down while you type, with keyboard navigation. Search says which drives it couldn't search because they aren't synced on this device, and offers to sync them. It no longer sticks on "Searching…" or opens a folder from another drive at its root. (#2287)
A shorter upload dialog. Cost and payment come first; thumbnails, license and deployment options sit behind Options. Counts and sizes match between the confirm and progress steps, and cost reads in credits everywhere. The license step is readable, and Creative Commons no longer preselects CC0. (#2283, #2291, #2314)
Wallet-paid (AR) uploads finish. Chunks a gateway rejects are retried, and Re-Upload resends the same signed transaction rather than paying again. The app warns you to keep the tab open while a wallet-paid upload runs. Turbo uploads are unchanged. (#2266)
Shared links open where they point. A folder link opens that folder for someone who doesn't have the drive. A drive or folder link pasted into a tab already running ArDrive opens what it names, and Back and Forward follow. The private folder share dialog says the link opens the whole drive. (#2289, #2294)
Your permanence. A new panel on the profile card shows how much you have preserved, what you have spent in credits and AR, what it would cost today (to the cent under $100), and a shareable image card. Its figures are kept for the session rather than fetched on every open. (#2244, #2326, #2329, #2330)
Manifests are now "deployments". Every place a user sees the word, in all six languages; "Import from manifest" keeps its name. New deployment opens in the folder you're viewing, leaves hidden folders out, and no longer drops a file whose path collides with another. Import from manifest works through gateways that refuse its query, and its results count imported and failed files correctly. (#2317, #2313, #2265, #2237, #2319)
First syncs of older drives are much faster. GraphQL queries go out with their fragments written out. turbo-gateway took about 8 s per query over old block ranges and now takes about 0.35 s. (#2267)
Smaller things
/view/{txId}uses the shared file page's layout (PE-9205: /view shares the shared file page's card #2241)Fixes
Behaviour changes worth knowing
Known issues, not fixed here
Internal
Golden drive state fixtures and a cross test with core-js (#2297); browser e2e tooling and guide, now with a journey for opening a drive without logging in (#2276, #2285, #2308, #2328, #2332, #2336);
dart formaton the files this release touched (#2331); staging deploys can't be overwritten by an older one (#2273); docs (#2275, #2305); dead Jira steps removed (#2286); dependabot bumps inweb-pstanddeploy(#1634, #1695, #1707, #2309, #2310).Verified
ec2eae634:flutter analyzeclean for the app and all 12 packages; the app suite (3,721), the package suites and the 47 browser tests pass; the 395 Dart files this release touched aredart formatclean. (ardrive_io's path test fails only on Windows separators; it passes on Linux CI.) On6ce1dc53a, the commit staging now runs: the app suite passes (3,732) anddev's CI is green.6ce1dc53a, new profile, test wallet, 2026-10-21: all 14 journeys pass, plus a fifteenth for feat: open a drive from the sign-in screen without signing in #2333: open New Test Drive by ID and Private Drive Test by a keyed share link as a visitor, log in from the explorer and land back on the drive. Journey 11's file ise2e-290-renamed.bininUAT-TESTONLY-DELETEME/e2e-290-folder; a private download is byte-identical to its upload. Earlier runs at2b46e9892,a88146448andec2eae634covered the 9 spot checks and Say a drive menu's name once to a screen reader #2322–ui: one sync button on Your drives, and ticking drives turns the heading into the selection #2327 checks, with Safari tested by a teammate and a 40k-item drive synced and snapshotted.staging.json, so feat: turn drive state reading and publishing on in production #2335'sprod.jsonandconfigVersionchange is covered by its rail and config tests (46) only; both drive-state switches have been on for staging since 2026-10-16.chaos_report.py: OK). AR balance 1.0619 before and after.masterget no CI by design (pr.yamlignoresmaster); the release branch isdevat152041bb0plus the version bump. After the checklist run,devgained only docs: the release checklist opens a drive without logging in #2336 (the checklist doc) and ux: a visitor's New menu says "Open another drive" #2337 (one visitor string), both green ondev's CI.🤖 Generated with Claude Code
https://claude.ai/code/session_019ZiqyGae4T1gJLGGB29pR9