Afunana runs as a small set of Docker (or Podman) containers on the customer's own infrastructure. This page describes how those pieces fit together, from the source platform on one end to the web application and integrations on the other.
Topology
A standard install brings up the following containers, orchestrated by Docker Compose (on either Docker or Podman, auto-detected). In the default configuration only Caddy is published to the host; everything else is reachable only on the private container network.
| Container | Role |
|---|---|
| afunana-app | The application: FastAPI backend and the built React frontend, served together. Always present. |
| caddy | Reverse proxy and TLS terminator. Automatic HTTPS via Let's Encrypt when a domain is configured. Omitted when the customer fronts the app with their own managed proxy (nginx, F5, HAProxy). |
| sqlserver | Bundled SQL Server 2022, internal only — never exposed to the network. Omitted when the customer supplies an external SQL Server. |
Backend
The backend is Python 3.12 on FastAPI, served by Uvicorn workers behind Caddy. It is responsible for:
- Authentication and authorization (JWT, SSO/OIDC)
- Serving documentation, chat, and analysis data to the frontend and API clients
- Running the build pipeline that generates documentation
- The One AI Hub gateway that routes every LLM call
- The OAuth 2.0 authorization server for MCP clients
- Connecting to the source platform (IBM i, Oracle) for read-only source extraction, and — under approval — writing an executed change back to the IBM i
Database access uses raw, parameterized SQL via pyodbc — no ORM. A global rate limit is applied via slowapi. All LLM calls flow through a single router module so that provider selection, fallback, and parameter handling live in one place rather than scattered across the code.
Frontend
The frontend is a React 18 single-page application built with Vite and TypeScript, styled with Tailwind CSS and shadcn/ui components. It uses React Router for navigation, React Query for server state, React Flow for dependency and call-tree visualizations, and charting libraries for diagrams. The UI supports both left-to-right and right-to-left languages, and the documentation output language is configurable per collection.
The SPA talks to the backend exclusively through a centralized API helper that injects the auth token and handles errors uniformly.
Data stores
| Store | Purpose |
|---|---|
| SQL Server 2022 | Users, roles, collection and connection metadata, build history, configuration (app_config), model presets, change plans, chat history, and the security audit log. Bundled container by default, or a customer-supplied external SQL Server. |
| ChromaDB | Per-collection vector embeddings of the generated documentation, used for semantic search in chat. Embeddings are computed locally — no external embedding API. |
| BM25 index | A per-collection keyword index built alongside the vectors, for exact-match retrieval (program names, field names, codes). |
Filesystem (Data/) |
Per-collection extracted source, parsed structures, generated JSON documents, uploaded documents, and indexes. |
The analysis pipeline
The build pipeline transforms extracted source into searchable documentation. At a high level:
Structural mapping is deterministic — language grammar, not AI — and produces the call graph, cross-reference matrix, field catalog, and silent-failure findings. The documentation stages call the LLM. The index stage builds the local vector and keyword search layers, and a final stage derives business-concept tags. After the first full build, a content-hash delta rebuild re-analyzes only the programs whose source actually changed. See Build Process and AI & Analysis Pipeline for the full detail.
One AI Hub — the LLM gateway
Every LLM call is assigned a role — for example program documentation, file documentation, system overview, chat planning, chat answering, or code generation — and routes through a single governed gateway. Afunana defines eleven such roles in all, including a distinct SQL-documentation stage for plain-SQL sources. Each role is configured with an ordered list of provider-and-model choices: a primary and one or more fallbacks, so if the primary provider fails — rate limit, timeout, error — the router automatically falls back to the next entry.
The gateway supports four providers — Anthropic, OpenAI, Azure OpenAI, and local Ollama. Azure is first-class, configured with its own endpoint, key, and API version; Ollama serves local models for air-gapped sites. The shipped defaults use Anthropic Claude models as primaries with OpenAI models as fallbacks, and administrators can switch any role to Azure or Ollama. Model presets bundle a full set of per-role model choices, and a model advisor compares the models each provider currently offers against the active configuration and flags when a newer one is worth adopting. All routing is configurable in the admin panel — a provider or model switch is a configuration change, not a rebuild.
Every call through the gateway is also metered: token usage is priced against rates held in the database and rolled up into a Costs view, so the AI spend of each build and each query is visible per collection and per role rather than arriving as an undifferentiated cloud bill. See AI & Analysis Pipeline.
Source-platform integration
Afunana connects to the source platform to extract source, strictly read-only during analysis:
- IBM i (AS/400) — the primary path. A server-side extraction agent (the TTDOC component) is submitted via SBMJOB; Afunana polls it and pulls a package of catalog, file/field, key, relationship, and source-member data over FTP/IFS. Under an approved change plan, Afunana can also write source members back to the box.
- Oracle — read-only extraction via
python-oracledb(thin mode, no Oracle client) that reads the Oracle data dictionary (objects, source, columns, comments, constraints, dependencies) into the same internal contract the IBM i pipeline consumes. - z/OS (mainframe) — a defined connection type; full analysis support is on the near-term roadmap.
See Source Platform Integration.
Configuration system
Configuration follows a layered model. Bootstrap keys needed before a database connection exists (database coordinates, the JWT signing secret, the server role) come only from Docker Secrets or the environment. Everything else lives in the application configuration store, cached in memory and edited through the admin panel.
Seed values (such as an initial admin password) always read from the environment, never from the database, so empty placeholders can't shadow real values. See Environment Configuration for the full reference.
Interfaces
The same backend data is reachable four ways:
- Web application — the primary interface for documentation, chat, and administration.
- REST API — programmatic access for integration and automation. See API Reference.
- MCP endpoint — an authenticated Model Context Protocol server (OAuth 2.0 + PKCE) so AI tools (claude.ai, Cursor, VS Code, Copilot) can query the collection. See MCP Integration.
- VS Code extension — in-editor documentation, chat, and IBM i source editing. See VS Code Extension.
Security boundaries
- Caddy terminates TLS; the application and database never face the network directly.
- Authentication is JWT-based with optional SSO/OIDC; secrets (API keys, passwords, signing keys) are held in Docker Secrets, a writable secrets layer, or environment, masked in the admin UI, and never logged.
- Authorization is role-based across four roles — admin, user, read-only viewer, and a read-only
qareview role — so access can be scoped from full administration down to review-only. - The database runs as a least-privilege application user, internal to the Docker network, with Transparent Data Encryption in bundled mode.
- Every security-relevant event is written to a tamper-evident audit log with a SHA-256 hash chain and a database trigger that blocks modification.
See Security Architecture for the full model.
Deployment
Afunana is distributed as a private Docker image and installed with a single command that pulls the image and runs the installer (on Docker or Podman, auto-detected). The installer provisions secrets, generates the Compose and proxy configuration, and starts the application. In the default bundled mode it also brings up and hardens the SQL Server container; in external-DB mode it instead self-seeds its schema against the customer-supplied SQL Server. When a customer-managed reverse proxy is used, Caddy is omitted and TLS terminates upstream. Enterprise sites can pull images from an internal registry or install fully offline from a tar bundle. Updates re-pull the image and restart while preserving data. See Installation and Deployment & Updates.
Where to go next
- Build Process — the pipeline in detail.
- AI & Analysis Pipeline — how the AI stages work.
- Installation — standing up an instance.