Files
ThothII/docs/superpowers/plans/2026-07-16-user-owned-session-storage.md
T

11 KiB

User-owned sessions implementation plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Associate every ThothII session and preference with a stable logged-in or local OS principal.

Architecture: The harness owns a repository contract. FilesystemSessionRepository stores readable phase documents under the local user home; PostgresSessionRepository stores the same logical snapshot in a private Supabase schema. The backend resolves a trusted principal before every action and passes it through to tht; the portal proxy supplies that identity.

Tech Stack: Python 3.12, Typer, SQLAlchemy/psycopg2, PostgreSQL/Supabase RLS, Fastify/TypeScript, React/Vitest, Django/nginx.

Global Constraints

  • Server storage is PostgreSQL wire protocol with TLS verification, schema thoth_sessions; never PostgREST or browser DB access.
  • Server identity is (issuer, Django request.user.pk); clients never choose session owner.
  • Admin authorization uses Authentik group authentik Admins; unauthorized and missing session both return HTTP 404.
  • Server has no persistent session filesystem fallback or dual write; DB failure is HTTP 503 before Pi starts.
  • Local mode uses ~/.thothii or THT_HOME, runs loopback-only, and creates a UUID identity in identity.json.
  • Persist current artifacts and append-only decisions only; no chat transcript, artifact revisions, session embeddings, or content in audit logs.
  • New session IDs are UUIDv4. Existing solved_question behavior is unchanged.
  • Follow TDD: each behavior test must fail before its implementation is written.

Task 1: Session repository contract and local implementation

Files:

  • Create: harness/tht/session/repository.py, harness/tht/session/filesystem_repository.py
  • Modify: harness/tht/config.py, harness/tht/session/store.py, harness/tht/session/models.py, harness/pyproject.toml
  • Test: harness/tests/test_session_repository.py, harness/tests/test_local_identity.py

Interfaces: Produce PrincipalContext, SessionSnapshot, SessionRepository, and build_session_repository(config, principal). The filesystem adapter must preserve the present documents under <THT_HOME>/workspaces/<workspace>/sessions/<uuid4> and read/write artifact keys, decisions, manifest fields, and per-principal preferences.

  • Write failing tests proving UUIDv4 creation, principal-scoped local roots, readable phase artifacts, decision append, THT_HOME override, and an identity UUID stable across restarts.
  • Run cd harness && .venv/bin/pytest tests/test_session_repository.py tests/test_local_identity.py -q; confirm failure because repository and identity interfaces do not exist.
  • Implement the smallest repository contract and filesystem adapter. Use portalocker for mutations and private local directory/file permissions where supported.
  • Run the focused tests and cd harness && .venv/bin/pytest -q && .venv/bin/ruff check ..
  • Commit feat(harness): add local session repository.

Task 2: PostgreSQL schema, migrations, and repository

Files:

  • Create: harness/tht/session/postgres_repository.py, harness/tht/migrations/sessions/001_schema.sql, harness/tht/migrations/sessions/002_security.sql
  • Modify: harness/tht/cli/session_cmd.py, harness/tht/config.py
  • Test: harness/tests/test_postgres_session_repository.py, harness/tests/test_session_migrate_cmd.py

Interfaces: Add tht session migrate --database-url URL [--status] --json; PostgresSessionRepository implements the Task 1 contract, starts a transaction, sets actor/admin local settings, and maps cte_sql:<name> to artifacts.

  • Write failing unit/integration tests for migration status, owner isolation, admin cross-user access, cascade delete with content-free audit tombstone, and no embedding invocation.
  • Run the focused tests and confirm expected RED failures.
  • Implement idempotent migration runner, private tables, forced RLS policies, role separation, advisory transaction locks, and repository methods using direct PostgreSQL TLS settings.
  • Run focused tests, then full harness tests and Ruff.
  • Commit feat(harness): persist server sessions in postgres.

Task 3: Migrate harness workflow and deterministic write commands

Files:

  • Modify: harness/tht/session/store.py, harness/tht/decisions.py, harness/tht/phase.py, harness/tht/taskdoc.py, harness/tht/ctetest.py, harness/tht/solved.py, harness/tht/teardown.py, harness/tht/cli/{session,decision,cte,sql,phase,search,memory}_cmd.py, harness/.pi/skills/tht-sessione/SKILL.md, harness/.pi/extensions/tht-gate.js
  • Test: harness/tests/test_session_repository_workflow.py, harness/gate/__tests__/session-repository-writes.test.js

Interfaces: Existing workflow commands operate through the configured repository. Add tht cte save --session ID --name NAME --file - and tht sql set-final --session ID --file -; Pi tools write_cte_sql and write_final_sql use them instead of direct session paths.

  • Write failing tests that run phase calculation and finalize against an in-memory/filesystem repository, and prove Pi write tools persist CTE/final SQL without direct sessions/<id> writes.
  • Run focused tests and record RED results.
  • Refactor path-bound helpers into snapshot/ledger and repository calls; retain backwards-compatible readable local documents and pristine --json stdout.
  • Make finalization atomically store report/evidence/status only after DWH verification; leave solved-question creation best-effort.
  • Run harness and gate test suites, then commit refactor(harness): route workflow persistence through repositories.

Task 4: Trusted portal identity and proxy forwarding

Files:

  • Modify: /home/chirone/omics_portal/kokoro/datamart_catalog_views.py, /home/chirone/omics_portal/nginx/nginx.conf
  • Create: /home/chirone/omics_portal/kokoro/test_thothii_auth.py

Interfaces: The auth-request response supplies only X-Thoth-Principal-Issuer, X-Thoth-Principal-Subject, X-Thoth-Principal-Display-Name, and X-Thoth-Is-Admin. nginx removes client values for those headers and forwards subrequest values to ThothII.

  • Write Django tests for authenticated capability user, denied user, Django PK subject, admin group flag, and absent/spoofed client headers.
  • Run the focused Docker test and confirm RED.
  • Emit normalized headers from the capability endpoint and configure nginx auth-request header capture/injection.
  • Run docker compose exec -T web python manage.py test accounts.test_capabilities kokoro.test_thothii_auth -v 2.
  • Commit the portal changes in its own repository with feat(thothii): forward trusted principal.

Task 5: Backend principal enforcement and per-user settings

Files:

  • Create: backend/src/auth/principal.ts
  • Modify: backend/src/auth/auth.ts, backend/src/config.ts, backend/src/app.ts, backend/src/routes/{sessions,settings,sql,meta}.ts, backend/src/tht/tht-runner.ts, backend/src/pi/pi-process-manager.ts
  • Test: backend/test/auth.test.ts, backend/test/routes-sessions.test.ts, backend/test/sse-route.test.ts, backend/test/routes-settings.test.ts

Interfaces: Add GET /me; require a PrincipalContext for all session, document, SQL, response, steer and SSE operations. GET /sessions?scope=mine|all permits all only for admins. Local mode creates ~/.thothii/identity.json; upstream mode accepts only proxy-injected normalized headers.

  • Write failing route tests for missing identity (401), foreign session (404), admin all-scope, owner assignment server-side, SSE denial before Pi spawn, and preference isolation.
  • Run cd backend && npx vitest run test/auth.test.ts test/routes-sessions.test.ts test/sse-route.test.ts test/routes-settings.test.ts; confirm RED.
  • Implement principal parser, local identity, upstream validation, repository-aware ThtRunner, session authorization before Pi, /me, scope enforcement and async per-user settings.
  • Run backend Vitest, typecheck, and build; commit feat(backend): enforce user-owned sessions.

Task 6: Frontend identity and administrator UX

Files:

  • Modify: frontend/src/api/{client,sessions,settings,types}.ts, frontend/src/shell/{AppShell,NavSessions,SessionMenu}.tsx
  • Test: frontend/src/api/sessions.test.ts, frontend/src/shell/AppShell.session-mgmt.test.tsx, frontend/src/shell/NavSessions.test.tsx

Interfaces: Fetch /me; default to scope=mine. Display explicit All sessions only to admins, show owner labels/admin banner, and require confirmation before cross-owner destructive actions.

  • Write failing component/API tests for regular-user scope, admin scope switch, owner label, admin banner, and cross-owner confirmation.
  • Run focused Vitest tests and confirm RED.
  • Implement typed client calls, session scope state, and explicit admin affordances without changing ordinary user flow.
  • Run frontend Vitest, npx tsc -b, build and E2E; commit feat(frontend): expose owned session scopes.

Task 7: Deployment contract, migration and cutover tooling

Files:

  • Modify: docker/, deployment examples, README.md, PROJECT_STATE.md
  • Test: harness/tests/test_session_migrate_cmd.py, backend/test/config.test.ts

Interfaces: Define runtime/migrator DB secret names, AUTH_MODE=upstream server configuration, local loopback-only configuration, and health/readiness behavior returning 503 when repository storage is unavailable.

  • Write failing config tests for required server database/TLS inputs and rejected public/local combinations.
  • Run focused tests and confirm RED.
  • Document runtime/migrator roles, CA/secret injection, backup then deletion of the three legacy server sessions, maintenance-mode cutover, and no dual-write rollback policy.
  • Run all three layer gates; commit docs(deploy): document user-owned session cutover.

Task 8: End-to-end authorization verification and final review

Files:

  • Modify: test fixtures only as required by earlier tasks.

  • Add cross-layer tests for A/B/admin isolation, spoofed-header rejection, concurrent session mutation, local two-home isolation, absent embeddings, and failed DB startup before Pi.

  • Run harness, backend and frontend complete gates plus portal Docker tests.

  • Run the final whole-branch review, fix all Critical and Important findings, and re-run the covering tests.

  • Commit test: cover user-owned session security boundaries and prepare the branch for integration.