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

309 lines
12 KiB
Markdown

# 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:
```bash
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`:
```bash
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:
```bash
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:
```bash
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:
```bash
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:
```bash
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:
```bash
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:
```bash
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.