1.1 What Kalos Is
Kalos is a C++20 microkernel application server. It provides seven services — configuration, plugin loading, message bus, lifecycle management, logging, plugin registry, and management socket — and delegates all domain-specific behavior to dynamically loaded plugins.
The kernel has no knowledge of HTTP, SQL, authentication, or application logic. These capabilities are provided by four plugin archetypes:
- Transport plugins expose the message bus to external clients. The reference implementation is a REST transport with TLS, CORS, and rate limiting.
- Store plugins persist data. Reference implementations exist for SQLite and PostgreSQL.
- Handler plugins implement business logic by registering actions on the message bus. The ADL engine, the authentication system (authd), and the seeder are all handler plugins.
- Scripting plugins extend handler behavior at runtime. The reference implementation embeds Lua 5.4 via sol2.
Plugins are loaded via dlopen (POSIX) or LoadLibrary (Windows) and communicate exclusively through the kernel’s message bus. A transport plugin receives an external request, dispatches it as a bus action, a handler plugin processes it, a store plugin persists the result, and the transport returns the response. The kernel orchestrates the lifecycle; the plugins do the work.
Kalos is a single statically-linked binary. It requires no external runtime, no interpreter, and no virtual machine. It runs on Linux, Windows, and macOS, and is designed for eventual deployment on embedded platforms (ESP32, STM32) via WebAssembly compilation.
1.2 What ADL Is
ADL (Application Definition Language) is a YAML-based declarative language for defining complete backend applications. An ADL domain file specifies:
- Data models — resources with typed fields and constraints
- Relationships — belongsTo, hasMany, and belongsToMany associations with cascade behavior
- Permissions — role-based access control at the operation level and the field level
- State machines — named states with guarded transitions, required fields, and side effects
- Validation — field-level constraints and cross-field business rules
- Computed fields — virtual, materialized, and aggregation-based derived values
- History — domain-aware event timelines with human-readable labels [v0.3]
- Rules — cross-resource business policies with regulatory citations [v0.3]
- Notifications — triggered alerts delivered through configurable channels [v0.3]
- Scheduled tasks — recurring and one-shot time-based actions [v0.3]
- Workflows — multi-step, multi-resource process orchestration [v0.3]
- Reports — named queries, formatted reports, and dashboard widgets [v0.3]
- Templates — document generation from domain data [v0.3]
- Integrations — outbound and inbound communication with external systems [v0.3]
- Privacy — field-level PII classification, subject rights, and retention policies [v0.3]
- Localization — multi-language support with locale-aware formatting [v0.3]
The Kalos ADL engine plugin parses a domain file, generates the database schema, registers CRUD handlers on the message bus, maps REST routes, produces an OpenAPI specification, and manages schema evolution through a built-in migration system. The runtime interprets the domain model directly — there is no intermediate code generation step. The YAML file is the application.
A minimal ADL domain:
domain:
name: tasks
version: "1.0.0"
resources:
Task:
object:
id: { type: uuid, primaryKey: true }
title: { type: string, required: true }
done: { type: boolean, default: false }
$merge: Timestamp
objects:
Timestamp:
createdAt: { type: datetime, autoNow: create }
updatedAt: { type: datetime, autoNow: always }
This file, when submitted to a running Kalos instance, produces:
- A
taskstable withid,title,done,createdAt, andupdatedAtcolumns - Six REST endpoints:
GET /tasks,GET /tasks/:id,POST /tasks,PATCH /tasks/:id,PUT /tasks/:id,DELETE /tasks/:id - Query support: filtering, sorting, pagination, search, field selection, count, and distinct
- An OpenAPI 3.1.0 specification at
/api/v1/domains/tasks/openapi.json - Schema introspection at
/api/v1/domains/tasks/schema
No application code is written. No controllers, no models, no routes, no middleware. The domain file is the complete specification, and the runtime is the complete implementation.
1.3 Design Principles
Six principles govern ADL’s design. When a design decision must be made, these principles are applied in order.
1. Domain-Driven. The domain model is the source of truth. The database schema, the API, the permissions, the validation, the documentation, and the UI are all derived from the domain model. If the model changes, everything downstream changes automatically. There is no drift between specification and implementation because they are the same artifact.
2. Convention Over Configuration. Sensible defaults reduce the surface area of a domain file. A resource with no permissions: block defaults to admin-only access. A uuid primary key is auto-generated. Timestamps are auto-populated. Pluralization follows English rules. Explicit configuration overrides any convention, but most domains need very little of it.
3. Type Safety. Every field has a type. Every type has validation rules. Every constraint is enforced at the API boundary before data reaches the store. Type violations produce structured 422 responses with per-field error details. The type system is closed — only types defined in this specification are valid.
4. Incremental Complexity. A domain file with one resource and three fields produces a working API. Adding relationships, permissions, state machines, computed fields, history, notifications, workflows, reports, and integrations is additive — each feature is declared independently and composes with every other feature. A domain author never encounters complexity they did not request.
5. Declarative First, Imperative When Necessary. Every feature that can be expressed declaratively is expressed declaratively. When business logic exceeds the model’s expressiveness, Lua scripting provides a first-class imperative escape hatch with full access to the message bus and data store. The boundary between declarative and imperative is explicit: hooks in the YAML reference scripts by name, and scripts live in external files.
6. Database Agnostic. The domain model does not reference database-specific constructs. The same YAML file runs against SQLite and PostgreSQL without modification. Store-specific behavior (type mapping, DDL generation, migration strategies) is encapsulated in the store plugin. The domain author writes types, not columns.
1.4 Architecture Overview
The Kalos platform has four layers. Each layer consumes the output of the layer above it.
┌─────────────────────────────────────────────────────────┐
│ DOMAIN MODEL │
│ │
│ YAML file defining resources, relationships, │
│ permissions, state machines, validation, history, │
│ rules, notifications, schedules, workflows, │
│ reports, templates, integrations, privacy, │
│ localization │
└──────────────────────┬──────────────────────────────────┘
│ parsed by ADL engine
┌──────────────────────▼──────────────────────────────────┐
│ ADL ENGINE │
│ │
│ Parser → DomainModel struct │
│ DdlGenerator → database schema │
│ ActionGenerator → bus action handlers │
│ RouteRegistrar → REST route mappings │
│ MigrationGenerator → schema evolution plans │
│ OpenApiGenerator → API documentation │
│ HistoryWriter → event timeline recording [v0.3] │
│ RulesEngine → policy enforcement [v0.3] │
│ NotificationEngine → alert delivery [v0.3] │
│ SchedulerEngine → time-based automation [v0.3] │
│ WorkflowEngine → process orchestration [v0.3] │
│ ReportEngine → analytics computation [v0.3] │
│ TemplateEngine → document generation [v0.3] │
│ IntegrationEngine → external communication [v0.3] │
│ PrivacyEngine → compliance enforcement [v0.3] │
│ LocaleRegistry → translation management [v0.3] │
└──────────────────────┬──────────────────────────────────┘
│ registers on
┌──────────────────────▼──────────────────────────────────┐
│ MICROKERNEL │
│ │
│ Config · Plugin Loader · Message Bus · Lifecycle │
│ Logging · Plugin Registry · Management Socket │
└──────────────────────┬──────────────────────────────────┘
│ dispatches to
┌──────────────────────▼──────────────────────────────────┐
│ PLUGINS │
│ │
│ Transport (REST) · Store (SQLite, PostgreSQL) │
│ Auth (authd) · Scripting (Lua) │
│ Seeder · ADL Engine │
└─────────────────────────────────────────────────────────┘
Request lifecycle. An external HTTP request arrives at the REST transport plugin. The transport identifies the target action from the route mapping and dispatches it on the message bus. The middleware chain executes in order: rate limiting, request validation, endpoint enablement, JWT authentication, RBAC authorization, and audit logging. If all middleware passes, the ADL engine’s action handler processes the request — executing validation, evaluating business rules, checking state machine guards, persisting the record through the store plugin, writing history events, firing notifications, advancing workflows, and returning the response. The transport serializes the response and sends it to the client.
Internal requests. Lua scripts, workflow steps, and scheduled tasks invoke actions through kalos.call(), which dispatches directly on the message bus, bypassing the transport middleware. Internal requests carry the __system__ identity or the identity of the originating actor, depending on the calling context.
1.5 Specification Scope
This specification defines the complete behavior of the Kalos platform as of ADL v0.3. It is the authoritative reference for implementors, domain authors, tool builders, and test authors.
This specification defines:
- The YAML syntax for every ADL construct
- The runtime behavior of every declared feature
- The REST API contract (routes, methods, request/response formats, status codes)
- The expression language (AEL) syntax, semantics, and built-in functions
- The migration system behavior (diffing, planning, execution, verification)
- The authentication system endpoints and token lifecycle
- The Lua scripting API and hook integration model
- The seeder format and execution semantics
- The error taxonomy and response formats
- The OpenAPI generation contract
- The introspection endpoint responses
This specification does not define:
- C++ implementation details (class names, file structure, compiler requirements)
- Performance characteristics or benchmarks
- Deployment strategies or infrastructure requirements
- GUI or frontend implementation
- Third-party tool integrations beyond those declared in the integrations feature
- Behavior of features not yet implemented (features are specified when they are ready for implementation and testing)
Conformance. An implementation conforms to this specification if it correctly implements every behavior described herein and passes the corresponding proof-of-concept verification suite. Behaviors not specified in this document are implementation-defined and MUST NOT be relied upon by domain authors.
1.6 Notation Conventions
Requirement Levels
This specification uses the keywords defined in RFC 2119:
- MUST — the requirement is absolute. An implementation that does not satisfy a MUST requirement does not conform to this specification.
- MUST NOT — the prohibition is absolute.
- SHOULD — there may be valid reasons to deviate, but the implications must be understood and weighed.
- SHOULD NOT — there may be valid reasons to permit the behavior, but the implications must be understood.
- MAY — the behavior is optional. An implementation may include it or omit it.
YAML Examples
YAML examples in this specification are normative unless marked # illustrative. Every normative YAML example MUST be accepted by a conforming parser without error.
# This is a normative example. A conforming parser MUST accept it.
domain:
name: example
version: "1.0.0"
resources:
Item:
object:
id: { type: uuid, primaryKey: true }
name: { type: string, required: true }
Type Signatures
Function signatures use the notation functionName(param: Type, ...) → ReturnType. Optional parameters are suffixed with ?. Union types use |. Array types use Type[].
hasRole(role: string) → boolean
substring(s: string, start: integer, end?: integer) → string
field(name: string) → string | integer | boolean | null
Cross-References
References to other sections use the notation §N.N (e.g., §7.2 for Tier 0 types). References to appendixes use the notation Appendix X (e.g., Appendix B for the type reference table).
Version Markers
Features introduced in this version are marked [v0.3]. Features carried forward from v0.2.3 have no marker. Features planned for future versions are not included in this specification.
End of Chapter 1.
Next: Chapter 2 — Microkernel