Files
truf-server/DOCKER_MIGRATION.md
2026-09-30 20:30:56 +03:00

419 lines
32 KiB
Markdown

# Docker Development Copy
Status: runnable Linux container deployment with a passed fresh offline E2E.
Production source/provider parity and original-data migration are not proven.
Original Windows installation: `D:\truf`. Development copy: `D:\truf-docker`.
Only the development copy is changed; the original `D:\truf` and storage on `S:`
remain untouched. No original STOP or START was performed for this migration.
Docker/Compose installation in WSL was user-approved and has occurred. Earlier
statements about unavailable Docker, no installations, and no images describe
historical stages, not the current deployment.
The current acceptance evidence is from the isolated Docker runs on 2026-09-15.
The historical original-runtime lineage proof was not rerun.
## Copy And Local History
These are historical source-copy/baseline records, not a fresh Git inventory.
- The user changed the initial full-snapshot request to a source-only copy.
- The retained source selection was 295 files, approximately 6.82 MiB before Git and migration edits.
- Application Python, tests, configuration, documentation, OpenSpec artifacts, and project scripts were retained.
- Databases, WAL/SHM files, results, queues, logs, runtime state, provider input pools, real secrets, native Windows bundles, and dependency caches were omitted or removed from the copy.
- The partial external-data copy `D:\truf-docker-data` was removed. Original external storage on `S:` was not modified.
- SHA-256 comparison verified the selected source files before migration edits. The clone's `.gitignore` was strengthened before staging.
- Initial local commit: `1b3c7fc`, `chore: snapshot source for Docker migration`, 292 tracked files on `main`.
- Three copied OpenCode package metadata files remain ignored by their original nested ignore policy.
- No remote, push, Git configuration change, or second commit was made. Migration edits remain separate from the baseline.
## Safety Boundary
Copied root PowerShell tools and direct canonical Python runtime/control CLI
launches retain their staging refusals. The supported container path is the
image's `tini -> python3 -u -I -S -B app/container_runtime.py` entrypoint, which
uses authenticated bootstrap dispatch rather than removing host safeguards.
Do not use copied Windows maintenance/import scripts to operate this deployment.
The original `app/config.yaml` is preserved in the initial Git commit and in the
unchanged original installation. In this working tree it was renamed to
`app/config.linux.yaml`. The initial slice changed filesystem/deployment paths
only; subsequent container contracts fix private storage and control paths.
There is no automatically selected `app/config.yaml`; the container entrypoint
defaults explicitly to `/opt/truf/app/config.linux.yaml`. This production profile
is distinct from the verifier's deliberately narrowed `/data/config/e2e.yaml`.
The image requires read-only application storage, UID/GID 10001 for runtime
commands, a private native Linux named volume at `/data`, and private tmpfs at
`/run/truf`. Provisioning alone runs as root, with only CHOWN, DAC_OVERRIDE, and
FOWNER added to the dropped capability set. Private application/data directories
are mode 0700 and files 0600. System executables remain root-owned and immutable;
they must not be chowned to the application user to satisfy private-file checks.
PostgreSQL 16 runs under the supervisor in the same container, with generated
private credentials, loopback connectivity, and exact cluster identity binding.
External PostgreSQL authority is not implemented; changing a DSN or starting a
separate PostgreSQL service does not implement that backend. Never reuse physical
Windows PGDATA on Linux. Any original-data migration requires separately
approved logical export/import and validation. No host data bind mount, Docker
socket, privileged mode, or Docker-in-Docker is required for DockerHub scanning.
## Implemented Foundation
- Path defaults derive from this checkout instead of `D:\truf` or the current working directory.
- Generated filesystem templates use portable separators. Explicit YAML still overrides environment defaults.
- POSIX path resolution rejects Windows drive, UNC, device, and backslash syntax rather than silently joining it to a Linux directory.
- Generic path defaults retain the runtime-relative result-bundle directory and PostgreSQL's `runtime/postgres/data` suffix; the container profile explicitly selects the separate `/data` paths listed below.
- The Windows TruffleHog fallback is checked only on Windows. Managed PostgreSQL DSN precedence is unchanged.
- `.gitignore` excludes credentials and consumables. `.dockerignore` denies everything except reviewed, explicitly named build/source files, including nested provider modules.
- `.gitattributes` specifies LF for Linux-facing source/configuration files without changing global Git settings.
- Offline tests cover path behavior, the Linux profile, context allowlist, and refusal of copied control entrypoints.
## Implemented Lifecycle Changes
The lifecycle changes in `app/owned_process.py` and `app/supervisor.py` implement
Linux ownership and coordinated foreground shutdown. Native Linux ownership
tests and the fresh container E2E now pass within their selected scope; this is
not acceptance of every production source/provider or unsafe failure scenario.
- Linux startup now reports complete kernel-derived identities, verifies the host and payload sessions, and requires a verified child subreaper. Unreadable or already-exited executables fail startup rather than receiving a PID-only identity.
- Nested observers have independent sessions. Cleanup signals the still-pinned payload group before reaping its leader, then drains adopted children. Completed adopted observers are also reaped while the root remains alive.
- Payload signal status is reproduced only after cleanup, including SIGKILL as a real negative subprocess return code. Administrative stop remains a distinct nonzero result.
- Linux failed-start cleanup retains its observer through repeated interruptions until exit is confirmed; it does not hard-kill that observer on a timer.
- A configured owner sends an explicit stop byte over its retained pipe, so another inherited writer cannot suppress cancellation. Forked proxy finalization only detaches its local descriptor, without signalling the owner's job or taking an inherited mutex.
- Startup status descriptors have a single atomic owner. An unclaimed reader is cancelled before waiting for host cleanup, avoiding double close, reused-FD reads, and a blocked status writer during interrupted thread startup.
- Windows keeps its Job Object containment and resource checks. Its isolated host now uses the base interpreter rather than a virtual-environment redirecting launcher, so the retained process and acknowledged identity have the same PID.
- The supervisor's POSIX SIGTERM callback only latches a shutdown request. Locked checkpoints close admission before activation or further starts, and preserve coordinated child-before-PostgreSQL teardown.
- Metadata publication and shutdown interruptions retain closed gates and unsafe authority in `FAILED_HOLD`. Partial activation uses full coordinated cleanup; failures remain nonzero even if a later cleanup retry succeeds.
- Foreground and background shutdown publish the same instance-bound receipt after fallible control/log cleanup. The waiting authenticated stopper or locked stale reconciliation removes metadata; foreground no longer deletes it before the stopper can verify completion.
- PostgreSQL stop and close share one remaining timeout. This is not a bound on the complete shutdown sequence: unsafe authority is retained indefinitely rather than released when a timer expires.
Additional container work is implemented, rather than still pending:
- Source-start rollback retains uncertain owners and closes admission; locked stale-metadata reconciliation uses exact identity rather than PID alone.
- Durable state stays on `/data`; recoverable control metadata is under `/run/truf/control` and does not survive recreation.
- Linux manifests distinguish private application files from root-owned native binaries; the obsolete Windows OpenRouter PowerShell dependency is not the Linux provider entrypoint.
- `Dockerfile` packages Python 3.12.14, PostgreSQL 16.15, Git, tini, and hash-locked Python dependencies in the production server. TruffleHog 3.97.4 is pinned only in worker and test targets; the remote-only production server does not contain it.
- Fresh provisioning, empty-cluster initialization, 27 schema migrations, final cutover, and initialization/identity markers are implemented. Partial initialization fails closed and is not automatically repaired or adopted.
- Compose applies a read-only root filesystem, dropped capabilities, no-new-privileges, 2 CPUs, 6 GiB memory, 512 PIDs, 256 MiB shared memory, and bounded log rotation. Tini forwards SIGTERM to the foreground runtime/supervisor, not indiscriminately to its process group.
- Dependency-aware health checks require authenticated ACTIVE control, READY PostgreSQL, required workers and durable pipeline leases, schema/cutover validity, the expected PG16 data directory, and writable nonfull persistent storage.
Containment covers managed nested `OwnedProcess` trees, not arbitrary session
escapes or an observer independently killed by SIGKILL/OOM. The application
retains unsafe authority indefinitely in `FAILED_HOLD`, but Compose's stop grace
is only 10 minutes. Docker can then force termination; that is unsafe shutdown,
not successful coordinated cleanup. Two clean E2E stops do not prove safe
termination of `FAILED_HOLD` at that deadline.
## Current Linux Paths
These are the implemented image, volume, and tmpfs contracts.
| Purpose | Path |
| --- | --- |
| Image application root | `/opt/truf` |
| Application code | `/opt/truf/app` |
| New Linux runtime state | `/data/runtime-linux` |
| Separately initialized Linux PostgreSQL cluster | `/data/postgres-linux` |
| Durable result bundles | `/data/scanner-result-bundles` |
| Scanner scratch | `/data/scanner-work` |
| Private imported provider credentials | `/data/config/secrets.yaml` |
| Generated PostgreSQL password | `/data/postgres-password` |
| Ephemeral control and authority state | `/run/truf/control`, `/run/truf/authority` |
| Worker/test TruffleHog executable | `/usr/local/bin/trufflehog` (absent from the production server) |
The original physical cluster was PostgreSQL 16, but it was not retained in this
source-only copy. Do not mount Windows PostgreSQL data into a Linux server.
Initialize isolated development data; any later production-data migration needs
a separately approved logical export/import and validation procedure.
## Development Linux/WSL Procedure
This volume-only procedure is retained for isolated development and migration verification;
it is not the production edge installation procedure. Production operators must use
`deploy/edge/README.md`, including the fixed host-agent installer, active documents under
`/etc/truf/runtime`, immutable package manifests under `/etc/truf/worker-packages`, the
host-agent socket, and the combined base plus edge Compose invocation.
The following are operator commands, not commands executed by this documentation
update. Use a Linux shell or WSL with Python 3, Git, Docker's Linux daemon, and
the Compose plugin (`docker compose`). Verified host versions were Docker 29.8.0
and Compose 5.5.1. Keep Docker-managed named volumes on native Linux storage, not NTFS
or an original-runtime directory. Build steps need package/download network
access; the offline test runs below do not. Do not run the full legacy suite.
### Build
From the development checkout, define an explicitly scoped Compose helper. The
example uses the passwordless sudo Docker access used by the recorded verifier;
omit `sudo -n` if your account already has direct daemon access. Do not change
daemon permissions or install/reset WSL as part of these instructions.
```sh
cd /mnt/d/truf-docker
dc() { sudo -n docker compose --project-name truf-docker --project-directory "$PWD" --env-file /dev/null --file compose.yaml "$@"; }
dc --profile test build runtime test
```
On native Linux, substitute the development checkout path for `/mnt/d/truf-docker`.
This creates `truf-local:runtime` and `truf-local:test`. All lifecycle commands
below must retain this project name and checkout so they use the same volume.
The explicit env file avoids implicitly loading a checkout `.env`; do not supply
unreviewed Docker/Compose environment overrides or proxy credentials.
### Provision And Initialize
Use these one-off commands only while the runtime is stopped. `--no-deps` avoids
implicitly starting other services. Provision is network-disabled, generates a
new private database password, and seeds an empty provider-secret mapping. A
valid already-provisioned layout is checked without regenerating credentials;
nonempty or partially provisioned layouts are refused.
```sh
dc run --rm --no-deps --pull never -T provision
```
For an authorized production-profile run, import an existing private YAML mapping
from stdin. Replace the placeholder filename with an approved Linux-side secret
file, not a file in the original installation. Do not put secret values in command
arguments, the image, the checkout, or this document. This is not a Compose secret
mount: the locked, atomic import writes `/data/config/secrets.yaml` with private
ownership/mode and refuses an active runtime or PostgreSQL PID file. Imports can
also be repeated after confirmed shutdown for credential rotation.
```sh
dc run --rm --no-deps --pull never -T runtime import-secrets < /absolute/private/provider-secrets.yaml
dc run --rm --no-deps --pull never -T runtime initialize
```
Initialization creates an independent PG16 cluster, starts maintenance mode,
applies base/schema migrations and final cutover, confirms PostgreSQL stopped,
then publishes the initialization marker. A matching initialized volume is not
reinitialized. On partial initialization, stop and inspect offline; do not delete
markers, change identity, or rerun repair scripts to force admission.
### Start, Status, And Health
Starting `compose.yaml` uses the production configuration and can launch enabled
sources and provider workers with real network access. It is NOT the offline E2E
procedure and must only be used with separately authorized targets/credentials.
`run` initializes if needed before execing the noninteractive autostart supervisor;
the explicit initialization step above makes that first-install phase visible.
```sh
dc up --detach --no-deps --no-build --pull never runtime
dc ps runtime
dc exec -T runtime /usr/local/bin/python3 -I -S -B /opt/truf/app/container_runtime.py status
dc exec -T runtime /usr/local/bin/python3 -I -S -B /opt/truf/app/container_runtime.py health
```
`status` and `health` both call the same readiness function and return JSON on
success, nonzero on failure. They are not general stopped-runtime inventory
commands. Run them with `exec` in the existing runtime, not `compose run`, because
a new container has a different control tmpfs. During initial startup, readiness
can fail until activation and worker leases complete; Compose checks every 30
seconds with a 15-second timeout, 240-second start period, and three retries.
Readiness is not proof that every provider works or that production load is safe.
### Stop And Recreate
```sh
dc stop --timeout 600 runtime
cid=$(dc ps --all --quiet runtime)
sudo -n docker container inspect --format 'status={{.State.Status}} exit={{.State.ExitCode}} oom={{.State.OOMKilled}} restarts={{.RestartCount}}' "$cid"
```
Require an exited container, exit code 0, and OOM false; investigate unexpected
restarts. A successful `compose stop` invocation alone is not graceful-exit proof.
Do not shorten the timeout, force-kill, remove the data volume, or treat a
10-minute forced termination as safe. Runtime restart policy is `on-failure:3`;
it is not a substitute for investigating uncertain ownership or partial state.
To replace a confirmed-stopped container while retaining its existing data:
```sh
dc up --detach --no-deps --no-build --pull never --force-recreate runtime
dc exec -T runtime /usr/local/bin/python3 -I -S -B /opt/truf/app/container_runtime.py health
```
Allow readiness to complete again. Never use `down --volumes` on data you intend
to retain. The old `docker-compose.postgres.yml` is a noncanonical manual-recovery
fixture, not a deployment or an external-authority implementation.
### Offline Verification
Use the reviewed container selection, not unrestricted pytest discovery:
```sh
dc --profile test run --rm --no-deps --pull never -T test
python3 -I -S -B docker/test_verify.py
python3 -I -S -B docker/verify.py
```
The selected container suite runs without `/data` or provider credentials, with
network disabled and temporary fixtures in `/tmp`; native local child processes
and loopback control sockets are intentional. Only this unit-test service allows
execution from its 512 MiB `/tmp` for temporary venv and askpass fixtures. Both
the production and E2E services use the same 128 MiB `noexec,nosuid,nodev` `/tmp`.
`docker/test_verify.py` is a separate six-test stdlib regression suite, passing
on both Windows and WSL Linux;
its total is not silently added to the selected container-suite count.
`docker/verify.py` requires already-built local runtime/test images and an already
Git-ignored `docker/test-results/latest.json`. It performs no builds or pulls and
does not edit ignore files. Run the verifier itself as the normal Linux user; it
tries direct Docker access, then `sudo -n docker`. Git is used for the read-only
evidence ignore guard, not for mutations.
The verifier invokes only `compose.e2e.yaml`, generates a unique `truf-e2e-*`
project, pins the local images by ID, and uses fresh private `data` and `tools`
named volumes. All services have network disabled, proxy settings cleared, no
host data binds or published ports, and no automatic restarts. It preserves the
production runtime image/entrypoint but prepares a narrowed offline configuration:
a local Git fixture and real TruffleHog with verification disabled, then the real
scan/bundle/ingestion/projection pipeline and OpenAI worker. ONLY that worker's
HTTP transport is substituted with a synthetic 401 response; no live provider
request is made. Production source selection/provider parity is not tested by
this profile. Do not manually merge it into production Compose or rerun prepare
after recreation.
The verifier checks healthy activation, pipeline lineage, one synthetic HTTP
request, graceful stop, recreation on the same volume, unchanged persisted
counts/hashes, no duplicates and no second HTTP request, health, and a second
graceful stop. Its aggregate check budget is 3600 seconds, each health wait at
most 240 seconds, each stop 600 seconds, and failure handling has a separate
720-second budget. Nonzero, forced, or OOM exits cannot pass.
On success it removes only its ownership-verified containers and volumes; use
`python3 -I -S -B docker/verify.py --keep` instead to retain stopped test artifacts.
Failures retain artifacts after a guarded stop attempt, possibly with running
containers if ownership or stopping cannot be proven. Record the printed project
name for investigation; do not use broad prune/down/kill commands. Evidence is
written to `docker/test-results/latest.json` as counts, hashes, image IDs, statuses,
and durations without raw command logs or secret values.
## Current Verified Evidence
The fresh recorded E2E in `docker/test-results/latest.json` has `status.result`
and `status.checks` both `passed`, `status.cleanup` equal to `removed`, and zero
owned containers, networks, or volumes remaining. The final run on 2026-09-15
took 54.374 seconds and repeated the earlier successful fresh-volume run.
- Fresh PG16 initialization and all 27 migrations completed with identity/cutover checks; both authenticated health checks passed.
- Real local Git and native TruffleHog produced one finding, one scan, one result bundle/reservation, and one queue attempt through ingestion and projection, with zero pipeline quarantine/errors.
- The real OpenAI worker used only the offline synthetic 401 transport: one first HTTP request, one linked keycheck result/current state, two projection jobs, and three projection appends.
- Recreation used a new container on the same volume without rerunning prepare. Persisted artifact IDs, migration/cutover hashes, SQL summary, output bytes and projection ledger hashes matched; repeated keycheck made zero HTTP requests and introduced no duplicate rows/appends.
- Both graceful stops recorded container exit 0, OOM false, and zero restarts. Both separate read-only stopped-volume checks confirmed private PG storage, initialization, and absence of `postmaster.pid`.
- Shutdown receipt publication is inferred ONLY from the foreground zero-exit contract. The receipt itself was not read after stop because `/run/truf` tmpfs had disappeared; evidence labels this `exit_contract_only_tmpfs_removed`.
- Final selected container regression suite: 578 passed, seven Windows-only tests skipped on Linux, in 22.25 seconds. This includes all six fresh-volume regressions. Separately, `docker/test_verify.py` passed all six tests on both Windows and WSL Linux. These are scope-specific counts, not counts stored in the E2E JSON.
- All 157 Python files under `app`, `tests`, and `docker` parsed successfully. `git diff --check` passed; existing PowerShell LF/CRLF notices were not whitespace failures. No changes were staged or committed and no Git remote was added.
Recorded image IDs (not a promise that mutable local tags still point to them):
- Runtime: `sha256:92502a2581ebcabe79ddc28744dabcfb3000b99b7c0c5262c4c09aff9dc0267b`.
- Test: `sha256:4ce11325728ba3e58e6643c1c8e800f317179d5c7c50e7e80568b58f62dbdfd0`.
## Remaining Limitations
`DOCKER_READINESS_AUDIT.md` records the original Windows audit. Its historical
line references and pending foundation tasks are not a current implementation
checklist. The remaining acceptance boundaries are:
1. `FAILED_HOLD` can outlive Docker's 10-minute grace and be terminated unsafely. No general crash/OOM/forced-stop recovery proof is claimed.
2. Production source/provider parity, live providers, real credentials, broad discovery, sustained load, throughput, and resource sizing have not been validated by the offline E2E.
3. There is no arm64 build/runtime proof, even though TruffleHog has an arm64 checksum entry.
4. External PostgreSQL authority is not implemented. Only a fresh supervisor-owned native Linux PG16 cluster is supported here.
5. There is no original Windows database migration, original-data equivalence, or production cutover proof. The historical read-only lineage record below is not such a migration proof and was not executed by this update.
## Historical Verification (Superseded Status)
The sections below preserve earlier scoped verification records. Their test
counts, file inventories, no-install/no-image statements, staging status, and
then-open container checks apply only to those stages and are superseded by the
current evidence above. At the earlier lifecycle stage Docker CLI was unavailable
and no image build/container/database migration had yet been performed. That is
no longer the current state. No historical original-runtime operation below is
claimed as an execution by this documentation update or by the fresh offline E2E.
### WSL Ownership Verification
Verified on 2026-09-14 in `Ubuntu-24.04`, WSL version 2, Linux kernel
`6.18.33.2-microsoft-standard-WSL2`, CPython 3.12.3, as unprivileged UID 1000:
- The initial successful startup took approximately 44 seconds, exceeding the earlier 10-second probe limit. WSL reported automatic NAT-to-VirtioProxy networking fallback. No network setting was changed, and the tests needed no network access.
- All nine previously skipped `LinuxOwnedProcessIntegrationTests` first passed on the real kernel. They were then included in the expanded run: 38 tests passed, zero failures/errors/skips, in 3.682 seconds excluding WSL startup.
- The expanded selection also covers mocked failure paths, ordinary output/timeout behavior, static process-safety checks, isolated-host startup, an offline temporary virtual environment, and synthetic credential filtering.
- The first expanded run exposed a test-fixture issue: Ubuntu's standard-library `sitecustomize.py` shadowed the virtual environment's fixture in the positive control. The test now puts its own module first through a temporary `PYTHONPATH`, supplied to both control and isolated-host scenarios. Both startup-hook markers must appear in the control and remain absent for the isolated host. No application code was changed for this correction.
- The existing Windows selection was rerun after that test-only fix: 159 passed, nine Linux-only skips. Those nine skips are covered by the successful WSL run, not left untested.
- The Linux runner used only the standard-library `unittest`, `python3 -I -S -B`, an empty inherited environment via `env -i`, and explicit safe locale/path/temp settings. No packages were installed and no pytest plugins were loaded. It asserted the effective `tempfile` directory before collection; a 90-second test watchdog was separate from the longer WSL startup allowance.
- Code was read from `/mnt/d/truf-docker`; `HOME`, `TMPDIR`, `TEMP`, and `TMP` were confined to `/mnt/c/Users/PRO100~1/AppData/Local/Temp/opencode`. Fixtures used mounted Windows storage, not a new native Linux data volume. This does not validate Linux storage ownership, permissions, or container mounts.
- No canonical runtime CLI, original database, provider, Docker service, or copied recovery Compose fixture was launched. Staging refusals remain unchanged.
Exact expanded `unittest` selection, with the clone's `tests` directory explicitly
added to the isolated runner's module search path:
- `test_owned_process_linux`
- `test_owned_process.OwnedProcessTests`
- `test_owned_process.StaticProcessSafetyTests`
- `test_owned_process_boundary.OwnedProcessHostBoundaryTests`
- `test_owned_process_boundary.CredentialBoundaryTests.test_host_environment_strips_mixed_case_database_credentials_only`
### Earlier Windows Lifecycle Verification
Verified on 2026-09-14 with Windows CPython 3.12.3 after the lifecycle changes:
- 159 selected tests passed; nine native Linux tests were skipped because they require a real Linux kernel and `/proc`. The passing selection includes native Windows Job/virtual-environment checks, mocked Linux kernel operations, mocked supervisor lifecycle scenarios, and the previous foundation checks.
- Regressions cover interrupted status-reader startup, cancellation before host reaping, duplicate control writers, foreign-proxy detachment, sticky failure results, receipt verification, shutdown ordering, and graceful TERM between activation/start checkpoints.
- The nine Linux-only fixtures cover live kernel identities and sessions, transitive cleanup on normal exit and actual pipe EOF, explicit stop with another writer retained, forked-proxy finalization, live adopted-child reaping, SIGKILL/SIGTERM status, and rejected startup after nested children are ready. Test signals use pidfds bound to the acknowledged payload identity.
- All 145 application/test Python files parsed successfully. The source-only artifact check found 301 files excluding `.git`, with no credential pools, databases, results, runtime/cache directories, or links.
- `git diff --check` passed. Seven existing PowerShell LF/CRLF warnings are not whitespace failures. The index and remote list remain empty; the only commit is still `1b3c7fc`.
- Independent scoped static reviews were followed by regression fixes and reruns. The last ownership review found no remaining concrete issue in the reviewed corrections; this is not a Linux conformance result.
- At that stage, a bounded WSL probe timed out without output; the subsequent WSL investigation and successful tests are recorded above. No WSL reset/install, image build, application launch, database access, or live provider test was performed by that lifecycle continuation.
The combined selection was limited to these modules/node IDs:
- `tests/test_owned_process_linux.py`
- `tests/test_owned_process.py`
- `tests/test_owned_process_boundary.py::OwnedProcessHostBoundaryTests`
- `tests/test_owned_process_boundary.py::CredentialBoundaryTests::test_host_environment_strips_mixed_case_database_credentials_only`
- `tests/test_supervisor_foreground_shutdown.py`
- `tests/test_supervisor_managed_postgres_gate.py`
- `tests/test_observer_only_coordinated_shutdown.py`
- `tests/test_docker_foundation.py`
- `tests/test_postgres_runtime.py::PostgresRuntimePathTests::test_default_data_directory_is_unchanged`
- `tests/test_postgres_runtime.py::PostgresRuntimePathTests::test_external_data_directory_expands_without_moving_runtime_assets`
- `tests/test_postgres_runtime.py::PostgresRuntimePathTests::test_external_data_identity_mismatch_remains_fail_closed`
- `tests/test_postgres_runtime.py::PostgresRuntimePathTests::test_external_data_identity_verifies_only_when_exactly_bound`
- `tests/test_supervisor_safety.py::ManagedConfigurationAuthorityTests::test_managed_dsn_overrides_config_database_urls`
The test child used `python -X utf8 -B`, pytest `-q --tb=short -rs`,
`-p no:cacheprovider -o addopts= --confcutdir=tests`, disabled plugin autoload,
and empty `PYTHONPATH`, `PYTEST_ADDOPTS`, and `PYTEST_PLUGINS`. Runtime/DSN
overrides were removed only from that child's environment. All of `TMPDIR`,
`TEMP`, and `TMP` pointed at the approved temporary work area, and the runner
asserted the actual `tempfile` directory before collecting tests.
### Previously Recorded Verification
The following earlier results are retained as historical records. They are not
new original-runtime operations performed by this lifecycle continuation.
Recorded on 2026-09-14 with Windows CPython 3.12.3:
- 19 targeted offline tests passed: all 14 foundation tests, four existing PostgreSQL path/identity tests, and the existing managed-DSN precedence test.
- The existing external-data path fixture now uses portable separators too; intentional Windows-path rejection remains separately covered.
- Python CLI tests verify the complete literal refusal AST before invoking an isolated interpreter. PowerShell safety checks parse scripts without executing them, so a broken refusal cannot make the test control the host.
- All 143 Python application/test files parsed successfully; no syntax errors.
- Parsed YAML comparison against the initial Git commit found exactly 31 changed deployment-path fields; all other settings were identical.
- The final source tree contained 299 files, approximately 6.85 MiB excluding `.git`, with no real credentials/pools, databases, results, runtime/cache directories, or links found by the artifact check.
- The original supervisor and PostgreSQL were still running; no copy writers remained. There were no staged changes or Git remotes, and the only commit remained the initial baseline.
- A read-only original-runtime lineage proof joined one completed queue reservation through its bundle, scan, finding, keycheck candidate/result, projection jobs, appends, and stream generations. Exact event/hash relationships held, and both scan projections plus the keycheck projection matched their recorded byte offsets, lengths, record counts, and SHA-256 digests; no target or credential value was emitted.
Tests ran with bytecode writes, pytest plugin autoload, and pytest cache disabled;
application/database environment overrides were removed from the test process.
Temporary test files were confined to the approved temporary work area. The
PowerShell review and Windows POSIX-path emulation do not prove Linux container
behavior, and the context allowlist check is not an actual Docker build.
Do not run the entire existing test suite against this machine: it includes
native-process, socket, database, and live integration scenarios.