8.1 KiB
Simple Docker Configuration Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development to implement this plan task-by-task with review checkpoints.
Goal: Make a fresh ThothII clone runnable with docker compose up --build -d, using one
deploy/secrets/thothii.secrets bundle while preserving a tested legacy fallback.
Architecture: A strict Python secret-bundle loader becomes the single in-process source of
secret values. Compose mounts the one bundle only where needed; the core converts values to
provider/database runtime interfaces without logging or placing them in argv. The root .env
is the default Compose interpolation file and selects the appropriate overlay through
COMPOSE_FILE/COMPOSE_PROFILES; legacy THT_*_SECRET_FILE installations remain supported.
Tech Stack: Docker Compose v2, YAML, Python 3.12/Pydantic, Fastify/TypeScript, shell smoke tests, pytest, Vitest.
Global Constraints
- The normal command must be exactly
docker compose up --build -dfromThothII/. - The canonical secret bundle is
deploy/secrets/thothii.secrets, key/value syntax, mode0600, ignored by Git and excluded from image build contexts. - Secret values must never appear in Compose config output, logs, argv, settings, health, or committed workspace files.
- Existing
THT_*_SECRET_FILEvariables remain a documented compatibility path until removed by a later migration. - External, local-vector, and preprocess overlays must remain independently renderable.
- Provider compound credentials remain fail-closed; only supported single-key providers are restored from the bundle.
- Every task starts with a failing regression test and ends with focused tests, diff checks, and a small commit.
Task 1: Add the strict secret-bundle loader and compatibility adapter
Files:
- Create:
backend/src/config/secret-bundle.ts - Modify:
backend/src/config.ts - Modify:
backend/src/pi/provider-credentials.ts - Modify:
backend/src/pi/pi-process-manager.ts - Modify:
backend/src/pi/list-models.ts - Create:
backend/test/secret-bundle.test.ts - Modify:
backend/test/provider-credentials.test.ts - Modify:
backend/test/pi-process-manager.test.ts - Modify:
backend/test/list-models.test.ts
Interfaces:
-
loadSecretBundle(file: string): ReadonlyMap<string, string>validatesNAME=VALUElines, duplicate/unknown/empty keys,lstat/open(O_NOFOLLOW)/fstatidentity, owner and mode. -
secretValue(config, key)first readsTHT_SECRETS_FILE, then falls back to the existingTHT_*_SECRET_FILEvariable for compatibility. -
The existing provider environment builder consumes a value map, so session and model-listing children share identical scrubbing and canonical-provider mapping.
-
Step 1: Write failing tests for valid bundle parsing, comments/blank lines, duplicate keys, unknown keys, missing file, mode/owner failure, inode replacement, and secret redaction.
-
Step 2: Run
cd backend && npx vitest run test/secret-bundle.test.ts; expected failure because the loader does not exist. -
Step 3: Implement the loader with bounded line lengths, strict key allowlist, no shell evaluation, sanitized errors, and legacy adapter lookup.
-
Step 4: Add tests proving session spawn and model listing use the same bundle values and do not inherit bundle path or unselected provider credentials.
-
Step 5: Run
cd backend && npm run build && npx tsc --noEmit -p . && npx vitest run; expected all backend tests pass. -
Step 6: Commit
git commit -m "feat(config): load one validated secret bundle".
Task 2: Make the root Compose command the default
Files:
- Create:
.env.example - Modify:
.gitignore - Modify:
compose.yaml - Modify:
deploy/compose.production.yaml - Modify:
deploy/compose.local.yaml - Modify:
deploy/env.example - Create:
deploy/secrets/thothii.secrets.example - Create:
scripts/test-default-compose.sh - Modify:
scripts/test-container-deployment.sh
Interfaces:
-
Root
.envis Compose's automatic interpolation file;.env.examplecontains relativeTHT_SECRETS_FILE=deploy/secrets/thothii.secrets, defaultCOMPOSE_FILE=compose.yaml, and the selected overlay/profile values. -
compose.yamlstartscoreandfrontendwithout requiring a profile; overlays extend it. -
Core receives one
/run/secrets/thothii.secretsmount andTHT_SECRETS_FILEpath. -
Step 1: Write failing static tests that run
docker compose config --quietfrom a temporary clone with.envand assert the default services arecoreandfrontend, one bundle is declared, and no legacy secret file is required. -
Step 2: Run
./scripts/test-default-compose.sh; expected failure because root defaults still require profiles/separate secret files. -
Step 3: Implement
.env.example,.gitignore, Compose defaults and one secret mount. Preservedeploy/compose.production.yamlas an optional authenticated production override. -
Step 4: Run
docker compose --env-file .env.example config --quietand the existing deployment/security scripts; expected no secret values in rendered YAML. -
Step 5: Commit
git commit -m "build(compose): make root startup the default".
Task 3: Convert local-vector and preprocess services to the bundle
Files:
- Modify:
deploy/compose.local-vector.yaml - Modify:
deploy/compose.preprocess-local-vector.yaml - Modify:
deploy/compose.preprocess.yaml - Modify:
deploy/workspaces/local-vector.yaml - Modify:
deploy/workspaces/preprocess-evidence.yaml - Modify:
deploy/workspaces/preprocess-dwh.yaml - Modify:
scripts/local-vector-smoke.sh - Modify:
scripts/preprocess-smoke.sh - Modify:
scripts/test-preprocess-compose-config.sh - Modify:
scripts/test-vector-backup-restore-safety.sh
Interfaces:
-
Every local-vector/preprocess service reads the same mounted bundle path and selects only the named value through the shared loader/helper.
-
No service declares four file-backed Compose secrets after this task.
-
Step 1: Add failing tests asserting one bundle mount, no
vector_*_passwordsecret declarations, and valid local-vector workspace resolution. -
Step 2: Run focused Compose config and smoke tests; expected failure with current separate-secret declarations.
-
Step 3: Implement bundle mounts and helper invocations for bootstrap/migrator/reader/ writer operations, keeping passwords out of URLs and shell logs.
-
Step 4: Run
./scripts/test-preprocess-compose-config.sh, local-vector smoke and preprocess smoke with a clean generated project; expected all pass. -
Step 5: Commit
git commit -m "feat(compose): use one secret bundle for local services".
Task 4: Finish documentation and end-to-end default verification
Files:
- Modify:
README.md - Modify:
docs/installazione-docker-4-contesti.md - Modify:
docs/index.md - Modify:
deploy/secrets/README.md - Modify:
scripts/docker-smoke.sh - Modify:
scripts/test-default-compose.sh
Interfaces:
-
Installation docs show only
cp .env.example .env, create/fill one bundle, thendocker compose up --build -d. -
Advanced overlays are shown as optional
.envpresets, not mandatory command-line flags. -
Step 1: Add failing documentation/smoke assertions for the exact command and default files.
-
Step 2: Implement concise context-specific instructions and migration notes for old separate secret files.
-
Step 3: Run all shell syntax/config gates, backend/frontend builds/tests, full harness, default Docker smoke, local-vector smoke, preprocess smoke and
git diff --check. -
Step 4: Commit
git commit -m "docs: document one-command Docker installation".
Task 5: Whole-plan review and handoff
- Review
a6b195b..HEADagainst this plan and confirm no secret leakage, profile regression, or legacy fallback bypass. - Run the complete verification matrix and report exact counts, skipped L2 tests, and any unavailable Docker/registry prerequisites.
- Keep the branch/worktree intact for the user's integration choice.