Spine Architecture Sketch

Present

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.

ProblemURL 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 ShapeURL 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"]

ContractURL copied

  1. ingest reads source files and produces source facts only.
  2. normalize turns source facts into one neutral model.
  3. plan decides intent, grouping, and migration relationships.
  4. each renderer owns one target family and its file structure.
  5. each target gets its own validation and packaging path.

Interface ConsequenceURL 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 RailsURL 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.