Hetzner Port Completion Audit
Date: 2026-05-05
Verdict
The goal is not complete yet.
The local folder, imported source, local rebuild slices, coordinated non-Python local runtime smoke, database gate, guarded source sync helper, local full-stack evidence contract, Hetzner Compose package, config helpers, Python gate, stack runbook, milestone runner, completion gate, backup runbook, and documentation site are in place. The missing proof is still the Python-backed full stack running either as one local assembly or on a native Hetzner Linux/amd64 host.
Objective Restated As Success Criteria
Original objective:
Port the full code base of Picasso, Zweistein, and Studio API to Hetzner, first rebuilding it locally in the new folder.
Concrete success criteria:
- Work happens only in
LegacyBlinkin-2-Hetzner, not inblinkin-2-platform. - The legacy Picasso FE, Zweistein, and Studio API source trees are present in the new project.
- Real secrets and real runtime env files are not copied or committed.
- Local rebuild slices prove each major service can install/build/start where the current machine can support it.
- A local runtime map shows the whole platform assembly order and current gaps.
- Hetzner deployment files exist for the full platform stack.
- Hetzner runtime config is initialized safely from templates and passes strict placeholder checks on the server.
- Hetzner host bootstrap, Docker Compose config, image builds, stack startup, health checks, proxy startup, backup, and evidence collection run on a native Linux/amd64 host.
- A complete end-to-end platform flow is verified: Studio Editor to published Houston App to Zweistein Agent/AI runtime.
Prompt-To-Artifact Checklist
| Requirement | Evidence inspected | Current result | Status |
|---|---|---|---|
Do not touch blinkin-2-platform |
Current workdir is /Users/josef/Desktop/LegacyBlinkin-2-Hetzner; all inspected/edited paths are under that folder. |
No current slice required edits outside the new project. | Complete for this audit slice |
| New project folder exists | /Users/josef/Desktop/LegacyBlinkin-2-Hetzner exists and contains package.json, docs/, legacy-src/, configs/, scripts/, and Compose files. |
Project folder exists. | Complete |
| Picasso FE source present | legacy-src/picasso-fe/package.json and app package files are required by scripts/verify-local-rebuild.mjs. |
npm run legacy:verify passed and reported 13 package.json files. |
Complete for required source presence |
| Zweistein source present | legacy-src/zweistein/server, admin, embedding-widget, and Python service files are required by scripts/verify-local-rebuild.mjs. |
npm run legacy:verify passed and reported 4 Python projects. |
Complete for required source presence |
| Studio API source present | legacy-src/studio-api/package.json, nest-cli.json, src/main.ts, .env.example, and Docker context are required by scripts/verify-local-rebuild.mjs. |
npm run legacy:verify passed. |
Complete for required source presence |
| No copied real env files | scripts/verify-local-rebuild.mjs, .gitignore, and runtime config status. |
npm run legacy:verify reported forbidden real env files: 0. find configs/hetzner ... reported 0 runtime env/Caddy files locally. |
Complete locally |
| No obvious hardcoded secrets | Secret scan for common key formats and scripts/verify-local-rebuild.mjs. |
npm run legacy:verify reported potential hardcoded secrets: 0. External secret scan exit was 1, meaning no matches. |
Complete for scanned patterns |
| Safe source sync helper | scripts/hetzner-sync.mjs, configs/hetzner/rsync-filter.rules, npm run hetzner:sync:check, npm run hetzner:sync:target, and npm run hetzner:sync:plan. |
Sync helper checks filter safety, warns about root .env, reports 0 local Hetzner runtime env/Caddy files, validates the target format/path before sync, refuses non-standard remote paths, refuses rsync --delete without confirmation, and writes redacted dry-run/push evidence files after successful sync commands. |
Complete as local helper, missing real server sync |
| Database readiness gate | scripts/database-gate.mjs, npm run db:local:check, npm run hetzner:db:plan, and npm run hetzner:db:commands. |
Local DB gate reports 84 Studio migration source files, 84 applied Studio migrations, 37 Studio public tables, 39 Zweistein public tables, and the current Zweistein synchronize:true boundary. |
Complete locally, missing server DB gate |
| Local base infrastructure | npm run legacy:runtime:status. |
Postgres, Redis, and MinIO are currently Up 2 hours; Weaviate is optional and not created. |
Partial: base infra is up, optional AI infra not running |
| Studio API local rebuild | docs/porting/2026-05-05-studio-api-local-runtime.md, docs/porting/2026-05-05-local-non-python-runtime-smoke.md, scripts/local-non-python-smoke.mjs, and npm run legacy:runtime:smoke:non-python. |
Prior slice proved install/build/migrations. Repeatable smoke reported HTTP 200 while running with the other non-Python services. | Complete for non-Python local smoke |
| Zweistein Server local rebuild | docs/porting/2026-05-05-zweistein-server-local-runtime.md, docs/porting/2026-05-05-local-non-python-runtime-smoke.md, scripts/local-non-python-smoke.mjs, and npm run legacy:runtime:smoke:non-python. |
Repeatable smoke started the server, returned Server is healthy, and reported 39 public DB tables. |
Complete for non-Python local smoke |
| Zweistein Admin local rebuild | docs/porting/2026-05-05-zweistein-admin-local-runtime.md, docs/porting/2026-05-05-local-non-python-runtime-smoke.md, scripts/local-non-python-smoke.mjs, and npm run legacy:runtime:smoke:non-python. |
Repeatable smoke reported HTTP 200 on /ai/. |
Complete for non-Python local smoke |
| Zweistein Embedding Widget local rebuild | docs/porting/2026-05-05-zweistein-embedding-widget-local-runtime.md, docs/porting/2026-05-05-local-non-python-runtime-smoke.md, scripts/local-non-python-smoke.mjs, and npm run legacy:runtime:smoke:non-python. |
Repeatable smoke reported HTTP 200. | Complete for non-Python local smoke |
| Picasso Houston, Editor, and Widget local rebuild | docs/porting/2026-05-05-picasso-fe-local-build-runtime.md, docs/porting/2026-05-05-local-non-python-runtime-smoke.md, scripts/local-non-python-smoke.mjs, and npm run legacy:runtime:smoke:non-python. |
Repeatable smoke reported HTTP 200 for Houston, Editor, and Widget. | Complete for non-Python local smoke |
| Python Query Engine local rebuild | docs/porting/2026-05-05-zweistein-python-services-local-probe.md, docs/porting/2026-05-05-hetzner-python-gate.md, scripts/hetzner-python-gate.mjs, and npm run legacy:runtime:status. |
Lightweight import passes; main import reaches the legacy router graph and then fails on missing torch; install plan shows only torch (2.10.0+cpu) remains in the current venv. Linux/amd64 Torch probe passes. The server-side gate now has npm run hetzner:python:build:query, imports, subset startup, and health commands. |
Blocked locally, must pass Hetzner Python gate |
| Python Ingestion Worker local rebuild | docs/porting/2026-05-05-zweistein-python-services-local-probe.md, docs/porting/2026-05-05-hetzner-python-gate.md, scripts/hetzner-python-gate.mjs, and npm run legacy:runtime:status. |
Environment exists but redis is not installed. Dry-run install plan needs 307 packages including torch, opencv-python, spider-rs, and openai-whisper; low-disk guard blocks local install. The server-side gate now has npm run hetzner:python:build:ingestion and import probes. |
Blocked locally, must pass Hetzner Python gate |
| Local runtime assembly map | scripts/local-runtime-assembly.mjs, scripts/local-non-python-smoke.mjs, npm run legacy:runtime:status, npm run legacy:runtime:missing, and npm run legacy:runtime:smoke:non-python. |
Status table exists; legacy:runtime:missing reports no required runtime assembly files missing. Repeatable non-Python smoke exists. |
Complete as a map and non-Python smoke, incomplete as a full Python-backed running platform |
| Non-Python services running together locally | docs/porting/2026-05-05-local-non-python-runtime-smoke.md and npm run legacy:runtime:smoke:non-python. |
Studio API, Zweistein Server/Admin/Widget, Picasso Houston/Editor/Widget all reported HTTP 200 in one repeatable coordinated smoke. The command stopped its own app processes afterward. | Complete for non-Python scope |
| All services running together locally | npm run legacy:runtime:status. |
Python Query Engine remains not responding; Python Ingestion Worker remains manual. |
Missing |
| Local full-stack evidence contract | scripts/local-full-stack-evidence.mjs, npm run local:full-stack:plan, npm run local:full-stack:probe, npm run local:full-stack:collect, and npm run local:full-stack:check. |
Helper defines the full local rebuild evidence contract, live-probes all seven non-Python URLs plus the Query Engine URL, and refuses to write complete evidence unless the verifier confirms the worker and Agent/AI observations. It intentionally fails until docs/evidence/*-local-full-stack.md contains Status: complete, Target: local, : yes HTTP 200 markers for every UI/API service, Query Engine HTTP 200: yes, Ingestion Worker observed: yes, Agent/AI response observed: yes, Evidence collector command: npm run local:full-stack:collect, and Live probe source: scripts/local-full-stack-evidence.mjs. |
Helper complete, full local evidence missing |
| End-to-end local product flow | No current browser/e2e evidence file exists for Studio Editor to Houston App to Zweistein Agent/AI runtime. | Not verified. | Missing |
| Platform E2E evidence contract | scripts/platform-e2e-evidence.mjs, npm run platform:e2e:plan, npm run platform:e2e:template, and npm run platform:e2e:check. |
Helper defines the manual Studio Editor to Houston App to Zweistein Agent/AI evidence contract and intentionally fails until docs/evidence/*-platform-e2e.md contains Status: complete, Target: Hetzner staging, a Published App URL:, verifier, password check result, and Agent/AI response observed: yes. |
Helper complete, E2E evidence missing |
| Hetzner Compose package | docker-compose.hetzner.yml, configs/hetzner/*.env.example, scripts/hetzner-staging-probe.mjs, npm run hetzner:check. |
npm run hetzner:check passed locally with YAML fallback. |
Complete for package shape |
| Hetzner runtime config helper | scripts/hetzner-config.mjs, npm run hetzner:config:status, and npm run hetzner:config:checklist. |
Helper exists; local status reports 8 runtime config files missing, as expected. The checklist reads templates only and prints required keys, placeholders, staging defaults, optional blanks, target runtime file names, and modes without reading or printing real runtime values. | Complete as helper, missing real server configs |
| Hetzner env readiness | npm run hetzner:env:check is available. |
Not run successfully against real server values because runtime configs do not exist locally. | Missing server proof |
| Hetzner host bootstrap | scripts/hetzner-bootstrap.mjs, npm run hetzner:bootstrap:check. |
Helper exists; current Mac is not the target Linux x64 host. | Missing server proof |
| Hetzner stack build/start | scripts/hetzner-stack.mjs, npm run hetzner:stack:commands. |
Commands are generated; hetzner:stack:config is intentionally guarded and refuses to run on macOS. |
Missing server proof |
| Hetzner milestone runner | scripts/hetzner-runbook.mjs, npm run hetzner:runbook:plan, and npm run hetzner:runbook:commands. |
Runner defines 6 milestones and 28 commands, stops at first failure, requires native Linux x64/amd64, requires HETZNER_RUNBOOK_CONFIRM=1 before executing a milestone, and writes redacted docs/evidence/*-hetzner-runbook-<milestone>.md files after confirmed milestone runs. Future milestone evidence includes Expected command count and the expected command manifest. |
Helper complete, missing server execution |
| Python gate on Hetzner | scripts/hetzner-python-gate.mjs, npm run hetzner:python:plan, and npm run hetzner:python:commands. |
Gate commands exist for preflight, Torch wheel probe, Query Engine build, Ingestion Worker build, image import probes, Python subset startup, JSON Compose running-state inspection, and Query Engine health. Local preflight fails as expected on darwin arm64 with low disk and missing Docker Compose. |
Missing server proof |
| Query Engine image build on Hetzner | npm run hetzner:python:build:query and npm run hetzner:stack:build:query commands exist. |
Not executed on native Linux/amd64. | Missing and highest-risk blocker |
| All Hetzner images build | npm run hetzner:stack:build command exists. |
Not executed on native Linux/amd64. | Missing |
| Hetzner stack health | npm run hetzner:health:check exists. |
Not run against a live Hetzner stack. | Missing |
| Public reverse proxy and TLS | configs/hetzner/Caddyfile.example, reverse-proxy Compose profile, npm run hetzner:stack:proxy:up. |
Templates and command exist; no real DNS, Caddy config, or TLS proof. | Missing server proof |
| Backup and restore | scripts/hetzner-backup.mjs, docs/porting/2026-05-05-hetzner-backup-restore.md, npm run hetzner:backup:commands, npm run hetzner:backup:run, npm run hetzner:restore:commands, and npm run hetzner:restore:rehearse. |
Guarded backup run path exists, requires native Linux x64/amd64 plus HETZNER_BACKUP_CONFIRM=1, requires the Compose env file, and writes redacted docs/evidence/*-hetzner-backup.md command-status evidence. Guarded restore rehearsal path exists, requires native Linux x64/amd64, HETZNER_RESTORE_CONFIRM=1, HETZNER_RESTORE_TARGET=recovery, a concrete restore stamp, matching backup evidence, the Compose env file, and writes docs/evidence/*-backup-restore-rehearsal.md. Docker Compose backup/restore/restart commands now include --env-file configs/hetzner/frontend-build.env. No real backup or restore rehearsal evidence exists yet. |
Missing server proof |
| Evidence collection | scripts/hetzner-evidence.mjs, runbook milestone evidence, docs/evidence/, and npm run hetzner:evidence:check. |
Collector exists and now captures source sync safety, host/env readiness, Python gate status, database gate status, backup support, Docker/Compose status, Compose services/images, health probes, completion-gate status, and platform E2E evidence status. Confirmed runbook milestones now write separate redacted command evidence files. docs/evidence/ currently has 0 real Hetzner evidence files. |
Helper complete, missing server evidence |
| Completion gate | scripts/port-completion-gate.mjs, npm run port:completion:plan, npm run port:completion:status, and npm run port:completion:check. |
Gate maps the full objective to concrete source, artifact, local full-stack evidence, config, runbook, staging, end-to-end, and backup/restore evidence. It now requires a structured local full-stack evidence file, Linux x64 runbook/staging evidence with expected command manifests, a structured platform E2E evidence file with a published App URL, and structured backup/restore rehearsal evidence from a recovery target. It is read-only and currently fails as expected because local full-stack and server evidence are missing. | Helper complete, goal still incomplete |
| Public docs site | npm run build, npm run check, Cloudflare Pages deploy. |
Site is live at https://blinkindocs.pages.dev/ with 47 generated pages as of the latest local build/check cycle. |
Complete |
Commands Inspected In This Audit
npm run legacy:verify
npm run hetzner:sync:check
npm run hetzner:sync:target
npm run db:local:check
npm run legacy:runtime:smoke:non-python
npm run legacy:runtime:status
npm run legacy:runtime:missing
npm run hetzner:python:plan
npm run hetzner:python:commands
npm run hetzner:python:preflight
npm run hetzner:runbook:plan
npm run hetzner:runbook:commands
npm run hetzner:runbook:check
npm run port:completion:plan
npm run port:completion:status
npm run port:completion:check
npm run local:full-stack:plan
npm run local:full-stack:probe
npm run local:full-stack:template
npm run local:full-stack:collect
npm run local:full-stack:check
npm run platform:e2e:plan
npm run platform:e2e:template
npm run platform:e2e:check
npm run hetzner:evidence:check
npm run hetzner:backup:commands
npm run hetzner:restore:commands
npm run hetzner:check
npm run hetzner:config:status
npm run hetzner:config:checklist
npm run hetzner:stack:commands
find docs/evidence -maxdepth 1 -type f
find configs/hetzner -maxdepth 1 \( -name '*.env' -o -name 'Caddyfile' \) -type f
Observed current facts:
legacy:verifypassed.hetzner:sync:checkpassed; it reported 0 local Hetzner runtime env/Caddy files and warned that root.envis excluded by the rsync filter.hetzner:sync:targetfails locally as expected withoutHETZNER_SYNC_TARGETand refuses non-standard remote paths before SSH.hetzner:sync:pushrefuses to runrsync --deletewithoutHETZNER_SYNC_CONFIRM=1or--yes.- Successful source sync dry-run and push commands now write redacted
docs/evidence/*-hetzner-source-sync-*.mdfiles. db:local:checkpassed; Studio API source/applied migration counts both equal 84, Studio has 37 public tables, and Zweistein has 39 public tables.- Zweistein has no imported
src/dataSource.tsorsrc/migrationsdirectory and currently relies on the primary TypeORM connection'ssynchronize:truefor schema creation. legacy:runtime:smoke:non-pythonpassed and left the seven app ports free after shutdown.legacy:runtime:missingreports no missing required runtime assembly files.legacy:runtime:statusduring the repeatable coordinated smoke showed all non-Python app services responding with HTTP 200.hetzner:python:planandhetzner:python:commandsprint the new server-side Python gate.hetzner:python:commandsnow printsdocker compose ... ps --format json redis query-engine ingestion-worker.hetzner:python:psis guarded for native Linux x64/amd64 and will parse Docker Compose JSON on Hetzner to fail unlessredis,query-engine, andingestion-workerare allrunning.hetzner:python:preflightfails locally as expected because this machine isdarwin arm64with about 7.6 GiB free disk and no Docker Compose plugin, while the gate requires native Linux x64/amd64 and 40 GiB free disk.hetzner:runbook:planandhetzner:runbook:commandsprint 6 milestones and 28 commands.hetzner:runbook:checkfails locally as expected because this machine isdarwin arm64.hetzner:runbook:readinessrefuses to run with diagnostics override unlessHETZNER_RUNBOOK_CONFIRM=1is set.- Confirmed runbook milestone execution now writes redacted
docs/evidence/*-hetzner-runbook-<milestone>.mdfiles, but no confirmed milestone was executed locally. - Future runbook milestone evidence includes
Expected command countand a## Expected Commandsmanifest;port:completion:*requires this manifest before accepting a milestone as complete. port:completion:planandport:completion:statusrun locally.port:completion:checkfails locally as expected because local full-stack evidence, real server runtime config, runbook evidence, source-sync evidence, end-to-end evidence, and backup/restore evidence are missing.local:full-stack:planandlocal:full-stack:templaterun locally.local:full-stack:probeis available and performs live HTTP checks for the seven non-Python local URLs plushttp://127.0.0.1:5001/docsfor the Query Engine.local:full-stack:collectis available and refuses to write complete evidence unless all live HTTP probes pass,LOCAL_FULL_STACK_VERIFIERis set,LOCAL_FULL_STACK_EVIDENCE_CONFIRM=1is set, and both manual observation flags are set.local:full-stack:checkfails locally as expected because no completeddocs/evidence/*-local-full-stack.mdfile exists.platform:e2e:planandplatform:e2e:templaterun locally.platform:e2e:checkfails locally as expected because no completeddocs/evidence/*-platform-e2e.mdfile exists.hetzner:evidence:checkpasses locally and reports 18 configured read-only/status evidence commands.hetzner:backup:commandsprints the backup command list.hetzner:backup:commandsnow prints the Postgres dump with--env-file configs/hetzner/frontend-build.env.hetzner:backup:runrefuses locally withoutHETZNER_BACKUP_CONFIRM=1and refuses on macOS even with confirmation unless diagnostics override is explicitly set.hetzner:restore:commandsprints the destructive restore rehearsal command list without running it.hetzner:restore:commandsnow prints Docker Compose stop, Postgres restore, and restart commands with--env-file configs/hetzner/frontend-build.env.hetzner:restore:rehearserefuses locally withoutHETZNER_RESTORE_CONFIRM=1, refuses on macOS even with confirmation, and still refuses with diagnostics override whenconfigs/hetzner/backup.envis missing.- Python disk readiness is still below the local install/build guards; the latest Python gate preflight saw about 7.6 GiB free, below the 8 GiB install guard, 20 GiB Docker build guard, and 40 GiB Hetzner Python gate guard.
- Ingestion Worker install dry-run reports 307 installs; Query Engine install dry-run reports only
torchstill pending in the local venv. hetzner:checkpasses locally only for file presence and YAML fallback.hetzner:config:statusreports 8 real runtime config files missing locally.hetzner:config:checklistprints the required server value checklist from checked-in templates only and does not read runtime env values.hetzner:stack:commandsprints the exact server Compose commands.docs/evidence/currently has 0 real Hetzner evidence files.- There is no
docs/evidence/*-hetzner-backup.mdbackup evidence yet. - There is no
docs/evidence/*-backup-restore-rehearsal.mdrestore rehearsal evidence yet. configs/hetzner/currently has 0 real runtime env/Caddy files locally.
Completion Blockers
The goal cannot be marked complete until these are proven:
- Real runtime config files are created on Hetzner and
npm run hetzner:env:checkpasses. - Full local-stack evidence exists for Studio API, Picasso, Zweistein, Query Engine, Ingestion Worker, and Agent/AI runtime behavior.
- Source is actually synced to the Hetzner host with
npm run hetzner:sync:dry-runfollowed by confirmednpm run hetzner:sync:push. npm run hetzner:bootstrap:checkandnpm run hetzner:host:checkpass on native Linux/amd64.HETZNER_RUNBOOK_CONFIRM=1 npm run hetzner:runbook:readinesspasses on Hetzner.npm run hetzner:stack:configpasses with real server config.HETZNER_RUNBOOK_CONFIRM=1 npm run hetzner:runbook:pythonpasses on Hetzner.HETZNER_RUNBOOK_CONFIRM=1 npm run hetzner:runbook:buildpasses on Hetzner.HETZNER_RUNBOOK_CONFIRM=1 npm run hetzner:runbook:databasepasses on Hetzner.HETZNER_RUNBOOK_CONFIRM=1 npm run hetzner:runbook:stackpasses on Hetzner.HETZNER_RUNBOOK_CONFIRM=1 npm run hetzner:runbook:proxystarts the public edge after DNS/config is real.- One Studio Editor to Houston published App to Zweistein Agent/AI flow is manually verified.
npm run hetzner:evidence:collectwrites real evidence files underdocs/evidence/.- Backup and restore rehearsal evidence exists.
Next Concrete Action
Move from local preparation to a real Hetzner staging run:
npm run hetzner:sync:plan
npm run hetzner:sync:check
npm run db:local:check
npm run hetzner:db:plan
npm run hetzner:runbook:plan
npm run port:completion:plan
npm run hetzner:python:plan
npm run hetzner:stack:plan
npm run hetzner:stack:commands
Then run the listed server gates on a native Linux/amd64 Hetzner host and capture evidence.