feat(deep-audit-v1.21): CSP hardening + zh locale + coverage batches + VAD→Whisper WASM bridge#102
Merged
Conversation
…der endpoints Removed `wss://*.workers.dev wss: ws:` open wildcards from index.html connect-src (XSS WebSocket exfiltration vector). Added all AI provider endpoints that were present in tauri.conf.json but missing from the web CSP: xAI, Groq, OpenRouter, Ollama (localhost:11434), LM Studio (localhost:1234), generic local AI (localhost:8000). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Translated all untranslated zh keys (worlds.json 52, writer.json 80,
settings.json 13, dashboard.json 1, common.json 1, export.json 1,
lora.json 1). Fixed 3 {{token}} localization issues (dashboard.momentum
.ofGoal, writer.studio.tools.improve.instruction, writer.chapter.label).
Result: 10/2358 EN-identical keys (0.4% placeholders, down from 6.3%).
ja was already at 0.9% — no changes needed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ownload, idbAsset - ecoModeService.test.ts: 17 tests covering battery threshold, isCriticalBattery, explicit override, listener lifecycle, applyAdaptiveMode with getBattery mock - localAiDeviceProfiler.test.ts: 11 tests covering recommendBackend branches, cpuCores fallback, platform detection (pwa-web/tauri-desktop), cache TTL, invalidateDeviceProfile, profile shape - voiceDownloadAndIntent.test.ts: 10 tests covering downloadVoiceModels (happy path, pre-aborted signal, mid-download abort, error, TTS model id), handleDictationResult (blank/non-blank), processTranscript (intent found/not found) - idbAssetStore.test.ts: 13 tests covering image CRUD, binder asset CRUD, listBinderAssetIds prefix filter with cursor iteration Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…lizePersistedSettings defaults - cloudSyncBackend.test.ts: +11 tests covering saveStoryCodex/getStoryCodex/deleteStoryCodex, saveRagVectors/getRagVectors (null→empty array)/deleteRagVectors, deviceId meta shape - idbProjectStore.test.ts: +7 tests covering backup/voice/performance/notifications defaults, advancedAi defaults, keyboardShortcuts/writingGoals array normalization Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…T bridge Wires WebRtcVadEngine PCM frames into WasmSttEngine via a dedicated coordinator, completing the P1-2 VAD→Inference→Transcript pipeline. Only activated when enableVoiceWasm + sttEngine.id === 'whisper'. - New: services/voice/voiceActivityCoordinator.ts — frame pump, MIN_SPEECH_CHUNKS gate, MAX_BUFFER_MS flush, clean teardown - feat: voiceCommandService.ts routes start/stop/dispose through coordinator when WASM path is active - test: 12 coordinator unit tests (start/stop/dispose + error paths) - fix: cloudSyncBackend test codex shape (entities[] not characters[]) - fix: idbAssetStore test renamed fields (originalFileName/byteSize) - fix: voiceDownloadAndIntent dispatch shim types + createLogger mock - chore: gitignore .translation-progress-*.json checkpoint files Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- P1-2 marked as VAD→STT bridge complete (VoiceActivityCoordinator shipped) - AUDIT.md follow-up chain extended with feat/deep-audit-v1.21 session entries - Version bumped to v1.21.1 in AUDIT header Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
CodeAnt AI is reviewing your PR. Thanks for using CodeAnt! 🎉We're free for open-source projects. if you're enjoying it, help us grow by sharing. Share on X · |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
CodeAnt AI finished reviewing your PR. |
voiceCommandService now imports voiceActivityCoordinator which calls createLogger at module-level. Any test that mocks services/logger and transitively loads the coordinator needs createLogger in the mock factory. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…mpotent init, CSP https: - voiceActivityCoordinator: null segment from WebRtcVadEngine now preserves lastVadSpeechState instead of coercing to silence (was preventing MIN_SPEECH_CHUNKS from being reached during steady-state speech) - flushStt: isFlushing guard prevents overlapping stop()+start() cycles over Whisper WASM's shared mediaStream/recorder — race would corrupt the capture session on every long utterance - start(): isEngineInitialized flag prevents re-loading the 40 MB Whisper pipeline on every start() call; dispose() resets it so the next lifecycle reinitializes cleanly - index.html: add https: to connect-src so user-configured openAiCompatibleBaseUrl endpoints (arbitrary remote proxies) are not blocked by CSP - coordinator test: switch to vi.stubGlobal/vi.unstubAllGlobals pattern to prevent AudioContext global pollution across test files; FakeAudioContext defined at module level to close over mutable mockAudioCtxInstance; add behavior tests for all three fixed invariants - .gitignore: suppress .translation-progress-*.json checkpoint files Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…pia writing theme - featureFlagsSlice: all 20 flags now default to true so new installs get the full feature set immediately; enableRtlLayout stays false — ar/he locales are stubs only and enabling RTL layout without localized content breaks the UI - settingsSlice: appearancePreset default changed from 'default' to 'sepia' — warm sepia tones reduce eye strain for long writing sessions Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
CodeAnt AI is reviewing your PR. Thanks for using CodeAnt! 🎉We're free for open-source projects. if you're enjoying it, help us grow by sharing. Share on X · |
|
CodeAnt AI finished reviewing your PR. |
…, mobile nav Three root causes fixed: Select dropdown (settings z-index bug): - Select dropdown list: z-[--sc-z-docked] (10) → z-[--sc-z-sticky] (100) - Dropdowns now appear above the VoiceControlPanel FAB (z-50) and mobile nav (z-40) so opening a select in Voice Settings no longer shows the mic button bleeding through VoiceControlPanel (mobile layout): - bottom-4 → bottom-20 on mobile, md:bottom-4 on desktop - Clears the ~60px mobile bottom-nav bar (z-40); FAB was partially hidden behind it - Desktop position unchanged (bottom-4 right-4) ManuscriptEditor word count (overlap fix): - Moved from absolute bottom-4 right-6 (collides with VoiceControlPanel FAB) to absolute bottom-20 left-6 md:bottom-4 - Mobile: word count and voice FAB are now side by side (both at bottom-20, left vs right) - Desktop: word count at bottom-left, voice FAB at bottom-right — no overlap Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ections - PassphraseModal: add 'unlock' mode (re-derives in-memory key without overwriting sentinel), Spinner for busy state, focus-on-mount via useEffect+ref - PrivacySection: fix critical bug — unlock button now opens 'unlock' modal instead of 'set'; add euDataResidency toggle (was in state but never rendered) - SettingsShared ToggleSwitch: add hint prop with aria-describedby wiring - IntegrationsSection: add ariaLabel to sync provider Select; role=status+aria-live on ltMsg feedback; comingSoon hint on unimplemented toggles (Evernote/Notion/Scrivener/GoogleDocs) - CommunitySection: add focus-visible:ring-2 to community links; fix --sc-interactive-bg/fg (non-existent tokens) → --sc-info-bg/fg - i18n: add euDataResidency + comingSoon keys to all 12 locales; rebuild bundles (2351 keys) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
voiceActivityCoordinator: - MIN_SPEECH_CHUNKS 2 → 1: WebRtcVadEngine emits exactly one isSpeech edge per transition, so 2 was unreachable - start(): add early-return guard if already running to prevent double mic stream leak voiceCommandService: - dispose() + null previous coordinator before creating new one on startListening() — prevents leaking audio capture sessions on repeated calls idbAssetStore.test.ts: - Fix storageBackend mock to match real production key contract (sanitize + '::' delimiter) - Update all test key references from 'binder/proj/asset' to 'proj::asset' - Fix getBinderAsset fixture: 'filename' → 'originalFileName', add byteSize: 4 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…reset, 6 privacy toggles - featureFlagsSlice.test: initialState all true except enableRtlLayout; defaultOn cases updated - settingsSlice.test: appearancePreset 'default' → 'sepia' - PrivacySection.test: 5 toggles → 6 (euDataResidency added); mock privacy includes euDataResidency - plotBoardAiThunks.test: duckDbEnabled false → true (enableDuckDbAnalytics now defaults true) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ranslations
Lighthouse accessibility 0.92 → pass:
- index.css: --sc-text-muted darkened from #8a7f72 (3.33:1) to #655c50 (5.57:1 on
#f4ecd8) — covers subtitle, FeatureHighlight descriptions, LanguageSelector chevrons
- index.css: added missing sepia state-color overrides (danger/success/warning/info fg+bg)
that were inheriting dark-theme values (e.g. #4ade80 success-fg = 1.48:1 on sepia bg)
Help center audit & translations:
- locales/en/help.json: 9 keys rewritten (desktop stub, privacy FAQ, API key FAQ,
export formats, flags list 12→21, feature flag count, SHA-256 iter 310k→600k)
- locales/{de,fr,es,it,ja,zh,pt,el,ar,he}/help.json: same 9 keys force-translated via
translate-help-forced.mjs (POST to translate.googleapis.com, no key required)
- scripts/translate-help-forced.mjs: new script for force-updating specific stale keys
across all 10 non-EN locales with proper HTML POST (avoids GET URL-length limits)
- public/locales/*/bundle.json: rebuilt — 2351 keys × 11 locales
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
E2E axe caught two color-contrast failures in the Settings view:
1. <span>General</span> in active settings nav: --nav-text-active #b45309
on blended active-bg (#ecdabf) = 3.66:1 (needs 4.5:1)
2. <button class="text-[var(--sc-accent)]">Sample link</button> in
AccessibilitySection: #b45309 on #f4ecd8 = 4.26:1 (needs 4.5:1)
Root cause: --sc-accent #b45309 (was also --nav-text-active) is too light
for text use on sepia's warm beige surfaces.
Fix: darken accent family in .appearance-sepia
- --sc-accent: #b45309 → #92400e (6.02:1 on base, 5.05:1 on active-nav-bg)
- --sc-accent-hover: #92400e → #78350f
- --sc-accent-subtle: rgba(180,83,9,0.14) → rgba(146,64,14,0.14)
- --sc-accent-glow: rgba(180,83,9,0.28) → rgba(146,64,14,0.28)
- --sc-border-focus: #b45309 → #92400e
- --sc-ring-focus: rgba(180,83,9,0.45) → rgba(146,64,14,0.45)
- --nav-text-active: #b45309 → #92400e
- --nav-background-active: rgba(180,83,9,0.12) → rgba(146,64,14,0.12)
- --sc-warning-fg: #92400e → #9a3412 (now distinct from accent)
White text on primary buttons: 7.09:1 ✓
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The E2E axe color-contrast failures in the sepia theme (fgColor #6d6457 on bgColor #e4d9c5, ratio 4.16:1) were caused by the command-palette fade-in animation running at partial opacity (~0.94) when axe sampled the element. Playwright emulates prefers-reduced-motion:reduce but the animate-in/fade-in class was not gated behind motion-reduce. axe blends fg+bg at that opacity and reports an effective fg that is lighter than the CSS value, producing a false contrast failure. Adding motion-reduce:animate-none to the dialog panel ensures it renders at full opacity instantly under reduced-motion, so axe sees #655c50 on #e8dcc8 (5.19:1, well above 4.5:1 AA). Also adds motion-reduce:transition-none to the backdrop overlay. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
User description
Summary
wss:*wildcard, add explicit AI provider endpoints (openrouter.ai,api.groq.com,api.mistral.ai, Anthropic) and streaming event sourceVoiceActivityCoordinator— bridgesWebRtcVadEnginePCM frames intoWasmSttEnginevia frame pump withMIN_SPEECH_CHUNKSgate andMAX_BUFFER_MSflush. Only activated whenenableVoiceWasm + sttEngine.id === 'whisper'.voiceCommandServicenow routesstart/stop/disposethrough the coordinator on the WASM path. 12 unit tests.entities[]), idbAssetStore (originalFileName/byteSize), voiceDownloadAndIntent dispatch shim types +createLoggermockTest plan
tsgo --noEmit)🤖 Generated with Claude Code
CodeAnt-AI Description
Turn on core features by default, route Whisper voice input through speech detection, and tighten browser access
What Changed
Impact
✅ Faster first-run setup✅ Fewer stuck voice sessions✅ Safer browser connections💡 Usage Guide
Checking Your Pull Request
Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.
Talking to CodeAnt AI
Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:
This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.
Example
Preserve Org Learnings with CodeAnt
You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:
This helps CodeAnt AI learn and adapt to your team's coding style and standards.
Example
Retrigger review
Ask CodeAnt AI to review the PR again, by typing:
Check Your Repository Health
To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.