Start here

Module boundaries and portability

Separate module-owned behavior from host-owned composition and lifecycle policy.

The easiest way to keep a module reusable is to separate domain ownership from application policy. A module defines what it can do. The host decides where and how those capabilities run.

What a module owns

In Damat, a module owns:

  • its models, migrations, service, and credential schema;
  • optional routes, workflows, jobs, events, pipelines, and tests;
  • provider implementation details when it supports a provider role.

The module is portable because it exports stable capabilities instead of global app logic.

module/
├── damat.json
├── src/
│   ├── index.ts
│   ├── service.ts
│   ├── models/
│   ├── workflows/
│   ├── routes/
│   ├── jobs/
│   ├── events/
│   ├── pipelines/
│   └── migrations/

What the application owns

The host app decides:

  • module registration and the IDs used by getModule;
  • links between modules;
  • provider-role bindings;
  • queues, worker selection, concurrency, retention, Redis policy, and deployment;
  • authentication and authorization for operational tools.

This is why installers never edit shared app policy files automatically: they preserve host-level control.

A quick placement test

If code needs another module's table or chooses which workers run, it does not belong inside a portable module. Put cross-module data relationships in app-owned links and runtime choices in damat.config.ts.