Telegram-Drive Documentation

Turn your Telegram account into an unlimited, secure cloud storage drive. an Open-source desktop app built with Tauri, Rust, and React.

5,396 stars Rust Rust 1 file ยท ~57,467 tokens #open-source#react#rust#tauri#telegram#telegramapi#typescript
RAW Doc

Technical Documentation: caamer20/Telegram-Drive

โ„น๏ธ Provenance: Multi-Tier Ingestion ยท CodeWiki Reference

Overview (README.md)

Telegram Drive turns Telegram's familiar file storage into a focused, desktop-style workspace. The app connects directly to Telegram with credentials you provide; it does not run a separate file-storage or relay service. Every application feature is available without payment.

[!IMPORTANT]
Telegram Drive is an independent project and is not affiliated with Telegram FZ-LLC. Files remain subject to Telegram's account, service, and per-file limits. Telegram Drive should not be treated as literally unlimited storage or as the only backup of important data.

Contents

At a glance

Platforms Windows, macOS Intel, macOS Apple Silicon, Linux, Android, and Google TV
Storage model Saved Messages is the home location; Telegram channels can be presented as folders
Transfers Files, folders, drag and drop, remote URLs, durable queues, background operation, and retry controls
Media Image preview, PDF viewing, audio playback, video streaming, thumbnails, and archive tools
Desktop integrations Folder Sync, local REST API, WebDAV, local share links, tray controls, and native notifications
Privacy Local configuration and caches, opt-in crash reporting, loopback-only local servers, and no separate file relay
Languages 24 selectable locales plus automatic system-language selection
Price Every feature is free; an optional one-time $5 supporter license removes sponsor placements for life on up to three supported devices total

Download and install

Desktop 4.0.0 and Android / Google TV 4.1.0 preview use separate version lines. The desktop release does not update or include Android or Google TV. Downloads are listed below.

Platform Download Notes
Windows x64 Installer Includes the required Microsoft Visual C++ runtime setup
macOS โ€” Apple Silicon DMG For M-series Macs
macOS โ€” Intel DMG For Intel-based Macs
Linux x64 AppImage ยท Debian ยท RPM ยท Arch Choose your distribution; Arch updates remain managed by pacman
Android phones and tablets Signed universal APK Android 7.0 or newer; supports ARM64, ARMv7, x86, and x86_64
Android TV / Google TV Signed TV-compatible APK The same universal package includes the TV launcher and remote navigation

The new desktop workspace adds collections, saved searches, a media timeline, Continue Watching, offline trip packs, transfer activity, storage controls, cleanup, and sync previews. Android 4.1.0 includes the latest native media and offline improvements and fixes the folder sidebar reported in issue #212. Install the signed APK over your existing app to preserve its data and activation.

Desktop release assets also include updater/signature sidecars where applicable. Download installers only from this repository's GitHub Releases page. See the Linux packaging and rendering guide for Arch installation, updater ownership, diagnostics, and AppImage safe mode.

First-time setup

Telegram requires third-party clients to use an application API ID and API hash. Telegram Drive does not provide shared credentials.

  1. Sign in at my.telegram.org and open API development tools.
  2. Create a Telegram application and copy its api_id and api_hash.
  3. Install and open Telegram Drive, then enter those credentials locally.
  4. Authenticate with your phone number and login code, or use QR login. If Telegram cloud-password protection is enabled, complete that step as well.
  5. Open Saved Messages or select/create Telegram channels to use as folders.

[!WARNING]
Treat the API hash, Telegram login codes, session data, encryption credentials, REST keys, and WebDAV links as secrets. Do not paste them into issues, logs, screenshots, or support messages.

How it works

Telegram Drive uses Telegram's MTProto API for authentication and file operations:

  • Saved Messages appears as the main personal storage location.
  • Telegram channels created or selected by the app can appear as folders.
  • Transfers move directly between the application and Telegram.
  • Desktop metadata, settings, queues, sync state, thumbnails, and preview caches stay on the local device.
  • Standard uploads are stored in Telegram in their normal form. Optional TDENC2 uploads are encrypted locally before transfer.

The application caps a Telegram object at exactly 2,000,000,000 bytes. Encrypted files need additional envelope space, so their maximum original plaintext size is slightly lower.

Features

File management and organization

  • Grid and list views with virtualized rendering for large folders.
  • Adjustable file-card sizing from 50% to 200%.
  • Filename search, persistent sorting, multi-select, range selection, and bulk actions.
  • Upload, download, rename, copy, move, and delete workflows where Telegram permits them.
  • Drag-and-drop uploads and internal drag-and-drop organization.
  • Folder creation, rename, deletion, visibility controls, and custom local folder groups.
  • Whole-folder uploads with optional ZIP creation before transfer.
  • Remote URL uploads with progress, cancellation, retries, redirects, bounded size checks, and resumable ranges when supported by the source server.
  • Duplicate-file, empty-folder, media-metadata, and storage-insight tools through the local REST API.

Reliable transfers and desktop operation

  • Durable desktop upload and download queues that recover across window and application restarts.
  • Independent upload/download concurrency controls, bandwidth controls, pause, resume, retry, cancel, cooldown, network-waiting, and vault-unlock states.
  • Background operation from the system tray while transfers are active.
  • Native transfer notifications for completion, failure, pause, and attention-required states, with per-category controls.
  • Suspend, resume, network-recovery, and Telegram flood-wait handling.
  • Verified downloads written through private temporary files and atomically published to their destination.
  • A versioned local desktop file inventory so previously scanned folders appear while Telegram reconciliation continues.

Viewing, playback, and archives

  • Lazy-loaded thumbnails and bounded memory/disk preview caches.
  • Desktop HEIC/HEIF still images use bounded JPEG display renditions in previews, gallery/slideshow and offline viewing. macOS tries /usr/bin/sips first; other desktops need user-installed FFmpeg 8.1 or newer. External opening and downloads keep the original. See HEIC preview limits.
  • A desktop image viewer with zoom, pan, fit-to-window, actual-size, wheel, double-click, and keyboard navigation controls.
  • Built-in PDF viewer and audio player.
  • Video playback with seeking, HLS/fMP4 streaming, remuxing/transcoding fallbacks, and cache recovery for supported plaintext media.
  • Native Android playback with system media controls, resume, subtitle/audio-track selection, playback speed, and Picture-in-Picture where supported.
  • ZIP, RAR, and 7z archive browsing and extraction, including extraction back into Telegram Drive where the platform supports it.
  • Offline preview-cache controls for recently viewed standard files.
  • Recorded plain previews, thumbnails and ready offline copies from 3.9.x retain external opening after an update. The first open verifies and registers each private cache file; arbitrary files and edited copies remain refused.

Some media depends on operating-system codec support or FFmpeg. Supported protected audio, video, and PDF content can use authenticated local byte-range streaming while the vault is unlocked, without publishing a persistent plaintext copy. See encrypted-file limitations.

Sharing and local integrations

  • Password-protected local download links with optional expiration, listing, and revocation.
  • Native Telegram message links for files in public channels.
  • An opt-in desktop REST API for programmatic file, folder, bulk, storage, thumbnail, and media operations.
  • Opt-in desktop WebDAV access for mounting Telegram Drive in compatible file managers.
  • Optional, passphrase-encrypted settings backup through the user's own Telegram Saved Messages. Credentials, API/WebDAV keys, supporter activation, proxy details, and file data are excluded.

[!NOTE]
REST, WebDAV, and Telegram Drive share links are served by the running desktop application. They are not hosted public internet links. Keep the app open, do not forward its local ports, and protect every generated password, key, and capability URL.

Personalization, language, and network controls

  • System, light, dark, and default appearance preferences.
  • Built-in theme presets and a custom-theme editor.
  • Reduced-motion and interface-performance preferences.
  • 24 selectable production locales with locale-aware dates, numbers, file sizes, and transfer rates.
  • Right-to-left document direction and bidirectional-text protections for Arabic, Persian, and Urdu.
  • SOCKS5 and HTTP/HTTPS proxy routing with proxy credentials stored in the operating system's secure credential manager.
  • Configurable VPN-oriented timeouts, retries, keep-alive behavior, polling, bandwidth, transfer chunk size, and archive limits.
  • Signed desktop updates on supported self-updating packages; pacman-managed Arch installs open the verified release for package-manager updates.
  • Android share-sheet intake, foreground transfers, and native downloaded-file publication.

Screenshots

Screenshots show representative workflows; small details may change between releases.

Desktop

Folder and list management Video playback

Android

Files Transfer queue

Additional desktop and mobile captures are available in the screenshots directory.

Folder Sync (desktop)

Folder Sync is an opt-in, bidirectional mapping between a local directory and one Telegram channel on Windows, macOS, or Linux. It compares three statesโ€”the current local tree, the current remote tree, and the last successfully synced treeโ€”before changing either side.

Safety behavior includes:

  • Explicit conflicts instead of silent overwrites when local and remote versions both change.
  • Keep Local, Keep Remote, and Keep Both conflict choices.
  • A greater-than-50% mass-deletion guard.
  • Atomic temporary-file downloads and exact transfer-size checks.
  • Protection against nested mappings, duplicate remote paths, reserved temporary names, incomplete remote scans, and platform-incompatible filenames.
  • Vault-aware queue pauses for encrypted mappings.
  • A 50,000 file-bearing-message safety ceiling per mapped channel.

Folder Sync is disabled until enabled in Settings โ†’ Folder Sync. Read the Folder Sync guide before mapping an important directory, and keep a separate tested backup.

Optional client-side encryption (beta, format frozen)

See the frozen format specification and recovery drill.

Telegram Drive includes opt-in encrypted transfers using the versioned TDENC2 envelope. Standard uploads remain the default. Encryption can be selected as a default for future uploads or chosen for an individual upload.

Mode Protection Required to unlock
Standard Existing plaintext Telegram upload Nothing
Vault Encrypts with a key held in the local encrypted vault Unlocked vault
File passphrase Adds a passphrase slot to the individual file File passphrase
Vault + file passphrase Adds both vault and per-file passphrase access Any supported valid slot

The implementation provides streaming XChaCha20-Poly1305 encryption before upload, authenticated streaming downloads, optional protection of the original filename and MIME type, vault auto-lock controls, recovery-bundle export/import, per-file state badges, and encryption-aware transfer queues.

[!CAUTION]
Telegram Drive cannot recover, reset, or reconstruct a lost vault passphrase, file passphrase, encryption key, or unusable recovery bundle. Protect and test your recovery material and keep an independent backup of important files. Lost credentials or damaged recovery material can make encrypted data permanently unrecoverable.

The encryption design and implementation have not received an independent security audit. Use isolated test data first. This frozen-format beta is not a substitute for a tested backup strategy.

Current encrypted-file limitations

The following operations fail closed for encrypted objects while retaining their normal behavior for standard files:

  • In-app encrypted image and archive previews.
  • Encrypted thumbnails, HLS/fMP4 remuxing, and transcoding.
  • Local plaintext share links and REST/local-server plaintext access.
  • WebDAV read, overwrite, rename, move, copy, and delete operations.
  • Remote rename of encrypted Telegram media.
  • Plaintext-to-encrypted migration, decrypt-in-place migration, rekey/slot-management UI, and full format migration.

TDENC2-protected audio, video, and PDF content can stream in supported in-app viewers while the vault is unlocked. The session-scoped credential is revoked when the vault locks, and the app does not publish a persistent plaintext copy. Download and authenticate other encrypted files before opening them in another application.

Privacy and security

  • The Telegram API ID and application state are stored locally. The API hash is kept separately in the desktop operating-system credential manager or Android Keystore; legacy plaintext values are removed only after secure migration succeeds.
  • Telegram session data, settings, transfer state, sync metadata, encryption registry data, and vault material are stored locally in the application's data directories.
  • Standard uploads send ordinary file content to Telegram. TDENC2 uploads send ciphertext, although Telegram can still observe transport/account metadata such as ciphertext size, time, account, and destination channel.
  • The project does not operate a separate file-relay service.
  • Crash reporting is disabled by default and requires explicit consent. Reports exclude file names, paths, contents, messages, Telegram identifiers, credentials, phone numbers, and user-entered values.
  • The REST API and WebDAV server are disabled by default and bind only to 127.0.0.1.
  • The REST API stores only a hash of its generated key; the plaintext key is shown once.
  • WebDAV capability links are shown once and can be revoked by regeneration.
  • Proxy credentials use the operating system's secure credential manager.
  • Optional supporter verification receives no Telegram credentials or file activity and does not create a purchaser email profile.

Read the complete Privacy Policy, WebDAV guide, and REST API reference.

Languages

Telegram Drive supports a System language preference and these 24 selectable locales:

English Spanish Russian Ukrainian
Polish Persian Urdu Malay
Simplified Chinese Traditional Chinese French Italian
Arabic Brazilian Portuguese German Hindi
Bengali (Bangladesh) Indonesian Filipino (Philippines) Turkish
Thai (Thailand) Japanese Korean Vietnamese

Locale selection and formatting are production-supported. Authentication, encryption, desktop supporter copy and visible data arrays use canonical translations, and the eleven large locales have zero copied-English findings. Mobile follow-up changes remain local under the ownerโ€™s pre-commit hook. Noncritical English copy and full native-language, legal-copy, RTL, long-string, CJK and device review remain outstanding; see the measured locale review.

Optional $5 lifetime ad-free supporter license

Every Telegram Drive feature is available to non-paying users. Supported desktop and Android builds offer an optional $5.00 USD Lifetime Ad-Free Supporter License that removes sponsor placements on up to three supported Windows, macOS, Linux, or Android devices in total after one verified PayPal payment.

  • It is a one-time purchase, not a subscription.
  • Existing purchasers are not required to pay again after normal application updates.
  • Active and offline-grace entitlements keep sponsor placements hidden.
  • Reinstallation or another device can be restored with the recovery code, subject to the three-device allowance.
  • Checkout is available only inside Settings โ†’ Privacy โ†’ Supporter.
  • Payment does not create a Telegram Drive account or purchaser email profile.

[!WARNING]
Save the recovery code shown after activation. Payment alone does not bypass verification. Refunds are not automatic or guaranteed except where required by law. A refund, payment reversal, chargeback, or upheld dispute revokes the associated ad-free entitlement. Read the Supporter Terms before paying.

Android and Google TV (signed preview)

The Android build is currently distributed separately from the desktop release as a signed sideload preview. It is not available through Google Play.

  1. Open the Android / Android TV 4.1.0 release.
  2. Download the signed universal Android APK listed in that release.
  3. On Android, allow Install unknown apps for the browser or file manager you used.
  4. Open the APK and choose Install.
  5. Enter your own Telegram API ID and API hash on first launch.

Android requirements and notes:

  • Android 7.0 / API 24 or newer.

  • One signed APK supports phones, tablets, Android TV, and Google TV.

  • Google TV users can transfer the APK to the television or install it with ADB:

    bash
    adb install -r Telegram-Drive-v4.1.0-android-universal.apk
  • Android validates the package signature during installation. Future compatible updates must use the same signing identity.

  • Release maintainers should follow the Android and Google TV release runbook.

Local REST API and WebDAV

Both integrations are desktop-only, disabled by default, and loopback-only.

Integration Default address Authentication Access
REST API http://127.0.0.1:8550/api/v1 X-API-Key header File/folder operations, bulk actions, storage data, thumbnails, and media metadata
WebDAV http://127.0.0.1:8551/dav// One-time capability URL Read-only by default; writes require explicit opt-in

Do not expose these ports to a LAN or the internet. See the REST API endpoint reference and WebDAV guide for setup, security behavior, examples, and limitations.

Documentation

User documentation

Document Purpose
Changelog Release notes, compatibility information, and upgrade history
Privacy Policy Local data, Telegram data flow, crash reporting, sponsors, sharing, and supporter privacy
Security Policy Private vulnerability reporting, redaction guidance, and responsible testing boundaries
Folder Sync guide Sync safety model, limits, conflict resolution, and integration behavior
WebDAV guide Setup instructions for macOS, Windows, and Linux clients
REST API reference Authentication, endpoints, request examples, and error responses
Linux packaging guide Linux formats, Arch installation, rendering safe mode, diagnostics, and release safeguards
Linux/Arch implementation plan Design decisions, compatibility rules, release gates, acceptance matrix, and rollback
Supporter Terms Activation, recovery, device allowance, refunds, availability, and privacy

Maintainer and release documentation

Document Purpose
Supporter license invariants Protected $5 lifetime-license compatibility contract and required verification
Supporter service operations Worker, PayPal, D1, secure configuration, and release checks
Supporter backup and recovery D1 backup provisioning, restore drills, and production recovery
Android and Google TV release runbook Signing, packaging, acceptance, and sideload-release checks
Desktop code signing macOS notarization and Windows Authenticode settings, and first-signed-release acceptance

Build from source

Prerequisites

  • Node.js: 20.19.0+ within Node 20, or 22.12.0+.
  • Rust: the latest stable toolchain installed with rustup.
  • Telegram API credentials: an api_id and api_hash created at my.telegram.org.
  • Tauri system dependencies: follow the official Tauri 2 prerequisites for your platform.

Common requirements:

  • macOS: Xcode Command Line Tools (xcode-select --install).

  • Windows: Visual Studio Build Tools with Desktop development with C++ and the Microsoft Edge WebView2 Runtime.

  • Ubuntu/Debian:

    bash
    sudo apt-get update
    sudo apt-get install -y libwebkit2gtk-4.1-dev build-essential curl wget file \
      libssl-dev libdbus-1-dev libgtk-3-dev libayatana-appindicator3-dev \
      librsvg2-dev libfuse2

Install and run

bash
git clone https://github.com/caamer20/Telegram-Drive.git
cd Telegram-Drive/app
npm ci
npm run tauri dev

The first run downloads and compiles the Rust dependency graph and may take several minutes. Later builds reuse Cargo's compilation cache.

Create release bundles with:

bash
cd app
npm run tauri build

On Windows, the build scripts download and validate Microsoft's signed Visual C++ Redistributable before creating the NSIS installer.

Validation

Behavioral tests are end-to-end journeys; there are no unit suites. Run the relevant checks from app/ before submitting changes:

bash
npm run build:verify
npm test
npm run i18n:check
cd src-tauri
cargo fmt --all -- --check
cargo clippy --locked --features native-e2e --lib --all-targets -- -D warnings
cargo test --locked --features native-e2e --test native_e2e

node scripts/run-e2e.cjs from the repository root runs every host suite. See TESTING.md for what each suite covers and what still needs installed-app or device acceptance.

The application is built with Tauri 2, Rust, React 19, TypeScript, Tailwind CSS 4, TanStack Query/Virtual, SQLite, Tokio, Actix Web, Grammers, PDF.js, HLS.js, and MP4Box.

Support and community

  • Report reproducible, non-sensitive problems through GitHub Issues.
  • Use GitHub Discussions for questions, ideas, and general feedback.
  • Never include Telegram credentials, session data, payment identifiers, recovery codes, encryption keys, private filenames, or file contents in a public report.
  • For a sensitive security report, follow the private-disclosure guidance in the Security Policy.

Direct cryptocurrency tips help support development but do not activate the lifetime ad-free entitlement:


TV field navigation

With TV directional navigation, arrows edit a focused native field. After finishing an edit (or closing a native select picker), press Escape to return that field to directional navigation; the next arrow moves focus to another control. Enter resumes editing. A second Escape while already in navigation mode keeps the normal dialog-close behavior. Browser Escape is verified; physical Google TV Back event delivery and remote acceptance remain unrun.


Docs ANDROID SIDELOAD RELEASE (`Docs/ANDROID_SIDELOAD_RELEASE.md`)

Android and Google TV sideload release runbook

Telegram Drive is distributed as a signed sideloaded Android application, not through Google Play. The same universal APK supports Android phones, tablets, Android TV, and Google TV.

Fixed application identity

  • Package name: com.cameronamer.telegramdrive
  • Minimum Android version: Android 7.0 / API 24
  • Target SDK: API 36
  • Release keystore: ${XDG_CONFIG_HOME:-$HOME/.config}/telegram-drive/signing/telegram-drive-release.keystore
  • Key alias: telegram-drive
  • Keystore file SHA-256 as of 2026-08-23: b937e396837de9600325774564d45ee1502f55fbc2a6684476829be19742506c

The keystore-file SHA-256 is only a backup-integrity checksum. It is not the Android signing-certificate fingerprint. Obtain the certificate fingerprint from a signed APK with:

bash
$ANDROID_HOME/build-tools/36.0.0/apksigner verify --print-certs Telegram-Drive-vX.Y.Z-android-universal.apk

Never change the package name or signing key for an update. Android accepts an in-place upgrade only when both remain stable and the new versionCode is greater.

Android builds are local

Android is built, signed, and verified on the maintainer's machine. No GitHub workflow builds Android, and the Android project, build configuration, generated project folders, and Android test projects are never committed or uploaded. Only the compiled, signed binaries are published, as assets of the separate Android release.

Provide these values to the local build through the environment, never through a tracked file:

  • ANDROID_KEYSTORE_PASSWORD
  • ANDROID_KEY_ALIAS
  • ANDROID_KEY_PASSWORD
  • ANDROID_SIGNING_CERT_SHA256 (certificate fingerprint, not keystore file hash)
  • TAURI_PRIVATE_KEY (the local packaging signer input)
  • TAURI_KEY_PASSWORD when the updater key is encrypted

The packaging scripts fail closed if Android signing, updater signing, or the pinned certificate is absent.

Local build and binary publication

Status: all Android builds, artifact verification and installed-device acceptance for this tree are UNRUN. The desktop workflow is not Android verification. The version-line decision belongs to the owner; do not change shared desktop versions merely to follow this runbook.

  1. On the maintainer's private machine, use the reviewed release commit, Node 22, Rust 1.92, Java/Android SDK/NDK required by the local project, and the existing signing identity. Keep the generated Android project and all credentials outside outgoing Git commits. Choose the Android release version/code only after the owner decides the version line; verify the relevant inputs with npm run android:version:check -- --tag vX.Y.Z from app/.
  2. Run the host gates in TESTING.md. In app/, run npm ci, npm run build:verify, then the established local Android generation/build command npm run tauri -- android build. Preserve the locally maintained Android configuration; no Android project is created in GitHub. Confirm universal APK/AAB and the four ABI-specific signed APK outputs exist before packaging.
  3. From app/, run bash scripts/verify-android-artifacts.sh src-tauri/gen/android/app/build/outputs. This checks Baseline Profile presence, all four ABIs and 16 KiB ELF/ZIP alignment. Run bash scripts/package-android-release.sh with the existing private signing environment and pinned ANDROID_SIGNING_CERT_SHA256. It verifies certificates and AAB signing, packages binaries, creates SHA256SUMS, and creates/signs android-update.json. Preserve the APK hash, versionCode, package name, update-manifest URL and source revision in the private acceptance log. Do not publish signing keys.
  4. On a dedicated device with the previous signed APK installed, sign in, activate an existing supporter recovery code, create a test folder and transfer queue, and record data/activation visibly before upgrade. Run bash scripts/verify-android-upgrade.sh /private/path/previous.apk /private/path/current.apk from app/. It checks matching certificates, increasing versionCode, in-place install and launch. It does not itself inspect application data or supporter state. After it finishes, check that the Telegram session, folder/queue, recovery code and active ad-free entitlement survived with no purchase prompt. Repeat on phone and TV. Any data/activation loss blocks publication.
  5. Complete the device matrix below and release acceptance. Verify android-update.json identifies the exact package, monotonically newer code, APK filename, SHA-256 and separate Android release URL; verify its Minisign signature with the existing embedded public key. Compare SHA256SUMS against the final APK bytes, not an earlier build.
  6. Before any GitHub push, run node scripts/check-android-publication.cjs --range BASE..HEAD at the repository root, replacing BASE with the remote published revision, and manually inspect git diff --name-status BASE..HEAD and every outgoing commit. The guard's pending owner-review list is not permission to publish those paths. Android project/configuration/generated/test sources and signing files must never be pushed, even if a later outgoing commit removes them.
  7. Only after owner authorization and every local gate passes, create/use the separate Android release and upload the compiled signed APKs and their checksums/update manifest/signature. Keep the AAB as a private archive unless separately authorized as a compiled release asset. Never upload source folders, Gradle reports containing private paths, projects, credentials or signing backups. Do not push a desktop version tag as part of Android publication.

The updater metadata is derived from the exact universal APK, using scripts/create-android-release-manifest.cjs (arguments --apk, --version, --version-code, --repository, --tag, --output) and the existing updater signing key. Use the real separate Android tag in the final manifest. Local packaging/version verification may use the plain semantic tag required by its checker; inspect the final download URL before signing rather than assuming it is correct for an Androidv... tag. Publication and key changes are owner actions, not performed by this pass.

Android and TV advertising

Free Android phone, tablet, Android TV, and Google TV users receive the app's remote-focusable sponsored placement. Its action uses the production Adsterra campaign URL defined in src/services/sponsorLinks.ts. Verified lifetime supporters remain ad-free. The placement is automatically suppressed during media playback, previews, dialogs, and active transfers so it does not cover controls or compete with streaming bandwidth.

Do not add Google Mobile Ads or an AdMob application ID to the television package. Google Mobile Ads does not support Android TV; Telegram Drive's Android/TV advertising path is the in-app Adsterra placement.

Phone, tablet, and television acceptance

Use at least one API 24โ€“28 phone-class device, one API 35 phone/tablet, and one API 35 Android TV or Google TV device/emulator. Verify:

  • cold sign-in and session restoration;
  • D-pad focus, Select/Enter activation, Back navigation, Leanback launcher banner, and landscape layout on TV;
  • remote-friendly file browsing, settings, transfer controls, and in-app media playback;
  • the remote-focusable in-app sponsor placement for free users on TV, its supporter/ad-free suppression, and its automatic suppression during playback, previews, dialogs, and active transfers;
  • audio/video streaming without leaving Telegram Drive, system MediaSession controls, seek/resume, playback speed, subtitle/audio track selection, and Picture-in-Picture where supported;
  • Wi-Fi/metered/roaming, low-battery, charging, Doze, process-death, reboot, and low-storage transfer behavior;
  • notification denial and recovery, app lock, screenshot/Recents protection, and private lock-screen media metadata;
  • install-over-existing upgrade without clearing app data.

Useful test commands:

bash
bash scripts/run-android-emulator-tests.sh phone
bash scripts/run-android-emulator-tests.sh google-tv
bash scripts/test-android-resilience.sh com.cameronamer.telegramdrive process-death
bash scripts/test-android-resilience.sh com.cameronamer.telegramdrive low-battery
bash scripts/test-android-resilience.sh com.cameronamer.telegramdrive doze
bash scripts/verify-android-upgrade.sh previous.apk current.apk

The emulator runner creates an isolated AVD and requires the matching API 36 system image. Run it for both the phone and Google TV images. The resilience script changes emulator/device power state and resets it on exit. Use reboot-recovery only on a dedicated test device.

Sideloading

On Android phones/tablets, download the signed universal APK from the matching GitHub release, compare it with SHA256SUMS, allow the browser/file manager to install unknown apps, and open the APK.

On Android TV or Google TV, either transfer the APK with a trusted local file-transfer tool or install it through ADB:

bash
adb install Telegram-Drive-vX.Y.Z-android-universal.apk

For an upgrade, use adb install -r ... or the in-app updater. Never uninstall first unless intentionally deleting the device's local Telegram Drive data.

Signing-key recovery

The production key exists and is permission-restricted (0600). Create two independent encrypted/offline backups; do not put either in Git, cloud-sync folders without client-side encryption, issue trackers, or chat:

bash
bash app/scripts/backup-android-signing-key.sh /Volumes/EncryptedBackup/TelegramDrive

Store the keystore password separately from both key copies. Test one backup by comparing the .sha256 file and listing its alias in an offline environment. Losing either the key or its password permanently prevents normal in-place updates to installed copies.

Android developer verification

Because the app is sideloaded, the owner should register the package and signing certificate in Android Developer Console using the same legal developer identity and release certificate. This is an authenticated external-account action and cannot be completed by repository automation. Record the completed registration and certificate fingerprint in the private release-operations log; do not store identity documents or keystore passwords in this repository.


Docs AUTH PASSWORD CONTRACT (`Docs/AUTH_PASSWORD_CONTRACT.md`)

Cloud-password command contract

cmd_auth_check_password in app/src-tauri/src/commands/auth.rs currently returns either Ok(AuthResult { success: true, next_step: dashboard, error: None }) or a command error. It has no success: false return.

Authentication/account acquisition, a missing consumed password challenge and verified-account completion may fail through ? or a command error. grammers_client::SignInError::InvalidPassword renews the password challenge, then returns Err(INVALID_TWO_STEP_PASSWORD). Other client failures renew the challenge and return Err(2FA Failed: โ€ฆ). The success branch is the only constructed response.

Consequently a rejected cloud password enters the frontend's handleAuthError and displays the specific backend error. The generic canonical common.operation_failed fallback only handles a hypothetical unsuccessful response outside the current command contract. No production authentication code, credentials, locale resources or byte ceilings changed in this review.

The browser contract journey uses the actual sign-in UI with controlled native responses. It verifies the specific rejected-password message, then injects a clearly counterfactual success: false response to exercise the defensive generic branch, then signs in successfully. That injected response is not evidence of backend reachability. The existing wrong-password recovery/restart journey also passes. Live Telegram, real password challenge renewal and installed credential behavior remain UNRUN.


Docs CODE SIGNING (`Docs/CODE_SIGNING.md`)

Desktop Code Signing

The release workflow signs and notarizes desktop builds when signing credentials are present in the repository settings. When they are absent, the workflow prints a warning and produces the same unsigned builds as before. A platform with only some of its values set fails the release instead of publishing a build that is signed but not notarized.

Signing changes only the code signature. The bundle identifier com.cameronamer.telegramdrive, the updater key, the supporter credential service and account names, the entitlement token format, and the supporter service are not affected.

macOS: Developer ID and notarization

Requires an Apple Developer Program membership.

Setting Kind Value
APPLE_CERTIFICATE Secret Base64 of the exported Developer ID Application certificate (.p12)
APPLE_CERTIFICATE_PASSWORD Secret Password chosen when exporting the .p12
APPLE_SIGNING_IDENTITY Secret For example Developer ID Application: Name (TEAMID)
APPLE_API_ISSUER Secret App Store Connect API issuer ID
APPLE_API_KEY Secret App Store Connect API key ID
APPLE_API_KEY_P8 Secret Contents of the AuthKey_<key id>.p8 file

The build signs with the hardened runtime and the existing entitlements.plist, submits the application for notarization, and staples the ticket. A later step fails the release unless codesign --verify, stapler validate, and Gatekeeper assessment all accept the application and its identifier is unchanged.

Windows: Azure Artifact Signing

Requires an Azure Artifact Signing (formerly Trusted Signing) account with a certificate profile, and an app registration that has the certificate profile signer role. The workflow installs artifact-signing-cli 0.11.0, which calls signtool on the runner.

Setting Kind Value
AZURE_CLIENT_ID Secret App registration client ID
AZURE_CLIENT_SECRET Secret App registration client secret
AZURE_TENANT_ID Secret Directory (tenant) ID
AZURE_TRUSTED_SIGNING_ENDPOINT Variable For example https://eus.codesigning.azure.net
AZURE_TRUSTED_SIGNING_ACCOUNT Variable Signing account name
AZURE_TRUSTED_SIGNING_PROFILE Variable Certificate profile name

The application executable and the installer are signed and timestamped. A later step fails the release unless both carry a valid, timestamped Authenticode signature. An OV or EV certificate held on a hardware token cannot be used from a hosted runner; it needs a different sign command.

First signed release: required acceptance

Run these on real machines before publishing the first signed release. They are not automated.

  1. Update from the last unsigned release. Install the previous release, sign in, then update in the app. The session, settings, encryption vault, and folder layout must be unchanged.
  2. Supporter activation survives the update. On a machine with an active $5 lifetime activation, update and confirm the supporter status is still active and no sponsor placement appears. On macOS the first signed build has a new code identity, so the system may ask once for permission to read the existing Keychain items.
    • Choosing Always Allow must restore the activation with no further prompts.
    • Choosing Deny, or dismissing the prompt, must not show advertisements or a purchase prompt to an existing purchaser. The stored entitlement token still verifies without the Keychain; only refresh and recovery-code display need it.
    • If either case fails, do not publish. Existing purchasers must never be asked to pay again.
  3. Recovery code. Restore the activation with its recovery code on a second machine running the signed build.
  4. Gatekeeper and SmartScreen. Download the published artifacts with a browser on a clean machine and open them. macOS must open the application without the unidentified-developer dialog. Windows SmartScreen reputation builds over time; record what is shown.

Rehearsal

These workflow steps have not been run with real credentials. Before the first public signed release, push a pre-release tag to a private fork that has the credentials and confirm that the signing step and the two verification steps pass.


Docs ENCRYPTION RECOVERY DRILL (`Docs/ENCRYPTION_RECOVERY_DRILL.md`)

Encryption recovery drill

Status: native fixture recovery journeys PASS locally; real-device drill UNRUN. Use expendable test files and a separate backup of the existing encrypted vault before replacing anything. Supporter activation recovery is a separate system and is not changed by this drill.

  1. Create/unlock a test vault in Settings โ†’ Encryption. Upload a plain control file and protected files with and without protected names, including a Folder Sync file with a nested relative path. Keep original plaintext hashes outside the app. Expected: protected downloads match; the nested path restores correctly. Failure means transfer or metadata placement is not ready.
  2. Export a recovery bundle with a distinct strong recovery passphrase. Store the bundle and passphrase separately. Verify it in the current unlocked vault. Expected: verification covers the current master key and all profile keys. Re-export after changing any supported encryption material. The native fixture separately adds a profile key and proves an older bundle reports incomplete coverage; profile creation has no production UI, so that substep is fixture-only. Failure risks losing newer keys.
  3. Lock, restart and unlock. Change the vault passphrase using the current passphrase. Try an incorrect current passphrase first. Expected: rejection leaves the existing passphrase and file intact; the correct change preserves protected downloads after restart. Failure means authentication or persistence is unsafe.
  4. On a separate private test installation, restore the bundle with the recovery passphrase and a new vault passphrase. When replacing an existing vault, read the replacement warning and confirm deliberately; preserve the original vault backup. Expected: restored identity/profile coverage matches, downloads authenticate, and restart unlocks using the new vault passphrase. Failure blocks release acceptance.
  5. Try a wrong recovery passphrase and a truncated bundle. Expected: rejection creates no partial replacement; the prior vault remains usable. Cancel/lock during a derivation. Expected: no late unlock or file commit. Failure is a release blocker.
  6. Test an interrupted protected upload larger than 10 MiB and resume after restart with unchanged source and credentials. Expected: it continues the envelope, publishes once and decrypts to the original hash. Change the source in a separate test. Expected: a fresh upload rather than reused ciphertext. Failure risks integrity or nonce reuse.
  7. If recovery replacement was mistaken, quit the app and restore the saved original encrypted vault or the newest replacement archive in the private application-data directory. Restart and use its original passphrase. Expected: the original identity and files are recoverable. Do not delete archives until verified. Record the exact paths privately; do not publish secrets in acceptance evidence.

Record OS, installed version, fixture file hashes, each result and any sanitized error in RELEASE_ACCEPTANCE.md. Loss of the vault keys and recovery bundle makes vault-only encrypted files unrecoverable. A separate file-passphrase slot still requires its file passphrase. Exporting a bundle is not proof until a restore and authenticated download succeed.


Docs EXTERNAL OPENING (`Docs/EXTERNAL_OPENING.md`)

External opening inventory and acceptance

Caller inventory reviewed before restrictions (2026-10-02):

Boundary Callers and produced destinations
Shell open AuthWizard (Telegram API setup, existing Trust Wallet LTC/BTC links, auth gateway); HelpCenterDialog (GitHub issues); SettingsTabs (author site/repository); SupporterSettingsSection (PayPal approval, terms, help); FfmpegInstallNotice (FFmpeg download); services/sponsorLinks.ts (existing campaign)
Opener openUrl MobileSupporterCard (PayPal, terms, help); MobileDashboard (privacy/author/repository); useUpdateCheck (release page)
Opener revealItemInDir useFileDownload (newly saved files and durable queued-job paths)
Native cmd_open_file_externally DesktopDashboard (offline/downloaded asset); PdfViewer (app preview or provided offline file); MobileMediaPlayer (existing Android JNI path)

Desktop shell URLs permit only HTTP, HTTPS and mailto. Opener URL scopes use the same schemes, and reveal-in-directory remains permitted; generic opener open-path is not granted. Sponsor destination validation and its window.open(..., 'noopener,noreferrer') fallback are untouched. The Android native file-opening branch is untouched.

Desktop native opening requires a successfully produced, account-scoped regular file. Downloads are registered after publication. Exact recorded cache and ready offline paths retain their private-directory, removal and protection checks on every external open, including files registered earlier. Arbitrary files, substituted symlinks, protected cache records and other accounts remain refused. Historical workspace and flat desktop cache filenames remain supported. A missing previously migrated registration cannot be recreated silently. User-chosen download folders remain eligible for new app-produced downloads, but cannot be adopted through legacy cache migration.

Registration computes SHA-256 and records identity from the actual open handle. External opening can reuse that digest when every identity field and its account/cache context matches. A changed identity runs a full hash: different content is refused; identical content refreshes the identity for subsequent opens. Registration, identities, proofs and invalidation epochs use the existing per-account key/value store without a schema migration. A normal restart preserves reuse. Old registrations missing identity fields pay one full verification before becoming eligible.

The verified handle remains alive through the final identity/protection/account check and OS dispatch. The OS opener accepts a path, so replacement after the final check and before the OS opens that path remains an unavoidable race. Hashing uses at most two blocking workers and 64 KiB buffers. No Telegram request, new dependency, UI string or budget increase is added.

Accepted metadata trade-off

The owner approved verified-digest reuse on 2026-10-03. Matching metadata is not proof of current contents. POSIX identity uses device, inode, size, modification time and status-change time with nanosecond fields. An unprivileged POSIX process cannot set status-change time directly. Windows uses the handle's volume serial and 128-bit file ID where available (64-bit file-index fallback), plus size and FILE_BASIC_INFO LastWriteTime/ChangeTime at their 100 ns precision. A same-user Windows process with write access may set ChangeTime; this is a weaker protection accepted by the owner. File-ID reuse, metadata rollback or a privileged attacker can also defeat metadata-based inference. POSIX stat fields, Windows basic information.

Missing or zero identity fields always fall back to full hashing. Filesystem eligibility is conservative: APFS on macOS; NTFS/ReFS after successful handle-based volume queries on Windows. Unknown filesystems, FAT/exFAT, HFS/HFS+ and all Linux mounts retain full hashing. HFS catalog timestamps have second precision, and Linux nanosecond fields can still carry coarse per-jiffy values unless kernel/filesystem multigrain timestamp support is qualified. Failed Windows volume queries, including unsupported SMB volume management, retain full hashing. These are code paths, not claims of machine acceptance. Only this Mac's APFS path has been executed. Apple HFS dates, Windows volume query, Linux timestamp semantics.

Account sign-out/switch and Clear cache persist an account epoch change before cache deletion. Pinned survivors therefore require a fresh hash. A failed epoch write disables reuse for the process; logout continues its secure cleanup. A session-file identity also fences replaced logins. Cache proofs reject removal/protection changes at verification and handoff. Changed files never receive an updated identity until their hash matches the original digest and a transaction rechecks the registration and epoch.

HEIC source validation and internal cache reuse continue to hash fully. Cache LRU timestamp updates invalidate external reuse rather than blessing a new tuple. Consequently a UI flow that prepares or touches a cache before external opening may still read the full contents during preparation and again during opening. Direct repeated opening avoids those reads when identity is unchanged. Unsupported filesystems retain the original full-read costs.

Local native journeys use an opening sink instead of launching another OS application. Browser journeys prove sponsor, terms, fixture PayPal approval and donation links reach the permitted opener; they do not exercise OS browser dispatch or real payment. Installed Tauri/OS checks remain UNRUN: open a plain PDF preview, an offline file and a completed download; reveal the download in Finder/Explorer; verify sponsor/terms/approval links open. Arbitrary files and substituted symlinks must be refused. Record results in release acceptance.

Final file-capability regressions replace a file after successful hashing and before lease return, through separate native processes and real filesystem replacement. Opening and cache timestamp renewal retain the exact authenticated identity; neither can authorize a replacement by capturing a later identity. The controlled sink does not launch an OS application.

The opt-in measurement on this Mac wrote and synced 2,000,000,000 synthetic bytes, then opened a recorded ready offline copy through the native driver. With no other verification gate running, the debug driver took 213.8 seconds for first registration/opening (4 GB hashed) and 108.8 seconds for the subsequent open (2 GB hashed). This is warm local-storage and debug-code evidence, not release-build, cold-disk or installed-OS dispatch performance. No rehash was skipped. The measurement fixture was removed. Migration performs no Telegram requests: workspace caches scan account metadata one row at a time; an offline copy reads its pack record. Hash buffers remain 64 KiB with at most two workers; registration adds two small per-file records in the existing account database.

Release-build baseline before reuse

On macOS 15.7.9 (24G830), the x86_64-apple-darwin driver built with Rust 1.92.0 and cargo build --release --locked --features native-e2e --bin native-e2e-driver -j 4 completed under the optimized release profile confirmed by the build output. Binary SHA-256: d86cc4288a30b280a0a2a36d44c186ede2ccbe02cf8b197c77759d6b864ff220. These are separate single-run warm measurements, not installed application/OS dispatch benchmarks. No other verification gate ran during timed opening. The native-e2e build includes hash-byte instrumentation and a controlled opening sink.

Allocated synthetic bytes First legacy open seconds Reuse seconds First/reuse hashed bytes
2,000,000,000 16.223549 7.858260 4,000,000,000 / 2,000,000,000
200,000,000 1.579457 0.789655 400,000,000 / 200,000,000

The synthetic file writes, fixture record/hard-link setup and driver startup precede timing. Fixture seeding does not hash contents. First opening includes migration registration and validation; reuse retains a complete hash. Hash-byte assertions pass for both files. The private fixtures were removed after a clean driver exit. No Telegram request or real OS application launch occurs.

Cold-cache values are UNMEASURED. No purge was performed: this host offers a system-wide purge utility, but no verified, file-scoped purge was used. Synced writes or restarting the driver are not treated as cold. Release/cold behavior on other hardware, Windows/Linux and installed OS dispatch remain unmeasured.

Release-build measurements after reuse

The optimized release driver was built on macOS 15.7.9 (24G830), x86_64, Rust/Cargo 1.92.0 with cargo build --release --locked --features native-e2e --bin native-e2e-driver -j 4. The build log confirms release profile [optimized], completing in 5m 41s on the final rebuild. Binary SHA-256: 03f73fea503ececb3b9cb7908ab2df1e89d9772c775a6d77fcee4e4f447da811. No verification gate from this pass ran during timing; unrelated host activity was not controlled. These are single-run warm allocated synthetic files with startup, writes/fsync and fixture seeding before timing. No cache purge or real OS application launch occurred. Private fixtures were removed after a clean driver exit.

Bytes Before first/reuse seconds After first/reuse seconds After first/reuse hashed bytes
2,000,000,000 16.223549 / 7.858260 10.999386 / 0.005315 2,000,000,000 / 0
200,000,000 1.579457 / 0.789655 0.969191 / 0.006127 200,000,000 / 0

The baseline first opens read twice; new first legacy opens read once on APFS, and unchanged repeated opens read zero content bytes. Hash-byte assertions passed for both sizes. Cold-cache, installed OS dispatch and Windows/Linux timing remain unmeasured. Linux always hashes, and unsupported metadata/filesystems retain full reads. Internal cache/HEIC preparation also retains strict hashing; LRU touches cause the next external open to hash again.


Docs HEIC PREVIEW (`Docs/HEIC_PREVIEW.md`)

Desktop HEIC/HEIF preview limits

Plain desktop HEIC/HEIF still images use a separate JPEG display rendition. Original previews, ready offline copies, external opening and downloads keep the original bytes. macOS tries /usr/bin/sips; fallback candidates match the existing FFmpeg resource-directory/PATH search, with a bounded runtime version check requiring FFmpeg 8.1 or newer. Upstream 8.1 added automatic CLI tiled HEIF assembly (changelog); demuxer support in 7.0 alone is insufficient. Do not map the first video stream: that selects one tile. FFmpeg's automatic grid already uses a complex graph, so output sizing supplies the final scale instead of an incompatible simple-vf filter.

The version gate accepts an anchored numeric major/minor of at least 8.1, with an optional lowercase n release prefix, numeric patch and -/+ vendor suffix. Controlled native pipeline journeys accept 8.1.2, 8.1-full_build-www.gyan.dev, n8.1-3-g0123abcd and 9.0; they refuse 8.0.1, 7.1.1-1ubuntu1, malformed 8.1foo, and unversioned N-121234-g0123abcd-20260901. Master banners without a release number are deliberately refused using the existing translated preview-recovery message; dates, revision counts and hashes are never treated as a capability/version claim. No capability-probe cache is added. Original downloads/external actions remain available. The controlled helper proves gating, process routing and retained originals, not real vendor decoding on Windows.

Renditions fit 4096ร—4096, contain at most 8 MiB, and never upscale. Thumbnail fallback fits 480ร—360 and 1 MiB and retains the existing 16 MiB source-download cap; Telegram's thumbnail takes priority. Decode inputs are regular files up to 64 MiB, rejected before rendition hashing when oversized or unauthorized, with bounded 1 MiB metadata, 64 million primary pixels and bounded item/grid counts. Malformed boxes, external data references, unsupported clean-aperture/item layouts and oversized auxiliary/tile dimensions fail closed. The original remains available. AVIF, sequence frames beyond the primary still, Android/TV, WIC and bundled/WASM decoders are outside this change. No CSP or decoder dependency changes were made.

Each rendition is keyed by file/account identity, exact original path and verified SHA-256, separate from the original cache namespace. Original and JPEG hashes are rechecked on reuse; source mutation, removal/protection changes, account changes and canceled cache epochs refuse publication. One HEIF decoder runs at a time. Cache admission, byte reservations, file/category locks and original/partial paths remain held by the worker after an awaiting caller aborts. Associations are keyed per original path so viewing an offline copy cannot overwrite the online pin relationship. Pin/unpin and Clear cache cover the original/rendition pair. Offline input requires an exact account-owned plain pack/cache record; arbitrary download paths and substituted symlinks are refused. Protected sources produce no plaintext rendition.

Helpers have a 30-second total decode/probe deadline, 20 seconds per conversion, a 2-second/8 KiB version probe, output-size checks and process-tree cleanup. Linux additionally enforces a 2 GiB address-space limit. Windows creates the helper suspended, assigns a 1 GiB committed-memory Job Object, then resumes it. This macOS 15.7.9 host rejects the proposed 2 GiB RLIMIT_AS setting during preflight; macOS therefore uses a 1 GiB sampled RSS termination threshold with 10 ms requested polling. This is a reactive threshold and can overshoot; it is not a hard memory ceiling. Missing monitoring refuses execution. OS peak RSS belongs to the observed helper, not the entire app or unrelated OS services. Windows/Linux containment remains unexecuted on actual machines.

Synthetic host measurements

Measured through the real native process/cache pipeline on macOS 15.7.9 with sips 316 and FFmpeg 8.1.2, using a debug build and warm local storage. No other gate ran during the final measurement. Full pipeline time includes source verification, JPEG validation and publication; decoder time measures the conversion child only. Peaks below distinguish OS wait4 accounting from sampled RSS; a sampled value can miss a short-lived peak.

Decoder Synthetic source Decode seconds Pipeline seconds OS peak MiB Sampled peak MiB
sips 4032ร—3024 0.3421 3.2753 19.81 19.04
sips 8064ร—6048 3.6679 6.8445 438.25 438.25
ffmpeg 4032ร—3024 0.3255 3.3690 108.59 108.07
ffmpeg 8064ร—6048 0.5656 3.2319 221.93 221.30

Both decoders also pass the synthetic 240ร—180 rotation/mirror journeys: 180ร—240 after 90-degree counterclockwise rotation and 240ร—180 after vertical reflection. Pixel comparison against the transformed reference stays below 1.46 mean absolute channel levels. Full 12MP output matches the reference pattern (mean error 0 for sips and 0.493 for FFmpeg), proving full-grid assembly rather than a stretched first tile. These are synthetic transform checks, not acceptance of real iPhone metadata or color/HDR behavior.

Normal preview download/registration still occurs first under the existing preview-cache limit; the 64 MiB decoder-input limit does not prevent that preceding original download. Recorded offline/cached sources are size/provenance checked before rendition hashing.

The first uncached rendition adds one JPEG write and small account-store records; temporary decode output is removed or promoted. It needs no additional Telegram request after the original is available. A thumbnail without Telegram's own thumbnail downloads the bounded original once. Display verification reads the complete original before and after conversion/reuse, and reads the JPEG on reuse; it does not rely on timestamps alone. The cache temporarily reserves up to 16 MiB for conversion output while counting retained original bytes separately. JPEG validation allows 128 MiB of decoder allocation, independently of the child process controls. Existing cache/file/download limits still apply.

A browser/WebView that previously decoded an original larger than 4096 pixels now sees a downscaled, lossy JPEG; original opening/download remain available for full detail. Missing or unsupported decoders show translated recovery text with original actions. Real WebViews, real iPhone 12MP/48MP files, live Telegram, installed upgrades and Windows/Linux machines remain UNRUN. Desktop HEIC cannot be viewed where neither sips nor an eligible FFmpeg works, where the image exceeds these bounds, or where its layout is unsupported. Android and TV retain their existing behavior.

Fixture provenance, mutations and SHA-256 digests live in app/src-tauri/test-support/fixtures/heic/manifest.json. To repeat host journeys after building the native driver, run node scripts/measure-heic-preview.cjs /absolute/path/to/synthetic-48mp.heic; see TESTING.md. No photographs are included in these fixtures.


Docs LINUX ARCH IMPLEMENTATION PLAN (`Docs/LINUX_ARCH_IMPLEMENTATION_PLAN.md`)

Linux and Arch compatibility implementation plan

Status: implemented locally; CI and real-device acceptance remain required before a release is published.

Assessment of the original plan

The original plan was not safe to execute verbatim.

  1. The proposed unconditional Rust environment change duplicated an existing pre-WebKit startup hook and would have overridden the existing user preference.
  2. The release workflow modified the local AppImage only after tauri-action had signed and uploaded the release artifact. The published artifact therefore did not receive the patch; re-uploading a modified copy would invalidate the updater signature and metadata.
  3. The replacement AppRun changed accessibility, locale, graphics-library loading, EGL selection, and media paths together. That blast radius was too large for an unconfirmed DMA-BUF diagnosis.
  4. The proposed PKGBUILD used the wrong source/build paths, treated a Debian ar archive as a tar archive, installed under /usr/local, used a floating source, skipped integrity verification, and named a source build as a -bin package.
  5. It declared MIT even though the repository has no checked-in license text. That must not be invented, and it blocks responsible AUR publication.
  6. It did not account for updater ownership. A Tauri Linux self-update must not replace files owned by pacman.

Upgraded design

mermaid
flowchart TD
    Tag[Version tag] --> Verify[Frontend, Rust, Worker, supporter-contract, and release gates]
    Verify --> Draft[Create draft GitHub release]
    Draft --> Tauri[Tauri platform matrix]
    Tauri --> AppImage[Signed AppImage uploaded unchanged]
    Tauri --> Deb[Verified x86_64 Debian artifact]
    Deb --> Render[Render checksum-locked telegram-drive-bin PKGBUILD]
    Render --> Arch[Unprivileged build in digest-pinned Arch container]
    Arch --> PackageChecks[namcap, metadata, desktop, ldd, reinstall, Xvfb startup]
    PackageChecks --> ArchAssets[Arch package and runtime SBOM uploaded]
    AppImage --> Assurance[Final artifact assurance]
    ArchAssets --> Assurance
    Assurance --> Attest[Checksums, source SBOM, Arch SBOM, provenance attestations]
    Attest --> Publish[Publish only after every dependency succeeds]

    LinuxStart[Linux process starts] --> Explicit{Explicit WebKit rendering choice?}
    Explicit -->|Yes| Preserve[Preserve it unchanged]
    Explicit -->|No| Safe{Safe-rendering flag?}
    Safe -->|Yes| Composite[Disable compositing for this launch]
    Safe -->|No| Portable{AppImage and setting enabled?}
    Portable -->|Yes| Shm[Use shared-memory DMA-BUF transport]
    Portable -->|No| Native[Leave distro GTK, EGL, and WebKit defaults unchanged]

Compatibility rules

  • Never mutate AppImage/updater bytes after signing or upload.
  • Never force GDK_BACKEND or EGL_PLATFORM globally.
  • Never remove caller-provided rendering environment variables.
  • Preserve the existing linuxRenderingFix setting and default so upgrades remain compatible.
  • Honor XDG_DATA_HOME when locating the existing settings file.
  • Keep the normal native .deb, .rpm, and pacman rendering path on distribution WebKitGTK defaults.
  • Keep application identifier, app-data paths, secure credential service/account names, supporter token format, recovery behavior, price, lifetime entitlement, ad suppression, and three-device allowance unchanged.
  • Package only system-owned files under /usr; never package or remove user data.
  • Let pacman own updates for .pkg.tar.zst installations.
  • Do not publish to AUR until an intended license file is checked in and publication is explicitly authorized.

Implemented phases

1. Rendering policy

  • Refactored startup selection into unit-testable pure decisions.
  • Scoped the automatic fallback to AppImage runtime variables.
  • Replaced the legacy blanket disablement with WEBKIT_DMABUF_RENDERER_FORCE_SHM=1.
  • Added TELEGRAM_DRIVE_SAFE_RENDERING=1 as a launch-time last resort.
  • Preserved all explicit environment values and stopped forcing Wayland/EGL.
  • Added package/rendering values to copied diagnostics.
  • Updated the rendering preference description in all 24 shipped locales.

2. Signed artifact integrity

  • Removed the post-upload AppImage extraction/repacking block.
  • Added a regression gate that rejects AppImage mutation tooling or broad AppRun overrides after tauri-action.

3. Arch package

  • Added a checksum-rendered telegram-drive-bin recipe that consumes the exact release .deb.
  • Preserved the upstream ELF bytes with !strip/!debug and renamed only the installed system paths.
  • Added a stable launcher, desktop entry, icon identifier, runtime dependencies, and transparent upstream-license notice.
  • Marked the launched app as pacman-managed without changing the Tauri application identifier or data paths.

4. Updater ownership

  • Added a native installation-info command.
  • Retained update checks for pacman installs but changed the install action to open the verified release instead of running Tauri installation against /usr.
  • Kept existing AppImage, Windows, macOS, and Android install behavior unchanged.

5. CI and release assurance

  • Added PR/main Arch package-contract CI against a SHA-256-pinned upstream fixture.
  • Added a release Arch job downstream of the already-protected Tauri build.
  • Added package structure, dependency, desktop-entry, user-data exclusion, reinstall, and headless startup checks.
  • Added a resolved Arch runtime CycloneDX SBOM and package-specific SBOM attestation.
  • Made final assurance wait for the Arch package before checksums/provenance are generated.
  • Removed hard-coded application versions from source and Android SBOM generators.

6. Documentation and rollout

  • Added package selection, installation, updater ownership, safe-mode, diagnostics, rollback, and AUR-status guidance.
  • Added the Arch asset to README and product-site download discovery.
  • Kept the AUR step out of automation.

Acceptance gates

Automated gates:

  • browser end-to-end journeys;
  • production frontend build and bundle ceilings;
  • localization structure, variables, copied-English baseline, and literal-debt ceiling;
  • Rust format, strict Clippy, and the native process/HTTP/storage end-to-end journeys;
  • Worker type-check, HTTP/local-D1 end-to-end journeys, and Wrangler dry-run;
  • Playwright visual and Axe accessibility tests;
  • PKGBUILD checksum/source validation, .SRCINFO, namcap, desktop-file-validate, package metadata/content checks, unresolved-library detection, clean pacman install/reinstall, Xvfb startup, SBOM generation, final checksums, and attestations.

Manual release-candidate gates:

  • current EndeavourOS or Arch under Wayland with Mesa;
  • the GPU/driver family from the original failure report, including proprietary NVIDIA if applicable;
  • at least one X11 session;
  • AppImage and pacman package launch, resize, sign-in, file browsing, previews/media, accessibility bridge, tray, and update check;
  • install a previous Arch package, activate/restore a supporter entitlement, install the candidate with pacman, and confirm activation and recovery remain intact.

Rollback

If the AppImage fallback regresses, disable the existing Linux Rendering Fix preference or launch with an explicit reviewed WebKit variable; native packages are unaffected by the automatic policy. If the Arch package regresses, keep the release draft, remove no user data, correct the package recipe, and rebuild from the unchanged verified .deb. If a problem escapes publication, install the previous package with pacman and retain the application data and secure credential identifiers.

No AUR repository, live payment, production Worker, D1 data, signing key, supporter entitlement, or published GitHub release was changed while executing this plan.


Docs LINUX PACKAGING (`Docs/LINUX_PACKAGING.md`)

Linux packaging and rendering compatibility

Telegram Drive ships Linux release artifacts for different installation models. All of them use the same application identifier and data locations, and none of the packages should remove user configuration, cached metadata, Telegram sessions, or supporter activation during an install or upgrade.

Choose a package

Format Best fit Update ownership
.AppImage Portable use across distributions Telegram Drive's signed desktop updater
.deb Debian, Ubuntu, and derivatives The installed application/updater behavior provided by that release
.rpm RPM-based distributions The installed application/updater behavior provided by that release
.pkg.tar.zst Arch Linux, EndeavourOS, and compatible systems Pacman; the app may report an available version but opens the GitHub release instead of replacing pacman-owned files

Install the verified Arch release asset with:

bash
sudo pacman -U ./telegram-drive-bin-X.Y.Z-1-x86_64.pkg.tar.zst

To update, download the newer package from the official release and run the same pacman -U command. The package installs its program under /usr, while application state remains in the user's standard configuration/data directories.

AppImage rendering policy

The AppImage starts with WebKitGTK's shared-memory DMA-BUF transport fallback when the Linux Rendering Fix setting is enabled. This compatibility policy runs before WebKitGTK starts and is deliberately limited to AppImage launches. It does not force GDK_BACKEND or EGL_PLATFORM, and an explicitly supplied WebKit rendering variable is never removed or replaced.

The automatic fallback can be disabled from Settings โ†’ General โ†’ Performance & Compatibility. A restart is required. Native .deb, .rpm, and pacman packages use the WebKitGTK behavior chosen by the installed distribution.

If the window is blank and Settings cannot be reached, launch a one-time conservative mode:

bash
TELEGRAM_DRIVE_SAFE_RENDERING=1 ./Telegram.Drive_X.Y.Z_amd64.AppImage

This disables WebKit compositing for that launch and can be slower. It is a diagnostic/last-resort mode, not the normal default.

For an older published build that predates the safe-rendering flag, the legacy diagnostic workaround is:

bash
WEBKIT_DISABLE_DMABUF_RENDERER=1 ./Telegram.Drive_X.Y.Z_amd64.AppImage

Do not add these variables globally to a shell profile unless testing shows they are required for other applications too.

Report a Linux startup problem

Copy Telegram Drive's diagnostics from Settings when possible. Also include:

  • distribution and version;
  • package format and Telegram Drive version;
  • X11 or Wayland session;
  • desktop environment;
  • GPU model and driver;
  • whether the native package and AppImage behave differently;
  • terminal output from the failing launch; and
  • whether TELEGRAM_DRIVE_SAFE_RENDERING=1 changes the result.

Review diagnostic output before posting it publicly. Do not include Telegram credentials, API hashes, recovery codes, supporter tokens, or private filenames.

Release safeguards

The release workflow does not rewrite AppImage bytes after Tauri signs and uploads them. This keeps the AppImage, its updater signature, updater metadata, checksums, and provenance aligned.

The Arch package is produced from the exact .deb artifact already built by the protected desktop release job. The packaging step:

  • renders a PKGBUILD with exact SHA-256 checksums and no SKIP entries;
  • builds as an unprivileged user in a digest-pinned Arch container;
  • runs namcap, package-content, dependency, desktop-entry, reinstall-preservation, and X11 startup checks;
  • marks the installation as pacman-managed so Tauri does not overwrite files under /usr;
  • includes a resolved Arch runtime CycloneDX SBOM; and
  • enters release checksums and provenance before the draft is published.

CI provides a structural and headless X11 smoke test. Before treating a rendering issue as closed, also test the release candidate on real current Arch/EndeavourOS Wayland hardware and on any GPU/driver family involved in the original report.

AUR status

The release workflow does not publish to the Arch User Repository. The repository currently has no checked-in license text, so the package uses an explicit upstream-license-unspecified notice rather than inventing an MIT grant. Add and review the intended license first; AUR publication should then be a separate, explicitly authorized action with a release checksum and generated .SRCINFO.

Rollback

Install a previously downloaded release package with the appropriate package tool. Do not delete the application data directory as part of a package rollback. If the issue is AppImage-only, the native distribution package is the preferred temporary alternative while retaining the same data and entitlement identifiers.


Docs LOCALIZATION BUDGET REVIEW (`Docs/LOCALIZATION_BUDGET_REVIEW.md`)

P2-08 localization capacity review

The owner approved two locale-only ceiling increases sized by an exact dry-run encode, with at most 2% temporary headroom and no other budget changes. The target is zero hard-coded supporter, encryption and authentication presentation, translations for the eleven large locales, and visible data arrays. Remaining noncritical standalone copy and native-language acceptance keep broader P2-08 partly done; translations do not hold the tag.

Measured capacity

Measure Before Part 4 Final dry run and production build Temporary ceiling Final ceiling
Largest locale packet 124,881 138,790 141,523 138,790
Total locale data, including shared dictionary 1,734,675 1,952,434 1,990,950 1,952,434

The original ceilings were 125,000 and 1,800,000. The revised full target includes 128 new keys in all 24 catalogs, 110 distinct copied-English keys in the eleven large locales, and 176 previously exempt Folder Sync prose values. The complete draft was encoded with the production sorted union key table, SHA-256 dictionary identifier and td-locale-v1 JSON format before the corresponding canonical additions. Review identified further visible arrays and encrypted Settings Sync copy; each expanded draft was remeasured before shipping it. The final โ€œUnmuteโ€ label was included before lowering the ceilings.

The dictionary is 40,537 bytes and English is 53,195 bytes, for 93,732 bytes of separate startup data (previously 84,352). Total locale growth is 217,759 bytes. Loading remains one shared dictionary and one complete selected catalog; there are no additional Telegram requests, decoder work, persistent disk writes or feature dependencies. Resource memory grows with the selected translated data; no whole-application resident-memory claim is made.

The production build counts every locale and the dictionary. No bytes are reclassified or compressed out of accounting. Initial JavaScript, route, feature and CSS ceilings are unchanged. The accepted working build measures 504,787 initial JavaScript bytes, 2,448,590 total JavaScript bytes, 131,204 CSS bytes, 300,983 desktop-route bytes, 149,233 Settings bytes and 249,246 media-feature bytes. Other translations are not shortened to fit. The thirteen-string authentication draft is historical evidence, not the estimate used for this pass.

Scope and acceptance

All eleven target locales have zero copied-English findings, including formerly globally exempt Sync prose. Brands and protocol invariants remain exempt; the validator specifically enforces these Sync translations in the target eleven languages. Presentation scanning includes mapped data arrays, error-state setters, conditional templates and the encryption-sensitive Settings Sync section. Stored IDs, technical protocol values, physical shortcut glyphs and owner names are excluded by actual presentation flow rather than an expanded prose allowlist.

The complete working target measures 308 remaining noncritical literals: transfers/local services 94, media/help 73, other 141; supporter, encryption, authentication and sync are zero. The permitted candidate uses the original scanner and measures 298 literals: supporter 1, encryption/authentication/sync 0, transfers/local services 90, media/help 69 and other 138. Every staged literal ceiling decreases. The strengthened scanner would expose pre-existing hook-held mobile arrays and require an unauthorized candidate area increase, so that scanner and its matching release-tool test hunks remain uncommitted alongside the three mobile files, two mobile E2E journeys and 308-target baseline hunks matching the strengthened scanner. Diagnostic counts from the two scanner versions are not directly comparable. No ceiling is raised to accommodate held copy. The permitted desktop and canonical translation changes are verified from an exported index tree before commit.

Every authored range is listed in LOCALIZATION_REVIEW.md. All 24 native-review statuses remain UNRUN. Browser fixtures exercise presentation and state with controlled Telegram, payment and native-command boundaries; they do not establish linguistic quality, installed upgrades or Android/device behavior.


Docs LOCALIZATION REVIEW (`Docs/LOCALIZATION_REVIEW.md`)

Localization review required

These translations and added plural forms require owner-arranged native-language review. Structural, interpolation, browser and layout checks do not establish linguistic quality. No entry below is approved by a native reviewer. The protected $5.00 USD one-time lifetime ad-free promise, three-device allowance, recovery, offline grace and no-subscription meaning must remain intact.

Earlier P2 additions

The following ranges were authored in every listed locale: en, ar, bn-BD, de, es, fa-IR, fil-PH, fr, hi, id, it, ja, ko, ms-MY, pl-PL, pt-BR, ru, th-TH, tr, uk-UA, ur-PK, vi, zh-CN, zh-TW.

  • P2-03: workspace.protection, protection_plain, protection_locked, protection_unlocked, search_complete, search_partial.
  • P2-07: settings.weekly_quota, upload_limit, bandwidth_schedule, window_days, window_start, window_end, window_pause, window_add, window_remove.
  • P2-20: ads.closes_in, auto_close_label.
  • P2-09: settings.show_passphrase, hide_passphrase.

P2-08 added plural forms

The following forms need plural-grammar review. In Spanish, French, Italian and Brazilian Portuguese, million-category forms reuse the existing general plural wording; they have not received new native review.

  • es, fr, it, pt-BR: settings.encryption_experimental_inventory_many, files.drop_hint_many, notifications.uploads_queued_many, notifications.drop_rejected_many, workspace.seconds_many, workspace.result_count_many, workspace.selected_count_many.
  • ru: settings.encryption_experimental_inventory_few, settings.encryption_experimental_inventory_many.
  • ar: settings.encryption_experimental_inventory_zero, settings.encryption_experimental_inventory_few, settings.encryption_experimental_inventory_many.

P2-08 copied-English cleanup, batch 1

252 values were translated in this batch. Each row lists every changed key in that locale. All keys in this table have the common. prefix.

Locale Keys requiring review
de status, proxy, host, port, name, start, settings, light_mode, dark_mode, switch_light, switch_dark, expand_sidebar, collapse_sidebar, groups, all, unassigned, hide_groups, show_groups, save, create_group, edit_group_name, new_group_name, theme_color, delete_group, enter_group_name, hide_groups_desc
es proxy, host, start, settings, light_mode, dark_mode, switch_light, switch_dark, expand_sidebar, collapse_sidebar, groups, all, unassigned, hide_groups, show_groups, save, create_group, edit_group_name, new_group_name, theme_color, delete_group, enter_group_name, hide_groups_desc
fr proxy, port, start, settings, light_mode, dark_mode, switch_light, switch_dark, expand_sidebar, collapse_sidebar, groups, all, unassigned, hide_groups, show_groups, save, create_group, edit_group_name, new_group_name, theme_color, delete_group, enter_group_name, hide_groups_desc
ar start, settings, light_mode, dark_mode, switch_light, switch_dark, expand_sidebar, collapse_sidebar, groups, all, unassigned, hide_groups, show_groups, save, create_group, edit_group_name, new_group_name, theme_color, delete_group, enter_group_name, hide_groups_desc
pt-BR status, proxy, host, start, settings, light_mode, dark_mode, switch_light, switch_dark, expand_sidebar, collapse_sidebar, groups, all, unassigned, hide_groups, show_groups, save, create_group, edit_group_name, new_group_name, theme_color, delete_group, enter_group_name, hide_groups_desc
ru start, settings, light_mode, dark_mode, switch_light, switch_dark, expand_sidebar, collapse_sidebar, groups, all, unassigned, hide_groups, show_groups, save, create_group, edit_group_name, new_group_name, theme_color, delete_group, enter_group_name, hide_groups_desc
hi start, settings, light_mode, dark_mode, switch_light, switch_dark, expand_sidebar, collapse_sidebar, groups, all, unassigned, hide_groups, show_groups, save, create_group, edit_group_name, new_group_name, theme_color, delete_group, enter_group_name, hide_groups_desc
id status, host, port, start, settings, light_mode, dark_mode, switch_light, switch_dark, expand_sidebar, collapse_sidebar, groups, all, unassigned, hide_groups, show_groups, save, create_group, edit_group_name, new_group_name, theme_color, delete_group, enter_group_name, hide_groups_desc
tr start, settings, light_mode, dark_mode, switch_light, switch_dark, expand_sidebar, collapse_sidebar, groups, all, unassigned, hide_groups, show_groups, save, create_group, edit_group_name, new_group_name, theme_color, delete_group, enter_group_name, hide_groups_desc
ko start, settings, light_mode, dark_mode, switch_light, switch_dark, expand_sidebar, collapse_sidebar, groups, all, unassigned, hide_groups, show_groups, save, create_group, edit_group_name, new_group_name, theme_color, delete_group, enter_group_name, hide_groups_desc
zh-CN start, settings, light_mode, dark_mode, switch_light, switch_dark, expand_sidebar, collapse_sidebar, groups, all, unassigned, hide_groups, show_groups, save, create_group, edit_group_name, new_group_name, theme_color, delete_group, enter_group_name, hide_groups_desc
fil-PH status, proxy, host, port, light_mode, dark_mode

P2-08 resource bootstrap

common.language_load_failed was authored in all 24 locales: en, ar, bn-BD, de, es, fa-IR, fil-PH, fr, hi, id, it, ja, ko, ms-MY, pl-PL, pt-BR, ru, th-TH, tr, uk-UA, ur-PK, vi, zh-CN, zh-TW. Each translation needs native review. Existing loading and retry translations are reused.

P2-08 copied-English cleanup, batch 2

WebDAV copy was translated without changing access, protected-file or link-regeneration behavior. All keys below have the settings. prefix and require native review.

Locale Keys requiring review
de webdav_title, enable_webdav, webdav_running, webdav_stopped, webdav_port_desc, webdav_allow_changes, webdav_connection_link, webdav_link_generated, webdav_generate_failed, webdav_update_failed, webdav_port_updated, webdav_started, webdav_stopped_toast, webdav_read_only, webdav_changes_enabled, webdav_last_error, webdav_regenerate_title, webdav_enable_changes_title, webdav_description, webdav_local_only, webdav_allow_changes_desc, webdav_link_configured, webdav_link_unset, webdav_copy_alert, webdav_mobile_unavailable, webdav_regenerate_desc, webdav_enable_changes_confirm
es webdav_title, enable_webdav, webdav_running, webdav_stopped, webdav_port_desc, webdav_allow_changes, webdav_connection_link, webdav_link_generated, webdav_generate_failed, webdav_update_failed, webdav_port_updated, webdav_started, webdav_stopped_toast, webdav_read_only, webdav_changes_enabled, webdav_last_error, webdav_regenerate_title, webdav_enable_changes_title, webdav_description, webdav_local_only, webdav_allow_changes_desc, webdav_link_configured, webdav_link_unset, webdav_copy_alert, webdav_mobile_unavailable, webdav_regenerate_desc, webdav_enable_changes_confirm
fr webdav_title, enable_webdav, webdav_running, webdav_stopped, webdav_port_desc, webdav_allow_changes, webdav_connection_link, webdav_link_generated, webdav_generate_failed, webdav_update_failed, webdav_port_updated, webdav_started, webdav_stopped_toast, webdav_read_only, webdav_changes_enabled, webdav_last_error, webdav_regenerate_title, webdav_enable_changes_title, webdav_description, webdav_local_only, webdav_allow_changes_desc, webdav_link_configured, webdav_link_unset, webdav_copy_alert, webdav_mobile_unavailable, webdav_regenerate_desc, webdav_enable_changes_confirm
ar webdav_title, enable_webdav, webdav_running, webdav_stopped, webdav_port_desc, webdav_allow_changes, webdav_connection_link, webdav_link_generated, webdav_generate_failed, webdav_update_failed, webdav_port_updated, webdav_started, webdav_stopped_toast, webdav_read_only, webdav_changes_enabled, webdav_last_error, webdav_regenerate_title, webdav_enable_changes_title, webdav_description, webdav_local_only, webdav_allow_changes_desc, webdav_link_configured, webdav_link_unset, webdav_copy_alert, webdav_mobile_unavailable, webdav_regenerate_desc, webdav_enable_changes_confirm
pt-BR webdav_title, enable_webdav, webdav_running, webdav_stopped, webdav_port_desc, webdav_allow_changes, webdav_connection_link, webdav_link_generated, webdav_generate_failed, webdav_update_failed, webdav_port_updated, webdav_started, webdav_stopped_toast, webdav_read_only, webdav_changes_enabled, webdav_last_error, webdav_regenerate_title, webdav_enable_changes_title, webdav_description, webdav_local_only, webdav_allow_changes_desc, webdav_link_configured, webdav_link_unset, webdav_copy_alert, webdav_mobile_unavailable, webdav_regenerate_desc, webdav_enable_changes_confirm
ru webdav_title, enable_webdav, webdav_running, webdav_stopped, webdav_port_desc, webdav_allow_changes, webdav_connection_link, webdav_link_generated, webdav_generate_failed, webdav_update_failed, webdav_port_updated, webdav_started, webdav_stopped_toast, webdav_read_only, webdav_changes_enabled, webdav_last_error, webdav_regenerate_title, webdav_enable_changes_title, webdav_description, webdav_local_only, webdav_allow_changes_desc, webdav_link_configured, webdav_link_unset, webdav_copy_alert, webdav_mobile_unavailable, webdav_regenerate_desc, webdav_enable_changes_confirm
hi webdav_title, enable_webdav, webdav_running, webdav_stopped, webdav_port_desc, webdav_allow_changes, webdav_connection_link, webdav_link_generated, webdav_generate_failed, webdav_update_failed, webdav_port_updated, webdav_started, webdav_stopped_toast, webdav_read_only, webdav_changes_enabled, webdav_last_error, webdav_regenerate_title, webdav_enable_changes_title, webdav_description, webdav_local_only, webdav_allow_changes_desc, webdav_link_configured, webdav_link_unset, webdav_copy_alert, webdav_mobile_unavailable, webdav_regenerate_desc, webdav_enable_changes_confirm
id webdav_title, enable_webdav, webdav_running, webdav_stopped, webdav_port_desc, webdav_allow_changes, webdav_connection_link, webdav_link_generated, webdav_generate_failed, webdav_update_failed, webdav_port_updated, webdav_started, webdav_stopped_toast, webdav_read_only, webdav_changes_enabled, webdav_last_error, webdav_regenerate_title, webdav_enable_changes_title, webdav_description, webdav_local_only, webdav_allow_changes_desc, webdav_link_configured, webdav_link_unset, webdav_copy_alert, webdav_mobile_unavailable, webdav_regenerate_desc, webdav_enable_changes_confirm
tr webdav_title, enable_webdav, webdav_running, webdav_stopped, webdav_port_desc, webdav_allow_changes, webdav_connection_link, webdav_link_generated, webdav_generate_failed, webdav_update_failed, webdav_port_updated, webdav_started, webdav_stopped_toast, webdav_read_only, webdav_changes_enabled, webdav_last_error, webdav_regenerate_title, webdav_enable_changes_title, webdav_description, webdav_local_only, webdav_allow_changes_desc, webdav_link_configured, webdav_link_unset, webdav_copy_alert, webdav_mobile_unavailable, webdav_regenerate_desc, webdav_enable_changes_confirm
ko webdav_title, enable_webdav, webdav_running, webdav_stopped, webdav_port_desc, webdav_allow_changes, webdav_connection_link, webdav_link_generated, webdav_generate_failed, webdav_update_failed, webdav_port_updated, webdav_started, webdav_stopped_toast, webdav_read_only, webdav_changes_enabled, webdav_last_error, webdav_regenerate_title, webdav_enable_changes_title, webdav_description, webdav_local_only, webdav_allow_changes_desc, webdav_link_configured, webdav_link_unset, webdav_copy_alert, webdav_mobile_unavailable, webdav_regenerate_desc, webdav_enable_changes_confirm
zh-CN webdav_title, enable_webdav, webdav_running, webdav_stopped, webdav_port_desc, webdav_allow_changes, webdav_connection_link, webdav_link_generated, webdav_generate_failed, webdav_update_failed, webdav_port_updated, webdav_started, webdav_stopped_toast, webdav_read_only, webdav_changes_enabled, webdav_last_error, webdav_regenerate_title, webdav_enable_changes_title, webdav_description, webdav_local_only, webdav_allow_changes_desc, webdav_link_configured, webdav_link_unset, webdav_copy_alert, webdav_mobile_unavailable, webdav_regenerate_desc, webdav_enable_changes_confirm
fil-PH webdav_title

P2-08 shared wording reuse, batch 3

Identical English labels now reuse existing translations from comparable contexts. Their new context still needs native review. No selection-clearing wording was reused for cache deletion.

Locale Keys requiring context review
ar settings.theme_name, settings.transfers, settings.language_region, settings.api_running, settings.proxy_status_off, settings.off, settings.expired, settings.connection_diagnostics, share.never
de settings.tab_proxy, settings.theme_name, settings.transfers, settings.language_region, settings.api_running, settings.proxy_status_off, settings.off, settings.expired, settings.connection_diagnostics, share.never
es settings.tab_proxy, settings.theme_name, settings.transfers, settings.language_region, settings.api_running, settings.proxy_status_off, settings.off, settings.expired, settings.connection_diagnostics, share.never
fil-PH settings.tab_proxy, settings.connection_diagnostics
fr settings.tab_proxy, settings.theme_name, settings.transfers, settings.language_region, settings.api_running, settings.proxy_status_off, settings.off, settings.expired, settings.connection_diagnostics, share.never
hi settings.theme_name, settings.transfers, settings.language_region, settings.api_running, settings.proxy_status_off, settings.off, settings.expired, settings.connection_diagnostics, share.never
id settings.theme_name, settings.transfers, settings.language_region, settings.api_running, settings.proxy_status_off, settings.off, settings.expired, settings.connection_diagnostics, share.never
ko settings.theme_name, settings.transfers, settings.language_region, settings.api_running, settings.proxy_status_off, settings.off, settings.expired, settings.connection_diagnostics, share.never
pt-BR settings.tab_proxy, settings.theme_name, settings.transfers, settings.language_region, settings.api_running, settings.proxy_status_off, settings.off, settings.expired, settings.connection_diagnostics, share.never
ru settings.theme_name, settings.transfers, settings.language_region, settings.api_running, settings.proxy_status_off, settings.off, settings.expired, settings.connection_diagnostics, share.never
tr settings.tab_proxy, settings.theme_name, settings.transfers, settings.language_region, settings.api_running, settings.proxy_status_off, settings.off, settings.expired, settings.connection_diagnostics, share.never
zh-CN settings.theme_name, settings.transfers, settings.language_region, settings.api_running, settings.proxy_status_off, settings.off, settings.expired, settings.connection_diagnostics, share.never

Settings labels batch 4 โ€” native review required

Only values still identical to English were replaced; existing translations were preserved. These labels were translated here and are not native-approved.

  • de (52): settings.tab_themes, settings.auto, settings.presets, settings.custom_themes, settings.create_theme, settings.edit_theme, settings.base_mode, settings.delete_theme, settings.delete_theme_confirm, settings.reset_default, settings.color_bg, settings.color_surface, settings.color_primary, settings.color_secondary, settings.color_text, settings.color_subtext, settings.regenerate, settings.generate, settings.storage, settings.optional, settings.reconnecting, settings.reconnect_now, settings.proxy_status_checking, settings.checking, settings.proxy_status_connected, settings.proxy_status_unreachable, settings.proxy_testing, settings.test_connection, settings.base_delay, settings.max_delay, settings.unlimited, settings.protected, settings.public, settings.never_expires, settings.copy_share_link, settings.revoke_link, settings.copy_diagnostics, settings.reset_defaults, settings.done, settings.clear, settings.clearing, settings.clear_all, settings.original, settings.updates, settings.check_now, settings.offline, settings.not_tested, settings.testing, settings.check_ping, settings.excellent, settings.good, settings.slow.
  • es (50): settings.tab_themes, settings.auto, settings.presets, settings.custom_themes, settings.create_theme, settings.edit_theme, settings.delete_theme, settings.delete_theme_confirm, settings.reset_default, settings.color_bg, settings.color_surface, settings.color_primary, settings.color_secondary, settings.color_text, settings.color_subtext, settings.regenerate, settings.generate, settings.storage, settings.optional, settings.reconnecting, settings.reconnect_now, settings.proxy_status_checking, settings.checking, settings.proxy_status_connected, settings.proxy_status_unreachable, settings.proxy_testing, settings.test_connection, settings.base_delay, settings.max_delay, settings.unlimited, settings.protected, settings.public, settings.never_expires, settings.copy_share_link, settings.revoke_link, settings.copy_diagnostics, settings.reset_defaults, settings.done, settings.clear, settings.clearing, settings.clear_all, settings.updates, settings.check_now, settings.offline, settings.not_tested, settings.testing, settings.check_ping, settings.excellent, settings.good, settings.slow.
  • fr (47): settings.tab_themes, settings.auto, settings.presets, settings.custom_themes, settings.create_theme, settings.edit_theme, settings.delete_theme, settings.delete_theme_confirm, settings.reset_default, settings.color_bg, settings.color_primary, settings.color_secondary, settings.color_text, settings.color_subtext, settings.regenerate, settings.generate, settings.storage, settings.optional, settings.reconnecting, settings.reconnect_now, settings.proxy_status_checking, settings.checking, settings.proxy_status_connected, settings.proxy_status_unreachable, settings.proxy_testing, settings.test_connection, settings.base_delay, settings.max_delay, settings.unlimited, settings.protected, settings.never_expires, settings.copy_share_link, settings.revoke_link, settings.copy_diagnostics, settings.reset_defaults, settings.done, settings.clear, settings.clearing, settings.clear_all, settings.updates, settings.check_now, settings.offline, settings.not_tested, settings.testing, settings.check_ping, settings.good, settings.slow.
  • ar (52): settings.tab_themes, settings.auto, settings.presets, settings.custom_themes, settings.create_theme, settings.edit_theme, settings.base_mode, settings.delete_theme, settings.delete_theme_confirm, settings.reset_default, settings.color_bg, settings.color_surface, settings.color_primary, settings.color_secondary, settings.color_text, settings.color_subtext, settings.regenerate, settings.generate, settings.storage, settings.optional, settings.reconnecting, settings.reconnect_now, settings.proxy_status_checking, settings.checking, settings.proxy_status_connected, settings.proxy_status_unreachable, settings.proxy_testing, settings.test_connection, settings.base_delay, settings.max_delay, settings.unlimited, settings.protected, settings.public, settings.never_expires, settings.copy_share_link, settings.revoke_link, settings.copy_diagnostics, settings.reset_defaults, settings.done, settings.clear, settings.clearing, settings.clear_all, settings.original, settings.updates, settings.check_now, settings.offline, settings.not_tested, settings.testing, settings.check_ping, settings.excellent, settings.good, settings.slow.
  • pt-BR (50): settings.tab_themes, settings.auto, settings.presets, settings.custom_themes, settings.create_theme, settings.edit_theme, settings.delete_theme, settings.delete_theme_confirm, settings.reset_default, settings.color_bg, settings.color_surface, settings.color_primary, settings.color_secondary, settings.color_text, settings.color_subtext, settings.regenerate, settings.generate, settings.storage, settings.optional, settings.reconnecting, settings.reconnect_now, settings.proxy_status_checking, settings.checking, settings.proxy_status_connected, settings.proxy_status_unreachable, settings.proxy_testing, settings.test_connection, settings.base_delay, settings.max_delay, settings.unlimited, settings.protected, settings.public, settings.never_expires, settings.copy_share_link, settings.revoke_link, settings.copy_diagnostics, settings.reset_defaults, settings.done, settings.clear, settings.clearing, settings.clear_all, settings.updates, settings.check_now, settings.offline, settings.not_tested, settings.testing, settings.check_ping, settings.excellent, settings.good, settings.slow.
  • ru (52): settings.tab_themes, settings.auto, settings.presets, settings.custom_themes, settings.create_theme, settings.edit_theme, settings.base_mode, settings.delete_theme, settings.delete_theme_confirm, settings.reset_default, settings.color_bg, settings.color_surface, settings.color_primary, settings.color_secondary, settings.color_text, settings.color_subtext, settings.regenerate, settings.generate, settings.storage, settings.optional, settings.reconnecting, settings.reconnect_now, settings.proxy_status_checking, settings.checking, settings.proxy_status_connected, settings.proxy_status_unreachable, settings.proxy_testing, settings.test_connection, settings.base_delay, settings.max_delay, settings.unlimited, settings.protected, settings.public, settings.never_expires, settings.copy_share_link, settings.revoke_link, settings.copy_diagnostics, settings.reset_defaults, settings.done, settings.clear, settings.clearing, settings.clear_all, settings.original, settings.updates, settings.check_now, settings.offline, settings.not_tested, settings.testing, settings.check_ping, settings.excellent, settings.good, settings.slow.
  • hi (52): settings.tab_themes, settings.auto, settings.presets, settings.custom_themes, settings.create_theme, settings.edit_theme, settings.base_mode, settings.delete_theme, settings.delete_theme_confirm, settings.reset_default, settings.color_bg, settings.color_surface, settings.color_primary, settings.color_secondary, settings.color_text, settings.color_subtext, settings.regenerate, settings.generate, settings.storage, settings.optional, settings.reconnecting, settings.reconnect_now, settings.proxy_status_checking, settings.checking, settings.proxy_status_connected, settings.proxy_status_unreachable, settings.proxy_testing, settings.test_connection, settings.base_delay, settings.max_delay, settings.unlimited, settings.protected, settings.public, settings.never_expires, settings.copy_share_link, settings.revoke_link, settings.copy_diagnostics, settings.reset_defaults, settings.done, settings.clear, settings.clearing, settings.clear_all, settings.original, settings.updates, settings.check_now, settings.offline, settings.not_tested, settings.testing, settings.check_ping, settings.excellent, settings.good, settings.slow.
  • id (52): settings.tab_themes, settings.auto, settings.presets, settings.custom_themes, settings.create_theme, settings.edit_theme, settings.base_mode, settings.delete_theme, settings.delete_theme_confirm, settings.reset_default, settings.color_bg, settings.color_surface, settings.color_primary, settings.color_secondary, settings.color_text, settings.color_subtext, settings.regenerate, settings.generate, settings.storage, settings.optional, settings.reconnecting, settings.reconnect_now, settings.proxy_status_checking, settings.checking, settings.proxy_status_connected, settings.proxy_status_unreachable, settings.proxy_testing, settings.test_connection, settings.base_delay, settings.max_delay, settings.unlimited, settings.protected, settings.public, settings.never_expires, settings.copy_share_link, settings.revoke_link, settings.copy_diagnostics, settings.reset_defaults, settings.done, settings.clear, settings.clearing, settings.clear_all, settings.original, settings.updates, settings.check_now, settings.offline, settings.not_tested, settings.testing, settings.check_ping, settings.excellent, settings.good, settings.slow.
  • tr (52): settings.tab_themes, settings.auto, settings.presets, settings.custom_themes, settings.create_theme, settings.edit_theme, settings.base_mode, settings.delete_theme, settings.delete_theme_confirm, settings.reset_default, settings.color_bg, settings.color_surface, settings.color_primary, settings.color_secondary, settings.color_text, settings.color_subtext, settings.regenerate, settings.generate, settings.storage, settings.optional, settings.reconnecting, settings.reconnect_now, settings.proxy_status_checking, settings.checking, settings.proxy_status_connected, settings.proxy_status_unreachable, settings.proxy_testing, settings.test_connection, settings.base_delay, settings.max_delay, settings.unlimited, settings.protected, settings.public, settings.never_expires, settings.copy_share_link, settings.revoke_link, settings.copy_diagnostics, settings.reset_defaults, settings.done, settings.clear, settings.clearing, settings.clear_all, settings.original, settings.updates, settings.check_now, settings.offline, settings.not_tested, settings.testing, settings.check_ping, settings.excellent, settings.good, settings.slow.
  • ko (52): settings.tab_themes, settings.auto, settings.presets, settings.custom_themes, settings.create_theme, settings.edit_theme, settings.base_mode, settings.delete_theme, settings.delete_theme_confirm, settings.reset_default, settings.color_bg, settings.color_surface, settings.color_primary, settings.color_secondary, settings.color_text, settings.color_subtext, settings.regenerate, settings.generate, settings.storage, settings.optional, settings.reconnecting, settings.reconnect_now, settings.proxy_status_checking, settings.checking, settings.proxy_status_connected, settings.proxy_status_unreachable, settings.proxy_testing, settings.test_connection, settings.base_delay, settings.max_delay, settings.unlimited, settings.protected, settings.public, settings.never_expires, settings.copy_share_link, settings.revoke_link, settings.copy_diagnostics, settings.reset_defaults, settings.done, settings.clear, settings.clearing, settings.clear_all, settings.original, settings.updates, settings.check_now, settings.offline, settings.not_tested, settings.testing, settings.check_ping, settings.excellent, settings.good, settings.slow.
  • zh-CN (52): settings.tab_themes, settings.auto, settings.presets, settings.custom_themes, settings.create_theme, settings.edit_theme, settings.base_mode, settings.delete_theme, settings.delete_theme_confirm, settings.reset_default, settings.color_bg, settings.color_surface, settings.color_primary, settings.color_secondary, settings.color_text, settings.color_subtext, settings.regenerate, settings.generate, settings.storage, settings.optional, settings.reconnecting, settings.reconnect_now, settings.proxy_status_checking, settings.checking, settings.proxy_status_connected, settings.proxy_status_unreachable, settings.proxy_testing, settings.test_connection, settings.base_delay, settings.max_delay, settings.unlimited, settings.protected, settings.public, settings.never_expires, settings.copy_share_link, settings.revoke_link, settings.copy_diagnostics, settings.reset_defaults, settings.done, settings.clear, settings.clearing, settings.clear_all, settings.original, settings.updates, settings.check_now, settings.offline, settings.not_tested, settings.testing, settings.check_ping, settings.excellent, settings.good, settings.slow.
  • fil-PH (5): settings.base_mode, settings.color_text, settings.color_subtext, settings.base_delay, settings.offline.

Runtime update and recovery copy โ€” native review required

All 24 locales (ar, bn-BD, de, en, es, fa-IR, fil-PH, fr, hi, id, it, ja, ko, ms-MY, pl-PL, pt-BR, ru, th-TH, tr, uk-UA, ur-PK, vi, zh-CN, zh-TW) have newly authored runtime.update_available, runtime.update_downloading, runtime.update_verifying, runtime.update_installing, runtime.error_title, runtime.error_description, runtime.error_details, runtime.error_recover, runtime.update_complete, runtime.update_whats_new, runtime.update_fallback, runtime.update_verified values. Every translated range needs native review; none is native-approved. The existing English recovery promise and signed-update descriptions were preserved.

Startup progress โ€” native review required

All 24 locales (ar, bn-BD, de, en, es, fa-IR, fil-PH, fr, hi, id, it, ja, ko, ms-MY, pl-PL, pt-BR, ru, th-TH, tr, uk-UA, ur-PK, vi, zh-CN, zh-TW) have newly authored runtime.startup_{initial,local,session,empty,invalid,connect,account,sponsor}_{label,detail} and runtime.startup_percent values. These translations need native review. Stage meanings and progress values are unchanged.

Viewer controls and progress โ€” native review required

All 24 locales (ar, bn-BD, de, en, es, fa-IR, fil-PH, fr, hi, id, it, ja, ko, ms-MY, pl-PL, pt-BR, ru, th-TH, tr, uk-UA, ur-PK, vi, zh-CN, zh-TW) have newly authored viewer.previous_file, viewer.next_file, viewer.close_player, viewer.close_archive, viewer.close_pdf, viewer.close_preview, viewer.close_shortcut, viewer.previous_shortcut, viewer.next_shortcut, viewer.play_pause_shortcut, viewer.fullscreen_shortcut, viewer.exit_fullscreen_shortcut, viewer.enter_fullscreen, viewer.play_pause, viewer.navigate, viewer.space, viewer.mute, viewer.debug, viewer.cap, viewer.buffered, viewer.mode, viewer.source, viewer.playing, viewer.playback_error, viewer.loading_video, viewer.preparing_stream, viewer.unsupported_media, viewer.loading_document, viewer.downloading_telegram, viewer.unable_pdf, viewer.fit_width, viewer.open_native, viewer.opening, viewer.open_external, viewer.loading_preview, viewer.preview_error, viewer.preview_unsupported, viewer.file_type values. These translations need native review. Keyboard identifiers such as Esc, F, ArrowLeft and J remain literal within translated shortcut descriptions.

Short action-label templates and sign-out alias

All24 locales have common.action_name and common.action_count structural templates; ja/ko/zh-CN/zh-TW place the filename before the action. Native grammar review is required for these label templates. common.sign_out preserves English โ€œSign Outโ€ and reuses each other localeโ€™s existing common.logout translation. No prose is shortened or replaced by these templates. Exact-English debt now excludes only references with no Unicode letters outside recognized interpolation tokens; variable/plural validation remains required and CLI regressions reject missing variables and copied Delete {{name}}. The only newly excluded existing exact match is the immutable $5 price (no static language), in es/ru/uk-UA/pl-PL/fa-IR/ur-PK/ms-MY/zh-CN/fr/ar/pt-BR/de/hi/id/tr/ko. Each affected copied-English ceiling was reduced by one; all other locales had zero newly excluded matches. No spare allowance was created, and the displayed protected price is unchanged.

File-operation dialogs and outcomes โ€” native review required

All 24 locales (ar, bn-BD, de, en, es, fa-IR, fil-PH, fr, hi, id, it, ja, ko, ms-MY, pl-PL, pt-BR, ru, th-TH, tr, uk-UA, ur-PK, vi, zh-CN, zh-TW) have newly authored operations.delete_file, operations.delete_file_question, operations.delete_files, operations.delete_files_question, operations.delete_all, operations.deleted_count, operations.delete_failed_count, operations.renamed, operations.move_one_source, operations.already_in_folder, operations.bulk_move, operations.move_question, operations.move_action, operations.moved_count, operations.downloaded_count, operations.bulk_download_failed, operations.folder_empty, operations.folder_downloading, operations.folder_download_complete, operations.no_shareable_files, operations.share_failed, operations.share_links_failed, operations.link_copied, operations.share_failed_copied, operations.file_deleted values. Every translated range needs native review. Count outcomes use a noun label followed by the actual count, avoiding an English-only suffix. Account checks and transfer actions are unchanged.

Transfer confirmation, restoration and notifications โ€” native review required

All 24 locales (ar, bn-BD, de, en, es, fa-IR, fil-PH, fr, hi, id, it, ja, ko, ms-MY, pl-PL, pt-BR, ru, th-TH, tr, uk-UA, ur-PK, vi, zh-CN, zh-TW) have newly authored transfer_copy.queue_load_error, transfer_copy.upload_failed, transfer_copy.downloaded, transfer_copy.download_failed, transfer_copy.migrated_uploads, transfer_copy.migrated_downloads, transfer_copy.upload_migrate_failed, transfer_copy.download_migrate_failed, transfer_copy.restored_uploads, transfer_copy.restored_downloads, transfer_copy.uploads_cancelled, transfer_copy.downloads_cancelled, transfer_copy.uploads_paused, transfer_copy.downloads_paused, transfer_copy.uploads_resumed, transfer_copy.downloads_resumed, transfer_copy.download_tip, transfer_copy.confirm_download, transfer_copy.download_file, transfer_copy.download_files, transfer_copy.choose_location, transfer_copy.selection_summary, transfer_copy.downloading_to_downloads, transfer_copy.queued_downloads, transfer_copy.unknown_error, transfer_copy.remote_upload_queued values. Every translated range needs native review. Count summaries use noun labels followed by the actual count. Queues, account ownership, cancellation and native actions are unchanged.

Shared controls โ€” native review required

All 24 locales (ar, bn-BD, de, en, es, fa-IR, fil-PH, fr, hi, id, it, ja, ko, ms-MY, pl-PL, pt-BR, ru, th-TH, tr, uk-UA, ur-PK, vi, zh-CN, zh-TW) have newly authored ui_copy.security_center, ui_copy.vault, ui_copy.recovery, ui_copy.how_it_works, ui_copy.unlocked_session, ui_copy.not_configured, ui_copy.recovery_verified, ui_copy.action_required, ui_copy.file_actions, ui_copy.folder_actions, ui_copy.open_folders, ui_copy.close_folders, ui_copy.search_scope, ui_copy.current_scope, ui_copy.global_scope, ui_copy.reset_filters, ui_copy.sort_files, ui_copy.thumbnail_size, ui_copy.keyboard_shortcuts, ui_copy.close_shortcuts, ui_copy.help_faq, ui_copy.close_help, ui_copy.advanced_settings, ui_copy.search_settings, ui_copy.understood, ui_copy.creating, ui_copy.create_private_folder, ui_copy.finish, ui_copy.dark, ui_copy.light values. Every translated range needs native review. Existing workspace.next is reused rather than adding another unused key.

Shared-control follow-up: ui_copy.locked was retired and its consumer reuses settings.vault_locked. All24 locales have newly authored ui_copy.nav_essentials, ui_copy.nav_security, ui_copy.nav_connections, ui_copy.nav_support (native review required); Advanced reuses settings.tab_advanced. These translate the visible Settings group headings; hidden search keywords remain search metadata.

Vault recovery drill and safety notices โ€” native review required

All 24 locales (ar, bn-BD, de, en, es, fa-IR, fil-PH, fr, hi, id, it, ja, ko, ms-MY, pl-PL, pt-BR, ru, th-TH, tr, uk-UA, ur-PK, vi, zh-CN, zh-TW) have newly authored recovery_copy.drill_required, recovery_copy.drill_description, recovery_copy.new_passphrase, recovery_copy.passphrase_label, recovery_copy.creating, recovery_copy.create_bundle, recovery_copy.generated_bundle, recovery_copy.saved_label, recovery_copy.continue_restore, recovery_copy.verify_description, recovery_copy.paste_bundle, recovery_copy.verify_bundle_label, recovery_copy.verification_passphrase, recovery_copy.testing, recovery_copy.verify_finish, recovery_copy.bundle_mismatch, recovery_copy.drill_passed, recovery_copy.test_failed, recovery_copy.export_failed, recovery_copy.vault_created, recovery_copy.safety_disabled, recovery_copy.safety_paused, recovery_copy.passphrase_placeholder. Every translated range needs native review. The drill only verifies a bundle; it does not import or replace vault keys. Existing settings.copy_bundle is reused.

All 24 locales (ar, bn-BD, de, en, es, fa-IR, fil-PH, fr, hi, id, it, ja, ko, ms-MY, pl-PL, pt-BR, ru, th-TH, tr, uk-UA, ur-PK, vi, zh-CN, zh-TW) have newly authored navigation_copy.favorite_add, navigation_copy.favorite_remove, navigation_copy.favorite_added, navigation_copy.favorite_removed, navigation_copy.pin, navigation_copy.unpin, navigation_copy.unpinned, navigation_copy.public_only, navigation_copy.generating_links, navigation_copy.clipboard_error, navigation_copy.invite_copied. These translations need native review. File flags, public-channel eligibility and clipboard actions are unchanged.

File and share labels โ€” native review required

Only values still identical to English were replaced; existing translations were preserved. These labels were translated here and are not native-approved.

  • de (22): files.folder_settings, files.download_folder, files.remote_upload, files.remote_upload_url, files.switch_list, files.switch_grid, files.move_to, files.move_to_group, share.title, share.enter_password, share.expiration, share.one_hour, share.one_day, share.seven_days, share.generate_link, share.link_created, share.done, settings.api_key_configured, settings.api_key_unset, settings.refresh_links, settings.no_active_links, settings.clear_shared_files.
  • es (22): files.folder_settings, files.download_folder, files.remote_upload, files.remote_upload_url, files.switch_list, files.switch_grid, files.move_to, files.move_to_group, share.title, share.enter_password, share.expiration, share.one_hour, share.one_day, share.seven_days, share.generate_link, share.link_created, share.done, settings.api_key_configured, settings.api_key_unset, settings.refresh_links, settings.no_active_links, settings.clear_shared_files.
  • fr (21): files.folder_settings, files.download_folder, files.remote_upload, files.remote_upload_url, files.switch_list, files.switch_grid, files.move_to, files.move_to_group, share.title, share.enter_password, share.one_hour, share.one_day, share.seven_days, share.generate_link, share.link_created, share.done, settings.api_key_configured, settings.api_key_unset, settings.refresh_links, settings.no_active_links, settings.clear_shared_files.
  • ar (22): files.folder_settings, files.download_folder, files.remote_upload, files.remote_upload_url, files.switch_list, files.switch_grid, files.move_to, files.move_to_group, share.title, share.enter_password, share.expiration, share.one_hour, share.one_day, share.seven_days, share.generate_link, share.link_created, share.done, settings.api_key_configured, settings.api_key_unset, settings.refresh_links, settings.no_active_links, settings.clear_shared_files.
  • pt-BR (22): files.folder_settings, files.download_folder, files.remote_upload, files.remote_upload_url, files.switch_list, files.switch_grid, files.move_to, files.move_to_group, share.title, share.enter_password, share.expiration, share.one_hour, share.one_day, share.seven_days, share.generate_link, share.link_created, share.done, settings.api_key_configured, settings.api_key_unset, settings.refresh_links, settings.no_active_links, settings.clear_shared_files.
  • ru (22): files.folder_settings, files.download_folder, files.remote_upload, files.remote_upload_url, files.switch_list, files.switch_grid, files.move_to, files.move_to_group, share.title, share.enter_password, share.expiration, share.one_hour, share.one_day, share.seven_days, share.generate_link, share.link_created, share.done, settings.api_key_configured, settings.api_key_unset, settings.refresh_links, settings.no_active_links, settings.clear_shared_files.
  • hi (22): files.folder_settings, files.download_folder, files.remote_upload, files.remote_upload_url, files.switch_list, files.switch_grid, files.move_to, files.move_to_group, share.title, share.enter_password, share.expiration, share.one_hour, share.one_day, share.seven_days, share.generate_link, share.link_created, share.done, settings.api_key_configured, settings.api_key_unset, settings.refresh_links, settings.no_active_links, settings.clear_shared_files.
  • id (22): files.folder_settings, files.download_folder, files.remote_upload, files.remote_upload_url, files.switch_list, files.switch_grid, files.move_to, files.move_to_group, share.title, share.enter_password, share.expiration, share.one_hour, share.one_day, share.seven_days, share.generate_link, share.link_created, share.done, settings.api_key_configured, settings.api_key_unset, settings.refresh_links, settings.no_active_links, settings.clear_shared_files.
  • tr (22): files.folder_settings, files.download_folder, files.remote_upload, files.remote_upload_url, files.switch_list, files.switch_grid, files.move_to, files.move_to_group, share.title, share.enter_password, share.expiration, share.one_hour, share.one_day, share.seven_days, share.generate_link, share.link_created, share.done, settings.api_key_configured, settings.api_key_unset, settings.refresh_links, settings.no_active_links, settings.clear_shared_files.
  • ko (22): files.folder_settings, files.download_folder, files.remote_upload, files.remote_upload_url, files.switch_list, files.switch_grid, files.move_to, files.move_to_group, share.title, share.enter_password, share.expiration, share.one_hour, share.one_day, share.seven_days, share.generate_link, share.link_created, share.done, settings.api_key_configured, settings.api_key_unset, settings.refresh_links, settings.no_active_links, settings.clear_shared_files.
  • zh-CN (22): files.folder_settings, files.download_folder, files.remote_upload, files.remote_upload_url, files.switch_list, files.switch_grid, files.move_to, files.move_to_group, share.title, share.enter_password, share.expiration, share.one_hour, share.one_day, share.seven_days, share.generate_link, share.link_created, share.done, settings.api_key_configured, settings.api_key_unset, settings.refresh_links, settings.no_active_links, settings.clear_shared_files.
  • fil-PH (2): files.remote_upload, files.remote_upload_url.

Local share password page โ€” native review required

All 24 locales (ar, bn-BD, de, en, es, fa-IR, fil-PH, fr, hi, id, it, ja, ko, ms-MY, pl-PL, pt-BR, ru, th-TH, tr, uk-UA, ur-PK, vi, zh-CN, zh-TW) now contain share_page.title, share_page.heading, share_page.description, share_page.verify, share_page.incorrect. All need native review. Existing English, Spanish, Russian, Vietnamese, Bengali, Thai, Filipino and Traditional Chinese page text was preserved; the other language values were authored here. Password and filename labels reuse common.password and files.file_name.

Desktop transfer notifications โ€” native review required

All 24 locales (ar, bn-BD, de, en, es, fa-IR, fil-PH, fr, hi, id, it, ja, ko, ms-MY, pl-PL, pt-BR, ru, th-TH, tr, uk-UA, ur-PK, vi, zh-CN, zh-TW) have newly authored native_notifications.title_completed, native_notifications.title_failed, native_notifications.title_paused, native_notifications.title_attention, native_notifications.many_completed, native_notifications.many_failed, native_notifications.many_paused, native_notifications.many_attention, native_notifications.name_completed, native_notifications.name_failed, native_notifications.name_paused, native_notifications.upload_completed, native_notifications.download_completed, native_notifications.failed, native_notifications.paused, native_notifications.unlock, native_notifications.network, native_notifications.telegram, native_notifications.attention, native_notifications.unnamed_file. Every translated range needs native review. Aggregate sentences use noun labels followed by counts to avoid English-only plural rules. Filename privacy, transition categories, receipts and delays remain protected. Serialized native subset bytes are reported separately; every value still ships in the frontend catalogs and counts toward locale budgets.

Desktop tray โ€” native review required

All 24 locales (ar, bn-BD, de, en, es, fa-IR, fil-PH, fr, hi, id, it, ja, ko, ms-MY, pl-PL, pt-BR, ru, th-TH, tr, uk-UA, ur-PK, vi, zh-CN, zh-TW) have newly authored native_tray.pause_all, native_tray.quit, native_tray.active, native_tray.paused, native_tray.attention, native_tray.failed, native_tray.current. All need native review. Open/Transfers/Resume labels reuse common.action_name, files.open, activity.resume, common.app_title and common.transfers; label-template grammar also needs native review. Counters use noun labels where needed, avoiding language-specific plural inflection.

Authentication catalog โ€” native review required

Only values still identical to English were replaced; existing translations were preserved. These labels were translated here and are not native-approved.

  • de (29): auth.desktop_required, auth.desktop_required_desc, auth.open_window_prompt, auth.too_many_requests, auth.flood_wait_msg, auth.please_wait, auth.timer_reset_warning, auth.api_id, auth.api_hash, auth.configure, auth.how_to_get_credentials, auth.dev_mode, auth.phone_number, auth.qr_code, auth.continue, auth.back_to_config, auth.scan_qr, auth.waiting_for_scan, auth.refresh_qr, auth.telegram_code, auth.change_phone, auth.two_factor_enabled, auth.cloud_password, auth.password_placeholder, auth.back_to_code, auth.donate, auth.getting_started, auth.close_help, auth.privacy_note.
  • es (2): auth.api_id, auth.api_hash.
  • fr (29): auth.desktop_required, auth.desktop_required_desc, auth.open_window_prompt, auth.too_many_requests, auth.flood_wait_msg, auth.please_wait, auth.timer_reset_warning, auth.api_id, auth.api_hash, auth.configure, auth.how_to_get_credentials, auth.dev_mode, auth.phone_number, auth.qr_code, auth.continue, auth.back_to_config, auth.scan_qr, auth.waiting_for_scan, auth.refresh_qr, auth.telegram_code, auth.change_phone, auth.two_factor_enabled, auth.cloud_password, auth.password_placeholder, auth.back_to_code, auth.donate, auth.getting_started, auth.close_help, auth.privacy_note.
  • ar (29): auth.desktop_required, auth.desktop_required_desc, auth.open_window_prompt, auth.too_many_requests, auth.flood_wait_msg, auth.please_wait, auth.timer_reset_warning, auth.api_id, auth.api_hash, auth.configure, auth.how_to_get_credentials, auth.dev_mode, auth.phone_number, auth.qr_code, auth.continue, auth.back_to_config, auth.scan_qr, auth.waiting_for_scan, auth.refresh_qr, auth.telegram_code, auth.change_phone, auth.two_factor_enabled, auth.cloud_password, auth.password_placeholder, auth.back_to_code, auth.donate, auth.getting_started, auth.close_help, auth.privacy_note.
  • pt-BR (29): auth.desktop_required, auth.desktop_required_desc, auth.open_window_prompt, auth.too_many_requests, auth.flood_wait_msg, auth.please_wait, auth.timer_reset_warning, auth.api_id, auth.api_hash, auth.configure, auth.how_to_get_credentials, auth.dev_mode, auth.phone_number, auth.qr_code, auth.continue, auth.back_to_config, auth.scan_qr, auth.waiting_for_scan, auth.refresh_qr, auth.telegram_code, auth.change_phone, auth.two_factor_enabled, auth.cloud_password, auth.password_placeholder, auth.back_to_code, auth.donate, auth.getting_started, auth.close_help, auth.privacy_note.
  • ru (2): auth.api_id, auth.api_hash.
  • hi (29): auth.desktop_required, auth.desktop_required_desc, auth.open_window_prompt, auth.too_many_requests, auth.flood_wait_msg, auth.please_wait, auth.timer_reset_warning, auth.api_id, auth.api_hash, auth.configure, auth.how_to_get_credentials, auth.dev_mode, auth.phone_number, auth.qr_code, auth.continue, auth.back_to_config, auth.scan_qr, auth.waiting_for_scan, auth.refresh_qr, auth.telegram_code, auth.change_phone, auth.two_factor_enabled, auth.cloud_password, auth.password_placeholder, auth.back_to_code, auth.donate, auth.getting_started, auth.close_help, auth.privacy_note.
  • id (29): auth.desktop_required, auth.desktop_required_desc, auth.open_window_prompt, auth.too_many_requests, auth.flood_wait_msg, auth.please_wait, auth.timer_reset_warning, auth.api_id, auth.api_hash, auth.configure, auth.how_to_get_credentials, auth.dev_mode, auth.phone_number, auth.qr_code, auth.continue, auth.back_to_config, auth.scan_qr, auth.waiting_for_scan, auth.refresh_qr, auth.telegram_code, auth.change_phone, auth.two_factor_enabled, auth.cloud_password, auth.password_placeholder, auth.back_to_code, auth.donate, auth.getting_started, auth.close_help, auth.privacy_note.
  • tr (29): auth.desktop_required, auth.desktop_required_desc, auth.open_window_prompt, auth.too_many_requests, auth.flood_wait_msg, auth.please_wait, auth.timer_reset_warning, auth.api_id, auth.api_hash, auth.configure, auth.how_to_get_credentials, auth.dev_mode, auth.phone_number, auth.qr_code, auth.continue, auth.back_to_config, auth.scan_qr, auth.waiting_for_scan, auth.refresh_qr, auth.telegram_code, auth.change_phone, auth.two_factor_enabled, auth.cloud_password, auth.password_placeholder, auth.back_to_code, auth.donate, auth.getting_started, auth.close_help, auth.privacy_note.
  • ko (28): auth.desktop_required, auth.desktop_required_desc, auth.open_window_prompt, auth.too_many_requests, auth.flood_wait_msg, auth.please_wait, auth.timer_reset_warning, auth.api_hash, auth.configure, auth.how_to_get_credentials, auth.dev_mode, auth.phone_number, auth.qr_code, auth.continue, auth.back_to_config, auth.scan_qr, auth.waiting_for_scan, auth.refresh_qr, auth.telegram_code, auth.change_phone, auth.two_factor_enabled, auth.cloud_password, auth.password_placeholder, auth.back_to_code, auth.donate, auth.getting_started, auth.close_help, auth.privacy_note.
  • zh-CN (28): auth.desktop_required, auth.desktop_required_desc, auth.open_window_prompt, auth.too_many_requests, auth.flood_wait_msg, auth.please_wait, auth.timer_reset_warning, auth.api_hash, auth.configure, auth.how_to_get_credentials, auth.dev_mode, auth.phone_number, auth.qr_code, auth.continue, auth.back_to_config, auth.scan_qr, auth.waiting_for_scan, auth.refresh_qr, auth.telegram_code, auth.change_phone, auth.two_factor_enabled, auth.cloud_password, auth.password_placeholder, auth.back_to_code, auth.donate, auth.getting_started, auth.close_help, auth.privacy_note.
  • fil-PH (5): auth.api_hash, auth.dev_mode, auth.qr_code, auth.telegram_code, auth.cloud_password.

File protection explanation โ€” native review required

All 24 locales (ar, bn-BD, de, en, es, fa-IR, fil-PH, fr, hi, id, it, ja, ko, ms-MY, pl-PL, pt-BR, ru, th-TH, tr, uk-UA, ur-PK, vi, zh-CN, zh-TW) have newly authored protection_copy.why, protection_copy.how, protection_copy.close, protection_copy.current, protection_copy.locked, protection_copy.corrupt, protection_copy.unlocked, protection_copy.before_upload, protection_copy.integrity, protection_copy.limitations, protection_copy.recovery_warning. Every translated range needs native review. The original safety statements and key-loss limitations are preserved.

Local access explanation โ€” native review required

All 24 locales (ar, bn-BD, de, en, es, fa-IR, fil-PH, fr, hi, id, it, ja, ko, ms-MY, pl-PL, pt-BR, ru, th-TH, tr, uk-UA, ur-PK, vi, zh-CN, zh-TW) have newly authored access_copy.webdav_title, access_copy.rest_title, access_copy.close, access_copy.server_scope, access_copy.webdav_token, access_copy.rest_key, access_copy.webdav_changes, access_copy.rest_changes, access_copy.protection_label, access_copy.protection_warning, access_copy.webdav_open, access_copy.rest_open. Every translated range needs native review. Device/port scope, capability credentials, revocation, read-only operations and fail-closed encryption limitations retain their meaning.

Additional verified retirement and exact canonical reuse

Retired in all24 catalogs after TypeScript literal/dynamic-prefix analysis and frontend/native/build/public/local-source inspection (no local Java/Kotlin consumers present in this worktree): settings.encryption_capabilities, settings.core_available, settings.vault_exists, files.select_all, share.title, share.done, auth.configure, sync.error.mass_deletion, workspace.completed, workspace.in_progress, workspace.restart, workspace.mark_finished. Native/Android families remain preserved. These are no longer translated ranges requiring review.

All24 values were byte-identical for each consolidated pair; callers now use the retained key, with unchanged interpolation and displayed text:

  • settings.connection_diagnostics โ†’ common.diagnostics.
  • settings.theme_name โ†’ common.name.
  • settings.offline_cache โ†’ common.offline_files.
  • settings.webdav_running โ†’ settings.api_running.
  • settings.proxy_status_checking โ†’ settings.checking.
  • settings.diagnostics_copy_failed โ†’ settings.failed_prefix.
  • syncPreview.uploads โ†’ activity.uploads.
  • syncPreview.downloads โ†’ activity.downloads.
  • storage.title โ†’ workspace.tabs.storage.

Upload storage choice โ€” native review required

All 24 locales (ar, bn-BD, de, en, es, fa-IR, fil-PH, fr, hi, id, it, ja, ko, ms-MY, pl-PL, pt-BR, ru, th-TH, tr, uk-UA, ur-PK, vi, zh-CN, zh-TW) have newly authored upload_choice_copy.question, upload_choice_copy.description, upload_choice_copy.store, upload_choice_copy.plain_description, upload_choice_copy.protect, upload_choice_copy.protect_description. Every translated range needs native review. The heading uses the explicit selected-file count for all languages; normal upload and configured pre-upload encryption remain the two choices.

Historical authentication capacity draft โ€” native review required

Only en and bn-BD have a review draft in localization-auth-capacity-draft.json; it is not a shipping resource, and the other 22 locale values are not yet authored. The bn-BD values for proposed auth_copy.qr_title, auth_copy.qr_description, auth_copy.advanced, auth_copy.continue_phone, auth_copy.continue_qr, auth_copy.qr_path, auth_copy.help_intro, auth_copy.portal_heading, auth_copy.portal_instruction, auth_copy.create_heading, auth_copy.create_instruction, auth_copy.copy_heading, and auth_copy.copy_instruction require native review. See LOCALIZATION_BUDGET_REVIEW.md for the measured owner decision.

TV sponsor offer label correction โ€” native review required

ads.view_offer was authored in all 24 locales: ar, bn-BD, de, en, es, fa-IR, fil-PH, fr, hi, id, it, ja, ko, ms-MY, pl-PL, pt-BR, ru, th-TH, tr, uk-UA, ur-PK, vi, zh-CN, zh-TW. These translations need native review. It restores โ€œView offerโ€; the sign-in gateway browser/once-only explanation is no longer reused on the TV banner. No supporter promise or sponsor destination changes.

Release correction C9: reused-copy context audit

The release review checked the existing English meaning at each of the 194 file/key pairs below, including pairs moved by other UI changes. Controls still describe their actions; generic failure messages still describe a failed operation; supporter price, lifetime rights, device allowance, recovery and refund terms retain their established meaning. Plural labels, status text, media controls and encryption prompts were checked in their current render or callback context. Native translation and grammar review remains UNRUN.

The Google TV offer was the identified meaning regression. It now uses the new ads.view_offer key rather than the sign-in gateway sentence. The desktop sponsor fallback's ads.browser_note and generic failure text already existed at HEAD and were not introduced by P2-08; they remain part of the real-WebView acceptance review. No other incorrect literal-to-existing-key substitution was found in this audit.

Consumer Existing keys checked
app/src/components/desktop/DesktopDashboard.tsx common.pinned, workspace.error_operation, settings.offline, files.share_link, settings.done
app/src/components/desktop/dashboard/AdaptiveMediaPlayer.tsx workspace.exit_fullscreen, playback.speed, settings.unlimited, settings.original, settings.clearing, workspace.fullscreen
app/src/components/desktop/dashboard/CreateFolderDialog.tsx common.create_folder
app/src/components/desktop/dashboard/DesktopAdBanner.tsx common.loading
app/src/components/desktop/dashboard/DriveConceptTour.tsx workspace.next
app/src/components/desktop/dashboard/FileCard.tsx files.preview, files.download, files.share, files.delete
app/src/components/desktop/dashboard/MediaPlayer.tsx workspace.exit_fullscreen, workspace.fullscreen
app/src/components/desktop/dashboard/PdfViewer.tsx common.operation_failed, common.zoom_out_shortcut, common.zoom_out, common.zoom_in_shortcut, common.zoom_in
app/src/components/desktop/dashboard/SettingsModal.tsx settings.tab_advanced, common.port, common.offline_files, settings.proxy_status_off, settings.off, settings.checking, settings.proxy_status_connected, settings.proxy_status_unreachable, settings.live_state, settings.live_state_desc, settings.http_bridge_desc, settings.proxy_test_success, settings.proxy_test_failed, settings.proxy_testing, settings.test_connection, settings.offline, settings.api_running, settings.failed_prefix
app/src/components/desktop/dashboard/ShareDialog.tsx settings.rest_api, settings.tab_advanced
app/src/components/desktop/dashboard/Sidebar.tsx common.app_title, common.expand_sidebar, common.collapse_sidebar, common.groups, common.show_groups, common.hide_groups, common.create_group, common.cancel, common.save, common.all, common.unassigned, workspace.scan
app/src/components/desktop/dashboard/SidebarItem.tsx files.move_to_group, common.unassigned
app/src/components/desktop/dashboard/ThemesTab.tsx common.name
app/src/components/desktop/dashboard/TopBar.tsx workspace.types.all, workspace.types.image, workspace.types.video, workspace.types.audio, workspace.types.document, workspace.types.archive, workspace.types.other, workspace.sizes.any, workspace.sizes.small, workspace.sizes.medium, workspace.sizes.large, workspace.dates.any, workspace.dates.7d, workspace.dates.30d, workspace.dates.1y, common.all, settings.protected, settings.offline
app/src/components/desktop/dashboard/TransferCenter.tsx activity.title, common.transfers, activity.uploads, common.retry, activity.downloads
app/src/components/desktop/dashboard/settings/SettingsTabs.tsx settings.tab_advanced, common.app_title, settings.tagline
app/src/components/desktop/sync/SyncPlanPreview.tsx activity.uploads, activity.downloads
app/src/components/dev/DesignGallery.tsx common.offline_files
app/src/components/mobile/MobileDashboard.tsx settings.failed_prefix, notifications.telegram_link_copied, notifications.copy_link_failed, common.app_title, playback.title, common.transfers, activity.pause, activity.resume, settings.clear, common.cancel, common.retry, supporter_license.title, supporter_license.mobile_description, common.diagnostics, common.offline_files, playback.speed_label, files.folder_name, common.create_folder, settings.proxy_status_connected, settings.offline, files.share_link, settings.done
app/src/components/mobile/MobileSupporterCard.tsx supporter_license.purchase_restored, supporter_license.mobile_title, supporter_license.mobile_description, supporter_license.checking, supporter_license.active, supporter_license.inactive, supporter_license.android_updates_preserved, supporter_offer.price_suffix, supporter_license.save_recovery, supporter_license.recovery_storage_android, supporter_license.waiting_payment, supporter_license.waiting_payment_android, supporter_license.purchase_info, supporter_license.purchase_policy_mobile, supporter_license.preparing_checkout, supporter_license.checkout_opened, supporter_license.purchase_action, supporter_license.check_payment, supporter_license.verification_refreshed, supporter_license.refresh_verification, supporter_license.terms_action, supporter_license.restore_heading_mobile, supporter_license.restore_description_mobile, supporter_license.recovery_code_label, supporter_license.restore_action_mobile, supporter_license.help_action
app/src/components/mobile/TouchFileList.tsx common.sync, files.items_selected, files.clear_selection, files.download, files.move, files.share, files.no_other_folders
app/src/components/shared/AdsterraBanner.tsx ads.sponsored
app/src/components/shared/AuthWizard.tsx common.switch_light, common.switch_dark, common.app_title
app/src/components/shared/ConfirmationDialogs.tsx settings.min_passphrase_length, settings.passphrases_no_match, settings.confirm_passphrase, common.cancel, common.confirm
app/src/components/shared/EncryptionSettingsSection.tsx settings.copy_bundle, settings.min_passphrase_length, settings.passphrases_no_match, settings.import_recovery_bundle, settings.import_recovery_confirmation, settings.import, settings.paste_bundle, settings.recovery_passphrase, settings.new_vault_passphrase, settings.confirm_passphrase, settings.vault_locked, settings.default_upload_protection, settings.protect_metadata, settings.auto_lock_vault, settings.lock_on_sleep, settings.temp_plaintext_policy
app/src/components/shared/WhatsNewDialog.tsx common.close, auth.continue
app/src/components/shared/auth/AuthSteps.tsx auth.verifying
app/src/components/workspace/ActivityPanel.tsx settings.encryption_mode_passphrase
app/src/components/workspace/StoragePanel.tsx workspace.tabs.storage, storage.description, storage.refresh
app/src/components/workspace/WorkspaceHub.tsx common.all, settings.protected, workspace.error_operation, settings.offline, workspace.prepare_offline, workspace.choose_collection, workspace.add_to_collection, workspace.remove_membership
app/src/hooks/useFileDownload.ts settings.encryption_mode_passphrase, settings.vault_is_locked, files.download
app/src/hooks/useFileOperations.ts files.delete
app/src/hooks/useFileUpload.ts settings.encryption_disclaimer_title, settings.encryption_disclaimer_body, settings.encryption_mode_passphrase, settings.min_passphrase_length
app/src/hooks/useTelegramConnection.ts files.delete, files.make_private

Encryption beta: current passphrase

settings.current_vault_passphrase has a proper current-vault-passphrase label in all 24 canonical locales. The packed dry-run adds 62 bytes to Bengali (124,881/125,000) and 1,016 bytes in total (1,734,675/1,800,000), with no ceiling increase. Native linguistic and device review remains UNRUN for every translation. The field is masked and uses the current-password autocomplete role; it is distinct from the replacement and confirmation fields.

The storage-insight partial indicator reuses workspace.search_partial: its count is the retained generation-backed index count, so "indexed results ยท partial inventory" describes this source accurately. The existing key is present in all 24 catalogs; no new locale bytes were added for this indicator. Native-language review remains UNRUN.

Part 4 follow-up โ€” all native review UNRUN

The original capacity draft is historical evidence. Its authentication strings now ship in all 24 canonical catalogs. This pass adds 128 keys per catalog, translates the remaining copied English in the eleven target locales (ar, de, es, fr, hi, id, ko, pt-BR, ru, tr, zh-CN), and includes 16 formerly exempt Folder Sync prose keys per target locale. Brands, protocols, physical shortcut bindings, stored theme identifiers and owner-entered theme names retain their meaning and identity. French settings.public is corrected to โ€œAccรจs publicโ€. No language has native, legal-copy or full-device acceptance.

The protected price remains $5.00 USD once for lifetime ad-free access, with three devices, recovery and offline grace. This pass translates presentation and recovery examples; it does not change entitlement or payment behavior.

Every key below was added in every catalog and requires context and linguistic review:

  • auth_copy.qr_title
  • auth_copy.qr_description
  • auth_copy.advanced
  • auth_copy.continue_phone
  • auth_copy.continue_qr
  • auth_copy.qr_path
  • auth_copy.help_intro
  • auth_copy.portal_heading
  • auth_copy.portal_instruction
  • auth_copy.create_heading
  • auth_copy.create_instruction
  • auth_copy.copy_heading
  • auth_copy.copy_instruction
  • auth_copy.hash_example
  • auth_copy.open_portal
  • auth_copy.privacy
  • auth_copy.connecting
  • auth_copy.unlock
  • protection_labels.decrypted
  • protection_labels.encrypted
  • protection_labels.key_missing
  • protection_labels.newer_version
  • protection_labels.corrupt
  • protection_labels.verifying
  • protection_labels.learn
  • protection_labels.explain
  • supporter_license.recovery_example
  • drive_intro.drive_title
  • drive_intro.drive_body
  • drive_intro.folders_title
  • drive_intro.folders_body
  • drive_intro.protection_title
  • drive_intro.protection_body
  • drive_intro.progress
  • drive_intro.skip
  • drive_intro.progress_label
  • drive_intro.help
  • help_topics.storage_question
  • help_topics.storage_answer
  • help_topics.limits_question
  • help_topics.limits_answer
  • help_topics.protection_question
  • help_topics.protection_answer
  • help_topics.sharing_question
  • help_topics.sharing_answer
  • help_topics.guest_question
  • help_topics.guest_answer
  • help_topics.more
  • help_topics.support
  • shortcut_labels.search
  • shortcut_labels.select_all
  • shortcut_labels.open
  • shortcut_labels.rename
  • shortcut_labels.download
  • shortcut_labels.share
  • shortcut_labels.delete
  • shortcut_labels.close
  • shortcut_labels.show
  • privacy_destinations.device_title
  • privacy_destinations.device_body
  • privacy_destinations.telegram_body
  • privacy_destinations.sponsors_title
  • privacy_destinations.sponsors_body
  • privacy_destinations.crash_title
  • privacy_destinations.crash_body
  • theme_names.default_dark
  • theme_names.charcoal
  • theme_names.cyber_teal
  • theme_names.default_light
  • theme_names.ocean
  • theme_names.forest
  • theme_names.plum
  • theme_names.paper
  • theme_names.rose
  • theme_names.mint
  • theme_names.sky
  • common.browser_picker
  • auth_copy.id_number
  • protection_labels.contract_error
  • protection_labels.settings_rejected
  • auth_copy.no_spaces
  • auth_copy.credentials_required
  • protection_labels.auth_export
  • protection_labels.auth_check
  • protection_labels.auth_import
  • protection_labels.auth_change
  • ads.thanks
  • common.system
  • advanced_copy.rest_description
  • advanced_copy.webdav_description
  • advanced_copy.proxy_description
  • advanced_copy.vpn_title
  • advanced_copy.vpn_description
  • settings_sync_copy.replace_title
  • settings_sync_copy.replace_description
  • settings_sync_copy.replace
  • settings_sync_copy.uploaded
  • settings_sync_copy.apply_title
  • settings_sync_copy.apply_description
  • settings_sync_copy.apply
  • settings_sync_copy.downloaded
  • settings_sync_copy.title
  • settings_sync_copy.description
  • settings_sync_copy.enable
  • settings_sync_copy.warning
  • settings_sync_copy.exclusions
  • settings_sync_copy.passphrase
  • settings_sync_copy.placeholder
  • settings_sync_copy.upload
  • settings_sync_copy.download
  • settings_sync_copy.refresh
  • settings_sync_copy.latest
  • settings_sync_copy.this_device
  • settings_sync_copy.other_device
  • settings_sync_copy.none
  • protection_labels.provide_credentials
  • common.download_destination
  • common.download_folder_to
  • common.upload_folder_picker
  • common.show_in_folder
  • common.webdav_settings
  • viewer.stream_failed
  • viewer.pdf_document_failed
  • viewer.pdf_native_failed
  • viewer.pdf_path_failed
  • viewer.pdf_load_failed
  • viewer.image_render_failed
  • viewer.unmute
Locale Native review Encoded catalog bytes
en UNRUN 53,195
es UNRUN 65,778
ru UNRUN 106,017
uk-UA UNRUN 107,665
pl-PL UNRUN 64,691
fa-IR UNRUN 93,559
ur-PK UNRUN 93,055
ms-MY UNRUN 60,091
zh-CN UNRUN 50,850
zh-TW UNRUN 51,582
fr UNRUN 69,703
it UNRUN 64,302
ar UNRUN 86,762
pt-BR UNRUN 64,527
de UNRUN 66,176
hi UNRUN 132,548
bn-BD UNRUN 138,790
id UNRUN 58,144
fil-PH UNRUN 66,529
tr UNRUN 62,879
th-TH UNRUN 136,703
ja UNRUN 78,381
ko UNRUN 66,897
vi UNRUN 73,073

Existing keys whose values changed in this pass also require review:

  • es (113): settings.tab_sync, settings.sync.title, settings.sync.toggle, settings.sync.select_folder, settings.sync.remove, settings.sync.add_folder, settings.sync.select_channel, settings.sync.no_channels, settings.tab_general, settings.max_uploads_desc, settings.max_downloads_desc, settings.zip_folders_desc, settings.performance_mode_desc, settings.app_language, settings.choose_language, settings.api_stopped, settings.api_copy_alert, settings.transcode_cache_desc, settings.proxy_config, settings.enable_proxy_desc, settings.socks5_desc, settings.host_desc, settings.proxy_reconnect_note, settings.vpn_optimizer, settings.vpn_mode, settings.vpn_mode_desc, settings.timeout_multiplier, settings.timeout_multiplier_desc, settings.retry_attempts, settings.retry_attempts_desc, settings.retry_backoff, settings.preferred_dc, settings.preferred_dc_desc, settings.dc_fallback_attempts, settings.dc_fallback_desc, settings.respect_flood, settings.respect_flood_desc, settings.bandwidth_throttle, settings.download_limit, settings.transfer_chunk_size, settings.chunk_size_desc, settings.keep_alive, settings.keep_alive_desc, settings.bulk_archive_limit, settings.bulk_archive_desc, settings.auto_detect_vpn, settings.vpn_detected, settings.no_vpn_detected, settings.shared_links, settings.ip_override, settings.ip_override_desc, settings.no_active_links_desc, settings.expires_at, settings.clear_local_cache, settings.clear_local_cache_desc, settings.clear_cache_title, settings.clear_cache_desc, settings.cache_cleared, settings.cache_clear_failed, settings.transcode_cache, settings.clear_transcode_title, settings.clear_transcode_message, settings.failed_prefix, settings.clear_variants_for, settings.original, settings.no_transcoded_cached, settings.check_for_updates, settings.check_updates_desc, settings.update_restart, settings.update_available_toast, settings.latest_version_toast, settings.update_prod_only_toast, settings.update_check_failed_toast, settings.update_failed_toast, settings.load_shares_failed, settings.revoke_link_title, settings.revoke_link_desc, settings.link_revoked, settings.link_revoke_failed, settings.port_range_error, settings.api_server_started, settings.api_server_stopped, settings.api_update_failed, settings.api_port_updated, settings.api_port_update_failed, settings.generate_api_key_title, settings.regenerate_api_key_desc, settings.generate_api_key_desc, settings.api_key_generated, settings.api_key_generate_failed, settings.copy_clipboard_failed, settings.restart_app_toast, settings.reconnect_success_toast, settings.reconnect_failed_toast, settings.reconnect_failed_err_toast, settings.diagnostics_copied, settings.shared_files, settings.select_app_language, settings.socks5_desc_mobile, settings.http_bridge_desc, settings.proxy_test_success, settings.proxy_test_failed, settings.live_state, settings.live_state_desc, settings.base_mode, sync.status.disabled, sync.status.syncing, sync.status.synced, sync.status.conflicts, sync.conflict.title, sync.conflict.keep_local, sync.conflict.keep_remote, sync.conflict.keep_both.
  • ru (110): settings.tab_sync, settings.sync.title, settings.sync.toggle, settings.sync.select_folder, settings.sync.remove, settings.sync.add_folder, settings.sync.select_channel, settings.sync.no_channels, settings.max_uploads_desc, settings.max_downloads_desc, settings.zip_folders_desc, settings.performance_mode_desc, settings.app_language, settings.choose_language, settings.api_stopped, settings.api_copy_alert, settings.transcode_cache_desc, settings.proxy_config, settings.enable_proxy_desc, settings.socks5_desc, settings.host_desc, settings.proxy_reconnect_note, settings.vpn_optimizer, settings.vpn_mode, settings.vpn_mode_desc, settings.timeout_multiplier, settings.timeout_multiplier_desc, settings.retry_attempts, settings.retry_attempts_desc, settings.retry_backoff, settings.preferred_dc, settings.preferred_dc_desc, settings.dc_fallback_attempts, settings.dc_fallback_desc, settings.respect_flood, settings.respect_flood_desc, settings.bandwidth_throttle, settings.download_limit, settings.transfer_chunk_size, settings.chunk_size_desc, settings.keep_alive, settings.keep_alive_desc, settings.bulk_archive_limit, settings.bulk_archive_desc, settings.auto_detect_vpn, settings.vpn_detected, settings.no_vpn_detected, settings.shared_links, settings.ip_override, settings.ip_override_desc, settings.no_active_links_desc, settings.expires_at, settings.clear_local_cache, settings.clear_local_cache_desc, settings.clear_cache_title, settings.clear_cache_desc, settings.cache_cleared, settings.cache_clear_failed, settings.transcode_cache, settings.clear_transcode_title, settings.clear_transcode_message, settings.failed_prefix, settings.clear_variants_for, settings.no_transcoded_cached, settings.check_for_updates, settings.check_updates_desc, settings.update_restart, settings.update_available_toast, settings.latest_version_toast, settings.update_prod_only_toast, settings.update_check_failed_toast, settings.update_failed_toast, settings.load_shares_failed, settings.revoke_link_title, settings.revoke_link_desc, settings.link_revoked, settings.link_revoke_failed, settings.port_range_error, settings.api_server_started, settings.api_server_stopped, settings.api_update_failed, settings.api_port_updated, settings.api_port_update_failed, settings.generate_api_key_title, settings.regenerate_api_key_desc, settings.generate_api_key_desc, settings.api_key_generated, settings.api_key_generate_failed, settings.copy_clipboard_failed, settings.restart_app_toast, settings.reconnect_success_toast, settings.reconnect_failed_toast, settings.reconnect_failed_err_toast, settings.diagnostics_copied, settings.shared_files, settings.select_app_language, settings.socks5_desc_mobile, settings.http_bridge_desc, settings.proxy_test_success, settings.proxy_test_failed, settings.live_state, settings.live_state_desc, sync.status.disabled, sync.status.syncing, sync.status.synced, sync.status.conflicts, sync.conflict.title, sync.conflict.keep_local, sync.conflict.keep_remote, sync.conflict.keep_both.
  • zh-CN (115): settings.tab_sync, settings.sync.title, settings.sync.toggle, settings.sync.select_folder, settings.sync.remove, settings.sync.add_folder, settings.sync.select_channel, settings.sync.no_channels, settings.max_uploads_desc, settings.max_downloads_desc, settings.zip_folders_desc, settings.performance_mode_desc, settings.app_language, settings.choose_language, settings.api_stopped, settings.api_copy_alert, settings.transcode_cache_desc, settings.proxy_config, settings.enable_proxy_desc, settings.socks5_desc, settings.host_desc, settings.proxy_reconnect_note, settings.vpn_optimizer, settings.vpn_mode, settings.vpn_mode_desc, settings.timeout_multiplier, settings.timeout_multiplier_desc, settings.retry_attempts, settings.retry_attempts_desc, settings.retry_backoff, settings.preferred_dc, settings.preferred_dc_desc, settings.dc_fallback_attempts, settings.dc_fallback_desc, settings.respect_flood, settings.respect_flood_desc, settings.bandwidth_throttle, settings.download_limit, settings.transfer_chunk_size, settings.chunk_size_desc, settings.keep_alive, settings.keep_alive_desc, settings.bulk_archive_limit, settings.bulk_archive_desc, settings.auto_detect_vpn, settings.vpn_detected, settings.no_vpn_detected, settings.shared_links, settings.ip_override, settings.ip_override_desc, settings.no_active_links_desc, settings.expires_at, settings.clear_local_cache, settings.clear_local_cache_desc, settings.clear_cache_title, settings.clear_cache_desc, settings.cache_cleared, settings.cache_clear_failed, settings.transcode_cache, settings.clear_transcode_title, settings.clear_transcode_message, settings.failed_prefix, settings.clear_variants_for, settings.no_transcoded_cached, settings.check_for_updates, settings.check_updates_desc, settings.update_restart, settings.update_available_toast, settings.latest_version_toast, settings.update_prod_only_toast, settings.update_check_failed_toast, settings.update_failed_toast, settings.load_shares_failed, settings.revoke_link_title, settings.revoke_link_desc, settings.link_revoked, settings.link_revoke_failed, settings.port_range_error, settings.api_server_started, settings.api_server_stopped, settings.api_update_failed, settings.api_port_updated, settings.api_port_update_failed, settings.generate_api_key_title, settings.regenerate_api_key_desc, settings.generate_api_key_desc, settings.api_key_generated, settings.api_key_generate_failed, settings.copy_clipboard_failed, settings.restart_app_toast, settings.reconnect_success_toast, settings.reconnect_failed_toast, settings.reconnect_failed_err_toast, settings.diagnostics_copied, settings.shared_files, settings.select_app_language, settings.socks5_desc_mobile, settings.http_bridge_desc, settings.proxy_test_success, settings.proxy_test_failed, settings.live_state, settings.live_state_desc, sync.status.disabled, sync.status.syncing, sync.status.synced, sync.status.conflicts, sync.conflict.title, sync.conflict.keep_local, sync.conflict.keep_remote, sync.conflict.keep_both, ads.sponsored, ads.sponsor_message, ads.continue_to_files, ads.browser_note, ads.close_ad.
  • fr (123): common.date, settings.tab_sync, settings.sync.title, settings.sync.toggle, settings.sync.select_folder, settings.sync.remove, settings.sync.add_folder, settings.sync.select_channel, settings.sync.no_channels, settings.max_uploads_desc, settings.max_downloads_desc, settings.zip_folders_desc, settings.performance_mode_desc, settings.app_language, settings.choose_language, settings.api_stopped, settings.api_copy_alert, settings.transcode_cache_desc, settings.proxy_config, settings.enable_proxy_desc, settings.socks5_desc, settings.host_desc, settings.proxy_reconnect_note, settings.vpn_optimizer, settings.vpn_mode, settings.vpn_mode_desc, settings.timeout_multiplier, settings.timeout_multiplier_desc, settings.retry_attempts, settings.retry_attempts_desc, settings.retry_backoff, settings.preferred_dc, settings.preferred_dc_desc, settings.dc_fallback_attempts, settings.dc_fallback_desc, settings.respect_flood, settings.respect_flood_desc, settings.bandwidth_throttle, settings.download_limit, settings.transfer_chunk_size, settings.chunk_size_desc, settings.keep_alive, settings.keep_alive_desc, settings.bulk_archive_limit, settings.bulk_archive_desc, settings.auto_detect_vpn, settings.vpn_detected, settings.no_vpn_detected, settings.shared_links, settings.ip_override, settings.ip_override_desc, settings.no_active_links_desc, settings.public, settings.expires_at, settings.clear_local_cache, settings.clear_local_cache_desc, settings.clear_cache_title, settings.clear_cache_desc, settings.cache_cleared, settings.cache_clear_failed, settings.transcode_cache, settings.clear_transcode_title, settings.clear_transcode_message, settings.failed_prefix, settings.clear_variants_for, settings.original, settings.no_transcoded_cached, settings.check_for_updates, settings.check_updates_desc, settings.update_restart, settings.update_available_toast, settings.latest_version_toast, settings.update_prod_only_toast, settings.update_check_failed_toast, settings.update_failed_toast, settings.load_shares_failed, settings.revoke_link_title, settings.revoke_link_desc, settings.link_revoked, settings.link_revoke_failed, settings.port_range_error, settings.api_server_started, settings.api_server_stopped, settings.api_update_failed, settings.api_port_updated, settings.api_port_update_failed, settings.generate_api_key_title, settings.regenerate_api_key_desc, settings.generate_api_key_desc, settings.api_key_generated, settings.api_key_generate_failed, settings.copy_clipboard_failed, settings.restart_app_toast, settings.reconnect_success_toast, settings.reconnect_failed_toast, settings.reconnect_failed_err_toast, settings.diagnostics_copied, settings.excellent, settings.shared_files, settings.select_app_language, settings.socks5_desc_mobile, settings.http_bridge_desc, settings.proxy_test_success, settings.proxy_test_failed, settings.live_state, settings.live_state_desc, settings.base_mode, settings.color_surface, share.expiration, sync.status.disabled, sync.status.syncing, sync.status.synced, sync.status.conflicts, sync.conflict.title, sync.conflict.keep_local, sync.conflict.keep_remote, sync.conflict.keep_both, ads.sponsored, ads.sponsor_message, ads.continue_to_files, ads.browser_note, ads.close_ad, workspace.protection.
  • ar (115): settings.tab_sync, settings.sync.title, settings.sync.toggle, settings.sync.select_folder, settings.sync.remove, settings.sync.add_folder, settings.sync.select_channel, settings.sync.no_channels, settings.max_uploads_desc, settings.max_downloads_desc, settings.zip_folders_desc, settings.performance_mode_desc, settings.app_language, settings.choose_language, settings.api_stopped, settings.api_copy_alert, settings.transcode_cache_desc, settings.proxy_config, settings.enable_proxy_desc, settings.socks5_desc, settings.host_desc, settings.proxy_reconnect_note, settings.vpn_optimizer, settings.vpn_mode, settings.vpn_mode_desc, settings.timeout_multiplier, settings.timeout_multiplier_desc, settings.retry_attempts, settings.retry_attempts_desc, settings.retry_backoff, settings.preferred_dc, settings.preferred_dc_desc, settings.dc_fallback_attempts, settings.dc_fallback_desc, settings.respect_flood, settings.respect_flood_desc, settings.bandwidth_throttle, settings.download_limit, settings.transfer_chunk_size, settings.chunk_size_desc, settings.keep_alive, settings.keep_alive_desc, settings.bulk_archive_limit, settings.bulk_archive_desc, settings.auto_detect_vpn, settings.vpn_detected, settings.no_vpn_detected, settings.shared_links, settings.ip_override, settings.ip_override_desc, settings.no_active_links_desc, settings.expires_at, settings.clear_local_cache, settings.clear_local_cache_desc, settings.clear_cache_title, settings.clear_cache_desc, settings.cache_cleared, settings.cache_clear_failed, settings.transcode_cache, settings.clear_transcode_title, settings.clear_transcode_message, settings.failed_prefix, settings.clear_variants_for, settings.no_transcoded_cached, settings.check_for_updates, settings.check_updates_desc, settings.update_restart, settings.update_available_toast, settings.latest_version_toast, settings.update_prod_only_toast, settings.update_check_failed_toast, settings.update_failed_toast, settings.load_shares_failed, settings.revoke_link_title, settings.revoke_link_desc, settings.link_revoked, settings.link_revoke_failed, settings.port_range_error, settings.api_server_started, settings.api_server_stopped, settings.api_update_failed, settings.api_port_updated, settings.api_port_update_failed, settings.generate_api_key_title, settings.regenerate_api_key_desc, settings.generate_api_key_desc, settings.api_key_generated, settings.api_key_generate_failed, settings.copy_clipboard_failed, settings.restart_app_toast, settings.reconnect_success_toast, settings.reconnect_failed_toast, settings.reconnect_failed_err_toast, settings.diagnostics_copied, settings.shared_files, settings.select_app_language, settings.socks5_desc_mobile, settings.http_bridge_desc, settings.proxy_test_success, settings.proxy_test_failed, settings.live_state, settings.live_state_desc, sync.status.disabled, sync.status.syncing, sync.status.synced, sync.status.conflicts, sync.conflict.title, sync.conflict.keep_local, sync.conflict.keep_remote, sync.conflict.keep_both, ads.sponsored, ads.sponsor_message, ads.continue_to_files, ads.browser_note, ads.close_ad.
  • pt-BR (117): settings.tab_sync, settings.sync.title, settings.sync.toggle, settings.sync.select_folder, settings.sync.remove, settings.sync.add_folder, settings.sync.select_channel, settings.sync.no_channels, settings.max_uploads_desc, settings.max_downloads_desc, settings.zip_folders_desc, settings.performance_mode_desc, settings.app_language, settings.choose_language, settings.api_stopped, settings.api_copy_alert, settings.transcode_cache_desc, settings.proxy_config, settings.enable_proxy_desc, settings.socks5_desc, settings.host_desc, settings.proxy_reconnect_note, settings.vpn_optimizer, settings.vpn_mode, settings.vpn_mode_desc, settings.timeout_multiplier, settings.timeout_multiplier_desc, settings.retry_attempts, settings.retry_attempts_desc, settings.retry_backoff, settings.preferred_dc, settings.preferred_dc_desc, settings.dc_fallback_attempts, settings.dc_fallback_desc, settings.respect_flood, settings.respect_flood_desc, settings.bandwidth_throttle, settings.download_limit, settings.transfer_chunk_size, settings.chunk_size_desc, settings.keep_alive, settings.keep_alive_desc, settings.bulk_archive_limit, settings.bulk_archive_desc, settings.auto_detect_vpn, settings.vpn_detected, settings.no_vpn_detected, settings.shared_links, settings.ip_override, settings.ip_override_desc, settings.no_active_links_desc, settings.expires_at, settings.clear_local_cache, settings.clear_local_cache_desc, settings.clear_cache_title, settings.clear_cache_desc, settings.cache_cleared, settings.cache_clear_failed, settings.transcode_cache, settings.clear_transcode_title, settings.clear_transcode_message, settings.failed_prefix, settings.clear_variants_for, settings.original, settings.no_transcoded_cached, settings.check_for_updates, settings.check_updates_desc, settings.update_restart, settings.update_available_toast, settings.latest_version_toast, settings.update_prod_only_toast, settings.update_check_failed_toast, settings.update_failed_toast, settings.load_shares_failed, settings.revoke_link_title, settings.revoke_link_desc, settings.link_revoked, settings.link_revoke_failed, settings.port_range_error, settings.api_server_started, settings.api_server_stopped, settings.api_update_failed, settings.api_port_updated, settings.api_port_update_failed, settings.generate_api_key_title, settings.regenerate_api_key_desc, settings.generate_api_key_desc, settings.api_key_generated, settings.api_key_generate_failed, settings.copy_clipboard_failed, settings.restart_app_toast, settings.reconnect_success_toast, settings.reconnect_failed_toast, settings.reconnect_failed_err_toast, settings.diagnostics_copied, settings.shared_files, settings.select_app_language, settings.socks5_desc_mobile, settings.http_bridge_desc, settings.proxy_test_success, settings.proxy_test_failed, settings.live_state, settings.live_state_desc, settings.base_mode, sync.status.disabled, sync.status.syncing, sync.status.synced, sync.status.conflicts, sync.conflict.title, sync.conflict.keep_local, sync.conflict.keep_remote, sync.conflict.keep_both, ads.sponsored, ads.sponsor_message, ads.continue_to_files, ads.browser_note, ads.close_ad.
  • de (115): settings.tab_sync, settings.sync.title, settings.sync.toggle, settings.sync.select_folder, settings.sync.remove, settings.sync.add_folder, settings.sync.select_channel, settings.sync.no_channels, settings.max_uploads_desc, settings.max_downloads_desc, settings.zip_folders_desc, settings.performance_mode_desc, settings.app_language, settings.choose_language, settings.api_stopped, settings.api_copy_alert, settings.transcode_cache_desc, settings.proxy_config, settings.enable_proxy_desc, settings.socks5_desc, settings.host_desc, settings.proxy_reconnect_note, settings.vpn_optimizer, settings.vpn_mode, settings.vpn_mode_desc, settings.timeout_multiplier, settings.timeout_multiplier_desc, settings.retry_attempts, settings.retry_attempts_desc, settings.retry_backoff, settings.preferred_dc, settings.preferred_dc_desc, settings.dc_fallback_attempts, settings.dc_fallback_desc, settings.respect_flood, settings.respect_flood_desc, settings.bandwidth_throttle, settings.download_limit, settings.transfer_chunk_size, settings.chunk_size_desc, settings.keep_alive, settings.keep_alive_desc, settings.bulk_archive_limit, settings.bulk_archive_desc, settings.auto_detect_vpn, settings.vpn_detected, settings.no_vpn_detected, settings.shared_links, settings.ip_override, settings.ip_override_desc, settings.no_active_links_desc, settings.expires_at, settings.clear_local_cache, settings.clear_local_cache_desc, settings.clear_cache_title, settings.clear_cache_desc, settings.cache_cleared, settings.cache_clear_failed, settings.transcode_cache, settings.clear_transcode_title, settings.clear_transcode_message, settings.failed_prefix, settings.clear_variants_for, settings.no_transcoded_cached, settings.check_for_updates, settings.check_updates_desc, settings.update_restart, settings.update_available_toast, settings.latest_version_toast, settings.update_prod_only_toast, settings.update_check_failed_toast, settings.update_failed_toast, settings.load_shares_failed, settings.revoke_link_title, settings.revoke_link_desc, settings.link_revoked, settings.link_revoke_failed, settings.port_range_error, settings.api_server_started, settings.api_server_stopped, settings.api_update_failed, settings.api_port_updated, settings.api_port_update_failed, settings.generate_api_key_title, settings.regenerate_api_key_desc, settings.generate_api_key_desc, settings.api_key_generated, settings.api_key_generate_failed, settings.copy_clipboard_failed, settings.restart_app_toast, settings.reconnect_success_toast, settings.reconnect_failed_toast, settings.reconnect_failed_err_toast, settings.diagnostics_copied, settings.shared_files, settings.select_app_language, settings.socks5_desc_mobile, settings.http_bridge_desc, settings.proxy_test_success, settings.proxy_test_failed, settings.live_state, settings.live_state_desc, sync.status.disabled, sync.status.syncing, sync.status.synced, sync.status.conflicts, sync.conflict.title, sync.conflict.keep_local, sync.conflict.keep_remote, sync.conflict.keep_both, ads.sponsored, ads.sponsor_message, ads.continue_to_files, ads.browser_note, ads.close_ad.
  • hi (115): settings.tab_sync, settings.sync.title, settings.sync.toggle, settings.sync.select_folder, settings.sync.remove, settings.sync.add_folder, settings.sync.select_channel, settings.sync.no_channels, settings.max_uploads_desc, settings.max_downloads_desc, settings.zip_folders_desc, settings.performance_mode_desc, settings.app_language, settings.choose_language, settings.api_stopped, settings.api_copy_alert, settings.transcode_cache_desc, settings.proxy_config, settings.enable_proxy_desc, settings.socks5_desc, settings.host_desc, settings.proxy_reconnect_note, settings.vpn_optimizer, settings.vpn_mode, settings.vpn_mode_desc, settings.timeout_multiplier, settings.timeout_multiplier_desc, settings.retry_attempts, settings.retry_attempts_desc, settings.retry_backoff, settings.preferred_dc, settings.preferred_dc_desc, settings.dc_fallback_attempts, settings.dc_fallback_desc, settings.respect_flood, settings.respect_flood_desc, settings.bandwidth_throttle, settings.download_limit, settings.transfer_chunk_size, settings.chunk_size_desc, settings.keep_alive, settings.keep_alive_desc, settings.bulk_archive_limit, settings.bulk_archive_desc, settings.auto_detect_vpn, settings.vpn_detected, settings.no_vpn_detected, settings.shared_links, settings.ip_override, settings.ip_override_desc, settings.no_active_links_desc, settings.expires_at, settings.clear_local_cache, settings.clear_local_cache_desc, settings.clear_cache_title, settings.clear_cache_desc, settings.cache_cleared, settings.cache_clear_failed, settings.transcode_cache, settings.clear_transcode_title, settings.clear_transcode_message, settings.failed_prefix, settings.clear_variants_for, settings.no_transcoded_cached, settings.check_for_updates, settings.check_updates_desc, settings.update_restart, settings.update_available_toast, settings.latest_version_toast, settings.update_prod_only_toast, settings.update_check_failed_toast, settings.update_failed_toast, settings.load_shares_failed, settings.revoke_link_title, settings.revoke_link_desc, settings.link_revoked, settings.link_revoke_failed, settings.port_range_error, settings.api_server_started, settings.api_server_stopped, settings.api_update_failed, settings.api_port_updated, settings.api_port_update_failed, settings.generate_api_key_title, settings.regenerate_api_key_desc, settings.generate_api_key_desc, settings.api_key_generated, settings.api_key_generate_failed, settings.copy_clipboard_failed, settings.restart_app_toast, settings.reconnect_success_toast, settings.reconnect_failed_toast, settings.reconnect_failed_err_toast, settings.diagnostics_copied, settings.shared_files, settings.select_app_language, settings.socks5_desc_mobile, settings.http_bridge_desc, settings.proxy_test_success, settings.proxy_test_failed, settings.live_state, settings.live_state_desc, sync.status.disabled, sync.status.syncing, sync.status.synced, sync.status.conflicts, sync.conflict.title, sync.conflict.keep_local, sync.conflict.keep_remote, sync.conflict.keep_both, ads.sponsored, ads.sponsor_message, ads.continue_to_files, ads.browser_note, ads.close_ad.
  • id (117): settings.tab_sync, settings.sync.title, settings.sync.toggle, settings.sync.select_folder, settings.sync.remove, settings.sync.add_folder, settings.sync.select_channel, settings.sync.no_channels, settings.max_uploads_desc, settings.max_downloads_desc, settings.zip_folders_desc, settings.video_upload_file, settings.video_upload_media, settings.performance_mode_desc, settings.app_language, settings.choose_language, settings.api_stopped, settings.api_copy_alert, settings.transcode_cache_desc, settings.proxy_config, settings.enable_proxy_desc, settings.socks5_desc, settings.host_desc, settings.proxy_reconnect_note, settings.vpn_optimizer, settings.vpn_mode, settings.vpn_mode_desc, settings.timeout_multiplier, settings.timeout_multiplier_desc, settings.retry_attempts, settings.retry_attempts_desc, settings.retry_backoff, settings.preferred_dc, settings.preferred_dc_desc, settings.dc_fallback_attempts, settings.dc_fallback_desc, settings.respect_flood, settings.respect_flood_desc, settings.bandwidth_throttle, settings.download_limit, settings.transfer_chunk_size, settings.chunk_size_desc, settings.keep_alive, settings.keep_alive_desc, settings.bulk_archive_limit, settings.bulk_archive_desc, settings.auto_detect_vpn, settings.vpn_detected, settings.no_vpn_detected, settings.shared_links, settings.ip_override, settings.ip_override_desc, settings.no_active_links_desc, settings.expires_at, settings.clear_local_cache, settings.clear_local_cache_desc, settings.clear_cache_title, settings.clear_cache_desc, settings.cache_cleared, settings.cache_clear_failed, settings.transcode_cache, settings.clear_transcode_title, settings.clear_transcode_message, settings.failed_prefix, settings.clear_variants_for, settings.no_transcoded_cached, settings.check_for_updates, settings.check_updates_desc, settings.update_restart, settings.update_available_toast, settings.latest_version_toast, settings.update_prod_only_toast, settings.update_check_failed_toast, settings.update_failed_toast, settings.load_shares_failed, settings.revoke_link_title, settings.revoke_link_desc, settings.link_revoked, settings.link_revoke_failed, settings.port_range_error, settings.api_server_started, settings.api_server_stopped, settings.api_update_failed, settings.api_port_updated, settings.api_port_update_failed, settings.generate_api_key_title, settings.regenerate_api_key_desc, settings.generate_api_key_desc, settings.api_key_generated, settings.api_key_generate_failed, settings.copy_clipboard_failed, settings.restart_app_toast, settings.reconnect_success_toast, settings.reconnect_failed_toast, settings.reconnect_failed_err_toast, settings.diagnostics_copied, settings.shared_files, settings.select_app_language, settings.socks5_desc_mobile, settings.http_bridge_desc, settings.proxy_test_success, settings.proxy_test_failed, settings.live_state, settings.live_state_desc, sync.status.disabled, sync.status.syncing, sync.status.synced, sync.status.conflicts, sync.conflict.title, sync.conflict.keep_local, sync.conflict.keep_remote, sync.conflict.keep_both, ads.sponsored, ads.sponsor_message, ads.continue_to_files, ads.browser_note, ads.close_ad.
  • tr (115): settings.tab_sync, settings.sync.title, settings.sync.toggle, settings.sync.select_folder, settings.sync.remove, settings.sync.add_folder, settings.sync.select_channel, settings.sync.no_channels, settings.max_uploads_desc, settings.max_downloads_desc, settings.zip_folders_desc, settings.performance_mode_desc, settings.app_language, settings.choose_language, settings.api_stopped, settings.api_copy_alert, settings.transcode_cache_desc, settings.proxy_config, settings.enable_proxy_desc, settings.socks5_desc, settings.host_desc, settings.proxy_reconnect_note, settings.vpn_optimizer, settings.vpn_mode, settings.vpn_mode_desc, settings.timeout_multiplier, settings.timeout_multiplier_desc, settings.retry_attempts, settings.retry_attempts_desc, settings.retry_backoff, settings.preferred_dc, settings.preferred_dc_desc, settings.dc_fallback_attempts, settings.dc_fallback_desc, settings.respect_flood, settings.respect_flood_desc, settings.bandwidth_throttle, settings.download_limit, settings.transfer_chunk_size, settings.chunk_size_desc, settings.keep_alive, settings.keep_alive_desc, settings.bulk_archive_limit, settings.bulk_archive_desc, settings.auto_detect_vpn, settings.vpn_detected, settings.no_vpn_detected, settings.shared_links, settings.ip_override, settings.ip_override_desc, settings.no_active_links_desc, settings.expires_at, settings.clear_local_cache, settings.clear_local_cache_desc, settings.clear_cache_title, settings.clear_cache_desc, settings.cache_cleared, settings.cache_clear_failed, settings.transcode_cache, settings.clear_transcode_title, settings.clear_transcode_message, settings.failed_prefix, settings.clear_variants_for, settings.no_transcoded_cached, settings.check_for_updates, settings.check_updates_desc, settings.update_restart, settings.update_available_toast, settings.latest_version_toast, settings.update_prod_only_toast, settings.update_check_failed_toast, settings.update_failed_toast, settings.load_shares_failed, settings.revoke_link_title, settings.revoke_link_desc, settings.link_revoked, settings.link_revoke_failed, settings.port_range_error, settings.api_server_started, settings.api_server_stopped, settings.api_update_failed, settings.api_port_updated, settings.api_port_update_failed, settings.generate_api_key_title, settings.regenerate_api_key_desc, settings.generate_api_key_desc, settings.api_key_generated, settings.api_key_generate_failed, settings.copy_clipboard_failed, settings.restart_app_toast, settings.reconnect_success_toast, settings.reconnect_failed_toast, settings.reconnect_failed_err_toast, settings.diagnostics_copied, settings.shared_files, settings.select_app_language, settings.socks5_desc_mobile, settings.http_bridge_desc, settings.proxy_test_success, settings.proxy_test_failed, settings.live_state, settings.live_state_desc, sync.status.disabled, sync.status.syncing, sync.status.synced, sync.status.conflicts, sync.conflict.title, sync.conflict.keep_local, sync.conflict.keep_remote, sync.conflict.keep_both, ads.sponsored, ads.sponsor_message, ads.continue_to_files, ads.browser_note, ads.close_ad.
  • ko (115): settings.tab_sync, settings.sync.title, settings.sync.toggle, settings.sync.select_folder, settings.sync.remove, settings.sync.add_folder, settings.sync.select_channel, settings.sync.no_channels, settings.max_uploads_desc, settings.max_downloads_desc, settings.zip_folders_desc, settings.performance_mode_desc, settings.app_language, settings.choose_language, settings.api_stopped, settings.api_copy_alert, settings.transcode_cache_desc, settings.proxy_config, settings.enable_proxy_desc, settings.socks5_desc, settings.host_desc, settings.proxy_reconnect_note, settings.vpn_optimizer, settings.vpn_mode, settings.vpn_mode_desc, settings.timeout_multiplier, settings.timeout_multiplier_desc, settings.retry_attempts, settings.retry_attempts_desc, settings.retry_backoff, settings.preferred_dc, settings.preferred_dc_desc, settings.dc_fallback_attempts, settings.dc_fallback_desc, settings.respect_flood, settings.respect_flood_desc, settings.bandwidth_throttle, settings.download_limit, settings.transfer_chunk_size, settings.chunk_size_desc, settings.keep_alive, settings.keep_alive_desc, settings.bulk_archive_limit, settings.bulk_archive_desc, settings.auto_detect_vpn, settings.vpn_detected, settings.no_vpn_detected, settings.shared_links, settings.ip_override, settings.ip_override_desc, settings.no_active_links_desc, settings.expires_at, settings.clear_local_cache, settings.clear_local_cache_desc, settings.clear_cache_title, settings.clear_cache_desc, settings.cache_cleared, settings.cache_clear_failed, settings.transcode_cache, settings.clear_transcode_title, settings.clear_transcode_message, settings.failed_prefix, settings.clear_variants_for, settings.no_transcoded_cached, settings.check_for_updates, settings.check_updates_desc, settings.update_restart, settings.update_available_toast, settings.latest_version_toast, settings.update_prod_only_toast, settings.update_check_failed_toast, settings.update_failed_toast, settings.load_shares_failed, settings.revoke_link_title, settings.revoke_link_desc, settings.link_revoked, settings.link_revoke_failed, settings.port_range_error, settings.api_server_started, settings.api_server_stopped, settings.api_update_failed, settings.api_port_updated, settings.api_port_update_failed, settings.generate_api_key_title, settings.regenerate_api_key_desc, settings.generate_api_key_desc, settings.api_key_generated, settings.api_key_generate_failed, settings.copy_clipboard_failed, settings.restart_app_toast, settings.reconnect_success_toast, settings.reconnect_failed_toast, settings.reconnect_failed_err_toast, settings.diagnostics_copied, settings.shared_files, settings.select_app_language, settings.socks5_desc_mobile, settings.http_bridge_desc, settings.proxy_test_success, settings.proxy_test_failed, settings.live_state, settings.live_state_desc, sync.status.disabled, sync.status.syncing, sync.status.synced, sync.status.conflicts, sync.conflict.title, sync.conflict.keep_local, sync.conflict.keep_remote, sync.conflict.keep_both, ads.sponsored, ads.sponsor_message, ads.continue_to_files, ads.browser_note, ads.close_ad.

The working target has zero scanned literals in supporter, encryption and authentication. The owner hook holds mobile presentation files; the committed subset therefore retains one mobile supporter literal and mobile action-array debt (298 under the original scanner; the strengthened scanner and its dependent assurance-test hunks remain held). The held strengthened scanner, assurance-test hunks, baseline matching the strengthened scanner and mobile E2E journeys describe the complete working target. Remaining noncritical literal debt and other locales' copied values remain measured, and no native review is represented as passed. These translations do not hold the release tag.


Docs RELEASE ACCEPTANCE (`Docs/RELEASE_ACCEPTANCE.md`)

Release acceptance: owner checklist

For desktop 4.0.0, every manual platform, installed-upgrade, real WebView, live Telegram and PayPal sandbox acceptance row below is not run for 4.0.0 by owner decision. These rows are not passed by local fixtures or automated CI. Automated builds and suites still must pass. No manual platform or live-service exercise is authorized in this release cycle.

The steps below remain a future acceptance runbook. Record source revision, installed version, OS/device/WebView, exact artifact/checksum/signature, date and sanitized evidence if a later owner decision authorizes them. Never expose sessions, API hashes, payment credentials, recovery codes or private keys. TDENC2 remains frozen-format beta with independent cryptographic review pending. Desktop 4.0.0 and Android/Google TV 4.1.0 preview are independent version lines; no Android build or release occurs here.

Telegram and transfers

Status Exact steps Expected result What failure means
not run for 4.0.0 by owner decision On each supported desktop OS, start from a private clean profile, enter valid personal API credentials, complete phone/QR login with Telegram two-factor enabled, enter a wrong two-factor password, then the correct password; restart. Correct translated retry, successful sign-in, restored session; no plaintext API hash in the visible config/log. Live authentication or secret storage is not accepted.
not run for 4.0.0 by owner decision Sign out in Telegram Drive; inspect Telegram โ†’ Settings โ†’ Devices on another signed-in Telegram client. Restart Drive and try listing. The Drive session is revoked remotely and locally signed out; a remote revocation failure is clearly disclosed. Logout/session-revocation regression.
not run for 4.0.0 by owner decision Upload a patterned/hash-recorded file larger than 10 MiB to Saved Messages and a Drive folder. Interrupt network after acknowledged parts, quit, restart, reconnect and resume. Download and compare SHA-256. Repeat with a TDENC2 vault slot and separately a file-passphrase slot, including protected metadata and nested Folder Sync placement. One publication, previously acknowledged parts reused, continued protected envelope, exact downloaded hash. Changed-source retry uses a fresh session. Transfer persistence/integrity or nonce-continuation blocker.
not run for 4.0.0 by owner decision Configure Folder Sync on an expendable folder, add/modify a file, inspect Transfer Center, pause/resume, restart while queued, reconnect. Work runs through the durable queue, restores after restart, publishes once, updates the correct remote folder. Scheduler/queue integration is unverified.
not run for 4.0.0 by owner decision Open a Drive folder exceeding 50,000 media rows; retain a known older cached entry. Refresh after own desktop/REST/WebDAV/Folder Sync upload. Repeat after an external rename/delete. Newest bounded listing is usable and explicitly incomplete; known older rows are not pruned by incomplete discovery. Own upload appears on next listing; external changes follow the documented audit/stale policy. Inventory completeness, isolation or reconciliation regression.
not run for 4.0.0 by owner decision Enable local REST with a private key; request folder list/files/search/statistics/duplicates/empty folders across more than 20 Drive folders. Repeat a global search after 31 seconds with no changes. Record source/RPC counts from sanitized diagnostics. Correct account-only results, explicit partial status above limits, no needless second index build/source requests when generations are valid. Fixture cost evidence does not hold against real Telegram.
not run for 4.0.0 by owner decision Search a large library with names, filters, favorites/tags and locked/unlocked protected files. Lock/switch account during a long build. Responsive bounded answers with partial status, no protected-name persistence or stale-account publication. Search integrity/isolation/release blocker.
not run for 4.0.0 by owner decision During a naturally encountered or authorized controlled Telegram FLOOD_WAIT, observe queued transfer and listing/search behavior through the full advertised wait; reconnect and resume after the wait. If no actual wait occurs, leave this row UNRUN. Wait is surfaced and respected without retry storms, lost parts or account crossover; operation resumes. Real rate-limit handling is not accepted.

Installed upgrades and supporter compatibility

Future installed acceptance covers Windows, macOS Intel, macOS Apple Silicon and Linux; these checks are not authorized for 4.0.0. Preserve a backup of the installed 3.9.8 test profile and use its active lifetime entitlement. Do not buy again.

Status Exact steps Expected result What failure means
not run for 4.0.0 by owner decision Start installed 3.9.8 with an active existing supporter entitlement; verify ad-free state, recovery-code availability, session, queue, preferences and encrypted vault. Install the matching signed candidate over it, restart online then offline, and inspect the same data. Activation and recovery code intact, active/offline-grace ads suppressed throughout startup, no purchase prompt, no new payment required, data/vault/queue preserved. Protected lifetime/update compatibility blocker.
not run for 4.0.0 by owner decision On the first signed macOS candidate, upgrade from the prior installed app and exercise Keychain access, unlock, existing supporter refresh and recovery-code display; quit/restart. Record any Keychain access/ACL prompt and whether consent restores existing credentials. Stable service/identifiers and existing secrets retained; any legitimate OS consent succeeds without repurchase or lost recovery. Signing/Keychain migration behavior needs owner investigation; do not rotate identifiers or keys to bypass it.
not run for 4.0.0 by owner decision On each OS, deny then allow native keyring access using a test profile. Exercise API-hash retrieval, supporter state, recovery, restart and temporary service outage. Clear recoverable failure, no plaintext fallback, ad-free grace retained where applicable and no repurchase solicitation. Real OS credential boundary is not accepted.
not run for 4.0.0 by owner decision Verify a saved recovery code restores an existing entitlement on a second supported device; fill the supported three-device allowance and attempt a fourth with the authorized test entitlement. Recovery works; three-device contract enforced; every app feature still usable without payment. Device/recovery compatibility blocker.
not run for 4.0.0 by owner decision After the owner explicitly authorizes a PayPal sandbox exercise, use sandbox credentials/service: accept terms, complete exactly $5.00 USD once, verify token/ad-free state, return/cancel/retry, refresh, recovery, device limit and sandbox refund/revocation. Record merchant/capture validation privately. Correct one-time lifetime promise and recovery; no subscription, double purchase or backup-health dependency. Payment-path acceptance not complete. No transaction, deployment, production D1 mutation or key rotation is authorized by this checklist itself.
not run for 4.0.0 by owner decision Run preflight against the configured production supporter URL with the exact build public key, then verify downloaded binary checksum and gh attestation verify ARTIFACT --repo caamer20/Telegram-Drive. Price 5.00, USD, allowance 3, matching public key; expected repository/workflow/tag provenance. Release configuration/provenance mismatch blocks publication. The separate automated health result does not complete this downloaded-artifact acceptance row.

OS integration, packages and update rehearsal

Status Exact steps Expected result What failure means
not run for 4.0.0 by owner decision For each DMG/updater app archive, NSIS installer, AppImage, DEB, RPM and Arch package, use the exact checksummed artifact in a clean supported environment. Install/extract and run the packaged startup smoke helper, then manually complete first-launch/sign-in navigation. Real frontend-to-native startup readiness, database/app-data/stream runtime ready, no rendering crash or missing runtime dependency. Packaged startup is not accepted; build-only evidence is insufficient.
not run for 4.0.0 by owner decision Rehearse a tag vX.Y.Z-rc.N after the owner finalizes plain application version X.Y.Z and its first changelog block. Inspect the draft/rerun and final release properties. From a stable 3.9.8 installation query the stable updater. One reused draft, published as prerelease with make_latest=false; stable updater receives no rehearsal. Do not copy RC updater metadata to the stable website endpoint. Rehearsal can reach ordinary users; block any stable tag. RC binaries intentionally keep the plain base application version; reinstall the final artifact manually in the rehearsal profile because version numbers are equal.
not run for 4.0.0 by owner decision Deny/allow native notification permission, finish/fail a transfer, click the notification, close to tray, reopen, hide/show and quit while transfers run. Repeat dark/light/RTL and tray system themes. Correct localized notifications, predictable tray/background behavior and no lost queue. OS integration or native-copy acceptance missing.
not run for 4.0.0 by owner decision Upgrade an installed 3.9.x account with flat desktop previews/thumbnails, workspace previews and ready offline packs; open each externally online and offline. Plant a sibling and substitute a symlink. Recorded plain originals open once migrated; planted, protected, other-account and substituted files are refused. Installed legacy-cache migration compatibility failure.
not run for 4.0.0 by owner decision Open an app-produced plain PDF preview, offline file and completed download externally; reveal downloads in Finder/Explorer. Try an arbitrary local path, edited/replaced produced file and substituted symlink. Permitted files open/reveal, arbitrary/substituted files refused; recorded 3.9.x plain cached previews, thumbnails and ready offline copies open after upgrade without another download. Native file-capability enforcement or legitimate caller compatibility failure.
not run for 4.0.0 by owner decision Open sponsor, supporter terms, authorized sandbox approval, auth help, author/repository and FFmpeg download links. Test HTTP/HTTPS/mailto and refusal of file/tel/custom schemes through generic URL capabilities. Legitimate destinations open through OS browser/application; scheme restrictions hold. Sponsor fallback keeps noopener,noreferrer. Restricted capabilities broke intended destinations or left a bypass.
not run for 4.0.0 by owner decision Run complete SPONSOR_ACCEPTANCE.md matrix on WebView2, WKWebView, WebKitGTK and Android WebView, free/active/grace users, hung provider/origin and return cycles. Free placement reliable; supporters never see ads; current origin and 15-minute return interval accepted. Owner must decide origin/interval only after this matrix; fixture passes cannot decide them.
not run for 4.0.0 by owner decision Review the 128 newly authored keys in every catalog, the eleven localesโ€™ copied-English/Sync ranges and hook-held mobile follow-up, then every required language/surface with a native speaker using LOCALIZATION_REVIEW.md, especially TV offer/current passphrase and every reused key listed there; traverse RTL and TV D-pad controls. Meaning, wrapping, direction, plural/interpolation and accessibility acceptable. Translation remains unreviewed or release-visible localization debt needs an explicit owner decision.

Android, Google TV and WebDAV clients

Status Exact steps Expected result What failure means
not run for 4.0.0 by owner decision Follow ANDROID_SIDELOAD_RELEASE.md locally: signed universal/four-ABI build, artifact verification, manifest/signature/checksums, old-to-new install-over-existing, data and activation before/after. Run phone and TV device suites and resilience scenarios. Stable identity/certificate, increasing code, all ABIs/alignment, preserved session/queue/activation, D-pad/Back/TV launcher/media behavior. Android acceptance remains blocked; desktop CI says nothing about Android. Publish only compiled binaries and metadata after owner approval.
not run for 4.0.0 by owner decision On Android/Google TV free and licensed profiles, browse during transfers/playback/dialogs, open the sponsored offer, then test network loss, Doze/reboot/low storage and notification denial. Remote-focusable short offer, appropriate suppression and ad-free supporters; durable recovery where the existing Android path supports it. Real device or sponsor/transfer compatibility missing. P2-12 engine migration is not implemented in this pass.
not run for 4.0.0 by owner decision Mount loopback WebDAV in Finder and Windows Explorer using a private token; list a large/partial folder, upload a >10 MiB file, rename/delete/move, reconnect after interrupted upload, and sign out/switch account. Native clients see correct names/statuses, uploads publish once and appear next listing, no stale cross-account access, malformed ranges ignored correctly. Native client behavior differs from HTTP fixtures and blocks advertised WebDAV acceptance.

Pending owner decisions and independent checks

UNRUN: independent cryptographic review before TDENC2 general availability; separately approved fuzz research (no harness added); license/distribution review; signing/notarization certificates and first real signed build; next Android version-code decision P2-33 (independent version line; its next versionCode must exceed the existing 4.1.0 preview); Android pending publication review; full P2-08 native review, noncritical copy and hook-held mobile follow-up; sponsor matrix origin/interval. Manual Windows/Linux machines, packaged OS launches, live Telegram, PayPal sandbox and real WebViews are not run for 4.0.0 by owner decision. Automated local and CI build/suite results and the separately authorized read-only production supporter preflight are recorded in the release-readiness report; they do not fill these manual rows.

Desktop iPhone photo acceptance

Status Exact steps Expected result What failure means
not run for 4.0.0 by owner decision Use expendable real iPhone 12MP/48MP HEIC/HEIF photos with rotation/mirroring on each desktop OS. Record OS/WebView and decoder versions. Open a normal preview, gallery/slideshow and an offline pack; zoom/pan, navigate/prefetch, clear cache and repeat. Try no decoder/old FFmpeg, then open externally and download. Repeat with a protected source. An upright complete primary image appears as a bounded JPEG; metadata identity and account changes invalidate it. Telegram thumbnails take priority. Recovery text and original actions work when no decoder qualifies. The original stays intact; protected sources produce no plaintext rendition. Decoder/grid/transform incompatibility or platform lifecycle regression; record evidence and defer acceptance. Synthetic host measurements do not fill this row.

Docs RELEASE NOTES TEMPLATE (`Docs/RELEASE_NOTES_TEMPLATE.md`)

Release notes template

Replace VERSION and filenames with the actual release. Use the reviewed first changelog block and distinguish local E2E evidence from installed/device acceptance. State whether this is a rehearsal prerelease or a stable release. Prereleases are never latest and are not offered by the stable updater.

Verify downloaded artifacts

Download the artifact and SHA256SUMS.txt from the same release. On Linux run sha256sum -c SHA256SUMS.txt; on macOS use shasum -a 256 for the selected file; on Windows use Get-FileHash -Algorithm SHA256 and compare the matching manifest entry. Checksums detect corruption; provenance verifies the producing repository/workflow.

sh
gh attestation verify ./DOWNLOADED_ARTIFACT --repo caamer20/Telegram-Drive

Require a successful verification for the expected repository and inspect the reported release workflow/ref against the tag you downloaded. Do not install on a failed or unexpected verification. Source CycloneDX SBOM, Arch runtime SBOM and Sigstore bundles accompany the checksums. Verification needs a current GitHub CLI with attestation support and network access; no verification is claimed until run.

Compatibility and acceptance

TDENC2 is a frozen-format beta; independent cryptographic review remains pending. Every feature remains free. The optional one-time $5.00 USD lifetime ad-free supporter entitlement, three-device allowance and recovery codes remain compatible. Link the acceptance runbook and record actual executed platforms rather than implying all platforms passed.

Rehearsal packaging retains the plain base application version: tag vX.Y.Z-rc.N uses application/changelog X.Y.Z, so DMG, NSIS, Debian and Arch inputs keep the existing plain-version shape. The same-version final installer must be installed manually in the isolated rehearsal profile. Suffix-version acceptance by the real macOS/NSIS bundlers is UNRUN; this policy avoids requiring it. Never mirror rehearsal latest.json to the stable website endpoint.

Packaged startup smoke is restricted to disposable OS users/VMs. It uses a unique runtime Tauri identifier and validates actual resolved profile paths before native initialization; environment variables alone do not redirect OS known folders or keyrings. The private token/PID/profile marker is written by the existing frontend-to-native startup-health request only after database, app-data and streaming readiness. Fixture launcher tests do not count as packaged OS acceptance.


Docs SEO (`Docs/SEO.md`)

Product website SEO

The canonical product website is https://telegram-drive.com/. GitHub Pages
publishes Docs/Telegram-Drive.html as /index.html through
.github/workflows/pages.yml, along with Docs/assets/, Docs/robots.txt, and
Docs/sitemap.xml. Markdown documentation in Docs/ is not published by this
workflow.

Search configuration

  • robots.txt allows crawlers to fetch the page and its assets and advertises the
    absolute sitemap URL. Do not block assets needed to render the page.
  • The sitemap contains only the canonical homepage. Section anchors such as
    #download and #faq are not separate pages and must not be added as sitemap URLs.
    Add future pages only when they are published and independently indexable.
  • The canonical link, Open Graph URL, and structured data all use the HTTPS custom
    domain. Keep the title and descriptions consistent with the visible product copy.
  • WebSite structured data supplies the site name. SoftwareApplication describes
    the free application; the optional supporter license does not change the app's
    zero purchase price. Do not invent ratings or reviews to satisfy rich-result checks.
    Google's software-app rich result requires a qualifying rating or review, which
    this page does not currently provide.
  • All main text, FAQ answers, and download fallback links are present in the static
    HTML. JavaScript is not required to discover them.
  • The sitemap intentionally omits lastmod: a deployment time is not necessarily
    a substantive content update. Add it only when it can be maintained accurately.

Verify after an authorized deployment

  1. Confirm these URLs return HTTP 200 and the expected file contents:
  2. Confirm https://caamer20.github.io/Telegram-Drive/ still redirects permanently
    to https://telegram-drive.com/, and GitHub Pages still enforces HTTPS.
  3. In the verified Google Search Console
    property for this domain, submit https://telegram-drive.com/sitemap.xml in
    Sitemaps. Use URL inspection โ†’ Test live URL for the homepage, then
    Request indexing. Domain verification requires the owner's Google account
    and DNS access if the property has not already been verified.
  4. Inspect the page in Google's Rich Results Test
    and PageSpeed Insights. Monitor Search Console's
    indexing, selected canonical, and search performance after Google recrawls.
    Crawl permission and structured data do not guarantee indexing or rankings.

Google references


Docs SPONSOR ACCEPTANCE (`Docs/SPONSOR_ACCEPTANCE.md`)

The established media/share loopback origin remains the default. On desktop, start the candidate with TELEGRAM_DRIVE_AD_ORIGIN=separate to select a dedicated OS-assigned loopback listener. Startup health reports sponsor_port; the frame and its message checks use that actual port. In separate mode the media server's ad routes are inert, and the ad server exposes no media, share or HLS routes. Failure of the separate listener shows the bounded fallback; it does not silently revert to the media origin. No setting or entitlement migration is required.

Owner decision: switching the default to the separate origin waits for this matrix to be completed and reviewed. The existing return interval is 15 minutes; older release notes saying 45 minutes do not change the current constant. Any different interval is a separate owner decision.

Current evidence

Native child-process journeys use real loopback HTTP, synthetic signed device-bound entitlements and a controlled loader HTTP server. They exercise route isolation, actual ports/CSP, active and offline-grace 204 suppression, invalid-token rejection, deadline expiry, and verification during fresh/stale loader responses. The controlled loader replaces the provider's network boundary; it does not establish Adsterra delivery, real secure-storage behavior, production revocation or WebView behavior. Browser journeys use the application UI with a simulated native boundary and static sponsor frame.

The fallback UA is Chrome154's reduced desktop UA, based on the official stable release announcement of 22 September 2026. A nonempty request UA is forwarded unchanged. The Adsterra loader URL, direct loader, relay validation, DNS-over-HTTPS fallback, sandbox and external-link bridge remain in place.

Required matrix

Every cell below is UNRUN. Record OS, app build, WebView version, date, tester and observed provider delivery/failure reason. Run desktop rows with both default and separate origins; Android uses its existing external sponsor banner/gateway and has no desktop loopback creative.

Runtime Default origin / existing placement Selectable separate origin Supporter / recovery / update Result
Windows WebView2 UNRUN UNRUN UNRUN UNRUN
macOS WKWebView UNRUN UNRUN UNRUN UNRUN
Linux WebKitGTK UNRUN UNRUN UNRUN UNRUN
Android WebView / Google TV UNRUN on device Not applicable: desktop-only listener; confirm unchanged external placement UNRUN UNRUN

For every applicable origin/runtime:

  1. Start free, confirm the optional post-sign-in gateway, continue without opening an offer, and verify every feature remains available.
  2. Load the actual creative directly; force direct-loader failure to exercise the validated relay, and normal DNS failure to exercise the existing DoH recovery. Record CSP/network errors and provider delivery separately.
  3. Occupy the preferred media port. Confirm actual media/sponsor ports, CSP and message-origin/source checks follow the bound listeners. In separate mode confirm media ad routes are inert, ad routes cannot access media/share/HLS, and the sponsor origin is not accepted by media CORS.
  4. Block the provider/relay and verify the fallback appears within 12 seconds. Check translated loading/status/countdown and screen-reader labels. Countdown begins after loaded/fallback, dismisses after 10 seconds, manual dismissal works, and the banner returns after 15 minutes within the same session. Restart must clear the legacy persisted dismissal.
  5. Open the fallback and creative links by real user activation. Confirm the intended external browser destination, noopener,noreferrer fallback and unchanged bridge; reject untrusted message origin/source and unsafe URL schemes.
  6. Hold entitlement loading, then verify active and offline-grace supporters see no gateway/banner/frame or sponsor request. Direct local /ad-banner and /ad-script requests return204/no-store after verified local state loads. A verification arriving during a pending relay must suppress its final body, including retained stale fallback.
  7. Check temporary offline refresh failure preserves ad-free access through the signed grace deadline, existing recovery works within the three-device allowance, and an update preserves activation. No second payment prompt. A sandbox revocation exercise requires explicit owner authorization; do not use live PayPal or production state.
  8. Exit while the frame/relay is active, restart, and confirm both desktop loopback listeners close and reopen cleanly. On Android/TV check external sponsor action, dismissal, D-pad focus and lifecycle on actual hardware.

The backend is an additional hiding layer only. Its RAM cache is populated by the existing local signature/device verification and expires at the signed offline deadline. HTTP handlers do not call the supporter network service, secure storage or backup health, and cannot cause frontend sponsor content to appear. Telegram sign-out does not clear this device-wide entitlement.


Docs TDENC2 FORMAT (`Docs/TDENC2_FORMAT.md`)

TDENC2 frozen-format beta

The format shipped by 3.9.8 and retained for 4.0.0 is version 2. The beta freezes these bytes; it does not claim an independent cryptographic review. Standard uploads remain the default. Sharing and legacy migration remain disabled. mode_alpha is a legacy compatibility field, not a new rollout switch. A future incompatible format needs a new version and an explicit migration decision.

The authoritative implementations are crypto/envelope/{header,key_slot,encrypt_reader,decrypt_reader,length}.rs, crypto/kdf.rs, crypto/policy.rs, crypto/vault/{file,export}.rs and commands/fs.rs. All integers below are unsigned little-endian unless specified. Strings and domains are UTF-8 bytes without a terminating zero. Concatenation has no padding.

Envelope layout

The file is complete header, content records in order, then one final record. No record-length prefixes or trailing bytes are permitted. Cipher suite 1 is XChaCha20-Poly1305 with a 32-byte key, 24-byte nonce and 16-byte authentication tag appended to ciphertext.

Offset Bytes Core field
0 6 ASCII TDENC2
6 2 Format version 2
8 16 Random file UUID
24 2 Cipher suite 1
26 4 Complete header length
30 4 Plaintext chunk size (writer: 1,048,576)
34 4 Key-slot table length
38 4 Encrypted metadata length, including its tag; zero if absent
42 8 Total plaintext length
50 16 Random nonce prefix
66 32 HMAC-SHA-256 header authenticator
98 variable Key-slot table, then encrypted metadata

The 66-byte prefix ends before the authenticator. Each slot is 104 bytes: kind u8, unique slot ID u8, KDF u16, Argon2 memory KiB u32, iterations u32, parallelism u32, salt 16 bytes, independent wrapping nonce 24 bytes, wrapped DEK 48 bytes (32 bytes plus tag). Kind/KDF pairs are vault 1/HKDF 2, passphrase 2/Argon2id 1, recovery 3/HKDF 2. HKDF slots require all Argon2 fields zero. The current transfer path creates vault and/or passphrase slots and does not consume recovery slots.

Argon2id is version 0x13 with a 32-byte output. Current writers use 65,536 KiB, 3 iterations, parallelism 1; readers admit memory 65,536โ€“262,144 KiB, iterations 3โ€“100, parallelism 1โ€“8. The passphrase is its supplied UTF-8 bytes without normalization. HKDF-SHA-256 file wrapping uses the slot salt, the master key as IKM, and info telegram-drive:file-wrap:v2 + UUID + kind u8 + ID u8. Slot wrapping AAD is telegram-drive:tdenc2:key-slot + version u16 + UUID + kind + ID + KDF u16 + memory u32 + iterations u32 + parallelism u32 + salt. The independent wrapping nonce is stored in the slot; it is not derived from the content nonce.

HKDF-SHA-256 with no salt and the DEK as IKM derives separate 32-byte keys with info telegram-drive:header-auth:v2, telegram-drive:metadata-enc:v2, and telegram-drive:content-enc:v2. The header HMAC covers telegram-drive:tdenc2:header-mac + prefix + encoded slots + encrypted metadata. Metadata AAD is telegram-drive:tdenc2:metadata + prefix + slots. Its nonce is the prefix + u64::MAX. The authenticator must verify before metadata is used.

Protected metadata is serialized compact JSON in field order: schema_version (1), original_name, mime_type, and optional sync_path. Absent sync_path is omitted, not null. It is a relative Folder Sync placement path, for example docs/2026/fixed-answer.bin; consumers still validate safe placement. Metadata is absent when metadata protection is off. Names and paths stay encrypted inside the header; Telegram can still observe account, destination, time and ciphertext size.

Content record i (starting at zero) encrypts up to chunk_size plaintext bytes. Its nonce is prefix + i u64. Its AAD is telegram-drive:tdenc2:chunk + version u16 + UUID + header authenticator + i u64 + plaintext offset u64 + this plaintext length u32 + total plaintext length u64. The last content record can be short; an empty file has no content records. This binds ordering, offsets and declared length.

The final record uses nonce prefix + (u64::MAXโˆ’1). Its 52-byte plaintext is chunk count u32, total plaintext length u64, SHA-256 of all plaintext (32 bytes), and eight reserved zero bytes. Its AAD is telegram-drive:tdenc2:final + version u16 + UUID + header authenticator + chunk count u32 + total plaintext length u64. Ciphertext plus tag is exactly 68 bytes. The decoder verifies the final digest, counts, length and reserved bytes and refuses trailing bytes. Individual authenticated chunks can stream to session-scoped viewers; a complete downloaded file is published only after final verification.

Reader policy: 1โ€“8 unique slots, chunk sizes 65,536โ€“16,777,216 bytes, complete header at most 65,536 bytes. Although the metadata plaintext policy also says 65,536, the complete-header ceiling is tighter: with n slots, at most 65,536โˆ’98โˆ’104nโˆ’16 metadata plaintext bytes fit. Exact ciphertext length is header length + plaintext length + 16ร—ceil(plaintext/chunk_size) + 68, bounded by application writer/transfer policy at 2,000,000,000 bytes; the low-level header parser and streaming decoder do not independently enforce that total-size cap. TDENC1 is quarantined and rejected; it is never reinterpreted as TDENC2.

Interrupted uploads

The resumable upload journal stores the original header and source fingerprint. Continuation parses and authenticates that header, checks plaintext size, default chunk size, protection mode, and exact metadata bytes, unwraps every slot with the credentials supplied now, and requires all slots to yield the same DEK. EncryptionSession::from_header then reuses the UUID, nonce prefix, DEK and complete header. Re-reading the unchanged plaintext from the beginning reproduces exactly the same ciphertext; acknowledged Telegram parts can be skipped by the part-upload layer. It does not start encrypting at an arbitrary plaintext offset without recomputing the final hash.

A changed source fingerprint or incompatible credentials/header/metadata starts a fresh envelope with fresh randomness and a new upload session. Never reuse a nonce/key pair for changed plaintext. Native journeys cover vault and standalone passphrase envelopes over 10 MiB, interrupted part uploads, process restart, continued headers and authenticated download. Live Telegram acceptance remains UNRUN.

Vault and recovery container compatibility

TDVLT2 vaults and TDREC2 recovery bundles have a 64-byte header: magic 6, version u16 (2), Argon2 memory/iterations/parallelism u32 each, salt 16, nonce 24, ciphertext length u32. XChaCha20-Poly1305 encrypts the binary vault payload with the Argon2-derived key. AAD is respectively telegram-drive:persistent-vault:v2 or telegram-drive:recovery-bundle:v2, followed by the complete header. Lengths and KDF policy are checked before derivation. Recovery ciphertext permits a payload up to 1 MiB. The binary payload is magic TDVPL2 (6 bytes), creation timestamp i64 (8), vault master key (32), profile count u16, then profiles sorted by ID: ID byte length u16, UTF-8 ID bytes, 32-byte key. At most 64 profiles, ID length 1โ€“128 bytes, duplicate IDs and trailing bytes rejected. Recovery replacement archives the old encrypted vault; it does not modify remote envelopes.

Vault and per-file preparations use at most two shared blocking workers, outside the state mutex. Other derivations, such as encrypted settings sync, have independent blocking calls and are not included in this bound. At writer settings the shared preparation pool admits up to 128 MiB of Argon2 memory; maximum accepted settings admit up to 512 MiB. A detached canceled worker retains its permit until finished and cannot commit. Commit revalidates state/session revision and captured file identity/content. A successful atomic replacement is the commit point; later backup cleanup failure is reported in the log without reverting live key state.

Immutable compatibility evidence

app/src-tauri/test-support/crypto-vectors/manifest.json records public inputs and SHA-256 checksums. The 3.9.8 files came from local tag v3.9.8, commit 10f470617fd24d955acfda00350d535e1551be48, using its unchanged encoders with public deterministic entropy and a fixed vault fixture constructor. The dependency versions are recorded; this is source-level compatibility evidence, not an installed historical-binary run. The current vector adds optional sync_path. Native child-process journeys reproduce both envelopes byte for byte, reconstruct a continuation, decrypt saved envelopes with the historical vault, restore the historical recovery bundle, restart, and reject truncation, reordered records, bit flips, trailing bytes and an unrelated key without publishing plaintext. The fixture decoder stages plaintext in memory until final verification; this corruption journey does not exercise live Telegram download staging.

No coverage-guided fuzz harness is added under the E2E-only policy. Proposed owner decision: authorize a separate non-release research harness for parser/decryptor fuzzing, preserving saved failing inputs as native journeys. The owner must commission an independent cryptographic review before general availability; neither local journeys nor format freezing substitute for that review.


--- METRICS ---