Monorepo RFC 003 l1 domain taxonomy

RFC-003 — L1 Domain Taxonomy: five domains with a single criterion

Field Value
Status *ccepted*(20260428)
Author(s) Rodrigo (with Claude as scribe)
Date 20260428
Affects Monorepo root structure; all modules
Depends on monorepo-RFC-001-area-first-directory-structure.md, monorepo-RFC-002-directory-nomenclature.md

1. Summary

Introduce a new level above the current Areas (L1 → L2) by grouping all directories into five *omains*at the true L1. Each Domain is defined by a single, uniform criterion: *ow is the component consumed?*


2. Problem

RFC001 established Areafirst directories, but the monorepo root remained heterogeneous: some Areas are defined by who uses them (suite/, vertical/), others by technical function (data/, infra/), others by artifact type (sdk/, brand/, docs/). No single classification criterion applies uniformly across all L1 directories.

This makes placement decisions arbitrary for new modules and creates ambiguity when reading the directory tree.


3. Principle: Linnaean taxonomy applied to the monorepo

Each level of the directory tree must have *ne and only one*classification criterion, consistent across all entries at that level — as in biology:

Kingdom → Phylum → Class → Order → Family → Genus → Species

The criterion at each level is what defines the split. At the monorepo root (L1), the criterion must be answerable for any component, deterministically.


4. The criterion for L1: form of consumption

The most consistent single criterion across all components in the monorepo is:

*ow is this component consumed?*

This question has exactly five distinct answers, yielding five Domains:

Answer Domain Directory
Direct interaction — UI / DX The user interacts with it directly (UI, CLI experience, developer experience) products/
API call — servicetoservice Other services or products call it over the network (HTTPgRPCWebSocket) services/
Embedding — import + execute locally It is imported as a dependency and runs inside the caller (library, SDK, runtime, codec) engines/
Operation — deploy + configure It is deployed and configured as infrastructure substrate; products do not import it infra/
Reading — documentation, reference It is read by humans; not deployed as a service meta/

5. The five Domains

5.1 products/ — consumed by direct interaction

Components with end users, UX/DX, and brand identity. The consumer interacts with the product directly through an interface.

*ub-Areas (L2):*

  • horizontal/ — horizontal B2C products (any user, any industry) — renamed from suite/ by RFC-007
  • vertical/ — vertical B2B solutions (specific sector)
  • dev/ — developer platform (B2D: git forge, CI, terminal, IDE, registry)

*ule of thumb:*if you would design an onboarding flow for it, it belongs here.

5.2 services/ — consumed by API call

Shared backend services consumed by products and other services over the network. No direct end-user UX. Deployed as servers.

*ub-Areas (L2):*

  • foundation/ — cross-product primitives (identity, billing, payments, moderation, ads)
  • ai/ — AI services (gateway, runtime, recsys, voice, agents, RAG)
  • media/ — audio/video processing services (transcoding, streaming, manifests)

*ule of thumb:*if a product calls it via HTTP/gRPC, it belongs here.

5.3 engines/ — consumed by embedding

Reusable components that are imported and executed locally inside the caller. Stateless or nearly stateless. Portable across backends, frontends, CLIs, WASM, and standalone processes. Not deployed as independent network services. Includes both internal and external SDKs — the consumption form (embedding) is the criterion, not the audience (internal vs. external).

*ub-Areas (L2):*

  • kodec/ — audio/video codec (Rust; native lib, C API, WASM, bindings, CLI)
  • lang/ — Kode language, runtime, compiler, stdlib, KMD
  • sdk/ — client SDKs (Go, JS, Python, Dart/Flutter, Rust) and internal

    component libraries (koder_kit, koder_ipc, koder_player, koder_web_kit)

*ule of thumb:*if a product imports it as a dependency and executes it locally (not via network call), it belongs here.

*ote on sdk:*the `sdk directory contains both internal SDKs used to build Koder's own apps (koderkit, koderipc, etc.) and external SDKs distributed to third-party developers (go, js, python, rust). Both are consumed by embedding, so both belong in enginessdk. The internal/external distinction is a sub-classification within sdk/`, not a Domain-level distinction.

5.4 infra/ — consumed by operation

Infrastructure substrate: the components that the platform runs on. Products and services do not import infra/ components as libraries — they depend on them operationally (they are configured, deployed, and managed separately).

*ub-Areas (L2):*

  • net/ — network, security, edge, DNS, mesh (current infra/ contents)
  • data/ — databases, queues, search, blob, pipelines
  • observe/ — APM, logs, metrics, alerting, uptime, dashboards
  • linux/ — Koder Linux distro and desktop environment

*ule of thumb:*if removing it takes down the data center (not a specific product), it belongs here.

5.5 meta/ — consumed by reading

Non-deployed artifacts: documentation, brand assets, landing pages, internal tooling configuration. Consumed by humans reading, not by machines calling APIs or importing code.

*ub-Areas (L2):*

  • brand/ — visual identity: logos, palettes, fonts, guidelines
  • docs/ — technical Stack documentation: RFCs, deep-dives, catalog, vocabulary
  • sites/ — institutional and Area landing pages
  • context/ — internal Claude Code configuration (not a product)

*ule of thumb:*if a machine does not consume it at runtime, it belongs here.


6. Vocabulary: the term "Domain"

The L1 level is named *omain*(Domínio in Portuguese). This term sits above the existing terms Area (now L2) and Sector (now L3):

Domain (L1)  →  Area (L2)  →  Sector (L3)  →  Distribution form (L4)
products/        suite/         kmail/            backend/, app/mobile/, site/
services/        ai/            gateway/          backend/
engines/         sdk/           koder_kit/        (library — no L4 split)
infra/           data/          kdb/              backend/

vocabulary.md is updated separately with the formal definition of Domain.


7. Placement decision tree

For any new module, answer these questions in order:

Does it have end users + UX + brand?
  YES → products/
  NO ↓

Does it expose a network API (HTTP/gRPC/WS) consumed by other services?
  YES → services/
  NO ↓

Is it imported as a dependency and executed locally?
  YES → engines/
  NO ↓

Is it infrastructure that products depend on operationally (not via import)?
  YES → infra/
  NO ↓

→ meta/

8. Migration: current root → new structure

Current path New path
suite/ products/horizontal/ (renamed from suite/ per RFC-007)
vertical/ products/vertical/
dev/ products/dev/
foundation/ services/foundation/
ai/ services/ai/
media/ services/media/
core/kodec/ engines/kodec/
lang/ engines/lang/
sdk/ engines/sdk/
core/ (remainder) distribute per §5 (see below)
infra/ infra/net/
data/ infra/data/
observe/ infra/observe/
linux/ infra/linux/
brand/ meta/brand/
docs/ meta/docs/
sites/ meta/sites/
context/ meta/context/

*core remainder** — after kodec moves to engines/, the remaining core/ contents (apis, device, audiorecorder, settings, botserver`) should each be classified individually using the decision tree in §7 before migration. This RFC does not pre-decide their placement.

*egacy directories*(apps/, platform/, projects/, server/, tools/, store-cli/, koder-* top-level repos) are subject to a separate migration decision — they are not part of this RFC.


9. Rationale for the criterion choice

Several alternative criteria were considered and rejected:

Criterion Problem
Who uses it Breaks for foundation/ (used by everyone) and sdk/ (used internally and externally)
Technical function Every component has a function; produces too many categories
Deployment model sdk/ and infra/ are both "deployed" but to very different ends
Importance / fundamentalness Subjective; every team claims their module is "core"

*orm of consumption*is the only criterion that is:

  1. Answerable for any component (deterministic)
  2. Consistent — the same question, the same five answers, always
  3. Stable over time — how you consume a component rarely changes
  4. Free of audience bias — the consumer (internal vs. external) is not the criterion

10. Acknowledgment

This RFC was validated by four independent AI systems (Gemini, Codex, Kimi, Qwen) that were given only the problem statement and six hypotheses. All four independently converged on engines/ for kodec + lang + sdk/, and on the formofconsumption as the unifying criterion. The sdk/koder_kit counterexample — an internal Flutter SDK consumed by embedding, not by external developer interaction — was raised after the AI consultation and confirmed that sdk/ as a whole belongs in engines/, not in products/dev/.

Source: ../home/koder/dev/koder/meta/docs/stack/rfcs/monorepo-RFC-003-l1-domain-taxonomy.md