Skip to content

trevor — Iteration Plan

Spec-driven, iterative delivery. Each iteration produces working, tested code and a refined spec layer. Spec artefacts (API schema, data model updates) are written before implementation within each iteration.


Iteration 0 — Project skeleton & local dev

Goal: A running trevor with no features, but with the full scaffolding in place.

Deliverables: - uv-managed Python project, ruff config, prek hooks - FastAPI app with health endpoint - SQLModel + Alembic setup (SQLite locally, PostgreSQL path documented) - Keycloak dev container + OIDC login flow (or DEV_AUTH_BYPASS) - MinIO dev container + S3 client abstraction (aioboto3) - ARQ worker + Redis setup - Tilt / k3d local dev environment - Helm chart skeleton - Docker image + GitHub Actions CI (lint, test, build) - spec/ directory with all initial ADRs (this document set)


Iteration 1 — Project sync & user model

Goal: trevor knows about projects and users.

Spec to write first: - OpenAPI paths: GET /projects, GET /projects/{id}, GET /users/me - DB migration: Project, User, ProjectMembership tables

Deliverables: - CRD sync CronJob reading CR8TOR project CRDs - User shadow record created/updated on Keycloak login - ProjectMembership CRUD (admin only) - Role conflict validation (researcher ≠ checker on same project) - Admin UI: project list, checker assignment


Iteration 2 — Airlock request lifecycle (researcher side)

Goal: Researcher can create a request and upload output objects.

Spec to write first: - OpenAPI paths: POST /requests, GET /requests, GET /requests/{id}, POST /requests/{id}/objects, GET /requests/{id}/objects/{object_id} - DB migration: AirlockRequest, OutputObject, OutputObjectMetadata, AuditEvent - State machine implementation

Deliverables: - Request creation (egress + ingress direction) - File upload with streaming to quarantine S3, checksum computation - Object metadata form (title, description, statbarn, justification, suppression notes) - File preview rendering (markdown, CSV, image, PDF, parquet, code) - Request submission - Researcher dashboard: list requests, view status - Audit event emission on all state transitions


Iteration 3 — Agent review

Goal: Automatic statbarn-based review runs on submission.

Spec to write first: - Agent rule engine design (statbarn → rules mapping) - Review table migration - ARQ job: agent_review_job

Deliverables: - Statbarn rule engine (initial rule set from SACRO guide) - Agent review ARQ job triggered on SUBMITTED - Structured report output per object - Optional LLM narrative via configurable provider - Agent report stored as Review record - State transition: SUBMITTEDAGENT_REVIEWHUMAN_REVIEW - Notification to checkers when agent report is ready


Iteration 4 — Human review (checker side)

Goal: Output checkers can review requests and provide structured feedback.

Spec to write first: - OpenAPI paths: POST /requests/{id}/reviews, GET /requests/{id}/reviews - Checker dashboard spec

Deliverables: - Checker dashboard: queue of requests awaiting review - Per-object review form with agent report displayed alongside - Accept agent findings / override per object - Decision: approve / request changes / reject - Checker feedback written to OutputObjectMetadata.checker_feedback - Two-reviewer rule enforcement - State transitions to CHANGES_REQUESTED, APPROVED, REJECTED - Notifications: researcher notified of outcome


Iteration 5 — Revision cycle (researcher response)

Goal: Researcher can respond to feedback and resubmit.

Deliverables: - Researcher sees per-object feedback inline with their objects - Replacement object upload (new version of a logical object) - Metadata carry-forward on replacement - Resubmission (returns request to SUBMITTED, triggers agent review again) - Lineage display in UI: version history per logical object


Iteration 6 — Release (RO-Crate + pre-signed URL)

Goal: Approved requests are packaged and delivered.

Deliverables: - RO-Crate assembly from approved objects + metadata - Checksum verification before assembly - Upload crate zip to release S3 bucket - Pre-signed URL generation (configurable TTL) - ReleaseRecord created - Email notification with download link - State transition to RELEASED - URL expiry warning notification (CronJob)


Iteration 7 — Admin dashboard & metrics

Goal: Admins and senior checkers have full visibility and operational metrics.

Deliverables: - All-projects request overview (status, age, direction) - Metrics: median time to review, requests per checker, approval rates, revision counts - Audit log viewer (filterable by project, user, event type, date range) - Checker assignment management - Stuck request detection (requests waiting > configurable SLA) - Export audit log as CSV


Iteration 7.5 — Datastar UI

Goal: Server-rendered Datastar UI covering all backend functionality from iterations 1–7.

Spec to write first: - Template structure, Datastar patterns, SSE endpoints - See spec/iteration-7.5-spec.md for full spec

Deliverables: - Base template shell (nav, project switcher, auth state, flash messages) - Researcher views: request list, create, detail, upload, metadata, replace, resubmit - Checker views: review queue, review form with agent report alongside - Admin views: request overview, metrics dashboard, audit log, membership management - File preview component (CSV, markdown, code, image, PDF) - SSE live updates (request status, review queue) - Minimal custom CSS (no framework, no build step)


Iteration 8 — Ingress flow

Goal: Complete the ingress direction (import into TRE).

Deliverables: - Ingress request creation by admin/external submitter - Pre-signed PUT URL for external file submission - Review flow (same as egress) - Delivery to workspace on approval (pre-signed GET URL for workspace to consume) - UI: Ingress-specific views (upload via pre-signed PUT, delivery status)


Iteration 9 — Hardening & observability

Deliverables: - Prometheus metrics endpoint (/metrics) - Structured JSON logging - OpenTelemetry tracing - Horizontal scaling smoke tests (multi-pod ARQ worker concurrency) - Security review: CSRF, rate limiting, input validation audit - Pen test checklist - Production Helm values review - Runbook documentation - UI: CSRF token integration, error pages (403, 404, 500), loading states


Iteration 10 — Local development environment

Goal: Single-command local dev stack with Tilt, k3d, and all infrastructure dependencies.

Deliverables: - Devcontainer configuration (VS Code / Codespaces / remote) - Bare-metal setup scripts (scripts/dev-setup.sh, scripts/dev-teardown.sh) - Tiltfile rewrite: trevor + PostgreSQL + Redis + SeaweedFS + Keycloak in k3d - Kubernetes dev manifests (deploy/dev/): SeaweedFS, PostgreSQL, Redis, Keycloak - Pre-configured Keycloak realm with test users - SeaweedFS replaces MinIO (ADR-0013 — licensing) - Developer quick-start documentation


Iteration 11 — Production Helm chart completion

Goal: Complete Helm chart with all Kubernetes resources for production deployment.

Deliverables: - Service, ServiceAccount, Ingress templates - ARQ worker Deployment template - HorizontalPodAutoscaler template - PodDisruptionBudget template - Network policies (optional, gated) - Alembic migration Job (Helm pre-upgrade hook) - envFromSecrets wired into API and worker containers - Startup probes, init container migration option - NOTES.txt post-install message


Iteration 12 — OIDC login/logout flow & JWT validation

Goal: Full browser login/logout UX via Keycloak OIDC and JWT validation for API Bearer tokens.

Spec: spec/iterations/iteration-12-spec.md
ADR: ADR-0007 (existing — covers all auth decisions)

Deliverables: - OIDC client module: discovery, PKCE, token exchange, JWKS cache, ID token validation - Session cookie module: stateless signed cookie via itsdangerous - Auth routes: /auth/login (redirect to Keycloak), /auth/callback (code exchange), /auth/logout - Dual auth in get_auth_context: session cookie for UI, Bearer token for API, dev bypass unchanged - JWT validation against Keycloak JWKS (python-jose) - 401 handler: redirect to login for browser requests, JSON for API - Logout link in nav template - Keycloak realm config: standardFlowEnabled: true - Tests: PKCE, session cookie roundtrip, JWT validation, login/callback/logout flow (mocked Keycloak)


Iteration 12.5 — Checker UI Redesign (Split-Pane Review)

Goal: Redesign output checker UI from flat review queue to three-level drill-down (project list → request list → split-pane review) inspired by SACRO Outputs Viewer, adapted for trevor's domain model.

Spec: spec/iterations/iteration-12.5-spec.md

Deliverables: - Project list page: card grid with pending request counts and oldest wait time - Per-project request list with agent decision badges - Full-viewport split-pane review form: - Left sidebar: object list with status indicators, Datastar-powered client-side selection - Right detail panel: metadata grid, researcher justification, agent assessment (statbarn confirmation, disclosure risk, rule checks, narrative), per-object approve/reject controls - Bottom footer: overall decision radios, summary input, submit - Agent findings parsed per-object from Review.findings JSON - Researcher metadata (justification, suppression notes) surfaced to checker - All-or-none release model enforced in UI - 4 new tests (164 total)


Iteration 13 — CRD Sync Reconciler

Goal: Automatically sync CR8TOR Project, User, and Group CRDs into trevor's database.

Spec: spec/iterations/iteration-13-spec.md
ADRs: ADR-0012 (CRD sync design), ADR-0016 (official kubernetes client, supersedes ADR-0014)

Deliverables: - kubernetes>=31.0 dependency (official Python client) - CRD client module (crd.py) — CustomObjectsApi list functions wrapped for async via run_in_executor - Sync service (crd_sync_service.py) — parse CRDs, reconcile projects/users/memberships - ARQ cron job running every 5 minutes - RBAC manifest (ClusterRole + ClusterRoleBinding) - Researcher memberships derived from parent + analyst Group CRDs - Checker memberships preserved (never deleted by sync) - Role conflict detection and warning


Iteration 14 — Notification Service: Core + In-App Backend

Goal: Pluggable notification system with in-app notification storage and API.

Spec: spec/iterations/iteration-14-spec.md
ADR: ADR-0009 (notification abstraction)

Deliverables: - Notification DB model + Alembic migration - NotificationEvent dataclass, NotificationBackend protocol - NotificationRouter with error-isolated multi-backend dispatch - InAppBackend — writes to Notification table - ARQ job send_notifications_job for async dispatch - API: GET /notifications, PATCH /notifications/{id}/read, GET /notifications/unread-count - Nav bar badge showing unread notification count (static, SSE in iter 16) - Notification triggers wired into review, release, and state-transition flows


Iteration 15 — Email Notification Backend

Goal: SMTP email delivery for all notification events.

Spec: spec/iterations/iteration-15-spec.md
ADR: ADR-0009

Deliverables: - aiosmtplib dependency - SmtpBackend implementing NotificationBackend protocol - 7 Jinja2 email templates (HTML + plain-text): submitted, agent_report_ready, changes_requested, approved, rejected, released, url_expiring - Settings: smtp_host, smtp_port, smtp_from_address, smtp_use_tls - Error-isolated dispatch (SMTP failure logged, never blocks) - Registration in NotificationRouter when email_notifications_enabled=True


Iteration 16 — SSE Live Updates

Goal: Real-time UI updates via Server-Sent Events using Datastar's native SSE support.

Spec: spec/iterations/iteration-16-spec.md
ADR: ADR-0015 (SSE live updates)

Deliverables: - SSE helper utility for Datastar fragment events - GET /ui/sse/requests/{id}/status — live request status badge - GET /ui/sse/review/queue-count — live review queue count for checkers - GET /ui/sse/notifications/count — live unread notification count - Template updates: data-on-load attributes on status badges and nav badges - Database polling (2s interval, 5min connection timeout) - Auth via session cookie on connection open


Iteration 17 — ARQ Cron Jobs: URL Expiry & Stuck Requests

Goal: Proactive alerts for expiring pre-signed URLs and stuck requests.

Spec: spec/iterations/iteration-17-spec.md

Deliverables: - url_expiry_warning_job — detect ReleaseRecords with URLs expiring within 48h, notify researcher - stuck_request_alert_job — detect requests stuck in review > configurable hours, notify admins - expiry_warned_at field on ReleaseRecord (Alembic migration) - request.stuck notification event type - Idempotent — expiry_warned_at prevents duplicate warnings - Settings: url_expiry_warning_hours


Iteration 18 — File Preview Rendering

Goal: Server-side file preview for CSV, markdown, code, images in the review and detail views.

Spec: spec/iterations/iteration-18-spec.md

Deliverables: - Preview service (preview_service.py) — render file content to HTML - CSV/TSV/Parquet via polars (first 50 rows) - Markdown via mistune - Code via pygments syntax highlighting - Images via base64 data URI - HTML sanitization via nh3 - Size limit: skip preview for files > 10MB - Graceful degradation when S3 unavailable (dev mode) - Updated file_preview.html template


Iteration 19 — Production Readiness

Goal: PostgreSQL migration testing, Helm hardening, CI improvements, operational documentation.

Spec: spec/iterations/iteration-19-spec.md

Deliverables: - CI job running Alembic migrations + tests against PostgreSQL - values.production.yaml with production-appropriate Helm defaults - Helm lint + template validation in CI - Dockerfile scan (trivy) in CI - docs/runbook.md — deployment, migrations, failure modes, monitoring, scaling - docs/security-checklist.md — CSRF, rate limiting, auth, secrets, container security


Iteration 20 — Two-Panel Researcher/Checker UI

Goal: Redesign the researcher request detail page and the checker review form into a consistent two-panel layout with inline upload, inline metadata editing, file-type icons, and per-object state dots. Expose the title metadata field in all relevant forms and views.

Spec: spec/iterations/iteration-20-spec.md

Deliverables: - Two-panel researcher detail page: left nav (ft-icon + state dot) + right panel (object detail, inline upload, inline metadata edit, Reviews/Audit tabs) - Datastar signals replacing deprecated data-store in checker review form - title field added to metadata POST endpoint, upload form, and checker review metadata display - _build_request_detail_ctx shared context helper - CSS: ft-icon file-type palette (tabular/figure/code/report/model/other), obj-state-dot state indicators - 10 new tests (262 total)


Later / backlog

  • Per-user notification preference settings
  • Slack / Teams webhook backend
  • Multi-language UI (i18n)
  • Bulk operations (approve multiple objects in one action)
  • Researcher self-service statbarn lookup / guidance
  • API key support for programmatic submission
  • TRE-specific RO-Crate profile proposal (community contribution)
  • CRD watch mode (real-time sync, complement to periodic reconcile)