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.
Pass 1 (correctness sweep):
- All native invocations (mysql, mysqld init, winget, curl downloads,
cargo run, seed curl) now go through Invoke-Native, so a caller capturing
the scripts' output can never turn ordinary stderr (warnings, progress)
into a terminating NativeCommandError under Stop preference
- Provisioning DDL feeds through a temp file + `source` and prints the mysql
output when it fails (with the MYSQL_ROOT_PASSWORD hint)
- Get-MySqlCount distinguishes "table empty" (0) from "query failed" (-1);
bootstrap and doctor no longer misread a failed COUNT as unseeded
- diesel_cli that is present but broken (moved libmysql.dll) is detected via
an exit-code probe and reinstalled with --force
- Shared Add-BuildToolsToSession maps winget install dirs + LIBCLANG_PATH in
bootstrap, doctor, and run_backend_dev (cargo run may recompile); the tools
check maps PATH before probing so re-runs skip winget entirely
- my.ini values quoted (clone paths with spaces); service-start timeouts
point at the .devstack log files
Pass 2 (live retest matrix, all green on this machine):
- Full re-run with output captured in-PowerShell: exit 0, no NativeCommandError
- Wiped-state rebuild (mysql-data/my.ini/redis/secrets deleted): re-init,
re-provision, 281 migrations replayed, seeds + secrets regenerated, backend
booted, demo user recreated via /v1/create_account, doctor 0 fail / 0 warn
- Failure paths: seed without backend and doctor without services both die
cleanly with actionable messages and exit 1; stop_dev_services frees both
ports gracefully
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.
We need to remove irrelevant FakeYou records that do not impact the
ArtCraft product
- 87M irrelevant media file records (no relation to ArtCraft)
- 105M jobs records (which we purge occasionally anyway)
- lots of other files: audit logs, old/irrelevant stripe event logs,
feed data, etc. etc.
Two reasons for this:
- super brittle when pinned to non-main commit
e1a70095c4409478c1ded499fb8dd4afa540fb90
- I was recently stuck on a flight without good wifi and setting up a
new devenv. Cargo was totally unable to download the remote github
dependency, but was fine downloading the entire artcraft repo. Seems bad
to link to other repos that Cargo can't quickly pull on low bandwidth.
We'll need to slim this down later and eventually get back on main
branch.