diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f8fa3c1f..4bf4a07e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -129,7 +129,11 @@ jobs: # and `scikit-learn` (framework/requirements.txt) — mirror that here. Without these the # suite errors out during collection (5 collection errors), a false red the moment the # scripts change. They resolve against the already-installed torch, so torch is untouched. - pip install -r backend/fl-platform-api/requirements.txt pytest "peft>=0.11" scikit-learn + # PyJWT: the FL-server import chain (security/token_verify.py -> `import jwt`, pulled in by + # the connection-token interceptor) needs it; framework/requirements.txt declares it, but + # this job installs the backend lockfile + uses the framework via sys.path, so add it here + # (mirrors framework/requirements.txt's `PyJWT>=2.8,<3`), like peft/scikit-learn above. + pip install -r backend/fl-platform-api/requirements.txt pytest "peft>=0.11" scikit-learn "PyJWT>=2.8,<3" # TE-10: the skip-integrity guard in tests/conftest.py fails this job if any test is # SKIPPED (this suite allowlists no skip reasons; `-m "not slow"` deselection is not a skip). - name: pytest (FL trainer scripts; pytest.ini deselects -m slow) diff --git a/.github/workflows/mobile.yml b/.github/workflows/mobile.yml index 0a841314..cc0dc438 100644 --- a/.github/workflows/mobile.yml +++ b/.github/workflows/mobile.yml @@ -68,10 +68,18 @@ jobs: run: | python -m pip install --upgrade pip pip install --index-url https://download.pytorch.org/whl/cpu "torch==${TORCH_VERSION}" - pip install numpy pytest + # test_perturbation.py imports `fedlearn`, whose package __init__ eagerly pulls in the gRPC + # server (grpc/protobuf) and token-verify (PyJWT) — so the parity job needs the framework's + # full dependency set, not just numpy. requirements.txt pins the matching torch==2.12.0 + # (already installed above) and no torchvision, so this resolves cleanly. + # pytest-cov: framework/pytest.ini addopts include --cov=fedlearn (TE-11), so pytest errors + # with "unrecognized arguments: --cov" unless it is installed — even for this subset run. + pip install -r framework/requirements.txt pytest pytest-cov - name: Run perturbation parity tests working-directory: framework - run: PYTHONPATH=src pytest tests/test_perturbation.py -v + # --no-cov: this runs a single test file, not the full suite, so coverage would trip the + # --cov-fail-under floor by design (see the pytest.ini note). Disable it for the subset. + run: PYTHONPATH=src pytest tests/test_perturbation.py -v --no-cov # ---- C++ parity gate: the gtests compare the C++ core to the Python golden fixture ---- # The core links the ExecuTorch runtime (no libtorch/ATen). The ET pip package ships headers but diff --git a/.gitleaks.toml b/.gitleaks.toml index 8b831bb2..8577ba92 100644 --- a/.gitleaks.toml +++ b/.gitleaks.toml @@ -15,4 +15,8 @@ description = "Public test/dev-only fixture credentials (never used outside test paths = [ '''.*/src/test/.*''', '''.*/application-(test|dev)\.properties$''', + # Framework test fixtures — e.g. framework/tests/fixtures/golden_connection_token.json, a + # golden token signed with the dummy secret base64("fedlearn-golden-token-secret-32b") used + # by the cross-language connection-token parity tests. Test-only, never a real credential. + '''.*/tests/fixtures/.*''', ] diff --git a/README.md b/README.md index 3c481940..414055dc 100644 --- a/README.md +++ b/README.md @@ -299,7 +299,7 @@ FedLearn-Platform/ │ │ ├── repository/ # JPA repositories │ │ ├── model/ # Entities │ │ ├── security/ # JWT provider -│ │ └── flower/ # FlowerServerManager +│ │ └── orchestration/ # FlServerManager (renamed from flower/, DA-12) │ ├── src/main/resources/ │ │ └── scripts/ # Python FL server scripts │ └── README.md # Backend documentation @@ -308,7 +308,7 @@ FedLearn-Platform/ │ ├── src/ # main / preload / renderer │ └── README.md # Desktop documentation │ -├── mobile_client/ # React Native client + native C++ (libtorch) core +├── mobile_client/ # React Native client + native C++ (ExecuTorch) core │ ├── proto/ # Byte-mirror of /proto (checked in CI) │ └── README.md # Mobile documentation │ @@ -516,7 +516,7 @@ Live at **https://fedlearn.duckdns.org**. Deploy procedure: [`docs/guides/aws_de - Let's Encrypt certbot for auto-renewing TLS - PostgreSQL 16 (local Docker Compose or host package) on the EC2 host, data dir EBS-backed across reboots - Spring Boot as a systemd service (`fedlearn.service`) -- Python FL servers spawned by `FlowerServerManager` +- Python FL servers spawned by `FlServerManager` Required env vars (set in `/etc/systemd/system/fedlearn.service`): diff --git a/backend/fl-platform-api/requirements.txt b/backend/fl-platform-api/requirements.txt index 7d092e9e..76fe0add 100644 --- a/backend/fl-platform-api/requirements.txt +++ b/backend/fl-platform-api/requirements.txt @@ -1,6 +1,6 @@ accelerate==1.10.0 aiohappyeyeballs==2.6.1 -aiohttp==3.12.15 +aiohttp>=3.14.0,<4.0 # SE-22: CVE-2026-34993/47265 (RCE) + DoS/smuggling fixes (was 3.12.15) aiohttp-cors==0.8.1 aiosignal==1.4.0 annotated-types==0.7.0 @@ -13,7 +13,7 @@ click==8.1.8 colorama==0.4.6 colorful==0.5.7 contourpy==1.3.3 -cryptography==44.0.3 +cryptography==44.0.3 # SE-22: the framework floor is >=46.0.6, but this lockfile uses flwr-datasets (FederatedDataset in fl_server.py/client.py) -> flwr 1.20.0, which pins cryptography<45.0.0. The 46.x floor is therefore UNREACHABLE here until flwr-datasets is dropped/updated; 44.0.3 is the newest flwr-compatible pin. Tracked as the SE-22 residual. cycler==0.12.1 datasets==3.1.0 dill==0.3.8 @@ -58,7 +58,7 @@ opentelemetry-semantic-conventions==0.57b0 packaging==25.0 pandas==2.3.1 pathspec==0.12.1 -pillow==11.0.0 +pillow>=12.2.0,<13.0 # SE-22: PYSEC-2026-165 + CVE-2026-40192/42309/42310/42311 (was 11.0.0) platformdirs==4.3.8 prometheus_client==0.22.1 propcache==0.3.2 @@ -82,7 +82,7 @@ PyYAML==6.0.2 ray==2.48.0 referencing==0.36.2 regex==2025.7.34 -requests==2.32.4 +requests>=2.33.0,<3.0 # SE-22: CVE-2026-25645 (was 2.32.4) rich==13.9.4 rpds-py==0.27.0 rsa==4.9.1 diff --git a/backend/fl-platform-api/src/main/java/com/federated/fl_platform_api/bootstrap/StartupReconciler.java b/backend/fl-platform-api/src/main/java/com/federated/fl_platform_api/bootstrap/StartupReconciler.java index a91e70d3..97233195 100644 --- a/backend/fl-platform-api/src/main/java/com/federated/fl_platform_api/bootstrap/StartupReconciler.java +++ b/backend/fl-platform-api/src/main/java/com/federated/fl_platform_api/bootstrap/StartupReconciler.java @@ -1,6 +1,6 @@ package com.federated.fl_platform_api.bootstrap; -import com.federated.fl_platform_api.flower.FlowerServerManager; +import com.federated.fl_platform_api.orchestration.FlServerManager; import com.federated.fl_platform_api.model.Run; import com.federated.fl_platform_api.model.RunStatus; import com.federated.fl_platform_api.repository.ProjectRepository; @@ -23,11 +23,11 @@ /** * BA-3: reconciles FL-server processes against persisted run state on backend startup. * - *

FL servers are spawned as child OS processes and tracked only in {@link FlowerServerManager}'s + *

FL servers are spawned as child OS processes and tracked only in {@link FlServerManager}'s * in-memory map, so a backend crash orphans them: children keep running (holding gRPC ports) while * their runs sit forever in a non-terminal state with no handle to stop them. On boot this loads every * still-in-flight run and, using the PID + OS start-instant recorded at spawn (see - * {@link FlowerServerManager#recordProcessIdentity}): + * {@link FlServerManager#recordProcessIdentity}): *