Skip to the content.

Sub-Prism Inheritance

Overview

Every prism can contain a hierarchy of sub-prisms declared under bundled_prisms. Each sub-prism is a YAML config file that contributes settings to the final merged configuration. Like a prism refracting white light into a spectrum, this system refracts organizational complexity into layered, composable configurations.

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#eef2ff', 'primaryTextColor': '#1e293b', 'primaryBorderColor': '#6366f1', 'lineColor': '#6366f1', 'secondaryColor': '#f0fdf4', 'tertiaryColor': '#faf5ff', 'background': '#ffffff', 'mainBkg': '#eef2ff', 'nodeBorder': '#6366f1', 'clusterBkg': '#f8faff', 'edgeLabelBackground': '#ffffff'}}}%%

flowchart TD
    P["💎 fortune500.prism"]

    subgraph required["Required — applied to everyone"]
        B["base\nEnterprise standards\nproxy · security · git"]
    end

    subgraph optional["Optional — user selects one per tier"]
        D1["divisions / technology"]
        D2["divisions / digital"]
        D3["divisions / data"]
        R1["roles / software-engineer"]
        R2["roles / devops-engineer"]
        R3["roles / data-engineer"]
    end

    subgraph result["Merged Result"]
        M["merged-config.yaml\ntools_required · environment\nrepositories · security"]
    end

    P --> required
    P --> optional
    required --> result
    D1 --> result
    R2 --> result

    style required fill:#f0fdf4,stroke:#22c55e,color:#1e293b
    style optional fill:#eef2ff,stroke:#6366f1,color:#1e293b
    style result fill:#faf5ff,stroke:#a855f7,color:#1e293b
    style P fill:#fff7ed,stroke:#f97316,color:#1e293b
    style B fill:#dcfce7,stroke:#22c55e,color:#1e293b
    style M fill:#f3e8ff,stroke:#a855f7,color:#1e293b

Each layer inherits and extends from previous layers:


How Sub-Prism Merging Works

When you install a prism, the engine:

  1. Loads all required sub-prisms automatically (the base tier)
  2. Applies any user-selected sub-prisms from optional tiers
  3. Deep-merges them in declaration order using ConfigMerger
  4. Writes the merged result to config/merged-config.yaml

The merged config drives everything: which tools get installed, which repos get cloned, which proxy settings apply.

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#eef2ff', 'primaryTextColor': '#1e293b', 'primaryBorderColor': '#6366f1', 'lineColor': '#6366f1', 'secondaryColor': '#f0fdf4', 'tertiaryColor': '#faf5ff', 'background': '#ffffff', 'mainBkg': '#eef2ff', 'nodeBorder': '#6366f1', 'edgeLabelBackground': '#ffffff'}}}%%

sequenceDiagram
    participant E as InstallationEngine
    participant B as base/company.yaml
    participant D as divisions/technology.yaml
    participant R as roles/devops-engineer.yaml
    participant M as merged-config.yaml

    E->>B: load (required)
    B-->>E: tools=[git,docker] env={proxy}
    E->>D: load (user selected)
    D-->>E: tools=[vscode,kubectl] stack={...}
    E->>R: load (user selected)
    R-->>E: tools=[terraform,ansible]
    Note over E: union merge tools_required
    Note over E: deep_merge environment
    E->>M: write final merged config
    M-->>E: git·docker·vscode·kubectl·terraform·ansible

Merge Strategies

Controlled by config/inheritance.yaml (or the built-in defaults):

Arrays (lists):

merge_strategy:
  arrays:
    tools_required: "union"     # Combine, remove duplicates
    resources: "append"         # Keep all, in order
    onboarding_tasks: "append"

Objects (dicts):

merge_strategy:
  objects:
    environment: "deep_merge"   # Recursively merge
    git: "override"             # Later layer wins
    career: "user_only"         # Only the user can set this

Example — union merge:

# Base sub-prism
tools_required: [git, docker, kubectl]

# Role sub-prism
tools_required: [terraform, helm]

# Merged result:
tools_required: [git, docker, kubectl, terraform, helm]

Example — deep_merge:

# Base
environment:
  proxy:
    http: "http://proxy.company.com:8080"
  maven:
    url: "https://maven.company.com"

# Division
environment:
  npm:
    registry: "https://npm.company.com"

# Merged:
environment:
  proxy:
    http: "http://proxy.company.com:8080"
  maven:
    url: "https://maven.company.com"
  npm:
    registry: "https://npm.company.com"

Real-World Example

Scenario: New Developer at Fortune 500

Selected sub-prisms:

Merged result:

# From base:
environment:
  proxy:
    http: "http://proxy.company.com:8080"
  vpn:
    required: true

tools_required:
  - git
  - docker
  - kubectl
  - python3

security:
  sso_required: true
  mfa_required: true

# From Technology Division:
tools_required:
  - vscode
  - docker
  - kubectl

tech_stack:
  languages: [Python, TypeScript, Java]
  platforms: [Kubernetes, AWS, GCP]

# From DevOps Engineer:
tools_required:
  - terraform
  - ansible
  - kubectl
  - docker
  - git

Final merged tools_required (union): git, docker, kubectl, python3, vscode, terraform, ansible


Defining Sub-Prisms in bundled_prisms

bundled_prisms:
  # Required tier — applied to every user
  base:
    - id: "company-base"
      name: "Company Base"
      description: "Company-wide settings: proxy, git, required tools"
      required: true              # ← always included
      config: "base/company.yaml"

  # Optional tier — user picks one
  divisions:
    - id: "technology"
      name: "Technology Division"
      description: "IT and software engineering"
      config: "divisions/technology.yaml"

    - id: "digital"
      name: "Digital Division"
      description: "Digital products and platforms"
      config: "divisions/digital.yaml"

  # Optional tier — user picks one
  roles:
    - id: "software-engineer"
      name: "Software Engineer"
      config: "roles/software-engineer.yaml"

    - id: "devops-engineer"
      name: "DevOps Engineer"
      config: "roles/devops-engineer.yaml"

Sub-Prism Config File Structure

Each sub-prism is a plain YAML file. Any keys it contains are merged into the final config. Tools are referenced by string name only — they must exist in the centralized tool-registry.yaml:

# base/company.yaml
company:
  name: "My Company"
  domain: "mycompany.com"

environment:
  proxy:
    http: "http://proxy.mycompany.com:8080"
  vpn:
    required: true

tools_required:
  - git
  - docker
  - kubectl

security:
  sso_required: true
# divisions/technology.yaml
division:
  id: "technology"
  name: "Technology Division"

tools_required:
  - vscode
  - kubernetes

tech_stack:
  languages: [Python, TypeScript]
# roles/devops-engineer.yaml
role:
  id: "devops-engineer"
  name: "DevOps Engineer"

tools_required:
  - terraform
  - ansible
  - helm

Environment Variable Substitution

Use ${VAR} and ${VAR:-default} placeholders in sub-prism configs:

git:
  user:
    name: "${USER}"
    email: "${USER}@mycompany.com"

cloud:
  region: "${CLOUD_REGION:-us-central1}"

These are resolved at install time by the engine.


Python API

from scripts.config_merger import load_merged_config

config = load_merged_config(
    company="config/base/company.yaml",
    sub_org="config/orgs/engineering.yaml",
    department="config/departments/supply-chain.yaml",
    team="config/teams/receiving-systems.yaml",
    user="config/user-profile.yaml"
)

proxy = config["environment"]["proxy"]["http"]
tools = config["tools_required"]
repos = config.get("repositories", [])

Benefits

DRY — define company standards once, inherit everywhere ✅ Flexible — each layer can override or extend ✅ Scalable — add new teams without duplicating config ✅ Maintainable — update the base once, all users get the change ✅ Contextual — each developer gets exactly what their role needs