docs: plan PSD server deployment program
This commit is contained in:
+32
-2
@@ -7,10 +7,40 @@
|
|||||||
> ThothII per il repository (app + CLI `tht`), (3) come usare l'applicazione ThothII di base
|
> ThothII per il repository (app + CLI `tht`), (3) come usare l'applicazione ThothII di base
|
||||||
> (sessioni, domande, gate). Il documento userà parole semplici ed esempi; i dettagli tecnici
|
> (sessioni, domande, gate). Il documento userà parole semplici ed esempi; i dettagli tecnici
|
||||||
> resteranno nei contratti esistenti. Esempio pratico completo: Policlinico San Donato.
|
> resteranno nei contratti esistenti. Esempio pratico completo: Policlinico San Donato.
|
||||||
> Last updated: 2026-08-18 (final-review fix round 2 recorded; native Windows authentication gate
|
> Last updated: 2026-08-20 (PSD server replacement and Authentik-integration program designed;
|
||||||
> passed, remediation is complete, and unrelated release gates remain open).
|
> executable survey, two gated project plans, human-test guides, and evidence templates prepared;
|
||||||
|
> no server mutation has been executed).
|
||||||
> Point a fresh session here ("read PROJECT_STATE.md") before substantial work.
|
> Point a fresh session here ("read PROJECT_STATE.md") before substantial work.
|
||||||
|
|
||||||
|
### PSD server deployment program — design approved, execution PENDING (2026-08-20)
|
||||||
|
|
||||||
|
- **Approved design:** `docs/plans/2026-08-20-psd-server-deployment-program-design.md`; design
|
||||||
|
commit `3fd177b`. The owner approved a common read-only survey followed by two independently
|
||||||
|
accepted projects: A installs/proves a private local-auth stack through F1-F8; B starts only
|
||||||
|
after A PASS and integrates Supabase schema storage, Authentik OIDC, Nginx, the load balancer,
|
||||||
|
and the existing Aritmolab sidebar journey.
|
||||||
|
- **Executable entrypoint:** `docs/plans/2026-08-20-psd-server-deployment-program.md`, with separate
|
||||||
|
plans for the survey, Project A, and Project B. The server-local Sol agent must execute them with
|
||||||
|
`superpowers:executing-plans`, checkpointing every verified step and stopping on the documented
|
||||||
|
owner/secret/rollback boundaries.
|
||||||
|
- **Human gates:** `docs/testing/psd-server-project-a-manual.md` and
|
||||||
|
`docs/testing/psd-server-project-b-manual.md`; survey and Project A/B report templates are under
|
||||||
|
`docs/testing/evidence/`. Automated evidence never substitutes for the two explicit human PASS
|
||||||
|
decisions.
|
||||||
|
- **Workspace decision:** keep one `psd-clinical` descriptor in `tht-workspace-psd`; publish
|
||||||
|
`supported_transports: [rest_api, postgres_direct]`. Mac selects REST, server selects direct;
|
||||||
|
all installation bindings/secrets remain outside Git.
|
||||||
|
- **Data/runtime decision:** migrate configuration only. Legacy work sessions, Qdrant indexes, and
|
||||||
|
Ollama cache are not imported. Project A rebuilds internal Qdrant/Ollama and uses filesystem work
|
||||||
|
sessions. Project B uses the existing Supabase PostgreSQL database with isolated schema
|
||||||
|
`thoth_sessions`, dedicated migrator/runtime roles, forced RLS, and no PostgREST exposure.
|
||||||
|
- **Network/auth decision:** no SSH tunnel. Project A is loopback-only unless the surveyed load
|
||||||
|
balancer can prove an operator-only temporary endpoint. Project B preserves the real user flow
|
||||||
|
`Aritmolab homepage -> sidebar -> load balancer -> Nginx -> ThothII`, with direct ThothII-managed
|
||||||
|
OIDC and no second Nginx `auth_request`.
|
||||||
|
- **State:** survey `PENDING`; Project A `PENDING`; Project B `BLOCKED_BY_PROJECT_A`; server and
|
||||||
|
external repositories/services unchanged by this planning work.
|
||||||
|
|
||||||
### Authentication final-review fix round 2 — remediation PASS, release gates remain (2026-08-18)
|
### Authentication final-review fix round 2 — remediation PASS, release gates remain (2026-08-18)
|
||||||
|
|
||||||
- Frozen source is `2a9359071257f9b8a71d36ec2bbb25b161003f81` on `feat/thoth-auth`.
|
- Frozen source is `2a9359071257f9b8a71d36ec2bbb25b161003f81` on `feat/thoth-auth`.
|
||||||
|
|||||||
@@ -0,0 +1,220 @@
|
|||||||
|
# PSD Server Deployment Program Implementation Plan
|
||||||
|
|
||||||
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||||||
|
|
||||||
|
**Goal:** Replace the legacy PSD ThothII installation, prove the replacement with local authentication, and then integrate the accepted release with Supabase, Authentik, Nginx, the load balancer, and the Aritmolab sidebar.
|
||||||
|
|
||||||
|
**Architecture:** A read-only common survey freezes the actual server topology before any mutation. Project A installs a clean private stack and proves a complete PSD workflow; Project B begins only after a signed Project A PASS and performs the public OIDC/SSO cutover. Each project has an independent rollback boundary, human test guide, and evidence report.
|
||||||
|
|
||||||
|
**Tech Stack:** Linux, Docker Engine, Docker Compose v2, native `tht`, Fastify/React/Pi, PostgreSQL/Supabase, Qdrant, Ollama, Nginx, Authentik OIDC, Aritmolab, load balancer.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Required reading and authority
|
||||||
|
|
||||||
|
Read these files completely before starting:
|
||||||
|
|
||||||
|
- `AGENTS.md`
|
||||||
|
- `PROJECT_STATE.md`
|
||||||
|
- `docs/plans/2026-08-20-psd-server-deployment-program-design.md`
|
||||||
|
- `docs/install/server.md`
|
||||||
|
- `docs/install/server-workspace-registry.md`
|
||||||
|
- `docs/install/authentication-local.md`
|
||||||
|
- `docs/install/authentication-oidc.md`
|
||||||
|
- `docs/install/authentik.md`
|
||||||
|
- `docs/contracts/workspace-preprocessing-cli.md`
|
||||||
|
- `docs/testing/authentication-manual-acceptance.md`
|
||||||
|
|
||||||
|
The current `compose.yaml`, `deploy/compose.server.yaml`, repository instructions, and design are
|
||||||
|
authoritative where older server prose still describes Qdrant or Ollama as external.
|
||||||
|
|
||||||
|
Run only from a terminal local to the server. Do not require SSH port forwarding. Do not print or
|
||||||
|
paste passwords, tokens, cookies, private keys, hashes, or raw identity claims. Commands that need
|
||||||
|
a credential must read a protected file or use an echo-free prompt.
|
||||||
|
|
||||||
|
## Documents used during execution
|
||||||
|
|
||||||
|
- Survey plan: `docs/plans/2026-08-20-psd-server-survey.md`
|
||||||
|
- Survey report: `docs/testing/evidence/psd-server-survey-report-template.md`
|
||||||
|
- Project A plan: `docs/plans/2026-08-20-psd-server-project-a-standalone.md`
|
||||||
|
- Project A human guide: `docs/testing/psd-server-project-a-manual.md`
|
||||||
|
- Project A report: `docs/testing/evidence/psd-server-project-a-report-template.md`
|
||||||
|
- Project B plan: `docs/plans/2026-08-20-psd-server-project-b-authentik.md`
|
||||||
|
- Project B human guide: `docs/testing/psd-server-project-b-manual.md`
|
||||||
|
- Project B report: `docs/testing/evidence/psd-server-project-b-report-template.md`
|
||||||
|
|
||||||
|
The detailed evidence directory is a protected path on the server selected during the survey. The
|
||||||
|
repository receives only redacted reports after explicit owner review.
|
||||||
|
|
||||||
|
### Task 1: Freeze the planning source
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Read: `docs/plans/2026-08-20-psd-server-deployment-program-design.md`
|
||||||
|
- Record: protected server execution journal selected during the survey
|
||||||
|
|
||||||
|
**Step 1: Verify the application checkout**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git status --short --branch
|
||||||
|
git rev-parse HEAD
|
||||||
|
git rev-parse origin/main
|
||||||
|
git show -s --format='%H%n%P%n%s' HEAD
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: the tree is clean and `HEAD` is the explicitly approved `origin/main` SHA. A newer SHA
|
||||||
|
than the design-time `5c0dc8c` is allowed only after recording and reviewing the intervening commits.
|
||||||
|
|
||||||
|
**Step 2: Verify the plan files exist at that SHA**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
test -f docs/plans/2026-08-20-psd-server-survey.md
|
||||||
|
test -f docs/plans/2026-08-20-psd-server-project-a-standalone.md
|
||||||
|
test -f docs/plans/2026-08-20-psd-server-project-b-authentik.md
|
||||||
|
git diff --check
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: every command exits zero.
|
||||||
|
|
||||||
|
**Step 3: Record the immutable planning identity**
|
||||||
|
|
||||||
|
Record the application SHA, plan commit, UTC timestamp, operator identity, and terminal-local access
|
||||||
|
method in the protected journal. Do not record CyberArk session secrets or screenshots.
|
||||||
|
|
||||||
|
### Task 2: Execute and approve the common survey
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Execute: `docs/plans/2026-08-20-psd-server-survey.md`
|
||||||
|
- Create from: `docs/testing/evidence/psd-server-survey-report-template.md`
|
||||||
|
|
||||||
|
**Step 1: Execute every survey task without mutation**
|
||||||
|
|
||||||
|
Expected: the survey identifies exact paths and owners for the old and new installations, Nginx,
|
||||||
|
load balancer, Aritmolab, Authentik, Supabase, the DWH, and protected credentials.
|
||||||
|
|
||||||
|
**Step 2: Resolve every unknown**
|
||||||
|
|
||||||
|
If an Authentik credential cannot be located, stop and ask the owner. If a configuration owner or
|
||||||
|
rollback boundary is unclear, stop; do not infer authority from file readability.
|
||||||
|
|
||||||
|
**Step 3: Review the survey GO/NO-GO**
|
||||||
|
|
||||||
|
Expected: GO requires a verified old-stack recovery path, a new-installation root, enough resources,
|
||||||
|
a read-only DWH path, and no unresolved shared-infrastructure mutation.
|
||||||
|
|
||||||
|
**Step 4: Checkpoint the survey**
|
||||||
|
|
||||||
|
Hash the protected report and record only its path, SHA-256, timestamp, and GO result in the journal.
|
||||||
|
|
||||||
|
### Task 3: Execute Project A
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Execute: `docs/plans/2026-08-20-psd-server-project-a-standalone.md`
|
||||||
|
- Complete: `docs/testing/evidence/psd-server-project-a-report-template.md`
|
||||||
|
|
||||||
|
**Step 1: Confirm the survey is GO**
|
||||||
|
|
||||||
|
Expected: the survey report hash matches the journal and no unresolved blocker remains.
|
||||||
|
|
||||||
|
**Step 2: Execute Project A task-by-task**
|
||||||
|
|
||||||
|
Do not configure Authentik, change the production Aritmolab sidebar, or open the production route.
|
||||||
|
|
||||||
|
**Step 3: Run the Project A human guide**
|
||||||
|
|
||||||
|
Follow `docs/testing/psd-server-project-a-manual.md`. Record PASS/FAIL for every case; do not infer
|
||||||
|
manual PASS from automated output.
|
||||||
|
|
||||||
|
**Step 4: Close the Project A report**
|
||||||
|
|
||||||
|
Expected: automated gates and the human guide are PASS; one harmless PSD session reached F8 and
|
||||||
|
produced validated read-only SQL; rollback remains available.
|
||||||
|
|
||||||
|
**Step 5: Obtain explicit owner approval**
|
||||||
|
|
||||||
|
Record the approval and report digest. Project B remains forbidden without it.
|
||||||
|
|
||||||
|
### Task 4: Freeze the Project B candidate
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Read: accepted Project A report
|
||||||
|
- Record: protected server execution journal
|
||||||
|
|
||||||
|
**Step 1: Recheck source and running images**
|
||||||
|
|
||||||
|
Run the Project A plan's identity commands again. Record application SHA, workspace SHA, core image
|
||||||
|
ID, frontend image ID, Qdrant image digest, Ollama image digest, and local-auth configuration revision.
|
||||||
|
|
||||||
|
Expected: all values match the accepted Project A report.
|
||||||
|
|
||||||
|
**Step 2: Recheck rollback**
|
||||||
|
|
||||||
|
Prove that the public route is still closed and the protected Project A configuration can be
|
||||||
|
selected without reconstructing it from memory.
|
||||||
|
|
||||||
|
### Task 5: Execute Project B
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Execute: `docs/plans/2026-08-20-psd-server-project-b-authentik.md`
|
||||||
|
- Complete: `docs/testing/evidence/psd-server-project-b-report-template.md`
|
||||||
|
|
||||||
|
**Step 1: Execute Project B task-by-task**
|
||||||
|
|
||||||
|
Keep public traffic closed until Authentik, Supabase migrations, ThothII diagnostics, Nginx, TLS,
|
||||||
|
and load-balancer preflight all pass.
|
||||||
|
|
||||||
|
**Step 2: Run the Project B human guide**
|
||||||
|
|
||||||
|
Follow `docs/testing/psd-server-project-b-manual.md` using approved ordinary and administrator
|
||||||
|
identities. The final path begins at the Aritmolab homepage and uses its existing sidebar link.
|
||||||
|
|
||||||
|
**Step 3: Close the Project B report**
|
||||||
|
|
||||||
|
Expected: SSO, roles, PostgreSQL ownership, the F1-F8 session, rollback rehearsal, and cleanup of the
|
||||||
|
temporary Project A endpoint all pass.
|
||||||
|
|
||||||
|
### Task 6: Close the program
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `PROJECT_STATE.md`
|
||||||
|
- Optionally create: reviewed redacted acceptance reports under `docs/testing/evidence/`
|
||||||
|
|
||||||
|
**Step 1: Reconcile final state**
|
||||||
|
|
||||||
|
Record final SHAs, image identities, workspace revision, Authentik object names/IDs (never secrets),
|
||||||
|
Supabase database/schema names, public origin, sidebar source revision, Nginx configuration identity,
|
||||||
|
and both report digests.
|
||||||
|
|
||||||
|
**Step 2: Verify final negative boundaries**
|
||||||
|
|
||||||
|
Expected: old stack stopped; Project A private endpoint removed; core/Qdrant/Ollama not externally
|
||||||
|
published; `thoth_sessions` absent from PostgREST exposed schemas; no secret appears in reports.
|
||||||
|
|
||||||
|
**Step 3: Update project state**
|
||||||
|
|
||||||
|
Add a dated factual section to `PROJECT_STATE.md`. Mark anything not actually run as PENDING.
|
||||||
|
|
||||||
|
**Step 4: Run documentation checks**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git diff --check
|
||||||
|
bash scripts/auth-docs-smoke.sh
|
||||||
|
bash scripts/verify-workspace-install-docs.sh --fixtures-only
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: all checks pass.
|
||||||
|
|
||||||
|
**Step 5: Commit only reviewed redacted documentation**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add PROJECT_STATE.md docs/testing/evidence
|
||||||
|
git diff --cached --check
|
||||||
|
git commit -m "docs: record PSD server deployment acceptance"
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: the commit contains no raw server inventory or secret material.
|
||||||
@@ -0,0 +1,500 @@
|
|||||||
|
# PSD Server Project A Standalone Implementation Plan
|
||||||
|
|
||||||
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||||||
|
|
||||||
|
**Goal:** Install a clean PSD ThothII stack with local authentication, direct read-only DWH access, internal Qdrant/Ollama, rebuilt preprocessing, and one completed F1-F8 work session.
|
||||||
|
|
||||||
|
**Architecture:** Preserve the stopped legacy installation and deploy the current canonical five-service Compose stack from an adjacent clean clone. A reviewed server-local override disables public exposure and uses filesystem work sessions; an optional load-balancer route is permitted only when it is operator-only and its denial boundary is proved first.
|
||||||
|
|
||||||
|
**Tech Stack:** Git, Docker/Compose, native `tht`, local Argon2id authentication, PSD Supabase PostgreSQL direct transport, Qdrant, Ollama, Pi, Nginx/load-balancer test route where safe.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Preconditions
|
||||||
|
|
||||||
|
- Common survey result is GO and its digest is recorded.
|
||||||
|
- Every path below is replaced by the exact survey result before execution.
|
||||||
|
- No production Nginx/load-balancer/sidebar/Authentik change is in scope.
|
||||||
|
- The old stack remains running only until backup verification finishes; old and new stacks never
|
||||||
|
run together.
|
||||||
|
- The server's workspace deploy credential remains read-only. A curator with write access publishes
|
||||||
|
the workspace change.
|
||||||
|
|
||||||
|
### Task 1: Freeze exact inputs
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Read: protected survey report
|
||||||
|
- Read: `docs/plans/2026-08-20-psd-server-deployment-program-design.md`
|
||||||
|
- Record: protected Project A journal
|
||||||
|
|
||||||
|
**Step 1: Record application identity**
|
||||||
|
|
||||||
|
Run in the new planning checkout:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git status --short --branch
|
||||||
|
git rev-parse HEAD
|
||||||
|
git rev-parse origin/main
|
||||||
|
git diff --check
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: clean and explicitly approved SHA.
|
||||||
|
|
||||||
|
**Step 2: Record workspace remote identity**
|
||||||
|
|
||||||
|
Use the surveyed read-only credential and run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git ls-remote <workspace-remote> refs/heads/main
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: one SHA recorded as the pre-change workspace revision.
|
||||||
|
|
||||||
|
**Step 3: Check old-stack recoverability**
|
||||||
|
|
||||||
|
Expected: exact old start/stop procedure, source SHA, Compose identity, volumes/binds, proxy closure
|
||||||
|
procedure, and backup destination are present in the survey. Stop if any is missing.
|
||||||
|
|
||||||
|
### Task 2: Publish the multi-transport workspace revision
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify in authorized curator clone: `psd-clinical/workspace.yaml`
|
||||||
|
- Verify: `thoth-workspaces.yaml`
|
||||||
|
|
||||||
|
**Step 1: Create a clean curator branch**
|
||||||
|
|
||||||
|
Run in a write-authorized clone, never in the application-managed registry checkout:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git status --short --branch
|
||||||
|
git fetch origin main
|
||||||
|
git switch --create codex/psd-direct-transport origin/main
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: clean branch at the recorded remote SHA.
|
||||||
|
|
||||||
|
**Step 2: Make the minimal descriptor change**
|
||||||
|
|
||||||
|
Change exactly:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
supported_transports: [rest_api]
|
||||||
|
```
|
||||||
|
|
||||||
|
to:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
supported_transports: [rest_api, postgres_direct]
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not duplicate the workspace or change its ID, collection, Evidence, annotations, model policy,
|
||||||
|
database, or schema.
|
||||||
|
|
||||||
|
**Step 3: Review the descriptor-only diff**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git diff --check
|
||||||
|
git diff -- psd-clinical/workspace.yaml thoth-workspaces.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: one semantic line changed; catalog metadata remains identical.
|
||||||
|
|
||||||
|
**Step 4: Validate with the current ThothII contract**
|
||||||
|
|
||||||
|
Use a disposable installation/registry or the repository's current registry validation harness to
|
||||||
|
activate the candidate commit before publication. Expected: schema v3 accepts both transports,
|
||||||
|
Evidence and annotations materialize, and no secret is required for source validation.
|
||||||
|
|
||||||
|
If no supported validator can be run in the curator environment, stop and request the owner to run
|
||||||
|
the established Mac validation; do not publish based only on YAML parsing.
|
||||||
|
|
||||||
|
**Step 5: Commit and publish through curator review**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add psd-clinical/workspace.yaml
|
||||||
|
git diff --cached --check
|
||||||
|
git commit -m "feat: support direct PSD DWH transport"
|
||||||
|
git push --set-upstream origin codex/psd-direct-transport
|
||||||
|
```
|
||||||
|
|
||||||
|
Merge through the repository's normal review path. Record the resulting `main` SHA.
|
||||||
|
|
||||||
|
**Step 6: Prove the Mac REST installation is unchanged**
|
||||||
|
|
||||||
|
The owner pulls/activates the new workspace commit on the Mac, confirms selected transport
|
||||||
|
`rest_api`, runs workspace inspection/connection diagnostics, and records PASS. Project A server
|
||||||
|
deployment stops if this cross-installation proof is not available.
|
||||||
|
|
||||||
|
### Task 3: Back up and stop the legacy installation
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Create: surveyed protected legacy backup directory
|
||||||
|
- Record: Project A journal
|
||||||
|
|
||||||
|
**Step 1: Capture final legacy state**
|
||||||
|
|
||||||
|
Run the surveyed legacy status/doctor commands, record source SHA and image IDs, and confirm no
|
||||||
|
active user work. Do not use the new `tht` against an incompatible old descriptor.
|
||||||
|
|
||||||
|
**Step 2: Close or maintenance-gate the old ThothII route**
|
||||||
|
|
||||||
|
Change only the surveyed ThothII-specific route using its established mechanism. Validate Nginx and
|
||||||
|
load-balancer configuration before applying. Confirm external requests no longer reach the app.
|
||||||
|
|
||||||
|
**Step 3: Create the legacy backup**
|
||||||
|
|
||||||
|
Use the surveyed, version-compatible backup procedure. Include source/config metadata and all old
|
||||||
|
runtime volumes/binds needed to restart; store credentials separately under existing protected
|
||||||
|
custody. Create SHA-256 checksums and verify them.
|
||||||
|
|
||||||
|
**Step 4: Stop the old stack**
|
||||||
|
|
||||||
|
Use its own supported controller. Expected: old containers stopped, not removed; volumes and bind
|
||||||
|
trees unchanged.
|
||||||
|
|
||||||
|
**Step 5: Rehearse the restart command without executing it**
|
||||||
|
|
||||||
|
Record the exact command, preconditions, port ownership, and route-restoration order. If it cannot
|
||||||
|
be stated unambiguously, stop before creating the new stack.
|
||||||
|
|
||||||
|
### Task 4: Prepare the adjacent clean installation
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Create: survey-selected new source root
|
||||||
|
- Create: survey-selected operator, secret, data, Pi-state, registry, and backup roots
|
||||||
|
|
||||||
|
**Step 1: Create dedicated identities and paths**
|
||||||
|
|
||||||
|
Follow `docs/install/server.md` ownership rules using the surveyed available UID/GID. Do not reuse a
|
||||||
|
UID already owned by another service and do not change image UID 10001 without a reviewed mapping.
|
||||||
|
|
||||||
|
**Step 2: Clone the frozen application source**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git -c core.autocrlf=false clone <thothii-remote> <new-source-root>/ThothII
|
||||||
|
git -C <new-source-root>/ThothII config --local core.autocrlf false
|
||||||
|
git -C <new-source-root>/ThothII switch --detach <approved-application-sha>
|
||||||
|
git -C <new-source-root>/ThothII status --short --branch
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: detached exact SHA, clean tree.
|
||||||
|
|
||||||
|
**Step 3: Verify source and platform**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd <new-source-root>/ThothII
|
||||||
|
bash scripts/verify-line-endings.sh
|
||||||
|
docker version
|
||||||
|
docker compose version
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: all pass.
|
||||||
|
|
||||||
|
**Step 4: Prepare Pi state and build the operator**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo scripts/prepare-server-pi-state.sh <new-pi-state-root> 10001 10001
|
||||||
|
THT_THT_OUTPUT_DIRECTORY=<protected-build-output> bash scripts/build-tht.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Install only the binary matching the surveyed server architecture. Run `tht version --json` and
|
||||||
|
record its source identity.
|
||||||
|
|
||||||
|
### Task 5: Create the protected Project A configuration
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Create outside Git: `<project-a-operator-root>/server.env`
|
||||||
|
- Create outside Git: `<project-a-operator-root>/thothii-installation.yaml`
|
||||||
|
- Create outside Git: `<project-a-operator-root>/project-a-private.yaml`
|
||||||
|
- Create outside Git: `<project-a-auth-root>/auth.yaml` through `tht`
|
||||||
|
|
||||||
|
**Step 1: Start from current examples**
|
||||||
|
|
||||||
|
Copy `deploy/env/server.env.example` and `docs/install/examples/thothii-installation.server.yaml`
|
||||||
|
to the protected Project A operator root. Replace every placeholder with surveyed absolute paths.
|
||||||
|
Never source `server.env` as shell code.
|
||||||
|
|
||||||
|
**Step 2: Add the private/local-session override**
|
||||||
|
|
||||||
|
Create this reviewed override:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
core:
|
||||||
|
environment:
|
||||||
|
THOTH_PUBLIC_EXPOSURE: "false"
|
||||||
|
THT_SESSION_STORAGE: local
|
||||||
|
frontend:
|
||||||
|
ports: !override
|
||||||
|
- "127.0.0.1:<project-a-port>:8080"
|
||||||
|
```
|
||||||
|
|
||||||
|
Select an unused loopback port proved by `ss -lntp`. Do not publish core, Qdrant, or Ollama.
|
||||||
|
|
||||||
|
**Step 3: Compose the installation descriptor**
|
||||||
|
|
||||||
|
Use `profile: server`, the exact new source root/env/auth root, workspace remote/branch/read-only
|
||||||
|
access, Project A override, and exactly one Git transport override. Do not include the public
|
||||||
|
session-server overlay in Project A.
|
||||||
|
|
||||||
|
**Step 4: Validate permissions and render**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
<new-tht> --installation <project-a-installation> update --check-only
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: Compose validates; only frontend has a loopback port; core declares public exposure false
|
||||||
|
and local session storage; Qdrant/Ollama are internal.
|
||||||
|
|
||||||
|
**Step 5: Configure the local administrator**
|
||||||
|
|
||||||
|
Create a temporary mode-0600 password file using an echo-free prompt, then run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
<new-tht> --installation <project-a-installation> auth configure \
|
||||||
|
--mode local --public-url <project-a-origin> \
|
||||||
|
--admin-user <test-admin> --admin-display-name <display-name> \
|
||||||
|
--password-file <protected-temporary-password-file>
|
||||||
|
```
|
||||||
|
|
||||||
|
Remove the temporary input file after success and record that removal. Do not delete generated
|
||||||
|
`auth.yaml` or `users.yaml`.
|
||||||
|
|
||||||
|
### Task 6: Build and start the clean stack
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Record: Project A evidence directory
|
||||||
|
|
||||||
|
**Step 1: Build current images**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd <new-source-root>/ThothII
|
||||||
|
bash scripts/build-local.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: current core/frontend images build; pinned Qdrant/Ollama references resolve.
|
||||||
|
|
||||||
|
**Step 2: Run preflight**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
<new-tht> --installation <project-a-installation> update --check-only
|
||||||
|
<new-tht> --installation <project-a-installation> pi doctor
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: no mutation error and no secret in output.
|
||||||
|
|
||||||
|
**Step 3: Start through `tht`**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
<new-tht> --installation <project-a-installation> start --build
|
||||||
|
<new-tht> --installation <project-a-installation> status
|
||||||
|
<new-tht> --installation <project-a-installation> doctor --json
|
||||||
|
<new-tht> --installation <project-a-installation> pi test
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: frontend, core, Qdrant, embedding healthy and model initializer completed. Doctor has the
|
||||||
|
documented ordered checks and authentication PASS.
|
||||||
|
|
||||||
|
**Step 4: Verify listener boundaries**
|
||||||
|
|
||||||
|
Use `ss -lntp` and bounded Docker inspection. Expected: only the selected frontend loopback port is
|
||||||
|
host-published; no external core, Qdrant, or Ollama listener.
|
||||||
|
|
||||||
|
### Task 7: Activate the workspace and direct DWH binding
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify only through authenticated Workspace Management: encrypted workspace secret store
|
||||||
|
|
||||||
|
**Step 1: Pull and inspect the reviewed workspace revision**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
<new-tht> --installation <project-a-installation> \
|
||||||
|
workspace inspect --workspace psd-clinical --json
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: active workspace SHA equals the approved multi-transport revision.
|
||||||
|
|
||||||
|
**Step 2: Configure runtime bindings**
|
||||||
|
|
||||||
|
Through the authenticated Workspace Management API/UI, select `postgres_direct` and provide the
|
||||||
|
surveyed host, port, runtime user, password, and optional TLS CA. Secret values go to the encrypted
|
||||||
|
vault; they do not enter `server.env`, Git, shell arguments, or evidence.
|
||||||
|
|
||||||
|
The generated contract names are:
|
||||||
|
|
||||||
|
```text
|
||||||
|
THT_WS_PSD_CLINICAL_DWH_TRANSPORT
|
||||||
|
THT_WS_PSD_CLINICAL_DWH_HOST
|
||||||
|
THT_WS_PSD_CLINICAL_DWH_PORT
|
||||||
|
THT_WS_PSD_CLINICAL_DWH_USER
|
||||||
|
THT_WS_PSD_CLINICAL_DWH_PASSWORD_FILE
|
||||||
|
THT_WS_PSD_CLINICAL_DWH_TLS_CA_FILE
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 3: Validate and test connections**
|
||||||
|
|
||||||
|
Run static validation, live connection test, workspace inspect, and `doctor --json`. Expected: DWH,
|
||||||
|
workspace, internal embedding, and Qdrant checks pass with redacted output.
|
||||||
|
|
||||||
|
**Step 4: Re-prove read-only grants**
|
||||||
|
|
||||||
|
Use the survey's catalog query through the exact configured identity. Expected: no DML/DDL grant on
|
||||||
|
`datawarehouse`. Stop if the runtime user is an owner, superuser, or write-capable role.
|
||||||
|
|
||||||
|
### Task 8: Rebuild and verify semantic preprocessing
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Create: Project A preprocessing evidence
|
||||||
|
|
||||||
|
**Step 1: Inspect the empty/new collection state**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
<new-tht> --installation <project-a-installation> \
|
||||||
|
workspace vector inspect --workspace psd-clinical --json
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: either a compatible empty collection or the documented missing-collection state.
|
||||||
|
|
||||||
|
**Step 2: Create the descriptor-owned collection when missing**
|
||||||
|
|
||||||
|
Use the guarded vector rebuild only for collection `psd-clinical`, with exact repeated confirmation
|
||||||
|
and `--destroy`. Do not run it against any other collection.
|
||||||
|
|
||||||
|
**Step 3: Run complete preprocessing**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
<new-tht> --installation <project-a-installation> \
|
||||||
|
workspace preprocess run --workspace psd-clinical --json
|
||||||
|
```
|
||||||
|
|
||||||
|
If it returns `manual_review_required`, inspect the exact run and curated annotations, obtain the
|
||||||
|
required human decision, run `workspace schema accept --workspace psd-clinical --run <run-id> --yes`,
|
||||||
|
then resume the same run. Never auto-approve unknown FK changes.
|
||||||
|
|
||||||
|
**Step 4: Verify collection contract and counts**
|
||||||
|
|
||||||
|
Run vector inspection and record dimensions, cosine distance, required keyword indexes, and bounded
|
||||||
|
counts by payload kind/revision. Expected: all points carry the active workspace revision.
|
||||||
|
|
||||||
|
**Step 5: Prove idempotency**
|
||||||
|
|
||||||
|
Run the complete preprocessing command again. Expected: no new review, no duplicate logical points,
|
||||||
|
unchanged Evidence reported as unchanged, and the same effective configuration identity.
|
||||||
|
|
||||||
|
### Task 9: Configure and test local users
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify through `tht auth user`: protected local user registry
|
||||||
|
|
||||||
|
**Step 1: Add an ordinary test user**
|
||||||
|
|
||||||
|
Use an echo-free prompt or protected temporary password file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
<new-tht> --installation <project-a-installation> auth user add <test-user> \
|
||||||
|
--role user --display-name <display-name> --password-file <protected-temporary-password-file>
|
||||||
|
```
|
||||||
|
|
||||||
|
Remove the temporary input file after success.
|
||||||
|
|
||||||
|
**Step 2: Run authentication diagnostics**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
<new-tht> --installation <project-a-installation> auth status --json
|
||||||
|
<new-tht> --installation <project-a-installation> auth check --json
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: pristine redacted JSON and PASS.
|
||||||
|
|
||||||
|
**Step 3: Execute automated local-auth cases**
|
||||||
|
|
||||||
|
Use same-origin requests or a local headless browser to prove ordinary/admin authorization, generic
|
||||||
|
wrong-password failure, disable/enable, password/role revision invalidation, logout-all, CSRF, and
|
||||||
|
remembered-session survival after core restart. Do not retain cookie jars after the test.
|
||||||
|
|
||||||
|
### Task 10: Optionally add the private network-path test
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify only surveyed test-specific load-balancer/Nginx files
|
||||||
|
- Create: test certificate through the existing managed mechanism
|
||||||
|
|
||||||
|
**Step 1: Prove allowlist capability before proxying**
|
||||||
|
|
||||||
|
Create a temporary hostname that returns a fixed maintenance response. From an approved operator
|
||||||
|
source expect success; from an unapproved source expect denial. Do not point it at ThothII yet.
|
||||||
|
|
||||||
|
**Step 2: Validate and activate the test proxy**
|
||||||
|
|
||||||
|
Configure Nginx with the same Host/HTTPS forwarding and SSE settings intended for production. Run
|
||||||
|
`nginx -t`, validate the load balancer, then reload through the established mechanism.
|
||||||
|
|
||||||
|
**Step 3: Reconfigure local-auth public URL transactionally**
|
||||||
|
|
||||||
|
If the exact private HTTPS origin differs from the loopback origin, use the supported authentication
|
||||||
|
configuration workflow and invalidate prior test sessions. Re-run auth and doctor checks.
|
||||||
|
|
||||||
|
**Step 4: Prove both sides**
|
||||||
|
|
||||||
|
Expected: authorized operator reaches the local login; unauthorized source remains denied before
|
||||||
|
ThothII. If this cannot be demonstrated, remove the test route and continue on loopback.
|
||||||
|
|
||||||
|
### Task 11: Complete the F1-F8 acceptance session
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Complete: `docs/testing/psd-server-project-a-manual.md`
|
||||||
|
- Create: protected session evidence
|
||||||
|
|
||||||
|
**Step 1: Select the approved harmless question**
|
||||||
|
|
||||||
|
Use a known read-only PSD question agreed by the owner. Record the wording in the protected report;
|
||||||
|
do not include patient-identifying values.
|
||||||
|
|
||||||
|
**Step 2: Create the session as the ordinary local user**
|
||||||
|
|
||||||
|
Use the private browser route when present; otherwise drive the same-origin frontend/API from the
|
||||||
|
server-local terminal/headless browser. Record only session ID and sanitized milestones.
|
||||||
|
|
||||||
|
**Step 3: Review every gate**
|
||||||
|
|
||||||
|
Complete F1-F8 without auto-confirming human decisions. Confirm persisted phase/artifact state after
|
||||||
|
each gate and resume once to prove recovery.
|
||||||
|
|
||||||
|
**Step 4: Validate final SQL**
|
||||||
|
|
||||||
|
Expected: finalized session, DWH validation PASS, SQL is read-only, and no clinical mutation occurs.
|
||||||
|
|
||||||
|
**Step 5: Inspect persisted state**
|
||||||
|
|
||||||
|
Confirm manifest, question, schema linking, Evidence, CTE plan/tests, final SQL, validation report,
|
||||||
|
and decision ledger exist in local filesystem session storage. Chat/SSE need not persist.
|
||||||
|
|
||||||
|
### Task 12: Close Project A and preserve rollback
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Complete: `docs/testing/evidence/psd-server-project-a-report-template.md`
|
||||||
|
|
||||||
|
**Step 1: Run final diagnostics**
|
||||||
|
|
||||||
|
Run status, doctor, auth check, workspace inspect, vector inspect, Pi test, and a bounded secret scan
|
||||||
|
of the intended report.
|
||||||
|
|
||||||
|
**Step 2: Create a transactional new-installation backup**
|
||||||
|
|
||||||
|
Use `tht backup --drain` with a protected explicit output. Verify its checksum. Do not include
|
||||||
|
secrets in the ordinary evidence archive.
|
||||||
|
|
||||||
|
**Step 3: Complete human acceptance**
|
||||||
|
|
||||||
|
Every row in `docs/testing/psd-server-project-a-manual.md` must be PASS or explicitly blocking.
|
||||||
|
|
||||||
|
**Step 4: Record the gate**
|
||||||
|
|
||||||
|
Record exact SHAs/images, workspace revision, preprocessing identity/counts, session ID, report
|
||||||
|
digest, rollback status, and explicit `PROJECT_A_PASS` or `PROJECT_A_FAIL`.
|
||||||
|
|
||||||
|
**Step 5: Stop on FAIL**
|
||||||
|
|
||||||
|
On FAIL, stop the new stack and use the surveyed old-stack recovery plan if service restoration is
|
||||||
|
desired. Do not start Project B.
|
||||||
@@ -0,0 +1,437 @@
|
|||||||
|
# PSD Server Project B Authentik Integration Implementation Plan
|
||||||
|
|
||||||
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||||||
|
|
||||||
|
**Goal:** Convert the accepted Project A installation to public OIDC mode, store owned work sessions in the existing Supabase database's `thoth_sessions` schema, and restore the established Aritmolab-sidebar user journey through the load balancer and Nginx.
|
||||||
|
|
||||||
|
**Architecture:** Keep the same installation-descriptor path and Compose project so Project A Qdrant/Ollama volumes and bind state remain authoritative. Close ingress, snapshot Project A configuration, configure Authentik and Supabase, replace the protected installation configuration transactionally at the same paths, validate privately, then open the production route and sidebar link.
|
||||||
|
|
||||||
|
**Tech Stack:** Authentik OAuth2/OIDC Authorization Code + PKCE, ThothII OIDC/session store, Supabase PostgreSQL schema migrations/RLS, Docker Compose, Nginx, load balancer, Aritmolab.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Preconditions
|
||||||
|
|
||||||
|
- Project A automated and human reports are PASS and explicitly owner-approved.
|
||||||
|
- Application SHA, workspace SHA, images, Project A report digest, and rollback configuration match
|
||||||
|
the accepted evidence.
|
||||||
|
- The production route is closed before authentication/session-storage changes.
|
||||||
|
- All Authentik operations use the installed version's API/OpenAPI contract. Official current
|
||||||
|
references include [OAuth2/OIDC providers](https://docs.goauthentik.io/add-secure-apps/providers/oauth2/),
|
||||||
|
[provider property mappings](https://docs.goauthentik.io/add-secure-apps/providers/property-mappings/),
|
||||||
|
[application bindings](https://docs.goauthentik.io/add-secure-apps/applications/manage_apps/), and
|
||||||
|
[blueprint export](https://docs.goauthentik.io/customize/blueprints/export); installed-version
|
||||||
|
behavior wins over newer documentation.
|
||||||
|
|
||||||
|
### Task 1: Freeze Project A and close ingress
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Read: accepted Project A report
|
||||||
|
- Create: protected Project B transaction root
|
||||||
|
|
||||||
|
**Step 1: Verify exact Project A state**
|
||||||
|
|
||||||
|
Run status, doctor, auth check, workspace inspect, vector inspect, Pi status/test, Git SHA, and image
|
||||||
|
identity checks from Project A. Expected: all match the accepted report.
|
||||||
|
|
||||||
|
**Step 2: Create a protected transaction root**
|
||||||
|
|
||||||
|
Use `mktemp -d` under the survey-approved protected parent, mode `0700`. Record its path and do not
|
||||||
|
place it in Git.
|
||||||
|
|
||||||
|
**Step 3: Close production and temporary ingress**
|
||||||
|
|
||||||
|
Keep or restore a maintenance response at the production ThothII route. Disable the optional
|
||||||
|
Project A test route before changing authentication unless it is needed for a separately approved
|
||||||
|
private preflight. Confirm neither route reaches ThothII.
|
||||||
|
|
||||||
|
**Step 4: Stop and back up Project A**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
<tht> --installation <stable-installation-path> backup \
|
||||||
|
--output <project-b-transaction-root>/project-a-backup.tar --drain
|
||||||
|
<tht> --installation <stable-installation-path> stop
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify the archive using the controller's manifest/checksum contract. Preserve a copy of the exact
|
||||||
|
installation descriptor, env file, override files, auth directory, Nginx fragment, load-balancer
|
||||||
|
route, Aritmolab sidebar file/revision, and relevant Authentik export metadata.
|
||||||
|
|
||||||
|
### Task 2: Decide exact Authentik names and roles
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Create: protected `authentik-change-manifest.yaml`
|
||||||
|
|
||||||
|
**Step 1: Select the final public origin**
|
||||||
|
|
||||||
|
Use the live survey result, not historical `.it`/`.com` assumptions. Record exactly one HTTPS origin
|
||||||
|
and callback `<origin>/api/auth/oidc/callback`.
|
||||||
|
|
||||||
|
**Step 2: Select exact groups**
|
||||||
|
|
||||||
|
Default to dedicated `TOT Users` and `TOT Admin`. Reuse existing groups only if their membership
|
||||||
|
semantics match and the owner approves. Record exact case-sensitive names.
|
||||||
|
|
||||||
|
**Step 3: Define least privilege**
|
||||||
|
|
||||||
|
Map user group → `user`, admin group → `admin`. Define a separate service account/token with only
|
||||||
|
the installed Authentik permission needed to view exact group objects. No write, user-management,
|
||||||
|
directory-administration, or superuser permission.
|
||||||
|
|
||||||
|
**Step 4: Obtain owner approval of the manifest**
|
||||||
|
|
||||||
|
The manifest contains object names, slugs, intended bindings, callback, scopes, grant types,
|
||||||
|
credential destinations, and rollback action—but no secret values. Do not mutate Authentik before
|
||||||
|
approval.
|
||||||
|
|
||||||
|
### Task 3: Export and prepare Authentik
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Create: protected pre-change Authentik export
|
||||||
|
- Modify: Authentik objects named in the approved manifest
|
||||||
|
|
||||||
|
**Step 1: Export relevant configuration**
|
||||||
|
|
||||||
|
Use the installed version's supported blueprint/API export. A worker command such as
|
||||||
|
`ak export_blueprint` is valid only if present in that version. Protect export mode `0600`; remember
|
||||||
|
write-only provider secrets are not included, so backup their custody separately without printing.
|
||||||
|
|
||||||
|
**Step 2: Verify API credential scope**
|
||||||
|
|
||||||
|
Use a read-only call to list relevant groups/applications. Expected: administrative creation access
|
||||||
|
for the setup identity and a distinct path for the future group-view service account. Stop if the
|
||||||
|
credential is missing or ambiguous.
|
||||||
|
|
||||||
|
**Step 3: Create or confirm exact groups**
|
||||||
|
|
||||||
|
Create missing dedicated groups, or record approved existing group IDs. Do not bulk-copy LDAP or
|
||||||
|
unrelated Authentik memberships.
|
||||||
|
|
||||||
|
**Step 4: Create the group-catalog service account**
|
||||||
|
|
||||||
|
Grant only exact group-view permission. Create its token through the approved protected-secret
|
||||||
|
mechanism; write it directly to the ThothII secret destination without displaying it.
|
||||||
|
|
||||||
|
**Step 5: Create the OIDC provider**
|
||||||
|
|
||||||
|
Configure a confidential OAuth2/OIDC provider with the exact callback, issuer mode observed as
|
||||||
|
appropriate, Authorization Code, PKCE support, and Device Code only when required for
|
||||||
|
`tht auth check --interactive` and supported by the installed release. Do not enable implicit flow.
|
||||||
|
|
||||||
|
**Step 6: Configure scopes and direct groups claim**
|
||||||
|
|
||||||
|
Select `openid`, `profile`, and `email`. Inspect a disposable identity's decoded claim keys through
|
||||||
|
a protected verifier; retain only a redacted shape. Expected: ID token includes direct non-empty
|
||||||
|
`groups: [string, ...]`.
|
||||||
|
|
||||||
|
If the installed default profile mapping already provides that exact claim, reuse it. Otherwise add
|
||||||
|
a provider scope/property mapping under the requested `profile` scope that returns:
|
||||||
|
|
||||||
|
```python
|
||||||
|
return {"groups": [group.name for group in request.user.ak_groups.all()]}
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify the installed mapping merge semantics before activation. Do not add a custom unrequested
|
||||||
|
scope because ThothII requests only `openid`, `profile`, and `email`.
|
||||||
|
|
||||||
|
**Step 7: Create the Authentik application**
|
||||||
|
|
||||||
|
Bind it to the provider. Configure display metadata according to local Aritmolab conventions. Do not
|
||||||
|
use an Authentik proxy provider or Nginx forward-auth for ThothII.
|
||||||
|
|
||||||
|
**Step 8: Create and store the client secret**
|
||||||
|
|
||||||
|
Write the client secret directly into the protected ThothII secret bundle key
|
||||||
|
`THT_OIDC_CLIENT_SECRET`. Store the service-account token as `THT_AUTHENTIK_API_TOKEN`. Never place
|
||||||
|
either value in the change manifest, shell history, Compose environment, or evidence.
|
||||||
|
|
||||||
|
### Task 4: Prepare Supabase schema roles and backup
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Read: `harness/tht/migrations/sessions/001_schema.sql`
|
||||||
|
- Read: `harness/tht/migrations/sessions/002_security.sql`
|
||||||
|
- Create: protected Supabase backup/evidence
|
||||||
|
- Create: runtime and migrator credential files
|
||||||
|
|
||||||
|
**Step 1: Confirm the database/schema boundary**
|
||||||
|
|
||||||
|
Expected: use the surveyed existing Supabase PostgreSQL database; clinical data remains in
|
||||||
|
`datawarehouse`; application sessions use schema `thoth_sessions`; no new database is created.
|
||||||
|
|
||||||
|
**Step 2: Back up database metadata/data consistently**
|
||||||
|
|
||||||
|
Use the existing Supabase/PostgreSQL backup procedure before DDL. Record backup ID, timestamp,
|
||||||
|
checksum, and restore command. Do not put a dump in the Git repository.
|
||||||
|
|
||||||
|
**Step 3: Create or validate dedicated roles**
|
||||||
|
|
||||||
|
Create one migrator login and one runtime login according to the migration contract. The runtime
|
||||||
|
role must not be superuser, owner, BYPASSRLS, CREATEROLE, CREATEDB, or a member of DWH write roles.
|
||||||
|
The migrator credential remains unavailable to core.
|
||||||
|
|
||||||
|
**Step 4: Write protected credential files**
|
||||||
|
|
||||||
|
Create separate mode-0640 runtime-password, migrator-password, and session-CA files with surveyed
|
||||||
|
ownership. Do not use command-line password arguments.
|
||||||
|
|
||||||
|
**Step 5: Confirm PostgREST exclusion before migration**
|
||||||
|
|
||||||
|
Record the exact exposed schema list. Expected: `thoth_sessions` absent. If the system exposes all
|
||||||
|
schemas implicitly, stop and resolve the boundary before migration.
|
||||||
|
|
||||||
|
### Task 5: Prepare the stable Project B installation configuration
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify at the same stable paths: operator env, installation descriptor, authentication directory
|
||||||
|
- Create: reviewed session-server override copied from `deploy/compose.session-server.yaml.example`
|
||||||
|
- Create: protected server-session workspace config copied from `deploy/workspaces/server-sessions.yaml.example`
|
||||||
|
|
||||||
|
**Step 1: Preserve the Compose project name**
|
||||||
|
|
||||||
|
The native controller derives the project name from the absolute installation-descriptor path.
|
||||||
|
Keep that exact path. Do not point Project B at a second descriptor path, because that would create
|
||||||
|
new Qdrant/Ollama named volumes instead of using the Project A accepted state.
|
||||||
|
|
||||||
|
**Step 2: Stage Project B files beside the live files**
|
||||||
|
|
||||||
|
Prepare new env/descriptor/override/auth inputs in the protected transaction root. Add the session
|
||||||
|
DB host/port/existing database name/runtime role/migrator role/TLS mode and three secret source
|
||||||
|
paths. Use `verify-full` where hostname/SAN permits; any `verify-ca` exception requires explicit
|
||||||
|
survey evidence and owner approval.
|
||||||
|
|
||||||
|
**Step 3: Add the server-session override**
|
||||||
|
|
||||||
|
Copy the current example to a reviewed local file and add it to the existing stable descriptor's
|
||||||
|
overrides before the Git transport override ordering required by the installation. Do not edit the
|
||||||
|
tracked example.
|
||||||
|
|
||||||
|
**Step 4: Replace local auth state transactionally**
|
||||||
|
|
||||||
|
With the stack stopped, move the complete Project A auth directory into the protected transaction
|
||||||
|
root, recreate an empty private directory at the same path/ownership/mode, and configure OIDC:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
<tht> --installation <stable-installation-path> auth configure \
|
||||||
|
--mode oidc --public-url <final-https-origin> \
|
||||||
|
--issuer <authentik-issuer> --client-id <oidc-client-id> \
|
||||||
|
--authentik-base-url <authentik-base-url> \
|
||||||
|
--user-group '<exact-user-group>' --admin-group '<exact-admin-group>'
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: non-secret `auth.yaml` only; secrets resolved from the protected bundle.
|
||||||
|
|
||||||
|
**Step 5: Atomically install staged path-only files**
|
||||||
|
|
||||||
|
Use same-filesystem rename and preserve required ownership/mode. Keep the Project A originals in
|
||||||
|
the transaction root. Run `update --check-only`; on failure restore the originals immediately.
|
||||||
|
|
||||||
|
### Task 6: Run and verify session migrations
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify through one-shot migrator: existing database schema `thoth_sessions`
|
||||||
|
|
||||||
|
**Step 1: Validate migration rendering**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
<tht> --installation <stable-installation-path> update --check-only
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: core and `session-migrate` resolve the same core image; core lacks migrator password;
|
||||||
|
only the one-shot service sees it.
|
||||||
|
|
||||||
|
**Step 2: Run migrations once**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
<tht> --installation <stable-installation-path> sessions migrate --yes
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected JSON: `"pending":[]` and `"drifted":[]`; `applied` may list `001` and `002` on first use.
|
||||||
|
|
||||||
|
**Step 3: Run migration status/idempotency again**
|
||||||
|
|
||||||
|
Run the same command. Expected: no new application and both pending/drifted remain empty.
|
||||||
|
|
||||||
|
**Step 4: Verify database security**
|
||||||
|
|
||||||
|
Through bounded catalog queries, prove forced RLS, policies on session tables, runtime role without
|
||||||
|
BYPASSRLS/ownership/DDL, migrator absent from core, and no runtime privileges on unrelated schemas.
|
||||||
|
|
||||||
|
**Step 5: Recheck PostgREST exclusion**
|
||||||
|
|
||||||
|
Expected: `thoth_sessions` still absent from exposed schemas and REST endpoints cannot address it.
|
||||||
|
|
||||||
|
### Task 7: Validate Authentik and start privately
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Record: Project B protected evidence
|
||||||
|
|
||||||
|
**Step 1: Run static configuration validation**
|
||||||
|
|
||||||
|
Run `update --check-only` and redacted `auth status --json`. Expected: mode OIDC, exact public origin,
|
||||||
|
issuer/client ID/group names, and no secret values.
|
||||||
|
|
||||||
|
**Step 2: Start while public ingress remains closed**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
<tht> --installation <stable-installation-path> start
|
||||||
|
<tht> --installation <stable-installation-path> status
|
||||||
|
<tht> --installation <stable-installation-path> auth check --json
|
||||||
|
<tht> --installation <stable-installation-path> doctor --json
|
||||||
|
<tht> --installation <stable-installation-path> pi test
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: OIDC discovery/issuer/JWKS, client-secret access, Authentik catalog token, exact mapped
|
||||||
|
groups, PostgreSQL session storage, workspace, services, workflow, and Pi pass.
|
||||||
|
|
||||||
|
**Step 3: Run interactive device check when supported**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
<tht> --installation <stable-installation-path> auth check --interactive
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: approved identity completes Device Authorization and direct groups claim validates. If
|
||||||
|
the installed provider does not support device flow, record PENDING rather than substituting a token.
|
||||||
|
|
||||||
|
### Task 8: Prepare Nginx, TLS, load balancer, and sidebar
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify only survey-approved ThothII Nginx fragment
|
||||||
|
- Modify only survey-approved load-balancer route
|
||||||
|
- Modify only exact Aritmolab sidebar source when its target must change
|
||||||
|
|
||||||
|
**Step 1: Prepare direct-OIDC Nginx configuration**
|
||||||
|
|
||||||
|
Follow `docs/install/reverse-proxy-nginx.md`, direct OIDC section. Required behavior: no
|
||||||
|
`auth_request`, no callback rewrite, frontend loopback upstream, Host and HTTPS forwarded headers,
|
||||||
|
HTTP/1.1, buffering/cache off, long SSE read timeout, and `X-Accel-Buffering: no`.
|
||||||
|
|
||||||
|
**Step 2: Validate the managed certificate**
|
||||||
|
|
||||||
|
Expected: SAN matches final hostname, validity is current, chain is trusted by approved clients,
|
||||||
|
private-key permissions match local policy, and renewal/generation ownership is recorded. Never
|
||||||
|
copy the key into ThothII.
|
||||||
|
|
||||||
|
**Step 3: Validate Nginx without opening traffic**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo nginx -t
|
||||||
|
curl --fail http://127.0.0.1:<frontend-port>/health
|
||||||
|
```
|
||||||
|
|
||||||
|
Use local `--resolve`/Host tests only when they do not bypass the identity behavior being tested.
|
||||||
|
|
||||||
|
**Step 4: Prepare the load-balancer route**
|
||||||
|
|
||||||
|
Configure backend/health/TLS according to the surveyed owner procedure, initially disabled or
|
||||||
|
operator-only. Confirm it targets Nginx, never core/Qdrant/Ollama directly.
|
||||||
|
|
||||||
|
**Step 5: Preserve the Aritmolab link contract**
|
||||||
|
|
||||||
|
If the existing sidebar target already equals the final origin/path, leave source unchanged and
|
||||||
|
record proof. Otherwise make the smallest reviewed change, test it in Aritmolab's own test/build
|
||||||
|
system, and commit in that repository before deployment.
|
||||||
|
|
||||||
|
### Task 9: Open ingress and run OIDC acceptance
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Complete: `docs/testing/psd-server-project-b-manual.md`
|
||||||
|
|
||||||
|
**Step 1: Reload Nginx through the established mechanism**
|
||||||
|
|
||||||
|
Run `nginx -t` immediately before reload. Expected: reload succeeds and unrelated virtual hosts
|
||||||
|
remain healthy.
|
||||||
|
|
||||||
|
**Step 2: Enable the final load-balancer route**
|
||||||
|
|
||||||
|
Expected: HTTP redirects to HTTPS; TLS is valid; `/api/auth/oidc/login` redirects to the correct
|
||||||
|
Authentik provider; callback returns to the exact public origin.
|
||||||
|
|
||||||
|
**Step 3: Test ordinary and admin identities**
|
||||||
|
|
||||||
|
Start at Aritmolab, authenticate once, then use the sidebar. Expected: no second credential prompt;
|
||||||
|
ordinary user can use sessions but receives 403 for admin operations; admin has only documented
|
||||||
|
permissions.
|
||||||
|
|
||||||
|
**Step 4: Test no-role and malformed cases**
|
||||||
|
|
||||||
|
An identity with no mapped group authenticates but receives no application role/403. Missing,
|
||||||
|
malformed, indirect, or ambiguous group claims fail closed with generic browser errors and redacted
|
||||||
|
diagnostics. Do not retain raw claims.
|
||||||
|
|
||||||
|
**Step 5: Test logout and restart**
|
||||||
|
|
||||||
|
Verify ThothII logout revokes its own cookie. Document whether the Authentik SSO session remains and
|
||||||
|
therefore allows immediate re-login without credentials; do not claim global logout unless
|
||||||
|
configured and tested. Restart core and verify expected OIDC session behavior.
|
||||||
|
|
||||||
|
### Task 10: Verify PostgreSQL ownership and complete F1-F8
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Create: protected Project B session evidence
|
||||||
|
|
||||||
|
**Step 1: Create sessions under two identities**
|
||||||
|
|
||||||
|
Expected: ordinary users see only their own sessions; cross-user access returns the documented
|
||||||
|
not-found boundary; admin behavior matches `session.read_all/manage_all` permissions.
|
||||||
|
|
||||||
|
**Step 2: Verify RLS with the runtime path**
|
||||||
|
|
||||||
|
Use application/API tests and bounded catalog evidence. Never disable RLS for diagnosis.
|
||||||
|
|
||||||
|
**Step 3: Complete one harmless OIDC PSD session**
|
||||||
|
|
||||||
|
Use the same approved read-only question or another owner-approved one. Complete F1-F8, validate
|
||||||
|
final SQL, resume once, and confirm session/artifacts/decisions are stored in `thoth_sessions`.
|
||||||
|
|
||||||
|
**Step 4: Verify ephemeral boundaries**
|
||||||
|
|
||||||
|
Expected: no chat transcript or SSE stream stored as session artifacts; no vectors in PostgreSQL;
|
||||||
|
Qdrant remains the semantic store.
|
||||||
|
|
||||||
|
### Task 11: Test controlled failures and rollback
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Record: protected rollback evidence
|
||||||
|
|
||||||
|
**Step 1: Test a reversible provider/catalog failure**
|
||||||
|
|
||||||
|
Use a controlled, owner-approved method such as a temporary disabled test credential or test object.
|
||||||
|
Expected: auth diagnostics and browser login fail closed, redacted, then pass after restoration.
|
||||||
|
Never break unrelated Authentik applications.
|
||||||
|
|
||||||
|
**Step 2: Rehearse ingress-first rollback**
|
||||||
|
|
||||||
|
Close the production route, validate Nginx restoration commands, and prove the protected Project A
|
||||||
|
configuration snapshot is complete. A full rollback need not destroy `thoth_sessions`.
|
||||||
|
|
||||||
|
**Step 3: Verify additive database rollback boundary**
|
||||||
|
|
||||||
|
Expected: rollback leaves schema/data intact for evidence and future recovery. No automatic DROP
|
||||||
|
SCHEMA or role deletion.
|
||||||
|
|
||||||
|
### Task 12: Close Project B
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Complete: `docs/testing/evidence/psd-server-project-b-report-template.md`
|
||||||
|
|
||||||
|
**Step 1: Run final diagnostics**
|
||||||
|
|
||||||
|
Run status, doctor, auth check, interactive check when supported, workspace inspect, vector inspect,
|
||||||
|
Pi test, Nginx validation, load-balancer health, Supabase migration/security checks, and sidebar test.
|
||||||
|
|
||||||
|
**Step 2: Remove the Project A temporary endpoint**
|
||||||
|
|
||||||
|
Remove only its load-balancer route, Nginx fragment, and managed certificate reference according to
|
||||||
|
their owners. Validate/reload and prove the hostname no longer routes.
|
||||||
|
|
||||||
|
**Step 3: Complete the human guide and report**
|
||||||
|
|
||||||
|
Every mandatory row must be PASS. Record exact source/image/workspace identities, Authentik object
|
||||||
|
names/IDs, Supabase database plus `thoth_sessions`, public origin, Aritmolab revision, report digest,
|
||||||
|
and `PROJECT_B_PASS` or `PROJECT_B_FAIL`.
|
||||||
|
|
||||||
|
**Step 4: Handle FAIL safely**
|
||||||
|
|
||||||
|
On FAIL, close ingress first. Restore Project A files at the same stable paths, move OIDC auth state
|
||||||
|
to protected evidence, restore the local-auth directory, validate, and start Project A privately.
|
||||||
|
Disable new Authentik objects; do not delete them or drop the session schema automatically.
|
||||||
@@ -0,0 +1,308 @@
|
|||||||
|
# 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.
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
# PSD Server Project A — Acceptance Report
|
||||||
|
|
||||||
|
> Template only. Store detailed/raw evidence in the protected server evidence root. This report
|
||||||
|
> must not contain passwords, tokens, cookies, keys, hashes of passwords, secret-file contents,
|
||||||
|
> raw claims, patient-identifying data, or unbounded logs.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
- Result: `PROJECT_A_PASS` / `PROJECT_A_FAIL` / `PROJECT_A_PENDING`
|
||||||
|
- Decision timestamp UTC:
|
||||||
|
- Owner/reviewer:
|
||||||
|
- Protected evidence path:
|
||||||
|
- Evidence manifest SHA-256:
|
||||||
|
|
||||||
|
## Frozen identities
|
||||||
|
|
||||||
|
- ThothII source SHA:
|
||||||
|
- Plan source SHA:
|
||||||
|
- Workspace previous SHA:
|
||||||
|
- Workspace multi-transport SHA:
|
||||||
|
- Mac REST validation result/evidence reference:
|
||||||
|
- Native `tht` version/build identity:
|
||||||
|
- Core image ID/digest:
|
||||||
|
- Frontend image ID/digest:
|
||||||
|
- Qdrant image digest:
|
||||||
|
- Ollama image digest:
|
||||||
|
- Pi version/provider/model/thinking:
|
||||||
|
|
||||||
|
## Survey and legacy recovery
|
||||||
|
|
||||||
|
- Survey result/digest:
|
||||||
|
- Legacy source/image identity:
|
||||||
|
- Legacy backup location/checksum reference:
|
||||||
|
- Legacy restart recipe verified: PASS/FAIL
|
||||||
|
- Legacy stack stopped without deletion: PASS/FAIL
|
||||||
|
- Production route closed: PASS/FAIL
|
||||||
|
|
||||||
|
## New installation
|
||||||
|
|
||||||
|
- Installation descriptor path:
|
||||||
|
- Compose project:
|
||||||
|
- Frontend loopback/private origin:
|
||||||
|
- Optional private endpoint used: yes/no
|
||||||
|
- Optional allowlist positive/negative result:
|
||||||
|
- Service health result:
|
||||||
|
- Doctor result:
|
||||||
|
- Pi result:
|
||||||
|
- Listener-boundary result:
|
||||||
|
|
||||||
|
## Authentication
|
||||||
|
|
||||||
|
- Mode: local
|
||||||
|
- Admin/user separation:
|
||||||
|
- Wrong-password generic failure:
|
||||||
|
- Disable/enable:
|
||||||
|
- Password/role/logout-all invalidation:
|
||||||
|
- Remembered restart:
|
||||||
|
- Logout:
|
||||||
|
- CSRF/cross-origin rejection:
|
||||||
|
- Manual guide result and reviewer:
|
||||||
|
|
||||||
|
## Workspace and data plane
|
||||||
|
|
||||||
|
- Workspace ID/revision:
|
||||||
|
- Server transport: postgres_direct
|
||||||
|
- Mac transport remains rest_api: PASS/FAIL
|
||||||
|
- Supabase database name:
|
||||||
|
- DWH schema: datawarehouse
|
||||||
|
- Read-only role proof reference:
|
||||||
|
- DWH connection diagnostics:
|
||||||
|
- Qdrant collection contract:
|
||||||
|
- Ollama model/dimensions:
|
||||||
|
- Preprocess first run ID/result:
|
||||||
|
- FK review digest/result:
|
||||||
|
- Schema point count:
|
||||||
|
- Evidence point/chunk count:
|
||||||
|
- Preprocess idempotency result:
|
||||||
|
- Effective configuration identity:
|
||||||
|
|
||||||
|
## F1-F8 session
|
||||||
|
|
||||||
|
- Approved sanitized question reference:
|
||||||
|
- Session ID:
|
||||||
|
- Owner identity type: local ordinary user
|
||||||
|
- Resume tested:
|
||||||
|
- F1-F8 result:
|
||||||
|
- Finalized:
|
||||||
|
- Final SQL read-only validation:
|
||||||
|
- Persisted artifact/decision inventory:
|
||||||
|
- No patient-identifying evidence retained: PASS/FAIL
|
||||||
|
|
||||||
|
## Rollback and hygiene
|
||||||
|
|
||||||
|
- New-installation backup/checksum reference:
|
||||||
|
- Legacy rollback remains available:
|
||||||
|
- Secret scan result:
|
||||||
|
- Unrelated failures or pending items:
|
||||||
|
- Reason for final decision:
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
# PSD Server Project B — Acceptance Report
|
||||||
|
|
||||||
|
> Template only. Store raw Authentik exports, database backups, browser traces, and server topology
|
||||||
|
> only in protected server storage. Never retain passwords, provider/client secrets, API tokens,
|
||||||
|
> cookies, raw claims, callback query strings, private keys, patient-identifying data, or unbounded
|
||||||
|
> logs in this report.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
- Result: `PROJECT_B_PASS` / `PROJECT_B_FAIL` / `PROJECT_B_PENDING`
|
||||||
|
- Decision timestamp UTC:
|
||||||
|
- Owner/reviewer:
|
||||||
|
- Protected evidence path:
|
||||||
|
- Evidence manifest SHA-256:
|
||||||
|
- Accepted Project A report digest:
|
||||||
|
|
||||||
|
## Frozen candidate
|
||||||
|
|
||||||
|
- ThothII source SHA:
|
||||||
|
- Workspace SHA:
|
||||||
|
- Core/frontend image identities:
|
||||||
|
- Qdrant/Ollama image identities:
|
||||||
|
- Pi provider/model:
|
||||||
|
- Public origin:
|
||||||
|
- Aritmolab source/deployment revision:
|
||||||
|
|
||||||
|
## Authentik
|
||||||
|
|
||||||
|
- Installed version:
|
||||||
|
- Pre-change export reference/checksum:
|
||||||
|
- Application name/ID:
|
||||||
|
- Provider name/ID:
|
||||||
|
- Issuer:
|
||||||
|
- Callback path verified:
|
||||||
|
- Grant types/scopes verified:
|
||||||
|
- Direct groups claim shape verified:
|
||||||
|
- User group name/ID:
|
||||||
|
- Admin group name/ID:
|
||||||
|
- Group-catalog service account name/ID:
|
||||||
|
- Least-privilege result:
|
||||||
|
- `auth check --json` result:
|
||||||
|
- Interactive device check: PASS/FAIL/PENDING
|
||||||
|
- No secret/raw claim in evidence: PASS/FAIL
|
||||||
|
|
||||||
|
## Supabase session storage
|
||||||
|
|
||||||
|
- Existing database name:
|
||||||
|
- Session schema: thoth_sessions
|
||||||
|
- Backup reference/checksum:
|
||||||
|
- Migration result (`pending=[]`, `drifted=[]`):
|
||||||
|
- Migration idempotency:
|
||||||
|
- Runtime role security/RLS result:
|
||||||
|
- Migrator absent from core:
|
||||||
|
- PostgREST exposed schemas proof:
|
||||||
|
- `thoth_sessions` not REST-exposed: PASS/FAIL
|
||||||
|
- DWH `datawarehouse` privileges unchanged: PASS/FAIL
|
||||||
|
|
||||||
|
## Nginx, TLS, load balancer, and Aritmolab
|
||||||
|
|
||||||
|
- Nginx configuration file/revision:
|
||||||
|
- `nginx -t` result:
|
||||||
|
- Certificate subject/SAN/expiry metadata:
|
||||||
|
- Certificate trust result:
|
||||||
|
- Load-balancer route/health result:
|
||||||
|
- Same-origin API/callback result:
|
||||||
|
- SSE unbuffered result:
|
||||||
|
- No double `auth_request`: PASS/FAIL
|
||||||
|
- Sidebar source/link result:
|
||||||
|
- Other virtual hosts unchanged: PASS/FAIL
|
||||||
|
|
||||||
|
## Human SSO and authorization
|
||||||
|
|
||||||
|
- Aritmolab login → sidebar → ThothII without second credential prompt:
|
||||||
|
- Ordinary user permissions:
|
||||||
|
- Administrator permissions:
|
||||||
|
- No-role user result:
|
||||||
|
- Extra unrelated group result:
|
||||||
|
- Missing/malformed group negative result:
|
||||||
|
- Forged-header result:
|
||||||
|
- ThothII logout result:
|
||||||
|
- Authentik SSO session behavior documented:
|
||||||
|
- Provider/catalog controlled failure and recovery:
|
||||||
|
- Manual guide result and reviewer:
|
||||||
|
|
||||||
|
## OIDC F1-F8 session and ownership
|
||||||
|
|
||||||
|
- Approved sanitized question reference:
|
||||||
|
- Session ID:
|
||||||
|
- OIDC principal reference (non-identifying):
|
||||||
|
- F1-F8/final SQL result:
|
||||||
|
- PostgreSQL manifest/artifact/decision persistence:
|
||||||
|
- Resume/restart result:
|
||||||
|
- Cross-user isolation result:
|
||||||
|
- Admin cross-user result:
|
||||||
|
- Chat/SSE ephemeral boundary:
|
||||||
|
|
||||||
|
## Rollback, cleanup, and hygiene
|
||||||
|
|
||||||
|
- Ingress-first rollback rehearsal:
|
||||||
|
- Project A protected configuration available:
|
||||||
|
- Authentik disable plan verified:
|
||||||
|
- Additive schema rollback boundary verified:
|
||||||
|
- Project A temporary endpoint removed:
|
||||||
|
- Legacy stack stopped/unexposed:
|
||||||
|
- Core/Qdrant/Ollama private:
|
||||||
|
- Secret scan result:
|
||||||
|
- Unrelated failures or pending items:
|
||||||
|
- Reason for final decision:
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
# PSD Server — Survey Report
|
||||||
|
|
||||||
|
> Template only. The completed report and raw inventory remain in protected server storage. Do not
|
||||||
|
> include passwords, tokens, cookies, private keys, password hashes, raw claims, full container
|
||||||
|
> environments, patient-identifying data, or unbounded logs.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
- Result: `SURVEY_GO` / `SURVEY_NO_GO`
|
||||||
|
- Timestamp UTC:
|
||||||
|
- Operator:
|
||||||
|
- Protected evidence path:
|
||||||
|
- Report SHA-256:
|
||||||
|
- Blocking unknowns:
|
||||||
|
|
||||||
|
## Host
|
||||||
|
|
||||||
|
- OS/version/kernel:
|
||||||
|
- Architecture:
|
||||||
|
- Docker/Compose versions:
|
||||||
|
- CPU/RAM/free disk:
|
||||||
|
- Approved service UID/GID:
|
||||||
|
- Local terminal/CyberArk constraints:
|
||||||
|
|
||||||
|
## Legacy ThothII
|
||||||
|
|
||||||
|
- Source path/SHA/dirty state:
|
||||||
|
- Compose/controller path and project:
|
||||||
|
- Services/images:
|
||||||
|
- Published ports:
|
||||||
|
- Networks:
|
||||||
|
- Volumes/binds:
|
||||||
|
- Data/config/secret reference paths:
|
||||||
|
- Current health:
|
||||||
|
- Active sessions/users:
|
||||||
|
- Recovery/maintenance state:
|
||||||
|
- Backup procedure and owner:
|
||||||
|
- Exact stop/start commands:
|
||||||
|
|
||||||
|
## New installation roots
|
||||||
|
|
||||||
|
- Adjacent source root:
|
||||||
|
- Operator root:
|
||||||
|
- Secret root:
|
||||||
|
- Data root:
|
||||||
|
- Pi-state root:
|
||||||
|
- Workspace-registry root:
|
||||||
|
- Backup root:
|
||||||
|
- Protected evidence root:
|
||||||
|
- Port reserved for Project A:
|
||||||
|
|
||||||
|
## Nginx, TLS, and load balancer
|
||||||
|
|
||||||
|
- Nginx version/config owner:
|
||||||
|
- Relevant virtual-host/include files:
|
||||||
|
- Current ThothII upstream:
|
||||||
|
- Forwarded headers/SSE behavior:
|
||||||
|
- Certificate subject/SAN/issuer/expiry:
|
||||||
|
- Certificate generation/renewal owner:
|
||||||
|
- Load-balancer owner/config surface:
|
||||||
|
- Health check/TLS boundary/source addresses:
|
||||||
|
- Temporary hostname allowlist possible: yes/no
|
||||||
|
- Exact reload/rollback procedure:
|
||||||
|
|
||||||
|
## Aritmolab
|
||||||
|
|
||||||
|
- Public origin observed:
|
||||||
|
- Source/deployment path and SHA:
|
||||||
|
- Compose/network identity:
|
||||||
|
- Sidebar file/line/link target:
|
||||||
|
- Historical `.it`/`.com` discrepancy resolved as:
|
||||||
|
- Build/test/deploy procedure:
|
||||||
|
- Configuration owner:
|
||||||
|
|
||||||
|
## Authentik
|
||||||
|
|
||||||
|
- Installed version/image:
|
||||||
|
- Deployment path/services:
|
||||||
|
- Base URL/issuer conventions:
|
||||||
|
- Existing Aritmolab application/provider pattern:
|
||||||
|
- Groups relevant to ThothII:
|
||||||
|
- Credential reference paths and usability:
|
||||||
|
- Export/backup procedure:
|
||||||
|
- API/OpenAPI version:
|
||||||
|
- Required human help:
|
||||||
|
|
||||||
|
## Supabase/PostgreSQL
|
||||||
|
|
||||||
|
- Existing database name:
|
||||||
|
- PostgreSQL/pooler/PostgREST components:
|
||||||
|
- Direct container-to-database route:
|
||||||
|
- TLS mode/CA reference:
|
||||||
|
- Existing schemas:
|
||||||
|
- Existing `thoth_sessions` state:
|
||||||
|
- PostgREST exposed schemas:
|
||||||
|
- Backup/restore mechanism:
|
||||||
|
- Proposed runtime/migrator role names:
|
||||||
|
- Role-creation owner:
|
||||||
|
|
||||||
|
## PSD DWH
|
||||||
|
|
||||||
|
- Database/schema:
|
||||||
|
- Direct host/port from core:
|
||||||
|
- Runtime role reference:
|
||||||
|
- Read-only grant proof result:
|
||||||
|
- TLS requirements:
|
||||||
|
- REST binding retained for Mac:
|
||||||
|
|
||||||
|
## Workspace Git
|
||||||
|
|
||||||
|
- Remote/branch/access:
|
||||||
|
- Current main SHA:
|
||||||
|
- Server deploy-key scope:
|
||||||
|
- Descriptor schema/transports:
|
||||||
|
- Evidence/annotations state:
|
||||||
|
- Curator with push authority:
|
||||||
|
|
||||||
|
## Pi, LLM, Qdrant, and Ollama
|
||||||
|
|
||||||
|
- Pi version/provider/model/thinking:
|
||||||
|
- Credential reference:
|
||||||
|
- LLM endpoint reachability:
|
||||||
|
- Qdrant/Ollama image architecture support:
|
||||||
|
- Capacity assessment:
|
||||||
|
|
||||||
|
## Topology
|
||||||
|
|
||||||
|
Describe the observed final flow and every trust boundary. Reference a protected diagram if the
|
||||||
|
topology itself is considered sensitive.
|
||||||
|
|
||||||
|
## Intended changes by owner
|
||||||
|
|
||||||
|
| Owner/component | Exact files/objects | Project | Rollback |
|
||||||
|
|---|---|---|---|
|
||||||
|
| New ThothII | | A/B | |
|
||||||
|
| Workspace curator | | A | |
|
||||||
|
| Nginx | | A optional/B | |
|
||||||
|
| Load balancer | | A optional/B | |
|
||||||
|
| Aritmolab | | B | |
|
||||||
|
| Authentik | | B | |
|
||||||
|
| Supabase | | B | |
|
||||||
|
|
||||||
|
## GO/NO-GO rationale
|
||||||
|
|
||||||
|
- Verified old-stack rollback:
|
||||||
|
- Verified secret custody:
|
||||||
|
- Verified read-only DWH:
|
||||||
|
- Verified configuration owners:
|
||||||
|
- Verified resources:
|
||||||
|
- Unresolved risks:
|
||||||
|
- Final rationale:
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
# Progetto A PSD — collaudo manuale
|
||||||
|
|
||||||
|
Questo documento guida il collaudo umano del nuovo ThothII sul server con autenticazione locale.
|
||||||
|
Non sostituisce i controlli automatici del piano. Compilarlo soltanto dopo che Sol ha dichiarato
|
||||||
|
verdi installazione, workspace, DWH, Qdrant, Ollama e preprocessing.
|
||||||
|
|
||||||
|
## Regole
|
||||||
|
|
||||||
|
- Eseguire i comandi dal terminale locale del server; non usare tunnel SSH.
|
||||||
|
- Non copiare nel rapporto password, cookie, token, chiavi, hash, stringhe di connessione o righe di
|
||||||
|
log che li contengano.
|
||||||
|
- Usare un amministratore locale e un utente ordinario creati appositamente.
|
||||||
|
- Non effettuare più tentativi di password errata del necessario: il login applica rate limiting.
|
||||||
|
- Per ogni prova segnare `PASS`, `FAIL` o `PENDING`, con una nota breve e non sensibile.
|
||||||
|
- Un solo `FAIL` obbligatorio impedisce di avviare il Progetto B.
|
||||||
|
|
||||||
|
## Dati iniziali
|
||||||
|
|
||||||
|
| Campo | Valore redatto |
|
||||||
|
|---|---|
|
||||||
|
| Data/ora UTC | |
|
||||||
|
| SHA ThothII | |
|
||||||
|
| SHA workspace | |
|
||||||
|
| Installation descriptor | percorso protetto, senza contenuto |
|
||||||
|
| Origine di test | loopback oppure hostname privato |
|
||||||
|
| Endpoint temporaneo usato | sì/no |
|
||||||
|
| ID domanda di prova approvata | |
|
||||||
|
| Operatore | |
|
||||||
|
|
||||||
|
## 1. Stato generale
|
||||||
|
|
||||||
|
Eseguire:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
THT_BIN=<percorso-tht>
|
||||||
|
INSTALLATION=<percorso-assoluto-thothii-installation.yaml>
|
||||||
|
"$THT_BIN" --installation "$INSTALLATION" status
|
||||||
|
"$THT_BIN" --installation "$INSTALLATION" doctor --json
|
||||||
|
"$THT_BIN" --installation "$INSTALLATION" auth check --json
|
||||||
|
"$THT_BIN" --installation "$INSTALLATION" pi test
|
||||||
|
```
|
||||||
|
|
||||||
|
| Prova | Risultato atteso | Esito | Note |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Stato servizi | frontend, core, qdrant ed embedding sani; initializer completato | | |
|
||||||
|
| Doctor | tutti i controlli obbligatori passano | | |
|
||||||
|
| Autenticazione | modalità `local`, configurazione pronta | | |
|
||||||
|
| Pi | provider e modello rispondono | | |
|
||||||
|
| Secret hygiene | nessun secret nell’output | | |
|
||||||
|
|
||||||
|
## 2. Confine di rete
|
||||||
|
|
||||||
|
Dal terminale controllare i listener e la configurazione renderizzata secondo il piano.
|
||||||
|
|
||||||
|
| Prova | Risultato atteso | Esito | Note |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Frontend | pubblicato solo su loopback o tramite endpoint privato approvato | | |
|
||||||
|
| Core | nessuna porta host pubblica | | |
|
||||||
|
| Qdrant | nessuna porta host pubblica nel profilo server | | |
|
||||||
|
| Ollama | nessuna porta host pubblica | | |
|
||||||
|
| URL produzione | non raggiunge il nuovo stack | | |
|
||||||
|
| Endpoint privato, se usato | sorgente autorizzata ammessa | | |
|
||||||
|
| Endpoint privato, se usato | sorgente non autorizzata respinta prima di ThothII | | |
|
||||||
|
|
||||||
|
Se non esiste un endpoint privato, usare il browser headless/API sul server. Non segnare come
|
||||||
|
eseguite prove browser che non sono state realmente svolte.
|
||||||
|
|
||||||
|
## 3. Autenticazione locale
|
||||||
|
|
||||||
|
Eseguire tramite frontend/browser quando disponibile; altrimenti usare richieste same-origin dal
|
||||||
|
terminale, conservando cookie e password soltanto in file temporanei mode `0600`, poi eliminandoli.
|
||||||
|
|
||||||
|
| Prova | Azione | Risultato atteso | Esito | Note |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| Accesso anonimo | aprire pagina/API protetta | appare login oppure HTTP 401 | | |
|
||||||
|
| Password errata | un tentativo con utente valido | errore generico; nessun dettaglio account | | |
|
||||||
|
| Utente ordinario | login corretto | accesso alle sessioni | | |
|
||||||
|
| Confine ruoli | aprire Pi Management/amministrazione | negato o non visibile | | |
|
||||||
|
| Logout | uscire e ricaricare | sessione rifiutata, nuovo login richiesto | | |
|
||||||
|
| Amministratore | login corretto | funzioni amministrative previste disponibili | | |
|
||||||
|
| Disabilitazione | Sol disabilita l’utente di prova | login rifiutato genericamente | | |
|
||||||
|
| Riabilitazione | Sol riabilita l’utente | login nuovamente possibile | | |
|
||||||
|
| Invalidazione | cambio password/ruolo o `logout-all` | vecchia sessione non più valida | | |
|
||||||
|
| Remember me | login persistente, riavvio core | sessione ancora valida entro TTL | | |
|
||||||
|
| CSRF | mutazione senza token corretto | richiesta respinta | | |
|
||||||
|
|
||||||
|
Non disabilitare o demansionare l’ultimo amministratore abilitato.
|
||||||
|
|
||||||
|
## 4. Workspace e DWH
|
||||||
|
|
||||||
|
Eseguire:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
"$THT_BIN" --installation "$INSTALLATION" \
|
||||||
|
workspace inspect --workspace psd-clinical --json
|
||||||
|
"$THT_BIN" --installation "$INSTALLATION" \
|
||||||
|
workspace vector inspect --workspace psd-clinical --json
|
||||||
|
```
|
||||||
|
|
||||||
|
| Prova | Risultato atteso | Esito | Note |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Revisione Git | coincide con lo SHA approvato | | |
|
||||||
|
| Trasporto server | `postgres_direct` | | |
|
||||||
|
| Database/schema | database Supabase rilevato, schema `datawarehouse` | | |
|
||||||
|
| Utente DWH | read-only dimostrato dai grant | | |
|
||||||
|
| Workspace Mac | prova separata conferma ancora `rest_api` | | |
|
||||||
|
| Qdrant | 1024 dimensioni, cosine, indici payload richiesti | | |
|
||||||
|
| Ollama | `qwen3-embedding:0.6b` | | |
|
||||||
|
| Evidence | corpus Git attivo alla stessa revisione | | |
|
||||||
|
|
||||||
|
## 5. Preprocessing e idempotenza
|
||||||
|
|
||||||
|
Esaminare i due risultati consecutivi del preprocessing prodotti da Sol.
|
||||||
|
|
||||||
|
| Prova | Risultato atteso | Esito | Note |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Introspezione DWH | completata senza scritture cliniche | | |
|
||||||
|
| Annotazioni FK | revisione umana registrata e legata al digest corretto | | |
|
||||||
|
| Schema index | record presenti con workspace revision | | |
|
||||||
|
| Evidence index | documenti/chunk presenti con workspace revision | | |
|
||||||
|
| Seconda esecuzione | nessun duplicato; contenuti invariati riconosciuti | | |
|
||||||
|
| Identità effettiva | invariata tra i due run | | |
|
||||||
|
|
||||||
|
## 6. Sessione completa F1–F8
|
||||||
|
|
||||||
|
Usare una domanda innocua approvata, senza identificativi reali di pazienti.
|
||||||
|
|
||||||
|
| Fase | Controllo manuale | Esito | Note |
|
||||||
|
|---|---|---|---|
|
||||||
|
| F1 | domanda compresa/disambiguata correttamente | | |
|
||||||
|
| F2 | concetti e contesto coerenti | | |
|
||||||
|
| F3 | tabelle candidate ragionevoli | | |
|
||||||
|
| F4 | colonne/join curati e confermati | | |
|
||||||
|
| F5 | piano CTE comprensibile | | |
|
||||||
|
| F6 | ogni CTE testata e approvata | | |
|
||||||
|
| F7 | SQL finale read-only e validato | | |
|
||||||
|
| F8 | conclusione, memoria e riepilogo coerenti | | |
|
||||||
|
|
||||||
|
Durante una fase intermedia chiudere/riprendere la sessione una volta. Il resume deve tornare
|
||||||
|
all’ultima fase incompleta senza creare una nuova domanda.
|
||||||
|
|
||||||
|
Verificare infine:
|
||||||
|
|
||||||
|
| Prova | Risultato atteso | Esito | Note |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Stato | sessione `finalized` | | |
|
||||||
|
| SQL | solo lettura; validazione DWH verde | | |
|
||||||
|
| Artefatti | manifest, question, schema linking, Evidence, CTE, SQL, validation presenti | | |
|
||||||
|
| Decisioni | gate registrati nel ledger | | |
|
||||||
|
| Persistenza | artefatti leggibili dopo riavvio | | |
|
||||||
|
| Chat/SSE | non richiesti come persistenza | | |
|
||||||
|
|
||||||
|
## 7. Decisione
|
||||||
|
|
||||||
|
| Gate | Esito |
|
||||||
|
|---|---|
|
||||||
|
| Tutti i controlli obbligatori PASS | |
|
||||||
|
| Nessun secret raccolto | |
|
||||||
|
| Rollback vecchio stack ancora disponibile | |
|
||||||
|
| Progetto B autorizzabile | |
|
||||||
|
|
||||||
|
Decisione finale: `PROJECT_A_PASS` / `PROJECT_A_FAIL` / `PROJECT_A_PENDING`
|
||||||
|
|
||||||
|
Revisore e data: ______________________________________
|
||||||
|
|
||||||
|
Motivazione sintetica: ______________________________________
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
# Progetto B PSD — collaudo manuale Authentik e Aritmolab
|
||||||
|
|
||||||
|
Questo documento verifica il percorso finale di produzione. Si esegue soltanto dopo il PASS del
|
||||||
|
Progetto A e dopo che Sol ha completato i preflight Authentik, Supabase, Nginx e bilanciatore.
|
||||||
|
|
||||||
|
## Regole
|
||||||
|
|
||||||
|
- Usare identità di prova approvate: una ordinaria, una amministrativa e, se disponibile, una senza
|
||||||
|
gruppi ThothII.
|
||||||
|
- Non acquisire token, cookie, password, chiavi private, claim completi o trace browser contenenti
|
||||||
|
URL di callback con parametri.
|
||||||
|
- Partire dalla home reale di Aritmolab, non da un URL interno di ThothII.
|
||||||
|
- Segnare `PASS`, `FAIL` o `PENDING`; non dedurre il PASS da test automatici.
|
||||||
|
|
||||||
|
## Dati iniziali
|
||||||
|
|
||||||
|
| Campo | Valore redatto |
|
||||||
|
|---|---|
|
||||||
|
| Data/ora UTC | |
|
||||||
|
| SHA ThothII/workspace | |
|
||||||
|
| Origine pubblica | |
|
||||||
|
| SHA/revisione Aritmolab | |
|
||||||
|
| Nome/ID applicazione Authentik | non inserire secret |
|
||||||
|
| Database Supabase | |
|
||||||
|
| Schema sessioni | `thoth_sessions` |
|
||||||
|
| Operatore/revisore | |
|
||||||
|
|
||||||
|
## 1. TLS, routing e pagina iniziale
|
||||||
|
|
||||||
|
| Prova | Azione | Risultato atteso | Esito | Note |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| HTTP | aprire origine in HTTP | redirect a HTTPS | | |
|
||||||
|
| Certificato | ispezionare il lucchetto/catena | hostname corretto, nessun warning | | |
|
||||||
|
| Home Aritmolab | aprire URL ufficiale | pagina disponibile | | |
|
||||||
|
| Sidebar | individuare ThothII | link presente come prima | | |
|
||||||
|
| Destinazione | aprire il link | nuovo frontend ThothII | | |
|
||||||
|
| API | caricare l’app | nessun 502/404 o mixed content | | |
|
||||||
|
| SSE | avviare attività modello | aggiornamenti continui, niente buffering evidente | | |
|
||||||
|
|
||||||
|
## 2. Single sign-on
|
||||||
|
|
||||||
|
Chiudere ogni precedente sessione di test secondo la procedura concordata. Accedere ad Aritmolab
|
||||||
|
con l’identità ordinaria, quindi aprire ThothII dalla sidebar.
|
||||||
|
|
||||||
|
| Prova | Risultato atteso | Esito | Note |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Primo login | Authentik autentica l’utente | | |
|
||||||
|
| Passaggio sidebar | nessuna seconda richiesta di credenziali | | |
|
||||||
|
| Callback | ritorno all’origine pubblica ThothII | | |
|
||||||
|
| Identità | nome visualizzato coerente, senza dati grezzi del token | | |
|
||||||
|
| Browser storage | nessun access/id token in Local/Session Storage | | |
|
||||||
|
| Cookie | cookie ThothII HttpOnly/Secure/SameSite secondo configurazione | | |
|
||||||
|
|
||||||
|
Non copiare il valore del cookie nel rapporto.
|
||||||
|
|
||||||
|
## 3. Ruoli e autorizzazione
|
||||||
|
|
||||||
|
| Identità/caso | Risultato atteso | Esito | Note |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Gruppo utente | può creare, leggere e gestire le proprie sessioni | | |
|
||||||
|
| Gruppo utente | Pi Management e funzioni admin negate con 403/non visibili | | |
|
||||||
|
| Gruppo admin | funzioni amministrative documentate disponibili | | |
|
||||||
|
| Nessun gruppo mappato | autenticato ma operazioni protette negate | | |
|
||||||
|
| Gruppo estraneo aggiuntivo | nessun cambiamento e nessun warning | | |
|
||||||
|
| Header identità forgiato | nessun privilegio aggiuntivo | | |
|
||||||
|
|
||||||
|
Le prove su claim mancante/malformato possono essere eseguite da Sol con un’identità/provider di
|
||||||
|
test controllato. Il revisore verifica soltanto esito HTTP generico e report redatto, mai il token.
|
||||||
|
|
||||||
|
## 4. Logout e riavvio
|
||||||
|
|
||||||
|
| Prova | Azione | Risultato atteso | Esito | Note |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| Logout ThothII | usare il comando dell’app | cookie ThothII revocato | | |
|
||||||
|
| SSO ancora attivo | riaprire ThothII | possibile nuovo accesso senza password; documentare | | |
|
||||||
|
| Logout Authentik globale | se configurato e in scope | comportamento conforme alla policy locale | | |
|
||||||
|
| Riavvio core | Sol riavvia in finestra controllata | sessione browser valida secondo TTL/policy | | |
|
||||||
|
| Provider indisponibile | prova controllata | nuovo login fallisce chiuso e redatto | | |
|
||||||
|
| Ripristino provider | ripetere diagnosi/login | servizio torna operativo | | |
|
||||||
|
|
||||||
|
Non dichiarare “logout globale” se è stato testato soltanto il logout locale di ThothII.
|
||||||
|
|
||||||
|
## 5. Sessioni PostgreSQL e isolamento
|
||||||
|
|
||||||
|
| Prova | Risultato atteso | Esito | Note |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Migrazioni | `pending=[]`, `drifted=[]` | | |
|
||||||
|
| Schema | `thoth_sessions` nel database Supabase esistente | | |
|
||||||
|
| PostgREST | schema non esposto | | |
|
||||||
|
| RLS | forzata sulle tabelle previste | | |
|
||||||
|
| Utente A/B | ciascuno vede soltanto le proprie sessioni | | |
|
||||||
|
| Accesso incrociato | risposta not-found/negata come da contratto | | |
|
||||||
|
| Admin | accesso trasversale solo secondo permessi documentati | | |
|
||||||
|
| Credenziale migratore | non montata nel core | | |
|
||||||
|
| Schema clinico | nessun nuovo privilegio runtime | | |
|
||||||
|
|
||||||
|
## 6. Sessione completa sotto OIDC
|
||||||
|
|
||||||
|
Come utente ordinario, eseguire una domanda innocua approvata e completare F1–F8.
|
||||||
|
|
||||||
|
| Prova | Risultato atteso | Esito | Note |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Creazione | sessione associata all’identità OIDC | | |
|
||||||
|
| Gate F1–F8 | tutti presentati e registrati correttamente | | |
|
||||||
|
| Resume | ritorna alla sessione corretta | | |
|
||||||
|
| SQL finale | sola lettura e validato | | |
|
||||||
|
| Persistenza | manifest, artefatti e decisioni in PostgreSQL | | |
|
||||||
|
| SSE/chat | funzionano live; non richiesti come artefatti persistiti | | |
|
||||||
|
| Riavvio | sessione di lavoro ancora disponibile | | |
|
||||||
|
|
||||||
|
## 7. Integrazione e pulizia finale
|
||||||
|
|
||||||
|
| Prova | Risultato atteso | Esito | Note |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Endpoint temporaneo A | rimosso/non instradato | | |
|
||||||
|
| Vecchio stack | fermo, non esposto | | |
|
||||||
|
| Link sidebar | punta solo alla nuova release | | |
|
||||||
|
| Servizi privati | core/Qdrant/Ollama non pubblicati | | |
|
||||||
|
| Altri servizi Nginx | invariati e sani | | |
|
||||||
|
| Rollback | procedura verificata e disponibile | | |
|
||||||
|
| Evidenze | nessun secret o dato clinico identificabile | | |
|
||||||
|
|
||||||
|
## 8. Decisione
|
||||||
|
|
||||||
|
Decisione finale: `PROJECT_B_PASS` / `PROJECT_B_FAIL` / `PROJECT_B_PENDING`
|
||||||
|
|
||||||
|
Revisore e data: ______________________________________
|
||||||
|
|
||||||
|
Motivazione sintetica: ______________________________________
|
||||||
|
|
||||||
|
Conferma percorso finale “Aritmolab → sidebar → ThothII → SSO”: ______________________________
|
||||||
@@ -50,6 +50,9 @@ nav:
|
|||||||
- Guida utente: guida-utente.md
|
- Guida utente: guida-utente.md
|
||||||
- Accettazione autenticazione: testing/authentication-manual-acceptance.md
|
- Accettazione autenticazione: testing/authentication-manual-acceptance.md
|
||||||
- Setup Policlinico San Donato: install/psd-workspace-setup.md
|
- Setup Policlinico San Donato: install/psd-workspace-setup.md
|
||||||
|
- Programma deploy server PSD: plans/2026-08-20-psd-server-deployment-program.md
|
||||||
|
- Collaudo PSD Progetto A: testing/psd-server-project-a-manual.md
|
||||||
|
- Collaudo PSD Progetto B: testing/psd-server-project-b-manual.md
|
||||||
- ThothII (Documentazione Tecnica):
|
- ThothII (Documentazione Tecnica):
|
||||||
- Panoramica Architettura: architecture/overview.md
|
- Panoramica Architettura: architecture/overview.md
|
||||||
- Autenticazione: architecture/authentication.md
|
- Autenticazione: architecture/authentication.md
|
||||||
|
|||||||
Reference in New Issue
Block a user