5.9 KiB
Task 2 report — portable Compose contract
Status
Completed. The root Compose file is now a portable two-service base, with explicit local and server overrides. Workspace-registry configuration remains generic and continues to require an installation-provided Git remote.
Changed files
.env.example— shared non-secret, generic endpoint and registry examples.compose.yaml— portablecoreandfrontendbase, ownedthothiinetwork, health checks, named settings/Pi/registry/session volumes, and generic external endpoint variables.deploy/compose.local.yaml— loopback core/frontend ports,AUTH_MODE=none, local installation identity, and non-persistent restart policy.deploy/compose.server.yaml— frontend-only configurable host bind,AUTH_MODE=upstream, server identity, host-root data/Pi/registry mounts, and restart policy.deploy/env/local.env.exampleanddeploy/env/server.env.example— safe profile-specific values using.example.invaliddocumentation domains.scripts/test-default-compose.sh— default local portable Compose assertion.scripts/test-unified-compose.sh— JSON structural assertions for base/local/server plus the required missing-remote failure checks.
RED evidence
Before changing Compose, bash scripts/test-unified-compose.sh exited 1 with:
Error: forbidden application coupling
The failure was raised by the required assertion while the rendered root config still contained the portal-specific networks and host paths.
GREEN evidence
The following fresh commands completed with exit status 0:
bash scripts/test-default-compose.sh
# default Compose contract passed.
bash scripts/test-unified-compose.sh
# unified Compose contract passed.
bash -lc 'set -a; source deploy/env/local.env.example; set +a; docker compose -f compose.yaml -f deploy/compose.local.yaml config --quiet'
bash -lc 'set -a; source deploy/env/server.env.example; set +a; docker compose -f compose.yaml -f deploy/compose.server.yaml config --quiet'
bash scripts/verify-line-endings.sh
git diff --check
The two config --quiet invocations source only their non-secret profile example so the requested
commands can validate the required Git-remote interpolation without an operator .env file.
Self-review
- The base renders exactly
coreandfrontend; it has no portal, Chirone, local-LLM-network, or host-path coupling. - Local publishing is loopback-only; server has no core host port and publishes the frontend bind.
- The core retains outbound access for configured external DWH, vector, Git, embedding, and LLM endpoints; the owned Compose network is private to this stack but is not marked Docker-internal.
- The structural test validates the exact required service assertion, forbidden-coupling assertion,
required base network/volumes, profile port policy, and
THT_WORKSPACE_GIT_REMOTEfailure. - All new YAML and shell files were checked by the repository line-ending verifier.
Commit
2595d35682a5200b877acb71764b4eb195a39ea4 — deploy: unify local and server compose stack
Concerns
None for Task 2. Git and connector secret transport remains intentionally outside this base/profile contract and is addressed by the next scoped task.
Fix round 1/5 — Pi auth mount and generic LLM endpoint
Status
Completed. Pi’s mutable state remains writable, while provider authentication is supplied only by
the deterministic PI_AUTH_FILE host-file contract mounted read-only at Pi’s canonical
/home/thoth/.pi/agent/auth.json path. The base now exposes the generic THT_LLM_URL contract;
the local and server examples set only documentation endpoint values.
Changed files
compose.yaml— addsTHT_LLM_URLand a read-onlyPI_AUTH_FILEbind while retaining the writablepi-statevolume for non-secret runtime state.deploy/compose.server.yaml— retains the auth-file bind when its storage mounts override the portable base..env.example,deploy/env/local.env.example, anddeploy/env/server.env.example— document the generichttps://llm.example.invalidendpoint; profile examples also document the required host auth-file path without including a secret.scripts/test-unified-compose.sh— asserts generic LLM contract presence, no Docker socket/daemon mount, and exactly one read-only Pi auth file bind in the base and both profiles.
RED evidence
Before the Compose changes, this command exited 1:
bash scripts/test-unified-compose.sh
Error: core must expose a generic THT_LLM_URL endpoint contract
The failure was raised by the new structural assertion against the previous rendered base.
GREEN evidence
The following focused commands completed with exit status 0 after the fix:
bash scripts/test-unified-compose.sh
# unified Compose contract passed.
bash scripts/test-default-compose.sh
# default Compose contract passed.
docker compose --env-file deploy/env/local.env.example -f compose.yaml -f deploy/compose.local.yaml config --quiet
docker compose --env-file deploy/env/server.env.example -f compose.yaml -f deploy/compose.server.yaml config --quiet
bash scripts/verify-line-endings.sh
git diff --check
Self-review
- Both rendered profile contracts carry a single
bindmount to the Piauth.jsonfile withread_only: true; no auth value appears in Compose or the environment examples. - The writable Pi-state mount does not replace the read-only auth file, and the server override explicitly retains that file bind after replacing the base storage list.
- The structural regression test rejects any Docker socket/daemon mount and validates the generic LLM endpoint contract without adding provider-specific endpoints or hostnames.
- The deferred Minor report-wording finding was not changed.
Commit
2ce2e0089a66ca508db041a71db9807f66d0bf24 — fix: harden compose Pi auth mounts
Concerns
None for this focused round.