Files
transcription/docs/roadmap_plan.md
T
2026-08-23 12:23:57 -05:00

240 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Roadmap Review: Recommendations & Version Plan
This is a review/consulting deliverable. It organizes your near-term changes,
nice-to-haves, and long-range goals into version buckets, building on
`./docs/ver4.8/feature_backlog_v4_8.md` (already-scoped image work) and
folding in the additional items from your original list.
Versioning convention (per your direction): **4.84.11** are incremental
feature/fix releases; **5.x and 6.x are reserved for major changes** to the
app (a shared data-model overhaul, and the hosting migration, respectively).
Final deliverable will be saved to `./docs` in the repo per your instruction.
---
## V4.8 — Bug fixes + Image Experience
**Bug fixes (do first within this release — data correctness, not features):**
1. **Stale Error Detail after resubmit.** Root cause found in `db/models.py`:
`Source.latest_error_detail` sorts all `execution_attempts` on the latest
job by `attempt_number` descending and returns the **first attempt with
any `error_detail`**, even if that's an older attempt and the latest
attempt succeeded. Fix: only report error detail from the latest attempt,
don't fall through to earlier ones.
2. **"View Jobs" ≠ "View Sources" behavior.** `/documents/{id}/sources`
already redirects to the filtered Transcription Pipeline Jobs page;
`/documents/{id}/jobs` renders its own bare two-field custom page instead.
Fix: make `/documents/{id}/jobs` redirect the same way, filtered by document.
**Image Experience (Track A from the V4.8 backlog doc — already scoped, high
value/low risk, storage layer already exists):**
3. **Homepage Image Gallery** (recommended first feature in that doc):
`list_homepage_images()` already returns every stored image; only the
multi-image carousel UI and optional slideshow rotation are missing.
4. **Pan and Zoom on Source Detail**: recover `document_panzoom.py` from git
history (deleted in V4.6 Phase 5, `6a3ee26`), but vendor the Panzoom
library locally instead of the unpkg CDN, and reuse `resolve_media_url`
from `media_urls.py` instead of recreating its old helper. Scope to Source
Detail only — do not add it to the shared `dark_room_viewer`.
**Note:** the backlog doc's model-performance/telemetry item still applies as
stated there — it must wait for V4.7 Phase 4 to land first, since `duration_ms`
today mixes provider latency with preprocessing/DB commit time.
---
## V4.9 — Detail Page Parity Pass
Small, low-risk structural-parity fixes across Person/Job/Document detail pages:
- Hide "Maiden Name" on Person detail when empty.
- Job Record detail "Document Links" box → mirror the Document detail page's
"Sources & Pipeline Jobs" box (clickable name, Sources count, single
"View Sources" button, no "+Add Job").
- Transcription Pipeline Jobs page: add a Document Name column; resolve
Created vs. Updated by keeping **Updated** as the primary/visible field
(more actionable) and de-emphasizing Created rather than deleting it outright.
- Person detail "Linked Documents" → 3-column table (Document Name, Role,
Number of Pages), with clickable document names, dropping the "Open" button.
---
## V4.10 — Settings Consolidation & Small Enhancements
- **Settings page → tabs**, not sub-pages (per your confirmation). Convert the
existing stacked cards (Document Types, Person Roles, Prompts) into
`ui.tabs`/`ui.tab_panels`, and add a new **Home Page Text** tab. One route,
no navigation overhead, scales cleanly as more settings are added.
- **Google Maps links** for Person birth/death locations — cheap, no
scraping, a formatted place string becomes a Maps search link.
- **FamilySearch ID lookup** (scope confirmed as narrow): on the Person
create/edit form, add a FamilySearch ID field and an "Auto-fill from
FamilySearch" button that fetches only birth date/place, death date/place,
and marriage date/spouse for that specific ID — a single-record lookup, not
a crawler. This keeps FamilySearch.org as a companion reference rather than
a data source the app tries to replace. Because it's ID-driven and
single-record, it's a much smaller, safer feature than open-ended scraping —
worth doing at this scope, revisit if FamilySearch's page structure changes
and breaks the parser.
---
## V4.11 — Approved Scope
- **Tags** (supersedes "collections"): many-to-many tagging for Documents with
Settings-style management (same pattern as Document Types and Person Roles),
autocomplete-capable assignment, and a dedicated **Tags** entry point for
browse/filter-by-tag workflows.
- **Source Detail simplification**: remove the separate **Transcription Text**
card; show Source image + Editable Revision + Source/SourceJob metadata in a
3-column top layout, then keep Candidate Machine Transcriptions below the
image/revision area.
- **Integrity reconciliation checks in tests**:
- document folder count under `UPLOAD_DIR/documents` must equal `document`
row count.
- source file count under each `UPLOAD_DIR/documents/{document_id}` folder
must equal `source` row count for that Document.
- failures should include actionable mismatch details (missing row/folder or
file/source mapping).
- **UI table updates**:
- Archival Documents: remove **Archive Ref**, add **# Sources**.
- Archival Entities: People: remove **Display Name** and **Maiden Name**
columns, add **FamilySearch ID**.
- Transcription Pipeline Jobs: add **# Sources**.
- **Create Processing Job page**: Provider and Model must be selectable for new
job creation.
Deferred out of this release:
- UI theme selection.
- Settings-based `.env` editing and runtime controls.
- Person table structural redesign (removing/splitting name fields).
---
## V5.0 — Unified Photos Table (major data-model change)
V5.0 standardizes homepage images and Person portraits into one shared `photo`
table and one storage layout.
Finalized shape:
- `photo`: `id`, nullable `person_id`, `path`, `description`, `is_primary`,
timestamps.
- `person_id IS NULL` = homepage photos; non-null = Person photos.
- `is_primary` is the featured/first photo for that owner (homepage or Person).
- No separate context enum; ownership is derived from `person_id`.
- All image files are stored under `UPLOAD_DIR/photos/{photo_id}{suffix}`.
- `Person.portrait_path` is removed.
- `HOMEPAGE_DIR` is retired; homepage markdown remains file-backed at
`UPLOAD_DIR/homepage.md`.
Migration policy for legacy installs:
- Export/import rebuild remains the migration mechanism.
- Legacy `person.portrait_path` values are backfilled into `photo` rows.
- Legacy homepage images under `UPLOAD_DIR/homepage` are backfilled into
homepage `photo` rows.
- Legacy homepage markdown is relocated to `UPLOAD_DIR/homepage.md`.
---
## V5.1 — Person table structural redesign
- Replace `person.full_name` with split required fields:
- `last_name`
- `given_names` (first + middle)
- Remove `display_name` and `maiden_name` from active schema/UI.
- Keep `family_search_id` optional and unique (not required in this version).
- Add `person_tag` many-to-many links so People use the same Tag registry as Documents.
- Update Archival Entities: People list columns to:
- Last Name
- First & Middle
- FamilySearch ID
- Birth Date
- Death Date
- # Documents
- Migration/export-import behavior backfills split names from legacy `full_name` values.
---
## V6.0 — Server Hosting Migration
Your stated approach (Postgres in Docker, app in Docker, Cloudflare Tunnel) is
the standard, low-maintenance way to get secure remote access without exposing
ports or running your own VPN/reverse-proxy TLS setup. Sequential stages
(each de-risks the next):
**Stage 0 — Prerequisites**
- Confirm data access already goes through the service layer (it does, per
`.github/instructions/services.instructions.md`) — this is what makes the
DB swap and later auth additive rather than a rewrite.
- Confirm upload/file storage path (`settings.upload_dir`) is Docker-volume-friendly.
- Confirm DB URL and upload dir are both env-overridable (`.env`/`.env.example`
already exist).
**Stage 1 — Containerize** against the *existing* SQLite file first (smallest
possible change) to validate the container boundary (networking, volumes,
permissions) before also switching databases. `Dockerfile`/`docker-compose.yml`
already exist in the repo — confirm current intent vs. extend for production.
**Stage 2 — Migrate to PostgreSQL.** Since the app uses SQLModel/SQLAlchemy,
this should mostly be a connection string/dialect change plus a data migration
script. Do this as its own isolated step so a regression is attributable to
the DB swap alone. Resolve the Postgres connection through a small
factory/indirection point rather than a single global engine constant — this
costs nothing now and keeps the door open for per-user databases later (see
Beyond, below).
**Stage 3 — Expose via Cloudflare Tunnel.** Add a `cloudflared` container
pointed at the app's internal port (no public port exposure needed). Put the
tunnel hostname behind Cloudflare Access (free tier, email OTP/SSO) as the
**first layer of remote-access auth**, even before the app has its own login
system — gets secure remote access working quickly and buys time to do
Stage 4 and later user-auth properly instead of rushed.
**Stage 4 — Backups & operational hygiene.** Automated Postgres backups
(scheduled `pg_dump`) and uploaded-file backups *before* exposing this to the
internet — this is the point where a data-loss incident would be most
damaging. Basic container health checks/restart policies in compose.
---
## V6.1 — Reporting Features
Independent of hosting — can be built any time, including in parallel with
V6.0:
- **Person timelines**: a query/aggregation feature (documents by person,
ordered by document date), no hosting dependency.
- **AI-written biographies/family histories**: likely reuses the existing
prompt/provider abstraction (`services/prompts.py`) already built for
transcription, rather than needing new infrastructure.
---
## Beyond / Pie-in-the-sky (informational only — no version assigned)
Not being built now, but the plan above is checked against these so nothing
forecloses them later:
- **Individual user logins + roles** (admin/editor/contributor/view-only):
Cloudflare Access (V6.0 Stage 3) is a stopgap, not this. When you get here,
add a real `User`/`Role` model and auth middleware. Because the codebase
already funnels data access through the service layer, adding a
"current user + role check" later is additive — this is the reason to keep
service-layer discipline intact through all the versions above, so
authorization can be bolted on without touching every page.
- **Per-user databases**: protected for by the Stage 2 connection-factory
recommendation above (schema-per-tenant or database-per-tenant becomes
much easier if the DB connection is already resolved through an
indirection point rather than hardcoded at startup).
---
## Current status
- V5.0 unified photos has been implemented with:
- shared `photo` table (`person_id` nullable for homepage ownership),
- flat media storage under `UPLOAD_DIR/photos/{photo_id}{suffix}`,
- migration backfill from legacy Person portraits and homepage images,
- homepage markdown relocated to `UPLOAD_DIR/homepage.md`.
- Version numbering/grouping is now established by implementation and can
proceed to V5.1 planning/execution.