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 @@ TypeScript 7 (tsgo) Gemini · OpenAI · OpenRouter · Ollama · WebLLM WebGPU · ONNX · Transformers.js - v1.26.0 + v1.27.0 IndexedDB v8 PWA v3.0 i18n 19 locales — 2919 keys 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 `