Skip to main content

RFC-0012 — Package tier clarity (extends RFC-0011 Decision D)

Tier: Public
Status: Accepted 2026-06-08 (solo-author; amends RFC-0011 Decision D and RFC-0002 contracts/SDK paths)
Audience: contributors, evaluators, module developers onboarding to the monorepo tree.
Document role: replaces ambiguous packages/sdk/ with four peer tiers whose folder names match governance vocabulary (platform, sdk, canonical, verticals).

Disclaimer. This RFC changes on-disk package paths and semver baseline for the MIT SDK batch. It does not rename npm package names (@umbraculum/pim-contracts, @umbraculum/module-sdk, …), change web URLs, or move services/api/src/modules/<code>/.

Companion: docs/NAVIGATE-MONOREPO.md (onboarding map + worked example).


1. Summary

Three decisions:

  • Decision A — Four peer package tiers. Under packages/, only these top-level folders hold npm workspaces: platform/, sdk/, canonical/, verticals/. Delete packages/modules/.

  • Decision B — Symmetric domain nesting. Canonical and vertical domain packages use <tier>/<code>/<artifact>/ (same shape as verticals/brewery/contracts/). Canonical contracts live at packages/canonical/<code>/contracts/@umbraculum/<code>-contracts. SDK packages live at packages/sdk/<name>/.

  • Decision C — npm names unchanged; semver bump. Tier is visible in paths, not npm names (Magento parallel: Magento_Catalog, not Magento_Canonical_Catalog). MIT publish batch at 0.2.0 on npm (tier-move; registry cannot accept downward publish from prior 0.1.1 / 0.0.2). Updated repository.directory fields. No re-export shims from old paths.

Amendments:

Prior RFCWhat changes
RFC-0011 Decision Dpackages/modules/*packages/sdk/* + packages/canonical/*/*
RFC-0002 Decision AContracts slice: packages/canonical/<code>/contracts/ (canonical) or packages/verticals/<code>/contracts/ (vertical)
RFC-0002 Decision CSDK path: packages/sdk/module-sdk/

Explicit non-goals:

  • No rename of services/api/src/modules/ (all registered domains remain peer API slices).
  • No change to (code)/ web route groups or URLs.
  • No npm scope or package name renames (@umbraculum/pim-contracts stays).

2. Motivation

RFC-0011 Wave 3a grouped packages into platform/, modules/, and verticals/. verticals/ read correctly; modules/ did not. It mixed:

  • canonical module contracts (pim-contracts, …),
  • plug-in registration SDK (module-sdk, ai-tool-sdk, i18n-keys),

while docs and E2E already used canonical as a governance term (e2e/canonical/, docs/modules/canonical/).

Three meanings of "module" collided:

Location"Module" meant
services/api/src/modules/Any registered domain (PIM, brewery, …)
packages/sdk/Canonical contracts + SDK
Docs "canonical module"Reserved-code governance tier

Integrators familiar with Magento expect vendor separation: vendor/magento/framework, vendor/magento/module-catalog, extension vendor, merchant code — not a folder named modules that hides the SDK.


3. Decision A — Target tree (commit)

packages/
platform/ # industry-agnostic horizontal libs
ui/
contracts/ @umbraculum/contracts
api-client/


sdk/ # plug-in registration spine (MIT)
module-sdk/ @umbraculum/module-sdk
ai-tool-sdk/
i18n-keys/

canonical/ # reserved-domain modules (contracts slice today)
pim/
contracts/ @umbraculum/pim-contracts
mrp/
contracts/
crp/
contracts/
automation/
contracts/

verticals/ # reference + pattern for ISV verticals
brewery/
contracts/
core/
recipes-ui/

Root workspace globs:

"packages/platform/*",
"packages/sdk/*",
"packages/canonical/*/*",
"packages/verticals/*/*"

4. Decision B — Magento mapping (commit)

Magento 2Umbraculum tierPath
vendor/magento/frameworkPlatformpackages/platform/*
vendor/magento/module-catalogCanonical modulepackages/canonical/pim/contracts/ + β API/web/native slices
Extension registration / module.xml contractSDKpackages/sdk/module-sdk/
Magento_SampleData* / vendor/amasty/*Reference verticalpackages/verticals/brewery/*
app/code/Vendor/ModuleIntegrator verticalYour repo — same β shape

See BUILDING-YOUR-VERTICAL.md §1 for the full parallel table.


5. Decision C — npm and semver (commit)

ArtifactPathnpm name
Platform contractspackages/platform/contracts/@umbraculum/contracts
Registration SDKpackages/sdk/module-sdk/@umbraculum/module-sdk
PIM contractspackages/canonical/pim/contracts/@umbraculum/pim-contracts
Brewery contractspackages/verticals/brewery/contracts/@umbraculum/brewery-contracts

MIT publish batch (ai-tool-sdk, i18n-keys, module-sdk, four *-contracts) ships at 0.2.0 on npm (RFC-0012 tier-move release; registry already had 0.1.1 / 0.0.2 — npm cannot publish downward). Monorepo package.json versions match. No backward-compat path shims.

Rejected: @umbraculum/canonical-pim-contracts — tier belongs in the path; npm keeps domain-first names.


6. Future extension (document only)

When a canonical module needs packages beyond contracts:

packages/canonical/pim/
contracts/
ui/ # future — same pattern as verticals/brewery/recipes-ui/

Workspace glob packages/canonical/*/* supports this without another tier rename.


7. Resolution

Change procedure: same as RFC-0011 §11 and LICENSING.md §10.

Implementation: single coordinated PR — git mv, workspace globs, eslint pkg-sdk + pkg-canonical, docker bind mounts, docs sweep, semver 0.1.0.