Core Concepts
Vendor Namespace Rules
The vendor namespace keeps extension code separate from core MyronCMS behavior. The same vendor identity appears in package directories, manifests, action URIs, action domains, MIC resolver types, mail transport IDs, migrations, and admin route mounts.
Human Path
Choose one snake_case vendor:
my_vendor
Use it consistently:
| Surface | Shape |
|---|---|
| Local package | app/extensions/my_vendor/ |
| Manifest vendor | "vendor": "my_vendor" |
| Action URI | /api/v1/x/my_vendor/hello |
| Action domain | x.my_vendor.hello |
| MIC type | x.my_vendor.catalog |
| MIC token | [mic-x.my_vendor.catalog-mic_0123456789abcdef] |
| Mail transport | x.my_vendor.resend |
| Migration table | my_vendor_pings |
| Admin route mount | /x/my_vendor/hello |
AI Path
An AI coding agent can apply these rules while authoring files locally. It should use the same vendor across manifest.json, PHP class metadata, migration table names, and any descriptors returned by resolvers or transports.
An installed MCP client only sees loaded runtime tools and resources. It should treat tool names, action metadata, and MCP resources as discovery outputs, not as permission to create new namespaces in PHP.
Vendor and Directory Rules
Manifest vendors must match:
^[a-z][a-z0-9_]*$
The loader scans app/extensions/*/manifest.json. It normalizes hyphens in the directory name to underscores before parsing the manifest:
| Directory | Expected manifest vendor |
|---|---|
my_vendor | my_vendor |
my-vendor | my_vendor |
If the manifest vendor does not match the normalized directory vendor, parsing fails.
Action Namespace
Extension actions are registered through ActionRegistry::registerExtension(). It rejects actions unless:
- the URI starts with
/api/v1/x/{vendor}/, - the domain starts with
x.{vendor}., inputSchemais not an empty array,outputSchemais not an empty array.
Valid:
uri: '/api/v1/x/my_vendor/hello',
domain: 'x.my_vendor.hello',
Invalid:
uri: '/api/v1/content/pages',
domain: 'content.pages',
Core action domains and core API paths are not extension territory.
MIC Namespace
Extension MIC resolvers are registered with:
myronMicElementRegistry()->registerExtension($vendor, 'catalog', $resolver);
The local slug passed to registerExtension() is catalog, not x.my_vendor.catalog. The registry constructs the fully qualified slug:
x.my_vendor.catalog
The resolver descriptor must then report the same fully qualified slug:
'slug' => 'x.my_vendor.catalog',
The rich-text token shape is:
[mic-x.my_vendor.catalog-mic_0123456789abcdef]
Passing a fully qualified x.* slug as the local registration slug is rejected.
Mail Transport Namespace
Extension mail transports are registered with a snake_case vendor and snake_case slug:
myronMailTransportRegistry()->registerExtension('my_vendor', 'resend', $transport);
The registered transport ID is:
x.my_vendor.resend
The transport descriptor should use the same fully qualified slug.
Admin Route Namespace
Admin route declarations live in manifest.json:
{
"key": "sample-hello",
"path": "admin/routes/hello.php"
}
The loader mounts extension admin routes under:
/x/{vendor}/{tail}
Admin route files are isolated extension surfaces. They do not inject new core rail sections.
Safety Boundary
Do not use namespace rules to reach into core behavior. Extension v1 does not support public render hooks, core action overrides, design token group registration, snapshot contribution, or core admin rail injection.
Verification
Run:
php app/tests/verify-extension-system-foundation.php
The test verifies valid action registration, invalid URI/domain/schema rejection, sample admin route mounting, and migration table-prefix isolation.
Failure Modes
| Failure | Enforcement point |
|---|---|
| Vendor is not snake_case | Manifest, action, MIC, mail, or migration registration. |
| Directory and manifest vendor do not match | Manifest parsing. |
Action URI does not start with /api/v1/x/{vendor}/ | Action registry. |
Action domain does not start with x.{vendor}. | Action registry. |
MIC local slug starts with x. | MIC registry. |
| MIC descriptor slug differs from registered slug | MIC registry. |
| Mail vendor or slug is not snake_case | Mail transport registry. |
Migration touches a non-{vendor}_* table | Migration runner. |