diff --git a/.github/SECURITY.md b/.github/SECURITY.md
index 5b08e80c9..86617284a 100644
--- a/.github/SECURITY.md
+++ b/.github/SECURITY.md
@@ -4,8 +4,8 @@
| Version | Supported |
| --- | --- |
-| `main` (v1.26.0) | ✅ Full support |
-| `1.3.x – 1.25.0` | ⚠️ Best effort (upgrade strongly recommended) |
+| `main` (v1.27.0) | ✅ Full support |
+| `1.3.x – 1.26.0` | ⚠️ Best effort (upgrade strongly recommended) |
| `< 1.3.0` | ❌ Not supported |
Maintainer-facing documentation (CI, contributing, architecture) is indexed in [`README.md`](README.md#-documentation-hub) and enumerated in [`AUDIT.md`](AUDIT.md).
diff --git a/AGENTS.md b/AGENTS.md
index 9739a6f9d..76fc1a6bb 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -11,7 +11,7 @@
- **Primary deploy target:** Static SPA on GitHub Pages (`/WorldScript-Studio/` base path)
- **Secondary targets:** Vercel (root base) and Cloudflare Pages via edge builds (`pnpm run build:edge`)
- **Desktop:** Tauri 2 bundles for Linux (AppImage), macOS (DMG), and Windows (MSI); auto-updater enabled via `latest.json`
-- **Version:** `1.26.0`
+- **Version:** `1.27.0`
- **License:** MIT
The app supports a multi-provider AI stack (Gemini, OpenAI, Claude, Grok, OpenRouter, Ollama, WebLLM, ONNX Runtime Web, Transformers.js), four AI execution modes (Hybrid / Cloud / Local / Eco), real-time collaboration with E2E encryption, a Plot Board v2 with swimlane/canvas/timeline modes, character/world management, manuscript export, voice dictation, and a 19-locale i18n layer.
diff --git a/AUDIT.md b/AUDIT.md
index 153bc597d..612d1a571 100644
--- a/AUDIT.md
+++ b/AUDIT.md
@@ -1,8 +1,10 @@
# WorldScript Studio — Codebase Audit Report
-**Date:** 2026-04-17 (baseline); **follow-up chain:** … → 2026-05-28 (v1.19.0 — Security/Voice/RTL/Logger B-1..B-8) → **2026-05-30 (B-1 passphrase UX + CI unblock)** → **2026-05-31 (i18n audit + settings features + CI stabilization)** → **2026-05-31 (Edge-AI Perfection Cycle — Phases 0-7 complete)** → **2026-06-01 (Post-crash session: CI stabilisation + 14 CodeAnt AI fixes + E2E hardening)** → **2026-06-02 (Perf Phase 2.3 — pipeline-LRU unification + PR #69 CodeAnt fixes)** → **2026-06-03 (WorkerBus v2 Phase 3 — Rust TaskSupervisor + Tauri-build unblock)** → **2026-06-06 (Phase 3 i18n Expansion — ja/zh/pt/el + Intl APIs)** → **2026-06-09 (v1.21 Deep Audit Correction — Whisper WASM download UI + 3 CodeAnt fixes + CloudSync LWW)** → **2026-06-09 (feat/deep-audit-v1.21 — CSP hardening, zh locale ≤5% EN, coverage Batches A/B/C, VoiceActivityCoordinator B-2 bridge)** → **2026-06-11 (Ultimate Copilot v2 Phase 2+3 — markdown, sidebar, Apply-to-chapter, InlineAnnotation, ProForge chip; PR #110+#111)** → **2026-06-11 (v1.22.0 release — OpenRouter Cloud 5 provider, AI Execution Modes hybrid/cloud/local/eco, AiModeIndicator, SW cache-invalidation fix)** → **2026-06-13/14 (v1.23 perfection batch — OpenRouter + AI-Execution-Mode settings sections localized/modernized, i18n single-brace interpolation bug-class fix + `i18nPlaceholders` regression guard, bundle split + budget tightening PR #130)** → **2026-06-16 (v1.23.0 release — rebrand StoryCraft → WorldScript Studio, local-first data foundation ADR-0008, Tauri blank-screen + asset-URL fixes, AI error taxonomy + retry hardening, command-palette & local-AI settings localization, WorldScript W monogram icons)** → **2026-06-16 (post-release documentation perfection pass — corpus sync, metric reconciliation, history archival, dependabot hardening)** → **2026-06-17 (Language expansion — +6 locales fi/sv/hu/is/eu/fa (RTL); PR #174 merged; `LanguageSelector` exonym localization via `portal.language.names.*`; portal chrome 100 % for the 6 new langs; README/AUDIT/CHANGELOG docs sync)** → **2026-07-28 (v1.24.1 — Local-AI reliability fixes #266, Dependabot backlog triage, Issue #60 audit closeout, security/build hardening)** → **2026-07-29 (v1.24.2, PR #284 — CSP functional-truth, desktop crypto, and doc-truth hardening; the local-inference stack had been silently non-functional in production for two months; merged and tagged)** → **2026-07-30 (v1.24.3, WorkerBus v2 worker-generation consolidation — 5 stacked PRs #286–288/#290–291 + independent #289 recovered after an interrupted merge queue; ADR-0015; merged and tagged)** → **2026-08-12 (encryption lifecycle + desktop reliability + recovery journal — stacked PRs #335/#336/#337 merged into `main`; fail-closed IDB encryption lifecycle, desktop AI/Python provider hardening for #332/#333, durable resumable migration journal with secondary-store adapters; PR #339 closes the write-vs-migration TOCTOU race CodeRabbit and Qodo independently found on #337; PR #310 closed as superseded; Phase-4 production wiring for disable/rotate tracked as issue #338)**
+**Date:** 2026-04-17 (baseline); **follow-up chain:** … → 2026-05-28 (v1.19.0 — Security/Voice/RTL/Logger B-1..B-8) → **2026-05-30 (B-1 passphrase UX + CI unblock)** → **2026-05-31 (i18n audit + settings features + CI stabilization)** → **2026-05-31 (Edge-AI Perfection Cycle — Phases 0-7 complete)** → **2026-06-01 (Post-crash session: CI stabilisation + 14 CodeAnt AI fixes + E2E hardening)** → **2026-06-02 (Perf Phase 2.3 — pipeline-LRU unification + PR #69 CodeAnt fixes)** → **2026-06-03 (WorkerBus v2 Phase 3 — Rust TaskSupervisor + Tauri-build unblock)** → **2026-06-06 (Phase 3 i18n Expansion — ja/zh/pt/el + Intl APIs)** → **2026-06-09 (v1.21 Deep Audit Correction — Whisper WASM download UI + 3 CodeAnt fixes + CloudSync LWW)** → **2026-06-09 (feat/deep-audit-v1.21 — CSP hardening, zh locale ≤5% EN, coverage Batches A/B/C, VoiceActivityCoordinator B-2 bridge)** → **2026-06-11 (Ultimate Copilot v2 Phase 2+3 — markdown, sidebar, Apply-to-chapter, InlineAnnotation, ProForge chip; PR #110+#111)** → **2026-06-11 (v1.22.0 release — OpenRouter Cloud 5 provider, AI Execution Modes hybrid/cloud/local/eco, AiModeIndicator, SW cache-invalidation fix)** → **2026-06-13/14 (v1.23 perfection batch — OpenRouter + AI-Execution-Mode settings sections localized/modernized, i18n single-brace interpolation bug-class fix + `i18nPlaceholders` regression guard, bundle split + budget tightening PR #130)** → **2026-06-16 (v1.23.0 release — rebrand StoryCraft → WorldScript Studio, local-first data foundation ADR-0008, Tauri blank-screen + asset-URL fixes, AI error taxonomy + retry hardening, command-palette & local-AI settings localization, WorldScript W monogram icons)** → **2026-06-16 (post-release documentation perfection pass — corpus sync, metric reconciliation, history archival, dependabot hardening)** → **2026-06-17 (Language expansion — +6 locales fi/sv/hu/is/eu/fa (RTL); PR #174 merged; `LanguageSelector` exonym localization via `portal.language.names.*`; portal chrome 100 % for the 6 new langs; README/AUDIT/CHANGELOG docs sync)** → **2026-07-28 (v1.24.1 — Local-AI reliability fixes #266, Dependabot backlog triage, Issue #60 audit closeout, security/build hardening)** → **2026-07-29 (v1.24.2, PR #284 — CSP functional-truth, desktop crypto, and doc-truth hardening; the local-inference stack had been silently non-functional in production for two months; merged and tagged)** → **2026-07-30 (v1.24.3, WorkerBus v2 worker-generation consolidation — 5 stacked PRs #286–288/#290–291 + independent #289 recovered after an interrupted merge queue; ADR-0015; merged and tagged)** → **2026-08-12 (encryption lifecycle + desktop reliability + recovery journal — stacked PRs #335/#336/#337 merged into `main`; fail-closed IDB encryption lifecycle, desktop AI/Python provider hardening for #332/#333, durable resumable migration journal with secondary-store adapters; PR #339 closes the write-vs-migration TOCTOU race CodeRabbit and Qodo independently found on #337; PR #310 closed as superseded; Phase-4 production wiring for disable/rotate tracked as issue #338)** → **2026-08-13 (v1.27.0 — Phase 4 encryption disable/rotate production wiring + i18n (#342/#343 close issue #338), Tauri desktop boot-hydration + flush-on-quit + Settings re-render perf fixes (#332, PR #345), AI Writing Studio unreadable-text fix (#341, PR #344), download-progress bytes/speed for voice + WebLLM models (#333 item 1, PR #346); all 5 PRs' correction loops ran to full quiescence — codebase-wide QNBS-v3/i18n fixes, a real data-integrity bug found and fixed in the rekey-recovery try/catch scoping, and sequential main-reconciliation merges across the whole 5-PR stack)**
**Scope:** Full application, repository configuration, CI/CD, documentation, release validation
-**Current version:** **v1.26.0** — the WorkerBus inactivity watchdog and memory-tier sizing, native desktop notifications, and the residual audit's authoritative bounded-scheduler correction are consolidated into this minor release. **2904 keys × 19 locales**. Historical release sections below remain historical.
+**Current version:** **v1.27.0** — Phase 4 closes out the encryption lifecycle feature (issue #338: production disable/rotate wiring, now user-facing in Settings › Privacy), alongside three independently-shipped reliability/UX fixes for #332, #333, and #341. **2919 keys × 19 locales**. Historical release sections below remain historical.
+
+**Quality gate (2026-08-13 — v1.27.0, 5-PR merge):** lint ✅ · typecheck ✅ (tsgo) · i18n:check ✅ (**2919 keys × 19 locales**) · targeted unit tests ✅ across all 5 PRs' correction loops (storageEncryptionService 75 tests, useSettingsView 38, VoiceModelDownloadModal/voiceCommandService/downloadProgressFormat, desktopTray/desktopMenu, ContextPanel/Textarea, and the full post-merge reconciliation suite) · CI Quality Gate (Node 22 + 24), E2E, E2E Deep Coverage, Build, Storybook, Lighthouse, and Visual Regression all green on every one of #342/#343/#344/#345/#346's final commits. #342 (disable/rotate production wiring), #343 (its stacked i18n), #344 (#341 fix), #345 (#332 fix), #346 (#333 item 1) all merged into `main`. Phase-4 (issue #338) is now fully closed — encryption disable and passphrase rotation are live in the Settings UI.
**Quality gate (2026-08-12 — encryption lifecycle + desktop reliability + recovery journal):** lint ✅ · typecheck ✅ (tsgo) · i18n:check ✅ (**2904 keys × 19 locales**) · targeted unit tests ✅ (271 across the full affected storage suite post-merge: `protectedStoreMigration`, `encryptionMigrationJournal`, `secondaryPayloadStoreAdapter(s)`, `protectedWriteAdmission`, `idbStoreEncryption`, `dbService*`, `sceneRevisionService`, `aiInferenceCacheService`) · CI Quality Gate (Node 22 + 24) green on #337/#339 · codecov/patch ✅ (73.46% → target after adding secondary-adapter payload-shape coverage). #335 (fail-closed lifecycle), #336 (desktop AI/Python hardening for #332/#333), #337 (durable migration journal + secondary-store adapters), #339 (cross-tab write-admission fixing the migration TOCTOU race) all merged into `main`. PR #310 closed as superseded (`docs/PR-310-RECONCILIATION.md`). Production disable/passphrase-rotation wiring remains open Phase-4 work — [issue #338](https://github.com/qnbs/WorldScript-Studio/issues/338).
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ee40851b1..e943880c7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+## [1.27.0] — 2026-08-13
+
### Added
- **Durable encryption migration journal** (`services/storage/encryptionMigrationJournal.ts`) —
@@ -38,6 +40,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
total MB and speed, derived from the existing 0-1 progress fraction × a new per-model known-size
table (`WEBLLM_MODEL_APPROX_MB`) — the installed `@mlc-ai/web-llm`'s own progress callback exposes
no structured byte counts, so this is clearly labeled as an estimate, not measured telemetry.
+- **Disabling at-rest encryption and rotating the storage passphrase are now live** in Settings ›
+ Privacy — the production wiring the prior release's migration journal was built for. Both flows
+ run through the same resumable, crash-recoverable migration journal, verify identity via a
+ durable AES-GCM sentinel/verifier before touching any data, and surface an `EncryptionRecoveryModal`
+ on next startup if a migration was interrupted mid-flight. Closes
+ [issue #338](https://github.com/qnbs/WorldScript-Studio/issues/338). (#342, #343)
### Changed
@@ -47,10 +55,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
where an intervening `await` (opening a transaction, awaiting encryption) could let Lock Session
race a write into plaintext. Every previously-unguarded destructive/listing path (`deleteImage`,
`deleteBinderAsset`, `listBinderAssetIds`, `deleteStoryCodex`, `listSnapshots`, `deleteSnapshot`,
- `deleteProject`) now has the same guard. Disabling encryption or rotating the passphrase is
- intentionally unavailable until the migration journal's resumable conversion protocol is wired to
- a production trigger — see [issue #338](https://github.com/qnbs/WorldScript-Studio/issues/338).
- (#335)
+ `deleteProject`) now has the same guard. At the time of this change, disabling encryption or
+ rotating the passphrase was intentionally unavailable pending the migration journal's resumable
+ conversion protocol being wired to a production trigger — see the "Added" section above for the
+ production wiring that shipped in this same release. (#335)
- **Desktop AI provider and Python integration hardening**, addressing user-reported release-quality
issues #332/#333: removed the brittle Gemini `AIza`-prefix key rejection in favor of minimal
syntax checks plus real provider validation; Local AI cancel/retry now operates on the actual
@@ -121,9 +129,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Closed out the [PR #310 reconciliation ledger](docs/PR-310-RECONCILIATION.md) as **superseded** —
#335/#336/#337 are merged into `main`, satisfying the one condition its merge decision previously
left open. PR #310 itself was never merged; its own branch remained non-resumable throughout.
-- Opened [issue #338](https://github.com/qnbs/WorldScript-Studio/issues/338) tracking the remaining
- Phase-4 work: wiring the migration journal to a real disable/passphrase-rotation UI flow, primary
- IDB-store adapters, and the two above race-condition fixes' production reachability.
+- Opened, then closed in this same release, [issue #338](https://github.com/qnbs/WorldScript-Studio/issues/338)
+ tracking the Phase-4 work: wiring the migration journal to a real disable/passphrase-rotation UI
+ flow, primary IDB-store adapters, and the two above race-condition fixes' production reachability
+ — all landed via #342/#343 (see "Added" above).
## [1.26.0] — 2026-08-01
diff --git a/README.md b/README.md
index e960f167f..66401b016 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@
-
+
diff --git a/docs/DEEPSOURCE-REMEDIATION-PLAN.md b/docs/DEEPSOURCE-REMEDIATION-PLAN.md
index bbdb9416d..5bd1199d1 100644
--- a/docs/DEEPSOURCE-REMEDIATION-PLAN.md
+++ b/docs/DEEPSOURCE-REMEDIATION-PLAN.md
@@ -71,7 +71,7 @@ Fix in this order — highest user/security impact first; cosmetic last. Within
| Issue code | Title | Occ. | Files / modules | Decision | Status | PR |
|---|---|---|---|---|---|---|
| CWE/SANS Top-25 rows | code-level Top-25 CWE violations | **0** | — | none needed (clean) | done | — |
-| **JS-0440** | Avoid dangerous JSX props — `dangerouslySetInnerHTML` (CWE-937 / OWASP; the report's "1 active") | 1 | `components/HelpView.tsx:125` | **dashboard "Ignore" (reviewed-safe)** — `__html` is `DOMPurify.sanitize()`d (repo's documented safe pattern); not a real XSS. In-code `skipcq` can't attach to a JSX attribute (§4b). | maintainer-click | — |
+| **JS-0440** | Avoid dangerous JSX props — `dangerouslySetInnerHTML` (CWE-937 / OWASP; the report's "1 active") | 1 | `components/HelpView.tsx:125` | **dashboard "Ignore" (reviewed-safe)** — `__html` is `DOMPurify.sanitize()`d (repo's documented safe pattern); not a real XSS. In-code `skipcq` can't attach to a JSX attribute (§4b). **Re-surfaced 2026-08-01** as an active, non-ignored **Major** finding on the dashboard — the 2026-06-24 ignore click did not persist (or a rescan reset it); re-click Ignore and re-verify after the next full-repo scan. | todo (re-ignore + verify) | — |
### P1 — Bug-risk / Reliability
| Issue code | Title | Occ. | Files / modules | Decision | Status | PR |
@@ -150,7 +150,7 @@ config level (`.deepsource.toml`) instead of scattering inline `skipcq`. Log eac
| Rule / analyzer | Action | Rationale | Date |
|---|---|---|---|
| **JS-0323** (`any`) | dashboard rule-ignore, **test-file scope** | 34 occ all in test mocks, already governed by Biome `noExplicitAny` + the suppression ratchet (baseline 52); double-suppressing is noise. 0 production `any`. Long-term cleanup → §4c. | 2026-06-24 |
-| **JS-0440** (`dangerouslySetInnerHTML`) | dashboard "Ignore" (single occurrence) | reviewed-safe — `__html` is DOMPurify-sanitized (repo policy). In-code skipcq can't attach to a JSX attribute (§4b). | 2026-06-24 |
+| **JS-0440** (`dangerouslySetInnerHTML`) | dashboard "Ignore" (single occurrence) — **re-click needed, see §11 in `DEEPSOURCE-REVIEW-LOOP.md`** | reviewed-safe — `__html` is DOMPurify-sanitized (repo policy). In-code skipcq can't attach to a JSX attribute (§4b). Ignore did not survive to 2026-08-01; re-verified as still safe, only the dashboard-suppression state needs re-applying. | 2026-06-24 (re-observed 2026-08-01) |
| **JS-0067** ("unexpected function declaration in the global scope") | recommend dashboard rule-ignore (not yet actioned — maintainer click) | flagged on PR #305 for ordinary top-level `function`/`async function` declarations in `services/ai/localAiDeviceProfiler.ts` + `services/workerBusManager.ts` — idiomatic Biome-approved ES-module code, not `