archik 0.3.0 → 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.
@@ -124,17 +124,30 @@ The YAML tracks **shape**, not implementation detail.
124
124
 
125
125
  ## Hard rules for editing
126
126
 
127
+ The schema enforces these — `archik validate` will reject the file
128
+ if you break any of them, so don't bother trying.
129
+
127
130
  - **Never put coordinates** (`x`, `y`, `width`, `height`, `viewport`) in
128
131
  the YAML. Layout is computed by ELK on every render. The schema
129
132
  rejects unknown keys at root, node, edge, and metadata levels.
130
133
  - **Every id matches** `^[a-z][a-z0-9-]*$` — lowercase, starts with a
131
134
  letter, hyphens allowed.
132
- - **Edges reference existing nodes**. If `from` or `to` doesn't match a
133
- node id, the document fails to load.
134
- - **`parentId` references existing nodes** (typically `module` or
135
- `custom` containers).
135
+ - **Node ids and edge ids are unique** within their respective lists.
136
+ Duplicates fail validation.
137
+ - **Edges reference existing nodes**. If `from` or `to` doesn't match
138
+ a node id, the document fails to load.
139
+ - **No self-loop edges** — `from === to` isn't meaningful for an
140
+ architecture diagram and the schema rejects it.
141
+ - **`parentId` references an existing node** (any kind — typically a
142
+ `module` or `custom` container, but any node-with-children renders
143
+ as a container).
144
+ - **No `parentId` cycles** — a → b → a, or a node with itself as parent.
145
+ - **Any node with children is rendered as a container** regardless of
146
+ kind. So you can have a `frontend` "Web App" containing `module`
147
+ sub-areas, or a `service` containing `adapter` children — the icon
148
+ and KIND tag in the header still reflect the node's own kind.
136
149
  - **Don't rename a node id**. Remove the old node and re-add it with
137
- the new id, then fix every edge that referenced it.
150
+ the new id, then fix every edge / parentId that referenced it.
138
151
  - **Don't change `version`** — it's `"1.0"`.
139
152
 
140
153
  ## Schema (top-level)
@@ -218,8 +231,27 @@ Picking the right kind:
218
231
  - A logical grouping container (component, module) → `module`
219
232
  - Anything that doesn't fit and you want a custom shape → `custom`
220
233
 
221
- `module` and `custom` render as containers when they have children — set
222
- `parentId` on the children to nest them inside.
234
+ **Distinct visual shapes** (not just an icon — the *outline* differs):
235
+
236
+ | Kind | Shape |
237
+ | ---- | ----- |
238
+ | `database` | classic UML cylinder |
239
+ | `cloud` | cumulus cloud silhouette |
240
+ | `queue` | rounded capsule (pill) |
241
+ | `external` | dashed-border card |
242
+ | `module` / `custom` (with children) | container panel with header + tinted body |
243
+
244
+ Every other kind renders as the standard rounded card — the kind icon
245
+ in the header and the KIND label do the visual lifting. Don't expect
246
+ each kind to have its own outline; the icon + KIND tag is the
247
+ identity.
248
+
249
+ **Containers**: any node with children (declared via other nodes'
250
+ `parentId`) renders as a container, regardless of kind. So
251
+ `frontend` "Web App" can contain `module` sub-areas, a `service`
252
+ can contain hexagonal `port`/`adapter` children, etc. The kind of
253
+ the container itself controls the icon + accent colour shown in the
254
+ header bar.
223
255
 
224
256
  ## Edge fields
225
257
 
@@ -234,29 +266,56 @@ Picking the right kind:
234
266
  color: "#f97316" # optional, any CSS color (hex / named / var())
235
267
  ```
236
268
 
237
- ## Relationships (12 total)
238
-
239
- | Category | Relationship | Visual |
240
- | -------------- | ------------ | ------ |
241
- | Sync calls | `http_call`, `invokes`, `routes_to` | dotted, animated |
242
- | Data access | `reads`, `writes` | dotted, animated |
243
- | Messaging | `publishes`, `subscribes`, `streams_to` | dotted, animated |
244
- | Architectural | `implements`, `depends_on`, `has_a`, `uses` | static + muted |
269
+ ## Relationships (17 total)
270
+
271
+ | Category | Relationship | Visual signature |
272
+ | -------------- | ------------ | ---------------- |
273
+ | Sync wire | `http_call` | dotted, animated, filled-triangle arrow |
274
+ | | `grpc` | thicker dashed, animated, **double-tick chevron** arrow |
275
+ | | `invokes` | dotted, animated, filled-triangle arrow |
276
+ | | `routes_to` | solid, no animation |
277
+ | Bidirectional | `websocket` | dashed, **fast** animation, **arrows on both ends** |
278
+ | Async callback | `webhook` | long-dash dashed, animated, hollow-triangle arrow |
279
+ | Data access | `reads` | dotted, animated, hollow-triangle arrow |
280
+ | | `writes` | thicker dotted, animated, filled-triangle arrow |
281
+ | Messaging | `publishes` | dotted, animated, **circle** arrow head |
282
+ | | `subscribes` | dotted, animated, filled-triangle arrow |
283
+ | | `streams_to` | long-dash, **fast** animation, filled-triangle |
284
+ | UML structural | `implements` | dashed, **hollow-triangle** at the interface end (UML realisation) |
285
+ | | `extends` | solid, **hollow-triangle** at parent end (UML inheritance) |
286
+ | | `composes` | solid, **filled-diamond at the owner (source) end** (UML composition) |
287
+ | Loose deps | `depends_on` | dashed, hollow-triangle arrow |
288
+ | | `has_a` | solid, filled-triangle (informal composition) |
289
+ | | `uses` | short-dash, hollow-triangle (lightest dependency) |
245
290
 
246
291
  Picking the right relationship:
247
292
 
248
- - Service-to-service HTTP / RPC call → `http_call`
249
- - Calling a function or agent → `invokes`
250
- - Gateway routing requests → `routes_to`
293
+ **Wire-protocol calls** (something is going over the network *now*):
294
+ - Generic HTTP / REST call → `http_call`
295
+ - Typed RPC (protobuf, Connect, Twirp) → `grpc`
296
+ - Function / agent / lambda invocation → `invokes`
297
+ - Gateway / ingress routing → `routes_to`
298
+ - Long-lived bidirectional connection (chat, live trading, collab) → `websocket`
299
+ - Async callback the *other party* pushes to *us* (Stripe webhook, GitHub event) → `webhook`
300
+
301
+ **Data access**:
251
302
  - DB read query → `reads`
252
303
  - DB write / mutation → `writes`
304
+
305
+ **Messaging**:
253
306
  - Emitting an event / message → `publishes`
254
307
  - Consuming an event / message → `subscribes`
255
- - Continuous stream of records → `streams_to`
256
- - Adapter implements an interface → `implements`
257
- - A depends on B at the package / build level → `depends_on`
258
- - Composition / ownership ("has a") → `has_a`
259
- - Lighter-weight dependency → `uses`
308
+ - Continuous stream of records (Kafka, Kinesis, log shipping) → `streams_to`
309
+
310
+ **UML class-diagram structural** (drawn in the same style as a UML class diagram, so the visual matches what an engineer expects on a board):
311
+ - Adapter realises an abstract interface → `implements`
312
+ - Subclass / subtype inherits → `extends`
313
+ - Whole owns the part's lifecycle (component composition) → `composes`
314
+
315
+ **Looser architectural** (not UML-strict — for "X depends on Y" without claiming a specific relationship):
316
+ - Package / build-level dependency → `depends_on`
317
+ - Informal "has a" without lifecycle ownership → `has_a`
318
+ - Lightest weight: "X uses Y somewhere" → `uses`
260
319
 
261
320
  ## Common editing patterns
262
321
 
@@ -340,6 +399,67 @@ edges:
340
399
  relationship: implements
341
400
  ```
342
401
 
402
+ **Modelling a real-time chat with WebSocket + a Stripe webhook**:
403
+
404
+ ```yaml
405
+ nodes:
406
+ - id: web
407
+ kind: frontend
408
+ name: Web App
409
+ - id: api
410
+ kind: service
411
+ name: Chat API
412
+ - id: stripe
413
+ kind: external
414
+ name: Stripe
415
+ edges:
416
+ - id: web-api-ws
417
+ from: web
418
+ to: api
419
+ relationship: websocket # bidirectional, fast animation
420
+ label: messages
421
+ - id: stripe-api-webhook
422
+ from: stripe
423
+ to: api
424
+ relationship: webhook # async callback
425
+ label: payment.succeeded
426
+ ```
427
+
428
+ **gRPC between two Go services + UML class hierarchy**:
429
+
430
+ ```yaml
431
+ nodes:
432
+ - id: orders
433
+ kind: service
434
+ name: Orders
435
+ - id: payments
436
+ kind: service
437
+ name: Payments
438
+ - id: order
439
+ kind: interface
440
+ name: Order
441
+ - id: subscription-order
442
+ kind: interface
443
+ name: SubscriptionOrder
444
+ - id: cart
445
+ kind: custom
446
+ name: Cart
447
+ edges:
448
+ - id: orders-payments-grpc
449
+ from: orders
450
+ to: payments
451
+ relationship: grpc # double-tick chevron
452
+ label: ChargeRequest
453
+ - id: subscription-extends-order
454
+ from: subscription-order
455
+ to: order
456
+ relationship: extends # UML hollow triangle
457
+ - id: cart-composes-order
458
+ from: cart
459
+ to: order
460
+ relationship: composes # UML filled diamond at Cart
461
+ ```
462
+
343
463
  ## CLI
344
464
 
345
465
  These commands are available globally if archik was installed via