Skip to content

fix(tauri): resolve Windows blank screen via relative base path#113

Merged
qnbs merged 2 commits into
mainfrom
fix/tauri-windows-runtime-and-p0-p1-hardening-2026-06-12
Jun 12, 2026
Merged

fix(tauri): resolve Windows blank screen via relative base path#113
qnbs merged 2 commits into
mainfrom
fix/tauri-windows-runtime-and-p0-p1-hardening-2026-06-12

Conversation

@qnbs

@qnbs qnbs commented Jun 12, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes the Tauri Windows blank screen issue by making Vite base path detection Tauri-aware.

Changes

Tauri Windows Runtime Fix (Primary)

  • vite.config.ts: Detect TAURI_PLATFORM env var and return './' for Tauri builds
  • src-tauri/src/lib.rs: Add RunEvent handlers (Ready/Opened/SecondInstance) for lifecycle logging and deep-link support

P0/P1 Hardening (Secondary)

  • services/pluginRegistry.ts: Add structured logging for plugin execution (telemetry)
  • tests/unit/plugins/pluginRegistryLoad.test.ts: 7 tests for loadPlugin scenarios (timeout/fetch/error handling)
  • docs/PLUGINS-BETA.md: Document plugin system Beta/opt-in status
  • .npmrc: Add strict-dep-builds, block-exotic-subdeps, minimum-release-age (7 days)
  • pnpm-workspace.yaml: Add security justification comments to overrides
  • stryker.conf.json: Add aiRetry, fetchAdapter, routingLogger to mutation targets
  • AUDIT.md: Document P0/P1 implementation status and known overrides table

Verification

  • TypeScript typecheck: PASSED
  • Biome lint: PASSED
  • Vitest tests: 7/7 passed

Next Steps

Run tauri-build workflow to verify the Tauri build works on Windows.

- vite.config.ts: detect TAURI_PLATFORM env var and return './' for Tauri builds
- src-tauri/src/lib.rs: add RunEvent handlers (Ready/Opened/SecondInstance)
- services/pluginRegistry.ts: add structured logging for plugin execution
- tests/unit/plugins/pluginRegistryLoad.test.ts: 7 tests for loadPlugin scenarios
- docs/PLUGINS-BETA.md: document plugin system Beta status
- .npmrc: add strict-dep-builds, block-exotic-subdeps, minimum-release-age
- pnpm-workspace.yaml: add security justification comments to overrides
- stryker.conf.json: add aiRetry/fetchAdapter/routingLogger to mutate targets
- AUDIT.md: document P0/P1 implementation status and known overrides

QNBS-v3: Tauri builds load via file:// and require relative paths.
The TAURI_PLATFORM env var is set by Tauri CLI during desktop builds.
@codeant-ai

codeant-ai Bot commented Jun 12, 2026

Copy link
Copy Markdown

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 ·
Reddit ·
LinkedIn

@vercel

vercel Bot commented Jun 12, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
storycraft-studio Ready Ready Preview, Comment Jun 12, 2026 6:43am

@codeant-ai codeant-ai Bot added the size:L This PR changes 100-499 lines, ignoring generated files label Jun 12, 2026
Comment thread src-tauri/src/lib.rs Outdated
log::info!("Tauri app ready");
}
tauri::RunEvent::Opened { args, .. } => {
log::info!("Main window opened with args: {:?}", args);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: Avoid logging raw startup arguments in runtime events; either remove this log in production or sanitize it to only emit non-sensitive metadata (for example, count or event type). [custom_rule_security]

Severity Level: Critical 🚨

Why it matters? 🤔

This is a production runtime log (log::info!) that prints the full args payload with debug formatting. The custom rule explicitly flags production logging that could expose sensitive data, so this is a real violation.

Fix in Cursor | Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** src-tauri/src/lib.rs
**Line:** 88:88
**Comment:**
	*Custom Rule Security: Avoid logging raw startup arguments in runtime events; either remove this log in production or sanitize it to only emit non-sensitive metadata (for example, count or event type).

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Comment thread src-tauri/src/lib.rs Outdated
log::info!("Main window opened with args: {:?}", args);
}
tauri::RunEvent::SecondInstance { args, .. } => {
log::info!("Second instance started: {:?}", args);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: Do not log full second-instance argument payloads directly; replace this with a redacted message or restrict it to debug-only execution. [custom_rule_security]

Severity Level: Critical 🚨

Why it matters? 🤔

This is also a production log::info! call that emits the complete args payload. Since the rule forbids production logging that could expose sensitive content, this is a genuine violation.

Fix in Cursor | Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** src-tauri/src/lib.rs
**Line:** 91:91
**Comment:**
	*Custom Rule Security: Do not log full second-instance argument payloads directly; replace this with a redacted message or restrict it to debug-only execution.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Comment thread src-tauri/src/lib.rs Outdated
Comment on lines +90 to +94
tauri::RunEvent::SecondInstance { args, .. } => {
log::info!("Second instance started: {:?}", args);
// Emit deep-link event for deep-link plugin to handle
let _ = app.emit("deep-link://new-url", args);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: This emits deep-link://new-url manually on SecondInstance, even though the deep-link/single-instance plugin already emits that event, which can cause the same deep-link payload to be processed twice (duplicate import/open side effects). Remove the manual emit or gate it so only one source emits the event. [logic error]

Severity Level: Major ⚠️
- ❌ Deep-link file opens import the same project twice.
- ⚠️ Duplicate navigation and notifications for one deep-link.
- ⚠️ Potential race conditions in project import side effects.
Steps of Reproduction ✅
1. The Tauri entrypoint `run()` in `src-tauri/src/lib.rs:39-50` registers
`tauri_plugin_single_instance` and `tauri_plugin_deep_link`, with the comment at lines
42-45 explicitly stating that the deep-link plugin "automatically handles CLI args and
emits \"deep-link://new-url\" event".

2. On the frontend, `services/tauriDeepLink.ts:27-49` defines `initTauriDeepLink`, which
uses `listen('deep-link://new-url', ...)` at line 37 to subscribe to these events and, for
each URL payload, imports the project via `importProjectThunk` and navigates to the
manuscript view (lines 51-95).

3. The same `run()` builder in `src-tauri/src/lib.rs` now attaches a `.on_event` handler
at lines 81-97 that matches `tauri::RunEvent::SecondInstance { args, .. }` and, inside
that arm at lines 90-93, logs `"Second instance started"` and calls `let _ =
app.emit("deep-link://new-url", args);`.

4. When a user opens a `.storycraft` or `.scst` file via OS file association,
`tauri_plugin_single_instance` handles the second-instance CLI args and
`tauri_plugin_deep_link` emits a `"deep-link://new-url"` event once; the additional manual
`app.emit("deep-link://new-url", args)` in `src-tauri/src/lib.rs:90-93` causes
`initTauriDeepLink` to receive a second event for the same open operation, leading to
duplicate `importProjectThunk` dispatches and double-handling (import and navigation) of
the same deep-link payload.

Fix in Cursor | Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** src-tauri/src/lib.rs
**Line:** 90:94
**Comment:**
	*Logic Error: This emits `deep-link://new-url` manually on `SecondInstance`, even though the deep-link/single-instance plugin already emits that event, which can cause the same deep-link payload to be processed twice (duplicate import/open side effects). Remove the manual emit or gate it so only one source emits the event.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Comment on lines +54 to +69
const originalFetch = global.fetch;
global.fetch = vi.fn().mockResolvedValue({
ok: false,
status: 404,
text: () => Promise.resolve(''),
}) as unknown as typeof fetch;

const result = await registry.loadPlugin(
makePlugin({ entrypoint: 'https://example.com/missing.js' }),
mockApi,
);
expect(result.ok).toBe(false);
if (!result.ok) expect(result.error).toMatch(/Failed to fetch plugin/);

// Restore fetch
global.fetch = originalFetch;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: These tests mutate global.fetch but restore it only at the end of each test body; if an assertion throws earlier, cleanup is skipped and subsequent tests inherit the mocked fetch. Move restoration into try/finally (or centralized afterEach) to prevent cross-test contamination. [missing cleanup]

Severity Level: Major ⚠️
- ⚠️ Failing tests can leave global.fetch mocked.
- ⚠️ Subsequent tests rely on polluted global state.
- ⚠️ Test suite behaviour becomes order-dependent and flaky.
Steps of Reproduction ✅
1. In `tests/unit/plugins/pluginRegistryLoad.test.ts:52-70`, the test `it('returns error
when fetch fails with non-OK status', ...)` saves `const originalFetch = global.fetch;` at
line 54 and then overrides it with `global.fetch = vi.fn().mockResolvedValue(...)` at
lines 55-59 before invoking `registry.loadPlugin(...)`.

2. After assertions at lines 61-66, the test restores the original implementation with
`global.fetch = originalFetch;` at line 69; other tests in the same file follow the same
pattern of manual override and restoration (lines 72-87, 89-107, 109-129, 131-153,
155-163).

3. The `afterEach` hook at lines 41-43 only calls `vi.restoreAllMocks()`, which resets vi
mocks and spies but does not revert direct property assignments like `global.fetch = ...`,
so it cannot undo the manual override if the test body exits early.

4. If this test (or any similar one) throws or fails an assertion after `global.fetch` has
been assigned but before `global.fetch = originalFetch;` runs, the jest/vitest runner
skips the trailing cleanup line, leaving `global.fetch` pointing at the mocked function;
subsequent tests then capture this mocked value as their `originalFetch` or rely on it
directly, causing cross-test contamination, order dependence, and hard-to-debug flakiness
whenever a failure occurs mid-test.

Fix in Cursor | Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** tests/unit/plugins/pluginRegistryLoad.test.ts
**Line:** 54:69
**Comment:**
	*Missing Cleanup: These tests mutate `global.fetch` but restore it only at the end of each test body; if an assertion throws earlier, cleanup is skipped and subsequent tests inherit the mocked fetch. Move restoration into `try/finally` (or centralized `afterEach`) to prevent cross-test contamination.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

@codeant-ai

codeant-ai Bot commented Jun 12, 2026

Copy link
Copy Markdown

CodeAnt AI finished reviewing your PR.

- src-tauri/src/lib.rs: Remove sensitive args from logs, remove duplicate deep-link emit
- tests/unit/plugins/pluginRegistryLoad.test.ts: Centralize fetch cleanup in afterEach

Security: Logs no longer expose raw CLI args (could contain file paths/sensitive data).
Logic: Removed duplicate deep-link event emission - the deep-link plugin already handles this.
@qnbs
qnbs merged commit c1b5cbd into main Jun 12, 2026
17 checks passed
@qnbs
qnbs deleted the fix/tauri-windows-runtime-and-p0-p1-hardening-2026-06-12 branch June 12, 2026 07:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L This PR changes 100-499 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant