Refactored the `modify_entry` method in `src/seedpass/core/entry_management.py` to delegate entry modification logic to specialized private helper methods:
- `_modify_common_fields`: Handles fields common to all entries (label, notes, archived, etc.)
- `_modify_password_entry`: Handles password-specific fields and policy
- `_modify_totp_entry`: Handles TOTP-specific fields (period, digits)
- `_modify_key_value_entry`: Handles key-value specific fields
- `_modify_managed_account_entry`: Handles managed account specific fields
This change improves code readability and maintainability by breaking down a large, complex function into smaller, focused units. Verified with existing tests.
Co-authored-by: PR0M3TH3AN <[email protected]>
Consolidated duplicated menu loop logic from `_entry_actions_menu`, `_entry_edit_menu`, and `_entry_qr_menu` in `src/seedpass/core/manager.py` into a reusable `run_menu` method in `src/seedpass/core/menu_handler.py`. This improves maintainability by centralizing the loop handling, input prompting, and header clearing logic.
* Added `run_menu` to `MenuHandler`.
* Refactored `_entry_actions_menu` to use `run_menu`.
* Refactored `_entry_edit_menu` to use `run_menu`.
* Refactored `_entry_qr_menu` (NOSTR section) to use `run_menu`.
Co-authored-by: PR0M3TH3AN <[email protected]>
Extracts the hardcoded BeeWare GUI backend configuration (package names, versions, and SHA256 hashes) from `src/seedpass/cli/__init__.py` into a new `GUI_BACKEND_CONFIG` dictionary in `src/constants.py`. This improves maintainability by centralizing configuration and simplifying the CLI logic.
- Adds `GUI_BACKEND_CONFIG` to `src/constants.py`.
- Updates `src/seedpass/cli/__init__.py` to import and use `GUI_BACKEND_CONFIG`.
Co-authored-by: PR0M3TH3AN <[email protected]>
This change replaces insecure file writes followed by `os.chmod` with `utils.atomic_write.atomic_write` in `portable_backup.py` and `manager.py`. The `atomic_write` function uses `tempfile.mkstemp` to ensure files are created with restrictive permissions (0o600) from the start, eliminating the race condition where sensitive data could be briefly world-readable.
- Updated `export_backup` in `portable_backup.py` to use `atomic_write` for both the JSON backup and its encrypted counterpart.
- Updated `handle_export_totp_codes` in `manager.py` to use `atomic_write` for TOTP exports.
- Added `test_atomic_write_perms.py` to verify permissions behavior (though it relies on system-specific `mkstemp` behavior).
- Verified fix by running existing tests `test_portable_backup.py`, `test_export_totp_codes.py`, and `test_atomic_write.py`.
Co-authored-by: PR0M3TH3AN <[email protected]>
- Introduced `_clear_header_add_entry`, `_mark_dirty`, `_sync_and_pause` helpers.
- Introduced `_entry_op_context` context manager for error handling.
- Applied these patterns to `handle_add_totp`, `handle_add_ssh_key`, `handle_add_seed`, `handle_add_pgp`, `handle_add_nostr_key`, `handle_add_key_value`, and `handle_add_managed_account`.
- Ensured `is_dirty` flag is set immediately after entry creation to prevent data loss if subsequent UI steps are cancelled.
Co-authored-by: PR0M3TH3AN <[email protected]>
This change explicitly adds `pycryptodome` to `pyproject.toml` and `src/requirements.txt` to resolve a `ModuleNotFoundError` when generating PGP RSA keys. The `Crypto` namespace provided by `pycryptodome` is required by `src/seedpass/core/password_generation.py`.
Verified with `reproduce_issue.py` (which now passes) and `src/tests/test_pgp_entry.py`.
Co-authored-by: PR0M3TH3AN <[email protected]>
Add `src/tests/test_fingerprint.py` to cover:
- Happy path fingerprint generation.
- Custom fingerprint length.
- Input normalization (whitespace/case).
- Error handling via mocked exception in `hashlib.sha256`.
- Invalid input handling (NoneType).
This addresses the gap where the exception path in `src/utils/fingerprint.py` was unreachable with standard inputs.
Co-authored-by: PR0M3TH3AN <[email protected]>
Split the `load_index` method in `src/seedpass/core/vault.py` into
`_handle_legacy_file_migration`, `_restore_legacy_backup`,
`_load_and_handle_decryption`, `_check_schema_version`, and
`_apply_schema_migrations`. This improves readability and maintainability
by separating the concerns of legacy file handling, decryption, and schema
migration.
Verified with existing tests in `src/tests/test_legacy_migration.py` and
`src/tests/test_migrations.py`.
Co-authored-by: PR0M3TH3AN <[email protected]>
This change mitigates an arbitrary file overwrite vulnerability in the
`backup_parent_seed` API endpoint. Previously, the endpoint did not
check if the destination file already existed, allowing attackers or
accidental misuse to overwrite critical files if the path validation
passed.
The fix introduces a check using `resolved_path.exists()` after path
validation. If the file exists, the request is rejected with a
409 Conflict error.
A reproduction test case confirmed the vulnerability and verified the
fix. Regression tests on the API passed successfully.
Co-authored-by: PR0M3TH3AN <[email protected]>
Executed `scheduler-update-agent`.
- Verified daily and weekly prompt directories against `roster.json`.
- Confirmed no drift in `daily-scheduler.md` and `weekly-scheduler.md`.
- Published completion log.
Co-authored-by: PR0M3TH3AN <[email protected]>
Extracted the monolithic `display_sensitive_entry_info` method from `PasswordManager` into a new `DisplayService` class in `src/seedpass/core/display_service.py`. This improves maintainability and separation of concerns.
- Created `src/seedpass/core/display_service.py` with `DisplayService` class.
- Implemented specific display methods for each entry type (TOTP, SSH, SEED, PGP, Nostr, Key/Value, Managed Account, Password).
- Updated `src/seedpass/core/manager.py` to use `DisplayService`.
- Verified with existing tests `test_manager_retrieve_totp.py` and `test_manager_search_display.py`.
Co-authored-by: PR0M3TH3AN <[email protected]>
Refactors `import_vault` endpoint in `src/seedpass/api.py` to use `asyncio.to_thread` for blocking file I/O and synchronous `PasswordManager.handle_import_database` calls.
Replaces synchronous `pm.sync_vault()` with `await pm.sync_vault_async()` (with fallback) to prevent blocking the event loop or triggering `asyncio.run` errors.
This change ensures the API remains responsive during large vault imports.
Verified with a custom benchmark script showing concurrent requests are no longer blocked.
Co-authored-by: PR0M3TH3AN <[email protected]>
This commit adds a new test file `src/tests/test_stats_manager.py` to verify the functionality of the `StatsManager.reset` method. The test ensures that the `reset` method correctly resets the internal `_displayed` flag, allowing stats to be displayed again after a reset.
Testing:
- Added `test_stats_manager_reset` which mocks the manager and verifies `display_stats` calls before and after reset.
- Verified the test passes in isolation.
- Skipped full integration tests due to environment limitations, but the change is isolated to a new test file and does not modify production code.
Co-authored-by: PR0M3TH3AN <[email protected]>
Added two new test cases to `src/tests/test_atomic_write.py`:
- `test_atomic_write_cleanup_on_failure`: Verifies that the temporary file is deleted if the write operation fails.
- `test_atomic_write_preserves_existing_on_failure`: Verifies that an existing destination file is preserved if the write operation fails.
These tests ensure the robustness of the `atomic_write` utility function.
Co-authored-by: PR0M3TH3AN <[email protected]>
- Update `src/tests/test_profile_management.py` to use a more robust `input` mock iterator.
- Mock returns fallback "y" responses after the initial choice ("3") to break any potential infinite loops in `confirm_action` if mocking fails or module reloading interferes.
- Addresses `OSError` and timeout on Windows CI caused by interactive prompt loops.
Co-authored-by: PR0M3TH3AN <[email protected]>
Replace unsafe module reloading with explicit monkeypatching of constants.
This prevents potential OSError: [Errno 22] Invalid argument on Windows
during TemporaryDirectory cleanup or test execution when modules are reloaded
in a way that affects global state or file handles.
Also ensured `pm.fingerprint_manager` is initialized using the monkeypatched
`APP_DIR` from the manager module context to guarantee it operates within
the temporary directory context and aligns with the mocked constants.
Co-authored-by: PR0M3TH3AN <[email protected]>
Patched `masked_input` in `utils.password_prompt` to bypass `msvcrt.getwch()` usage during tests, preventing `OSError: [Errno 22] Invalid argument` in non-interactive CI environments.
Ensured the test logic relies on the mocked `builtins.input` as intended.
Co-authored-by: PR0M3TH3AN <[email protected]>