[REFACTOR] Tauri 도입#29
Conversation
|
Warning Review limit reached
Next review available in: 48 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. WalkthroughElectron JSON DB 경로를 유지하면서 토론 데이터 모델, Rust 기반 Tauri JSON DB, Tauri 프론트엔드 브리지, Electron preload API, Windows용 Electron·Tauri 빌드 워크플로우를 추가했다. ChangesTauri 기반 전환과 DB 통합
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (5)
src-electron/api.test.ts (1)
110-113: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value주석을 훅(hook)의 동작과 일치하도록 수정하세요.
주석에는 "after each test"라고 되어 있으나, 실제로는 모든 테스트가 끝난 후 한 번만 실행되는
afterAll훅을 사용하고 있습니다. 혼동을 피하기 위해 주석을 수정하는 것을 권장합니다.📝 제안하는 수정안
afterAll(async () => { - // Delete all files and temp directory after each test + // Delete all files and temp directory after all tests await fs.rm(TEST_DIR, { recursive: true, force: true }); });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src-electron/api.test.ts` around lines 110 - 113, Update the comment above the afterAll hook to state that files and the temporary directory are deleted after all tests complete, matching the one-time cleanup performed by afterAll.src-electron/preload.ts (1)
2-3: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value타입 전용으로 가져오기(type import)를 사용하세요.
이 파일에서
DebateTableData와UUID는 타입으로만 사용됩니다.import type을 명시적으로 사용하면 빌드 시점에 완전히 지워지므로, 프리로드(preload) 환경에서 발생할 수 있는 불필요한 모듈 해석 문제를 예방할 수 있습니다.♻️ 제안하는 수정안
-import { DebateTableData } from './type'; -import { UUID } from 'crypto'; +import type { DebateTableData } from './type'; +import type { UUID } from 'crypto';🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src-electron/preload.ts` around lines 2 - 3, Update the imports of DebateTableData and UUID in the preload module to use type-only imports, ensuring both type references are removed from the runtime bundle while preserving their existing type usage..github/workflows/build-windows.yml (1)
94-99: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win추가한 Rust lint를 CI에서도 실행하세요.
현재 테스트와 빌드는
cargo fmt --check및clippy -D warnings를 보장하지 않습니다. x64 작업에서npm run lint:tauri:rust를 한 번 실행하면 됩니다.수정 예시
- name: Typecheck Tauri configuration run: npm run lint:tauri:tsc + - name: Lint Tauri Rust backend + if: matrix.architecture == 'x64' + run: npm run lint:tauri:rust + - name: Test Tauri Rust backend🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/build-windows.yml around lines 94 - 99, Add an x64-only CI step in the workflow near the existing Tauri checks to run npm run lint:tauri:rust. Ensure the Windows job executes this Rust lint command so cargo fmt --check and clippy -D warnings are validated alongside the existing Rust tests.src-tauri/tauri.conf.json (2)
26-28: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win보안 강화를 위해 Content Security Policy(CSP) 활성화 권장
"csp": null로 설정하여 Tauri가 제공하는 기본 CSP(콘텐츠 보안 정책) 주입을 비활성화했습니다.index.html내부에 강력한<meta>태그 기반 CSP가 선언되어 있지 않다면, XSS(크로스 사이트 스크립팅) 취약점이 발생했을 때 악의적인 스크립트 실행이나 로컬 데이터 변조를 막아줄 방어막이 얇아집니다.
앱의 전반적인 보안(Defense-in-depth)을 위해 가급적 엄격한 CSP를 설정하는 것을 권장합니다.🛡️ CSP 설정 예시
"security": { - "csp": null + "csp": "default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; connect-src 'self' ipc: http://ipc.localhost" }(앱에서 외부 API를 호출하거나 외부 리소스를 사용한다면 해당 도메인을
connect-src나img-src등에 추가해야 합니다)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src-tauri/tauri.conf.json` around lines 26 - 28, Update the security configuration to enable a strict Content Security Policy instead of setting csp to null. Define the policy using the app’s required resource and API sources, preserving necessary functionality while defaulting to restrictive directives.
26-28: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value보안 강화를 위해 Content Security Policy(CSP) 활성화 권장
"csp": null로 설정하여 Tauri가 제공하는 기본 CSP 주입을 비활성화했습니다.index.html내부에서 강력한<meta>태그 기반 CSP를 이미 제공하고 있지 않다면, XSS(크로스 사이트 스크립팅) 공격 시 방어막이 얇아져 로컬 DB 변조 등의 위험이 발생할 수 있습니다.
앱의 보안을 위해 가급적 엄격한 CSP(예:"default-src 'self'; script-src 'self' 'unsafe-inline'")를 설정하는 것을 권장합니다.🛡️ CSP 설정 예시
"security": { - "csp": null + "csp": "default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; connect-src 'self' ipc: http://ipc.localhost" }(앱에서 외부 API를 호출하거나 외부 이미지를 사용한다면 해당 도메인을
connect-src,img-src등에 추가해야 합니다)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src-tauri/tauri.conf.json` around lines 26 - 28, Update the Tauri security configuration around the csp key to enable a strict Content Security Policy instead of setting csp to null. Use an appropriate policy for the app’s actual script, connection, and image sources, preserving only the required trusted origins and avoiding unnecessary allowances.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/build-windows.yml:
- Around line 49-64: Update the build-tauri job to declare contents read-only
permissions, and configure its actions/checkout@v4 step with persist-credentials
disabled. Keep the existing matrix and build steps unchanged.
In `@package.json`:
- Line 18: Remove the hardcoded --project-token value from the chromatic script
in package.json and configure Chromatic to receive the token through the CI
secret/environment-variable mechanism instead. Revoke the exposed token and
issue a replacement outside the repository.
In `@src-electron/api.ts`:
- Around line 11-16: Update the readDb function to catch fs.readFile errors and
return an empty array when the database file is missing (ENOENT), while
preserving the existing JSON parsing and array validation behavior for existing
files.
In `@src-tauri/src/db.rs`:
- Around line 123-125: Update the Invalid branch in the database read/recovery
flow and replace_with_seed_locked so database writes use a temporary file in the
same directory followed by an atomic replacement. When parsing fails, preserve
the original file by backing it up and return the read error (or invoke an
explicit recovery procedure) instead of deleting it and replacing all user data
with the seed database.
In `@vite.config.tauri.mts`:
- Around line 6-23: tauriDatabaseBridge의 transformIndexHtml 핸들러에서 db.ts의 고정 경로를
제거하고 Vite의 설정된 base를 반영하는 경로로 생성하세요. 프로덕션에서 base가 ./인 경우에도 주입된 script의 src가 올바른
상대 경로가 되도록 하며, 개발 환경의 동작은 유지하세요.
---
Nitpick comments:
In @.github/workflows/build-windows.yml:
- Around line 94-99: Add an x64-only CI step in the workflow near the existing
Tauri checks to run npm run lint:tauri:rust. Ensure the Windows job executes
this Rust lint command so cargo fmt --check and clippy -D warnings are validated
alongside the existing Rust tests.
In `@src-electron/api.test.ts`:
- Around line 110-113: Update the comment above the afterAll hook to state that
files and the temporary directory are deleted after all tests complete, matching
the one-time cleanup performed by afterAll.
In `@src-electron/preload.ts`:
- Around line 2-3: Update the imports of DebateTableData and UUID in the preload
module to use type-only imports, ensuring both type references are removed from
the runtime bundle while preserving their existing type usage.
In `@src-tauri/tauri.conf.json`:
- Around line 26-28: Update the security configuration to enable a strict
Content Security Policy instead of setting csp to null. Define the policy using
the app’s required resource and API sources, preserving necessary functionality
while defaulting to restrictive directives.
- Around line 26-28: Update the Tauri security configuration around the csp key
to enable a strict Content Security Policy instead of setting csp to null. Use
an appropriate policy for the app’s actual script, connection, and image
sources, preserving only the required trusted origins and avoiding unnecessary
allowances.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 953c9fc0-a873-4f10-ac95-668f0d59ad30
⛔ Files ignored due to path filters (2)
package-lock.jsonis excluded by!**/package-lock.jsonsrc-tauri/Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (28)
.github/workflows/build-windows.yml.gitignore.stylelintignoreeslint.config.mjspackage.jsonsrc-electron/api.test.tssrc-electron/api.tssrc-electron/constants.tssrc-electron/main.tssrc-electron/preload.tssrc-electron/type.tssrc-tauri/Cargo.tomlsrc-tauri/build.rssrc-tauri/capabilities/default.jsonsrc-tauri/frontend/db.test.tssrc-tauri/frontend/db.tssrc-tauri/src/commands.rssrc-tauri/src/db.rssrc-tauri/src/lib.rssrc-tauri/src/main.rssrc-tauri/src/model.rssrc-tauri/src/seed.rssrc-tauri/tauri.conf.jsonsrc/renderer.d.tstsconfig.node.jsontsconfig.tauri.jsonvite.config.electron.mtsvite.config.tauri.mts
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 5
🧹 Nitpick comments (5)
src-electron/api.test.ts (1)
110-113: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value주석을 훅(hook)의 동작과 일치하도록 수정하세요.
주석에는 "after each test"라고 되어 있으나, 실제로는 모든 테스트가 끝난 후 한 번만 실행되는
afterAll훅을 사용하고 있습니다. 혼동을 피하기 위해 주석을 수정하는 것을 권장합니다.📝 제안하는 수정안
afterAll(async () => { - // Delete all files and temp directory after each test + // Delete all files and temp directory after all tests await fs.rm(TEST_DIR, { recursive: true, force: true }); });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src-electron/api.test.ts` around lines 110 - 113, Update the comment above the afterAll hook to state that files and the temporary directory are deleted after all tests complete, matching the one-time cleanup performed by afterAll.src-electron/preload.ts (1)
2-3: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value타입 전용으로 가져오기(type import)를 사용하세요.
이 파일에서
DebateTableData와UUID는 타입으로만 사용됩니다.import type을 명시적으로 사용하면 빌드 시점에 완전히 지워지므로, 프리로드(preload) 환경에서 발생할 수 있는 불필요한 모듈 해석 문제를 예방할 수 있습니다.♻️ 제안하는 수정안
-import { DebateTableData } from './type'; -import { UUID } from 'crypto'; +import type { DebateTableData } from './type'; +import type { UUID } from 'crypto';🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src-electron/preload.ts` around lines 2 - 3, Update the imports of DebateTableData and UUID in the preload module to use type-only imports, ensuring both type references are removed from the runtime bundle while preserving their existing type usage..github/workflows/build-windows.yml (1)
94-99: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win추가한 Rust lint를 CI에서도 실행하세요.
현재 테스트와 빌드는
cargo fmt --check및clippy -D warnings를 보장하지 않습니다. x64 작업에서npm run lint:tauri:rust를 한 번 실행하면 됩니다.수정 예시
- name: Typecheck Tauri configuration run: npm run lint:tauri:tsc + - name: Lint Tauri Rust backend + if: matrix.architecture == 'x64' + run: npm run lint:tauri:rust + - name: Test Tauri Rust backend🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/build-windows.yml around lines 94 - 99, Add an x64-only CI step in the workflow near the existing Tauri checks to run npm run lint:tauri:rust. Ensure the Windows job executes this Rust lint command so cargo fmt --check and clippy -D warnings are validated alongside the existing Rust tests.src-tauri/tauri.conf.json (2)
26-28: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win보안 강화를 위해 Content Security Policy(CSP) 활성화 권장
"csp": null로 설정하여 Tauri가 제공하는 기본 CSP(콘텐츠 보안 정책) 주입을 비활성화했습니다.index.html내부에 강력한<meta>태그 기반 CSP가 선언되어 있지 않다면, XSS(크로스 사이트 스크립팅) 취약점이 발생했을 때 악의적인 스크립트 실행이나 로컬 데이터 변조를 막아줄 방어막이 얇아집니다.
앱의 전반적인 보안(Defense-in-depth)을 위해 가급적 엄격한 CSP를 설정하는 것을 권장합니다.🛡️ CSP 설정 예시
"security": { - "csp": null + "csp": "default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; connect-src 'self' ipc: http://ipc.localhost" }(앱에서 외부 API를 호출하거나 외부 리소스를 사용한다면 해당 도메인을
connect-src나img-src등에 추가해야 합니다)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src-tauri/tauri.conf.json` around lines 26 - 28, Update the security configuration to enable a strict Content Security Policy instead of setting csp to null. Define the policy using the app’s required resource and API sources, preserving necessary functionality while defaulting to restrictive directives.
26-28: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value보안 강화를 위해 Content Security Policy(CSP) 활성화 권장
"csp": null로 설정하여 Tauri가 제공하는 기본 CSP 주입을 비활성화했습니다.index.html내부에서 강력한<meta>태그 기반 CSP를 이미 제공하고 있지 않다면, XSS(크로스 사이트 스크립팅) 공격 시 방어막이 얇아져 로컬 DB 변조 등의 위험이 발생할 수 있습니다.
앱의 보안을 위해 가급적 엄격한 CSP(예:"default-src 'self'; script-src 'self' 'unsafe-inline'")를 설정하는 것을 권장합니다.🛡️ CSP 설정 예시
"security": { - "csp": null + "csp": "default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; connect-src 'self' ipc: http://ipc.localhost" }(앱에서 외부 API를 호출하거나 외부 이미지를 사용한다면 해당 도메인을
connect-src,img-src등에 추가해야 합니다)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src-tauri/tauri.conf.json` around lines 26 - 28, Update the Tauri security configuration around the csp key to enable a strict Content Security Policy instead of setting csp to null. Use an appropriate policy for the app’s actual script, connection, and image sources, preserving only the required trusted origins and avoiding unnecessary allowances.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/build-windows.yml:
- Around line 49-64: Update the build-tauri job to declare contents read-only
permissions, and configure its actions/checkout@v4 step with persist-credentials
disabled. Keep the existing matrix and build steps unchanged.
In `@package.json`:
- Line 18: Remove the hardcoded --project-token value from the chromatic script
in package.json and configure Chromatic to receive the token through the CI
secret/environment-variable mechanism instead. Revoke the exposed token and
issue a replacement outside the repository.
In `@src-electron/api.ts`:
- Around line 11-16: Update the readDb function to catch fs.readFile errors and
return an empty array when the database file is missing (ENOENT), while
preserving the existing JSON parsing and array validation behavior for existing
files.
In `@src-tauri/src/db.rs`:
- Around line 123-125: Update the Invalid branch in the database read/recovery
flow and replace_with_seed_locked so database writes use a temporary file in the
same directory followed by an atomic replacement. When parsing fails, preserve
the original file by backing it up and return the read error (or invoke an
explicit recovery procedure) instead of deleting it and replacing all user data
with the seed database.
In `@vite.config.tauri.mts`:
- Around line 6-23: tauriDatabaseBridge의 transformIndexHtml 핸들러에서 db.ts의 고정 경로를
제거하고 Vite의 설정된 base를 반영하는 경로로 생성하세요. 프로덕션에서 base가 ./인 경우에도 주입된 script의 src가 올바른
상대 경로가 되도록 하며, 개발 환경의 동작은 유지하세요.
---
Nitpick comments:
In @.github/workflows/build-windows.yml:
- Around line 94-99: Add an x64-only CI step in the workflow near the existing
Tauri checks to run npm run lint:tauri:rust. Ensure the Windows job executes
this Rust lint command so cargo fmt --check and clippy -D warnings are validated
alongside the existing Rust tests.
In `@src-electron/api.test.ts`:
- Around line 110-113: Update the comment above the afterAll hook to state that
files and the temporary directory are deleted after all tests complete, matching
the one-time cleanup performed by afterAll.
In `@src-electron/preload.ts`:
- Around line 2-3: Update the imports of DebateTableData and UUID in the preload
module to use type-only imports, ensuring both type references are removed from
the runtime bundle while preserving their existing type usage.
In `@src-tauri/tauri.conf.json`:
- Around line 26-28: Update the security configuration to enable a strict
Content Security Policy instead of setting csp to null. Define the policy using
the app’s required resource and API sources, preserving necessary functionality
while defaulting to restrictive directives.
- Around line 26-28: Update the Tauri security configuration around the csp key
to enable a strict Content Security Policy instead of setting csp to null. Use
an appropriate policy for the app’s actual script, connection, and image
sources, preserving only the required trusted origins and avoiding unnecessary
allowances.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 953c9fc0-a873-4f10-ac95-668f0d59ad30
⛔ Files ignored due to path filters (2)
package-lock.jsonis excluded by!**/package-lock.jsonsrc-tauri/Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (28)
.github/workflows/build-windows.yml.gitignore.stylelintignoreeslint.config.mjspackage.jsonsrc-electron/api.test.tssrc-electron/api.tssrc-electron/constants.tssrc-electron/main.tssrc-electron/preload.tssrc-electron/type.tssrc-tauri/Cargo.tomlsrc-tauri/build.rssrc-tauri/capabilities/default.jsonsrc-tauri/frontend/db.test.tssrc-tauri/frontend/db.tssrc-tauri/src/commands.rssrc-tauri/src/db.rssrc-tauri/src/lib.rssrc-tauri/src/main.rssrc-tauri/src/model.rssrc-tauri/src/seed.rssrc-tauri/tauri.conf.jsonsrc/renderer.d.tstsconfig.node.jsontsconfig.tauri.jsonvite.config.electron.mtsvite.config.tauri.mts
🛑 Comments failed to post (5)
.github/workflows/build-windows.yml (1)
49-64: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash set -euo pipefail printf '%s\n' '--- .github/workflows/build-windows.yml (outline) ---' ast-grep outline .github/workflows/build-windows.yml --view expanded || true printf '\n%s\n' '--- relevant lines ---' nl -ba .github/workflows/build-windows.yml | sed -n '1,140p' printf '\n%s\n' '--- search for permissions / persist-credentials in workflows ---' rg -n "permissions:|persist-credentials|actions/checkout@v4" .github/workflows -S || trueRepository: debate-timer/debate-timer-fe-win
Length of output: 338
🏁 Script executed:
#!/bin/bash set -euo pipefail printf '%s\n' '--- .github/workflows/build-windows.yml ---' cat -n .github/workflows/build-windows.yml | sed -n '1,180p' printf '\n%s\n' '--- workflow-level permission/checkout search ---' rg -n "^(permissions:|\\s+persist-credentials:|\\s+uses: actions/checkout@v4)" .github/workflows -S || trueRepository: debate-timer/debate-timer-fe-win
Length of output: 4307
build-tauri에 최소 권한을 명시하고 checkout 자격 증명을 남기지 마세요.
permissions: contents: read를 추가하고actions/checkout에persist-credentials: false를 설정하면, 빌드 중 불필요한 쓰기 권한과 토큰 잔존을 줄일 수 있습니다.🧰 Tools
🪛 zizmor (1.26.1)
[warning] 63-64: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
[warning] 49-110: overly broad permissions (excessive-permissions): default permissions used due to no permissions: block
(excessive-permissions)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/build-windows.yml around lines 49 - 64, Update the build-tauri job to declare contents read-only permissions, and configure its actions/checkout@v4 step with persist-credentials disabled. Keep the existing matrix and build steps unchanged.Source: Linters/SAST tools
package.json (1)
18-18: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash set -euo pipefail # Show the relevant package.json section with line numbers sed -n '1,80p' package.json | nl -ba # Locate any other Chromatic references in the repository rg -n "chromatic|chpt_[A-Za-z0-9]+" .Repository: debate-timer/debate-timer-fe-win
Length of output: 210
🏁 Script executed:
#!/bin/bash set -euo pipefail echo "=== package.json ===" cat -n package.json | sed -n '1,80p' echo echo "=== Chromatic references ===" rg -n "chromatic|chpt_[A-Za-z0-9]+" . || trueRepository: debate-timer/debate-timer-fe-win
Length of output: 5204
Chromatic 토큰을 제거하고 교체하세요.
package.json:18의--project-token하드코딩은 저장소 접근자에게 노출됩니다. 스크립트에서 토큰을 빼고 CI secret/환경변수로 주입한 뒤, 현재 토큰은 폐기·재발급하세요.🧰 Tools
🪛 Betterleaks (1.6.1)
[high] 18-18: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@package.json` at line 18, Remove the hardcoded --project-token value from the chromatic script in package.json and configure Chromatic to receive the token through the CI secret/environment-variable mechanism instead. Revoke the exposed token and issue a replacement outside the repository.Source: Linters/SAST tools
src-electron/api.ts (1)
11-16: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
초기 읽기 시 데이터베이스 파일이 없는 경우를 처리하세요.
앱의 첫 실행 등 데이터베이스 파일이 아직 생성되지 않은 상태에서
fs.readFile이 호출되면ENOENT에러가 발생하여 앱 초기화나postItem등의 작업이 실패하게 됩니다. 에러를catch로 잡아서 파일이 존재하지 않는 경우 빈 배열을 반환하도록 예외 처리를 추가하는 것이 좋습니다.🛠️ 제안하는 수정안
async function readDb(dbPath: string) { - const data = await fs.readFile(dbPath, 'utf-8'); - const parsedData = JSON.parse(data); - return Array.isArray(parsedData) ? parsedData : []; + try { + const data = await fs.readFile(dbPath, 'utf-8'); + const parsedData = JSON.parse(data); + return Array.isArray(parsedData) ? parsedData : []; + } catch (error: any) { + if (error.code === 'ENOENT') { + return []; + } + throw error; + } }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.// Read database (helper function for API requests) async function readDb(dbPath: string) { try { const data = await fs.readFile(dbPath, 'utf-8'); const parsedData = JSON.parse(data); return Array.isArray(parsedData) ? parsedData : []; } catch (error: any) { if (error.code === 'ENOENT') { return []; } throw error; } }🧰 Tools
🪛 ast-grep (0.44.1)
[warning] 12-12: Filesystem path is not a string literal; a request-/variable-derived path can enable path traversal. Validate and normalize the path before use.
Context: fs.readFile(dbPath, 'utf-8')
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').(detect-non-literal-fs-filename-typescript)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src-electron/api.ts` around lines 11 - 16, Update the readDb function to catch fs.readFile errors and return an empty array when the database file is missing (ENOENT), while preserving the existing JSON parsing and array validation behavior for existing files.src-tauri/src/db.rs (1)
123-125: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
손상된 JSON 하나로 전체 사용자 DB를 초기화하지 마세요.
현재 파일을 직접 덮어쓰므로 쓰기 중 종료 시 부분 JSON이 남을 수 있고, 다음 읽기에서는 해당 파일을 삭제한 뒤 seed로 교체합니다. 단일 레코드의 스키마 오류도 같은 방식으로 모든 토론 데이터를 영구 삭제합니다.
같은 디렉터리의 임시 파일에 기록한 뒤 원자적으로 교체하고, 파싱 실패 파일은 삭제하지 말고 백업한 후 오류를 반환하거나 명시적인 복구 절차를 제공해 주세요.
Also applies to: 143-145
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src-tauri/src/db.rs` around lines 123 - 125, Update the Invalid branch in the database read/recovery flow and replace_with_seed_locked so database writes use a temporary file in the same directory followed by an atomic replacement. When parsing fails, preserve the original file by backing it up and return the read error (or invoke an explicit recovery procedure) instead of deleting it and replacing all user data with the seed database.vite.config.tauri.mts (1)
6-23: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash # Vite 빌드를 수행하고 index.html의 변환 결과를 확인합니다. npm run tauri:frontend:build || npx vite build -c vite.config.tauri.mts cat dist/tauri-renderer/index.html | grep db.ts || echo "db.ts가 별도 파일로 분리되지 않았거나 번들링 후 해시된 파일명으로 변경되었는지 확인해야 합니다."Repository: debate-timer/debate-timer-fe-win
Length of output: 15588
🏁 Script executed:
#!/bin/bash set -euo pipefail printf '\n## vite.config.tauri.mts\n' if [ -f vite.config.tauri.mts ]; then cat -n vite.config.tauri.mts else echo 'missing' fi printf '\n## index.html / related html files\n' git ls-files '*.html' | sed -n '1,20p' for f in $(git ls-files '*.html'); do printf '\n### %s\n' "$f" cat -n "$f" done printf '\n## src-tauri/frontend/db.ts and references\n' git ls-files | rg '^src-tauri/frontend/db\.ts$|^src-tauri/frontend/|db\.ts$|tauri-database-bridge|transformIndexHtml|base:' -n || true printf '\n## any imports/references to /src-tauri/frontend/db.ts\n' rg -n --hidden --glob '!node_modules' '/src-tauri/frontend/db\.ts|src-tauri/frontend/db\.ts|db\.ts' .Repository: debate-timer/debate-timer-fe-win
Length of output: 2789
🌐 Web query:
Vite transformIndexHtml injected script tag absolute src base './' build rewrite module script entry handling💡 Result:
In Vite, the base path configuration ('base: "./"') is primarily intended for production builds to generate relative asset paths, making the deployment host-agnostic [1][2]. However, this behavior often conflicts with manual script injection via the transformIndexHtml hook, which may produce absolute paths that break in sub-path deployments [3][4]. Key Technical Considerations: 1. Base Configuration (./): Setting base to './' in your vite.config.ts directs Vite to use relative paths for built assets [1]. During the build process, Vite automatically rewrites standard <script> tags in index.html to respect this relative base [1]. 2. transformIndexHtml Injection: When you manually inject a <script> tag via the transformIndexHtml hook, Vite does not automatically rewrite the src attribute of your custom tag during the build [5][6]. It treats your injected tag as literal HTML and injects it as-is [4]. 3. Handling Entry Points: To ensure your injected scripts work in both development (where absolute paths like /src/main.js are typically required by the dev server) and production (where relative paths are required), you must handle the logic inside the hook based on the command [4]: Implementation Pattern: You can check viteConfig.command within your plugin to conditionally set the path [4]. // Example Logic transformIndexHtml(html, { bundle }) { const isBuild = process.env.NODE_ENV === 'production'; // Or check viteConfig.command const src = isBuild? './my-script.js': '/my-script.js'; return [ { tag: 'script', attrs: { type: 'module', src }, injectTo: 'body', }, ]; } 4. Ordering: Always ensure your transformIndexHtml hook uses order: 'pre' if you need the script to be processed by Vite's pipeline, or 'post' if you want it to run after Vite has already processed the HTML [7][5][8]. For script injection, 'pre' or 'post' depends on whether you want the injected script to be subject to further transformations (like asset hashing or minification) [7]. If your injected script needs to reference hashed assets generated by Vite, you should look up the resulting filename in the bundle object provided to the transformIndexHtml hook rather than hardcoding paths [4].
Citations:
- 1: https://github.com/vitejs/vite/blob/main/docs/guide/build.md
- 2: https://github.com/vitejs/vite/blob/64dfee12/docs/config/shared-options.md
- 3: vitejs/vite#15099
- 4: storybookjs/storybook#33792
- 5: vitejs/vite#13319
- 6: vitejs/vite#5166
- 7: https://vite.dev/guide/api-plugin
- 8: vitejs/vite#14263
🌐 Web query:
Vite transformIndexHtml injected module script src build entry relative base rewrite official docs💡 Result:
Vite does not provide a native, direct configuration option within the transformIndexHtml hook to automatically rewrite or force-inject relative paths for build entry scripts [1][2]. When using transformIndexHtml, keep the following technical considerations in mind: 1. Handling of Build Entry Points: Vite processes index.html entry points during the build to resolve assets, apply hashing, and update paths based on the base configuration [3][4]. If you inject a script tag manually via transformIndexHtml, Vite might not automatically process the src attribute if the hook logic does not account for the build pipeline or if the injection happens after standard path resolution [5][6]. 2. Injection Order: To ensure your injected tags interact correctly with the build process, consider using the order property in your plugin hook (e.g., order: 'pre') [5]. This ensures your transformation occurs before other plugins or internal Vite HTML processing [7]. 3. Base URL and Relative Paths: Vite typically handles absolute path rewriting based on the base configuration [3][4]. If you require relative paths (like./assets/...), you may need to manually compute the path relative to the current HTML file's location within your plugin's transformIndexHtml implementation, as Vite's internal processors prioritize configured base paths [3][8][4]. 4. Plugin Strategy: If you need to modify script tags injected by Vite or dynamically inject your own, a common pattern is to return an array of tags from the transformIndexHtml hook [1][5]. For complex manipulations (like rewriting paths to be relative), many developers use the hook to perform a string replacement or DOM-like transformation on the HTML content [9][6]. Note that if you are attempting to modify existing tags, you must ensure your hook executes at the appropriate stage (pre or post) relative to Vite's internal HTML plugins [7][6]. For further implementation, consult the official Vite Plugin API documentation regarding the IndexHtmlTransformHook interface, which allows for either returning a transformed HTML string or an array of tag objects for injection [1].
Citations:
- 1: https://vite.dev/guide/api-plugin
- 2: https://vite.dev/guide/api-javascript
- 3: https://vite.dev/config/build-options
- 4: https://github.com/vitejs/vite/blob/main/packages/vite/src/node/server/middlewares/indexHtml.ts
- 5: vitejs/vite#13319
- 6: vitejs/vite#5851
- 7: https://github.com/vitejs/vite/blob/main/packages/vite/src/node/plugins/html.ts
- 8: vitejs/vite#13763
- 9: vitejs/vite#11926
🌐 Web query:
site:vite.dev transformIndexHtml injected script tag rewritten by build base config src attribute official💡 Result:
When using the Vite transformIndexHtml hook to inject a script tag, Vite does not automatically rewrite the src attribute of manually injected tags to respect the build.base configuration. You are responsible for ensuring the injected path accounts for the base public path [1][2]. To correctly handle the base path in your injected script: 1. Retrieve the current base configuration from the Vite config object. The transformIndexHtml hook provides access to the server or bundle, but the base path is generally available via the resolved configuration. 2. Manually prepend the base path to your script src. Example implementation: import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ { name: 'inject-script-with-base', configResolved(config) { this.base = config.base; }, transformIndexHtml { return [ { tag: 'script', attrs: { src:
${this.base}path/to/your/script.js, type: 'module' }, injectTo: 'head' } ]; } } ] }); If you are injecting a script that you want Vite to process (e.g., resolve as a module, add hashes, or apply base path rewriting automatically), you should use the tag injection mechanism provided by transformIndexHtml returning an array of HtmlTagDescriptor objects [3]. However, Vite's automatic base path rewriting primarily applies to static references in your source index.html file during the build process, not necessarily to dynamic strings returned by plugin hooks unless Vite explicitly processes those specific attributes [1][2]. To ensure reliability, manually prefixing with the resolved base path is the recommended official approach [1].Citations:
- 1: https://v2.vite.dev/guide/build
- 2: https://v2.vite.dev/guide/build.html
- 3: https://v2.vite.dev/guide/api-plugin
/src-tauri/frontend/db.ts를 base-aware 경로로 바꾸세요
transformIndexHtml로 주입한 태그는base: './'를 자동 반영하지 않아서, 프로덕션 빌드에/src-tauri/frontend/db.ts가 그대로 남을 수 있습니다. 이 경우 Tauri 배포판에서 모듈을 찾지 못합니다.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@vite.config.tauri.mts` around lines 6 - 23, tauriDatabaseBridge의 transformIndexHtml 핸들러에서 db.ts의 고정 경로를 제거하고 Vite의 설정된 base를 반영하는 경로로 생성하세요. 프로덕션에서 base가 ./인 경우에도 주입된 script의 src가 올바른 상대 경로가 되도록 하며, 개발 환경의 동작은 유지하세요.
🚩 연관 이슈
Closes #26
Closes #27
Closes #28
📝 작업 내용
1. 변경 개요
기존 Electron 빌드와 실행 경로를 유지하면서, 같은 React 애플리케이션을 Windows용 Tauri 앱으로도 빌드하고 사용할 수 있도록 기반을 추가했습니다.
window.db계약을 변경하지 않고 Tauri Rust 백엔드와 연결했습니다.src/**React 구현과 Electron 백엔드의 기능 동작은 변경하지 않았습니다.2. Electron과 Tauri 빌드 체계 분리
Electron
electron/에서src-electron/으로 이동했습니다.vite.config.mts를vite.config.electron.mts로 변경하고 관련 npm script와 TypeScript 설정의 참조를 함께 수정했습니다.Tauri
src-tauri/에 Tauri 2 프로젝트와 Windows 전용 설정을 추가했습니다.디베이트 타이머로 설정했습니다.Debate Timer (Tauri)로 유지했습니다.com.debatetimer.app.tauri로 분리했습니다.dist/tauri-renderer와src-tauri/target에 별도로 생성됩니다.3. Electron/Tauri 데이터 소스 격리
두 앱을 동시에 실행해도 같은 JSON 파일을 조작하지 않도록 저장 경로를 분리했습니다.
4. Rust DB 백엔드 구현
Electron의 TypeScript 백엔드 동작을 다음 Rust 모듈로 나누어 이식했습니다.
model.rs— TypeScript interface에 대응하는 데이터 모델DebateTableData,DebateInfo,TimeBoxInfo구조체를 정의했습니다.Stance,TimeBoxTypeenum을 정의하고 기존 JSON 문자열인PROS,CONS,NEUTRAL,NORMAL,TIME_BASED와 호환되도록 구성했습니다.serde의 camelCase 변환을 통해 기존 JSON key를 그대로 유지합니다.null이 가능한 값은Option<T>로 표현했습니다. 이는 TypeScript의T | null또는 optional 값과 유사합니다.#[serde(flatten)]map에 보관합니다. 따라서 데이터를 읽고 다시 저장해도 추가 필드가 사라지지 않습니다.seed.rs— Electron 초기 데이터 이식src-electron/constants.ts의 초기 토론 2건을 값 단위로 동일하게 옮겼습니다.datetime을 저장합니다.db.rs— JSON DB와 CRUD 처리get,get_all,post,delete,patch의 반환 동작과 없는 ID 처리 방식을 기존 Electron 구현에 맞췄습니다.tokio::sync::Mutex로 한 Tauri 프로세스 안의 read-modify-write 작업을 직렬화해 동시 요청에 의한 lost update를 방지합니다.commands.rs와lib.rs— Electron IPC handler에 대응하는 진입점commands.rs의db_get,db_get_all,db_post,db_delete,db_patch는 Electron의 IPC handler와 같은 역할을 합니다.db.rs에 배치했습니다.Result<T, DbError>는 TypeScript 관점에서 성공 시 resolve되고 실패 시 reject되는 Promise와 유사합니다.lib.rs는 앱 시작 시 Tauri 전용 DB 경로를 계산하고 초기화를 완료한 다음,DbState와 다섯 command를 Tauri에 등록합니다.5. React와 Rust 연결
src-tauri/frontend/db.ts에서@tauri-apps/api/core의invoke를 기존window.dbAPI로 변환합니다.vite.config.tauri.mts가 이 bridge를 기존 React entry보다 먼저 주입합니다.window.db를 그대로 사용합니다.@tauri-apps/api호출이 포함되지 않습니다.6. 의존성과 품질 설정
@tauri-apps/cli: Tauri 개발 및 빌드 명령@tauri-apps/api: 프런트엔드에서 Rust command 호출serde,serde_json: 모델 및 JSON 직렬화/역직렬화uuid: UUID v4 생성chrono: 로컬 시각 생성과 정렬tokio: 비동기 파일 I/O와 mutexthiserror: DB 오류 구분tempfile: 격리된 Rust DB 테스트7. GitHub Actions
기존
buildjob을 다음 두 job으로 분리했습니다.build-electronbuild-tauri8. 테스트 및 빌드 결과
npm run lintnpm run lint:tauricargo checkcargo checkRust 테스트에는 다음 항목이 포함됩니다.
🏞️ 스크린샷 (선택)
UI 변경 없이 동일한 React 화면을 Electron과 Tauri에서 사용하므로 별도 스크린샷은 첨부하지 않았습니다.
🗣️ 리뷰 요구사항 (선택)
권장 리뷰 순서
Rust가 익숙하지 않은 경우 다음 순서로 보면 TypeScript/Electron 구조와 비교하기 쉽습니다.
src-tauri/frontend/db.tswindow.db호출이 어떤 Tauri command로 변환되는지 확인합니다.src-tauri/src/commands.rssrc-tauri/src/model.rssrc-tauri/src/db.rssrc-tauri/src/seed.rssrc-tauri/src/lib.rs중점 확인 요청
delete해도 현재 배열을 저장하고 반환합니다.patch해도 DB는 바뀌지 않지만 전달받은 항목을 반환합니다.Mutex는 Tauri 프로세스 내부 요청만 보호하며, 여러 Tauri 프로세스가 같은 파일을 동시에 조작하는 경우는 이번 범위 밖입니다.(Tauri)를 제거했지만 내부 바이너리 이름에는 구분을 위해 유지했습니다.Summary by CodeRabbit
새 기능
개선 사항