Commit Graph

6 Commits

Author SHA1 Message Date
Alpamys 9300ee3412 feat(governance,sign): v0.71.2 — ed25519 signing + supply-chain gates
ed25519 signing (#179/#185 ed25519 half): new utils/signing.py + [sign]
extra. `soup adapters sign/verify --backend ed25519` (--key/--generate-key/
--public-key) and `soup attest emit --sign ed25519` + new `soup attest
verify`. Sigstore keyless stays infra-blocked (OIDC/Fulcio/Rekor network).

#186 namespace-pin gate wired into download_repo (anti-AI-Jacking; fail-open)
#187 adapters merge auto-detects each adapter's license
#190 license-override reason recorded to the audit log
#191 NamespacePinStore WAL + busy_timeout + cross-process lock
#192 merge refuses scan-FAIL inputs unless --allow-unscanned

+106 tests (12153 -> 12259); full suite 79.07% cov. cryptography added to
[dev] for CI. 5 review waves, all findings fixed.
2026-06-01 17:17:44 +05:00
Alpamys 76f033a6ff feat(v0.53.10): Quick wins + packaging + UX wiring
7 issues closed:
- #150 [mix] pyproject extra bundles scikit-optimize so `soup data mix
  --optimize` runs the Bayesian loop instead of the v0.48.0 Dirichlet
  fallback; new describe_default_optimizer() helper labels the active
  backend without paying skopt's import cost.
- #113 [data-pro] extras (langdetect + presidio-analyzer) with lazy
  fall-through helpers in utils/data_score (broader language coverage +
  Presidio entity recognition on top of the v0.47.0 regex baseline).
  Llama-Guard-3-1B documented as a manual recipe (license + size).
- #154 SOUP_POSTHOG_KEY / SOUP_POSTHOG_ENDPOINT env override via
  sentinel-based explicit-vs-env precedence; HTTPS-only +
  RFC1918/link-local rejection on the endpoint; null-byte / control-char
  / >256-char rejection on the key.
- #152 --hub flag plumbed on chat / serve / infer / merge / export /
  push via shared utils/hubs.apply_hub_to_cli_model +
  prefetch_model_from_hub helpers; push uses upload_repo (skips
  HF-specific Collections + model-card auto-render on non-HF hubs).
- #153 `soup data download --hub modelscope|modelers` live SDK
  (lifts the v0.53.8 advisory-only path); friendly ImportError
  advisory when the SDK is missing.
- #155 Web UI Tool Outputs panel — `loadToolOutputs` polls
  /api/tool-outputs every 3s; XSS-safe DOM-built table (textContent
  per cell, no innerHTML for user-controlled fields); Bearer token
  threaded via the v0.53.9 window._authToken bootstrap.
- #156 SoupTrainerCallback.on_step_end records tool_calls counts
  from kwargs['inputs'] into the global tool buffer. Best-effort
  (# noqa: BLE001 per project policy — training must never crash).

13 review-fixes applied (4 HIGH / 5 MEDIUM / 4 LOW):
- HIGH PostHog explicit-endpoint precedence sentinel
- HIGH absolute path leak in local_path advisory reduced to relpath
- HIGH Rich markup escape on base / local_path / cache_dir
- HIGH callback # noqa: BLE001 per project policy
- MED `import time` moved out of try block
- MED oversize key + explicit-empty key rejection tests
- MED source-grep regression guards (advisory-removal, helper imports
  across 5 non-push commands)
- MED `prefetch_model_from_hub` outside-cwd cache_root rejection
- LOW empty-list + bool-True tool_calls no-op tests
- LOW push.py uses upload_repo + validate_hub_name regression guard

Test count: 8285 -> 8330 (+45 in tests/test_v05310.py).
Full suite green; ruff clean; on Win+Py3.10.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 13:58:20 +05:00
Alpamys bde9d149a0 feat(v0.53.9): Live Dashboard + UX + Bench + Standalone CLIs
Eight features that close out the v0.44.x live-monitoring deferrals
plus a long tail of standalone CLI wins:

- #94  /api/train/stream async SSE with per-subscriber cursor + JS
       EventSource consumer; SoupTrainerCallback pushes TrainEvent on
       each on_log.
- #95  soup ui --public derives LAN IP via SOCK_DGRAM connect-trick,
       prints scannable QR; --auth-token override; SPA bootstrap
       hydrates window._authToken from ?token= + sessionStorage and
       cleans the URL via history.replaceState; CORS regex auto-widens
       to loopback + RFC1918 in public mode; set_auth_token rotation
       race fixed via threading.Lock.
- #98  soup serve --reasoning-parser strips <think>...</think> (and
       OpenThinker tags); pre-compiled regex with marker-token
       fast-path + 1 MiB cap + leading-newline-only strip.
- #100 ToolOutputsBuffer global singleton + /api/tool-outputs JSON
       endpoint; best-effort observation hook in callback.on_log.
- #15  soup tokenizer train: BPE training CLI with raw-path lstat
       symlink rejection, 50 MiB total / 8 KiB per-line caps,
       post-mkdir output-dir re-check, --special-token NUL/oversize
       dedup, vocab bounds [256, 200000].
- #26  soup bench --p50 --p95 renders extra per-prompt tail-latency
       Rich table; --prompts-file gains symlink rejection.
- #28  soup bench --backend auto: MLX weights.npz probe (per-entry
       lstat) -> config.json model_type keyword -> transformers
       fallback; SOUP_BENCH_BACKEND env hint.
- #12  examples/synthetic_workflow.{md,yaml} end-to-end walkthrough.

Review fixes: 0 CRITICAL + 11 HIGH + 14 MEDIUM + 9 LOW across the
python / code / security / tdd review agents. Notable HIGH:
- QR token now consumed by SPA (was unreachable previously).
- set_auth_token rotation lock-protected, 8-thread stress tested.
- Tokenizer input + output symlink TOCTOU defence on raw path.
- SSE generator switched to async (asyncio.sleep) for non-blocking
  multi-subscriber operation.
- CORS regex for --public LAN mode (the old fixed allowlist of
  http://0.0.0.0:port never matched a real Origin header).
- _has_mlx_weights per-entry lstat so a symlinked weights.npz can't
  trigger MLX dispatch.

Test count: 8257 -> 8285 (+57 in tests/test_v0539.py, minus the
relaxed v0.53.8 version-pin asserts in tests/test_v0538.py).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 04:28:19 +05:00
Alpamys 53bb82afeb fix(v0.53.8.1): hatch artifacts directive — fix PyPI duplicate-filename 400
v0.53.8 PyPI publish failed with:
  400 Invalid distribution file. ZIP archive not accepted:
  Duplicate filename in local headers

Root cause: `[tool.hatch.build.targets.wheel.force-include]` shipped
`soup_cli/data/_fixtures/` AND `packages = ["soup_cli"]` recursed into
the same path, so both the wheel and sdist contained each JSONL twice.

Fix: switch from force-include to `artifacts = [...]` which adds
non-Python files to the existing package tree exactly once. Standard
hatchling pattern for shipping data files inside an already-packaged
directory.

Version bumped to v0.53.8.1 (patch) — same code surface, just a build
config fix. v0.53.8 GitHub release remains as the feature changelog;
PyPI ships under v0.53.8.1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 00:18:20 +05:00
Alpamys 7b98982ab6 fix(test): v0.53.8 CI hardening — strip ANSI + use _repo_root() helper
Five v0.53.8 CI failures (ubuntu/macos × py3.9/3.11/3.12):

1. test_help_lists_hub_flag — Typer's Rich-rendered help wraps long
   option help across ANSI box-drawing lines; "--hub" appears as
   "│ --\nhub" in the CI terminal renderer. Strip ANSI + collapse
   whitespace before asserting.

2-5. test_pyproject_version / test_*_extra_present / test_force_include
   — used `Path("pyproject.toml")` (relative to cwd). CI invokes pytest
   from a different cwd than the repo root on at least one matrix
   entry. Switched to a `_repo_root()` helper that derives from
   `__file__` (matches v0.43.0 Part D demo_bundles approach).

Local re-run: 66/66 v0.53.8 tests pass after the fix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 00:04:29 +05:00
Alpamys 6d2170c4f3 feat(v0.53.8): Remote data + Hubs + Trackers (wave 2) — 6 features
- #85 fsspec live loaders — data/loader.py routes the v0.42.0 fsspec
  scheme allowlist (s3:// / gs:// / gcs:// / az:// / abfs:// / abfss:// /
  oci://) through fsspec.open with validate_remote_uri containment
  BEFORE connection. Friendly Rich panel names the pip install
  advisory when the backend SDK is missing. Threads data.streaming
  + data.buffer_size. Row count capped at 1M.

- #130 Hub dispatcher live — utils/hubs.download_repo() and
  upload_repo() lazy-import per backend (huggingface_hub /
  modelscope / openmind_hub). Shared _validate_repo_id_shape (bool /
  null-byte / leading-slash / .. / control-char / oversize) + cwd
  containment on local_dir / folder_path. commands/train.py pre-fetches
  non-HF base into .soup_hub_cache/ (sanitised slug, idempotent on
  resume, cfg.base updated via model_copy). soup data download --hub
  flag plumbed. Multi-command rollout for chat / serve / infer / merge
  / export / push tracked for v0.53.9.

- #89 [trackers] pyproject extra bundles mlflow / swanlab / trackio;
  tracker_missing_dep_message surfaces a friendly pip install advisory
  via importlib.util.find_spec (non-executing probe).

- #90 utils/trackers.send_telemetry_payload — opt-IN via SOUP_TELEMETRY=1;
  lazy httpx; 1s hard timeout; HTTPS-only with SSRF re-validation
  (mirrors v0.51.0 hub endpoint policy); silent-fail on every exception.

- #93 Fixtures migrated to soup_cli/data/_fixtures/ — zipapp /
  namespace-package safe via [tool.hatch.build.targets.wheel.force-include];
  _bundle_source_path falls back to examples/data/ for editable installs.

- #69 utils/hf_space.detect_space_sdk(requirements_text) — picks
  "streamlit" / "gradio" from the rendered requirements.txt; closes
  the v0.40.2 known limitation that custom Spaces always defaulted to
  gradio. Wired into commands/deploy.py.

Review pass: python-review + code-review + security-review ran in
parallel; 16 findings fixed (3 HIGH + 8 MEDIUM + 5 LOW). Highlights:
cwd-containment on local_dir/folder_path, Windows ..\ traversal
defence on .soup_hub_cache slug, Pydantic model_copy(update=...)
instead of attribute mutation, idempotent pre-fetch via cache probe,
1M-row cap on remote materialisation, SSRF re-validation on
telemetry endpoint override, 256 KB cap on detect_space_sdk input,
modelscope.push_model commit_message kwarg removed (would TypeError
at runtime), find_spec instead of __import__ to avoid swanlab
side-effects.

Test count: 8162 -> 8257 (+66 in tests/test_v0538.py + 29 net adjustments).
Lint clean. CPU smoke: version, --help, load_config_from_string with
hub: modelscope passes; mlx + non-HF rejected; data download --hub
modelscope advisory rendered; detect_space_sdk live on real
requirements.txt bodies; package-data fixtures resolve from
soup_cli/data/_fixtures/.

v0.53.7 known limitation #1 (bash 501 marker) bumped to v0.53.9.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 23:55:23 +05:00