# DM002 — Reconcilix Persistence Model

**Version:** 0.1  
**Status:** Draft  
**Scope:** Relational persistence of DM001 in MySQL  
**Principle:** KISS — nachvollziehbarer Zustand statt Event Sourcing.

## 1. Purpose

DM002 beschreibt die relationale Persistenzsicht auf DM001. Ziel ist, jeden Reconciliation-Vorgang fachlich nachvollziehbar zu speichern, ohne das System frühzeitig mit Event Sourcing, Graph Database oder komplexer Historisierung zu überladen.

MySQL wird von Beginn an als persistentes Backend verwendet.

## 2. Design Principles

1. DM001 bleibt das fachliche Referenzmodell.
2. DM002 bildet den aktuellen fachlichen Zustand relational ab.
3. Domain Objects kennen die Persistenz nicht selbst.
4. Fremdschlüssel sichern die Nachvollziehbarkeit der Ableitungskette.
5. Klassifikationen werden zunächst als URI-Referenzen gespeichert.
6. Die erste Implementierung unterstützt nur den aktuellen Scope `CONCEPT` und xTree/MCT.

## 3. Tables

### 3.1 `source_value`

| Column | Type | Notes |
|---|---|---|
| `id` | BIGINT PK | interne ID |
| `value` | TEXT | unveränderter Literalwert |
| `source_field` | VARCHAR(255) NULL | Quellfeld |
| `source_record_id` | VARCHAR(255) NULL | Quelldatensatz |
| `datatype` | VARCHAR(100) NULL | Datentyp |
| `language` | VARCHAR(35) NULL | BCP 47 |
| `preferred_entity_type_uri` | VARCHAR(1024) | URI der Klassifikation |
| `provenance_json` | JSON NULL | kompakte Source Provenance |
| `created_at` | DATETIME | Zeitpunkt |

### 3.2 `context_item`

| Column | Type | Notes |
|---|---|---|
| `id` | BIGINT PK | interne ID |
| `source_value_id` | BIGINT FK | Bezug zum SourceValue |
| `context_type_uri` | VARCHAR(1024) | Typ des Kontextes |
| `value` | TEXT | Kontextwert |
| `source_uri` | VARCHAR(1024) NULL | abweichende Quelle |

### 3.3 `interpretation_graph`

| Column | Type | Notes |
|---|---|---|
| `id` | BIGINT PK | interne ID |
| `source_value_id` | BIGINT FK | Bezug zum SourceValue |
| `span_start` | INT | inklusiver Startoffset |
| `span_end` | INT | exklusiver Endoffset |
| `source_fragment` | TEXT | unveränderter Ausschnitt |
| `status_uri` | VARCHAR(1024) | Bearbeitungsstatus |
| `version` | INT DEFAULT 1 | Graph-Version |
| `created_at` | DATETIME | Zeitpunkt |

### 3.4 `interpretation_node`

| Column | Type | Notes |
|---|---|---|
| `id` | BIGINT PK | interne ID |
| `interpretation_graph_id` | BIGINT FK | Graph |
| `parent_node_id` | BIGINT FK NULL | zunächst höchstens ein Parent |
| `value` | TEXT | interpretierter Wert |
| `level` | INT | Ableitungstiefe |
| `status_uri` | VARCHAR(1024) | Status |
| `created_by` | VARCHAR(255) NULL | Agent/System |
| `technique_uri` | VARCHAR(1024) NULL | verwendete Technique |
| `note` | TEXT NULL | Erläuterung |
| `created_at` | DATETIME | Zeitpunkt |

### 3.5 `interpretation_node_property`

Join Table für `0..* InterpretationProperty`.

| Column | Type | Notes |
|---|---|---|
| `interpretation_node_id` | BIGINT FK | Node |
| `property_uri` | VARCHAR(1024) | URI der Klassifikation |
| `confidence` | DECIMAL(6,5) NULL | optional |
| `note` | TEXT NULL | optional |

Primary Key:

```text
(interpretation_node_id, property_uri)
```

### 3.6 `reconciliation_result`

| Column | Type | Notes |
|---|---|---|
| `id` | BIGINT PK | interne ID |
| `interpretation_node_id` | BIGINT FK | bearbeitete Node |
| `success` | BOOLEAN | Ergebnis |
| `matching_strategy_uri` | VARCHAR(1024) NULL | Strategy |
| `vocabulary_matching_pattern_uri` | VARCHAR(1024) NULL | 0..1 Pattern |
| `confidence` | DECIMAL(6,5) NULL | optional |
| `target_vocabulary_uri` | VARCHAR(1024) NULL | xTree/MCT etc. |
| `note` | TEXT NULL | Erläuterung |
| `created_at` | DATETIME | Zeitpunkt |

### 3.7 `candidate_item`

| Column | Type | Notes |
|---|---|---|
| `id` | BIGINT PK | interne technische ID |
| `reconciliation_result_id` | BIGINT FK | Ergebnis |
| `uri` | VARCHAR(2048) | fachliche Identifikation |
| `display_label` | TEXT | Anzeigeform |
| `entity_type_uri` | VARCHAR(1024) | tatsächlicher Entity Type |
| `source_system_uri` | VARCHAR(1024) NULL | Zielsystem |
| `score` | DECIMAL(10,8) NULL | Score |
| `rank` | INT NULL | Rang |
| `qualifier` | VARCHAR(1024) NULL | Homonymzusatz |
| `payload_json` | JSON NULL | optionale typspezifische Daten |

### 3.8 `match_decision`

| Column | Type | Notes |
|---|---|---|
| `id` | BIGINT PK | interne ID |
| `reconciliation_result_id` | BIGINT FK | Ergebnis |
| `selected_candidate_item_id` | BIGINT FK NULL | optionaler Candidate |
| `decision_uri` | VARCHAR(1024) | kontrollierte Entscheidung |
| `confidence` | DECIMAL(6,5) NULL | optional |
| `decided_by` | VARCHAR(255) NULL | Person/Rolle/System |
| `comment` | TEXT NULL | Erläuterung |
| `decided_at` | DATETIME | Zeitpunkt |

## 4. Relational Overview

```mermaid
erDiagram
    SOURCE_VALUE ||--o{ CONTEXT_ITEM : has
    SOURCE_VALUE ||--|{ INTERPRETATION_GRAPH : segmented_into
    INTERPRETATION_GRAPH ||--|{ INTERPRETATION_NODE : contains
    INTERPRETATION_NODE o|--o{ INTERPRETATION_NODE : derives
    INTERPRETATION_NODE ||--o{ INTERPRETATION_NODE_PROPERTY : classified_by
    INTERPRETATION_NODE ||--o{ RECONCILIATION_RESULT : produces
    RECONCILIATION_RESULT ||--o{ CANDIDATE_ITEM : contains
    RECONCILIATION_RESULT ||--o{ MATCH_DECISION : receives
    CANDIDATE_ITEM o|--o{ MATCH_DECISION : selected_by
```

## 5. Deliberate Simplifications

Nicht Bestandteil von v0.1:

- Event Sourcing
- Graph Database
- vollständige Run-Historisierung
- Node-Merge und mehrere Parent Nodes
- separate Tabellen für Candidate-Typen
- persistierte LLM-Prompts oder Embeddings
- materialisierte Auswertungsmodelle

## 6. Repository Boundary

Die Domain Classes speichern sich nicht selbst. Vorgesehen ist mindestens eine Persistenzschnittstelle, beispielsweise:

```text
ReconciliationRepository
- saveSourceValue(...)
- saveInterpretationGraph(...)
- saveReconciliationResult(...)
- saveMatchDecision(...)
- loadBySourceValueId(...)
```

Die konkrete API wird im ADR- und Implementierungsschritt festgelegt.

## 7. First Implementation Scope

Die erste MySQL-Umsetzung umfasst:

- alle acht Tabellen,
- Foreign Keys und grundlegende Indizes,
- Speichern eines vollständigen einfachen Reconciliation-Verlaufs,
- Lesen eines Verlaufs für Debugging und Evaluation,
- zunächst genau einen `InterpretationGraph` pro `SourceValue`,
- zunächst lineare Node-Ableitung,
- `CONCEPT` als Entity Type,
- xTree/MCT als Target.
