archsight 0.3.2 → 0.4.0

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 (189) 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 +32 -0
  8. data/docs/import.md +178 -55
  9. data/docs/index.md.erb +31 -8
  10. data/docs/modeling.md +772 -24
  11. data/docs/pages.md +44 -13
  12. data/docs/search.md +21 -1
  13. data/docs/togaf.md +5 -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 +246 -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/asset_annotations.rb +34 -0
  21. data/lib/archsight/annotations/link_annotations.rb +15 -0
  22. data/lib/archsight/annotations/resource_reference.rb +12 -0
  23. data/lib/archsight/annotations/risk_annotations.rb +21 -0
  24. data/lib/archsight/cli.rb +124 -23
  25. data/lib/archsight/database.rb +40 -0
  26. data/lib/archsight/diagram/cli.rb +50 -2
  27. data/lib/archsight/diagram/formatter.rb +112 -0
  28. data/lib/archsight/diagram/routing/edge_router/orthogonal_path.rb +38 -10
  29. data/lib/archsight/diagram/routing/edge_router.rb +29 -4
  30. data/lib/archsight/diagram/routing/edge_routing.rb +61 -5
  31. data/lib/archsight/diagram/style/theme.rb +7 -2
  32. data/lib/archsight/documentation.rb +3 -2
  33. data/lib/archsight/editor/page_source.rb +13 -1
  34. data/lib/archsight/export/confluence/analysis_output.rb +101 -0
  35. data/lib/archsight/export/confluence/client.rb +13 -0
  36. data/lib/archsight/export/confluence/diagram_links.rb +1 -1
  37. data/lib/archsight/export/confluence/exporter.rb +40 -13
  38. data/lib/archsight/export/confluence/labels.rb +25 -0
  39. data/lib/archsight/export/confluence/page_properties.rb +4 -6
  40. data/lib/archsight/export/confluence/storage.rb +38 -2
  41. data/lib/archsight/helpers/embeds.rb +18 -7
  42. data/lib/archsight/helpers/resource_resolver.rb +25 -0
  43. data/lib/archsight/import/executor.rb +139 -16
  44. data/lib/archsight/import/handler.rb +55 -6
  45. data/lib/archsight/import/handler_loader.rb +64 -0
  46. data/lib/archsight/import/handlers/cache_pruner.rb +30 -7
  47. data/lib/archsight/import/handlers/command.rb +120 -0
  48. data/lib/archsight/import/handlers/github.rb +4 -1
  49. data/lib/archsight/import/handlers/gitlab.rb +4 -1
  50. data/lib/archsight/import/handlers/go_dep_resolver.rb +10 -2
  51. data/lib/archsight/import/handlers/go_grapher.rb +102 -5
  52. data/lib/archsight/import/handlers/go_module_parser.rb +88 -0
  53. data/lib/archsight/import/handlers/grapher.rb +40 -1
  54. data/lib/archsight/import/handlers/repository.rb +3 -0
  55. data/lib/archsight/import/handlers/rest_api_index.rb +3 -0
  56. data/lib/archsight/import/registry.rb +22 -1
  57. data/lib/archsight/import.rb +64 -1
  58. data/lib/archsight/linter/structure.rb +239 -0
  59. data/lib/archsight/linter.rb +217 -6
  60. data/lib/archsight/page_loader.rb +12 -1
  61. data/lib/archsight/query/evaluator.rb +13 -6
  62. data/lib/archsight/query/parser.rb +73 -6
  63. data/lib/archsight/query.rb +1 -1
  64. data/lib/archsight/references.rb +3 -3
  65. data/lib/archsight/renderer.rb +80 -23
  66. data/lib/archsight/resources/analysis.rb +3 -2
  67. data/lib/archsight/resources/application_component.rb +83 -8
  68. data/lib/archsight/resources/application_event.rb +79 -0
  69. data/lib/archsight/resources/application_service.rb +18 -2
  70. data/lib/archsight/resources/base.rb +58 -5
  71. data/lib/archsight/resources/business_actor.rb +14 -1
  72. data/lib/archsight/resources/business_contract.rb +72 -0
  73. data/lib/archsight/resources/business_control.rb +10 -2
  74. data/lib/archsight/resources/business_event.rb +79 -0
  75. data/lib/archsight/resources/business_process.rb +8 -1
  76. data/lib/archsight/resources/business_product.rb +12 -0
  77. data/lib/archsight/resources/business_role.rb +70 -0
  78. data/lib/archsight/resources/compliance_evidence.rb +8 -2
  79. data/lib/archsight/resources/data_object.rb +6 -1
  80. data/lib/archsight/resources/implementation_deliverable.rb +63 -0
  81. data/lib/archsight/resources/implementation_event.rb +52 -0
  82. data/lib/archsight/resources/implementation_gap.rb +49 -0
  83. data/lib/archsight/resources/implementation_plateau.rb +67 -0
  84. data/lib/archsight/resources/implementation_work_package.rb +84 -0
  85. data/lib/archsight/resources/import.rb +37 -11
  86. data/lib/archsight/resources/location.rb +56 -0
  87. data/lib/archsight/resources/motivation_assessment.rb +121 -0
  88. data/lib/archsight/resources/motivation_constraint.rb +7 -1
  89. data/lib/archsight/resources/motivation_driver.rb +50 -0
  90. data/lib/archsight/resources/motivation_goal.rb +13 -1
  91. data/lib/archsight/resources/motivation_principle.rb +75 -0
  92. data/lib/archsight/resources/motivation_requirement.rb +18 -2
  93. data/lib/archsight/resources/motivation_stakeholder.rb +21 -0
  94. data/lib/archsight/resources/page.rb +9 -7
  95. data/lib/archsight/resources/strategy_capability.rb +9 -0
  96. data/lib/archsight/resources/technology_artifact.rb +11 -4
  97. data/lib/archsight/resources/technology_communication_network.rb +89 -0
  98. data/lib/archsight/resources/technology_device.rb +88 -0
  99. data/lib/archsight/resources/technology_equipment.rb +75 -0
  100. data/lib/archsight/resources/technology_event.rb +80 -0
  101. data/lib/archsight/resources/technology_facility.rb +70 -0
  102. data/lib/archsight/resources/technology_node.rb +57 -1
  103. data/lib/archsight/resources/technology_service.rb +33 -0
  104. data/lib/archsight/resources/technology_system_software.rb +28 -0
  105. data/lib/archsight/resources.rb +12 -0
  106. data/lib/archsight/version.rb +1 -1
  107. data/lib/archsight/web/api/analysis_helpers.rb +55 -0
  108. data/lib/archsight/web/api/json_helpers.rb +3 -37
  109. data/lib/archsight/web/api/openapi/spec.yaml +10 -8
  110. data/lib/archsight/web/api/page_helpers.rb +1 -8
  111. data/lib/archsight/web/api/routes.rb +7 -2
  112. data/lib/archsight/web/application.rb +38 -2
  113. data/lib/archsight/web/editor/routes.rb +2 -1
  114. data/lib/archsight/web/public/vue/ApiDocsPage-COp4onwn.js +1 -0
  115. data/lib/archsight/web/public/vue/DocPage-D52OwaKc.js +1 -0
  116. data/lib/archsight/web/public/vue/EditorPage-3aqL7yVf.js +35 -0
  117. data/lib/archsight/web/public/vue/ErrorPage--b9XeSYa.js +2 -0
  118. data/lib/archsight/web/public/vue/GraphView-qh_EtRrQ.js +1 -0
  119. data/lib/archsight/web/public/vue/HomePage-C2TNh2U-.js +2 -0
  120. data/lib/archsight/web/public/vue/InstanceRouter-ZaCcjlIX.css +1 -0
  121. data/lib/archsight/web/public/vue/InstanceRouter-uzb_OMG0.js +1 -0
  122. data/lib/archsight/web/public/vue/KindList-CyJuP_uq.js +1 -0
  123. data/lib/archsight/web/public/vue/KindList-yYcRT2BV.css +1 -0
  124. data/lib/archsight/web/public/vue/PageView-B93woeN3.css +1 -0
  125. data/lib/archsight/web/public/vue/PageView-FyygrS-b.js +1 -0
  126. data/lib/archsight/web/public/vue/QueryError-B4Ex_csZ.js +1 -0
  127. data/lib/archsight/web/public/vue/ResourceList-BY6Z1Kcb.js +2 -0
  128. data/lib/archsight/web/public/vue/ResourceList-D75O87zG.css +1 -0
  129. data/lib/archsight/web/public/vue/{SearchResults-CyPUZZSC.css → SearchResults-BV6UHriJ.css} +1 -1
  130. data/lib/archsight/web/public/vue/SearchResults-CkFpHF8m.js +1 -0
  131. data/lib/archsight/web/public/vue/WikiPage-BoHNewCX.js +3 -0
  132. data/lib/archsight/web/public/vue/WikiPage-TpmM1VAF.css +1 -0
  133. data/lib/archsight/web/public/vue/architecture-7GRP2DOG-BvzKZE4e.js +1 -0
  134. data/lib/archsight/web/public/vue/cynefin-OW5HDTMX-D-xs_Hxh.js +1 -0
  135. data/lib/archsight/web/public/vue/eventmodeling-NTZA5JFV-nbjxG01S.js +1 -0
  136. data/lib/archsight/web/public/vue/gitGraph-4MIJSDKK-CW6mw2ab.js +1 -0
  137. data/lib/archsight/web/public/vue/index-BGlYCbi7.js +3 -0
  138. data/lib/archsight/web/public/vue/index-eUHmJ7K2.css +1 -0
  139. data/lib/archsight/web/public/vue/info-A6RAGUB7-C12sjlHe.js +1 -0
  140. data/lib/archsight/web/public/vue/{mermaid-BjEi5URd.js → mermaid-DjsXQ_XN.js} +35 -35
  141. data/lib/archsight/web/public/vue/packet-AYTQ26CC-wMwKwHmA.js +1 -0
  142. data/lib/archsight/web/public/vue/pie-WAS4IAKB-w1-sAU_K.js +1 -0
  143. data/lib/archsight/web/public/vue/radar-RG4KPBEZ-DpwqIFoy.js +1 -0
  144. data/lib/archsight/web/public/vue/railroad-74A4TZTK-Ce5XC24d.js +1 -0
  145. data/lib/archsight/web/public/vue/railroad-abnf-HS5TGJTU-BSQO2pds.js +1 -0
  146. data/lib/archsight/web/public/vue/railroad-ebnf-LZEXJU2U-Dq1c2YtD.js +1 -0
  147. data/lib/archsight/web/public/vue/railroad-peg-WCYAUIDC-DKj6dli0.js +1 -0
  148. data/lib/archsight/web/public/vue/rolldown-runtime-hePW80VL.js +1 -0
  149. data/lib/archsight/web/public/vue/treeView-Q6P3EWNA-BmHNTWxU.js +1 -0
  150. data/lib/archsight/web/public/vue/treemap-WGGIJYW6-DsEI7sSD.js +1 -0
  151. data/lib/archsight/web/public/vue/{useGraphviz-DweKV7Kg.js → useGraphviz-4evusK9i.js} +13 -1
  152. data/lib/archsight/web/public/vue/{useHighlight-D5Gf8DLl.js → useHighlight-DPguaxfm.js} +8 -8
  153. data/lib/archsight/web/public/vue/usePanZoom-seQE1TPk.js +12 -0
  154. data/lib/archsight/web/public/vue/wardley-WFR3VGLG-CSCW83-M.js +1 -0
  155. data/lib/archsight/web/public/vue.html +5 -5
  156. metadata +72 -38
  157. data/lib/archsight/web/public/vue/ApiDocsPage-DoOxKjG0.js +0 -1
  158. data/lib/archsight/web/public/vue/DocPage-CfsC3CeQ.js +0 -1
  159. data/lib/archsight/web/public/vue/EditorPage-CsJA0q8n.js +0 -35
  160. data/lib/archsight/web/public/vue/ErrorPage-OJpJz9df.js +0 -2
  161. data/lib/archsight/web/public/vue/GraphView-CBq6oFRV.js +0 -1
  162. data/lib/archsight/web/public/vue/HomePage-BwgMLgVC.js +0 -2
  163. data/lib/archsight/web/public/vue/InstanceRouter-DQz-SsQq.js +0 -1
  164. data/lib/archsight/web/public/vue/InstanceRouter-jeavM6PW.css +0 -1
  165. data/lib/archsight/web/public/vue/KindList-4q0K9Cll.js +0 -1
  166. data/lib/archsight/web/public/vue/PageView-DzeGnvoS.js +0 -1
  167. data/lib/archsight/web/public/vue/QueryError-kg6Yf-pW.js +0 -1
  168. data/lib/archsight/web/public/vue/ResourceList-B0FLaFR3.css +0 -1
  169. data/lib/archsight/web/public/vue/ResourceList-Df_0e0qt.js +0 -2
  170. data/lib/archsight/web/public/vue/SearchResults-CKgY6_wH.js +0 -1
  171. data/lib/archsight/web/public/vue/WikiPage-DoFJ0dbW.css +0 -1
  172. data/lib/archsight/web/public/vue/WikiPage-DrvCHwJ7.js +0 -13
  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/index-D0Q5GZRs.js +0 -3
  178. data/lib/archsight/web/public/vue/index-oF-iyZvk.css +0 -1
  179. data/lib/archsight/web/public/vue/info-A6RAGUB7-BIlCVuUY.js +0 -1
  180. data/lib/archsight/web/public/vue/packet-AYTQ26CC-eoQTjY3j.js +0 -1
  181. data/lib/archsight/web/public/vue/pie-WAS4IAKB-DEOotGhh.js +0 -1
  182. data/lib/archsight/web/public/vue/radar-RG4KPBEZ-C2yucuUN.js +0 -1
  183. data/lib/archsight/web/public/vue/railroad-74A4TZTK-CzONK5VY.js +0 -1
  184. data/lib/archsight/web/public/vue/railroad-abnf-HS5TGJTU-9zRPsDsx.js +0 -1
  185. data/lib/archsight/web/public/vue/railroad-ebnf-LZEXJU2U-BJ4dkz9l.js +0 -1
  186. data/lib/archsight/web/public/vue/railroad-peg-WCYAUIDC-DFy_rqAj.js +0 -1
  187. data/lib/archsight/web/public/vue/treeView-Q6P3EWNA-2cq5CyD2.js +0 -1
  188. data/lib/archsight/web/public/vue/treemap-WGGIJYW6-DK-e9Ez4.js +0 -1
  189. data/lib/archsight/web/public/vue/wardley-WFR3VGLG-BQwqUqfB.js +0 -1
data/docs/modeling.md CHANGED
@@ -7,17 +7,327 @@ 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)
21
+ ```
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
+
26
+ ## Direction of Relations
27
+
28
+ Model and read the architecture **top-down**: Motivation, Strategy, Business, Application, Technology; the
29
+ Implementation & Migration layer describes change across all of them. A relation is written on an element and points
30
+ to what that element depends on, is served by, or is answered by. Following relations from a high-level element
31
+ therefore walks down to people, code and infrastructure, and the relations form a DAG: nothing may lead back to where
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".
34
+
35
+ There are two families of verbs:
36
+
37
+ | Family | Verbs | Written on | Points to |
38
+ |--------|-------|------------|-----------|
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 |
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) |
41
+
42
+ Rules:
43
+
44
+ - A pair of kinds never has the same relation in both directions: a goal `realizes` a requirement, a requirement does not
45
+ `realize` a goal. Reverse relations are shown for free as incoming relations.
46
+ - Responsibility ends at the actor: process, control, risk, policy, work package point to a `BusinessRole`, the role
47
+ points to the `BusinessActor` that holds it, and the actor points to nothing further.
48
+ - The docs draw realization chains top-down ("Requirement, down to Service") while the data is stored on the concrete
49
+ element, so the file of a service says what it realizes.
50
+ - `mentions` and `depicts` are not part of this structure. They are derived from the text and diagrams of a resource
51
+ (never written in a file) and show how things are linked sideways, in prose and pictures. They neither follow nor
52
+ contradict the direction above and are left out of the cycle check.
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
+ 9. An overlay that software builds (an SDN agent wiring tenant networks on each host, an operator creating VXLAN
194
+ segments, a load-balancer controller announcing public addresses) is `realizedBy` that `ApplicationComponent` or
195
+ `ApplicationService` (ArchiMate cross-layer realization). This holds even when the software runs on the nodes the
196
+ network serves: point at the application component, not at the node's system software, which would close a cycle
197
+ (network → system software → node → network).
198
+ 10. One `TechnologyDevice` per physical machine, `locatedAt` its room (a TechnologyFacility of `facility/type: room`
199
+ the data center is `composedOf`). A group of machines with one role stays a logical `TechnologyNode` that is
200
+ `realizedBy` its devices; a rack or hardware block is TechnologyEquipment `composedOf` them; a virtual chassis or
201
+ stack is a device `composedOf` its members.
202
+ 11. A network is `realizedBy` the devices that build it (switches, routers) and `connects` the devices attached to it.
203
+ Both are written on the network, so a switch attached to the network it builds closes no cycle.
204
+ 12. Cables are `connectedTo` between devices, declared once on one of the two ends. Cabling runs both ways by nature
205
+ and is left out of the cycle check.
206
+ 13. Devices, equipment, nodes and networks are `ownedBy` the team (BusinessActor) or BusinessRole that operates
207
+ them. Devices, equipment and nodes are `servedBy` the team they are dedicated to (ArchiMate serving: the
208
+ technology serves the actor), such as the servers of a shared test cluster partitioned among teams;
209
+ `device/purpose` and `equipment/purpose` say what for ("kernel regression tests"). A partition is equipment
210
+ `servedBy` its team and `composedOf` its devices, which then need no team of their own. Both relations point
211
+ down to the team, which points to nothing further. On a TechnologyFacility, `servedBy` stays the operator of
212
+ the site.
213
+
214
+ **Checked by `archsight lint`**
215
+
216
+ As above, these are **warnings** in the "Modeling warnings" section and never fail the lint:
217
+
218
+ | Warning | Rule |
219
+ |---------|------|
220
+ | `TechnologyEquipment 'Equipment:Link:A-B' is a link located at 1 facility, not 2` | 2 |
221
+ | `TechnologyCommunicationNetwork 'Network:Overlay:EVPN' is an overlay network served by no network` | 3 |
222
+ | `TechnologyFacility 'Facility:Madrid:DC' is located at no Location` | where |
223
+ | `TechnologyEquipment 'Equipment:Rack01' is located at no TechnologyFacility` | where |
224
+ | `TechnologyDevice 'Device:Server01' is located at no TechnologyFacility` | 10 |
225
+ | `TechnologyDevice 'Device:Switch01' is connectedTo itself` | 12 |
226
+ | `TechnologyDevice 'Device:Router01' is a router that realizes no TechnologyCommunicationNetwork` | 11 |
227
+ | `TechnologyDevice 'Device:a:server-3' is servedBy 'Kernel:Team', not by the team of its equipment ('Compute:Team')` | 13 |
228
+
229
+ Nested facilities need no location of their own (the outermost facility has it), and TechnologyEquipment that is part of other
230
+ TechnologyEquipment, or composed of placed parts, needs no facility of its own. The same holds for a device inside a
231
+ rack or a virtual chassis, and for a chassis whose members are placed; the members of a chassis realize the network
232
+ through the chassis.
233
+
234
+ **Example chain**
235
+
236
+ ```
237
+ Location "Location:Germany:Frankfurt"
238
+ ↑ locatedAt
239
+ TechnologyFacility "Facility:Frankfurt:Campus" ──composedOf──> TechnologyFacility "Facility:Frankfurt:HallA"
240
+ ↑ locatedAt (both ends) ↑ locatedAt
241
+ TechnologyEquipment "Equipment:Link:Frankfurt-Madrid" (link) TechnologyNode "Node:Frankfurt:Web01"
242
+ ↑ composedOf │ servedBy
243
+ TechnologyEquipment "Equipment:Backbone" ↓
244
+ ↑ realizedBy TechnologyCommunicationNetwork "Network:Management:Frankfurt"
245
+ TechnologyService "Network:Backbone"
246
+ ```
247
+
248
+ Devices, one level further down (hall A of the example):
249
+
250
+ ```
251
+ TechnologyCommunicationNetwork "Network:Management:Frankfurt"
252
+ │ realizedBy │ connects
253
+ ↓ ↓
254
+ TechnologyDevice "Device:Frankfurt:Switch:Core" TechnologyDevice "Device:Frankfurt:Server01" ──locatedAt──> TechnologyFacility "Facility:Frankfurt:HallA:Room1"
255
+ │ composedOf │ connectedTo ↑ composedOf
256
+ ↓ ↓ TechnologyFacility "Facility:Frankfurt:HallA"
257
+ TechnologyDevice "Device:Frankfurt:Switch:Core:n0" ←─┘
258
+ ```
259
+
260
+ The physical machines of hall A, two rooms with their servers, switches, routers and firewalls, are in
261
+ `examples/archsight/technology/devices.yaml`, drawn room by room on the same example page.
262
+
263
+ The overlay `Network:Overlay:EVPN` is `servedBy` the underlay and `realizedBy` the routing software
264
+ `Tech:Routing:EVPN`. All of it is in `examples/archsight/technology/` (`facilities.yaml`, `networks.yaml`), walked
265
+ through on the example page "Infrastructure Modeling".
266
+
267
+ **Anti-patterns**
268
+
269
+ | Anti-pattern | Fix |
270
+ |--------------|-----|
271
+ | A data center modeled as a TechnologyNode | TechnologyFacility; the servers in it are nodes `locatedAt` it |
272
+ | Sites as annotations (`deployment/locations: dc-1,dc-2`) | TechnologyFacility elements and `locatedAt` |
273
+ | One copy of a service or cluster per site | One element `locatedAt` every site |
274
+ | A Location used for a building | TechnologyFacility `locatedAt` the Location |
275
+ | A link or fibre route as a TechnologyService | TechnologyEquipment `link`; the network service is `realizedBy` it |
276
+ | A network per tenant or customer | One overlay network; tenants stay out of the model |
277
+ | An element per pair of sites in a mesh | One network with `network/topology: mesh` |
278
+ | An overlay or VPN with nothing under it | `servedBy` the underlay or the network it tunnels through |
279
+
280
+ ## Identity and Links
281
+
282
+ A resource has one **name**, the key everything refers to (relations, `[[wiki links]]`, URLs). Two annotations say more
283
+ about who it is and where else it lives. Both are available on every resource kind (pages have the links too).
284
+
285
+ ### Aliases
286
+
287
+ `architecture/aliases` holds the other identifiers of a resource, comma-separated: `ApplicationService:Foo` can also be
288
+ `ITGS:A001`. Aliases are **unique among the resources of a kind** (`archsight lint` reports a duplicate with both
289
+ resources); the same alias on resources of different kinds is fine, like names. They are found by search and open a
290
+ resource by URL:
291
+
292
+ ```
293
+ ITGS:A001 # the search box: the name shortcut also tests aliases
294
+ ApplicationService: architecture/aliases == "ITGS:A001"
295
+ name == "ITGS:A001"
296
+ /kinds/ApplicationService/instances/ITGS:A001 # redirects to /kinds/ApplicationService/instances/Foo
19
297
  ```
20
298
 
299
+ In a URL (and the instance API) a name always wins; when no resource has that name, the one resource of the kind
300
+ with that alias opens under its real name. An alias is an identifier, so each alias is shown as a chip without a link
301
+ 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
302
+ relation or a `[[wiki link]]` must use the name. When two documents describe the same resource, their aliases (and
303
+ tags) are added together instead of one replacing the other.
304
+
305
+ For kind authors: `annotation "key", unique: true` makes any annotation an identifier of this kind: unique per kind,
306
+ checked by `archsight lint`, shown as chips without links. `annotation "key", deprecated: "what to use instead"` keeps an
307
+ annotation working while `archsight lint` lists every use as a deprecation (with the text), without failing.
308
+ `annotation "key", default: "value"` gives every resource that does not set the annotation that value when the
309
+ resources are loaded (queries, filters and pages see it; the editor does not write it into the file).
310
+
311
+ ### Links
312
+
313
+ `link/<name>` holds a URL on any resource. The name says which system: `link/confluence`, `link/jira`,
314
+ `link/servicenow`; a second link into the same system gets another name (`link/confluence-isms`). A link has **no
315
+ direction**: it is where the resource comes from, where it was published to, or just a related page. A page writes them
316
+ as `links:` in its frontmatter (see [Pages](/doc/pages)):
317
+
318
+ ```yaml
319
+ kind: ApplicationService
320
+ metadata:
321
+ name: Foo
322
+ annotations:
323
+ architecture/aliases: ITGS:A001
324
+ link/confluence: https://confluence.example.com/spaces/ARCH/pages/12345/Foo
325
+ link/jira: https://jira.example.com/browse/ARCH-12
326
+ ```
327
+
328
+ Links render with the icon of their system wherever a resource or page is shown. Artifacts also carry many generated
329
+ `link/*` entries (links found in the README); they are listed apart from the ones you write.
330
+
21
331
  ## Starting Points
22
332
 
23
333
  ### Top-Down Modeling
@@ -54,8 +364,41 @@ Model **why** the architecture exists.
54
364
  | MotivationOutcome | For measurable results ("99.9% availability", "Sub-100ms response") |
55
365
  | MotivationRequirement | For must-have capabilities (compliance, functional needs) |
56
366
  | MotivationConstraint | For limitations (budget, regulations, technical debt) |
367
+ | MotivationDriver | For threats, opportunities, regulation and market forces that motivate action (`driver/type`) |
368
+ | MotivationAssessment | For risks, vulnerabilities, findings and supplier or protection-need analyses (`assessment/type`) |
369
+ | MotivationPrinciple | For policies, guidelines and architecture principles (`principle/type`) |
57
370
 
58
- **Example chain:** Stakeholder "Security Team" → hasConcern → Goal "Achieve Compliance" → realizes → Requirement "Encrypt data at rest"
371
+ **Example chain:** Stakeholder "Security Team" → hasConcern → Goal "Achieve Compliance" → realizes → Requirement "Encrypt data at rest"; Stakeholder "Security Team" → representedBy → Actor "Security Office"
372
+
373
+ **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.
374
+
375
+ ### Strategy Layer
376
+
377
+ Model strategic **capabilities**.
378
+
379
+ | Resource | When to Use |
380
+ |----------|-------------|
381
+ | StrategyCapability | For abilities the organization needs ("Payment Processing", "Data Analytics"); not a product, team or certificate |
382
+
383
+ **Example chain:** Product "Online Checkout" → realizes → Capability "Payment Processing" → realizes → Requirement "Card Payments" (see [Choosing the Kind](#choosing-the-kind))
384
+
385
+ ### Implementation & Migration Layer
386
+
387
+ Model **change**: what is done, what it delivers and how the architecture looks before and after.
388
+
389
+ | Resource | When to Use |
390
+ |----------|-------------|
391
+ | ImplementationWorkPackage | For projects, measures, remediation of risks and findings, audit programmes (`workpackage/type`, status, due date) |
392
+ | ImplementationDeliverable | For the results of work packages: documents, systems, process changes, evidence (`deliverable/type`) |
393
+ | ImplementationEvent | For milestones, go-lives and deadlines (`event/type`) |
394
+ | ImplementationPlateau | For a state of the architecture: baseline, transition, target (`plateau/type`) |
395
+ | ImplementationGap | For the difference between two plateaus (`gap/status`, `gap/impact`) |
396
+
397
+ **Migration path:** Plateau "Baseline" → triggers → Plateau "Target"; Gap → compares → both plateaus; Work Package → realizes → Deliverable → realizes → Plateau "Target"; Gap → closedBy → Work Package.
398
+
399
+ **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`.
400
+
401
+ **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.
59
402
 
60
403
  ### Business Layer
61
404
 
@@ -64,23 +407,63 @@ Model **who** does **what** in business terms.
64
407
  | Resource | When to Use |
65
408
  |----------|-------------|
66
409
  | BusinessActor | For teams, departments, or organizations |
410
+ | BusinessRole | For responsibilities held by actors: control owner, risk owner, information security officer (`role/type`) |
67
411
  | BusinessProcess | For workflows that produce business value |
68
- | BusinessProduct | For offerings to customers (cloud services, APIs) |
412
+ | BusinessProduct | For what a customer buys or contracts, as on a price list ("Online Checkout", "Premium Support") |
413
+ | BusinessContract | For what a customer and a provider agreed: framework contracts, call-offs, SLAs, amendments (`contract/type`) |
69
414
  | BusinessControl | For controls that guide a process (access review, change approval), with an owner and executors |
415
+ | BusinessEvent | For things that happen in the business: threat events, loss events, incidents, triggers (`event/type`) |
70
416
 
71
- **Example chain:** Actor "Platform Team" → performedBy → Process "Incident Response" → servedBy → Service "Monitoring"
72
-
73
- **Controls:** Process "Incident Response" → guidedBy → Control "Escalation Review" → ownedBy / executedBy → Actor "Platform Team". How controls, requirements and evidence fit together is described under Relation Patterns below.
417
+ **Example chain:** Process "Incident Response" → performedBy → Actor "Platform Team"; Process "Incident Response" → servedBy → Service "Monitoring"
74
418
 
75
- ### Strategy Layer
419
+ **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.
76
420
 
77
- Model strategic **capabilities**.
421
+ **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.
78
422
 
79
- | Resource | When to Use |
80
- |----------|-------------|
81
- | StrategyCapability | For abilities the organization needs ("Container Orchestration", "Data Analytics") |
423
+ **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.
82
424
 
83
- **Example chain:** Capability "Managed Kubernetes" → realizes → Requirement "Container Platform" and servedBy → Service "ManagedKubernetes"
425
+ ```yaml
426
+ kind: BusinessProduct
427
+ metadata:
428
+ name: PrivateCloudOffering
429
+ spec:
430
+ servedBy:
431
+ applicationServices: [ComputeService, ObjectStorage]
432
+ aggregates:
433
+ businessContracts: [Contract:Customer]
434
+ ---
435
+ kind: BusinessContract
436
+ metadata:
437
+ name: Contract:Customer
438
+ annotations:
439
+ contract/type: framework
440
+ contract/from: '2024-01-01'
441
+ spec:
442
+ agreedBy:
443
+ businessActors: [CustomerOrg, ProviderOrg]
444
+ composedOf:
445
+ businessContracts: [Contract:Customer:Block1, Contract:Customer:Block2]
446
+ ---
447
+ kind: BusinessContract
448
+ metadata:
449
+ name: Contract:Customer:Block2
450
+ annotations:
451
+ contract/type: call-off
452
+ spec:
453
+ covers:
454
+ technologyEquipment: [Block2]
455
+ realizedThrough:
456
+ implementationDeliverables: [Block2Delivered]
457
+ ---
458
+ kind: ImplementationWorkPackage
459
+ metadata:
460
+ name: BuildBlock2
461
+ spec:
462
+ realizes:
463
+ implementationDeliverables: [Block2Delivered]
464
+ affects:
465
+ technologyEquipment: [Block2]
466
+ ```
84
467
 
85
468
  ### Application Layer
86
469
 
@@ -88,12 +471,49 @@ Model **software** that supports the business.
88
471
 
89
472
  | Resource | When to Use |
90
473
  |----------|-------------|
91
- | ApplicationService | For high-level services (ManagedKubernetes, ObjectStorage) |
92
- | ApplicationComponent | For deployable parts of services (API server, worker, scheduler) |
474
+ | ApplicationService | For behaviour software offers to a consumer, named by its function ("Payment Authorization", "Document Search") |
475
+ | ApplicationComponent | For what is built, deployed and versioned, by runtime role ("Payments:API", "Payments:Worker") |
93
476
  | ApplicationInterface | For APIs and integration points |
94
477
  | DataObject | For data structures and schemas |
95
478
 
96
- **Example chain:** Service "ManagedKubernetes" → realizedThrough → Component "kube-apiserver" → exposes → Interface "Kubernetes:RestAPI"
479
+ **Example chain:** Service "Payment Authorization" → realizedThrough → Component "Payments:API" → exposes → Interface "Payments:RestAPI"
480
+
481
+ #### Classifying components
482
+
483
+ Components are not all alike: some are run, some are only imported, some bundle both. Say which with `component/type`
484
+ (`executable`, `library`, `module`, `plugin`, `frontend`, `other`) and, for executables and plugins, what they do with
485
+ `component/role` (`service`, `cli`, `job`, `operator`, `agent`). Importers set `component/type` and add machine tags
486
+ (`namespace:value`, such as `ecosystem:go`, `packaging:go-module`, `linkage:shared`) to the regular
487
+ `architecture/tags` from the manifests; the tags a person set stay, and a re-import only replaces the machine tags of
488
+ those namespaces. The entry points (main packages such as `cmd/api`) are written to `component/entrypoints`, a list
489
+ you query like a tag (`component/entrypoints == "cmd/api"`) that is not a sidebar filter, because there are too many
490
+ 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
491
+ two repositories declare the same module path (a prototype and its successor, a fork), each gets its own component:
492
+ the repository the module path names keeps the plain name (`github.com/acme/library` names `Repo:acme:library`),
493
+ then the one that is not archived, then the first by name; the other gets its repository appended
494
+ (`alice:shop@acme:shop-prototype`), and a dependency on the module path points at the plain name. A `go.mod` in a
495
+ subdirectory whose module path names another known repository is a copy of that repository's module and gets no
496
+ component at all. Neither does a nested `go.mod` below a test, tool, example or benchmark directory (`test/e2e`,
497
+ `tools`, `hack`, `examples/foo`, `internal/systemtest`): nothing realizes such code or depends on it, so its packages
498
+ 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
499
+ import after that; until then `archsight lint` warns about the merged component. A hand-written component that lists
500
+ several repositories is left as it is. The computed `component/dependents` counts the components that depend on a
501
+ component, which shows how widely a library or module is shared.
502
+
503
+ | Ecosystem | Executable | Library | Module (bundles both) |
504
+ |-----------|------------|---------|-----------------------|
505
+ | Go | `package main` (`component/entrypoints`: one per main package) | no `main` package | main packages plus importable packages outside `internal/` and `cmd/` |
506
+ | JavaScript, TypeScript | `bin`, a server entry point | `main`, `exports`, `types` | `workspaces` root |
507
+ | Ruby | gemspec `executables`, Rails app | gem without executables | monorepo of gems |
508
+ | Python | `[project.scripts]`, `__main__.py` | package published to an index | distribution of several packages |
509
+ | Rust | `[[bin]]`, `src/main.rs` | `[lib]` | Cargo workspace |
510
+ | Java | `Main-Class`, Spring Boot, application plugin | plain jar | Maven or Gradle multi-module parent |
511
+ | C, C++ | `add_executable`, `bin_PROGRAMS` | `add_library`, `lib_LTLIBRARIES` (`linkage:` shared, static, header-only) | none |
512
+ | Shell, Perl | scripts (`bin/`) | `.pm` distributions, sourced files | none |
513
+
514
+ Today the Go importer sets the type of the components it generates; the other ecosystems are classified by hand until
515
+ their importers emit components. Deployable forms (container image, Helm chart, deb, rpm) are `TechnologyArtifact`s
516
+ (`artifact/type`), not component types.
97
517
 
98
518
  ### Technology Layer
99
519
 
@@ -101,14 +521,126 @@ Model **infrastructure** and **code**.
101
521
 
102
522
  | Resource | When to Use |
103
523
  |----------|-------------|
104
- | TechnologyArtifact | For source code repositories |
524
+ | TechnologyArtifact | For source code repositories, packages, images and binaries (`artifact/type`); `aggregates` its contents, nodes are `assignedTo` it |
105
525
  | TechnologyService | For infrastructure services (Postgres, Redis, Kubernetes platform) |
106
526
  | TechnologySystemSoftware | For logical infrastructure (database cluster, message queue) |
107
- | TechnologyArtifact | For deployed containers/binaries |
108
- | TechnologyNode | For infrastructure instances |
527
+ | TechnologyNode | For infrastructure instances; `specializes` / `composedOf` another node |
109
528
  | TechnologyInterface | For technical protocols and endpoints |
529
+ | TechnologyCommunicationNetwork | For logical networks: underlay, overlay, management, public, VPN (`network/type`) |
530
+
531
+ **Example chain:** Component "Payments:API" → realizedThrough → Artifact "Repo:payments-api" → maintainedBy → Actor "Platform Team"
532
+
533
+ #### Logical Networks
534
+
535
+ 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
536
+ `TechnologyEquipment`; the network is what runs over them.
537
+
538
+ | From | Verb | To |
539
+ |------|------|----|
540
+ | `TechnologyCommunicationNetwork` | `composedOf` | `TechnologyCommunicationNetwork` (a metro network of its site networks) |
541
+ | `TechnologyCommunicationNetwork` | `specializes` | `TechnologyCommunicationNetwork` (concept and implementation) |
542
+ | `TechnologyCommunicationNetwork` | `servedBy` | `TechnologyCommunicationNetwork` (the network it runs over) |
543
+ | `TechnologyCommunicationNetwork` | `locatedAt` | `TechnologyFacility`, `Location` (many) |
544
+ | `TechnologyCommunicationNetwork` | `realizedBy` | `TechnologyEquipment` (the fabric), `TechnologySystemSoftware` (routing stack, VPN software) |
545
+ | `TechnologyCommunicationNetwork` | `realizedBy` | `ApplicationComponent`, `ApplicationService` (software that builds the network: an SDN agent, a network operator) |
546
+ | `TechnologyCommunicationNetwork` | `realizedBy` | `TechnologyDevice` (the switches and routers that build it) |
547
+ | `TechnologyCommunicationNetwork` | `connects` | `TechnologyDevice` (the devices attached to it) |
548
+ | `TechnologyNode` | `servedBy` | `TechnologyCommunicationNetwork` |
549
+
550
+ - **Underlay and overlay:** the underlay *serves* the overlay, so the overlay is `servedBy` the underlay. A BGP-EVPN
551
+ network that carries customer workloads is one `overlay` network served by the underlay and realized by the routing
552
+ system software. Do not model a network per customer or tenant.
553
+ - **VPN:** a network of `network/type: vpn`, `servedBy` the network it tunnels through (usually the public network),
554
+ `locatedAt` the sites it joins and `realizedBy` the gateway software.
555
+ - **Mesh:** `network/topology: mesh` on **one** network that is `locatedAt` all its sites. Only when single tunnels
556
+ matter (capacity, owner) are they sub-networks, `composedOf` into the mesh.
557
+ - **Nesting and metro regions:** a network that supports a metro region is `locatedAt` the `Location` and
558
+ `composedOf` the networks of its sites. `composedOf` and `specializes` only point at networks and must not form a
559
+ cycle; `archsight lint` reports cycles of `composedOf`, `specializes` and `servedBy`.
560
+ - **Attachment:** a node is `servedBy` the networks it is attached to; the network page lists them. A physical
561
+ device is attached the other way round: the network `connects` it, so the network can also be `realizedBy` the
562
+ same switch without a cycle.
563
+
564
+ ```
565
+ # all overlay networks
566
+ TechnologyCommunicationNetwork: network/type == "overlay"
567
+
568
+ # networks that reach TechnologyFacility X
569
+ TechnologyCommunicationNetwork: -> "Facility:Madrid:DC"
570
+ ```
571
+
572
+ See `examples/archsight/technology/networks.yaml`.
573
+
574
+ ### Where Technology Runs
575
+
576
+ Which kind to pick is in [Choosing the Kind: Infrastructure](#choosing-the-kind-infrastructure).
577
+
578
+ Model **where** technology runs with `TechnologyFacility` (a building, data center or site, nested with `composedOf`),
579
+ `Location` (a country, metro or region) and, when the physical grouping matters, `TechnologyEquipment` (racks, fabrics,
580
+ physical clusters). Do not model sites as annotations, as one service per site, or as `TechnologyNode`s: a data
581
+ center is not a computational resource.
582
+
583
+ | Resource | When to Use |
584
+ |----------|-------------|
585
+ | Location | For a country, metro or region |
586
+ | TechnologyFacility | For a data center, colocation, office or edge site (`facility/type`), also a campus or hall inside one |
587
+ | TechnologyEquipment | Optional: racks, network fabrics, physical clusters inside a facility (`equipment/type`) |
588
+ | TechnologyDevice | Optional: one physical machine, `locatedAt` its room (`facility/type: room`) |
589
+
590
+ Relations are written on the element that is placed (see [Direction of Relations](#direction-of-relations)):
591
+
592
+ | From | Verb | To |
593
+ |------|------|----|
594
+ | `TechnologyNode`, `TechnologyService`, `TechnologySystemSoftware`, `TechnologyEquipment`, `TechnologyDevice` | `locatedAt` | `TechnologyFacility` (many) |
595
+ | `TechnologyFacility` | `locatedAt` | `Location` |
596
+ | `TechnologyFacility` | `composedOf` | `TechnologyFacility` (nested sites, the rooms of a data center) |
597
+ | `TechnologyFacility` | `servedBy` | `BusinessActor` (the operator) |
598
+ | `TechnologyDevice`, `TechnologyEquipment`, `TechnologyNode`, `TechnologyCommunicationNetwork` | `ownedBy` | `BusinessActor`, `BusinessRole` (the team that operates it) |
599
+ | `TechnologyDevice`, `TechnologyEquipment`, `TechnologyNode` | `servedBy` | `BusinessActor` (the team it is dedicated to, e.g. a test partition) |
600
+
601
+ `locatedAt` with many targets is the point: a service that runs in three data centers is **one** service with three
602
+ `locatedAt` relations. A `locatedAt` target that is not a TechnologyFacility (or, from a facility, a Location) is rejected by
603
+ `archsight lint`. TechnologyFacility and Location pages list what is located there (incoming `locatedAt`), grouped by kind.
604
+
605
+ A service may run on different platforms in different facilities (a managed platform in site A, a self-hosted one in
606
+ site B). There is no qualifier on the relation: locate the nodes or system software of each platform at its
607
+ facilities too, and the pair (platform, facility) is derivable.
608
+
609
+ Queries:
610
+
611
+ ```
612
+ # all technology services in TechnologyFacility X
613
+ TechnologyService: -> "DC:Alpha"
614
+
615
+ # facilities that host service Y
616
+ TechnologyFacility: <- "Orders:Cluster"
617
+ ```
618
+
619
+ #### Backbone and links between facilities
110
620
 
111
- **Example chain:** Component "kube-apiserver" → realizedThrough → Artifact "kubernetes/kubernetes" → maintainedBy → Actor "Platform Team"
621
+ The physical network between sites is `TechnologyEquipment`. A **link** (fibre route, carrier circuit) is one TechnologyEquipment with
622
+ `equipment/type: link` that is `locatedAt` **both** end facilities. A **backbone** is a TechnologyEquipment that is `composedOf`
623
+ its links (composition only points at TechnologyEquipment and must not form a cycle). The logical network is a
624
+ `TechnologyService` (and routers are `TechnologyNode`s) that is `realizedBy` the TechnologyEquipment it runs over, and is
625
+ `locatedAt` the facilities it reaches:
626
+
627
+ ```
628
+ TechnologyService "Network:Backbone" --realizedBy--> TechnologyEquipment "Equipment:Backbone"
629
+ --composedOf--> TechnologyEquipment "Equipment:Link:Frankfurt-Madrid" (link)
630
+ --locatedAt--> TechnologyFacility Frankfurt, TechnologyFacility Madrid
631
+ ```
632
+
633
+ ```
634
+ # all links between facilities
635
+ TechnologyEquipment: equipment/type == "link"
636
+
637
+ # links that end in TechnologyFacility X
638
+ TechnologyEquipment: equipment/type == "link" & -> "Facility:Madrid:DC"
639
+ ```
640
+
641
+ The TechnologyEquipment page lists what is realized by it (incoming `realizedBy`) and the backbones it belongs to (incoming
642
+ `composedOf`). A link has no endpoints of its own: it is placed at its facilities, so keep to two `locatedAt` targets
643
+ per link. See `examples/archsight/technology/facilities.yaml`.
112
644
 
113
645
  ## Relation Patterns
114
646
 
@@ -131,6 +663,8 @@ TechnologyArtifact
131
663
  Shows how services depend on each other:
132
664
 
133
665
  ```
666
+ ApplicationService
667
+ ↓ dependsOn (another ApplicationService)
134
668
  ApplicationService
135
669
  ↓ servedBy
136
670
  TechnologyService
@@ -138,7 +672,101 @@ TechnologyService
138
672
  TechnologySystemSoftware
139
673
  ```
140
674
 
141
- ### Requirements, Controls and Evidence
675
+ A service that uses another one says so with `dependsOn` on the service, the same verb components use between each
676
+ other. Do not add the other service's components to your own `realizedThrough`: the component would then belong to
677
+ two services, its owner is ambiguous and every rollup over the service's components counts it twice. Two services may
678
+ 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
679
+ "Payment Authorization" depends on "Refunds" (it asks to reverse a payment it cannot complete).
680
+
681
+ ### Where a Component Runs
682
+
683
+ Three relations say what something runs on; each answers a different question:
684
+
685
+ | Relation | Means | Example |
686
+ |----------|-------|---------|
687
+ | ApplicationComponent `servedBy technologyServices` | the platform service the component is deployed on | `Payments:API` runs in `Payments:Cluster` |
688
+ | ApplicationComponent `servedBy technologySystemSoftware` | the runtime it runs on | a Kubernetes distribution, a JVM |
689
+ | ApplicationService `servedBy technologyServices` | a platform service the service as a whole uses | a managed database, the clusters of its own components |
690
+
691
+ Deployment importers (Argo CD, Helm, Cluster API) know every cluster a deployable runs in and write the relation per
692
+ component. Keep the service-level relation to the clusters of the service's own components: a sidecar or agent that
693
+ the products deploy into their own clusters (a DNS or monitoring agent) is `servedBy` each of those clusters, and its
694
+ owning service is not, so it does not look like it runs everywhere. The TechnologyService page lists the components
695
+ deployed on it as incoming `servedBy` from ApplicationComponent. The `deployment/cluster` annotation is deprecated in
696
+ favour of the relation, which the graph, views and analyses see; it still loads, and `archsight lint` lists every use
697
+ as a deprecation without failing. See
698
+ `examples/archsight/technology/payments-platform.yaml`.
699
+
700
+ ### Concept and Implementation
701
+
702
+ One technology *concept* often has several *implementations*: a "regional cluster" is implemented by a hypervisor
703
+ platform on some sites and by bare metal on others. Model the concept as an element and let every implementation
704
+ **specialize** it (ArchiMate specialization). The specialization is written on the specific element and always points
705
+ to an element of the **same kind**:
706
+
707
+ | Kind | Verb | Target | ArchiMate |
708
+ |------|------|--------|-----------|
709
+ | `TechnologyNode` | `specializes` | `TechnologyNode` | specialization |
710
+ | `TechnologySystemSoftware` | `specializes` | `TechnologySystemSoftware` | specialization |
711
+ | `TechnologyService` | `specializes` | `TechnologyService` | specialization |
712
+ | `TechnologyNode` | `composedOf` | `TechnologyNode` | composition (a cluster made of hosts) |
713
+ | `TechnologySystemSoftware` | `composedOf` | `TechnologySystemSoftware` | composition (a platform bundles components) |
714
+
715
+ ```yaml
716
+ kind: TechnologyNode
717
+ metadata:
718
+ name: Tech:RegionalCluster # the concept
719
+ spec: {}
720
+ ---
721
+ kind: TechnologyNode
722
+ metadata:
723
+ name: Tech:RegionalCluster:Hypervisor # one implementation
724
+ spec:
725
+ specializes:
726
+ technologyNodes:
727
+ - Tech:RegionalCluster
728
+ composedOf:
729
+ technologyNodes:
730
+ - Tech:RegionalCluster:Host
731
+ ```
732
+
733
+ The page of the concept shows the implementations as incoming `specializes`, the implementation shows what it
734
+ `specializes`. A target of another kind is rejected when the resources are loaded, and `archsight lint` reports a
735
+ `specializes` or `composedOf` chain that leads back to where it started. Do not use `realizedBy` between elements of
736
+ one kind: realization goes from concrete to abstract across layers. See `examples/archsight/technology/platforms.yaml`.
737
+
738
+ ### Deployment
739
+
740
+ An artifact (`TechnologyArtifact`) describes what reaches a host; three relations connect it to the rest:
741
+
742
+ | Kind | Verb | Target | ArchiMate | Meaning |
743
+ |------|------|--------|-----------|---------|
744
+ | `TechnologyArtifact` | `aggregates` | `TechnologyArtifact` | aggregation | an image contains packages, a chart references container images |
745
+ | `TechnologyNode` | `assignedTo` | `TechnologyArtifact` | assignment | the artifact is deployed on the node |
746
+ | `TechnologySystemSoftware` | `assignedTo` | `TechnologyArtifact` | assignment | the artifact is executed by the system software |
747
+
748
+ `assignedTo` is written on the node or system software, which owns the deployment. A bootable OS image, VM template or
749
+ disk image is an artifact of `artifact/type: image` (`binary` and `archive` exist as well).
750
+
751
+ ```
752
+ ApplicationComponent
753
+ ↓ realizedThrough (what the component is built from)
754
+ TechnologyArtifact (image)
755
+ ↓ aggregates (what the image contains)
756
+ TechnologyArtifact (package)
757
+
758
+ TechnologyNode
759
+ ↓ assignedTo (where the artifact is deployed)
760
+ TechnologyArtifact
761
+ ```
762
+
763
+ The artifact's page shows `aggregates` as incoming "contained in" and `assignedTo` as incoming "deployed on"; the node's
764
+ page shows what it `assignedTo`. This answers "which hosts get package X" with a reverse lookup instead of a package list in
765
+ an annotation. `archsight lint` reports an `aggregates` chain that leads back to where it started. Example: a host role
766
+ boots an image that contains two packages, and configuration management installs a third on the same hosts, see
767
+ `examples/archsight/technology/deployment.yaml`. Do not use `servedBy` between artifacts for contents: it reads as
768
+ "is served by", not "contains".
769
+
142
770
 
143
771
  A requirement is the point where the process side and the application side of compliance meet:
144
772
 
@@ -189,6 +817,100 @@ spec:
189
817
  evidencedBy: { complianceEvidences: [Evidence:DeploymentAuditLog] }
190
818
  ```
191
819
 
820
+ ### Security and Risk
821
+
822
+ Security and risk are modelled with the elements above, following the risk and security overlay of the Open Group
823
+ white paper [Modeling Enterprise Risk Management and Security with the ArchiMate Language](#reference). There is no
824
+ separate security layer: a concept is an ordinary element that carries a **type** (a specialization, the paper's
825
+ "stereotype") plus profile annotations. The type is a filterable annotation, so views, queries and lists can group by it.
826
+
827
+ | Security concept | Kind | Type annotation | Notes |
828
+ |------------------|------|-----------------|-------|
829
+ | Threat (circumstance) | `MotivationDriver` | `driver/type: threat` | also opportunity, regulation, market |
830
+ | Threat agent | `BusinessActor`, `ApplicationComponent`, `TechnologyNode` | none | the `causedBy` of an event |
831
+ | Threat event | `BusinessEvent`, `ApplicationEvent`, `TechnologyEvent` | `event/type: threat-event` or `attack` | `attack` = intentional |
832
+ | Loss event, incident | the three event kinds | `event/type: loss-event` or `incident` | the layer says where it happens |
833
+ | Risk | `MotivationAssessment` | `assessment/type: risk` | initial and residual profile, `risk/treatment` |
834
+ | Vulnerability | `MotivationAssessment` | `assessment/type: vulnerability` | `assesses` the assets it is found on |
835
+ | Control objective | `MotivationGoal` | `goal/type: control-objective` | the risk is `mitigatedBy` it |
836
+ | Control measure | `MotivationRequirement` | `requirement/type: control-measure` | a goal `realizes` it; the risk can be `mitigatedBy` it |
837
+ | Control implementation | `BusinessControl`, applications, nodes, processes | none | `satisfies` / `realizes` the measure |
838
+ | Proof of the control | `ComplianceEvidence` | `evidence/type` | `evidence/status: not-applicable` where the requirement does not apply |
839
+ | Asset at risk | any application, technology, data or process kind | `asset/value`, `asset/confidentiality`, `asset/integrity`, `asset/availability` | the protection need (BSI Schutzbedarf) |
840
+ | Policy (design level) | `MotivationPrinciple` | `principle/type: security-policy` or `risk-policy` | status, validity, framework mapping |
841
+ | Operational policy, regulation | `MotivationConstraint` | none | the paper has no element for operational policy |
842
+ | Risk domain | none; annotation `risk/domain` | `risk/domain`, `risk/category` | group by it with a query or a `View` |
843
+
844
+ The chain, as in the paper's Coldhard Steel example:
845
+
846
+ ```
847
+ MotivationDriver (threat) ──influences──→ MotivationAssessment (risk) ──mitigatedBy──→ MotivationGoal (control objective)
848
+ │ triggers │ assesses │ realizes
849
+ ↓ ↓ ↓
850
+ BusinessEvent (loss event) ←──influences── MotivationAssessment (vulnerability) MotivationRequirement (control measure)
851
+ ↑ triggers ↑ satisfies / realizes
852
+ TechnologyEvent / ApplicationEvent (threat event, attack) BusinessControl / asset ──evidencedBy──→ ComplianceEvidence
853
+ ```
854
+
855
+ ```yaml
856
+ kind: MotivationDriver
857
+ metadata: { name: Threat:Intrusion, annotations: { driver/type: threat } }
858
+ spec:
859
+ influences: { motivationAssessments: [Risk:Intrusion] }
860
+ triggers: { businessEvents: [Loss:DataLeak] }
861
+ ---
862
+ kind: MotivationAssessment
863
+ metadata:
864
+ name: Risk:Intrusion
865
+ annotations:
866
+ assessment/type: risk
867
+ risk/initial-likelihood: high
868
+ risk/residual-likelihood: low
869
+ risk/treatment: mitigate
870
+ risk/domain: customer-data
871
+ spec:
872
+ ownedBy: { businessRoles: [Role:RiskOwner] }
873
+ assesses: { technologyNodes: [Node:Web1] }
874
+ mitigatedBy: { goals: [Objective:ReduceExposure], businessControls: [Control:FirewallReview] }
875
+ ---
876
+ kind: MotivationGoal
877
+ metadata: { name: Objective:ReduceExposure, annotations: { goal/type: control-objective } }
878
+ spec:
879
+ realizes: { motivationRequirements: [Measure:Firewall] }
880
+ ---
881
+ kind: MotivationRequirement
882
+ metadata: { name: Measure:Firewall, annotations: { requirement/type: control-measure } }
883
+ spec: {}
884
+ ---
885
+ kind: BusinessControl
886
+ metadata: { name: Control:FirewallReview }
887
+ spec:
888
+ ownedBy: { businessRoles: [Role:ControlOwner] }
889
+ satisfies: { motivationRequirements: [Measure:Firewall] }
890
+ ```
891
+
892
+ How to model it:
893
+
894
+ - **Events and their types.** A threat event `triggers` a loss event; the three event kinds (business, application,
895
+ technology) say on which level it happens and a technology event may trigger an application or business event. Use
896
+ `event/type` to tell threat events, attacks, loss events, incidents, opportunity events, audits, scans and changes apart.
897
+ - **Vulnerability scan.** One `MotivationAssessment` of type `vulnerability` per finding, `assesses` every node it was
898
+ found on, `influences` the loss events and risks it makes possible. Business impact follows from the model: the node
899
+ serves services, services serve processes.
900
+ - **Grouping (risk domains).** ArchiMate has no domain element; set `risk/domain` (and `risk/category`: hazard,
901
+ financial, operational, strategic, compliance, security) on events, assessments, drivers, requirements, controls and
902
+ assets, and query or build a `View` per domain to see its threats, risks, measures and assets together.
903
+ - **Policies.** The text of a policy is a `Page`; the structured statement (owner, validity, status, framework) is a
904
+ `MotivationPrinciple` that links to the page with `[[Page]]`.
905
+ - **Initial and residual risk.** Record both on the assessment (`risk/initial-*`, `risk/residual-*`) and the decision
906
+ in `risk/treatment`.
907
+
908
+ <a id="reference"></a>
909
+ **Reference:** Band, Engelsman, Feltus, González Paredes, Hietala, Jonkers, Massart,
910
+ [Modeling Enterprise Risk Management and Security with the ArchiMate Language](https://pure.unamur.be/ws/files/12366722/Modeling_Enterprise_Risk_Management_and_Secutity_with_the_ArchiMate_Language.pdf),
911
+ The Open Group white paper (ArchiMate 2.1). For the NIST OSCAL vocabulary used for names of assessment and evidence
912
+ fields see [OSCAL](https://pages.nist.gov/OSCAL/learn/concepts/layer/).
913
+
192
914
  ### Compliance Chain
193
915
 
194
916
  Shows how requirements are satisfied:
@@ -254,6 +976,32 @@ Use annotations to capture metadata:
254
976
  - `architecture/diagram` - A hand-drawn [`.asd` diagram](diagram.md#the-architecturediagram-annotation), shown next to the generated dependency graph
255
977
  (`.asd` code blocks also render inside `architecture/description` markdown). Nodes can link to resources with `resource "Name"`.
256
978
 
979
+ ### Lifecycle
980
+
981
+ `lifecycle/status` marks any resource with `architecture/*` annotations (products, components, services, artifacts, ...) as
982
+ `planned` (not yet in use), `active`, `deprecated` (do not start new uses), `sunset` (being phased out) or `end-of-life`
983
+ (no longer operated or supported). A resource without the annotation is `active`: the annotation's default, so
984
+ `lifecycle/status == "active"` finds it and the sidebar filter counts it (the editor does not write the default into the
985
+ file). The status shows as a badge (blue for `planned`, yellow for `deprecated`, red for `sunset` and `end-of-life`) and
986
+ is a sidebar filter and query term (`lifecycle/status == "deprecated"`).
987
+
988
+ | Annotation | Purpose |
989
+ |------------|---------|
990
+ | `lifecycle/status` | The state above |
991
+ | `lifecycle/activeAt`, `lifecycle/deprecatedAt`, `lifecycle/sunsetAt`, `lifecycle/endOfLifeAt` | When it happened or will happen (ISO 8601 date or time, checked by `archsight lint`) |
992
+ | `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 |
993
+ | `lifecycle/reason` | Why, in markdown |
994
+
995
+ ```yaml
996
+ kind: ApplicationService
997
+ metadata:
998
+ name: LegacyExport
999
+ annotations:
1000
+ lifecycle/status: sunset
1001
+ lifecycle/sunsetAt: 2027-03-31
1002
+ lifecycle/replacedBy: ApplicationService/ExportV2
1003
+ ```
1004
+
257
1005
  ## Common Patterns
258
1006
 
259
1007
  ### Microservice