Local Rebuild Foundation
Date: 2026-05-05
Objective
Start the local rebuild of the legacy Picasso, Zweistein, and Studio API codebases inside LegacyBlinkin-2-Hetzner without modifying blinkin-2-platform.
Current Local Source Layout
The imported source snapshot lives in legacy-src/:
legacy-src/picasso-fe: Picasso FE monorepo with Houston, Picasso Editor, Widget, and shared packages.legacy-src/zweistein: Zweistein admin app, NestJS server, embedding widget, Python query engine, and ingestion worker.legacy-src/studio-api: Studio API NestJS backend.
The copy intentionally excludes:
.gitnode_modules- build outputs such as
dist,build,.next, coverage, and caches - real
.envfiles - virtual environments and Python caches
Only .env.example templates are preserved.
Local Infrastructure
docker-compose.local.yml now defines the first shared local services:
- Postgres on host port
54320 - Redis on host port
63790 - MinIO on host ports
9000and9001 - optional Weaviate on host port
8088behind theaiprofile
The Postgres init script creates:
studio_apizweistein
Verification
Run:
npm run legacy:verify
This verifies that the required imported packages exist and that forbidden generated folders or real env files were not copied.
Latest verification evidence:
npm run legacy:verifypassed.- Imported code contains 13
package.jsonfiles. - Imported Python services contain 4
pyproject.tomlfiles. - Imported source keeps 6
.env.exampletemplates. - Forbidden generated folders: 0.
- Forbidden real env files: 0.
- Strict secret scan for common real key formats returned no hits after redacting Stripe values in the imported Zweistein Helm dev values copy.
- Local Postgres, Redis, and MinIO containers started through
npm run legacy:infra:up. - Postgres accepts connections and contains the
studio_apiandzweisteindatabases. - Redis responds with
PONG. - MinIO health endpoint responds successfully.
- Studio API now has a verified local runtime slice: dependencies installed, build passed, 84 migrations applied, and
/health/returned HTTP 200 on Node 20. - Zweistein server now has a verified local runtime slice: dependencies installed with Yarn 4, build passed, server booted on Node 20,
/ai/healthzreturned HTTP 200, and the localzweisteindatabase contains 39 synchronized tables. - Zweistein admin now has a verified local frontend runtime slice: dependencies installed with Yarn 1, Dockerfile-near Vite build passed, dev server served
/ai/on127.0.0.1:5176, and/ai/api/authz/configproxied to the local Zweistein server. - Zweistein embedding widget now has a verified local runtime slice: dependencies installed with npm, strict package build passed,
dist/assets/emb-chat.jswas emitted, and the Vite dev route responded on127.0.0.1:5177. - Picasso FE now has a verified local build/runtime slice: monorepo install passed, Houston build passed, Picasso Editor build passed, Picasso widget build passed, and all three Vite dev routes responded locally.
- Zweistein Python services now have a first local probe: Poetry metadata checks pass after restoring missing READMEs, local placeholder env templates exist, Query Engine uses Python 3.12, the FastAPI app import reaches the legacy router graph before failing on missing
torch, the macOS local install is blocked by Torch wheel compatibility, and a Linux/amd64 Docker probe confirms thattorch (2.10.0+cpu)is available for a Hetzner-like target. - The Python helper now has disk guards and dry-run install plans. On this Mac, Query Engine has one remaining local install operation (
torch), while Ingestion Worker would need 307 installs and is intentionally blocked by the low-disk guard. - The local runtime assembly helper now maps the full service start order and current live status across infrastructure, Studio API, Zweistein Server/Admin/Widget, Picasso Houston/Editor/Widget, and Python services.
- The repeatable non-Python smoke helper now runs
npm run legacy:runtime:smoke:non-python, starts the seven non-Python app services together, verifies every health helper, checks the Zweistein DB table count, prints runtime status, and shuts down its own app processes. - Studio API and Zweistein Admin generated artifacts were refreshed after the assembly audit, and their local health checks passed again.
- The database readiness gate now verifies Studio API source/applied migration counts, Studio public table count, Zweistein public table count, and the current Zweistein
synchronize:truemigration boundary. - The foundation verifier now checks for common hardcoded secret patterns and reports
potential hardcoded secrets: 0. - The first Hetzner staging package now exists:
docker-compose.hetzner.yml, placeholder-onlyconfigs/hetzner/*.env.examplefiles, and a read-onlynpm run hetzner:checkprobe. - The Hetzner staging probe now has a non-printing env readiness gate:
npm run hetzner:envfor local status andnpm run hetzner:env:checkas the strict server-side pre-build check. - The Hetzner staging probe now includes a post-start health gate:
npm run hetzner:healthfor status andnpm run hetzner:health:checkfor strict staging readiness. - The Hetzner staging probe now includes a host preflight gate:
npm run hetzner:hostfor status andnpm run hetzner:host:checkto require native Linux/amd64, Docker Compose, free ports, and enough disk before building. - The Hetzner Compose topology now includes static Nginx services for Picasso Widget and Zweistein Embedding Widget, plus
.dockerignorefiles to keep local generated folders and env files out of Docker build contexts. - Existing backend and Python Docker contexts now have stricter
.dockerignorecoverage for generated folders, caches, virtual environments, and real env files before server-side builds. - A Hetzner rsync filter now documents how to move the source tree to the server without generated folders or real env files:
configs/hetzner/rsync-filter.rules. - The Hetzner source sync helper now wraps that filter in
npm run hetzner:sync:check,npm run hetzner:sync:dry-run, and guardednpm run hetzner:sync:push. - The first public edge is now mapped as an optional Caddy
reverse-proxyprofile withconfigs/hetzner/Caddyfile.exampleandconfigs/hetzner/reverse-proxy.env.example. - The first backup/restore runbook now exists with
configs/hetzner/backup.env.exampleandscripts/hetzner-backup.mjs. - The first server-side evidence workflow now exists with
scripts/hetzner-evidence.mjs. - The first Hetzner bootstrap gate now exists with
scripts/hetzner-bootstrap.mjs. - The first Hetzner runtime config initializer now exists with
scripts/hetzner-config.mjs; it creates ignored config files from templates without overwriting existing files. - The first Hetzner stack runner now exists with
scripts/hetzner-stack.mjs; it guards heavy Compose build/start commands for native Linux x64/amd64. - A coordinated non-Python local runtime smoke now proves Studio API, Zweistein Server/Admin/Widget, and Picasso Houston/Editor/Widget can run together with HTTP 200 health checks.
Local Commands
Start local base infrastructure:
npm run legacy:infra:up
Check local base infrastructure:
npm run legacy:infra:status
Stop local base infrastructure:
npm run legacy:infra:down
Set LEGACY_BLINKIN_AI=1 before legacy:infra:up to include the optional Weaviate container.
Show the local runtime assembly plan:
npm run legacy:runtime:plan
Check what is currently generated or running:
npm run legacy:runtime:status
npm run legacy:runtime:missing
Check local database readiness:
npm run db:local:check
Run the coordinated non-Python local smoke:
npm run legacy:runtime:smoke:non-python
Show the Hetzner staging plan:
npm run hetzner:plan
Validate the Hetzner staging files without building images:
npm run hetzner:sync:plan
npm run hetzner:sync:check
npm run hetzner:bootstrap:plan
npm run hetzner:config:plan
npm run hetzner:config:status
npm run hetzner:stack:plan
npm run hetzner:stack:commands
npm run hetzner:host
npm run hetzner:check
npm run hetzner:env
npm run hetzner:health
npm run hetzner:backup:plan
npm run hetzner:evidence:plan
Not Yet Done
- Dependency installation and build paths have not been verified for every imported legacy package yet. Studio API, Zweistein server, Zweistein admin, Zweistein embedding widget, and Picasso FE are the first verified slices.
- Runtime env files are not generated locally by default. Use
npm run hetzner:config:initon Hetzner to create ignored placeholder copies, then replace every placeholder with real staging values. - NestJS migrations are not adapted for every service yet. Studio API migrations have been applied against local Postgres. Zweistein server currently uses TypeORM
synchronize: truebecause no migration source files were found in the imported snapshot. - Strict TypeScript checking is not clean for Zweistein admin yet, even though the Dockerfile-near Vite build passes.
- Picasso FE builds and serves locally, but its authenticated flows are not yet wired end to end to the local Studio API, Zweistein server, and Houston runtime.
- The Zweistein embedding widget and Picasso widget are locally buildable and now mapped into first static Hetzner services, but their server-side image builds and production public paths are not verified yet.
- Python query and ingestion services are not fully containerized for local Hetzner-style operation yet. Query Engine local Poetry install is currently blocked by a Torch wheel mismatch on macOS/Python 3.12, while Linux/amd64 resolves the required CPU Torch wheel. A full Query Engine Docker build still needs to pass on native Linux/amd64 or a Hetzner staging box.
- Ingestion Worker local Poetry install is intentionally blocked on this Mac by the Python low-disk guard; its dry-run plan needs 307 installs, including heavy ML/media dependencies.
- The Hetzner Compose package has only been validated locally for file presence and YAML shape. Full Docker Compose config validation and image builds still need to run on Hetzner/Linux after real staging env files are created.
- A coordinated non-Python local runtime smoke is proven, but no complete end-to-end local product flow is running yet.
- Runtime assembly currently reports no missing required local runtime artifacts, but the services are not all running together yet.
This foundation makes the next slice concrete: keep adding one verified service at a time, then connect the verified services into a local end-to-end flow.