mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2025-09-08 07:18:47 +00:00
Add dependency scanning and optional dependency checks
This commit is contained in:
6
.github/workflows/python-ci.yml
vendored
6
.github/workflows/python-ci.yml
vendored
@@ -83,10 +83,8 @@ jobs:
|
|||||||
pip-compile --generate-hashes --output-file=requirements.lock src/requirements.txt
|
pip-compile --generate-hashes --output-file=requirements.lock src/requirements.txt
|
||||||
git diff --exit-code requirements.lock
|
git diff --exit-code requirements.lock
|
||||||
pip install --require-hashes -r requirements.lock
|
pip install --require-hashes -r requirements.lock
|
||||||
- name: Run pip-audit
|
- name: Run dependency scan
|
||||||
run: |
|
run: scripts/dependency_scan.sh --ignore-vuln GHSA-wj6h-64fc-37mp
|
||||||
pip install pip-audit
|
|
||||||
pip-audit -r requirements.lock --ignore-vuln GHSA-wj6h-64fc-37mp
|
|
||||||
- name: Determine stress args
|
- name: Determine stress args
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
9
scripts/dependency_scan.sh
Executable file
9
scripts/dependency_scan.sh
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Run pip-audit against the pinned requirements
|
||||||
|
if ! command -v pip-audit >/dev/null 2>&1; then
|
||||||
|
python -m pip install --quiet pip-audit
|
||||||
|
fi
|
||||||
|
|
||||||
|
pip-audit -r requirements.lock "$@"
|
21
src/main.py
21
src/main.py
@@ -18,6 +18,7 @@ from colorama import init as colorama_init
|
|||||||
from termcolor import colored
|
from termcolor import colored
|
||||||
from utils.color_scheme import color_text
|
from utils.color_scheme import color_text
|
||||||
import traceback
|
import traceback
|
||||||
|
import importlib
|
||||||
|
|
||||||
from seedpass.core.manager import PasswordManager
|
from seedpass.core.manager import PasswordManager
|
||||||
from nostr.client import NostrClient
|
from nostr.client import NostrClient
|
||||||
@@ -38,6 +39,25 @@ from local_bip85.bip85 import Bip85Error
|
|||||||
|
|
||||||
colorama_init()
|
colorama_init()
|
||||||
|
|
||||||
|
OPTIONAL_DEPENDENCIES = {
|
||||||
|
"pyperclip": "clipboard support for secret mode",
|
||||||
|
"qrcode": "QR code generation for TOTP setup",
|
||||||
|
"toga": "desktop GUI features",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _warn_missing_optional_dependencies() -> None:
|
||||||
|
"""Log warnings for any optional packages that are not installed."""
|
||||||
|
for module, feature in OPTIONAL_DEPENDENCIES.items():
|
||||||
|
try:
|
||||||
|
importlib.import_module(module)
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
logging.warning(
|
||||||
|
"Optional dependency '%s' is not installed; %s will be unavailable.",
|
||||||
|
module,
|
||||||
|
feature,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def load_global_config() -> dict:
|
def load_global_config() -> dict:
|
||||||
"""Load configuration from ~/.seedpass/config.toml if present."""
|
"""Load configuration from ~/.seedpass/config.toml if present."""
|
||||||
@@ -1205,6 +1225,7 @@ def main(argv: list[str] | None = None, *, fingerprint: str | None = None) -> in
|
|||||||
Optional seed profile fingerprint to select automatically.
|
Optional seed profile fingerprint to select automatically.
|
||||||
"""
|
"""
|
||||||
configure_logging()
|
configure_logging()
|
||||||
|
_warn_missing_optional_dependencies()
|
||||||
initialize_app()
|
initialize_app()
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
logger.info("Starting SeedPass Password Manager")
|
logger.info("Starting SeedPass Password Manager")
|
||||||
|
@@ -22,19 +22,21 @@ pgpy==0.6.0
|
|||||||
pyotp>=2.8.0
|
pyotp>=2.8.0
|
||||||
|
|
||||||
freezegun
|
freezegun
|
||||||
pyperclip
|
|
||||||
qrcode>=8.2
|
|
||||||
typer>=0.12.3
|
typer>=0.12.3
|
||||||
fastapi>=0.116.1
|
|
||||||
uvicorn>=0.35.0
|
# Optional dependencies - install as needed for additional features
|
||||||
starlette>=0.47.2
|
pyperclip # Clipboard support for secret mode
|
||||||
httpx>=0.28.1
|
qrcode>=8.2 # Generate QR codes for TOTP setup
|
||||||
requests>=2.32
|
fastapi>=0.116.1 # API server
|
||||||
python-multipart>=0.0.20
|
uvicorn>=0.35.0 # API server
|
||||||
PyJWT
|
starlette>=0.47.2 # API server
|
||||||
orjson
|
httpx>=0.28.1 # API server
|
||||||
argon2-cffi
|
requests>=2.32 # API server
|
||||||
toga-core>=0.5.2
|
python-multipart>=0.0.20 # API server file uploads
|
||||||
pillow
|
PyJWT # JWT authentication for API server
|
||||||
toga-dummy>=0.5.2 # for headless GUI tests
|
orjson # Fast JSON serialization for API server
|
||||||
slowapi
|
argon2-cffi # Password hashing for API server
|
||||||
|
toga-core>=0.5.2 # Desktop GUI
|
||||||
|
pillow # Image support for GUI
|
||||||
|
toga-dummy>=0.5.2 # Headless GUI tests
|
||||||
|
slowapi # Rate limiting for API server
|
||||||
|
@@ -1,47 +1,51 @@
|
|||||||
# utils/__init__.py
|
# utils/__init__.py
|
||||||
|
|
||||||
|
"""Utility package exports and optional feature handling."""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import traceback
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
try:
|
from .file_lock import exclusive_lock, shared_lock
|
||||||
from .file_lock import exclusive_lock, shared_lock
|
from .key_derivation import (
|
||||||
from .key_derivation import (
|
derive_key_from_password,
|
||||||
derive_key_from_password,
|
derive_key_from_parent_seed,
|
||||||
derive_key_from_parent_seed,
|
derive_index_key,
|
||||||
derive_index_key,
|
derive_totp_secret,
|
||||||
derive_totp_secret,
|
EncryptionMode,
|
||||||
EncryptionMode,
|
DEFAULT_ENCRYPTION_MODE,
|
||||||
DEFAULT_ENCRYPTION_MODE,
|
TOTP_PURPOSE,
|
||||||
TOTP_PURPOSE,
|
)
|
||||||
)
|
from .checksum import (
|
||||||
from .checksum import (
|
calculate_checksum,
|
||||||
calculate_checksum,
|
verify_checksum,
|
||||||
verify_checksum,
|
json_checksum,
|
||||||
json_checksum,
|
canonical_json_dumps,
|
||||||
canonical_json_dumps,
|
initialize_checksum,
|
||||||
initialize_checksum,
|
update_checksum_file,
|
||||||
update_checksum_file,
|
)
|
||||||
)
|
from .password_prompt import prompt_for_password
|
||||||
from .password_prompt import prompt_for_password
|
from .seed_prompt import masked_input, prompt_seed_words
|
||||||
from .seed_prompt import masked_input, prompt_seed_words
|
from .input_utils import timed_input
|
||||||
from .input_utils import timed_input
|
from .memory_protection import InMemorySecret
|
||||||
from .memory_protection import InMemorySecret
|
from .terminal_utils import (
|
||||||
from .clipboard import copy_to_clipboard
|
clear_screen,
|
||||||
from .terminal_utils import (
|
pause,
|
||||||
clear_screen,
|
clear_and_print_fingerprint,
|
||||||
pause,
|
clear_header_with_notification,
|
||||||
clear_and_print_fingerprint,
|
)
|
||||||
clear_header_with_notification,
|
from .atomic_write import atomic_write
|
||||||
)
|
|
||||||
from .atomic_write import atomic_write
|
# Optional clipboard support
|
||||||
|
try: # pragma: no cover - exercised when dependency missing
|
||||||
|
from .clipboard import copy_to_clipboard
|
||||||
|
except Exception as exc: # pragma: no cover - executed only if pyperclip missing
|
||||||
|
|
||||||
|
def copy_to_clipboard(*_args, **_kwargs):
|
||||||
|
"""Stub when clipboard support is unavailable."""
|
||||||
|
logger.warning("Clipboard support unavailable: %s", exc)
|
||||||
|
return False
|
||||||
|
|
||||||
if logger.isEnabledFor(logging.DEBUG):
|
|
||||||
logger.info("Modules imported successfully.")
|
|
||||||
except Exception as e:
|
|
||||||
if logger.isEnabledFor(logging.DEBUG):
|
|
||||||
logger.error(f"Failed to import one or more modules: {e}", exc_info=True)
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"derive_key_from_password",
|
"derive_key_from_password",
|
||||||
|
Reference in New Issue
Block a user