@ybotok/loam 0.2.0-alpha.5 → 0.2.0-alpha.6

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 (273) hide show
  1. package/CHANGELOG.md +901 -0
  2. package/MIGRATING-from-OpenSpec.md +7 -4
  3. package/QUICKSTART.md +8 -3
  4. package/README.md +13 -7
  5. package/ROADMAP.md +264 -11
  6. package/SCHEMA.md +439 -38
  7. package/WORKFLOW.md +23 -10
  8. package/dist/commands/adopt/render.js +47 -8
  9. package/dist/commands/adopt/render.js.map +1 -1
  10. package/dist/commands/archive/plan/landscape.js +45 -1
  11. package/dist/commands/archive/plan/landscape.js.map +1 -1
  12. package/dist/commands/archive/plan/model/extending.js +85 -0
  13. package/dist/commands/archive/plan/model/extending.js.map +1 -0
  14. package/dist/commands/archive/run.js +5 -2
  15. package/dist/commands/archive/run.js.map +1 -1
  16. package/dist/commands/context/print.js +11 -1
  17. package/dist/commands/context/print.js.map +1 -1
  18. package/dist/commands/doctor.js +46 -0
  19. package/dist/commands/doctor.js.map +1 -1
  20. package/dist/commands/explore.js +12 -2
  21. package/dist/commands/explore.js.map +1 -1
  22. package/dist/commands/list/views.js +5 -1
  23. package/dist/commands/list/views.js.map +1 -1
  24. package/dist/commands/seed/plan.js +97 -3
  25. package/dist/commands/seed/plan.js.map +1 -1
  26. package/dist/commands/seed/seed.js +7 -2
  27. package/dist/commands/seed/seed.js.map +1 -1
  28. package/dist/commands/show/feature.js +2 -1
  29. package/dist/commands/show/feature.js.map +1 -1
  30. package/dist/commands/show/marks.js +3 -5
  31. package/dist/commands/show/marks.js.map +1 -1
  32. package/dist/commands/show/service.js +39 -18
  33. package/dist/commands/show/service.js.map +1 -1
  34. package/dist/commands/subsystem/sync.js +128 -74
  35. package/dist/commands/subsystem/sync.js.map +1 -1
  36. package/dist/commands/subsystem/txn/exclude.js +132 -0
  37. package/dist/commands/subsystem/txn/exclude.js.map +1 -0
  38. package/dist/commands/subsystem/txn/report.js +124 -0
  39. package/dist/commands/subsystem/txn/report.js.map +1 -0
  40. package/dist/commands/subsystem/txn/txn.js +10 -3
  41. package/dist/commands/subsystem/txn/txn.js.map +1 -1
  42. package/dist/commands/subsystem/txn/views.js +113 -16
  43. package/dist/commands/subsystem/txn/views.js.map +1 -1
  44. package/dist/commands/validate/arch-coverage.js +16 -9
  45. package/dist/commands/validate/arch-coverage.js.map +1 -1
  46. package/dist/commands/validate/checks/fleet-shape.js +30 -77
  47. package/dist/commands/validate/checks/fleet-shape.js.map +1 -1
  48. package/dist/commands/validate/checks/vocabulary.js +4 -19
  49. package/dist/commands/validate/checks/vocabulary.js.map +1 -1
  50. package/dist/commands/validate/feature.js +1 -1
  51. package/dist/commands/validate/feature.js.map +1 -1
  52. package/dist/commands/validate/fleet/census.js +11 -10
  53. package/dist/commands/validate/fleet/census.js.map +1 -1
  54. package/dist/commands/validate/fleet/landscape.js +127 -119
  55. package/dist/commands/validate/fleet/landscape.js.map +1 -1
  56. package/dist/commands/validate/fleet/load.js +66 -0
  57. package/dist/commands/validate/fleet/load.js.map +1 -1
  58. package/dist/commands/validate/fleet/map/attest.js +103 -0
  59. package/dist/commands/validate/fleet/map/attest.js.map +1 -0
  60. package/dist/commands/validate/fleet/map/bindings.js +96 -0
  61. package/dist/commands/validate/fleet/map/bindings.js.map +1 -0
  62. package/dist/commands/validate/fleet/map/consumers.js +298 -0
  63. package/dist/commands/validate/fleet/map/consumers.js.map +1 -0
  64. package/dist/commands/validate/fleet/map/isolation.js +116 -0
  65. package/dist/commands/validate/fleet/map/isolation.js.map +1 -0
  66. package/dist/commands/validate/fleet/map/usecases.js +56 -0
  67. package/dist/commands/validate/fleet/map/usecases.js.map +1 -0
  68. package/dist/commands/validate/fleet/usecases/steps.js +49 -17
  69. package/dist/commands/validate/fleet/usecases/steps.js.map +1 -1
  70. package/dist/commands/validate/fleet/views/fleet-project.js +217 -0
  71. package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -0
  72. package/dist/commands/validate/fleet/views/ids.js +13 -9
  73. package/dist/commands/validate/fleet/views/ids.js.map +1 -1
  74. package/dist/commands/validate/fleet/views/projects.js +258 -70
  75. package/dist/commands/validate/fleet/views/projects.js.map +1 -1
  76. package/dist/commands/validate/fleet/views/root-documents.js +97 -0
  77. package/dist/commands/validate/fleet/views/root-documents.js.map +1 -0
  78. package/dist/commands/validate/fleet/views/stale.js +2 -2
  79. package/dist/commands/validate/fleet/views/stale.js.map +1 -1
  80. package/dist/commands/validate/service/model/diverged.js +226 -0
  81. package/dist/commands/validate/service/model/diverged.js.map +1 -0
  82. package/dist/commands/validate/service/model/grade.js +163 -0
  83. package/dist/commands/validate/service/model/grade.js.map +1 -0
  84. package/dist/commands/validate/service/service.js +110 -34
  85. package/dist/commands/validate/service/service.js.map +1 -1
  86. package/dist/commands/validate/service/specs.js +39 -5
  87. package/dist/commands/validate/service/specs.js.map +1 -1
  88. package/dist/commands/validate/service/spine.js +41 -3
  89. package/dist/commands/validate/service/spine.js.map +1 -1
  90. package/dist/commands/validate/service/usecases/tags.js +113 -0
  91. package/dist/commands/validate/service/usecases/tags.js.map +1 -0
  92. package/dist/commands/validate/service/usecases/usecases.js +209 -0
  93. package/dist/commands/validate/service/usecases/usecases.js.map +1 -0
  94. package/dist/commands/validate/validate.js +10 -24
  95. package/dist/commands/validate/validate.js.map +1 -1
  96. package/dist/core/agent/agents-md/artifacts.js +1 -0
  97. package/dist/core/agent/agents-md/artifacts.js.map +1 -1
  98. package/dist/core/agent/agents-md/command-map.js +18 -4
  99. package/dist/core/agent/agents-md/command-map.js.map +1 -1
  100. package/dist/core/agent/agents-md/cycle.js +24 -9
  101. package/dist/core/agent/agents-md/cycle.js.map +1 -1
  102. package/dist/core/agent/agents-md/map/lenses/context.js +4 -3
  103. package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -1
  104. package/dist/core/agent/agents-md/map/subsystem.js +51 -11
  105. package/dist/core/agent/agents-md/map/subsystem.js.map +1 -1
  106. package/dist/core/agent/agents-md/map/usecases.js +45 -3
  107. package/dist/core/agent/agents-md/map/usecases.js.map +1 -1
  108. package/dist/core/agent/agents-md.js +14 -4
  109. package/dist/core/agent/agents-md.js.map +1 -1
  110. package/dist/core/agent/support/report.js +39 -5
  111. package/dist/core/agent/support/report.js.map +1 -1
  112. package/dist/core/agent/workflows/adopt.js +123 -14
  113. package/dist/core/agent/workflows/adopt.js.map +1 -1
  114. package/dist/core/agent/workflows/check.js +35 -20
  115. package/dist/core/agent/workflows/check.js.map +1 -1
  116. package/dist/core/agent/workflows/closing.js +3 -1
  117. package/dist/core/agent/workflows/closing.js.map +1 -1
  118. package/dist/core/brief/brief.js +63 -11
  119. package/dist/core/brief/brief.js.map +1 -1
  120. package/dist/core/brief/checks.js +133 -7
  121. package/dist/core/brief/checks.js.map +1 -1
  122. package/dist/core/brief/landscape.js +212 -129
  123. package/dist/core/brief/landscape.js.map +1 -1
  124. package/dist/core/brief/map/extend.js +81 -0
  125. package/dist/core/brief/map/extend.js.map +1 -0
  126. package/dist/core/brief/map/owed.js +284 -0
  127. package/dist/core/brief/map/owed.js.map +1 -0
  128. package/dist/core/brief/targets.js +30 -29
  129. package/dist/core/brief/targets.js.map +1 -1
  130. package/dist/core/brief/unchecked.js +12 -2
  131. package/dist/core/brief/unchecked.js.map +1 -1
  132. package/dist/core/c4/likec4.js +23 -1
  133. package/dist/core/c4/likec4.js.map +1 -1
  134. package/dist/core/c4/parsed/deployment.js +5 -3
  135. package/dist/core/c4/parsed/deployment.js.map +1 -1
  136. package/dist/core/c4/parsed/view-ids.js +39 -1
  137. package/dist/core/c4/parsed/view-ids.js.map +1 -1
  138. package/dist/core/c4/prefetch/fleet.js +142 -0
  139. package/dist/core/c4/prefetch/fleet.js.map +1 -0
  140. package/dist/core/c4/project/architecture.js +52 -4
  141. package/dist/core/c4/project/architecture.js.map +1 -1
  142. package/dist/core/c4/project/batch.js +140 -0
  143. package/dist/core/c4/project/batch.js.map +1 -0
  144. package/dist/core/c4/project/documents.js +9 -4
  145. package/dist/core/c4/project/documents.js.map +1 -1
  146. package/dist/core/c4/project/load.js +77 -38
  147. package/dist/core/c4/project/load.js.map +1 -1
  148. package/dist/core/c4/project/staged.js +46 -12
  149. package/dist/core/c4/project/staged.js.map +1 -1
  150. package/dist/core/c4/resolve/attested.js +0 -0
  151. package/dist/core/c4/resolve/attested.js.map +1 -0
  152. package/dist/core/c4/resolve/service.js +8 -17
  153. package/dist/core/c4/resolve/service.js.map +1 -1
  154. package/dist/core/c4/resolve/steps.js +18 -0
  155. package/dist/core/c4/resolve/steps.js.map +1 -1
  156. package/dist/core/c4/root-project/exclude.js +352 -0
  157. package/dist/core/c4/root-project/exclude.js.map +1 -0
  158. package/dist/core/c4/service-model/documents.js +47 -0
  159. package/dist/core/c4/service-model/documents.js.map +1 -0
  160. package/dist/core/c4/service-model/fleet/extending.js +82 -0
  161. package/dist/core/c4/service-model/fleet/extending.js.map +1 -0
  162. package/dist/core/c4/service-model/load.js +165 -0
  163. package/dist/core/c4/service-model/load.js.map +1 -0
  164. package/dist/core/c4/service-model/renderer.js +128 -0
  165. package/dist/core/c4/service-model/renderer.js.map +1 -0
  166. package/dist/core/c4/service-model/shape.js +126 -0
  167. package/dist/core/c4/service-model/shape.js.map +1 -0
  168. package/dist/core/c4/service-model/slice.js +188 -0
  169. package/dist/core/c4/service-model/slice.js.map +1 -0
  170. package/dist/core/c4/source-scan.js +26 -0
  171. package/dist/core/c4/source-scan.js.map +1 -1
  172. package/dist/core/c4/splice/authored-source.js +60 -13
  173. package/dist/core/c4/splice/authored-source.js.map +1 -1
  174. package/dist/core/c4/splice/contract.js.map +1 -1
  175. package/dist/core/c4/splice/identity/declared.js +87 -0
  176. package/dist/core/c4/splice/identity/declared.js.map +1 -0
  177. package/dist/core/c4/splice/identity/edges.js +17 -0
  178. package/dist/core/c4/splice/identity/edges.js.map +1 -1
  179. package/dist/core/c4/splice/identity/existing.js +80 -0
  180. package/dist/core/c4/splice/identity/existing.js.map +1 -0
  181. package/dist/core/c4/splice/identity/interior.js +80 -0
  182. package/dist/core/c4/splice/identity/interior.js.map +1 -0
  183. package/dist/core/c4/splice/identity/owner.js +50 -0
  184. package/dist/core/c4/splice/identity/owner.js.map +1 -0
  185. package/dist/core/c4/splice/landscape-merge.js +154 -100
  186. package/dist/core/c4/splice/landscape-merge.js.map +1 -1
  187. package/dist/core/c4/splice/model/merge.js +140 -0
  188. package/dist/core/c4/splice/model/merge.js.map +1 -0
  189. package/dist/core/c4/splice/placement.js +14 -4
  190. package/dist/core/c4/splice/placement.js.map +1 -1
  191. package/dist/core/c4/workspace.js +2 -1
  192. package/dist/core/c4/workspace.js.map +1 -1
  193. package/dist/core/coherence/coherence.js +7 -0
  194. package/dist/core/coherence/coherence.js.map +1 -1
  195. package/dist/core/delta/delta.js +9 -0
  196. package/dist/core/delta/delta.js.map +1 -1
  197. package/dist/core/deployment/delta.js +4 -0
  198. package/dist/core/deployment/delta.js.map +1 -1
  199. package/dist/core/diff/base-state.js +21 -5
  200. package/dist/core/diff/base-state.js.map +1 -1
  201. package/dist/core/diff/victims.js +10 -1
  202. package/dist/core/diff/victims.js.map +1 -1
  203. package/dist/core/docs.js +29 -24
  204. package/dist/core/docs.js.map +1 -1
  205. package/dist/core/doctor/config.js +7 -3
  206. package/dist/core/doctor/config.js.map +1 -1
  207. package/dist/core/doctor/doctor.js +36 -8
  208. package/dist/core/doctor/doctor.js.map +1 -1
  209. package/dist/core/doctor/report.js.map +1 -1
  210. package/dist/core/doctor/reports/scan.js +242 -0
  211. package/dist/core/doctor/reports/scan.js.map +1 -0
  212. package/dist/core/explain/refusals.js +1 -1
  213. package/dist/core/explain/refusals.js.map +1 -1
  214. package/dist/core/explore/explore.js +44 -9
  215. package/dist/core/explore/explore.js.map +1 -1
  216. package/dist/core/fleet-context.js +47 -0
  217. package/dist/core/fleet-context.js.map +1 -1
  218. package/dist/core/gate/partners.js +5 -9
  219. package/dist/core/gate/partners.js.map +1 -1
  220. package/dist/core/kernel/ids/fqn/ancestors.js +65 -0
  221. package/dist/core/kernel/ids/fqn/ancestors.js.map +1 -0
  222. package/dist/core/pack/living.js +47 -13
  223. package/dist/core/pack/living.js.map +1 -1
  224. package/dist/core/pack/pack.js +9 -6
  225. package/dist/core/pack/pack.js.map +1 -1
  226. package/dist/core/projection/arch-slice.js +2 -2
  227. package/dist/core/projection/arch-slice.js.map +1 -1
  228. package/dist/core/repo/paths.js +11 -9
  229. package/dist/core/repo/paths.js.map +1 -1
  230. package/dist/core/repo/tree/render/projects.js +93 -35
  231. package/dist/core/repo/tree/render/projects.js.map +1 -1
  232. package/dist/core/repo/tree/render/stale.js +2 -3
  233. package/dist/core/repo/tree/render/stale.js.map +1 -1
  234. package/dist/core/repo/tree/render/views.js +51 -3
  235. package/dist/core/repo/tree/render/views.js.map +1 -1
  236. package/dist/core/repo/tree/walk.js +45 -2
  237. package/dist/core/repo/tree/walk.js.map +1 -1
  238. package/dist/core/scaffold/landscape.js +219 -9
  239. package/dist/core/scaffold/landscape.js.map +1 -1
  240. package/dist/core/staging/writes.js.map +1 -1
  241. package/dist/core/usecases/delta/claims.js +1 -0
  242. package/dist/core/usecases/delta/claims.js.map +1 -1
  243. package/dist/core/usecases/delta/overlay.js +4 -0
  244. package/dist/core/usecases/delta/overlay.js.map +1 -1
  245. package/dist/core/usecases/fleet.js +18 -6
  246. package/dist/core/usecases/fleet.js.map +1 -1
  247. package/dist/core/usecases/operations.js +7 -0
  248. package/dist/core/usecases/operations.js.map +1 -1
  249. package/dist/core/usecases/service/exclude.js +119 -0
  250. package/dist/core/usecases/service/exclude.js.map +1 -0
  251. package/dist/core/usecases/service/flows.js +161 -0
  252. package/dist/core/usecases/service/flows.js.map +1 -0
  253. package/dist/core/vocabulary/maturity.js +10 -0
  254. package/dist/core/vocabulary/maturity.js.map +1 -1
  255. package/examples/README.md +24 -6
  256. package/examples/docs/architecture/landscape.likec4 +41 -0
  257. package/examples/docs/architecture/usecases/order-notification.likec4 +5 -2
  258. package/examples/docs/likec4.config.json +0 -1
  259. package/examples/docs/services/checkout-web/model.likec4 +39 -56
  260. package/examples/docs/services/order-service/arch.spec.md +13 -6
  261. package/examples/docs/services/order-service/model.likec4 +53 -67
  262. package/examples/docs/services/payment-service/arch.spec.md +7 -4
  263. package/examples/docs/services/payment-service/model.likec4 +32 -35
  264. package/examples/docs/services/platform/identity-service/arch.spec.md +7 -4
  265. package/examples/docs/services/platform/identity-service/model.likec4 +29 -33
  266. package/examples/docs/services/platform/notification-service/health.yaml +8 -3
  267. package/examples/docs/services/platform/notification-service/model.likec4 +39 -59
  268. package/package.json +1 -1
  269. package/examples/docs/services/checkout-web/likec4.config.json +0 -4
  270. package/examples/docs/services/order-service/likec4.config.json +0 -4
  271. package/examples/docs/services/payment-service/likec4.config.json +0 -4
  272. package/examples/docs/services/platform/identity-service/likec4.config.json +0 -4
  273. package/examples/docs/services/platform/notification-service/likec4.config.json +0 -4
@@ -1,30 +1,22 @@
1
- // The identity-service C4 model: the containers behind the token API and the
2
- // two stores they reach.
1
+ // identity-service's own C4 — what is INSIDE the element the fleet map binds to
2
+ // services/platform/identity-service/: the containers behind the token API and
3
+ // the two stores they reach.
3
4
  //
4
- // The `specification` block is repeated in every .likec4 file on purpose. loam
5
- // parses each document ALONE — it never stitches this file to
6
- // architecture/landscape.likec4 before reading it — so a kind declared only in
7
- // the landscape would resolve in the LikeC4 workspace and fail here, and the
8
- // failure surfaces as `c4.invalid` on a file whose text looks perfect.
9
- specification {
10
- element softwareSystem
11
- element container
12
- element database
13
- }
14
-
5
+ // An EXTENDING model. There is no `specification` block here and there must not
6
+ // be one: the kinds come from architecture/landscape.likec4, which is read as
7
+ // part of the SAME LikeC4 project (the root `likec4.config.json` excludes
8
+ // `**/node_modules/**` and `features/**`, and nothing under `services/`). A
9
+ // second declaration of a kind the map already declares is a duplicate error
10
+ // blamed on both files. `extend` takes the fully-qualified id the map minted —
11
+ // `marketplace.identityService` — because the element is nested in the
12
+ // `marketplace` group; `extend identityService` resolves to nothing.
13
+ //
14
+ // Where the service sits in the SUBSYSTEM tree changes none of this: the model
15
+ // is found by walking `services/`, and `services/platform/` is a grouping
16
+ // directory, never part of any id. SCHEMA.md, "Two shapes of a service model",
17
+ // has the standalone shape and the recipe for migrating a model to this one.
15
18
  model {
16
- identityService = softwareSystem 'identity-service' {
17
- description 'Issues the access tokens the rest of the fleet presents, and answers whether one is still good'
18
- // The binding — not the title — is what ties this element to
19
- // services/identity-service/. With a title alone, renaming the box to
20
- // 'Identity' would silently stop every join that reads this file (health
21
- // dependencies, `Covers:` entries, the landscape spine) while `loam
22
- // validate` stayed green, because a title that fails to match is only a
23
- // guess at a binding and is graded as one.
24
- metadata {
25
- service 'identity-service'
26
- }
27
-
19
+ extend marketplace.identityService {
28
20
  api = container 'api' {
29
21
  description 'HTTP surface: POST /tokens, POST /tokens/introspect, GET /tokens/{token}/valid'
30
22
  technology 'Go'
@@ -51,7 +43,9 @@ model {
51
43
  // architecture/landscape.likec4 as a peer is `landscape.datastore-private`:
52
44
  // drawn at fleet level a store reads as a system in its own right, available
53
45
  // for somebody else's service to depend on, which is the one coupling that is
54
- // hardest to undo once a second team believes the picture.
46
+ // hardest to undo once a second team believes the picture. The extending
47
+ // shape makes that the default rather than a discipline — internals are
48
+ // written where they belong because there is nowhere else to write them.
55
49
  introspectionCache = container 'introspection-cache' {
56
50
  description 'Short-TTL introspection verdicts, keyed by token id'
57
51
  technology 'Redis'
@@ -61,11 +55,12 @@ model {
61
55
  // These three edges are the WHOLE runtime graph of this service:
62
56
  // identity-service is the fleet's root of trust and calls nothing outside
63
57
  // its own boundary, which is why health.yaml carries no `dependencies:`
64
- // key. They still have to be drawn — with four nested elements and no edge
65
- // joining any of them this model is `c4.no-relationships`, on the grounds
66
- // that parts which reach nothing are almost never the truth. (The check is
67
- // evidence-gated: one lone container proves nothing and stays silent, which
68
- // is why the warning is about a model this shape and not about any model.)
58
+ // key, and why this model draws no cross-boundary edge at all. They still
59
+ // have to be drawn — with four nested elements and no edge joining any of
60
+ // them this model is `c4.no-relationships`, on the grounds that parts which
61
+ // reach nothing are almost never the truth. (The check is evidence-gated:
62
+ // one lone container proves nothing and stays silent, which is why the
63
+ // warning is about a model this shape and not about any model.)
69
64
  tokens -> keyStore 'Signs with the active key; rotation promotes the next; introspection reads keys and revocations back'
70
65
  tokens -> introspectionCache 'Caches introspection verdicts, invalidates on revocation'
71
66
  }
@@ -74,9 +69,10 @@ model {
74
69
  // Views belong to LikeC4's renderer; no loam check reads anything below. One
75
70
  // view is enough here because the whole model fits inside one boundary — the
76
71
  // landscape splits its views only because a fleet-wide `include *` is the page
77
- // nobody can read.
72
+ // nobody can read. View ids are flat across the whole project now that the map
73
+ // and every model share one, so this one is spelled to be unique.
78
74
  views {
79
- view identity_service of identityService {
75
+ view identity_service of marketplace.identityService {
80
76
  title 'identity-service — containers'
81
77
  include *
82
78
  }
@@ -25,9 +25,14 @@ checks:
25
25
  liveness: GET /internal/health/liveness
26
26
  readiness: GET /internal/health/readiness # consumer group joined + both stores reachable
27
27
  dependencies:
28
- # Resolved against services/notification-service/model.likec4 and never the
29
- # landscape (`health.dependency-unmodelled` when nothing there answers to the
30
- # name). The delivery log and the contact store are absent on purpose: both
28
+ # Resolved against services/platform/notification-service/model.likec4 — this
29
+ # service's own model, never the fleet map read on its own
30
+ # (`health.dependency-unmodelled` when nothing there answers to the name).
31
+ # That model EXTENDS the map, so what answers is its own slice: the elements
32
+ # it adds, plus the partners it points at and their ancestors. `kafka` below
33
+ # resolves through the second half — the edges name `kafka.orderEvents` and
34
+ # the broker that owns the topic comes with it.
35
+ # The delivery log and the contact store are absent on purpose: both
31
36
  # are nested inside the service element and share its lifecycle, so they are
32
37
  # blast radius rather than dependency — identity-service's health.yaml states
33
38
  # the same rule for its two stores.
@@ -1,35 +1,21 @@
1
- // Per-service C4. Written by an agent from the `loam adopt` brief, then curated.
1
+ // notification-service's own C4 — what is INSIDE the element the fleet map binds
2
+ // to services/platform/notification-service/. Written by an agent from the
3
+ // `loam adopt` brief, then curated.
2
4
  //
3
- // Every .likec4 file is parsed ALONE, so the kinds this document uses have to be
4
- // declared in this document: a `specification` block here is not a duplicate of
5
- // the landscape's, it is what makes this file readable without it.
6
- specification {
7
- element softwareSystem
8
- element container
9
- element database
10
- // Declared because the consumption edges below point at CHANNELS rather than
11
- // at the broker. Three edges into one `kafka` box would say only "talks to
12
- // kafka"; three edges into three topics say which contracts this service is
13
- // standing on, and they line up one-for-one with the channels in
14
- // asyncapi.yaml.
15
- element topic {
16
- style {
17
- shape queue
18
- }
19
- }
20
- }
21
-
5
+ // An EXTENDING model: no `specification` block, no partner copies. The topics
6
+ // this service consumes — `kafka.orderEvents`, `kafka.paymentEvents`,
7
+ // `kafka.crmEvents` — are the MAP's, declared there once with the `topic` kind
8
+ // that carries `#external` and `#platform`; this file points at them. So is
9
+ // `notificationProvider`, the third-party gateway: a system this service reaches
10
+ // belongs in architecture/landscape.likec4, and declaring a copy of it here
11
+ // would be `c4.element-unowned`. `extend` takes the fully-qualified id because
12
+ // the element is nested in the `marketplace` group.
13
+ //
14
+ // SCHEMA.md, "Two shapes of a service model", has the standalone shape — a model
15
+ // that declares its own `specification` and is therefore parsed alone — and the
16
+ // ordered recipe for migrating one to this shape.
22
17
  model {
23
- notificationService = softwareSystem 'notification-service' {
24
- description 'Turns fleet events into customer email and SMS'
25
- // The binding, not the title, is what ties this element to
26
- // services/notification-service/. With only a title, renaming the box in a
27
- // diagram silently detaches every join that runs through it — health.yaml's
28
- // dependencies, `Covers:` entries, the landscape's service checks.
29
- metadata {
30
- service 'notification-service'
31
- }
32
-
18
+ extend marketplace.notificationService {
33
19
  consumer = container 'consumer' {
34
20
  description 'Kafka consumer group; one handler per message name'
35
21
  technology 'Go'
@@ -67,30 +53,12 @@ model {
67
53
  sender -> deliveryLog 'Records delivered / failed'
68
54
  }
69
55
 
70
- // Everything the service touches belongs in its own model, cross-boundary
71
- // dependencies included — the landscape carries only the boundary crossing.
72
- // health.yaml names `kafka` as a critical dependency and that id has to resolve
73
- // HERE, by element id, `metadata { service }` binding or title
74
- // (`health.dependency-unmodelled` otherwise); and a model with elements and no
75
- // edges beside a health.yaml that declares dependencies is `c4.no-relationships`
76
- // — a service that reaches nothing is almost never true.
77
- kafka = softwareSystem 'kafka' {
78
- description 'Event backbone (platform)'
79
- orderEvents = topic 'order.events'
80
- paymentEvents = topic 'payment.events'
81
- crmEvents = topic 'crm.events'
82
- }
83
-
84
- // The second thing this service reaches across its own boundary, and the one
85
- // the runbook spends an incident section on: while the provider is down or
86
- // throttling, nothing is delivered and there is no fallback path. It belongs
87
- // here for the same reason payment-service's model draws `stripe` — a model
88
- // that stopped at the broker would show a worker whose only failure mode is
89
- // lag, which is the half of the picture the on-call graphs already give you.
90
- provider = softwareSystem 'notification-provider' {
91
- description 'Third-party email and SMS gateway — quota-limited, and outside this fleet'
92
- }
93
-
56
+ // The three channels this service takes messages off, pointing at the map's
57
+ // topics. health.yaml names `kafka` as a critical dependency and that id has to
58
+ // resolve through this model (`health.dependency-unmodelled` otherwise): it
59
+ // does, because a partner brings its ANCESTORS with it — the edges name the
60
+ // topics and the broker answers for them.
61
+ //
94
62
  // No `metadata { consumes }` on these edges, and adding it would change
95
63
  // nothing: loam reads the event spine off `architecture/landscape.likec4`
96
64
  // alone, never off a service model. What resolves a consumed name against
@@ -104,15 +72,27 @@ model {
104
72
  // Drawn topic → consumer, the direction the landscape uses and the one the
105
73
  // event spine requires there: `consumes` binds the edge's TARGET, so the same
106
74
  // edge drawn the other way round binds to nothing at all.
107
- kafka.orderEvents -> notificationService.consumer 'OrderPlaced triggers the confirmation'
108
- kafka.paymentEvents -> notificationService.consumer 'PaymentCaptured triggers the receipt'
109
- kafka.crmEvents -> notificationService.consumer 'CustomerUpdated refreshes contact details'
75
+ kafka.orderEvents -> marketplace.notificationService.consumer 'OrderPlaced triggers the confirmation'
76
+ kafka.paymentEvents -> marketplace.notificationService.consumer 'PaymentCaptured triggers the receipt'
77
+ kafka.crmEvents -> marketplace.notificationService.consumer 'CustomerUpdated refreshes contact details'
110
78
 
111
- notificationService.sender -> provider 'Sends email and SMS, and backs off on 429'
79
+ // The second thing this service reaches across its own boundary, and the one
80
+ // the runbook spends an incident section on: while the provider is down or
81
+ // throttling, nothing is delivered and there is no fallback path. Its element
82
+ // is the map's, and the map also carries the SERVICE-level twin of this edge
83
+ // (`marketplace.notificationService -> notificationProvider`), because every
84
+ // fleet check reads the map alone. The cross-boundary call is written twice on
85
+ // purpose — container-level here, service-level there — and that remainder is
86
+ // recorded in ROADMAP.md rather than hidden.
87
+ marketplace.notificationService.sender -> notificationProvider 'Sends email and SMS, and backs off on 429'
112
88
  }
113
89
 
90
+ // Views belong to LikeC4's renderer; no loam check reads anything below. This
91
+ // file is part of the root project, so `npx likec4 start` at the docs root draws
92
+ // this view beside the fleet map — there is no per-service likec4.config.json,
93
+ // and loam never writes one beside an extending model.
114
94
  views {
115
- view notification_service of notificationService {
95
+ view notification_service of marketplace.notificationService {
116
96
  include *
117
97
  }
118
98
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ybotok/loam",
3
- "version": "0.2.0-alpha.5",
3
+ "version": "0.2.0-alpha.6",
4
4
  "description": "Architecture-first semantic integrity and change governance for evolving software systems: connect C4, requirements, contracts, and verification evidence.",
5
5
  "author": "spentsov",
6
6
  "repository": {
@@ -1,4 +0,0 @@
1
- {
2
- "name": "checkout-web",
3
- "title": "checkout-web"
4
- }
@@ -1,4 +0,0 @@
1
- {
2
- "name": "order-service",
3
- "title": "order-service"
4
- }
@@ -1,4 +0,0 @@
1
- {
2
- "name": "payment-service",
3
- "title": "payment-service"
4
- }
@@ -1,4 +0,0 @@
1
- {
2
- "name": "identity-service",
3
- "title": "identity-service"
4
- }
@@ -1,4 +0,0 @@
1
- {
2
- "name": "notification-service",
3
- "title": "notification-service"
4
- }