Customizing engine (contract + capture)
Two steps toward the SDK Customizing surface (sdk-customizing-v0.9.md): the code-owned reference-catalog projection that lifts vocabularies like partner roles out of host seed migrations onto ui5:sync, plus a layering cleanup of the sync workers.
Added
Customizing\Contracts\CustomizingEntry— the meta-interface a Customizing attribute class fulfils (e.g. a host's#[PartnerRole]): the static catalog shape (catalog()/table()/identityColumn()/translatable()) split from the per-row data (identity()/columns()). Codes areBackedEnum|string;identity()dissolves an enum to its scalar->value. This interface is the one frozen seam of the Customizing surface. Consumers ship their own attributes against it.SdkRegistry::customizing()+ theregisterCustomizing()capture pass inafterLoad()Pass 1. A single reflection sweep (ReflectionAttribute::IS_INSTANCEOF) discovers everyCustomizingEntryattribute declared across modules, grouped by physical table (descriptor + rows), with a hard duplicate-identity guard. Sync-time data likeroles()/abilities()— intentionally not exported to the registry cache.Customizing\CustomizingWorker— the generic flat projection of every declared catalog. For each table it reconciles the DB to the complete declared set (insert / update-if-dirty / delete-absent), keyed on the catalog's identity column, column-agnostic, via the query builder (no per-catalog model); it stampscreated_at/updated_atonly when the table carries them. Wired intoSyncServiceafterRolesWorker(FK-independent). Inherits the pipeline's one-transaction / dry-run / fail-loud contract; a delete blocked by anON DELETE RESTRICTfrom a configuration table bubbles loud rather than being swallowed.
Changed
- Sync workers relocated into the domains they project.
ArtifactsWorker,AbilitiesWorker,RolesWorkermovedSync\Workers\→Security\;SettingsWorker→Settings\. The worker now lives with the model/table it writes, reversing the oldSync → domain-modeldependency.Sync\keeps only the orchestration (SyncService,SyncPipeline, the contexts,SyncWorkerInterface);SyncServicestill wires the hardcoded worker list in FK order — no registration seam added, so the Sync spec's D2 holds. (Internal relocation: the four worker classes are@internal; no public contract changed. In-house consumers only.)