Skip to main content
Amends, by Notes, 0109 (the registry records products and editions), 0296 (the root runway’s product section) and 0326 (a brands list beside identity). Reads with the notes of 2026-10-24 on 0201 and rule 22 of 0334.

Context

The owner decided on 2026-10-24, in the Muslin rethink, that commerce is a product of its own above Figentra OS, and that Muslin is its fashion edition: the same commerce engine, with fashion packs, a brand and a plan ladder of its own. Other verticals follow as other editions. Nothing in the ADRs says what an edition is, where it is declared, how the registry lists it, how runway deploys it, or how its apps are built and branded. Without a rule, each edition would become a fork of its base product, which is the thing the module model exists to prevent (0259, 0200).

Decision

  1. An edition is a product. An edition is a first-party product (layer 3 of 0201) that is made of another product’s modules, called its base, plus its own packs, its brand and its entitlement bundle. It has its own repository, its own app members and its own plan ladder. Muslin is an edition of Figentra Commerce (working name); Figentra Commerce is a product above Figentra OS and is not an edition. It is built in its own repository from its design records; the thin commerce reference slice planned for this repository stays a reference app under 0075 decision 2, proves the framework, and seeds no product.
  2. Declared once, in the root runway. The edition’s root runway.yaml declares a product section: product: { key, edition: { of: <base product key>, version: <range> } }. A product with no edition is a base product. The key is the product’s registry key, and the base’s version range names the released base manifests the edition builds against. This is the one place the relation is written; nothing in code repeats it.
  3. The base is consumed as released packages and clients, never as a fork. An edition imports the base product’s modules the way Figentra OS imports Stackra packages (0200 decision 2): released versions from the registry, a local link only in a development profile and never in CI. It calls the base’s services through the generated clients and listens to the base’s integration events. It never copies a base module into its own tree.
  4. Packs are ordinary modules. An edition’s own features are modules in one of the three homes of 0259: the edition’s service, or an edition package when two of its members share them. A pack that extends a base model or a base screen does it through 0336, never by editing the base.
  5. The registry lists editions. The registry of 0109 records a product’s manifests under its key and, for an edition, the base key and version range. The marketplace lists an edition as an installable product. A tenant installs an edition, not a base plus packs: the base’s modules that the edition bundles install with it.
  6. The entitlement bundle is one plan ladder. An edition has its own plan ladder in the form of 0242, and each tier’s effective set (0215) bundles the module entitlements of the base that the edition sells with its own. A tenant on an edition plan never buys the base separately, and a base entitlement the edition does not bundle is not available to that tenant.
  7. One brand per edition, per-tenant branding at run time. The edition’s brand (tokens overlay, name, lang catalogue, store listing text) is build-time data of its app members, written once in the identity section of 0326. Within an edition, a tenant’s own branding is run-time data through the experience service (receipts, lock screens, the staff app’s chrome), as the tenant branding rules already allow. An edition therefore has one staff app codebase, published under the edition’s name and branded per tenant at run time.
  8. Per-brand builds come from a brands list. An app member that is built per retailer brand (a white-label shopper app) declares brands: [...] beside identity in stackra.config.ts; each entry carries its own identity (app id, bundle ids, names, store listing) and its brand tokens. Such an app is not our own app, so it uses the free @stackra/ui only (0310 as amended the same day). Gen runs the app build once per brand, from the same codebase, with that brand’s identity in place. Content for a shopper app comes from the page builder (0114) per tenant; the build carries no tenant content.
  9. Shared by every edition of a base. Pricing and Markets, the payments ledger, invoicing, identity, tenancy and the other OS modules stay in the OS and reach an edition through its base, by the placement rule of 0334 rule 22.

Consequences

  • A vertical is an edition, so a new vertical is packs, a brand and a ladder, and never a second commerce engine.
  • The relation to the base is one line in runway, so runway and the registry can check an edition against its base’s released versions, and an upgrade of the base is a version bump in the edition.
  • A white-label app is a brand entry and a build, not a repository.
  • An edition’s tenant sees one product in the marketplace and one plan ladder, and never a bill for the base.

Enforcement

  • planned — runway validator (STA-339): an edition whose base key is unknown to the registry, or whose version range matches no released base manifest, fails; a product key that collides with another product fails.
  • planned — gen (STA-340): a brands entry without a complete identity fails, and two brands with the same app id fail; an edition member that imports a base module from source rather than a released package fails the boundary check.
  • planned — the registry refuses an edition manifest whose bundled module entitlements are not entitlements of its base.

Supersedes and sources

Supersedes: none. Amends, by Notes: 0109, 0296 and 0326. Builds on 0200, 0201, 0215, 0242, 0259 and 0334. Sources: the owner’s Muslin rethink decisions of 2026-10-24 (STA-451), restated in this ADR’s own words.