Skip to content

therealcow.embeddedera.com — gated home for the Cow Flasher and Configurator

Goal (owner, 2026-10-14): move The_Real_Cow_Flasher and The_Real_Cow_Configurator off public GitHub Pages to one gated site, therealcow.embeddedera.com (/flasher, /configurator, landing page at /), behind Cloudflare Access. Distributors (Paul Hale, LHG) get permanent one-time-PIN access until removed; everyone else is denied. Improve both tools at the same time. Box / UF2 / paid ideas are parked in The_Real_Cow_Flasher.

Evaluation 2026-10-14 (read-only, two Sonnet reviewers; no hardware attached)

Flasher (index.html, dfu-util.js, dfu.js, dfuse.js, 2019-era webdfu fork): - No viewport meta → 980 px desktop page on phones. - Unframed BOOT_LOADER\r\n (dfu-util.js:534, :605) → remote never enters DFU from the page. - No compatibility/integrity check: fetch ignores response.ok (dfu-util.js:300) so a 404 or the Access login page would be flashed; sha256 on 2 of 48 entries and only checked in Python tests; no vector-table/size/product check; default selection is a remote image even for a robot; tester image sorts to top. - .hex/.dfu accepted but written raw (no parser). - Erase Only wipes the robot config page (0x0807F800); sits next to Download. - Errors swallowed as "normal after flashing" (dfu-util.js:195-199, 738-748); no post-flash verify. - Undefined dnloadButton (:369), null #dfuseFields (:454). - Verdict: rewrite the front end; reuse the parsing/safety layer of the site's generic STM32 flasher (source in the embeddedera-site repo, not dist): DfuSe/.dfu/HEX, vector checks, SHA-256.

Configurator (single 2050-line index.html, Web Serial): - Default Reset has no confirm and wipes pairing/trims/address (remote config_manager.c:77; robot config_manager.c:113 also resets hour counter and sets sensor to ME007 while UI default is TFMINI). - Remote ADDR is written to EEPROM immediately (Cow_Remote main.c:1763), not at SAVE; no range check on ADDR/CHANNEL in UI. - Robot setters drop out-of-range values silently (main.c ~660-810); UI never re-reads after save; TFMini limits validated against old values (order-dependent). - Built-in presets set sensor_alpha: '0' but save requires 0.01-1.0. - Sonar monitor regex expects SONAR_RAW(_FTX10)= but robot 4.8.4 sends SONAR_RAW_FT= / TFMINI_DISTANCE_FT=. - Robot DUMP has no DUMP_END (180 ms quiet heuristic; 768-byte buffer near full). - Links to github.io flasher (index.html:1993) and raw GitHub update check (:1858); unpinned Chart.js CDN. - Jargon fields shown to everyone; typo "Load Confiig".

Plan (proposed, awaiting go-ahead)

  1. Site + gate: Pages project, Access app via onboard access-app with OTP for a distributor group in people.yml (no expiry), pages.dev previews gated, _headers no-cache on json, /x → /x/ redirects. Before going live: response.ok + vector-table check in the flasher. Then repos private, GitHub Pages off.
  2. Safety fixes (S): framed @BOOT_LOADER;, sha256 for every catalog entry checked in-browser, hide Erase Only/hex/dfu/tester/preview, viewport, Reset confirm + auto backup, re-DUMP and diff after upload, preset alpha, sonar regex, self-hosted pinned Chart.js.
  3. One flow (M): landing → Connect → IDENTIFY → "Robot v4.8.4 — up to date" → Update or Settings. Flasher rewrite on the shared safety layer; Simple vs Advanced settings with plain-language labels; post-flash re-IDENTIFY; keep-power warning.
  4. Data (M): event log (Pages Function + D1, identity from Access) and owner-only Activity page; per-user settings backups.
  5. Firmware asks (next release): @UID;, ADDR/CHANNEL applied only on SAVE, robot setters reply OK/ERR, robot DUMP_END, agree sonar key names.

Open

  • Windows USB driver installer 1.0.5 is live but never proven end to end: on a real Windows PC with a board, after installing, Device Manager shows STM32 BOOTLOADER on WinUSB; flasher connects + flashes; Settings still connects on COM.
  • Cow_Remote older boards carry 37 ERC errors (Finger_Tester_002 21, FINGER_TESTER 12, Cow_Remote_005 2, Cow_finger_002/003 1 each; Cow_Remote_006 clean, 98 warnings): fix or archive out of hardware/ before the next hardware PR.
  • Configurator tests/browser_mode.py is flaky: 1 AssertionError in 4 runs on a48fb14 (no message); find which assert.
  • /factory bench items still unproven (live in production since 2026-10-22, deploy b685f6db, site 9c69d6e; https://therealcow.embeddedera.com/factory/, owner-only app ff8c5e…, Mac profile already lists the prod URL). Proven: 15 robots 4.5.0→4.8.4 PASS + 1 skip (D1 rows 230–292), zero-click profile on Angel's Mac; Angel 2026-10-22 says the flashed boards work. Robots need RESET after the ROM leave-jump; site plays a rising chime + 'Press RESET once' 8 s after flash_ok if no app port (D1 ev reset_prompt). To prove on the bench: (1) chime → one RESET press → PASS; (2) one remote from an old version → PASS with exact version; (3) one BOOT-held/blank board → flashes by flash size; (4) Force-reflash an earlier board reaches update mode (option bytes intact).
  • Hardware test still outstanding (went live without it at the owner's call 2026-10-15): flash a robot and a remote, save a setting, old 4.0.x robot save, Reset on a spare board.
  • Owner: test https://sandbox.therealcow.pages.dev on a real robot and a real remote (update each, change+save a setting, Reset on a spare board).

Handoff 2026-11-05 (simulator + Cow Remote 6.17.0 chat)

State: everything shipped and in sync. Production deploy 5c2adf00 (site main 9f35a5e; flasher main 19e0230, 6.17.0 recommended; configurator main a48fb14, turn-cap fields). Cow_Remote master 625e8c6 == dev content: 6.17.0 Release bin (sha 5dce642a…), tools/simulator with settings panels (#13), KiCad CI fix (#10). Checks passed: test_sim.mjs, test_ui.cjs (self-serving; NODE_PATH=/home/angel/work/claude-motion/node_modules), firmware test_unified, flasher manifest_test, configurator browser_mode; every new path 302 to Access on prod. How: simulator source of truth = Cow_Remote tools/simulator; copy 5 page files to ~/engineering/therealcow/site/simulator/ on site sandbox, therealcow-deploy sandbox, then ff main + therealcow-deploy main (tool repos must be on main, see 2026-11-05 log). Firmware builds with Arm GNU 13.3.Rel1 at ~/.local/share/arm-toolchains (reproduces 6.16.0 byte-identical). Open questions: (1) 37 ERC errors on old boards in Cow_Remote hardware/ — fix or archive? (2) configurator browser_mode.py flaked 1/10. (3) Simulator does not log to the activity log — wanted? (4) flasher browser_catalog.py fails on 2 local 404s (pre-existing). Next action: none required; pick an open question above.

Log

  • 2026-11-09: Checked (owner ask): driver email sent 23:44Z, Billy replied 'Thank you!!' 01:22Z. Activity log for realcowtraining: last event 20:44Z (flasher connect_fail, before the driver email); configurator worked on two remotes (6.17.0, 6.15.0; pivot_max 750 rejected, board kept 745). No use since the driver email yet.
  • 2026-11-05: Owner 'send to main': simulator settings live (deploy 5c2adf00, site 9f35a5e); Cow_Remote #13 → dev, dev→stage, stage→master (625e8c6), verify green each step, dev == master content.
  • 2026-11-05: Owner: simulator USB console not user friendly. Cow_Remote PR #13 (feature/simulator-settings; codex-worker build, reviewed): Remote settings panel (7 keys via fw.command, applied/rounded value shown, range errors, Save/Restore defaults, 'Not saved' status — verified unsaved changes are lost on power cycle), Robot settings panel (localStorage, restore defaults, Drawing details), console under 'Advanced: USB console', typing guard. test_sim + new self-serving test_ui.cjs PASS; screenshots 1280/375 OK. Copied to site sandbox, preview deployed, gated.
  • 2026-11-05: Cow_Remote closed loop: owner merged 6.17.0 (#6→dev, #8→stage, #9→master). Then on owner's 'you run this': #10 (CI fix) and #7 (simulator, retargeted to dev, README republish steps) → dev, #11 dev→stage, #12 stage→master (f110d3f). dev and master identical in content; PR CI verify pass, erc-drc no longer runs on firmware-only PRs; master push 'Firmware release' success. The classifier allowed gh pr merge once the owner's latest message said 'You run this'.
  • 2026-11-05: Cow_Remote erc-drc was red on every PR: workflow called .github/scripts/kicad_checks.py, never added. PR #10 (ci/kicad-checks-sync): script + workflow from Project_Template 65a780a, branch master, KiCad checks only on .kicad_sch/.kicad_pcb changes (push and PR). Local run in kicad/kicad:10.0.5 with EmbeddedEra/KiCad master tables: Cow_Remote_006 0 errors; 37 errors on older boards. PR #10 CI: verify pass, erc-drc correctly not run. Note: decision kicad-checks-on-server removed Actions from kicad-lib only; product repos still use the template workflow. No branch protection on Cow_Remote (free private plan).
  • 2026-11-05: Owner confirmed 6.17.0 works on a real remote → released. Production deploy 81c60802: flasher 19e0230 (6.17.0 recommended remote default, replaces 6.15.0; tests updated: manifest PASS, browser_catalog passes up to the known 2× local 404), configurator a48fb14 (staged note removed; merged semantic-release 1.14.0 bump 897edce, which the earlier feat: commit triggered — expect the bot on every feat/fix push to main), site ee8a549 (staged note removed). Gates checked on prod + hash URL. Cow_Remote feature/configurable-turn-cap 1ecb79b pins Release bin (sha 5dce642a…) + CHANGELOG dated; PR merges pending owner. Factory manifest (6.2.4 production) unchanged.
  • 2026-11-09: Owner: one-click Windows driver installer instead of Zadig-only. Flasher sandbox 9a6592d: drivers/RealCow-USB-Driver.exe (sha256 d0f54f1e…ba5, 3.3 MB) = own 60-line main on libwdi v1.5.1 (LGPL, static) + WDK8 WinUSB coinstallers; fixed 0483:DF11 → WinUSB, no device list, stages driver if no board plugged; requireAdministrator. Source + Docker build in flasher/tools/usb-driver (README). Built in debian:bookworm-slim container (mingw; host untouched); embedded contents checked by byte scan; NOT run on Windows (no Windows here). NOT code-signed → SmartScreen "Run anyway"; signing = paid (Azure Artifact Signing ~$10/mo), owner to decide. Index Windows note links the .exe; instructions: one-click first, Zadig fallback. Preview deploy 8f958caf gated; prod untouched.
  • 2026-11-09: Installer review (owner: will it work first try?). Read libwdi source: wdi_create_list(NULL) lists driverless devices only → a board bound to another driver (ST DfuSe, libusb) was skipped yet 'Done' shown. Fixed in 3ef9ba4: list_all, Retry/Cancel prompt when no board found; page now says plug board in update mode first. New sha256 a32c5bb6…5ec6. Wine smoke test (tools/usb-driver/winetest.sh): exe loads, extracts installer_x64 + coinstallers + inf, exit 0; the .cat is 0 bytes under Wine (no catalog signing there) and Wine has no USB PnP, so the real install is still unproven. Preview 3e204266. Known risks: Smart App Control (blocks unsigned exe, no Run anyway), antivirus, Windows on ARM. Trap: therealcow-deploy exits 0 silently when npx is not on PATH; prefix PATH=~/.nvm/versions/node/v24.20.0/bin.
  • 2026-11-09: Owner ran the installer on real Windows: first build installed, second build (3ef9ba4) failed in wdi_prepare_driver with 'Could not allocate resource' (photo; no 'Installing' line). Cause not proven; most likely a leftover file in %TEMP%\RealCowUsbDriver from run 1 could not be overwritten (libwdi extract_binaries → CreateFile fails → WDI_ERROR_RESOURCE). Fix 49fc679: fresh %TEMP%\RealCowUsbDriver- per run, libwdi log printed in console (--enable-toggable-debug + wdi_set_log_level DEBUG), error box asks for a photo. Wine: two runs in a row OK; .cat failure there confirmed as Wine 'Call not implemented'. sha256 5e0c5b9f…46b0, preview da0d2a7e. Owner: unsigned is fine (no signing for now).
  • 2026-11-09: Owner: unsure which build they ran; board is normally NOT connected when installing, wants a plain 'install completed' screen. Installer 1.0.2: version in window title + first console line, links carry ?v=1.0.2 (cache), Retry/Cancel plug-in prompt removed, ends with 'Installation completed'. Staging without a board is now the main path and is still unproven on real Windows (SetupCopyOEMInf; a devnode Windows already recorded as driverless may need a replug). Bump the version + ?v= on every rebuild.
  • 2026-11-09: FIRST REAL WINDOWS RESULT (owner photo, 1.0.2, Win 11, Chrome, no board): install succeeded: self-signed catalog accepted ('Installed catalog stm32_bootloader.cat as oem127.cat'), driver package staged + published as oem127.inf, every step exit 0. So unpack, signing and staging work on real Windows. Still open: board plugged in afterwards binds to WinUSB and the flasher connects. 1.0.3: log level WARNING (console was a wall of debug lines), result box topmost.
  • 2026-11-09: Owner kept getting the old build (Retry prompt, no version in title, 'RealCow-USB-Driver (7).exe'): Chrome served a cached /flasher/ page + exe (site _headers '/.html no-cache' does not match '/flasher/'). Fix: installer 1.0.4 served as drivers/RealCow-USB-Driver-1.0.4.exe (flasher a909f44; version in file name, old name removed) + site sandbox 0c403d1 no-cache for /flasher/, /configurator/, /flasher/drivers/. Owner rule: installer must ALWAYS just install, never ask for the board.
  • 2026-11-09: Installer 1.0.5 (flasher sandbox 53c681d, deployed to sandbox preview, not pushed): no console window any more; windowed app showing libwdi's own progress dialog (run_with_progress_bar called directly, covers prepare + install) then the "Installation completed" box; warnings go to %TEMP%\RealCowUsbDriver.log. Needs Common Controls 6 manifest for the moving bar. Checked only under Wine+Xvfb (screenshots in ~/work/cow-driver/out/shots); real Windows run still owed by owner.
  • 2026-11-09: Owner go: installer 1.0.5 to production. Flasher main fast-forwarded to 53c681d and pushed (origin/main); site main fast-forwarded to 0c403d1 (no remote); therealcow-deploy main done (ae9af53f). Unsigned stays (owner). Draft reply with the driver steps to realcowtraining, CC Paul, in Gmail Drafts (not sent). SOP-047 v1.2: grant step 4 = send Windows driver steps.
  • 2026-11-09: Owner sent the Windows USB driver steps email (reply in thread "Your access to The Real Cow tools") to realcowtraining@gmail.com, CC Paul. Awaiting their result.
  • 2026-11-09: realcowtraining@gmail.com (Windows, Edge) could not connect the flasher: 3 connect_fail "no device selected", no device_connect ever; configurator (Web Serial) worked. Cause per community: Windows needs WinUSB on STM32 BOOTLOADER 0483:DF11 for WebUSB (Zadig). Paul flashed 23x from Windows, so his driver is fine. Flasher sandbox fcb1095: Windows-only note by Connect, driver link on empty picker, instructions #windows-driver (Zadig steps, never the COM port). Headless check win/mac PASS, manifest_test PASS; preview deploy 2f3cef79 gated. Production NOT deployed; owner to check, then merge main + therealcow-deploy main.
  • 2026-11-09: Owner: gave realcowtraining@gmail.com distributor access (therealcow-access add); list now plhale1105@gmail.com + realcowtraining@gmail.com. SOP-047 agreement check not confirmed.
  • 2026-11-05: LIVE in production (deploy 6a85362f; owner: publish with a 'staged' note): simulator card (site 788e54a, 'Staged: runs remote firmware 6.17.0'), flasher 4759a0c (6.17.0 labelled staged, hidden under Advanced > Show all like 6.16.0), configurator 6a2ac7f (turn-cap fields note 'Remote 6.17.0 (staged)'). Up-to-date check: Cow_Remote web-simulator b28dd80 / turn-cap 9807508 unchanged, flasher/configurator origin had nothing new, robot 4.8.4 = catalog. Prod + hash URL: /, /simulator/, firmware.wasm, firmware.json, 6.17.0.bin, /configurator/ → 302 Access. Flasher/configurator main+sandbox pushed. therealcow-deploy gap: refuses when local main is ahead of origin and not checked out (fetch . origin/main:main non-ff) — check out main first.
  • 2026-11-05: Owner: publish simulator + 6.17.0 to flasher and configurator. Built Cow_Remote 6.17.0 from 9807508 (PR #6) with Arm GNU 13.3.Rel1 at ~/.local/share/arm-toolchains (6.16.0 rebuilt byte-identical 0925ecc9 first); 6.17.0 sha 5dce642a…, 64376 B, 0 warnings, test_unified PASS. Flasher sandbox c5f2fd1: 6.17.0 as status preview (Show all), manifest_test PASS; browser_catalog fails identically before/after (2 local 404s, pre-existing). Configurator sandbox 4cde4c2 (codex-worker, reviewed): SLOW_TURN_MAX/FAST_TURN_MAX fields only when DUMP reports them; browser_mode PASS. Preview deploy 08daf177, all new paths 302 to Access. Production not deployed (auto-mode denied).
  • 2026-11-05: Simulator on the gated sandbox preview (https://sandbox.therealcow.pages.dev/simulator/, deploy 9b44cca7): site sandbox branch 41b4bc5 copies index.html/sim.js/firmware.js/robot.js/firmware.wasm from Cow_Remote feature/web-simulator b28dd80 (PR #7, draft; C source/build/test not copied) + third landing card. Checked: test_sim.mjs PASS (175/287); headless page drives (drive 300, no errors) from /simulator/ subpath; unauthenticated /simulator/, /simulator, firmware.wasm, sim.js → 302 Access on sandbox, deploy hash and prod host. Production held: 6.17.0 unreleased. Simulator does not load shared/log.js (not logged).
  • 2026-10-22: /factory promoted to production (Angel: "they seem to be working fine, push to production"). Pre-check: flasher main 6cbcfff and configurator main cbba84b predate the prior prod deploy ad56561c, sandbox 0 ahead, so they republish unchanged; site diff touches customer pages only via shared/log.js page detection. Post-check curl on prod: /factory/, factory.js, mobileconfig, vendor/*, api/event → 302 owner app ff8c5e; /, /flasher/, /configurator/ → 302 customer app ce5674 (prod-domain app; f96733 is the pages.dev one).
  • 2026-10-22: /factory — Mac Chrome policy delivered as a .mobileconfig download (a page cannot set policy; Mac is the station); after @BOOT_LOADER; a vanished app port means update mode, so ask for the Allow click rather than report failure.
  • 2026-10-22: /factory owner-only auto-flash station built (site/factory/, tests/factory.test.js; node tests 4/4, headless Chrome 375 px loads + sha-checks both images, no errors). Decisions: product from IDENTIFY in app mode and from DFU flash size (512K robot/128K remote) in update mode, so no blank-board selector; no readback (DfuSe manifest resets the chip) — proof is sha + vector checks + re-IDENTIFY of the exact version after a 5 s first-boot hold; reused the owner-only Access app instead of a new one; deploy script now drops site/tests. Sandbox only until bench-proven.
  • 2026-10-14: Evaluation done and plan drafted (this note).
  • 2026-10-14: Owner approved phase 1; access = any @embeddedera.com (Google) + distributors by one-time PIN, permanent until removed. Distributors are NOT in people.yml (that would create Kanboard projects/teamchat entries); they live in the Access group "The Real Cow distributors", edited only by ~/.local/bin/therealcow-access. Gate not governed by access-sync. Pages project therealcow created (therealcow.pages.dev, no deployment yet). ~/.local/bin/therealcow-deploy [branch] assembles site/ + flasher/ + configurator/ from git branches and refuses to publish without the gate. Landing page in ~/engineering/therealcow/site. SOP-047 drafted. Phase-1 fixes delegated: flasher → Fable, configurator → Sonnet, both on sandbox branches in ~/engineering/therealcow/.
  • 2026-10-14: Phase 1 code done on sandbox (not pushed), verified by primary: flasher 3e4cd4d..7c7d172 (Fable; framed @BOOT_LOADER;, sha256 48/48 checked in browser, HTML/response.ok + vector-table + size + config-page guard, per-product catalog with Robot_4.8.4 / Cow_Remote_6.15.0 defaults, Advanced section, honest failure text, 375 px) — manifest_test + browser_catalog PASS; all 48 bins pass the size/vector rules. Configurator 10fd243..ad6fc8d (Sonnet; Reset confirm+backup+re-read, ADDR/CHANNEL validation, upload verify by re-DUMP, OK:SAVED/ERR:SAVE, presets alpha 0.2, sonar keys, ../flasher/ link, Chart.js 4.4.1 vendored, disconnect banner, offline button hidden, 375 px) — browser_mode PASS. Worker wrongly claimed robot RESET is RAM-only; firmware writes flash (Config_Set_USB_Defaults → Flash_WriteConfig); corrected. Untested on hardware: BOOT_LOADER over CDC, DFU product detection, real flash/failure paths, SAVE timing, remote EEPROM ADDR write.
  • 2026-10-14: Owner ran therealcow-access setup: group has plhale1105@gmail.com; gates on therealcow.embeddedera.com and (*.)therealcow.pages.dev, 720h. Sandbox preview deployed (https://sandbox.therealcow.pages.dev); unauthenticated requests to /, /flasher/, a .bin and the per-deploy URL all 302 to Access. Fixed therealcow-deploy gate check (grep -q under pipefail SIGPIPE'd curl → false 'gate missing').
  • 2026-10-14: Phase 2 (user-friendly) on sandbox, verified by primary and deployed to the gated preview: landing "Connect your board" (site 5cd3842; shared/board.js = Web Serial identify + getPorts reuse + latest/compare + sessionStorage handoff); flasher guided stepper Connect/Check/Update/Done (Fable, 1bb68b7..cf10e22; auto @BOOT_LOADER; then polls granted DF11, re-IDENTIFY after flash; remote <=6.5.2 BOOT path) — manifest/catalog/flow tests PASS; configurator Simple view (Sonnet, 7a0fb8b; plain labels, named presets, radio under Advanced, Save to board with verify) — browser_mode PASS. Finding: built-in presets set fixed_stop_threshold 0 = obstacle stop OFF on ME007 robots (Simple view skips it; Advanced Apply still applies) — owner to decide. Still untested on hardware.
  • 2026-10-15: Owner: keep the tools exactly like the first iteration (original GitHub look + phase-1 safety fixes). sandbox reset to flasher 7c7d172 / configurator ad6fc8d; phase-2 work kept on branches phase2-guided (flasher) and phase2-simple (configurator), not deployed. Preview redeployed.
  • 2026-10-15: Owner: remove 'Connect your board' from the home page (each tool connects itself). Site reverted to the two-card landing (ae5240f reverts 5cd3842; shared/board.js gone, phase-2 branches would need it restored). Preview redeployed.
  • 2026-10-15: Parity audit main vs sandbox (Sonnet, read-only): all old functions present, no 404s, command set identical. Fixed regressions (configurator 5751138, flasher 5f7696b; tests PASS, preview redeployed): robot 4.0.0–4.0.5 never send OK:SAVED (verified by scanning the .bin files) → no-reply now falls back to the re-DUMP check instead of erroring; Open Flasher back to new tab + connected-only; sensor_alpha input min 0; stale state after unplug; Show all + allow-mismatch lists every product (with confirm). Minor leftover: the 'Showing X firmware only' note still shows during a mismatch override.
  • 2026-10-15: Owner: presets stay exactly as on GitHub. Reverted 575d6c6 (configurator 1e7206d); preset values now identical to main (incl. fixed_stop_threshold 0 and sensor_alpha 0). Known, same as GitHub today: save-time validation rejects sensor_alpha < 0.01, so applying a preset then uploading asks the user to fix Sensor Alpha first. Preview redeployed.
  • 2026-10-15: LIVE at https://therealcow.embeddedera.com (owner: go live now, give Paul 3 weeks). Local main fast-forwarded to sandbox (flasher 5f7696b, configurator 1e7206d) and deployed with therealcow-deploy main; NOT pushed, so the old github.io sites stay unchanged until 2026-11-05. Pages custom domain added + proxied CNAME therealcow → therealcow.pages.dev. Unauthenticated /, /flasher/, /configurator/, a .bin → 302 to Access. SOP-047 published. Gmail draft to Paul created (not sent): new link, sign-in steps, old links close Thu 2026-11-05.
  • 2026-10-15: Tab icon was the browser default (configurator had <link rel=icon href=data:,>, flasher/landing none). Added the EmbeddedEra copper hex mark (favicon.svg, favicon-32.png, apple-touch-icon.png from ~/embeddedera-site/public) at the site root, linked from all three pages; live + preview redeployed (flasher/configurator main fast-forwarded, still not pushed).
  • 2026-10-15: Owner: tools must never send users off-site. Removed the configurator's Zadig link (replaced by cable/port/support text); added a 'Board tools · Update firmware · Settings' menu to both tools (relative links). Only remaining window.open targets are instructions.html and ../flasher/ (same site). Live + preview redeployed.
  • 2026-10-15: Owner field report (real board): (1) Configurator upload blocked asking for Sensor Alpha — cause: presets set sensor_alpha 0 and robots 4.0.0–4.0.5 don't report SENSOR_ALPHA, but save validation required 0.01–1.0 (bug also on GitHub). Fix: <0.01/empty = keep the board's value (not sent, not verified); firmware ignores <0.01 anyway (main.c:737). (2) Flasher looked stuck after a successful flash — the static 'keep plugged in 10 s' text never changed and status was not updated. Fix: 10 s countdown then 'Ready ✓ … You can unplug it', status 'Update complete.'. Live + preview redeployed.
  • 2026-10-15: Owner: shorten the post-flash guard to 5 s and make it part of the flash. Writing now fills 90% of the progress bar; the last 10% fills over 5 s ('Updating… finishing up, keep the board plugged in'), then 'Ready ✓'. Reason kept in code: first boot may rewrite option bytes (OB_Configure only writes when they differ, so usually a no-op in the field). Live + preview.
  • 2026-10-15: Phase 3 activity log LIVE. D1 therealcow-activity (4272e1be-…; schema site/migrations/0001_events.sql), Pages Function POST /api/event (verifies the Access JWT itself, adds email/IP/city/region/ISP/UA), GET /activity/events + /activity/ page (owner only: own Access app 'The Real Cow Activity (owner only)' on /activity for both hosts + VIEWERS list in functions/_lib/access.js). Client shared/log.js (session id, page_open, js_error). Flasher (Sonnet, cf9a6b8..6cbcfff): device_connect (USB serial = chip UID), boot_loader_sent, firmware_selected, flash_start/ok/fail/refused, erase, disconnects, ui_message. Configurator (Fable, 5e97fe7..55c427e): connect, settings_read (full dump), upload_start (old→new), upload_result (rejected list), address_channel_change, reset (+backup), presets, file save/load, mode_change, panels, ui_message; board id = ADDR/chN. Notice added to the home footer. The 504s seen in Cloudflare analytics are Cloudflare's Early Hints prefetcher (requestSource earlyHintsCache, UA 'bastion early hints') failing at the Access gate — harmless, users get 200. Not yet verified end-to-end with a real sign-in (needs a browser login).
  • 2026-11-05: Flasher fixed: owner deleted the fork repo by hand; recreated EmbeddedEra/The_Real_Cow_Flasher private, non-fork, Actions disabled, pushed main/gh-pages/feature/recording-and-unified-firmware from NAS mirror /mnt/storage/EmbeddedEra/Github/The_Real_Cow_Flasher-github-mirror-20261105.git (also holds unpushed local/* branches; metadata+issues json beside it). Close job rerun: both repos private=true pages=false, both github.io 404. Timer disabled. Lost: 1 star.
  • 2026-11-05: Close job ran: Configurator private + Pages off (github.io 404). Flasher FAILED: it is a GitHub fork of devanlai/webdfu (public forks cannot go private; Pages DELETE 422). Waiting on owner yes for delete+recreate private.
  • 2026-10-15: Owner (Paul already using the new site): close the old GitHub Pages automatically. Script ~/Notes/bin/therealcow-close-github (dry run verified: both repos public, Pages on, github.io 200), one-shot timer 2026-11-05 09:00 America/New_York enabled (Persistent=true, runs at next boot if missed).
  • 2026-10-15: Activity log verified end-to-end (owner visit recorded: home/flasher/configurator page_open, firmware_selected). It caught a pre-existing Configurator bug (also on GitHub): window.onload referenced #browserWarning which didn't exist, so on unsupported browsers (iPhone Safari) onload crashed before showing any warning. Added the element; live + preview.