Audits · audits/2026-05-05-hetzner-port-completion-audit.md Docs Home

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:

  1. Work happens only in LegacyBlinkin-2-Hetzner, not in blinkin-2-platform.
  2. The legacy Picasso FE, Zweistein, and Studio API source trees are present in the new project.
  3. Real secrets and real runtime env files are not copied or committed.
  4. Local rebuild slices prove each major service can install/build/start where the current machine can support it.
  5. A local runtime map shows the whole platform assembly order and current gaps.
  6. Hetzner deployment files exist for the full platform stack.
  7. Hetzner runtime config is initialized safely from templates and passes strict placeholder checks on the server.
  8. 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.
  9. 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:verify passed.
  • hetzner:sync:check passed; it reported 0 local Hetzner runtime env/Caddy files and warned that root .env is excluded by the rsync filter.
  • hetzner:sync:target fails locally as expected without HETZNER_SYNC_TARGET and refuses non-standard remote paths before SSH.
  • hetzner:sync:push refuses to run rsync --delete without HETZNER_SYNC_CONFIRM=1 or --yes.
  • Successful source sync dry-run and push commands now write redacted docs/evidence/*-hetzner-source-sync-*.md files.
  • db:local:check passed; 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.ts or src/migrations directory and currently relies on the primary TypeORM connection's synchronize:true for schema creation.
  • legacy:runtime:smoke:non-python passed and left the seven app ports free after shutdown.
  • legacy:runtime:missing reports no missing required runtime assembly files.
  • legacy:runtime:status during the repeatable coordinated smoke showed all non-Python app services responding with HTTP 200.
  • hetzner:python:plan and hetzner:python:commands print the new server-side Python gate.
  • hetzner:python:commands now prints docker compose ... ps --format json redis query-engine ingestion-worker.
  • hetzner:python:ps is guarded for native Linux x64/amd64 and will parse Docker Compose JSON on Hetzner to fail unless redis, query-engine, and ingestion-worker are all running.
  • hetzner:python:preflight fails locally as expected because this machine is darwin arm64 with 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:plan and hetzner:runbook:commands print 6 milestones and 28 commands.
  • hetzner:runbook:check fails locally as expected because this machine is darwin arm64.
  • hetzner:runbook:readiness refuses to run with diagnostics override unless HETZNER_RUNBOOK_CONFIRM=1 is set.
  • Confirmed runbook milestone execution now writes redacted docs/evidence/*-hetzner-runbook-<milestone>.md files, but no confirmed milestone was executed locally.
  • Future runbook milestone evidence includes Expected command count and a ## Expected Commands manifest; port:completion:* requires this manifest before accepting a milestone as complete.
  • port:completion:plan and port:completion:status run locally.
  • port:completion:check fails 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:plan and local:full-stack:template run locally.
  • local:full-stack:probe is available and performs live HTTP checks for the seven non-Python local URLs plus http://127.0.0.1:5001/docs for the Query Engine.
  • local:full-stack:collect is available and refuses to write complete evidence unless all live HTTP probes pass, LOCAL_FULL_STACK_VERIFIER is set, LOCAL_FULL_STACK_EVIDENCE_CONFIRM=1 is set, and both manual observation flags are set.
  • local:full-stack:check fails locally as expected because no completed docs/evidence/*-local-full-stack.md file exists.
  • platform:e2e:plan and platform:e2e:template run locally.
  • platform:e2e:check fails locally as expected because no completed docs/evidence/*-platform-e2e.md file exists.
  • hetzner:evidence:check passes locally and reports 18 configured read-only/status evidence commands.
  • hetzner:backup:commands prints the backup command list.
  • hetzner:backup:commands now prints the Postgres dump with --env-file configs/hetzner/frontend-build.env.
  • hetzner:backup:run refuses locally without HETZNER_BACKUP_CONFIRM=1 and refuses on macOS even with confirmation unless diagnostics override is explicitly set.
  • hetzner:restore:commands prints the destructive restore rehearsal command list without running it.
  • hetzner:restore:commands now prints Docker Compose stop, Postgres restore, and restart commands with --env-file configs/hetzner/frontend-build.env.
  • hetzner:restore:rehearse refuses locally without HETZNER_RESTORE_CONFIRM=1, refuses on macOS even with confirmation, and still refuses with diagnostics override when configs/hetzner/backup.env is 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 torch still pending in the local venv.
  • hetzner:check passes locally only for file presence and YAML fallback.
  • hetzner:config:status reports 8 real runtime config files missing locally.
  • hetzner:config:checklist prints the required server value checklist from checked-in templates only and does not read runtime env values.
  • hetzner:stack:commands prints the exact server Compose commands.
  • docs/evidence/ currently has 0 real Hetzner evidence files.
  • There is no docs/evidence/*-hetzner-backup.md backup evidence yet.
  • There is no docs/evidence/*-backup-restore-rehearsal.md restore 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:

  1. Real runtime config files are created on Hetzner and npm run hetzner:env:check passes.
  2. Full local-stack evidence exists for Studio API, Picasso, Zweistein, Query Engine, Ingestion Worker, and Agent/AI runtime behavior.
  3. Source is actually synced to the Hetzner host with npm run hetzner:sync:dry-run followed by confirmed npm run hetzner:sync:push.
  4. npm run hetzner:bootstrap:check and npm run hetzner:host:check pass on native Linux/amd64.
  5. HETZNER_RUNBOOK_CONFIRM=1 npm run hetzner:runbook:readiness passes on Hetzner.
  6. npm run hetzner:stack:config passes with real server config.
  7. HETZNER_RUNBOOK_CONFIRM=1 npm run hetzner:runbook:python passes on Hetzner.
  8. HETZNER_RUNBOOK_CONFIRM=1 npm run hetzner:runbook:build passes on Hetzner.
  9. HETZNER_RUNBOOK_CONFIRM=1 npm run hetzner:runbook:database passes on Hetzner.
  10. HETZNER_RUNBOOK_CONFIRM=1 npm run hetzner:runbook:stack passes on Hetzner.
  11. HETZNER_RUNBOOK_CONFIRM=1 npm run hetzner:runbook:proxy starts the public edge after DNS/config is real.
  12. One Studio Editor to Houston published App to Zweistein Agent/AI flow is manually verified.
  13. npm run hetzner:evidence:collect writes real evidence files under docs/evidence/.
  14. 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.