10 Commits
Author SHA1 Message Date
JerryTseng f736c106a3 feat(tools): read-only Taiwan stock snapshot tool (#848)
Adds a read-only agent tool over a published Taiwan-market SQLite
snapshot (stdlib + sqlite3 only, mode=ro&immutable=1, no network).

Maintainer repairs on top of the contribution:

- Bulk responses are now budgeted to 9,500 serialized characters so they
  survive the agent loop's 10,000-char tool-result cut as valid JSON. At
  the documented maximum (200 rows x 50 stocks) the response was 5.4 MB
  and the prefix cut produced a JSON parse error. Rows are retained
  newest-first, round-robin across stocks, so the newest bar of every
  stock survives trimming; responses carry total_rows, returned_rows,
  truncated and a narrowing hint. The budget covers history, universe,
  latest and lookup — the size overflow was not limited to history.
- Indicators are no longer mis-dated. The tool picked the newest price
  row and the newest feature row independently but reported a single
  date, so 07-23 indicators were served under date=07-24. latest and
  universe now return price_date, feature_date and a stale_features
  flag.
- The Compose snapshot mount no longer defaults inside the checkout
  (./data/tw-stock was also un-gitignored). The default host path is
  now ${HOME}/.vibe-trading/tw-stock, overridable via
  VIBE_TW_STOCK_DATA_DIR; no market data can land in the working tree.
- The snapshot schema (4 tables, 37 columns) is validated on open, so an
  unrelated or stale SQLite file reports an actionable error instead of
  registering successfully and failing mid-query.
- Fixed a connection leak: sqlite3's connection context manager commits
  but never closes, leaking a handle per call.

The contributor's unrelated requirements-lock.txt rewrite (21 stale pin
changes, including FastAPI and OpenAI downgrades) was dropped; the tool
needs no dependency change.
2026-07-30 13:15:16 +08:00
Haozhe Wu 1e5b79dac6 chore(frontend): move to Node 22 and React Router 8
React Router 7.12.0 through 8.2.x carry a high-severity RSC-mode CSRF bypass
(GHSA-qwww-vcr4-c8h2). We were on 7.18.1, inside that range. The advisory is not
reachable here — the app is a client-side SPA on createBrowserRouter with no
@react-router/server and no RSC entry point, and the frontend ships as static
Vite output — but 7.18.1 is the final 7.x release, no backport exists, and 8.3.0
is the only patched version, so staying put means staying on an EOL line with a
permanent open alert.

react-router-dom has no 8.x at all; the DOM exports moved into react-router
itself. So the dependency is swapped and every import rewritten. All ten APIs in
use here are unchanged in 8.3.0, and none of the data-layer surface that changed
most between majors is used.

react-router 8 requires Node >=22.22.0, which is the same wall that had jsdom 30
and @testing-library/jest-dom 7 sitting in the Dependabot ignore list. Node 20
reached EOL on 2026-04-30, so the toolchain moves to Node 22 across CI, the wiki
workflow, the Dockerfile and docker-compose. That unblocks all three at once:
jsdom and jest-dom are taken here too, and their ignores are removed rather than
left carrying a rationale that no longer holds.

Verified on the frontend suite: tsc -b and vite build clean, 310 tests across 35
files pass before and after the jsdom/jest-dom bumps.
2026-07-28 14:39:59 +08:00
Haozhe Wu 4e3c91c77a security: address all 10 findings from external audit (issue #476)
Implements VT-001 through VT-010 from the 2026-07-10 external security
audit (Trivy/Semgrep/ZAP/Gitleaks/pip-audit against a real deployment):

- VT-001 (Critical): AST hardening in backtest/runner.py rejects
  network/subprocess/eval/os.environ/unsafe-open calls reachable from
  generated SignalEngine method bodies (previously only checked
  top-level statements). Defense-in-depth: ephemeral per-run HOME,
  RLIMIT_AS/NOFILE caps, best-effort UID-drop to a new vibe-sandbox
  user (currently inert under Docker's cap model - see session doc;
  accepted as documented residual gap, primary AST defense unaffected).
- VT-002: multi-stage Dockerfile split so build-essential never
  reaches the runtime image.
- VT-003: SSE auth moved from a long-lived API key in the URL query
  string to short-lived single-use tickets; access-log redaction for
  any remaining query secrets.
- VT-004: agent/.env split-brain fixed (bind mount + atomic 0600
  writes) between docker-compose and Web UI settings writes.
- VT-005: /correlation now requires auth + per-IP rate limit; generic
  exceptions no longer leak raw text to clients.
- VT-006: CSP-Report-Only + security headers middleware; Google Fonts
  replaced with self-hosted @fontsource packages.
- VT-007: docker-compose hardening (cap_drop ALL + minimal cap_add,
  no-new-privileges, read_only rootfs, resource limits).
- VT-008: /health split into /live (liveness) and /ready (real
  provider-config readiness check); /health kept as a compat alias.
- VT-009: base images pinned by digest, GitHub Actions pinned by
  commit SHA, dependabot.yml added, hash-verified requirements-lock.txt
  now actually wired into the Docker build via --require-hashes.
- VT-010: universe-panel pickle cache sidecar upgraded from an
  unkeyed SHA-256 (forgeable by anyone with cache-dir write access)
  to a keyed HMAC.

Implemented via a 5-parcel Workflow (file-disjoint, independent
adversarial verification per parcel, then a holistic final audit).
The final audit caught a real regression (CI env-var-gate violation)
and confirmed a dependency-pinning gap, both fixed and re-verified
here, including a latent transitive-dependency bug the fix surfaced
(smartmoneyconcepts<0.0.27 pulls an unbuildable zigzag package) - see
docs/sessions/2026-07-13_session_vt476_security_hardening.md (local,
gitignored) for full evidence trail.

Full suite: 5191 passed, 6 pre-existing/environmental failures
(unchanged from main). Docker build + hardened compose boot verified
end-to-end.
2026-07-13 01:40:53 +08:00
shadowinlife 2b9647a5be fix(docker): bind frontend dev port to loopback for consistency with backend
The frontend dev service published port 5899 on all interfaces
(0.0.0.0) while the backend was correctly bound to 127.0.0.1:8899.
On a shared/LAN network, this exposed the Vite dev server (source,
module graph, HMR websocket) to other hosts unnecessarily.

Add the 127.0.0.1 prefix to the frontend port mapping so both
services share the same loopback-only exposure discipline.

Closes #334

Co-Authored-By: OpenCode <noreply@opencode.ai>
AI-Model: qwen3.7-max
Co-Authored-By: opencode <noreply@ai-tool.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
AI-Contributed/Feature: 2/2
AI-Contributed/UT: 0/0
2026-06-30 17:05:15 +08:00
Haozhe Wu 2ba6ae2f0c fix(docker): persist user agent state across container rebuilds
All user-level agent state lives under ~/.vibe-trading in the container
(persistent memory, sessions.db search index, user-created skills,
shadow accounts, hypothesis registry, broker connector config), but
docker-compose only mounted volumes for web sessions and backtest runs.
Every `docker compose up --build` therefore recreated the container and
silently wiped the user's memory store (#197). Swarm run history and
uploads were lost the same way.

- Mount vibe-home -> /home/vibe/.vibe-trading, plus vibe-swarm-runs and
  vibe-uploads.
- Pre-create /home/vibe/.vibe-trading owned by the service user in the
  Dockerfile so the named volume inherits writable permissions (a named
  volume mounted onto a missing path is created root-owned and the
  non-root user cannot write).
- README: document what persists across updates.

Verified end-to-end: memory written via PersistentMemory in one
container is intact in a fresh container on the same volume; the
counterfactual run without the volume reproduces the wipe.

Fixes #197.
2026-06-11 13:17:04 +08:00
b6fd9b1fd4 fix(docker): reach host Ollama via host.docker.internal (#196)
* fix(docker): reach host Ollama via host.docker.internal

Inside the container, OLLAMA_BASE_URL=http://localhost:11434 resolves to
the container itself, so the agent's preflight check and AgentLoop fail
with "Connection refused" even when Ollama is running on the host.

Override OLLAMA_BASE_URL to http://host.docker.internal:11434 in the
compose service (leaving agent/.env correct for bare-metal runs) and add
an extra_hosts host-gateway mapping so the same file also works on Linux.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(docker): parameterize OLLAMA_BASE_URL and document host networking

Address PR review feedback:
- Make OLLAMA_BASE_URL overridable via Compose variable substitution
  (${OLLAMA_BASE_URL:-http://host.docker.internal:11434}) so it can be
  changed without editing the compose file when Ollama runs elsewhere.
- Note the Docker Engine >= 20.10 / Compose v2 requirement for the
  host-gateway mapping, both inline and in the README Docker section.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Shah Newaz Khan <shah.khan@lexful.ai>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 12:55:48 +08:00
Haozhe Wu 9454d4a27a Harden API and tool security defaults 2026-05-03 22:42:20 +08:00
Matheus Nunes Dantas de Sena 1a40e53bdd feat: add docker-compose profile for frontend-only dev (#18)
* feat: add docker-compose profile for frontend-only dev

* fix: improve networking and use explicit service dependency
2026-04-11 00:19:17 +08:00
warren618 b0f59bd7f4 fix: Docker build + MCP/PyPI/ClawHub sync (v0.1.4)
- Fix #8: remove COPY data/ data/ from Dockerfile (dir doesn't exist)
- Add akshare/ccxt to requirements.txt and pyproject.toml dependencies
- Remove non-existent run_agent from py-modules
- MCP: rewrite _get_loader to use registry with fallback, add web_search tool (16→17)
- MCP: update docstrings (56→68 skills, add akshare/ccxt source docs)
- ClawHub SKILL.md: 64→68 skills, 3→5 sources, 16→17 tools, add version field
- docker-compose: remove dead fin-data volume, rename fin-→vibe- prefix
- .dockerignore: expand exclusions (tests, docs, assets, build artifacts)
- README: merge 4/10 news, update MCP 16→17, fix contributing (remove done items)
- Bump version 0.1.3→0.1.4, published to PyPI and ClawHub
2026-04-10 22:11:07 +08:00
warren618 34eae37ba4 Initial commit 2026-04-01 18:14:49 +08:00