Repository navigation
HiMe v1.2.0
HiMe v1.2.0
Since v1.1.0 (e7067cb) — 25 commits, 113 files changed.
This release is dominated by a full-project audit (#36) that swept the backend,
frontend, iOS app and deployment config. Several of the findings were real
security holes or silent data loss, so upgrading is recommended.
Security
- Feishu webhook accepted tokenless event POSTs, allowing forged user
messages. Added the missing encrypted-event (AES-256-CBC) support, signature
freshness checks,event_iddedup, and a reconnect loop with link-loss
detection. - Feishu card actions bypassed the inbound allowlist. The
chat_idcame
from the attacker-controllable callback payload, so a crafted action could
exfiltrate a user's health-data SQL results to an arbitrary chat. - WebSocket routes were unauthenticated.
BearerAuthMiddlewaresubclasses
Starlette'sBaseHTTPMiddleware, which short-circuits every non-httpASGI
scope, so WS handshakes never hit it. Routes now validate the bearer token
themselves. - The API token was baked into the public JS bundle —
.dockerignoredid
not matchfrontend/.env.local. The frontend now resolves the token at
runtime, which also unbreaks the dashboard for Docker installs with auth on. - Port 8765 was unauthenticated in Docker: the watch service had no
env_file, soAPI_AUTH_TOKENnever reached it. - Path traversal in
create_page— the patch branch ran beforepage_id
validation. - Personalised pages now render in a genuine opaque-origin sandbox (
srcdoc+
validatedpostMessagebridge), so agent-generated HTML can no longer reach
the app origin, and no token appears in any URL. - The code tool now opens the health database in SQLite read-only URI mode,
matching the guarantee thesqltool already enforced. - iOS stores its token in the Keychain.
Data loss and correctness
- LLM retries were dead code.
openai_provider._call()returned the
completion coroutine without awaiting it, so the request happened outside
retry_async— backoff, fallback degradation and context-overflow
max_tokensreduction never ran. Same class of bug inanthropic_provider. - iOS background uploads deleted unsent records. Success was inferred from
error == nilwithout checking HTTP status, popping the pending queue on
401/403/400; a foreground WS flush could also double-pop against an in-flight
HTTP task. - Sub-analysis loops appended assistant messages carrying
tool_callsthey then
skipped, leaving orphantool_useids that 400'd on the next turn. watch_db_readerread a naive local clock as UTC, so east of UTC the query
window landed in the future and returned nothing.- Decibels, METs and the 6-minute walk test were aggregated with
SUM. - Timezone handling fixed in
page_helpers,data_store_reader, and frontend
date parsing/formatting. hime.sh stopused a barepkill -f uvicorn|vite|multiprocessing, killing
unrelated processes on the same machine.- Telegram:
allowed_updatesencoding, HTML truncation on tag boundaries, and
offset/cursor persistence so restarts stop replaying messages. - Large tracebacks in a failed code run could blow the context window — the
result truncator now caps theerrorfield, not justoutput. - Reports now state honestly when data is missing for the requested period
instead of inventing or recycling numbers from a previous report.
Fixes and improvements
- Agent-sent charts now persist and replay on reload. They were delivered
only as a livechat_imageWS event, so they vanished if the app was offline
and never came back. Images are copied to durable per-user storage (90-day
reap) and baked into the persisted transcript as a markdown image line. - iOS: the dashboard's segmented control overflowed its page bounds at
accessibility text sizes, getting clipped and colliding with the page dots. - iOS: the onboarding survey could be submitted twice —
flushPendingSurvey()
is called from four places with no single-flight guard. - Frontend: the memory / knowledge base page broke on tables with no rows.
- Blocking I/O moved off the event loop, rate-limit buckets split per endpoint,
WS disconnect detection in the streaming service, plus several resource leaks
and retain cycles. - Widget unit conversions, and nginx / entrypoint / CI fixes.
Build and dependencies
pyproject.tomlnow reads its dependencies fromrequirements.txt.
Dependabot's pip updater is registered on/backendonly, so the two lists
desynced on every dependency PR.- Bumps: react-router-dom 6.30 → 7.14, anthropic ≥ 0.97, pyyaml ≥ 6.0.3,
qrcode ≥ 8.2, actions/checkout 4 → 7. Dropped the unused pyarrow dependency. - iOS version numbers are now declared once in a shared xcconfig and inherited
by all four targets, instead of being duplicated across eight build
configurations where they had already drifted apart.
Testing
Backend tests 348 → 441, frontend 61 → 75, ESLint 25 errors → 0.
Also
The HiMe paper is now on arXiv — see the badge in the README.