From 100e1f996e364884fe04296f7fabee74ae916fda Mon Sep 17 00:00:00 2001 From: Scot Wells Date: Sun, 1 Mar 2026 12:14:08 -0600 Subject: [PATCH 1/2] feat(c4-diagrams): add multi-boundary layout patterns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add documentation for creating clean, readable C4 diagrams with multiple system boundaries (e.g., cross-control-plane architectures). New patterns documented: - Side-by-side boundary placement using Rel_L/Rel_R - Grid structure within boundaries (2x2 layout) - Relationship direction guidelines for different scenarios - Data flow alignment (left-to-right: entry → processing → execution) - Complete cross-control-plane example These patterns emerged from designing the Functions service control plane architecture diagram and help avoid overlapping lines and cluttered layouts. Co-Authored-By: Claude Opus 4.5 --- .../skills/c4-diagrams/SKILL.md | 126 ++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/plugins/datum-platform/skills/c4-diagrams/SKILL.md b/plugins/datum-platform/skills/c4-diagrams/SKILL.md index 991c2e0..aa7cf54 100644 --- a/plugins/datum-platform/skills/c4-diagrams/SKILL.md +++ b/plugins/datum-platform/skills/c4-diagrams/SKILL.md @@ -185,6 +185,132 @@ Layout macros: | `LAYOUT_WITH_LEGEND()` | Add legend to diagram | | `LAYOUT_AS_SKETCH()` | Hand-drawn style | +## Multi-Boundary Layout Patterns + +When creating diagrams with multiple system boundaries (e.g., cross-control-plane +architectures), use these patterns for clean, readable layouts. + +### Side-by-Side Boundaries + +Place related boundaries horizontally using `Rel_L` / `Rel_R` for cross-boundary +relationships: + +```plantuml +@startuml +!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml + +LAYOUT_WITH_LEGEND() + +System_Boundary(consumer, "Consumer Control Plane") { + Container(function, "Function", "CRD", "User-facing resource") + Container(endpoint, "ServiceEndpoint", "Service Connect", "Private IP") +} + +System_Boundary(provider, "Service Control Plane") { + Container(controller, "Controller", "Go", "Watches resources") + Container(publication, "ServicePublication", "Service Connect", "Exposes service") +} + +' Cross-boundary: use Rel_L to connect right boundary to left +Rel_L(controller, function, "Watches", "direct API") +Rel_L(publication, endpoint, "Connected via", "Service Connect") + +@enduml +``` + +### Grid Structure Within Boundaries + +Arrange elements in a 2x2 grid using mixed directions: + +``` +TopLeft ──Rel_R──→ TopRight + │ │ + Rel_D Rel_D + ↓ ↓ +BottomLeft ←─Rel_L── BottomRight +``` + +Example: + +```plantuml +' Within a boundary, create grid with mixed directions +Rel_R(httproute, function, "References", "backendRef") ' top row horizontal +Rel_U(gateway, httproute, "Attaches", "parentRef") ' left column vertical +Rel_D(function, endpoint, "Resolves to", "status.endpoint") ' right column vertical +``` + +### Relationship Direction Guidelines + +| Relationship Type | Direction | Rationale | +|-------------------|-----------|-----------| +| Cross-boundary | `Rel_L` / `Rel_R` | Creates side-by-side boundary layout | +| Within-boundary horizontal | `Rel_R` | Maintains left-to-right data flow | +| Within-boundary vertical | `Rel_D` / `Rel_U` | Creates grid rows within boundary | +| Reverse flow (e.g., load balancing) | `Rel_L` | Shows return path or reverse relationship | + +### Data Flow Alignment + +Arrange elements by data flow direction (left-to-right): + +| Position | Element Types | +|----------|---------------| +| Left | Entry points (Gateway, API endpoints) | +| Middle | Processing/routing (Controllers, Functions) | +| Right | Execution/storage (Instances, Databases) | + +### Complete Example: Cross-Control-Plane Architecture + +```plantuml +@startuml +!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml + +LAYOUT_WITH_LEGEND() +title Cross-Control-Plane Architecture + +System_Boundary(consumer, "Consumer Control Plane") { + Container(httproute, "HTTPRoute", "Gateway API", "Routes traffic") + Container(function, "Function", "CRD", "User-facing resource") + Container(gateway, "Gateway", "Gateway API", "Accepts traffic") + Container(endpoint, "ServiceEndpoint", "Service Connect", "Private IP") +} + +System_Boundary(provider, "Service Control Plane") { + Container(controller, "Controller", "Go", "Reconciles resources") + Container(workload, "Workload", "CRD", "Manages instances") + Container(publication, "ServicePublication", "Service Connect", "Exposes workload") + Container(instance, "Instance", "Runtime", "Execution environment") +} + +' Consumer internal: grid layout +Rel_U(gateway, httproute, "Attaches", "parentRef") +Rel_R(httproute, function, "References", "backendRef") +Rel_D(function, endpoint, "Resolves to", "status.endpoint") + +' Provider internal: grid layout +Rel_R(controller, workload, "Generates", "owner ref") +Rel_D(controller, publication, "Creates") +Rel_D(workload, instance, "Manages", "scale 0-N") +Rel_L(publication, workload, "Load balances to") + +' Cross-boundary: horizontal connections +Rel_L(controller, function, "Watches & updates", "direct API") +Rel_L(publication, endpoint, "Connected via", "Service Connect") + +@enduml +``` + +### Tips for Clean Multi-Boundary Layouts + +1. **Consistent boundary placement** — Keep related boundaries at same level + (side-by-side or stacked) +2. **Align cross-boundary connections** — Connect elements at similar vertical + positions +3. **Use grids within boundaries** — 2x2 or 2x3 grids keep elements organized +4. **Minimize line crossings** — Adjust directions to avoid overlapping + relationship lines +5. **Group by function** — Entry points together, processing together, execution + together + ## Styling Customize colors and appearance: From 0827d6755f4928e1b1d6f5dd3f8cf0a3b7d8749c Mon Sep 17 00:00:00 2001 From: Scot Wells Date: Sun, 1 Mar 2026 12:38:29 -0600 Subject: [PATCH 2/2] docs(c4-diagrams): add guidance on internal vs external elements Add documentation for when to use Container vs Container_Ext (and other _Ext variants) based on ownership: - Internal: elements your team owns and maintains - External: elements owned by other teams or external services Key pattern: "Resource you create, other service processes" should be Container_Ext since the other team owns the controller that processes it. Includes: - Ownership rule explanation - Common patterns table with rationale - Functions service example - Context vs Container diagram guidance Co-Authored-By: Claude Opus 4.5 --- .../skills/c4-diagrams/SKILL.md | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/plugins/datum-platform/skills/c4-diagrams/SKILL.md b/plugins/datum-platform/skills/c4-diagrams/SKILL.md index aa7cf54..91ffbef 100644 --- a/plugins/datum-platform/skills/c4-diagrams/SKILL.md +++ b/plugins/datum-platform/skills/c4-diagrams/SKILL.md @@ -143,6 +143,55 @@ Rel(handler, storage, "Uses") | `ComponentDb(alias, label, technology, description)` | Database component | | `ComponentQueue(alias, label, technology, description)` | Queue component | +### Internal vs External Elements + +Use `_Ext` variants to distinguish elements your service owns from those it interacts with. + +**Ownership Rule**: Use internal (`Container`, `System`) for elements your team owns and +maintains. Use external (`Container_Ext`, `System_Ext`) for elements owned by other teams +or external services. + +| Element Type | Internal (you own) | External (others own) | +|--------------|-------------------|----------------------| +| System | `System()` | `System_Ext()` | +| Container | `Container()` | `Container_Ext()` | +| Component | `Component()` | `Component_Ext()` | +| Database | `ContainerDb()` | `ContainerDb_Ext()` | + +**Common patterns:** + +| Scenario | Classification | Rationale | +|----------|---------------|-----------| +| CRD your service defines | `Container` | You own the resource definition | +| Controller your service runs | `Container` | You own the code | +| Resource you create, other service processes | `Container_Ext` | Other team owns the controller | +| Platform service (Gateway, Workload) | `Container_Ext` | Other team owns | +| Consumer's application | `Container_Ext` | Consumer owns | +| External SaaS (GitHub, Stripe) | `System_Ext` | Truly external | + +**Example: Functions service perspective** + +```plantuml +' Internal - Functions owns these +Container(function, "Function", "CRD", "We define this resource") +Container(controller, "Function Controller", "Go", "We own this code") + +' External - we create but others process +Container_Ext(workload, "Workload", "CRD", "We create, Workload team processes") +Container_Ext(service_pub, "ServicePublication", "Service Connect", "We create, Service Connect processes") + +' External - other teams own entirely +Container_Ext(gateway, "Gateway", "Gateway API", "Networking team owns") +Container_Ext(instance, "Instance", "Unikraft", "Workload controller creates") +``` + +**Context vs Container diagrams:** + +- **Context (Level 1)**: Use `System` for other services in your organization, + `System_Ext` for truly external services (SaaS, third-party APIs) +- **Container (Level 2)**: Use `Container_Ext` for any container not owned by your team, + even if it's within your organization + ### Relationships | Macro | Description |