1. The module
A Kewos module declares. It does not build a screen, does not draw a form, does not write SQL.
Declaring a model gives you, with nothing more: the table, the API, the screens, search, audit, permissions, translation and export. The administration discovers everything from the server, so adding a module never requires redeploying the interface.
The skeleton
A module is a directory under modules/. Ours is called library.
modules/library/├── module.json <- identity and dependencies├── __init__.py <- the entry point the kernel calls├── icon.svg <- the launcher icon├── acl.json <- the permissions├── models/│ ├── __init__.py│ ├── title.py <- the work│ ├── copy.py <- the physical copy│ ├── member.py <- the member│ ├── loan.py <- the loan│ └── workflow.py <- the loan lifecycle├── reports/ <- the PDF documents├── views/ <- fourteen screens, in JSON└── i18n/ ├── en.json └── fr.jsonmodules/library/├── manifest.yaml <- identity and dependencies├── icon.svg <- the launcher icon├── security.yaml <- groups, permissions, record and field rules├── models/│ ├── library_title.yaml <- the work│ ├── library_copy.yaml <- the physical copy│ ├── library_member.yaml <- the member│ └── library_loan.yaml <- the loan├── automation/│ └── workflows.yaml <- the loan lifecycle├── views/ <- one file per model, all its screens inside└── i18n/ ├── en.yaml └── fr.yamlNo entry point: there is nothing to call. The kernel reads the files.
modules/library/└── library.km <- the whole module, in one fileThat is KM’s main argument against YAML. The same module, one tree fewer: what eight files describe reads here from top to bottom.
The files appear as the steps go. For now, create the directory and the manifest.
The manifest
module.json:
{ "name": "library", "depends": ["core"], "summary": "Library management: catalogue, copies, members and loans.", "version": "0.1.0", "category": "operations"}manifest.yaml, with one extra key:
name: librarykind: declarativeversion: 0.1.0depends: [core]category: operationssummary: "Library management: catalogue, copies, members and loans."kind: declarative is what tells the kernel to read the directory instead of importing it.
It is the only difference of identity between the two formats.
At the top of library.km:
module library { title "Library" version 0.1.0 depends core}No kind: the .km extension already says it. The kernel reads this block, makes
the same manifest as the YAML beside it, and hands the whole thing to the same
loader.
| Key | Role |
|---|---|
name | The technical name. It prefixes every one of your tables. |
depends | The modules yours needs. core at minimum. |
version | A semantic version. Used for upgrades and migrations. |
category | The launcher aisle: sales, assets, operations, hr, finance… |
summary | One sentence, shown in the module list. |
The entry point
__init__.py, at the module’s root, exposes the function the kernel calls at boot.
"""``library`` -- catalogue, copies, members and loans."""
from __future__ import annotations
from pathlib import Pathfrom typing import TYPE_CHECKING
from kewos.orm import apply_module_aclsfrom kewos.pdf import register_reports_from_dirfrom kewos.views import register_views_from_dir
from . import models
if TYPE_CHECKING: from kewos.orm.registry import Registry
_MODULE_DIR = Path(__file__).parent
def register(registry: Registry) -> None: """Declare the module: models, permissions, screens, then documents.""" models.register_models(registry) apply_module_acls(registry, _MODULE_DIR / "acl.json") register_views_from_dir(_MODULE_DIR / "views") register_reports_from_dir(_MODULE_DIR / "reports")Four lines, in that order: what exists, who may touch it, how it is shown, what it prints. That is the reading order of a Kewos module, and it never changes.
There is none.
The loader discovers models/, views/, security.yaml, automation/ and i18n/ by their
names, and calls the same kernel functions the Python module would have called. That is the
whole principle of the format: translate, do not reinvent.
The order is the same; it is simply imposed by the loader instead of written by you.
There is none here either, for the same reason: KM produces exactly the same documents as YAML, and the declarative loader applies them.
The reading order is your file’s own: what you write at the top is read first.
Next
The data: declaring the four models.