# akentner/phone-logger architecture

> Architecture diagram of the GitHub repository akentner/phone-logger, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-11-12). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/akentner/phone-logger
- Repository: https://github.com/akentner/phone-logger

## Overview

Phone Logger is a Home Assistant phone-event logging and number-resolution service. Fritz!Box, REST, and optional MQTT inputs produce normalized call events; the pipeline enriches events with PBX line state, resolves numbers through an ordered adapter chain, then dispatches results to history and optional integrations. Its API and web interface also manage contacts, call history, cache, configuration, and PBX state. Evidence for several adapter and UI links comes from the README and SOURCE INDEX; unsampled implementation details are not inferred beyond those references.

Main entry points: [`src/core/pipeline.py`](https://github.com/akentner/phone-logger/blob/main/src/core/pipeline.py) (Event pipeline), [`src/api/routes`](https://github.com/akentner/phone-logger/tree/main/src/api/routes) (REST API routes), [`src/db/database.py`](https://github.com/akentner/phone-logger/blob/main/src/db/database.py) (SQLite database), [`src/main.py`](https://github.com/akentner/phone-logger/blob/main/src/main.py) (Application startup)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_ingest["Event ingestion"]
  node_fritz["Fritz monitor"]
  node_rest_input["REST input<br/>[rest.py]"]
  node_mqtt["MQTT adapter<br/>[mqtt.py]"]
end

subgraph group_processing["Call processing"]
  node_event["Call event model<br/>[event.py]"]
  node_pipeline["Event pipeline<br/>[pipeline.py]"]
  node_pbx["PBX state manager<br/>[pbx.py]"]
  node_number["Number normalization<br/>[phone_number.py]"]
end

subgraph group_storage["Resolution and storage"]
  node_resolver_chain["Resolver chain<br/>[chain.py]"]
  node_static_resolvers["Local resolvers"]
  node_web_resolvers["Web lookup resolvers"]
  node_database[("SQLite database<br/>[database.py]")]
end

subgraph group_service["API and integration"]
  node_call_log["Call history output<br/>[call_log.py]"]
  node_webhook["Webhook output<br/>[webhook.py]"]
  node_config["Configuration<br/>[config.py]"]
  node_api["REST API routes"]
  node_app["Application startup<br/>[main.py]"]
end

subgraph group_ui["Web interface"]
  node_frontend["Web interface<br/>[App.tsx]"]
  node_frontend_pages["Management pages"]
  node_frontend_api["API client"]
end

node_operator(("Phone Logger operator"))
node_fritzbox(("Fritz!Box"))
node_lookup_sites(("Lookup services"))
node_ha(("Home Assistant"))
node_mqtt_broker(("MQTT broker"))

node_fritzbox -->|"sends events"| node_fritz
node_fritz -->|"emits events"| node_pipeline
node_rest_input -->|"emits events"| node_pipeline
node_mqtt_broker -->|"sends triggers"| node_mqtt
node_mqtt -->|"emits events"| node_pipeline
node_pipeline -->|"processes"| node_event
node_pipeline -->|"enriches state"| node_pbx
node_pipeline -->|"normalizes numbers"| node_number
node_pipeline -->|"resolves through"| node_resolver_chain
node_resolver_chain -->|"tries local sources"| node_static_resolvers
node_resolver_chain -->|"tries web sources"| node_web_resolvers
node_web_resolvers -->|"looks up numbers"| node_lookup_sites
node_web_resolvers -->|"caches results"| node_database
node_static_resolvers -->|"reads contacts"| node_database
node_pipeline -->|"dispatches events"| node_call_log
node_pipeline -->|"dispatches results"| node_webhook
node_pipeline -->|"publishes results"| node_mqtt
node_call_log -->|"records calls"| node_database
node_webhook -->|"posts events"| node_ha
node_mqtt -->|"publishes events"| node_mqtt_broker
node_operator -->|"uses interface"| node_frontend
node_frontend -->|"routes views"| node_frontend_pages
node_frontend_pages -->|"requests data"| node_frontend_api
node_frontend_api -->|"calls endpoints"| node_api
node_operator -->|"manages service"| node_api
node_app -->|"registers routes"| node_api
node_app -->|"starts pipeline"| node_pipeline
node_app -->|"opens database"| node_database
node_app -->|"loads settings"| node_config
node_api -->|"manages records"| node_database
node_api -->|"triggers calls"| node_pipeline
node_api -->|"reports settings"| node_config

click node_fritz "https://github.com/akentner/phone-logger/blob/main/src/adapters/input/fritz_callmonitor.py"
click node_rest_input "https://github.com/akentner/phone-logger/blob/main/src/adapters/input/rest.py"
click node_mqtt "https://github.com/akentner/phone-logger/blob/main/src/adapters/mqtt.py"
click node_event "https://github.com/akentner/phone-logger/blob/main/src/core/event.py"
click node_pipeline "https://github.com/akentner/phone-logger/blob/main/src/core/pipeline.py"
click node_pbx "https://github.com/akentner/phone-logger/blob/main/src/core/pbx.py"
click node_number "https://github.com/akentner/phone-logger/blob/main/src/core/phone_number.py"
click node_resolver_chain "https://github.com/akentner/phone-logger/blob/main/src/adapters/resolver/chain.py"
click node_static_resolvers "https://github.com/akentner/phone-logger/tree/main/src/adapters/resolver"
click node_web_resolvers "https://github.com/akentner/phone-logger/tree/main/src/adapters/resolver"
click node_database "https://github.com/akentner/phone-logger/blob/main/src/db/database.py"
click node_call_log "https://github.com/akentner/phone-logger/blob/main/src/adapters/output/call_log.py"
click node_webhook "https://github.com/akentner/phone-logger/blob/main/src/adapters/output/webhook.py"
click node_config "https://github.com/akentner/phone-logger/blob/main/src/config.py"
click node_api "https://github.com/akentner/phone-logger/tree/main/src/api/routes"
click node_app "https://github.com/akentner/phone-logger/blob/main/src/main.py"
click node_frontend "https://github.com/akentner/phone-logger/blob/main/src/frontend/src/App.tsx"
click node_frontend_pages "https://github.com/akentner/phone-logger/tree/main/src/frontend/src/pages"
click node_frontend_api "https://github.com/akentner/phone-logger/tree/main/src/frontend/src/api"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_fritz,node_rest_input,node_mqtt toneBlue
class node_event,node_pipeline,node_pbx,node_number toneAmber
class node_resolver_chain,node_static_resolvers,node_web_resolvers,node_database toneMint
class node_call_log,node_webhook,node_config,node_api,node_app toneRose
class node_frontend,node_frontend_pages,node_frontend_api,node_operator,node_fritzbox,node_lookup_sites,node_ha,node_mqtt_broker toneIndigo
```

## Components

### Event ingestion

- [Fritz monitor](https://github.com/akentner/phone-logger/blob/main/src/adapters/input/fritz_callmonitor.py): `src/adapters/input/fritz_callmonitor.py`
- [REST input](https://github.com/akentner/phone-logger/blob/main/src/adapters/input/rest.py): `src/adapters/input/rest.py`
- [MQTT adapter](https://github.com/akentner/phone-logger/blob/main/src/adapters/mqtt.py): `src/adapters/mqtt.py`

### Call processing

- [Call event model](https://github.com/akentner/phone-logger/blob/main/src/core/event.py): `src/core/event.py`
- [Event pipeline](https://github.com/akentner/phone-logger/blob/main/src/core/pipeline.py): `src/core/pipeline.py`
- [PBX state manager](https://github.com/akentner/phone-logger/blob/main/src/core/pbx.py): `src/core/pbx.py`
- [Number normalization](https://github.com/akentner/phone-logger/blob/main/src/core/phone_number.py): `src/core/phone_number.py`

### Resolution and storage

- [Resolver chain](https://github.com/akentner/phone-logger/blob/main/src/adapters/resolver/chain.py): `src/adapters/resolver/chain.py`
- [Local resolvers](https://github.com/akentner/phone-logger/tree/main/src/adapters/resolver): `src/adapters/resolver`
- [Web lookup resolvers](https://github.com/akentner/phone-logger/tree/main/src/adapters/resolver): `src/adapters/resolver`
- [SQLite database](https://github.com/akentner/phone-logger/blob/main/src/db/database.py): `src/db/database.py`

### API and integration

- [Call history output](https://github.com/akentner/phone-logger/blob/main/src/adapters/output/call_log.py): `src/adapters/output/call_log.py`
- [Webhook output](https://github.com/akentner/phone-logger/blob/main/src/adapters/output/webhook.py): `src/adapters/output/webhook.py`
- [Configuration](https://github.com/akentner/phone-logger/blob/main/src/config.py): `src/config.py`
- [REST API routes](https://github.com/akentner/phone-logger/tree/main/src/api/routes): `src/api/routes`
- [Application startup](https://github.com/akentner/phone-logger/blob/main/src/main.py): `src/main.py`

### Web interface

- [Web interface](https://github.com/akentner/phone-logger/blob/main/src/frontend/src/App.tsx): `src/frontend/src/App.tsx`
- [Management pages](https://github.com/akentner/phone-logger/tree/main/src/frontend/src/pages): `src/frontend/src/pages`
- [API client](https://github.com/akentner/phone-logger/tree/main/src/frontend/src/api): `src/frontend/src/api`

### Other components

- **Phone Logger operator**
- **Fritz!Box**
- **Lookup services**
- **Home Assistant**
- **MQTT broker**

## Connections

- Fritz!Box → Fritz monitor: sends events
- Fritz monitor → Event pipeline: emits events (evidence: `src/core/pipeline.py`)
- REST input → Event pipeline: emits events (evidence: `src/core/pipeline.py`)
- MQTT broker → MQTT adapter: sends triggers
- MQTT adapter → Event pipeline: emits events (evidence: `src/adapters/mqtt.py`)
- Event pipeline → Call event model: processes (evidence: `src/core/pipeline.py`)
- Event pipeline → PBX state manager: enriches state (evidence: `src/core/pipeline.py`)
- Event pipeline → Number normalization: normalizes numbers (evidence: `src/core/pipeline.py`)
- Event pipeline → Resolver chain: resolves through (evidence: `src/core/pipeline.py`)
- Resolver chain → Local resolvers: tries local sources (evidence: `src/adapters/resolver/chain.py`)
- Resolver chain → Web lookup resolvers: tries web sources (evidence: `src/adapters/resolver/chain.py`)
- Web lookup resolvers → Lookup services: looks up numbers
- Web lookup resolvers → SQLite database: caches results (evidence: `src/adapters/resolver/tellows.py`)
- Local resolvers → SQLite database: reads contacts (evidence: `src/adapters/resolver/tellows.py`)
- Event pipeline → Call history output: dispatches events (evidence: `src/core/pipeline.py`)
- Event pipeline → Webhook output: dispatches results (evidence: `src/core/pipeline.py`)
- Event pipeline → MQTT adapter: publishes results (evidence: `src/core/pipeline.py`)
- Call history output → SQLite database: records calls (evidence: `src/adapters/output/call_log.py`)
- Webhook output → Home Assistant: posts events (evidence: `src/adapters/output/webhook.py`)
- MQTT adapter → MQTT broker: publishes events
- Phone Logger operator → Web interface: uses interface
- Web interface → Management pages: routes views (evidence: `src/frontend/src/App.tsx`)
- Management pages → API client: requests data (evidence: `src/frontend/src/pages/CallsPage.tsx`)
- API client → REST API routes: calls endpoints
- Phone Logger operator → REST API routes: manages service
- Application startup → REST API routes: registers routes (evidence: `src/main.py`)
- Application startup → Event pipeline: starts pipeline (evidence: `src/main.py`)
- Application startup → SQLite database: opens database (evidence: `src/main.py`)
- Application startup → Configuration: loads settings (evidence: `src/main.py`)
- REST API routes → SQLite database: manages records
- REST API routes → Event pipeline: triggers calls
- REST API routes → Configuration: reports settings
