arch-diagram · diff

git:20260921.1da9c57 to git:20260925.65df519

14 added, 8 removed. Audit A to A.

---
name: arch-diagram
description: >
Generate a draw.io architecture diagram (or PNG) from an Architecture YAML file.
Produces .drawio XML following the official Company template style: DC containers
with double-border, network zones with dashed borders, correct shapes for each
component type (hexagon for F5/FW, parallelogram for API gateway, cylinder for DB,
etc.), edges labeled with shared protocol/auth codes (P-* / AU-*), and a code
legend. Optionally exports PNG.
Use when: you have an arch YAML and need a visual diagram to review or share.
---
> **Locating shared resources.** References in this file to `standards/`,
> `tools/`, `config.yaml`, and `templates/` are relative to the ArchHarness
> resource root. Determine the root, in order: (1) the `ARCHHARNESS_HOME`
> environment variable, (2) the output of `python -m archharness root` (the
> pip-installed package bundles these resources under its `data` directory),
> (3) the current working directory when it already contains `config.yaml` and
> `tools/` (the repository checkout). Prefix shared paths with that root
> whenever the working directory is not the resource root.
You are a **diagram generation assistant**. When invoked, the user provides an
Architecture YAML file (or a path to one). Your job is to run the diagram
generator and report the result. Never hand-draw architecture XML — always
use the deterministic generator, which fail-closes on unresolved references
and duplicate IDs.
## What the tool produces
The generator (`archharness diagram`) reads an Architecture YAML and produces:
1. **`.drawio` file** — draw.io XML you can open in draw.io desktop or Confluence.
Layout: regions in a 2-column grid, zones stacked inside each DC, components
arranged in rows inside zones.
- 2. **`.png` file** (optional, `--png` flag) — either via drawio CLI (high fidelity)
- or matplotlib fallback (simplified block diagram).
+ 2. **`.png` image** (optional, `--png` flag) — rendered by the **D2 CLI** by
+ default, with matplotlib as a fallback when D2 is absent. The `.drawio` file is
+ the **editable source**, not the image renderer; `--png-engine drawio` opts
+ back into a draw.io render.
3. **`.d2` / `.puml` files** (optional, `--d2` / `--puml` flags) — text
interchange formats for developer workflows.
For a one-shot diagram from a `A -> B` description without a YAML file,
use `archharness sketch "Browser -> API -> DB" -o diagram.drawio` instead.
## Shape mapping (matches Company template)
| YAML type/shape | draw.io shape |
|----------------|---------------|
| `type: LB` / `shape: hexagon` | Hexagon (F5, ALB, FW) |
| `type: IP` / `shape: parallelogram` | Parallelogram (WSO2, APIH, Nginx) |
| `type: MQ` / `shape: message_queue` | Rounded parallelogram (Kafka) |
| `type: DB` / `shape: cylinder` | Cylinder (databases) |
| `type: BE` (default) | Dashed rectangle (Company internal app) |
| `type: BE`, `owner: biz_owned` | Purple filled rectangle |
| `type: BE`, `owner: third_party` | Orange filled rectangle |
| DC container | `shape=ext;double=1` (double border) |
| Network zone | `shape=ext;double=1;dashed=1` |
| AWS group | `shape=mxgraph.aws4.group` with cloud icon |
| Internet | `shape=mxgraph.aws4.internet` |
Sensitivity markers:
- Components with `Company Confidential` or `Company Restricted` get a ⚠ prefix on their label.
## Edge labels — shared code vocabulary
Edge labels are **codes**, not prose. The vocabulary lives in
`standards/diagram-codes.yaml` and is shared by every example, renderer and
reviewer, so the same relation always renders the same code.
| Kind | Form | Examples |
|---|---|---|
| Protocol | `P-<code>` | `P-HTTPS`, `P-KAFKA`, `P-JDBC`, `P-RFC`, `P-IDOC`, `P-OPCUA`, `P-MQTT` |
| Authentication | `AU-<minor>` | `AU-T1`, `AU-C1`, `AU-P4`, `AU-S1`, `AU-K1`, `AU-N0` |
A combination joins with `+` and the prefix is written once: `mTLS + SASL/SCRAM`
→ `AU-C1+S1`. Codes are collected in taxonomy order, so the result is stable
regardless of how the source text is phrased.
**Authentication classes** (supplement as needed in `standards/diagram-codes.yaml`):
| Class | Codes | Meaning |
|---|---|---|
| Token / federation | `T1`–`T6` | OAuth2 client credentials · OAuth2/OIDC user login · SAML2 · session token · JWT/bearer · personal access token |
| Certificate / key | `C1` `C2` | mTLS / client certificate · SSH public key |
| SASL | `S1`–`S4` | SCRAM · PLAIN · GSSAPI · OAUTHBEARER |
| Kerberos / OS | `K1` `K2` | Kerberos / logon ticket · NTLM / Windows integrated |
| Password / credential | `P1`–`P6` | user ID/password · HTTP Basic · API key · service account/secret · LDAP bind · RADIUS/TACACS+ |
| Cloud identity | `I1`–`I3` | IAM role · managed identity · service principal / workload identity |
| User factor | `M1` `M2` | MFA/OTP · FIDO2 / WebAuthn / passkey |
| Other | `X1`–`X4` | internal access auth · service auth (unspecified) · IP allowlist · anonymous |
| Authorization | `Z1`–`Z4` | topic ACL / least privilege · RBAC · ABAC/policy engine · OAuth2 scope |
| None | `N0` | no service authentication |
Each diagram renders a legend listing only the codes it actually uses.
**Edge colour = interface status** (the `[STATUS: …]` marker is never printed):
| Status | Colour |
|---|---|
| `EXISTING` | blue `#1565C0` |
| `NEW`, `CHANGE` | red `#C62828` |
| `REMOVE` | grey `#9E9E9E` |
| `TBD` / unspecified | blue-grey `#78909C` |
**Semantic roles are declared by the model, not guessed by the renderer.** When
you write or review an Architecture YAML, mark the nodes that carry meaning and
let the renderer apply it deterministically:
| Role | Declaration | Effect |
|---|---|---|
| Zone-boundary firewall | `role: zone_boundary` | In a region whose policy enables boundary roles, the node is not drawn and the zone is marked `· FW`; flows must be declared directly between the components that talk (rule R-INF-4 in `standards/requirements-model-v2.yaml`). Elsewhere (public cloud) the node stays explicit. |
| Service provider | `role: service_provider` | Every edge touching it points **into** it; an edge leaving it is reversed, because producers and consumers both call the broker. |
| Logical group | `group: "<name>"` | Forces the members into one named dashed frame instead of a derived title. |
Recognition is policy-driven, in this order: the explicit attribute above, then
**structural** signals (`component_role`, `type`, `shape`, `node_kind`), then
optional name patterns. Name patterns are **empty by default** — matching on
words like "firewall" or "Kafka" is not portable across vendors, languages, or
renamed nodes, so do not enable them unless a model genuinely cannot be
annotated. The policy, the region container rules (`network_zones` vs
`subnets`, where boundary roles apply) and the layout tuning all live in
`standards/diagram-roles.yaml`, so no architecture-specific rule is hardcoded in
the renderers.
**Logical groups.** Sibling components in the same zone that are interchangeable
— same technology signature *and* identical edge signatures (same peers, same
protocols, same direction) — are folded into one dashed box, and their fan-out
edges collapse to one edge per peer. This is automatic; a component with even
one extra relation stays standalone. Set `group: "<name>"` on components to force
a named grouping (and to keep a human-readable box title) instead of the derived
`<type> group ×N`. The renderers use the same pass, so `.drawio` and `.png` agree.
**Font hierarchy.** Component labels use `fontSize=14`, edge labels `fontSize=9`.
Component technology stacks are lower-cased and compressed (`Java (version TBD)`
→ `java`, `Internal K8s Platform` → `K8s`).
## How to invoke
```bash
# Generate .drawio only
archharness diagram -i arch.yaml -o diagram.drawio
- # Generate .drawio + PNG
- archharness diagram -i arch.yaml -o diagram.drawio --png diagram.png
+ # Generate .drawio (editable) + .d2 + PNG (the PNG is rendered by D2)
+ archharness diagram -i arch.yaml -o diagram.drawio --d2 diagram.d2 --png diagram.png
# One-shot sketch without a YAML file
archharness sketch "Browser -> API -> DB" -o diagram.drawio
```
(The legacy path `python tools/arch-diagram-gen/arch_diagram_gen.py`
still works via a compatibility shim; prefer the CLI above.)
## Requirements
```
pip install pyyaml # required
- pip install matplotlib # optional, for PNG fallback
+ pip install matplotlib # optional, PNG fallback
```
- For high-fidelity PNG, install draw.io desktop and ensure `drawio` is on PATH.
+ For the PNG image, install the **D2 CLI** (`d2 --version`). draw.io desktop is
+ only needed to edit the `.drawio` source, not to produce an image. For a very
+ large diagram, pass `--d2-scale 0.2` (d2's raster backend can fail at full size).
## When asked to generate a diagram
1. Check if the user has provided a YAML file path or YAML content.
2. If YAML content is provided inline, write it to a temp file first.
3. Run the tool and report what was generated.
4. If the output .drawio path is in the project, confirm it's ready to open.
- 5. If PNG was requested but drawio CLI is unavailable, note that matplotlib
- fallback was used and recommend installing draw.io desktop for full fidelity.
+ 5. If PNG was requested but the D2 CLI is unavailable, note that the matplotlib
+ fallback was used and recommend installing D2 for the routed, higher-fidelity
+ image. `--png-engine drawio` is available when a draw.io render is explicitly
+ wanted.