Files
ThothII/docs/plans/2026-08-20-psd-server-survey.md
T

12 KiB

PSD Server Survey Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

Goal: Produce a non-mutating, redacted survey of the PSD server that resolves every path, owner, network boundary, credential location, and rollback prerequisite needed by Projects A and B.

Architecture: Collect bounded metadata from the terminal local to the server, retain raw output only in a protected directory, and summarize it in a redacted report. The survey makes no service, file, database, proxy, Authentik, or Git mutation.

Tech Stack: Linux utilities, Docker/Compose inspection, Git, Nginx, OpenSSL, PostgreSQL/Supabase metadata queries, Authentik metadata/API discovery, Aritmolab source inspection.


Safety contract

  • Do not run docker inspect without a restrictive Go template; its default output can contain secrets.
  • Do not run docker compose config into chat or a public log. Store raw output mode 0600, then create a redacted derivative.
  • Do not print process environments, secret-file contents, private keys, cookies, tokens, password hashes, or raw OIDC claims.
  • Do not reload/restart services, fetch/pull Git, log in interactively, change file modes, or make API mutations.
  • When a command needs privilege, use the server's approved CyberArk/local-terminal procedure.

Task 1: Create the protected survey workspace

Files:

  • Create: /var/tmp/thothii-psd-survey.<random>/
  • Create: protected survey-report.md

Step 1: Create a private temporary root

Run:

umask 0077
PSD_SURVEY_ROOT="$(mktemp -d /var/tmp/thothii-psd-survey.XXXXXX)"
test -d "$PSD_SURVEY_ROOT"
chmod 0700 "$PSD_SURVEY_ROOT"
printf '%s\n' "$PSD_SURVEY_ROOT"

Expected: one new mode-0700 directory whose exact path is recorded in the operator journal.

Step 2: Copy the report template

Create $PSD_SURVEY_ROOT/survey-report.md from the headings in the design's Common Survey section. Record only findings and references to protected raw files.

Task 2: Record host and Docker facts

Files:

  • Create: $PSD_SURVEY_ROOT/host.txt
  • Create: $PSD_SURVEY_ROOT/docker-projects.json
  • Create: $PSD_SURVEY_ROOT/docker-containers.txt

Step 1: Record bounded host metadata

Run each command with output redirected to $PSD_SURVEY_ROOT/host.txt:

date -u '+%Y-%m-%dT%H:%M:%SZ'
uname -a
cat /etc/os-release
getconf LONG_BIT
nproc
free -h
df -hT
docker version
docker compose version

Expected: no credential content and enough capacity information to judge a parallel source tree and a new five-service stack.

Step 2: Record Compose projects and bounded container identity

Run:

docker compose ls --format json > "$PSD_SURVEY_ROOT/docker-projects.json"
docker ps -a --no-trunc --format '{{json .}}' > "$PSD_SURVEY_ROOT/docker-containers.txt"
docker network ls --format '{{json .}}' > "$PSD_SURVEY_ROOT/docker-networks.txt"
docker volume ls --format '{{json .}}' > "$PSD_SURVEY_ROOT/docker-volumes.txt"

Expected: inventory only. Do not inspect full container JSON.

Step 3: Identify candidate legacy ThothII containers

Use names, images, Compose project labels, published ports, and health from the bounded inventory. For each candidate, query only these templates:

docker inspect --format '{{.Name}} {{.Config.Image}} {{index .Config.Labels "com.docker.compose.project"}} {{index .Config.Labels "com.docker.compose.project.working_dir"}}' <container>
docker inspect --format '{{json .NetworkSettings.Networks}}' <container>
docker inspect --format '{{range .Mounts}}{{.Type}} {{.Source}} -> {{.Destination}} rw={{.RW}}{{println}}{{end}}' <container>

Expected: exact source/Compose ownership and mounts without environment values.

Task 3: Survey the legacy ThothII installation

Files:

  • Create: $PSD_SURVEY_ROOT/legacy-thothii.txt
  • Create: $PSD_SURVEY_ROOT/legacy-compose.redacted.yaml

Step 1: Resolve source and operator paths from evidence

Do not search broad filesystem roots. Derive paths from Compose labels, systemd units, Nginx upstreams, and known operator documentation. Record uncertainty rather than guessing.

Step 2: Record source identity without fetching

Run in the identified source tree:

git status --short --branch
git rev-parse HEAD
git remote -v
git log -5 --oneline --decorate

Expected: no mutation. Mark a dirty tree as NO-GO until the owner decides how to preserve it.

Step 3: Record lifecycle state with the legacy controller

If the old installation has a supported tht, run its bounded status, doctor, pi status, and pi maintenance status commands. Otherwise record exact read-only Docker health and identify the old lifecycle mechanism. Do not substitute current tht against an incompatible descriptor.

Step 4: Render and redact Compose safely

Store the raw render as mode 0600. Replace secret-bearing scalar values with [redacted] before using the derivative in analysis. Confirm the redacted render still shows service names, networks, ports, volumes, image/build identities, and config file paths.

Task 4: Survey Nginx, TLS, and the load balancer

Files:

  • Create: $PSD_SURVEY_ROOT/nginx.raw.txt (protected)
  • Create: $PSD_SURVEY_ROOT/nginx-thothii.redacted.txt
  • Create: $PSD_SURVEY_ROOT/tls-metadata.txt
  • Create: $PSD_SURVEY_ROOT/load-balancer.md

Step 1: Validate and capture Nginx without reload

Run:

sudo nginx -t
sudo nginx -T > "$PSD_SURVEY_ROOT/nginx.raw.txt" 2>&1
chmod 0600 "$PSD_SURVEY_ROOT/nginx.raw.txt"

Expected: configuration test passes. Do not reload Nginx.

Step 2: Extract only relevant directives

Create the redacted derivative containing the ThothII/Aritmolab server_name, listen, location, proxy_pass, proxy_set_header, proxy_buffering, timeout, certificate path, and include-file directives. Exclude unrelated virtual hosts and all authorization values.

Step 3: Record certificate metadata only

For each relevant public certificate—not its key—run:

openssl x509 -in <certificate-path> -noout -subject -issuer -serial -dates -ext subjectAltName

Expected: exact SAN/expiry/issuer and the observed generation/renewal mechanism.

Step 4: Map the load balancer

Record its owner, configuration surface, current Aritmolab backend, health check, TLS boundary, source addresses seen by Nginx, and whether it can enforce a temporary hostname allowlist. Do not create a route. If Sol cannot inspect it, name the human/team required for Project A/B gates.

Task 5: Survey Aritmolab and the sidebar integration

Files:

  • Create: $PSD_SURVEY_ROOT/aritmolab.md

Step 1: Resolve the Aritmolab source/deployment

Use Compose labels, Nginx paths, or the documented service unit. Record repository path, SHA, dirty state, deployment command, container/network identity, and configuration owner.

Step 2: Locate the sidebar link

Use rg in the resolved source tree for the current ThothII URL, label, historical datamart-builder, and sidebar/navigation definitions. Record exact files and line numbers.

Step 3: Resolve the real public origin

The owner reports aritmolab.policlinicosandonato.com; historical project state mentions a .it origin and /datamart-builder. Record the live browser-visible origin and path from deployed configuration. Do not choose between them without evidence.

Task 6: Survey Authentik

Files:

  • Create: $PSD_SURVEY_ROOT/authentik.md

Step 1: Identify deployment and version

Record Authentik containers/services, immutable image reference, version, base URL, database/Redis dependencies, configuration owner, and backup/export procedure. Do not print container environments.

Step 2: Locate credential references

Record only file/secret-object paths, ownership, mode, and whether the local operator can use them. If no usable administrative/API credential is found, stop and request owner help.

Step 3: Inventory relevant objects read-only

Using the installed version's API schema or admin interface, list only names/IDs for current Aritmolab applications/providers, authorization flows, property mappings, groups, service accounts, and policies that establish local conventions. Do not retrieve write-only secrets or raw tokens.

Step 4: Record version-specific constraints

Consult the official documentation matching the installed release for OAuth2/OIDC providers, scope/property mappings, application bindings, blueprints/export, and API permission semantics. Do not copy examples from a newer release without comparing the installed OpenAPI schema.

Task 7: Survey Supabase and the PSD DWH

Files:

  • Create: $PSD_SURVEY_ROOT/supabase.md
  • Create: $PSD_SURVEY_ROOT/dwh-readonly.txt

Step 1: Map Supabase services without environments

Record PostgreSQL, pooler, PostgREST, gateway, and backup components; container networks and local listeners; database name; TLS listener/CA; and the approved direct-connect route from ThothII core.

Step 2: Record exposed PostgREST schemas

Query only the explicit PostgREST schema setting through its known configuration mechanism. Do not dump the whole environment. Confirm whether thoth_sessions already exists or is exposed.

Step 3: Inspect schemas and migration state

Through an approved administrative connection, run bounded catalog queries for existing schemas, owners, and any thoth_sessions tables/migration records. Do not change them.

Step 4: Prove the intended DWH runtime identity is read-only

Connect using the protected runtime credential mechanism and query current_database(), current_user, and grants for schema datawarehouse. Expected: USAGE/SELECT as required and no INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER, CREATE, or ownership privileges. Do not run a write probe against clinical tables.

Step 5: Identify session-schema roles

Record names or naming rules for a future migrator and runtime role. Do not create them. The final design uses the existing database plus schema thoth_sessions, never a new database.

Task 8: Survey Git workspace and model boundaries

Files:

  • Create: $PSD_SURVEY_ROOT/workspace-and-models.md

Step 1: Inspect the workspace remote read-only

Record remote URL, branch, fetch credential path, current remote SHA, catalog entry, descriptor schema version, current supported_transports, Evidence tree, annotations blob, and deploy-key permissions. Do not push with the server's read-only deployment credential.

Step 2: Inspect Pi/LLM policy

Record selected provider/model/thinking level and credential references. Use bounded tht pi status and pi doctor where compatible. Do not output provider keys.

Step 3: Check internal semantic capacity

Record CPU/GPU availability, free storage, and whether Docker can run the pinned Qdrant and Ollama architectures. Do not pull images or models during the survey.

Task 9: Produce the survey decision

Files:

  • Modify: $PSD_SURVEY_ROOT/survey-report.md

Step 1: Complete the topology

Include exact component owners and flows for user → load balancer → Nginx → Aritmolab/sidebar → ThothII, and core → Supabase DWH/auth session schema/Qdrant/Ollama/LLM/Authentik.

Step 2: List exact intended change files

Separate files owned by the new ThothII installation, workspace curator, Nginx, load balancer, Aritmolab, Authentik, and Supabase. Mark shared files as owner-gated.

Step 3: State GO or NO-GO

GO requires all mandatory paths, permissions, backup owners, and rollback boundaries. NO-GO must name concrete missing facts and the person/system needed to resolve them.

Step 4: Hash and retain the report

Run:

sha256sum "$PSD_SURVEY_ROOT/survey-report.md" > "$PSD_SURVEY_ROOT/survey-report.sha256"
sha256sum --check "$PSD_SURVEY_ROOT/survey-report.sha256"

Expected: checksum passes. Move the complete mode-0700 survey directory to the approved protected evidence root without changing its contents; record the final path and digest in the journal.