# tanmaysheoran/fastapi-audit architecture

> Architecture diagram of the GitHub repository tanmaysheoran/fastapi-audit, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-20). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/tanmaysheoran/fastapi-audit
- Repository: https://github.com/tanmaysheoran/fastapi-audit

## Overview

1. **Repository purpose**
   - This is a Python package, `fastapi-audit`, that adds audit logging to FastAPI/Starlette applications.
   - Its architecture is centered on capturing activity at two boundaries: the HTTP request lifecycle and SQLAlchemy ORM/session changes.

2. **Public integration surface**
   - The main entry points are `AuditMiddleware`, `AuditConfig`, `create_tables`, and `audit_log`.
   - Applications typically install the middleware into FastAPI and point it at a separate audit database via `control_db_url`.

3. **HTTP request/response subsystem**
   - `middleware.py` is the primary runtime interceptor.
   - It captures request metadata such as method, path, query params, IP, user agent, and timing, then records response status and latency after the downstream app returns.
   - It also supports optional request/response body capture and path-based exclusions.

4. **Actor and identity extraction**
   - `jwt_parser.py` handles extraction of actor identity from the `Authorization` header JWT.
   - The package expects claims like `sub`, `actor_type`, and `email`, and supports alias mapping for organization-specific actor types.
   - This is the main identity boundary between application authentication and audit logging.

5. **Tenant context boundary**
   - The middleware can read tenant metadata from `request.state.tenant`.
   - Tenant information is not owned by the package; the app provides it, and the audit layer simply propagates `tenant_id` and `tenant_slug` into audit records.

6. **ORM diff tracking subsystem**
   - `orm_listener.py` integrates with SQLAlchemy async sessions to detect INSERT, UPDATE, and DELETE activity.
   - The repository uses session/event-level listeners plus context isolation so diffs remain associated with the right request or task.
   - This is the non-HTTP path into the audit system and complements middleware-based request logging.

7. **Sanitization and redaction**
   - `sanitizer.py` applies sensitive-field redaction before persistence.
   - Default redaction covers fields like passwords, tokens, and secrets, and config allows custom redaction fields.
   - This layer sits between data capture and storage, ensuring audit logs do not retain raw secrets.

8. **Persistence model and writer**
   - `models.py` defines the audit record shape stored in the audit database.
   - `writer.py` is responsible for writing records asynchronously, matching the package’s “fire-and-forget” design so audit I/O does not block the request path.
   - The storage target is a single `audit_logs` table, with PostgreSQL/asyncpg as the supported backend.

9. **Schema provisioning**
   - `create_tables()` provisions the audit schema, including the `audit_logs` table and its related enum/type.
   - This is a deployment/setup boundary rather than a runtime feature; it ensures the audit database is prepared before logging begins.

10. **Configuration layer**
   - `config.py` defines the package’s operational settings, likely using Pydantic-style config and `AUDIT_` environment variables.
   - Key knobs include the audit DB URL, body capture flags, ORM diff capture, anonymous logging behavior, excluded paths, and actor alias mappings.

11. **Data flow summary**
   - A request enters FastAPI → middleware extracts actor/request context → optional ORM listeners collect diffs during the request → data is sanitized/redacted → writer persists an audit row to the separate audit database.
   - Manual calls to `audit_log()` bypass the HTTP path but reuse the same persistence and sanitization pipeline.

12. **Package and test structure**
   - The codebase is organized as a small, modular library with focused modules rather than a large application.
   - Tests mirror the architecture: config, JWT parsing, middleware, ORM listening, sanitization, helpers, table creation, and export/import behavior.
   - That suggests the core design goal is stable integration points rather than a standalone service.

Main entry points: [`fastapi_audit/middleware.py`](https://github.com/tanmaysheoran/fastapi-audit/blob/main/fastapi_audit/middleware.py) (Middleware), [`fastapi_audit/writer.py`](https://github.com/tanmaysheoran/fastapi-audit/blob/main/fastapi_audit/writer.py) (Writer), [`fastapi_audit/__init__.py`](https://github.com/tanmaysheoran/fastapi-audit/blob/main/fastapi_audit/__init__.py) (API Surface), [`fastapi_audit/config.py`](https://github.com/tanmaysheoran/fastapi-audit/blob/main/fastapi_audit/config.py) (Config)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_public["Public API"]
  node_package_api["API Surface<br/>package exports<br/>[__init__.py]"]
  node_create_tables_api["Create Tables<br/>setup API"]
  node_audit_log_api["Audit Log<br/>manual API"]
end

subgraph group_http["HTTP Audit"]
  node_audit_middleware["Middleware<br/>[middleware.py]"]
  node_jwt_parser["JWT Parser<br/>identity parser<br/>[jwt_parser.py]"]
  node_tenant_state(("Tenant State<br/>request context"))
  node_request_context["Request Context<br/>captured context"]
end

subgraph group_orm["ORM Audit"]
  node_orm_listener["ORM Listener<br/>session listener<br/>[orm_listener.py]"]
end

subgraph group_storage["Storage"]
  node_sanitizer["Sanitizer<br/>redaction layer<br/>[sanitizer.py]"]
  node_models[("Audit Model<br/>audit schema<br/>[models.py]")]
  node_writer["Writer<br/>[writer.py]"]
  node_audit_table[("audit_logs<br/>table")]
  node_audit_enum{{"Audit Type<br/>db enum"}}
end

subgraph group_shared["Shared"]
  node_config["Config<br/>runtime settings<br/>[config.py]"]
  node_helpers["Helpers<br/>[helpers.py]"]
end

node_package_api -->|"exports"| node_audit_middleware
node_package_api -->|"exports"| node_config
node_package_api -->|"exports"| node_create_tables_api
node_package_api -->|"exports"| node_audit_log_api
node_audit_middleware -->|"captures"| node_request_context
node_audit_middleware -->|"parses actor"| node_jwt_parser
node_audit_middleware -->|"reads tenant"| node_tenant_state
node_audit_middleware -->|"redacts"| node_sanitizer
node_audit_middleware -->|"writes"| node_writer
node_orm_listener -->|"redacts"| node_sanitizer
node_orm_listener -->|"writes"| node_writer
node_audit_log_api -->|"redacts"| node_sanitizer
node_audit_log_api -->|"writes"| node_writer
node_writer -->|"uses"| node_models
node_writer -->|"persists"| node_audit_table
node_create_tables_api -->|"creates"| node_audit_table
node_create_tables_api -->|"creates"| node_audit_enum
node_config -->|"configures"| node_audit_middleware
node_config -->|"configures"| node_orm_listener
node_config -->|"configures"| node_sanitizer
node_helpers -->|"supports"| node_jwt_parser
node_helpers -->|"supports"| node_writer

click node_package_api "https://github.com/tanmaysheoran/fastapi-audit/blob/main/fastapi_audit/__init__.py"
click node_audit_middleware "https://github.com/tanmaysheoran/fastapi-audit/blob/main/fastapi_audit/middleware.py"
click node_jwt_parser "https://github.com/tanmaysheoran/fastapi-audit/blob/main/fastapi_audit/jwt_parser.py"
click node_orm_listener "https://github.com/tanmaysheoran/fastapi-audit/blob/main/fastapi_audit/orm_listener.py"
click node_config "https://github.com/tanmaysheoran/fastapi-audit/blob/main/fastapi_audit/config.py"
click node_helpers "https://github.com/tanmaysheoran/fastapi-audit/blob/main/fastapi_audit/helpers.py"
click node_sanitizer "https://github.com/tanmaysheoran/fastapi-audit/blob/main/fastapi_audit/sanitizer.py"
click node_models "https://github.com/tanmaysheoran/fastapi-audit/blob/main/fastapi_audit/models.py"
click node_writer "https://github.com/tanmaysheoran/fastapi-audit/blob/main/fastapi_audit/writer.py"

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_package_api,node_create_tables_api,node_audit_log_api toneBlue
class node_audit_middleware,node_jwt_parser,node_tenant_state,node_request_context toneAmber
class node_orm_listener toneMint
class node_sanitizer,node_models,node_writer,node_audit_table,node_audit_enum toneRose
class node_config,node_helpers toneIndigo
```

## Components

### Public API

Entry points used by applications and deployment setup

- [API Surface](https://github.com/tanmaysheoran/fastapi-audit/blob/main/fastapi_audit/__init__.py): package exports · Public imports and helper entry points for application integration · `fastapi_audit/__init__.py`
- **Create Tables**: setup API · Provisions audit schema and supporting database types
- **Audit Log**: manual API · Manual logging entry point that bypasses the HTTP boundary

### HTTP Audit

Request/response interception and actor extraction

- [Middleware](https://github.com/tanmaysheoran/fastapi-audit/blob/main/fastapi_audit/middleware.py): ASGI middleware · Captures request context, response status, latency, and optional bodies · `fastapi_audit/middleware.py`
- [JWT Parser](https://github.com/tanmaysheoran/fastapi-audit/blob/main/fastapi_audit/jwt_parser.py): identity parser · Extracts actor identity from Authorization JWT claims and aliases · `fastapi_audit/jwt_parser.py`
- **Tenant State**: request context · Tenant metadata provided by the host app via request.state
- **Request Context**: captured context · Method, path, query, IP, user agent, timing, and bodies

### ORM Audit

Session-level change capture for SQLAlchemy

- [ORM Listener](https://github.com/tanmaysheoran/fastapi-audit/blob/main/fastapi_audit/orm_listener.py): session listener · Detects INSERT, UPDATE, and DELETE activity from SQLAlchemy sessions · `fastapi_audit/orm_listener.py`

### Storage

Audit record shape, sanitization, and async persistence

- [Sanitizer](https://github.com/tanmaysheoran/fastapi-audit/blob/main/fastapi_audit/sanitizer.py): redaction layer · Redacts secrets and sensitive fields before persistence · `fastapi_audit/sanitizer.py`
- [Audit Model](https://github.com/tanmaysheoran/fastapi-audit/blob/main/fastapi_audit/models.py): audit schema · Defines the audit log record stored in the audit database · `fastapi_audit/models.py`
- [Writer](https://github.com/tanmaysheoran/fastapi-audit/blob/main/fastapi_audit/writer.py): async writer · Persists audit records without blocking the request path · `fastapi_audit/writer.py`
- **audit_logs**: table · Single audit storage table in the separate control database
- **Audit Type**: db enum · Related database enum/type used by the audit schema

### Shared

Configuration and helper utilities

- [Config](https://github.com/tanmaysheoran/fastapi-audit/blob/main/fastapi_audit/config.py): runtime settings · Operational flags, audit database URL, exclusions, and redaction options · `fastapi_audit/config.py`
- [Helpers](https://github.com/tanmaysheoran/fastapi-audit/blob/main/fastapi_audit/helpers.py): utility helpers · Small shared helpers used across the package · `fastapi_audit/helpers.py`

## Connections

- API Surface → Middleware: exports · Application installs the middleware from the package surface
- API Surface → Config: exports · Configuration is part of the public integration surface
- API Surface → Create Tables: exports · Deployment/setup entry point
- API Surface → Audit Log: exports · Manual logging entry point
- Middleware → Request Context: captures · Builds request/response audit context
- Middleware → JWT Parser: parses actor · Extracts actor identity from Authorization JWT
- Middleware → Tenant State: reads tenant · Propagates tenant metadata supplied by the host app
- Middleware → Sanitizer: redacts · Sanitizes captured request data before persistence
- Middleware → Writer: writes · Submits audit row asynchronously after the response
- ORM Listener → Sanitizer: redacts · Sanitizes ORM diffs before they are persisted
- ORM Listener → Writer: writes · Emits ORM change events into the same persistence path
- Audit Log → Sanitizer: redacts · Manual logging reuses the same redaction pipeline
- Audit Log → Writer: writes · Manual logging persists through the async writer
- Writer → Audit Model: uses · Serializes data into the audit record shape
- Writer → audit_logs: persists · Targets the audit_logs table in the audit database
- Create Tables → audit_logs: creates · Provisioning step creates the audit_logs table
- Create Tables → Audit Type: creates · Provisioning step creates related enum/type definitions
- Config → Middleware: configures · Controls body capture, exclusions, and anonymous logging
- Config → ORM Listener: configures · Controls ORM diff capture behavior
- Config → Sanitizer: configures · Provides custom redaction fields
- Helpers → JWT Parser: supports · Shared utility functions used by parsing and integration code
- Helpers → Writer: supports · Shared utility functions used by persistence code
