From d9777fb90e0b8bd4ddbb32475609dd565817063f Mon Sep 17 00:00:00 2001 From: Root At Skic Date: Sun, 8 Nov 2026 22:57:00 +0200 Subject: [PATCH] arc42 and ArchiMate examples: nine models, three per framework; 1.2 The six models from extension 0.11.0 (arc42 by section, ArchiMate by layer) next to the three C4 ones; model:scaffold --example offers them and the tests validate each with 0 problems. --- SKILL.md | 6 +- .../0300-context/technical-context.archify | 30 +++++++ .../0500-building-blocks/booking.archify | 49 +++++++++++ .../0500-building-blocks/level-1.archify | 64 +++++++++++++++ .../0600-runtime/book-seats.archify | 27 +++++++ .../0600-runtime/check-in.archify | 19 +++++ .../0700-deployment/production.archify | 58 +++++++++++++ .../0001-seat-holds-with-ttl.archify-decision | 20 +++++ ...oking-owns-seat-inventory.archify-decision | 20 +++++ .../0003-signed-qr-codes.archify-decision | 19 +++++ examples/arc42-cinema-tickets/main.archify | 72 +++++++++++++++++ .../registry/building-blocks.archify-registry | 57 +++++++++++++ .../registry/people.archify-registry | 14 ++++ .../registry/systems.archify-registry | 30 +++++++ .../0300-context/technical-context.archify | 35 ++++++++ .../0500-building-blocks/ingest.archify | 50 ++++++++++++ .../0500-building-blocks/level-1.archify | 77 ++++++++++++++++++ .../0600-runtime/device-provisioning.archify | 20 +++++ .../0600-runtime/telemetry-to-alert.archify | 20 +++++ .../0700-deployment/production.archify | 44 ++++++++++ ...0001-mqtt-with-mutual-tls.archify-decision | 21 +++++ ...timescaledb-for-telemetry.archify-decision | 20 +++++ examples/arc42-iot-telemetry/main.archify | 76 +++++++++++++++++ .../registry/building-blocks.archify-registry | 61 ++++++++++++++ .../registry/people.archify-registry | 20 +++++ .../registry/systems.archify-registry | 27 +++++++ .../0300-context/technical-context.archify | 26 ++++++ .../0500-building-blocks/level-1.archify | 47 +++++++++++ .../0500-building-blocks/wiki-api.archify | 55 +++++++++++++ .../0600-runtime/search-page.archify | 20 +++++ .../0600-runtime/sign-in.archify | 19 +++++ .../0700-deployment/production.archify | 48 +++++++++++ ...postgres-full-text-search.archify-decision | 20 +++++ ...-sso-only-via-company-idp.archify-decision | 19 +++++ examples/arc42-team-wiki/main.archify | 66 +++++++++++++++ .../registry/building-blocks.archify-registry | 33 ++++++++ .../registry/people.archify-registry | 15 ++++ .../registry/systems.archify-registry | 24 ++++++ .../0100-business/business-services.archify | 36 +++++++++ .../0100-business/onboard-employee.archify | 25 ++++++ .../application-components.archify | 44 ++++++++++ .../application-cooperation.archify | 29 +++++++ .../0300-technology/infrastructure.archify | 42 ++++++++++ ...hr-system-drives-identity.archify-decision | 20 +++++ .../0002-zero-touch-laptops.archify-decision | 20 +++++ examples/archimate-hr-onboarding/main.archify | 59 ++++++++++++++ .../registry/application.archify-registry | 81 +++++++++++++++++++ .../registry/business.archify-registry | 81 +++++++++++++++++++ .../registry/technology.archify-registry | 53 ++++++++++++ .../0100-business/business-layer.archify | 31 +++++++ .../0100-business/handle-claim.archify | 29 +++++++ .../application-cooperation.archify | 32 ++++++++ .../application-structure.archify | 36 +++++++++ .../0300-technology/infrastructure.archify | 45 +++++++++++ ...olicies-stay-on-mainframe.archify-decision | 20 +++++ ...cuments-in-object-storage.archify-decision | 20 +++++ .../archimate-insurance-claims/main.archify | 59 ++++++++++++++ .../registry/application.archify-registry | 76 +++++++++++++++++ .../registry/business.archify-registry | 50 ++++++++++++ .../registry/technology.archify-registry | 62 ++++++++++++++ .../0100-business/business-services.archify | 34 ++++++++ .../0100-business/deliver-shipment.archify | 25 ++++++ .../application-cooperation.archify | 32 ++++++++ .../application-services.archify | 34 ++++++++ .../0300-technology/infrastructure.archify | 44 ++++++++++ ...roker-for-tracking-events.archify-decision | 20 +++++ ...i-gateway-in-front-of-tms.archify-decision | 20 +++++ ...3-photo-proof-of-delivery.archify-decision | 17 ++++ .../archimate-logistics-tracking/main.archify | 59 ++++++++++++++ .../registry/application.archify-registry | 67 +++++++++++++++ .../registry/business.archify-registry | 54 +++++++++++++ .../registry/technology.archify-registry | 55 +++++++++++++ scripts/src/actions/model-scaffold/action.mjs | 6 ++ scripts/src/test/run.mjs | 10 ++- 74 files changed, 2768 insertions(+), 7 deletions(-) create mode 100644 examples/arc42-cinema-tickets/0300-context/technical-context.archify create mode 100644 examples/arc42-cinema-tickets/0500-building-blocks/booking.archify create mode 100644 examples/arc42-cinema-tickets/0500-building-blocks/level-1.archify create mode 100644 examples/arc42-cinema-tickets/0600-runtime/book-seats.archify create mode 100644 examples/arc42-cinema-tickets/0600-runtime/check-in.archify create mode 100644 examples/arc42-cinema-tickets/0700-deployment/production.archify create mode 100644 examples/arc42-cinema-tickets/decisions/0001-seat-holds-with-ttl.archify-decision create mode 100644 examples/arc42-cinema-tickets/decisions/0002-booking-owns-seat-inventory.archify-decision create mode 100644 examples/arc42-cinema-tickets/decisions/0003-signed-qr-codes.archify-decision create mode 100644 examples/arc42-cinema-tickets/main.archify create mode 100644 examples/arc42-cinema-tickets/registry/building-blocks.archify-registry create mode 100644 examples/arc42-cinema-tickets/registry/people.archify-registry create mode 100644 examples/arc42-cinema-tickets/registry/systems.archify-registry create mode 100644 examples/arc42-iot-telemetry/0300-context/technical-context.archify create mode 100644 examples/arc42-iot-telemetry/0500-building-blocks/ingest.archify create mode 100644 examples/arc42-iot-telemetry/0500-building-blocks/level-1.archify create mode 100644 examples/arc42-iot-telemetry/0600-runtime/device-provisioning.archify create mode 100644 examples/arc42-iot-telemetry/0600-runtime/telemetry-to-alert.archify create mode 100644 examples/arc42-iot-telemetry/0700-deployment/production.archify create mode 100644 examples/arc42-iot-telemetry/decisions/0001-mqtt-with-mutual-tls.archify-decision create mode 100644 examples/arc42-iot-telemetry/decisions/0002-timescaledb-for-telemetry.archify-decision create mode 100644 examples/arc42-iot-telemetry/main.archify create mode 100644 examples/arc42-iot-telemetry/registry/building-blocks.archify-registry create mode 100644 examples/arc42-iot-telemetry/registry/people.archify-registry create mode 100644 examples/arc42-iot-telemetry/registry/systems.archify-registry create mode 100644 examples/arc42-team-wiki/0300-context/technical-context.archify create mode 100644 examples/arc42-team-wiki/0500-building-blocks/level-1.archify create mode 100644 examples/arc42-team-wiki/0500-building-blocks/wiki-api.archify create mode 100644 examples/arc42-team-wiki/0600-runtime/search-page.archify create mode 100644 examples/arc42-team-wiki/0600-runtime/sign-in.archify create mode 100644 examples/arc42-team-wiki/0700-deployment/production.archify create mode 100644 examples/arc42-team-wiki/decisions/0001-postgres-full-text-search.archify-decision create mode 100644 examples/arc42-team-wiki/decisions/0002-sso-only-via-company-idp.archify-decision create mode 100644 examples/arc42-team-wiki/main.archify create mode 100644 examples/arc42-team-wiki/registry/building-blocks.archify-registry create mode 100644 examples/arc42-team-wiki/registry/people.archify-registry create mode 100644 examples/arc42-team-wiki/registry/systems.archify-registry create mode 100644 examples/archimate-hr-onboarding/0100-business/business-services.archify create mode 100644 examples/archimate-hr-onboarding/0100-business/onboard-employee.archify create mode 100644 examples/archimate-hr-onboarding/0200-application/application-components.archify create mode 100644 examples/archimate-hr-onboarding/0200-application/application-cooperation.archify create mode 100644 examples/archimate-hr-onboarding/0300-technology/infrastructure.archify create mode 100644 examples/archimate-hr-onboarding/decisions/0001-hr-system-drives-identity.archify-decision create mode 100644 examples/archimate-hr-onboarding/decisions/0002-zero-touch-laptops.archify-decision create mode 100644 examples/archimate-hr-onboarding/main.archify create mode 100644 examples/archimate-hr-onboarding/registry/application.archify-registry create mode 100644 examples/archimate-hr-onboarding/registry/business.archify-registry create mode 100644 examples/archimate-hr-onboarding/registry/technology.archify-registry create mode 100644 examples/archimate-insurance-claims/0100-business/business-layer.archify create mode 100644 examples/archimate-insurance-claims/0100-business/handle-claim.archify create mode 100644 examples/archimate-insurance-claims/0200-application/application-cooperation.archify create mode 100644 examples/archimate-insurance-claims/0200-application/application-structure.archify create mode 100644 examples/archimate-insurance-claims/0300-technology/infrastructure.archify create mode 100644 examples/archimate-insurance-claims/decisions/0001-policies-stay-on-mainframe.archify-decision create mode 100644 examples/archimate-insurance-claims/decisions/0002-documents-in-object-storage.archify-decision create mode 100644 examples/archimate-insurance-claims/main.archify create mode 100644 examples/archimate-insurance-claims/registry/application.archify-registry create mode 100644 examples/archimate-insurance-claims/registry/business.archify-registry create mode 100644 examples/archimate-insurance-claims/registry/technology.archify-registry create mode 100644 examples/archimate-logistics-tracking/0100-business/business-services.archify create mode 100644 examples/archimate-logistics-tracking/0100-business/deliver-shipment.archify create mode 100644 examples/archimate-logistics-tracking/0200-application/application-cooperation.archify create mode 100644 examples/archimate-logistics-tracking/0200-application/application-services.archify create mode 100644 examples/archimate-logistics-tracking/0300-technology/infrastructure.archify create mode 100644 examples/archimate-logistics-tracking/decisions/0001-broker-for-tracking-events.archify-decision create mode 100644 examples/archimate-logistics-tracking/decisions/0002-edi-gateway-in-front-of-tms.archify-decision create mode 100644 examples/archimate-logistics-tracking/decisions/0003-photo-proof-of-delivery.archify-decision create mode 100644 examples/archimate-logistics-tracking/main.archify create mode 100644 examples/archimate-logistics-tracking/registry/application.archify-registry create mode 100644 examples/archimate-logistics-tracking/registry/business.archify-registry create mode 100644 examples/archimate-logistics-tracking/registry/technology.archify-registry diff --git a/SKILL.md b/SKILL.md index 10a776a..3953349 100644 --- a/SKILL.md +++ b/SKILL.md @@ -15,7 +15,7 @@ license: MIT compatibility: Requires Node.js 18+, bash and go-task (task). No network access; Archify is bundled under scripts/vendor. metadata: author: root-at-skic - version: "1.1" + version: "1.2" origin-repository: https://gitea.lego-cloud.eu/vscode-extensions-skills/archify-vscode-ext.git targets: Archify Diagram Viewer (root-at-skic.archify-vscode-ext) --- @@ -41,7 +41,7 @@ task --list-all | `task model:list -- --dir=""` | What the model page shows: metadata, diagrams by folder, registry elements with "used in N diagrams", decisions with status and the diagrams that reference them. | | `task model:graph -- --dir="" [--query="uses:api"] [--links]` | The model as one graph, as the extension's **Graph** page shows it: every element, every connection once, plus a node per decision and per registry file. `--query` narrows it with the page's language: `database`, `type:backend`, `diagram:0200-*`, `decision:`, `uses:api`, `near:api,2`, `from:web to:db` (shortest path), `unused`, `shared`, `-shared`; terms AND together, a leading `-` excludes. Use it to answer "what talks to X", "how does A reach B", "what does this decision touch", "which registry elements are unused". | | `task model:scaffold -- --dir="" --id="" --name="" [--description="…"] [--c4]` | Creates `main.archify`; with `--c4` also `registry/` and the `0100-context`, `0200-containers`, `0300-components` folders with starter diagrams. Never overwrites. | -| `task model:scaffold -- --dir="" --example="" [--id=""] [--name=""] [--description="…"]` | Copies a complete example model: `c4-standard-web-app`, `c4-e-shop` or `c4-event-based-integration` (the same three the extension offers under *Archify \| New Model…*). Id, name and description default to the example's own. Never overwrites. | +| `task model:scaffold -- --dir="" --example="" [--id=""] [--name=""] [--description="…"]` | Copies a complete example model: C4 `c4-standard-web-app`, `c4-e-shop`, `c4-event-based-integration`; arc42 `arc42-cinema-tickets`, `arc42-iot-telemetry`, `arc42-team-wiki`; ArchiMate `archimate-insurance-claims`, `archimate-hr-onboarding`, `archimate-logistics-tracking` (the same nine the extension offers under *Archify \| New Model…*). Id, name and description default to the example's own. Never overwrites. | | `task model:resolve -- --file="" [--out=""]` | The Archify JSON the extension hands to Archify, for the plain Archify CLI or CI. | | `task diagram:validate -- --file=""` | One diagram through Archify (refs resolved when inside a model). | | `task diagram:render -- --file="" --out=""` | Standalone HTML page for people without VS Code. | @@ -187,4 +187,4 @@ Diagrams next to `main.archify` are listed first, ungrouped; deeper ones by fold - Read `references/authoring.md` when writing or repairing a diagram: kinds, fields, grid, labels, boundaries, brands, validator codes and fixes. - Read `references/formats.md` when writing `main.archify`, a registry, a `ref` or a link, or when unsure what the tasks strip before Archify runs. - Read `references/folders.md` when laying out a model folder or explaining how the extension finds the root and groups diagrams. -- `examples/c4-standard-web-app/`, `examples/c4-e-shop/` and `examples/c4-event-based-integration/` are complete C4-style models that validate with 0 problems; copy their shape, or copy one with `model:scaffold --example`. +- `examples/` holds nine complete models that validate with 0 problems; copy their shape, or copy one with `model:scaffold --example`. Three C4 (`c4-*`: context, containers, components). Three arc42 (`arc42-*`: the overview is section 3 business context with goals, constraints, quality, risks and glossary as `cards`; `0300-context`, `0500-building-blocks`, `0600-runtime` sequence diagrams, `0700-deployment`; decisions are section 9). Three ArchiMate (`archimate-*`: the overview is a layered view in three region boundaries; `0100-business`, `0200-application`, `0300-technology`; one registry file per layer; each element's ArchiMate type as its `tag` and `sublabel`, since Archify shows tags only in the focus panel). diff --git a/examples/arc42-cinema-tickets/0300-context/technical-context.archify b/examples/arc42-cinema-tickets/0300-context/technical-context.archify new file mode 100644 index 0000000..8a4f92e --- /dev/null +++ b/examples/arc42-cinema-tickets/0300-context/technical-context.archify @@ -0,0 +1,30 @@ +schema_version: 1 +diagram_type: architecture +meta: + title: Technical context + output: technical-context.html +components: + - ref: customer + pos: [40, 60] + size: [130, 60] + - ref: usher + pos: [40, 260] + size: [130, 60] + - ref: tickets + pos: [290, 160] + size: [150, 60] + - ref: psp + pos: [560, 60] + size: [150, 60] + - ref: mail + pos: [560, 160] + size: [150, 60] + - ref: pos + pos: [560, 260] + size: [150, 60] +connections: + - { from: customer, to: tickets, label: HTTPS JSON, variant: emphasis } + - { from: usher, to: tickets, label: HTTPS app } + - { from: tickets, to: psp, label: REST webhook, variant: security } + - { from: tickets, to: mail, label: SMTP TLS } + - { from: tickets, to: pos, label: REST VPN } diff --git a/examples/arc42-cinema-tickets/0500-building-blocks/booking.archify b/examples/arc42-cinema-tickets/0500-building-blocks/booking.archify new file mode 100644 index 0000000..2fd0e5c --- /dev/null +++ b/examples/arc42-cinema-tickets/0500-building-blocks/booking.archify @@ -0,0 +1,49 @@ +schema_version: 1 +diagram_type: architecture +meta: + title: Booking API - level 2 + output: booking.html +decisions: [seat-holds-with-ttl] +components: + - ref: web + pos: [40, 160] + size: [130, 60] + - id: programme + type: backend + label: Programme + sublabel: shows, halls + pos: [250, 60] + size: [130, 60] + - id: seats + type: backend + label: Seat Holds + sublabel: lock, release + pos: [250, 160] + size: [130, 60] + - id: checkout + type: backend + label: Checkout + sublabel: orders, webhook + pos: [250, 260] + size: [130, 60] + - ref: seatlock + pos: [460, 160] + size: [130, 60] + decisions: [seat-holds-with-ttl] + - ref: db + pos: [460, 60] + size: [130, 60] + - ref: psp + pos: [460, 360] + size: [150, 60] +boundaries: + - kind: region + label: Booking API + wraps: [programme, seats, checkout] +connections: + - { from: web, to: programme, label: browse } + - { from: web, to: seats, label: hold, variant: emphasis } + - { from: web, to: checkout, label: pay } + - { from: programme, to: db, label: SQL } + - { from: seats, to: seatlock, label: SET NX, decisions: [seat-holds-with-ttl] } + - { from: checkout, to: psp, label: session, variant: security } diff --git a/examples/arc42-cinema-tickets/0500-building-blocks/level-1.archify b/examples/arc42-cinema-tickets/0500-building-blocks/level-1.archify new file mode 100644 index 0000000..03b2a5e --- /dev/null +++ b/examples/arc42-cinema-tickets/0500-building-blocks/level-1.archify @@ -0,0 +1,64 @@ +schema_version: 1 +diagram_type: architecture +meta: + title: Building blocks - level 1 + output: level-1.html +decisions: [booking-owns-seat-inventory] +components: + - ref: web + pos: [40, 110] + size: [130, 60] + - ref: mobile + pos: [40, 210] + size: [130, 60] + - ref: scanner + pos: [40, 360] + size: [130, 60] + - ref: booking + pos: [250, 160] + size: [130, 60] + - ref: seatlock + pos: [460, 60] + size: [130, 60] + - ref: db + pos: [460, 260] + size: [130, 60] + - ref: ticketing + pos: [250, 360] + size: [130, 60] + - ref: possync + pos: [670, 260] + size: [130, 60] + - ref: psp + pos: [900, 160] + size: [150, 60] + - ref: pos + pos: [900, 260] + size: [150, 60] + - ref: mail + pos: [900, 460] + size: [150, 60] +boundaries: + - kind: region + label: Cinema Tickets + wraps: [web, mobile, scanner, booking, seatlock, db, ticketing, possync] +connections: + - { from: web, to: booking, label: JSON, variant: emphasis } + - { from: mobile, to: booking, label: JSON } + - { from: booking, to: seatlock, label: hold } + - { from: booking, to: db, label: SQL } + - { from: booking, to: psp, label: checkout, variant: security } + - { from: booking, to: ticketing, label: issue, labelAt: [315, 234] } + - { from: scanner, to: ticketing, label: check-in } + - { from: ticketing, to: db, label: SQL } + - { from: ticketing, to: mail, label: QR mail } + - { from: possync, to: db, label: SQL } + - { from: possync, to: pos, label: sales, decisions: [booking-owns-seat-inventory] } +cards: + - dot: amber + title: 8 Crosscutting concepts + items: + - "Times in UTC; shown in cinema local time" + - "Every write carries an idempotency key" + - "QR payload signed with an Ed25519 key" + - "Structured logs with order id as trace key" diff --git a/examples/arc42-cinema-tickets/0600-runtime/book-seats.archify b/examples/arc42-cinema-tickets/0600-runtime/book-seats.archify new file mode 100644 index 0000000..a03fbff --- /dev/null +++ b/examples/arc42-cinema-tickets/0600-runtime/book-seats.archify @@ -0,0 +1,27 @@ +schema_version: 1 +diagram_type: sequence +meta: + title: Runtime - book seats + output: book-seats.html + viewBox: [1060, 680] + column_fit: spread +decisions: [seat-holds-with-ttl] +participants: + - { ref: customer } + - { ref: web } + - { ref: booking } + - { ref: seatlock } + - { ref: psp } + - { ref: ticketing } + - { ref: mail } +messages: + - { from: customer, to: web, y: 170, label: pick seats, variant: emphasis } + - { from: web, to: booking, y: 214, label: POST /holds } + - { from: booking, to: seatlock, y: 258, label: SET NX TTL 8m, decisions: [seat-holds-with-ttl] } + - { from: seatlock, to: booking, y: 302, label: OK, variant: return } + - { from: booking, to: web, y: 346, label: hold id, variant: return } + - { from: web, to: psp, y: 390, label: hosted checkout, variant: security } + - { from: psp, to: booking, y: 434, label: webhook paid, variant: security } + - { from: booking, to: ticketing, y: 478, label: issue tickets } + - { from: ticketing, to: mail, y: 522, label: QR e-mail } + - { from: mail, to: customer, y: 566, label: tickets, variant: return } diff --git a/examples/arc42-cinema-tickets/0600-runtime/check-in.archify b/examples/arc42-cinema-tickets/0600-runtime/check-in.archify new file mode 100644 index 0000000..45ce878 --- /dev/null +++ b/examples/arc42-cinema-tickets/0600-runtime/check-in.archify @@ -0,0 +1,19 @@ +schema_version: 1 +diagram_type: sequence +meta: + title: Runtime - check-in at the door + output: check-in.html + viewBox: [900, 480] + column_fit: spread +decisions: [signed-qr-codes] +participants: + - { ref: usher } + - { ref: scanner } + - { ref: ticketing } + - { ref: db } +messages: + - { from: usher, to: scanner, y: 180, label: scan QR, variant: emphasis, note: signature checked offline, decisions: [signed-qr-codes] } + - { from: scanner, to: ticketing, y: 230, label: POST /checkins } + - { from: ticketing, to: db, y: 280, label: first scan wins } + - { from: ticketing, to: scanner, y: 330, label: valid seat 7F, variant: return } + - { from: scanner, to: usher, y: 380, label: green light, variant: return } diff --git a/examples/arc42-cinema-tickets/0700-deployment/production.archify b/examples/arc42-cinema-tickets/0700-deployment/production.archify new file mode 100644 index 0000000..878745d --- /dev/null +++ b/examples/arc42-cinema-tickets/0700-deployment/production.archify @@ -0,0 +1,58 @@ +schema_version: 1 +diagram_type: architecture +meta: + title: Deployment - production + output: production.html +components: + - ref: customer + pos: [40, 160] + size: [130, 60] + - id: ingress + type: security + label: Ingress + sublabel: TLS, WAF + pos: [250, 160] + size: [130, 60] + - ref: web + pos: [460, 60] + size: [130, 60] + - ref: booking + pos: [460, 160] + size: [130, 60] + - ref: ticketing + pos: [460, 260] + size: [130, 60] + - ref: possync + pos: [460, 360] + size: [130, 60] + - ref: seatlock + pos: [710, 110] + size: [130, 60] + - ref: db + pos: [710, 260] + size: [130, 60] + - ref: pos + pos: [250, 460] + size: [150, 60] + - ref: scanner + pos: [40, 460] + size: [130, 60] +boundaries: + - kind: region + label: EU cloud - k8s cluster + wraps: [ingress, web, booking, ticketing, possync] + - kind: security-group + label: Managed data zone + wraps: [seatlock, db] + - kind: region + label: Cinema site + wraps: [pos, scanner] +connections: + - { from: customer, to: ingress, label: HTTPS, variant: emphasis } + - { from: ingress, to: web, label: route } + - { from: ingress, to: booking, label: route } + - { from: booking, to: seatlock, label: TLS } + - { from: booking, to: db, label: TLS } + - { from: ticketing, to: db, label: TLS } + - { from: possync, to: pos, label: VPN, variant: security } + - { from: scanner, to: ingress, label: HTTPS } diff --git a/examples/arc42-cinema-tickets/decisions/0001-seat-holds-with-ttl.archify-decision b/examples/arc42-cinema-tickets/decisions/0001-seat-holds-with-ttl.archify-decision new file mode 100644 index 0000000..72529d2 --- /dev/null +++ b/examples/arc42-cinema-tickets/decisions/0001-seat-holds-with-ttl.archify-decision @@ -0,0 +1,20 @@ +schema_version: 1 +decision: + id: seat-holds-with-ttl + title: Seat holds as Redis keys with a TTL + status: accepted + date: 2026-09-08 + elements: [booking, seatlock] + diagrams: [0500-building-blocks/booking.archify, 0600-runtime/book-seats.archify] +context: > + A customer may spend minutes at the payment page. Holding seats + as rows in the database left orphans when a browser closed, and + a nightly job freed them far too late for Friday shows. +decision: > + A hold is one Redis key per seat, set with SET NX and an + 8-minute TTL. The payment webhook turns holds into an order in + PostgreSQL; an expired key frees the seat without any job. +consequences: > + Holds survive no Redis restart; at worst a customer re-picks + seats. The webhook must check the hold still exists before it + confirms the order, otherwise it refunds. diff --git a/examples/arc42-cinema-tickets/decisions/0002-booking-owns-seat-inventory.archify-decision b/examples/arc42-cinema-tickets/decisions/0002-booking-owns-seat-inventory.archify-decision new file mode 100644 index 0000000..f934697 --- /dev/null +++ b/examples/arc42-cinema-tickets/decisions/0002-booking-owns-seat-inventory.archify-decision @@ -0,0 +1,20 @@ +schema_version: 1 +decision: + id: booking-owns-seat-inventory + title: The Booking API owns the seat inventory + status: accepted + date: 2026-09-22 + elements: [booking, db, possync, pos] + diagrams: [0500-building-blocks/level-1.archify] +context: > + The box-office POS and the web shop both sold seats from their + own copy of the seat map. Twice a month a seat was sold at the + counter and online. +decision: > + The Tickets DB is the only seat inventory. The POS asks POS Sync + for a seat before it prints a ticket; POS Sync writes the sale + through the same rules as online orders. +consequences: > + The counter needs the network to sell; a fallback block of + reserved seats per show covers outages. The POS vendor adapter + is ours to maintain. diff --git a/examples/arc42-cinema-tickets/decisions/0003-signed-qr-codes.archify-decision b/examples/arc42-cinema-tickets/decisions/0003-signed-qr-codes.archify-decision new file mode 100644 index 0000000..3255fb0 --- /dev/null +++ b/examples/arc42-cinema-tickets/decisions/0003-signed-qr-codes.archify-decision @@ -0,0 +1,19 @@ +schema_version: 1 +decision: + id: signed-qr-codes + title: Signed QR codes checked offline at the door + status: accepted + date: 2026-10-06 + elements: [ticketing, scanner] + diagrams: [0600-runtime/check-in.archify] +context: > + Cinema Wi-Fi drops when a full hall arrives. A scanner that + needs the server for every ticket stops the queue. +decision: > + The Ticket Service signs each QR payload (ticket id, show, + seat) with a private key. The scanner app verifies it with the + public key and queues check-ins until it is online again. +consequences: > + A forwarded ticket scans twice while offline; the second scan + is flagged when the queue syncs. Key rotation needs an app + update window. diff --git a/examples/arc42-cinema-tickets/main.archify b/examples/arc42-cinema-tickets/main.archify new file mode 100644 index 0000000..7a6a2ab --- /dev/null +++ b/examples/arc42-cinema-tickets/main.archify @@ -0,0 +1,72 @@ +schema_version: 1 +model: + id: cinema-tickets + name: Cinema Tickets + description: > + An arc42 example: online and mobile seat booking for a small + cinema chain. This overview is section 3 (business context) with + cards for sections 1, 2, 10, 11 and 12. 0300-context holds the + technical context (3), 0500-building-blocks the building block + view (5), 0600-runtime the runtime view (6), 0700-deployment the + deployment view (7), decisions/ the architecture decisions (9). + Crosscutting concepts (8) are a card on the level-1 diagram. +diagram_type: architecture +meta: + title: Cinema Tickets - business context + output: main.html +components: + - ref: customer + pos: [40, 60] + size: [130, 60] + - ref: usher + pos: [40, 260] + size: [130, 60] + - ref: tickets + pos: [280, 160] + size: [150, 60] + - ref: psp + pos: [540, 60] + size: [150, 60] + - ref: mail + pos: [540, 160] + size: [150, 60] + - ref: pos + pos: [540, 260] + size: [150, 60] +connections: + - { from: customer, to: tickets, label: books seats, variant: emphasis } + - { from: usher, to: tickets, label: checks in } + - { from: tickets, to: psp, label: payments, variant: security } + - { from: tickets, to: mail, label: tickets } + - { from: tickets, to: pos, label: seat sales } +cards: + - dot: cyan + title: 1 Quality goals + items: + - "No seat is ever sold twice" + - "Checkout under 2 s at Friday peak" + - "Door check-in works offline" + - dot: slate + title: 2 Constraints + items: + - "Existing box-office POS stays" + - "Card data only at the provider" + - "Team of four; hosted in the EU" + - dot: emerald + title: 10 Quality scenarios + items: + - "500 holds on one show in 1 min: no double sale" + - "Wi-Fi down at the door: scans go on, sync later" + - "Payment fails: seats free again within 8 min" + - dot: rose + title: 11 Risks + items: + - "POS vendor API is slow and undocumented" + - "Forwarded QR e-mails: first scan wins" + - dot: violet + title: 12 Glossary + items: + - "Show: one screening of a film in a hall" + - "Hold: a seat locked for one customer" + - "Check-in: first valid scan of a ticket" + - "POS: point-of-sale till at the box office" diff --git a/examples/arc42-cinema-tickets/registry/building-blocks.archify-registry b/examples/arc42-cinema-tickets/registry/building-blocks.archify-registry new file mode 100644 index 0000000..f35e243 --- /dev/null +++ b/examples/arc42-cinema-tickets/registry/building-blocks.archify-registry @@ -0,0 +1,57 @@ +schema_version: 1 +elements: + web: + type: frontend + label: Web Shop + sublabel: React + brand: react + description: > + Programme, seat map and checkout in the browser. + mobile: + type: frontend + label: Mobile App + sublabel: iOS and Android + description: > + The same booking flow as the web shop, plus a ticket wallet. + scanner: + type: frontend + label: Scanner App + sublabel: door phones + description: > + Reads QR codes at the door; checks signatures offline. + booking: + type: backend + label: Booking API + sublabel: Node.js + brand: node-js + description: > + Shows, seat maps, seat holds and orders; the only writer of + the seat inventory. + diagram: 0500-building-blocks/booking.archify + ticketing: + type: backend + label: Ticket Service + sublabel: QR, check-in + description: > + Issues signed QR tickets, sends them by e-mail and records + check-ins at the door. + possync: + type: backend + label: POS Sync + sublabel: adapter + description: > + Exchanges seat sales with the box-office POS in both directions. + seatlock: + type: database + label: Seat Locks + sublabel: Redis + brand: redis + description: > + Short-lived seat holds with a TTL while the customer pays. + db: + type: database + label: Tickets DB + sublabel: PostgreSQL + brand: postgresql + description: > + Shows, seats, orders and tickets; the source of truth. diff --git a/examples/arc42-cinema-tickets/registry/people.archify-registry b/examples/arc42-cinema-tickets/registry/people.archify-registry new file mode 100644 index 0000000..8250d1d --- /dev/null +++ b/examples/arc42-cinema-tickets/registry/people.archify-registry @@ -0,0 +1,14 @@ +schema_version: 1 +elements: + customer: + type: external + label: Moviegoer + sublabel: web and mobile + description: > + Picks a show, holds seats and pays; gets the tickets by e-mail. + usher: + type: external + label: Usher + sublabel: door staff + description: > + Scans tickets at the auditorium door with the scanner app. diff --git a/examples/arc42-cinema-tickets/registry/systems.archify-registry b/examples/arc42-cinema-tickets/registry/systems.archify-registry new file mode 100644 index 0000000..b43d67e --- /dev/null +++ b/examples/arc42-cinema-tickets/registry/systems.archify-registry @@ -0,0 +1,30 @@ +schema_version: 1 +elements: + tickets: + type: cloud + label: Cinema Tickets + sublabel: the system + description: > + Online booking, seat holds, e-mail tickets and door check-in + for the five cinemas of the fictional Lantern Cinemas chain. + diagram: 0500-building-blocks/level-1.archify + psp: + type: external + label: Payment provider + sublabel: hosted checkout + description: > + Takes card and wallet payments on its own page; we never see + card numbers. + pos: + type: external + label: Box-office POS + sublabel: in each cinema + description: > + Till system at the counter; sells walk-in seats from the same + seat map. + mail: + type: external + label: E-mail service + sublabel: transactional + description: > + Delivers ticket e-mails with QR codes and receipts. diff --git a/examples/arc42-iot-telemetry/0300-context/technical-context.archify b/examples/arc42-iot-telemetry/0300-context/technical-context.archify new file mode 100644 index 0000000..7437a09 --- /dev/null +++ b/examples/arc42-iot-telemetry/0300-context/technical-context.archify @@ -0,0 +1,35 @@ +schema_version: 1 +diagram_type: architecture +meta: + title: Technical context + output: technical-context.html +decisions: [mqtt-with-mutual-tls] +components: + - ref: homeowner + pos: [40, 60] + size: [130, 60] + - ref: ops-engineer + pos: [40, 160] + size: [130, 60] + - ref: installer + pos: [40, 260] + size: [130, 60] + - ref: telemetry-platform + pos: [280, 160] + size: [150, 60] + - ref: heat-pump + pos: [540, 60] + size: [130, 60] + - ref: push-service + pos: [540, 160] + size: [130, 60] + - ref: service-desk + pos: [540, 260] + size: [130, 60] +connections: + - { from: homeowner, to: telemetry-platform, label: HTTPS } + - { from: ops-engineer, to: telemetry-platform, label: HTTPS, variant: security } + - { from: installer, to: telemetry-platform, label: HTTPS } + - { from: heat-pump, to: telemetry-platform, label: MQTT 8883, variant: emphasis, decisions: [mqtt-with-mutual-tls] } + - { from: telemetry-platform, to: push-service, label: HTTP/2 } + - { from: telemetry-platform, to: service-desk, label: webhook } diff --git a/examples/arc42-iot-telemetry/0500-building-blocks/ingest.archify b/examples/arc42-iot-telemetry/0500-building-blocks/ingest.archify new file mode 100644 index 0000000..800dedb --- /dev/null +++ b/examples/arc42-iot-telemetry/0500-building-blocks/ingest.archify @@ -0,0 +1,50 @@ +schema_version: 1 +diagram_type: architecture +meta: + title: Ingest, level 2 + output: ingest.html +components: + - ref: mqtt-broker + pos: [40, 160] + size: [130, 60] + - id: decoder + type: backend + label: Decoder + sublabel: payload v1, v2 + pos: [250, 160] + size: [130, 60] + - id: validator + type: backend + label: Validator + sublabel: ranges, clock + pos: [460, 160] + size: [130, 60] + - id: writer + type: backend + label: Batch writer + sublabel: 500 rows + pos: [670, 160] + size: [130, 60] + - id: dead-letter + type: database + label: Dead letters + sublabel: rejected readings + pos: [460, 310] + size: [130, 60] + - ref: tsdb + pos: [880, 160] + size: [130, 60] + - ref: rules + pos: [670, 310] + size: [130, 60] +boundaries: + - kind: region + label: Ingest + wraps: [decoder, validator, writer, dead-letter] +connections: + - { from: mqtt-broker, to: decoder, label: messages, variant: emphasis } + - { from: decoder, to: validator, label: readings, variant: emphasis } + - { from: validator, to: writer, label: valid, variant: emphasis } + - { from: validator, to: dead-letter, label: invalid, variant: dashed, labelAt: [525, 234] } + - { from: writer, to: tsdb, label: COPY, variant: emphasis } + - { from: writer, to: rules, label: stream, labelAt: [735, 234] } diff --git a/examples/arc42-iot-telemetry/0500-building-blocks/level-1.archify b/examples/arc42-iot-telemetry/0500-building-blocks/level-1.archify new file mode 100644 index 0000000..84490cf --- /dev/null +++ b/examples/arc42-iot-telemetry/0500-building-blocks/level-1.archify @@ -0,0 +1,77 @@ +schema_version: 1 +diagram_type: architecture +meta: + title: Building blocks, level 1 + output: level-1.html +decisions: [timescaledb-for-telemetry] +components: + - ref: heat-pump + pos: [40, 160] + size: [130, 60] + - ref: installer + pos: [40, 360] + size: [130, 60] + - ref: mqtt-broker + pos: [250, 160] + size: [130, 60] + decisions: [mqtt-with-mutual-tls] + - ref: provisioning + pos: [250, 360] + size: [130, 60] + - ref: rules + pos: [460, 60] + size: [130, 60] + - ref: ingest + pos: [460, 160] + size: [130, 60] + - ref: device-registry + pos: [460, 360] + size: [130, 60] + - ref: tsdb + pos: [670, 160] + size: [130, 60] + - ref: device-api + pos: [670, 360] + size: [130, 60] + - ref: ops-dashboard + pos: [880, 160] + size: [130, 60] + - ref: customer-app + pos: [880, 360] + size: [130, 60] + - ref: push-service + pos: [1090, 60] + size: [130, 60] + - ref: ops-engineer + pos: [1090, 160] + size: [130, 60] + - ref: homeowner + pos: [1090, 360] + size: [130, 60] +boundaries: + - kind: region + label: IoT Telemetry + wraps: [mqtt-broker, provisioning, rules, ingest, device-registry, tsdb, device-api, ops-dashboard, customer-app] +connections: + - { from: heat-pump, to: mqtt-broker, label: publish, variant: emphasis, decisions: [mqtt-with-mutual-tls] } + - { from: mqtt-broker, to: ingest, label: subscribe, variant: emphasis } + - { from: ingest, to: tsdb, label: write, variant: emphasis } + - { from: ingest, to: rules, label: stream } + - { from: ingest, to: device-registry, label: lookup, labelAt: [525, 234] } + - { from: rules, to: push-service, label: alert } + - { from: installer, to: provisioning, label: register } + - { from: provisioning, to: mqtt-broker, label: certs, variant: security } + - { from: provisioning, to: device-registry, label: store } + - { from: device-api, to: tsdb, label: read } + - { from: device-api, to: device-registry, label: read } + - { from: tsdb, to: ops-dashboard, label: query } + - { from: customer-app, to: device-api, label: REST } + - { from: ops-engineer, to: ops-dashboard, label: views } + - { from: homeowner, to: customer-app, label: uses } +cards: + - dot: amber + title: 8 Crosscutting concepts + items: + - Device identity, one X.509 certificate per device + - Idempotent writes, keyed by device id and timestamp + - Observability, metrics and traces on every service diff --git a/examples/arc42-iot-telemetry/0600-runtime/device-provisioning.archify b/examples/arc42-iot-telemetry/0600-runtime/device-provisioning.archify new file mode 100644 index 0000000..fef0bf8 --- /dev/null +++ b/examples/arc42-iot-telemetry/0600-runtime/device-provisioning.archify @@ -0,0 +1,20 @@ +schema_version: 1 +diagram_type: sequence +meta: + title: Device provisioning + output: device-provisioning.html +decisions: [mqtt-with-mutual-tls] +participants: + - { ref: installer } + - { ref: provisioning } + - { ref: device-registry, label: Devices } + - { ref: heat-pump } + - { ref: mqtt-broker } +messages: + - { from: installer, to: provisioning, y: 160, label: register serial, variant: emphasis } + - { from: provisioning, to: device-registry, y: 210, label: store device } + - { from: provisioning, to: installer, y: 260, label: certificate, variant: return } + - { from: installer, to: heat-pump, y: 310, label: load certificate } + - { from: heat-pump, to: mqtt-broker, y: 360, label: connect mTLS, variant: emphasis } + - { from: mqtt-broker, to: provisioning, y: 410, label: check revocation } + - { from: mqtt-broker, to: heat-pump, y: 460, label: CONNACK, variant: return } diff --git a/examples/arc42-iot-telemetry/0600-runtime/telemetry-to-alert.archify b/examples/arc42-iot-telemetry/0600-runtime/telemetry-to-alert.archify new file mode 100644 index 0000000..1795b1f --- /dev/null +++ b/examples/arc42-iot-telemetry/0600-runtime/telemetry-to-alert.archify @@ -0,0 +1,20 @@ +schema_version: 1 +diagram_type: sequence +meta: + title: Fault reading to alert + output: telemetry-to-alert.html +participants: + - { ref: heat-pump } + - { ref: mqtt-broker } + - { ref: ingest } + - { ref: tsdb, label: TSDB } + - { ref: rules } + - { ref: push-service } +messages: + - { from: heat-pump, to: mqtt-broker, y: 160, label: publish fault, variant: emphasis } + - { from: mqtt-broker, to: ingest, y: 210, label: deliver QoS 1 } + - { from: ingest, to: tsdb, y: 260, label: write batch } + - { from: tsdb, to: ingest, y: 310, label: committed, variant: return } + - { from: ingest, to: mqtt-broker, y: 360, label: ack, variant: return } + - { from: ingest, to: rules, y: 410, label: reading } + - { from: rules, to: push-service, y: 460, label: send alert, variant: emphasis } diff --git a/examples/arc42-iot-telemetry/0700-deployment/production.archify b/examples/arc42-iot-telemetry/0700-deployment/production.archify new file mode 100644 index 0000000..c74de51 --- /dev/null +++ b/examples/arc42-iot-telemetry/0700-deployment/production.archify @@ -0,0 +1,44 @@ +schema_version: 1 +diagram_type: architecture +meta: + title: Deployment, production + output: production.html +decisions: [timescaledb-for-telemetry] +components: + - ref: heat-pump + pos: [40, 160] + size: [130, 60] + - ref: mqtt-broker + pos: [280, 160] + size: [130, 60] + - ref: ingest + pos: [490, 160] + size: [130, 60] + - ref: rules + pos: [490, 60] + size: [130, 60] + - ref: provisioning + pos: [280, 260] + size: [130, 60] + - ref: device-api + pos: [490, 260] + size: [130, 60] + - ref: tsdb + pos: [760, 160] + size: [130, 60] + - ref: device-registry + pos: [760, 260] + size: [130, 60] +boundaries: + - kind: region + label: Kubernetes cluster, eu-central + wraps: [mqtt-broker, ingest, rules, provisioning, device-api] + - kind: security-group + label: Managed DB zone + wraps: [tsdb, device-registry] +connections: + - { from: heat-pump, to: mqtt-broker, label: "8883", variant: emphasis } + - { from: mqtt-broker, to: ingest, label: in-cluster } + - { from: ingest, to: tsdb, label: "5432", variant: emphasis } + - { from: ingest, to: rules, label: gRPC } + - { from: device-api, to: device-registry, label: "5432" } diff --git a/examples/arc42-iot-telemetry/decisions/0001-mqtt-with-mutual-tls.archify-decision b/examples/arc42-iot-telemetry/decisions/0001-mqtt-with-mutual-tls.archify-decision new file mode 100644 index 0000000..42d8b45 --- /dev/null +++ b/examples/arc42-iot-telemetry/decisions/0001-mqtt-with-mutual-tls.archify-decision @@ -0,0 +1,21 @@ +schema_version: 1 +decision: + id: mqtt-with-mutual-tls + title: MQTT with mutual TLS for device traffic + status: accepted + date: 2026-08-12 + elements: [heat-pump, mqtt-broker, provisioning] + diagrams: [0300-context/technical-context.archify, 0500-building-blocks/level-1.archify] +context: > + Heat pumps sit behind home routers on slow and flaky links. + The first prototype polled an HTTPS endpoint and drained + mobile data plans; shared API keys leaked from one device. +decision: > + Devices publish over MQTT 3.1.1 on port 8883. Each device + has its own client certificate issued by Provisioning; + the broker rejects any connection without one. +consequences: > + Small messages and one long-lived connection per device. + Certificates must be rotated and revoked, so Provisioning + is a critical building block. Installers need a step to + register the device before it can connect. diff --git a/examples/arc42-iot-telemetry/decisions/0002-timescaledb-for-telemetry.archify-decision b/examples/arc42-iot-telemetry/decisions/0002-timescaledb-for-telemetry.archify-decision new file mode 100644 index 0000000..cc34525 --- /dev/null +++ b/examples/arc42-iot-telemetry/decisions/0002-timescaledb-for-telemetry.archify-decision @@ -0,0 +1,20 @@ +schema_version: 1 +decision: + id: timescaledb-for-telemetry + title: TimescaleDB for telemetry + status: accepted + date: 2026-09-03 + elements: [tsdb, ingest, ops-dashboard] + diagrams: [0500-building-blocks/level-1.archify, 0700-deployment/production.archify] +context: > + The fleet sends about 4,000 readings a second. A plain + PostgreSQL table grew too fast and dashboards slowed down + after a few weeks of data. +decision: > + Store telemetry in TimescaleDB hypertables with hourly + continuous aggregates. Raw data is kept 90 days, rollups + 10 years. The team already runs PostgreSQL. +consequences: > + SQL stays the query language for the API and the + dashboard. Retention jobs must be monitored. Very high + device counts may need sharding later (see risk R1). diff --git a/examples/arc42-iot-telemetry/main.archify b/examples/arc42-iot-telemetry/main.archify new file mode 100644 index 0000000..c0533f7 --- /dev/null +++ b/examples/arc42-iot-telemetry/main.archify @@ -0,0 +1,76 @@ +schema_version: 1 +model: + id: iot-telemetry + name: IoT Telemetry + description: > + An arc42 example: a fictional heat pump maker collects device telemetry + over MQTT, stores it, raises alerts and shows it to operations and customers. + main.archify holds section 3 business context with cards for sections + 1 goals, 2 constraints, 10 quality, 11 risks and 12 glossary; + 0300-context the technical context; 0500-building-blocks section 5; + 0600-runtime section 6; 0700-deployment section 7; decisions/ section 9; + the crosscutting concepts of section 8 are a card on level-1. +diagram_type: architecture +meta: + title: Business context + output: main.html +components: + - ref: homeowner + pos: [40, 60] + size: [130, 60] + - ref: ops-engineer + pos: [40, 160] + size: [130, 60] + - ref: installer + pos: [40, 260] + size: [130, 60] + - ref: telemetry-platform + pos: [280, 160] + size: [150, 60] + - ref: heat-pump + pos: [540, 60] + size: [130, 60] + - ref: push-service + pos: [540, 160] + size: [130, 60] + - ref: service-desk + pos: [540, 260] + size: [130, 60] +connections: + - { from: homeowner, to: telemetry-platform, label: checks } + - { from: ops-engineer, to: telemetry-platform, label: monitors } + - { from: installer, to: telemetry-platform, label: registers } + - { from: heat-pump, to: telemetry-platform, label: telemetry, variant: emphasis } + - { from: telemetry-platform, to: push-service, label: alerts } + - { from: telemetry-platform, to: service-desk, label: tickets } +cards: + - dot: cyan + title: 1 Quality goals + items: + - Reliability, no telemetry lost once accepted + - Timeliness, alert within 60 s of a fault + - Security, every device authenticated + - dot: slate + title: 2 Constraints + items: + - Devices speak MQTT only; firmware by a partner + - Data stays in one EU region + - Team of six; PostgreSQL skills in house + - dot: emerald + title: 10 Quality scenarios + items: + - A fault code reaches the homeowner within 60 s + - Broker restart, devices reconnect, no data lost + - A stolen certificate is revoked within 15 min + - dot: rose + title: 11 Risks + items: + - R1 fleet growth beyond one TSDB node + - R2 partner firmware delays certificate rotation + - dot: violet + title: 12 Glossary + items: + - Telemetry, readings a device sends + - Rollup, hourly aggregate of telemetry + - Provisioning, giving a device its identity + - Fault code, error number from the device diff --git a/examples/arc42-iot-telemetry/registry/building-blocks.archify-registry b/examples/arc42-iot-telemetry/registry/building-blocks.archify-registry new file mode 100644 index 0000000..55631d1 --- /dev/null +++ b/examples/arc42-iot-telemetry/registry/building-blocks.archify-registry @@ -0,0 +1,61 @@ +schema_version: 1 +elements: + mqtt-broker: + type: messagebus + label: MQTT broker + sublabel: mutual TLS + description: > + Terminates device connections; one topic per device. + ingest: + type: backend + label: Ingest + sublabel: Go + brand: go + description: > + Decodes, validates and stores telemetry; forwards it to the rules. + diagram: 0500-building-blocks/ingest.archify + tsdb: + type: database + label: Time series DB + sublabel: TimescaleDB + brand: postgresql + description: > + Raw telemetry for 90 days and hourly rollups for 10 years. + rules: + type: backend + label: Rules engine + sublabel: alerting + description: > + Evaluates thresholds and fault codes; raises alerts. + provisioning: + type: security + label: Provisioning + sublabel: device certs + description: > + Registers devices and issues their client certificates. + device-registry: + type: database + label: Device registry + sublabel: PostgreSQL + brand: postgresql + description: > + Devices, owners, firmware versions and certificate state. + device-api: + type: backend + label: Device API + sublabel: REST + description: > + Serves telemetry and device data to the customer app. + ops-dashboard: + type: frontend + label: Ops dashboard + sublabel: Grafana + brand: grafana + description: > + Fleet view for the operations team, read only on the TSDB. + customer-app: + type: frontend + label: Customer app + sublabel: mobile + description: > + Shows the homeowner their heat pump and its alerts. diff --git a/examples/arc42-iot-telemetry/registry/people.archify-registry b/examples/arc42-iot-telemetry/registry/people.archify-registry new file mode 100644 index 0000000..8dd89d6 --- /dev/null +++ b/examples/arc42-iot-telemetry/registry/people.archify-registry @@ -0,0 +1,20 @@ +schema_version: 1 +elements: + homeowner: + type: external + label: Homeowner + sublabel: customer app + description: > + Owns a heat pump; checks temperatures and gets fault alerts. + ops-engineer: + type: external + label: Ops engineer + sublabel: operations team + description: > + Watches the fleet, handles alerts and plans service visits. + installer: + type: external + label: Installer + sublabel: field service + description: > + Mounts heat pumps on site and registers them with the platform. diff --git a/examples/arc42-iot-telemetry/registry/systems.archify-registry b/examples/arc42-iot-telemetry/registry/systems.archify-registry new file mode 100644 index 0000000..52a2c46 --- /dev/null +++ b/examples/arc42-iot-telemetry/registry/systems.archify-registry @@ -0,0 +1,27 @@ +schema_version: 1 +elements: + telemetry-platform: + type: cloud + label: IoT Telemetry + sublabel: the system + description: > + Everything we build and run; broker, ingest, stores, rules and apps. + diagram: 0500-building-blocks/level-1.archify + heat-pump: + type: external + label: Heat pump + sublabel: field device + description: > + Sends telemetry every 30 seconds over MQTT; built by a partner. + push-service: + type: external + label: Push service + sublabel: mobile push + description: > + Delivers push notifications to the customer app. + service-desk: + type: external + label: Service desk + sublabel: ticketing + description: > + Opens service tickets for faults that need a visit. diff --git a/examples/arc42-team-wiki/0300-context/technical-context.archify b/examples/arc42-team-wiki/0300-context/technical-context.archify new file mode 100644 index 0000000..2d0f65b --- /dev/null +++ b/examples/arc42-team-wiki/0300-context/technical-context.archify @@ -0,0 +1,26 @@ +schema_version: 1 +diagram_type: architecture +meta: + title: Technical context + output: technical-context.html +components: + - ref: engineer + pos: [40, 60] + size: [130, 60] + - ref: wiki-admin + pos: [40, 260] + size: [130, 60] + - ref: wiki + pos: [280, 160] + size: [150, 60] + - ref: idp + pos: [520, 60] + size: [150, 60] + - ref: object-store + pos: [520, 260] + size: [150, 60] +connections: + - { from: engineer, to: wiki, label: HTTPS, variant: emphasis } + - { from: wiki-admin, to: wiki, label: kubectl } + - { from: wiki, to: idp, label: OIDC, variant: security } + - { from: wiki, to: object-store, label: S3 API } diff --git a/examples/arc42-team-wiki/0500-building-blocks/level-1.archify b/examples/arc42-team-wiki/0500-building-blocks/level-1.archify new file mode 100644 index 0000000..20b2a3d --- /dev/null +++ b/examples/arc42-team-wiki/0500-building-blocks/level-1.archify @@ -0,0 +1,47 @@ +schema_version: 1 +diagram_type: architecture +meta: + title: Building blocks - level 1 + output: level-1.html +decisions: [postgres-full-text-search] +components: + - ref: engineer + pos: [40, 160] + size: [130, 60] + - ref: web + pos: [250, 160] + size: [130, 60] + - ref: api + pos: [460, 160] + size: [130, 60] + - ref: db + pos: [460, 360] + size: [130, 60] + - ref: backup-job + pos: [670, 360] + size: [130, 60] + - ref: idp + pos: [670, 60] + size: [130, 60] + - ref: object-store + pos: [880, 160] + size: [130, 60] +boundaries: + - kind: region + label: Team Wiki + wraps: [web, api, db, backup-job] +connections: + - { from: engineer, to: web, label: HTTPS, variant: emphasis } + - { from: web, to: api, label: JSON, variant: emphasis } + - { from: api, to: db, label: SQL, labelAt: [525, 234], decisions: [postgres-full-text-search] } + - { from: api, to: idp, label: OIDC, variant: security } + - { from: api, to: object-store, label: files } + - { from: backup-job, to: db, label: dump } + - { from: backup-job, to: object-store, label: upload } +cards: + - dot: amber + title: 8 Crosscutting concepts + items: + - Access - every request checked against space groups + - Logs - JSON to stdout, collected by the cluster + - Config - environment variables, secrets from the vault diff --git a/examples/arc42-team-wiki/0500-building-blocks/wiki-api.archify b/examples/arc42-team-wiki/0500-building-blocks/wiki-api.archify new file mode 100644 index 0000000..494b95b --- /dev/null +++ b/examples/arc42-team-wiki/0500-building-blocks/wiki-api.archify @@ -0,0 +1,55 @@ +schema_version: 1 +diagram_type: architecture +meta: + title: Building blocks - level 2, Wiki API + output: wiki-api.html +components: + - ref: web + pos: [40, 160] + size: [130, 60] + - id: auth + type: security + label: Auth + sublabel: OIDC session + pos: [250, 60] + size: [130, 60] + - id: pages + type: backend + label: Pages + sublabel: revisions + pos: [250, 160] + size: [130, 60] + - id: search + type: backend + label: Search + sublabel: full-text + pos: [250, 260] + size: [130, 60] + decisions: [postgres-full-text-search] + - id: attachments + type: backend + label: Attachments + pos: [250, 360] + size: [130, 60] + - ref: idp + pos: [460, 60] + size: [130, 60] + - ref: db + pos: [460, 210] + size: [130, 60] + - ref: object-store + pos: [460, 360] + size: [130, 60] +boundaries: + - kind: region + label: Wiki API + wraps: [auth, pages, search, attachments] +connections: + - { from: web, to: auth, label: sign in, variant: security } + - { from: web, to: pages, label: edit, labelAt: [222, 182] } + - { from: web, to: search, label: query } + - { from: web, to: attachments, label: upload } + - { from: auth, to: idp, label: OIDC, variant: security } + - { from: pages, to: db, label: SQL } + - { from: search, to: db, label: SQL } + - { from: attachments, to: object-store, label: S3 } diff --git a/examples/arc42-team-wiki/0600-runtime/search-page.archify b/examples/arc42-team-wiki/0600-runtime/search-page.archify new file mode 100644 index 0000000..ae302b4 --- /dev/null +++ b/examples/arc42-team-wiki/0600-runtime/search-page.archify @@ -0,0 +1,20 @@ +schema_version: 1 +diagram_type: sequence +meta: + title: Runtime - search and open a page + output: search-page.html +participants: + - ref: engineer + - ref: web + - ref: api + - { ref: db, label: DB } + - { ref: object-store, label: Object store } +messages: + - { from: engineer, to: web, y: 160, label: type query, variant: emphasis } + - { from: web, to: api, y: 210, label: GET /search } + - { from: api, to: db, y: 260, label: full-text query } + - { from: db, to: api, y: 310, label: ranked pages, variant: return } + - { from: api, to: web, y: 360, label: results, variant: return } + - { from: web, to: api, y: 410, label: GET /pages/id } + - { from: api, to: object-store, y: 460, label: signed URL } + - { from: api, to: web, y: 510, label: page, variant: return } diff --git a/examples/arc42-team-wiki/0600-runtime/sign-in.archify b/examples/arc42-team-wiki/0600-runtime/sign-in.archify new file mode 100644 index 0000000..f48de74 --- /dev/null +++ b/examples/arc42-team-wiki/0600-runtime/sign-in.archify @@ -0,0 +1,19 @@ +schema_version: 1 +diagram_type: sequence +meta: + title: Runtime - sign in + output: sign-in.html +decisions: [sso-only-via-company-idp] +participants: + - ref: engineer + - ref: web + - ref: api + - { ref: idp, label: Company IdP } +messages: + - { from: engineer, to: web, y: 160, label: open wiki, variant: emphasis } + - { from: web, to: api, y: 210, label: GET /session } + - { from: api, to: web, y: 260, label: redirect, variant: return } + - { from: web, to: idp, y: 310, label: OIDC login, variant: security } + - { from: idp, to: api, y: 360, label: code, variant: return } + - { from: api, to: idp, y: 410, label: token exchange, variant: security } + - { from: api, to: web, y: 460, label: session cookie, variant: return } diff --git a/examples/arc42-team-wiki/0700-deployment/production.archify b/examples/arc42-team-wiki/0700-deployment/production.archify new file mode 100644 index 0000000..f03255b --- /dev/null +++ b/examples/arc42-team-wiki/0700-deployment/production.archify @@ -0,0 +1,48 @@ +schema_version: 1 +diagram_type: architecture +meta: + title: Deployment - production + output: production.html +components: + - ref: engineer + pos: [40, 160] + size: [130, 60] + - id: ingress + type: security + label: Ingress + sublabel: TLS + pos: [250, 160] + size: [130, 60] + - ref: web + pos: [460, 60] + size: [130, 60] + - ref: api + pos: [460, 160] + size: [130, 60] + - ref: db + pos: [670, 160] + size: [130, 60] + - ref: backup-job + pos: [670, 360] + size: [130, 60] + - ref: idp + pos: [460, 460] + size: [130, 60] + - ref: object-store + pos: [880, 460] + size: [130, 60] +boundaries: + - kind: region + label: Company cluster + wraps: [ingress, web, api, db, backup-job] + - kind: security-group + label: Namespace team-wiki + wraps: [web, api, db, backup-job] +connections: + - { from: engineer, to: ingress, label: HTTPS, variant: emphasis } + - { from: ingress, to: web, label: static } + - { from: ingress, to: api, label: /api, variant: emphasis } + - { from: api, to: db, label: SQL } + - { from: api, to: idp, label: OIDC, variant: security, labelAt: [525, 234] } + - { from: backup-job, to: db, label: dump } + - { from: backup-job, to: object-store, label: S3 } diff --git a/examples/arc42-team-wiki/decisions/0001-postgres-full-text-search.archify-decision b/examples/arc42-team-wiki/decisions/0001-postgres-full-text-search.archify-decision new file mode 100644 index 0000000..ab9ee26 --- /dev/null +++ b/examples/arc42-team-wiki/decisions/0001-postgres-full-text-search.archify-decision @@ -0,0 +1,20 @@ +schema_version: 1 +decision: + id: postgres-full-text-search + title: PostgreSQL full-text search, no search engine + status: accepted + date: 2026-10-05 + elements: [api, db] + diagrams: [0500-building-blocks/level-1.archify, 0500-building-blocks/wiki-api.archify] +context: > + The wiki holds a few thousand pages for one team. A + separate search engine would be one more service to run, + back up and keep in sync. +decision: > + Search uses PostgreSQL full-text search on a generated + column of each page. The API queries it in the same + transaction as the page data. +consequences: > + Results are never stale and backups cover search too. + Ranking is simpler than a search engine. Revisit when + the wiki grows past 100000 pages. diff --git a/examples/arc42-team-wiki/decisions/0002-sso-only-via-company-idp.archify-decision b/examples/arc42-team-wiki/decisions/0002-sso-only-via-company-idp.archify-decision new file mode 100644 index 0000000..1368402 --- /dev/null +++ b/examples/arc42-team-wiki/decisions/0002-sso-only-via-company-idp.archify-decision @@ -0,0 +1,19 @@ +schema_version: 1 +decision: + id: sso-only-via-company-idp + title: Sign-in only through the company identity provider + status: accepted + date: 2026-10-12 + elements: [idp, api, web] + diagrams: [0300-context/technical-context.archify, 0600-runtime/sign-in.archify] +context: > + Leavers kept access to the old wiki because it had its + own passwords. Nobody owned the user list. +decision: > + The wiki has no local accounts. Users sign in with OIDC + at the company identity provider; team groups map to + wiki spaces. +consequences: > + Offboarding removes wiki access at once. The wiki cannot + be used when the identity provider is down. The admin + needs a break-glass account kept in the vault. diff --git a/examples/arc42-team-wiki/main.archify b/examples/arc42-team-wiki/main.archify new file mode 100644 index 0000000..021886d --- /dev/null +++ b/examples/arc42-team-wiki/main.archify @@ -0,0 +1,66 @@ +schema_version: 1 +model: + id: team-wiki + name: Team Wiki + description: > + An arc42 example: a small self-hosted wiki for an engineering + team. Sections 1 goals, 2 constraints, 3 business context, + 10 quality, 11 risks and 12 glossary are on this overview; + 0300-context holds 3 technical context, 0500-building-blocks + 5 building blocks, 0600-runtime 6 runtime, 0700-deployment + 7 deployment and decisions 9 architecture decisions. +diagram_type: architecture +meta: + title: Team Wiki - business context + output: main.html +decisions: [sso-only-via-company-idp] +components: + - ref: engineer + pos: [40, 60] + size: [130, 60] + - ref: wiki-admin + pos: [40, 260] + size: [130, 60] + - ref: wiki + pos: [280, 160] + size: [150, 60] + - ref: idp + pos: [520, 60] + size: [150, 60] + - ref: object-store + pos: [520, 260] + size: [150, 60] +connections: + - { from: engineer, to: wiki, label: reads, variant: emphasis } + - { from: wiki-admin, to: wiki, label: runs } + - { from: wiki, to: idp, label: sign-in, variant: security } + - { from: wiki, to: object-store, label: files } +cards: + - dot: cyan + title: 1 Quality goals + items: + - Findability - any page found in two searches + - Security - only current staff can read + - Operability - one person runs it in an hour a week + - dot: slate + title: 2 Constraints + items: + - Runs on the company Kubernetes cluster + - Sign-in only via the company identity provider + - dot: emerald + title: 10 Quality scenarios + items: + - A search over 5000 pages answers in under 1 s + - A leaver loses access within 5 minutes + - The admin restores last night's state in 30 minutes + - dot: rose + title: 11 Risks + items: + - Identity provider outage blocks all sign-ins + - Backups untested until a restore drill is run + - dot: violet + title: 12 Glossary + items: + - Space - pages of one team, mapped to a group + - Revision - one saved version of a page + - Attachment - a file stored beside a page diff --git a/examples/arc42-team-wiki/registry/building-blocks.archify-registry b/examples/arc42-team-wiki/registry/building-blocks.archify-registry new file mode 100644 index 0000000..db8fbd7 --- /dev/null +++ b/examples/arc42-team-wiki/registry/building-blocks.archify-registry @@ -0,0 +1,33 @@ +schema_version: 1 +elements: + web: + type: frontend + label: Web App + sublabel: React + brand: react + description: > + Page editor, viewer and search box in the browser; talks + only to the API. + api: + type: backend + label: Wiki API + sublabel: REST + description: > + Pages, search, attachments and access checks; the only + writer of the database. + diagram: 0500-building-blocks/wiki-api.archify + db: + type: database + label: Database + sublabel: PostgreSQL + brand: postgresql + description: > + Pages, revisions, users and the full-text index; the + source of truth. + backup-job: + type: backend + label: Backup job + sublabel: nightly + description: > + Dumps the database at 02:00 and writes it to the backup + bucket; keeps 30 days. diff --git a/examples/arc42-team-wiki/registry/people.archify-registry b/examples/arc42-team-wiki/registry/people.archify-registry new file mode 100644 index 0000000..3b9b863 --- /dev/null +++ b/examples/arc42-team-wiki/registry/people.archify-registry @@ -0,0 +1,15 @@ +schema_version: 1 +elements: + engineer: + type: external + label: Engineer + sublabel: team member + description: > + Reads and edits pages, searches, attaches files; signs in + with the company account. + wiki-admin: + type: external + label: Wiki admin + sublabel: platform team + description: > + Runs the wiki, restores backups and manages spaces. diff --git a/examples/arc42-team-wiki/registry/systems.archify-registry b/examples/arc42-team-wiki/registry/systems.archify-registry new file mode 100644 index 0000000..9b15766 --- /dev/null +++ b/examples/arc42-team-wiki/registry/systems.archify-registry @@ -0,0 +1,24 @@ +schema_version: 1 +elements: + wiki: + type: cloud + label: Team Wiki + sublabel: the system + description: > + Everything we build and run; web app, API, database and + the backup job. + diagram: 0500-building-blocks/level-1.archify + idp: + type: security + label: Identity provider + sublabel: company SSO + description: > + The company identity provider; signs users in over OIDC + and owns team membership. + object-store: + type: external + label: Object storage + sublabel: S3-compatible + description: > + Company object storage; holds attachments and nightly + backups in separate buckets. diff --git a/examples/archimate-hr-onboarding/0100-business/business-services.archify b/examples/archimate-hr-onboarding/0100-business/business-services.archify new file mode 100644 index 0000000..aa86547 --- /dev/null +++ b/examples/archimate-hr-onboarding/0100-business/business-services.archify @@ -0,0 +1,36 @@ +schema_version: 1 +diagram_type: architecture +meta: + title: Business actors and services + output: business-services.html +components: + - ref: hr + pos: [40, 60] + size: [130, 60] + - ref: manager + pos: [40, 160] + size: [130, 60] + - ref: service-desk + pos: [40, 260] + size: [130, 60] + - ref: onboard + pos: [250, 160] + size: [150, 60] + diagram: 0100-business/onboard-employee.archify + - ref: onboarding-svc + pos: [480, 60] + size: [130, 60] + - ref: workplace-svc + pos: [480, 260] + size: [130, 60] + - ref: new-hire + pos: [690, 160] + size: [130, 60] +connections: + - { from: hr, to: onboard, label: assigned } + - { from: manager, to: onboard, label: assigned } + - { from: service-desk, to: onboard, label: assigned } + - { from: onboard, to: onboarding-svc, label: realizes } + - { from: onboard, to: workplace-svc, label: realizes } + - { from: onboarding-svc, to: new-hire, label: serves, variant: emphasis } + - { from: workplace-svc, to: new-hire, label: serves } diff --git a/examples/archimate-hr-onboarding/0100-business/onboard-employee.archify b/examples/archimate-hr-onboarding/0100-business/onboard-employee.archify new file mode 100644 index 0000000..f39465c --- /dev/null +++ b/examples/archimate-hr-onboarding/0100-business/onboard-employee.archify @@ -0,0 +1,25 @@ +schema_version: 2 +diagram_type: workflow +meta: + title: Onboard Employee + output: onboard-employee.html + viewBox: [1040, 660] +lanes: + - { id: hr-lane, label: HR } + - { id: manager-lane, label: Hiring manager } + - { id: desk-lane, label: IT service desk } + - { id: hire-lane, label: New hire } +mainPath: [contract-signed, record, request, create-accounts, issue-laptop, first-day] +nodes: + - { ref: contract-signed, lane: hr-lane, col: 0, width: 120 } + - { id: record, lane: hr-lane, col: 1, type: backend, label: Create record, tag: Business Process } + - { id: request, lane: manager-lane, col: 2, type: frontend, label: Request access, tag: Business Process } + - { ref: create-accounts, lane: desk-lane, col: 3, width: 120, decisions: [hr-system-drives-identity] } + - { ref: issue-laptop, lane: desk-lane, col: 4, decisions: [zero-touch-laptops] } + - { ref: first-day, lane: hire-lane, col: 5 } +edges: + - { from: contract-signed, to: record, label: triggers } + - { from: record, to: request, label: notifies } + - { from: request, to: create-accounts, label: ticket } + - { from: create-accounts, to: issue-laptop, label: then } + - { from: issue-laptop, to: first-day, label: hand over } diff --git a/examples/archimate-hr-onboarding/0200-application/application-components.archify b/examples/archimate-hr-onboarding/0200-application/application-components.archify new file mode 100644 index 0000000..e5951ae --- /dev/null +++ b/examples/archimate-hr-onboarding/0200-application/application-components.archify @@ -0,0 +1,44 @@ +schema_version: 1 +diagram_type: architecture +meta: + title: Application components, services and data + output: application-components.html +components: + - ref: provisioning-svc + pos: [250, 60] + size: [130, 60] + - ref: portal + pos: [460, 60] + size: [130, 60] + - ref: device-svc + pos: [670, 60] + size: [130, 60] + - ref: hr-system + pos: [40, 160] + size: [130, 60] + - ref: iam + pos: [250, 160] + size: [130, 60] + - ref: itsm + pos: [460, 160] + size: [130, 60] + - ref: mdm-app + pos: [670, 160] + size: [130, 60] + - ref: employee-record + pos: [40, 260] + size: [130, 60] + - ref: account + pos: [250, 260] + size: [130, 60] + - ref: asset + pos: [460, 260] + size: [130, 60] +connections: + - { from: iam, to: provisioning-svc, label: realizes } + - { from: itsm, to: portal, label: realizes } + - { from: mdm-app, to: device-svc, label: realizes } + - { from: hr-system, to: employee-record, label: writes, labelAt: [105, 234] } + - { from: iam, to: account, label: writes, labelAt: [315, 234] } + - { from: itsm, to: asset, label: writes, labelAt: [525, 234] } + - { from: mdm-app, to: asset, label: reads } diff --git a/examples/archimate-hr-onboarding/0200-application/application-cooperation.archify b/examples/archimate-hr-onboarding/0200-application/application-cooperation.archify new file mode 100644 index 0000000..89f39d9 --- /dev/null +++ b/examples/archimate-hr-onboarding/0200-application/application-cooperation.archify @@ -0,0 +1,29 @@ +schema_version: 1 +diagram_type: architecture +meta: + title: Application cooperation + output: application-cooperation.html +decisions: [hr-system-drives-identity] +components: + - ref: hr-system + pos: [40, 160] + size: [130, 60] + - ref: iam + pos: [250, 60] + size: [130, 60] + diagram: 0200-application/application-components.archify + - ref: itsm + pos: [250, 260] + size: [130, 60] + - ref: collab + pos: [460, 60] + size: [130, 60] + - ref: mdm-app + pos: [460, 260] + size: [130, 60] +connections: + - { from: hr-system, to: iam, label: joiner event, variant: emphasis, decisions: [hr-system-drives-identity] } + - { from: hr-system, to: itsm, label: laptop request } + - { from: iam, to: collab, label: provisions } + - { from: iam, to: mdm-app, label: users } + - { from: itsm, to: mdm-app, label: assigns } diff --git a/examples/archimate-hr-onboarding/0300-technology/infrastructure.archify b/examples/archimate-hr-onboarding/0300-technology/infrastructure.archify new file mode 100644 index 0000000..63dd774 --- /dev/null +++ b/examples/archimate-hr-onboarding/0300-technology/infrastructure.archify @@ -0,0 +1,42 @@ +schema_version: 1 +diagram_type: architecture +meta: + title: Technology layer + output: infrastructure.html +decisions: [zero-touch-laptops] +components: + - ref: hr-saas + pos: [40, 60] + size: [130, 60] + - ref: sso + pos: [250, 60] + size: [130, 60] + - ref: directory + pos: [460, 60] + size: [130, 60] + - ref: itsm-saas + pos: [40, 160] + size: [130, 60] + - ref: mdm-saas + pos: [460, 160] + size: [130, 60] + - ref: laptop + pos: [460, 360] + size: [130, 60] + - ref: office-net + pos: [250, 360] + size: [130, 60] +boundaries: + - kind: region + label: SaaS tenants + wraps: [hr-saas, sso, directory, itsm-saas, mdm-saas] + - kind: security-group + label: Office + wraps: [laptop, office-net] +connections: + - { from: directory, to: sso, label: realizes } + - { from: sso, to: hr-saas, label: serves } + - { from: sso, to: itsm-saas, label: serves } + - { from: directory, to: mdm-saas, label: devices, labelAt: [525, 134] } + - { from: mdm-saas, to: laptop, label: manages, labelAt: [525, 234], variant: security, decisions: [zero-touch-laptops] } + - { from: laptop, to: office-net, label: connects } diff --git a/examples/archimate-hr-onboarding/decisions/0001-hr-system-drives-identity.archify-decision b/examples/archimate-hr-onboarding/decisions/0001-hr-system-drives-identity.archify-decision new file mode 100644 index 0000000..5a21c77 --- /dev/null +++ b/examples/archimate-hr-onboarding/decisions/0001-hr-system-drives-identity.archify-decision @@ -0,0 +1,20 @@ +schema_version: 1 +decision: + id: hr-system-drives-identity + title: The HR system drives identity + status: accepted + date: 2026-09-08 + elements: [hr-system, iam, account, employee-record] + diagrams: [0200-application/application-cooperation.archify, 0100-business/onboard-employee.archify] +context: > + Accounts were created by hand from emails sent by HR. + New hires waited days for access, and leavers kept + accounts for weeks after their last day. +decision: > + The HR system is the source of truth for joiners and + leavers. Identity management reads its events and + creates, changes and disables accounts automatically. +consequences: > + No account without an employee record. HR data quality + now decides access, so start dates must be right. The + service desk only handles exceptions. diff --git a/examples/archimate-hr-onboarding/decisions/0002-zero-touch-laptops.archify-decision b/examples/archimate-hr-onboarding/decisions/0002-zero-touch-laptops.archify-decision new file mode 100644 index 0000000..7de9d0a --- /dev/null +++ b/examples/archimate-hr-onboarding/decisions/0002-zero-touch-laptops.archify-decision @@ -0,0 +1,20 @@ +schema_version: 1 +decision: + id: zero-touch-laptops + title: Zero-touch enrollment for laptops + status: accepted + date: 2026-10-05 + elements: [mdm-app, mdm-saas, laptop, device-svc, asset] + diagrams: [0300-technology/infrastructure.archify, 0100-business/onboard-employee.archify] +context: > + Every laptop was imaged by hand at the service desk, + which took half a day per device and left settings that + differed from one laptop to the next. +decision: > + Laptops are registered in device management at purchase. + They configure themselves at first sign-in over any + internet connection; the office network needs no VPN. +consequences: > + Laptops can be shipped straight to the new hire. A lost + laptop is wiped remotely. Setup depends on the MDM + tenant being reachable on the first day. diff --git a/examples/archimate-hr-onboarding/main.archify b/examples/archimate-hr-onboarding/main.archify new file mode 100644 index 0000000..a174f05 --- /dev/null +++ b/examples/archimate-hr-onboarding/main.archify @@ -0,0 +1,59 @@ +schema_version: 1 +model: + id: hr-onboarding + name: HR Onboarding + description: > + An ArchiMate example: how a new employee is onboarded, from signed + contract to first day. Business, application and technology layers + map to folders; each element's ArchiMate type is shown as its tag. +diagram_type: architecture +meta: + title: HR Onboarding - layered view + output: main.html +components: + - ref: new-hire + pos: [40, 70] + size: [170, 60] + - ref: onboarding-svc + pos: [270, 70] + size: [170, 60] + - ref: onboard + pos: [500, 70] + size: [170, 60] + - ref: portal + pos: [40, 270] + size: [170, 60] + - ref: iam + pos: [270, 270] + size: [170, 60] + - ref: provisioning-svc + pos: [500, 270] + size: [170, 60] + - ref: office-net + pos: [40, 470] + size: [170, 60] + - ref: sso + pos: [270, 470] + size: [170, 60] + - ref: directory + pos: [500, 470] + size: [170, 60] +boundaries: + - kind: region + label: Business layer + wraps: [new-hire, onboarding-svc, onboard] + - kind: region + label: Application layer + wraps: [portal, iam, provisioning-svc] + - kind: region + label: Technology layer + wraps: [office-net, sso, directory] +connections: + - { from: onboarding-svc, to: new-hire, label: serves, variant: emphasis } + - { from: onboard, to: onboarding-svc, label: realizes } + - { from: portal, to: new-hire, label: serves } + - { from: provisioning-svc, to: onboard, label: serves } + - { from: iam, to: provisioning-svc, label: realizes } + - { from: office-net, to: portal, label: serves } + - { from: sso, to: iam, label: serves } + - { from: directory, to: sso, label: realizes } diff --git a/examples/archimate-hr-onboarding/registry/application.archify-registry b/examples/archimate-hr-onboarding/registry/application.archify-registry new file mode 100644 index 0000000..4d96413 --- /dev/null +++ b/examples/archimate-hr-onboarding/registry/application.archify-registry @@ -0,0 +1,81 @@ +schema_version: 1 +elements: + hr-system: + type: backend + label: HR system + sublabel: App Component + tag: App Component + description: > + Holds employee records and contracts; the source of truth for joiners. + diagram: 0200-application/application-cooperation.archify + iam: + type: security + label: Identity mgmt + sublabel: App Component + tag: App Component + description: > + Creates and removes accounts from HR events; single sign-on for all apps. + diagram: 0200-application/application-components.archify + itsm: + type: backend + label: IT service mgmt + sublabel: App Component + tag: App Component + description: > + Tickets, requests and the asset inventory of the IT service desk. + mdm-app: + type: backend + label: Device mgmt + sublabel: App Component + tag: App Component + description: > + Enrolls laptops, pushes policies and apps, wipes lost devices. + collab: + type: backend + label: Mail and chat + sublabel: App Component + tag: App Component + description: > + Mailbox, calendar and chat; accounts provisioned by identity management. + provisioning-svc: + type: cloud + label: Provisioning + sublabel: App Service + tag: App Service + description: > + Account create, change and disable, triggered by the HR system. + device-svc: + type: cloud + label: Enrollment + sublabel: App Service + tag: App Service + description: > + Zero-touch enrollment; the laptop configures itself at first sign-in. + portal: + type: frontend + label: Service portal + sublabel: App Interface + tag: App Interface + description: > + Where managers request equipment and access for a new hire. + employee-record: + type: database + label: Employee record + sublabel: Data Object + tag: Data Object + description: > + Name, role, department, manager and start date of an employee. + account: + type: database + label: Account + sublabel: Data Object + tag: Data Object + description: > + User id, groups and licences of one person. + asset: + type: database + label: Asset + sublabel: Data Object + tag: Data Object + description: > + A laptop with serial number, owner and enrollment state. diff --git a/examples/archimate-hr-onboarding/registry/business.archify-registry b/examples/archimate-hr-onboarding/registry/business.archify-registry new file mode 100644 index 0000000..a8dd8e5 --- /dev/null +++ b/examples/archimate-hr-onboarding/registry/business.archify-registry @@ -0,0 +1,81 @@ +schema_version: 1 +elements: + new-hire: + type: external + label: New hire + sublabel: Business Actor + tag: Business Actor + description: > + The person joining the company; signs the contract and starts on day one. + hr: + type: external + label: HR officer + sublabel: Business Role + tag: Business Role + description: > + Prepares the contract and the employee record; owns the onboarding process. + manager: + type: external + label: Hiring manager + sublabel: Business Role + tag: Business Role + description: > + Requests access and equipment for the new hire and plans the first day. + service-desk: + type: external + label: IT service desk + sublabel: Business Role + tag: Business Role + description: > + Creates accounts, prepares the laptop and hands it over. + onboard: + type: backend + label: Onboard Employee + sublabel: Business Process + tag: Business Process + description: > + From signed contract to a productive first day. + diagram: 0100-business/onboard-employee.archify + onboarding-svc: + type: cloud + label: Onboarding + sublabel: Business Service + tag: Business Service + description: > + What the new hire gets from HR; contract, record, welcome and first day plan. + diagram: 0100-business/business-services.archify + workplace-svc: + type: cloud + label: Workplace setup + sublabel: Business Service + tag: Business Service + description: > + Accounts and a ready laptop, delivered by the IT service desk. + contract-signed: + type: messagebus + label: Contract signed + sublabel: Business Event + tag: Business Event + description: > + Starts the process; HR records the start date. + create-accounts: + type: backend + label: Create accounts + sublabel: Business Process + tag: Business Process + description: > + Service desk confirms the accounts the identity system provisioned. + issue-laptop: + type: backend + label: Issue laptop + sublabel: Business Process + tag: Business Process + description: > + An enrolled laptop is assigned and handed over. + first-day: + type: messagebus + label: First day + sublabel: Business Event + tag: Business Event + description: > + The new hire signs in for the first time; the process ends. diff --git a/examples/archimate-hr-onboarding/registry/technology.archify-registry b/examples/archimate-hr-onboarding/registry/technology.archify-registry new file mode 100644 index 0000000..2eb9d03 --- /dev/null +++ b/examples/archimate-hr-onboarding/registry/technology.archify-registry @@ -0,0 +1,53 @@ +schema_version: 1 +elements: + hr-saas: + type: cloud + label: HR tenant + sublabel: Node + tag: Node + description: > + The SaaS tenant that runs the HR system. + diagram: 0300-technology/infrastructure.archify + itsm-saas: + type: cloud + label: ITSM tenant + sublabel: Node + tag: Node + description: > + The SaaS tenant that runs IT service management. + mdm-saas: + type: cloud + label: MDM tenant + sublabel: Node + tag: Node + description: > + The SaaS tenant that runs device management. + directory: + type: backend + label: Directory + sublabel: System Software + tag: System Software + description: > + Cloud directory service; users, groups and devices. + diagram: 0300-technology/infrastructure.archify + sso: + type: security + label: Single sign-on + sublabel: Tech Service + tag: Tech Service + description: > + SAML and OIDC sign-in for every SaaS tenant, backed by the directory. + laptop: + type: frontend + label: Laptop + sublabel: Device + tag: Device + description: > + Company laptop, enrolled before it is handed over. + office-net: + type: messagebus + label: Office network + sublabel: Network + tag: Network + description: > + Wired and wireless network of the office; internet only, no VPN. diff --git a/examples/archimate-insurance-claims/0100-business/business-layer.archify b/examples/archimate-insurance-claims/0100-business/business-layer.archify new file mode 100644 index 0000000..f24b587 --- /dev/null +++ b/examples/archimate-insurance-claims/0100-business/business-layer.archify @@ -0,0 +1,31 @@ +schema_version: 1 +diagram_type: architecture +meta: + title: Business layer + output: business-layer.html +components: + - ref: customer + pos: [40, 160] + size: [130, 60] + - ref: insurant + pos: [250, 160] + size: [130, 60] + - ref: claim-registration + pos: [460, 60] + size: [150, 60] + - ref: claim-payment + pos: [460, 260] + size: [150, 60] + - ref: handle-claim + pos: [690, 160] + size: [150, 60] + - ref: claims-handler + pos: [920, 160] + size: [130, 60] +connections: + - { from: customer, to: insurant, label: assigned to } + - { from: claim-registration, to: insurant, label: serves, variant: emphasis } + - { from: claim-payment, to: insurant, label: serves } + - { from: handle-claim, to: claim-registration, label: realizes } + - { from: handle-claim, to: claim-payment, label: realizes } + - { from: claims-handler, to: handle-claim, label: assigned to } diff --git a/examples/archimate-insurance-claims/0100-business/handle-claim.archify b/examples/archimate-insurance-claims/0100-business/handle-claim.archify new file mode 100644 index 0000000..94a4a2d --- /dev/null +++ b/examples/archimate-insurance-claims/0100-business/handle-claim.archify @@ -0,0 +1,29 @@ +schema_version: 2 +diagram_type: workflow +meta: + title: Handle Claim + output: handle-claim.html + viewBox: [840, 534] +lanes: + - { id: insurant-lane, label: Insurant } + - { id: handler-lane, label: Claims handler } + - { id: systems-lane, label: Applications } +mainPath: [damage, register, accept, valuate, pay] +nodes: + - { id: damage, lane: insurant-lane, col: 0, type: external, label: Damage occurs, tag: Business Event } + - { ref: insurant, lane: insurant-lane, col: 5 } + - { id: register, lane: handler-lane, col: 1, type: backend, label: Register, tag: Business Process } + - { id: accept, lane: handler-lane, col: 2, type: security, label: Accept, sublabel: check coverage, tag: Business Process } + - { id: valuate, lane: handler-lane, col: 3, type: backend, label: Valuate, tag: Business Process } + - { id: pay, lane: handler-lane, col: 4, type: backend, label: Pay, tag: Business Process } + - { ref: claims-app, lane: systems-lane, col: 2 } + - { ref: payment, lane: systems-lane, col: 4 } +edges: + - { from: damage, to: register, label: report } + - { from: register, to: accept } + - { from: accept, to: valuate, label: covered } + - { from: valuate, to: pay, label: approved } + - { from: pay, to: insurant, label: paid } + - { from: accept, to: insurant, label: rejected, role: branch, variant: dashed } + - { from: claims-app, to: accept, label: serves, role: async } + - { from: payment, to: pay, label: serves, role: async } diff --git a/examples/archimate-insurance-claims/0200-application/application-cooperation.archify b/examples/archimate-insurance-claims/0200-application/application-cooperation.archify new file mode 100644 index 0000000..60fd045 --- /dev/null +++ b/examples/archimate-insurance-claims/0200-application/application-cooperation.archify @@ -0,0 +1,32 @@ +schema_version: 1 +diagram_type: architecture +meta: + title: Application cooperation + output: application-cooperation.html +components: + - ref: portal + pos: [40, 260] + size: [130, 60] + - ref: claims-app + pos: [250, 260] + size: [130, 60] + - ref: crm + pos: [250, 60] + size: [130, 60] + - ref: policy-admin + pos: [460, 160] + size: [130, 60] + decisions: [policies-stay-on-mainframe] + - ref: doc-mgmt + pos: [460, 360] + size: [130, 60] + decisions: [documents-in-object-storage] + - ref: payment + pos: [250, 460] + size: [130, 60] +connections: + - { from: portal, to: claims-app, label: claims, variant: emphasis } + - { from: crm, to: claims-app, label: customer, labelAt: [315, 134] } + - { from: policy-admin, to: claims-app, label: coverage, decisions: [policies-stay-on-mainframe] } + - { from: claims-app, to: doc-mgmt, label: documents } + - { from: claims-app, to: payment, label: payments, labelAt: [315, 334] } diff --git a/examples/archimate-insurance-claims/0200-application/application-structure.archify b/examples/archimate-insurance-claims/0200-application/application-structure.archify new file mode 100644 index 0000000..4550d8b --- /dev/null +++ b/examples/archimate-insurance-claims/0200-application/application-structure.archify @@ -0,0 +1,36 @@ +schema_version: 1 +diagram_type: architecture +meta: + title: Application structure + output: application-structure.html +components: + - ref: portal + pos: [40, 160] + size: [130, 60] + - ref: claims-admin + pos: [250, 160] + size: [130, 60] + - ref: claims-app + pos: [460, 160] + size: [130, 60] + - ref: claim + pos: [460, 360] + size: [130, 60] + - ref: crm + pos: [670, 60] + size: [130, 60] + - ref: customer-file + pos: [880, 60] + size: [130, 60] + - ref: policy-admin + pos: [670, 260] + size: [130, 60] + - ref: policy + pos: [880, 260] + size: [130, 60] +connections: + - { from: claims-admin, to: portal, label: serves, variant: emphasis } + - { from: claims-app, to: claims-admin, label: realizes } + - { from: claims-app, to: claim, label: accesses, labelAt: [525, 234] } + - { from: crm, to: customer-file, label: accesses } + - { from: policy-admin, to: policy, label: accesses } diff --git a/examples/archimate-insurance-claims/0300-technology/infrastructure.archify b/examples/archimate-insurance-claims/0300-technology/infrastructure.archify new file mode 100644 index 0000000..d0e6e2c --- /dev/null +++ b/examples/archimate-insurance-claims/0300-technology/infrastructure.archify @@ -0,0 +1,45 @@ +schema_version: 1 +diagram_type: architecture +meta: + title: Technology layer + output: infrastructure.html +components: + - ref: dmz + pos: [40, 160] + size: [130, 60] + - ref: doc-store + pos: [250, 60] + size: [130, 60] + decisions: [documents-in-object-storage] + - ref: app-servers + pos: [250, 160] + size: [130, 60] + - ref: db-service + pos: [250, 260] + size: [130, 60] + - ref: db-cluster + pos: [250, 360] + size: [130, 60] + - ref: mq + pos: [460, 160] + size: [130, 60] + - ref: mainframe + pos: [670, 160] + size: [130, 60] + decisions: [policies-stay-on-mainframe] + - ref: dc-lan + pos: [670, 360] + size: [130, 60] +boundaries: + - kind: region + label: Data centre + wraps: [doc-store, app-servers, db-service, db-cluster, mq, mainframe, dc-lan] +connections: + - { from: dmz, to: app-servers, label: HTTPS, variant: security } + - { from: app-servers, to: doc-store, label: S3 API } + - { from: db-service, to: app-servers, label: serves } + - { from: db-cluster, to: db-service, label: realizes } + - { from: app-servers, to: mq, label: MQ } + - { from: mq, to: mainframe, label: bridge } + - { from: db-cluster, to: dc-lan, label: LAN } + - { from: mainframe, to: dc-lan, label: LAN, labelAt: [735, 234] } diff --git a/examples/archimate-insurance-claims/decisions/0001-policies-stay-on-mainframe.archify-decision b/examples/archimate-insurance-claims/decisions/0001-policies-stay-on-mainframe.archify-decision new file mode 100644 index 0000000..050a840 --- /dev/null +++ b/examples/archimate-insurance-claims/decisions/0001-policies-stay-on-mainframe.archify-decision @@ -0,0 +1,20 @@ +schema_version: 1 +decision: + id: policies-stay-on-mainframe + title: Policies stay on the mainframe + status: accepted + date: 2026-09-08 + elements: [policy-admin, mainframe, mq, claims-app] + diagrams: [0200-application/application-cooperation.archify, 0300-technology/infrastructure.archify] +context: > + The new claims application needs coverage data for every + claim. Policy administration has run on the mainframe for + twenty years and a migration was estimated at three years. +decision: > + Policy administration stays on the mainframe. The claims + application reads coverage through the message queue bridge + and never copies policies into its own database. +consequences: > + Accepting a claim depends on the mainframe being up during + office hours. The queue bridge must be kept and tested. + A later migration needs its own decision. diff --git a/examples/archimate-insurance-claims/decisions/0002-documents-in-object-storage.archify-decision b/examples/archimate-insurance-claims/decisions/0002-documents-in-object-storage.archify-decision new file mode 100644 index 0000000..efc50f4 --- /dev/null +++ b/examples/archimate-insurance-claims/decisions/0002-documents-in-object-storage.archify-decision @@ -0,0 +1,20 @@ +schema_version: 1 +decision: + id: documents-in-object-storage + title: Claim documents in object storage + status: accepted + date: 2026-10-14 + elements: [doc-mgmt, doc-store, claims-app] + diagrams: [0200-application/application-cooperation.archify, 0300-technology/infrastructure.archify] +context: > + Photos and expert reports were stored as blobs in the claims + database. The database grew by forty gigabytes a month and + backups no longer fitted the nightly window. +decision: > + Document management stores every file in the document store + and keeps only a reference in the claim. The claims + application never writes files itself. +consequences: > + Database backups shrink and stay fast. Documents get their own + retention rules. A claim and its files are restored from two + places after an incident. diff --git a/examples/archimate-insurance-claims/main.archify b/examples/archimate-insurance-claims/main.archify new file mode 100644 index 0000000..fe7cca3 --- /dev/null +++ b/examples/archimate-insurance-claims/main.archify @@ -0,0 +1,59 @@ +schema_version: 1 +model: + id: insurance-claims + name: Insurance Claims + description: > + ArchiMate example: how Halbrook Mutual handles claims. The business, + application and technology layers are mapped to folders, and each + element's ArchiMate type is shown as its tag. +diagram_type: architecture +meta: + title: Insurance Claims - layered view + output: main.html +components: + - ref: insurant + pos: [40, 70] + size: [170, 60] + - ref: claim-registration + pos: [270, 70] + size: [170, 60] + - ref: handle-claim + pos: [500, 70] + size: [170, 60] + - ref: portal + pos: [40, 270] + size: [170, 60] + - ref: claims-app + pos: [270, 270] + size: [170, 60] + - ref: claims-admin + pos: [500, 270] + size: [170, 60] + - ref: dmz + pos: [40, 470] + size: [170, 60] + - ref: app-servers + pos: [270, 470] + size: [170, 60] + - ref: db-cluster + pos: [500, 470] + size: [170, 60] +boundaries: + - kind: region + label: Business layer + wraps: [insurant, claim-registration, handle-claim] + - kind: region + label: Application layer + wraps: [portal, claims-app, claims-admin] + - kind: region + label: Technology layer + wraps: [dmz, app-servers, db-cluster] +connections: + - { from: claim-registration, to: insurant, label: serves, variant: emphasis } + - { from: handle-claim, to: claim-registration, label: realizes } + - { from: portal, to: insurant, label: serves } + - { from: claims-admin, to: handle-claim, label: serves } + - { from: claims-app, to: claims-admin, label: realizes } + - { from: dmz, to: portal, label: serves } + - { from: app-servers, to: claims-app, label: serves } + - { from: db-cluster, to: app-servers, label: serves } diff --git a/examples/archimate-insurance-claims/registry/application.archify-registry b/examples/archimate-insurance-claims/registry/application.archify-registry new file mode 100644 index 0000000..4b7b12d --- /dev/null +++ b/examples/archimate-insurance-claims/registry/application.archify-registry @@ -0,0 +1,76 @@ +schema_version: 1 +elements: + portal: + type: frontend + label: Customer Portal + sublabel: App Interface + tag: App Interface + description: > + Web and mobile front end where customers report claims and + follow their status. + claims-admin: + type: cloud + label: Claims Admin + sublabel: App Service + tag: App Service + description: > + Register, look up and update claims; used by the portal and + by claims handlers. + claims-app: + type: backend + label: Claims App + sublabel: App Component + tag: App Component + description: > + Owns claims from registration to payment; the system of + record for claims. + diagram: 0200-application/application-structure.archify + crm: + type: backend + label: CRM + sublabel: App Component + tag: App Component + description: > + Customer contacts, addresses and the customer file. + policy-admin: + type: backend + label: Policy Admin + sublabel: App Component + tag: App Component + description: > + Policies, coverage and premiums; runs on the mainframe. + doc-mgmt: + type: backend + label: Document Mgmt + sublabel: App Component + tag: App Component + description: > + Scanned letters, photos and expert reports attached to claims. + payment: + type: backend + label: Payment + sublabel: App Component + tag: App Component + description: > + Sends approved claim payments to the bank in daily batches. + claim: + type: database + label: Claim + sublabel: Data Object + tag: Data Object + description: > + One reported damage, its valuation and its payment status. + policy: + type: database + label: Policy + sublabel: Data Object + tag: Data Object + description: > + Coverage, deductible and term of an insurance contract. + customer-file: + type: database + label: Customer File + sublabel: Data Object + tag: Data Object + description: > + Everything known about a customer; contacts, policies, claims. diff --git a/examples/archimate-insurance-claims/registry/business.archify-registry b/examples/archimate-insurance-claims/registry/business.archify-registry new file mode 100644 index 0000000..fcb7d71 --- /dev/null +++ b/examples/archimate-insurance-claims/registry/business.archify-registry @@ -0,0 +1,50 @@ +schema_version: 1 +elements: + customer: + type: external + label: Customer + sublabel: Business Actor + tag: Business Actor + description: > + A person or small business holding one or more policies + with Halbrook Mutual. + insurant: + type: external + label: Insurant + sublabel: Business Role + tag: Business Role + description: > + The role a customer plays while a claim is open; reports + damage and receives the payment. + claims-handler: + type: external + label: Claims handler + sublabel: Business Role + tag: Business Role + description: > + Employee of the claims department who accepts, valuates + and approves claims. + handle-claim: + type: backend + label: Handle Claim + sublabel: Business Process + tag: Business Process + description: > + Register, accept, valuate and pay a claim; the core process + of the claims department. + diagram: 0100-business/handle-claim.archify + claim-registration: + type: frontend + label: Claim Registration + sublabel: Business Service + tag: Business Service + description: > + Lets an insurant report damage by phone, mail or the + customer portal. + claim-payment: + type: frontend + label: Claim Payment + sublabel: Business Service + tag: Business Service + description: > + Pays the valuated amount to the insurant or a repairer. diff --git a/examples/archimate-insurance-claims/registry/technology.archify-registry b/examples/archimate-insurance-claims/registry/technology.archify-registry new file mode 100644 index 0000000..c9d297e --- /dev/null +++ b/examples/archimate-insurance-claims/registry/technology.archify-registry @@ -0,0 +1,62 @@ +schema_version: 1 +elements: + app-servers: + type: backend + label: App Servers + sublabel: Node + tag: Node + description: > + Two virtual machine hosts running the claims app, CRM and the + portal back end. + diagram: 0300-technology/infrastructure.archify + db-cluster: + type: database + label: DB Cluster + sublabel: Node + brand: postgresql + tag: Node + description: > + Primary and standby database servers for claims and CRM data. + doc-store: + type: database + label: Document Store + sublabel: System Software + tag: System Software + description: > + Object storage for scans and photos; written by document + management only. + mainframe: + type: backend + label: Mainframe + sublabel: Node + tag: Node + description: > + Hosts policy administration and the nightly payment batch. + mq: + type: messagebus + label: Message Queue + sublabel: System Software + tag: System Software + description: > + Queue manager between the app servers and the mainframe. + db-service: + type: cloud + label: DB Service + sublabel: Tech Service + tag: Tech Service + description: > + Managed SQL access with backups, offered to all applications. + dc-lan: + type: messagebus + label: Data Centre LAN + sublabel: Network + tag: Network + description: > + Internal network linking app servers, databases and mainframe. + dmz: + type: security + label: DMZ Gateway + sublabel: Network + tag: Network + description: > + Reverse proxy and firewall between the internet and the LAN. diff --git a/examples/archimate-logistics-tracking/0100-business/business-services.archify b/examples/archimate-logistics-tracking/0100-business/business-services.archify new file mode 100644 index 0000000..35fc4ff --- /dev/null +++ b/examples/archimate-logistics-tracking/0100-business/business-services.archify @@ -0,0 +1,34 @@ +schema_version: 1 +diagram_type: architecture +meta: + title: Business actors and services + output: business-services.html +components: + - ref: shipper + pos: [40, 60] + size: [130, 60] + - ref: recipient + pos: [40, 260] + size: [130, 60] + - ref: delivery-service + pos: [250, 60] + size: [130, 60] + - ref: tracking-service + pos: [250, 260] + size: [130, 60] + - ref: deliver-shipment + pos: [460, 160] + size: [130, 60] + - ref: driver + pos: [670, 60] + size: [130, 60] + - ref: customer-service + pos: [670, 260] + size: [130, 60] +connections: + - { from: delivery-service, to: shipper, label: serves, variant: emphasis } + - { from: tracking-service, to: recipient, label: serves } + - { from: deliver-shipment, to: delivery-service, label: realizes } + - { from: deliver-shipment, to: tracking-service, label: realizes } + - { from: driver, to: deliver-shipment, label: assigned to } + - { from: customer-service, to: tracking-service, label: assigned to } diff --git a/examples/archimate-logistics-tracking/0100-business/deliver-shipment.archify b/examples/archimate-logistics-tracking/0100-business/deliver-shipment.archify new file mode 100644 index 0000000..03cd271 --- /dev/null +++ b/examples/archimate-logistics-tracking/0100-business/deliver-shipment.archify @@ -0,0 +1,25 @@ +schema_version: 2 +diagram_type: workflow +meta: + title: Deliver Shipment + output: deliver-shipment.html + viewBox: [840, 534] +lanes: + - { id: customer-lane, label: Shipper and recipient } + - { id: driver-lane, label: Driver } + - { id: hub-lane, label: Hub } +mainPath: [book, pick-up, sort, line-haul, last-mile, pod-step] +nodes: + - { id: book, lane: customer-lane, col: 0, type: external, label: Book shipment, tag: Business Event } + - { id: pick-up, lane: driver-lane, col: 1, type: backend, label: Pick up, tag: Business Process } + - { id: sort, lane: hub-lane, col: 2, type: backend, label: Sort at hub, tag: Business Process } + - { id: line-haul, lane: hub-lane, col: 3, type: backend, label: Line haul, tag: Business Process } + - { id: last-mile, lane: driver-lane, col: 4, type: backend, label: Last mile, tag: Business Process } + - { id: pod-step, lane: customer-lane, col: 5, type: security, label: Delivered, sublabel: proof of delivery, tag: Business Process } +edges: + - { from: book, to: pick-up, label: triggers } + - { from: pick-up, to: sort, label: parcel } + - { from: sort, to: line-haul, label: trailer } + - { from: line-haul, to: last-mile, label: route } + - { from: last-mile, to: pod-step, label: hand over } + - { from: last-mile, to: sort, label: not home, role: return, variant: dashed } diff --git a/examples/archimate-logistics-tracking/0200-application/application-cooperation.archify b/examples/archimate-logistics-tracking/0200-application/application-cooperation.archify new file mode 100644 index 0000000..fb7b4a0 --- /dev/null +++ b/examples/archimate-logistics-tracking/0200-application/application-cooperation.archify @@ -0,0 +1,32 @@ +schema_version: 1 +diagram_type: architecture +meta: + title: Application cooperation + output: application-cooperation.html +decisions: [edi-gateway-in-front-of-tms] +components: + - ref: shipper + pos: [40, 260] + size: [130, 60] + - ref: edi-gateway + pos: [250, 260] + size: [130, 60] + decisions: [edi-gateway-in-front-of-tms] + - ref: tms + pos: [460, 260] + size: [130, 60] + - ref: driver-app + pos: [460, 60] + size: [130, 60] + - ref: telematics + pos: [460, 460] + size: [130, 60] + - ref: tracking-portal + pos: [670, 260] + size: [130, 60] +connections: + - { from: shipper, to: edi-gateway, label: bookings, variant: emphasis } + - { from: edi-gateway, to: tms, label: shipments, variant: emphasis } + - { from: driver-app, to: tms, label: scans, labelAt: [525, 134], decisions: [broker-for-tracking-events] } + - { from: telematics, to: tms, label: positions, decisions: [broker-for-tracking-events] } + - { from: tms, to: tracking-portal, label: status } diff --git a/examples/archimate-logistics-tracking/0200-application/application-services.archify b/examples/archimate-logistics-tracking/0200-application/application-services.archify new file mode 100644 index 0000000..b1281f9 --- /dev/null +++ b/examples/archimate-logistics-tracking/0200-application/application-services.archify @@ -0,0 +1,34 @@ +schema_version: 1 +diagram_type: architecture +meta: + title: Application services and data + output: application-services.html +components: + - ref: tracking-portal + pos: [40, 160] + size: [130, 60] + - ref: tracking-svc + pos: [250, 160] + size: [130, 60] + - ref: tms + pos: [460, 160] + size: [130, 60] + - ref: driver-app + pos: [670, 160] + size: [130, 60] + - ref: shipment + pos: [250, 360] + size: [130, 60] + - ref: tracking-event + pos: [460, 360] + size: [130, 60] + - ref: pod + pos: [670, 360] + size: [130, 60] +connections: + - { from: tracking-svc, to: tracking-portal, label: serves, variant: emphasis } + - { from: tms, to: tracking-svc, label: realizes } + - { from: driver-app, to: tms, label: uses } + - { from: tms, to: shipment, label: accesses } + - { from: tms, to: tracking-event, label: accesses, labelAt: [525, 234] } + - { from: driver-app, to: pod, label: accesses, labelAt: [735, 234] } diff --git a/examples/archimate-logistics-tracking/0300-technology/infrastructure.archify b/examples/archimate-logistics-tracking/0300-technology/infrastructure.archify new file mode 100644 index 0000000..33c4f80 --- /dev/null +++ b/examples/archimate-logistics-tracking/0300-technology/infrastructure.archify @@ -0,0 +1,44 @@ +schema_version: 1 +diagram_type: architecture +meta: + title: Technology infrastructure + output: infrastructure.html +decisions: [broker-for-tracking-events] +components: + - ref: handhelds + pos: [40, 160] + size: [130, 60] + - ref: telematics-units + pos: [40, 360] + size: [130, 60] + - ref: mobile-network + pos: [250, 260] + size: [130, 60] + - ref: cloud-cluster + pos: [460, 160] + size: [130, 60] + - ref: message-broker + pos: [460, 360] + size: [130, 60] + decisions: [broker-for-tracking-events] + - ref: db-server + pos: [670, 160] + size: [130, 60] + - ref: event-streaming + pos: [670, 360] + size: [130, 60] +boundaries: + - kind: region + label: Field devices + wraps: [handhelds, telematics-units] + - kind: security-group + label: Cloud platform + wraps: [cloud-cluster, message-broker, db-server, event-streaming] +connections: + - { from: handhelds, to: mobile-network, label: LTE } + - { from: telematics-units, to: mobile-network, label: LTE } + - { from: mobile-network, to: cloud-cluster, label: HTTPS, variant: security } + - { from: mobile-network, to: message-broker, label: MQTT, variant: security } + - { from: cloud-cluster, to: message-broker, label: hosts, labelAt: [525, 234] } + - { from: cloud-cluster, to: db-server, label: SQL } + - { from: message-broker, to: event-streaming, label: realizes } diff --git a/examples/archimate-logistics-tracking/decisions/0001-broker-for-tracking-events.archify-decision b/examples/archimate-logistics-tracking/decisions/0001-broker-for-tracking-events.archify-decision new file mode 100644 index 0000000..4021de7 --- /dev/null +++ b/examples/archimate-logistics-tracking/decisions/0001-broker-for-tracking-events.archify-decision @@ -0,0 +1,20 @@ +schema_version: 1 +decision: + id: broker-for-tracking-events + title: A message broker for tracking events + status: accepted + date: 2026-09-08 + elements: [message-broker, telematics, driver-app, tms, tracking-event] + diagrams: [0300-technology/infrastructure.archify, 0200-application/application-cooperation.archify] +context: > + Handhelds and telematics units posted every scan and position + straight to the TMS. At evening peaks the TMS fell behind and + dropped events when a device retried over a weak signal. +decision: > + Devices publish tracking events to a Kafka message broker on + the cloud cluster. The TMS and telematics read the topics at + their own pace; events are kept for seven days for replay. +consequences: > + Spikes no longer reach the TMS. Status on the tracking portal + can lag by seconds. Consumers must handle duplicate events, + and the broker is one more platform service to run. diff --git a/examples/archimate-logistics-tracking/decisions/0002-edi-gateway-in-front-of-tms.archify-decision b/examples/archimate-logistics-tracking/decisions/0002-edi-gateway-in-front-of-tms.archify-decision new file mode 100644 index 0000000..f2d1248 --- /dev/null +++ b/examples/archimate-logistics-tracking/decisions/0002-edi-gateway-in-front-of-tms.archify-decision @@ -0,0 +1,20 @@ +schema_version: 1 +decision: + id: edi-gateway-in-front-of-tms + title: An EDI gateway in front of the TMS + status: accepted + date: 2026-09-22 + elements: [edi-gateway, tms, shipper, shipment] + diagrams: [0200-application/application-cooperation.archify] +context: > + Large shippers send bookings as EDI files in three dialects. + Each dialect was parsed inside the TMS, so a new shipper meant + a TMS release. +decision: > + A separate EDI gateway receives, validates and translates + every booking into one shipment message for the TMS. It also + sends status messages back in the shipper's dialect. +consequences: > + New shippers are onboarded in the gateway alone. The TMS has + one booking interface. A rejected booking now fails at the + gateway, which customer service must be able to see. diff --git a/examples/archimate-logistics-tracking/decisions/0003-photo-proof-of-delivery.archify-decision b/examples/archimate-logistics-tracking/decisions/0003-photo-proof-of-delivery.archify-decision new file mode 100644 index 0000000..7835d4e --- /dev/null +++ b/examples/archimate-logistics-tracking/decisions/0003-photo-proof-of-delivery.archify-decision @@ -0,0 +1,17 @@ +schema_version: 1 +decision: + id: photo-proof-of-delivery + title: Photo as proof of delivery + status: proposed + date: 2026-10-27 + elements: [pod, driver-app, handhelds] + diagrams: [0200-application/application-services.archify, 0100-business/deliver-shipment.archify] +context: > + Most parcels are left at the door when nobody signs. Disputes + about such parcels take customer service days to settle. +decision: > + The driver app takes a photo of every parcel left without a + signature and stores it with the proof of delivery. +consequences: > + Disputes are settled from the photo. Photos are personal data + and are deleted after 90 days. Uploads add mobile data cost. diff --git a/examples/archimate-logistics-tracking/main.archify b/examples/archimate-logistics-tracking/main.archify new file mode 100644 index 0000000..6070cc8 --- /dev/null +++ b/examples/archimate-logistics-tracking/main.archify @@ -0,0 +1,59 @@ +schema_version: 1 +model: + id: logistics-tracking + name: Logistics Tracking + description: > + An ArchiMate example: a parcel carrier lets shippers and recipients + track shipments. Business, application and technology layers are + mapped to folders; each element's ArchiMate type is shown as its tag. +diagram_type: architecture +meta: + title: Logistics Tracking - layered view + output: main.html +components: + - ref: recipient + pos: [40, 70] + size: [170, 60] + - ref: tracking-service + pos: [270, 70] + size: [170, 60] + - ref: deliver-shipment + pos: [500, 70] + size: [170, 60] + - ref: tracking-portal + pos: [40, 270] + size: [170, 60] + - ref: tms + pos: [270, 270] + size: [170, 60] + - ref: tracking-svc + pos: [500, 270] + size: [170, 60] + - ref: mobile-network + pos: [40, 470] + size: [170, 60] + - ref: cloud-cluster + pos: [270, 470] + size: [170, 60] + - ref: event-streaming + pos: [500, 470] + size: [170, 60] +boundaries: + - kind: region + label: Business layer + wraps: [recipient, tracking-service, deliver-shipment] + - kind: region + label: Application layer + wraps: [tracking-portal, tms, tracking-svc] + - kind: region + label: Technology layer + wraps: [mobile-network, cloud-cluster, event-streaming] +connections: + - { from: tracking-service, to: recipient, label: serves, variant: emphasis } + - { from: deliver-shipment, to: tracking-service, label: realizes } + - { from: tracking-portal, to: recipient, label: serves } + - { from: tracking-svc, to: deliver-shipment, label: serves } + - { from: tms, to: tracking-svc, label: realizes } + - { from: mobile-network, to: tracking-portal, label: serves } + - { from: cloud-cluster, to: tms, label: serves } + - { from: event-streaming, to: tracking-svc, label: serves } diff --git a/examples/archimate-logistics-tracking/registry/application.archify-registry b/examples/archimate-logistics-tracking/registry/application.archify-registry new file mode 100644 index 0000000..1e55bf1 --- /dev/null +++ b/examples/archimate-logistics-tracking/registry/application.archify-registry @@ -0,0 +1,67 @@ +schema_version: 1 +elements: + tms: + type: backend + label: TMS + sublabel: App Component + tag: App Component + description: > + Owns shipments, routes and hub plans; the source of truth for status. + diagram: 0200-application/application-cooperation.archify + tracking-portal: + type: frontend + label: Tracking portal + sublabel: App Component + tag: App Component + description: > + Public site where shippers and recipients follow a shipment. + edi-gateway: + type: security + label: EDI gateway + sublabel: App Component + tag: App Component + description: > + Receives booking messages from large shippers and returns status. + driver-app: + type: frontend + label: Driver app + sublabel: App Component + tag: App Component + description: > + Scans parcels at every hand-over and captures proof of delivery. + telematics: + type: backend + label: Telematics + sublabel: App Component + tag: App Component + description: > + Collects vehicle positions and turns them into arrival estimates. + tracking-svc: + type: backend + label: Tracking service + sublabel: App Service + tag: App Service + description: > + Status and arrival estimate of one shipment, offered by the TMS. + diagram: 0200-application/application-services.archify + shipment: + type: database + label: Shipment + sublabel: Data Object + tag: Data Object + description: > + One booked parcel with sender, recipient, route and status. + tracking-event: + type: database + label: Tracking event + sublabel: Data Object + tag: Data Object + description: > + A scan or position report; the history of a shipment. + pod: + type: database + label: Proof of delivery + sublabel: Data Object + tag: Data Object + description: > + Signature or photo taken at the door; closes the shipment. diff --git a/examples/archimate-logistics-tracking/registry/business.archify-registry b/examples/archimate-logistics-tracking/registry/business.archify-registry new file mode 100644 index 0000000..d7cbf44 --- /dev/null +++ b/examples/archimate-logistics-tracking/registry/business.archify-registry @@ -0,0 +1,54 @@ +schema_version: 1 +elements: + shipper: + type: external + label: Shipper + sublabel: Business Actor + tag: Business Actor + description: > + Books shipments, hands parcels over at pick-up and follows + them until delivery. + recipient: + type: external + label: Recipient + sublabel: Business Actor + tag: Business Actor + description: > + Receives the parcel; tracks it and may reschedule delivery. + driver: + type: external + label: Driver + sublabel: Business Role + tag: Business Role + description: > + Collects parcels, drives the routes and captures proof of delivery. + customer-service: + type: external + label: Customer service + sublabel: Business Role + tag: Business Role + description: > + Answers shipper and recipient questions about late or lost parcels. + deliver-shipment: + type: backend + label: Deliver Shipment + sublabel: Business Process + tag: Business Process + description: > + Pick up, sort at hub, line haul, last mile and proof of delivery. + diagram: 0100-business/deliver-shipment.archify + delivery-service: + type: backend + label: Parcel delivery + sublabel: Business Service + tag: Business Service + description: > + What the carrier sells; a parcel collected and delivered on time. + diagram: 0100-business/business-services.archify + tracking-service: + type: backend + label: Shipment tracking + sublabel: Business Service + tag: Business Service + description: > + Where a parcel is and when it arrives, for shippers and recipients. diff --git a/examples/archimate-logistics-tracking/registry/technology.archify-registry b/examples/archimate-logistics-tracking/registry/technology.archify-registry new file mode 100644 index 0000000..e585b1c --- /dev/null +++ b/examples/archimate-logistics-tracking/registry/technology.archify-registry @@ -0,0 +1,55 @@ +schema_version: 1 +elements: + cloud-cluster: + type: cloud + label: Cloud cluster + sublabel: Node + brand: kubernetes + tag: Node + description: > + Container cluster that runs the TMS, portal, EDI gateway and telematics. + diagram: 0300-technology/infrastructure.archify + message-broker: + type: messagebus + label: Message broker + sublabel: System Software + brand: apache-kafka + tag: System Software + description: > + Carries tracking events from devices and vehicles to the applications. + db-server: + type: database + label: Database server + sublabel: System Software + brand: postgresql + tag: System Software + description: > + Stores shipments, tracking events and proofs of delivery. + event-streaming: + type: backend + label: Event streaming + sublabel: Tech Service + tag: Tech Service + description: > + Durable, ordered topics that applications publish to and read from. + handhelds: + type: external + label: Handhelds + sublabel: Device + tag: Device + description: > + Scanners carried by drivers and hub staff; run the driver app. + telematics-units: + type: external + label: Telematics units + sublabel: Device + tag: Device + description: > + GPS boxes in vans and trucks; report position every minute. + mobile-network: + type: security + label: Mobile network + sublabel: Network + tag: Network + description: > + Carrier-grade mobile network that links devices to the cluster. diff --git a/scripts/src/actions/model-scaffold/action.mjs b/scripts/src/actions/model-scaffold/action.mjs index a611d7e..d3265f6 100644 --- a/scripts/src/actions/model-scaffold/action.mjs +++ b/scripts/src/actions/model-scaffold/action.mjs @@ -16,6 +16,12 @@ export const EXAMPLES = { 'c4-standard-web-app': 'C4 - Standard Web App: single-page app, API, database, cache, file storage, identity provider', 'c4-e-shop': 'C4 - E-Shop: web shop, API, worker, queue, payment and email providers', 'c4-event-based-integration': 'C4 - Event-Based Integration: event bus, router, dead-letter queue, event store, consumers', + 'arc42-cinema-tickets': 'arc42 - Cinema Tickets: context, building blocks, runtime and deployment; seat booking with payment', + 'arc42-iot-telemetry': 'arc42 - IoT Telemetry: devices over MQTT, ingest, time-series store, alerting, dashboards', + 'arc42-team-wiki': 'arc42 - Team Wiki: a small self-hosted wiki, the arc42 sections at their smallest', + 'archimate-insurance-claims': 'ArchiMate - Insurance Claims: business, application and technology layers of claim handling', + 'archimate-hr-onboarding': 'ArchiMate - HR Onboarding: onboarding a new employee across HR, identity and IT services', + 'archimate-logistics-tracking': 'ArchiMate - Logistics Tracking: shipment tracking from pick-up to proof of delivery', }; export const help = `model-scaffold — create main.archify (and with --c4 the C4 folders), or copy an example diff --git a/scripts/src/test/run.mjs b/scripts/src/test/run.mjs index 67c03ed..fce9227 100644 --- a/scripts/src/test/run.mjs +++ b/scripts/src/test/run.mjs @@ -206,17 +206,19 @@ try { assert(r.status === 0, `exit ${r.status}`); }); - // The shipped examples: the same three the extension offers under "Archify | New Model…". + // The shipped examples: the same nine the extension offers under "Archify | New Model…". const examplesDir = path.join(skill, 'examples'); const exampleNames = fs.readdirSync(examplesDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort(); - check('examples/ holds exactly the three C4 examples', [], () => { - assert(exampleNames.join(',') === 'c4-e-shop,c4-event-based-integration,c4-standard-web-app', `unexpected examples: ${exampleNames.join(',')}`); + check('examples/ holds the nine examples: three C4, three arc42, three ArchiMate', [], () => { + const expected = 'arc42-cinema-tickets,arc42-iot-telemetry,arc42-team-wiki,archimate-hr-onboarding,archimate-insurance-claims,archimate-logistics-tracking,c4-e-shop,c4-event-based-integration,c4-standard-web-app'; + assert(exampleNames.join(',') === expected, `unexpected examples: ${exampleNames.join(',')}`); }); for (const name of exampleNames) { check(`example ${name} validates with 0 problems`, ['--action', 'model-validate', '--dir', path.join(examplesDir, name)], (r) => { assert(r.status === 0, `exit ${r.status}`); assert(yamlValue(r.stdout, ' errors') === '0' && yamlValue(r.stdout, ' warnings') === '0', 'example has problems'); - assert(yamlValue(r.stdout, ' diagrams') === '4', 'expected 4 diagrams'); + const diagrams = Number(yamlValue(r.stdout, ' diagrams')); + assert(diagrams >= 4 && yamlValue(r.stdout, ' diagramsOk') === String(diagrams), `expected at least 4 diagrams, all ok (${diagrams})`); }); } const fromExample = path.join(tmp, 'from-example');