Closes the two gaps found smoke-testing the local stack: an empty gallery
(zero media_files rows, media URLs hardcoded to the remote r2.dev bucket)
and generation flows that could not complete (omni_gen calls providers
synchronously in the handler, so dummy keys meant a 500 after billing;
the webapp blocked submits earlier anyway because signup grants no wallet).
Backend (all development-only):
- CDN_BASE_URL env override in cdn_link.rs (host-only, validated loudly;
precedence over the compiled-in hosts for every domain/env) and a
dev-gated actix-files mount serving LOCAL_MEDIA_ROOT/media at /media,
mirroring the public bucket layout - media URLs in API responses resolve
against the backend itself
- DEV_FAKE_GENERATION flag on ServerState (easyenv bool, forced off outside
Development): the omni_gen image/video pipelines skip the external
provider call and return a synthetic Fal enqueue (external id fake_<uuid>),
so billing, prompt insert, and the pending generic_inference_jobs row all
stay real
- dev_fake_generation_resolver_thread: polls pending fake_ jobs (new
runtime-query list_pending_fake_generation_jobs in mysql_queries) and
after DEV_FAKE_GENERATION_RESOLVE_SECS (default 6s) marks them
complete_success with a media_files row backed by a test_data asset
copied under LOCAL_MEDIA_ROOT (mp4 results get -thumb.jpg/-thumb.gif
siblings since the thumbnail job never runs locally), or complete_failure
via the existing simulate_artcraft_failure prompt triggers (category word
supported, e.g. "simulate_artcraft_failure face_not_detected")
Bootstrap/seeds (PS + bash kept in lockstep):
- seed_demo_user seeds an artcraft wallet (DEMO_CREDITS, default 100k
banked + ledger rows; idempotent top-up) - signup creates no wallet and
the webapp gates generate on balance, which is why submits went nowhere
- seed_demo_user also seeds 6 gallery images (test_data jpgs) with objects
under .devstack/media in the exact bucket fan-out layout
- fixed the already-exists detection in seed_demo_user: create_account
returns error_type, not error_code, so re-runs died on UsernameTaken
- generated secrets env gains DEV_FAKE_GENERATION/CDN_BASE_URL/
LOCAL_MEDIA_ROOT (appended to existing files on bootstrap re-runs);
stale "providers are only contacted by workers" comments corrected
- doctor checks wallet balance, media rows, and the new secrets keys
Docs: dev_setup_local_stack.md documents the new flags, corrects the
sync-provider-call and upload-500 claims, updates the seams table and
verification checklist; storyteller_web CLAUDE.md video model examples
fixed (seedance_2p0_fast_g -> seedance_2p0_fast).
Verified E2E on this machine: gallery lists 8 items on localhost URLs;
image and video submits go pending ~6s then complete with locally-served
results (mp4 + gif preview 200); failure trigger yields complete_failure
with category face_not_detected; credits genuinely deducted (100000 ->
99932); doctor 0 failures / 0 warnings.
Adds script/bootstrap/windows/*.ps1 (PowerShell 5.1-compatible) as the primary
bootstrap path, validated end-to-end on a real Windows 10 machine:
- Portable stack under gitignored .devstack/: MySQL 8.4.11 (official
cdn.mysql.com zip, --initialize-insecure, bound to 127.0.0.1) and Redis
5.0.14.1 (tporadowski build, REDIS_ZIP_URL-overridable) run as plain user
processes - no admin, no services, no WSL, no Docker
- bootstrap_dev_stack.ps1: winget-installs missing build tools (Strawberry
Perl, NASM, LLVM; wreq's BoringSSL + aws-lc-sys need them), compiles
diesel_cli against the portable MySQL's own client lib
(MYSQLCLIENT_LIB_DIR), runs all 281 migrations, seeds roles/badges
idempotently, generates the dummy secrets env (plus TEMP_DIR for Windows),
builds storyteller-web, installs frontend deps
- start/stop_dev_services.ps1, run_backend_dev.ps1, seed_demo_user.ps1,
dev_stack_doctor.ps1 mirror the bash variants
- Invoke-Native (cmd /c ... 2>&1) wraps long-running native calls so PS 5.1
cannot turn harmless stderr warnings into terminating NativeCommandErrors
when output is captured; my.ini uses forward slashes (MySQL escape rules)
Verified on this machine: 281/281 migrations applied, backend built (3m05s)
and booted on :12345 with dummy secrets, POST /v1/create_account +
/v1/login round-trip succeeded, webapp dev server served on :4201, doctor
reports 0 failures. The bash scripts remain the Linux/WSL2/CI path.
Adds script/bootstrap/ — idempotent Ubuntu 22.04+/WSL2/CI automation that takes
a fresh clone to a running local stack with zero production traffic:
- bootstrap_dev_stack.sh: apt packages, MySQL 8 + Redis up, storyteller DB/user,
281 diesel migrations, idempotent role/badge seeds, generated dummy
development-secrets.env (19 required-at-boot vars no checked-in config
supplies), SQLX_OFFLINE backend build, frontend npm install
- run_backend_dev.sh / seed_demo_user.sh: run the API from the repo root and
create+verify a demo login through the real POST /v1/create_account path
- dev_stack_doctor.sh: PASS/WARN/FAIL diagnosis of every prerequisite
_docs/dev_setup_local_stack.md records the requirements the scripts encode and
corrects stale claims (server reads MYSQL_URL, not DATABASE_URL; repo-root .env
is not loaded by the server; config precedence is first-value-wins;
SQLX_OFFLINE is compile-time only).
.gitattributes now forces LF for *.sh/*.env so Windows clones run under WSL2.