# Person Schema-to-UI Mapping

Purpose: Map the Person schema to the UI, while clearly separating intended target behavior from current implementation.

Companion document: user-journey.md
Acceptance criteria: acceptance-criteria.md

## 1. Entity Snapshot

- Table: Person
- Primary key: id (UUID)
- Related entities: DocumentPerson, Document
- Canonical schema references:
  - src/transcription/db/models.py
  - docs/schema_v2.md

## 2. Mapping Rules

This document uses three lenses:
1. Intended behavior: what the UX should support.
2. Current behavior: what the code supports today.
3. Gap to target: what must change to align implementation with the intended UX.

## 3. Field Inventory

| Field | DB Type | Nullable | Default/Auto Value | Intended UI Treatment | Notes |
|---|---|---|---|---|---|
| id | UUID | No | uuid4() | Hidden, system-managed | Primary key |
| full_name | str | No | None | Shown, editable on create and update | Required canonical name |
| display_name | str | Yes | None | Shown, editable | Optional |
| maiden_name | str | Yes | None | Shown, editable | Optional |
| birth_date | date | Yes | None | Shown, editable | Canonical exact date when present |
| birth_date_raw | str | Yes | None | Shown, editable | Approximate or unknown date text |
| birth_place | str | Yes | None | Shown, editable | Optional |
| death_date | date | Yes | None | Shown, editable | Canonical exact date when present |
| death_date_raw | str | Yes | None | Shown, editable | Approximate or unknown date text |
| death_place | str | Yes | None | Shown, editable | Optional |
| biography | str | Yes | None | Shown, editable | Optional narrative |
| portrait_path | str | Yes | None | Shown, editable | Optional path |
| metadata_ | JSONB/JSON | Yes | None | Hidden in first release | Advanced metadata |
| created_at | datetime | No | datetime.now(UTC) | Hidden or read-only | System-managed |
| updated_at | datetime | No | datetime.now(UTC) | Hidden or read-only | System-managed |

## 4. CREATE Mapping

### 4.1 Intended Create Flow

Entry point: Person page  
User action: Create new person  
Success destination: new Person detail page

| Field | Intended User Input | Required | Visible | Notes |
|---|---|---|---|---|
| full_name | Text input | Yes | Yes | Canonical identity field |
| display_name | Text input | No | Yes | Optional |
| maiden_name | Text input | No | Yes | Optional |
| birth_date | Date input | No | Yes | Structured exact date |
| birth_date_raw | Text input | No | Yes | Approximate/uncertain date |
| birth_place | Text input | No | Yes | Optional |
| death_date | Date input | No | Yes | Structured exact date |
| death_date_raw | Text input | No | Yes | Approximate/uncertain date |
| death_place | Text input | No | Yes | Optional |
| biography | Text area | No | Yes | Optional |
| portrait_path | Text input | No | Yes | Optional |
| metadata_ | None | No | No | Hidden in first release |
| created_at | None | No | No | System-generated |
| updated_at | None | No | No | Not user-entered |

Related records during intended create:
- No DocumentPerson link is required during Person creation.
- Document linking can be done later from Document or Person workflows.

### 4.2 Current Implementation

Current entry point: dedicated People page and Person create/edit flows  
Current user action: open Person create page, fill form fields, optionally upload portrait  
Current backend path: People page submit callbacks -> DocumentService.create_person() / update_person()

| Field | Current Value at Create | Source | Visible to User | Evidence |
|---|---|---|---|---|
| id | Generated UUID | System | No | Person model default factory in src/transcription/db/models.py |
| full_name | Form input | User input | Yes | src/transcription/ui/pages/people_page.py |
| display_name | Form input or None | User input | Yes | src/transcription/ui/pages/people_page.py |
| maiden_name | Form input or None | User input | Yes | src/transcription/ui/pages/people_page.py |
| birth_date | Form input or None | User input | Yes | src/transcription/ui/pages/people_page.py |
| birth_date_raw | Form input or None | User input | Yes | src/transcription/ui/pages/people_page.py |
| birth_place | Form input or None | User input | Yes | src/transcription/ui/pages/people_page.py |
| death_date | Form input or None | User input | Yes | src/transcription/ui/pages/people_page.py |
| death_date_raw | Form input or None | User input | Yes | src/transcription/ui/pages/people_page.py |
| death_place | Form input or None | User input | Yes | src/transcription/ui/pages/people_page.py |
| biography | Form input or None | User input | Yes | src/transcription/ui/pages/people_page.py |
| portrait_path | Relative upload path or manual path | Upload helper + user input | Yes | src/transcription/ui/pages/people_page.py, src/transcription/services/store.py |
| metadata_ | Caller-provided or None | Service/API caller | No | Person model in src/transcription/db/models.py |
| created_at | Current UTC timestamp | System | No | Person model default in src/transcription/db/models.py |
| updated_at | Current UTC timestamp | System | No | Person model default in src/transcription/db/models.py |

### 4.3 Gap to Target

To satisfy the intended Create flow, implementation now includes:
1. a Person page and dedicated create form
2. user-entered controls for Person fields
3. create validation and success/failure UX states
4. post-submit routing to a Person detail page

## 5. READ Mapping

### 5.1 Intended Read Behavior

On the Person detail page, the user should be able to see:
1. Person identity and biographical metadata
2. linked Documents (through DocumentPerson)
3. empty-state behavior when no linked documents exist

### 5.2 Current Implementation

Current Person visibility is implemented in dedicated list/detail/edit/delete pages.

| Field | Current Rendering | Visible to User | Notes | Evidence |
|---|---|---|---|---|
| full_name | Rendered in header and summary | Yes | Dedicated Person page exists | `src/transcription/ui/pages/people_page.py` |
| display_name | Rendered | Yes | Visible in detail and list contexts | src/transcription/ui/pages/people_page.py |
| maiden_name | Rendered | Yes | Visible in detail context | src/transcription/ui/pages/people_page.py |
| birth_date | Rendered | Yes | Visible in detail context | src/transcription/ui/pages/people_page.py |
| birth_date_raw | Rendered | Yes | Visible in detail context | src/transcription/ui/pages/people_page.py |
| birth_place | Rendered | Yes | Visible in detail context | src/transcription/ui/pages/people_page.py |
| death_date | Rendered | Yes | Visible in detail context | src/transcription/ui/pages/people_page.py |
| death_date_raw | Rendered | Yes | Visible in detail context | src/transcription/ui/pages/people_page.py |
| death_place | Rendered | Yes | Visible in detail context | src/transcription/ui/pages/people_page.py |
| biography | Rendered | Yes | Visible in detail context | src/transcription/ui/pages/people_page.py |
| portrait_path | Rendered as text and image when available | Yes | Dedicated Person page exists | `src/transcription/ui/pages/people_page.py` |
| metadata_ | Not rendered | No | Hidden advanced field | no current UI field |
| created_at | Rendered read-only | Yes | Visible in detail context | src/transcription/ui/pages/people_page.py |
| updated_at | Rendered read-only | Yes | Visible in detail context | src/transcription/ui/pages/people_page.py |

### 5.3 Gap to Target

To satisfy the intended Read flow, implementation now includes:
1. metadata rendering for Person fields
2. linked Documents section with empty states
3. document-link navigation paths

## 6. UPDATE Mapping

### 6.1 Intended Update Behavior

The user should be able to edit Person metadata from the Person detail page or a dedicated edit flow.

Intended editable fields:
- full_name
- display_name
- maiden_name
- birth_date
- birth_date_raw
- birth_place
- death_date
- death_date_raw
- death_place
- biography
- portrait_path

Intended system-managed fields:
- id
- created_at
- updated_at

Hidden in first release:
- metadata_

### 6.2 Current Implementation

| Field | Updatable via UI | Updatable via Service | Notes |
|---|---|---|---|
| id | No | Practically no | Primary key should be treated as immutable |
| full_name | Yes | Yes | Editable from Person edit page via DocumentService.update_person() |
| display_name | Yes | Yes | Editable from Person edit page via DocumentService.update_person() |
| maiden_name | Yes | Yes | Editable from Person edit page via DocumentService.update_person() |
| birth_date | Yes | Yes | Editable from Person edit page via DocumentService.update_person() |
| birth_date_raw | Yes | Yes | Editable from Person edit page via DocumentService.update_person() |
| birth_place | Yes | Yes | Editable from Person edit page via DocumentService.update_person() |
| death_date | Yes | Yes | Editable from Person edit page via DocumentService.update_person() |
| death_date_raw | Yes | Yes | Editable from Person edit page via DocumentService.update_person() |
| death_place | Yes | Yes | Editable from Person edit page via DocumentService.update_person() |
| biography | Yes | Yes | Editable from Person edit page via DocumentService.update_person() |
| portrait_path | Yes | Yes | Editable manually and via portrait upload helper |
| metadata_ | No | Yes | Technically updatable, hidden in first release |
| created_at | No | Technically yes | Should remain system-managed |
| updated_at | No | Technically yes | Should remain system-managed |

### 6.3 Gap to Target

Implementation now includes:
1. Person edit controls in the UI
2. validation and save behavior for Person metadata
3. a consistent updated_at update policy for Person edits

## 7. DELETE Mapping

### 7.1 Intended Delete Behavior

The UI should provide a delete action for Person with guardrails.

Rules:
1. Deletion can proceed when relationship policy allows no retained document links.
2. If linked DocumentPerson records exist and policy requires cleanup first, deletion is blocked.
3. Delete confirmation must make clear that deletion is permanent.

### 7.2 Current Implementation

| Action | UI Exposed | Backend Capability | Notes |
|---|---|---|---|
| Delete Person | Yes | Yes | Dedicated delete page enforces linked-document guardrails before service delete |

### 7.3 Gap to Target

Implementation includes:
1. a Person delete control in the UI
2. relationship-aware pre-delete checks
3. user-facing blocked-delete messaging
4. confirmation UX for successful delete attempts

## 8. Hidden and System-Managed Fields

| Field | Category | Why Hidden or Protected |
|---|---|---|
| id | System-managed | Internal identifier |
| created_at | System-managed | Audit timestamp |
| updated_at | System-managed | Audit timestamp |
| metadata_ | Hidden in first release | Advanced JSON metadata not needed in initial UI |

## 9. Structured Name Deferred Note

Structured name fields are deferred to a future schema revision.

Current policy:
1. full_name remains canonical and required.

Future revision intent:
1. introduce first_name, middle_name, last_name, and optional suffix fields.
2. maintain compatibility with existing full_name records during migration.
3. define normalization and reconciliation rules when structured and canonical forms differ.

## 10. Traceability Anchors

Schema and models:
- docs/schema_v2.md
- src/transcription/db/models.py

Current implementation:
- src/transcription/services/documents.py
- src/transcription/ui/pages/people_page.py
- src/transcription/services/store.py

Companion UX spec:
- docs/ui/entities/person/user-journey.md

Acceptance checklist:
- docs/ui/entities/person/acceptance-criteria.md

## 11. Acceptance Checklist Summary

- Every Person schema field appears in the field inventory.
- Intended Create behavior matches the companion user journey.
- Current Create behavior reflects dedicated UI form implementation with optional portrait upload handling.
- Gaps between intended and current behavior are explicit.
- Read, Update, and Delete sections distinguish target behavior from current code.