Search by

uhifadhi / seam-module

The seam: the module seam runtime every uhifadhi module registers with — the catalogue, per-area installation, the permission declarations modules contribute, and the seed that keeps them in step.

Maintainers

Package info

github.com/uhifadhilabs/seam-module

Type:symfony-bundle

pkg:composer/uhifadhi/seam-module

Transparency log

Statistics

Installs: 185

Dependents: 5

Suggesters: 2

Stars: 0

Open Issues: 0

v0.2.1 2026-09-05 13:28 UTC

This package is auto-updated.

Last update: 2026-09-05 14:01:51 UTC


README

The seam: the module seam runtime every uhifadhi module registers with. A uhifadhi platform module.

What it is

Uhifadhi is one skeleton and a set of modules. uhifadhi/uhifadhi is the project skeleton — copied once, never updated; everything else arrives as a module, updated forever. A module registers with the seam (uhifadhi/seam-module — this repository) and renders in the shell (uhifadhi/shell-module); everything a deployment can do — patrols, incidents, rosters — is a module.

The seam carries the catalogue, the per-area record of what is switched on, the permissions modules declare, and the seed command that keeps the catalogue in step with what is installed. It renders nothing.

Installation

composer require uhifadhi/seam-module

The bundle registers via Flex ("type": "symfony-bundle"), which adds Uhifadhi\Seam\UhifadhiSeamBundle to config/bundles.php and copies config/packages/seam.yaml in.

An area is required, and a module answers it

The per-area table has a NOT NULL foreign key to an area, so until AreaInterface resolves to a class there is no schema to create. Installing the answer-module states the resolution for you:

composer require uhifadhi/area-module

Your installation writes no doctrine.yaml line at all. You write a resolution line only to disagree — see docs/configuration.md for that, and for why the seam cannot name an area class itself.

Then the tables

bin/console doctrine:database:create
bin/console doctrine:migrations:diff      # your history, your migration
bin/console doctrine:migrations:migrate
bin/console seam:catalogue:seed

The seam ships no migration versions: the tables are the seam's, the migration history is the installation's.

Parking a module closes its routes

Where an area has parked a module, that module's pages answer 404 there — enforced once, in the seam, before any controller runs. Nothing is asked of the module, but a module that says which one it is gets read precisely rather than inferred from its URL. One line per controller:

use Uhifadhi\Seam\UhifadhiSeamBundle;

#[Route(defaults: [UhifadhiSeamBundle::MODULE_ROUTE_DEFAULT => 'your-slug'])]
final class YourModuleController { /* every route below is yours */ }

404 and not 403: parking withholds nothing, it means the area is not running the module. See docs/guarantees.md for the recognition rules, the cost, and what the gate deliberately does not do.

Configuration

# config/packages/seam.yaml (your application)
seam:
    default_category: operations   # where an unplaced module is filed
    dev_tools: false               # dev-only tooling; enable via when@dev / when@test

Both keys have defaults and the tree is closed. There is deliberately no key listing modules — see docs/configuration.md.

Learn more

  • docs/architecture.md — what the seam owns, why zero modules is a working installation, and where each piece lives in src/.
  • docs/boundaries.md — what the seam is not: why the module grid and the customize screen belong to the shell, with the split in a table.
  • docs/guarantees.md — the behaviour table, every row a test, and the attention-list promise behind it.
  • docs/configuration.md — the seam: tree, resolving the area contract, bringing your own area, and whose migration history the tables are.
  • docs/development.md — the standard, tests-first, and the two test kernels.

License

AGPL-3.0-or-later — see LICENSE: the same license as the uhifadhi host this bundle carries. Use, modify and self-host freely; if you offer a modified version to users over a network, they are entitled to the source of what they're running.