# AFI Architecture

Mizan is an **Application Framework Interface (AFI)** — the
server-client unification layer.

## Package layout

Tree organized by role.

```
backends/         server protocol adapters
    mizan-django/      Django adapter
    mizan-fastapi/     FastAPI adapter (AFI-common scope)
    mizan-rust-axum/   Rust/Axum adapter (handlers, errors, IR export)
    mizan-tauri/       Tauri adapter — Mizan calls served in-process
    mizan-ts/          TypeScript adapter (proves the protocol is language-agnostic)
frontends/        client kernel + per-framework adapters + transports
    mizan-base/        framework-agnostic kernel (@mizan/base); owns data, status,
                       error; adapters subscribe through the MizanTransport interface
    mizan-react/       React contexts + hooks over the kernel
    mizan-vue/         Vue composables over the kernel
    mizan-svelte/      Svelte stores/runes over the kernel
    mizan-rust/        Rust client kernel
    mizan-tauri-transport/    MizanTransport over Tauri IPC
    mizan-webview-transport/  MizanTransport over a webview message channel
    mizan-webview-channels/   channel transport over a webview bridge
cores/            shared language-level primitives
    mizan-python/      @client decorator, registry, MWT, HMAC cache keys
    mizan-rust/        Rust core — IR build (build_ir()), registry
    mizan-rust-macros/ #[derive(Mizan)] / #[mizan::client] proc-macros
    mizan-rust-ssr/    embedded-V8 SSR engine (deno_core + deno_web); evals the
                       build-time bundle, renders per request; no_rsc guard
protocol/         protocol-level tooling
    mizan-codegen/   codegen — Rust binary (crate `mizan-codegen`); reads KDL IR,
                     emits typed clients. Targets: stage1, react, vue, svelte,
                     channels, python, rust. Askama templates under templates/.
    mizan-generate/  thin npm-package launcher (bin/launcher.mjs) dispatching to
                     the compiled mizan-codegen binary per platform
```

## Two orthogonal products

- **RPC** — typed client generation via codegen
- **SSR** — server rendering via the embedded-V8 engine in the Rust
  binary (see `docs/SSR_ARCHITECTURE.md`)

Independent and composable. Either ships standalone; together they
compose.

## Kernel model

The client kernel (`@mizan/base`) is the one hard thing. It owns
`ContextState<T> = {data, status, error}`, the context registry
(`registerContext`), `mizanCall` / `mizanFetch`, server-driven `merge`
and `invalidate`, and `initSession`. It reaches the backend through a
pluggable `MizanTransport` (`call` / `fetch`); the default is the
HTTP `httpTransport()`, swapped via `configure({ transport })` for
Tauri / webview hosts. Per-framework adapters are thin idiomatic
wrappers that subscribe to the kernel. Codegen emits typed bindings
against the framework adapter's surface — a React developer gets
`useEcho()` hooks, a Vue developer gets `useEcho()` composables, a
Svelte developer gets readable stores. Same kernel underneath.

## KDL is the IR

The Mizan IR is **KDL** — the LLVM-IR-equivalent of the system. Every
backend adapter produces KDL describing its registered functions,
contexts, types, and invalidation graph. Every codegen target consumes
KDL. KDL is the contract; everything else (REST envelopes, OpenAPI
documents, framework idioms) is sediment around it.

The IR is validated against multiple adapters — single-adapter
validation hides assumptions, and divergence between adapters is what
the IR exists to prevent.

Forward-direction primitives:

- Each backend adapter emits KDL on stdout from an IR-export command:
  FastAPI `python -m mizan_fastapi.ir <module>`, Django
  `python manage.py export_mizan_ir`, Rust a consumer-side cargo bin
  that calls `mizan_core::build_ir()`. Python's `build_ir()` walks
  `mizan_core.registry`. The IR grammar (`type` / `function` /
  `context` / `channel` nodes) is parsed by `mizan-codegen`'s
  `src/ir.rs`; fixtures live at
  `protocol/mizan-codegen/tests/fixtures/*.kdl`.
- `protocol/mizan-codegen/src/fetch.rs` spawns the configured source
  command and parses the KDL it writes.
- Codegen reads KDL directly — no OpenAPI envelope, no
  `openapi-typescript`, no per-backend converter divergence; codegen
  is a single Rust binary.
- Edge manifest, MWT claims, and other protocol artifacts derive from
  the same registry/IR.

## Authoring surface

Python (Django) + React is the reference stack. Vue and Svelte are
co-equal codegen targets over the same kernel. The TypeScript backend
(`mizan-ts`) proves the protocol is portable.

## Why the AFI shape

Quadratic ecosystem growth (N server adapters × M client adapters)
collapses to linear (one adapter per stack) when both sides
communicate through a shared protocol.

## Invariants

- All cross-package communication goes through the protocol. No
  direct cross-package dependencies.
- New adapters land as new packages, not as modifications to existing
  ones.
- Framework adapters wrap the kernel in framework idioms — they
  don't bypass it. Codegen targets the adapter, not the raw kernel.
