Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
6 changes: 4 additions & 2 deletions AUDIT.md
Original file line number Diff line number Diff line change
@@ -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).

Expand Down
23 changes: 16 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Comment thread
qnbs marked this conversation as resolved.

### Added

- **Durable encryption migration journal** (`services/storage/encryptionMigrationJournal.ts`) —
Expand Down Expand Up @@ -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

Expand All @@ -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
Expand Down Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<img src="https://img.shields.io/badge/TypeScript-7.x_(tsgo)-3178C6?logo=typescript&logoColor=white" alt="TypeScript 7 (tsgo)">
<img src="https://img.shields.io/badge/AI-Gemini_%7C_OpenAI_%7C_OpenRouter_%7C_Ollama_%7C_WebLLM-4285F4?logo=google" alt="Gemini · OpenAI · OpenRouter · Ollama · WebLLM">
<img src="https://img.shields.io/badge/Local_AI-WebGPU_%7C_ONNX_%7C_Transformers.js-8B5CF6" alt="WebGPU · ONNX · Transformers.js">
<img src="https://img.shields.io/badge/Version-v1.26.0-6366F1" alt="v1.26.0">
<img src="https://img.shields.io/badge/Version-v1.27.0-6366F1" alt="v1.27.0">
<img src="https://img.shields.io/badge/Storage-IndexedDB_v8-F59E0B" alt="IndexedDB v8">
<img src="https://img.shields.io/badge/PWA-v3.0-5BB974?logo=pwa" alt="PWA v3.0">
<img src="https://img.shields.io/badge/i18n-19_locales-2919_keys-0EA5E9" alt="i18n 19 locales — 2919 keys">
Expand Down
4 changes: 2 additions & 2 deletions docs/DEEPSOURCE-REMEDIATION-PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down Expand Up @@ -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 `<script>`-tag global pollution; repo-wide pattern, not a per-file fix. Informational-only check (not in required-status list). See `DEEPSOURCE-REVIEW-LOOP.md` §11, 2026-08-01 entry. | 2026-08-01 |

## 6. Definition of done
Expand Down
Loading
Loading