30 KiB
Unified Docker Compose Deployment Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Convert ThothII into one autonomous Docker Compose distribution for Windows, macOS, and Linux servers, with external configurable data/AI services, embedded Pi, guided Pi management, reproducible local builds, and deterministic line endings.
Architecture: compose.yaml is the sole complete stack definition; local and server files are small overrides. The mandatory stack contains only frontend and core; DWH, VectorDB, embedding, and LLM remain independently operated endpoints even when co-resident. Pi is pinned inside core; a Go thothctl executable wraps host-side Compose operations, while a web Pi Management page handles safe configuration and diagnostics.
Tech Stack: Docker BuildKit/Compose v2, Node.js 22, TypeScript/Fastify, React/Vite, nginx-unprivileged, Python 3.12 harness, Go 1.24 for thothctl, Vitest, Playwright, shell/PowerShell verification.
Design: docs/superpowers/specs/2026-08-04-unified-compose-deployment-design.md
Global Constraints
- ThothII has no active build/runtime dependency on PSD, Chirone, or
omics_portal. - The mandatory stack contains only
frontendandcore; it never starts DWH, VectorDB, embedding, LLM, or a reverse proxy. - External services use installation/workspace addresses even when they run on the Docker host.
- Pi is pinned inside
core; no host Pi or host Node/Python/Go runtime is required. corenever mounts a Docker daemon endpoint.- Secrets remain file-mounted under
/run/secretsand never enter Git, images, browser storage, rendered Compose, or logs. - Local ports bind to
127.0.0.1; server deployment publishes only the frontend port. - Shell, YAML, Dockerfile, JSON, TypeScript, Python, and Markdown use LF; PowerShell uses CRLF.
- Every task follows red-green TDD and ends with a reviewable commit.
Target file map
.gitattributes,.editorconfig,scripts/verify-line-endings.sh: line-ending contract.compose.yaml,deploy/compose.local.yaml,deploy/compose.server.yaml: portable stack and profiles.deploy/compose.git-*.yaml,deploy/compose.connector-secrets.yaml: optional secret mounts..env.example,deploy/env/*.env.example: non-secret operator contracts.docker/core.Dockerfile,docker/frontend.Dockerfile,docker/nginx.conf.template: reproducible images and same-origin routing.tools/thothctl/: cross-platform host control executable.backend/src/pi/management.ts,backend/src/routes/pi-management.ts: sanitized Pi APIs.frontend/src/api/pi-management.ts,frontend/src/shell/PiManagement.tsx: Pi operator UI.docs/install/local.md,docs/install/server.md,docs/install/pi-management.md: installation manuals.
Task 1: Enforce deterministic line endings
Files:
- Create:
.gitattributes - Create:
.editorconfig - Create:
scripts/verify-line-endings.sh - Create:
scripts/test-verify-line-endings.sh - Modify:
docker/core.Dockerfile - Test:
scripts/test-verify-line-endings.sh
Interfaces:
-
Produces:
scripts/verify-line-endings.sh [root], exit0when compliant and1with offending paths for CRLF. -
Consumes: tracked files at repository root or an explicit fixture root; never scans volumes or secrets.
-
Step 1: Write the failing verifier test
Create a temporary fixture with LF ok.sh and CRLF bad.sh, compose.yaml, and Dockerfile. Assert all bad paths are reported, ok.sh is absent, and LF-only input exits 0.
fixture_root="$(mktemp -d)"
trap 'rm -rf "$fixture_root"' EXIT
printf '#!/bin/sh\r\nexit 0\r\n' > "$fixture_root/bad.sh"
if ./scripts/verify-line-endings.sh "$fixture_root"; then
echo "expected CRLF rejection" >&2
exit 1
fi
- Step 2: Confirm red
Run: bash scripts/test-verify-line-endings.sh
Expected: failure because the verifier does not exist.
- Step 3: Add attributes, editor settings, and verifier
Use this .gitattributes contract:
* text=auto
*.sh text eol=lf
Dockerfile* text eol=lf
*.Dockerfile text eol=lf
*.yml text eol=lf
*.yaml text eol=lf
*.json text eol=lf
*.ts text eol=lf
*.tsx text eol=lf
*.py text eol=lf
*.md text eol=lf
*.ps1 text eol=crlf
Use git ls-files for the repository and find only for fixture mode. Detect carriage returns with LC_ALL=C grep -Il $'\r'. Add an image-build check before chmod of Docker scripts.
- Step 4: Renormalize and verify
Run:
git add --renormalize .
bash scripts/test-verify-line-endings.sh
bash scripts/verify-line-endings.sh
git diff --check
Expected: both scripts pass; review renormalized files to confirm line-ending-only changes.
- Step 5: Commit
git add .gitattributes .editorconfig scripts/verify-line-endings.sh scripts/test-verify-line-endings.sh docker/core.Dockerfile
git commit -m "build: enforce portable line endings"
Task 2: Define the portable Compose contract
Files:
- Modify:
compose.yaml - Modify:
deploy/compose.local.yaml - Create:
deploy/compose.server.yaml - Create:
deploy/env/local.env.example - Create:
deploy/env/server.env.example - Create:
.env.example - Modify:
scripts/test-default-compose.sh - Create:
scripts/test-unified-compose.sh
Interfaces:
-
Produces: base services
coreandfrontend, networkthothii, and volumessettings,pi-state,workspace-registry,sessions. -
Produces: supported pairs base+local and base+server.
-
Step 1: Write failing structural assertions
Render both profiles as JSON and assert:
const services = Object.keys(config.services).sort();
if (services.join(",") !== "core,frontend") throw new Error("mandatory stack must be core,frontend");
if (/omics_portal|chirone|localllm_default|\/home\/chirone/i.test(JSON.stringify(config))) {
throw new Error("forbidden application coupling");
}
Assert local publishes loopback frontend and optional loopback core; server publishes frontend only.
- Step 2: Confirm red
Run: bash scripts/test-unified-compose.sh
Expected: failure on current portal networks and host paths.
- Step 3: Replace root Compose with the portable base
Define only core, frontend, private network, health checks, and named volumes. depends_on may connect frontend to healthy core but never external services. Keep endpoint variables generic and secret-free.
- Step 4: Add local/server overrides
Local: AUTH_MODE=none, loopback ports, named volumes, installation ID local. Server: configurable frontend bind, AUTH_MODE=upstream, no core host port, THT_DATA_ROOT mounts, installation ID server.
- Step 5: Add environment examples
Use documentation domains such as https://dwh.example.invalid. Assert absent THT_WORKSPACE_GIT_REMOTE fails rendering with that exact variable name.
- Step 6: Verify and commit
bash scripts/test-default-compose.sh
bash scripts/test-unified-compose.sh
docker compose -f compose.yaml -f deploy/compose.local.yaml config --quiet
docker compose -f compose.yaml -f deploy/compose.server.yaml config --quiet
git add compose.yaml deploy/compose.local.yaml deploy/compose.server.yaml deploy/env .env.example scripts/test-default-compose.sh scripts/test-unified-compose.sh
git commit -m "deploy: unify local and server compose stack"
Task 3: Isolate Git and connector secrets
Files:
- Create:
deploy/compose.git-ssh.yaml - Create:
deploy/compose.git-https.yaml - Create:
deploy/compose.connector-secrets.yaml - Modify:
deploy/workspace-registry.env.example - Create:
scripts/test-compose-secret-policy.sh - Modify:
scripts/verify-workspace-install-docs.sh
Interfaces:
-
Produces: mutually exclusive Git overrides and explicit connector targets under
/run/secrets. -
Consumes:
THT_WS_*_FILEand host-only*_SOURCEvariables. -
Step 1: Write failing rendered-secret tests
Assert base has no /dev/null mounts; SSH mounts only key/known-hosts; HTTPS mounts only credentials/CA; connector mounts match declared _FILE targets; rendered output never contains fixture secret values.
- Step 2: Confirm red
Run: bash scripts/test-compose-secret-policy.sh
Expected: failure because secret mounts currently live in the portal-oriented base.
- Step 3: Implement overrides
Use read-only mounts and ${VAR:?message} only in selected overrides. Keep strict SSH host checking and HTTPS CA verification. Reject relative/non-normalized _SOURCE paths.
- Step 4: Verify and commit
bash scripts/test-compose-secret-policy.sh
bash scripts/test-verify-workspace-install-docs.sh
bash scripts/workspace-registry-smoke.sh
git add deploy/compose.git-ssh.yaml deploy/compose.git-https.yaml deploy/compose.connector-secrets.yaml deploy/workspace-registry.env.example scripts/test-compose-secret-policy.sh scripts/verify-workspace-install-docs.sh
git commit -m "deploy: isolate git and connector secrets"
Task 4: Make frontend-to-core routing same-origin
Files:
- Modify:
docker/nginx.conf.template - Modify:
docker/frontend-entrypoint.sh - Modify:
docker/frontend.Dockerfile - Modify:
frontend/src/api/runtime-config.ts - Test:
frontend/src/api/runtime-config.test.ts - Modify:
docker/smoke/frontend-policy-smoke.sh - Modify:
scripts/test-backend-url-policy.sh
Interfaces:
-
Produces: browser base
/api; nginx proxies tohttp://core:8787privately. -
Consumes: optional internal
THT_FRONTEND_API_UPSTREAMonly. -
Step 1: Write failing routing tests
Assert /api default, rejection of browser-facing absolute production URLs, and nginx SSE settings:
proxy_http_version 1.1;
proxy_buffering off;
proxy_read_timeout 3600s;
- Step 2: Confirm red
npm --prefix frontend test -- --run src/api/runtime-config.test.ts
bash scripts/test-backend-url-policy.sh
Expected: failure because deployment-specific build arguments remain.
- Step 3: Implement runtime routing and blocking frontend build
Build once with / assets and /api. Render private upstream at startup, strip /api, preserve SSE. Replace non-blocking typecheck with RUN npm run build. Remove /datamart-builder assumptions.
- Step 4: Verify and commit
npm --prefix frontend test -- --run src/api/runtime-config.test.ts
npm --prefix frontend run build
bash scripts/test-backend-url-policy.sh
bash docker/smoke/frontend-policy-smoke.sh
git add docker/nginx.conf.template docker/frontend-entrypoint.sh docker/frontend.Dockerfile docker/smoke/frontend-policy-smoke.sh frontend/src/api/runtime-config.ts frontend/src/api/runtime-config.test.ts scripts/test-backend-url-policy.sh
git commit -m "deploy: route frontend and core through one origin"
Task 5: Harden local image builds and embedded Pi
Files:
- Modify:
docker/core.Dockerfile - Modify:
docker/pi-runtime/package.json - Modify:
docker/pi-runtime/package-lock.json - Create:
.dockerignore - Modify:
docker/smoke/core-smoke.sh - Modify:
scripts/verify-container-images.sh - Create:
scripts/build-local.sh - Create:
scripts/build-local.ps1 - Test:
scripts/test-container-deployment.sh
Interfaces:
-
Produces:
corecontaining the pinned/usr/local/bin/piand a standalonefrontendimage. -
Produces: local build launchers requiring only Docker, Compose, and Git.
-
Step 1: Write failing image-contract assertions
Inside core, assert pi --version matches PI_VERSION, UID is 10001, Docker socket is absent, /data is writable, and no portal/Chirone path exists. Assert frontend health and /api routing.
- Step 2: Confirm red
Run: bash scripts/test-container-deployment.sh
Expected: failure on at least one old deployment contract.
- Step 3: Pin Pi from its lock input
Make docker/pi-runtime/package-lock.json the sole Pi dependency lock. Install with npm ci --omit=dev in a build stage, copy into core, and fail build when pi --version differs from PI_VERSION.
- Step 4: Add exclusions and platform launchers
Exclude .git, .worktrees, .env, secrets, dependencies, virtual environments, coverage, and runtime data. Both launchers run:
docker compose -f compose.yaml -f deploy/compose.local.yaml build --pull
They print the same next command and preserve Docker's exit code.
- Step 5: Verify and commit
bash scripts/build-local.sh
bash scripts/test-container-deployment.sh
bash scripts/verify-container-images.sh
git add .dockerignore docker/core.Dockerfile docker/pi-runtime docker/smoke/core-smoke.sh scripts/build-local.sh scripts/build-local.ps1 scripts/test-container-deployment.sh scripts/verify-container-images.sh
git commit -m "build: make embedded pi images reproducible"
Windows gate: powershell -ExecutionPolicy Bypass -File scripts/build-local.ps1.
Task 6: Build the cross-platform thothctl foundation
Files:
- Create:
tools/thothctl/go.mod - Create:
tools/thothctl/cmd/thothctl/main.go - Create:
tools/thothctl/internal/compose/runner.go - Create:
tools/thothctl/internal/config/installation.go - Create:
tools/thothctl/internal/output/sanitize.go - Test:
tools/thothctl/internal/compose/runner_test.go - Test:
tools/thothctl/internal/config/installation_test.go - Test:
tools/thothctl/internal/output/sanitize_test.go - Create:
docker/thothctl.Dockerfile - Create:
scripts/build-thothctl.sh
Interfaces:
-
Produces:
thothctl --installation <absolute-path> <command>binaries for Windows amd64, macOS amd64/arm64, Linux amd64/arm64. -
Produces:
Runner.Run(ctx, args, stdin) (Result, error)using argument arrays, never shell concatenation. -
Step 1: Write failing tests
Cover local/server Compose selection, paths containing spaces, missing Docker, propagated exit codes, and replacement of values matching password/token/key fields or secret-file contents with [REDACTED].
- Step 2: Confirm red
Run: docker run --rm -v "$PWD:/src" -w /src/tools/thothctl golang:1.24 go test ./...
Expected: failure because packages do not exist.
- Step 3: Implement installation discovery and safe runner
Read thothii-installation.yaml fields profile, projectDirectory, envFile, and overrides. Resolve and validate absolute paths. Invoke docker compose with exec.CommandContext argument slices.
- Step 4: Implement base commands
Add status, doctor, logs, start, stop, and update --check-only. doctor validates Docker/Compose versions, rendered config, LF, volumes, and frontend/core health without printing environment values.
- Step 5: Cross-compile with Docker and verify
Produce dist/thothctl/thothctl-windows-amd64.exe, Darwin amd64/arm64, and Linux amd64/arm64 from docker/thothctl.Dockerfile.
docker run --rm -v "$PWD:/src" -w /src/tools/thothctl golang:1.24 go test ./...
bash scripts/build-thothctl.sh
Run the host-matching binary with --help, then commit:
git add tools/thothctl docker/thothctl.Dockerfile scripts/build-thothctl.sh
git commit -m "feat: add cross-platform thothctl"
Task 7: Implement safe Pi lifecycle commands in thothctl
Files:
- Create:
tools/thothctl/internal/pi/commands.go - Create:
tools/thothctl/internal/pi/update.go - Create:
tools/thothctl/internal/pi/state.go - Test:
tools/thothctl/internal/pi/commands_test.go - Test:
tools/thothctl/internal/pi/update_test.go - Modify:
tools/thothctl/cmd/thothctl/main.go - Create:
docs/contracts/tht-pi.md
Interfaces:
-
Produces:
pi status|doctor|configure|test|update|logs. -
Produces:
.thothctl/update-state.jsonwith previous/new image references and phase, never credentials. -
Consumes: existing
/health,/models, and/settingsAPIs plusdocker compose exec core pi --version; Task 8 replaces the temporary composite checks with the dedicated Pi Management API. -
Step 1: Write failing update-state tests
With a fake Compose runner cover success and failure during build/pull, recreate, health, version, and smoke. Assert every post-recreate failure restores the prior image and leaves volume names unchanged.
- Step 2: Confirm red
Run: docker run --rm -v "$PWD:/src" -w /src/tools/thothctl golang:1.24 go test ./internal/pi -v
Expected: failure because Pi commands are absent.
- Step 3: Implement read-only commands
status runs core pi --version; doctor verifies image version, writable Pi volume, provider configuration presence, and /health; test combines /models, /settings, and a fixed core pi --version probe until Task 8 supplies the dedicated smoke endpoint; logs uses the shared sanitizer.
- Step 4: Implement guided configuration
Offer provider/model/reasoning choices returned by the backend. Atomically write non-secret defaults. For credentials print the expected secret filename and permissions; never accept secret text as an argument.
- Step 5: Implement transactional update
Record current image ID, pull/build requested pinned version, recreate only core, verify health/version/test, and roll back on failure. Refuse update while sessions are active unless --drain completes.
- Step 6: Verify and commit
docker run --rm -v "$PWD:/src" -w /src/tools/thothctl golang:1.24 go test ./internal/pi -v
docker run --rm -v "$PWD:/src" -w /src/tools/thothctl golang:1.24 go test ./...
git add tools/thothctl docs/contracts/tht-pi.md
git commit -m "feat: manage embedded pi with thothctl"
Task 8: Add sanitized Pi Management backend APIs
Files:
- Create:
backend/src/pi/management.ts - Create:
backend/src/routes/pi-management.ts - Modify:
backend/src/app.ts - Modify:
backend/src/config.ts - Modify:
tools/thothctl/internal/pi/commands.go - Test:
backend/test/pi-management.test.ts - Test:
backend/test/routes-pi-management.test.ts - Test:
tools/thothctl/internal/pi/commands_test.go
Interfaces:
-
Produces:
GET /pi-management/status,GET /pi-management/options,PUT /pi-management/config,POST /pi-management/test,GET /pi-management/logs. -
Produces: sanitized
PiStatus,PiOptions,PiInstallationConfig, and stable errors. -
Step 1: Write failing service/route tests
Mock process execution and settings. Assert version parsing, closed choices, free-field validation, atomic writes, smoke timeout, 200-line log limit, redaction, and 403 pi_management_forbidden in exposed server mode without trusted admin identity.
- Step 2: Confirm red
Run: cd backend && npx vitest run test/pi-management.test.ts test/routes-pi-management.test.ts
Expected: module-not-found failure.
- Step 3: Implement service and authorization
Use execFile with fixed argument arrays. Return only version, readiness, provider names, model IDs, reasoning choices, timestamps, and sanitized messages. Allow AUTH_MODE=none only when public exposure is false; upstream mode requires the documented admin claim. Expose no image-update API.
- Step 4: Switch
thothctlto the dedicated API
Replace the Task 7 composite /health//models//settings test with POST /pi-management/test; load closed configuration choices from GET /pi-management/options. Preserve the direct in-container pi --version check as an independent image-integrity signal.
- Step 5: Verify and commit
cd backend
npx vitest run test/pi-management.test.ts test/routes-pi-management.test.ts
npx vitest run
npx tsc --noEmit -p .
cd ..
docker run --rm -v "$PWD:/src" -w /src/tools/thothctl golang:1.24 go test ./internal/pi -v
git add backend/src/pi/management.ts backend/src/routes/pi-management.ts backend/src/app.ts backend/src/config.ts backend/test/pi-management.test.ts backend/test/routes-pi-management.test.ts tools/thothctl/internal/pi/commands.go tools/thothctl/internal/pi/commands_test.go
git commit -m "feat: expose safe pi management api"
Task 9: Add the Pi Management interface
Files:
- Create:
frontend/src/api/pi-management.ts - Create:
frontend/src/api/pi-management.test.ts - Create:
frontend/src/shell/PiManagement.tsx - Create:
frontend/src/shell/PiManagement.test.tsx - Modify:
frontend/src/shell/AppShell.tsx - Modify:
frontend/src/shell/AppShell.session-mgmt.test.tsx
Interfaces:
-
Consumes: Task 8 Pi APIs.
-
Produces: right-sidebar Pi Management panel without image-update execution or browser terminal.
-
Step 1: Write failing UI tests
Cover loading/version, closed selects, validation, save, smoke test, sanitized logs, forbidden state, and copyable thothctl pi update instruction. Assert no secret input or browser terminal.
- Step 2: Confirm red
Run: cd frontend && npx vitest run src/shell/PiManagement.test.tsx src/api/pi-management.test.ts
Expected: module-not-found failure.
- Step 3: Implement API and panel
Use query keys ['pi-management','status'] and ['pi-management','options']. Render provider/model/reasoning as closed choices, validate numeric fields before PUT, and show credentials only as present/missing.
- Step 4: Attach to the right sidebar
Add Pi next to Workspace Management, preserve current session/activity panels and accessibility, and remove AppShell comments/layout assumptions about Omics Portal chrome.
- Step 5: Verify and commit
cd frontend
npx vitest run src/shell/PiManagement.test.tsx src/api/pi-management.test.ts src/shell/AppShell.session-mgmt.test.tsx
npx vitest run
npx tsc -b
git add src/api/pi-management.ts src/api/pi-management.test.ts src/shell/PiManagement.tsx src/shell/PiManagement.test.tsx src/shell/AppShell.tsx src/shell/AppShell.session-mgmt.test.tsx
git commit -m "feat: add pi management interface"
Task 10: Remove active PSD and portal deployment coupling
Files:
- Delete:
deploy/compose.production.yaml - Delete:
deploy/compose.psd-local.yaml.example - Modify:
README.md - Modify:
PROJECT_STATE.md - Modify:
scripts/run-stack.sh - Create:
scripts/test-no-deployment-coupling.sh - Modify:
scripts/test-external-compose-lifecycle.sh
Interfaces:
-
Produces: active deployment files free of PSD/Chirone/portal networks, paths, and prefixes.
-
Preserves: generic external endpoint support and historical design documents.
-
Step 1: Write the failing coupling scan
Scan active Compose, Docker, root README, install guides, env examples, and run scripts for omics_portal, /home/chirone, localllm_default, datamart-builder, and PSD deployment filenames. Exclude historical specs/plans and canonical workspace content.
- Step 2: Confirm red
Run: bash scripts/test-no-deployment-coupling.sh
Expected: failure listing current portal-oriented files.
- Step 3: Remove superseded files and genericize launch behavior
Delete only deployment files replaced by Tasks 2–5. Make run-stack.sh call base+local or direct users to thothctl start. Preserve data migration utilities that do not affect runtime coupling.
- Step 4: Update root documentation and verify
State that co-location never puts DWH/vector/embedding inside ThothII.
bash scripts/test-no-deployment-coupling.sh
bash scripts/test-unified-compose.sh
bash scripts/test-external-compose-lifecycle.sh
git add -A deploy/compose.production.yaml deploy/compose.psd-local.yaml.example README.md PROJECT_STATE.md scripts/run-stack.sh scripts/test-no-deployment-coupling.sh scripts/test-external-compose-lifecycle.sh
git commit -m "refactor: remove portal deployment coupling"
Task 11: Write and verify the PC/Mac installation manual
Files:
- Create:
docs/install/local.md - Create:
docs/install/windows-line-endings.md - Create:
docs/install/pi-management.md - Create:
docs/install/examples/thothii-installation.local.yaml - Modify:
docs/install/local-workspace-registry.md - Modify:
scripts/verify-workspace-install-docs.sh - Modify:
scripts/test-verify-workspace-install-docs.sh
Interfaces:
-
Produces: complete clean-install, build, update, backup, restore, Pi, and CRLF instructions for Windows/WSL2, macOS, and Linux PC.
-
Step 1: Extend the verifier first
Require prerequisites, Git clone, LF verification, .env, external-service addressing, build, start, health, browser URL, thothctl, Pi update/rollback, backup/restore, pull update, and data-preserving uninstall. Require pi-management.md to cover UI permissions, every thothctl pi command, secret handling, direct support access, and failed-update recovery. Copy examples to a temporary path containing spaces and render there.
- Step 2: Confirm red
Run: bash scripts/test-verify-workspace-install-docs.sh
Expected: failure naming missing local-guide sections.
- Step 3: Write platform-specific instructions
Document macOS, Windows PowerShell, Windows WSL2, and Linux separately. Recommend cloning inside the WSL filesystem. Include LF checks after clone/pull. For an existing CRLF clone, prefer recloning; describe repository-local core.autocrlf=false and renormalization. If mentioning git reset --hard, require explicit backup/commit and a destructive-action warning immediately before it.
- Step 4: Document external services on the host
Show host.docker.internal for Docker Desktop and extra_hosts: host.docker.internal:host-gateway for Linux. Explain that container 127.0.0.1 is not the host. All addresses remain configurable.
- Step 5: Verify and commit
bash scripts/test-verify-workspace-install-docs.sh
bash scripts/verify-workspace-install-docs.sh --profile local
bash scripts/docker-smoke.sh
git add docs/install/local.md docs/install/windows-line-endings.md docs/install/pi-management.md docs/install/examples/thothii-installation.local.yaml docs/install/local-workspace-registry.md scripts/verify-workspace-install-docs.sh scripts/test-verify-workspace-install-docs.sh
git commit -m "docs: add autonomous local installation guide"
Task 12: Write and verify the server installation manual
Files:
- Create:
docs/install/server.md - Create:
docs/install/reverse-proxy-nginx.md - Create:
docs/install/reverse-proxy-caddy.md - Create:
docs/install/examples/thothii-installation.server.yaml - Modify:
docs/install/server-workspace-registry.md - Modify:
scripts/verify-workspace-install-docs.sh - Test:
scripts/test-verify-workspace-install-docs.sh
Interfaces:
-
Produces: generic Linux server deployment independent of another application's network.
-
Consumes: server profile, secret overrides,
thothctl, and same-origin frontend. -
Step 1: Add failing server-guide assertions
Require service account/UID, directories, firewall, co-resident external endpoints, DNS/host-gateway choices, generic TLS proxy, upstream auth, local build or pinned images, startup, readiness, Pi management, drain, rollback, backup, restore, and diagnostics.
- Step 2: Confirm red
Run: bash scripts/test-verify-workspace-install-docs.sh
Expected: failure naming missing server sections.
- Step 3: Write the server and proxy guides
Use /srv/thothii only as an example operator root. State that DWH/vector/embedding on the same physical machine remain independently addressed services. Nginx/Caddy proxy only to frontend, preserve SSE, terminate TLS, and forward identity only after authentication.
- Step 4: Verify and commit
bash scripts/test-verify-workspace-install-docs.sh
bash scripts/verify-workspace-install-docs.sh --profile server
bash scripts/test-unified-compose.sh
git add docs/install/server.md docs/install/reverse-proxy-nginx.md docs/install/reverse-proxy-caddy.md docs/install/examples/thothii-installation.server.yaml docs/install/server-workspace-registry.md scripts/verify-workspace-install-docs.sh scripts/test-verify-workspace-install-docs.sh
git commit -m "docs: add autonomous server installation guide"
Task 13: Add end-to-end deployment and update gates
Files:
- Create:
scripts/unified-deployment-smoke.sh - Create:
scripts/thothctl-update-smoke.sh - Create:
scripts/test-windows-clone-contract.ps1 - Create:
.github/workflows/deployment.yml - Modify:
PROJECT_STATE.md - Modify:
README.md
Interfaces:
-
Produces: release gate for rendering, image build, embedded Pi, registry persistence, offline recovery, and update rollback.
-
Step 1: Write failing orchestration smoke
Create an isolated Compose project and bare Git registry, build, start local, verify frontend/core/Pi/registry, recreate offline, perform a valid Git update, and prove volumes survive. Inject a bad Pi image/version and prove rollback.
- Step 2: Confirm red
Run: bash scripts/unified-deployment-smoke.sh
Expected: failure because the script is absent.
- Step 3: Implement exact-resource cleanup
Generate a unique project name and temporary directory, label resources, and remove only those exact resources on exit. Never prune global Docker state. Sanitize captured logs.
- Step 4: Add Windows and CI gates
PowerShell scans tracked shell/YAML/Docker files for byte 0x0D, renders Compose, and invokes Windows thothctl. CI runs LF and TypeScript gates everywhere, Docker smoke on Linux, and clone/Compose contract on Windows.
- Step 5: Run final verification
bash scripts/verify-line-endings.sh
bash scripts/test-unified-compose.sh
bash scripts/test-compose-secret-policy.sh
bash scripts/unified-deployment-smoke.sh
bash scripts/thothctl-update-smoke.sh
bash scripts/test-verify-workspace-install-docs.sh
cd backend && npx vitest run && npx tsc --noEmit -p .
cd ../frontend && npx vitest run && npx tsc -b
cd ../harness && .venv/bin/pytest -q
Expected: all non-L2 tests pass; Docker-dependent harness tests run on a Docker-capable host.
- Step 6: Commit
git add scripts/unified-deployment-smoke.sh scripts/thothctl-update-smoke.sh scripts/test-windows-clone-contract.ps1 .github/workflows/deployment.yml PROJECT_STATE.md README.md
git commit -m "test: gate unified compose deployment"
Completion criteria
- Clean GitHub clones build/run on Windows Docker Desktop/WSL2 and macOS using only Docker, Compose, and Git.
- The same source/images deploy on Linux through the server override.
- Active deployment files contain no PSD, Chirone, or
omics_portaldependency. - DWH, VectorDB, embedding, and LLM are always configurable external endpoints.
- Pi exists in
core, is configurable through Pi Management, and is safely updated bythothctl. - Git attributes prevent CRLF and verification catches corruption before image startup.
- Local/server guides pass executable documentation checks.
- Failed updates restore the previous image while preserving registry, sessions, settings, and Pi state.