SPLENT overview
SPLENT is built in layers. A product line describes what can be combined, features are the pieces, a product is one combination, the framework assembles it, containers run it and releases ship it. Every file and every command belongs to one layer, so knowing the layers tells you where a change goes and what it touches.
The layers
| Layer | What it is | Where it lives |
|---|---|---|
| Product line | The UVL model, its features and their constraints | splent_spl_<name>/, published on UVLHub |
| Features | Versioned Python packages, one capability each | splent_feature_<name>/ |
| Product | One configuration of the line, with the versions it pins | <product>/ |
| Framework | The runtime that builds the app from the product’s features | splent_framework |
| Infrastructure | The containers the product runs in, in development and in production | <product>/docker/, <product>/deploy/ |
| Delivery | Releases, the stable channel and the servers that follow it |
the forge, PyPI, image registries |
Two things span all six. The workspace and the CLI are where you work on every layer, and the ecosystem is where the layers are published and found.
How they relate
- The line names the features. Each feature of the UVL model points at a package. The model’s constraints decide which features need which, and so the order they load and migrate in.
- Features extend each other through contracts. A feature declares the hooks, services and models others may extend, and nothing else crosses from one feature to another. The contracts are checked before anything runs.
- A product is a configuration. It selects features from the line and pins a version of each, and of the model. The selection is checked against the model before it is applied.
- The framework assembles the product at boot. It reads the product’s selection, loads each feature in the model’s order and wires its routes, models, templates and extensions into one Flask app.
- The same app runs in two kinds of containers. In development the features are your checkouts and the cache’s snapshots. In production they are the pinned releases, installed in an image.
- A release ships a layer. A feature release publishes its package, a product release its image, and a server that follows the
stablechannel deploys it.
Where a change goes
| You want to | Layer | Start with |
|---|---|---|
| Allow or forbid a combination of features | Product line | Edit the model, then spl:publish |
| Add a capability several products can use | Features | feature:create |
| Change what another feature does | Features | feature:refine |
| Choose the features of one product | Product | product:configure |
| Change a setting of one product | Product | [tool.splent.config], then product:env |
| Run the product on your machine | Infrastructure | product:derive --dev |
| Put it in production | Delivery | product:release |
Development and production
The layers are the same in both. What changes is where the features come from and how the product runs.
| Development | Production | |
|---|---|---|
| Features | Editable checkouts at the workspace root, pinned snapshots from the cache | Pinned releases, installed from PyPI or their tag |
| Product | The same pyproject.toml |
The same pyproject.toml |
| Framework | Flask’s development server | gunicorn, inside the image |
| Infrastructure | The dev stack, with each feature’s own services | The deploy bundle deploy/ and the image |
| Delivery | Nothing leaves your machine | A release, and servers that follow stable |