Spine Architecture Sketch
1-min readUpdated May 11, 2026
Copied Raw Markdown!
This project should grow like a spine with replaceable vertebrae, not a hub with random spokes.
Problem URL copied
Today one center pipeline is starting to absorb too much:
- Apigee parsing rules
- semantic mapping rules
- Mule app rendering
- Flex GitOps rendering
- custom policy bundle rendering
- validation and packaging
If all new behavior lands in one center, pipeline.py and execute.py become god-objects.
Target Shape URL copied
flowchart LR
A["Source Reader"] --> B["Normalizer"]
B --> C["Migration Plan"]
C --> D["Renderer: Mule App"]
C --> E["Renderer: Mule Custom Policy"]
C --> F["Renderer: Flex GitOps"]
D --> G["Target Validator"]
E --> H["Package Builder"]
F --> I["GitOps Validator"]
Contract URL copied
ingestreads source files and produces source facts only.normalizeturns source facts into one neutral model.plandecides intent, grouping, and migration relationships.- each
rendererowns one target family and its file structure. - each target gets its own validation and packaging path.
Interface Consequence URL copied
User interface stays small because internals are separated:
migrate <source> --target mule-app
migrate <source> --target mule-custom-policy
migrate <source> --target flex-gitops
The CLI chooses one renderer. The renderer decides folders, files, and validators for that target.
Guard Rails URL copied
- no target-specific file writing inside shared planner stages
- no Flex YAML rules inside Mule app renderer
- no custom policy packaging logic inside generic execute path
- shared stages return data, not files
Litmus test
If adding a new target mostly means adding one renderer and one validator, shape is healthy.