archsight 0.3.3 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +7 -1
  3. data/docs/archimate.md +21 -1
  4. data/docs/configuration.md +1 -0
  5. data/docs/diagram.md +15 -3
  6. data/docs/docker.md +4 -1
  7. data/docs/icons.md +8 -2
  8. data/docs/import.md +178 -55
  9. data/docs/index.md.erb +24 -18
  10. data/docs/modeling.md +645 -34
  11. data/docs/pages.md +46 -15
  12. data/docs/search.md +21 -1
  13. data/docs/togaf.md +2 -1
  14. data/lib/archsight/analysis/result.rb +8 -2
  15. data/lib/archsight/analysis/sandbox.rb +8 -0
  16. data/lib/archsight/analysis/typst_renderer.rb +245 -0
  17. data/lib/archsight/analysis.rb +1 -0
  18. data/lib/archsight/annotations/annotation.rb +30 -3
  19. data/lib/archsight/annotations/architecture_annotations.rb +47 -0
  20. data/lib/archsight/annotations/link_annotations.rb +15 -0
  21. data/lib/archsight/annotations/resource_reference.rb +12 -0
  22. data/lib/archsight/cli.rb +124 -23
  23. data/lib/archsight/database.rb +40 -0
  24. data/lib/archsight/diagram/cli.rb +50 -2
  25. data/lib/archsight/diagram/formatter.rb +112 -0
  26. data/lib/archsight/diagram/routing/edge_router/orthogonal_path.rb +38 -10
  27. data/lib/archsight/diagram/routing/edge_router.rb +29 -4
  28. data/lib/archsight/diagram/routing/edge_routing.rb +61 -5
  29. data/lib/archsight/diagram/style/theme.rb +7 -2
  30. data/lib/archsight/documentation.rb +4 -4
  31. data/lib/archsight/editor/page_source.rb +13 -1
  32. data/lib/archsight/export/confluence/analysis_output.rb +100 -0
  33. data/lib/archsight/export/confluence/client.rb +13 -0
  34. data/lib/archsight/export/confluence/diagram_links.rb +1 -1
  35. data/lib/archsight/export/confluence/exporter.rb +43 -14
  36. data/lib/archsight/export/confluence/labels.rb +25 -0
  37. data/lib/archsight/export/confluence/page_properties.rb +6 -9
  38. data/lib/archsight/export/confluence/storage.rb +63 -14
  39. data/lib/archsight/export/confluence/tables.rb +2 -3
  40. data/lib/archsight/git_source.rb +81 -0
  41. data/lib/archsight/helpers/asset_images.rb +3 -4
  42. data/lib/archsight/helpers/embeds.rb +18 -7
  43. data/lib/archsight/helpers/resource_resolver.rb +25 -0
  44. data/lib/archsight/import/executor.rb +140 -16
  45. data/lib/archsight/import/handler.rb +55 -6
  46. data/lib/archsight/import/handler_loader.rb +64 -0
  47. data/lib/archsight/import/handlers/cache_pruner.rb +30 -7
  48. data/lib/archsight/import/handlers/command.rb +120 -0
  49. data/lib/archsight/import/handlers/github.rb +4 -1
  50. data/lib/archsight/import/handlers/gitlab.rb +4 -1
  51. data/lib/archsight/import/handlers/go_dep_resolver.rb +10 -2
  52. data/lib/archsight/import/handlers/go_grapher.rb +102 -5
  53. data/lib/archsight/import/handlers/go_module_parser.rb +88 -0
  54. data/lib/archsight/import/handlers/grapher.rb +40 -1
  55. data/lib/archsight/import/handlers/repository.rb +3 -0
  56. data/lib/archsight/import/handlers/rest_api_index.rb +3 -0
  57. data/lib/archsight/import/registry.rb +22 -1
  58. data/lib/archsight/import.rb +89 -1
  59. data/lib/archsight/linter/structure.rb +239 -0
  60. data/lib/archsight/linter.rb +123 -16
  61. data/lib/archsight/markdown.rb +48 -0
  62. data/lib/archsight/openapi.rb +169 -0
  63. data/lib/archsight/page_loader.rb +12 -1
  64. data/lib/archsight/page_tree.rb +2 -3
  65. data/lib/archsight/query/evaluator.rb +13 -6
  66. data/lib/archsight/query/parser.rb +73 -6
  67. data/lib/archsight/query.rb +1 -1
  68. data/lib/archsight/references.rb +3 -3
  69. data/lib/archsight/renderer.rb +80 -23
  70. data/lib/archsight/resources/analysis.rb +3 -2
  71. data/lib/archsight/resources/application_component.rb +75 -7
  72. data/lib/archsight/resources/application_interface.rb +12 -0
  73. data/lib/archsight/resources/application_service.rb +12 -1
  74. data/lib/archsight/resources/base.rb +58 -5
  75. data/lib/archsight/resources/business_actor.rb +5 -0
  76. data/lib/archsight/resources/business_contract.rb +72 -0
  77. data/lib/archsight/resources/business_product.rb +12 -0
  78. data/lib/archsight/resources/business_role.rb +1 -0
  79. data/lib/archsight/resources/implementation_deliverable.rb +1 -0
  80. data/lib/archsight/resources/implementation_plateau.rb +8 -2
  81. data/lib/archsight/resources/implementation_work_package.rb +2 -1
  82. data/lib/archsight/resources/import.rb +37 -11
  83. data/lib/archsight/resources/location.rb +56 -0
  84. data/lib/archsight/resources/motivation_requirement.rb +6 -0
  85. data/lib/archsight/resources/motivation_stakeholder.rb +14 -0
  86. data/lib/archsight/resources/page.rb +4 -7
  87. data/lib/archsight/resources/strategy_capability.rb +9 -0
  88. data/lib/archsight/resources/technology_artifact.rb +11 -4
  89. data/lib/archsight/resources/technology_communication_network.rb +91 -0
  90. data/lib/archsight/resources/technology_device.rb +88 -0
  91. data/lib/archsight/resources/technology_equipment.rb +75 -0
  92. data/lib/archsight/resources/technology_facility.rb +70 -0
  93. data/lib/archsight/resources/technology_node.rb +50 -0
  94. data/lib/archsight/resources/technology_service.rb +33 -0
  95. data/lib/archsight/resources/technology_system_software.rb +28 -0
  96. data/lib/archsight/resources.rb +12 -0
  97. data/lib/archsight/version.rb +1 -1
  98. data/lib/archsight/web/api/analysis_helpers.rb +55 -0
  99. data/lib/archsight/web/api/docs.rb +2 -1
  100. data/lib/archsight/web/api/json_helpers.rb +3 -37
  101. data/lib/archsight/web/api/openapi/spec.yaml +146 -35
  102. data/lib/archsight/web/api/page_helpers.rb +1 -8
  103. data/lib/archsight/web/api/routes.rb +9 -4
  104. data/lib/archsight/web/application.rb +40 -4
  105. data/lib/archsight/web/editor/routes.rb +2 -1
  106. data/lib/archsight/web/public/vendor/redoc/LICENSE +22 -0
  107. data/lib/archsight/web/public/vendor/redoc/VERSION +1 -0
  108. data/lib/archsight/web/public/vendor/redoc/api.html +27 -0
  109. data/lib/archsight/web/public/vendor/redoc/api.js +19 -0
  110. data/lib/archsight/web/public/vendor/redoc/redoc.standalone.js +1851 -0
  111. data/lib/archsight/web/public/vendor/redoc/redoc.standalone.js.LICENSE.txt +102 -0
  112. data/lib/archsight/web/public/vue/DocPage-C2ubTXH7.js +1 -0
  113. data/lib/archsight/web/public/vue/EditorPage-Dso6PLMn.js +35 -0
  114. data/lib/archsight/web/public/vue/ErrorPage-DnZ6YJLi.js +2 -0
  115. data/lib/archsight/web/public/vue/GraphView-CTl03Yre.js +1 -0
  116. data/lib/archsight/web/public/vue/HomePage-C339nihQ.js +2 -0
  117. data/lib/archsight/web/public/vue/InstanceRouter-DFW7tOrD.js +1 -0
  118. data/lib/archsight/web/public/vue/InstanceRouter-ZaCcjlIX.css +1 -0
  119. data/lib/archsight/web/public/vue/KindList-C0oaM3CF.js +1 -0
  120. data/lib/archsight/web/public/vue/KindList-yYcRT2BV.css +1 -0
  121. data/lib/archsight/web/public/vue/PageView-B93woeN3.css +1 -0
  122. data/lib/archsight/web/public/vue/PageView-OZB6G9Wu.js +1 -0
  123. data/lib/archsight/web/public/vue/QueryError-C2xLkCEm.js +1 -0
  124. data/lib/archsight/web/public/vue/ResourceList-D75O87zG.css +1 -0
  125. data/lib/archsight/web/public/vue/ResourceList-DooWFwQP.js +2 -0
  126. data/lib/archsight/web/public/vue/SearchResults-BK-HjFnv.js +1 -0
  127. data/lib/archsight/web/public/vue/{SearchResults-BewvsfOc.css → SearchResults-BV6UHriJ.css} +1 -1
  128. data/lib/archsight/web/public/vue/WikiPage-B2FYmeHL.js +3 -0
  129. data/lib/archsight/web/public/vue/WikiPage-TpmM1VAF.css +1 -0
  130. data/lib/archsight/web/public/vue/architecture-WOLXFQ4H-BGN-TV5r.js +1 -0
  131. data/lib/archsight/web/public/vue/cynefin-EF2NZ3EQ-CZd6g_tq.js +1 -0
  132. data/lib/archsight/web/public/vue/eventmodeling-K75KTNOO-CYnbEx8O.js +1 -0
  133. data/lib/archsight/web/public/vue/gitGraph-VSP46ZUC-DialfQSk.js +1 -0
  134. data/lib/archsight/web/public/vue/graphviz-1lWBhpEX.js +3 -0
  135. data/lib/archsight/web/public/vue/index-BLSE5DSv.css +1 -0
  136. data/lib/archsight/web/public/vue/index-CLuLTE5I.js +3 -0
  137. data/lib/archsight/web/public/vue/info-OHQRW6UA-BuhOW7ss.js +1 -0
  138. data/lib/archsight/web/public/vue/katex-B_JcIwqj.js +257 -0
  139. data/lib/archsight/web/public/vue/mermaid-C3bOamfn.js +3999 -0
  140. data/lib/archsight/web/public/vue/packet-JDAUHWVQ-CUeRz7w4.js +1 -0
  141. data/lib/archsight/web/public/vue/pie-XZMESJXO-DnuewJI6.js +1 -0
  142. data/lib/archsight/web/public/vue/radar-ABXABTNO-Bi9l8bcv.js +1 -0
  143. data/lib/archsight/web/public/vue/railroad-I3PHUGI6-DSlxFbxk.js +1 -0
  144. data/lib/archsight/web/public/vue/railroad-abnf-LNEFI6M7-D6Kqu8wu.js +1 -0
  145. data/lib/archsight/web/public/vue/railroad-ebnf-DWYD2UWJ-MR7uCYT0.js +1 -0
  146. data/lib/archsight/web/public/vue/railroad-peg-JR7BVNR7-BL7aKIc-.js +1 -0
  147. data/lib/archsight/web/public/vue/rolldown-runtime-COiEfhsA.js +1 -0
  148. data/lib/archsight/web/public/vue/treeView-D4JQ5SDB-CamtB04D.js +1 -0
  149. data/lib/archsight/web/public/vue/treemap-SAJKECNS-DeQxu_HM.js +1 -0
  150. data/lib/archsight/web/public/vue/{useGraphviz-DlSnFeCL.js → useGraphviz-Dnm2pkon.js} +2 -2
  151. data/lib/archsight/web/public/vue/useHighlight-BH32C7yt.js +10 -0
  152. data/lib/archsight/web/public/vue/usePanZoom-HxgEsqq2.js +12 -0
  153. data/lib/archsight/web/public/vue/wardley-7MLQ67FV-BvKIB6Tv.js +1 -0
  154. data/lib/archsight/web/public/vue.html +5 -5
  155. metadata +68 -41
  156. data/lib/archsight/web/public/vue/ApiDocsPage-BgqnQgwa.js +0 -1
  157. data/lib/archsight/web/public/vue/ApiDocsPage-DZ0fa5-h.css +0 -1
  158. data/lib/archsight/web/public/vue/DocPage-CNO71nBH.js +0 -1
  159. data/lib/archsight/web/public/vue/EditorPage-DR0FCNTz.js +0 -35
  160. data/lib/archsight/web/public/vue/ErrorPage-BfYArv6s.js +0 -2
  161. data/lib/archsight/web/public/vue/GraphView-BVTW30Ak.js +0 -1
  162. data/lib/archsight/web/public/vue/HomePage-Wk9P4Pma.js +0 -2
  163. data/lib/archsight/web/public/vue/InstanceRouter-BV8ycydz.js +0 -1
  164. data/lib/archsight/web/public/vue/InstanceRouter-jeavM6PW.css +0 -1
  165. data/lib/archsight/web/public/vue/KindList-C8yMsN5J.js +0 -1
  166. data/lib/archsight/web/public/vue/PageView-BaN6TyJB.js +0 -1
  167. data/lib/archsight/web/public/vue/QueryError-D790wH-a.js +0 -1
  168. data/lib/archsight/web/public/vue/ResourceList-B0FLaFR3.css +0 -1
  169. data/lib/archsight/web/public/vue/ResourceList-D-66nas2.js +0 -2
  170. data/lib/archsight/web/public/vue/SearchResults-CHyqIerQ.js +0 -1
  171. data/lib/archsight/web/public/vue/WikiPage-D2svpk6B.js +0 -13
  172. data/lib/archsight/web/public/vue/WikiPage-DoFJ0dbW.css +0 -1
  173. data/lib/archsight/web/public/vue/architecture-7GRP2DOG-BfA1TPxQ.js +0 -1
  174. data/lib/archsight/web/public/vue/cynefin-OW5HDTMX-BmgdUKVD.js +0 -1
  175. data/lib/archsight/web/public/vue/eventmodeling-NTZA5JFV-DbXDvAWF.js +0 -1
  176. data/lib/archsight/web/public/vue/gitGraph-4MIJSDKK-BkVhrKS1.js +0 -1
  177. data/lib/archsight/web/public/vue/graphviz-SXWTgZH5.js +0 -3
  178. data/lib/archsight/web/public/vue/index-BXXkUK1V.js +0 -3
  179. data/lib/archsight/web/public/vue/index-Cov1SnzY.css +0 -1
  180. data/lib/archsight/web/public/vue/info-A6RAGUB7-BIlCVuUY.js +0 -1
  181. data/lib/archsight/web/public/vue/katex-CXMH3UgJ.js +0 -257
  182. data/lib/archsight/web/public/vue/mermaid-BjEi5URd.js +0 -3334
  183. data/lib/archsight/web/public/vue/packet-AYTQ26CC-eoQTjY3j.js +0 -1
  184. data/lib/archsight/web/public/vue/pie-WAS4IAKB-DEOotGhh.js +0 -1
  185. data/lib/archsight/web/public/vue/radar-RG4KPBEZ-C2yucuUN.js +0 -1
  186. data/lib/archsight/web/public/vue/railroad-74A4TZTK-CzONK5VY.js +0 -1
  187. data/lib/archsight/web/public/vue/railroad-abnf-HS5TGJTU-9zRPsDsx.js +0 -1
  188. data/lib/archsight/web/public/vue/railroad-ebnf-LZEXJU2U-BJ4dkz9l.js +0 -1
  189. data/lib/archsight/web/public/vue/railroad-peg-WCYAUIDC-DFy_rqAj.js +0 -1
  190. data/lib/archsight/web/public/vue/treeView-Q6P3EWNA-2cq5CyD2.js +0 -1
  191. data/lib/archsight/web/public/vue/treemap-WGGIJYW6-DK-e9Ez4.js +0 -1
  192. data/lib/archsight/web/public/vue/useHighlight-D5Gf8DLl.js +0 -10
  193. data/lib/archsight/web/public/vue/wardley-WFR3VGLG-BQwqUqfB.js +0 -1
data/docs/modeling.md CHANGED
@@ -7,31 +7,36 @@ This guide explains how to model your architecture using ArchiMate concepts and
7
7
  Architecture modeling follows a layered approach, from business motivation down to technical implementation:
8
8
 
9
9
  ```
10
- Motivation Layer Why we do things (goals, stakeholders, requirements)
10
+ Motivation Layer Why we do things (goals, stakeholders, requirements, risks, policies)
11
11
  |
12
- Strategy Layer What capabilities we need
12
+ Strategy Layer What capabilities we need
13
13
  |
14
- Business Layer How business operates (processes, actors, products)
14
+ Implementation & Migration How the change happens (work packages, plateaus, gaps)
15
15
  |
16
- Application Layer What software supports the business
16
+ Business Layer How business operates (processes, actors, products)
17
17
  |
18
- Technology Layer How software is built and deployed
18
+ Application Layer What software supports the business
19
+ |
20
+ Technology Layer How software is built and deployed, and where it runs (facilities, equipment, networks)
19
21
  ```
20
22
 
23
+ The sidebar, the search facets, the metamodel diagram and these guides list the layers in this order, top to bottom;
24
+ the tool's own kinds (pages, views, imports, analyses) come last under "Other".
25
+
21
26
  ## Direction of Relations
22
27
 
23
28
  Model and read the architecture **top-down**: Motivation, Strategy, Business, Application, Technology; the
24
29
  Implementation & Migration layer describes change across all of them. A relation is written on an element and points
25
30
  to what that element depends on, is served by, or is answered by. Following relations from a high-level element
26
31
  therefore walks down to people, code and infrastructure, and the relations form a DAG: nothing may lead back to where
27
- it started. `archsight lint` reports every cycle (only `dependsOn` is exempt, because components may depend on each
28
- other at runtime).
32
+ it started. `archsight lint` reports every cycle (only `dependsOn` is exempt, because components and services may depend on each
33
+ other at runtime, and `connectedTo`, because cables between devices run both ways). `specializes`, `composedOf` and `aggregates` are checked per verb, see "Concept and Implementation" and "Deployment".
29
34
 
30
35
  There are two families of verbs:
31
36
 
32
37
  | Family | Verbs | Written on | Points to |
33
38
  |--------|-------|------------|-----------|
34
- | Responsibility and provider (down) | `performedBy`, `ownedBy`, `executedBy`, `servedBy`, `guidedBy`, `maintainedBy`, `contributedBy`, `hasConcern`, `realizedThrough`, `exposes`, `mitigatedBy`, `influences`, `triggers`, `affects`, `assesses`, `contains`, `closedBy`, `compares` | the element that needs, uses or is concerned with something | what provides it or is responsible for it |
39
+ | Responsibility and provider (down) | `performedBy`, `ownedBy`, `executedBy`, `servedBy`, `guidedBy`, `maintainedBy`, `contributedBy`, `hasConcern`, `representedBy`, `realizedThrough`, `exposes`, `connects`, `mitigatedBy`, `influences`, `triggers`, `affects`, `assesses`, `contains`, `closedBy`, `compares` | the element that needs, uses or is concerned with something | what provides it or is responsible for it |
35
40
  | Realization (up) | `realizes`, `partiallyRealizes`, `plans`, `satisfies`, `evidencedBy` (on the evidenced element), `provides` | the concrete element | the abstract element it answers to (requirement, goal, capability, plateau) |
36
41
 
37
42
  Rules:
@@ -46,6 +51,286 @@ Rules:
46
51
  (never written in a file) and show how things are linked sideways, in prose and pictures. They neither follow nor
47
52
  contradict the direction above and are left out of the cycle check.
48
53
 
54
+ ## Choosing the Kind
55
+
56
+ Four kinds carry most of a model: StrategyCapability, BusinessProduct, ApplicationService and ApplicationComponent.
57
+ Each answers one question. The test decides the kind, not the name.
58
+
59
+ | Kind | Question | Test | Name |
60
+ |------|----------|------|------|
61
+ | StrategyCapability | What must the organization be *able* to do? | Survives swapping product, team and technology; not a certificate or quality | ability noun phrase ("Payment Processing"), never a product, team or technology |
62
+ | BusinessProduct | What does a customer buy or contract? | Appears on a price list, catalog or customer documentation | market name ("Online Checkout") |
63
+ | ApplicationService | What behaviour does software offer a consumer? | Describable without naming repos, deployments or runtime objects; one owning actor | the function, not the technology or deployment object ("Payment Authorization") |
64
+ | ApplicationComponent | What is built, deployed and versioned? | Has artifacts and a `component/type`; can be deployed or linked | the part, by runtime role (API, Operator, Worker), not by repo category ("Payments:API") |
65
+
66
+ **Decision questions**, asked in order for any new element:
67
+
68
+ 1. Is it something the organization must be able to do, whoever or whatever does it? Capability.
69
+ 2. Is it something a customer selects, buys or signs a contract for? Product. The contract itself (framework, call-off,
70
+ SLA, amendment) is a `BusinessContract` the product aggregates, not a DataObject and not text in a description.
71
+ 3. Is it a function another system or a user calls or consumes, nameable without saying how it is built? Service.
72
+ 4. Is it something that is built, versioned and deployed or linked? Component.
73
+ 5. Is it a repository, package, image or binary? Artifact.
74
+ 6. Is it a proof, rule or obligation (certificate, regulation, policy)? Motivation or Compliance, not one of the above.
75
+ 7. Is it another name or id of something already modeled? `architecture/aliases` or `link/*` on that element, not a
76
+ new element.
77
+ 8. Does the same name already exist as a different kind? Check whether the two are really different. If they are not,
78
+ keep the element at the highest level where the test holds and link the others to it.
79
+
80
+ **Rules**
81
+
82
+ 1. One path up: Product `realizes` Capability, Product `servedBy` Service, Service `realizedThrough` Component,
83
+ Component `realizedThrough` Artifact. Capability `servedBy` Service only for internal capabilities that no product
84
+ carries.
85
+ 2. A component belongs to exactly one service; one service using another is `dependsOn` between the services (see
86
+ [Service Chain](#service-chain)), not the same component listed twice.
87
+ 3. An artifact is realized by exactly one component. When one repository holds several finer components (a monorepo),
88
+ the larger logical component (`component/type: module`) is realized by the artifact and the finer components
89
+ `dependsOn` it; the services use the finer components, and their rollups still reach the repository.
90
+ 4. A service whose only component has the same name is a smell: name the service by its function, or fold it into the
91
+ service it belongs to.
92
+ 5. Test, tooling and infrastructure-as-code repositories are not components of their own. They go on the component
93
+ they build, test or deploy.
94
+ 6. A product served by nearly every service is a catalog, not a product. A service that serves many products is a
95
+ shared service and is modeled once.
96
+ 7. Certifications and regulations are Motivation (requirement or constraint) with Compliance evidence, not
97
+ capabilities.
98
+ 8. Other identifiers of an element (register ids, wiki or ticket pages) are `architecture/aliases` and `link/*` on the
99
+ element itself, never a parallel element.
100
+
101
+ **Checked by `archsight lint`**
102
+
103
+ Rules 1 to 4 are checked on every `archsight lint` run and reported as **warnings** (section "Modeling warnings"),
104
+ never as errors, so they do not make the lint fail: they point at decisions to review and have legitimate exceptions,
105
+ such as an internal service or a capability that no product carries yet.
106
+
107
+ | Warning | Rule |
108
+ |---------|------|
109
+ | `ApplicationComponent 'Payments:API' is realized by 2 services: 'Payment Authorization', 'Refunds'` | 2 |
110
+ | `TechnologyArtifact 'Repo:payments-api' is realized by 2 components: ...` | 3 |
111
+ | `ApplicationService 'Billing' has one component with the same name` | 4 |
112
+ | `BusinessProduct 'Online Checkout' is served by no ApplicationService` | 1 |
113
+ | `ApplicationService 'Ledger' is not served to any product or process` | 1 |
114
+ | `StrategyCapability 'Payment Processing' is realized by no product` | 1 |
115
+ | `ApplicationComponent 'alice:shop' is generated from 2 repositories with the same module path: ...` | import, see [Classifying components](#classifying-components) |
116
+
117
+ A service counts as served when a product or a process is `servedBy` it, directly or through other services that
118
+ `dependsOn` it. Each finding starts with the file and line of the resource, like the errors.
119
+
120
+ **Example chain**
121
+
122
+ ```
123
+ StrategyCapability "Payment Processing"
124
+ ↑ realizes
125
+ BusinessProduct "Online Checkout"
126
+ ↓ servedBy
127
+ ApplicationService "Payment Authorization"
128
+ ↓ realizedThrough
129
+ ApplicationComponent "Payments:API"
130
+ ↓ realizedThrough
131
+ TechnologyArtifact "Repo:payments-api"
132
+ ```
133
+
134
+ The chain is part of `examples/archsight` (`strategy/`, `business/`, `services/`, `components/`, `technology/`).
135
+
136
+ **Anti-patterns**
137
+
138
+ | Anti-pattern | Fix |
139
+ |--------------|-----|
140
+ | A service named after a deployment object (ingress route, Helm release, admin endpoint) | Name it by the function it offers; the deployment object is part of the component or artifact |
141
+ | Components named after repo categories ("Testing", "Tools", "Infrastructure") | Name components by runtime role; put test, tooling and infrastructure repositories on the component they belong to |
142
+ | A catalog product that everything serves | Model the products customers really buy; the catalog is a view or page |
143
+ | A certificate modeled as a capability | Requirement or constraint with Compliance evidence |
144
+ | A parallel set of services that re-groups the same components for an inventory or register | `architecture/aliases` and `link/*` on the real service |
145
+
146
+ ## Choosing the Kind: Infrastructure
147
+
148
+ Infrastructure is modeled in five tiers: **where** (Location, TechnologyFacility), **physical** (TechnologyEquipment),
149
+ **device** (TechnologyDevice), **network** (TechnologyCommunicationNetwork) and **compute** (TechnologyNode,
150
+ TechnologySystemSoftware, TechnologyService, TechnologyArtifact). The same principle holds as above: the test decides the kind, not the name.
151
+
152
+ | Kind | Question | Test | Name |
153
+ |------|----------|------|------|
154
+ | Location | In which region or country is it? | A place on a map, not a building; holds facilities | the place ("Location:Germany:Frankfurt") |
155
+ | TechnologyFacility | In which building or site does hardware stand? | Has an address and can be visited; can be nested (campus, hall) | the site ("Facility:Frankfurt:HallA") |
156
+ | TechnologyEquipment | Which physical thing can you touch? | Racks, fabrics, fibre routes, carrier circuits; no software of its own | the thing and its place ("Equipment:Link:Frankfurt-Madrid") |
157
+ | TechnologyDevice | Which single machine stands in the room? | One server, switch, router, firewall or appliance with a serial number; it is cabled | the host ("Device:Frankfurt:Server01") |
158
+ | TechnologyCommunicationNetwork | What carries data between nodes? | Has a network role (`network/type`); exists beyond any single link | role and scope ("Network:Management:Frankfurt") |
159
+ | TechnologyNode | On which machine does software run? | A VM, host role or logical group of machines with a lifecycle of its own | the host or host role ("Node:Frankfurt:Web01") |
160
+ | TechnologySystemSoftware | What software hosts other software or data? | An operating system, database cluster, routing stack, platform | the product and role ("Tech:Routing:EVPN") |
161
+ | TechnologyService | What does infrastructure offer to its consumers? | Consumed without knowing which nodes run it | the offering ("Network:Backbone", "Postgres") |
162
+ | TechnologyArtifact | Which file is built and deployed? | A repository, image, package or binary | the artifact ("Repo:payments-api") |
163
+
164
+ **Decision questions**, asked in order for any new infrastructure element:
165
+
166
+ 1. Is it a country, metro or region? Location.
167
+ 2. Is it a building, campus, hall or site that can be visited? TechnologyFacility.
168
+ 3. Is it a physical thing (rack, switch fabric, fibre, circuit) without software of its own? TechnologyEquipment.
169
+ 4. Is it one physical machine (server, switch, router, firewall, appliance) whose room or cabling matters?
170
+ TechnologyDevice.
171
+ 5. Does it carry data between nodes, with a role such as underlay, overlay, management, public or VPN?
172
+ TechnologyCommunicationNetwork.
173
+ 6. Is it a machine (virtual, or a host role) that software runs on? TechnologyNode.
174
+ 7. Is it software that hosts other software, data or traffic? TechnologySystemSoftware.
175
+ 8. Is it something consumed by others without them knowing how it is run? TechnologyService.
176
+ 9. Is it a file that is built and deployed? TechnologyArtifact.
177
+
178
+ **Rules**
179
+
180
+ 1. One element per thing, many `locatedAt`: a service, network or cluster that runs in three data centers is one
181
+ element with three relations, never a copy per site.
182
+ 2. A link between sites is one TechnologyEquipment (`equipment/type: link`) `locatedAt` exactly its two facilities. A backbone
183
+ is TechnologyEquipment `composedOf` its links.
184
+ 3. Physical before logical: a network is `realizedBy` the TechnologyEquipment it runs over and the system software that
185
+ implements it; an overlay or VPN is `servedBy` the network it runs over.
186
+ 4. No element per tenant or customer network: the overlay is one network, its tenants are instances of it.
187
+ 5. A mesh is `network/topology: mesh` on one network, not an element per pair of sites. Single tunnels are
188
+ sub-networks only when they have their own owner or capacity.
189
+ 6. Concept and implementation with `specializes` (management network → management network of one site), structure
190
+ with `composedOf` (metro network → site networks, campus → halls, backbone → links).
191
+ 7. A network that supports a metro region is `locatedAt` the Location and `composedOf` the networks of its sites.
192
+ 8. Nodes attach to networks with `servedBy` and stand in facilities with `locatedAt`.
193
+ An `ApplicationInterface` is `servedBy` the networks on which it can be reached. Write them only when they are
194
+ known: an interface without a network makes no claim about its reachability, and an analysis cannot tell "not
195
+ reachable" from "not recorded".
196
+ 9. An overlay that software builds (an SDN agent wiring tenant networks on each host, an operator creating VXLAN
197
+ segments, a load-balancer controller announcing public addresses) is `realizedBy` that `ApplicationComponent` or
198
+ `ApplicationService` (ArchiMate cross-layer realization). This holds even when the software runs on the nodes the
199
+ network serves: point at the application component, not at the node's system software, which would close a cycle
200
+ (network → system software → node → network).
201
+ 10. One `TechnologyDevice` per physical machine, `locatedAt` its room (a TechnologyFacility of `facility/type: room`
202
+ the data center is `composedOf`). A group of machines with one role stays a logical `TechnologyNode` that is
203
+ `realizedBy` its devices; a rack or hardware block is TechnologyEquipment `composedOf` them; a virtual chassis or
204
+ stack is a device `composedOf` its members.
205
+ 11. A network is `realizedBy` the devices that build it (switches, routers) and `connects` the devices attached to it.
206
+ Both are written on the network, so a switch attached to the network it builds closes no cycle.
207
+ 12. Cables are `connectedTo` between devices, declared once on one of the two ends. Cabling runs both ways by nature
208
+ and is left out of the cycle check.
209
+ 13. Devices, equipment, nodes and networks are `ownedBy` the team (BusinessActor) or BusinessRole that operates
210
+ them. Devices, equipment and nodes are `servedBy` the team they are dedicated to (ArchiMate serving: the
211
+ technology serves the actor), such as the servers of a shared test cluster partitioned among teams;
212
+ `device/purpose` and `equipment/purpose` say what for ("kernel regression tests"). A partition is equipment
213
+ `servedBy` its team and `composedOf` its devices, which then need no team of their own. Both relations point
214
+ down to the team, which points to nothing further. On a TechnologyFacility, `servedBy` stays the operator of
215
+ the site.
216
+
217
+ **Checked by `archsight lint`**
218
+
219
+ As above, these are **warnings** in the "Modeling warnings" section and never fail the lint:
220
+
221
+ | Warning | Rule |
222
+ |---------|------|
223
+ | `TechnologyEquipment 'Equipment:Link:A-B' is a link located at 1 facility, not 2` | 2 |
224
+ | `TechnologyCommunicationNetwork 'Network:Overlay:EVPN' is an overlay network served by no network` | 3 |
225
+ | `TechnologyFacility 'Facility:Madrid:DC' is located at no Location` | where |
226
+ | `TechnologyEquipment 'Equipment:Rack01' is located at no TechnologyFacility` | where |
227
+ | `TechnologyDevice 'Device:Server01' is located at no TechnologyFacility` | 10 |
228
+ | `TechnologyDevice 'Device:Switch01' is connectedTo itself` | 12 |
229
+ | `TechnologyDevice 'Device:Router01' is a router that realizes no TechnologyCommunicationNetwork` | 11 |
230
+ | `TechnologyDevice 'Device:a:server-3' is servedBy 'Kernel:Team', not by the team of its equipment ('Compute:Team')` | 13 |
231
+
232
+ Nested facilities need no location of their own (the outermost facility has it), and TechnologyEquipment that is part of other
233
+ TechnologyEquipment, or composed of placed parts, needs no facility of its own. The same holds for a device inside a
234
+ rack or a virtual chassis, and for a chassis whose members are placed; the members of a chassis realize the network
235
+ through the chassis.
236
+
237
+ **Example chain**
238
+
239
+ ```
240
+ Location "Location:Germany:Frankfurt"
241
+ ↑ locatedAt
242
+ TechnologyFacility "Facility:Frankfurt:Campus" ──composedOf──> TechnologyFacility "Facility:Frankfurt:HallA"
243
+ ↑ locatedAt (both ends) ↑ locatedAt
244
+ TechnologyEquipment "Equipment:Link:Frankfurt-Madrid" (link) TechnologyNode "Node:Frankfurt:Web01"
245
+ ↑ composedOf │ servedBy
246
+ TechnologyEquipment "Equipment:Backbone" ↓
247
+ ↑ realizedBy TechnologyCommunicationNetwork "Network:Management:Frankfurt"
248
+ TechnologyService "Network:Backbone"
249
+ ```
250
+
251
+ Devices, one level further down (hall A of the example):
252
+
253
+ ```
254
+ TechnologyCommunicationNetwork "Network:Management:Frankfurt"
255
+ │ realizedBy │ connects
256
+ ↓ ↓
257
+ TechnologyDevice "Device:Frankfurt:Switch:Core" TechnologyDevice "Device:Frankfurt:Server01" ──locatedAt──> TechnologyFacility "Facility:Frankfurt:HallA:Room1"
258
+ │ composedOf │ connectedTo ↑ composedOf
259
+ ↓ ↓ TechnologyFacility "Facility:Frankfurt:HallA"
260
+ TechnologyDevice "Device:Frankfurt:Switch:Core:n0" ←─┘
261
+ ```
262
+
263
+ The physical machines of hall A, two rooms with their servers, switches, routers and firewalls, are in
264
+ `examples/archsight/technology/devices.yaml`, drawn room by room on the same example page.
265
+
266
+ The overlay `Network:Overlay:EVPN` is `servedBy` the underlay and `realizedBy` the routing software
267
+ `Tech:Routing:EVPN`. All of it is in `examples/archsight/technology/` (`facilities.yaml`, `networks.yaml`), walked
268
+ through on the example page "Infrastructure Modeling".
269
+
270
+ **Anti-patterns**
271
+
272
+ | Anti-pattern | Fix |
273
+ |--------------|-----|
274
+ | A data center modeled as a TechnologyNode | TechnologyFacility; the servers in it are nodes `locatedAt` it |
275
+ | Sites as annotations (`deployment/locations: dc-1,dc-2`) | TechnologyFacility elements and `locatedAt` |
276
+ | One copy of a service or cluster per site | One element `locatedAt` every site |
277
+ | A Location used for a building | TechnologyFacility `locatedAt` the Location |
278
+ | A link or fibre route as a TechnologyService | TechnologyEquipment `link`; the network service is `realizedBy` it |
279
+ | A network per tenant or customer | One overlay network; tenants stay out of the model |
280
+ | An element per pair of sites in a mesh | One network with `network/topology: mesh` |
281
+ | An overlay or VPN with nothing under it | `servedBy` the underlay or the network it tunnels through |
282
+
283
+ ## Identity and Links
284
+
285
+ A resource has one **name**, the key everything refers to (relations, `[[wiki links]]`, URLs). Two annotations say more
286
+ about who it is and where else it lives. Both are available on every resource kind (pages have the links too).
287
+
288
+ ### Aliases
289
+
290
+ `architecture/aliases` holds the other identifiers of a resource, comma-separated: `ApplicationService:Foo` can also be
291
+ `ITGS:A001`. Aliases are **unique among the resources of a kind** (`archsight lint` reports a duplicate with both
292
+ resources); the same alias on resources of different kinds is fine, like names. They are found by search and open a
293
+ resource by URL:
294
+
295
+ ```
296
+ ITGS:A001 # the search box: the name shortcut also tests aliases
297
+ ApplicationService: architecture/aliases == "ITGS:A001"
298
+ name == "ITGS:A001"
299
+ /kinds/ApplicationService/instances/ITGS:A001 # redirects to /kinds/ApplicationService/instances/Foo
300
+ ```
301
+
302
+ In a URL (and the instance API) a name always wins; when no resource has that name, the one resource of the kind
303
+ with that alias opens under its real name. An alias is an identifier, so each alias is shown as a chip without a link
304
+ and is not a facet in the sidebar (it would only ever point at one resource). It is not a name in the model: a
305
+ relation or a `[[wiki link]]` must use the name. When two documents describe the same resource, their aliases (and
306
+ tags) are added together instead of one replacing the other.
307
+
308
+ For kind authors: `annotation "key", unique: true` makes any annotation an identifier of this kind: unique per kind,
309
+ checked by `archsight lint`, shown as chips without links. `annotation "key", deprecated: "what to use instead"` keeps an
310
+ annotation working while `archsight lint` lists every use as a deprecation (with the text), without failing.
311
+ `annotation "key", default: "value"` gives every resource that does not set the annotation that value when the
312
+ resources are loaded (queries, filters and pages see it; the editor does not write it into the file).
313
+
314
+ ### Links
315
+
316
+ `link/<name>` holds a URL on any resource. The name says which system: `link/confluence`, `link/jira`,
317
+ `link/servicenow`; a second link into the same system gets another name (`link/confluence-isms`). A link has **no
318
+ direction**: it is where the resource comes from, where it was published to, or just a related page. A page writes them
319
+ as `links:` in its frontmatter (see [Pages](/doc/pages)):
320
+
321
+ ```yaml
322
+ kind: ApplicationService
323
+ metadata:
324
+ name: Foo
325
+ annotations:
326
+ architecture/aliases: ITGS:A001
327
+ link/confluence: https://confluence.example.com/spaces/ARCH/pages/12345/Foo
328
+ link/jira: https://jira.example.com/browse/ARCH-12
329
+ ```
330
+
331
+ Links render with the icon of their system wherever a resource or page is shown. Artifacts also carry many generated
332
+ `link/*` entries (links found in the README); they are listed apart from the ones you write.
333
+
49
334
  ## Starting Points
50
335
 
51
336
  ### Top-Down Modeling
@@ -86,26 +371,19 @@ Model **why** the architecture exists.
86
371
  | MotivationAssessment | For risks, vulnerabilities, findings and supplier or protection-need analyses (`assessment/type`) |
87
372
  | MotivationPrinciple | For policies, guidelines and architecture principles (`principle/type`) |
88
373
 
89
- **Example chain:** Stakeholder "Security Team" → hasConcern → Goal "Achieve Compliance" → realizes → Requirement "Encrypt data at rest"
374
+ **Example chain:** Stakeholder "Security Team" → hasConcern → Goal "Achieve Compliance" → realizes → Requirement "Encrypt data at rest"; Stakeholder "Security Team" → representedBy → Actor "Security Office"
90
375
 
91
- ### Business Layer
376
+ **Source of a requirement:** the stakeholder that `hasConcern` for a requirement (directly, or for the goal the requirement answers) is its source, and the stakeholder is `representedBy` the `BusinessActor` or `BusinessRole` behind it: the actual organisation, not a generic "customer". This follows ArchiMate, where a stakeholder is a motivation role associated with the actor or role that plays it, and TOGAF, where the requirements repository records each requirement's source and the stakeholder map links stakeholders to organisation units. The requirement's page shows its stakeholders, the actor's page the stakeholder roles it represents. A source is optional.
92
377
 
93
- Model **who** does **what** in business terms.
378
+ ### Strategy Layer
379
+
380
+ Model strategic **capabilities**.
94
381
 
95
382
  | Resource | When to Use |
96
383
  |----------|-------------|
97
- | BusinessActor | For teams, departments, or organizations |
98
- | BusinessRole | For responsibilities held by actors: control owner, risk owner, information security officer (`role/type`) |
99
- | BusinessProcess | For workflows that produce business value |
100
- | BusinessProduct | For offerings to customers (cloud services, APIs) |
101
- | BusinessControl | For controls that guide a process (access review, change approval), with an owner and executors |
102
- | BusinessEvent | For things that happen in the business: threat events, loss events, incidents, triggers (`event/type`) |
384
+ | StrategyCapability | For abilities the organization needs ("Payment Processing", "Data Analytics"); not a product, team or certificate |
103
385
 
104
- **Example chain:** Process "Incident Response" → performedBy → Actor "Platform Team"; Process "Incident Response" → servedBy → Service "Monitoring"
105
-
106
- **Roles:** Process "Incident Response" → performedBy → Role "Incident Manager" → performedBy → Actor "Platform Team". Controls, risks, policies and work packages use `ownedBy` (and controls `executedBy`) the same way. Use a role where the responsibility has a name of its own and should survive a change of team; pointing straight at an actor stays valid.
107
-
108
- **Controls:** Process "Incident Response" → guidedBy → Control "Escalation Review" → ownedBy / executedBy → Role or Actor. How controls, requirements and evidence fit together is described under Relation Patterns below.
386
+ **Example chain:** Product "Online Checkout" → realizes → Capability "Payment Processing" → realizes → Requirement "Card Payments" (see [Choosing the Kind](#choosing-the-kind))
109
387
 
110
388
  ### Implementation & Migration Layer
111
389
 
@@ -121,17 +399,74 @@ Model **change**: what is done, what it delivers and how the architecture looks
121
399
 
122
400
  **Migration path:** Plateau "Baseline" → triggers → Plateau "Target"; Gap → compares → both plateaus; Work Package → realizes → Deliverable → realizes → Plateau "Target"; Gap → closedBy → Work Package.
123
401
 
402
+ **Platform migration:** a plateau `contains` the technology elements of its state: `technologyServices`, `technologySystemSoftware`, `technologyNodes` and (optionally) `technologyArtifacts`, next to application components and requirements. Model the past, current and target platform as three plateaus chained with `triggers`, with a Gap per step; the plateau page lists what it contains, the technology element shows (reverse lookup) in which plateaus it appears, and comparing the plateaus of a gap shows what is added or removed. See `examples/archsight/implementation/platform-migration.yaml`.
403
+
124
404
  **Remediation:** Assessment "Risk" → mitigatedBy → Work Package → realizes → Deliverable (type `evidence`) → realizes → ComplianceEvidence. Group by `risk/domain` to see the plan of one domain, filter by `workpackage/status` and `workpackage/due` for what is open or late.
125
405
 
126
- ### Strategy Layer
406
+ ### Business Layer
127
407
 
128
- Model strategic **capabilities**.
408
+ Model **who** does **what** in business terms.
129
409
 
130
410
  | Resource | When to Use |
131
411
  |----------|-------------|
132
- | StrategyCapability | For abilities the organization needs ("Container Orchestration", "Data Analytics") |
412
+ | BusinessActor | For teams, departments, or organizations |
413
+ | BusinessRole | For responsibilities held by actors: control owner, risk owner, information security officer (`role/type`) |
414
+ | BusinessProcess | For workflows that produce business value |
415
+ | BusinessProduct | For what a customer buys or contracts, as on a price list ("Online Checkout", "Premium Support") |
416
+ | BusinessContract | For what a customer and a provider agreed: framework contracts, call-offs, SLAs, amendments (`contract/type`) |
417
+ | BusinessControl | For controls that guide a process (access review, change approval), with an owner and executors |
418
+ | BusinessEvent | For things that happen in the business: threat events, loss events, incidents, triggers (`event/type`) |
419
+
420
+ **Example chain:** Process "Incident Response" → performedBy → Actor "Platform Team"; Process "Incident Response" → servedBy → Service "Monitoring"
421
+
422
+ **Roles:** Process "Incident Response" → performedBy → Role "Incident Manager" → performedBy → Actor "Platform Team". Controls, risks, policies and work packages use `ownedBy` (and controls `executedBy`) the same way. Use a role where the responsibility has a name of its own and should survive a change of team; pointing straight at an actor stays valid.
423
+
424
+ **Controls:** Process "Incident Response" → guidedBy → Control "Escalation Review" → ownedBy / executedBy → Role or Actor. How controls, requirements and evidence fit together is described under Relation Patterns below.
133
425
 
134
- **Example chain:** Capability "Managed Kubernetes" → realizes → Requirement "Container Platform" and servedBy → Service "ManagedKubernetes"
426
+ **Contracts:** Product → aggregates → Contract (framework) → composedOf → Contract (call-off) → covers → Equipment, and the call-off → realizedThrough → Deliverable ← realizes ← Work Package → affects → Equipment. The contract is `agreedBy` the actual organisations (the customer and the provider), not a generic role. All relations are written on the more abstract element; the equipment, the actors and the deliverable show them as incoming ("covered by", "agreed contracts", "fulfils"). A contract is a `BusinessContract`, not a `DataObject` and not text in a description.
427
+
428
+ ```yaml
429
+ kind: BusinessProduct
430
+ metadata:
431
+ name: PrivateCloudOffering
432
+ spec:
433
+ servedBy:
434
+ applicationServices: [ComputeService, ObjectStorage]
435
+ aggregates:
436
+ businessContracts: [Contract:Customer]
437
+ ---
438
+ kind: BusinessContract
439
+ metadata:
440
+ name: Contract:Customer
441
+ annotations:
442
+ contract/type: framework
443
+ contract/from: '2024-01-01'
444
+ spec:
445
+ agreedBy:
446
+ businessActors: [CustomerOrg, ProviderOrg]
447
+ composedOf:
448
+ businessContracts: [Contract:Customer:Block1, Contract:Customer:Block2]
449
+ ---
450
+ kind: BusinessContract
451
+ metadata:
452
+ name: Contract:Customer:Block2
453
+ annotations:
454
+ contract/type: call-off
455
+ spec:
456
+ covers:
457
+ technologyEquipment: [Block2]
458
+ realizedThrough:
459
+ implementationDeliverables: [Block2Delivered]
460
+ ---
461
+ kind: ImplementationWorkPackage
462
+ metadata:
463
+ name: BuildBlock2
464
+ spec:
465
+ realizes:
466
+ implementationDeliverables: [Block2Delivered]
467
+ affects:
468
+ technologyEquipment: [Block2]
469
+ ```
135
470
 
136
471
  ### Application Layer
137
472
 
@@ -139,12 +474,49 @@ Model **software** that supports the business.
139
474
 
140
475
  | Resource | When to Use |
141
476
  |----------|-------------|
142
- | ApplicationService | For high-level services (ManagedKubernetes, ObjectStorage) |
143
- | ApplicationComponent | For deployable parts of services (API server, worker, scheduler) |
477
+ | ApplicationService | For behaviour software offers to a consumer, named by its function ("Payment Authorization", "Document Search") |
478
+ | ApplicationComponent | For what is built, deployed and versioned, by runtime role ("Payments:API", "Payments:Worker") |
144
479
  | ApplicationInterface | For APIs and integration points |
145
480
  | DataObject | For data structures and schemas |
146
481
 
147
- **Example chain:** Service "ManagedKubernetes" → realizedThrough → Component "kube-apiserver" → exposes → Interface "Kubernetes:RestAPI"
482
+ **Example chain:** Service "Payment Authorization" → realizedThrough → Component "Payments:API" → exposes → Interface "Payments:RestAPI"
483
+
484
+ #### Classifying components
485
+
486
+ Components are not all alike: some are run, some are only imported, some bundle both. Say which with `component/type`
487
+ (`executable`, `library`, `module`, `plugin`, `frontend`, `other`) and, for executables and plugins, what they do with
488
+ `component/role` (`service`, `cli`, `job`, `operator`, `agent`). Importers set `component/type` and add machine tags
489
+ (`namespace:value`, such as `ecosystem:go`, `packaging:go-module`, `linkage:shared`) to the regular
490
+ `architecture/tags` from the manifests; the tags a person set stay, and a re-import only replaces the machine tags of
491
+ those namespaces. The entry points (main packages such as `cmd/api`) are written to `component/entrypoints`, a list
492
+ you query like a tag (`component/entrypoints == "cmd/api"`) that is not a sidebar filter, because there are too many
493
+ distinct values. `component/role` is set by hand and never overwritten. A generated component is named after its module path (`github.com/alice/shop` → `alice:shop`). When
494
+ two repositories declare the same module path (a prototype and its successor, a fork), each gets its own component:
495
+ the repository the module path names keeps the plain name (`github.com/acme/library` names `Repo:acme:library`),
496
+ then the one that is not archived, then the first by name; the other gets its repository appended
497
+ (`alice:shop@acme:shop-prototype`), and a dependency on the module path points at the plain name. A `go.mod` in a
498
+ subdirectory whose module path names another known repository is a copy of that repository's module and gets no
499
+ component at all. Neither does a nested `go.mod` below a test, tool, example or benchmark directory (`test/e2e`,
500
+ `tools`, `hack`, `examples/foo`, `internal/systemtest`): nothing realizes such code or depends on it, so its packages
501
+ only appear in the repository's module graph; `cmd/<name>/go.mod` stays a component. The importer only sees the other repository once both were imported, so the names separate on the
502
+ import after that; until then `archsight lint` warns about the merged component. A hand-written component that lists
503
+ several repositories is left as it is. The computed `component/dependents` counts the components that depend on a
504
+ component, which shows how widely a library or module is shared.
505
+
506
+ | Ecosystem | Executable | Library | Module (bundles both) |
507
+ |-----------|------------|---------|-----------------------|
508
+ | Go | `package main` (`component/entrypoints`: one per main package) | no `main` package | main packages plus importable packages outside `internal/` and `cmd/` |
509
+ | JavaScript, TypeScript | `bin`, a server entry point | `main`, `exports`, `types` | `workspaces` root |
510
+ | Ruby | gemspec `executables`, Rails app | gem without executables | monorepo of gems |
511
+ | Python | `[project.scripts]`, `__main__.py` | package published to an index | distribution of several packages |
512
+ | Rust | `[[bin]]`, `src/main.rs` | `[lib]` | Cargo workspace |
513
+ | Java | `Main-Class`, Spring Boot, application plugin | plain jar | Maven or Gradle multi-module parent |
514
+ | C, C++ | `add_executable`, `bin_PROGRAMS` | `add_library`, `lib_LTLIBRARIES` (`linkage:` shared, static, header-only) | none |
515
+ | Shell, Perl | scripts (`bin/`) | `.pm` distributions, sourced files | none |
516
+
517
+ Today the Go importer sets the type of the components it generates; the other ecosystems are classified by hand until
518
+ their importers emit components. Deployable forms (container image, Helm chart, deb, rpm) are `TechnologyArtifact`s
519
+ (`artifact/type`), not component types.
148
520
 
149
521
  ### Technology Layer
150
522
 
@@ -152,14 +524,131 @@ Model **infrastructure** and **code**.
152
524
 
153
525
  | Resource | When to Use |
154
526
  |----------|-------------|
155
- | TechnologyArtifact | For source code repositories |
527
+ | TechnologyArtifact | For source code repositories, packages, images and binaries (`artifact/type`); `aggregates` its contents, nodes are `assignedTo` it |
156
528
  | TechnologyService | For infrastructure services (Postgres, Redis, Kubernetes platform) |
157
529
  | TechnologySystemSoftware | For logical infrastructure (database cluster, message queue) |
158
- | TechnologyArtifact | For deployed containers/binaries |
159
- | TechnologyNode | For infrastructure instances |
530
+ | TechnologyNode | For infrastructure instances; `specializes` / `composedOf` another node |
160
531
  | TechnologyInterface | For technical protocols and endpoints |
532
+ | TechnologyCommunicationNetwork | For logical networks: underlay, overlay, management, public, VPN (`network/type`) |
533
+
534
+ **Example chain:** Component "Payments:API" → realizedThrough → Artifact "Repo:payments-api" → maintainedBy → Actor "Platform Team"
535
+
536
+ #### Logical Networks
537
+
538
+ Which kind to pick is in [Choosing the Kind: Infrastructure](#choosing-the-kind-infrastructure). A logical network is a `TechnologyCommunicationNetwork` (ArchiMate Communication Network). Physical links and fabrics stay
539
+ `TechnologyEquipment`; the network is what runs over them.
540
+
541
+ | From | Verb | To |
542
+ |------|------|----|
543
+ | `TechnologyCommunicationNetwork` | `composedOf` | `TechnologyCommunicationNetwork` (a metro network of its site networks) |
544
+ | `TechnologyCommunicationNetwork` | `specializes` | `TechnologyCommunicationNetwork` (concept and implementation) |
545
+ | `TechnologyCommunicationNetwork` | `servedBy` | `TechnologyCommunicationNetwork` (the network it runs over) |
546
+ | `TechnologyCommunicationNetwork` | `locatedAt` | `TechnologyFacility`, `Location` (many) |
547
+ | `TechnologyCommunicationNetwork` | `realizedBy` | `TechnologyEquipment` (the fabric), `TechnologySystemSoftware` (routing stack, VPN software) |
548
+ | `TechnologyCommunicationNetwork` | `realizedBy` | `ApplicationComponent`, `ApplicationService` (software that builds the network: an SDN agent, a network operator) |
549
+ | `TechnologyCommunicationNetwork` | `realizedBy` | `TechnologyDevice` (the switches and routers that build it) |
550
+ | `TechnologyCommunicationNetwork` | `connects` | `TechnologyDevice` (the devices attached to it) |
551
+ | `TechnologyNode` | `servedBy` | `TechnologyCommunicationNetwork` |
552
+ | `ApplicationInterface` | `servedBy` | `TechnologyCommunicationNetwork` (the networks on which it can be reached) |
553
+
554
+ - **Underlay and overlay:** the underlay *serves* the overlay, so the overlay is `servedBy` the underlay. A BGP-EVPN
555
+ network that carries customer workloads is one `overlay` network served by the underlay and realized by the routing
556
+ system software. Do not model a network per customer or tenant.
557
+ - **VPN:** a network of `network/type: vpn`, `servedBy` the network it tunnels through (usually the public network),
558
+ `locatedAt` the sites it joins and `realizedBy` the gateway software.
559
+ - **Mesh:** `network/topology: mesh` on **one** network that is `locatedAt` all its sites. Only when single tunnels
560
+ matter (capacity, owner) are they sub-networks, `composedOf` into the mesh.
561
+ - **Nesting and metro regions:** a network that supports a metro region is `locatedAt` the `Location` and
562
+ `composedOf` the networks of its sites. `composedOf` and `specializes` only point at networks and must not form a
563
+ cycle; `archsight lint` reports cycles of `composedOf`, `specializes` and `servedBy`.
564
+ - **Attachment:** a node is `servedBy` the networks it is attached to; the network page lists them. A physical
565
+ device is attached the other way round: the network `connects` it, so the network can also be `realizedBy` the
566
+ same switch without a cycle.
567
+ - **Reachability of an interface:** an `ApplicationInterface` is `servedBy` the networks on which it can be reached,
568
+ next to the `TechnologyInterface` that carries it. With `api/authenticationMethod` this is the exposure of the
569
+ interface (see the example analysis `Analysis:Interface:ExposedWithoutAuthentication`). Leave it out when the
570
+ networks are not known.
571
+
572
+ ```
573
+ # all overlay networks
574
+ TechnologyCommunicationNetwork: network/type == "overlay"
575
+
576
+ # networks that reach TechnologyFacility X
577
+ TechnologyCommunicationNetwork: -> "Facility:Madrid:DC"
578
+ ```
579
+
580
+ See `examples/archsight/technology/networks.yaml`.
581
+
582
+ ### Where Technology Runs
583
+
584
+ Which kind to pick is in [Choosing the Kind: Infrastructure](#choosing-the-kind-infrastructure).
585
+
586
+ Model **where** technology runs with `TechnologyFacility` (a building, data center or site, nested with `composedOf`),
587
+ `Location` (a country, metro or region) and, when the physical grouping matters, `TechnologyEquipment` (racks, fabrics,
588
+ physical clusters). Do not model sites as annotations, as one service per site, or as `TechnologyNode`s: a data
589
+ center is not a computational resource.
590
+
591
+ | Resource | When to Use |
592
+ |----------|-------------|
593
+ | Location | For a country, metro or region |
594
+ | TechnologyFacility | For a data center, colocation, office or edge site (`facility/type`), also a campus or hall inside one |
595
+ | TechnologyEquipment | Optional: racks, network fabrics, physical clusters inside a facility (`equipment/type`) |
596
+ | TechnologyDevice | Optional: one physical machine, `locatedAt` its room (`facility/type: room`) |
597
+
598
+ Relations are written on the element that is placed (see [Direction of Relations](#direction-of-relations)):
599
+
600
+ | From | Verb | To |
601
+ |------|------|----|
602
+ | `TechnologyNode`, `TechnologyService`, `TechnologySystemSoftware`, `TechnologyEquipment`, `TechnologyDevice` | `locatedAt` | `TechnologyFacility` (many) |
603
+ | `TechnologyFacility` | `locatedAt` | `Location` |
604
+ | `TechnologyFacility` | `composedOf` | `TechnologyFacility` (nested sites, the rooms of a data center) |
605
+ | `TechnologyFacility` | `servedBy` | `BusinessActor` (the operator) |
606
+ | `TechnologyDevice`, `TechnologyEquipment`, `TechnologyNode`, `TechnologyCommunicationNetwork` | `ownedBy` | `BusinessActor`, `BusinessRole` (the team that operates it) |
607
+ | `TechnologyDevice`, `TechnologyEquipment`, `TechnologyNode` | `servedBy` | `BusinessActor` (the team it is dedicated to, e.g. a test partition) |
608
+
609
+ `locatedAt` with many targets is the point: a service that runs in three data centers is **one** service with three
610
+ `locatedAt` relations. A `locatedAt` target that is not a TechnologyFacility (or, from a facility, a Location) is rejected by
611
+ `archsight lint`. TechnologyFacility and Location pages list what is located there (incoming `locatedAt`), grouped by kind.
612
+
613
+ A service may run on different platforms in different facilities (a managed platform in site A, a self-hosted one in
614
+ site B). There is no qualifier on the relation: locate the nodes or system software of each platform at its
615
+ facilities too, and the pair (platform, facility) is derivable.
616
+
617
+ Queries:
618
+
619
+ ```
620
+ # all technology services in TechnologyFacility X
621
+ TechnologyService: -> "DC:Alpha"
622
+
623
+ # facilities that host service Y
624
+ TechnologyFacility: <- "Orders:Cluster"
625
+ ```
626
+
627
+ #### Backbone and links between facilities
628
+
629
+ The physical network between sites is `TechnologyEquipment`. A **link** (fibre route, carrier circuit) is one TechnologyEquipment with
630
+ `equipment/type: link` that is `locatedAt` **both** end facilities. A **backbone** is a TechnologyEquipment that is `composedOf`
631
+ its links (composition only points at TechnologyEquipment and must not form a cycle). The logical network is a
632
+ `TechnologyService` (and routers are `TechnologyNode`s) that is `realizedBy` the TechnologyEquipment it runs over, and is
633
+ `locatedAt` the facilities it reaches:
634
+
635
+ ```
636
+ TechnologyService "Network:Backbone" --realizedBy--> TechnologyEquipment "Equipment:Backbone"
637
+ --composedOf--> TechnologyEquipment "Equipment:Link:Frankfurt-Madrid" (link)
638
+ --locatedAt--> TechnologyFacility Frankfurt, TechnologyFacility Madrid
639
+ ```
640
+
641
+ ```
642
+ # all links between facilities
643
+ TechnologyEquipment: equipment/type == "link"
644
+
645
+ # links that end in TechnologyFacility X
646
+ TechnologyEquipment: equipment/type == "link" & -> "Facility:Madrid:DC"
647
+ ```
161
648
 
162
- **Example chain:** Component "kube-apiserver" → realizedThrough → Artifact "kubernetes/kubernetes" → maintainedBy → Actor "Platform Team"
649
+ The TechnologyEquipment page lists what is realized by it (incoming `realizedBy`) and the backbones it belongs to (incoming
650
+ `composedOf`). A link has no endpoints of its own: it is placed at its facilities, so keep to two `locatedAt` targets
651
+ per link. See `examples/archsight/technology/facilities.yaml`.
163
652
 
164
653
  ## Relation Patterns
165
654
 
@@ -182,6 +671,8 @@ TechnologyArtifact
182
671
  Shows how services depend on each other:
183
672
 
184
673
  ```
674
+ ApplicationService
675
+ ↓ dependsOn (another ApplicationService)
185
676
  ApplicationService
186
677
  ↓ servedBy
187
678
  TechnologyService
@@ -189,7 +680,101 @@ TechnologyService
189
680
  TechnologySystemSoftware
190
681
  ```
191
682
 
192
- ### Requirements, Controls and Evidence
683
+ A service that uses another one says so with `dependsOn` on the service, the same verb components use between each
684
+ other. Do not add the other service's components to your own `realizedThrough`: the component would then belong to
685
+ two services, its owner is ambiguous and every rollup over the service's components counts it twice. Two services may
686
+ depend on each other, so `dependsOn` is exempt from the cycle check. In `examples/archsight`, "Refunds" depends on "Payment Authorization" (it refunds an authorized payment) and
687
+ "Payment Authorization" depends on "Refunds" (it asks to reverse a payment it cannot complete).
688
+
689
+ ### Where a Component Runs
690
+
691
+ Three relations say what something runs on; each answers a different question:
692
+
693
+ | Relation | Means | Example |
694
+ |----------|-------|---------|
695
+ | ApplicationComponent `servedBy technologyServices` | the platform service the component is deployed on | `Payments:API` runs in `Payments:Cluster` |
696
+ | ApplicationComponent `servedBy technologySystemSoftware` | the runtime it runs on | a Kubernetes distribution, a JVM |
697
+ | ApplicationService `servedBy technologyServices` | a platform service the service as a whole uses | a managed database, the clusters of its own components |
698
+
699
+ Deployment importers (Argo CD, Helm, Cluster API) know every cluster a deployable runs in and write the relation per
700
+ component. Keep the service-level relation to the clusters of the service's own components: a sidecar or agent that
701
+ the products deploy into their own clusters (a DNS or monitoring agent) is `servedBy` each of those clusters, and its
702
+ owning service is not, so it does not look like it runs everywhere. The TechnologyService page lists the components
703
+ deployed on it as incoming `servedBy` from ApplicationComponent. The `deployment/cluster` annotation is deprecated in
704
+ favour of the relation, which the graph, views and analyses see; it still loads, and `archsight lint` lists every use
705
+ as a deprecation without failing. See
706
+ `examples/archsight/technology/payments-platform.yaml`.
707
+
708
+ ### Concept and Implementation
709
+
710
+ One technology *concept* often has several *implementations*: a "regional cluster" is implemented by a hypervisor
711
+ platform on some sites and by bare metal on others. Model the concept as an element and let every implementation
712
+ **specialize** it (ArchiMate specialization). The specialization is written on the specific element and always points
713
+ to an element of the **same kind**:
714
+
715
+ | Kind | Verb | Target | ArchiMate |
716
+ |------|------|--------|-----------|
717
+ | `TechnologyNode` | `specializes` | `TechnologyNode` | specialization |
718
+ | `TechnologySystemSoftware` | `specializes` | `TechnologySystemSoftware` | specialization |
719
+ | `TechnologyService` | `specializes` | `TechnologyService` | specialization |
720
+ | `TechnologyNode` | `composedOf` | `TechnologyNode` | composition (a cluster made of hosts) |
721
+ | `TechnologySystemSoftware` | `composedOf` | `TechnologySystemSoftware` | composition (a platform bundles components) |
722
+
723
+ ```yaml
724
+ kind: TechnologyNode
725
+ metadata:
726
+ name: Tech:RegionalCluster # the concept
727
+ spec: {}
728
+ ---
729
+ kind: TechnologyNode
730
+ metadata:
731
+ name: Tech:RegionalCluster:Hypervisor # one implementation
732
+ spec:
733
+ specializes:
734
+ technologyNodes:
735
+ - Tech:RegionalCluster
736
+ composedOf:
737
+ technologyNodes:
738
+ - Tech:RegionalCluster:Host
739
+ ```
740
+
741
+ The page of the concept shows the implementations as incoming `specializes`, the implementation shows what it
742
+ `specializes`. A target of another kind is rejected when the resources are loaded, and `archsight lint` reports a
743
+ `specializes` or `composedOf` chain that leads back to where it started. Do not use `realizedBy` between elements of
744
+ one kind: realization goes from concrete to abstract across layers. See `examples/archsight/technology/platforms.yaml`.
745
+
746
+ ### Deployment
747
+
748
+ An artifact (`TechnologyArtifact`) describes what reaches a host; three relations connect it to the rest:
749
+
750
+ | Kind | Verb | Target | ArchiMate | Meaning |
751
+ |------|------|--------|-----------|---------|
752
+ | `TechnologyArtifact` | `aggregates` | `TechnologyArtifact` | aggregation | an image contains packages, a chart references container images |
753
+ | `TechnologyNode` | `assignedTo` | `TechnologyArtifact` | assignment | the artifact is deployed on the node |
754
+ | `TechnologySystemSoftware` | `assignedTo` | `TechnologyArtifact` | assignment | the artifact is executed by the system software |
755
+
756
+ `assignedTo` is written on the node or system software, which owns the deployment. A bootable OS image, VM template or
757
+ disk image is an artifact of `artifact/type: image` (`binary` and `archive` exist as well).
758
+
759
+ ```
760
+ ApplicationComponent
761
+ ↓ realizedThrough (what the component is built from)
762
+ TechnologyArtifact (image)
763
+ ↓ aggregates (what the image contains)
764
+ TechnologyArtifact (package)
765
+
766
+ TechnologyNode
767
+ ↓ assignedTo (where the artifact is deployed)
768
+ TechnologyArtifact
769
+ ```
770
+
771
+ The artifact's page shows `aggregates` as incoming "contained in" and `assignedTo` as incoming "deployed on"; the node's
772
+ page shows what it `assignedTo`. This answers "which hosts get package X" with a reverse lookup instead of a package list in
773
+ an annotation. `archsight lint` reports an `aggregates` chain that leads back to where it started. Example: a host role
774
+ boots an image that contains two packages, and configuration management installs a third on the same hosts, see
775
+ `examples/archsight/technology/deployment.yaml`. Do not use `servedBy` between artifacts for contents: it reads as
776
+ "is served by", not "contains".
777
+
193
778
 
194
779
  A requirement is the point where the process side and the application side of compliance meet:
195
780
 
@@ -399,6 +984,32 @@ Use annotations to capture metadata:
399
984
  - `architecture/diagram` - A hand-drawn [`.asd` diagram](diagram.md#the-architecturediagram-annotation), shown next to the generated dependency graph
400
985
  (`.asd` code blocks also render inside `architecture/description` markdown). Nodes can link to resources with `resource "Name"`.
401
986
 
987
+ ### Lifecycle
988
+
989
+ `lifecycle/status` marks any resource with `architecture/*` annotations (products, components, services, artifacts, ...) as
990
+ `planned` (not yet in use), `active`, `deprecated` (do not start new uses), `sunset` (being phased out) or `end-of-life`
991
+ (no longer operated or supported). A resource without the annotation is `active`: the annotation's default, so
992
+ `lifecycle/status == "active"` finds it and the sidebar filter counts it (the editor does not write the default into the
993
+ file). The status shows as a badge (blue for `planned`, yellow for `deprecated`, red for `sunset` and `end-of-life`) and
994
+ is a sidebar filter and query term (`lifecycle/status == "deprecated"`).
995
+
996
+ | Annotation | Purpose |
997
+ |------------|---------|
998
+ | `lifecycle/status` | The state above |
999
+ | `lifecycle/activeAt`, `lifecycle/deprecatedAt`, `lifecycle/sunsetAt`, `lifecycle/endOfLifeAt` | When it happened or will happen (ISO 8601 date or time, checked by `archsight lint`) |
1000
+ | `lifecycle/replacedBy` | The resource that replaces it: a name for a resource of the same kind, `Kind/Name` for another kind (a component replaced by an `ApplicationService/...`). Shown as a link, `archsight lint` checks that it exists |
1001
+ | `lifecycle/reason` | Why, in markdown |
1002
+
1003
+ ```yaml
1004
+ kind: ApplicationService
1005
+ metadata:
1006
+ name: LegacyExport
1007
+ annotations:
1008
+ lifecycle/status: sunset
1009
+ lifecycle/sunsetAt: 2027-03-31
1010
+ lifecycle/replacedBy: ApplicationService/ExportV2
1011
+ ```
1012
+
402
1013
  ## Common Patterns
403
1014
 
404
1015
  ### Microservice