Skip to content

i18n: settings.privacy.* keys for encryption disable/rotate/recovery UI (#338) - #343

Merged
qnbs merged 18 commits into
mainfrom
feat/encryption-migration-phase4-b-i18n
Aug 13, 2026
Merged

i18n: settings.privacy.* keys for encryption disable/rotate/recovery UI (#338)#343
qnbs merged 18 commits into
mainfrom
feat/encryption-migration-phase4-b-i18n

Conversation

@qnbs

@qnbs qnbs commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Summary

Stacked on #342 (base branch). Adds the 9 new settings.privacy.* i18n keys that PR
#342's UI (PassphraseModal disable/rotate modes, EncryptionRecoveryModal,
PrivacySection buttons) needs:

  • encryptionChangedStatus, encryptionDisableFailed, encryptionMigrationProgress
    (+ Label), encryptionRecoveryTitle/Body*/Stuck/ResumeButton

Also reuses several i18n keys that already existed from an earlier, never-wired-up B-1
scaffold (encryptionChangeAction/Button, encryptionModalChangeTitle,
encryptionDisableAction/Button/Confirm, encryptionModalDisableTitle) — PR #342's
components were adjusted to reference those instead of duplicating new ones.

  • Real translations for the 5 production locales (en + de/es/fr/it).
  • Remaining 14 locales carry the English fallback via check-i18n-keys.mjs --fix, per
    this repo's tiered i18n convention (/i18n-key skill covers those manually later).
  • Rebuilds every public/locales/<lang>/bundle.json.
  • Fixes the check-doc-metrics.mjs drift this created (README badge/table/prose:
    2904 → 2913 keys).

144 locale/bundle files + 1 README file. Kept as its own PR (not folded into #342) so
CodeAnt's ~100-file review threshold still fires on both PRs.

Test plan

  • pnpm run i18n:check — 19 locales match 2913 keys
  • pnpm run typecheck — clean
  • pnpm run lint — clean
  • node scripts/check-doc-metrics.mjs — no drift
  • CI (pending)

🤖 Generated with Claude Code

Summary by Sourcery

Add new settings privacy i18n strings for encryption disable/rotate/recovery flows and update locale bundles and metrics accordingly.

Enhancements:

  • Expand i18n coverage to include encryption status, migration, and recovery messaging in the settings privacy UI.

Documentation:

  • Update README i18n key counts and metrics to reflect the expanded set of localized strings.

Summary by CodeRabbit

  • New Features

    • Added localized UI text for assisted mode, fallback messaging, character and world generation guidance, plot-board suggestions, outline heuristics, grammar checking, local AI diagnostics, and related writing tools across supported languages.
    • Added dashboard notifications and labels for RAG, token usage, voice feedback, and progress indicators.
  • Warning Updates

    • Expanded encryption-disable confirmations to clearly explain decryption, local data retention, and loss of passphrase protection.
  • Improvements

    • Reorganized translation content for clearer, more consistent localization coverage.

qnbs and others added 6 commits August 12, 2026 15:45
…ble/rotate (#338 items 1+2)

Replaces the clearIdbPassphrase/rotateIdbPassphrase stubs with real journal-backed
migrations: new primary-store adapters (images, binder assets, codex, app-data,
snapshots, RAG vectors) plug into the existing secondary-store adapters via a new
encryptionMigrationOrchestrator.ts, giving the previously test-only migration engine
its first production callers. Disable/rotate now migrate and verify every protected
store before touching the passphrase sentinel, and fail closed into the resumable
journal (not a partial verifier change) on error.

Breaks a circular import (storageEncryptionService -> orchestrator -> adapters ->
storageEncryptionService) via a dynamic import at the two call sites, matching this
codebase's existing dynamic-import convention for avoiding heavy/circular static
coupling (listenerMiddleware.ts, aiApi.ts).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…st encryption (#338 items 1+2)

Extends PassphraseModal with 'disable'/'rotate' modes (live migration progress bar),
adds Disable/Change-passphrase buttons to PrivacySection, and wires both through
useSettingsView to the real clearIdbPassphrase/rotateIdbPassphrase implementations.

Adds EncryptionRecoveryModal + an App.tsx startup check: if a disable/rotate journal
was interrupted (reload/crash) before reaching 'completed', it takes priority over the
normal unlock flow and lets the user re-enter their passphrase(s) to safely resume —
CryptoKey material is never persisted, only re-derivable. A 'recovery-required' journal
(the migration's own verification found an inconsistency) is surfaced as a distinct,
honest stuck state rather than a fake auto-fix.

Refactors clearIdbPassphrase/rotateIdbPassphrase's post-migration commit steps and
key/verifier derivation into shared helpers so resumeEncryptionMigration() (used by
the recovery UX) reaches the exact same end state as a fresh-start migration.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ry UX (#338)

Real-data round-trip tests (image, codex 3-shape dispatch, binder asset Blob<->bytes,
RAG vectors aggregate<->individual duality) through rekey then disable — the prior
disable/rotate tests only proved migration completes over empty stores. Adds
resumeEncryptionMigration coverage (correct resume, wrong source passphrase, missing
target passphrase for rekey), new EncryptionRecoveryModal component tests, and
disable/rotate mode + progress-bar tests for PassphraseModal, PrivacySection's new
Change/Disable buttons, and useSettingsView's handlePassphraseConfirm branches.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Updates CLAUDE.md § At-rest encryption and Known Technical Debt, docs/IDB-ENCRYPTION.md,
and ADR-0018's status line to reflect the production migration wiring implemented in
this branch — the orchestrator, primary-store adapters, protectedWriteAdmission cross-tab
gate, and EncryptionRecoveryModal. Remaining gap noted honestly: no E2E coverage yet for
the disable/rotate/recovery round trips (unit + component tests only so far).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ecovery UI (#338)

9 new keys (disable-failed, migration-progress + label, recovery title/body/stuck/
resume, changed-status) added to en/settings.json and propagated to all 19 locales
via check-i18n-keys.mjs --fix. Real translations for the 5 production locales
(en + de/es/fr/it); the remaining 14 carry the English fallback per this repo's
tiered i18n convention. Rebuilds every public/locales/<lang>/bundle.json.

Stacked on feat/encryption-migration-phase4-b to keep that PR's code-only diff
under the ~100-file threshold the review bot needs to actually run.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Fixes the doc-metrics drift check.mjs flagged after adding 9 settings.privacy.* keys
for the encryption disable/rotate/recovery UI in the previous commit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@codeant-ai

codeant-ai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Skipping CodeAnt AI review — this PR changes more than 100 files, which usually means a migration, codemod, or vendored drop. Line-level review on diffs this large produces duplicate findings on the same rewrite pattern and drowns out anything that actually matters.

If you still want a review, comment @codeant-ai : review. For better signal, consider splitting the PR into smaller chunks.

@vercel

vercel Bot commented Aug 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
worldscript-studio Ready Ready Preview Aug 13, 2026 4:34am

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 803f24bd-1db2-49cb-806e-9ea53b3cdc4b

📥 Commits

Reviewing files that changed from the base of the PR and between 6822b41 and aba4117.

📒 Files selected for processing (144)
  • locales/ar/characters.json
  • locales/ar/common.json
  • locales/ar/outline.json
  • locales/ar/settings.json
  • locales/ar/worlds.json
  • locales/ar/writer.json
  • locales/de/characters.json
  • locales/de/common.json
  • locales/de/dashboard.json
  • locales/de/desktop.json
  • locales/de/export.json
  • locales/de/lora.json
  • locales/de/outline.json
  • locales/de/settings.json
  • locales/de/worlds.json
  • locales/de/writer.json
  • locales/el/characters.json
  • locales/el/common.json
  • locales/el/outline.json
  • locales/el/settings.json
  • locales/el/worlds.json
  • locales/el/writer.json
  • locales/en/settings.json
  • locales/es/characters.json
  • locales/es/common.json
  • locales/es/dashboard.json
  • locales/es/desktop.json
  • locales/es/export.json
  • locales/es/lora.json
  • locales/es/outline.json
  • locales/es/settings.json
  • locales/es/worlds.json
  • locales/es/writer.json
  • locales/eu/characters.json
  • locales/eu/common.json
  • locales/eu/outline.json
  • locales/eu/settings.json
  • locales/eu/worlds.json
  • locales/eu/writer.json
  • locales/fa/characters.json
  • locales/fa/common.json
  • locales/fa/outline.json
  • locales/fa/settings.json
  • locales/fa/worlds.json
  • locales/fa/writer.json
  • locales/fi/characters.json
  • locales/fi/common.json
  • locales/fi/outline.json
  • locales/fi/settings.json
  • locales/fi/worlds.json
  • locales/fi/writer.json
  • locales/fr/characters.json
  • locales/fr/common.json
  • locales/fr/dashboard.json
  • locales/fr/desktop.json
  • locales/fr/export.json
  • locales/fr/lora.json
  • locales/fr/outline.json
  • locales/fr/settings.json
  • locales/fr/worlds.json
  • locales/fr/writer.json
  • locales/he/characters.json
  • locales/he/common.json
  • locales/he/outline.json
  • locales/he/settings.json
  • locales/he/worlds.json
  • locales/he/writer.json
  • locales/hu/characters.json
  • locales/hu/common.json
  • locales/hu/outline.json
  • locales/hu/settings.json
  • locales/hu/worlds.json
  • locales/hu/writer.json
  • locales/is/characters.json
  • locales/is/common.json
  • locales/is/outline.json
  • locales/is/settings.json
  • locales/is/worlds.json
  • locales/is/writer.json
  • locales/it/characters.json
  • locales/it/common.json
  • locales/it/dashboard.json
  • locales/it/desktop.json
  • locales/it/export.json
  • locales/it/lora.json
  • locales/it/outline.json
  • locales/it/settings.json
  • locales/it/worlds.json
  • locales/it/writer.json
  • locales/ja/characters.json
  • locales/ja/common.json
  • locales/ja/outline.json
  • locales/ja/settings.json
  • locales/ja/worlds.json
  • locales/ja/writer.json
  • locales/ko/characters.json
  • locales/ko/common.json
  • locales/ko/outline.json
  • locales/ko/settings.json
  • locales/ko/worlds.json
  • locales/ko/writer.json
  • locales/pt/characters.json
  • locales/pt/common.json
  • locales/pt/outline.json
  • locales/pt/settings.json
  • locales/pt/worlds.json
  • locales/pt/writer.json
  • locales/ru/characters.json
  • locales/ru/common.json
  • locales/ru/outline.json
  • locales/ru/settings.json
  • locales/ru/worlds.json
  • locales/ru/writer.json
  • locales/sv/characters.json
  • locales/sv/common.json
  • locales/sv/outline.json
  • locales/sv/settings.json
  • locales/sv/worlds.json
  • locales/sv/writer.json
  • locales/zh/characters.json
  • locales/zh/common.json
  • locales/zh/outline.json
  • locales/zh/settings.json
  • locales/zh/worlds.json
  • locales/zh/writer.json
  • public/locales/ar/bundle.json
  • public/locales/de/bundle.json
  • public/locales/el/bundle.json
  • public/locales/en/bundle.json
  • public/locales/es/bundle.json
  • public/locales/eu/bundle.json
  • public/locales/fa/bundle.json
  • public/locales/fi/bundle.json
  • public/locales/fr/bundle.json
  • public/locales/he/bundle.json
  • public/locales/hu/bundle.json
  • public/locales/is/bundle.json
  • public/locales/it/bundle.json
  • public/locales/ja/bundle.json
  • public/locales/ko/bundle.json
  • public/locales/pt/bundle.json
  • public/locales/ru/bundle.json
  • public/locales/sv/bundle.json
  • public/locales/zh/bundle.json

📝 Walkthrough

Walkthrough

This PR updates locale source files and generated public bundles across multiple languages. It adds heuristic, assisted-mode, fallback, grammar, diagnostics, and encryption-warning strings. It also groups related translation keys and removes duplicate placements.

Changes

Localization catalog alignment

Layer / File(s) Summary
Feature translation entries
locales/*/*.json
Adds or relocates character, world, outline, assisted-mode, fallback, plot-board, grammar, token, and diagnostics translations across supported locales.
Settings and catalog ordering
locales/*/settings.json, locales/*/common.json, locales/*/writer.json, locales/*/dashboard.json, locales/*/desktop.json, locales/*/export.json, locales/*/lora.json
Expands encryption-disable confirmations and reorders related translation groups without changing most existing values.
Generated public bundles
public/locales/*/bundle.json
Mirrors the locale additions, relocations, deduplication, and encryption-warning updates in the public catalogs.

Estimated code review effort: 2 (Simple) | ~15 minutes

Possibly related PRs

Suggested labels: size:XL

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/encryption-migration-phase4-b-i18n

Comment @coderabbitai help to get the list of available commands.

@sourcery-ai

sourcery-ai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Adds new settings.privacy encryption-related i18n keys and propagates them across all 19 locales and bundled JSON files, while updating README i18n key counts and keeping documentation metrics in sync.

File-Level Changes

Change Details Files
Introduce and populate new encryption-related settings.privacy i18n keys across all locales, with real translations for production locales and English fallbacks elsewhere.
  • Add 9 new settings.privacy.* keys for encryption disable/rotate/recovery UI into the base locale JSON (settings and related files).
  • Provide production-quality translations for the new keys in en/de/es/fr/it locale JSON files.
  • Apply English fallback values for the remaining 14 locales using the i18n key checker/fixer script.
  • Ensure all per-namespace locale JSONs remain schema-aligned after key additions.
locales/en/settings.json
locales/de/settings.json
locales/es/settings.json
locales/fr/settings.json
locales/it/settings.json
locales/ar/settings.json
locales/el/settings.json
locales/eu/settings.json
locales/fa/settings.json
locales/fi/settings.json
locales/he/settings.json
locales/hu/settings.json
locales/is/settings.json
locales/ja/settings.json
locales/ko/settings.json
locales/pt/settings.json
locales/ru/settings.json
locales/sv/settings.json
locales/zh/settings.json
locales/*/characters.json
locales/*/common.json
locales/*/outline.json
locales/*/dashboard.json
locales/*/desktop.json
locales/*/export.json
locales/*/lora.json
locales/*/worlds.json
locales/*/writer.json
Regenerate bundled locale files and update README i18n metrics to reflect the increased key count.
  • Rebuild public/locales//bundle.json files for all 19 locales to include new keys and ensure consistency with source locale JSONs.
  • Update README i18n badge, feature table entry, and metrics section from 2904 to 2913 keys × 19 locales.
  • Run and satisfy documentation metrics checks so key counts and tooling remain in sync.
public/locales/ar/bundle.json
public/locales/de/bundle.json
public/locales/el/bundle.json
public/locales/en/bundle.json
public/locales/es/bundle.json
public/locales/eu/bundle.json
public/locales/fa/bundle.json
public/locales/fi/bundle.json
public/locales/fr/bundle.json
public/locales/he/bundle.json
public/locales/hu/bundle.json
public/locales/is/bundle.json
public/locales/it/bundle.json
public/locales/ja/bundle.json
public/locales/ko/bundle.json
public/locales/pt/bundle.json
public/locales/ru/bundle.json
public/locales/sv/bundle.json
public/locales/zh/bundle.json
README.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@codeant-ai

codeant-ai Bot commented Aug 12, 2026

Copy link
Copy Markdown

🏁 CodeAnt Quality Gate Results

Commit: aba4117a
Scan Time: 2026-08-13 04:39:02 UTC

✅ Overall Status: PASSED

Quality Gate Details

Quality Gate Status Details
Secrets ✅ PASSED 0 secrets found
Duplicate Code ✅ PASSED 0.0% duplicated
SAST ✅ PASSED No security issues
Bugs ✅ PASSED Rating S: No bugs
IAC ✅ PASSED Rating S: No issues

View Full Results

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@qodo-code-review

qodo-code-review Bot commented Aug 12, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Disable warning mistranslated ✓ Resolved 🐞 Bug ≡ Correctness
Description
settings.privacy.encryptionDisableConfirm was changed in English to a detailed disable-encryption
warning, but other locales (including de/es) still translate it as a short “Disable encryption”
label. Since PassphraseModal renders this key as the disable-mode warning paragraph, non-English
users get degraded/misleading warning copy for a sensitive action.
Code

locales/en/settings.json[676]

+  "settings.privacy.encryptionDisableConfirm": "This will decrypt all your data and turn off at-rest encryption. Your data stays on this device, no longer protected by a passphrase.",
Relevance

●●● Strong

Team historically fixes locale strings when user-visible copy is wrong/left as English; no matching
rejection precedent.

PR-#218
PR-#272
PR-#198

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The modal displays settings.privacy.encryptionDisableConfirm as warning body text in disable mode,
but the English locale now contains a long warning while other locales still contain a short
label-like translation for the same key.

components/settings/PassphraseModal.tsx[184-187]
locales/en/settings.json[674-677]
locales/de/settings.json[674-677]
locales/es/settings.json[674-677]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`settings.privacy.encryptionDisableConfirm` is rendered as a disable-encryption warning paragraph in `PassphraseModal`, but only the English locale updates it to the intended full warning; other locales still contain the previous short label-like translation.

## Issue Context
Because the key exists in each locale, normal fallback mechanisms won't apply; users will see the outdated localized value.

## Fix Focus Areas
- locales/de/settings.json[672-677]
- locales/es/settings.json[672-677]
- locales/fr/settings.json[672-677]
- locales/it/settings.json[672-677]
- locales/ar/settings.json[672-677]
- public/locales/de/bundle.json[2319-2324]

(And regenerate all `public/locales/*/bundle.json` after updating source locale JSONs.)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context
✅ Compliance rules (platform): 81 rules
Review mode: ⚖️ Balanced: This is primarily a large, mechanically regenerated i18n and bundle update; despite many files and hunks, it has low logical density and no new application logic.

Grey Divider

Tip of the day
💡 Did you know, you can type 'qodo, fix this' on a finding and the fix lands right on your PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread locales/en/settings.json
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

i18n: add settings.privacy encryption disable/rotate/recovery strings

✨ Enhancement 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Add settings.privacy.* strings for encryption disable/rotate/recovery and migration progress UI.
• Sync all 19 locales to the canonical key set (EN fallback where needed).
• Rebuild locale bundles and update README i18n key-count metrics (2904 → 2913).
Diagram

graph TD
  DEV["Developer"] --> EN["locales/en/settings.json"] --> SYNC["check-i18n-keys.mjs --fix"] --> LOCALES["locales/<lang>/*.json"] --> BUNDLES["public/locales/<lang>/bundle.json"] --> I18N["I18nContext"] --> UI["Settings Privacy UI"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Generate locale bundles in CI (do not commit `public/locales/*/bundle.json`)
  • ➕ Smaller PR diffs and fewer generated-file merge conflicts
  • ➕ Reviews focus on source locale JSONs, not compiled artifacts
  • ➖ Requires reliable CI/build steps for every deployment target
  • ➖ Harder to inspect exactly what shipped without artifacts in git
2. Adopt a translation platform/workflow (e.g., Crowdin/Locize)
  • ➕ Streamlines non-EN translation updates and review flow
  • ➕ Reduces long-term EN-fallback drift across many locales
  • ➖ Introduces vendor/tooling dependency and operational overhead
  • ➖ May not align with the repo’s tiered-locale convention

Recommendation: Given the repo’s current convention (tiered locales with EN fallback and committed runtime bundles), this PR’s approach is appropriate: add the new encryption UI keys in the canonical EN file, propagate via the existing sync tooling, then rebuild bundles and docs to keep runtime and metrics consistent. Review should focus on correctness/clarity of the new encryption recovery/migration strings and placeholder usage (e.g., {{current}}, {{total}}).

Files changed (145) +3904 / -3562

Enhancement (19) +406 / -235
settings.jsonAdd encryption UI strings to AR settings (with fallbacks) +22/-13

Add encryption UI strings to AR settings (with fallbacks)

• Propagates new 'settings.privacy.*' encryption disable/rotate/recovery and migration-progress strings into Arabic settings. Uses EN fallback where translations are not provided per tiering.

locales/ar/settings.json

settings.jsonAdd encryption UI strings to DE settings +22/-13

Add encryption UI strings to DE settings

• Adds German strings for encryption status changes, disable failure, migration progress (+label), and recovery/resume messaging. Keeps settings keys aligned with the canonical key set.

locales/de/settings.json

settings.jsonAdd encryption UI strings to EL settings (with fallbacks) +22/-13

Add encryption UI strings to EL settings (with fallbacks)

• Propagates new encryption-related 'settings.privacy.*' keys into Greek settings. Uses EN fallback where translations are not provided per tiering.

locales/el/settings.json

settings.jsonAdd new settings.privacy encryption disable/rotate/recovery keys +10/-1

Add new settings.privacy encryption disable/rotate/recovery keys

• Adds new 'settings.privacy.*' keys for passphrase-changed status, disable failure, migration progress (+label), and recovery modal title/body/stuck/resume messaging. Expands the disable-confirm text to explicitly warn about decrypting data and removing passphrase protection.

locales/en/settings.json

settings.jsonAdd encryption UI strings to ES settings +22/-13

Add encryption UI strings to ES settings

• Adds Spanish strings for new encryption recovery/migration/disable messaging and status updates. Keeps settings keys aligned with the canonical key set.

locales/es/settings.json

settings.jsonAdd encryption UI strings to EU settings (with fallbacks) +22/-13

Add encryption UI strings to EU settings (with fallbacks)

• Propagates new encryption-related 'settings.privacy.*' keys into Basque settings. Uses EN fallback where translations are not provided per tiering.

locales/eu/settings.json

settings.jsonAdd encryption UI strings to FA settings (with fallbacks) +22/-13

Add encryption UI strings to FA settings (with fallbacks)

• Propagates new encryption-related 'settings.privacy.*' keys into Persian settings. Uses EN fallback where translations are not provided per tiering.

locales/fa/settings.json

settings.jsonAdd encryption UI strings to FI settings (with fallbacks) +22/-13

Add encryption UI strings to FI settings (with fallbacks)

• Propagates new encryption-related 'settings.privacy.*' keys into Finnish settings. Uses EN fallback where translations are not provided per tiering.

locales/fi/settings.json

settings.jsonAdd encryption UI strings to FR settings +22/-13

Add encryption UI strings to FR settings

• Adds French strings for new encryption recovery/migration/disable messaging and status updates. Keeps settings keys aligned with the canonical key set.

locales/fr/settings.json

settings.jsonAdd encryption UI strings to HE settings (with fallbacks) +22/-13

Add encryption UI strings to HE settings (with fallbacks)

• Propagates new encryption-related 'settings.privacy.*' keys into Hebrew settings. Uses EN fallback where translations are not provided per tiering.

locales/he/settings.json

settings.jsonAdd encryption UI strings to HU settings (with fallbacks) +22/-13

Add encryption UI strings to HU settings (with fallbacks)

• Propagates new encryption-related 'settings.privacy.*' keys into Hungarian settings. Uses EN fallback where translations are not provided per tiering.

locales/hu/settings.json

settings.jsonAdd encryption UI strings to IS settings (with fallbacks) +22/-13

Add encryption UI strings to IS settings (with fallbacks)

• Propagates new encryption-related 'settings.privacy.*' keys into Icelandic settings. Uses EN fallback where translations are not provided per tiering.

locales/is/settings.json

settings.jsonAdd encryption UI strings to IT settings +22/-13

Add encryption UI strings to IT settings

• Adds Italian strings for new encryption recovery/migration/disable messaging and status updates. Keeps settings keys aligned with the canonical key set.

locales/it/settings.json

settings.jsonAdd encryption UI strings to JA settings (with fallbacks) +22/-13

Add encryption UI strings to JA settings (with fallbacks)

• Propagates new encryption-related 'settings.privacy.*' keys into Japanese settings. Uses EN fallback where translations are not provided per tiering.

locales/ja/settings.json

settings.jsonAdd encryption UI strings to KO settings (with fallbacks) +22/-13

Add encryption UI strings to KO settings (with fallbacks)

• Propagates new encryption-related 'settings.privacy.*' keys into Korean settings. Uses EN fallback where translations are not provided per tiering.

locales/ko/settings.json

settings.jsonAdd encryption UI strings to PT settings (with fallbacks) +22/-13

Add encryption UI strings to PT settings (with fallbacks)

• Propagates new encryption-related 'settings.privacy.*' keys into Portuguese settings. Uses EN fallback where translations are not provided per tiering.

locales/pt/settings.json

settings.jsonAdd encryption UI strings to RU settings (with fallbacks) +22/-13

Add encryption UI strings to RU settings (with fallbacks)

• Propagates new encryption-related 'settings.privacy.*' keys into Russian settings. Uses EN fallback where translations are not provided per tiering.

locales/ru/settings.json

settings.jsonAdd encryption UI strings to SV settings (with fallbacks) +22/-13

Add encryption UI strings to SV settings (with fallbacks)

• Propagates new encryption-related 'settings.privacy.*' keys into Swedish settings. Uses EN fallback where translations are not provided per tiering.

locales/sv/settings.json

settings.jsonAdd encryption UI strings to ZH settings (with fallbacks) +22/-13

Add encryption UI strings to ZH settings (with fallbacks)

• Propagates new encryption-related 'settings.privacy.*' keys into Chinese settings. Uses EN fallback where translations are not provided per tiering.

locales/zh/settings.json

Documentation (1) +4 / -4
README.mdUpdate README i18n key-count metrics to 2913 +4/-4

Update README i18n key-count metrics to 2913

• Updates the i18n badge and documentation references to reflect the new total key count after adding encryption-related strings. Keeps the doc metrics check aligned with generated assets.

README.md

Other (125) +3494 / -3323
characters.jsonSync AR characters locale keys +9/-9

Sync AR characters locale keys

• Synchronizes the Arabic characters namespace to match the canonical i18n key set and ordering.

locales/ar/characters.json

common.jsonSync AR common locale keys +23/-23

Sync AR common locale keys

• Synchronizes the Arabic common namespace to match the canonical i18n key set and ordering.

locales/ar/common.json

outline.jsonSync AR outline locale keys +18/-18

Sync AR outline locale keys

• Synchronizes the Arabic outline namespace to match the canonical i18n key set and ordering.

locales/ar/outline.json

worlds.jsonSync AR worlds locale keys +6/-6

Sync AR worlds locale keys

• Synchronizes the Arabic worlds namespace to match the canonical i18n key set and ordering.

locales/ar/worlds.json

writer.jsonSync AR writer locale keys +18/-18

Sync AR writer locale keys

• Synchronizes the Arabic writer namespace to match the canonical i18n key set and ordering.

locales/ar/writer.json

characters.jsonSync DE characters locale keys +9/-9

Sync DE characters locale keys

• Synchronizes the German characters namespace to match the canonical i18n key set and ordering.

locales/de/characters.json

common.jsonSync DE common locale keys +32/-32

Sync DE common locale keys

• Synchronizes the German common namespace to match the canonical i18n key set, including newly introduced common strings and ordering normalization.

locales/de/common.json

dashboard.jsonSync DE dashboard locale keys +4/-4

Sync DE dashboard locale keys

• Synchronizes the German dashboard namespace to match the canonical i18n key set and ordering.

locales/de/dashboard.json

desktop.jsonSync DE desktop locale keys +17/-17

Sync DE desktop locale keys

• Synchronizes the German desktop namespace to match the canonical i18n key set and ordering.

locales/de/desktop.json

export.jsonSync DE export locale keys +4/-4

Sync DE export locale keys

• Synchronizes the German export namespace to match the canonical i18n key set and ordering.

locales/de/export.json

lora.jsonSync DE lora locale keys +13/-13

Sync DE lora locale keys

• Synchronizes the German lora namespace to match the canonical i18n key set and ordering.

locales/de/lora.json

outline.jsonSync DE outline locale keys +18/-18

Sync DE outline locale keys

• Synchronizes the German outline namespace to match the canonical i18n key set and ordering.

locales/de/outline.json

worlds.jsonSync DE worlds locale keys +6/-6

Sync DE worlds locale keys

• Synchronizes the German worlds namespace to match the canonical i18n key set and ordering.

locales/de/worlds.json

writer.jsonSync DE writer locale keys +33/-33

Sync DE writer locale keys

• Synchronizes the German writer namespace to match the canonical i18n key set and ordering.

locales/de/writer.json

characters.jsonSync EL characters locale keys +9/-9

Sync EL characters locale keys

• Synchronizes the Greek characters namespace to match the canonical i18n key set and ordering.

locales/el/characters.json

common.jsonSync EL common locale keys +23/-23

Sync EL common locale keys

• Synchronizes the Greek common namespace to match the canonical i18n key set and ordering.

locales/el/common.json

outline.jsonSync EL outline locale keys +18/-18

Sync EL outline locale keys

• Synchronizes the Greek outline namespace to match the canonical i18n key set and ordering.

locales/el/outline.json

worlds.jsonSync EL worlds locale keys +6/-6

Sync EL worlds locale keys

• Synchronizes the Greek worlds namespace to match the canonical i18n key set and ordering.

locales/el/worlds.json

writer.jsonSync EL writer locale keys +18/-18

Sync EL writer locale keys

• Synchronizes the Greek writer namespace to match the canonical i18n key set and ordering.

locales/el/writer.json

characters.jsonSync ES characters locale keys +9/-9

Sync ES characters locale keys

• Synchronizes the Spanish characters namespace to match the canonical i18n key set and ordering.

locales/es/characters.json

common.jsonSync ES common locale keys +32/-32

Sync ES common locale keys

• Synchronizes the Spanish common namespace to match the canonical i18n key set and ordering.

locales/es/common.json

dashboard.jsonSync ES dashboard locale keys +4/-4

Sync ES dashboard locale keys

• Synchronizes the Spanish dashboard namespace to match the canonical i18n key set and ordering.

locales/es/dashboard.json

desktop.jsonSync ES desktop locale keys +17/-17

Sync ES desktop locale keys

• Synchronizes the Spanish desktop namespace to match the canonical i18n key set and ordering.

locales/es/desktop.json

export.jsonSync ES export locale keys +4/-4

Sync ES export locale keys

• Synchronizes the Spanish export namespace to match the canonical i18n key set and ordering.

locales/es/export.json

lora.jsonSync ES lora locale keys +13/-13

Sync ES lora locale keys

• Synchronizes the Spanish lora namespace to match the canonical i18n key set and ordering.

locales/es/lora.json

outline.jsonSync ES outline locale keys +18/-18

Sync ES outline locale keys

• Synchronizes the Spanish outline namespace to match the canonical i18n key set and ordering.

locales/es/outline.json

worlds.jsonSync ES worlds locale keys +6/-6

Sync ES worlds locale keys

• Synchronizes the Spanish worlds namespace to match the canonical i18n key set and ordering.

locales/es/worlds.json

writer.jsonSync ES writer locale keys +33/-33

Sync ES writer locale keys

• Synchronizes the Spanish writer namespace to match the canonical i18n key set and ordering.

locales/es/writer.json

characters.jsonSync EU characters locale keys +9/-9

Sync EU characters locale keys

• Synchronizes the Basque characters namespace to match the canonical i18n key set and ordering.

locales/eu/characters.json

common.jsonSync EU common locale keys +23/-23

Sync EU common locale keys

• Synchronizes the Basque common namespace to match the canonical i18n key set and ordering.

locales/eu/common.json

outline.jsonSync EU outline locale keys +18/-18

Sync EU outline locale keys

• Synchronizes the Basque outline namespace to match the canonical i18n key set and ordering.

locales/eu/outline.json

worlds.jsonSync EU worlds locale keys +6/-6

Sync EU worlds locale keys

• Synchronizes the Basque worlds namespace to match the canonical i18n key set and ordering.

locales/eu/worlds.json

writer.jsonSync EU writer locale keys +18/-18

Sync EU writer locale keys

• Synchronizes the Basque writer namespace to match the canonical i18n key set and ordering.

locales/eu/writer.json

characters.jsonSync FA characters locale keys +9/-9

Sync FA characters locale keys

• Synchronizes the Persian characters namespace to match the canonical i18n key set and ordering.

locales/fa/characters.json

common.jsonSync FA common locale keys +23/-23

Sync FA common locale keys

• Synchronizes the Persian common namespace to match the canonical i18n key set and ordering.

locales/fa/common.json

outline.jsonSync FA outline locale keys +18/-18

Sync FA outline locale keys

• Synchronizes the Persian outline namespace to match the canonical i18n key set and ordering.

locales/fa/outline.json

worlds.jsonSync FA worlds locale keys +6/-6

Sync FA worlds locale keys

• Synchronizes the Persian worlds namespace to match the canonical i18n key set and ordering.

locales/fa/worlds.json

writer.jsonSync FA writer locale keys +18/-18

Sync FA writer locale keys

• Synchronizes the Persian writer namespace to match the canonical i18n key set and ordering.

locales/fa/writer.json

characters.jsonSync FI characters locale keys +9/-9

Sync FI characters locale keys

• Synchronizes the Finnish characters namespace to match the canonical i18n key set and ordering.

locales/fi/characters.json

common.jsonSync FI common locale keys +23/-23

Sync FI common locale keys

• Synchronizes the Finnish common namespace to match the canonical i18n key set and ordering.

locales/fi/common.json

outline.jsonSync FI outline locale keys +18/-18

Sync FI outline locale keys

• Synchronizes the Finnish outline namespace to match the canonical i18n key set and ordering.

locales/fi/outline.json

worlds.jsonSync FI worlds locale keys +6/-6

Sync FI worlds locale keys

• Synchronizes the Finnish worlds namespace to match the canonical i18n key set and ordering.

locales/fi/worlds.json

writer.jsonSync FI writer locale keys +18/-18

Sync FI writer locale keys

• Synchronizes the Finnish writer namespace to match the canonical i18n key set and ordering.

locales/fi/writer.json

characters.jsonSync FR characters locale keys +9/-9

Sync FR characters locale keys

• Synchronizes the French characters namespace to match the canonical i18n key set and ordering.

locales/fr/characters.json

common.jsonSync FR common locale keys +32/-32

Sync FR common locale keys

• Synchronizes the French common namespace to match the canonical i18n key set and ordering.

locales/fr/common.json

dashboard.jsonSync FR dashboard locale keys +4/-4

Sync FR dashboard locale keys

• Synchronizes the French dashboard namespace to match the canonical i18n key set and ordering.

locales/fr/dashboard.json

desktop.jsonSync FR desktop locale keys +17/-17

Sync FR desktop locale keys

• Synchronizes the French desktop namespace to match the canonical i18n key set and ordering.

locales/fr/desktop.json

export.jsonSync FR export locale keys +4/-4

Sync FR export locale keys

• Synchronizes the French export namespace to match the canonical i18n key set and ordering.

locales/fr/export.json

lora.jsonSync FR lora locale keys +13/-13

Sync FR lora locale keys

• Synchronizes the French lora namespace to match the canonical i18n key set and ordering.

locales/fr/lora.json

outline.jsonSync FR outline locale keys +18/-18

Sync FR outline locale keys

• Synchronizes the French outline namespace to match the canonical i18n key set and ordering.

locales/fr/outline.json

worlds.jsonSync FR worlds locale keys +6/-6

Sync FR worlds locale keys

• Synchronizes the French worlds namespace to match the canonical i18n key set and ordering.

locales/fr/worlds.json

writer.jsonSync FR writer locale keys +33/-33

Sync FR writer locale keys

• Synchronizes the French writer namespace to match the canonical i18n key set and ordering.

locales/fr/writer.json

characters.jsonSync HE characters locale keys +9/-9

Sync HE characters locale keys

• Synchronizes the Hebrew characters namespace to match the canonical i18n key set and ordering.

locales/he/characters.json

common.jsonSync HE common locale keys +23/-23

Sync HE common locale keys

• Synchronizes the Hebrew common namespace to match the canonical i18n key set and ordering.

locales/he/common.json

outline.jsonSync HE outline locale keys +18/-18

Sync HE outline locale keys

• Synchronizes the Hebrew outline namespace to match the canonical i18n key set and ordering.

locales/he/outline.json

worlds.jsonSync HE worlds locale keys +6/-6

Sync HE worlds locale keys

• Synchronizes the Hebrew worlds namespace to match the canonical i18n key set and ordering.

locales/he/worlds.json

writer.jsonSync HE writer locale keys +18/-18

Sync HE writer locale keys

• Synchronizes the Hebrew writer namespace to match the canonical i18n key set and ordering.

locales/he/writer.json

characters.jsonSync HU characters locale keys +9/-9

Sync HU characters locale keys

• Synchronizes the Hungarian characters namespace to match the canonical i18n key set and ordering.

locales/hu/characters.json

common.jsonSync HU common locale keys +23/-23

Sync HU common locale keys

• Synchronizes the Hungarian common namespace to match the canonical i18n key set and ordering.

locales/hu/common.json

outline.jsonSync HU outline locale keys +18/-18

Sync HU outline locale keys

• Synchronizes the Hungarian outline namespace to match the canonical i18n key set and ordering.

locales/hu/outline.json

worlds.jsonSync HU worlds locale keys +6/-6

Sync HU worlds locale keys

• Synchronizes the Hungarian worlds namespace to match the canonical i18n key set and ordering.

locales/hu/worlds.json

writer.jsonSync HU writer locale keys +18/-18

Sync HU writer locale keys

• Synchronizes the Hungarian writer namespace to match the canonical i18n key set and ordering.

locales/hu/writer.json

characters.jsonSync IS characters locale keys +9/-9

Sync IS characters locale keys

• Synchronizes the Icelandic characters namespace to match the canonical i18n key set and ordering.

locales/is/characters.json

common.jsonSync IS common locale keys +23/-23

Sync IS common locale keys

• Synchronizes the Icelandic common namespace to match the canonical i18n key set and ordering.

locales/is/common.json

outline.jsonSync IS outline locale keys +18/-18

Sync IS outline locale keys

• Synchronizes the Icelandic outline namespace to match the canonical i18n key set and ordering.

locales/is/outline.json

worlds.jsonSync IS worlds locale keys +6/-6

Sync IS worlds locale keys

• Synchronizes the Icelandic worlds namespace to match the canonical i18n key set and ordering.

locales/is/worlds.json

writer.jsonSync IS writer locale keys +18/-18

Sync IS writer locale keys

• Synchronizes the Icelandic writer namespace to match the canonical i18n key set and ordering.

locales/is/writer.json

characters.jsonSync IT characters locale keys +9/-9

Sync IT characters locale keys

• Synchronizes the Italian characters namespace to match the canonical i18n key set and ordering.

locales/it/characters.json

common.jsonSync IT common locale keys +32/-32

Sync IT common locale keys

• Synchronizes the Italian common namespace to match the canonical i18n key set and ordering.

locales/it/common.json

dashboard.jsonSync IT dashboard locale keys +4/-4

Sync IT dashboard locale keys

• Synchronizes the Italian dashboard namespace to match the canonical i18n key set and ordering.

locales/it/dashboard.json

desktop.jsonSync IT desktop locale keys +17/-17

Sync IT desktop locale keys

• Synchronizes the Italian desktop namespace to match the canonical i18n key set and ordering.

locales/it/desktop.json

export.jsonSync IT export locale keys +4/-4

Sync IT export locale keys

• Synchronizes the Italian export namespace to match the canonical i18n key set and ordering.

locales/it/export.json

lora.jsonSync IT lora locale keys +13/-13

Sync IT lora locale keys

• Synchronizes the Italian lora namespace to match the canonical i18n key set and ordering.

locales/it/lora.json

outline.jsonSync IT outline locale keys +18/-18

Sync IT outline locale keys

• Synchronizes the Italian outline namespace to match the canonical i18n key set and ordering.

locales/it/outline.json

worlds.jsonSync IT worlds locale keys +6/-6

Sync IT worlds locale keys

• Synchronizes the Italian worlds namespace to match the canonical i18n key set and ordering.

locales/it/worlds.json

writer.jsonSync IT writer locale keys +33/-33

Sync IT writer locale keys

• Synchronizes the Italian writer namespace to match the canonical i18n key set and ordering.

locales/it/writer.json

characters.jsonSync JA characters locale keys +9/-9

Sync JA characters locale keys

• Synchronizes the Japanese characters namespace to match the canonical i18n key set and ordering.

locales/ja/characters.json

common.jsonSync JA common locale keys +23/-23

Sync JA common locale keys

• Synchronizes the Japanese common namespace to match the canonical i18n key set and ordering.

locales/ja/common.json

outline.jsonSync JA outline locale keys +18/-18

Sync JA outline locale keys

• Synchronizes the Japanese outline namespace to match the canonical i18n key set and ordering.

locales/ja/outline.json

worlds.jsonSync JA worlds locale keys +6/-6

Sync JA worlds locale keys

• Synchronizes the Japanese worlds namespace to match the canonical i18n key set and ordering.

locales/ja/worlds.json

writer.jsonSync JA writer locale keys +18/-18

Sync JA writer locale keys

• Synchronizes the Japanese writer namespace to match the canonical i18n key set and ordering.

locales/ja/writer.json

characters.jsonSync KO characters locale keys +9/-9

Sync KO characters locale keys

• Synchronizes the Korean characters namespace to match the canonical i18n key set and ordering.

locales/ko/characters.json

common.jsonSync KO common locale keys +23/-23

Sync KO common locale keys

• Synchronizes the Korean common namespace to match the canonical i18n key set and ordering.

locales/ko/common.json

outline.jsonSync KO outline locale keys +18/-18

Sync KO outline locale keys

• Synchronizes the Korean outline namespace to match the canonical i18n key set and ordering.

locales/ko/outline.json

worlds.jsonSync KO worlds locale keys +6/-6

Sync KO worlds locale keys

• Synchronizes the Korean worlds namespace to match the canonical i18n key set and ordering.

locales/ko/worlds.json

writer.jsonSync KO writer locale keys +18/-18

Sync KO writer locale keys

• Synchronizes the Korean writer namespace to match the canonical i18n key set and ordering.

locales/ko/writer.json

characters.jsonSync PT characters locale keys +9/-9

Sync PT characters locale keys

• Synchronizes the Portuguese characters namespace to match the canonical i18n key set and ordering.

locales/pt/characters.json

common.jsonSync PT common locale keys +23/-23

Sync PT common locale keys

• Synchronizes the Portuguese common namespace to match the canonical i18n key set and ordering.

locales/pt/common.json

outline.jsonSync PT outline locale keys +18/-18

Sync PT outline locale keys

• Synchronizes the Portuguese outline namespace to match the canonical i18n key set and ordering.

locales/pt/outline.json

worlds.jsonSync PT worlds locale keys +6/-6

Sync PT worlds locale keys

• Synchronizes the Portuguese worlds namespace to match the canonical i18n key set and ordering.

locales/pt/worlds.json

writer.jsonSync PT writer locale keys +18/-18

Sync PT writer locale keys

• Synchronizes the Portuguese writer namespace to match the canonical i18n key set and ordering.

locales/pt/writer.json

characters.jsonSync RU characters locale keys +9/-9

Sync RU characters locale keys

• Synchronizes the Russian characters namespace to match the canonical i18n key set and ordering.

locales/ru/characters.json

common.jsonSync RU common locale keys +23/-23

Sync RU common locale keys

• Synchronizes the Russian common namespace to match the canonical i18n key set and ordering.

locales/ru/common.json

outline.jsonSync RU outline locale keys +18/-18

Sync RU outline locale keys

• Synchronizes the Russian outline namespace to match the canonical i18n key set and ordering.

locales/ru/outline.json

worlds.jsonSync RU worlds locale keys +6/-6

Sync RU worlds locale keys

• Synchronizes the Russian worlds namespace to match the canonical i18n key set and ordering.

locales/ru/worlds.json

writer.jsonSync RU writer locale keys +18/-18

Sync RU writer locale keys

• Synchronizes the Russian writer namespace to match the canonical i18n key set and ordering.

locales/ru/writer.json

characters.jsonSync SV characters locale keys +9/-9

Sync SV characters locale keys

• Synchronizes the Swedish characters namespace to match the canonical i18n key set and ordering.

locales/sv/characters.json

common.jsonSync SV common locale keys +23/-23

Sync SV common locale keys

• Synchronizes the Swedish common namespace to match the canonical i18n key set and ordering.

locales/sv/common.json

outline.jsonSync SV outline locale keys +18/-18

Sync SV outline locale keys

• Synchronizes the Swedish outline namespace to match the canonical i18n key set and ordering.

locales/sv/outline.json

worlds.jsonSync SV worlds locale keys +6/-6

Sync SV worlds locale keys

• Synchronizes the Swedish worlds namespace to match the canonical i18n key set and ordering.

locales/sv/worlds.json

writer.jsonSync SV writer locale keys +18/-18

Sync SV writer locale keys

• Synchronizes the Swedish writer namespace to match the canonical i18n key set and ordering.

locales/sv/writer.json

characters.jsonSync ZH characters locale keys +9/-9

Sync ZH characters locale keys

• Synchronizes the Chinese characters namespace to match the canonical i18n key set and ordering.

locales/zh/characters.json

common.jsonSync ZH common locale keys +23/-23

Sync ZH common locale keys

• Synchronizes the Chinese common namespace to match the canonical i18n key set and ordering.

locales/zh/common.json

outline.jsonSync ZH outline locale keys +18/-18

Sync ZH outline locale keys

• Synchronizes the Chinese outline namespace to match the canonical i18n key set and ordering.

locales/zh/outline.json

worlds.jsonSync ZH worlds locale keys +6/-6

Sync ZH worlds locale keys

• Synchronizes the Chinese worlds namespace to match the canonical i18n key set and ordering.

locales/zh/worlds.json

writer.jsonSync ZH writer locale keys +18/-18

Sync ZH writer locale keys

• Synchronizes the Chinese writer namespace to match the canonical i18n key set and ordering.

locales/zh/writer.json

bundle.jsonRebuild AR runtime i18n bundle +92/-83

Rebuild AR runtime i18n bundle

• Rebuilds the Arabic compiled bundle to include the updated locale key set and new encryption-related strings.

public/locales/ar/bundle.json

bundle.jsonRebuild DE runtime i18n bundle +154/-145

Rebuild DE runtime i18n bundle

• Rebuilds the German compiled bundle to include the updated locale key set and new encryption-related strings.

public/locales/de/bundle.json

bundle.jsonRebuild EL runtime i18n bundle +92/-83

Rebuild EL runtime i18n bundle

• Rebuilds the Greek compiled bundle to include the updated locale key set and new encryption-related strings.

public/locales/el/bundle.json

bundle.jsonRebuild EN runtime i18n bundle with new encryption keys +10/-1

Rebuild EN runtime i18n bundle with new encryption keys

• Updates the English compiled bundle with new 'settings.privacy.*' encryption recovery/migration/disable strings and updated disable-confirm copy.

public/locales/en/bundle.json

bundle.jsonRebuild ES runtime i18n bundle +154/-145

Rebuild ES runtime i18n bundle

• Rebuilds the Spanish compiled bundle to include the updated locale key set and new encryption-related strings.

public/locales/es/bundle.json

bundle.jsonRebuild EU runtime i18n bundle +92/-83

Rebuild EU runtime i18n bundle

• Rebuilds the Basque compiled bundle to include the updated locale key set and new encryption-related strings.

public/locales/eu/bundle.json

bundle.jsonRebuild FA runtime i18n bundle +92/-83

Rebuild FA runtime i18n bundle

• Rebuilds the Persian compiled bundle to include the updated locale key set and new encryption-related strings.

public/locales/fa/bundle.json

bundle.jsonRebuild FI runtime i18n bundle +92/-83

Rebuild FI runtime i18n bundle

• Rebuilds the Finnish compiled bundle to include the updated locale key set and new encryption-related strings.

public/locales/fi/bundle.json

bundle.jsonRebuild FR runtime i18n bundle +154/-145

Rebuild FR runtime i18n bundle

• Rebuilds the French compiled bundle to include the updated locale key set and new encryption-related strings.

public/locales/fr/bundle.json

bundle.jsonRebuild HE runtime i18n bundle +92/-83

Rebuild HE runtime i18n bundle

• Rebuilds the Hebrew compiled bundle to include the updated locale key set and new encryption-related strings.

public/locales/he/bundle.json

bundle.jsonRebuild HU runtime i18n bundle +92/-83

Rebuild HU runtime i18n bundle

• Rebuilds the Hungarian compiled bundle to include the updated locale key set and new encryption-related strings.

public/locales/hu/bundle.json

bundle.jsonRebuild IS runtime i18n bundle +92

[Comment truncated to fit github's 65,536-char limit.]

qnbs and others added 7 commits August 12, 2026 22:06
…Y false positive

gitleaks' generic-api-key rule flags PASSPHRASE_SENTINEL_RECORD_KEY =
'idb_passphrase_sentinel_v1' (services/storage/idbPassphraseSentinel.ts,
mirrored as a mock constant in storageEncryptionService.test.ts) purely
because the variable name contains "PASSPHRASE" + "KEY" next to a
sufficiently long, structured string. It's a static IndexedDB record-key
identifier, not a credential — the app must know it deterministically to
find the sentinel record via store.get/put/delete.

Verified locally against the exact PR commit range with gitleaks 8.24.3
(matching CI): confirmed the finding reproduces without this config, and is
suppressed with it, while an unrelated real-looking secret (Stripe key
pattern) is still caught — the allowlist does not weaken detection elsewhere.

No .gitleaks.toml existed before this; [extend] useDefault = true keeps every
default rule active. Scoped to the exact leaked value only (not combined with
a path filter) since gitleaks' top-level [allowlist] ORs paths/regexes rather
than ANDing them — combining both would broaden the exemption to "anything in
that file" instead of narrowing it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Independently flagged by CodeAnt, CodeRabbit, and qodo-code-review on PR #342:

1. Disable/rekey recovery can permanently strand an interrupted migration.
   commitDisableMigration deletes the sentinel/salt BEFORE completing the
   journal; commitRekeyMigration saves the new sentinel BEFORE completing the
   journal. If completeEncryptionMigration() fails after either mutation, the
   journal stays 'committing' but resumeEncryptionMigration's source-key
   derivation now fails — the sentinel it needs is already gone (disable) or
   already replaced (rekey) — permanently blocking recovery. resumeEncryptionMigration
   now special-cases a journal already at 'committing': for disable, an absent
   sentinel means the commit already ran — finish the journal bookkeeping
   without deriving a key. For rekey, if the old passphrase no longer decrypts
   the sentinel, verify the new passphrase against the journal's durable target
   verifier (independent of the sentinel) before concluding the commit already
   happened, instead of reporting a false wrong-passphrase error.

2. Blob optimistic-write check only compared size + MIME type, not bytes.
   Two Blobs can share both while holding different content (e.g. a concurrent
   binder-asset re-upload), so the migration's freshness check would silently
   accept a stale value and overwrite a newer asset. valuesMatch is now async
   and compares actual bytes for Blobs. writeBatch is split into a read phase
   (readCurrentValues) and a write phase (putValues) so the async Blob
   comparison never happens inside a live IDB transaction's request handler —
   safe because the whole batch already runs under an exclusive
   withMigrationAdmission() lock, so no writer can interleave between the two.

3. The app-data primary-store adapter corrupted IdbKeyStore records.
   APP_DATA_STORE holds project/settings data AND IdbKeyStore's raw
   non-extractable CryptoKey (local_crypto_key_v2) plus per-provider encrypted
   API keys (api_key_<provider>_enc/_iv, legacy gemini_api_key_*). The adapter
   only reserved the migration journal + passphrase sentinel keys, so
   enabling/rotating/disabling encryption would JSON.stringify the CryptoKey
   (destroying it) and re-encrypt the already-encrypted API-key bytes as if
   they were plaintext project data — permanently losing every stored API key.
   idbKeyStore.ts now exports isKeyStoreRecordKey(), wired into the app-data
   adapter via a new isReservedKey predicate (reservedKeys alone can't express
   the dynamic per-provider key family).

New regression coverage: 6 resumeEncryptionMigration committing-phase tests
(both operations × not-yet-committed / partially-committed sub-states), a
real disable+rekey round-trip proving a stored API key survives migration,
and 11 direct unit tests for valuesMatch's Blob comparison + isKeyStoreRecordKey.
All 98 pre-existing storageEncryptionService tests still pass unmodified.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- ErrorBoundary: new `fallback` render-prop lets a boundary override the
  default non-blocking ErrorFallback; wired into App.tsx's
  EncryptionRecoveryModal boundary so a crash inside the recovery modal
  still renders a blocking, focus-trapped Modal instead of leaving the
  app underneath interactive during a pending disable/rekey recovery.
- Condense every wrapped QNBS-v3 comment introduced this PR (App.tsx,
  EncryptionRecoveryModal.tsx) to the required single physical line.
- docs/adr/0018: fix stale "disable/rekey rejected outright" and
  "cross-tab admission not shipped" claims to match the current
  implementation.
- docs/IDB-ENCRYPTION.md: correct the protected-write call-path
  description — save paths snapshot the key via resolveProtectedWriteKey()
  then re-check only assertNoActiveEncryptionMigration() pre-transaction;
  delete paths call assertIdbProtectedWriteAllowed() directly.
- tests/unit/storage/storageEncryptionService.test.ts: give every test a
  fresh IDBFactory instead of one shared factory for the whole file, via
  new _resetDbForTest()/_resetSentinelStoreForTest() exports alongside the
  existing __resetEncryptionMigrationJournalConnectionsForTest() —
  closes a latent cross-test leak where an encrypted record from one
  test could outlive its salt/sentinel into a later test.
- tests/unit/hooks/useSettingsView.test.ts: add the rotate-failure
  coverage mirroring the existing disable-failure test.
- tests/unit/ErrorBoundary.test.tsx: cover the new fallback prop.

Assessed as already resolved by earlier commits in this PR (no further
change needed, verified against current code):
- PassphraseModal.tsx's rotate-mode catch already distinguishes a
  credential-mismatch IdbWrongPassphraseError (only ever thrown by the
  pre-migration old-passphrase check) from any other migration/journal
  failure, with test coverage for both paths.
- primaryProtectedStoreAdapter.ts's verify()/migrateNext() both skip
  isReservedKey() records via readBatch(), so clearGeminiApiKey()/
  clearApiKey() can no longer desync checkpoint.processed vs. verified —
  isKeyStoreRecordKey() already excludes them from migration scope entirely.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- src-tauri/osv-scanner.toml: add the GHSA-jmr9-qjv8-65gv (extract-zip)
  ignore entry already present on the sibling fix/333-download-progress-metrics
  branch — no fixed version exists, transitive Playwright devDependency only.
- .gitguardian.yaml: extend the existing "Generic Password" false-positive
  path exclusion to storageEncryptionService.test.ts, which pairs fake
  sourcePassphrase/targetPassphrase fixture literals ('original', 'new-pass',
  'wrong-old', ...) exercising the disable/rotate/recovery flows against
  fake-indexeddb — same detector, same false-positive class already
  documented for the locale trees above.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
settings.privacy.encryptionDisableConfirm was updated in English to a
detailed warning ("This will decrypt all your data and turn off at-rest
encryption...") but the other 18 locales still carried the old short
"Disable encryption" label. Since PassphraseModal renders this key as the
disable-mode warning paragraph (not a button label), non-English users
were seeing a misleading warning for a sensitive, irreversible-feeling
action. Translated properly for all 18 remaining locales and rebuilt bundles.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The IgnoredVulns entry itself was already added to
src-tauri/osv-scanner.toml in an earlier commit on this branch;
this adds the AUDIT.md documentation the repo's own housekeeping
policy requires for accepted dependency risk.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… commits

Resolves overlapping edits between this stacked i18n branch and #342's own
correction-loop work, which also touched locales/*/settings.json (both English
source wording and several locales' translations for the encryption
disable/rotate/recovery UI strings evolved independently after this branch
diverged).

Conflicts in the 19 locales/*/settings.json files were resolved with a
scripted 3-way per-key JSON merge (git's textual merge conflates adjacent
JSON lines into hunks even when only some individual keys actually conflict)
using this policy:
- Only one side changed a key from the merge base -> take that side.
- Both changed it identically, or only one side has a real (non-English)
  translation -> take the real translation.
- Both sides have differing real translations -> take #342's (verified this
  is not arbitrary: #342's non-English wording for every such key matches
  #342's own updated English source exactly, confirming its correction loop
  updated English + every translation together as one coherent unit, while
  this branch was simply stale relative to that whole update).
- ar/he/fa (documented English-fallback RTL stubs) -> always track #342's
  newer English source on conflict.
- The one key where this branch's content was genuinely unique and never
  touched by #342 (settings.privacy.encryptionDisableConfirm's fuller,
  more informative EN copy) was preserved.

All 19 public/locales/*/bundle.json files were regenerated fresh via
`pnpm run i18n:bundle` rather than hand-merged (2914 keys x 19 locales,
clean). Every other locale module file (characters/common/outline/worlds/
writer/etc.) this branch touches had no overlap with #342 and merged
automatically with no conflicts. All non-locale code/test/doc files from
#342's correction loop also merged automatically with no conflicts.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@gitguardian

gitguardian Bot commented Aug 13, 2026

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 7 secrets following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secrets in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
36028823 Triggered Generic Password 0ddcb44 tests/unit/storage/storageEncryptionService.test.ts View secret
36028823 Triggered Generic Password 423c115 tests/unit/storage/storageEncryptionService.test.ts View secret
36042393 Triggered Generic Password 423c115 tests/unit/storage/storageEncryptionService.test.ts View secret
36028823 Triggered Generic Password 423c115 tests/unit/storage/storageEncryptionService.test.ts View secret
36028823 Triggered Generic Password 8cd4989 tests/unit/storage/storageEncryptionService.test.ts View secret
36042393 Triggered Generic Password 8cd4989 tests/unit/storage/storageEncryptionService.test.ts View secret
36028823 Triggered Generic Password 8cd4989 tests/unit/storage/storageEncryptionService.test.ts View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secrets safely. Learn here the best practices.
  3. Revoke and rotate these secrets.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

qnbs and others added 4 commits August 13, 2026 04:34
These 9 threads were still unresolved from an earlier review pass on this
branch, surfaced while preparing to merge all 5 open PRs:

- services/storage/storageEncryptionService.ts: fixed a real data-integrity
  bug in resumeEncryptionMigration's committing-phase rekey recovery. The
  try block wrapped deriveAndVerifySourceKeyFromSentinel,
  deriveAndVerifyTargetKeyFromVerifier, AND commitRekeyMigration together, so
  a commitRekeyMigration failure (after both passphrases had already verified
  successfully) fell into the catch block, which then re-verified the target
  passphrase, concluded "the commit must have already happened," and cleared
  the journal — even though commitRekeyMigration had genuinely failed and the
  durable sentinel could still hold the old passphrase while stores were
  already re-encrypted under the new key. With no journal left, neither
  passphrase could unlock the library. Isolated source-passphrase
  verification into its own try/catch so only a genuine source-verify
  failure enters the "maybe already committed" recovery branch; a
  commitRekeyMigration failure now propagates as a retryable error with the
  journal intact.
- tests/unit/storage/storageEncryptionService.test.ts: added the missing
  hasPassphraseSentinel() assertion to the "rejects when neither passphrase
  matches" test, matching its disable counterpart, so a regression that
  clears the journal/sentinel on a failed recovery would fail this test.
  Renamed all fixture passphrase literals ('original', 'new-pass',
  'wrong-old', 'wrong-new') to an unambiguous 'test-fixture-*-passphrase'
  pattern to reduce GitGuardian false-positive risk.
- .gitguardian.yaml: documented why the test file's path exclusion remains
  (occurrence-scoped ignored_matches would be the narrower ideal, but
  computing their SHA256 hashes requires the ggshield CLI + an authenticated
  scan, unavailable in this environment) now that the fixture rename above
  reduces the practical risk the exclusion covers.
- 7 locales (el, fi, fr, it, ko, pt, ru): fixed mistranslated or
  inconsistent encryption-UI strings (Greek "disable" read as "make
  incapable"; Korean used "unused" instead of "at rest" for encryption, and
  a literal-translation "disable" verb instead of the idiomatic term; Russian
  "disable" read as "forbid"; French/Italian's stuck-recovery message named
  "the data" instead of "the migration" as unresumable; Finnish mixed
  "salasana"/"tunnuslause" for passphrase inconsistently; Portuguese's AI
  provider ready-status showed the infinitive "prepare" instead of "ready").
  Rebuilt all 19 runtime bundles via `pnpm run i18n:check` (2914 keys x 19
  locales, clean).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
CI's doc-metrics drift gate (scripts/check-doc-metrics.mjs) caught this: the
i18n additions from this branch's own correction-loop work plus the merged-in
stacked i18n branch raised the key count from 2904 to 2914, but README.md's
four "2904 keys" mentions (badge + 3 prose references) were never updated to
match. Regenerated via `node scripts/sync-readme-metrics.mjs`.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Base automatically changed from feat/encryption-migration-phase4-b to main August 13, 2026 04:27
PR #342 was squash-merged into main, creating a new commit distinct from the
individual commits this branch had already merged in from
feat/encryption-migration-phase4-b. This produced a fresh set of textual
conflicts in the 19 locales/*/settings.json files, but only ever the same
single key already resolved once before: settings.privacy.encryptionDisableConfirm.
This branch's own translation work (in all 19 languages, not just English)
gives it a fuller, more informative warning than main's terse placeholder —
kept this branch's version everywhere, matching the resolution already
applied to this same key in the prior merge commit.

Rebuilt all 19 public/locales/*/bundle.json bundles fresh via
`pnpm run i18n:check` (2914 keys x 19 locales, clean) rather than resolving
their conflicts by hand.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@qnbs
qnbs merged commit 9999c45 into main Aug 13, 2026
8 of 11 checks passed
@qnbs
qnbs deleted the feat/encryption-migration-phase4-b-i18n branch August 13, 2026 04:34
@codecov

codecov Bot commented Aug 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

qnbs added a commit that referenced this pull request Aug 13, 2026
Real conflicts (not just textual noise) resolved:

- hooks/useSettingsView.ts + tests/unit/hooks/useSettingsView.test.ts: this
  branch's D5 useMemo-wrapped context-value fix was missing `migrationProgress`
  from its returned object — main's independently-added encryption feature had
  it, this branch's earlier refactor didn't carry it forward. Merged both: kept
  the useMemo optimization, added migrationProgress to the memoized object and
  its dependency array. Test mocks reconciled the same way — kept this branch's
  stable-toast pattern (the actual regression test for the D5 fix) while
  aliasing mockToastInfo/mockToastSuccess to stableToast's own methods so the
  existing encryption tests' assertions against those names keep working.
- CHANGELOG.md: two genuinely distinct "### Fixed" entries from different PRs
  (#332's desktop boot/SettingsView fixes vs. #341/#344's AI Writing Studio
  readability fixes) — kept both.
- README.md + locales/*/settings.json (el/fi/hu/is/pt/sv) + their bundles:
  mix of stale i18n key-count badges (regenerated via
  `node scripts/sync-readme-metrics.mjs` post-merge rather than guessing) and
  the same encryptionSetupFailed/providerStatusReady translation conflicts
  already resolved once in the previous merge commit — reapplied the same
  per-key resolution (whichever side has the real, non-English translation).
  Rebuilt all 19 bundles fresh via `pnpm run i18n:check` (2915 keys x 19
  locales, clean) rather than resolving bundle.json conflicts by hand.
- src-tauri/osv-scanner.toml: cosmetic-only comment-header conflict (both
  sides already had the identical extract-zip IgnoredVulns entry) — kept the
  more current review-date comment.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
qnbs added a commit that referenced this pull request Aug 13, 2026
Real conflicts resolved:

- CHANGELOG.md: three genuinely distinct "### Fixed" entries from different
  PRs (#341/#344's AI Writing Studio readability fixes, already in main, vs.
  this branch's own voice-download-progress-scale fix) — kept both.
- locales/pt/settings.json + its bundle: same providerStatusReady
  ("Preparar" infinitive vs. the already-fixed "Pronto") conflict already
  resolved on the other branches this session — took main's already-correct
  side, since this branch never touched that key.
- README.md: stale i18n key-count/test-file-count badges — regenerated via
  `node scripts/sync-readme-metrics.mjs` post-merge rather than guessing
  (2918 keys × 19 locales, 547 test files).
- src-tauri/osv-scanner.toml: cosmetic-only comment-header conflict (both
  sides already had the identical extract-zip IgnoredVulns entry) — kept the
  more current review-date comment.

Rebuilt all 19 public/locales/*/bundle.json bundles fresh via
`pnpm run i18n:check` rather than resolving bundle.json conflicts by hand.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
qnbs added a commit that referenced this pull request Aug 13, 2026
…ontradictory local-only doc

- CHANGELOG.md: the [1.27.0] section never documented its own headline
  feature (#342/#343's disable-encryption/passphrase-rotation production
  wiring) and still carried the prior release's "intentionally unavailable
  ... see issue #338" caveat, directly contradicting what shipped in this
  same version (chatgpt-codex-connector). Added the missing entry, qualified
  the stale caveat as describing that point in time, and corrected the Docs
  section's "opened issue #338" line to note it closed in this release.
- docs/DEEPSOURCE-REVIEW-LOOP.md: two restored local-only tracking commits
  (originally discarded by an earlier `git reset --hard`, recovered via
  cherry-pick) carried "LOCAL-ONLY — not pushed to remote" / "do not push
  this entry upstream" wording that became false the moment they were
  committed to a pushed branch (qodo-code-review, coderabbitai). Removed the
  contradictory local-only framing, keeping the content as a normal dated
  log entry. Also softened the JS-0440 remediation TODO's "consider a
  rule-level ignore repo-wide" suggestion per coderabbitai's security
  concern — a blanket ignore would hide future unsafe
  `dangerouslySetInnerHTML` uses, not just the one reviewed occurrence.

The public/sw.js QNBS-v3-comment findings (qodo-code-review, coderabbitai)
were false positives — the existing single-line QNBS-v3 comment on the line
directly above APP_VERSION was already unchanged by this PR's one-line
version-bump diff; verified via `git diff main~1 -- public/sw.js`.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
qnbs added a commit that referenced this pull request Aug 13, 2026
…reliability fixes (#351)

* docs(deepsource): log re-surfaced JS-0440 finding (local-only, not for push)

Co-Authored-By: GitHub Copilot (Claude Sonnet 5) <noreply@github.com>

* docs(deepsource): correct stale JS-0440 disposition, re-surfaced 2026-08-01 (local-only)

Co-Authored-By: GitHub Copilot (Claude Sonnet 5) <noreply@github.com>

* release: v1.27.0 — Phase 4 encryption production wiring + desktop/AI reliability fixes

Closes out issue #338 (Phase 4 of the at-rest encryption lifecycle): disable
encryption and passphrase rotation are now live in Settings › Privacy,
backed by the durable resumable migration journal built in the prior
release. Also ships three independently-diagnosed reliability/UX fixes:

- Tauri desktop cold boot never read persisted state back (#332) — every
  desktop launch loaded as a brand-new user regardless of what was actually
  saved to disk; boot hydration now mirrors the already-correct save path.
  Quitting also now awaits any pending debounced autosave instead of risking
  a mid-debounce data loss.
- AI Writing Studio manuscript text was unreadable, with the caret/selection
  visually drifting from the real text (#341) — a blur/font-mismatch/
  scroll-desync defect in the invisible-input-over-visible-mirror rendering
  pattern used by both Writer Studio and the main manuscript editor.
- Voice and WebLLM model download progress bars showed real byte counts and
  transfer speed instead of a bare percentage, and the voice download bar's
  progress-scale bug (stuck at ~95% for most of the download) is fixed
  (#333 item 1).

All 5 correction-loop PRs (#342-#346) ran to full quiescence before merging
— every CodeRabbit/CodeAnt/Qodo/Sourcery finding fixed or justified with
evidence, 0 unresolved review threads, full CI green (Quality Gate, E2E, E2E
Deep Coverage, Build, Storybook, Lighthouse, Visual Regression) — including
a genuine data-integrity bug found and fixed during that loop: a shared
try/catch in the rekey-resume recovery path could, on a crash immediately
after `commitRekeyMigration`, misinterpret that crash as "already committed"
and clear the migration journal while the durable sentinel still held the
old passphrase — leaving neither passphrase able to unlock the library.

2919 i18n keys × 19 locales.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix: address PR #351 review findings — stale CHANGELOG claim + self-contradictory local-only doc

- CHANGELOG.md: the [1.27.0] section never documented its own headline
  feature (#342/#343's disable-encryption/passphrase-rotation production
  wiring) and still carried the prior release's "intentionally unavailable
  ... see issue #338" caveat, directly contradicting what shipped in this
  same version (chatgpt-codex-connector). Added the missing entry, qualified
  the stale caveat as describing that point in time, and corrected the Docs
  section's "opened issue #338" line to note it closed in this release.
- docs/DEEPSOURCE-REVIEW-LOOP.md: two restored local-only tracking commits
  (originally discarded by an earlier `git reset --hard`, recovered via
  cherry-pick) carried "LOCAL-ONLY — not pushed to remote" / "do not push
  this entry upstream" wording that became false the moment they were
  committed to a pushed branch (qodo-code-review, coderabbitai). Removed the
  contradictory local-only framing, keeping the content as a normal dated
  log entry. Also softened the JS-0440 remediation TODO's "consider a
  rule-level ignore repo-wide" suggestion per coderabbitai's security
  concern — a blanket ignore would hide future unsafe
  `dangerouslySetInnerHTML` uses, not just the one reviewed occurrence.

The public/sw.js QNBS-v3-comment findings (qodo-code-review, coderabbitai)
were false positives — the existing single-line QNBS-v3 comment on the line
directly above APP_VERSION was already unchanged by this PR's one-line
version-bump diff; verified via `git diff main~1 -- public/sw.js`.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

---------

Co-authored-by: GitHub Copilot (Claude Sonnet 5) <noreply@github.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant