From be009a40940c98e72d245562589439511902577f Mon Sep 17 00:00:00 2001 From: AFredefon Date: Thu, 9 Apr 2026 04:10:46 +0200 Subject: [PATCH] =?UTF-8?q?rename:=20FuzzForge=20=E2=86=92=20SecPipe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename the entire project from FuzzForge to SecPipe: - Python packages: fuzzforge_cli → secpipe_cli, fuzzforge_common → secpipe_common, fuzzforge_mcp → secpipe_mcp, fuzzforge_tests → secpipe_tests - Directories: fuzzforge-cli → secpipe-cli, fuzzforge-common → secpipe-common, fuzzforge-mcp → secpipe-mcp, fuzzforge-tests → secpipe-tests - Environment variables: FUZZFORGE_* → SECPIPE_* - MCP server name: SecPipe MCP Server - CI workflows, Makefile, Dockerfile, hub-config, NOTICE updated - Fix mcp-server.yml to use uvicorn secpipe_mcp.application:app --- .github/workflows/ci.yml | 30 ++--- .github/workflows/mcp-server.yml | 12 +- .gitignore | 1 + CONTRIBUTING.md | 70 +++++----- Makefile | 14 +- NOTICE | 4 +- README.md | 32 ++--- RELEASE_NOTES.md | 65 ++++++++++ ROADMAP.md | 2 +- USAGE.md | 96 +++++++------- .../src/fuzzforge_cli/tui/__init__.py | 1 - .../src/fuzzforge_cli/tui/screens/__init__.py | 1 - .../src/fuzzforge_common/__init__.py | 38 ------ .../fuzzforge_common/sandboxes/__init__.py | 23 ---- .../sandboxes/engines/__init__.py | 21 --- .../sandboxes/engines/base/__init__.py | 15 --- .../sandboxes/engines/docker/__init__.py | 13 -- .../sandboxes/engines/docker/configuration.py | 22 ---- .../sandboxes/engines/podman/__init__.py | 13 -- .../sandboxes/engines/podman/configuration.py | 22 ---- fuzzforge-common/tests/conftest.py | 1 - fuzzforge-mcp/src/fuzzforge_mcp/exceptions.py | 5 - .../src/fuzzforge_tests/__init__.py | 9 -- hub-config.json | 82 ++++++------ pyproject.toml | 32 ++--- {fuzzforge-cli => secpipe-cli}/Makefile | 0 {fuzzforge-cli => secpipe-cli}/README.md | 0 {fuzzforge-cli => secpipe-cli}/mypy.ini | 0 {fuzzforge-cli => secpipe-cli}/pyproject.toml | 10 +- {fuzzforge-cli => secpipe-cli}/pytest.ini | 0 {fuzzforge-cli => secpipe-cli}/ruff.toml | 10 +- .../src/secpipe_cli}/__init__.py | 0 .../src/secpipe_cli}/__main__.py | 2 +- .../src/secpipe_cli}/application.py | 30 ++--- .../src/secpipe_cli}/commands/__init__.py | 0 .../src/secpipe_cli}/commands/mcp.py | 120 +++++++++--------- .../src/secpipe_cli}/commands/projects.py | 8 +- .../src/secpipe_cli}/context.py | 6 +- secpipe-cli/src/secpipe_cli/tui/__init__.py | 1 + .../src/secpipe_cli}/tui/app.py | 36 +++--- .../src/secpipe_cli}/tui/helpers.py | 112 ++++++++-------- .../src/secpipe_cli/tui/screens/__init__.py | 1 + .../secpipe_cli}/tui/screens/agent_setup.py | 8 +- .../secpipe_cli}/tui/screens/build_image.py | 2 +- .../src/secpipe_cli}/tui/screens/build_log.py | 2 +- .../secpipe_cli}/tui/screens/hub_manager.py | 12 +- .../src/secpipe_cli}/utilities.py | 0 .../tests/__init__.py | 0 .../tests/conftest.py | 0 {fuzzforge-common => secpipe-common}/Makefile | 0 .../README.md | 0 {fuzzforge-common => secpipe-common}/mypy.ini | 0 .../pyproject.toml | 4 +- .../pytest.ini | 0 .../ruff.toml | 0 secpipe-common/src/secpipe_common/__init__.py | 38 ++++++ .../src/secpipe_common}/exceptions.py | 6 +- .../src/secpipe_common}/hub/__init__.py | 14 +- .../src/secpipe_common}/hub/client.py | 6 +- .../src/secpipe_common}/hub/executor.py | 6 +- .../src/secpipe_common}/hub/models.py | 2 +- .../src/secpipe_common}/hub/registry.py | 2 +- .../src/secpipe_common}/py.typed | 0 .../src/secpipe_common/sandboxes/__init__.py | 23 ++++ .../sandboxes/engines/__init__.py | 21 +++ .../sandboxes/engines/base/__init__.py | 15 +++ .../sandboxes/engines/base/configuration.py | 12 +- .../sandboxes/engines/base/engine.py | 12 +- .../sandboxes/engines/docker/__init__.py | 13 ++ .../sandboxes/engines/docker/cli.py | 12 +- .../sandboxes/engines/docker/configuration.py | 22 ++++ .../sandboxes/engines/docker/engine.py | 4 +- .../sandboxes/engines/enumeration.py | 2 +- .../sandboxes/engines/podman/__init__.py | 13 ++ .../sandboxes/engines/podman/cli.py | 16 +-- .../sandboxes/engines/podman/configuration.py | 22 ++++ .../sandboxes/engines/podman/engine.py | 16 +-- .../tests/.gitkeep | 0 .../tests/__init__.py | 0 secpipe-common/tests/conftest.py | 1 + .../tests/unit/__init__.py | 0 .../tests/unit/engines/__init__.py | 0 .../tests/unit/engines/conftest.py | 0 .../tests/unit/engines/test_docker.py | 2 +- .../tests/unit/engines/test_podman.py | 6 +- {fuzzforge-mcp => secpipe-mcp}/Dockerfile | 2 +- {fuzzforge-mcp => secpipe-mcp}/Makefile | 0 {fuzzforge-mcp => secpipe-mcp}/README.md | 58 ++++----- {fuzzforge-mcp => secpipe-mcp}/mypy.ini | 0 {fuzzforge-mcp => secpipe-mcp}/pyproject.toml | 14 +- {fuzzforge-mcp => secpipe-mcp}/pytest.ini | 0 {fuzzforge-mcp => secpipe-mcp}/ruff.toml | 0 .../src/secpipe_mcp}/__init__.py | 0 .../src/secpipe_mcp}/__main__.py | 6 +- .../src/secpipe_mcp}/application.py | 12 +- .../src/secpipe_mcp}/dependencies.py | 12 +- secpipe-mcp/src/secpipe_mcp/exceptions.py | 5 + .../src/secpipe_mcp}/resources/__init__.py | 4 +- .../src/secpipe_mcp}/resources/executions.py | 8 +- .../src/secpipe_mcp}/resources/project.py | 10 +- .../src/secpipe_mcp}/settings.py | 40 +++--- .../skills/firmware-analysis.yaml | 0 .../src/secpipe_mcp}/skills/go-fuzzing.yaml | 0 .../src/secpipe_mcp}/storage.py | 36 +++--- .../src/secpipe_mcp}/tools/__init__.py | 4 +- .../src/secpipe_mcp}/tools/hub.py | 12 +- .../src/secpipe_mcp}/tools/projects.py | 18 +-- .../src/secpipe_mcp}/tools/reports.py | 14 +- .../tests/__init__.py | 0 .../tests/conftest.py | 14 +- .../tests/test_resources.py | 4 +- {fuzzforge-tests => secpipe-tests}/Makefile | 0 {fuzzforge-tests => secpipe-tests}/README.md | 0 {fuzzforge-tests => secpipe-tests}/mypy.ini | 0 .../pyproject.toml | 8 +- {fuzzforge-tests => secpipe-tests}/ruff.toml | 0 secpipe-tests/src/secpipe_tests/__init__.py | 9 ++ .../src/secpipe_tests}/conftest.py | 4 +- .../src/secpipe_tests}/fixtures.py | 30 ++--- uv.lock | 68 +++++----- 120 files changed, 866 insertions(+), 800 deletions(-) create mode 100644 RELEASE_NOTES.md delete mode 100644 fuzzforge-cli/src/fuzzforge_cli/tui/__init__.py delete mode 100644 fuzzforge-cli/src/fuzzforge_cli/tui/screens/__init__.py delete mode 100644 fuzzforge-common/src/fuzzforge_common/__init__.py delete mode 100644 fuzzforge-common/src/fuzzforge_common/sandboxes/__init__.py delete mode 100644 fuzzforge-common/src/fuzzforge_common/sandboxes/engines/__init__.py delete mode 100644 fuzzforge-common/src/fuzzforge_common/sandboxes/engines/base/__init__.py delete mode 100644 fuzzforge-common/src/fuzzforge_common/sandboxes/engines/docker/__init__.py delete mode 100644 fuzzforge-common/src/fuzzforge_common/sandboxes/engines/docker/configuration.py delete mode 100644 fuzzforge-common/src/fuzzforge_common/sandboxes/engines/podman/__init__.py delete mode 100644 fuzzforge-common/src/fuzzforge_common/sandboxes/engines/podman/configuration.py delete mode 100644 fuzzforge-common/tests/conftest.py delete mode 100644 fuzzforge-mcp/src/fuzzforge_mcp/exceptions.py delete mode 100644 fuzzforge-tests/src/fuzzforge_tests/__init__.py rename {fuzzforge-cli => secpipe-cli}/Makefile (100%) rename {fuzzforge-cli => secpipe-cli}/README.md (100%) rename {fuzzforge-cli => secpipe-cli}/mypy.ini (100%) rename {fuzzforge-cli => secpipe-cli}/pyproject.toml (63%) rename {fuzzforge-cli => secpipe-cli}/pytest.ini (100%) rename {fuzzforge-cli => secpipe-cli}/ruff.toml (91%) rename {fuzzforge-cli/src/fuzzforge_cli => secpipe-cli/src/secpipe_cli}/__init__.py (100%) rename {fuzzforge-cli/src/fuzzforge_cli => secpipe-cli/src/secpipe_cli}/__main__.py (68%) rename {fuzzforge-cli/src/fuzzforge_cli => secpipe-cli/src/secpipe_cli}/application.py (58%) rename {fuzzforge-cli/src/fuzzforge_cli => secpipe-cli/src/secpipe_cli}/commands/__init__.py (100%) rename {fuzzforge-cli/src/fuzzforge_cli => secpipe-cli/src/secpipe_cli}/commands/mcp.py (77%) rename {fuzzforge-cli/src/fuzzforge_cli => secpipe-cli/src/secpipe_cli}/commands/projects.py (95%) rename {fuzzforge-cli/src/fuzzforge_cli => secpipe-cli/src/secpipe_cli}/context.py (88%) create mode 100644 secpipe-cli/src/secpipe_cli/tui/__init__.py rename {fuzzforge-cli/src/fuzzforge_cli => secpipe-cli/src/secpipe_cli}/tui/app.py (94%) rename {fuzzforge-cli/src/fuzzforge_cli => secpipe-cli/src/secpipe_cli}/tui/helpers.py (85%) create mode 100644 secpipe-cli/src/secpipe_cli/tui/screens/__init__.py rename {fuzzforge-cli/src/fuzzforge_cli => secpipe-cli/src/secpipe_cli}/tui/screens/agent_setup.py (91%) rename {fuzzforge-cli/src/fuzzforge_cli => secpipe-cli/src/secpipe_cli}/tui/screens/build_image.py (97%) rename {fuzzforge-cli/src/fuzzforge_cli => secpipe-cli/src/secpipe_cli}/tui/screens/build_log.py (98%) rename {fuzzforge-cli/src/fuzzforge_cli => secpipe-cli/src/secpipe_cli}/tui/screens/hub_manager.py (97%) rename {fuzzforge-cli/src/fuzzforge_cli => secpipe-cli/src/secpipe_cli}/utilities.py (100%) rename {fuzzforge-cli => secpipe-cli}/tests/__init__.py (100%) rename {fuzzforge-cli => secpipe-cli}/tests/conftest.py (100%) rename {fuzzforge-common => secpipe-common}/Makefile (100%) rename {fuzzforge-common => secpipe-common}/README.md (100%) rename {fuzzforge-common => secpipe-common}/mypy.ini (100%) rename {fuzzforge-common => secpipe-common}/pyproject.toml (79%) rename {fuzzforge-common => secpipe-common}/pytest.ini (100%) rename {fuzzforge-common => secpipe-common}/ruff.toml (100%) create mode 100644 secpipe-common/src/secpipe_common/__init__.py rename {fuzzforge-common/src/fuzzforge_common => secpipe-common/src/secpipe_common}/exceptions.py (80%) rename {fuzzforge-common/src/fuzzforge_common => secpipe-common/src/secpipe_common}/hub/__init__.py (65%) rename {fuzzforge-common/src/fuzzforge_common => secpipe-common/src/secpipe_common}/hub/client.py (99%) rename {fuzzforge-common/src/fuzzforge_common => secpipe-common/src/secpipe_common}/hub/executor.py (98%) rename {fuzzforge-common/src/fuzzforge_common => secpipe-common/src/secpipe_common}/hub/models.py (99%) rename {fuzzforge-common/src/fuzzforge_common => secpipe-common/src/secpipe_common}/hub/registry.py (99%) rename {fuzzforge-common/src/fuzzforge_common => secpipe-common/src/secpipe_common}/py.typed (100%) create mode 100644 secpipe-common/src/secpipe_common/sandboxes/__init__.py create mode 100644 secpipe-common/src/secpipe_common/sandboxes/engines/__init__.py create mode 100644 secpipe-common/src/secpipe_common/sandboxes/engines/base/__init__.py rename {fuzzforge-common/src/fuzzforge_common => secpipe-common/src/secpipe_common}/sandboxes/engines/base/configuration.py (50%) rename {fuzzforge-common/src/fuzzforge_common => secpipe-common/src/secpipe_common}/sandboxes/engines/base/engine.py (96%) create mode 100644 secpipe-common/src/secpipe_common/sandboxes/engines/docker/__init__.py rename {fuzzforge-common/src/fuzzforge_common => secpipe-common/src/secpipe_common}/sandboxes/engines/docker/cli.py (97%) create mode 100644 secpipe-common/src/secpipe_common/sandboxes/engines/docker/configuration.py rename {fuzzforge-common/src/fuzzforge_common => secpipe-common/src/secpipe_common}/sandboxes/engines/docker/engine.py (97%) rename {fuzzforge-common/src/fuzzforge_common => secpipe-common/src/secpipe_common}/sandboxes/engines/enumeration.py (74%) create mode 100644 secpipe-common/src/secpipe_common/sandboxes/engines/podman/__init__.py rename {fuzzforge-common/src/fuzzforge_common => secpipe-common/src/secpipe_common}/sandboxes/engines/podman/cli.py (97%) create mode 100644 secpipe-common/src/secpipe_common/sandboxes/engines/podman/configuration.py rename {fuzzforge-common/src/fuzzforge_common => secpipe-common/src/secpipe_common}/sandboxes/engines/podman/engine.py (97%) rename {fuzzforge-common => secpipe-common}/tests/.gitkeep (100%) rename {fuzzforge-common => secpipe-common}/tests/__init__.py (100%) create mode 100644 secpipe-common/tests/conftest.py rename {fuzzforge-common => secpipe-common}/tests/unit/__init__.py (100%) rename {fuzzforge-common => secpipe-common}/tests/unit/engines/__init__.py (100%) rename {fuzzforge-common => secpipe-common}/tests/unit/engines/conftest.py (100%) rename {fuzzforge-common => secpipe-common}/tests/unit/engines/test_docker.py (97%) rename {fuzzforge-common => secpipe-common}/tests/unit/engines/test_podman.py (95%) rename {fuzzforge-mcp => secpipe-mcp}/Dockerfile (72%) rename {fuzzforge-mcp => secpipe-mcp}/Makefile (100%) rename {fuzzforge-mcp => secpipe-mcp}/README.md (75%) rename {fuzzforge-mcp => secpipe-mcp}/mypy.ini (100%) rename {fuzzforge-mcp => secpipe-mcp}/pyproject.toml (62%) rename {fuzzforge-mcp => secpipe-mcp}/pytest.ini (100%) rename {fuzzforge-mcp => secpipe-mcp}/ruff.toml (100%) rename {fuzzforge-mcp/src/fuzzforge_mcp => secpipe-mcp/src/secpipe_mcp}/__init__.py (100%) rename {fuzzforge-mcp/src/fuzzforge_mcp => secpipe-mcp/src/secpipe_mcp}/__main__.py (63%) rename {fuzzforge-mcp/src/fuzzforge_mcp => secpipe-mcp/src/secpipe_mcp}/application.py (90%) rename {fuzzforge-mcp/src/fuzzforge_mcp => secpipe-mcp/src/secpipe_mcp}/dependencies.py (88%) create mode 100644 secpipe-mcp/src/secpipe_mcp/exceptions.py rename {fuzzforge-mcp/src/fuzzforge_mcp => secpipe-mcp/src/secpipe_mcp}/resources/__init__.py (60%) rename {fuzzforge-mcp/src/fuzzforge_mcp => secpipe-mcp/src/secpipe_mcp}/resources/executions.py (89%) rename {fuzzforge-mcp/src/fuzzforge_mcp => secpipe-mcp/src/secpipe_mcp}/resources/project.py (88%) rename {fuzzforge-mcp/src/fuzzforge_mcp => secpipe-mcp/src/secpipe_mcp}/settings.py (64%) rename {fuzzforge-mcp/src/fuzzforge_mcp => secpipe-mcp/src/secpipe_mcp}/skills/firmware-analysis.yaml (100%) rename {fuzzforge-mcp/src/fuzzforge_mcp => secpipe-mcp/src/secpipe_mcp}/skills/go-fuzzing.yaml (100%) rename {fuzzforge-mcp/src/fuzzforge_mcp => secpipe-mcp/src/secpipe_mcp}/storage.py (95%) rename {fuzzforge-mcp/src/fuzzforge_mcp => secpipe-mcp/src/secpipe_mcp}/tools/__init__.py (64%) rename {fuzzforge-mcp/src/fuzzforge_mcp => secpipe-mcp/src/secpipe_mcp}/tools/hub.py (98%) rename {fuzzforge-mcp/src/fuzzforge_mcp => secpipe-mcp/src/secpipe_mcp}/tools/projects.py (94%) rename {fuzzforge-mcp/src/fuzzforge_mcp => secpipe-mcp/src/secpipe_mcp}/tools/reports.py (95%) rename {fuzzforge-mcp => secpipe-mcp}/tests/__init__.py (100%) rename {fuzzforge-mcp => secpipe-mcp}/tests/conftest.py (53%) rename {fuzzforge-mcp => secpipe-mcp}/tests/test_resources.py (88%) rename {fuzzforge-tests => secpipe-tests}/Makefile (100%) rename {fuzzforge-tests => secpipe-tests}/README.md (100%) rename {fuzzforge-tests => secpipe-tests}/mypy.ini (100%) rename {fuzzforge-tests => secpipe-tests}/pyproject.toml (63%) rename {fuzzforge-tests => secpipe-tests}/ruff.toml (100%) create mode 100644 secpipe-tests/src/secpipe_tests/__init__.py rename {fuzzforge-tests/src/fuzzforge_tests => secpipe-tests/src/secpipe_tests}/conftest.py (78%) rename {fuzzforge-tests/src/fuzzforge_tests => secpipe-tests/src/secpipe_tests}/fixtures.py (77%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 65d8f56..ab669e9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,37 +25,37 @@ jobs: - name: Install dependencies run: uv sync - - name: Ruff check (fuzzforge-cli) + - name: Ruff check (secpipe-cli) run: | - cd fuzzforge-cli + cd secpipe-cli uv run --extra lints ruff check src/ - - name: Ruff check (fuzzforge-mcp) + - name: Ruff check (secpipe-mcp) run: | - cd fuzzforge-mcp + cd secpipe-mcp uv run --extra lints ruff check src/ - - name: Ruff check (fuzzforge-common) + - name: Ruff check (secpipe-common) run: | - cd fuzzforge-common + cd secpipe-common uv run --extra lints ruff check src/ - - name: Mypy type check (fuzzforge-cli) + - name: Mypy type check (secpipe-cli) run: | - cd fuzzforge-cli + cd secpipe-cli uv run --extra lints mypy src/ - - name: Mypy type check (fuzzforge-mcp) + - name: Mypy type check (secpipe-mcp) run: | - cd fuzzforge-mcp + cd secpipe-mcp uv run --extra lints mypy src/ - # NOTE: Mypy check for fuzzforge-common temporarily disabled + # NOTE: Mypy check for secpipe-common temporarily disabled # due to 37 pre-existing type errors in legacy code. # TODO: Fix type errors and re-enable strict checking - #- name: Mypy type check (fuzzforge-common) + #- name: Mypy type check (secpipe-common) # run: | - # cd fuzzforge-common + # cd secpipe-common # uv run --extra lints mypy src/ test: @@ -77,10 +77,10 @@ jobs: - name: Run MCP tests run: | - cd fuzzforge-mcp + cd secpipe-mcp uv run --extra tests pytest -v - name: Run common tests run: | - cd fuzzforge-common + cd secpipe-common uv run --extra tests pytest -v diff --git a/.github/workflows/mcp-server.yml b/.github/workflows/mcp-server.yml index 233fd42..b35fb89 100644 --- a/.github/workflows/mcp-server.yml +++ b/.github/workflows/mcp-server.yml @@ -27,23 +27,23 @@ jobs: - name: Start MCP server in background run: | - cd fuzzforge-mcp - nohup uv run python -m fuzzforge_mcp.server > server.log 2>&1 & + cd secpipe-mcp + nohup uv run uvicorn secpipe_mcp.application:app --host 127.0.0.1 --port 8000 > server.log 2>&1 & echo $! > server.pid sleep 3 - name: Run MCP tool tests run: | - cd fuzzforge-mcp + cd secpipe-mcp uv run --extra tests pytest tests/test_resources.py -v - name: Stop MCP server if: always() run: | - if [ -f fuzzforge-mcp/server.pid ]; then - kill $(cat fuzzforge-mcp/server.pid) || true + if [ -f secpipe-mcp/server.pid ]; then + kill $(cat secpipe-mcp/server.pid) || true fi - name: Show server logs if: failure() - run: cat fuzzforge-mcp/server.log || true + run: cat secpipe-mcp/server.log || true diff --git a/.gitignore b/.gitignore index 60f5afb..9837391 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ __pycache__ # User-specific hub config (generated at runtime) hub-config.json +*.egg-info/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8a53bbf..98628eb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -71,13 +71,13 @@ test(runner): add container execution tests 3. **Test Your Changes** ```bash # Test modules - FUZZFORGE_MODULES_PATH=./fuzzforge-modules uv run fuzzforge modules list + SECPIPE_MODULES_PATH=./secpipe-modules uv run secpipe modules list # Run a module - uv run fuzzforge modules run your-module --assets ./test-assets + uv run secpipe modules run your-module --assets ./test-assets # Test MCP integration (if applicable) - uv run fuzzforge mcp status + uv run secpipe mcp status ``` 4. **Submit Pull Request** @@ -88,11 +88,11 @@ test(runner): add container execution tests ## Module Development -SecPipe uses a modular architecture where security tools run as isolated containers. The `fuzzforge-modules-sdk` provides everything you need to create new modules. +SecPipe uses a modular architecture where security tools run as isolated containers. The `secpipe-modules-sdk` provides everything you need to create new modules. **Documentation:** -- [Module SDK Documentation](fuzzforge-modules/fuzzforge-modules-sdk/README.md) - Complete SDK reference -- [Module Template](fuzzforge-modules/fuzzforge-module-template/) - Starting point for new modules +- [Module SDK Documentation](secpipe-modules/secpipe-modules-sdk/README.md) - Complete SDK reference +- [Module Template](secpipe-modules/secpipe-module-template/) - Starting point for new modules - [USAGE Guide](USAGE.md) - Setup and installation instructions ### Creating a New Module @@ -100,8 +100,8 @@ SecPipe uses a modular architecture where security tools run as isolated contain 1. **Use the Module Template** ```bash # Generate a new module from template - cd fuzzforge-modules/ - cp -r fuzzforge-module-template my-new-module + cd secpipe-modules/ + cp -r secpipe-module-template my-new-module cd my-new-module ``` @@ -127,8 +127,8 @@ SecPipe uses a modular architecture where security tools run as isolated contain Edit `src/module/mod.py`: ```python - from fuzzforge_modules_sdk.api.modules import BaseModule - from fuzzforge_modules_sdk.api.models import ModuleResult + from secpipe_modules_sdk.api.modules import BaseModule + from secpipe_modules_sdk.api.models import ModuleResult from .models import MyModuleConfig, MyModuleOutput class MyModule(BaseModule[MyModuleConfig, MyModuleOutput]): @@ -157,7 +157,7 @@ SecPipe uses a modular architecture where security tools run as isolated contain Edit `src/module/models.py`: ```python from pydantic import BaseModel, Field - from fuzzforge_modules_sdk.api.models import BaseModuleConfig, BaseModuleOutput + from secpipe_modules_sdk.api.models import BaseModuleConfig, BaseModuleOutput class MyModuleConfig(BaseModuleConfig): """Configuration for your module.""" @@ -173,31 +173,31 @@ SecPipe uses a modular architecture where security tools run as isolated contain 5. **Build Your Module** ```bash # Build the SDK first (if not already done) - cd ../fuzzforge-modules-sdk + cd ../secpipe-modules-sdk uv build mkdir -p .wheels - cp ../../dist/fuzzforge_modules_sdk-*.whl .wheels/ + cp ../../dist/secpipe_modules_sdk-*.whl .wheels/ cd ../.. - docker build -t localhost/fuzzforge-modules-sdk:0.1.0 fuzzforge-modules/fuzzforge-modules-sdk/ + docker build -t localhost/secpipe-modules-sdk:0.1.0 secpipe-modules/secpipe-modules-sdk/ # Build your module - cd fuzzforge-modules/my-new-module - docker build -t fuzzforge-my-new-module:0.1.0 . + cd secpipe-modules/my-new-module + docker build -t secpipe-my-new-module:0.1.0 . ``` 6. **Test Your Module** ```bash # Run with test assets - uv run fuzzforge modules run my-new-module --assets ./test-assets + uv run secpipe modules run my-new-module --assets ./test-assets # Check module info - uv run fuzzforge modules info my-new-module + uv run secpipe modules info my-new-module ``` ### Module Development Guidelines **Important Conventions:** -- **Input/Output**: Use `/fuzzforge/input` for assets and `/fuzzforge/output` for results +- **Input/Output**: Use `/secpipe/input` for assets and `/secpipe/output` for results - **Configuration**: Support JSON configuration via stdin or file - **Logging**: Use structured logging (structlog is pre-configured) - **Error Handling**: Return proper exit codes and error messages @@ -206,7 +206,7 @@ SecPipe uses a modular architecture where security tools run as isolated contain - **Dependencies**: Minimize container size, use multi-stage builds **See also:** -- [Module SDK API Reference](fuzzforge-modules/fuzzforge-modules-sdk/src/fuzzforge_modules_sdk/api/) +- [Module SDK API Reference](secpipe-modules/secpipe-modules-sdk/src/secpipe_modules_sdk/api/) - [Dockerfile Best Practices](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/) ### Module Types @@ -273,8 +273,8 @@ SecPipe is designed to support modules across **all cybersecurity domains**. The ```python # src/module/mod.py from pathlib import Path -from fuzzforge_modules_sdk.api.modules import BaseModule -from fuzzforge_modules_sdk.api.models import ModuleResult +from secpipe_modules_sdk.api.modules import BaseModule +from secpipe_modules_sdk.api.models import ModuleResult from .models import ScannerConfig, ScannerOutput class SecurityScanner(BaseModule[ScannerConfig, ScannerOutput]): @@ -350,18 +350,18 @@ Beyond modules, you can contribute to SecPipe's core components. ### Core Components -- **fuzzforge-mcp** - MCP server for AI agent integration -- **fuzzforge-runner** - Module execution engine -- **fuzzforge-cli** - Command-line interface -- **fuzzforge-common** - Shared utilities and sandbox engines -- **fuzzforge-types** - Type definitions and schemas +- **secpipe-mcp** - MCP server for AI agent integration +- **secpipe-runner** - Module execution engine +- **secpipe-cli** - Command-line interface +- **secpipe-common** - Shared utilities and sandbox engines +- **secpipe-types** - Type definitions and schemas ### Development Setup 1. **Clone and Install** ```bash - git clone https://github.com/FuzzingLabs/fuzzforge_ai.git - cd fuzzforge_ai + git clone https://github.com/FuzzingLabs/secpipe_ai.git + cd secpipe_ai uv sync --all-extras ``` @@ -371,7 +371,7 @@ Beyond modules, you can contribute to SecPipe's core components. make test # Run specific package tests - cd fuzzforge-mcp + cd secpipe-mcp uv run pytest ``` @@ -381,7 +381,7 @@ Beyond modules, you can contribute to SecPipe's core components. make typecheck # Type check specific package - cd fuzzforge-runner + cd secpipe-runner uv run mypy . ``` @@ -399,7 +399,7 @@ Beyond modules, you can contribute to SecPipe's core components. When reporting bugs, please include: - **Environment**: OS, Python version, Docker version, uv version -- **SecPipe Version**: Output of `uv run fuzzforge --version` +- **SecPipe Version**: Output of `uv run secpipe --version` - **Module**: Which module or component is affected - **Steps to Reproduce**: Clear steps to recreate the issue - **Expected Behavior**: What should happen @@ -419,7 +419,7 @@ When reporting bugs, please include: **Module:** my-custom-scanner **Steps to Reproduce:** -1. Run `uv run fuzzforge modules run my-scanner --assets ./test-target` +1. Run `uv run secpipe modules run my-scanner --assets ./test-target` 2. Module fails with timeout error **Expected:** Module completes analysis @@ -491,7 +491,7 @@ Brief description of what this module does. ## Usage \`\`\`bash -uv run fuzzforge modules run module-name --assets ./path/to/assets +uv run secpipe modules run module-name --assets ./path/to/assets \`\`\` ## Output @@ -552,7 +552,7 @@ For module contributions: Need help contributing? - Join our [Discord](https://discord.gg/8XEX33UUwZ) -- Read the [Module SDK Documentation](fuzzforge-modules/fuzzforge-modules-sdk/README.md) +- Read the [Module SDK Documentation](secpipe-modules/secpipe-modules-sdk/README.md) - Check the module template for examples - Contact: contact@fuzzinglabs.com diff --git a/Makefile b/Makefile index f04b240..aa83149 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ SHELL := /bin/bash # Default target help: - @echo "FuzzForge AI Development Commands" + @echo "SecPipe AI Development Commands" @echo "" @echo " make install - Install all dependencies" @echo " make sync - Sync shared packages from upstream" @@ -20,17 +20,17 @@ help: install: uv sync -# Sync shared packages from upstream fuzzforge-core +# Sync shared packages from upstream secpipe-core sync: @if [ -z "$(UPSTREAM)" ]; then \ - echo "Usage: make sync UPSTREAM=/path/to/fuzzforge-core"; \ + echo "Usage: make sync UPSTREAM=/path/to/secpipe-core"; \ exit 1; \ fi ./scripts/sync-upstream.sh $(UPSTREAM) # Format all packages format: - @for pkg in packages/fuzzforge-*/; do \ + @for pkg in packages/secpipe-*/; do \ if [ -f "$$pkg/pyproject.toml" ]; then \ echo "Formatting $$pkg..."; \ cd "$$pkg" && uv run ruff format . && cd -; \ @@ -39,7 +39,7 @@ format: # Lint all packages lint: - @for pkg in packages/fuzzforge-*/; do \ + @for pkg in packages/secpipe-*/; do \ if [ -f "$$pkg/pyproject.toml" ]; then \ echo "Linting $$pkg..."; \ cd "$$pkg" && uv run ruff check . && cd -; \ @@ -48,7 +48,7 @@ lint: # Type check all packages typecheck: - @for pkg in packages/fuzzforge-*/; do \ + @for pkg in packages/secpipe-*/; do \ if [ -f "$$pkg/pyproject.toml" ] && [ -f "$$pkg/mypy.ini" ]; then \ echo "Type checking $$pkg..."; \ cd "$$pkg" && uv run mypy . && cd -; \ @@ -57,7 +57,7 @@ typecheck: # Run all tests test: - @for pkg in packages/fuzzforge-*/; do \ + @for pkg in packages/secpipe-*/; do \ if [ -f "$$pkg/pytest.ini" ]; then \ echo "Testing $$pkg..."; \ cd "$$pkg" && uv run pytest && cd -; \ diff --git a/NOTICE b/NOTICE index 26928a0..21dd079 100644 --- a/NOTICE +++ b/NOTICE @@ -1,4 +1,4 @@ -FuzzForge +SecPipe Copyright (c) 2025 FuzzingLabs This product includes software developed by FuzzingLabs (https://fuzzforge.ai). @@ -7,6 +7,6 @@ Licensed under the Business Source License 1.1 (BSL). After the Change Date (four years from the date of publication), this version of the Licensed Work will be made available under the Apache License, Version 2.0. -You may not use the name "FuzzingLabs" or "FuzzForge" nor the names of its +You may not use the name "FuzzingLabs" or "SecPipe" nor the names of its contributors to endorse or promote products derived from this software without specific prior written permission. diff --git a/README.md b/README.md index 7b41643..8e6e954 100644 --- a/README.md +++ b/README.md @@ -76,8 +76,8 @@ Agent → Crash Analysis: Deduplicate and triage discovered crashes If you find SecPipe useful, please **star the repo** to support development! 🚀 - - GitHub Stars + + GitHub Stars --- @@ -169,8 +169,8 @@ The hub is open source and can be extended with your own MCP servers. See the [m ```bash # Clone the repository -git clone https://github.com/FuzzingLabs/fuzzforge_ai.git -cd fuzzforge_ai +git clone https://github.com/FuzzingLabs/secpipe_ai.git +cd secpipe_ai # Install dependencies uv sync @@ -180,28 +180,28 @@ uv sync ```bash # Clone the MCP Security Hub -git clone https://github.com/FuzzingLabs/mcp-security-hub.git ~/.fuzzforge/hubs/mcp-security-hub +git clone https://github.com/FuzzingLabs/mcp-security-hub.git ~/.secpipe/hubs/mcp-security-hub # Build the Docker images for the hub tools ./scripts/build-hub-images.sh ``` -Or use the terminal UI (`uv run fuzzforge ui`) to link hubs interactively. +Or use the terminal UI (`uv run secpipe ui`) to link hubs interactively. ### Configure MCP for Your AI Agent ```bash # For GitHub Copilot -uv run fuzzforge mcp install copilot +uv run secpipe mcp install copilot # For Claude Code (CLI) -uv run fuzzforge mcp install claude-code +uv run secpipe mcp install claude-code # For Claude Desktop (standalone app) -uv run fuzzforge mcp install claude-desktop +uv run secpipe mcp install claude-desktop # Verify installation -uv run fuzzforge mcp status +uv run secpipe mcp status ``` **Restart your editor** and your AI agent will have access to SecPipe tools! @@ -228,12 +228,12 @@ See the [Usage Guide](USAGE.md) for detailed setup and advanced workflows. ## 📁 Project Structure ``` -fuzzforge_ai/ -├── fuzzforge-mcp/ # MCP server — the core of SecPipe -├── fuzzforge-cli/ # Command-line interface & terminal UI -├── fuzzforge-common/ # Shared abstractions (containers, storage) -├── fuzzforge-runner/ # Container execution engine (Docker/Podman) -├── fuzzforge-tests/ # Integration tests +secpipe_ai/ +├── secpipe-mcp/ # MCP server — the core of SecPipe +├── secpipe-cli/ # Command-line interface & terminal UI +├── secpipe-common/ # Shared abstractions (containers, storage) +├── secpipe-runner/ # Container execution engine (Docker/Podman) +├── secpipe-tests/ # Integration tests ├── mcp-security-hub/ # Default hub: 36 offensive security MCP servers └── scripts/ # Hub image build scripts ``` diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md new file mode 100644 index 0000000..dded70f --- /dev/null +++ b/RELEASE_NOTES.md @@ -0,0 +1,65 @@ +# v0.8.0 — MCP Hub Architecture + +SecPipe AI v0.8.0 is a major architectural rewrite. The previous module system has been replaced by the **MCP Hub** architecture — SecPipe now acts as a meta-MCP server that connects AI agents to collections of containerized security tools, discovered and orchestrated at runtime. + +--- + +## Highlights + +### MCP Hub System + +SecPipe no longer ships its own security modules. Instead, it connects to **MCP tool hubs** — registries of Dockerized MCP servers that AI agents can discover, chain, and execute autonomously. + +- **Runtime tool discovery** — agents call `list_hub_servers` and `discover_hub_tools` to find available tools +- **Agent context convention** — hub tools provide built-in usage tips, workflow guidance, and domain knowledge so agents can use them without human intervention +- **Category filtering** — servers are organized by category (`binary-analysis`, `web-security`, `reconnaissance`, etc.) for efficient discovery +- **Persistent sessions** — stateful tools like Radare2 run in long-lived containers with `start_hub_server` / `stop_hub_server` +- **Volume mounts** — project assets are automatically mounted into tool containers for seamless file access +- **Continuous mode** — long-running tools (fuzzers) with real-time status via `start_continuous_hub_tool` + +### MCP Security Hub Integration + +Ships with built-in support for the [MCP Security Hub](https://github.com/FuzzingLabs/mcp-security-hub) — **36 production-ready MCP servers** covering: + +| Category | Servers | Examples | +|----------|---------|----------| +| Reconnaissance | 8 | Nmap, Masscan, Shodan, WhatWeb | +| Web Security | 6 | Nuclei, SQLMap, ffuf, Nikto | +| Binary Analysis | 6 | Radare2, Binwalk, YARA, Capa, Ghidra | +| Blockchain | 3 | Medusa, Solazy, DAML Viewer | +| Cloud Security | 3 | Trivy, Prowler, RoadRecon | +| Code Security | 1 | Semgrep | +| Secrets Detection | 1 | Gitleaks | +| Exploitation | 1 | SearchSploit | +| Fuzzing | 2 | Boofuzz, Dharma | +| OSINT | 2 | Maigret, DNSTwist | +| Threat Intel | 2 | VirusTotal, AlienVault OTX | +| Active Directory | 1 | BloodHound | + +> **185+ individual security tools** accessible through a single MCP connection. + +### Terminal UI + +A new interactive terminal interface (`uv run secpipe ui`) for managing hubs and agents: + +- Dashboard with hub status overview +- One-click MCP server installation for GitHub Copilot, Claude Code, and Claude Desktop +- In-UI Docker image building with live log viewer +- Hub linking and registry management + +--- + +## Breaking Changes + +- The module system has been removed (`list_modules`, `execute_module`, `start_continuous_module`) +- Replaced by hub tools: `list_hub_servers`, `discover_hub_tools`, `execute_hub_tool`, `start_hub_server`, `stop_hub_server`, etc. +- `make build-modules` replaced by `./scripts/build-hub-images.sh` + +--- + +## Other Changes + +- **CI**: GitHub Actions workflows with ruff lint, mypy typecheck, and tests +- **Config**: `SECPIPE_USER_DIR` environment variable to override user-global data directory +- **Storage**: `~/.secpipe` for user-global data, `.secpipe/` in workspace for project storage +- **Docs**: README rewritten for hub-centric architecture diff --git a/ROADMAP.md b/ROADMAP.md index e00bdb3..de7d686 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -115,7 +115,7 @@ Features under consideration for future releases: Have suggestions for the roadmap? -- Open an issue on [GitHub](https://github.com/FuzzingLabs/fuzzforge_ai/issues) +- Open an issue on [GitHub](https://github.com/FuzzingLabs/secpipe_ai/issues) - Join our [Discord](https://discord.gg/8XEX33UUwZ) --- diff --git a/USAGE.md b/USAGE.md index e105643..3d4177b 100644 --- a/USAGE.md +++ b/USAGE.md @@ -3,7 +3,7 @@ This guide covers everything you need to know to get started with SecPipe AI — from installation to linking your first MCP hub and running security research workflows with AI. > **SecPipe is designed to be used with AI agents** (GitHub Copilot, Claude, etc.) via MCP. -> A terminal UI (`fuzzforge ui`) is provided for managing agents and hubs. +> A terminal UI (`secpipe ui`) is provided for managing agents and hubs. > The CLI is available for advanced users but the primary experience is through natural language interaction with your AI assistant. --- @@ -41,12 +41,12 @@ This guide covers everything you need to know to get started with SecPipe AI — ```bash # 1. Clone and install -git clone https://github.com/FuzzingLabs/fuzzforge_ai.git -cd fuzzforge_ai +git clone https://github.com/FuzzingLabs/secpipe_ai.git +cd secpipe_ai uv sync # 2. Launch the terminal UI -uv run fuzzforge ui +uv run secpipe ui # 3. Press 'h' → "FuzzingLabs Hub" to clone & link the default security hub # 4. Select an agent row and press Enter to install the MCP server for your agent @@ -63,12 +63,12 @@ Or do it entirely from the command line: ```bash # Install MCP for your AI agent -uv run fuzzforge mcp install copilot # For VS Code + GitHub Copilot +uv run secpipe mcp install copilot # For VS Code + GitHub Copilot # OR -uv run fuzzforge mcp install claude-code # For Claude Code CLI +uv run secpipe mcp install claude-code # For Claude Code CLI # Clone and link the default security hub -git clone git@github.com:FuzzingLabs/mcp-security-hub.git ~/.fuzzforge/hubs/mcp-security-hub +git clone git@github.com:FuzzingLabs/mcp-security-hub.git ~/.secpipe/hubs/mcp-security-hub # Build hub tool images (required — tools only run once their image is built) ./scripts/build-hub-images.sh @@ -112,7 +112,7 @@ sudo usermod -aG docker $USER ``` > **Note:** Podman is also supported. Use `--engine podman` with CLI commands -> or set `FUZZFORGE_ENGINE=podman` environment variable. +> or set `SECPIPE_ENGINE=podman` environment variable. --- @@ -121,8 +121,8 @@ sudo usermod -aG docker $USER ### 1. Clone the Repository ```bash -git clone https://github.com/FuzzingLabs/fuzzforge_ai.git -cd fuzzforge_ai +git clone https://github.com/FuzzingLabs/secpipe_ai.git +cd secpipe_ai ``` ### 2. Install Dependencies @@ -136,7 +136,7 @@ This installs all SecPipe components in a virtual environment. ### 3. Verify Installation ```bash -uv run fuzzforge --help +uv run secpipe --help ``` --- @@ -148,7 +148,7 @@ SecPipe ships with a terminal user interface (TUI) built on [Textual](https://te ### Launching the UI ```bash -uv run fuzzforge ui +uv run secpipe ui ``` ### Dashboard @@ -174,7 +174,7 @@ The main screen is split into two panels: Select an agent row in the AI Agents table and press `Enter`: - **If the agent is not linked** → a setup dialog opens asking for your container engine (Docker or Podman), then installs the SecPipe MCP configuration -- **If the agent is already linked** → a confirmation dialog offers to unlink it (removes the `fuzzforge` entry without touching other MCP servers) +- **If the agent is already linked** → a confirmation dialog offers to unlink it (removes the `secpipe` entry without touching other MCP servers) The setup auto-detects: - SecPipe installation root @@ -187,7 +187,7 @@ Press `h` to open the hub manager. This is where you manage your MCP hub reposit | Button | Action | |--------|--------| -| **FuzzingLabs Hub** | One-click clone of the official [mcp-security-hub](https://github.com/FuzzingLabs/mcp-security-hub) repository — clones to `~/.fuzzforge/hubs/mcp-security-hub`, scans for tools, and registers them in `hub-config.json` | +| **FuzzingLabs Hub** | One-click clone of the official [mcp-security-hub](https://github.com/FuzzingLabs/mcp-security-hub) repository — clones to `~/.secpipe/hubs/mcp-security-hub`, scans for tools, and registers them in `hub-config.json` | | **Link Path** | Link any local directory as a hub — enter a name and path, SecPipe scans it for `category/tool-name/Dockerfile` patterns | | **Clone URL** | Clone any git repository and link it as a hub | | **Remove** | Unlink the selected hub and remove its servers from the configuration | @@ -242,14 +242,14 @@ The default MCP hub is [mcp-security-hub](https://github.com/FuzzingLabs/mcp-sec **Clone it via the UI:** -1. `uv run fuzzforge ui` +1. `uv run secpipe ui` 2. Press `h` → click **FuzzingLabs Hub** 3. Wait for the clone to finish — servers are auto-registered **Or clone manually:** ```bash -git clone git@github.com:FuzzingLabs/mcp-security-hub.git ~/.fuzzforge/hubs/mcp-security-hub +git clone git@github.com:FuzzingLabs/mcp-security-hub.git ~/.secpipe/hubs/mcp-security-hub ``` ### Linking a Custom Hub @@ -286,7 +286,7 @@ If you prefer the command line over the TUI, you can configure agents directly: ### GitHub Copilot ```bash -uv run fuzzforge mcp install copilot +uv run secpipe mcp install copilot ``` The command auto-detects: @@ -295,7 +295,7 @@ The command auto-detects: **Optional overrides:** ```bash -uv run fuzzforge mcp install copilot --engine podman +uv run secpipe mcp install copilot --engine podman ``` **After installation:** Restart VS Code. SecPipe tools appear in GitHub Copilot Chat. @@ -303,7 +303,7 @@ uv run fuzzforge mcp install copilot --engine podman ### Claude Code (CLI) ```bash -uv run fuzzforge mcp install claude-code +uv run secpipe mcp install claude-code ``` Installs to `~/.claude.json`. SecPipe tools are available from any directory after restarting Claude. @@ -311,7 +311,7 @@ Installs to `~/.claude.json`. SecPipe tools are available from any directory aft ### Claude Desktop ```bash -uv run fuzzforge mcp install claude-desktop +uv run secpipe mcp install claude-desktop ``` **After installation:** Restart Claude Desktop. @@ -319,15 +319,15 @@ uv run fuzzforge mcp install claude-desktop ### Check Status ```bash -uv run fuzzforge mcp status +uv run secpipe mcp status ``` ### Remove Configuration ```bash -uv run fuzzforge mcp uninstall copilot -uv run fuzzforge mcp uninstall claude-code -uv run fuzzforge mcp uninstall claude-desktop +uv run secpipe mcp uninstall copilot +uv run secpipe mcp uninstall claude-code +uv run secpipe mcp uninstall claude-desktop ``` --- @@ -377,25 +377,25 @@ AI: Uses semgrep-mcp → "Found 5 findings: 2 high severity SQL injection ### UI Command ```bash -uv run fuzzforge ui # Launch the terminal dashboard +uv run secpipe ui # Launch the terminal dashboard ``` ### MCP Commands ```bash -uv run fuzzforge mcp status # Check agent configuration status -uv run fuzzforge mcp install # Install MCP config (copilot|claude-code|claude-desktop) -uv run fuzzforge mcp uninstall # Remove MCP config -uv run fuzzforge mcp generate # Preview config without installing +uv run secpipe mcp status # Check agent configuration status +uv run secpipe mcp install # Install MCP config (copilot|claude-code|claude-desktop) +uv run secpipe mcp uninstall # Remove MCP config +uv run secpipe mcp generate # Preview config without installing ``` ### Project Commands ```bash -uv run fuzzforge project init # Initialize a project -uv run fuzzforge project info # Show project info -uv run fuzzforge project executions # List executions -uv run fuzzforge project results # Get execution results +uv run secpipe project init # Initialize a project +uv run secpipe project info # Show project info +uv run secpipe project executions # List executions +uv run secpipe project results # Get execution results ``` --- @@ -406,21 +406,21 @@ Configure SecPipe using environment variables: ```bash # Override the SecPipe installation root (auto-detected from cwd by default) -export FUZZFORGE_ROOT=/path/to/fuzzforge_ai +export SECPIPE_ROOT=/path/to/secpipe_ai -# Override the user-global data directory (default: ~/.fuzzforge) +# Override the user-global data directory (default: ~/.secpipe) # Useful for isolated testing without touching your real installation -export FUZZFORGE_USER_DIR=/tmp/my-fuzzforge-test +export SECPIPE_USER_DIR=/tmp/my-secpipe-test -# Storage path for projects and execution results (default: /.fuzzforge/storage) -export FUZZFORGE_STORAGE__PATH=/path/to/storage +# Storage path for projects and execution results (default: /.secpipe/storage) +export SECPIPE_STORAGE__PATH=/path/to/storage # Container engine (Docker is default) -export FUZZFORGE_ENGINE__TYPE=docker # or podman +export SECPIPE_ENGINE__TYPE=docker # or podman # Podman-specific container storage paths -export FUZZFORGE_ENGINE__GRAPHROOT=~/.fuzzforge/containers/storage -export FUZZFORGE_ENGINE__RUNROOT=~/.fuzzforge/containers/run +export SECPIPE_ENGINE__GRAPHROOT=~/.secpipe/containers/storage +export SECPIPE_ENGINE__RUNROOT=~/.secpipe/containers/run ``` --- @@ -473,7 +473,7 @@ docker build -t :latest mcp-security-hub/// ```bash # Check agent configuration -uv run fuzzforge mcp status +uv run secpipe mcp status # Verify the config file path exists and contains valid JSON cat ~/.config/Code/User/mcp.json # Copilot @@ -484,29 +484,29 @@ cat ~/.claude.json # Claude Code ```bash # Install with Podman engine -uv run fuzzforge mcp install copilot --engine podman +uv run secpipe mcp install copilot --engine podman # Or set environment variable -export FUZZFORGE_ENGINE=podman +export SECPIPE_ENGINE=podman ``` ### Hub Registry -SecPipe stores linked hub information in `~/.fuzzforge/hubs.json`. If something goes wrong: +SecPipe stores linked hub information in `~/.secpipe/hubs.json`. If something goes wrong: ```bash # View registry -cat ~/.fuzzforge/hubs.json +cat ~/.secpipe/hubs.json # Reset registry -rm ~/.fuzzforge/hubs.json +rm ~/.secpipe/hubs.json ``` --- ## Next Steps -- 🖥️ Launch `uv run fuzzforge ui` and explore the dashboard +- 🖥️ Launch `uv run secpipe ui` and explore the dashboard - 🔒 Clone the [mcp-security-hub](https://github.com/FuzzingLabs/mcp-security-hub) for 40+ security tools - 💬 Join our [Discord](https://discord.gg/8XEX33UUwZ) for support diff --git a/fuzzforge-cli/src/fuzzforge_cli/tui/__init__.py b/fuzzforge-cli/src/fuzzforge_cli/tui/__init__.py deleted file mode 100644 index ed987a5..0000000 --- a/fuzzforge-cli/src/fuzzforge_cli/tui/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""FuzzForge terminal user interface.""" diff --git a/fuzzforge-cli/src/fuzzforge_cli/tui/screens/__init__.py b/fuzzforge-cli/src/fuzzforge_cli/tui/screens/__init__.py deleted file mode 100644 index 1cd8a98..0000000 --- a/fuzzforge-cli/src/fuzzforge_cli/tui/screens/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""TUI screens for FuzzForge.""" diff --git a/fuzzforge-common/src/fuzzforge_common/__init__.py b/fuzzforge-common/src/fuzzforge_common/__init__.py deleted file mode 100644 index b3353ac..0000000 --- a/fuzzforge-common/src/fuzzforge_common/__init__.py +++ /dev/null @@ -1,38 +0,0 @@ -"""FuzzForge Common - Shared abstractions and implementations for FuzzForge. - -This package provides: -- Sandbox engine abstractions (Podman, Docker) -- Common exceptions - -Example usage: - from fuzzforge_common import ( - AbstractFuzzForgeSandboxEngine, - ImageInfo, - Podman, - PodmanConfiguration, - ) -""" - -from fuzzforge_common.exceptions import FuzzForgeError -from fuzzforge_common.sandboxes import ( - AbstractFuzzForgeEngineConfiguration, - AbstractFuzzForgeSandboxEngine, - Docker, - DockerConfiguration, - FuzzForgeSandboxEngines, - ImageInfo, - Podman, - PodmanConfiguration, -) - -__all__ = [ - "AbstractFuzzForgeEngineConfiguration", - "AbstractFuzzForgeSandboxEngine", - "Docker", - "DockerConfiguration", - "FuzzForgeError", - "FuzzForgeSandboxEngines", - "ImageInfo", - "Podman", - "PodmanConfiguration", -] diff --git a/fuzzforge-common/src/fuzzforge_common/sandboxes/__init__.py b/fuzzforge-common/src/fuzzforge_common/sandboxes/__init__.py deleted file mode 100644 index 5efd40b..0000000 --- a/fuzzforge-common/src/fuzzforge_common/sandboxes/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -"""FuzzForge sandbox abstractions and implementations.""" - -from fuzzforge_common.sandboxes.engines import ( - AbstractFuzzForgeEngineConfiguration, - AbstractFuzzForgeSandboxEngine, - Docker, - DockerConfiguration, - FuzzForgeSandboxEngines, - ImageInfo, - Podman, - PodmanConfiguration, -) - -__all__ = [ - "AbstractFuzzForgeEngineConfiguration", - "AbstractFuzzForgeSandboxEngine", - "Docker", - "DockerConfiguration", - "FuzzForgeSandboxEngines", - "ImageInfo", - "Podman", - "PodmanConfiguration", -] diff --git a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/__init__.py b/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/__init__.py deleted file mode 100644 index f1a7c86..0000000 --- a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -"""Container engine implementations for FuzzForge sandboxes.""" - -from fuzzforge_common.sandboxes.engines.base import ( - AbstractFuzzForgeEngineConfiguration, - AbstractFuzzForgeSandboxEngine, - ImageInfo, -) -from fuzzforge_common.sandboxes.engines.docker import Docker, DockerConfiguration -from fuzzforge_common.sandboxes.engines.enumeration import FuzzForgeSandboxEngines -from fuzzforge_common.sandboxes.engines.podman import Podman, PodmanConfiguration - -__all__ = [ - "AbstractFuzzForgeEngineConfiguration", - "AbstractFuzzForgeSandboxEngine", - "Docker", - "DockerConfiguration", - "FuzzForgeSandboxEngines", - "ImageInfo", - "Podman", - "PodmanConfiguration", -] diff --git a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/base/__init__.py b/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/base/__init__.py deleted file mode 100644 index 5ebf022..0000000 --- a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/base/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -"""Base engine abstractions.""" - -from fuzzforge_common.sandboxes.engines.base.configuration import ( - AbstractFuzzForgeEngineConfiguration, -) -from fuzzforge_common.sandboxes.engines.base.engine import ( - AbstractFuzzForgeSandboxEngine, - ImageInfo, -) - -__all__ = [ - "AbstractFuzzForgeEngineConfiguration", - "AbstractFuzzForgeSandboxEngine", - "ImageInfo", -] diff --git a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/docker/__init__.py b/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/docker/__init__.py deleted file mode 100644 index a49075a..0000000 --- a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/docker/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Docker container engine implementation.""" - -from fuzzforge_common.sandboxes.engines.docker.cli import DockerCLI -from fuzzforge_common.sandboxes.engines.docker.configuration import ( - DockerConfiguration, -) -from fuzzforge_common.sandboxes.engines.docker.engine import Docker - -__all__ = [ - "Docker", - "DockerCLI", - "DockerConfiguration", -] diff --git a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/docker/configuration.py b/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/docker/configuration.py deleted file mode 100644 index 321e53f..0000000 --- a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/docker/configuration.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import TYPE_CHECKING, Literal - -from fuzzforge_common.sandboxes.engines.base.configuration import AbstractFuzzForgeEngineConfiguration -from fuzzforge_common.sandboxes.engines.docker.engine import Docker -from fuzzforge_common.sandboxes.engines.enumeration import FuzzForgeSandboxEngines - -if TYPE_CHECKING: - from fuzzforge_common.sandboxes.engines.base.engine import AbstractFuzzForgeSandboxEngine - - -class DockerConfiguration(AbstractFuzzForgeEngineConfiguration): - """TODO.""" - - #: TODO. - kind: Literal[FuzzForgeSandboxEngines.DOCKER] = FuzzForgeSandboxEngines.DOCKER - - #: TODO. - socket: str - - def into_engine(self) -> AbstractFuzzForgeSandboxEngine: - """TODO.""" - return Docker(socket=self.socket) diff --git a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/podman/__init__.py b/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/podman/__init__.py deleted file mode 100644 index 059af8b..0000000 --- a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/podman/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Podman container engine implementation.""" - -from fuzzforge_common.sandboxes.engines.podman.cli import PodmanCLI -from fuzzforge_common.sandboxes.engines.podman.configuration import ( - PodmanConfiguration, -) -from fuzzforge_common.sandboxes.engines.podman.engine import Podman - -__all__ = [ - "Podman", - "PodmanCLI", - "PodmanConfiguration", -] diff --git a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/podman/configuration.py b/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/podman/configuration.py deleted file mode 100644 index 2669303..0000000 --- a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/podman/configuration.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import TYPE_CHECKING, Literal - -from fuzzforge_common.sandboxes.engines.base.configuration import AbstractFuzzForgeEngineConfiguration -from fuzzforge_common.sandboxes.engines.enumeration import FuzzForgeSandboxEngines -from fuzzforge_common.sandboxes.engines.podman.engine import Podman - -if TYPE_CHECKING: - from fuzzforge_common.sandboxes.engines.base.engine import AbstractFuzzForgeSandboxEngine - - -class PodmanConfiguration(AbstractFuzzForgeEngineConfiguration): - """TODO.""" - - #: TODO. - kind: Literal[FuzzForgeSandboxEngines.PODMAN] = FuzzForgeSandboxEngines.PODMAN - - #: TODO. - socket: str - - def into_engine(self) -> AbstractFuzzForgeSandboxEngine: - """TODO.""" - return Podman(socket=self.socket) diff --git a/fuzzforge-common/tests/conftest.py b/fuzzforge-common/tests/conftest.py deleted file mode 100644 index f4324d8..0000000 --- a/fuzzforge-common/tests/conftest.py +++ /dev/null @@ -1 +0,0 @@ -pytest_plugins = ["fuzzforge_tests.fixtures"] diff --git a/fuzzforge-mcp/src/fuzzforge_mcp/exceptions.py b/fuzzforge-mcp/src/fuzzforge_mcp/exceptions.py deleted file mode 100644 index 527739f..0000000 --- a/fuzzforge-mcp/src/fuzzforge_mcp/exceptions.py +++ /dev/null @@ -1,5 +0,0 @@ -"""TODO.""" - - -class FuzzForgeMCPError(Exception): - """TODO.""" diff --git a/fuzzforge-tests/src/fuzzforge_tests/__init__.py b/fuzzforge-tests/src/fuzzforge_tests/__init__.py deleted file mode 100644 index 27fa30a..0000000 --- a/fuzzforge-tests/src/fuzzforge_tests/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -"""Common test utilities and fixtures for FuzzForge packages. - -This package provides shared test utilities, fixtures, and helpers that can be -reused across multiple FuzzForge packages to reduce code duplication and ensure -consistency in testing approaches. - -""" - -__all__ = [] diff --git a/hub-config.json b/hub-config.json index c99e0d8..0303bcf 100644 --- a/hub-config.json +++ b/hub-config.json @@ -8,7 +8,7 @@ "category": "active-directory", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -21,7 +21,7 @@ "category": "binary-analysis", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -34,7 +34,7 @@ "category": "binary-analysis", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -47,7 +47,7 @@ "category": "binary-analysis", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -60,7 +60,7 @@ "category": "binary-analysis", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -73,7 +73,7 @@ "category": "binary-analysis", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -86,7 +86,7 @@ "category": "binary-analysis", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -99,7 +99,7 @@ "category": "blockchain", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -112,7 +112,7 @@ "category": "blockchain", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -125,7 +125,7 @@ "category": "blockchain", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -138,7 +138,7 @@ "category": "cloud-security", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -151,7 +151,7 @@ "category": "cloud-security", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -164,7 +164,7 @@ "category": "cloud-security", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -177,7 +177,7 @@ "category": "code-security", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -190,7 +190,7 @@ "category": "exploitation", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -203,7 +203,7 @@ "category": "fuzzing", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -216,7 +216,7 @@ "category": "fuzzing", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -229,7 +229,7 @@ "category": "osint", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -242,7 +242,7 @@ "category": "osint", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -255,7 +255,7 @@ "category": "password-cracking", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -270,7 +270,7 @@ "NET_RAW" ], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -285,7 +285,7 @@ "NET_RAW" ], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -300,7 +300,7 @@ "NET_RAW" ], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -315,7 +315,7 @@ "NET_RAW" ], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -330,7 +330,7 @@ "NET_RAW" ], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -345,7 +345,7 @@ "NET_RAW" ], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -360,7 +360,7 @@ "NET_RAW" ], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -375,7 +375,7 @@ "NET_RAW" ], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -388,7 +388,7 @@ "category": "secrets", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -401,7 +401,7 @@ "category": "threat-intel", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -414,7 +414,7 @@ "category": "threat-intel", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -429,7 +429,7 @@ "NET_RAW" ], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -444,7 +444,7 @@ "NET_RAW" ], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -459,7 +459,7 @@ "NET_RAW" ], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -474,7 +474,7 @@ "NET_RAW" ], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -489,7 +489,7 @@ "NET_RAW" ], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -504,7 +504,7 @@ "NET_RAW" ], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -517,7 +517,7 @@ "category": "code-security", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -530,7 +530,7 @@ "category": "code-security", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -543,7 +543,7 @@ "category": "code-security", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" @@ -556,7 +556,7 @@ "category": "code-security", "capabilities": [], "volumes": [ - "/home/afredefon/.fuzzforge/hub/workspace:/data" + "/home/afredefon/.secpipe/hub/workspace:/data" ], "enabled": true, "source_hub": "mcp-security-hub" diff --git a/pyproject.toml b/pyproject.toml index 2e2e1eb..96bc516 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,16 +1,16 @@ [project] -name = "fuzzforge-oss" +name = "secpipe-oss" version = "0.8.0" -description = "FuzzForge AI - AI-driven security research platform for local execution" +description = "SecPipe AI - AI-driven security research platform for local execution" readme = "README.md" requires-python = ">=3.14" authors = [ { name = "FuzzingLabs", email = "contact@fuzzinglabs.com" } ] dependencies = [ - "fuzzforge-cli", - "fuzzforge-mcp", - "fuzzforge-common", + "secpipe-cli", + "secpipe-mcp", + "secpipe-common", ] [project.optional-dependencies] @@ -18,21 +18,21 @@ dev = [ "pytest==9.0.2", "pytest-asyncio==1.3.0", "pytest-httpx==0.36.0", - "fuzzforge-tests", - "fuzzforge-common", - "fuzzforge-mcp", + "secpipe-tests", + "secpipe-common", + "secpipe-mcp", ] [tool.uv.workspace] members = [ - "fuzzforge-common", - "fuzzforge-mcp", - "fuzzforge-cli", - "fuzzforge-tests", + "secpipe-common", + "secpipe-mcp", + "secpipe-cli", + "secpipe-tests", ] [tool.uv.sources] -fuzzforge-common = { workspace = true } -fuzzforge-mcp = { workspace = true } -fuzzforge-cli = { workspace = true } -fuzzforge-tests = { workspace = true } +secpipe-common = { workspace = true } +secpipe-mcp = { workspace = true } +secpipe-cli = { workspace = true } +secpipe-tests = { workspace = true } diff --git a/fuzzforge-cli/Makefile b/secpipe-cli/Makefile similarity index 100% rename from fuzzforge-cli/Makefile rename to secpipe-cli/Makefile diff --git a/fuzzforge-cli/README.md b/secpipe-cli/README.md similarity index 100% rename from fuzzforge-cli/README.md rename to secpipe-cli/README.md diff --git a/fuzzforge-cli/mypy.ini b/secpipe-cli/mypy.ini similarity index 100% rename from fuzzforge-cli/mypy.ini rename to secpipe-cli/mypy.ini diff --git a/fuzzforge-cli/pyproject.toml b/secpipe-cli/pyproject.toml similarity index 63% rename from fuzzforge-cli/pyproject.toml rename to secpipe-cli/pyproject.toml index 2bfc1fb..078ce40 100644 --- a/fuzzforge-cli/pyproject.toml +++ b/secpipe-cli/pyproject.toml @@ -1,12 +1,12 @@ [project] -name = "fuzzforge-cli" +name = "secpipe-cli" version = "0.0.1" -description = "FuzzForge CLI - Command-line interface for FuzzForge AI." +description = "SecPipe CLI - Command-line interface for SecPipe AI." authors = [] readme = "README.md" requires-python = ">=3.14" dependencies = [ - "fuzzforge-mcp==0.0.1", + "secpipe-mcp==0.0.1", "rich>=14.0.0", "textual>=1.0.0", "typer==0.20.1", @@ -23,7 +23,7 @@ tests = [ ] [project.scripts] -fuzzforge = "fuzzforge_cli.__main__:main" +secpipe = "secpipe_cli.__main__:main" [tool.uv.sources] -fuzzforge-mcp = { workspace = true } +secpipe-mcp = { workspace = true } diff --git a/fuzzforge-cli/pytest.ini b/secpipe-cli/pytest.ini similarity index 100% rename from fuzzforge-cli/pytest.ini rename to secpipe-cli/pytest.ini diff --git a/fuzzforge-cli/ruff.toml b/secpipe-cli/ruff.toml similarity index 91% rename from fuzzforge-cli/ruff.toml rename to secpipe-cli/ruff.toml index 6db025b..e1a9ce0 100644 --- a/fuzzforge-cli/ruff.toml +++ b/secpipe-cli/ruff.toml @@ -13,7 +13,7 @@ ignore = [ "PLR2004", # allowing comparisons using unamed numerical constants in tests "S101", # allowing 'assert' statements in tests ] -"src/fuzzforge_cli/tui/**" = [ +"src/secpipe_cli/tui/**" = [ "ARG002", # unused method argument: callback signature "BLE001", # blind exception: broad error handling in UI "C901", # complexity: UI logic @@ -39,7 +39,7 @@ ignore = [ "TC002", # TYPE_CHECKING: runtime type needs "TC003", # TYPE_CHECKING: runtime type needs ] -"src/fuzzforge_cli/commands/mcp.py" = [ +"src/secpipe_cli/commands/mcp.py" = [ "ARG001", # unused argument: callback signature "B904", # raise from: existing pattern "F841", # unused variable: legacy code @@ -48,14 +48,14 @@ ignore = [ "PLR0915", # too many statements "SIM108", # ternary: readability preference ] -"src/fuzzforge_cli/application.py" = [ +"src/secpipe_cli/application.py" = [ "B008", # function call in default: Path.cwd() "PLC0415", # import outside top-level: lazy loading ] -"src/fuzzforge_cli/commands/projects.py" = [ +"src/secpipe_cli/commands/projects.py" = [ "TC003", # TYPE_CHECKING: runtime type needs ] -"src/fuzzforge_cli/context.py" = [ +"src/secpipe_cli/context.py" = [ "TC002", # TYPE_CHECKING: runtime type needs "TC003", # TYPE_CHECKING: runtime type needs ] diff --git a/fuzzforge-cli/src/fuzzforge_cli/__init__.py b/secpipe-cli/src/secpipe_cli/__init__.py similarity index 100% rename from fuzzforge-cli/src/fuzzforge_cli/__init__.py rename to secpipe-cli/src/secpipe_cli/__init__.py diff --git a/fuzzforge-cli/src/fuzzforge_cli/__main__.py b/secpipe-cli/src/secpipe_cli/__main__.py similarity index 68% rename from fuzzforge-cli/src/fuzzforge_cli/__main__.py rename to secpipe-cli/src/secpipe_cli/__main__.py index 25c97c3..f492391 100644 --- a/fuzzforge-cli/src/fuzzforge_cli/__main__.py +++ b/secpipe-cli/src/secpipe_cli/__main__.py @@ -1,6 +1,6 @@ """TODO.""" -from fuzzforge_cli.application import application +from secpipe_cli.application import application def main() -> None: diff --git a/fuzzforge-cli/src/fuzzforge_cli/application.py b/secpipe-cli/src/secpipe_cli/application.py similarity index 58% rename from fuzzforge-cli/src/fuzzforge_cli/application.py rename to secpipe-cli/src/secpipe_cli/application.py index 2ff84cb..984a834 100644 --- a/fuzzforge-cli/src/fuzzforge_cli/application.py +++ b/secpipe-cli/src/secpipe_cli/application.py @@ -1,18 +1,18 @@ -"""FuzzForge CLI application.""" +"""SecPipe CLI application.""" from pathlib import Path from typing import Annotated -from fuzzforge_mcp.storage import LocalStorage # type: ignore[import-untyped] +from secpipe_mcp.storage import LocalStorage # type: ignore[import-untyped] from typer import Context as TyperContext from typer import Option, Typer -from fuzzforge_cli.commands import mcp, projects -from fuzzforge_cli.context import Context +from secpipe_cli.commands import mcp, projects +from secpipe_cli.context import Context application: Typer = Typer( - name="fuzzforge", - help="FuzzForge AI - Security research orchestration platform.", + name="secpipe", + help="SecPipe AI - Security research orchestration platform.", ) @@ -23,21 +23,21 @@ def main( Option( "--project", "-p", - envvar="FUZZFORGE_PROJECT__DEFAULT_PATH", - help="Path to the FuzzForge project directory.", + envvar="SECPIPE_PROJECT__DEFAULT_PATH", + help="Path to the SecPipe project directory.", ), ] = Path.cwd(), storage_path: Annotated[ Path, Option( "--storage", - envvar="FUZZFORGE_STORAGE__PATH", + envvar="SECPIPE_STORAGE__PATH", help="Path to the storage directory.", ), - ] = Path.cwd() / ".fuzzforge" / "storage", + ] = Path.cwd() / ".secpipe" / "storage", context: TyperContext = None, # type: ignore[assignment] ) -> None: - """FuzzForge AI - Security research orchestration platform. + """SecPipe AI - Security research orchestration platform. Discover and execute MCP hub tools for security research. @@ -56,15 +56,15 @@ application.add_typer(projects.application) @application.command( name="ui", - help="Launch the FuzzForge terminal interface.", + help="Launch the SecPipe terminal interface.", ) def launch_ui() -> None: - """Launch the interactive FuzzForge TUI dashboard. + """Launch the interactive SecPipe TUI dashboard. Provides a visual dashboard showing AI agent connection status and hub server availability, with wizards for setup and configuration. """ - from fuzzforge_cli.tui.app import FuzzForgeApp + from secpipe_cli.tui.app import SecPipeApp - FuzzForgeApp().run() + SecPipeApp().run() diff --git a/fuzzforge-cli/src/fuzzforge_cli/commands/__init__.py b/secpipe-cli/src/secpipe_cli/commands/__init__.py similarity index 100% rename from fuzzforge-cli/src/fuzzforge_cli/commands/__init__.py rename to secpipe-cli/src/secpipe_cli/commands/__init__.py diff --git a/fuzzforge-cli/src/fuzzforge_cli/commands/mcp.py b/secpipe-cli/src/secpipe_cli/commands/mcp.py similarity index 77% rename from fuzzforge-cli/src/fuzzforge_cli/commands/mcp.py rename to secpipe-cli/src/secpipe_cli/commands/mcp.py index 8eb9e78..6322773 100644 --- a/fuzzforge-cli/src/fuzzforge_cli/commands/mcp.py +++ b/secpipe-cli/src/secpipe_cli/commands/mcp.py @@ -1,4 +1,4 @@ -"""MCP server configuration commands for FuzzForge CLI. +"""MCP server configuration commands for SecPipe CLI. This module provides commands for setting up MCP server connections with various AI agents (VS Code Copilot, Claude Code, etc.). @@ -126,74 +126,74 @@ def _detect_docker_socket() -> str: return "/var/run/docker.sock" -def _find_fuzzforge_root() -> Path: - """Find the FuzzForge installation root. +def _find_secpipe_root() -> Path: + """Find the SecPipe installation root. - :returns: Path to fuzzforge-oss directory. + :returns: Path to secpipe-oss directory. """ # Check environment variable override first - env_root = os.environ.get("FUZZFORGE_ROOT") + env_root = os.environ.get("SECPIPE_ROOT") if env_root: return Path(env_root).resolve() - # Walk up from cwd to find a fuzzforge root (hub-config.json is the marker) + # Walk up from cwd to find a secpipe root (hub-config.json is the marker) for parent in [Path.cwd(), *Path.cwd().parents]: if (parent / "hub-config.json").is_file(): return parent - # Fall back to __file__-based search (dev install inside fuzzforge-oss) + # Fall back to __file__-based search (dev install inside secpipe-oss) current = Path(__file__).resolve() for parent in current.parents: - if (parent / "fuzzforge-mcp").is_dir(): + if (parent / "secpipe-mcp").is_dir(): return parent return Path.cwd() def _generate_mcp_config( - fuzzforge_root: Path, + secpipe_root: Path, engine_type: str, engine_socket: str, ) -> dict[str, Any]: """Generate MCP server configuration. - :param fuzzforge_root: Path to fuzzforge-oss installation. + :param secpipe_root: Path to secpipe-oss installation. :param engine_type: Container engine type (podman or docker). :param engine_socket: Container engine socket path. :returns: MCP configuration dictionary. """ - venv_python = fuzzforge_root / ".venv" / "bin" / "python" + venv_python = secpipe_root / ".venv" / "bin" / "python" # Use uv run if no venv, otherwise use venv python directly if venv_python.exists(): command = str(venv_python) - args = ["-m", "fuzzforge_mcp"] + args = ["-m", "secpipe_mcp"] else: command = "uv" - args = ["--directory", str(fuzzforge_root), "run", "fuzzforge-mcp"] + args = ["--directory", str(secpipe_root), "run", "secpipe-mcp"] - # User-global storage paths for FuzzForge containers. - # Kept under ~/.fuzzforge so images are built once and shared across - # all workspaces — regardless of where `fuzzforge mcp install` is run. - # Override with FUZZFORGE_USER_DIR for isolated testing. - user_dir_env = os.environ.get("FUZZFORGE_USER_DIR") - fuzzforge_home = Path(user_dir_env).resolve() if user_dir_env else Path.home() / ".fuzzforge" - graphroot = fuzzforge_home / "containers" / "storage" - runroot = fuzzforge_home / "containers" / "run" + # User-global storage paths for SecPipe containers. + # Kept under ~/.secpipe so images are built once and shared across + # all workspaces — regardless of where `secpipe mcp install` is run. + # Override with SECPIPE_USER_DIR for isolated testing. + user_dir_env = os.environ.get("SECPIPE_USER_DIR") + secpipe_home = Path(user_dir_env).resolve() if user_dir_env else Path.home() / ".secpipe" + graphroot = secpipe_home / "containers" / "storage" + runroot = secpipe_home / "containers" / "run" return { "type": "stdio", "command": command, "args": args, - "cwd": str(fuzzforge_root), + "cwd": str(secpipe_root), "env": { - "FUZZFORGE_ENGINE__TYPE": engine_type, - "FUZZFORGE_ENGINE__GRAPHROOT": str(graphroot), - "FUZZFORGE_ENGINE__RUNROOT": str(runroot), - "FUZZFORGE_HUB__ENABLED": "true", - "FUZZFORGE_HUB__CONFIG_PATH": str(fuzzforge_root / "hub-config.json"), + "SECPIPE_ENGINE__TYPE": engine_type, + "SECPIPE_ENGINE__GRAPHROOT": str(graphroot), + "SECPIPE_ENGINE__RUNROOT": str(runroot), + "SECPIPE_HUB__ENABLED": "true", + "SECPIPE_HUB__CONFIG_PATH": str(secpipe_root / "hub-config.json"), }, } @@ -214,9 +214,9 @@ def status(context: Context) -> None: table.add_column("Agent", style="cyan") table.add_column("Config Path") table.add_column("Status") - table.add_column("FuzzForge Configured") + table.add_column("SecPipe Configured") - fuzzforge_root = _find_fuzzforge_root() + secpipe_root = _find_secpipe_root() agents = [ ("GitHub Copilot", _get_copilot_mcp_path(), "servers"), @@ -229,12 +229,12 @@ def status(context: Context) -> None: try: config = json.loads(config_path.read_text()) servers = config.get(servers_key, {}) - has_fuzzforge = "fuzzforge" in servers + has_secpipe = "secpipe" in servers table.add_row( name, str(config_path), "[green]✓ Exists[/green]", - "[green]✓ Yes[/green]" if has_fuzzforge else "[yellow]✗ No[/yellow]", + "[green]✓ Yes[/green]" if has_secpipe else "[yellow]✗ No[/yellow]", ) except json.JSONDecodeError: table.add_row( @@ -256,7 +256,7 @@ def status(context: Context) -> None: # Show detected environment console.print() console.print("[bold]Detected Environment:[/bold]") - console.print(f" FuzzForge Root: {_find_fuzzforge_root()}") + console.print(f" SecPipe Root: {_find_secpipe_root()}") console.print(f" Podman Socket: {_detect_podman_socket()}") console.print(f" Docker Socket: {_detect_docker_socket()}") @@ -290,7 +290,7 @@ def generate( """ console = Console() - fuzzforge_root = _find_fuzzforge_root() + secpipe_root = _find_secpipe_root() # Detect socket if engine == "podman": @@ -300,16 +300,16 @@ def generate( # Generate config server_config = _generate_mcp_config( - fuzzforge_root=fuzzforge_root, + secpipe_root=secpipe_root, engine_type=engine, engine_socket=socket, ) # Format based on agent if agent == AIAgent.COPILOT: - full_config = {"servers": {"fuzzforge": server_config}} + full_config = {"servers": {"secpipe": server_config}} else: # Claude Desktop or Claude Code - full_config = {"mcpServers": {"fuzzforge": server_config}} + full_config = {"mcpServers": {"secpipe": server_config}} config_json = json.dumps(full_config, indent=4) @@ -322,14 +322,14 @@ def generate( if agent == AIAgent.COPILOT: config_path = _get_copilot_mcp_path() elif agent == AIAgent.CLAUDE_CODE: - config_path = _get_claude_code_mcp_path(fuzzforge_root) + config_path = _get_claude_code_mcp_path(secpipe_root) else: # Claude Desktop config_path = _get_claude_desktop_mcp_path() console.print() console.print(f"[bold]Save to:[/bold] {config_path}") console.print() - console.print("[dim]Or run 'fuzzforge mcp install' to install automatically.[/dim]") + console.print("[dim]Or run 'secpipe mcp install' to install automatically.[/dim]") @application.command( @@ -357,14 +357,14 @@ def install( Option( "--force", "-f", - help="Overwrite existing fuzzforge configuration.", + help="Overwrite existing secpipe configuration.", ), ] = False, ) -> None: """Install MCP configuration for the specified AI agent. This will create or update the MCP configuration file, adding the - fuzzforge server configuration. + secpipe server configuration. :param context: Typer context. :param agent: Target AI agent. @@ -373,7 +373,7 @@ def install( """ console = Console() - fuzzforge_root = _find_fuzzforge_root() + secpipe_root = _find_secpipe_root() # Determine config path if agent == AIAgent.COPILOT: @@ -394,7 +394,7 @@ def install( # Generate server config server_config = _generate_mcp_config( - fuzzforge_root=fuzzforge_root, + secpipe_root=secpipe_root, engine_type=engine, engine_socket=socket, ) @@ -408,47 +408,47 @@ def install( console.print("[dim]Please fix the file manually or delete it.[/dim]") raise SystemExit(1) - # Check if fuzzforge already exists + # Check if secpipe already exists servers = existing_config.get(servers_key, {}) - if "fuzzforge" in servers and not force: - console.print("[yellow]FuzzForge is already configured.[/yellow]") + if "secpipe" in servers and not force: + console.print("[yellow]SecPipe is already configured.[/yellow]") console.print("[dim]Use --force to overwrite existing configuration.[/dim]") raise SystemExit(1) - # Add/update fuzzforge + # Add/update secpipe if servers_key not in existing_config: existing_config[servers_key] = {} - existing_config[servers_key]["fuzzforge"] = server_config + existing_config[servers_key]["secpipe"] = server_config full_config = existing_config else: # Create new config config_path.parent.mkdir(parents=True, exist_ok=True) - full_config = {servers_key: {"fuzzforge": server_config}} + full_config = {servers_key: {"secpipe": server_config}} # Write config config_path.write_text(json.dumps(full_config, indent=4)) - console.print(f"[green]✓ Installed FuzzForge MCP configuration for {agent.value}[/green]") + console.print(f"[green]✓ Installed SecPipe MCP configuration for {agent.value}[/green]") console.print() console.print(f"[bold]Configuration file:[/bold] {config_path}") console.print() console.print("[bold]Settings:[/bold]") console.print(f" Engine: {engine}") console.print(f" Socket: {socket}") - console.print(f" Hub Config: {fuzzforge_root / 'hub-config.json'}") + console.print(f" Hub Config: {secpipe_root / 'hub-config.json'}") console.print() console.print("[bold]Next steps:[/bold]") if agent == AIAgent.COPILOT: console.print(" 1. Restart VS Code") - console.print(" 2. Open Copilot Chat and look for FuzzForge tools") + console.print(" 2. Open Copilot Chat and look for SecPipe tools") elif agent == AIAgent.CLAUDE_CODE: console.print(" 1. Run 'claude' from any directory") - console.print(" 2. FuzzForge tools will be available") + console.print(" 2. SecPipe tools will be available") else: # Claude Desktop console.print(" 1. Restart Claude Desktop") - console.print(" 2. The fuzzforge MCP server will be available") + console.print(" 2. The secpipe MCP server will be available") @application.command( @@ -464,14 +464,14 @@ def uninstall( ), ], ) -> None: - """Remove FuzzForge MCP configuration from the specified AI agent. + """Remove SecPipe MCP configuration from the specified AI agent. :param context: Typer context. :param agent: Target AI agent. """ console = Console() - fuzzforge_root = _find_fuzzforge_root() + secpipe_root = _find_secpipe_root() # Determine config path if agent == AIAgent.COPILOT: @@ -495,16 +495,16 @@ def uninstall( raise SystemExit(1) servers = config.get(servers_key, {}) - if "fuzzforge" not in servers: - console.print("[yellow]FuzzForge is not configured.[/yellow]") + if "secpipe" not in servers: + console.print("[yellow]SecPipe is not configured.[/yellow]") return - # Remove fuzzforge - del servers["fuzzforge"] + # Remove secpipe + del servers["secpipe"] # Write back config_path.write_text(json.dumps(config, indent=4)) - console.print(f"[green]✓ Removed FuzzForge MCP configuration from {agent.value}[/green]") + console.print(f"[green]✓ Removed SecPipe MCP configuration from {agent.value}[/green]") console.print() console.print("[dim]Restart your AI agent for changes to take effect.[/dim]") diff --git a/fuzzforge-cli/src/fuzzforge_cli/commands/projects.py b/secpipe-cli/src/secpipe_cli/commands/projects.py similarity index 95% rename from fuzzforge-cli/src/fuzzforge_cli/commands/projects.py rename to secpipe-cli/src/secpipe_cli/commands/projects.py index a21c666..68a0558 100644 --- a/fuzzforge-cli/src/fuzzforge_cli/commands/projects.py +++ b/secpipe-cli/src/secpipe_cli/commands/projects.py @@ -1,4 +1,4 @@ -"""Project management commands for FuzzForge CLI.""" +"""Project management commands for SecPipe CLI.""" from pathlib import Path from typing import Annotated @@ -7,7 +7,7 @@ from rich.console import Console from rich.table import Table from typer import Argument, Context, Option, Typer -from fuzzforge_cli.context import get_project_path, get_storage +from secpipe_cli.context import get_project_path, get_storage application: Typer = Typer( name="project", @@ -16,7 +16,7 @@ application: Typer = Typer( @application.command( - help="Initialize a new FuzzForge project.", + help="Initialize a new SecPipe project.", name="init", ) def init_project( @@ -28,7 +28,7 @@ def init_project( ), ] = None, ) -> None: - """Initialize a new FuzzForge project. + """Initialize a new SecPipe project. Creates the necessary storage directories for the project. diff --git a/fuzzforge-cli/src/fuzzforge_cli/context.py b/secpipe-cli/src/secpipe_cli/context.py similarity index 88% rename from fuzzforge-cli/src/fuzzforge_cli/context.py rename to secpipe-cli/src/secpipe_cli/context.py index 7e12511..755d6c8 100644 --- a/fuzzforge-cli/src/fuzzforge_cli/context.py +++ b/secpipe-cli/src/secpipe_cli/context.py @@ -1,11 +1,11 @@ -"""FuzzForge CLI context management.""" +"""SecPipe CLI context management.""" from __future__ import annotations from pathlib import Path from typing import TYPE_CHECKING, cast -from fuzzforge_mcp.storage import LocalStorage # type: ignore[import-untyped] +from secpipe_mcp.storage import LocalStorage # type: ignore[import-untyped] if TYPE_CHECKING: from typer import Context as TyperContext @@ -20,7 +20,7 @@ class Context: def __init__(self, storage: LocalStorage, project_path: Path) -> None: """Initialize an instance of the class. - :param storage: FuzzForge local storage instance. + :param storage: SecPipe local storage instance. :param project_path: Path to the current project. """ diff --git a/secpipe-cli/src/secpipe_cli/tui/__init__.py b/secpipe-cli/src/secpipe_cli/tui/__init__.py new file mode 100644 index 0000000..a18cae9 --- /dev/null +++ b/secpipe-cli/src/secpipe_cli/tui/__init__.py @@ -0,0 +1 @@ +"""SecPipe terminal user interface.""" diff --git a/fuzzforge-cli/src/fuzzforge_cli/tui/app.py b/secpipe-cli/src/secpipe_cli/tui/app.py similarity index 94% rename from fuzzforge-cli/src/fuzzforge_cli/tui/app.py rename to secpipe-cli/src/secpipe_cli/tui/app.py index 80c79fc..4102e5e 100644 --- a/fuzzforge-cli/src/fuzzforge_cli/tui/app.py +++ b/secpipe-cli/src/secpipe_cli/tui/app.py @@ -1,6 +1,6 @@ -"""FuzzForge TUI application. +"""SecPipe TUI application. -Main terminal user interface for FuzzForge, providing a dashboard +Main terminal user interface for SecPipe, providing a dashboard with AI agent connection status, hub server availability, and hub management capabilities. @@ -20,16 +20,16 @@ from textual.containers import Horizontal, Vertical, VerticalScroll from textual.message import Message from textual.widgets import Button, DataTable, Footer, Header -from fuzzforge_cli.tui.helpers import ( +from secpipe_cli.tui.helpers import ( check_agent_status, check_hub_image, - find_fuzzforge_root, + find_secpipe_root, get_agent_configs, load_hub_config, ) if TYPE_CHECKING: - from fuzzforge_cli.commands.mcp import AIAgent + from secpipe_cli.commands.mcp import AIAgent # Agent config entries stored alongside their linked status for row mapping _AgentRow = tuple[str, "AIAgent", Path, str, bool] @@ -70,10 +70,10 @@ class SingleClickDataTable(DataTable[Any]): self.post_message(SingleClickDataTable.RowClicked(self, row_index)) -class FuzzForgeApp(App[None]): - """FuzzForge AI terminal user interface.""" +class SecPipeApp(App[None]): + """SecPipe AI terminal user interface.""" - TITLE = "FuzzForge AI" + TITLE = "SecPipe AI" SUB_TITLE = "Security Research Orchestration" CSS = """ @@ -300,8 +300,8 @@ class FuzzForgeApp(App[None]): table.cursor_type = "row" try: - fuzzforge_root = find_fuzzforge_root() - hub_config = load_hub_config(fuzzforge_root) + secpipe_root = find_secpipe_root() + hub_config = load_hub_config(secpipe_root) except Exception: table.add_row( Text("Error loading config", style="red"), "", "", "" @@ -400,14 +400,14 @@ class FuzzForgeApp(App[None]): display_name, agent, _config_path, _servers_key, is_linked = self._agent_rows[idx] if is_linked: - from fuzzforge_cli.tui.screens.agent_setup import AgentUnlinkScreen + from secpipe_cli.tui.screens.agent_setup import AgentUnlinkScreen self.push_screen( AgentUnlinkScreen(agent, display_name), callback=self._on_agent_changed, ) else: - from fuzzforge_cli.tui.screens.agent_setup import AgentSetupScreen + from secpipe_cli.tui.screens.agent_setup import AgentSetupScreen self.push_screen( AgentSetupScreen(agent, display_name), @@ -430,7 +430,7 @@ class FuzzForgeApp(App[None]): # If a build is already running, open the live log viewer if image in self._active_builds: - from fuzzforge_cli.tui.screens.build_log import BuildLogScreen + from secpipe_cli.tui.screens.build_log import BuildLogScreen self._build_dialog_open = True self.push_screen( BuildLogScreen(image), @@ -443,10 +443,10 @@ class FuzzForgeApp(App[None]): return if hub_name == "manual": - self.notify("Manual servers must be built outside FuzzForge") + self.notify("Manual servers must be built outside SecPipe") return - from fuzzforge_cli.tui.screens.build_image import BuildImageScreen + from secpipe_cli.tui.screens.build_image import BuildImageScreen self._build_dialog_open = True @@ -473,7 +473,7 @@ class FuzzForgeApp(App[None]): @work(thread=True) def _run_build(self, server_name: str, image: str, hub_name: str) -> None: """Build a Docker/Podman image in a background thread.""" - from fuzzforge_cli.tui.helpers import build_image, find_dockerfile_for_server + from secpipe_cli.tui.helpers import build_image, find_dockerfile_for_server logs = self._build_logs.setdefault(image, []) @@ -528,7 +528,7 @@ class FuzzForgeApp(App[None]): def action_add_fuzzinglabs_hub(self) -> None: """Open the clone dialog pre-filled with the FuzzingLabs hub URL.""" - from fuzzforge_cli.tui.screens.hub_manager import CloneHubScreen + from secpipe_cli.tui.screens.hub_manager import CloneHubScreen self.push_screen( CloneHubScreen( @@ -541,7 +541,7 @@ class FuzzForgeApp(App[None]): def action_manage_hubs(self) -> None: """Open the hub manager.""" - from fuzzforge_cli.tui.screens.hub_manager import HubManagerScreen + from secpipe_cli.tui.screens.hub_manager import HubManagerScreen self.push_screen(HubManagerScreen(), callback=self._on_hub_changed) diff --git a/fuzzforge-cli/src/fuzzforge_cli/tui/helpers.py b/secpipe-cli/src/secpipe_cli/tui/helpers.py similarity index 85% rename from fuzzforge-cli/src/fuzzforge_cli/tui/helpers.py rename to secpipe-cli/src/secpipe_cli/tui/helpers.py index 3efce39..174d266 100644 --- a/fuzzforge-cli/src/fuzzforge_cli/tui/helpers.py +++ b/secpipe-cli/src/secpipe_cli/tui/helpers.py @@ -1,4 +1,4 @@ -"""Shared helpers for FuzzForge TUI and CLI. +"""Shared helpers for SecPipe TUI and CLI. Provides utility functions for checking AI agent configuration status, hub server image availability, installing/removing MCP configurations, @@ -15,11 +15,11 @@ import subprocess from pathlib import Path from typing import Any -from fuzzforge_cli.commands.mcp import ( +from secpipe_cli.commands.mcp import ( AIAgent, _detect_docker_socket, _detect_podman_socket, - _find_fuzzforge_root, + _find_secpipe_root, _generate_mcp_config, _get_claude_code_user_mcp_path, _get_claude_desktop_mcp_path, @@ -28,41 +28,41 @@ from fuzzforge_cli.commands.mcp import ( # --- Hub Management Constants --- -FUZZFORGE_DEFAULT_HUB_URL = "git@github.com:FuzzingLabs/mcp-security-hub.git" -FUZZFORGE_DEFAULT_HUB_NAME = "mcp-security-hub" +SECPIPE_DEFAULT_HUB_URL = "git@github.com:FuzzingLabs/mcp-security-hub.git" +SECPIPE_DEFAULT_HUB_NAME = "mcp-security-hub" -def get_fuzzforge_user_dir() -> Path: - """Return the user-global ``~/.fuzzforge/`` directory. +def get_secpipe_user_dir() -> Path: + """Return the user-global ``~/.secpipe/`` directory. Stores data that is shared across all workspaces: cloned hub repositories, the hub registry, container storage (graphroot/runroot), and the hub workspace volume. - Override with the ``FUZZFORGE_USER_DIR`` environment variable to + Override with the ``SECPIPE_USER_DIR`` environment variable to redirect all user-global data to a custom path — useful for testing - a fresh install without touching the real ``~/.fuzzforge/``. + a fresh install without touching the real ``~/.secpipe/``. - :return: ``Path.home() / ".fuzzforge"`` or ``$FUZZFORGE_USER_DIR`` + :return: ``Path.home() / ".secpipe"`` or ``$SECPIPE_USER_DIR`` """ - env_dir = os.environ.get("FUZZFORGE_USER_DIR") + env_dir = os.environ.get("SECPIPE_USER_DIR") if env_dir: return Path(env_dir).resolve() - return Path.home() / ".fuzzforge" + return Path.home() / ".secpipe" -def get_fuzzforge_dir() -> Path: - """Return the project-local ``.fuzzforge/`` directory. +def get_secpipe_dir() -> Path: + """Return the project-local ``.secpipe/`` directory. Stores data that is specific to the current workspace: fuzzing results and project artifacts. Similar to how ``.git/`` scopes version-control data to a single project. - :return: ``Path.cwd() / ".fuzzforge"`` + :return: ``Path.cwd() / ".secpipe"`` """ - return Path.cwd() / ".fuzzforge" + return Path.cwd() / ".secpipe" # Categories that typically need NET_RAW capability for network access _NET_RAW_CATEGORIES = {"reconnaissance", "web-security"} @@ -101,7 +101,7 @@ def get_agent_configs() -> list[tuple[str, AIAgent, Path, str]]: def check_agent_status(config_path: Path, servers_key: str) -> tuple[bool, str]: - """Check whether an AI agent has FuzzForge configured. + """Check whether an AI agent has SecPipe configured. :param config_path: Path to the agent's MCP config file. :param servers_key: JSON key for the servers dict (e.g. "servers" or "mcpServers"). @@ -113,7 +113,7 @@ def check_agent_status(config_path: Path, servers_key: str) -> tuple[bool, str]: try: config = json.loads(config_path.read_text()) servers = config.get(servers_key, {}) - if "fuzzforge" in servers: + if "secpipe" in servers: return True, "Linked" return False, "Config exists, not linked" except json.JSONDecodeError: @@ -123,14 +123,14 @@ def check_agent_status(config_path: Path, servers_key: str) -> tuple[bool, str]: def check_hub_image(image: str) -> tuple[bool, str]: """Check whether a container image exists locally. - Respects the ``FUZZFORGE_ENGINE__TYPE`` environment variable so that + Respects the ``SECPIPE_ENGINE__TYPE`` environment variable so that Podman users see the correct build status instead of always "Not built". :param image: Image name (e.g. "semgrep-mcp:latest"). :return: Tuple of (is_ready, status_description). """ - engine = os.environ.get("FUZZFORGE_ENGINE__TYPE", "docker").lower() + engine = os.environ.get("SECPIPE_ENGINE__TYPE", "docker").lower() cmd = "podman" if engine == "podman" else "docker" try: result = subprocess.run( @@ -148,14 +148,14 @@ def check_hub_image(image: str) -> tuple[bool, str]: return False, f"{cmd} not found" -def load_hub_config(fuzzforge_root: Path) -> dict[str, Any]: - """Load hub-config.json from the FuzzForge root. +def load_hub_config(secpipe_root: Path) -> dict[str, Any]: + """Load hub-config.json from the SecPipe root. - :param fuzzforge_root: Path to fuzzforge-oss directory. + :param secpipe_root: Path to secpipe-oss directory. :return: Parsed hub configuration dict, empty dict on error. """ - config_path = fuzzforge_root / "hub-config.json" + config_path = secpipe_root / "hub-config.json" if not config_path.exists(): return {} try: @@ -165,17 +165,17 @@ def load_hub_config(fuzzforge_root: Path) -> dict[str, Any]: return {} -def find_fuzzforge_root() -> Path: - """Find the FuzzForge installation root directory. +def find_secpipe_root() -> Path: + """Find the SecPipe installation root directory. - :return: Path to the fuzzforge-oss directory. + :return: Path to the secpipe-oss directory. """ - return _find_fuzzforge_root() + return _find_secpipe_root() def install_agent_config(agent: AIAgent, engine: str, force: bool = False) -> str: - """Install FuzzForge MCP configuration for an AI agent. + """Install SecPipe MCP configuration for an AI agent. :param agent: Target AI agent. :param engine: Container engine type ("docker" or "podman"). @@ -183,7 +183,7 @@ def install_agent_config(agent: AIAgent, engine: str, force: bool = False) -> st :return: Result message string. """ - fuzzforge_root = _find_fuzzforge_root() + secpipe_root = _find_secpipe_root() if agent == AIAgent.COPILOT: config_path = _get_copilot_mcp_path() @@ -198,7 +198,7 @@ def install_agent_config(agent: AIAgent, engine: str, force: bool = False) -> st socket = _detect_docker_socket() if engine == "docker" else _detect_podman_socket() server_config = _generate_mcp_config( - fuzzforge_root=fuzzforge_root, + secpipe_root=secpipe_root, engine_type=engine, engine_socket=socket, ) @@ -210,23 +210,23 @@ def install_agent_config(agent: AIAgent, engine: str, force: bool = False) -> st return f"Error: Invalid JSON in {config_path}" servers = existing.get(servers_key, {}) - if "fuzzforge" in servers and not force: + if "secpipe" in servers and not force: return "Already configured (use force to overwrite)" if servers_key not in existing: existing[servers_key] = {} - existing[servers_key]["fuzzforge"] = server_config + existing[servers_key]["secpipe"] = server_config full_config = existing else: config_path.parent.mkdir(parents=True, exist_ok=True) - full_config = {servers_key: {"fuzzforge": server_config}} + full_config = {servers_key: {"secpipe": server_config}} config_path.write_text(json.dumps(full_config, indent=4)) - return f"Installed FuzzForge for {agent.value}" + return f"Installed SecPipe for {agent.value}" def uninstall_agent_config(agent: AIAgent) -> str: - """Remove FuzzForge MCP configuration from an AI agent. + """Remove SecPipe MCP configuration from an AI agent. :param agent: Target AI agent. :return: Result message string. @@ -251,12 +251,12 @@ def uninstall_agent_config(agent: AIAgent) -> str: return "Error: Invalid JSON in config file" servers = config.get(servers_key, {}) - if "fuzzforge" not in servers: - return "FuzzForge is not configured for this agent" + if "secpipe" not in servers: + return "SecPipe is not configured for this agent" - del servers["fuzzforge"] + del servers["secpipe"] config_path.write_text(json.dumps(config, indent=4)) - return f"Removed FuzzForge from {agent.value}" + return f"Removed SecPipe from {agent.value}" # --------------------------------------------------------------------------- @@ -265,7 +265,7 @@ def uninstall_agent_config(agent: AIAgent) -> str: def get_hubs_registry_path() -> Path: - """Return path to the hubs registry file (``~/.fuzzforge/hubs.json``). + """Return path to the hubs registry file (``~/.secpipe/hubs.json``). Stored in the user-global directory so the registry is shared across all workspaces. @@ -273,11 +273,11 @@ def get_hubs_registry_path() -> Path: :return: Path to the registry JSON file. """ - return get_fuzzforge_user_dir() / "hubs.json" + return get_secpipe_user_dir() / "hubs.json" def get_default_hubs_dir() -> Path: - """Return default directory for cloned hubs (``~/.fuzzforge/hubs/``). + """Return default directory for cloned hubs (``~/.secpipe/hubs/``). Stored in the user-global directory so hubs are cloned once and reused in every workspace. @@ -285,14 +285,14 @@ def get_default_hubs_dir() -> Path: :return: Path to the default hubs directory. """ - return get_fuzzforge_user_dir() / "hubs" + return get_secpipe_user_dir() / "hubs" def _discover_hub_dirs() -> list[Path]: """Scan known hub directories for cloned repos. - Checks both the current global location (``~/.fuzzforge/hubs/``) and the - legacy workspace-local location (``/.fuzzforge/hubs/``) so that hubs + Checks both the current global location (``~/.secpipe/hubs/``) and the + legacy workspace-local location (``/.secpipe/hubs/``) so that hubs cloned before the global-dir migration are still found. :return: List of hub directory paths (each is a direct child with a ``.git`` @@ -300,7 +300,7 @@ def _discover_hub_dirs() -> list[Path]: """ candidates: list[Path] = [] - for base in (get_fuzzforge_user_dir() / "hubs", get_fuzzforge_dir() / "hubs"): + for base in (get_secpipe_user_dir() / "hubs", get_secpipe_dir() / "hubs"): if base.is_dir(): candidates.extend( entry for entry in base.iterdir() @@ -314,8 +314,8 @@ def load_hubs_registry() -> dict[str, Any]: If the registry file does not exist, auto-recovers it by scanning known hub directories and rebuilding entries for any discovered hubs. This handles - the migration from the old workspace-local ``/.fuzzforge/hubs.json`` - path to the global ``~/.fuzzforge/hubs.json`` path, as well as any case + the migration from the old workspace-local ``/.secpipe/hubs.json`` + path to the global ``~/.secpipe/hubs.json`` path, as well as any case where the registry was lost. :return: Registry dict with ``hubs`` key containing a list of hub entries. @@ -353,7 +353,7 @@ def load_hubs_registry() -> dict[str, Any]: "name": name, "path": str(hub_dir), "git_url": git_url, - "is_default": name == FUZZFORGE_DEFAULT_HUB_NAME, + "is_default": name == SECPIPE_DEFAULT_HUB_NAME, }) registry: dict[str, Any] = {"hubs": hubs} @@ -414,7 +414,7 @@ def scan_hub_for_servers(hub_path: Path) -> list[dict[str, Any]]: "image": f"{tool_name}:latest", "category": category, "capabilities": capabilities, - "volumes": [f"{get_fuzzforge_user_dir()}/hub/workspace:/data"], + "volumes": [f"{get_secpipe_user_dir()}/hub/workspace:/data"], "enabled": True, } ) @@ -571,8 +571,8 @@ def _merge_servers_into_hub_config( :return: Number of newly added servers. """ - fuzzforge_root = find_fuzzforge_root() - config_path = fuzzforge_root / "hub-config.json" + secpipe_root = find_secpipe_root() + config_path = secpipe_root / "hub-config.json" if config_path.exists(): try: @@ -608,8 +608,8 @@ def _remove_hub_servers_from_config(hub_name: str) -> int: :return: Number of servers removed. """ - fuzzforge_root = find_fuzzforge_root() - config_path = fuzzforge_root / "hub-config.json" + secpipe_root = find_secpipe_root() + config_path = secpipe_root / "hub-config.json" if not config_path.exists(): return 0 @@ -675,7 +675,7 @@ def build_image( """ if engine is None: - engine = os.environ.get("FUZZFORGE_ENGINE__TYPE", "docker").lower() + engine = os.environ.get("SECPIPE_ENGINE__TYPE", "docker").lower() engine = "podman" if engine == "podman" else "docker" context_dir = str(dockerfile.parent) diff --git a/secpipe-cli/src/secpipe_cli/tui/screens/__init__.py b/secpipe-cli/src/secpipe_cli/tui/screens/__init__.py new file mode 100644 index 0000000..0eca1c8 --- /dev/null +++ b/secpipe-cli/src/secpipe_cli/tui/screens/__init__.py @@ -0,0 +1 @@ +"""TUI screens for SecPipe.""" diff --git a/fuzzforge-cli/src/fuzzforge_cli/tui/screens/agent_setup.py b/secpipe-cli/src/secpipe_cli/tui/screens/agent_setup.py similarity index 91% rename from fuzzforge-cli/src/fuzzforge_cli/tui/screens/agent_setup.py rename to secpipe-cli/src/secpipe_cli/tui/screens/agent_setup.py index fee79e8..4ae8be1 100644 --- a/fuzzforge-cli/src/fuzzforge_cli/tui/screens/agent_setup.py +++ b/secpipe-cli/src/secpipe_cli/tui/screens/agent_setup.py @@ -1,4 +1,4 @@ -"""Agent setup and unlink modal screens for FuzzForge TUI. +"""Agent setup and unlink modal screens for SecPipe TUI. Provides context-aware modals that receive the target agent directly from the dashboard row selection — no redundant agent picker needed. @@ -12,8 +12,8 @@ from textual.containers import Horizontal, Vertical from textual.screen import ModalScreen from textual.widgets import Button, Label, RadioButton, RadioSet -from fuzzforge_cli.commands.mcp import AIAgent -from fuzzforge_cli.tui.helpers import install_agent_config, uninstall_agent_config +from secpipe_cli.commands.mcp import AIAgent +from secpipe_cli.tui.helpers import install_agent_config, uninstall_agent_config class AgentSetupScreen(ModalScreen[str | None]): @@ -76,7 +76,7 @@ class AgentUnlinkScreen(ModalScreen[str | None]): with Vertical(id="unlink-dialog"): yield Label(f"Unlink {self._display_name}?", classes="dialog-title") yield Label( - f"This will remove the FuzzForge MCP configuration from {self._display_name}.", + f"This will remove the SecPipe MCP configuration from {self._display_name}.", ) with Horizontal(classes="dialog-buttons"): diff --git a/fuzzforge-cli/src/fuzzforge_cli/tui/screens/build_image.py b/secpipe-cli/src/secpipe_cli/tui/screens/build_image.py similarity index 97% rename from fuzzforge-cli/src/fuzzforge_cli/tui/screens/build_image.py rename to secpipe-cli/src/secpipe_cli/tui/screens/build_image.py index f556f67..2758421 100644 --- a/fuzzforge-cli/src/fuzzforge_cli/tui/screens/build_image.py +++ b/secpipe-cli/src/secpipe_cli/tui/screens/build_image.py @@ -1,4 +1,4 @@ -"""Build-image confirm dialog for FuzzForge TUI. +"""Build-image confirm dialog for SecPipe TUI. Simple modal that asks the user to confirm before starting a background build. The actual build is managed by the app so the user is never diff --git a/fuzzforge-cli/src/fuzzforge_cli/tui/screens/build_log.py b/secpipe-cli/src/secpipe_cli/tui/screens/build_log.py similarity index 98% rename from fuzzforge-cli/src/fuzzforge_cli/tui/screens/build_log.py rename to secpipe-cli/src/secpipe_cli/tui/screens/build_log.py index e260af8..322e946 100644 --- a/fuzzforge-cli/src/fuzzforge_cli/tui/screens/build_log.py +++ b/secpipe-cli/src/secpipe_cli/tui/screens/build_log.py @@ -1,4 +1,4 @@ -"""Build-log viewer screen for FuzzForge TUI. +"""Build-log viewer screen for SecPipe TUI. Shows live output of a background build started by the app. Polls the app's ``_build_logs`` buffer every 500 ms so the user can pop this screen diff --git a/fuzzforge-cli/src/fuzzforge_cli/tui/screens/hub_manager.py b/secpipe-cli/src/secpipe_cli/tui/screens/hub_manager.py similarity index 97% rename from fuzzforge-cli/src/fuzzforge_cli/tui/screens/hub_manager.py rename to secpipe-cli/src/secpipe_cli/tui/screens/hub_manager.py index 975caf9..cf0bff8 100644 --- a/fuzzforge-cli/src/fuzzforge_cli/tui/screens/hub_manager.py +++ b/secpipe-cli/src/secpipe_cli/tui/screens/hub_manager.py @@ -1,4 +1,4 @@ -"""Hub management screens for FuzzForge TUI. +"""Hub management screens for SecPipe TUI. Provides modal dialogs for managing linked MCP hub repositories: - HubManagerScreen: list, add, remove linked hubs @@ -18,9 +18,9 @@ from textual.containers import Horizontal, Vertical from textual.screen import ModalScreen from textual.widgets import Button, DataTable, Input, Label, Static -from fuzzforge_cli.tui.helpers import ( - FUZZFORGE_DEFAULT_HUB_NAME, - FUZZFORGE_DEFAULT_HUB_URL, +from secpipe_cli.tui.helpers import ( + SECPIPE_DEFAULT_HUB_NAME, + SECPIPE_DEFAULT_HUB_URL, clone_hub, link_hub, load_hubs_registry, @@ -104,8 +104,8 @@ class HubManagerScreen(ModalScreen[str | None]): elif event.button.id == "btn-clone-default": self.app.push_screen( CloneHubScreen( - FUZZFORGE_DEFAULT_HUB_URL, - FUZZFORGE_DEFAULT_HUB_NAME, + SECPIPE_DEFAULT_HUB_URL, + SECPIPE_DEFAULT_HUB_NAME, is_default=True, ), callback=self._on_hub_action, diff --git a/fuzzforge-cli/src/fuzzforge_cli/utilities.py b/secpipe-cli/src/secpipe_cli/utilities.py similarity index 100% rename from fuzzforge-cli/src/fuzzforge_cli/utilities.py rename to secpipe-cli/src/secpipe_cli/utilities.py diff --git a/fuzzforge-cli/tests/__init__.py b/secpipe-cli/tests/__init__.py similarity index 100% rename from fuzzforge-cli/tests/__init__.py rename to secpipe-cli/tests/__init__.py diff --git a/fuzzforge-cli/tests/conftest.py b/secpipe-cli/tests/conftest.py similarity index 100% rename from fuzzforge-cli/tests/conftest.py rename to secpipe-cli/tests/conftest.py diff --git a/fuzzforge-common/Makefile b/secpipe-common/Makefile similarity index 100% rename from fuzzforge-common/Makefile rename to secpipe-common/Makefile diff --git a/fuzzforge-common/README.md b/secpipe-common/README.md similarity index 100% rename from fuzzforge-common/README.md rename to secpipe-common/README.md diff --git a/fuzzforge-common/mypy.ini b/secpipe-common/mypy.ini similarity index 100% rename from fuzzforge-common/mypy.ini rename to secpipe-common/mypy.ini diff --git a/fuzzforge-common/pyproject.toml b/secpipe-common/pyproject.toml similarity index 79% rename from fuzzforge-common/pyproject.toml rename to secpipe-common/pyproject.toml index 1a662ce..30ce084 100644 --- a/fuzzforge-common/pyproject.toml +++ b/secpipe-common/pyproject.toml @@ -1,7 +1,7 @@ [project] -name = "fuzzforge-common" +name = "secpipe-common" version = "0.0.1" -description = "FuzzForge's common types and utilities." +description = "SecPipe's common types and utilities." authors = [] readme = "README.md" requires-python = ">=3.14" diff --git a/fuzzforge-common/pytest.ini b/secpipe-common/pytest.ini similarity index 100% rename from fuzzforge-common/pytest.ini rename to secpipe-common/pytest.ini diff --git a/fuzzforge-common/ruff.toml b/secpipe-common/ruff.toml similarity index 100% rename from fuzzforge-common/ruff.toml rename to secpipe-common/ruff.toml diff --git a/secpipe-common/src/secpipe_common/__init__.py b/secpipe-common/src/secpipe_common/__init__.py new file mode 100644 index 0000000..4c02f07 --- /dev/null +++ b/secpipe-common/src/secpipe_common/__init__.py @@ -0,0 +1,38 @@ +"""SecPipe Common - Shared abstractions and implementations for SecPipe. + +This package provides: +- Sandbox engine abstractions (Podman, Docker) +- Common exceptions + +Example usage: + from secpipe_common import ( + AbstractSecPipeSandboxEngine, + ImageInfo, + Podman, + PodmanConfiguration, + ) +""" + +from secpipe_common.exceptions import SecPipeError +from secpipe_common.sandboxes import ( + AbstractSecPipeEngineConfiguration, + AbstractSecPipeSandboxEngine, + Docker, + DockerConfiguration, + SecPipeSandboxEngines, + ImageInfo, + Podman, + PodmanConfiguration, +) + +__all__ = [ + "AbstractSecPipeEngineConfiguration", + "AbstractSecPipeSandboxEngine", + "Docker", + "DockerConfiguration", + "SecPipeError", + "SecPipeSandboxEngines", + "ImageInfo", + "Podman", + "PodmanConfiguration", +] diff --git a/fuzzforge-common/src/fuzzforge_common/exceptions.py b/secpipe-common/src/secpipe_common/exceptions.py similarity index 80% rename from fuzzforge-common/src/fuzzforge_common/exceptions.py rename to secpipe-common/src/secpipe_common/exceptions.py index c3fa4ae..5853717 100644 --- a/fuzzforge-common/src/fuzzforge_common/exceptions.py +++ b/secpipe-common/src/secpipe_common/exceptions.py @@ -4,8 +4,8 @@ if TYPE_CHECKING: from typing import Any -class FuzzForgeError(Exception): - """Base exception for all FuzzForge custom exceptions. +class SecPipeError(Exception): + """Base exception for all SecPipe custom exceptions. All domain exceptions should inherit from this base to enable consistent exception handling and hierarchy navigation. @@ -13,7 +13,7 @@ class FuzzForgeError(Exception): """ def __init__(self, message: str, details: dict[str, Any] | None = None) -> None: - """Initialize FuzzForge error. + """Initialize SecPipe error. :param message: Error message. :param details: Optional error details dictionary. diff --git a/fuzzforge-common/src/fuzzforge_common/hub/__init__.py b/secpipe-common/src/secpipe_common/hub/__init__.py similarity index 65% rename from fuzzforge-common/src/fuzzforge_common/hub/__init__.py rename to secpipe-common/src/secpipe_common/hub/__init__.py index d719f3f..435d04f 100644 --- a/fuzzforge-common/src/fuzzforge_common/hub/__init__.py +++ b/secpipe-common/src/secpipe_common/hub/__init__.py @@ -1,8 +1,8 @@ -"""FuzzForge Hub - Generic MCP server bridge. +"""SecPipe Hub - Generic MCP server bridge. -This module provides a generic bridge to connect FuzzForge with any MCP server. +This module provides a generic bridge to connect SecPipe with any MCP server. It allows AI agents to discover and execute tools from external MCP servers -(like mcp-security-hub) through the same interface as native FuzzForge modules. +(like mcp-security-hub) through the same interface as native SecPipe modules. The hub is server-agnostic: it doesn't hardcode any specific tools or servers. Instead, it dynamically discovers tools by connecting to configured MCP servers @@ -15,9 +15,9 @@ Supported transport types: """ -from fuzzforge_common.hub.client import HubClient, HubClientError, PersistentSession -from fuzzforge_common.hub.executor import HubExecutionResult, HubExecutor -from fuzzforge_common.hub.models import ( +from secpipe_common.hub.client import HubClient, HubClientError, PersistentSession +from secpipe_common.hub.executor import HubExecutionResult, HubExecutor +from secpipe_common.hub.models import ( HubConfig, HubServer, HubServerConfig, @@ -25,7 +25,7 @@ from fuzzforge_common.hub.models import ( HubTool, HubToolParameter, ) -from fuzzforge_common.hub.registry import HubRegistry +from secpipe_common.hub.registry import HubRegistry __all__ = [ "HubClient", diff --git a/fuzzforge-common/src/fuzzforge_common/hub/client.py b/secpipe-common/src/secpipe_common/hub/client.py similarity index 99% rename from fuzzforge-common/src/fuzzforge_common/hub/client.py rename to secpipe-common/src/secpipe_common/hub/client.py index 5ffb43b..3e558f6 100644 --- a/fuzzforge-common/src/fuzzforge_common/hub/client.py +++ b/secpipe-common/src/secpipe_common/hub/client.py @@ -21,7 +21,7 @@ from dataclasses import dataclass, field from datetime import datetime, timezone from typing import TYPE_CHECKING, Any, cast -from fuzzforge_common.hub.models import ( +from secpipe_common.hub.models import ( HubServer, HubServerConfig, HubServerType, @@ -437,7 +437,7 @@ class HubClient: "protocolVersion": "2024-11-05", "capabilities": {}, "clientInfo": { - "name": "fuzzforge-hub", + "name": "secpipe-hub", "version": "0.1.0", }, }, @@ -570,7 +570,7 @@ class HubClient: msg = f"Docker image not specified for server '{config.name}'" raise HubClientError(msg) - container_name = f"fuzzforge-{config.name}" + container_name = f"secpipe-{config.name}" # Remove stale container with same name if it exists try: diff --git a/fuzzforge-common/src/fuzzforge_common/hub/executor.py b/secpipe-common/src/secpipe_common/hub/executor.py similarity index 98% rename from fuzzforge-common/src/fuzzforge_common/hub/executor.py rename to secpipe-common/src/secpipe_common/hub/executor.py index 37205e1..2a0b1e8 100644 --- a/fuzzforge-common/src/fuzzforge_common/hub/executor.py +++ b/secpipe-common/src/secpipe_common/hub/executor.py @@ -12,9 +12,9 @@ from __future__ import annotations from pathlib import Path from typing import TYPE_CHECKING, Any, cast -from fuzzforge_common.hub.client import HubClient, HubClientError, PersistentSession -from fuzzforge_common.hub.models import HubServer, HubServerConfig, HubTool -from fuzzforge_common.hub.registry import HubRegistry +from secpipe_common.hub.client import HubClient, HubClientError, PersistentSession +from secpipe_common.hub.models import HubServer, HubServerConfig, HubTool +from secpipe_common.hub.registry import HubRegistry if TYPE_CHECKING: from structlog.stdlib import BoundLogger diff --git a/fuzzforge-common/src/fuzzforge_common/hub/models.py b/secpipe-common/src/secpipe_common/hub/models.py similarity index 99% rename from fuzzforge-common/src/fuzzforge_common/hub/models.py rename to secpipe-common/src/secpipe_common/hub/models.py index e583e83..b6b0341 100644 --- a/fuzzforge-common/src/fuzzforge_common/hub/models.py +++ b/secpipe-common/src/secpipe_common/hub/models.py @@ -1,4 +1,4 @@ -"""Data models for FuzzForge Hub. +"""Data models for SecPipe Hub. This module defines the Pydantic models used to represent MCP servers and their tools in the hub registry. diff --git a/fuzzforge-common/src/fuzzforge_common/hub/registry.py b/secpipe-common/src/secpipe_common/hub/registry.py similarity index 99% rename from fuzzforge-common/src/fuzzforge_common/hub/registry.py rename to secpipe-common/src/secpipe_common/hub/registry.py index d93e6c6..b953a08 100644 --- a/fuzzforge-common/src/fuzzforge_common/hub/registry.py +++ b/secpipe-common/src/secpipe_common/hub/registry.py @@ -12,7 +12,7 @@ import json from pathlib import Path from typing import TYPE_CHECKING, cast -from fuzzforge_common.hub.models import ( +from secpipe_common.hub.models import ( HubConfig, HubServer, HubServerConfig, diff --git a/fuzzforge-common/src/fuzzforge_common/py.typed b/secpipe-common/src/secpipe_common/py.typed similarity index 100% rename from fuzzforge-common/src/fuzzforge_common/py.typed rename to secpipe-common/src/secpipe_common/py.typed diff --git a/secpipe-common/src/secpipe_common/sandboxes/__init__.py b/secpipe-common/src/secpipe_common/sandboxes/__init__.py new file mode 100644 index 0000000..84425c2 --- /dev/null +++ b/secpipe-common/src/secpipe_common/sandboxes/__init__.py @@ -0,0 +1,23 @@ +"""SecPipe sandbox abstractions and implementations.""" + +from secpipe_common.sandboxes.engines import ( + AbstractSecPipeEngineConfiguration, + AbstractSecPipeSandboxEngine, + Docker, + DockerConfiguration, + SecPipeSandboxEngines, + ImageInfo, + Podman, + PodmanConfiguration, +) + +__all__ = [ + "AbstractSecPipeEngineConfiguration", + "AbstractSecPipeSandboxEngine", + "Docker", + "DockerConfiguration", + "SecPipeSandboxEngines", + "ImageInfo", + "Podman", + "PodmanConfiguration", +] diff --git a/secpipe-common/src/secpipe_common/sandboxes/engines/__init__.py b/secpipe-common/src/secpipe_common/sandboxes/engines/__init__.py new file mode 100644 index 0000000..e7146ba --- /dev/null +++ b/secpipe-common/src/secpipe_common/sandboxes/engines/__init__.py @@ -0,0 +1,21 @@ +"""Container engine implementations for SecPipe sandboxes.""" + +from secpipe_common.sandboxes.engines.base import ( + AbstractSecPipeEngineConfiguration, + AbstractSecPipeSandboxEngine, + ImageInfo, +) +from secpipe_common.sandboxes.engines.docker import Docker, DockerConfiguration +from secpipe_common.sandboxes.engines.enumeration import SecPipeSandboxEngines +from secpipe_common.sandboxes.engines.podman import Podman, PodmanConfiguration + +__all__ = [ + "AbstractSecPipeEngineConfiguration", + "AbstractSecPipeSandboxEngine", + "Docker", + "DockerConfiguration", + "SecPipeSandboxEngines", + "ImageInfo", + "Podman", + "PodmanConfiguration", +] diff --git a/secpipe-common/src/secpipe_common/sandboxes/engines/base/__init__.py b/secpipe-common/src/secpipe_common/sandboxes/engines/base/__init__.py new file mode 100644 index 0000000..2c104b3 --- /dev/null +++ b/secpipe-common/src/secpipe_common/sandboxes/engines/base/__init__.py @@ -0,0 +1,15 @@ +"""Base engine abstractions.""" + +from secpipe_common.sandboxes.engines.base.configuration import ( + AbstractSecPipeEngineConfiguration, +) +from secpipe_common.sandboxes.engines.base.engine import ( + AbstractSecPipeSandboxEngine, + ImageInfo, +) + +__all__ = [ + "AbstractSecPipeEngineConfiguration", + "AbstractSecPipeSandboxEngine", + "ImageInfo", +] diff --git a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/base/configuration.py b/secpipe-common/src/secpipe_common/sandboxes/engines/base/configuration.py similarity index 50% rename from fuzzforge-common/src/fuzzforge_common/sandboxes/engines/base/configuration.py rename to secpipe-common/src/secpipe_common/sandboxes/engines/base/configuration.py index c255c72..35adf3a 100644 --- a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/base/configuration.py +++ b/secpipe-common/src/secpipe_common/sandboxes/engines/base/configuration.py @@ -3,22 +3,22 @@ from typing import TYPE_CHECKING from pydantic import BaseModel -from fuzzforge_common.sandboxes.engines.enumeration import ( - FuzzForgeSandboxEngines, +from secpipe_common.sandboxes.engines.enumeration import ( + SecPipeSandboxEngines, ) if TYPE_CHECKING: - from fuzzforge_common.sandboxes.engines.base.engine import AbstractFuzzForgeSandboxEngine + from secpipe_common.sandboxes.engines.base.engine import AbstractSecPipeSandboxEngine -class AbstractFuzzForgeEngineConfiguration(ABC, BaseModel): +class AbstractSecPipeEngineConfiguration(ABC, BaseModel): """TODO.""" #: TODO. - kind: FuzzForgeSandboxEngines + kind: SecPipeSandboxEngines @abstractmethod - def into_engine(self) -> AbstractFuzzForgeSandboxEngine: + def into_engine(self) -> AbstractSecPipeSandboxEngine: """TODO.""" message: str = f"method 'into_engine' is not implemented for class '{self.__class__.__name__}'" raise NotImplementedError(message) diff --git a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/base/engine.py b/secpipe-common/src/secpipe_common/sandboxes/engines/base/engine.py similarity index 96% rename from fuzzforge-common/src/fuzzforge_common/sandboxes/engines/base/engine.py rename to secpipe-common/src/secpipe_common/sandboxes/engines/base/engine.py index 3bd034b..45cf5c0 100644 --- a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/base/engine.py +++ b/secpipe-common/src/secpipe_common/sandboxes/engines/base/engine.py @@ -10,10 +10,10 @@ if TYPE_CHECKING: class ImageInfo: """Information about a container image.""" - #: Full image reference (e.g., "localhost/fuzzforge-module-echidna:latest"). + #: Full image reference (e.g., "localhost/secpipe-module-echidna:latest"). reference: str - #: Repository name (e.g., "localhost/fuzzforge-module-echidna"). + #: Repository name (e.g., "localhost/secpipe-module-echidna"). repository: str #: Image tag (e.g., "latest"). @@ -29,8 +29,8 @@ class ImageInfo: labels: dict[str, str] | None = None -class AbstractFuzzForgeSandboxEngine(ABC): - """Abstract class used as a base for all FuzzForge sandbox engine classes.""" +class AbstractSecPipeSandboxEngine(ABC): + """Abstract class used as a base for all SecPipe sandbox engine classes.""" @abstractmethod def list_images(self, filter_prefix: str | None = None) -> list[ImageInfo]: @@ -140,7 +140,7 @@ class AbstractFuzzForgeSandboxEngine(ABC): :param image: Full image reference to pull. :param timeout: Timeout in seconds for the pull operation. - :raises FuzzForgeError: If pull fails. + :raises SecPipeError: If pull fails. """ message: str = f"method 'pull_image' is not implemented for class '{self.__class__.__name__}'" @@ -306,7 +306,7 @@ class AbstractFuzzForgeSandboxEngine(ABC): Creates a temporary container, copies the file, and removes the container. - :param image: Image reference (e.g., "fuzzforge-rust-analyzer:latest"). + :param image: Image reference (e.g., "secpipe-rust-analyzer:latest"). :param path: Path to file inside image. :returns: File contents as string. diff --git a/secpipe-common/src/secpipe_common/sandboxes/engines/docker/__init__.py b/secpipe-common/src/secpipe_common/sandboxes/engines/docker/__init__.py new file mode 100644 index 0000000..41ae617 --- /dev/null +++ b/secpipe-common/src/secpipe_common/sandboxes/engines/docker/__init__.py @@ -0,0 +1,13 @@ +"""Docker container engine implementation.""" + +from secpipe_common.sandboxes.engines.docker.cli import DockerCLI +from secpipe_common.sandboxes.engines.docker.configuration import ( + DockerConfiguration, +) +from secpipe_common.sandboxes.engines.docker.engine import Docker + +__all__ = [ + "Docker", + "DockerCLI", + "DockerConfiguration", +] diff --git a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/docker/cli.py b/secpipe-common/src/secpipe_common/sandboxes/engines/docker/cli.py similarity index 97% rename from fuzzforge-common/src/fuzzforge_common/sandboxes/engines/docker/cli.py rename to secpipe-common/src/secpipe_common/sandboxes/engines/docker/cli.py index e80d984..2345242 100644 --- a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/docker/cli.py +++ b/secpipe-common/src/secpipe_common/sandboxes/engines/docker/cli.py @@ -13,8 +13,8 @@ from pathlib import Path, PurePath from tempfile import NamedTemporaryFile from typing import TYPE_CHECKING, cast -from fuzzforge_common.exceptions import FuzzForgeError -from fuzzforge_common.sandboxes.engines.base.engine import AbstractFuzzForgeSandboxEngine, ImageInfo +from secpipe_common.exceptions import SecPipeError +from secpipe_common.sandboxes.engines.base.engine import AbstractSecPipeSandboxEngine, ImageInfo if TYPE_CHECKING: from structlog.stdlib import BoundLogger @@ -27,7 +27,7 @@ def get_logger() -> BoundLogger: return cast("BoundLogger", get_logger()) -class DockerCLI(AbstractFuzzForgeSandboxEngine): +class DockerCLI(AbstractSecPipeSandboxEngine): """Docker engine using CLI commands. This implementation uses subprocess calls to the Docker CLI, @@ -37,7 +37,7 @@ class DockerCLI(AbstractFuzzForgeSandboxEngine): def __init__(self) -> None: """Initialize the DockerCLI engine.""" - AbstractFuzzForgeSandboxEngine.__init__(self) + AbstractSecPipeSandboxEngine.__init__(self) def _base_cmd(self) -> list[str]: """Get base Docker command. @@ -147,7 +147,7 @@ class DockerCLI(AbstractFuzzForgeSandboxEngine): get_logger().info("image pulled successfully", image=image) except subprocess.CalledProcessError as exc: message = f"Failed to pull image '{image}': {exc.stderr}" - raise FuzzForgeError(message) from exc + raise SecPipeError(message) from exc def tag_image(self, source: str, target: str) -> None: """Tag an image with a new name. @@ -440,7 +440,7 @@ class DockerCLI(AbstractFuzzForgeSandboxEngine): Uses docker run with --entrypoint override to read the file via cat. - :param image: Image reference (e.g., "fuzzforge-rust-analyzer:latest"). + :param image: Image reference (e.g., "secpipe-rust-analyzer:latest"). :param path: Path to file inside image. :returns: File contents as string. diff --git a/secpipe-common/src/secpipe_common/sandboxes/engines/docker/configuration.py b/secpipe-common/src/secpipe_common/sandboxes/engines/docker/configuration.py new file mode 100644 index 0000000..6e895ab --- /dev/null +++ b/secpipe-common/src/secpipe_common/sandboxes/engines/docker/configuration.py @@ -0,0 +1,22 @@ +from typing import TYPE_CHECKING, Literal + +from secpipe_common.sandboxes.engines.base.configuration import AbstractSecPipeEngineConfiguration +from secpipe_common.sandboxes.engines.docker.engine import Docker +from secpipe_common.sandboxes.engines.enumeration import SecPipeSandboxEngines + +if TYPE_CHECKING: + from secpipe_common.sandboxes.engines.base.engine import AbstractSecPipeSandboxEngine + + +class DockerConfiguration(AbstractSecPipeEngineConfiguration): + """TODO.""" + + #: TODO. + kind: Literal[SecPipeSandboxEngines.DOCKER] = SecPipeSandboxEngines.DOCKER + + #: TODO. + socket: str + + def into_engine(self) -> AbstractSecPipeSandboxEngine: + """TODO.""" + return Docker(socket=self.socket) diff --git a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/docker/engine.py b/secpipe-common/src/secpipe_common/sandboxes/engines/docker/engine.py similarity index 97% rename from fuzzforge-common/src/fuzzforge_common/sandboxes/engines/docker/engine.py rename to secpipe-common/src/secpipe_common/sandboxes/engines/docker/engine.py index 31ac9d8..c86c3c0 100644 --- a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/docker/engine.py +++ b/secpipe-common/src/secpipe_common/sandboxes/engines/docker/engine.py @@ -2,13 +2,13 @@ from __future__ import annotations from typing import TYPE_CHECKING -from fuzzforge_common.sandboxes.engines.base.engine import AbstractFuzzForgeSandboxEngine, ImageInfo +from secpipe_common.sandboxes.engines.base.engine import AbstractSecPipeSandboxEngine, ImageInfo if TYPE_CHECKING: from pathlib import Path, PurePath -class Docker(AbstractFuzzForgeSandboxEngine): +class Docker(AbstractSecPipeSandboxEngine): """TODO.""" #: TODO. diff --git a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/enumeration.py b/secpipe-common/src/secpipe_common/sandboxes/engines/enumeration.py similarity index 74% rename from fuzzforge-common/src/fuzzforge_common/sandboxes/engines/enumeration.py rename to secpipe-common/src/secpipe_common/sandboxes/engines/enumeration.py index 8de5650..8fb218a 100644 --- a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/enumeration.py +++ b/secpipe-common/src/secpipe_common/sandboxes/engines/enumeration.py @@ -1,7 +1,7 @@ from enum import StrEnum -class FuzzForgeSandboxEngines(StrEnum): +class SecPipeSandboxEngines(StrEnum): """TODO.""" #: TODO. diff --git a/secpipe-common/src/secpipe_common/sandboxes/engines/podman/__init__.py b/secpipe-common/src/secpipe_common/sandboxes/engines/podman/__init__.py new file mode 100644 index 0000000..354f9f4 --- /dev/null +++ b/secpipe-common/src/secpipe_common/sandboxes/engines/podman/__init__.py @@ -0,0 +1,13 @@ +"""Podman container engine implementation.""" + +from secpipe_common.sandboxes.engines.podman.cli import PodmanCLI +from secpipe_common.sandboxes.engines.podman.configuration import ( + PodmanConfiguration, +) +from secpipe_common.sandboxes.engines.podman.engine import Podman + +__all__ = [ + "Podman", + "PodmanCLI", + "PodmanConfiguration", +] diff --git a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/podman/cli.py b/secpipe-common/src/secpipe_common/sandboxes/engines/podman/cli.py similarity index 97% rename from fuzzforge-common/src/fuzzforge_common/sandboxes/engines/podman/cli.py rename to secpipe-common/src/secpipe_common/sandboxes/engines/podman/cli.py index 95aae1b..963cf86 100644 --- a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/podman/cli.py +++ b/secpipe-common/src/secpipe_common/sandboxes/engines/podman/cli.py @@ -15,8 +15,8 @@ from pathlib import Path, PurePath from tempfile import NamedTemporaryFile from typing import TYPE_CHECKING, cast -from fuzzforge_common.exceptions import FuzzForgeError -from fuzzforge_common.sandboxes.engines.base.engine import AbstractFuzzForgeSandboxEngine, ImageInfo +from secpipe_common.exceptions import SecPipeError +from secpipe_common.sandboxes.engines.base.engine import AbstractSecPipeSandboxEngine, ImageInfo if TYPE_CHECKING: from structlog.stdlib import BoundLogger @@ -43,7 +43,7 @@ def _is_running_under_snap() -> bool: return os.getenv("SNAP") is not None -class PodmanCLI(AbstractFuzzForgeSandboxEngine): +class PodmanCLI(AbstractSecPipeSandboxEngine): """Podman engine using CLI with custom storage paths. This implementation uses subprocess calls to the Podman CLI with --root @@ -71,7 +71,7 @@ class PodmanCLI(AbstractFuzzForgeSandboxEngine): Custom storage is used when running under Snap AND paths are provided. - :raises FuzzForgeError: If running on macOS (Podman not supported). + :raises SecPipeError: If running on macOS (Podman not supported). """ import sys # noqa: PLC0415 @@ -81,9 +81,9 @@ class PodmanCLI(AbstractFuzzForgeSandboxEngine): " brew install --cask docker\n" " # Or download from https://docker.com/products/docker-desktop" ) - raise FuzzForgeError(msg) + raise SecPipeError(msg) - AbstractFuzzForgeSandboxEngine.__init__(self) + AbstractSecPipeSandboxEngine.__init__(self) # Use custom storage only under Snap (to fix XDG_DATA_HOME issues) self.__use_custom_storage = _is_running_under_snap() and graphroot is not None and runroot is not None @@ -206,7 +206,7 @@ class PodmanCLI(AbstractFuzzForgeSandboxEngine): get_logger().info("image pulled successfully", image=image) except subprocess.CalledProcessError as exc: message = f"Failed to pull image '{image}': {exc.stderr}" - raise FuzzForgeError(message) from exc + raise SecPipeError(message) from exc def tag_image(self, source: str, target: str) -> None: """Tag an image with a new name. @@ -501,7 +501,7 @@ class PodmanCLI(AbstractFuzzForgeSandboxEngine): Uses podman run with --entrypoint override to read the file via cat. - :param image: Image reference (e.g., "fuzzforge-rust-analyzer:latest"). + :param image: Image reference (e.g., "secpipe-rust-analyzer:latest"). :param path: Path to file inside image. :returns: File contents as string. diff --git a/secpipe-common/src/secpipe_common/sandboxes/engines/podman/configuration.py b/secpipe-common/src/secpipe_common/sandboxes/engines/podman/configuration.py new file mode 100644 index 0000000..0bf7073 --- /dev/null +++ b/secpipe-common/src/secpipe_common/sandboxes/engines/podman/configuration.py @@ -0,0 +1,22 @@ +from typing import TYPE_CHECKING, Literal + +from secpipe_common.sandboxes.engines.base.configuration import AbstractSecPipeEngineConfiguration +from secpipe_common.sandboxes.engines.enumeration import SecPipeSandboxEngines +from secpipe_common.sandboxes.engines.podman.engine import Podman + +if TYPE_CHECKING: + from secpipe_common.sandboxes.engines.base.engine import AbstractSecPipeSandboxEngine + + +class PodmanConfiguration(AbstractSecPipeEngineConfiguration): + """TODO.""" + + #: TODO. + kind: Literal[SecPipeSandboxEngines.PODMAN] = SecPipeSandboxEngines.PODMAN + + #: TODO. + socket: str + + def into_engine(self) -> AbstractSecPipeSandboxEngine: + """TODO.""" + return Podman(socket=self.socket) diff --git a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/podman/engine.py b/secpipe-common/src/secpipe_common/sandboxes/engines/podman/engine.py similarity index 97% rename from fuzzforge-common/src/fuzzforge_common/sandboxes/engines/podman/engine.py rename to secpipe-common/src/secpipe_common/sandboxes/engines/podman/engine.py index fcd7969..e1487ac 100644 --- a/fuzzforge-common/src/fuzzforge_common/sandboxes/engines/podman/engine.py +++ b/secpipe-common/src/secpipe_common/sandboxes/engines/podman/engine.py @@ -8,8 +8,8 @@ from typing import TYPE_CHECKING, cast from podman.errors import ImageNotFound -from fuzzforge_common.exceptions import FuzzForgeError -from fuzzforge_common.sandboxes.engines.base.engine import AbstractFuzzForgeSandboxEngine, ImageInfo +from secpipe_common.exceptions import SecPipeError +from secpipe_common.sandboxes.engines.base.engine import AbstractSecPipeSandboxEngine, ImageInfo if TYPE_CHECKING: from podman import PodmanClient @@ -24,7 +24,7 @@ def get_logger() -> BoundLogger: return cast("BoundLogger", get_logger()) -class Podman(AbstractFuzzForgeSandboxEngine): +class Podman(AbstractSecPipeSandboxEngine): """TODO.""" #: TODO. @@ -36,7 +36,7 @@ class Podman(AbstractFuzzForgeSandboxEngine): :param socket: TODO. """ - AbstractFuzzForgeSandboxEngine.__init__(self) + AbstractSecPipeSandboxEngine.__init__(self) self.__socket = socket def get_client(self) -> PodmanClient: @@ -99,7 +99,7 @@ class Podman(AbstractFuzzForgeSandboxEngine): images = list(client.images.load(file_path=archive)) if len(images) != 1: message: str = "expected only one image" - raise FuzzForgeError(message) + raise SecPipeError(message) image = images[0] image.tag(repository=repository, tag="latest") @@ -254,7 +254,7 @@ class Podman(AbstractFuzzForgeSandboxEngine): :param image: Full image reference to pull. :param timeout: Timeout in seconds for the pull operation. - :raises FuzzForgeError: If pull fails. + :raises SecPipeError: If pull fails. """ client: PodmanClient = self.get_client() @@ -265,7 +265,7 @@ class Podman(AbstractFuzzForgeSandboxEngine): get_logger().info("image pulled successfully", image=image) except Exception as exc: message = f"Failed to pull image '{image}': {exc}" - raise FuzzForgeError(message) from exc + raise SecPipeError(message) from exc def tag_image(self, source: str, target: str) -> None: """Tag an image with a new name. @@ -524,7 +524,7 @@ class Podman(AbstractFuzzForgeSandboxEngine): Creates a temporary container, reads the file, and removes the container. - :param image: Image reference (e.g., "fuzzforge-rust-analyzer:latest"). + :param image: Image reference (e.g., "secpipe-rust-analyzer:latest"). :param path: Path to file inside image. :returns: File contents as string. diff --git a/fuzzforge-common/tests/.gitkeep b/secpipe-common/tests/.gitkeep similarity index 100% rename from fuzzforge-common/tests/.gitkeep rename to secpipe-common/tests/.gitkeep diff --git a/fuzzforge-common/tests/__init__.py b/secpipe-common/tests/__init__.py similarity index 100% rename from fuzzforge-common/tests/__init__.py rename to secpipe-common/tests/__init__.py diff --git a/secpipe-common/tests/conftest.py b/secpipe-common/tests/conftest.py new file mode 100644 index 0000000..ccbba1e --- /dev/null +++ b/secpipe-common/tests/conftest.py @@ -0,0 +1 @@ +pytest_plugins = ["secpipe_tests.fixtures"] diff --git a/fuzzforge-common/tests/unit/__init__.py b/secpipe-common/tests/unit/__init__.py similarity index 100% rename from fuzzforge-common/tests/unit/__init__.py rename to secpipe-common/tests/unit/__init__.py diff --git a/fuzzforge-common/tests/unit/engines/__init__.py b/secpipe-common/tests/unit/engines/__init__.py similarity index 100% rename from fuzzforge-common/tests/unit/engines/__init__.py rename to secpipe-common/tests/unit/engines/__init__.py diff --git a/fuzzforge-common/tests/unit/engines/conftest.py b/secpipe-common/tests/unit/engines/conftest.py similarity index 100% rename from fuzzforge-common/tests/unit/engines/conftest.py rename to secpipe-common/tests/unit/engines/conftest.py diff --git a/fuzzforge-common/tests/unit/engines/test_docker.py b/secpipe-common/tests/unit/engines/test_docker.py similarity index 97% rename from fuzzforge-common/tests/unit/engines/test_docker.py rename to secpipe-common/tests/unit/engines/test_docker.py index 9d3dbb3..1158895 100644 --- a/fuzzforge-common/tests/unit/engines/test_docker.py +++ b/secpipe-common/tests/unit/engines/test_docker.py @@ -4,7 +4,7 @@ from unittest import mock import pytest -from fuzzforge_common.sandboxes.engines.docker.cli import DockerCLI +from secpipe_common.sandboxes.engines.docker.cli import DockerCLI def test_docker_cli_base_cmd() -> None: diff --git a/fuzzforge-common/tests/unit/engines/test_podman.py b/secpipe-common/tests/unit/engines/test_podman.py similarity index 95% rename from fuzzforge-common/tests/unit/engines/test_podman.py rename to secpipe-common/tests/unit/engines/test_podman.py index 4bfd88a..4bf01d6 100644 --- a/fuzzforge-common/tests/unit/engines/test_podman.py +++ b/secpipe-common/tests/unit/engines/test_podman.py @@ -9,8 +9,8 @@ from unittest import mock import pytest -from fuzzforge_common.exceptions import FuzzForgeError -from fuzzforge_common.sandboxes.engines.podman.cli import PodmanCLI, _is_running_under_snap +from secpipe_common.exceptions import SecPipeError +from secpipe_common.sandboxes.engines.podman.cli import PodmanCLI, _is_running_under_snap # Helper to mock Linux platform for testing (since Podman is Linux-only) @@ -60,7 +60,7 @@ def test_snap_detection_when_snap_not_set() -> None: def test_podman_cli_blocks_macos() -> None: """Test that PodmanCLI raises error on macOS.""" with mock.patch.object(sys, "platform", "darwin"): - with pytest.raises(FuzzForgeError) as exc_info: + with pytest.raises(SecPipeError) as exc_info: PodmanCLI() assert "Podman is not supported on macOS" in str(exc_info.value) assert "Docker" in str(exc_info.value) diff --git a/fuzzforge-mcp/Dockerfile b/secpipe-mcp/Dockerfile similarity index 72% rename from fuzzforge-mcp/Dockerfile rename to secpipe-mcp/Dockerfile index 8d25f90..7329968 100644 --- a/fuzzforge-mcp/Dockerfile +++ b/secpipe-mcp/Dockerfile @@ -8,4 +8,4 @@ WORKDIR /app RUN /bin/uv venv && /bin/uv pip install --find-links /wheels $PACKAGE -CMD [ "/bin/uv", "run", "uvicorn", "fuzzforge_mcp.application:app"] +CMD [ "/bin/uv", "run", "uvicorn", "secpipe_mcp.application:app"] diff --git a/fuzzforge-mcp/Makefile b/secpipe-mcp/Makefile similarity index 100% rename from fuzzforge-mcp/Makefile rename to secpipe-mcp/Makefile diff --git a/fuzzforge-mcp/README.md b/secpipe-mcp/README.md similarity index 75% rename from fuzzforge-mcp/README.md rename to secpipe-mcp/README.md index 97cf078..c80fe15 100644 --- a/fuzzforge-mcp/README.md +++ b/secpipe-mcp/README.md @@ -21,16 +21,16 @@ Use the SecPipe CLI to automatically configure MCP for your AI agent: ```bash # For GitHub Copilot -uv run fuzzforge mcp install copilot +uv run secpipe mcp install copilot # For Claude Code (VS Code extension) -uv run fuzzforge mcp install claude-code +uv run secpipe mcp install claude-code # For Claude Desktop (standalone app) -uv run fuzzforge mcp install claude-desktop +uv run secpipe mcp install claude-desktop # Verify installation -uv run fuzzforge mcp status +uv run secpipe mcp status ``` After installation, restart your AI agent to activate the connection. @@ -44,13 +44,13 @@ For custom setups, you can manually configure the MCP server. ```json { "mcpServers": { - "fuzzforge": { - "command": "/path/to/fuzzforge_ai/.venv/bin/python", - "args": ["-m", "fuzzforge_mcp"], - "cwd": "/path/to/fuzzforge_ai", + "secpipe": { + "command": "/path/to/secpipe_ai/.venv/bin/python", + "args": ["-m", "secpipe_mcp"], + "cwd": "/path/to/secpipe_ai", "env": { - "FUZZFORGE_MODULES_PATH": "/path/to/fuzzforge_ai/fuzzforge-modules", - "FUZZFORGE_ENGINE__TYPE": "docker" + "SECPIPE_MODULES_PATH": "/path/to/secpipe_ai/secpipe-modules", + "SECPIPE_ENGINE__TYPE": "docker" } } } @@ -62,14 +62,14 @@ For custom setups, you can manually configure the MCP server. ```json { "servers": { - "fuzzforge": { + "secpipe": { "type": "stdio", - "command": "/path/to/fuzzforge_ai/.venv/bin/python", - "args": ["-m", "fuzzforge_mcp"], - "cwd": "/path/to/fuzzforge_ai", + "command": "/path/to/secpipe_ai/.venv/bin/python", + "args": ["-m", "secpipe_mcp"], + "cwd": "/path/to/secpipe_ai", "env": { - "FUZZFORGE_MODULES_PATH": "/path/to/fuzzforge_ai/fuzzforge-modules", - "FUZZFORGE_ENGINE__TYPE": "docker" + "SECPIPE_MODULES_PATH": "/path/to/secpipe_ai/secpipe-modules", + "SECPIPE_ENGINE__TYPE": "docker" } } } @@ -81,14 +81,14 @@ For custom setups, you can manually configure the MCP server. ```json { "mcpServers": { - "fuzzforge": { + "secpipe": { "type": "stdio", - "command": "/path/to/fuzzforge_ai/.venv/bin/python", - "args": ["-m", "fuzzforge_mcp"], - "cwd": "/path/to/fuzzforge_ai", + "command": "/path/to/secpipe_ai/.venv/bin/python", + "args": ["-m", "secpipe_mcp"], + "cwd": "/path/to/secpipe_ai", "env": { - "FUZZFORGE_MODULES_PATH": "/path/to/fuzzforge_ai/fuzzforge-modules", - "FUZZFORGE_ENGINE__TYPE": "docker" + "SECPIPE_MODULES_PATH": "/path/to/secpipe_ai/secpipe-modules", + "SECPIPE_ENGINE__TYPE": "docker" } } } @@ -99,10 +99,10 @@ For custom setups, you can manually configure the MCP server. | Variable | Required | Default | Description | | -------- | -------- | ------- | ----------- | -| `FUZZFORGE_MODULES_PATH` | Yes | - | Path to the modules directory | -| `FUZZFORGE_ENGINE__TYPE` | No | `docker` | Container engine (`docker` or `podman`) | -| `FUZZFORGE_ENGINE__GRAPHROOT` | No | - | Container storage path (Podman under Snap only) | -| `FUZZFORGE_ENGINE__RUNROOT` | No | - | Container runtime state path (Podman under Snap only) | +| `SECPIPE_MODULES_PATH` | Yes | - | Path to the modules directory | +| `SECPIPE_ENGINE__TYPE` | No | `docker` | Container engine (`docker` or `podman`) | +| `SECPIPE_ENGINE__GRAPHROOT` | No | - | Container storage path (Podman under Snap only) | +| `SECPIPE_ENGINE__RUNROOT` | No | - | Container runtime state path (Podman under Snap only) | ## Available Tools @@ -161,10 +161,10 @@ For testing during development, you can run the MCP server directly: ```bash # Run MCP server in stdio mode (for AI agents) -uv run python -m fuzzforge_mcp +uv run python -m secpipe_mcp # Run HTTP server for testing (not for production) -uv run uvicorn fuzzforge_mcp.application:app --reload +uv run uvicorn secpipe_mcp.application:app --reload ``` ## Architecture @@ -213,5 +213,5 @@ uv run pytest ## See Also - [SecPipe Main README](../README.md) - Overall project documentation -- [Module SDK](../fuzzforge-modules/fuzzforge-modules-sdk/README.md) - Creating custom modules +- [Module SDK](../secpipe-modules/secpipe-modules-sdk/README.md) - Creating custom modules - [Model Context Protocol](https://modelcontextprotocol.io/) - MCP specification diff --git a/fuzzforge-mcp/mypy.ini b/secpipe-mcp/mypy.ini similarity index 100% rename from fuzzforge-mcp/mypy.ini rename to secpipe-mcp/mypy.ini diff --git a/fuzzforge-mcp/pyproject.toml b/secpipe-mcp/pyproject.toml similarity index 62% rename from fuzzforge-mcp/pyproject.toml rename to secpipe-mcp/pyproject.toml index 5a0996b..c0bf485 100644 --- a/fuzzforge-mcp/pyproject.toml +++ b/secpipe-mcp/pyproject.toml @@ -1,13 +1,13 @@ [project] -name = "fuzzforge-mcp" +name = "secpipe-mcp" version = "0.0.1" -description = "FuzzForge MCP Server - AI agent gateway for FuzzForge AI." +description = "SecPipe MCP Server - AI agent gateway for SecPipe AI." authors = [] readme = "README.md" requires-python = ">=3.14" dependencies = [ "fastmcp==2.14.1", - "fuzzforge-common==0.0.1", + "secpipe-common==0.0.1", "pydantic==2.12.4", "pydantic-settings==2.12.0", "pyyaml>=6.0", @@ -15,7 +15,7 @@ dependencies = [ ] [project.scripts] -fuzzforge-mcp = "fuzzforge_mcp.__main__:main" +secpipe-mcp = "secpipe_mcp.__main__:main" [project.optional-dependencies] lints = [ @@ -24,12 +24,12 @@ lints = [ "ruff==0.14.4", ] tests = [ - "fuzzforge-tests==0.0.1", + "secpipe-tests==0.0.1", "pytest==9.0.2", "pytest-asyncio==1.3.0", "pytest-httpx==0.36.0", ] [tool.uv.sources] -fuzzforge-common = { workspace = true } -fuzzforge-tests = { workspace = true } +secpipe-common = { workspace = true } +secpipe-tests = { workspace = true } diff --git a/fuzzforge-mcp/pytest.ini b/secpipe-mcp/pytest.ini similarity index 100% rename from fuzzforge-mcp/pytest.ini rename to secpipe-mcp/pytest.ini diff --git a/fuzzforge-mcp/ruff.toml b/secpipe-mcp/ruff.toml similarity index 100% rename from fuzzforge-mcp/ruff.toml rename to secpipe-mcp/ruff.toml diff --git a/fuzzforge-mcp/src/fuzzforge_mcp/__init__.py b/secpipe-mcp/src/secpipe_mcp/__init__.py similarity index 100% rename from fuzzforge-mcp/src/fuzzforge_mcp/__init__.py rename to secpipe-mcp/src/secpipe_mcp/__init__.py diff --git a/fuzzforge-mcp/src/fuzzforge_mcp/__main__.py b/secpipe-mcp/src/secpipe_mcp/__main__.py similarity index 63% rename from fuzzforge-mcp/src/fuzzforge_mcp/__main__.py rename to secpipe-mcp/src/secpipe_mcp/__main__.py index a740b16..7181146 100644 --- a/fuzzforge-mcp/src/fuzzforge_mcp/__main__.py +++ b/secpipe-mcp/src/secpipe_mcp/__main__.py @@ -1,10 +1,10 @@ -"""FuzzForge MCP Server entry point.""" +"""SecPipe MCP Server entry point.""" -from fuzzforge_mcp.application import mcp +from secpipe_mcp.application import mcp def main() -> None: - """Run the FuzzForge MCP server in stdio mode. + """Run the SecPipe MCP server in stdio mode. This is the primary entry point for AI agent integration. The server communicates via stdin/stdout using the MCP protocol. diff --git a/fuzzforge-mcp/src/fuzzforge_mcp/application.py b/secpipe-mcp/src/secpipe_mcp/application.py similarity index 90% rename from fuzzforge-mcp/src/fuzzforge_mcp/application.py rename to secpipe-mcp/src/secpipe_mcp/application.py index ff0c5af..b77a14d 100644 --- a/fuzzforge-mcp/src/fuzzforge_mcp/application.py +++ b/secpipe-mcp/src/secpipe_mcp/application.py @@ -1,6 +1,6 @@ -"""FuzzForge MCP Server Application. +"""SecPipe MCP Server Application. -This is the main entry point for the FuzzForge MCP server, providing +This is the main entry point for the SecPipe MCP server, providing AI agents with tools to discover and execute MCP hub tools for security research. @@ -12,8 +12,8 @@ from typing import TYPE_CHECKING from fastmcp import FastMCP from fastmcp.server.middleware.error_handling import ErrorHandlingMiddleware -from fuzzforge_mcp import resources, tools -from fuzzforge_mcp.settings import Settings +from secpipe_mcp import resources, tools +from secpipe_mcp.settings import Settings if TYPE_CHECKING: from collections.abc import AsyncGenerator @@ -35,9 +35,9 @@ async def lifespan(_: FastMCP) -> AsyncGenerator[Settings]: mcp: FastMCP = FastMCP( - name="FuzzForge MCP Server", + name="SecPipe MCP Server", instructions=""" -FuzzForge is a security research orchestration platform. Use these tools to: +SecPipe is a security research orchestration platform. Use these tools to: 1. **List hub servers**: Discover registered MCP tool servers 2. **Discover tools**: Find available tools from hub servers diff --git a/fuzzforge-mcp/src/fuzzforge_mcp/dependencies.py b/secpipe-mcp/src/secpipe_mcp/dependencies.py similarity index 88% rename from fuzzforge-mcp/src/fuzzforge_mcp/dependencies.py rename to secpipe-mcp/src/secpipe_mcp/dependencies.py index 3f1dc83..b3faccd 100644 --- a/fuzzforge-mcp/src/fuzzforge_mcp/dependencies.py +++ b/secpipe-mcp/src/secpipe_mcp/dependencies.py @@ -1,4 +1,4 @@ -"""Dependency injection helpers for FuzzForge MCP.""" +"""Dependency injection helpers for SecPipe MCP.""" from __future__ import annotations @@ -7,9 +7,9 @@ from typing import TYPE_CHECKING, Any, cast from fastmcp.server.dependencies import get_context -from fuzzforge_mcp.exceptions import FuzzForgeMCPError -from fuzzforge_mcp.settings import Settings -from fuzzforge_mcp.storage import LocalStorage +from secpipe_mcp.exceptions import SecPipeMCPError +from secpipe_mcp.settings import Settings +from secpipe_mcp.storage import LocalStorage if TYPE_CHECKING: from fastmcp import Context @@ -41,13 +41,13 @@ def get_settings() -> Settings: """Get MCP server settings from context. :return: Settings instance. - :raises FuzzForgeMCPError: If settings not available. + :raises SecPipeMCPError: If settings not available. """ context: Context = get_context() if context.request_context is None: message: str = "Request context not available" - raise FuzzForgeMCPError(message) + raise SecPipeMCPError(message) return cast("Settings", context.request_context.lifespan_context) diff --git a/secpipe-mcp/src/secpipe_mcp/exceptions.py b/secpipe-mcp/src/secpipe_mcp/exceptions.py new file mode 100644 index 0000000..fd6ac3c --- /dev/null +++ b/secpipe-mcp/src/secpipe_mcp/exceptions.py @@ -0,0 +1,5 @@ +"""TODO.""" + + +class SecPipeMCPError(Exception): + """TODO.""" diff --git a/fuzzforge-mcp/src/fuzzforge_mcp/resources/__init__.py b/secpipe-mcp/src/secpipe_mcp/resources/__init__.py similarity index 60% rename from fuzzforge-mcp/src/fuzzforge_mcp/resources/__init__.py rename to secpipe-mcp/src/secpipe_mcp/resources/__init__.py index ac66e72..0da4d27 100644 --- a/fuzzforge-mcp/src/fuzzforge_mcp/resources/__init__.py +++ b/secpipe-mcp/src/secpipe_mcp/resources/__init__.py @@ -1,8 +1,8 @@ -"""FuzzForge MCP Resources.""" +"""SecPipe MCP Resources.""" from fastmcp import FastMCP -from fuzzforge_mcp.resources import executions, project +from secpipe_mcp.resources import executions, project mcp: FastMCP = FastMCP() diff --git a/fuzzforge-mcp/src/fuzzforge_mcp/resources/executions.py b/secpipe-mcp/src/secpipe_mcp/resources/executions.py similarity index 89% rename from fuzzforge-mcp/src/fuzzforge_mcp/resources/executions.py rename to secpipe-mcp/src/secpipe_mcp/resources/executions.py index 61df782..96d76b6 100644 --- a/fuzzforge-mcp/src/fuzzforge_mcp/resources/executions.py +++ b/secpipe-mcp/src/secpipe_mcp/resources/executions.py @@ -1,4 +1,4 @@ -"""Execution resources for FuzzForge MCP.""" +"""Execution resources for SecPipe MCP.""" from __future__ import annotations @@ -8,12 +8,12 @@ from typing import Any from fastmcp import FastMCP from fastmcp.exceptions import ResourceError -from fuzzforge_mcp.dependencies import get_project_path, get_storage +from secpipe_mcp.dependencies import get_project_path, get_storage mcp: FastMCP = FastMCP() -@mcp.resource("fuzzforge://executions/") +@mcp.resource("secpipe://executions/") async def list_executions() -> list[dict[str, Any]]: """List all executions for the current project. @@ -41,7 +41,7 @@ async def list_executions() -> list[dict[str, Any]]: raise ResourceError(message) from exception -@mcp.resource("fuzzforge://executions/{execution_id}") +@mcp.resource("secpipe://executions/{execution_id}") async def get_execution(execution_id: str) -> dict[str, Any]: """Get information about a specific execution. diff --git a/fuzzforge-mcp/src/fuzzforge_mcp/resources/project.py b/secpipe-mcp/src/secpipe_mcp/resources/project.py similarity index 88% rename from fuzzforge-mcp/src/fuzzforge_mcp/resources/project.py rename to secpipe-mcp/src/secpipe_mcp/resources/project.py index ee9717a..f933bb2 100644 --- a/fuzzforge-mcp/src/fuzzforge_mcp/resources/project.py +++ b/secpipe-mcp/src/secpipe_mcp/resources/project.py @@ -1,4 +1,4 @@ -"""Project resources for FuzzForge MCP.""" +"""Project resources for SecPipe MCP.""" from __future__ import annotations @@ -8,12 +8,12 @@ from typing import Any from fastmcp import FastMCP from fastmcp.exceptions import ResourceError -from fuzzforge_mcp.dependencies import get_project_path, get_settings, get_storage +from secpipe_mcp.dependencies import get_project_path, get_settings, get_storage mcp: FastMCP = FastMCP() -@mcp.resource("fuzzforge://project") +@mcp.resource("secpipe://project") async def get_project() -> dict[str, Any]: """Get information about the current project. @@ -44,9 +44,9 @@ async def get_project() -> dict[str, Any]: raise ResourceError(message) from exception -@mcp.resource("fuzzforge://project/settings") +@mcp.resource("secpipe://project/settings") async def get_project_settings() -> dict[str, Any]: - """Get current FuzzForge settings. + """Get current SecPipe settings. Returns the active configuration for the MCP server including engine, storage, and hub settings. diff --git a/fuzzforge-mcp/src/fuzzforge_mcp/settings.py b/secpipe-mcp/src/secpipe_mcp/settings.py similarity index 64% rename from fuzzforge-mcp/src/fuzzforge_mcp/settings.py rename to secpipe-mcp/src/secpipe_mcp/settings.py index a2d6bbd..5ad7952 100644 --- a/fuzzforge-mcp/src/fuzzforge_mcp/settings.py +++ b/secpipe-mcp/src/secpipe_mcp/settings.py @@ -1,16 +1,16 @@ -"""FuzzForge MCP Server settings. +"""SecPipe MCP Server settings. Standalone settings for the MCP server. Replaces the previous dependency -on fuzzforge-runner Settings now that the module system has been removed -and FuzzForge operates exclusively through MCP hub tools. +on secpipe-runner Settings now that the module system has been removed +and SecPipe operates exclusively through MCP hub tools. All settings can be configured via environment variables with the prefix -``FUZZFORGE_``. Nested settings use double-underscore as delimiter. +``SECPIPE_``. Nested settings use double-underscore as delimiter. Example: - ``FUZZFORGE_ENGINE__TYPE=docker`` - ``FUZZFORGE_STORAGE__PATH=/data/fuzzforge`` - ``FUZZFORGE_HUB__CONFIG_PATH=/path/to/hub-config.json`` + ``SECPIPE_ENGINE__TYPE=docker`` + ``SECPIPE_STORAGE__PATH=/data/secpipe`` + ``SECPIPE_HUB__CONFIG_PATH=/path/to/hub-config.json`` """ @@ -40,61 +40,61 @@ class EngineSettings(BaseModel): socket: str = Field(default="") #: Custom graph root for Podman storage. - graphroot: Path = Field(default=Path.home() / ".fuzzforge" / "containers" / "storage") + graphroot: Path = Field(default=Path.home() / ".secpipe" / "containers" / "storage") #: Custom run root for Podman runtime state. - runroot: Path = Field(default=Path.home() / ".fuzzforge" / "containers" / "run") + runroot: Path = Field(default=Path.home() / ".secpipe" / "containers" / "run") class StorageSettings(BaseModel): """Storage configuration for local filesystem storage.""" #: Base path for local storage. - path: Path = Field(default=Path.home() / ".fuzzforge" / "storage") + path: Path = Field(default=Path.home() / ".secpipe" / "storage") class ProjectSettings(BaseModel): """Project configuration.""" - #: Default path for FuzzForge projects. - default_path: Path = Field(default=Path.home() / ".fuzzforge" / "projects") + #: Default path for SecPipe projects. + default_path: Path = Field(default=Path.home() / ".secpipe" / "projects") class HubSettings(BaseModel): """MCP Hub configuration for external tool servers. - Controls the hub that bridges FuzzForge with external MCP servers + Controls the hub that bridges SecPipe with external MCP servers (e.g., mcp-security-hub). AI agents discover and execute tools from registered MCP servers. Configure via environment variables: - ``FUZZFORGE_HUB__ENABLED=true`` - ``FUZZFORGE_HUB__CONFIG_PATH=/path/to/hub-config.json`` - ``FUZZFORGE_HUB__TIMEOUT=300`` + ``SECPIPE_HUB__ENABLED=true`` + ``SECPIPE_HUB__CONFIG_PATH=/path/to/hub-config.json`` + ``SECPIPE_HUB__TIMEOUT=300`` """ #: Whether the MCP hub is enabled. enabled: bool = Field(default=True) #: Path to the hub configuration JSON file. - config_path: Path = Field(default=Path.home() / ".fuzzforge" / "hub-config.json") + config_path: Path = Field(default=Path.home() / ".secpipe" / "hub-config.json") #: Default timeout in seconds for hub tool execution. timeout: int = Field(default=300) class Settings(BaseSettings): - """FuzzForge MCP Server settings. + """SecPipe MCP Server settings. Settings can be configured via environment variables with the prefix - ``FUZZFORGE_``. Nested settings use double-underscore as delimiter. + ``SECPIPE_``. Nested settings use double-underscore as delimiter. """ model_config = SettingsConfigDict( case_sensitive=False, env_nested_delimiter="__", - env_prefix="FUZZFORGE_", + env_prefix="SECPIPE_", ) #: Container engine settings. diff --git a/fuzzforge-mcp/src/fuzzforge_mcp/skills/firmware-analysis.yaml b/secpipe-mcp/src/secpipe_mcp/skills/firmware-analysis.yaml similarity index 100% rename from fuzzforge-mcp/src/fuzzforge_mcp/skills/firmware-analysis.yaml rename to secpipe-mcp/src/secpipe_mcp/skills/firmware-analysis.yaml diff --git a/fuzzforge-mcp/src/fuzzforge_mcp/skills/go-fuzzing.yaml b/secpipe-mcp/src/secpipe_mcp/skills/go-fuzzing.yaml similarity index 100% rename from fuzzforge-mcp/src/fuzzforge_mcp/skills/go-fuzzing.yaml rename to secpipe-mcp/src/secpipe_mcp/skills/go-fuzzing.yaml diff --git a/fuzzforge-mcp/src/fuzzforge_mcp/storage.py b/secpipe-mcp/src/secpipe_mcp/storage.py similarity index 95% rename from fuzzforge-mcp/src/fuzzforge_mcp/storage.py rename to secpipe-mcp/src/secpipe_mcp/storage.py index 620bfdd..c0f3cbd 100644 --- a/fuzzforge-mcp/src/fuzzforge_mcp/storage.py +++ b/secpipe-mcp/src/secpipe_mcp/storage.py @@ -1,10 +1,10 @@ -"""FuzzForge MCP Server - Local project storage. +"""SecPipe MCP Server - Local project storage. -Lightweight project storage for managing `.fuzzforge/` directories, +Lightweight project storage for managing `.secpipe/` directories, execution results, and project configuration. Extracted from the -former fuzzforge-runner storage module. +former secpipe-runner storage module. -Storage is placed directly in the project directory as `.fuzzforge/` +Storage is placed directly in the project directory as `.secpipe/` for maximum visibility and ease of debugging. """ @@ -22,10 +22,10 @@ from uuid import uuid4 import yaml -logger = logging.getLogger("fuzzforge-mcp") +logger = logging.getLogger("secpipe-mcp") -#: Name of the FuzzForge storage directory within projects. -FUZZFORGE_DIR_NAME: str = ".fuzzforge" +#: Name of the SecPipe storage directory within projects. +SECPIPE_DIR_NAME: str = ".secpipe" #: Standard results archive filename. RESULTS_ARCHIVE_FILENAME: str = "results.tar.gz" @@ -36,14 +36,14 @@ class StorageError(Exception): class LocalStorage: - """Local filesystem storage backend for FuzzForge. + """Local filesystem storage backend for SecPipe. Provides lightweight storage for project configuration and execution results tracking. Directory structure (inside project directory):: - {project_path}/.fuzzforge/ + {project_path}/.secpipe/ config.json # Project config (source path reference) runs/ # Execution results {execution_id}/ @@ -63,18 +63,18 @@ class LocalStorage: self._base_path.mkdir(parents=True, exist_ok=True) def _get_project_path(self, project_path: Path) -> Path: - """Get the .fuzzforge storage path for a project. + """Get the .secpipe storage path for a project. :param project_path: Path to the project directory. - :returns: Storage path (.fuzzforge inside project). + :returns: Storage path (.secpipe inside project). """ - return project_path / FUZZFORGE_DIR_NAME + return project_path / SECPIPE_DIR_NAME def init_project(self, project_path: Path) -> Path: """Initialize storage for a new project. - Creates a .fuzzforge/ directory inside the project for storing + Creates a .secpipe/ directory inside the project for storing configuration and execution results. :param project_path: Path to the project directory. @@ -90,7 +90,7 @@ class LocalStorage: gitignore_path = storage_path / ".gitignore" if not gitignore_path.exists(): gitignore_path.write_text( - "# FuzzForge storage - ignore large/temporary files\n" + "# SecPipe storage - ignore large/temporary files\n" "runs/\n" "output/\n" "artifacts.json\n" @@ -374,7 +374,7 @@ class LocalStorage: ) -> list[dict[str, Any]]: """Scan the output directory for new or modified files and register them. - Compares the current state of .fuzzforge/output/ against the existing + Compares the current state of .secpipe/output/ against the existing artifact registry and registers any new or modified files. :param project_path: Path to the project directory. @@ -511,7 +511,7 @@ class LocalStorage: content: str, fmt: str = "markdown", ) -> Path: - """Save a generated report to .fuzzforge/reports/. + """Save a generated report to .secpipe/reports/. :param project_path: Path to the project directory. :param content: Report content string. @@ -558,7 +558,7 @@ class LocalStorage: # Skill packs # ------------------------------------------------------------------ - #: Directory containing built-in skill packs shipped with FuzzForge. + #: Directory containing built-in skill packs shipped with SecPipe. _BUILTIN_SKILLS_DIR: Path = Path(__file__).parent / "skills" def _skill_dirs(self, project_path: Path) -> list[Path]: @@ -597,7 +597,7 @@ class LocalStorage: seen.add(name) desc = skill.get("description", "") first_line = desc.strip().split("\n", 1)[0] if desc else "" - is_project = ".fuzzforge" in str(yaml_path.parent) + is_project = ".secpipe" in str(yaml_path.parent) source = "project" if is_project else "builtin" skills.append({ "name": name, diff --git a/fuzzforge-mcp/src/fuzzforge_mcp/tools/__init__.py b/secpipe-mcp/src/secpipe_mcp/tools/__init__.py similarity index 64% rename from fuzzforge-mcp/src/fuzzforge_mcp/tools/__init__.py rename to secpipe-mcp/src/secpipe_mcp/tools/__init__.py index e22d7db..db32c84 100644 --- a/fuzzforge-mcp/src/fuzzforge_mcp/tools/__init__.py +++ b/secpipe-mcp/src/secpipe_mcp/tools/__init__.py @@ -1,8 +1,8 @@ -"""FuzzForge MCP Tools.""" +"""SecPipe MCP Tools.""" from fastmcp import FastMCP -from fuzzforge_mcp.tools import hub, projects, reports +from secpipe_mcp.tools import hub, projects, reports mcp: FastMCP = FastMCP() diff --git a/fuzzforge-mcp/src/fuzzforge_mcp/tools/hub.py b/secpipe-mcp/src/secpipe_mcp/tools/hub.py similarity index 98% rename from fuzzforge-mcp/src/fuzzforge_mcp/tools/hub.py rename to secpipe-mcp/src/secpipe_mcp/tools/hub.py index 6f7a59e..27bb240 100644 --- a/fuzzforge-mcp/src/fuzzforge_mcp/tools/hub.py +++ b/secpipe-mcp/src/secpipe_mcp/tools/hub.py @@ -1,7 +1,7 @@ -"""MCP Hub tools for FuzzForge MCP server. +"""MCP Hub tools for SecPipe MCP server. This module provides tools for interacting with external MCP servers -through the FuzzForge hub. AI agents can: +through the SecPipe hub. AI agents can: - List available hub servers and their tools - Discover tools from hub servers - Execute hub tools @@ -14,9 +14,9 @@ from typing import Any from fastmcp import FastMCP from fastmcp.exceptions import ToolError -from fuzzforge_common.hub import HubExecutor, HubServerConfig, HubServerType +from secpipe_common.hub import HubExecutor, HubServerConfig, HubServerType -from fuzzforge_mcp.dependencies import get_project_path, get_settings, get_storage +from secpipe_mcp.dependencies import get_project_path, get_settings, get_storage mcp: FastMCP = FastMCP() @@ -67,7 +67,7 @@ def _get_hub_executor() -> HubExecutor: settings = get_settings() if not settings.hub.enabled: - msg = "MCP Hub is disabled. Enable it via FUZZFORGE_HUB__ENABLED=true" + msg = "MCP Hub is disabled. Enable it via SECPIPE_HUB__ENABLED=true" raise ToolError(msg) if _hub_executor is None: @@ -242,7 +242,7 @@ async def execute_hub_tool( Tool outputs are persisted to a writable shared volume: - /app/output/ (writable — extraction results, reports, etc.) Files written here survive container destruction and are available - to subsequent tool calls. The host path is .fuzzforge/output/. + to subsequent tool calls. The host path is .secpipe/output/. """ try: diff --git a/fuzzforge-mcp/src/fuzzforge_mcp/tools/projects.py b/secpipe-mcp/src/secpipe_mcp/tools/projects.py similarity index 94% rename from fuzzforge-mcp/src/fuzzforge_mcp/tools/projects.py rename to secpipe-mcp/src/secpipe_mcp/tools/projects.py index 598f653..0c25944 100644 --- a/fuzzforge-mcp/src/fuzzforge_mcp/tools/projects.py +++ b/secpipe-mcp/src/secpipe_mcp/tools/projects.py @@ -1,4 +1,4 @@ -"""Project management tools for FuzzForge MCP.""" +"""Project management tools for SecPipe MCP.""" from __future__ import annotations @@ -8,7 +8,7 @@ from typing import Any from fastmcp import FastMCP from fastmcp.exceptions import ToolError -from fuzzforge_mcp.dependencies import ( +from secpipe_mcp.dependencies import ( get_active_skill, get_project_path, get_storage, @@ -21,14 +21,14 @@ mcp: FastMCP = FastMCP() @mcp.tool async def init_project(project_path: str | None = None) -> dict[str, Any]: - """Initialize a new FuzzForge project workspace. + """Initialize a new SecPipe project workspace. - Creates a `.fuzzforge/` directory for storing configuration and execution results. + Creates a `.secpipe/` directory for storing configuration and execution results. Call this once before using hub tools. The project path is a working directory - for FuzzForge state — it does not need to contain the files you want to analyze. + for SecPipe state — it does not need to contain the files you want to analyze. Use `set_project_assets` separately to specify the target files. - :param project_path: Working directory for FuzzForge state. Defaults to current directory. + :param project_path: Working directory for SecPipe state. Defaults to current directory. :return: Project initialization result. """ @@ -46,7 +46,7 @@ async def init_project(project_path: str | None = None) -> dict[str, Any]: "success": True, "project_path": str(path), "storage_path": str(storage_path), - "message": f"Project initialized. Storage at {path}/.fuzzforge/", + "message": f"Project initialized. Storage at {path}/.secpipe/", } except Exception as exception: @@ -58,7 +58,7 @@ async def init_project(project_path: str | None = None) -> dict[str, Any]: async def set_project_assets(assets_path: str) -> dict[str, Any]: """Set the directory containing target files to analyze. - Points FuzzForge to the directory with your analysis targets + Points SecPipe to the directory with your analysis targets (firmware images, binaries, source code, etc.). This directory is mounted read-only into hub tool containers. @@ -227,7 +227,7 @@ async def list_skills() -> dict[str, Any]: Skill packs provide domain-specific pipeline guidance for AI agents. They describe analysis methodologies and list the hub servers needed. - Project-local skills (.fuzzforge/skills/) override built-in skills. + Project-local skills (.secpipe/skills/) override built-in skills. :return: List of available skills with name, summary, and server list. diff --git a/fuzzforge-mcp/src/fuzzforge_mcp/tools/reports.py b/secpipe-mcp/src/secpipe_mcp/tools/reports.py similarity index 95% rename from fuzzforge-mcp/src/fuzzforge_mcp/tools/reports.py rename to secpipe-mcp/src/secpipe_mcp/tools/reports.py index f49e71a..89ced55 100644 --- a/fuzzforge-mcp/src/fuzzforge_mcp/tools/reports.py +++ b/secpipe-mcp/src/secpipe_mcp/tools/reports.py @@ -1,4 +1,4 @@ -"""Report generation tools for FuzzForge MCP.""" +"""Report generation tools for SecPipe MCP.""" from __future__ import annotations @@ -10,7 +10,7 @@ from typing import Any from fastmcp import FastMCP from fastmcp.exceptions import ToolError -from fuzzforge_mcp.dependencies import get_project_path, get_storage +from secpipe_mcp.dependencies import get_project_path, get_storage mcp: FastMCP = FastMCP() @@ -214,7 +214,7 @@ def _build_markdown_report( + _report_summary(executions, artifacts) + _report_timeline(executions, artifacts) + _report_artifacts(artifacts) - + ["---", "", "*Generated by FuzzForge*", ""] + + ["---", "", "*Generated by SecPipe*", ""] ) return "\n".join(lines) @@ -265,13 +265,13 @@ async def generate_report( """Generate a comprehensive analysis report for the current project. Aggregates all execution history, tool outputs, and tracked artifacts - into a structured report. The report is saved to `.fuzzforge/reports/` + into a structured report. The report is saved to `.secpipe/reports/` and its content is returned so the agent can read it immediately. :param title: Optional report title. Defaults to the project folder name. :param report_format: Output format — ``"markdown"`` (default) or ``"json"``. :param output_path: Optional absolute path to save the report. When omitted, - the report is saved automatically to `.fuzzforge/reports/`. + the report is saved automatically to `.secpipe/reports/`. :return: Report content, save path, and counts of included items. """ @@ -290,7 +290,7 @@ async def generate_report( artifacts = storage.list_artifacts(project_path) assets_path = storage.get_project_assets_path(project_path) - resolved_title = title or f"FuzzForge Analysis Report — {project_path.name}" + resolved_title = title or f"SecPipe Analysis Report — {project_path.name}" if fmt == "json": content = _build_json_report( @@ -325,7 +325,7 @@ async def generate_report( async def list_reports() -> dict[str, Any]: """List all generated reports for the current project. - Reports are stored in `.fuzzforge/reports/` and are ordered newest-first. + Reports are stored in `.secpipe/reports/` and are ordered newest-first. :return: List of report files with filename, path, size, and creation time. diff --git a/fuzzforge-mcp/tests/__init__.py b/secpipe-mcp/tests/__init__.py similarity index 100% rename from fuzzforge-mcp/tests/__init__.py rename to secpipe-mcp/tests/__init__.py diff --git a/fuzzforge-mcp/tests/conftest.py b/secpipe-mcp/tests/conftest.py similarity index 53% rename from fuzzforge-mcp/tests/conftest.py rename to secpipe-mcp/tests/conftest.py index fe2e565..af195b4 100644 --- a/fuzzforge-mcp/tests/conftest.py +++ b/secpipe-mcp/tests/conftest.py @@ -5,26 +5,26 @@ from typing import TYPE_CHECKING import pytest from fastmcp import Client -from fuzzforge_mcp.application import mcp +from secpipe_mcp.application import mcp if TYPE_CHECKING: from collections.abc import AsyncGenerator, Callable from fastmcp.client import FastMCPTransport - from fuzzforge_tests.fixtures import FuzzForgeProjectIdentifier + from secpipe_tests.fixtures import SecPipeProjectIdentifier -pytest_plugins = ["fuzzforge_tests.fixtures"] +pytest_plugins = ["secpipe_tests.fixtures"] @pytest.fixture(autouse=True) def environment( monkeypatch: pytest.MonkeyPatch, - random_project_identifier: Callable[[], FuzzForgeProjectIdentifier], + random_project_identifier: Callable[[], SecPipeProjectIdentifier], ) -> None: """TODO.""" - monkeypatch.setenv("FUZZFORGE_PROJECT_IDENTIFIER", str(random_project_identifier())) - monkeypatch.setenv("FUZZFORGE_API_HOST", "127.0.0.1") - monkeypatch.setenv("FUZZFORGE_API_PORT", "8000") + monkeypatch.setenv("SECPIPE_PROJECT_IDENTIFIER", str(random_project_identifier())) + monkeypatch.setenv("SECPIPE_API_HOST", "127.0.0.1") + monkeypatch.setenv("SECPIPE_API_PORT", "8000") @pytest.fixture diff --git a/fuzzforge-mcp/tests/test_resources.py b/secpipe-mcp/tests/test_resources.py similarity index 88% rename from fuzzforge-mcp/tests/test_resources.py rename to secpipe-mcp/tests/test_resources.py index 6665f91..36deec7 100644 --- a/fuzzforge-mcp/tests/test_resources.py +++ b/secpipe-mcp/tests/test_resources.py @@ -1,6 +1,6 @@ -"""MCP tool tests for FuzzForge AI. +"""MCP tool tests for SecPipe AI. -Tests the MCP tools that are available in FuzzForge AI. +Tests the MCP tools that are available in SecPipe AI. """ import pytest diff --git a/fuzzforge-tests/Makefile b/secpipe-tests/Makefile similarity index 100% rename from fuzzforge-tests/Makefile rename to secpipe-tests/Makefile diff --git a/fuzzforge-tests/README.md b/secpipe-tests/README.md similarity index 100% rename from fuzzforge-tests/README.md rename to secpipe-tests/README.md diff --git a/fuzzforge-tests/mypy.ini b/secpipe-tests/mypy.ini similarity index 100% rename from fuzzforge-tests/mypy.ini rename to secpipe-tests/mypy.ini diff --git a/fuzzforge-tests/pyproject.toml b/secpipe-tests/pyproject.toml similarity index 63% rename from fuzzforge-tests/pyproject.toml rename to secpipe-tests/pyproject.toml index a12721c..1dd455b 100644 --- a/fuzzforge-tests/pyproject.toml +++ b/secpipe-tests/pyproject.toml @@ -1,7 +1,7 @@ [project] -name = "fuzzforge-tests" +name = "secpipe-tests" version = "0.0.1" -description = "Common test utilities and fixtures for FuzzForge packages." +description = "Common test utilities and fixtures for SecPipe packages." authors = [] readme = "README.md" requires-python = ">=3.14" @@ -9,7 +9,7 @@ dependencies = [ "podman==5.6.0", "pydantic>=2.12.4", "pytest==9.0.2", - "fuzzforge-common==0.0.1", + "secpipe-common==0.0.1", ] [project.optional-dependencies] @@ -20,4 +20,4 @@ lints = [ ] [tool.uv.sources] -fuzzforge-common = { workspace = true } +secpipe-common = { workspace = true } diff --git a/fuzzforge-tests/ruff.toml b/secpipe-tests/ruff.toml similarity index 100% rename from fuzzforge-tests/ruff.toml rename to secpipe-tests/ruff.toml diff --git a/secpipe-tests/src/secpipe_tests/__init__.py b/secpipe-tests/src/secpipe_tests/__init__.py new file mode 100644 index 0000000..f8cda10 --- /dev/null +++ b/secpipe-tests/src/secpipe_tests/__init__.py @@ -0,0 +1,9 @@ +"""Common test utilities and fixtures for SecPipe packages. + +This package provides shared test utilities, fixtures, and helpers that can be +reused across multiple SecPipe packages to reduce code duplication and ensure +consistency in testing approaches. + +""" + +__all__ = [] diff --git a/fuzzforge-tests/src/fuzzforge_tests/conftest.py b/secpipe-tests/src/secpipe_tests/conftest.py similarity index 78% rename from fuzzforge-tests/src/fuzzforge_tests/conftest.py rename to secpipe-tests/src/secpipe_tests/conftest.py index 58d5096..2a61df5 100644 --- a/fuzzforge-tests/src/fuzzforge_tests/conftest.py +++ b/secpipe-tests/src/secpipe_tests/conftest.py @@ -1,13 +1,13 @@ """Pytest configuration for shared fixtures. This conftest.py makes fixtures available to any test that imports from -fuzzforge_tests. Test packages should add 'pytest_plugins = ["fuzzforge_tests.fixtures"]' +secpipe_tests. Test packages should add 'pytest_plugins = ["secpipe_tests.fixtures"]' to their conftest.py to use these shared fixtures. """ # Import fixtures to make them available -from fuzzforge_tests.fixtures import ( +from secpipe_tests.fixtures import ( minio_container, random_module_execution_identifier, random_project_identifier, diff --git a/fuzzforge-tests/src/fuzzforge_tests/fixtures.py b/secpipe-tests/src/secpipe_tests/fixtures.py similarity index 77% rename from fuzzforge-tests/src/fuzzforge_tests/fixtures.py rename to secpipe-tests/src/secpipe_tests/fixtures.py index 3cb1b8e..5c792b2 100644 --- a/fuzzforge-tests/src/fuzzforge_tests/fixtures.py +++ b/secpipe-tests/src/secpipe_tests/fixtures.py @@ -1,7 +1,7 @@ -"""Common test fixtures for FuzzForge packages. +"""Common test fixtures for SecPipe packages. Provides reusable fixtures for generating random identifiers and other -common test utilities shared across multiple FuzzForge packages. +common test utilities shared across multiple SecPipe packages. """ @@ -12,18 +12,18 @@ from typing import TYPE_CHECKING from uuid import uuid4, uuid7 import pytest -from fuzzforge_common.sandboxes.engines.podman.configuration import PodmanConfiguration +from secpipe_common.sandboxes.engines.podman.configuration import PodmanConfiguration from podman import PodmanClient from pydantic import UUID7 # Type aliases for identifiers -type FuzzForgeProjectIdentifier = UUID7 -type FuzzForgeExecutionIdentifier = UUID7 +type SecPipeProjectIdentifier = UUID7 +type SecPipeExecutionIdentifier = UUID7 # Constants for validation -FUZZFORGE_PROJECT_NAME_LENGTH_MIN: int = 3 -FUZZFORGE_PROJECT_NAME_LENGTH_MAX: int = 64 -FUZZFORGE_PROJECT_DESCRIPTION_LENGTH_MAX: int = 256 +SECPIPE_PROJECT_NAME_LENGTH_MIN: int = 3 +SECPIPE_PROJECT_NAME_LENGTH_MAX: int = 64 +SECPIPE_PROJECT_DESCRIPTION_LENGTH_MAX: int = 256 if TYPE_CHECKING: from collections.abc import Callable, Generator @@ -47,8 +47,8 @@ def random_project_name() -> Callable[[], str]: def inner() -> str: return generate_random_string( - min_length=FUZZFORGE_PROJECT_NAME_LENGTH_MIN, - max_length=FUZZFORGE_PROJECT_NAME_LENGTH_MAX, + min_length=SECPIPE_PROJECT_NAME_LENGTH_MIN, + max_length=SECPIPE_PROJECT_NAME_LENGTH_MAX, ) return inner @@ -61,14 +61,14 @@ def random_project_description() -> Callable[[], str]: def inner() -> str: return generate_random_string( min_length=1, - max_length=FUZZFORGE_PROJECT_DESCRIPTION_LENGTH_MAX, + max_length=SECPIPE_PROJECT_DESCRIPTION_LENGTH_MAX, ) return inner @pytest.fixture -def random_project_identifier() -> Callable[[], FuzzForgeProjectIdentifier]: +def random_project_identifier() -> Callable[[], SecPipeProjectIdentifier]: """Generate random project identifiers. Returns a callable that generates fresh UUID7 identifiers for each call. @@ -78,14 +78,14 @@ def random_project_identifier() -> Callable[[], FuzzForgeProjectIdentifier]: """ - def inner() -> FuzzForgeProjectIdentifier: + def inner() -> SecPipeProjectIdentifier: return uuid7() return inner @pytest.fixture -def random_execution_identifier() -> Callable[[], FuzzForgeExecutionIdentifier]: +def random_execution_identifier() -> Callable[[], SecPipeExecutionIdentifier]: """Generate random execution identifiers. Returns a callable that generates fresh UUID7 identifiers for each call. @@ -95,7 +95,7 @@ def random_execution_identifier() -> Callable[[], FuzzForgeExecutionIdentifier]: """ - def inner() -> FuzzForgeExecutionIdentifier: + def inner() -> SecPipeExecutionIdentifier: return uuid7() return inner diff --git a/uv.lock b/uv.lock index 8c4b4ee..30441e8 100644 --- a/uv.lock +++ b/uv.lock @@ -4,11 +4,11 @@ requires-python = ">=3.14" [manifest] members = [ - "fuzzforge-cli", - "fuzzforge-common", - "fuzzforge-mcp", - "fuzzforge-oss", - "fuzzforge-tests", + "secpipe-cli", + "secpipe-common", + "secpipe-mcp", + "secpipe-oss", + "secpipe-tests", ] [[package]] @@ -358,11 +358,11 @@ wheels = [ ] [[package]] -name = "fuzzforge-cli" +name = "secpipe-cli" version = "0.0.1" -source = { editable = "fuzzforge-cli" } +source = { editable = "secpipe-cli" } dependencies = [ - { name = "fuzzforge-mcp" }, + { name = "secpipe-mcp" }, { name = "rich" }, { name = "textual" }, { name = "typer" }, @@ -381,7 +381,7 @@ tests = [ [package.metadata] requires-dist = [ { name = "bandit", marker = "extra == 'lints'", specifier = "==1.8.6" }, - { name = "fuzzforge-mcp", editable = "fuzzforge-mcp" }, + { name = "secpipe-mcp", editable = "secpipe-mcp" }, { name = "mypy", marker = "extra == 'lints'", specifier = "==1.18.2" }, { name = "pytest", marker = "extra == 'tests'", specifier = "==9.0.2" }, { name = "rich", specifier = ">=14.0.0" }, @@ -392,9 +392,9 @@ requires-dist = [ provides-extras = ["lints", "tests"] [[package]] -name = "fuzzforge-common" +name = "secpipe-common" version = "0.0.1" -source = { editable = "fuzzforge-common" } +source = { editable = "secpipe-common" } dependencies = [ { name = "podman" }, { name = "pydantic" }, @@ -424,12 +424,12 @@ requires-dist = [ provides-extras = ["lints", "tests"] [[package]] -name = "fuzzforge-mcp" +name = "secpipe-mcp" version = "0.0.1" -source = { editable = "fuzzforge-mcp" } +source = { editable = "secpipe-mcp" } dependencies = [ { name = "fastmcp" }, - { name = "fuzzforge-common" }, + { name = "secpipe-common" }, { name = "pydantic" }, { name = "pydantic-settings" }, { name = "pyyaml" }, @@ -443,7 +443,7 @@ lints = [ { name = "ruff" }, ] tests = [ - { name = "fuzzforge-tests" }, + { name = "secpipe-tests" }, { name = "pytest" }, { name = "pytest-asyncio" }, { name = "pytest-httpx" }, @@ -453,8 +453,8 @@ tests = [ requires-dist = [ { name = "bandit", marker = "extra == 'lints'", specifier = "==1.8.6" }, { name = "fastmcp", specifier = "==2.14.1" }, - { name = "fuzzforge-common", editable = "fuzzforge-common" }, - { name = "fuzzforge-tests", marker = "extra == 'tests'", editable = "fuzzforge-tests" }, + { name = "secpipe-common", editable = "secpipe-common" }, + { name = "secpipe-tests", marker = "extra == 'tests'", editable = "secpipe-tests" }, { name = "mypy", marker = "extra == 'lints'", specifier = "==1.18.2" }, { name = "pydantic", specifier = "==2.12.4" }, { name = "pydantic-settings", specifier = "==2.12.0" }, @@ -468,20 +468,20 @@ requires-dist = [ provides-extras = ["lints", "tests"] [[package]] -name = "fuzzforge-oss" +name = "secpipe-oss" version = "0.8.0" source = { virtual = "." } dependencies = [ - { name = "fuzzforge-cli" }, - { name = "fuzzforge-common" }, - { name = "fuzzforge-mcp" }, + { name = "secpipe-cli" }, + { name = "secpipe-common" }, + { name = "secpipe-mcp" }, ] [package.optional-dependencies] dev = [ - { name = "fuzzforge-common" }, - { name = "fuzzforge-mcp" }, - { name = "fuzzforge-tests" }, + { name = "secpipe-common" }, + { name = "secpipe-mcp" }, + { name = "secpipe-tests" }, { name = "pytest" }, { name = "pytest-asyncio" }, { name = "pytest-httpx" }, @@ -489,12 +489,12 @@ dev = [ [package.metadata] requires-dist = [ - { name = "fuzzforge-cli", editable = "fuzzforge-cli" }, - { name = "fuzzforge-common", editable = "fuzzforge-common" }, - { name = "fuzzforge-common", marker = "extra == 'dev'", editable = "fuzzforge-common" }, - { name = "fuzzforge-mcp", editable = "fuzzforge-mcp" }, - { name = "fuzzforge-mcp", marker = "extra == 'dev'", editable = "fuzzforge-mcp" }, - { name = "fuzzforge-tests", marker = "extra == 'dev'", editable = "fuzzforge-tests" }, + { name = "secpipe-cli", editable = "secpipe-cli" }, + { name = "secpipe-common", editable = "secpipe-common" }, + { name = "secpipe-common", marker = "extra == 'dev'", editable = "secpipe-common" }, + { name = "secpipe-mcp", editable = "secpipe-mcp" }, + { name = "secpipe-mcp", marker = "extra == 'dev'", editable = "secpipe-mcp" }, + { name = "secpipe-tests", marker = "extra == 'dev'", editable = "secpipe-tests" }, { name = "pytest", marker = "extra == 'dev'", specifier = "==9.0.2" }, { name = "pytest-asyncio", marker = "extra == 'dev'", specifier = "==1.3.0" }, { name = "pytest-httpx", marker = "extra == 'dev'", specifier = "==0.36.0" }, @@ -502,11 +502,11 @@ requires-dist = [ provides-extras = ["dev"] [[package]] -name = "fuzzforge-tests" +name = "secpipe-tests" version = "0.0.1" -source = { editable = "fuzzforge-tests" } +source = { editable = "secpipe-tests" } dependencies = [ - { name = "fuzzforge-common" }, + { name = "secpipe-common" }, { name = "podman" }, { name = "pydantic" }, { name = "pytest" }, @@ -522,7 +522,7 @@ lints = [ [package.metadata] requires-dist = [ { name = "bandit", marker = "extra == 'lints'", specifier = "==1.8.6" }, - { name = "fuzzforge-common", editable = "fuzzforge-common" }, + { name = "secpipe-common", editable = "secpipe-common" }, { name = "mypy", marker = "extra == 'lints'", specifier = "==1.18.2" }, { name = "podman", specifier = "==5.6.0" }, { name = "pydantic", specifier = ">=2.12.4" },