RFC-006 — L4 Distribution Forms: how a Sector reaches the world
| Field | Value |
|---|---|
| Status | Accepted (2026-04-29) · Amended (2026-06-22) |
| Author(s) | Rodrigo (with Claude as scribe) |
| Date | 2026-04-29 |
| Affects | Classification of fourth-level directories within each Sector; renames site/ → landing/; renames lib/ → engine/ (engines/ Domain only); restructures meta/sites/ |
| Depends on | monorepo-RFC-005-l3-sector-definition.md |
| Amendments | 2026-06-22 — add app/android/ (native Android, non-Flutter) to the closed L4 vocabulary (§3, §3.5). Meets the §3.4 bar with ≥3 Sectors: products/dev/konsul (already on app/android/, now in-vocabulary), Koder Keyboard (InputMethodService), and products/horizontal/kosm (Koder Kosm launcher, planned). |
1. Summary
Define distribution form as the L4 level of the monorepo taxonomy: the category of artifact through which a Sector is delivered to the consumer. This is the first level with a closed, uniform vocabulary — every distribution form has the same name across all Sectors, all Areas, and all Domains, regardless of the Sector's nature.
This RFC also resolves two consequential problems:
- The vocabulary collision between L2
meta/sites/and L4<sector>/site/,by renaming the L4 form to
landing/. - The misleading
meta/sites/opacity, by introducing an explicit subfolderstructure that names what each site represents.
2. Why a closed vocabulary at L4
Levels L1, L2, and L3 each apply a distinct criterion (consumption, theme, identity), but they let the terms vary by branch. L4 is different: every distribution form ties to a specific platform target, runtime, and packaging channel, all of which carry well-defined tooling, conventions, and CI pipelines.
A closed vocabulary at L4 is mandatory because:
- Tooling depends on it.
/k-parity,/k-test,/k-manifest, the SDKlints, and the CI matrix all key off the L4 folder name. Without a fixed set, every tool would need a discovery layer.
- L5 hangs off it. The next level (RFC-007) is *language and framework
conventions inside a distribution form* — Flutter conventions live inside
app/mobile/andapp/desktop/; Go conventions live insidebackend/andapp/cli/. Stable L4 names are a precondition for stable L5 rules. - It eliminates synonym drift. Without a closed set,
app/android/,mobile/,app/flutter/would all eventually appear in different Sectors meaning the same thing. The closed set forces every Sector to use the same name for the same artifact.
3. The closed vocabulary
| Folder | Artifact type | Platform target |
|---|---|---|
backend/ |
HTTPgRPCWebSocket server of the Sector | Linux server (Koder hosts) |
app/mobile/ |
Kroma app (Flutter = legacy, per-app migration → stack-RFC-019 Flutter sunset) |
Android + iOS |
app/android/ |
Native Android app (KotlinAndroidX, non-Flutter) — for surfaces that replace or extend OS-level Android components: home-screen launcher, IME (InputMethodService), accessibility bridge. Distinct from `appmobile/` (cross-platform). See §3.5 |
Android only |
app/desktop/ |
Kroma app (Flutter = legacy, per-app migration → stack-RFC-019) |
Linux + macOS + Windows |
app/tv/ |
JS/React app | TizenOS + WebOS |
app/web/ |
Web app: PWA, SaaS, admin console | Browser |
app/cli/ |
Command-line tool (non-interactive, flag-driven) | LinuxmacOSWindows |
app/tui/ |
Terminal UI (interactive, full-screen — Bubble Tea, Ratatui) | LinuxmacOSWindows |
engine/ |
Embeddable artifact (library, framework, SDK, runtime, component library, binding) — exclusive to Sectors in the engines/ Domain |
Multiple languages |
extension/ |
WebExtension MV3 injected into a host browser's chrome (≠ app/web/, which runs inside a tab) — added by rfcs/kruze-RFC-001 (ratified 2026-05-30) |
chromium / gecko / safari |
landing/ |
Marketing landing page for the Sector | Web (<sector>.koder.dev) |
<brand>/ |
B2B brand variant in an engine + product pair | Same runtime as the Sector, packaged under a different brand |
3.1 The semantic structure of L4
The folders cluster into four buckets along the same consumption axis used at L1:
backend/ ← consumed by API
app/{mobile,android,desktop,tv,web,cli,tui} ← consumed by direct human interaction
engine/ ← consumed by embedding (engines/ Domain only)
landing/ ← consumed by reading
<brand>/ ← brand-packaged variant of any of the aboveThis is not a coincidence. The criterion at L1 (form of consumption) reappears at L4 as a decomposer of the Sector: a Sector is a coherent identity that can be consumed in multiple ways, and L4 enumerates those ways.
engine/ is exclusive to the engines/ Domain
The L4 form engine/ only appears inside Sectors of the engines/ Domain. This is a deliberate constraint that gives the name discriminative power: seeing engine/ anywhere in a path immediately signals that the path is inside the engines/ Domain.
Why singular vs plural matters:
| Level | Term | Scope |
|---|---|---|
| L1 | engines/ (plural) |
Domain — the collection of Sectors consumed by embedding |
| L4 | engine/ (singular) |
The single embeddable artifact inside one Sector |
engine/ (singular) is never used in products/horizontal/, products/dev/, services/, infra/, or meta/ Sectors. RFC-002 explicitly retired the generic engine/ folder in product/service Sectors (where it had been used for the consumer-side backend, now renamed backend/). The reintroduction of engine/ as the L4 form is contextually disjoint — inside the engines/ Domain and inside the vertical exception documented below — and therefore unambiguous.
Vertical exception (META-DOCS-133)
products/vertical/ Sectors MAY use engine/ as their primary L4 subdir when all three criteria hold:
- The vertical is engine-shaped — a domain platform consumed by
tenant-specific apps and APIs, not a pure end-user app.
- The vertical's primary code surface is a backend daemon + CLI +
embeddable libraries, conceptually distinct from any UI.
- The vertical may later spawn
app/{mobile,desktop,…}/siblings;the
engine/subdir does not preclude that.
Rationale: vertical engines like products/vertical/edictus/engine/, products/vertical/clinic/engine/, products/vertical/iuris/engine/ deliver capability that consuming products embed; calling that subtree engine/ matches the conceptual role even when the vertical is shipped as a product (not as an embeddable library from engines/). 11 of 16 verticals follow this pattern (~69%); the exception formalizes observed reality rather than mandating a rename. The registry meta/docs/stack/registries/ticket-prefixes.md already codifies EDICTUS → products/vertical/edictus/engine as canonical.
products/horizontal/ and products/dev/ continue to use backend/ + app/ exclusively — those Sectors are user-facing, not engine-shaped, and don't qualify for the exception.
Why engine/ and not lib/: a Sector in engines/ may be a pure library (koder_ipc), a framework (koder_kit), an SDK (sdk/go), a runtime (lang/kode), a component library (koder_web_kit), or a binding (kodec/c). The umbrella term that covers all of them — and matches the L1 Domain name — is "engine" in the technical sense (RFC-002): a reusable algorithmic component, stateless, portable, embeddable. lib/ is too narrow.
3.2 app/ as the umbrella for human-facing artifacts
All distribution forms consumed by direct human interaction live under app/, distinguished by surface (mobile, desktop, TV, web, CLI, TUI). This makes `app