313 lines
12 KiB
Markdown
313 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 the scoped GO or NO-GO decisions**
|
|
|
|
State both `SURVEY_GO_PROJECT_A_PRIVATE` and `SURVEY_GO_PROJECT_B`. The private decision requires
|
|
all paths, permissions, backup owners and rollback boundaries used by Project A; it may defer
|
|
public-origin, load-balancer, Authentik and Mac REST closeout facts that Project A does not mutate.
|
|
The Project B decision requires every shared/public fact plus the Mac acceptance, completed
|
|
observation window and revoked legacy credential. Each 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.
|