Week 18 — Apr 28 – May 4, 2026
Summary
Two new services landed this week: static_site (static.grizzlebear.io) centralizes 5 demo pages under a shared TradeSpark-themed shell with CSS design tokens, JS utilities, and a Markdown blog engine; tsweb (tsweb.grizzlebear.io) quarantines all Supabase tsweb-app integrations into a single deletable boundary module with its own /projects API endpoint. The mobile-session demo was upgraded from free-text UUID inputs to live project/property dropdowns backed by the tsweb API (three-phase rollout: quarantine → endpoint → UI). Earlier in the week, the ML chat/stream endpoint gained per-provider message history and the Bruno test runner got retry logic for transient cold-start failures.
Later in the week, the livekit-recorder gained AES-CBC encryption at rest — recordings are now encrypted before S3 upload, with the Go recorder receiving the account DEK via environment variable. The COLMAP SfM pipeline added checkpoint-based preemption tolerance so Modal spot-instance restarts skip completed stages. LiveKit SDKs were bumped to 1.5.6. A tsweb deployment fix replaced top-level imports with per-function Image.add_local_python_source("tsweb") layering to stop crash loops in unrelated services, and two flaky on-prem chat tests were tagged skip-ci.
12 code commits | 86 files changed | +4,224 / -1,624 lines
Highlights
Static Site Service — Demo Centralization (Apr 30)
Merged from worktree branch. Five demo pages (ml-comparison, ml-dashboard, mobile-session, model-proxy, websocket-test) that were scattered across service modules are now consolidated under dev/static_site/ at static-{env}.grizzlebear.io. Features a shared CSS design system (TradeSpark tokens), JS utility layer (Site.apiFetch with auto-auth, Site.serviceUrl), header/footer templates, and a Markdown content engine with YAML frontmatter for blog posts.
tsweb Quarantine — Three-Phase Rollout (Apr 30)
All code that reads from the external tsweb-app Supabase tables is now isolated in dev/tsweb/:
- Phase A (
0c93938): Movedsupabase_queries.py,location.py, andsupabase_scraper.pyintodev/tsweb/. Nightly scraper cron moved fromml_endpointtotsweb.scheduled. - Phase B (
8931ec8): NewGET /projectsendpoint attsweb-{env}.grizzlebear.ioreturning user-scoped projects with joined property data. Newget_accessible_account_ids()auth helper. Bruno test coverage added. - Phase C (
8cedea6): Mobile-session demo's text inputs replaced with<select>dropdowns populated from the tsweb/projectsendpoint. Users see actual projects instead of typing UUIDs.
When tsweb-app is retired, the cleanup is a single-directory delete of dev/tsweb/.
Per-Provider Message History for Chat Stream (Apr 28)
New optional messages_by_provider field on ChatStreamRequest lets clients supply a distinct conversation history per provider in the multiplexed /ml/chat/stream endpoint. A provider not covered by the dict falls back to the top-level messages array — fully backward compatible. Bruno test added for two providers with distinct prior turns.
Bruno Test Suite Retry (Apr 28)
Transient failures — Modal cold-start TLS handshake errors, brief upstream blips — were producing one-off canary breaks that pass on re-run. test_app.sh now wraps bru run in a 3-attempt loop and only declares failure if every attempt fails. Whole-suite retry rather than per-test because Bruno tests share auth state through post-response scripts.
LiveKit Recorder Encryption at Rest (May 1)
The Go-based livekit-recorder now encrypts video and depth recordings using AES-CBC before writing to S3, mirroring the Python core.crypto.encrypt_account_data path. The recorder receives the account DEK via DEK_BASE64 env var, loaded by the Python agent before spawning the subprocess. load_dek_in_memory() was updated to return the DEK string. The VIDEO_DATA_BUCKET_NAME reference was removed in favor of the consolidated ASSET_DATA_BUCKET_NAME.
COLMAP Preemption Checkpointing (May 1)
The COLMAP SfM pipeline (colmap_undistorted_sfm_export.sh) now writes a checkpoint after each completed stage. On Modal preemption and restart, step_done()/mark_done() helpers skip already-completed stages. LiveKit SDKs bumped from 1.1.2/1.4.2 to 1.1.5/1.5.6; VAD prewarm disabled due to upstream livekit bug (loads inline via silero.VAD.load() instead). Session recording asset registration re-enabled. session_to_splat timeout extended from 4h to 6h.
tsweb Deployment Fix — Per-Function Image Layering (May 4)
Phase A's top-level from tsweb import ... hoists in auth.py and data_endpoint.py crashed every service that imports AuthContext but doesn't mount tsweb. Replaced with Modal 1.1.0's Image.add_local_python_source("tsweb") on only the users and data functions that actually call into tsweb at runtime. Two flaky on-prem chat tests tagged skip-ci (on-prem Ollama unreachable from dev; 60s timeout × 3 retries was 15+ min).
Temporary Supabase Prod Override (Apr 28)
The new prod Supabase project doesn't yet have anonymous sign-ins enabled or the canary test fixtures (test_project / test_location), so main temporarily uses SupabaseDev. Restoration checklist tracked in IMPROVE.md H19.
Daily Breakdown
May 4 (2 code commits, 3 docs-only)
558983aMount tsweb on users + data via per-function image layering; skip flaky on-prem chat tests (+33/-11)e3e6cf3Add descriptors and reorder demo cards on static site (+27/-5)84a29ccRefresh IMPROVE.md with 2026-05-01 review findings (docs-only)c4d156dAdd Apr 30 changelog, update W18 weekly summary (docs-only)958dd48Refresh IMPROVE.md with 2026-05-04 review findings (docs-only)
May 1 (2 code commits)
d790317Add checkpointing for Modal preemption, update LiveKit SDKs to 1.5.6, fix anon DEK issue (+282/-153)434ea24Make livekit-recorder write encrypted data (AES-CBC, DEK via env var) (+97/-15)
Apr 30 (5 code commits, 2 docs-only)
4867061Merge static.grizzlebear.io demo centralization into dev (+2,894/-1,355)e349957Allow bash<script>:*form in Claude Code settings0c93938Quarantine tsweb-app Supabase integration into dev/tsweb/ (Phase A)8931ec8Add tsweb /projects endpoint at tsweb-{env}.grizzlebear.io (Phase B)8cedea6Replace mobile-session text inputs with tsweb-backed dropdowns (Phase C)19ef58eRefresh IMPROVE.md with 2026-04-30 review findings (docs-only)12a2523Add Apr 28-29 changelogs, start W18 weekly summary (docs-only)
Apr 29 (1 commit — docs-only)
4cd1fc5Refresh IMPROVE.md with 2026-04-29 review findings (docs-only)
Apr 28 (3 code commits, 2 docs-only)
49469f8Add per-provider message history to /ml/chat/stream6ea8c3dPoint main env at SupabaseDev until new prod Supabase is restoreddc4e353Retry Bruno test suite up to 2x on failure in test_app.shc78e098Add Apr 27 changelog, refresh W17 weekly summary (docs-only)02fbeceRefresh IMPROVE.md with 2026-04-28 review findings (docs-only)
Modified Files
May 4
dev/users/auth.py— reverted top-level tsweb import; stays lazy in_resolve_location_contextdev/data/data_endpoint.py— reverted top-level sync import; tsweb layered onto data image viaadd_local_python_sourcedev/users/users_endpoint.py— tsweb layered onto users image viaadd_local_python_sourcebruno/.../Chat Stream Multi Provider.bru— addedskip-citagbruno/.../Chat Stream Per Provider History.bru— addedskip-citagdev/static_site/templates/index.html— demo list reordered, descriptors addeddev/static_site/assets/css/site.css—.demo-descstyling
May 1
dev/queues/colmap_undistorted_sfm_export.sh— checkpoint-based preemption tolerancedev/queues/session_to_splat.py— timeout 4h → 6hdev/queues/video_to_gsplat.sh— new: ffmpeg → COLMAP → splatting helperdev/livekit_ts/agent/agent.py— silero VAD inline, recording asset registration re-enabled, depth track handlingdev/livekit_ts/agent/recorder.py— S3 bucket fix, DEK loading +DEK_BASE64env vardev/livekit_ts/agent/room_agent_worker.py— VAD prewarm disableddev/livekit-recorder/pkg/participant/data.go—encryptBytes()+encryptAndWriteFile()(AES-CBC)dev/livekit-recorder/pkg/participant/processing.go— encrypted writes replacecopyFiledev/core/core.py—livekit-protocolpinned to 1.1.5dev/core/data.py—VIDEO_DATA_BUCKET_NAMEremoved;load_dek_in_memory()returns DEK stringdev/users/auth.py— anon DEK handling fixesdev/requirements.txt— LiveKit SDK bumps to 1.5.6dev/queues/1416529-sd_640_360_30fps.mp4,dev/queues/boot.mp4— removed (test videos)
Apr 30
dev/static_site/— new module: endpoint, templates (6 pages + partials), CSS/JS assets, content engine, blog postsdev/tsweb/— new module: quarantined tsweb-app integration (queries, location, scraper, endpoint, scheduled cron, client)dev/app.py— includesstatic_site.appandtsweb.appdev/core/core.py—ServiceType.STATICandServiceType.TSWEBenums + domain resolutiondev/ml/ml_endpoint.py— dropped inline demo routes and nightly scraper crondev/model_proxy/model_proxy_endpoint.py— dropped inline/demoroutedev/users/users_endpoint.py— dropped inline/mobile-sessionroute; auth gainsget_accessible_account_ids()dev/websocket/websocket_endpoint.py— dropped inline/testroutedev/data/sync.py,dev/data/data_endpoint.py— imports fromtsweb.*bruno/.../Tsweb API/— new folder with List Projects test- All 7 Bruno environment files — added
tsweb_endpointvariable .claude/settings.json— bash script allow entriesdev/model_proxy/demo.html— removed (moved to static_site)dev/users/mobile_session.html— removed (moved to static_site)dev/websocket/websocket_pages.py— removed (routes moved to static_site)
Apr 28
dev/ml/gateway/chat.py—messages_by_providerfield + per-provider message resolutionbruno/.../ML API/Chat Stream Per Provider History.bru— new: multi-provider history testdev/core/core.py—supabase_secret_namehardcoded to"SupabaseDev"(temporary)dev/test_app.sh— 3-attempt retry loop with failure detection (+48/-9)dev/test_app.md— updated retry documentation