An official developer portal of the Government of the Republic of Zambia ยท Test environmentVerify a certificate
Pamodzi Developer HubBuild, integrate and learn the e-Services framework

Modules and reusable capabilities

The core of the platform serves every MDA. Some MDAs need functions nobody else needs: a ministry's estate and rental management, forestry concessions, co-operative registration. These live in modules. Other functions could serve many MDAs: selling goods, quotas, inspections. These become reusable capabilities. This lesson explains both, and how to decide which one a need calls for.

What a module is

A module is an optional, versioned bundle that an MDA can switch on without changing core. It owns:

  • its own tables (migrations), routes and controllers;
  • its policy rules, named actions checked by the policy decision point;
  • its background jobs;
  • its back-office screens and menu entries, under "Ministry functions";
  • its contributions to core through extension points;
  • optionally, generic data-driven blocks for the portal and capabilities for the POS app.

In code, a module lives in zcm-backend/modules/<id>/ with a manifest (module.js), and its back-office screens in back-office-ui/src/modules/<id>/. New modules are created with scripts/newModule.js, and a worked example module shows every part.

Core never imports a module. A module plugs into core; core does not know which modules exist.

Switching modules on and off

A module is off by default. It is on for a caller only when every level says yes:

LevelSet byExample
1. CeilingEnvironment or Helm values (MODULES_AVAILABLE, MODULES_FORCE_OFF)The test environment never offers module X
2. InstallationAn administrator, under System administration โ†’ Modules, with maker-checkerModule X is switched on for this installation
3. Ministry assignmentThe same screenModule X is on only for the MDAs it is assigned to

A module whose dependency is off is off too. On the hub, a module is never assigned to a ministry that runs its own node: that ministry's node runs it.

Off means absent, but nothing is lost

When a module is off:

  • every one of its routes answers 404 MODULE_DISABLED;
  • its policy actions are refused at the very first step of every decision;
  • its jobs are skipped, and its menu entries and portal blocks disappear;
  • its data stays. Switching it on again restores everything.

There is one important exception, the money rule: a payment that was started while the module was on is still finalised by the module after it is switched off. Switching a module off must never lose money or records.

Extension points

Modules plug into core only through named extension points, listed in lib/modules/points.js. Some examples:

Extension pointWhat a module can do through it
case.onSubmitReact when an application is submitted
case.onDecision, case.onApprovedReact to a decision
payment.quoteCompute a fee from its own rules
payment.onFinalisedAct when a payment is finalised (also when the module is off)
geo.validatorsCheck a geometry, for example that an area does not overlap another licence
allocation.claimsClaim units in the allocation and quota ledger
registers.packsContribute register packs (typed registers)
documents.templatesContribute output-document templates
designer.stepTypesOffer a new step type in the process designer
dsr.exportSectionsAdd its data to a citizen's data access export

If a module needs a hook that does not exist, the answer is to add a new generic extension point to core and document it. Adding module logic to core files such as the case controller or the workflow engine is not allowed.

Reusable capabilities

When a feature could serve more than one MDA, it is built once, in core, and switched on per service through a service capability or setting. Examples already built:

  • the shop, for any ministry that sells products (a product catalogue for any service with the goods-sale

    capability);

  • the allocation and quota ledger;
  • name reservation;
  • inspections;
  • enforcement cases;
  • the geometry field, for any licence that covers an area.

A capability is cheaper for everyone: one implementation to test and secure, and any MDA can use it by configuration.

The portal stays generic

Modules may add only generic, data-driven blocks to the portal. For example:

  • a map and area block for any licence that carries a geometry;
  • a product catalogue for any service with the goods-sale capability.

A guard test with an allow-list enforces this, and nobody adds to the allow-list. Ministry-specific screens belong only in the back office.

Deciding: configuration, capability or module

NeedAnswer
A new licence with a form, an inspection, a fee and a certificateConfiguration only
Several MDAs sell goods to the publicThe shop capability, switched on per service
One ministry manages its own estate of government houses, leases and rent billingA module
A module needs to compute a fee from a register it ownsThe module, through payment.quote
A module needs to react to an event core does not announce yetA new generic extension point in core, then the module uses it
A citizen page "My forest licences"No. Licences appear under the generic "My licences / permits"

Example

An MDA wants applicants to reserve a business name before registering. Name reservation is useful to several registries, so it exists as a reusable capability. The MDA switches it on for its service and configures the rest. If the same MDA also needed a register of its own inspectors' equipment, used by nobody else, that would be a module, with its own tables and screens under Ministry functions, switched on only for that MDA.

Check your understanding

  • What is the default state of a module, and who switches it on?
  • What does every route of a disabled module answer?
  • What is the money rule, and why does it exist?
  • What should you do if a module needs a hook core does not offer?
  • Give two examples of reusable capabilities and say why they are not modules.

Sign in to record your progress.

Previous: Federation: one portal, many back offices Next: Security, evidence and environments