Afunana is built to run inside the most conservative environments there are — banks, insurers, and government IT — and to keep running, unattended, for years. That constraint shaped every engineering decision: the system has to be correct, lean, observable, and cheap to maintain, not merely feature-rich. This page describes the principles behind the codebase and the concrete mechanisms that enforce them.
Correctness first — deterministic where it counts, AI where it helps
The structural backbone — how programs call each other, which fields flow where, where a parameter's size disagrees across a boundary — is computed deterministically, by parsing the source, not by asking a model. AI is used only for the one thing it is genuinely better at: explaining code in business language.
That split is the single most important design decision in the product. It means the maps, cross-references, and silent-failure checks are reproducible and auditable, and the probabilistic component is contained to the documentation layer — where every claim is traced back to a source line a human can verify. Nothing that must be exact is left to a guess.
Lean by construction
- Afunana ships as a small set of containers (Docker or Podman), built from a shared base image plus a thin application image, so deployments are reproducible and updates are small.
- Embeddings are computed locally. There is no dependency on an external vector service or a third-party API simply to function.
- The analysis pipeline does the expensive work once, then only on what changed — rather than reprocessing the whole estate on every run.
Generic and extensible — one model for every platform
IBM i (COBOL / RPG / CL / DDS), Oracle (PL/SQL), and plain SQL are each extracted into one common internal model, then documented, quality-checked, and searched the same way. Adding a platform means teaching the extractor to populate that model; the documentation, chat, data dictionary, and checks downstream come along for free. z/OS mainframe COBOL is on the roadmap on exactly this foundation.
The same genericity applies to AI: every model call goes through one governed gateway, so supporting a new provider or model is a configuration change, not code scattered across the system.
Best practices, enforced by architecture — not by convention
Good structure here is load-bearing, not aspirational:
- One source of truth, no hidden defaults. Configuration lives in the database and is read through a single layered resolver; the app fails loudly if a required value is missing rather than guessing. Nothing critical is hardcoded.
- All AI behind one router. No part of the codebase talks to a model SDK directly — every call flows through the gateway, which is where routing, fallbacks, caching, and cost metering live. Swapping providers never touches business logic.
- Prompts are data, not code. The AI prompts live in editable files, changeable through the admin UI without a restart or redeploy — so tuning the product's voice or behavior is an operation, not an engineering release.
- Typed end to end. Validated data models on the backend and a typed frontend catch whole classes of error before they ship.
- A stable contract. Program documentation is produced against a fixed schema, and every factual claim carries a source-line citation by contract — the citation is part of the data model, not a nice-to-have.
- Separation of concerns. Extraction, structural analysis, AI documentation, indexing, and quality checks are distinct stages with clear boundaries, so each can evolve, be tested, or be re-run independently.
Performant
- Deterministic parsing is fast and runs in parallel under a configurable concurrency limit.
- Retrieval is hybrid — semantic vectors combined with keyword ranking and fused together — for accurate answers without brute-force scanning.
- A semantic cache short-circuits repeated questions, and database access is pooled rather than reconnecting on every request.
- Where a model supports it, prompt caching reuses the stable parts of a request to cut both latency and cost.
Scales with the estate
- After the first build, every change triggers a delta rebuild: a content hash identifies exactly which programs changed, and only those are re-analyzed. A million-line estate is not reprocessed because ten programs moved.
- Work is organized into independent collections, and heavy operations run under configurable parallelism, so throughput can be tuned to the hardware.
- The bundled database is fine to start, but the same system runs against a customer's own external database — including a high-availability cluster — with no code change.
Sustainable and maintainable
The real cost of software is the years after it ships, so the codebase is built to stay cheap to own:
- Config over code. Providers, models, prompts, check severities, timeouts, and thresholds are all settings — so most changes to behavior are made by an operator, not a developer, and without a release.
- Documentation that refreshes itself. Because rebuilds are incremental and automatic, the generated documentation tracks the live code instead of drifting out of date — the classic failure mode of hand-written documentation.
- A single documentation source of truth. The product's own documentation (these pages included) is written once and rendered to every surface, so it cannot silently diverge between places.
- Observability is built in. Every model call's tokens and cost are metered against a pricing table you control; security-relevant events are written to a tamper-evident audit log; and the system reports its own health — so operators can see what it is doing, and what it costs, without instrumenting it themselves.
Secure and operable by design
Security is part of the architecture, not a layer bolted on: secrets resolve from your own vault or a mounted secret store (never from application data), access is role-based, the audit log is tamper-evident, and the whole system can run fully air-gapped. The Security Architecture and System Architecture pages cover these in depth.