12. Shipping
Your module works on your machine. Here is how it gets elsewhere.
Packaging
kewos module pack ./modules/library --out library-0.3.0.kwsA .kws is an archive, and you can open it to check what it holds. It also carries a
digest manifest: every file is listed with its hash, which is how a package modified
between export and install is detected.
Installing
kewos module install library-0.3.0.kws --modules-root /opt/kewos/current/modulesThen align the schema and restart:
kewos reconcile --confirm --modules-root /opt/kewos/current/modulessudo systemctl restart kewos kewos-workerAnd do not forget to switch the module on for the installation, or it stays invisible (see Making it visible).
The signature
By default, install refuses an unsigned package. A module arriving from a third party has
to prove its origin: it runs inside the server’s process, with access to the database.
While developing, that requirement would be pointless friction, so the behaviour follows the environment:
# On a developer machine: accepted without a signature.KEWOS_ENV=development kewos module install library-0.3.0.kws
# On a server, you have to say so explicitly.kewos module install library-0.3.0.kws --allow-unsignedkewos module install library-0.3.0.kws --require-signedTo sign, you need a keypair and the target installation must trust your public key. Talk to Kewos if you distribute modules to your customers.
Migrations
From your module’s second version onwards, a schema change ships as a migration.
modules/library/migrations/versions/0001_add_lost_note.pyAnd migrations are non-destructive by default: you rename, you backfill, you add. Dropping a column, or a not-null constraint with no backfill, is asked for explicitly, because it can destroy a customer’s data.
A checklist before shipping
- The manifest carries the right version and category.
-
icon.svgexists and usescurrentColor. - Every language file has the same keys as the others.
- No visible string is hard-coded, in Python or in JSON.
- The module’s groups are prefixed with its name.
- No hand-written state machine.
- No float for an amount.
- No
importof another business module. - The tests pass, including one edge case and one error case per behaviour.
- A non-administrator account has been tested, not only
kws_admin.
Next
You have been round the walkthrough. Two companions are worth reading:
- Python or YAML, if you are still weighing the format.
- Reading a document (OCR), to turn an image into text.
The finished module, to download
You do not have to retype any of it. The module from this walkthrough is packaged exactly as described here, with its screens, translations, permissions, PDF report, flow and tests:
- library-0.3.0.kws (23 KB): the complete library module, steps 1 through 13, plus its business rules, its fee with its currency and its members map.
The checksum, to verify before installing anything:
03e62249c512b723c021a820131c8d4c7b83b7dc8b471217f0e2152d83fd6676 library-0.3.0.kwssha256sum library-0.3.0.kwsInstalling it on your instance
kewos module install library-0.3.0.kws \ --database-url "$KEWOS_DATABASE_URL" \ --modules-root "$KEWOS_MODULES_ROOT" \ --allow-unsignedinstalled library 0.1.0 (UNSIGNED) into /opt/kewos/app/modules--modules-root has to exist. Otherwise:
REFUSED: modules root /opt/kewos/modules does not exist (or is not a directory);point --modules-root at the instance's modules folderThe folder is not created for you, deliberately: a typo would drop the module into a path the server never reads, and the install would report success.
Then the two gestures the package does not do for you:
# 1. The schema: the module's tables do not exist yet.kewos reconcile --confirm
# 2. Restart, so the process loads the module it now has on disk.systemctl restart kewosAnd activate it for the installation, under Settings → Modules. That is step 4 of the
walkthrough, and the one people forget: a module whose API answers perfectly stays invisible
until it is activated, with no error and nothing in the log.
Why it refuses at first
kewos module install library-0.3.0.kws --database-url ... --modules-root ...REFUSED: package is not signed; install it with an explicit allowance(never in production) or publish a signed buildThis package is unsigned, deliberately: signing it would mean having you install something
carrying our guarantee on your instance, for a practice module. The --allow-unsigned you
type is a consent, not a formality worked around — it is exactly what you will never type on
a production machine.
A module you publish for real is signed at publishing time, with your delivery chain’s key, never from the machine that wrote it.
What next?
You can build a module. The other half of the job is extending one that already exists, without copying it: Extending an existing module.