-
Timmy review release 2026-10-30-1bbcc10a356f
Pre-ReleaseQuality gates / quality (push) Canceled after 0sreleased this
2026-10-30 12:38:15 +00:00 | 13 commits to main since this releasePrerelease for review — tag
daily-2026-10-30on commit1bbcc10a356f62d3ab2118081874cbb8ab5e7ea6(America/New_York release date 2026-10-30, built 2026-10-30T12:36Z).What changed
The release candidate is now attacked before anyone is asked to trust it (issue #40, PR #91). Timmy could describe what it does; nothing drove hostile input at the real boundary and recorded what happened. This release adds an executable abuse suite and the rule that turns its observations into a release decision.
scripts/security_attack_suite.mjsstarts the realserver.mjson a free loopback port, points it at a counting stub worker, and drives it with synthetic hostile bytes. Nine cases: oversized body, HTML polyglot dressed asimage/jpeg, undecodable bytes, request without consent, worker answer that breaks the schema, byte-identical replay, concurrent burst, captured-log scan, and deletion (out of surface — counted only whiletests/training-contribution.test.jsexists). It writes a JSON report, prints the verdict, and exits1when blocked.src/release-security-gate.jsowns the verdict so it is testable instead of asserted: nearest-rank percentiles, per-case pass/fail derived from the recorded observation (a partial match fails and names the broken field), and — any failing P0 case blocks RC approval; a required class with no verified evidence blocks it too. A report that still holds image bytes refuses to be written.docs/RC-SECURITY-EVIDENCE.mdstates the procedure, the rule, and the current finding plainly, rather than storing an "all clear" that goes stale on the next commit.- CI regenerates the same evidence on every change (
npm run test:security-attack). - Demo — a
SECURITY ATTACK SUITEcard drawn from a real run of the suite against the real server, printing the verdict it derived instead of a flattering one.
What this run actually found — the headline is a block, not a pass:
VERDICT: BLOCKED · 2 blocking · 1 heldingress-polyglot-htmlP0 fail — an HTML file dressed as a JPEG returns503and reaches the worker (worker 1); the expectation is400with the worker never called.ingress-garbage-bytesP0 fail — undecodable bytes reach the worker the same way.flood-concurrencyP1 held — the concurrent burst is not refused (refused false, 12 worker calls).- Passing as expected: oversized body (
413, worker never called), missing consent (400, worker never called), malformed worker answer (503, provider text not leaked), byte-identical replay, and the captured-log scan (image bytes false). - Load phase: 8 requests, p50 15 ms, p95 19 ms against the stub on loopback.
Bytes are still trusted from the data-URL label, so a hostile file gets through and only fails afterwards on schema. That is a finding against #16 (image ingress hardening, open as PR #82 and PR #63), not a claim that the boundary is now safe.
Scope note, stated plainly: the suite is a command line, not a screen in the app, and the card is a CLI card — this release does not imply UI. It also does not yet run as a gate inside
scripts/build_release.py: the verdict is evidence the release job must read, and it currently reads BLOCKED. Wiring it into the mandatory gate list belongs with #16 landing, not with publishing this harness.Not closed by this release. PR #91 deliberately does not close #40: the ticket's acceptance criteria are "P0 findings block RC approval" (delivered — the gate decides) together with a boundary that survives attack (not delivered — the two ingress holds above). The suite is honest that it is blocked.
Completed ticket / PR
- Issue #40 — Execute security, abuse, load, and medical-image leakage tests (open; suite and blocking rule delivered, ingress holds tracked in #16).
- PR #91
Execute security, abuse, load, and image-leakage tests against the RC (#40)— merged as0bf8230after diff review: 12 files, +782/−3, text and code only (no binaries, model weights, real medical imagery, or secrets; the only data-URI in the diff is the suite's own synthetic 1×1 JPEG used as hostile input), linked to a non-human-gate issue (labelsarea/privacy,area/release,priority/P0,type/security— nohuman-gatelabel). - Follow-up commit
1bbcc10— the first gated build's card renderedhttp undefined · worker 12on the flood case and repeated the bare status on the malformed case; the card now prints only the fields each case recorded (refused false,text leaked false), with a test that fails if the old formatter returns. The unpublished build of0bf8230was discarded and the whole gated build was re-run end to end from1bbcc10. - Pre-merge verification on the PR head
f0a9a73:npm test244/244,test:security-attack8/8 — green before the merge was issued.
Gates — 28/28 passed
npm test244/244; security-attack acceptance 8/8; corpus manifest 8/8; corpus review 21/21; dataset card 14/14; calibration harness 19/19; backup-restore 11/11; production-runbook 9/9; mobile green path; photo-first acceptance; sleek Hermes chat; manual fallback + draft recovery; provisional suggestion state; hard-stool follow-up; vision corpus refusal; abstention quality gate; worker container receipts; worker post-load readiness; longitudinal pattern summary; grounded chat citations; training contribution consent; production backup restore; production runbook commands; portable backup restore; dependency audit (0 high); syntax (node/bash/python); secret scan; forbidden artifacts; demo H.264 720×1280 probe; complete MP4 decode; release delta verified painted on camera (95/95 captions, delta caption 6 lines / padBottom 15 px).Artifacts
- source archive
timmy-talking-turd-2026-10-30-1bbcc10a356f.tar.gz— 357,094 bytes — sha25604552e814171e1da6fe5101369dca5189db334d2fe2ed4de72d368209c240d29 - demo video
timmy-talking-turd-2026-10-30-1bbcc10a356f-demo.mp4— 26,654,756 bytes — H.264 720×1280 yuv420p, 25 fps, 432.16 s — sha256aa6383c3632aa699a46eb42f5381df03aa06bcfe198a9ea4fab32597c277e1cb
Model / profile
Built and recorded by Hermes (profile
default, modeldeepseek-flash). The demo runs the real app from the built commit withTIMMY_VISION_ENABLED=false; vision replies replay the committed CC0 synthetic corpus through the app's real analysis path, and the app's configured vision profile remains self-hostedSmolVLM2-2.2B-Instruct(pinned GGUF) with the hosted profile as fallback. TheSECURITY ATTACK SUITEcard is a real suite run against a realserver.mjs— but the worker behind that server is a counting stub, so the card proves what the HTTP boundary did and whether the model boundary was reached. It measures no model quality. No live model inference appears in the video, no real photo is used anywhere, and every upload shown is synthetic hostile bytes.Demonstrated on camera
SECURITY ATTACK SUITE— subtitlecommand line, not app UI — real server, counted worker callsCOMMAND node scripts/security_attack_suite.mjsTARGET real server · counting stub worker · synthetic bytesOVERSIZED P0 pass · http 413 · worker 0— refused before any provider workPOLYGLOT P0 fail · http 503 · worker 1— the hostile file reached the workerTRUNCATED P0 fail · http 503 · worker 1CONSENT P0 pass · http 400 · worker 0MALFORMED P0 pass · http 503 · text leaked falseREPLAY P2 pass · http 200 · worker 1 · identical trueFLOOD P1 fail · refused false · worker 12LOG P0 pass · image bytes falseDELETION P0 covered-elsewhereLOAD 8 req · p50 15ms · p95 19ms · abstain 8VERDICT BLOCKED · 2 blocking · 1 held, withBLOCKS ingress-polyglot-htmlandBLOCKS ingress-garbage-bytes
Known accuracy limitation
The release candidate is not proven safe by this release. The suite's own verdict is
BLOCKEDon two P0 ingress holds, and the fix is in review at #16 (PR #82 / PR #63), not shipped here. Separately and unchanged: open-weight VLM acceptance is proven, Bristol accuracy is not clinically validated; the calibration receipt still reportsBLOCKEDbecause no candidate model clears every gate. User confirmation remains mandatory everywhere: photo analysis may suggest visible Bristol form, broad color, and image quality only, and never symptoms or a diagnosis. Visible color is not blood.Downloads