Skip to content

fix(settings): align defaults with PRD §6.10 (#67)#77

Merged
mpiton merged 13 commits intomainfrom
fix/issue-67-align-settings-defaults-prd
Apr 18, 2026
Merged

fix(settings): align defaults with PRD §6.10 (#67)#77
mpiton merged 13 commits intomainfrom
fix/issue-67-align-settings-defaults-prd

Conversation

@mpiton
Copy link
Copy Markdown
Owner

@mpiton mpiton commented Apr 18, 2026

Summary

  • Aligns 9 AppConfig defaults with PRD §6.10: autoExtract, maxConcurrentDownloads=4, maxRetries=5, retryDelaySeconds=10, verifyChecksums, webInterfacePort=9876, restApiEnabled, websocketEnabled, minFileSizeMb=1.0.
  • Adds resolve_system_download_dir() adapter wrapping dirs::download_dir() so downloadDir resolves cross-platform on first launch (Linux/macOS/Windows). Domain stays pure.
  • Aligns 11 frontend test fixtures that previously masked the divergence.
  • Documents the web_interface_enabled / rest_api_enabled / api_key security triad in the domain model.
  • No migration: existing config.toml files are preserved untouched (only fresh installs get the new defaults).

Closes #67.

Test plan

  • `cargo test --workspace` — 582 passed, 6 ignored
  • `cargo clippy --workspace -- -D warnings` — clean
  • `cargo fmt --check` — clean
  • `npx vitest run` — 367 passed
  • `npm run lint` (oxlint) — 0 warnings, 0 errors
  • Adversarial review (2 parallel reviewers) — 2 MAJOR + 2 MINOR findings addressed
  • Manual: fresh install on Linux — `~/.config/vortex/config.toml` contains `download_dir = "/home/$USER/Downloads"`
  • Manual: existing install — `config.toml` values unchanged

Summary by cubic

Aligns AppConfig defaults with PRD §6.10. On first launch we set downloadDir to the OS Downloads folder and generate a UUIDv4 apiKey (fail-fast if missing) so REST/WS never start unauthenticated; existing configs stay unchanged.

  • New Features

    • Defaults updated: autoExtract on, maxConcurrentDownloads=4, maxRetries=5, retryDelaySeconds=10, verifyChecksums on, minFileSizeMb=1.0, webInterfacePort=9876, restApiEnabled on, websocketEnabled on.
    • Added resolve_system_download_dir() (wraps dirs) to set downloadDir cross‑platform on first launch only.
    • First launch generates a UUIDv4 apiKey; we now fail fast if the bootstrap key is missing/blank to avoid starting REST/WebSocket without auth.
  • Migration

    • No action needed. Existing config.toml files are preserved; new defaults apply to fresh installs only.

Written for commit ac0d017. Summary will update on new commits.

Summary by CodeRabbit

  • Changed
    • Default settings updated: auto-extract enabled, download concurrency 4, retry policy 5 retries with 10s delay, checksum verification enabled, and min file size threshold raised to 1 MB.
    • On first launch the downloads directory now resolves to the OS Downloads folder and an API key is automatically generated.
    • Web interface port changed and remote access (REST API and WebSocket) enabled by default.

@github-actions github-actions Bot added documentation Improvements or additions to documentation rust frontend ui labels Apr 18, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 18, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 05314612-9344-4a4e-a784-0173a51c5fcd

📥 Commits

Reviewing files that changed from the base of the PR and between b996aec and ac0d017.

📒 Files selected for processing (2)
  • src-tauri/src/adapters/driven/config/toml_config_store.rs
  • src-tauri/tests/app_state_wiring.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • src-tauri/tests/app_state_wiring.rs
  • src-tauri/src/adapters/driven/config/toml_config_store.rs

📝 Walkthrough

Walkthrough

This PR aligns runtime defaults with PRD §6.10, injects first-launch defaults for download_dir and api_key, adds a system-download-dir resolver, and updates TomlConfigStore to accept injected defaults; multiple tests and startup wiring were adjusted accordingly.

Changes

Cohort / File(s) Summary
Changelog
CHANGELOG.md
Added Unreleased entry documenting new defaults and first-launch downloadDir/apiKey hydration.
Domain defaults
src-tauri/src/domain/model/config.rs
Changed AppConfig::default() to match PRD §6.10 (autoExtract=true, maxConcurrentDownloads 3→4, maxRetries 3→5, retryDelaySeconds 5→10, verifyChecksums=true, minFileSizeMb 0→1.0, webInterfacePort 9666→9876, restApiEnabled/websocketEnabled → true). Added docs and unit test for defaults.
Config store
src-tauri/src/adapters/driven/config/toml_config_store.rs
TomlConfigStore::new signature extended to accept default_download_dir: Option<String> and default_api_key: Option<String>; on missing TOML, store hydrates AppConfig from injected defaults and validates non-empty API key. Tests updated for first-launch semantics and preservation of persisted values.
Filesystem helper
src-tauri/src/adapters/driven/filesystem/download_dir.rs, src-tauri/src/adapters/driven/filesystem/mod.rs
Added resolve_system_download_dir() -> Option<String> (wraps dirs::download_dir()), re-exported from filesystem module, with platform-conditional test.
Startup wiring & exports
src-tauri/src/lib.rs
Re-exported resolve_system_download_dir; run() now supplies resolve_system_download_dir() and Uuid::new_v4().to_string() to TomlConfigStore::new.
Backend tests & wiring
src-tauri/src/domain/ports/driven/tests.rs, src-tauri/tests/app_state_wiring.rs
Adjusted tests and test wiring to account for new defaults and updated TomlConfigStore::new(...) constructor arguments; updated expected default concurrency to 4.
Frontend tests / fixtures
src/components/__tests__/*, src/hooks/__tests__/*, src/layouts/__tests__/*, src/stores/__tests__/*, src/views/**/__tests__/*
Updated ~11 test fixtures (baseConfig / mockConfig / mockDownloadDetail) to reflect new defaults (autoExtract, maxConcurrentDownloads, retries/delay, verifyChecksums, minFileSizeMb, webInterfacePort, restApiEnabled, websocketEnabled). Minor test adjustment to explicitly override restApiEnabled where needed.

Sequence Diagram(s)

sequenceDiagram
    participant Runner as App::run()
    participant Fs as resolve_system_download_dir()
    participant UUID as Uuid::new_v4()
    participant Store as TomlConfigStore::new()
    Runner->>Fs: query system Downloads dir
    Fs-->>Runner: Option<download_dir>
    Runner->>UUID: generate random api_key (UUIDv4)
    UUID-->>Runner: api_key String
    Runner->>Store: new(config_path, download_dir_opt, Some(api_key))
    alt TOML exists
        Store->>Store: load persisted AppConfig from disk
    else TOML missing
        Store->>Store: hydrate AppConfig using injected defaults
    end
    Store-->>Runner: configured TomlConfigStore
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Suggested labels

configuration

Poem

🐰 I fetched the Downloads path with care,
Seeded a UUID for keys to spare,
Retries grew patient, checksums in tow,
Ports and APIs now ready to go—
A happy rabbit hops: "Defaults all fair!"

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: aligning default settings with PRD §6.10 specifications as required by issue #67.
Linked Issues check ✅ Passed All code changes comprehensively address the linked issue #67 requirements: 9 AppConfig defaults aligned, downloadDir resolving to OS Downloads, apiKey bootstrap with UUIDv4, no migration of existing configs.
Out of Scope Changes check ✅ Passed All changes directly support the linked issue #67 objectives; test fixture updates and documentation changes are in-scope maintenance necessary for PR completeness.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/issue-67-align-settings-defaults-prd

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 18, 2026

Greptile Summary

This PR aligns 9 AppConfig defaults with PRD §6.10 (fresh installs only), adds a cross-platform resolve_system_download_dir() adapter, and generates a random UUIDv4 api_key on first launch so the REST/WebSocket protocols never start with an empty credential. The previously flagged concern about an empty api_key alongside enabled-by-default rest_api_enabled/websocket_enabled is fully resolved: the adapter layer now enforces a non-empty bootstrap key at construction time and returns a DomainError if one is absent, while the domain model correctly keeps web_interface_enabled: false as the server gatekeeper.

Confidence Score: 5/5

Safe to merge — the prior security concern is fully resolved; only a minor test-fixture inconsistency remains.

All P0/P1 findings from the previous review round are addressed: first-launch now enforces a non-empty UUID api_key, the domain gatekeeper (web_interface_enabled: false) is unchanged, and 582 backend + 367 frontend tests pass. The single remaining finding is a P2 style nit in a test fixture.

No files require special attention. settingsStore.test.ts has a minor apiKey fixture inconsistency worth cleaning up but it does not affect correctness.

Important Files Changed

Filename Overview
src-tauri/src/adapters/driven/config/toml_config_store.rs Adds default_download_dir and default_api_key constructor params, enforces non-empty bootstrap key on first launch, and provides comprehensive new tests covering all first-launch/existing-config edge cases.
src-tauri/src/domain/model/config.rs Defaults aligned to PRD; domain stays pure with gatekeeper web_interface_enabled: false; new test locks all 9 changed defaults and the intentional empty-key invariant.
src-tauri/src/lib.rs Wires resolve_system_download_dir() and a freshly-generated UUIDv4 into TomlConfigStore::new() — correct first-launch bootstrap that is inert on subsequent starts.
src-tauri/src/adapters/driven/filesystem/download_dir.rs Thin dirs::download_dir() adapter returning Option<String>; test guards against None in minimal envs (CI containers).
src-tauri/tests/app_state_wiring.rs Updated to pass a bootstrap key as default_api_key to the new TomlConfigStore::new signature.
src/views/SettingsView/tests/Sections.test.tsx Fixture defaults updated; the restApiEnabled=false override added correctly to the 'should not show API key' test that would otherwise always pass with the new true default.
src/stores/tests/settingsStore.test.ts Numeric defaults updated; apiKey left as empty string while restApiEnabled is now true — minor inconsistency with first-launch behaviour introduced in this PR.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[App startup
TomlConfigStore::new] -->|injects resolve_system_download_dir
+ uuid::Uuid::new_v4| B[get_config called]
    B --> C{config.toml
exists?}
    C -- No / First launch --> D[read_or_default:
validate default_api_key non-empty]
    D -->|empty or None| E[DomainError:
missing bootstrap key]
    D -->|valid UUID| F[AppConfig with
download_dir + api_key hydrated]
    F --> G[write_config to disk
atomic tmp→rename]
    C -- Yes / Existing install --> H[parse TOML via
serde default]
    H --> I[AppConfig from file
injected values ignored]
    G --> J[Return AppConfig]
    I --> J
Loading

Fix All in Claude Code

Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/stores/__tests__/settingsStore.test.ts
Line: 28

Comment:
**`apiKey` inconsistent with new first-launch behaviour**

`baseConfig` now has `restApiEnabled: true` (line 27) and `websocketEnabled: true` (line 30), but `apiKey` remains empty. On a fresh install the adapter injects a non-empty UUID, so this fixture represents a state the bootstrap guard explicitly rejects. If any test asserts on the API-key field visibility while `restApiEnabled` is `true`, a blank key may produce misleading coverage. Consider aligning this to a non-empty placeholder, matching `Sections.test.tsx`.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (3): Last reviewed commit: "fix(settings): fail-fast when first-laun..." | Re-trigger Greptile

Comment thread src-tauri/src/domain/model/config.rs
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
CHANGELOG.md (1)

14-14: Consider breaking dense settings list into bullets for readability.

The line currently documents 9 distinct default value changes in a single ~370-character sentence, making it difficult to scan. Breaking into sub-bullets would improve readability, especially for users reviewing the changelog to understand what changed.

♻️ Alternative formatting with bullets
-- Default settings values now match PRD §6.10: `autoExtract` on, `maxConcurrentDownloads=4`, `maxRetries=5`, `retryDelaySeconds=10`, `minFileSizeMb=1.0`, `verifyChecksums` on, `webInterfacePort=9876`, REST API and WebSocket enabled by default. `downloadDir` now resolves to the OS default Downloads directory on first launch. (`#67`)
+- Default settings values now match PRD §6.10 (fresh installations only; existing config.toml files are not migrated): (`#67`)
+  - `autoExtract` enabled
+  - `maxConcurrentDownloads` increased from 3 to 4
+  - `maxRetries` increased from 3 to 5
+  - `retryDelaySeconds` increased from 5 to 10
+  - `minFileSizeMb` increased from 0 to 1.0
+  - `verifyChecksums` enabled
+  - `webInterfacePort` changed from 9666 to 9876
+  - REST API and WebSocket enabled by default
+  - `downloadDir` now resolves to the OS default Downloads directory on first launch
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CHANGELOG.md` at line 14, Replace the single dense sentence in CHANGELOG.md
describing default setting changes with a short lead sentence followed by a
bulleted list enumerating each setting and its new default (referencing PRD
§6.10), e.g. separate entries for autoExtract, maxConcurrentDownloads=4,
maxRetries=5, retryDelaySeconds=10, minFileSizeMb=1.0, verifyChecksums,
webInterfacePort=9876, REST API and WebSocket enabled, and downloadDir behavior
(resolves to OS Downloads on first launch) so each change is easy to scan.
src-tauri/tests/app_state_wiring.rs (1)

44-47: Consider adding a companion test for the injected default-download-dir path.

Line 44–47 validates the new signature with None, but it doesn’t cover the new behavior branch where a default directory is injected. A small integration test using Some(...) would protect that path from regressions.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src-tauri/tests/app_state_wiring.rs` around lines 44 - 47, Add a new test
that asserts TomlConfigStore::new handles the injected default-download-dir by
calling TomlConfigStore::new with Some(path) instead of None, creating the
Arc<dyn ConfigStore> (same variable name config_store) and verifying the
stored/default download directory value is set to the provided path; locate the
constructor usage in the existing test (TomlConfigStore::new) and mirror the
setup (use config_dir.path().join(...) for a temporary dir) but pass
Some(default_dir) and add assertions that the ConfigStore API (the method that
returns the download-dir) returns that injected path to protect that branch from
regressions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@CHANGELOG.md`:
- Line 14: Update the CHANGELOG entry that starts "Default settings values now
match PRD §6.10" to explicitly state that these default value changes apply only
to fresh installations and that existing config.toml files will not be migrated
or modified; add a clarifying sentence such as "Existing installations and
config.toml files are left unchanged — these defaults apply only on first launch
/ fresh installs" immediately after the current description so readers know the
change does not alter user configs on upgrade.

In `@src-tauri/src/adapters/driven/filesystem/download_dir.rs`:
- Around line 22-30: The test resolves_some_path_on_supported_platforms is too
strict by asserting result.is_some() for resolve_system_download_dir (which
wraps dirs::download_dir()) — update the test to tolerate None: if
resolve_system_download_dir() returns Some(path) assert the path is not empty,
otherwise treat it as an acceptable skip (do not fail the test), optionally
emitting a message that the download dir is undiscoverable in this environment;
ensure you reference resolves_some_path_on_supported_platforms and
resolve_system_download_dir when making the change.

In `@src-tauri/src/domain/model/config.rs`:
- Around line 203-206: Add assertions to the regression test that verify the
security gate defaults to prevent accidental exposure: after the existing remote
access checks (where web_interface_port, rest_api_enabled, websocket_enabled are
asserted), assert that config.web_interface_enabled is false and that
config.api_key is empty (equal to an empty string) so the gatekeeper defaults
are locked down.

---

Nitpick comments:
In `@CHANGELOG.md`:
- Line 14: Replace the single dense sentence in CHANGELOG.md describing default
setting changes with a short lead sentence followed by a bulleted list
enumerating each setting and its new default (referencing PRD §6.10), e.g.
separate entries for autoExtract, maxConcurrentDownloads=4, maxRetries=5,
retryDelaySeconds=10, minFileSizeMb=1.0, verifyChecksums, webInterfacePort=9876,
REST API and WebSocket enabled, and downloadDir behavior (resolves to OS
Downloads on first launch) so each change is easy to scan.

In `@src-tauri/tests/app_state_wiring.rs`:
- Around line 44-47: Add a new test that asserts TomlConfigStore::new handles
the injected default-download-dir by calling TomlConfigStore::new with
Some(path) instead of None, creating the Arc<dyn ConfigStore> (same variable
name config_store) and verifying the stored/default download directory value is
set to the provided path; locate the constructor usage in the existing test
(TomlConfigStore::new) and mirror the setup (use config_dir.path().join(...) for
a temporary dir) but pass Some(default_dir) and add assertions that the
ConfigStore API (the method that returns the download-dir) returns that injected
path to protect that branch from regressions.
🪄 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: 61330c09-0fc9-4c88-b1bc-a8972af7e8fd

📥 Commits

Reviewing files that changed from the base of the PR and between 93c87c2 and 9db870e.

📒 Files selected for processing (18)
  • CHANGELOG.md
  • src-tauri/src/adapters/driven/config/toml_config_store.rs
  • src-tauri/src/adapters/driven/filesystem/download_dir.rs
  • src-tauri/src/adapters/driven/filesystem/mod.rs
  • src-tauri/src/domain/model/config.rs
  • src-tauri/src/domain/ports/driven/tests.rs
  • src-tauri/src/lib.rs
  • src-tauri/tests/app_state_wiring.rs
  • src/components/__tests__/ClipboardIndicator.test.tsx
  • src/hooks/__tests__/useAppEffects.test.ts
  • src/hooks/__tests__/useDownloadDetail.test.ts
  • src/layouts/__tests__/AppLayout.test.tsx
  • src/stores/__tests__/settingsStore.test.ts
  • src/views/DownloadDetailsPanel/__tests__/DownloadDetailsPanel.test.tsx
  • src/views/DownloadDetailsPanel/__tests__/FileInfoSection.test.tsx
  • src/views/DownloadDetailsPanel/__tests__/MetricsSection.test.tsx
  • src/views/SettingsView/__tests__/Sections.test.tsx
  • src/views/SettingsView/__tests__/SettingsView.test.tsx

Comment thread CHANGELOG.md Outdated
Comment thread src-tauri/src/adapters/driven/filesystem/download_dir.rs Outdated
Comment thread src-tauri/src/domain/model/config.rs Outdated
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 18 files

Address PR review:
- greptile (P1 security): hydrate api_key with a random uuid on first
  launch so REST/WS protocols never start with an empty credential.
  TomlConfigStore::new now takes a third Option<String> for the default
  key; lib.rs injects uuid::Uuid::new_v4() at bootstrap, tests pass None.
- coderabbit (CHANGELOG): clarify the change applies to fresh installs
  only; existing config.toml files are left untouched.
- coderabbit (download_dir test): tolerate None resolution on minimal
  environments instead of asserting is_some() unconditionally.
- coderabbit (snapshot test): lock web_interface_enabled=false and
  api_key empty in the bare-domain defaults to prevent accidental
  exposure regressions.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 625b7ce8-5604-4e55-8e04-0c89afcd5b50

📥 Commits

Reviewing files that changed from the base of the PR and between 9db870e and b996aec.

📒 Files selected for processing (6)
  • CHANGELOG.md
  • src-tauri/src/adapters/driven/config/toml_config_store.rs
  • src-tauri/src/adapters/driven/filesystem/download_dir.rs
  • src-tauri/src/domain/model/config.rs
  • src-tauri/src/lib.rs
  • src-tauri/tests/app_state_wiring.rs
✅ Files skipped from review due to trivial changes (1)
  • src-tauri/src/domain/model/config.rs
🚧 Files skipped from review as they are similar to previous changes (4)
  • src-tauri/tests/app_state_wiring.rs
  • src-tauri/src/lib.rs
  • src-tauri/src/adapters/driven/filesystem/download_dir.rs
  • CHANGELOG.md

Comment thread src-tauri/src/adapters/driven/config/toml_config_store.rs
#67)

coderabbit MAJOR: the unwrap_or_else fallback in read_or_default still
produced an empty api_key when default_api_key was None or whitespace,
defeating the bootstrap guarantee. Replace the fallback with a
StorageError so a misconfigured caller cannot silently ship an
unauthenticated REST/WebSocket server. Tests that don't assert on the
key now pass a constant bootstrap value; two new tests lock the None
and whitespace paths to the error branch.
@mpiton mpiton merged commit 254afea into main Apr 18, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation frontend rust ui

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[QA] Settings defaults don't match PRD §6.10 specifications

1 participant