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.
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.
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.
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
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.
* 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>