# Architecture (V1 Baseline)

This document describes the current architecture of the personal historical-document transcription system and serves as the V1 technical baseline.

## Architecture Objectives

- preserve source material as transcribed text
- keep operational complexity low for personal-scale deployment
- support asynchronous processing without external queue infrastructure
- maintain clear module boundaries for incremental extension

## Runtime Topology

V1 runtime is a modular monolith:

- one FastAPI + NiceGUI application process
- one in-process async worker loop
- relational persistence via SQLModel (SQLite baseline)

```mermaid
flowchart LR
    U[Browser User] --> A[FastAPI + NiceGUI App]
    A --> W[In-process Worker]
    A --> DB[(SQLite via SQLModel)]
    W --> P[OpenRouter Provider]
    W --> DB
```

## Lifecycle Ownership

Application lifespan owns runtime setup/teardown:

- configure logging
- initialize and dispose DB runtime resources
- optional schema bootstrap by environment policy
- recover stale processing jobs
- start/stop worker consumer lifespan

## Layered Module Structure

### Interface Layer

- `src/transcription/ui/**` (NiceGUI pages/components)
- `src/transcription/api/**` (FastAPI routes and error handlers)

### Application/Workflow Layer

- `src/transcription/services/workflows.py`
- `src/transcription/worker.py`

Responsibilities:

- orchestration and status transitions
- retry/timeout behavior
- provider call coordination

### Service Layer

- `src/transcription/services/*.py`

Responsibilities:

- CRUD and transactional boundaries
- domain-aligned persistence operations

### Infrastructure Layer

- `src/transcription/db/**` (runtime/session/bootstrap)
- `src/transcription/providers/**` (OpenRouter adapter)

## Processing Workflow

1. User uploads a source file from the UI.
2. App persists `Document`, `Job(queued)`, and `Source`.
3. Worker claims next queued job and marks `processing`.
4. Worker calls provider with prompt + source bytes.
5. On success, app writes immutable `Job.text` and marks `transcribed`.
6. On failure, app writes `Job.error_detail` and marks `failed`.
7. UI exposes job detail, original transcription, and optional revision.

## Domain Ownership Invariants

- `Job.text` is immutable original provider output.
- `Revision` is optional, user-authored, and linked to `Source`.
- `Revision` does not overwrite original job transcription.
- Status lifecycle is fixed to: `queued -> processing -> transcribed|failed`.

## Data Model Summary

- `Document` has many `Source` and many `Job`.
- `Source` belongs to one `Document` and one `Job`.
- `Source` has optional `Revision` (`0..1`) enforced by unique `revision.source_id`.

## Simplicity Guardrails (V1)

- no external queue/broker required
- no search engine required
- no distributed worker fleet required
- keep provider integration behind adapter boundary

## Extension Path

### V1 (current)

- SQLite baseline
- OpenRouter provider
- in-process worker
- optional single revision workflow

### V2 (planned)

- PostgreSQL as relational baseline
- optional MongoDB adjunct store for scoped use cases
- migration-first schema evolution

See [ver2/ver2.md](ver2/ver2.md) for roadmap details.

## Test Strategy

- unit tests for model/service behaviors
- integration tests for upload/workflow reliability
- UI integration tests for page/render contracts
- external provider tests opt-in via marker/config

## Related References

- [index.md](index.md)
- [requirements.md](requirements.md)
- [schema.md](schema.md)
- [error_handling.md](error_handling.md)
