@rse/specbook 1.0.3 → 1.0.4

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 (40) hide show
  1. package/README.md +106 -19
  2. package/dst/specbook-api.d.ts +29 -9
  3. package/dst/specbook-api.js +108 -33
  4. package/dst/specbook-cli.js +84 -25
  5. package/dst/specbook-cmd-describe.d.ts +7 -1
  6. package/dst/specbook-cmd-describe.js +56 -11
  7. package/dst/specbook-cmd-export.d.ts +2 -1
  8. package/dst/specbook-cmd-export.js +46 -3
  9. package/dst/specbook-cmd-lint.d.ts +2 -1
  10. package/dst/specbook-cmd-lint.js +12 -8
  11. package/dst/specbook-cmd-preview.d.ts +12 -0
  12. package/dst/specbook-cmd-preview.js +57 -0
  13. package/dst/specbook-config.d.ts +1 -1
  14. package/dst/specbook-config.js +187 -37
  15. package/dst/specbook-diagnostic.d.ts +2 -0
  16. package/dst/specbook-diagnostic.js +4 -2
  17. package/dst/specbook-diagram.d.ts +1 -0
  18. package/dst/specbook-diagram.js +0 -0
  19. package/dst/specbook-export-ast.js +4 -2
  20. package/dst/specbook-export-common.js +5 -3
  21. package/dst/specbook-export-html-search.js +118 -30
  22. package/dst/specbook-export-html.css +1140 -233
  23. package/dst/specbook-export-html.d.ts +1 -1
  24. package/dst/specbook-export-html.js +764 -120
  25. package/dst/specbook-export-md.js +4 -2
  26. package/dst/specbook-format-schema.d.ts +33 -1
  27. package/dst/specbook-format-schema.js +34 -2
  28. package/dst/specbook-format.md +193 -25
  29. package/dst/specbook-format.yaml +2291 -299
  30. package/dst/specbook-link.d.ts +2 -1
  31. package/dst/specbook-link.js +43 -3
  32. package/dst/specbook-mcp.js +19 -10
  33. package/dst/specbook-parse-common.d.ts +4 -2
  34. package/dst/specbook-parse-common.js +6 -3
  35. package/dst/specbook-parse-semantic.js +290 -30
  36. package/dst/specbook-parse-syntax.js +3 -1
  37. package/dst/specbook-parse-value.d.ts +1 -0
  38. package/dst/specbook-parse-value.js +17 -3
  39. package/dst/specbook-parse.js +1 -1
  40. package/package.json +14 -6
@@ -4,13 +4,100 @@
4
4
  ## Licensed under Apache 2.0 <https://spdx.org/licenses/Apache-2.0>
5
5
  ##
6
6
 
7
+ # This is the "Standard" SpecBook schema.
8
+ #
9
+ # Modeling Purpose
10
+ # ----------------
11
+ #
12
+ # This schema allows to specify a large variety documents for the
13
+ # precise specification of solutions, systems and software.
14
+ #
15
+ # Modeling Coverage
16
+ # -----------------
17
+ #
18
+ # | "Standard" SpecBook Object | PRD | StRS | SyRS | SRS | UIS | UISG | TCS | AD |
19
+ # | --------------------------------- | --- | ---- | ---- | --- | --- | ---- | --- | --- |
20
+ # | META: Title | | | | | | | | |
21
+ # | --------------------------------- | --- | ---- | ---- | --- | --- | ---- | --- | --- |
22
+ # | REQS: Solution Vision | X | X | | | | | | |
23
+ # | REQS: Solution Premises | X | X | X | X | | | | |
24
+ # | REQS: Domain Glossary | X | X | X | X | | | | |
25
+ # | REQS: User Personas | X | X | X | X | X | | | |
26
+ # | REQS: User Journey | X | X | | | X | | | |
27
+ # | REQS: Functional Requirements | X | X | X | X | | | | |
28
+ # | REQS: Non-Functional Requirements | X | X | X | X | X | | | |
29
+ # | REQS: Domain Rules | | X | X | X | | | | |
30
+ # | REQS: Domain Workflows | | X | X | X | | | | |
31
+ # | REQS: Use Cases | | | X | X | X | | | |
32
+ # | --------------------------------- | --- | ---- | ---- | --- | --- | ---- | --- | --- |
33
+ # | DATA: Data Model | | | X | X | | | | |
34
+ # | DATA: State Model | | | X | X | | | | |
35
+ # | DATA: Authorization Model | | | X | X | | | | |
36
+ # | --------------------------------- | --- | ---- | ---- | --- | --- | ---- | --- | --- |
37
+ # | APIS: Interface Model | | | X | X | | | | |
38
+ # | APIS: Interface Datatypes | | | | X | | | | |
39
+ # | APIS: Interface Endpoints | | | | X | | | | |
40
+ # | --------------------------------- | --- | ---- | ---- | --- | --- | ---- | --- | --- |
41
+ # | UXUI: Interaction Concept | | | | | X | X | | |
42
+ # | UXUI: Language Conventions | | | | | X | X | | |
43
+ # | UXUI: Dialog Patterns | | | | | X | X | | |
44
+ # | UXUI: Dialog Storyboard | | | | | X | | | |
45
+ # | UXUI: Visual Design | | | | | X | X | | |
46
+ # | --------------------------------- | --- | ---- | ---- | --- | --- | ---- | --- | --- |
47
+ # | TEST: Test Cases | | | | | | | X | |
48
+ # | --------------------------------- | --- | ---- | ---- | --- | --- | ---- | --- | --- |
49
+ # | ARCH: Context View | | | | | | | | X |
50
+ # | ARCH: Functionality View | | | | | | | | X |
51
+ # | ARCH: Information View | | | | | | | | X |
52
+ # | ARCH: Concurrency View | | | | | | | | X |
53
+ # | ARCH: Development View | | | | | | | | X |
54
+ # | ARCH: Deployment View | | | | | | | | X |
55
+ # | ARCH: Operations View | | | | | | | | X |
56
+ # | ARCH: Quality Perspectives | | | | | | | | X |
57
+ # | ARCH: Decision Record | | | | | | | | X |
58
+ # | ARCH: Technology Stack | | | | | | | | X |
59
+ #
60
+ # Legend:
61
+ # - PRD: Product Requirements Document (Cagan 2005)
62
+ # - StRS: Stakeholder Requirements Specification (ISO/IEC/IEEE 29148 StRS)
63
+ # - SyRS: System Requirements Specification (ISO/IEC/IEEE 29148 SyRS)
64
+ # - SRS: Software Requirements Specification (ISO/IEC/IEEE 29148 SRS)
65
+ # - UIS: Human-Centred Design: User Interface Specification (ISO 9241-210:2019)
66
+ # - UISG: User Interface Style Guide (ISO 9241-110/-112/-125/-161)
67
+ # - TCS: Test Case Specification (ISO/IEC/IEEE 29119-3:2021)
68
+ # - AD: Architecture Description (ISO/IEC/IEEE 42010)
69
+ #
70
+ # Design Decisions
71
+ # ----------------
72
+ #
73
+ # - All object references are strictly back-references, i.e., later
74
+ # objects reference earlier ones.
75
+ #
76
+ # - The depth of the modeling aspects is at maximum at level 3, which
77
+ # means that all objects stay at level 1 and 2 and level 3 is mainly
78
+ # for properties. This leads to decent headings and a not too deep
79
+ # Table of Contents.
80
+ #
81
+ # - The traditional hard Software Requirements Specification (SRS)
82
+ # vs. Architecture Description (AD) document split is
83
+ # intentionally smoothed, so we can link from AD to SRS objects
84
+ # and in AI-times (where no longer dedicated teams write
85
+ # those documents separately) the AI should see one coherent
86
+ # specification document, too.
87
+ #
88
+
7
89
  - kind: META
8
90
  name: Title
9
91
  id: TI
10
- file: META-01-TI-Title.md
92
+ file: 00-META-TI-Title.md
11
93
  desc: >
12
94
  The top-level specification meta information.
13
95
  Some of the information is rendered onto the title page.
96
+ diagram:
97
+ type: graph
98
+ nodes: "[[REQS:*]], [[DATA:*]], [[APIS:*]], [[UXUI:*]], [[TEST:*]], [[ARCH:*]]"
99
+ deep: true
100
+ qualified: true
14
101
  props:
15
102
  - name: LOGO
16
103
  desc: The logo of the specification.
@@ -47,33 +134,263 @@
47
134
  value: /^#[0-9a-fA-F]{6}$/
48
135
  optional: true
49
136
 
50
- - kind: SPEC
137
+ - kind: REQS
51
138
  name: Solution Vision
52
139
  id: SV
53
- file: SPEC-01-SV-Solution-Vision.md
140
+ file: 01-REQS-SV-Solution-Vision.md
54
141
  desc: >
55
- The high-level, aspirational description of the solution, capturing its purpose, value
56
- proposition, and the desired future state it aims to achieve.
142
+ The high-level, aspirational description of the solution,
143
+ capturing why it exists, whom it serves, what it is, which
144
+ benefit it offers, how it differs from the alternatives, where
145
+ its boundary runs, how its achievement is measured, and the
146
+ desired future state it aims to achieve. Every vision aspect is
147
+ stated in a concise (1-3 sentence) paragraph in an aspirational
148
+ but unambiguous tone.
149
+ refs: >
150
+ - ISO/IEC/IEEE 29148:2018: Systems and software engineering -- Life cycle processes -- Requirements engineering (2018),
151
+ https://www.iso.org/standard/72089.html
152
+ - Moore: Crossing the Chasm, 3rd ed. (2014),
153
+ https://www.harperbusiness.com/book/9780062293008/Crossing-the-Chasm-3rd-Edition-Geoffrey-A.-Moore/
154
+ - Pichler: The Product Vision Board (2011),
155
+ https://www.romanpichler.com/tools/product-vision-board/
156
+ props:
157
+ - name: PURPOSE
158
+ desc: >
159
+ Why the solution exists.
160
+ - name: TARGET-AUDIENCE
161
+ desc: >
162
+ Who the solution serves.
163
+ - name: SOLUTION
164
+ desc: >
165
+ What the solution is, in a single sentence naming its kind or
166
+ category (e.g. a self-hosted, browser-based streaming platform).
167
+ - name: VALUE-PROPOSITION
168
+ desc: >
169
+ The benefit the solution offers its target audience, stated in
170
+ absolute terms without reference to alternatives.
171
+ - name: DIFFERENTIATORS
172
+ desc: >
173
+ How the solution stands apart from the alternatives, naming the
174
+ alternatives it is compared against (including the status quo).
175
+ optional: true
176
+ - name: SCOPE
177
+ desc: >
178
+ The boundary of the solution, stating what it deliberately does
179
+ *not* cover and which adjacent concerns are left to others.
180
+ optional: true
181
+ - name: SUCCESS-CRITERIA
182
+ desc: >
183
+ The measurable business outcomes by which the achievement of the
184
+ vision is judged (e.g. adoption, cost, or time-to-value targets).
185
+ optional: true
186
+ - name: FUTURE-STATE
187
+ desc: >
188
+ The desired outcome once the solution is adopted, describing what
189
+ is true then that is not true today.
190
+ optional: true
191
+
192
+ - kind: REQS
193
+ name: Solution Premises
194
+ id: SP
195
+ file: 02-REQS-SP-Solution-Premises.md
196
+ desc: >
197
+ The premises the specification rests on but cannot guarantee itself: the assumptions
198
+ held true without proof, the dependencies on parties and systems outside the solution,
199
+ and the risks whose occurrence would endanger it, each rated by the likelihood and
200
+ the impact of its failure and stating what follows then, so that the requirements
201
+ resting on a premise are known and revisited once it turns out to be false. The
202
+ artifact complements the Solution Vision: the vision states what the solution aims
203
+ for, the premises state what it takes as given on the way there.
204
+ refs: >
205
+ - ISO/IEC/IEEE 29148:2018: Systems and software engineering -- Life cycle processes -- Requirements engineering (2018),
206
+ https://www.iso.org/standard/72089.html
207
+ - Robertson/Robertson: Volere Requirements Specification Template, 18th ed. (2018),
208
+ https://www.volere.org/templates/volere-requirements-specification-template/
209
+ - ISO 31000:2018: Risk management -- Guidelines (2018),
210
+ https://www.iso.org/standard/65694.html
211
+ - Boehm: Software Risk Management: Principles and Practices, IEEE Software 8(1) (1991),
212
+ https://doi.org/10.1109/52.62930
213
+ diagram:
214
+ type: grid
215
+ nodes: "[[REQS:SP.PREMISE:*]]"
216
+ properties:
217
+ - TYPE
218
+ - LIKELIHOOD
219
+ - IMPACT
220
+ config:
221
+ size-node-width-max: 440
222
+ size-node-height-scale: 1.75
223
+ grid-columns-max: 5
57
224
  childs:
58
- - kind: ASPECT
225
+ - kind: PREMISE
59
226
  desc: >
60
- A single vision aspect, named with a short (2-5 word) summary and described in a
61
- concise (1-3 sentence) paragraph in an aspirational but unambiguous tone.
227
+ A single premise, named with a short (3-8 word) summary phrased as the fact taken
228
+ as given or the event feared (e.g. `Streaming Providers Deliver the Video`, `Access
229
+ URLs Forwarded Beyond the Audience`) and described in a concise (1-3 sentence)
230
+ paragraph as a declarative statement of what is held true (an `Assumption` or
231
+ `Dependency`) or what may happen (a `Risk`), plus a 1-sentence rationale ("why")
232
+ stating the evidence or agreement the premise rests on or the cause the risk stems
233
+ from.
234
+
235
+ A premise is outside the control of the solution (a condition the solution
236
+ enforces itself is a Domain Rule or a Non-Functional Requirement instead) and
237
+ states a fact or event, not a decision (a deliberate exclusion is the `SCOPE` of
238
+ the Solution Vision or a `WONT` requirement instead).
239
+ format:
240
+ maxTableColumns: 5
241
+ props:
242
+ - name: TYPE
243
+ desc: >
244
+ The kind of premise: `Assumption` (a fact about the domain, the users,
245
+ or the environment held true without proof, whose falsity changes the
246
+ requirements), `Dependency` (a reliance on a party, system, or
247
+ deliverable outside the solution, which has to be available and to
248
+ behave as agreed), or `Risk` (an uncertain event which, if it occurs,
249
+ harms the achievement of the vision).
250
+ value: enum(Assumption,Dependency,Risk)
251
+ - name: TERMS
252
+ desc: >
253
+ Comma-separated references to the GLOSSARY terms the premise is about
254
+ (e.g. the external system a dependency relies on), anchoring it in the
255
+ ubiquitous language.
256
+ value: list([[REQS:GL.TERM:*]])
257
+ optional: true
258
+ - name: OWNER
259
+ desc: >
260
+ Reference to the User Personas object (usually a `Stakeholder`) who
261
+ vouches for the premise, i.e. who confirms an assumption, holds the
262
+ agreement of a dependency, or owns the mitigation of a risk, omitted when
263
+ nobody in particular is accountable.
264
+ value: "[[REQS:UP.PERSONA:*]]"
265
+ optional: true
266
+ - name: LIKELIHOOD
267
+ desc: >
268
+ The likelihood that the premise fails, i.e. that the assumption turns out
269
+ to be false, the dependency is not honored, or the risk occurs: `Low`,
270
+ `Medium`, or `High`.
271
+ value: enum(Low,Medium,High)
272
+ - name: IMPACT
273
+ desc: >
274
+ The severity of the `CONSEQUENCE` for the solution once the premise fails:
275
+ `Low`, `Medium`, or `High`, so that the product of likelihood and impact
276
+ ranks the premises by the attention they need.
277
+ value: enum(Low,Medium,High)
278
+ - name: CONSEQUENCE
279
+ desc: >
280
+ What concretely follows for the solution if the premise fails, stated
281
+ as a 1-2 sentence description of the harm (e.g. `attendees cannot enter
282
+ the event`), justifying the `IMPACT` rating.
283
+ - name: MITIGATION
284
+ desc: >
285
+ What is done to lower the likelihood or the impact of the failure or to
286
+ detect it early (e.g. a fallback, a contract, a load test), omitted for
287
+ a premise whose failure is knowingly accepted.
288
+ optional: true
289
+ - name: AFFECTS
290
+ desc: >
291
+ Comma-separated references to the FUNCTIONAL-REQUIREMENTS,
292
+ NON-FUNCTIONAL-REQUIREMENTS, or DOMAIN-RULES objects resting on the
293
+ premise, i.e. those to be revisited once it fails.
294
+ value: list([[REQS:FR.*]], [[REQS:NR.*]], [[REQS:DR.RULE:*]])
295
+ optional: true
62
296
 
63
- Recommended aspects are `Purpose` (why the solution exists), `Target Audience` (who
64
- it serves), `Value Proposition` (the unique benefit offered), `Differentiators` (how
65
- it stands apart from alternatives), and `Future State` (the desired outcome once
66
- adopted).
297
+ - kind: REQS
298
+ name: Domain Glossary
299
+ id: GL
300
+ file: 03-REQS-GL-Domain-Glossary.md
301
+ desc: >
302
+ The ubiquitous language of the domain, defining the meaning of each domain term in business
303
+ language, together with its synonyms, its place in the hierarchy of terms, and the terms it
304
+ has to be kept apart from, shared consistently across all Artifacts.
305
+ refs: >
306
+ - ISO 704:2022: Terminology work -- Principles and methods (2022),
307
+ https://www.iso.org/standard/79077.html
308
+ - ISO 1087:2019: Terminology work and terminology science -- Vocabulary (2019),
309
+ https://www.iso.org/standard/62330.html
310
+ - Evans: Domain-Driven Design: Tackling Complexity in the Heart of Software (2003),
311
+ https://www.domainlanguage.com/ddd/
312
+ diagram:
313
+ type: grid
314
+ nodes: "[[REQS:GL.TERM:*]]"
315
+ properties:
316
+ - TYPE
317
+ config:
318
+ size-node-width-max: 440
319
+ grid-columns-max: 4
320
+ childs:
321
+ - kind: TERM
322
+ name: "[A-Z][A-Za-z0-9-]*( [A-Z][A-Za-z0-9-]*)*"
323
+ desc: >
324
+ A single domain term, named with its canonical, preferred form (each word
325
+ capitalized, as it should appear in all artifacts) and defined in a concise (1-3
326
+ sentence) paragraph in business language, independent of any implementation,
327
+ referencing other terms by their name where helpful.
328
+
329
+ The definition is intensional (ISO 704): it opens with the superordinate concept
330
+ (the `BROADER` term where one exists) and adds the characteristics delimiting the
331
+ term from its siblings (e.g. `A Message submitted by an Attendee as ...`), so that
332
+ the hierarchy and the definitions cross-check each other.
333
+ format:
334
+ maxTableColumns: 5
335
+ referenced:
336
+ - "[[*]]"
337
+ diagram:
338
+ type: hub
339
+ center: self
340
+ nodes: "[[REQS:GL.TERM:*]], [[REQS:DR.RULE:*]], [[DATA:DM.ENTITY:*]], [[REQS:UP.PERSONA:*]]"
341
+ labeled: true
342
+ qualified: true
343
+ config:
344
+ size-node-width-max: 440
345
+ size-node-height-scale: 1.75
346
+ props:
347
+ - name: TYPE
348
+ desc: >
349
+ The kind of concept the term denotes: `Entity` (a thing of the domain,
350
+ usually materialized by a DATA-MODEL entity), `Actor` (a party acting in
351
+ the domain, be it a human role usually embodied by a PERSONA or an external
352
+ system), or `Activity` (a process or procedure of the domain).
353
+ value: enum(Entity,Actor,Activity)
354
+ - name: SYNONYMS
355
+ desc: >
356
+ Comma-separated list of alternative names or abbreviations that refer to the
357
+ same term but are *not* the preferred form; a synonym is unambiguous within
358
+ the Domain Glossary, so a shorthand shared by several terms (the ambiguity a
359
+ `DISTINCT-FROM` marks) is not a synonym of any of them.
360
+ optional: true
361
+ - name: BROADER
362
+ desc: >
363
+ Reference to the GLOSSARY term this term is a kind of (or a part of), so
364
+ that the terms form a hierarchy in which a rule governing the broader term
365
+ covers the narrower ones, too; at most one broader term, keeping the
366
+ hierarchy a tree.
367
+ value: "[[REQS:GL.TERM:*]]"
368
+ optional: true
369
+ acyclic: true
370
+ - name: DISTINCT-FROM
371
+ desc: >
372
+ Comma-separated references to the GLOSSARY terms easily confused with this
373
+ one but deliberately *not* synonymous, listed on both terms of each pair,
374
+ with the distinction stated in the definitions.
375
+ value: list([[REQS:GL.TERM:*]])
376
+ optional: true
377
+ symmetric: true
67
378
 
68
- - kind: SPEC
379
+ - kind: REQS
69
380
  name: User Personas
70
381
  id: UP
71
- file: SPEC-02-UP-User-Personas.md
382
+ file: 04-REQS-UP-User-Personas.md
72
383
  desc: >
73
384
  The *archetypal* user profiles representing distinct user groups, capturing their goals,
74
- needs, behaviors, and context.
75
- format:
76
- maxTableColumns: 5
385
+ needs, behaviors, and context, complemented by the non-user stakeholders whose interests
386
+ the solution has to serve.
387
+ refs: >
388
+ - Cooper: The Inmates Are Running the Asylum, 2nd ed. (2004),
389
+ https://www.informit.com/store/inmates-are-running-the-asylum-why-high-tech-products-9780672326141
390
+ - Cooper et al.: About Face: The Essentials of Interaction Design, 4th ed. (2014),
391
+ https://www.wiley.com/en-gb/About+Face:+The+Essentials+of+Interaction+Design,+4th+Edition-p-9781118766576
392
+ - Pruitt/Adlin: The Persona Lifecycle: Keeping People in Mind Throughout Product Design (2006),
393
+ https://www.sciencedirect.com/book/9780125662512/the-persona-lifecycle
77
394
  childs:
78
395
  - kind: PERSONA
79
396
  desc: >
@@ -81,41 +398,92 @@
81
398
  fictional person and carrying a short, bold first-person quote -- written in the
82
399
  persona's own voice, like a "tagline", "mantra", or "defining statement" -- that
83
400
  captures their core attitude, motivation, frustration, or need in a single memorable
84
- line.
401
+ line. Non-user stakeholders are modeled as personas of type `Stakeholder`.
402
+ format:
403
+ maxTableColumns: 5
404
+ referenced:
405
+ - "[[DATA:AM.ROLE:*]]"
85
406
  props:
407
+ - name: TYPE
408
+ desc: >
409
+ Whether the persona is a `User` of the solution, i.e. an archetype of the
410
+ people directly interacting with it, or a `Stakeholder`, i.e. a party
411
+ with a legitimate interest in the solution but without (or beyond) its
412
+ direct use -- like a sponsor, regulator, auditor, or operations team --
413
+ whose goals and frustrations shape the requirements and constraints, but
414
+ whose "quote" reflects an institutional rather than a personal voice;
415
+ defaults to `User`.
416
+ value: enum(User,Stakeholder)
417
+ optional: true
86
418
  - name: GENDER
87
419
  desc: >
88
420
  The gender of the persona: `male`, `female`, or `diverse`.
89
421
  value: enum(male,female,diverse)
422
+ optional: true
90
423
  - name: AGE
91
- desc: The age in years of the persona.
424
+ desc: >
425
+ The age in years of the persona.
92
426
  value: /^[0-9]+$/
427
+ optional: true
93
428
  - name: ROLE
94
- desc: The role of the persona.
429
+ desc: >
430
+ The role of the persona.
431
+ - name: TERMS
432
+ desc: >
433
+ Comma-separated references to the GLOSSARY terms the persona embodies, i.e.
434
+ the domain roles it acts in and the domain concepts it primarily deals
435
+ with, so that every persona is anchored in the ubiquitous language.
436
+ value: list([[REQS:GL.TERM:*]])
437
+ optional: true
438
+ - name: PROFICIENCY
439
+ desc: >
440
+ The technical and domain skill level of the persona: `novice`,
441
+ `intermediate`, or `expert`.
442
+ value: enum(novice,intermediate,expert)
443
+ optional: true
444
+ - name: GOAL
445
+ desc: >
446
+ What the persona wants to achieve with the solution overall, stated as one
447
+ or more concise goals.
448
+ - name: FRUSTRATION
449
+ desc: >
450
+ The status-quo pains and unmet needs motivating the persona, stated
451
+ independently of the per-step pain points of the User Journey, which
452
+ record the friction within the target journey instead.
453
+ optional: true
95
454
 
96
- - kind: SPEC
455
+ - kind: REQS
97
456
  name: User Journey
98
457
  id: UJ
99
- file: SPEC-03-UJ-User-Journey.md
458
+ file: 05-REQS-UJ-User-Journey.md
100
459
  desc: >
101
460
  The end-to-end experience a user has while discovering, adopting, and using the solution,
102
- mapping their steps, touchpoints, and emotions over time.
461
+ mapping their steps, touchpoints, and emotions over time. The journey is the *target*
462
+ journey with the solution in place, so the friction it records is what the solution has
463
+ to mitigate, not the status quo it replaces.
464
+ refs: >
465
+ - NN/g: Journey Mapping 101 (2018),
466
+ https://www.nngroup.com/articles/journey-mapping-101/
467
+ - Kalbach: Mapping Experiences, 2nd ed. (2020),
468
+ https://www.oreilly.com/library/view/mapping-experiences-2nd/9781492076629/
469
+ - Stickdorn et al.: This Is Service Design Doing (2018),
470
+ https://www.thisisservicedesigndoing.com/
103
471
  diagram:
104
472
  type: grid
105
- nodes: "[[SPEC:UJ.JOURNEY:*]]"
473
+ nodes: "[[REQS:UJ.JOURNEY:*]]"
106
474
  properties:
107
- - ACTOR
475
+ - ACTORS
108
476
  childs:
109
477
  - kind: JOURNEY
110
478
  desc: >
111
479
  The end-to-end journey of a single persona (or of multiple personas sharing the same
112
480
  experience as role variants), named with a 2-5 word summary of the pursued scenario.
113
481
  props:
114
- - name: ACTOR
482
+ - name: ACTORS
115
483
  desc: >
116
484
  Comma-separated references to the User Personas objects experiencing the
117
485
  journey.
118
- value: list([[SPEC:UP.PERSONA:*]])
486
+ value: list([[REQS:UP.PERSONA:*]])
119
487
  childs:
120
488
  - kind: STEP
121
489
  desc: >
@@ -128,10 +496,11 @@
128
496
  aware of the solution, but has a need), `Consideration` (the actor
129
497
  is aware of the solution and considers its use), `Decision` (the
130
498
  actor wants to pick the solution), `Onboarding` (the actor starts
131
- using the solution), `Retention` (the actor stays a user in the long
132
- term), or `Advocacy` (the actor is a fan of the solution and tells
133
- others).
134
- value: enum(Awareness,Consideration,Decision,Onboarding,Retention,Advocacy)
499
+ using the solution for the first time), `Usage` (the actor performs
500
+ the recurring core activity the solution is for), `Retention` (the
501
+ actor returns, renews, or extends use over the long term), or
502
+ `Advocacy` (the actor is a fan of the solution and tells others).
503
+ value: enum(Awareness,Consideration,Decision,Onboarding,Usage,Retention,Advocacy)
135
504
  - name: GOAL
136
505
  desc: What the actor wants to achieve at this step.
137
506
  - name: TOUCHPOINT
@@ -142,25 +511,41 @@
142
511
  desc: What the actor actually does at this step.
143
512
  - name: EMOTION
144
513
  desc: >
145
- The **AS IS** felt state at this step, given as a word plus an
146
- intensity on a 1-5 Likert scale (e.g. `Curious (4)`).
147
- value: /^.+ \([1-5]\)$/
514
+ The felt state of the actor at this step, given as a word plus its
515
+ valence on a signed 5-point Likert scale from `-2` (very negative)
516
+ over `0` (neutral) to `+2` (very positive), so that the emotion
517
+ curve of the journey can be derived (e.g. `Curious (+1)`).
518
+ value: /^.+ \((-[12]|0|\+[12])\)$/
148
519
  - name: PAIN-POINT
149
520
  desc: >
150
- The **AS IS** friction or frustration the actor encounters at this
151
- step.
521
+ The friction or frustration the actor encounters at this step,
522
+ i.e. what the solution has to mitigate here.
523
+ optional: true
524
+ - name: OPPORTUNITY
525
+ desc: >
526
+ The improvement the solution delivers (or should deliver) at this
527
+ step, mitigating the pain point or reinforcing the positive emotion,
528
+ and serving as the seed of Functional Requirements.
152
529
  optional: true
153
530
 
154
- - kind: SPEC
531
+ - kind: REQS
155
532
  name: Functional Requirements
156
533
  id: FR
157
- file: SPEC-04-FR-Functional-Requirements.md
534
+ file: 06-REQS-FR-Functional-Requirements.md
158
535
  desc: >
159
536
  The concrete behaviors and capabilities the solution must provide, describing *what* the
160
- system does in terms of functions, features, and operations.
537
+ system does in terms of functions, features, and operations, while the quality bounds and
538
+ constraints on them belong to the Non-Functional Requirements.
539
+ refs: >
540
+ - Mavin et al.: Easy Approach to Requirements Syntax (EARS) (2009),
541
+ https://ieeexplore.ieee.org/document/5328509
542
+ - ISO/IEC/IEEE 29148:2018: Systems and software engineering -- Life cycle processes -- Requirements engineering (2018),
543
+ https://www.iso.org/standard/72089.html
544
+ - DSDM: MoSCoW Prioritisation, DSDM Agile Project Framework (2014),
545
+ https://www.agilebusiness.org/dsdm-project-framework/moscow-prioritisation.html
161
546
  diagram:
162
547
  type: grid
163
- nodes: "[[SPEC:FR.REQUIREMENT:*]]"
548
+ nodes: "[[REQS:FR.REQUIREMENT:*]]"
164
549
  properties:
165
550
  - PRIORITY
166
551
  config:
@@ -170,28 +555,47 @@
170
555
  - kind: REQUIREMENT
171
556
  desc: >
172
557
  A single functional requirement, named with a short (3-8 word) summary and described
173
- in a concise (1-3 sentence) paragraph as *what* the solution must do, written with
174
- the keyword `MUST`, `SHOULD`, `COULD`, or `WONT` to indicate the obligation level,
175
- plus a 1-sentence rationale ("why").
558
+ in a concise (1-3 sentence) paragraph as *what* the solution must do, stating
559
+ exactly one obligation (split into several requirements otherwise) as an observable
560
+ behavior a test case can verify, written with exactly one keyword `MUST`, `SHOULD`,
561
+ or `COULD` matching its `PRIORITY`, plus a 1-sentence rationale ("why").
562
+
563
+ The statement follows one of the EARS patterns: ubiquitous (`The system MUST ...`),
564
+ event-driven (`When <trigger>, the system MUST ...`), state-driven (`While <state>,
565
+ the system MUST ...`), optional-feature (`Where <feature>, the system MUST ...`), or
566
+ unwanted-behavior (`If <condition>, then the system MUST ...`).
567
+ format:
568
+ maxTableColumns: 6
569
+ referenced:
570
+ - "[[REQS:UC.USE-CASE:*]]"
176
571
  props:
177
572
  - name: PRIORITY
178
573
  desc: >
179
574
  The MoSCoW priority of the requirement: `MUST`, `SHOULD`, `COULD`, or
180
- `WONT`. The `WONT` priority records a requirement deliberately excluded from
181
- the current scope ("won't have this time"), preserving the conscious
182
- decision rather than silently dropping it.
575
+ `WONT`, matching the keyword of the statement. The `WONT` priority records
576
+ a requirement deliberately excluded from the current scope ("won't have this
577
+ time"), preserving the conscious decision rather than silently dropping it,
578
+ with the statement still phrased as it would be if in scope.
183
579
  value: enum(MUST,SHOULD,COULD,WONT)
184
580
 
185
- - kind: SPEC
581
+ - kind: REQS
186
582
  name: Non-Functional Requirements
187
583
  id: NR
188
- file: SPEC-05-NR-Non-Functional-Requirements.md
584
+ file: 07-REQS-NR-Non-Functional-Requirements.md
189
585
  desc: >
190
586
  The quality attributes and constraints the solution must satisfy, such as performance,
191
587
  security, scalability, reliability, and usability.
588
+ refs: >
589
+ - ISO/IEC 25010:2023: Systems and software engineering -- Systems and software Quality Requirements and Evaluation (SQuaRE) -- Product quality model (2023),
590
+ https://www.iso.org/standard/78176.html
591
+ - ISO/IEC/IEEE 29148:2018: Systems and software engineering -- Life cycle processes -- Requirements engineering (2018),
592
+ https://www.iso.org/standard/72089.html
593
+ - DSDM: MoSCoW Prioritisation, DSDM Agile Project Framework (2014),
594
+ https://www.agilebusiness.org/dsdm-project-framework/moscow-prioritisation.html
595
+ - Doran: There's a S.M.A.R.T. Way to Write Management's Goals and Objectives, Management Review 70(11) (1981)
192
596
  diagram:
193
597
  type: grid
194
- nodes: "[[SPEC:NR.REQUIREMENT:*]]"
598
+ nodes: "[[REQS:NR.REQUIREMENT:*]]"
195
599
  properties:
196
600
  - PRIORITY
197
601
  - CATEGORY
@@ -203,78 +607,487 @@
203
607
  desc: >
204
608
  A single non-functional requirement, named with a short (3-8 word) summary and
205
609
  described in a concise (1-3 sentence) paragraph as the quality attribute or
206
- constraint the solution must satisfy, plus a 1-sentence rationale ("why").
207
-
208
- The description especially *MUST* contain a *METRIC* within the `CATEGORY`, which
209
- (according to the SMART principle) is the *specific*, *measurable*, *achievable*,
210
- *relevant*, and *time-bound* threshold or target by which the requirement is judged
211
- satisfied (e.g. `p95 latency < 200ms`, `99.9% uptime`).
610
+ constraint the solution must satisfy, stating exactly one obligation (split into
611
+ several requirements otherwise) which is verifiable against its `METRIC`, written
612
+ with exactly one keyword `MUST`, `SHOULD`, or `COULD` matching its `PRIORITY`, plus
613
+ a 1-sentence rationale ("why").
212
614
  props:
213
615
  - name: PRIORITY
214
616
  desc: >
215
617
  The MoSCoW priority of the requirement: `MUST`, `SHOULD`, `COULD`, or
216
- `WONT`. The `WONT` priority records a requirement deliberately excluded from
217
- the current scope ("won't have this time"), preserving the conscious
218
- decision rather than silently dropping it.
618
+ `WONT`, matching the keyword of the statement. The `WONT` priority records
619
+ a requirement deliberately excluded from the current scope ("won't have this
620
+ time"), preserving the conscious decision rather than silently dropping it,
621
+ with the statement still phrased as it would be if in scope.
219
622
  value: enum(MUST,SHOULD,COULD,WONT)
220
623
  - name: CATEGORY
221
624
  desc: >
222
- The quality attribute category the requirement addresses, according to the
223
- top-level characteristics of the ISO/IEC 25010:2023 Software-Quality Model
224
- (except for `Functional Suitability`, which is covered by the Functional
225
- Requirements instead).
226
- value: enum(Performance,Compatibility,Usability,Reliability,Security,Safety,Maintainability,Flexibility,Compliance)
625
+ The category of the requirement: the quality attribute it addresses,
626
+ according to the top-level characteristics of the ISO/IEC 25010:2023
627
+ Software-Quality Model (except for `Functional Suitability`, which is
628
+ covered by the Functional Requirements instead, and with `Usability` kept
629
+ as the name of `Interaction Capability`), plus the two non-quality
630
+ categories `Compliance` (a legal or regulatory obligation) and `Constraint`
631
+ (a technical, business, or environmental constraint on the *solution*,
632
+ e.g. a hosting, budget, or technology mandate, as opposed to a constraint
633
+ on the domain, which is a Domain Rule).
634
+ value: enum(Performance,Compatibility,Usability,Reliability,Security,Safety,Maintainability,Flexibility,Compliance,Constraint)
635
+ - name: QUALIFIES
636
+ desc: >
637
+ Comma-separated references to the FUNCTIONAL-REQUIREMENTS objects whose
638
+ capability the requirement bounds or constrains.
639
+ value: list([[REQS:FR.*]])
640
+ optional: true
641
+ - name: METRIC
642
+ desc: >
643
+ The threshold or target by which the requirement is judged satisfied,
644
+ stated as a scale plus a target value according to the SMART principle
645
+ (*specific*, *measurable*, *achievable*, *relevant*, and *time-bound*),
646
+ e.g. `p95 latency < 200 ms` or `uptime >= 99.9 % per month`.
227
647
 
228
- - kind: SPEC
229
- name: Business Rules
230
- id: BR
231
- file: SPEC-06-BR-Business-Rules.md
648
+ - kind: REQS
649
+ name: Domain Rules
650
+ id: DR
651
+ file: 08-REQS-DR-Domain-Rules.md
232
652
  desc: >
233
653
  The domain invariants, policies, and decision logic that must always hold true in the
234
654
  problem domain, independent of any single feature, constraining the Functional and
235
655
  Non-Functional Requirements.
656
+ refs: >
657
+ - Hay/Healy: Defining Business Rules ~ What Are They Really? (2000),
658
+ https://www.businessrulesgroup.org/first_paper/br01c0.htm
659
+ - BRG: Business Rules Manifesto (2003),
660
+ https://www.businessrulesgroup.org/brmanifesto.htm
661
+ - OMG DMN 1.5: Decision Model and Notation (2024),
662
+ https://www.omg.org/spec/DMN/
236
663
  diagram:
237
664
  type: grid
238
- nodes: "[[SPEC:BR.RULE:*]]"
665
+ nodes: "[[REQS:DR.RULE:*]]"
239
666
  properties:
240
667
  - CATEGORY
668
+ - SOURCE
241
669
  config:
242
670
  size-node-width-max: 440
243
671
  grid-columns-max: 5
244
672
  childs:
245
673
  - kind: RULE
246
674
  desc: >
247
- A single business rule, named with a short (3-8 word) summary and described in a
675
+ A single domain rule, named with a short (3-8 word) summary and described in a
248
676
  concise (1-3 sentence) paragraph stating the rule declaratively as a condition that
249
- must hold, written with the keyword `MUST`, `SHOULD`, or `MUST NOT` to indicate the
250
- obligation level and naming the domain terms it governs (as defined in the
251
- Glossary), plus a 1-sentence rationale ("why").
677
+ must hold, written with the keyword `MUST` or `MUST NOT` (`SHOULD` or `SHOULD NOT`
678
+ for a `Policy` only, as a `SHOULD` on any other kind contradicts its "must always
679
+ hold" nature) to indicate the obligation level and naming the domain terms it
680
+ governs (as defined in the Domain Glossary and listed in `GOVERNS`), plus a 1-sentence
681
+ rationale ("why"). A permission (`MAY`) is not a rule: state the obligation which
682
+ bounds the permitted choice instead (e.g. `MUST use only ...` rather than
683
+ `MAY use ...`).
684
+
685
+ The subject of the statement is a domain term, never the system: a rule holds in
686
+ the problem domain even if the solution were replaced, so if the sentence needs
687
+ `The system` as its subject, it is a Functional Requirement, not a rule.
688
+
689
+ A rule whose outcome depends on more than two conditions is stated as a decision
690
+ list instead of prose, in the manner of a DMN decision table: a lead sentence
691
+ naming the governed term and the obligation, an ordered list with one `<condition>:
692
+ <outcome>` item per case, applied in order with the first matching case winning,
693
+ and a closing sentence stating the outcome of the remaining cases ("otherwise")
694
+ and carrying the rationale.
695
+ format:
696
+ maxTableColumns: 5
697
+ referenced:
698
+ - "[[TEST:TC.TEST-CASE:*]]"
252
699
  props:
253
700
  - name: CATEGORY
254
701
  desc: >
255
- The kind of rule: `Invariant` (a condition that must always hold),
256
- `Constraint` (a limit on allowed values or actions), `Derivation` (a value
257
- computed from others), or `Policy` (a deliberate business decision or
258
- guideline).
259
- value: enum(Invariant,Constraint,Derivation,Policy)
702
+ The kind of rule: `Constraint` (a structural condition that must always
703
+ hold, limiting the allowed *domain* states, values, or actions, as opposed
704
+ to a constraint on the solution, which is a Non-Functional Requirement),
705
+ `Derivation` (a value computed or a fact inferred from others), `Action`
706
+ (an obligation triggered by a domain event, stated as `When <trigger>,
707
+ <term> MUST ...` and told apart from an event-driven Functional Requirement
708
+ by its domain subject alone), or `Policy` (a deliberate business guideline
709
+ stated with `SHOULD`/`SHOULD NOT`, which may be deviated from with
710
+ justification, whereas the other kinds are stated with `MUST`/`MUST NOT`
711
+ and cannot).
712
+ value: enum(Constraint,Derivation,Action,Policy)
713
+ - name: SOURCE
714
+ desc: >
715
+ The authority the rule originates from, determining who can change it:
716
+ `Law` (a statutory or regulatory obligation, changeable by the legislator
717
+ only), `Contract` (an agreement with a customer, partner, or supplier,
718
+ changeable by renegotiation only), `Standard` (an industry norm or
719
+ standard, deviated from with justification only), `Business` (a deliberate
720
+ decision of the organization, changeable by its owner), or `Domain` (an
721
+ inherent truth of the problem domain, not changeable without redefining
722
+ the domain). The concrete authority (e.g. `GDPR Art. 17`) is named in the
723
+ rationale of the rule.
724
+ value: enum(Law,Contract,Standard,Business,Domain)
725
+ optional: true
726
+ - name: GOVERNS
727
+ desc: >
728
+ Comma-separated references to the GLOSSARY terms the rule governs, i.e.
729
+ the domain terms its statement is about, so that every rule is anchored in
730
+ the ubiquitous language and every term shows the rules that hold for it.
731
+ value: list([[REQS:GL.TERM:*]])
732
+ optional: true
260
733
  - name: CONSTRAINS
261
734
  desc: >
262
735
  Comma-separated references to the FUNCTIONAL-REQUIREMENTS or
263
736
  NON-FUNCTIONAL-REQUIREMENTS objects the rule constrains.
264
- value: list([[SPEC:FR.*]], [[SPEC:NR.*]])
737
+ value: list([[REQS:FR.*]], [[REQS:NR.*]])
265
738
  optional: true
266
739
 
267
- - kind: SPEC
740
+ - kind: REQS
741
+ name: Domain Workflows
742
+ id: DW
743
+ file: 09-REQS-DW-Domain-Workflows.md
744
+ desc: >
745
+ The cross-actor, multi-sitting workflows of the domain (also known as business
746
+ processes) the solution takes part in, each an ordered set of activities connected by
747
+ handoffs between the acting parties, making the collaboration across roles and over time
748
+ explicit, which neither the User Journey (the experience of a single persona) nor the
749
+ Use Cases (the goal of a single actor in one sitting) capture. The artifact is absent for
750
+ a tool-like solution without any workflow spanning several actors or sittings.
751
+ optional: true
752
+ refs: >
753
+ - OMG: Business Process Model and Notation (BPMN) 2.0.2 (2013),
754
+ https://www.omg.org/spec/BPMN/2.0.2
755
+ - Dumas/La Rosa/Mendling/Reijers: Fundamentals of Business Process Management, 2nd ed. (2018),
756
+ https://link.springer.com/book/10.1007/978-3-662-56509-4
757
+ - van der Aalst: Process Mining: Data Science in Action, 2nd ed. (2016),
758
+ https://link.springer.com/book/10.1007/978-3-662-49851-4
759
+ diagram:
760
+ type: grid
761
+ nodes: "[[REQS:DW.WORKFLOW:*]]"
762
+ properties:
763
+ - ACTORS
764
+ config:
765
+ size-node-width-max: 440
766
+ size-node-height-scale: 2
767
+ grid-columns-max: 4
768
+ childs:
769
+ - kind: WORKFLOW
770
+ desc: >
771
+ A single workflow, named with a short (2-5 word) summary phrased as the outcome
772
+ pursued (e.g. `Run Broadcast Event`) and described in a concise (1-3 sentence)
773
+ paragraph at a glance, plus a 1-sentence rationale ("why") stating the value the
774
+ organization gains. A workflow is a flat control flow of `ACTIVITY`
775
+ objects (the work done by one party at a time) connected by `HANDOFF` objects (the
776
+ passing of control from one activity to the next): exactly one initial activity,
777
+ at least one final activity, every activity reachable from the initial one, and
778
+ some final activity reachable from every activity, while a handoff back to an
779
+ earlier activity (a rework loop) is permitted.
780
+
781
+ The workflow is at summary level, above the user-goal level of the Use Cases: it
782
+ spans several actors and several sittings, and its activities leave the
783
+ step-by-step interaction with the solution to the use cases referencing them.
784
+ automaton:
785
+ nodes: ACTIVITY
786
+ edges: HANDOFF
787
+ source: FROM
788
+ target: TO
789
+ initial: INITIAL
790
+ final: FINAL
791
+ diagram:
792
+ type: graph
793
+ edges: "[[REQS:DW.WORKFLOW:*.HANDOFF:*]]"
794
+ edgeSource: FROM
795
+ edgeTarget: TO
796
+ onlyConnected: true
797
+ properties:
798
+ - ACTOR
799
+ config:
800
+ size-node-width-max: 440
801
+ props:
802
+ - name: ACTORS
803
+ desc: >
804
+ Comma-separated references to the User Personas objects taking part in the
805
+ workflow, in the order of their first appearance, so that every `ACTOR` of
806
+ an activity is listed here.
807
+ value: list([[REQS:UP.PERSONA:*]])
808
+ - name: OWNER
809
+ desc: >
810
+ Reference to the User Personas object (usually a `Stakeholder`) accountable
811
+ for the workflow as a whole, i.e. for its outcome and its rules, as opposed
812
+ to the actors performing its activities.
813
+ value: "[[REQS:UP.PERSONA:*]]"
814
+ optional: true
815
+ - name: TRIGGER
816
+ desc: >
817
+ The event that starts the workflow, stated as a 1-sentence
818
+ occurrence (e.g. `A manager decides to hold a broadcast event.`).
819
+ - name: OUTCOME
820
+ desc: >
821
+ The result that holds once the workflow has reached a final
822
+ activity (e.g. `The event took place and its results are archived.`).
823
+ - name: JOURNEYS
824
+ desc: >
825
+ Comma-separated references to the User Journey objects the workflow spans,
826
+ i.e. the per-persona experiences of which the workflow is the cross-persona
827
+ counterpart.
828
+ value: list([[REQS:UJ.JOURNEY:*]])
829
+ optional: true
830
+ - name: TERMS
831
+ desc: >
832
+ Comma-separated references to the GLOSSARY terms of type `Activity` the
833
+ workflow realizes, anchoring it in the ubiquitous language.
834
+ value: list([[REQS:GL.TERM:*]])
835
+ optional: true
836
+ - name: RULES
837
+ desc: >
838
+ Comma-separated references to the DOMAIN-RULES objects governing the
839
+ workflow as a whole (e.g. a deadline or an approval policy), while a rule
840
+ checked at a single handoff is referenced from the handoff instead.
841
+ value: list([[REQS:DR.RULE:*]])
842
+ optional: true
843
+ childs:
844
+ - kind: ACTIVITY
845
+ desc: >
846
+ A single unit of work within the workflow, performed by one party without a
847
+ handoff in between, named with a short (2-5 word) verb phrase (e.g. `Invite
848
+ Attendees`) and described by a 1-2 sentence description of what is done and
849
+ what it yields. Every activity used in a handoff *MUST* be declared, every
850
+ activity *MUST* be reachable from the initial one, and every activity with
851
+ no outgoing handoff *MUST* be final.
852
+ format:
853
+ maxTableColumns: 5
854
+ props:
855
+ - name: ACTOR
856
+ desc: >
857
+ Reference to the User Personas object performing the activity, or
858
+ `System` for an activity the solution performs on its own (e.g.
859
+ sending the invitations) or `Time` for a waiting period ending with
860
+ a deadline; several parties are given only for an activity they
861
+ perform jointly, as a change of the acting party is a handoff.
862
+ value: list([[REQS:UP.PERSONA:*]], enum(System,Time))
863
+ - name: INITIAL
864
+ desc: >
865
+ Whether the activity is the initial one, i.e. the single activity
866
+ the `TRIGGER` of the workflow starts (exactly one per workflow).
867
+ value: /^(?:true|false)$/
868
+ unique: enum(true)
869
+ present: enum(true)
870
+ optional: true
871
+ - name: FINAL
872
+ desc: >
873
+ Whether the activity is a final one, i.e. one in which the workflow
874
+ may legally end with its `OUTCOME` (at least one per workflow).
875
+ value: /^(?:true|false)$/
876
+ present: enum(true)
877
+ optional: true
878
+ - kind: HANDOFF
879
+ name: "[a-z][a-z-]*"
880
+ desc: >
881
+ A single passing of control from one activity to the next, named with a
882
+ short, lower-cased verb of the completing event (e.g. `approve`, `publish`)
883
+ and described by a 1-sentence description of what is passed on
884
+ (information, artifact, or notification) and how the receiving party learns
885
+ about it. Several handoffs departing from the same activity form a decision
886
+ (told apart by their `CONDITION`) or a parallel split, several arriving at
887
+ the same activity a merge, and a handoff back to an earlier activity a
888
+ rework loop.
889
+ format:
890
+ maxTableColumns: 6
891
+ props:
892
+ - name: FROM
893
+ desc: The activity (of the same workflow) the handoff departs from.
894
+ value: "[[REQS:DW.WORKFLOW:*.ACTIVITY:*]]"
895
+ local: true
896
+ - name: TO
897
+ desc: The activity (of the same workflow) the handoff arrives at.
898
+ value: "[[REQS:DW.WORKFLOW:*.ACTIVITY:*]]"
899
+ local: true
900
+ - name: CONDITION
901
+ desc: >
902
+ The condition under which the handoff is taken when several
903
+ handoffs depart from the same activity, stated as a 1-sentence
904
+ statement of what has to hold (e.g. `The rehearsal revealed
905
+ defects.`); omitted for an unconditional handoff.
906
+ optional: true
907
+ - name: RULES
908
+ desc: >
909
+ Comma-separated references to the DOMAIN-RULES objects the
910
+ handoff enforces, usually through its `CONDITION`.
911
+ value: list([[REQS:DR.RULE:*]])
912
+ optional: true
913
+
914
+ - kind: REQS
915
+ name: Use Cases
916
+ id: UC
917
+ file: 10-REQS-UC-Use-Cases.md
918
+ desc: >
919
+ The discrete goals users pursue with the solution, each describing an actor's interaction to
920
+ achieve a specific outcome, together with the concrete step-by-step flows for main,
921
+ alternative, and exceptional paths.
922
+ refs: >
923
+ - Cockburn: Writing Effective Use Cases (2001),
924
+ https://www.informit.com/store/writing-effective-use-cases-9780201702255
925
+ - Jacobson et al.: Object-Oriented Software Engineering: A Use Case Driven Approach (1992),
926
+ https://www.informit.com/store/object-oriented-software-engineering-a-use-case-driven-9780201544350
927
+ - Jacobson/Spence/Bittner: Use-Case 2.0: The Guide to Succeeding with Use Cases (2011),
928
+ https://www.ivarjacobson.com/publications/white-papers/use-case-20-e-book
929
+ diagram:
930
+ type: grid
931
+ nodes: "[[REQS:UC.USE-CASE:*]]"
932
+ config:
933
+ size-node-height-scale: 4
934
+ grid-columns-max: 4
935
+ childs:
936
+ - kind: USE-CASE
937
+ desc: >
938
+ A discrete goal a user pursues with the solution, named with a short (3-8 word)
939
+ summary phrased as an actor goal (e.g. `Reset Forgotten Password`) and described in
940
+ a concise (1-3 sentence) paragraph at a glance, plus a 1-sentence rationale ("why")
941
+ stating the value the actor gains, without prescribing the step-by-step flow, which
942
+ belongs to its `SCENARIO` objects: exactly one `Main` scenario, listed first,
943
+ followed by any number of `Alternative` and `Exceptional` scenarios.
944
+
945
+ The use case is at user-goal level: a goal the actor completes in one sitting,
946
+ neither a summary of many sittings and actors (which belongs to a Domain Workflow
947
+ as a whole, or to a User Journey when seen by a single persona) nor a single
948
+ interaction (which belongs to a scenario as one of its steps).
949
+ diagram:
950
+ type: hub
951
+ center: self
952
+ nodes: "[[REQS:UC.USE-CASE:*]], [[REQS:UP.PERSONA:*]], [[REQS:UJ.JOURNEY:*.STEP:*]],
953
+ [[REQS:DW.WORKFLOW:*.ACTIVITY:*]], [[REQS:FR.REQUIREMENT:*]], [[REQS:DR.RULE:*]],
954
+ [[DATA:SM.LIFECYCLE:*.TRANSITION:*]]"
955
+ labeled: true
956
+ qualified: true
957
+ config:
958
+ size-node-width-max: 440
959
+ size-node-height-scale: 1.75
960
+ props:
961
+ - name: ACTOR
962
+ desc: >
963
+ Reference to the PERSONAS object denoting the primary actor pursuing the
964
+ goal.
965
+ value: "[[REQS:UP.PERSONA:*]]"
966
+ - name: JOURNEYS
967
+ desc: >
968
+ Comma-separated references to the User Journey STEP objects the use case
969
+ covers, tracing the journey into the use cases.
970
+ value: list([[REQS:UJ.JOURNEY:*.STEP:*]])
971
+ optional: true
972
+ - name: ACTIVITIES
973
+ desc: >
974
+ Comma-separated references to the Domain Workflow ACTIVITY objects within
975
+ which the actor performs the use case, tracing the workflow into the use
976
+ cases; omitted for a use case outside any workflow.
977
+ value: list([[REQS:DW.WORKFLOW:*.ACTIVITY:*]])
978
+ optional: true
979
+ - name: REQUIREMENTS
980
+ desc: >
981
+ Comma-separated references to the FUNCTIONAL-REQUIREMENTS objects the use
982
+ case exercises, i.e. whose behavior its scenarios walk through, so that every
983
+ Functional Requirement is exercised by at least one use case.
984
+ value: list([[REQS:FR.*]])
985
+ optional: true
986
+ - name: RULES
987
+ desc: >
988
+ Comma-separated references to the DOMAIN-RULES objects the scenarios of
989
+ the use case apply, i.e. whose condition a scenario step checks or enforces
990
+ (e.g. an access rule in an authentication step).
991
+ value: list([[REQS:DR.RULE:*]])
992
+ optional: true
993
+ - name: TRANSITIONS
994
+ desc: >
995
+ Comma-separated references to the STATE-MODEL transition objects the
996
+ scenarios of the use case trigger, i.e. whose state change a scenario
997
+ step causes, so that every transition is exercised by at least one use
998
+ case or test case.
999
+ value: list([[DATA:SM.LIFECYCLE:*.TRANSITION:*]])
1000
+ optional: true
1001
+ - name: INCLUDES
1002
+ desc: >
1003
+ Comma-separated references to the other USE-CASES objects this use case
1004
+ includes as sub-flows, i.e. whose entire flow one of its scenario steps
1005
+ invokes (e.g. `The attendee authenticates ([[USE-CASE:authenticate]]).`),
1006
+ factoring a flow shared by several use cases out into a use case of its own
1007
+ instead of restating its steps.
1008
+ value: list([[REQS:UC.USE-CASE:*]])
1009
+ optional: true
1010
+ acyclic: true
1011
+ - name: PRE-CONDITION
1012
+ desc: >
1013
+ The condition that must hold before the use case can begin.
1014
+ optional: true
1015
+ - name: TRIGGER
1016
+ desc: >
1017
+ The event that starts the use case, stated as a 1-sentence occurrence (e.g.
1018
+ `The attendee opens the event URL.`), as opposed to the `PRE-CONDITION`
1019
+ which is a state that has to hold, and matching the `When <trigger>` of the
1020
+ event-driven Functional Requirements the use case exercises.
1021
+ optional: true
1022
+ - name: POST-CONDITION
1023
+ desc: >
1024
+ The condition that holds after the use case completes successfully.
1025
+ optional: true
1026
+ childs:
1027
+ - kind: SCENARIO
1028
+ desc: >
1029
+ A concrete step-by-step flow of the use case, named with a short (3-8 word)
1030
+ summary and comprised of sequentially numbered, imperative steps, each
1031
+ naming the acting party (actor or system) and the action taken (e.g. `The
1032
+ user submits their credentials.`). The steps describe the intent and the
1033
+ information exchanged between actor and system, not the user interface
1034
+ (dialogs, screens, buttons, and the like), which belongs to the Dialog
1035
+ Patterns and the Dialog Storyboard instead.
1036
+ props:
1037
+ - name: TYPE
1038
+ desc: >
1039
+ The path the scenario represents: `Main` (the primary, happy-path
1040
+ flow, exactly one per use case), `Alternative` (a valid but
1041
+ secondary flow), or `Exceptional` (an error or failure-handling
1042
+ flow).
1043
+ value: enum(Main,Alternative,Exceptional)
1044
+ unique: enum(Main)
1045
+ present: enum(Main)
1046
+ - name: RESULT
1047
+ desc: >
1048
+ How an `Alternative` or `Exceptional` scenario ends: `Success` (the
1049
+ goal is reached, possibly in an end state differing from the `Main`
1050
+ scenario), `Failure` (the goal is abandoned), or `Resume` (the flow
1051
+ returns to the `Main` scenario at the step named in the `OUTCOME`),
1052
+ omitted on the `Main` scenario, which ends in the `POST-CONDITION`
1053
+ of the use case.
1054
+ value: enum(Success,Failure,Resume)
1055
+ optional: true
1056
+ - name: AT-MAIN-STEP
1057
+ desc: >
1058
+ The number of the step of the `Main` scenario at which an
1059
+ `Alternative` or `Exceptional` scenario branches off: the scenario
1060
+ shares the preceding steps of the `Main` scenario instead of
1061
+ restating them, and its own steps, numbered from this number on,
1062
+ replace the remaining ones (not applicable to the `Main` scenario
1063
+ itself).
1064
+ value: /^[1-9][0-9]*$/
1065
+ optional: true
1066
+ - name: OUTCOME
1067
+ desc: >
1068
+ The condition that holds when an `Alternative` or `Exceptional`
1069
+ scenario ends, stated like a post-condition and replacing the
1070
+ `POST-CONDITION` of the use case for this scenario (naming the
1071
+ `Main` step at which the flow continues in case of `Resume`),
1072
+ omitted on the `Main` scenario.
1073
+ optional: true
1074
+
1075
+ - kind: DATA
268
1076
  name: Data Model
269
1077
  id: DM
270
- file: SPEC-07-DM-Data-Model.md
1078
+ file: 11-DATA-DM-Data-Model.md
271
1079
  desc: >
272
1080
  The structure of named entities, with named attributes and directed relationships, of the
273
1081
  data the solution manages, defining how information is organized and connected.
1082
+ refs: >
1083
+ - Chen: The Entity-Relationship Model -- Toward a Unified View of Data (1976),
1084
+ https://dl.acm.org/doi/10.1145/320434.320440
1085
+ - OMG UML 2.5.1: Unified Modeling Language (2017),
1086
+ https://www.omg.org/spec/UML/2.5.1
274
1087
  diagram:
275
1088
  type: graph
276
- nodes: "[[SPEC:DM.ENTITY:*]]"
277
- edges: "[[SPEC:DM.ENTITY:*.RELATION:*]]"
1089
+ nodes: "[[DATA:DM.ENTITY:*]]"
1090
+ edges: "[[DATA:DM.ENTITY:*.RELATION:*]]"
278
1091
  childs:
279
1092
  - kind: ENTITY
280
1093
  name: "[A-Z][a-zA-Z0-9]*"
@@ -285,10 +1098,25 @@
285
1098
  diagram:
286
1099
  type: hub
287
1100
  center: self
288
- nodes: "[[SPEC:DM.ENTITY:*]]"
289
- edges: "[[SPEC:DM.ENTITY:*.RELATION:*]]"
1101
+ nodes: "[[DATA:DM.ENTITY:*]]"
1102
+ edges: "[[DATA:DM.ENTITY:*.RELATION:*]]"
290
1103
  config:
291
1104
  size-node-width-max: 440
1105
+ props:
1106
+ - name: REQUIREMENTS
1107
+ desc: >
1108
+ Comma-separated references to the FUNCTIONAL-REQUIREMENTS objects the
1109
+ entity supports, i.e. whose behavior needs the information it carries,
1110
+ tracing the requirements into the data model.
1111
+ value: list([[REQS:FR.*]])
1112
+ optional: true
1113
+ - name: TERMS
1114
+ desc: >
1115
+ Comma-separated references to the GLOSSARY terms the entity materializes,
1116
+ i.e. the domain terms whose information it carries, so that every entity
1117
+ is anchored in the ubiquitous language and every term shows its data.
1118
+ value: list([[REQS:GL.TERM:*]])
1119
+ optional: true
292
1120
  childs:
293
1121
  - kind: ATTRIBUTE
294
1122
  name: "[a-z][a-zA-Z0-9]*"
@@ -296,65 +1124,129 @@
296
1124
  A named attribute of the entity, carrying a camel-cased, 1-3 word long,
297
1125
  per-entity unique identifier, and described by a 1-sentence description
298
1126
  ("what") plus a 1-sentence rationale ("why").
1127
+ format:
1128
+ maxTableColumns: 6
299
1129
  props:
300
1130
  - name: TYPE
301
1131
  desc: >
302
- The type of the entity attribute, one of `boolean`, `string`,
303
- `integer`, `float`, `uuid`, `bytes`, `date`, `time`, `datetime`, or
304
- `enum(XXX,YYY[,...])`, optionally prefixed with the qualifier
305
- `unique` to indicate inclusion into the primary key of the entity,
306
- and optionally suffixed with `?` to indicate an optional (nullable)
307
- value.
308
- value: /^(?:unique\s+)?(?:boolean|string|integer|float|uuid|bytes|date|time|datetime|enum\((?:[A-Za-z0-9_]+)(?:,\s*[A-Za-z0-9_]+)*\))(?:\?)?$/
1132
+ The type of the entity attribute, one of `boolean`, `string`
1133
+ (short single-line text), `text` (long free-form text), `integer`,
1134
+ `float` (approximate), `decimal` (exact, e.g. for money), `uuid`,
1135
+ `bytes`, `date`, `time`, `datetime`, `duration` (time span), or
1136
+ `enum(XXX,YYY[,...])`, optionally prefixed with the qualifier `key`
1137
+ to indicate inclusion into the primary key of the entity or `unique`
1138
+ to indicate an alternate uniqueness constraint, or optionally
1139
+ suffixed with `?` to indicate an optional (nullable) value, where a
1140
+ `key` or `unique` attribute cannot be optional.
1141
+ value: /^(?!(?:key|unique)\s.*\?$)(?:(?:key|unique)\s+)?(?:boolean|string|text|integer|float|decimal|uuid|bytes|date|time|datetime|duration|enum\((?:[A-Za-z0-9_]+)(?:,\s*[A-Za-z0-9_]+)*\))(?:\?)?$/
309
1142
  - name: DEFAULT
310
1143
  desc: The default value of the entity attribute.
311
1144
  value: /.*/
312
1145
  optional: true
1146
+ - name: CONSTRAINT
1147
+ desc: >
1148
+ The constraint on the value of the entity attribute beyond its type,
1149
+ as a short phrase stating a range, unit, pattern, or invariant (e.g.
1150
+ `1..60 seconds`, `RFC 5322 address`, `not before begin`).
1151
+ value: /.+/
1152
+ optional: true
1153
+ - name: CLASSIFICATION
1154
+ desc: >
1155
+ The sensitivity classification of the entity attribute value:
1156
+ `Public` for a value disclosable to anyone, `Internal` for a value
1157
+ disclosable within the operating organization only, `Confidential`
1158
+ for a value disclosable to explicitly authorized persons only (e.g. a
1159
+ secret or credential), or `Personal` for a value identifying or
1160
+ relating to a natural person and hence subject to data protection
1161
+ law (e.g. GDPR); defaults to `Internal`.
1162
+ value: enum(Public,Internal,Confidential,Personal)
1163
+ optional: true
1164
+ - name: RETENTION
1165
+ desc: >
1166
+ The retention of the entity attribute value, as a short phrase
1167
+ stating the duration or the triggering event beyond which the value
1168
+ is deleted or anonymized (e.g. `30 days after creation`, `until
1169
+ event finish`, `until account deletion`); expected on every
1170
+ `Personal` classified attribute (GDPR Art. 5(1)(e), storage
1171
+ limitation) and on every `Confidential` classified one, while an
1172
+ absent retention means the value is kept as long as the entity
1173
+ exists.
1174
+ value: /.+/
1175
+ optional: true
313
1176
  - kind: RELATION
314
1177
  name: "[a-z][a-zA-Z0-9]*"
315
1178
  desc: >
316
1179
  A named directed relation of the entity, carrying a camel-cased, 1-3 word
317
1180
  long, per-entity unique identifier and targeting another entity, and
318
1181
  described by a 1-sentence description ("what") plus a 1-sentence rationale
319
- ("why").
1182
+ ("why"). A relation carries no attributes of its own: a relation needing
1183
+ attributes (an "association class") is reified as an entity of its own,
1184
+ related from both sides.
320
1185
  optional: true
321
1186
  props:
322
- - name: TYPE
1187
+ - name: TARGET
323
1188
  desc: Reference to the DATA-MODEL entity the directed relation targets.
324
- value: "[[SPEC:DM.ENTITY:*]]"
1189
+ value: "[[DATA:DM.ENTITY:*]]"
1190
+ - name: KIND
1191
+ desc: >
1192
+ The kind of the directed relation: `association` for a plain
1193
+ reference to an independent target entity, `aggregation` for a
1194
+ shared part-of relation whose target outlives the entity, or
1195
+ `composition` for an exclusive part-of relation whose target is
1196
+ owned by and deleted with the entity; defaults to `association`.
1197
+ value: enum(association,aggregation,composition)
1198
+ optional: true
325
1199
  - name: ARITY
326
1200
  desc: >
327
1201
  The arity (cardinality) of the relation at the target entity: `0..1`
328
1202
  or `?` for zero or one ("optional"), `1` for exactly one
329
1203
  ("mandatory"), `0..n` or `*` for zero or more, `1..n` or `+` for one
330
- or more, or `{n}`/`{n,m}` for an exact number or range.
331
- value: /^(?:\?|\*|\+|\{\d+(?:,\d+)?\}|1|0\.\.1|0\.\.n|1\.\.n)$/
1204
+ or more, or `{n}`/`{n,m}` for an exact number or range; defaults to
1205
+ `1`.
1206
+ value: /^(?:\?|\*|\+|\{\d+(?:,\d+)?\}|1|0\.\.1|0\.\.n|1\.\.n|\d+\.\.\d+)$/
332
1207
  optional: true
333
1208
 
334
- - kind: SPEC
1209
+ - kind: DATA
335
1210
  name: State Model
336
1211
  id: SM
337
- file: SPEC-08-SM-State-Model.md
1212
+ file: 12-DATA-SM-State-Model.md
338
1213
  desc: >
339
1214
  For each entity with a non-trivial lifecycle, the legal states it can occupy and the
340
1215
  permitted transitions between them over its lifetime, making the forbidden moves as explicit
341
1216
  as the allowed ones.
1217
+ refs: >
1218
+ - Shlaer/Mellor: Object Lifecycles: Modeling the World in States (1992)
1219
+ - Harel: Statecharts: A Visual Formalism for Complex Systems (1987),
1220
+ https://doi.org/10.1016/0167-6423(87)90035-9
1221
+ - OMG UML 2.5.1: Unified Modeling Language (2017),
1222
+ https://www.omg.org/spec/UML/2.5.1
342
1223
  diagram:
343
1224
  type: grid
344
- nodes: "[[SPEC:SM.LIFECYCLE:*]]"
1225
+ nodes: "[[DATA:SM.LIFECYCLE:*]]"
345
1226
  properties:
346
1227
  - ENTITY
347
1228
  config:
348
1229
  size-node-width-max: 440
1230
+ size-node-height-scale: 2
349
1231
  grid-columns-max: 5
350
1232
  childs:
351
1233
  - kind: LIFECYCLE
352
1234
  desc: >
353
1235
  The lifecycle of a single entity, named with the short (1-3 word) name of the
354
- lifecycle, normally the name of the entity it governs.
1236
+ lifecycle, normally the name of the entity it governs. A lifecycle is a flat finite
1237
+ state machine: exactly one initial state, at least one final state, every state
1238
+ reachable from the initial state, and some final state reachable from every state
1239
+ (a state from which no final state can be reached anymore is a livelock).
1240
+ automaton:
1241
+ nodes: STATE
1242
+ edges: TRANSITION
1243
+ source: FROM
1244
+ target: TO
1245
+ initial: INITIAL
1246
+ final: FINAL
355
1247
  diagram:
356
1248
  type: graph
357
- edges: "[[SPEC:SM.LIFECYCLE:*.TRANSITION:*]]"
1249
+ edges: "[[DATA:SM.LIFECYCLE:*.TRANSITION:*]]"
358
1250
  edgeSource: FROM
359
1251
  edgeTarget: TO
360
1252
  onlyConnected: true
@@ -366,8 +1258,10 @@
366
1258
  props:
367
1259
  - name: ENTITY
368
1260
  desc: >
369
- Reference to the DATA-MODEL entity whose lifecycle this models.
370
- value: "[[SPEC:DM.ENTITY:*]]"
1261
+ Reference to the DATA-MODEL entity whose lifecycle this models, at most one
1262
+ lifecycle per entity (an entity without a lifecycle has a trivial one).
1263
+ value: "[[DATA:DM.ENTITY:*]]"
1264
+ unique: true
371
1265
  childs:
372
1266
  - kind: STATE
373
1267
  name: "[A-Z][a-zA-Z0-9]*"
@@ -376,228 +1270,870 @@
376
1270
  per-lifecycle unique name (e.g. `Draft`, `Shipped`) and described by a
377
1271
  1-sentence description of what holds true in it.
378
1272
 
379
- Every state used in a transition *MUST* be declared, and every state with no
380
- outgoing transition *MUST* be final (a non-final state with no outgoing
381
- transition would be a stuck dead-end). The converse does *not* hold: a final
382
- state *MAY* still have outgoing transitions, modeling a resting state that
383
- can later be left again (e.g. a `Closed` state with a `reopen` transition
384
- back to `Active`). Thus the final states are a superset of, but not
385
- necessarily equal to, the states without outgoing transitions.
1273
+ Every state used in a transition *MUST* be declared, every state *MUST* be
1274
+ reachable from the initial state, and every state with no outgoing
1275
+ transition *MUST* be final (a non-final state with no outgoing transition
1276
+ would be a stuck dead-end). The converse does *not* hold: a final state
1277
+ *MAY* still have outgoing transitions, modeling a resting state that can
1278
+ later be left again (e.g. a `Closed` state with a `reopen` transition back
1279
+ to `Active`). Thus the final states are the "accepting" states of the
1280
+ automaton, a superset of, but not necessarily equal to, the states without
1281
+ outgoing transitions.
386
1282
  props:
387
1283
  - name: INITIAL
388
1284
  desc: >
389
1285
  Whether the state is the initial one, i.e. the single state every
390
- instance of the entity enters upon creation.
1286
+ instance of the entity enters upon creation (exactly one per
1287
+ lifecycle).
391
1288
  value: /^(?:true|false)$/
1289
+ unique: enum(true)
1290
+ present: enum(true)
392
1291
  optional: true
393
1292
  - name: FINAL
394
1293
  desc: >
395
1294
  Whether the state is a final one, i.e. a terminal state in which the
396
- entity may legally come to rest permanently.
1295
+ entity may legally come to rest permanently (at least one per
1296
+ lifecycle).
397
1297
  value: /^(?:true|false)$/
1298
+ present: enum(true)
398
1299
  optional: true
399
1300
  - kind: TRANSITION
400
- name: "[a-z]+"
1301
+ name: "[a-z][a-z-]*"
401
1302
  desc: >
402
1303
  A single permitted transition between two states, named with the short,
403
1304
  lower-cased verb of the triggering event or action (e.g. `submit`, `ship`,
404
1305
  `cancel`) and described by a 1-sentence description of its side effect
405
- ("what happens"), followed by a ", **WHEN** `<guard>`" clause stating the
406
- condition that must hold for the transition to be permitted. Any move not
407
- listed as a transition is implicitly forbidden.
1306
+ ("what happens"). The same verb *MAY* name several transitions departing
1307
+ from different states (told apart by their anchors), and a transition *MAY*
1308
+ arrive at the very state it departs from (an internal transition, e.g.
1309
+ `edit` on `Draft`). Any move not listed as a transition is implicitly
1310
+ forbidden.
1311
+ referenced:
1312
+ - "[[REQS:UC.USE-CASE:*]]"
1313
+ - "[[TEST:TC.TEST-CASE:*]]"
408
1314
  props:
409
1315
  - name: FROM
410
- desc: The state the transition departs from.
411
- value: "[[SPEC:SM.LIFECYCLE:*.STATE:*]]"
1316
+ desc: The state (of the same lifecycle) the transition departs from.
1317
+ value: "[[DATA:SM.LIFECYCLE:*.STATE:*]]"
1318
+ local: true
412
1319
  - name: TO
413
- desc: The state the transition arrives at.
414
- value: "[[SPEC:SM.LIFECYCLE:*.STATE:*]]"
1320
+ desc: The state (of the same lifecycle) the transition arrives at.
1321
+ value: "[[DATA:SM.LIFECYCLE:*.STATE:*]]"
1322
+ local: true
1323
+ - name: ACTOR
1324
+ desc: >
1325
+ Comma-separated references to the PERSONAS objects able to trigger
1326
+ the transition, and/or `System` for a transition the solution
1327
+ triggers on its own or `Time` for one triggered by the passing of
1328
+ time (e.g. an expiry); omitted when the trigger is irrelevant.
1329
+ value: list([[REQS:UP.PERSONA:*]], enum(System,Time))
1330
+ optional: true
1331
+ - name: GUARD
1332
+ desc: >
1333
+ The condition which, beyond being in the `FROM` state, has to be
1334
+ satisfied for the transition to be permitted, stated as a
1335
+ 1-sentence statement of what has to hold (e.g. `The order has at
1336
+ least one item.`); omitted when the `FROM` state alone permits it.
1337
+ optional: true
1338
+ - name: RULES
1339
+ desc: >
1340
+ Comma-separated references to the DOMAIN-RULES objects the
1341
+ transition enforces, usually through its `GUARD`.
1342
+ value: list([[REQS:DR.RULE:*]])
1343
+ optional: true
415
1344
 
416
- - kind: SPEC
417
- name: Glossary
418
- id: GL
419
- file: SPEC-09-GL-Glossary.md
1345
+ - kind: DATA
1346
+ name: Authorization Model
1347
+ id: AM
1348
+ file: 13-DATA-AM-Authorization-Model.md
420
1349
  desc: >
421
- The ubiquitous language of the domain, defining the meaning of each domain term in business
422
- language, together with its synonyms and the ambiguities to avoid, shared consistently
423
- across all Artifacts.
1350
+ The access rights of the solution, bundled into the roles a person acts in and stating for
1351
+ each role the operations it may perform on each entity, confined to the lifecycle states
1352
+ of the entity and to a further condition where necessary, so that "who may do what on
1353
+ which entity in which state" is answered in one place instead of being scattered over the
1354
+ actors of the state transitions, the actors of the use cases, and the prose of the domain
1355
+ rules. The model is closed: an operation not granted to a role is forbidden, exactly like
1356
+ a move not listed as a state transition.
1357
+ refs: >
1358
+ - Ferraiolo/Kuhn: Role-Based Access Controls, 15th National Computer Security Conference (1992),
1359
+ https://csrc.nist.gov/publications/detail/conference-paper/1992/10/13/role-based-access-controls
1360
+ - Sandhu/Coyne/Feinstein/Youman: Role-Based Access Control Models, IEEE Computer 29(2) (1996),
1361
+ https://doi.org/10.1109/2.485845
1362
+ - ANSI INCITS 359-2012: Information Technology -- Role Based Access Control (2012),
1363
+ https://csrc.nist.gov/projects/role-based-access-control
1364
+ - OASIS: eXtensible Access Control Markup Language (XACML) Version 3.0 (2013),
1365
+ https://docs.oasis-open.org/xacml/3.0/xacml-3.0-core-spec-os-en.html
424
1366
  diagram:
425
- type: grid
426
- nodes: "[[SPEC:GL.TERM:*]]"
1367
+ type: graph
1368
+ nodes: "[[DATA:AM.ROLE:*]], [[DATA:DM.ENTITY:*]]"
1369
+ edges: "[[DATA:AM.ROLE:*.PERMISSION:*]]"
1370
+ edgeTarget: ENTITY
1371
+ onlyConnected: true
1372
+ qualified: true
427
1373
  config:
428
1374
  size-node-width-max: 440
429
- grid-columns-max: 5
430
1375
  childs:
431
- - kind: TERM
1376
+ - kind: ROLE
432
1377
  desc: >
433
- A single domain term, named with its canonical, preferred form (capitalized as it
434
- should appear in all artifacts) and defined in a concise (1-3 sentence) paragraph in
435
- business language, independent of any implementation, referencing other terms by
436
- their name where helpful.
1378
+ A single role, named with the canonical name of the domain role it grants (e.g.
1379
+ `Moderator`, matching its GLOSSARY term of type `Actor`) and described in a concise
1380
+ (1-2 sentence) paragraph by the responsibility the role carries, plus a 1-sentence
1381
+ rationale ("why") stating why the rights are bundled this way. A role is the unit
1382
+ in which rights are granted to a person: the personas embodying it hold exactly
1383
+ its `PERMISSION` objects (plus those of the roles it `INHERITS`), while a persona
1384
+ holding several roles holds the union of their permissions.
1385
+ diagram:
1386
+ type: hub
1387
+ center: self
1388
+ deep: true
1389
+ nodes: "[[DATA:AM.ROLE:*]], [[REQS:UP.PERSONA:*]], [[REQS:GL.TERM:*]], [[DATA:DM.ENTITY:*]],
1390
+ [[REQS:DR.RULE:*]]"
1391
+ labeled: true
1392
+ qualified: true
1393
+ config:
1394
+ size-node-width-max: 440
1395
+ size-node-height-scale: 1.75
437
1396
  props:
438
- - name: SYNONYMS
1397
+ - name: ACTORS
1398
+ desc: >
1399
+ Comma-separated references to the User Personas objects embodying the
1400
+ role, i.e. the personas acting with exactly its rights, so that every
1401
+ persona holds at least one role and its rights are stated here rather than
1402
+ implied by its `ROLE` description, and/or to the GLOSSARY terms of type
1403
+ `Actor` denoting the external systems holding the role (e.g. a registration
1404
+ system calling the machine-facing interface), as an external system is no
1405
+ persona.
1406
+ value: list([[REQS:UP.PERSONA:*]], [[REQS:GL.TERM:*]])
1407
+ - name: TERM
1408
+ desc: >
1409
+ Reference to the GLOSSARY term of type `Actor` the role grants, anchoring
1410
+ the role in the ubiquitous language.
1411
+ value: "[[REQS:GL.TERM:*]]"
1412
+ optional: true
1413
+ - name: INHERITS
1414
+ desc: >
1415
+ Comma-separated references to the other ROLE objects whose permissions
1416
+ this role holds in addition to its own (a role hierarchy, e.g. a manager
1417
+ inheriting the rights of a moderator), where an inherited permission is
1418
+ not restated.
1419
+ value: list([[DATA:AM.ROLE:*]])
1420
+ optional: true
1421
+ acyclic: true
1422
+ childs:
1423
+ - kind: PERMISSION
1424
+ desc: >
1425
+ A single right of the role on a single entity, named with a short (2-5
1426
+ word) verb phrase of what the role may do (e.g. `Decide Pending Messages`)
1427
+ and described by a 1-sentence description of the right, in particular of
1428
+ the reach of its `CONDITION`. One permission covers one entity: the
1429
+ operations it grants, the states of the entity in which they are granted,
1430
+ and the condition under which they are granted, so that the permissions
1431
+ of all roles form the access matrix of roles against entities. Any
1432
+ operation, state, or condition not covered by a permission of the role (or
1433
+ of an inherited one) is forbidden.
1434
+ format:
1435
+ maxTableColumns: 7
1436
+ props:
1437
+ - name: ENTITY
1438
+ desc: Reference to the DATA-MODEL entity the permission is granted on.
1439
+ value: "[[DATA:DM.ENTITY:*]]"
1440
+ - name: OPERATIONS
1441
+ desc: >
1442
+ Comma-separated operations the role may perform on the entity: the
1443
+ generic `Create`, `Read`, `Update`, and `Delete`, and/or references
1444
+ to the STATE-MODEL transitions of the entity the role may trigger
1445
+ (a state change is not an `Update`: it is granted by its transition
1446
+ only), where every persona named as `ACTOR` of a transition holds
1447
+ a role granting it.
1448
+ value: list(enum(Create,Read,Update,Delete), [[DATA:SM.LIFECYCLE:*.TRANSITION:*]])
1449
+ - name: STATES
1450
+ desc: >
1451
+ Comma-separated references to the STATE-MODEL states of the entity
1452
+ in which the operations are granted (`Create` needs none, as a
1453
+ creation enters the initial state); omitted when granted in every
1454
+ state or when the entity has no lifecycle.
1455
+ value: list([[DATA:SM.LIFECYCLE:*.STATE:*]])
1456
+ optional: true
1457
+ - name: CONDITION
1458
+ desc: >
1459
+ The condition which, beyond the role and the `STATES`, has to hold
1460
+ for the operations to be granted, stated as a 1-sentence statement
1461
+ of what has to hold, typically the ownership of the instance (e.g.
1462
+ `The attendee is the sender of the message.`), a confinement to
1463
+ certain attributes (e.g. `The update is confined to the presenter
1464
+ alert.`), or a configuration of the surrounding entity; omitted
1465
+ when the role and the states alone grant the operations.
1466
+ optional: true
1467
+ - name: RULES
1468
+ desc: >
1469
+ Comma-separated references to the DOMAIN-RULES objects justifying
1470
+ or bounding the permission, i.e. the rules whose statement grants
1471
+ or limits the right.
1472
+ value: list([[REQS:DR.RULE:*]])
1473
+ optional: true
1474
+
1475
+ - kind: APIS
1476
+ name: Interface Model
1477
+ id: IM
1478
+ file: 14-APIS-IM-Interface-Model.md
1479
+ desc: >
1480
+ The machine-facing interfaces the solution provides to, or requires from, other programs
1481
+ (REST, GraphQL, gRPC, WebSocket, MQTT, AMQP, MCP, CLI, library, or custom ones), each
1482
+ described by its kind, direction, location, and consumers, while the named types,
1483
+ constants, and endpoints of all interfaces are modeled generically in the
1484
+ INTERFACE-DATATYPES and INTERFACE-ENDPOINTS artifacts, whose objects reference the
1485
+ interfaces they belong to. The artifact is absent when the solution neither provides nor
1486
+ requires any machine-facing interface.
1487
+ optional: true
1488
+ refs: >
1489
+ - OpenAPI Initiative: OpenAPI Specification 3.1 (2021),
1490
+ https://spec.openapis.org/oas/v3.1.0
1491
+ - GraphQL Foundation: GraphQL Specification (2021),
1492
+ https://spec.graphql.org/October2021/
1493
+ - OASIS: MQTT Version 5.0 (2019),
1494
+ https://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html
1495
+ - Anthropic: Model Context Protocol Specification (2025),
1496
+ https://modelcontextprotocol.io/specification/
1497
+ - IEEE/The Open Group: POSIX.1-2024, Utility Conventions (2024),
1498
+ https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap12.html
1499
+ diagram:
1500
+ type: grid
1501
+ nodes: "[[APIS:IM.INTERFACE:*]]"
1502
+ properties:
1503
+ - KIND
1504
+ - DIRECTION
1505
+ childs:
1506
+ - kind: INTERFACE
1507
+ desc: >
1508
+ A single interface, named with a short (2-5 word) summary (e.g. `Public REST API`,
1509
+ `Event Topics`, `Command Line`) and described in a concise (1-3 sentence) paragraph
1510
+ by its purpose and its consumers, plus a 1-sentence rationale ("why") for the
1511
+ interface's existence and boundary. All kinds of interfaces share the same model:
1512
+ the INTERFACE-DATATYPES `TYPE` objects are the data shapes exchanged (carrying the
1513
+ fixed values agreed upon as their `CONSTANT` objects) and the INTERFACE-ENDPOINTS
1514
+ `ENDPOINT` objects the operations offered, each referencing the interfaces it
1515
+ belongs to, where the kind-specific parts (HTTP method, GraphQL operation, topic
1516
+ direction, command) are carried by the `OPERATION` and `LOCATOR` properties of the
1517
+ endpoints only.
1518
+ diagram:
1519
+ type: hub
1520
+ center: self
1521
+ nodes: "[[APIS:IM.INTERFACE:*]], [[APIS:ID.TYPE:*]], [[APIS:IE.ENDPOINT:*]]"
1522
+ labeled: true
1523
+ qualified: true
1524
+ config:
1525
+ size-node-width-max: 440
1526
+ props:
1527
+ - name: KIND
1528
+ desc: |
1529
+ The kind of the interface, one of:
1530
+ - `REST`: HTTP resources addressed by URL paths and HTTP methods.
1531
+ - `GraphQL`: A GraphQL schema of queries, mutations, and subscriptions.
1532
+ - `gRPC`: Protocol Buffers based remote procedure calls.
1533
+ - `WebSocket`: Messages exchanged over a WebSocket connection.
1534
+ - `MQTT`: Messages published to and subscribed from MQTT topics.
1535
+ - `MCP`: Tools, resources, and prompts of a Model Context Protocol server.
1536
+ - `CLI`: Commands, options, and arguments of a command-line program.
1537
+ - `Library`: Functions, methods, and classes of a programming language library.
1538
+ - `Custom`: Any other kind of interface, explained in the description.
1539
+ value: enum(REST,GraphQL,gRPC,WebSocket,MQTT,MCP,CLI,Library,Custom)
1540
+ - name: DIRECTION
1541
+ desc: >
1542
+ Whether the interface is `Provided` by the solution to its consumers or
1543
+ `Required` by the solution from an external system; defaults to `Provided`.
1544
+ value: enum(Provided,Required)
1545
+ optional: true
1546
+ - name: LOCATION
439
1547
  desc: >
440
- Comma-separated list of alternative names or abbreviations that refer to the
441
- same term but are *not* the preferred form.
1548
+ Where the interface is reached, depending on its `KIND`: the base URL
1549
+ (e.g. `https://api.example.com/v1`), the broker URL or topic prefix (e.g.
1550
+ `wss://broker.example.com/mqtt`, `event/`), the server name (MCP), the
1551
+ executable name (e.g. `specbook`), or the package or module name (e.g.
1552
+ `@rse/specbook`).
1553
+ - name: VERSION
1554
+ desc: The version of the interface contract (e.g. `1.2`, `2026-08`).
1555
+ optional: true
1556
+ - name: CONSUMERS
1557
+ desc: >
1558
+ Comma-separated references to the PERSONAS objects which use the interface
1559
+ (the external systems using it reference the interface from the
1560
+ CONTEXT-VIEW instead).
1561
+ value: list([[REQS:UP.PERSONA:*]])
442
1562
  optional: true
443
1563
 
444
- - kind: SPEC
445
- name: Use Cases
446
- id: UC
447
- file: SPEC-10-UC-Use-Cases.md
1564
+ - kind: APIS
1565
+ name: Interface Datatypes
1566
+ id: ID
1567
+ file: 15-APIS-ID-Interface-Datatypes.md
448
1568
  desc: >
449
- The discrete goals users pursue with the solution, each describing an actor's interaction to
450
- achieve a specific outcome, together with the concrete step-by-step flows for main,
451
- alternative, and exceptional paths.
1569
+ The named data types exchanged through the machine-facing interfaces of the INTERFACES
1570
+ artifact, modeled generically for all kinds of interfaces: a type is either an object
1571
+ type composed of fields or a scalar, enumeration, alias, or union type, carries the fixed
1572
+ values agreed upon as its constants, and references the interfaces it is exchanged
1573
+ through, so that one type serves several interfaces. The artifact is absent when the
1574
+ solution neither provides nor requires any machine-facing interface.
1575
+ optional: true
1576
+ refs: >
1577
+ - OpenAPI Initiative: OpenAPI Specification 3.1 (2021),
1578
+ https://spec.openapis.org/oas/v3.1.0
1579
+ - GraphQL Foundation: GraphQL Specification (2021),
1580
+ https://spec.graphql.org/October2021/
452
1581
  diagram:
453
- type: grid
454
- nodes: "[[SPEC:UC.USE-CASE:*]]"
1582
+ type: graph
1583
+ nodes: "[[APIS:ID.TYPE:*]]"
1584
+ deep: true
1585
+ onlyConnected: true
1586
+ qualified: true
1587
+ config:
1588
+ size-node-width-max: 440
455
1589
  childs:
456
- - kind: USE-CASE
1590
+ - kind: TYPE
1591
+ name: "[A-Z][A-Za-z0-9_]*"
457
1592
  desc: >
458
- A discrete goal a user pursues with the solution, named with a short (3-8 word)
459
- summary phrased as an actor goal (e.g. `Reset Forgotten Password`) and described in
460
- a concise (1-3 sentence) paragraph at a glance, without prescribing the step-by-step
461
- flow (which belongs to its `SCENARIO` objects).
1593
+ A named data type exchanged through one or more interfaces, carrying a
1594
+ Pascal-cased, unique name (e.g. `Event`, `ChatMessage`, `Diagnostic`) and
1595
+ described by a 1-sentence description ("what") plus a 1-sentence rationale
1596
+ ("why"). A type without a `BASE` is an object type composed of its `FIELD`
1597
+ objects (plus the fields of the object types it `EXTENDS`); a type with a
1598
+ `BASE` is a scalar, enumeration, alias, or union type without fields. Either
1599
+ kind of type additionally carries the named fixed values agreed upon through
1600
+ its interfaces as its `CONSTANT` objects.
1601
+ optional: true
462
1602
  diagram:
463
1603
  type: hub
464
1604
  center: self
465
- nodes: "[[SPEC:UC.USE-CASE:*]], [[SPEC:UP.PERSONA:*]], [[SPEC:FR.REQUIREMENT:*]]"
1605
+ nodes: "[[APIS:ID.TYPE:*]], [[APIS:IM.INTERFACE:*]]"
1606
+ deep: true
1607
+ labeled: true
466
1608
  qualified: true
467
1609
  config:
468
- size-node-width-max: 440
1610
+ size-node-width-max: 600
1611
+ size-node-height-scale: 1.75
469
1612
  props:
470
- - name: ACTOR
1613
+ - name: INTERFACES
471
1614
  desc: >
472
- Reference to the PERSONAS object denoting the primary actor pursuing the
473
- goal.
474
- value: "[[SPEC:UP.PERSONA:*]]"
475
- - name: REQUIREMENTS
1615
+ Comma-separated references to the INTERFACE-MODEL objects the type is
1616
+ exchanged through, i.e. the interfaces whose endpoints consume or return it,
1617
+ directly or through the fields of another type.
1618
+ value: list([[APIS:IM.INTERFACE:*]])
1619
+ - name: BASE
476
1620
  desc: >
477
- Comma-separated references to the FUNCTIONAL-REQUIREMENTS objects the use
478
- case realizes.
479
- value: list([[SPEC:FR.*]])
1621
+ The underlying type of a non-object (value) type: one of the primitives
1622
+ `boolean`, `string` (short single-line text), `text` (long
1623
+ free-form text), `integer`, `float` (approximate), `decimal`
1624
+ (exact, e.g. for money), `uuid`, `bytes`, `date`, `time`,
1625
+ `datetime`, `duration` (time span), or `any` (a named scalar), an
1626
+ enumeration `enum(XXX,YYY[,...])`, or a reference to another `TYPE`
1627
+ object (an alias), where several
1628
+ comma-separated alternatives form a named union type; omitted for
1629
+ an object type composed of fields.
1630
+ value: list([[APIS:ID.TYPE:*]], /^(?:boolean|string|text|integer|float|decimal|uuid|bytes|date|time|datetime|duration|any|enum\((?:[A-Za-z0-9_-]+)(?:,\s*[A-Za-z0-9_-]+)*\))$/)
480
1631
  optional: true
481
- - name: GOAL
482
- desc: >
483
- The 1-sentence statement of what the actor wants to achieve through this use
484
- case.
485
- - name: PRE-CONDITION
1632
+ - name: EXTENDS
486
1633
  desc: >
487
- The condition that must hold before the use case can begin.
1634
+ Comma-separated references to the object types whose fields this
1635
+ object type inherits in addition to its own, so its instances carry
1636
+ the fields of all of them (e.g. a message type extending a common
1637
+ envelope type, or a GraphQL type implementing interfaces), where an
1638
+ inherited field is not redeclared; omitted for a type carrying a
1639
+ `BASE`.
1640
+ value: list([[APIS:ID.TYPE:*]])
1641
+ acyclic: true
488
1642
  optional: true
489
- - name: POST-CONDITION
1643
+ - name: MATERIALIZES
490
1644
  desc: >
491
- The condition that holds after the use case completes successfully.
1645
+ Comma-separated references to the DATA-MODEL entities the type
1646
+ materializes (e.g. as a data transfer object carrying the
1647
+ attributes of one entity, or as a view flattening several
1648
+ entities), tracing the interface into the data model.
1649
+ value: list([[DATA:DM.ENTITY:*]])
492
1650
  optional: true
493
1651
  childs:
494
- - kind: SCENARIO
1652
+ - kind: FIELD
1653
+ name: "[A-Za-z_][A-Za-z0-9_-]*"
495
1654
  desc: >
496
- A concrete step-by-step flow of the use case, named with a short (3-8 word)
497
- summary and comprised of sequentially numbered, imperative steps, each
498
- naming the acting party (actor or system) and the action taken (e.g. `The
499
- user submits the login form.`).
1655
+ A named field of an object type, carrying a per-type unique
1656
+ identifier in the naming convention of the interface (e.g.
1657
+ `eventId`, `event_id`, `event-id`) and described by a 1-sentence
1658
+ description ("what") plus a 1-sentence rationale ("why").
1659
+ optional: true
1660
+ format:
1661
+ maxTableColumns: 5
500
1662
  props:
501
1663
  - name: TYPE
502
1664
  desc: >
503
- The path the scenario represents: `Main` (the primary, happy-path
504
- flow), `Alternative` (a valid but secondary flow), or `Exceptional`
505
- (an error or failure-handling flow).
506
- value: enum(Main,Alternative,Exceptional)
507
-
508
- - kind: SPEC
509
- name: Test Cases
510
- id: TC
511
- file: SPEC-11-TC-Test-Cases.md
1665
+ The type of the field: a reference to a `TYPE` object of
1666
+ the interface, one of the primitives `boolean`, `string`,
1667
+ `text`, `integer`, `float`, `decimal`, `uuid`, `bytes`,
1668
+ `date`, `time`, `datetime`, `duration`, or `any`, or an inline
1669
+ enumeration `enum(XXX,YYY[,...])` (a reusable one is a `TYPE`
1670
+ object with an `enum(...)` base), where several comma-separated
1671
+ alternatives form a union type.
1672
+ value: list([[APIS:ID.TYPE:*]], /^(?:boolean|string|text|integer|float|decimal|uuid|bytes|date|time|datetime|duration|any|enum\((?:[A-Za-z0-9_-]+)(?:,\s*[A-Za-z0-9_-]+)*\))$/)
1673
+ - name: ARITY
1674
+ desc: >
1675
+ The arity (cardinality) of the field value: `0..1` or `?`
1676
+ for zero or one ("optional"), `1` for exactly one
1677
+ ("mandatory"), `0..n` or `*` for zero or more, `1..n` or
1678
+ `+` for one or more, or `{n}`/`{n,m}` for an exact number
1679
+ or range; defaults to `1`.
1680
+ value: /^(?:\?|\*|\+|\{\d+(?:,\d+)?\}|1|0\.\.1|0\.\.n|1\.\.n|\d+\.\.\d+)$/
1681
+ optional: true
1682
+ - name: DEFAULT
1683
+ desc: The default value of the field.
1684
+ value: /.*/
1685
+ optional: true
1686
+ - name: CONSTRAINT
1687
+ desc: >
1688
+ The constraint on the value of the field beyond its type,
1689
+ as a short phrase stating a range, unit, pattern, or
1690
+ invariant (e.g. `1..100`, `RFC 5322 address`).
1691
+ value: /.+/
1692
+ optional: true
1693
+ - kind: CONSTANT
1694
+ name: "[A-Za-z_][A-Za-z0-9_-]*"
1695
+ desc: >
1696
+ A named fixed value of the type, agreed upon through the interfaces of
1697
+ the type, carrying a per-type unique identifier in the naming convention
1698
+ of the interfaces (e.g. `MAX_PAGE_SIZE`, `defaultPort`, `topic-prefix`)
1699
+ and described by a 1-sentence description ("what") plus a 1-sentence
1700
+ rationale ("why").
1701
+ optional: true
1702
+ format:
1703
+ maxTableColumns: 5
1704
+ props:
1705
+ - name: TYPE
1706
+ desc: >
1707
+ The value type of the constant, i.e. the type its literal `VALUE`
1708
+ is of: one of the primitives `boolean`, `string`, `text`,
1709
+ `integer`, `float`, `decimal`, `uuid`, `bytes`, `date`, `time`,
1710
+ `datetime`, `duration`, or `any`, an inline enumeration
1711
+ `enum(XXX,YYY[,...])`, or a reference to a non-object `TYPE`
1712
+ object (a scalar, enumeration, alias, or union
1713
+ type carrying a `BASE`); an object type composed of fields is no
1714
+ value type and hence not admitted, as a literal cannot express it.
1715
+ value: list([[APIS:ID.TYPE:*]], /^(?:boolean|string|text|integer|float|decimal|uuid|bytes|date|time|datetime|duration|any|enum\((?:[A-Za-z0-9_-]+)(?:,\s*[A-Za-z0-9_-]+)*\))$/)
1716
+ - name: VALUE
1717
+ desc: >
1718
+ The literal value of the constant (e.g. `100`, `event/`), matching
1719
+ its `TYPE`.
1720
+ value: /.+/
1721
+ - kind: APIS
1722
+ name: Interface Endpoints
1723
+ id: IE
1724
+ file: 16-APIS-IE-Interface-Endpoints.md
512
1725
  desc: >
513
- The verifiable conditions and steps used to confirm that requirements are correctly
514
- implemented, with mandatory defined inputs, mandatory expected outcomes, and optional pre-
515
- and post-conditions.
1726
+ The operations offered by the machine-facing interfaces of the INTERFACE-MODEL artifact,
1727
+ modeled generically for all kinds of interfaces: an endpoint references the interface it
1728
+ belongs to and consumes the INTERFACE-DATATYPES types and constants through its positional
1729
+ arguments and named options and returns them through its results. The artifact is absent
1730
+ when the solution neither provides nor requires any machine-facing interface.
1731
+ optional: true
1732
+ refs: >
1733
+ - OpenAPI Initiative: OpenAPI Specification 3.1 (2021),
1734
+ https://spec.openapis.org/oas/v3.1.0
1735
+ - GraphQL Foundation: GraphQL Specification (2021),
1736
+ https://spec.graphql.org/October2021/
1737
+ - OASIS: MQTT Version 5.0 (2019),
1738
+ https://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html
1739
+ - Anthropic: Model Context Protocol Specification (2025),
1740
+ https://modelcontextprotocol.io/specification/
1741
+ - IEEE/The Open Group: POSIX.1-2024, Utility Conventions (2024),
1742
+ https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap12.html
516
1743
  diagram:
517
- type: grid
518
- nodes: "[[SPEC:TC.TEST-CASE:*]]"
1744
+ type: graph
1745
+ nodes: "[[APIS:IE.ENDPOINT:*]], [[APIS:ID.TYPE:*]]"
1746
+ deep: true
1747
+ onlyConnected: true
1748
+ qualified: true
1749
+ config:
1750
+ size-node-width-max: 440
519
1751
  childs:
520
- - kind: TEST-CASE
1752
+ - kind: ENDPOINT
1753
+ name: "[A-Za-z_][A-Za-z0-9_-]*"
521
1754
  desc: >
522
- A single verifiable test case, named with a short (3-8 word) summary and defined by
523
- its mandatory input and expected outcome plus its optional pre- and post-conditions.
1755
+ A single operation of an interface, carrying a technical, unique name in the
1756
+ naming convention of its interface (e.g. `createEvent`, `chat_message`, `lint`)
1757
+ and described by a 1-sentence description ("what") plus a 1-sentence rationale
1758
+ ("why").
1759
+
1760
+ An endpoint consumes its input through its positional `ARGUMENT` objects
1761
+ (in document order, e.g. the URL path placeholders, a request body, a message
1762
+ payload, or the operands of a command) and its named `OPTION` objects (e.g. the
1763
+ query parameters, the arguments of a GraphQL field or MCP tool, or the
1764
+ options of a command), and returns its output through its `RESULT`
1765
+ objects (e.g. a response body, a subscription message, or the output and
1766
+ exit code of a command).
1767
+
1768
+ Endpoints form a flat list: a hierarchy of sub-commands or sub-resources
1769
+ is expressed by a path-style `LOCATOR` (e.g. `remote add`,
1770
+ `/events/{eventId}/chat`) only.
524
1771
  diagram:
525
1772
  type: hub
526
1773
  center: self
527
- nodes: "[[SPEC:TC.TEST-CASE:*]], [[SPEC:FR.REQUIREMENT:*]], [[SPEC:NR.REQUIREMENT:*]]"
1774
+ nodes: "[[APIS:IE.ENDPOINT:*]], [[APIS:ID.TYPE:*]], [[APIS:ID.TYPE:*.CONSTANT:*]], [[APIS:IM.INTERFACE:*]],
1775
+ [[DATA:AM.ROLE:*.PERMISSION:*]]"
1776
+ deep: true
1777
+ labeled: true
528
1778
  qualified: true
529
1779
  config:
530
- size-node-width-max: 440
1780
+ size-node-width-max: 600
1781
+ size-node-height-scale: 1.75
531
1782
  props:
532
- - name: VERIFIES
1783
+ - name: INTERFACE
1784
+ desc: The INTERFACES object the endpoint belongs to and is addressed within.
1785
+ value: "[[APIS:IM.INTERFACE:*]]"
1786
+ - name: PERMISSIONS
533
1787
  desc: >
534
- Reference to the FUNCTIONAL-REQUIREMENTS or NON-FUNCTIONAL-REQUIREMENTS
535
- object the test case verifies.
536
- value: "[[SPEC:*.REQUIREMENT:*]]"
537
- - name: PRE-CONDITION
1788
+ Comma-separated references to the AUTHORIZATION-MODEL permission objects
1789
+ the endpoint enforces, i.e. the rights (of a persona or an external system,
1790
+ through one of their roles) a caller has to hold for the endpoint to serve
1791
+ the operation, so that the authorization of every endpoint is stated
1792
+ rather than left to the implementation; omitted for an endpoint open to
1793
+ every caller.
1794
+ value: list([[DATA:AM.ROLE:*.PERMISSION:*]])
1795
+ optional: true
1796
+ - name: OPERATION
1797
+ desc: |
1798
+ The kind-specific operation the endpoint performs, one of:
1799
+ - `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD`, `OPTIONS`:
1800
+ the HTTP method (`REST`).
1801
+ - `query`, `mutation`, `subscription`: the GraphQL operation
1802
+ type (`GraphQL`).
1803
+ - `call`, `stream`: a unary or streaming remote procedure call
1804
+ (`gRPC`).
1805
+ - `publish`, `subscribe`: the message direction from the
1806
+ perspective of the interface consumer (`WebSocket`, `MQTT`,
1807
+ `AMQP`).
1808
+ - `tool`, `resource`, `prompt`: the MCP primitive (`MCP`).
1809
+ - `command`: a command or sub-command (`CLI`).
1810
+ - `function`, `method`, `constructor`, `event`: the callable or
1811
+ emitted member (`Library`).
1812
+ - `custom`: any other operation, explained in the description.
1813
+ value: enum(GET,POST,PUT,PATCH,DELETE,HEAD,OPTIONS,query,mutation,subscription,call,stream,publish,subscribe,tool,resource,prompt,command,function,method,constructor,event,custom)
1814
+ - name: LOCATOR
538
1815
  desc: >
539
- The state or setup that must hold before the test is executed.
1816
+ How the endpoint is addressed within its interface, depending on
1817
+ the `KIND` of the interface: the URL path with `{xxx}` placeholders (e.g.
1818
+ `/events/{eventId}/chat`), the GraphQL field name, the topic
1819
+ pattern (e.g. `event/{eventId}/chat`), the tool, resource, or
1820
+ prompt name, the command path of words (e.g. `specbook lint`),
1821
+ or the symbol (e.g. `SpecBook.lint`); defaults to the
1822
+ endpoint name.
1823
+ value: /.+/
540
1824
  optional: true
541
- - name: INPUT
1825
+ - name: USE-CASES
542
1826
  desc: >
543
- The mandatory, concrete input data or actions applied during the test.
544
- - name: EXPECTED
1827
+ Comma-separated references to the USE-CASES objects the endpoint
1828
+ realizes, tracing the requirements into the interface.
1829
+ value: list([[REQS:UC.USE-CASE:*]])
1830
+ optional: true
1831
+ childs:
1832
+ - kind: OPTION
1833
+ name: "-{0,2}[A-Za-z_][A-Za-z0-9_-]*"
545
1834
  desc: >
546
- The mandatory, concrete expected outcome or observable result that defines a
547
- passing test.
548
- - name: POST-CONDITION
1835
+ A named input of the endpoint, carrying a per-endpoint unique
1836
+ identifier in the syntax of the interface (e.g. `--output`,
1837
+ `first`, `file_path`) and described by a 1-sentence description
1838
+ ("what") plus a 1-sentence rationale ("why").
1839
+ optional: true
1840
+ format:
1841
+ maxTableColumns: 6
1842
+ props:
1843
+ - name: TYPE
1844
+ desc: >
1845
+ The type of the option: a reference to a `TYPE` object of
1846
+ the interface, one of the primitives `boolean`, `string`,
1847
+ `text`, `integer`, `float`, `decimal`, `uuid`, `bytes`,
1848
+ `date`, `time`, `datetime`, `duration`, or `any`, or an inline
1849
+ enumeration `enum(XXX,YYY[,...])` (a reusable one is a `TYPE`
1850
+ object with an `enum(...)` base), where several comma-separated
1851
+ alternatives form a union type.
1852
+ value: list([[APIS:ID.TYPE:*]], /^(?:boolean|string|text|integer|float|decimal|uuid|bytes|date|time|datetime|duration|any|enum\((?:[A-Za-z0-9_-]+)(?:,\s*[A-Za-z0-9_-]+)*\))$/)
1853
+ - name: ALIAS
1854
+ desc: >
1855
+ Comma-separated alternative names of the option in the
1856
+ syntax of the interface (e.g. `-o` for `--output`).
1857
+ value: /^-{0,2}[A-Za-z_][A-Za-z0-9_-]*(?:,\s*-{0,2}[A-Za-z_][A-Za-z0-9_-]*)*$/
1858
+ optional: true
1859
+ - name: ARITY
1860
+ desc: >
1861
+ The arity (cardinality) of the option:
1862
+ - `0..1` or `?` for zero or one ("optional", the default)
1863
+ - `1` for exactly one ("mandatory")
1864
+ - `0..n` or `*` for zero or more
1865
+ - `1..n` or `+` for one or more
1866
+ - `{X}` or `X` for an exact number X
1867
+ - `{X,Y}` or `X...Y` for a range from X to Y
1868
+ value: /^(?:\?|\*|\+|\{\d+(?:,\d+)?\}|1|0\.\.1|0\.\.n|1\.\.n|\d+|\d+\.\.\d+)$/
1869
+ optional: true
1870
+ - name: DEFAULT
1871
+ desc: The default value of the option (matching its type).
1872
+ value: /.*/
1873
+ optional: true
1874
+ - name: CONSTRAINT
1875
+ desc: >
1876
+ The constraint on the value of the option beyond its type,
1877
+ as a short phrase stating a range, unit, pattern, or
1878
+ invariant (e.g. `1..65535`, `readable directory`).
1879
+ value: /.+/
1880
+ optional: true
1881
+ - kind: ARGUMENT
1882
+ name: "[A-Za-z_][A-Za-z0-9_-]*"
1883
+ desc: >
1884
+ A positional input of the endpoint, in document order, carrying a
1885
+ per-endpoint unique identifier (e.g. `eventId`, `body`, `file`)
1886
+ and described by a 1-sentence description ("what") plus a
1887
+ 1-sentence rationale ("why").
1888
+ optional: true
1889
+ format:
1890
+ maxTableColumns: 6
1891
+ props:
1892
+ - name: TYPE
1893
+ desc: >
1894
+ The type of the argument: a reference to a `TYPE` object
1895
+ of the interface, one of the primitives `boolean`,
1896
+ `string`, `text`, `integer`, `float`, `decimal`, `uuid`,
1897
+ `bytes`, `date`, `time`, `datetime`, `duration`, or `any`, or an
1898
+ inline enumeration `enum(XXX,YYY[,...])` (a reusable one is a
1899
+ `TYPE` object with an `enum(...)` base), where several comma-separated
1900
+ alternatives form a union type.
1901
+ value: list([[APIS:ID.TYPE:*]], /^(?:boolean|string|text|integer|float|decimal|uuid|bytes|date|time|datetime|duration|any|enum\((?:[A-Za-z0-9_-]+)(?:,\s*[A-Za-z0-9_-]+)*\))$/)
1902
+ - name: ARITY
1903
+ desc: >
1904
+ The arity (cardinality) of the argument:
1905
+ - `0..1` or `?` for zero or one ("optional", the default)
1906
+ - `1` for exactly one ("mandatory")
1907
+ - `0..n` or `*` for zero or more
1908
+ - `1..n` or `+` for one or more
1909
+ - `{X}` or `X` for an exact number X
1910
+ - `{X,Y}` or `X...Y` for a range from X to Y
1911
+ value: /^(?:\?|\*|\+|\{\d+(?:,\d+)?\}|1|0\.\.1|0\.\.n|1\.\.n|\d+|\d+\.\.\d+)$/
1912
+ optional: true
1913
+ - name: DEFAULT
1914
+ desc: The default value of the argument (matching its type).
1915
+ value: /.*/
1916
+ optional: true
1917
+ - name: CONSTRAINT
1918
+ desc: >
1919
+ The constraint on the value of the argument beyond its
1920
+ type, as a short phrase stating a range, unit, pattern, or
1921
+ invariant (e.g. `existing file`, `1..100`).
1922
+ value: /.+/
1923
+ optional: true
1924
+ - kind: RESULT
1925
+ name: "[A-Za-z_][A-Za-z0-9_-]*"
549
1926
  desc: >
550
- The state that must hold after the test completes.
1927
+ A named output of the endpoint, carrying a per-endpoint unique
1928
+ identifier (e.g. `body`, `message`, `stdout`, `exit-code`) and
1929
+ described by a 1-sentence description ("what") plus a 1-sentence
1930
+ rationale ("why"). An error outcome is a result of its own (e.g.
1931
+ `error` with an HTTP status in its `CONSTRAINT`).
551
1932
  optional: true
1933
+ format:
1934
+ maxTableColumns: 5
1935
+ props:
1936
+ - name: TYPE
1937
+ desc: >
1938
+ The type of the result: a reference to a `TYPE` object of
1939
+ the interface, one of the primitives `boolean`, `string`,
1940
+ `text`, `integer`, `float`, `decimal`, `uuid`, `bytes`,
1941
+ `date`, `time`, `datetime`, `duration`, or `any`, or an inline
1942
+ enumeration `enum(XXX,YYY[,...])` (a reusable one is a `TYPE`
1943
+ object with an `enum(...)` base), where several comma-separated
1944
+ alternatives form a union type.
1945
+ value: list([[APIS:ID.TYPE:*]], /^(?:boolean|string|text|integer|float|decimal|uuid|bytes|date|time|datetime|duration|any|enum\((?:[A-Za-z0-9_-]+)(?:,\s*[A-Za-z0-9_-]+)*\))$/)
1946
+ - name: ARITY
1947
+ desc: >
1948
+ The arity (cardinality) of the result:
1949
+ - `0..1` or `?` for zero or one ("optional", the default)
1950
+ - `1` for exactly one ("mandatory")
1951
+ - `0..n` or `*` for zero or more
1952
+ - `1..n` or `+` for one or more
1953
+ - `{X}` or `X` for an exact number X
1954
+ - `{X,Y}` or `X...Y` for a range from X to Y
1955
+ value: /^(?:\?|\*|\+|\{\d+(?:,\d+)?\}|1|0\.\.1|0\.\.n|1\.\.n|\d+|\d+\.\.\d+)$/
1956
+ optional: true
1957
+ - name: CONSTRAINT
1958
+ desc: >
1959
+ The constraint on the value of the result beyond its type,
1960
+ as a short phrase stating a range, unit, pattern, or
1961
+ invariant (e.g. `HTTP 201`, `0 iff no diagnostics`).
1962
+ value: /.+/
1963
+ optional: true
552
1964
 
553
- - kind: SPEC
1965
+ - kind: UXUI
554
1966
  name: Interaction Concept
555
1967
  id: IC
556
- file: SPEC-12-IC-Interaction-Concept.md
1968
+ file: 17-UXUI-IC-Interaction-Concept.md
557
1969
  desc: >
558
- The overarching idea of how users interact with the solution, describing the intended
559
- workflows and interaction philosophy (e.g. auto-save behavior).
1970
+ The interaction philosophy of the solution, stated as the set of cross-cutting principles
1971
+ (e.g. auto-save instead of explicit saving) which govern how users interact with the
1972
+ solution and which the Dialog Patterns, Dialog Storyboard, and Visual Design have to obey,
1973
+ while the concrete workflows belong to the User Journey, Use Cases, and Dialog Storyboard.
1974
+ The principles are listed in decreasing precedence, so that whenever two principles
1975
+ conflict in a particular design decision, the earlier one wins.
1976
+ refs: >
1977
+ - ISO 9241-110:2020: Ergonomics of human-system interaction -- Part 110: Interaction principles (2020),
1978
+ https://www.iso.org/standard/75258.html
1979
+ - Nielsen: 10 Usability Heuristics for User Interface Design (1994),
1980
+ https://www.nngroup.com/articles/ten-usability-heuristics/
1981
+ - Shneiderman: The Eight Golden Rules of Interface Design (1987),
1982
+ https://www.cs.umd.edu/users/ben/goldenrules.html
1983
+ optional: true
1984
+ diagram:
1985
+ type: grid
1986
+ nodes: "[[UXUI:IC.PRINCIPLE:*]]"
1987
+ properties:
1988
+ - CATEGORY
1989
+ config:
1990
+ size-node-width-max: 440
1991
+ size-node-height-scale: 2
1992
+ grid-columns-max: 4
560
1993
  childs:
561
1994
  - kind: PRINCIPLE
562
1995
  desc: >
563
1996
  A single interaction principle, named with a short (2-5 word) summary (e.g.
564
1997
  `Auto-Save`, `Optimistic Updates`, `Undo over Confirm`) and described in a concise
565
1998
  (1-3 sentence) paragraph by how it governs the user's experience across the
566
- solution, plus a 1-sentence rationale ("why").
1999
+ solution, plus a 1-sentence rationale ("why"). A principle is solution-wide and
2000
+ independent of any particular screen or flow (a structure recurring within one flow
2001
+ is a Dialog Pattern instead), decides between design alternatives (the alternative
2002
+ it rejects is its `TRADE-OFF`), and is not verifiable by a metric (a measurable
2003
+ quality bound is a Non-Functional Requirement instead).
2004
+ referenced:
2005
+ - "[[UXUI:DP.PATTERN:*]]"
567
2006
  props:
568
2007
  - name: CATEGORY
569
- desc: The aspect of interaction the principle governs.
570
- value: enum(Onboarding,Navigation,Input,Feedback,Workflow,Personalization,Awareness,Resilience,Privacy)
2008
+ desc: >
2009
+ The interaction principle of ISO 9241-110:2020 the principle primarily
2010
+ promotes: `Task-Suitability` (suitability for the user's tasks),
2011
+ `Self-Descriptiveness`, `Expectation-Conformity` (conformity with user
2012
+ expectations), `Learnability`, `Controllability`, `Error-Robustness` (use
2013
+ error robustness), or `Engagement` (user engagement).
2014
+ value: enum(Task-Suitability,Self-Descriptiveness,Expectation-Conformity,Learnability,Controllability,Error-Robustness,Engagement)
2015
+ - name: ACTORS
2016
+ desc: >
2017
+ Comma-separated references to the User Personas objects whose experience
2018
+ the principle governs, omitted for a principle governing the experience of
2019
+ all users alike.
2020
+ value: list([[REQS:UP.PERSONA:*]])
2021
+ optional: true
2022
+ - name: MOTIVATED-BY
2023
+ desc: >
2024
+ Comma-separated references to the User Journey step objects whose
2025
+ `PAIN-POINT` or `OPPORTUNITY` the principle answers, so that a principle is
2026
+ grounded in the observed experience rather than in taste alone.
2027
+ value: list([[REQS:UJ.JOURNEY:*.STEP:*]])
2028
+ optional: true
2029
+ - name: TRADE-OFF
2030
+ desc: >
2031
+ The competing concern the principle deliberately subordinates, stated so
2032
+ that the opposite of the principle is a defensible choice, too (e.g.
2033
+ `explicit confirmation before every destructive action` for `Undo over
2034
+ Confirm`), as opposed to the rationale which states why this side wins.
571
2035
 
572
- - kind: SPEC
2036
+ - kind: UXUI
573
2037
  name: Language Conventions
574
2038
  id: LC
575
- file: SPEC-13-LC-Language-Conventions.md
2039
+ file: 18-UXUI-LC-Language-Conventions.md
576
2040
  desc: >
577
- The terminology, naming, tone, and wording standards used consistently across the solution
578
- and its content.
2041
+ The voice, tone, and wording of the user-facing text of the solution (labels, messages,
2042
+ notifications, help), governing how the solution speaks to its users, so that the Interaction
2043
+ Concept states how it behaves, the Language Conventions how it talks, and the Visual Design
2044
+ how it looks. Domain terms are *defined* in the Domain Glossary and only *surfaced* here,
2045
+ while the conventions of the specification text itself and of code identifiers are out of
2046
+ scope (they belong to the Development View).
2047
+ refs: >
2048
+ - Podmajersky: Strategic Writing for UX (2019),
2049
+ https://www.oreilly.com/library/view/strategic-writing-for/9781492049388/
2050
+ - Metts/Welfle: Writing Is Designing: Words and the User Experience (2020),
2051
+ https://rosenfeldmedia.com/books/writing-is-designing/
2052
+ - Mailchimp: Content Style Guide -- Voice and Tone (2015),
2053
+ https://styleguide.mailchimp.com/
2054
+ - Microsoft: Microsoft Writing Style Guide (2018),
2055
+ https://learn.microsoft.com/en-us/style-guide/welcome/
2056
+ optional: true
2057
+ diagram:
2058
+ type: grid
2059
+ nodes: "[[UXUI:LC.CONVENTION:*]]"
2060
+ properties:
2061
+ - CATEGORY
2062
+ config:
2063
+ size-node-width-max: 440
2064
+ size-node-height-scale: 2
2065
+ grid-columns-max: 4
579
2066
  childs:
580
2067
  - kind: CONVENTION
581
2068
  desc: >
582
- A single language convention, named with a short (2-5 word) summary and described in
583
- a concise (1-3 sentence) paragraph as the convention to be applied consistently
584
- across the solution, optionally illustrated by a short, concrete example of the
585
- convention in practice.
2069
+ A single language convention, named with a short (2-5 word) summary (e.g. `Neutral
2070
+ Error Tone`, `Second-Person Address`) and described in a concise (1-3 sentence)
2071
+ paragraph as the rule the user-facing text of the solution has to follow
2072
+ consistently, plus a 1-sentence rationale ("why"). A convention governs how the
2073
+ solution phrases what it says, not what it does (a behavior is an Interaction
2074
+ Concept principle instead) and not what a term means (a definition is a Domain
2075
+ Glossary term instead).
586
2076
  props:
587
2077
  - name: CATEGORY
588
2078
  desc: >
589
- The aspect of language the convention governs: `Terminology` (preferred and
590
- forbidden terms), `Naming` (naming patterns), `Tone` (voice and register),
591
- `Capitalization`, `Punctuation`, or `Formatting`.
592
- value: enum(Terminology,Naming,Tone,Capitalization,Punctuation,Formatting)
2079
+ The aspect of language the convention governs: `Voice` (the stable persona
2080
+ the solution speaks with), `Tone` (the register varying with the situation,
2081
+ e.g. on errors), `Vocabulary` (preferred and forbidden words and phrasings),
2082
+ `Grammar` (person, tense, mood, sentence structure), `Capitalization`,
2083
+ `Punctuation`, `Formatting` (numbers, dates, units, quotations), or
2084
+ `Localization` (languages, translations, locale-dependent wording).
2085
+ value: enum(Voice,Tone,Vocabulary,Grammar,Capitalization,Punctuation,Formatting,Localization)
2086
+ - name: ACTORS
2087
+ desc: >
2088
+ Comma-separated references to the User Personas objects the convention
2089
+ addresses, omitted for a convention governing the text shown to all users
2090
+ alike.
2091
+ value: list([[REQS:UP.PERSONA:*]])
2092
+ optional: true
2093
+ - name: PRINCIPLES
2094
+ desc: >
2095
+ Comma-separated references to the INTERACTION-CONCEPT objects the convention
2096
+ supports in wording, so that a convention is grounded in the interaction
2097
+ philosophy rather than in taste alone.
2098
+ value: list([[UXUI:IC.PRINCIPLE:*]])
2099
+ optional: true
2100
+ - name: TERMS
2101
+ desc: >
2102
+ Comma-separated references to the GLOSSARY terms whose surfacing in the
2103
+ user-facing text the convention governs, so that the Domain Glossary defines
2104
+ the term and the convention states how it is written.
2105
+ value: list([[REQS:GL.TERM:*]])
2106
+ optional: true
2107
+ - name: EXAMPLE
2108
+ desc: >
2109
+ A short, concrete "do, not don't" pair illustrating the convention in
2110
+ practice, quoting the text as the user sees it (e.g. `"You are not
2111
+ authorized for this event.", not "Access forbidden!"`).
593
2112
 
594
- - kind: SPEC
2113
+ - kind: UXUI
595
2114
  name: Dialog Patterns
596
2115
  id: DP
597
- file: SPEC-14-DP-Dialog-Patterns.md
2116
+ file: 19-UXUI-DP-Dialog-Patterns.md
598
2117
  desc: >
599
2118
  The reusable interaction structures governing how the system and user exchange information
600
- across recurring conversational or UI flows (e.g. master-detail dialog).
2119
+ across recurring UI flows (e.g. master-detail dialog).
2120
+ refs: >
2121
+ - Alexander et al.: A Pattern Language: Towns, Buildings, Construction (1977),
2122
+ https://global.oup.com/academic/product/a-pattern-language-9780195019193
2123
+ - Borchers: A Pattern Approach to Interaction Design (2001),
2124
+ https://www.wiley.com/en-us/A+Pattern+Approach+to+Interaction+Design-p-9780471498285
2125
+ - Tidwell et al.: Designing Interfaces: Patterns for Effective Interaction Design, 3rd ed. (2020),
2126
+ https://www.oreilly.com/library/view/designing-interfaces-3rd/9781492051954/
2127
+ optional: true
2128
+ diagram:
2129
+ type: grid
2130
+ nodes: "[[UXUI:DP.PATTERN:*]]"
2131
+ properties:
2132
+ - CATEGORY
2133
+ config:
2134
+ size-node-width-max: 440
2135
+ size-node-height-scale: 2
2136
+ grid-columns-max: 4
601
2137
  childs:
602
2138
  - kind: PATTERN
603
2139
  desc: >
@@ -606,8 +2142,35 @@
606
2142
  paragraph by the interaction structure and how the system and user exchange
607
2143
  information within it, plus a 1-sentence rationale ("why") stating why this
608
2144
  particular structure is worth adopting -- the benefit it secures or the trade-off it
609
- wins.
2145
+ wins. A pattern is a structure recurring in at least two flows (a structure
2146
+ occurring in a single flow is a Dialog Storyboard frame instead) and is bound to a
2147
+ particular kind of screen or flow (a solution-wide rule independent of any screen
2148
+ is an Interaction Concept principle instead).
2149
+ diagram:
2150
+ type: hub
2151
+ center: self
2152
+ nodes: "[[UXUI:DP.PATTERN:*]], [[UXUI:IC.PRINCIPLE:*]], [[UXUI:DS.STORYBOARD:*]]"
2153
+ deep: true
2154
+ qualified: true
2155
+ config:
2156
+ size-node-width-max: 440
610
2157
  props:
2158
+ - name: CATEGORY
2159
+ desc: >
2160
+ The aspect of the interaction the pattern structures: `Navigation` (moving
2161
+ between the screens and places of the solution), `Layout` (arranging the
2162
+ regions of a screen), `List` (browsing, filtering, and selecting among many
2163
+ items), `Data` (presenting complex data and information graphics), `Form`
2164
+ (entering and editing data), `Action` (issuing commands and handling their
2165
+ effects), or `Feedback` (conveying status, progress, and notifications).
2166
+ value: enum(Navigation,Layout,List,Data,Form,Action,Feedback)
2167
+ - name: ACTORS
2168
+ desc: >
2169
+ Comma-separated references to the User Personas objects whose interaction
2170
+ the pattern structures, omitted for a pattern applied to the interaction of
2171
+ all users alike.
2172
+ value: list([[REQS:UP.PERSONA:*]])
2173
+ optional: true
611
2174
  - name: CONTEXT
612
2175
  desc: >
613
2176
  The recurring situation or flow in which the pattern is applied.
@@ -617,86 +2180,406 @@
617
2180
  pattern needed"), stated independently of its solution (which belongs to the
618
2181
  description) and of its rationale (which states why this particular solution
619
2182
  is worth adopting).
2183
+ - name: PRINCIPLES
2184
+ desc: >
2185
+ Comma-separated references to the INTERACTION-CONCEPT objects the pattern
2186
+ embodies, so that every principle is shown to be honored by at least one
2187
+ pattern rather than merely declared.
2188
+ value: list([[UXUI:IC.PRINCIPLE:*]])
2189
+ optional: true
2190
+ - name: USES
2191
+ desc: >
2192
+ Comma-separated references to the smaller DIALOG-PATTERNS objects the
2193
+ pattern is composed of (e.g. a `Master-Detail` using an `Inline Edit` in
2194
+ its detail), so that the patterns form a language of related structures
2195
+ rather than a flat catalogue.
2196
+ value: list([[UXUI:DP.PATTERN:*]])
2197
+ optional: true
2198
+ - name: TRADE-OFF
2199
+ desc: >
2200
+ The liability the pattern accepts in exchange for its benefit, stated so
2201
+ that not applying the pattern is a defensible choice, too (e.g. `the
2202
+ horizontal space of two panes, cramped on small screens` for
2203
+ `Master-Detail`), as opposed to the rationale which states why the benefit
2204
+ wins.
620
2205
 
621
- - kind: SPEC
2206
+ - kind: UXUI
622
2207
  name: Dialog Storyboard
623
2208
  id: DS
624
- file: SPEC-15-DS-Dialog-Storyboard.md
2209
+ file: 20-UXUI-DS-Dialog-Storyboard.md
625
2210
  desc: >
626
2211
  The sequenced visual or textual depiction of a specific dialog flow, illustrating how an
627
2212
  interaction unfolds screen by screen or turn by turn.
2213
+ refs: >
2214
+ - Truong et al.: Storyboarding: An Empirical Determination of Best Practices and Effective Guidelines (2006),
2215
+ https://dl.acm.org/doi/10.1145/1142405.1142410
2216
+ - Buxton: Sketching User Experiences: Getting the Design Right and the Right Design (2007),
2217
+ https://shop.elsevier.com/books/sketching-user-experiences-getting-the-design-right-and-the-right-design/buxton/978-0-12-374037-3
2218
+ - NN/g: Storyboards Help Visualize UX Ideas (2018),
2219
+ https://www.nngroup.com/articles/storyboards-visualize-ideas/
2220
+ optional: true
628
2221
  diagram:
629
2222
  type: grid
630
- nodes: "[[SPEC:DS.STORYBOARD:*]]"
2223
+ nodes: "[[UXUI:DS.STORYBOARD:*]]"
2224
+ properties:
2225
+ - ACTORS
2226
+ config:
2227
+ size-node-width-max: 440
2228
+ size-node-height-scale: 2
2229
+ grid-columns-max: 4
631
2230
  childs:
632
2231
  - kind: STORYBOARD
633
2232
  desc: >
634
2233
  A single depicted dialog flow, named with a short (3-8 word) summary of the flow and
635
- comprised of sequentially numbered frames.
2234
+ comprised of frames in sequence. A storyboard shows the concrete user interface of
2235
+ one flow, as seen by its actors (the intent and the information exchanged is a Use
2236
+ Cases scenario instead, and a structure recurring across flows is a Dialog Pattern
2237
+ instead).
636
2238
  diagram:
637
2239
  type: hub
638
2240
  center: self
639
- nodes: "[[SPEC:DS.STORYBOARD:*]], [[SPEC:UC.USE-CASE:*]],
640
- [[SPEC:UC.USE-CASE:*.SCENARIO:*]], [[SPEC:DP.PATTERN:*]]"
2241
+ nodes: "[[UXUI:DS.STORYBOARD:*]], [[REQS:UP.PERSONA:*]],
2242
+ [[REQS:UC.USE-CASE:*.SCENARIO:*]], [[UXUI:DP.PATTERN:*]]"
2243
+ deep: true
641
2244
  qualified: true
642
2245
  config:
643
2246
  size-node-width-max: 440
2247
+ size-node-height-scale: 1.75
644
2248
  props:
645
- - name: USE-CASE
2249
+ - name: ACTORS
646
2250
  desc: >
647
- Reference to the USE-CASES object the storyboard visualizes.
648
- value: "[[SPEC:UC.USE-CASE:*]]"
649
- optional: true
2251
+ Comma-separated references to the User Personas objects whose story the
2252
+ storyboard tells, in the order of their appearance, so that a storyboard
2253
+ switching its viewpoint between actors (e.g. from a moderator to a
2254
+ presenter) names all of them.
2255
+ value: list([[REQS:UP.PERSONA:*]])
650
2256
  - name: SCENARIO
651
2257
  desc: >
652
- Reference to the USE-CASES scenario object the storyboard visualizes.
653
- value: "[[SPEC:UC.USE-CASE:*.SCENARIO:*]]"
654
- optional: true
655
- - name: PATTERN
656
- desc: >
657
- Reference to the DIALOG-PATTERNS object the storyboard instantiates.
658
- value: "[[SPEC:DP.PATTERN:*]]"
2258
+ Reference to the USE-CASES scenario object the storyboard renders as user
2259
+ interface, omitted for a storyboard of a flow no scenario covers.
2260
+ value: "[[REQS:UC.USE-CASE:*.SCENARIO:*]]"
659
2261
  optional: true
660
2262
  childs:
661
2263
  - kind: FRAME
662
2264
  desc: >
663
2265
  A single frame of the storyboard, named with a short (2-5 word) label for
664
- the screen, turn, or state depicted and described in a concise (1-2
665
- sentence) paragraph by what the user sees and does at this frame of the
666
- interaction.
2266
+ the screen, turn, or state depicted, shown by its `SKETCH`, and described in
2267
+ a concise (1-2 sentence) paragraph by what the actor sees and does at this
2268
+ frame of the interaction.
2269
+ format:
2270
+ type: concise
2271
+ maxTableColumns: 5
2272
+ props:
2273
+ - name: SCENARIO-STEP
2274
+ desc: >
2275
+ The number of the step of the referenced USE-CASES scenario the
2276
+ frame renders, so that a frame traces back to the intent it gives a
2277
+ user interface to, omitted for a frame setting the scene before or
2278
+ between the steps.
2279
+ value: /^[1-9][0-9]*$/
2280
+ optional: true
2281
+ - name: ACTOR
2282
+ desc: >
2283
+ Reference to the User Personas object from whose viewpoint the frame
2284
+ is depicted, given whenever the storyboard names several `ACTORS`
2285
+ and omitted for a storyboard of a single actor.
2286
+ value: "[[REQS:UP.PERSONA:*]]"
2287
+ optional: true
2288
+ - name: PATTERNS
2289
+ desc: >
2290
+ Comma-separated references to the DIALOG-PATTERNS objects the frame
2291
+ instantiates, so that a pattern is shown to recur across the
2292
+ concrete flows rather than merely being catalogued.
2293
+ value: list([[UXUI:DP.PATTERN:*]])
2294
+ optional: true
2295
+ - name: SKETCH
2296
+ desc: >
2297
+ An image (`![...](...)`) of the frame, preferably a low-fidelity
2298
+ sketch or wireframe which invites critique, or a screenshot for an
2299
+ already existing user interface, so that the frame is seen rather
2300
+ than only read, omitted for a frame whose depiction differs from
2301
+ the preceding one only in a detail the description names.
2302
+ optional: true
667
2303
 
668
- - kind: SPEC
2304
+ - kind: UXUI
669
2305
  name: Visual Design
670
2306
  id: VD
671
- file: SPEC-16-VD-Visual-Design.md
2307
+ file: 21-UXUI-VD-Visual-Design.md
672
2308
  desc: >
673
- The aesthetic and layout aspects of the solution, defining colors, typography, spacing,
674
- imagery, and overall look and feel.
2309
+ The visual design decisions of the solution (brand, color, typography, spacing, shape,
2310
+ iconography, imagery, and motion), each stated as a rule with its rationale, plus the
2311
+ high-fidelity mockups showing the decisions applied to concrete screens, so that the
2312
+ Interaction Concept states how the solution behaves, the Language Conventions how it
2313
+ talks, and the Visual Design how it looks. The concrete token values live in the design
2314
+ system (token file, design tool library) and are referenced rather than restated, the
2315
+ arrangement of the regions of a screen is a Dialog Pattern, the screen of a particular
2316
+ flow step is a Dialog Storyboard frame, and a measurable visual bound (e.g. a contrast
2317
+ ratio) is a Non-Functional Requirement.
2318
+ refs: >
2319
+ - DTCG: Design Tokens Format Module (2025),
2320
+ https://www.designtokens.org/tr/format/
2321
+ - Google: Material Design 3 -- Styles: Color, Typography, Shape, Motion, Icons, Elevation (2021),
2322
+ https://m3.material.io/styles
2323
+ - Kholmatova: Design Systems: A practical guide for creating design languages for digital products (2017),
2324
+ https://www.smashingmagazine.com/printed-books/design-systems/
2325
+ optional: true
2326
+ diagram:
2327
+ type: grid
2328
+ nodes: "[[UXUI:VD.ELEMENT:*]]"
2329
+ properties:
2330
+ - CATEGORY
2331
+ config:
2332
+ size-node-width-max: 440
2333
+ size-node-height-scale: 2
2334
+ grid-columns-max: 4
675
2335
  childs:
676
2336
  - kind: ELEMENT
677
2337
  desc: >
678
- A single visual design element, named with a short (2-5 word) summary and described
679
- in a concise (1-3 sentence) paragraph specifying the concrete values, tokens, or
680
- rules that define it (e.g. palette, font family, scale), plus a 1-sentence rationale
681
- ("why").
2338
+ A single visual design element, named with a short (2-5 word) summary (e.g. `Brand
2339
+ Color Palette`, `Self-Hosted Typography`) and described in a concise (1-3 sentence)
2340
+ paragraph as the rule the appearance of the solution has to follow consistently,
2341
+ naming its stable concrete values (e.g. the primary color, the font family, the
2342
+ type scale) and deferring the remaining ones to its `SOURCE`, plus a 1-sentence
2343
+ rationale ("why"). An element decides how the solution looks (a behavior is an
2344
+ Interaction Concept principle instead, a wording is a Language Conventions
2345
+ convention instead), solution-wide rather than for one screen (a screen is a
2346
+ `MOCKUP` or a Dialog Storyboard frame instead), and is a decision rather than a
2347
+ list of token values (the values are in the design system) or a measurable bound
2348
+ (a bound is a Non-Functional Requirement instead).
2349
+ format:
2350
+ maxTableColumns: 5
2351
+ diagram:
2352
+ type: hub
2353
+ center: self
2354
+ nodes: "[[UXUI:VD.ELEMENT:*]], [[REQS:UP.PERSONA:*]], [[UXUI:IC.PRINCIPLE:*]], [[UXUI:VD.MOCKUP:*]]"
2355
+ qualified: true
2356
+ config:
2357
+ size-node-width-max: 440
682
2358
  props:
683
2359
  - name: CATEGORY
684
- desc: The aspects of visual design the element governs.
685
- value: tags(Color,Typography,Iconography,Imagery,Layout,Animation)
2360
+ desc: >
2361
+ The aspect of visual design the element governs: `Brand` (logo, wordmark,
2362
+ and identity marks), `Color` (palettes, themes, and semantic color roles),
2363
+ `Typography` (font families, type scale, and text styles), `Spacing`
2364
+ (spacing scale, grid, and breakpoints, i.e. the metrics of the arrangements
2365
+ the Dialog Patterns structure), `Shape` (corner radii, borders, and
2366
+ elevation), `Iconography` (icon set and its usage), `Imagery`
2367
+ (photography, illustration, and video treatment), or `Motion`
2368
+ (transitions, animations, and their timing).
2369
+ value: enum(Brand,Color,Typography,Spacing,Shape,Iconography,Imagery,Motion)
2370
+ - name: ACTORS
2371
+ desc: >
2372
+ Comma-separated references to the User Personas objects for whom the
2373
+ element governs the appearance, omitted for an element governing the
2374
+ appearance for all users alike.
2375
+ value: list([[REQS:UP.PERSONA:*]])
2376
+ optional: true
2377
+ - name: PRINCIPLES
2378
+ desc: >
2379
+ Comma-separated references to the INTERACTION-CONCEPT objects the element
2380
+ supports in appearance, so that an element is grounded in the interaction
2381
+ philosophy rather than in taste alone.
2382
+ value: list([[UXUI:IC.PRINCIPLE:*]])
2383
+ optional: true
2384
+ - name: SOURCE
2385
+ desc: >
2386
+ The authoritative external artifact holding the concrete values of the
2387
+ element (e.g. a design token file, a design tool library, a stylesheet),
2388
+ so that the values are maintained there and only referenced here, omitted
2389
+ for an element whose values are fully named in its description.
2390
+ optional: true
2391
+ - name: TRADE-OFF
2392
+ desc: >
2393
+ The liability the element accepts in exchange for its benefit, stated so
2394
+ that the opposite decision is a defensible choice, too (e.g. `a larger
2395
+ initial download` for `Self-Hosted Typography`), as opposed to the
2396
+ rationale which states why the benefit wins.
2397
+ - kind: MOCKUP
2398
+ desc: >
2399
+ A single high-fidelity mockup, named with a short (2-5 word) label for the screen
2400
+ depicted, shown by its `IMAGE`, and described in a concise (1-2 sentence) paragraph
2401
+ by which visual design elements it shows applied and where on the screen. A mockup
2402
+ is a reference rendering of the final look of one screen (a low-fidelity sketch of
2403
+ a screen within its flow is a Dialog Storyboard frame instead) and shows rules
2404
+ applied rather than stating them (a rule is an `ELEMENT` instead).
2405
+ format:
2406
+ type: complex
2407
+ props:
2408
+ - name: ACTORS
2409
+ desc: >
2410
+ Comma-separated references to the User Personas objects who see the
2411
+ depicted screen.
2412
+ value: list([[REQS:UP.PERSONA:*]])
2413
+ - name: STORYBOARD
2414
+ desc: >
2415
+ Reference to the DIALOG-STORYBOARD object whose flow the depicted screen
2416
+ belongs to, so that the high-fidelity look traces back to the sketched
2417
+ flow, omitted for a mockup of a screen no storyboard covers.
2418
+ value: "[[UXUI:DS.STORYBOARD:*]]"
2419
+ optional: true
2420
+ - name: ELEMENTS
2421
+ desc: >
2422
+ Comma-separated references to the `ELEMENT` objects the mockup shows
2423
+ applied, so that an element is shown to be realized rather than merely
2424
+ declared.
2425
+ value: list([[UXUI:VD.ELEMENT:*]])
2426
+ - name: IMAGE
2427
+ desc: >
2428
+ An image (`![...](...)`) of the mockup, a high-fidelity rendering from
2429
+ the design tool or a screenshot of an already existing user interface, so
2430
+ that the look is seen rather than only read.
2431
+
2432
+ - kind: TEST
2433
+ name: Test Cases
2434
+ id: TC
2435
+ file: 22-TEST-TC-Test-Cases.md
2436
+ desc: >
2437
+ The verifiable conditions and steps used to confirm that requirements, domain rules, use
2438
+ case scenarios, and state transitions are correctly implemented, with mandatory defined
2439
+ inputs, mandatory expected outcomes, and optional pre- and post-conditions.
2440
+
2441
+ Test cases are not derived from use cases alone: a use case scenario describes an intent-level
2442
+ flow, while a test case fixes the concrete data and the observable assertions that decide pass
2443
+ or fail, and many test cases (e.g. of Non-Functional Requirements or of cross-session rules)
2444
+ have no use case counterpart at all.
2445
+ refs: >
2446
+ - ISO/IEC/IEEE 29119-3:2021: Software and systems engineering -- Software testing -- Part 3: Test documentation (2021),
2447
+ https://www.iso.org/standard/79429.html
2448
+ - ISO/IEC/IEEE 29119-4:2021: Software and systems engineering -- Software testing -- Part 4: Test techniques (2021),
2449
+ https://www.iso.org/standard/79430.html
2450
+ - ISTQB CTFL 4.0: Certified Tester Foundation Level Syllabus (2023),
2451
+ https://istqb.org/certifications/certified-tester-foundation-level-ctfl-v4-0/
2452
+ diagram:
2453
+ type: grid
2454
+ nodes: "[[TEST:TC.TEST-CASE:*]]"
2455
+ config:
2456
+ size-node-width-max: 440
2457
+ size-node-height-scale: 2
2458
+ grid-columns-max: 4
2459
+ childs:
2460
+ - kind: TEST-CASE
2461
+ desc: >
2462
+ A single verifiable test case, named with a short (3-8 word) summary and defined by
2463
+ its mandatory input and expected outcome plus its optional pre- and post-conditions.
2464
+
2465
+ The test case is at verification level: it pins down what the objects it verifies
2466
+ leave open, namely concrete data (e.g. `the correct six-digit token`), a boundary
2467
+ or equivalence class (e.g. `one more question within the same minute`), and an
2468
+ observable assertion, including the negative one (e.g. `the rejected question is
2469
+ not stored and the earlier questions remain unchanged`).
2470
+
2471
+ A test case which merely rephrases a scenario in different words, adding none of these,
2472
+ is redundant and should be sharpened or dropped. Conversely, one scenario can require
2473
+ several test cases (one per boundary or equivalence class), and one test case can
2474
+ verify a requirement, a rule, and a scenario at once.
2475
+
2476
+ A test case whose stimulus is a sequence rather than a single action carries the
2477
+ procedure in its body as sequentially numbered, imperative steps, mirroring the
2478
+ steps of a use case scenario (e.g. `1. The user logs in on device A. 2. The same
2479
+ user logs in on device B.`), with `INPUT` naming the decisive stimulus among them.
2480
+ diagram:
2481
+ type: hub
2482
+ center: self
2483
+ nodes: "[[TEST:TC.TEST-CASE:*]], [[REQS:FR.REQUIREMENT:*]], [[REQS:NR.REQUIREMENT:*]],
2484
+ [[REQS:DR.RULE:*]], [[REQS:UC.USE-CASE:*.SCENARIO:*]], [[REQS:DW.WORKFLOW:*]],
2485
+ [[DATA:SM.LIFECYCLE:*.TRANSITION:*]], [[DATA:DM.ENTITY:*.ATTRIBUTE:*]],
2486
+ [[DATA:AM.ROLE:*.PERMISSION:*]], [[APIS:IE.ENDPOINT:*]],
2487
+ [[UXUI:DS.STORYBOARD:*.FRAME:*]]"
2488
+ labeled: true
2489
+ qualified: true
2490
+ config:
2491
+ size-node-width-max: 440
2492
+ size-node-height-scale: 1.75
2493
+ props:
2494
+ - name: VERIFIES
2495
+ desc: >
2496
+ Comma-separated references to the FUNCTIONAL-REQUIREMENTS or
2497
+ NON-FUNCTIONAL-REQUIREMENTS objects, the DOMAIN-RULES objects, the
2498
+ USE-CASES scenario objects, the STATE-MODEL transition objects, the
2499
+ DATA-MODEL attribute objects, the AUTHORIZATION-MODEL permission objects,
2500
+ the INTERFACE-ENDPOINTS objects, and/or the DIALOG-STORYBOARD frame objects
2501
+ the test case verifies, so that a scenario (in particular an `Exceptional`
2502
+ one, judged by its `OUTCOME`) is covered by an acceptance test beside the
2503
+ requirements it exercises, a rule (judged by the condition it states) is
2504
+ proven to hold, not just to be documented, a transition (judged by its
2505
+ `GUARD` and the resulting state) is proven to be permitted exactly as
2506
+ modeled, an attribute (judged by its `TYPE` and `CONSTRAINT`) is proven to
2507
+ reject the values outside its range, pattern, or invariant, a permission
2508
+ (judged by the operations it grants and, the model being closed, by the
2509
+ ones it denies) is proven to be enforced, an endpoint (judged by its
2510
+ arguments, options, and results) is proven to honor its contract, and a
2511
+ frame (judged by the dialog step it storyboards) is proven to be reachable
2512
+ and to behave as storyboarded.
2513
+ value: list([[REQS:*.REQUIREMENT:*]], [[REQS:DR.RULE:*]], [[REQS:UC.USE-CASE:*.SCENARIO:*]],
2514
+ [[DATA:SM.LIFECYCLE:*.TRANSITION:*]], [[DATA:DM.ENTITY:*.ATTRIBUTE:*]],
2515
+ [[DATA:AM.ROLE:*.PERMISSION:*]], [[APIS:IE.ENDPOINT:*]],
2516
+ [[UXUI:DS.STORYBOARD:*.FRAME:*]])
2517
+ - name: WORKFLOWS
2518
+ desc: >
2519
+ Comma-separated references to the DOMAIN-WORKFLOWS objects the test case
2520
+ walks through end to end, i.e. whose activities and handoffs its procedure
2521
+ steps cross in order, so that the collaboration across actors and sittings
2522
+ (not just the use cases of each single sitting) is proven to work as
2523
+ modeled; omitted for a test case confined to a single sitting.
2524
+ value: list([[REQS:DW.WORKFLOW:*]])
2525
+ optional: true
2526
+ - name: PRE-CONDITION
2527
+ desc: >
2528
+ The state or setup that must hold before the test is executed.
2529
+ optional: true
2530
+ - name: INPUT
2531
+ desc: >
2532
+ The mandatory, concrete input data or action applied during the test, i.e.
2533
+ the stimulus whose response the `EXPECTED` judges.
2534
+ - name: EXPECTED
2535
+ desc: >
2536
+ The mandatory, concrete, observable response of the solution to the `INPUT`
2537
+ (a message shown, a session issued, a submission rejected) that defines a
2538
+ passing test, as opposed to the `POST-CONDITION` which is the state left
2539
+ behind. When the test case verifies a NON-FUNCTIONAL-REQUIREMENTS object,
2540
+ the expected response restates the `METRIC` threshold of that requirement
2541
+ as the pass criterion (e.g. `p95 latency < 200 ms`) rather than a
2542
+ qualitative phrase (e.g. `remains responsive`).
2543
+ - name: POST-CONDITION
2544
+ desc: >
2545
+ The persisted state that must hold after the test completes (e.g. `the
2546
+ authorization token is in state used`), including the state that must not
2547
+ have changed (e.g. `no session token exists`), as opposed to the `EXPECTED`
2548
+ which is the immediate response, and omitted for a test whose input leaves
2549
+ no state behind.
2550
+ optional: true
686
2551
 
687
2552
  - kind: ARCH
688
2553
  name: Context View
689
2554
  id: CV
690
- file: ARCH-01-CV-Context-View.md
2555
+ file: 23-ARCH-CV-Context-View.md
691
2556
  desc: >
692
2557
  The relationships, dependencies, and interactions between the solution and its environment,
693
- defining the system's scope, external entities, and boundaries.
2558
+ defining the system's boundary by enumerating the external entities sitting at it. The
2559
+ artifact complements the Solution Vision: its `SCOPE` states what is deliberately *out* of
2560
+ the solution, the Context View enumerates what the solution touches *at* the boundary.
2561
+ refs: >
2562
+ - Rozanski/Woods: Software Systems Architecture, 2nd ed.: The Context Viewpoint (2011),
2563
+ https://www.viewpoints-and-perspectives.info/home/viewpoints/context/
2564
+ - Brown: The C4 Model: System Context Diagram (2018),
2565
+ https://c4model.com/diagrams/system-context
2566
+ - ISO/IEC/IEEE 42010:2022: Software, systems and enterprise -- Architecture description (2022),
2567
+ https://www.iso.org/standard/74393.html
694
2568
  diagram:
695
- type: grid
2569
+ type: hub
696
2570
  nodes: "[[ARCH:CV.ENTITY:*]]"
2571
+ center:
2572
+ source: "[[META:TI]]"
2573
+ property: TITLE
2574
+ kind: Solution
2575
+ centerEdges:
2576
+ property: DIRECTION
2577
+ inbound: Inbound
2578
+ outbound: Outbound
2579
+ both: Bidirectional
2580
+ qualified: true
697
2581
  properties:
698
2582
  - KIND
699
- - DIRECTION
700
2583
  childs:
701
2584
  - kind: ENTITY
702
2585
  desc: >
@@ -705,30 +2588,71 @@
705
2588
  concise (1-3 sentence) paragraph by the relationship and dependency between the
706
2589
  solution and the entity, plus a 1-sentence rationale ("why") for the entity being
707
2590
  part of the system context.
2591
+
2592
+ An entity is outside the solution and exchanges information with it across the
2593
+ boundary: a party with a mere interest in the solution but no such exchange is a
2594
+ `Stakeholder` persona of the User Personas instead, and a platform element the
2595
+ solution deploys and operates itself (e.g. a managed database of its own) is a
2596
+ Deployment View node instead -- only a party or system the solution merely
2597
+ consumes or serves belongs to the system context.
2598
+ format:
2599
+ maxTableColumns: 5
708
2600
  props:
709
2601
  - name: KIND
710
2602
  desc: |
711
2603
  The kind of the external entity, one of:
712
2604
  - `Person`: A human actor interacting with the solution.
713
- - `System`: An external software system the solution integrates
714
- with.
2605
+ - `System`: An external software system the solution integrates with.
715
2606
  - `Service`: A third-party or managed service the solution consumes.
716
- - `Datastore`: An external data repository the solution reads from or
717
- writes to.
718
- - `Device`: A physical device or sensor the solution communicates
719
- with.
2607
+ - `Datastore`: An external data repository the solution reads from or writes to.
2608
+ - `Device`: A physical device or sensor the solution communicates with.
720
2609
  - `Organization`: An external organizational party.
721
2610
  value: enum(Person,System,Service,Datastore,Device,Organization)
722
2611
  - name: DIRECTION
723
2612
  desc: >
724
- The flow of interaction relative to the solution: `Inbound` (the entity
725
- drives the solution), `Outbound` (the solution drives the entity), or
726
- `Bidirectional` (both directions).
2613
+ Who initiates the interaction: `Inbound` (the entity drives the solution),
2614
+ `Outbound` (the solution drives the entity), or `Bidirectional` (both
2615
+ sides initiate), independent of the direction the exchanged information
2616
+ flows in, which the `DATA` property describes (e.g. a datastore the
2617
+ solution reads from is `Outbound`, as the solution initiates, while the
2618
+ data flows in).
727
2619
  value: enum(Inbound,Outbound,Bidirectional)
2620
+ - name: TERMS
2621
+ desc: >
2622
+ Comma-separated references to the GLOSSARY terms the entity appears as in
2623
+ the domain (usually a term of type `Actor`, which covers an external system
2624
+ as a party acting in the domain), anchoring every boundary entity in the
2625
+ ubiquitous language.
2626
+ value: list([[REQS:GL.TERM:*]])
2627
+ optional: true
728
2628
  - name: INTERFACE
729
2629
  desc: >
730
- How the interaction happens (e.g. REST API, message queue, file exchange,
731
- web UI).
2630
+ Comma-separated references to the INTERFACE-MODEL objects through which
2631
+ the interaction happens, i.e. the interfaces the entity consumes (for a
2632
+ `Provided` one) or offers (for a `Required` one); omitted when the
2633
+ interaction happens through the user interface or outside any modeled
2634
+ interface (e.g. a file exchange).
2635
+ value: list([[APIS:IM.INTERFACE:*]])
2636
+ optional: true
2637
+ - name: ACTORS
2638
+ desc: >
2639
+ Comma-separated references to the User Personas objects acting behind the
2640
+ entity: a `Person` entity is the boundary-level role class and the referenced
2641
+ personas are its archetypes, while an `Organization` entity may reference
2642
+ the `Stakeholder` personas representing it, so the entity aggregates the
2643
+ personas instead of re-stating them; omitted when no persona stands behind
2644
+ the entity.
2645
+ value: list([[REQS:UP.PERSONA:*]])
2646
+ optional: true
2647
+ - name: PREMISES
2648
+ desc: >
2649
+ Comma-separated references to the SOLUTION-PREMISES objects (usually of
2650
+ type `Dependency`) resting on this entity: the entity describes the
2651
+ structural interaction with the external party, the premise the reliance
2652
+ on it and the consequence of its failure, so the risky context entities
2653
+ are found by traversal.
2654
+ value: list([[REQS:SP.PREMISE:*]])
2655
+ optional: true
732
2656
  - name: DATA
733
2657
  desc: >
734
2658
  The principal information exchanged across the boundary with this entity.
@@ -736,10 +2660,17 @@
736
2660
  - kind: ARCH
737
2661
  name: Functionality View
738
2662
  id: FV
739
- file: ARCH-02-FV-Functionality-View.md
2663
+ file: 24-ARCH-FV-Functionality-View.md
740
2664
  desc: >
741
2665
  The functional components of the solution, their responsibilities, interfaces, and primary
742
2666
  interactions, describing *what* the system does at runtime.
2667
+ refs: >
2668
+ - Rozanski/Woods: Software Systems Architecture, 2nd ed.: The Functional Viewpoint (2011),
2669
+ https://www.viewpoints-and-perspectives.info/home/viewpoints/functional/
2670
+ - Kruchten: Architectural Blueprints -- The "4+1" View Model of Software Architecture (1995),
2671
+ https://ieeexplore.ieee.org/document/469759
2672
+ - Brown: The C4 Model (2018),
2673
+ https://c4model.com/
743
2674
  diagram:
744
2675
  type: graph
745
2676
  nodes: "[[ARCH:FV.COMPONENT:*]]"
@@ -753,6 +2684,8 @@
753
2684
  described in a concise (1-3 sentence) paragraph by *what* it does and how it
754
2685
  collaborates with the components it depends on, plus a 1-sentence rationale ("why")
755
2686
  for the component's existence and boundary.
2687
+ format:
2688
+ maxTableColumns: 5
756
2689
  diagram:
757
2690
  type: hub
758
2691
  center: self
@@ -777,10 +2710,14 @@
777
2710
  desc: >
778
2711
  The 1-sentence statement of the single, primary responsibility the component
779
2712
  owns.
780
- - name: INTERFACE
2713
+ - name: PROVIDES
781
2714
  desc: >
782
- How other components interact with this component (e.g. REST API, library
783
- API, message topic, CLI).
2715
+ Comma-separated references to the INTERFACE-MODEL objects the component
2716
+ provides, i.e. through which other components and external entities
2717
+ interact with it; omitted when the component provides no modeled interface
2718
+ (e.g. a user interface or an internal module).
2719
+ value: list([[APIS:IM.INTERFACE:*]])
2720
+ optional: true
784
2721
  - name: DEPENDS-ON
785
2722
  desc: >
786
2723
  Comma-separated references to the FUNCTIONALITY-VIEW objects this component
@@ -791,10 +2728,15 @@
791
2728
  - kind: ARCH
792
2729
  name: Information View
793
2730
  id: IV
794
- file: ARCH-03-IV-Information-View.md
2731
+ file: 25-ARCH-IV-Information-View.md
795
2732
  desc: >
796
2733
  The way the solution stores, manages, manipulates, and distributes information, defining the
797
2734
  static data structure and dynamic information flow.
2735
+ refs: >
2736
+ - Rozanski/Woods: Software Systems Architecture, 2nd ed.: The Information Viewpoint (2011),
2737
+ https://www.viewpoints-and-perspectives.info/home/viewpoints/information/
2738
+ - Kleppmann: Designing Data-Intensive Applications (2017),
2739
+ https://dataintensive.net/
798
2740
  diagram:
799
2741
  type: grid
800
2742
  nodes: "[[ARCH:IV.ASPECT:*]]"
@@ -811,7 +2753,7 @@
811
2753
  diagram:
812
2754
  type: hub
813
2755
  center: self
814
- nodes: "[[ARCH:IV.ASPECT:*]], [[SPEC:DM.ENTITY:*]], [[ARCH:FV.COMPONENT:*]]"
2756
+ nodes: "[[ARCH:IV.ASPECT:*]], [[DATA:DM.ENTITY:*]], [[ARCH:FV.COMPONENT:*]]"
815
2757
  qualified: true
816
2758
  properties:
817
2759
  - CONCERN
@@ -827,7 +2769,7 @@
827
2769
  - name: ENTITIES
828
2770
  desc: >
829
2771
  Comma-separated references to the DATA-MODEL entities the aspect governs.
830
- value: list([[SPEC:DM.ENTITY:*]])
2772
+ value: list([[DATA:DM.ENTITY:*]])
831
2773
  optional: true
832
2774
  - name: OWNER
833
2775
  desc: >
@@ -842,10 +2784,17 @@
842
2784
  - kind: ARCH
843
2785
  name: Concurrency View
844
2786
  id: CO
845
- file: ARCH-04-CO-Concurrency-View.md
2787
+ file: 26-ARCH-CO-Concurrency-View.md
846
2788
  desc: >
847
2789
  The concurrency structure of the solution, mapping functional components to processes and
848
2790
  threads, and defining how they coordinate and communicate.
2791
+ refs: >
2792
+ - Rozanski/Woods: Software Systems Architecture, 2nd ed.: The Concurrency Viewpoint (2011),
2793
+ https://www.viewpoints-and-perspectives.info/home/viewpoints/concurrency/
2794
+ - Kruchten: Architectural Blueprints -- The "4+1" View Model of Software Architecture (1995),
2795
+ https://ieeexplore.ieee.org/document/469759
2796
+ - Schmidt et al.: Pattern-Oriented Software Architecture, Volume 2: Patterns for Concurrent and Networked Objects (2000),
2797
+ https://www.wiley.com/en-us/Pattern+Oriented+Software+Architecture,+Volume+2,+Patterns+for+Concurrent+and+Networked+Objects-p-9781118725177
849
2798
  diagram:
850
2799
  type: grid
851
2800
  nodes: "[[ARCH:CO.UNIT:*]]"
@@ -897,10 +2846,17 @@
897
2846
  - kind: ARCH
898
2847
  name: Development View
899
2848
  id: DV
900
- file: ARCH-05-DV-Development-View.md
2849
+ file: 27-ARCH-DV-Development-View.md
901
2850
  desc: >
902
2851
  The architecture supporting the software development process, defining the module
903
2852
  organization, build approach, and codeline conventions.
2853
+ refs: >
2854
+ - Rozanski/Woods: Software Systems Architecture, 2nd ed.: The Development Viewpoint (2011),
2855
+ https://www.viewpoints-and-perspectives.info/home/viewpoints/development/
2856
+ - Kruchten: Architectural Blueprints -- The "4+1" View Model of Software Architecture (1995),
2857
+ https://ieeexplore.ieee.org/document/469759
2858
+ - Clements et al.: Documenting Software Architectures: Views and Beyond, 2nd ed. (2010),
2859
+ https://www.informit.com/store/documenting-software-architectures-views-and-beyond-9780321552686
904
2860
  diagram:
905
2861
  type: grid
906
2862
  nodes: "[[ARCH:DV.ASPECT:*]]"
@@ -924,10 +2880,17 @@
924
2880
  - kind: ARCH
925
2881
  name: Deployment View
926
2882
  id: DP
927
- file: ARCH-06-DP-Deployment-View.md
2883
+ file: 28-ARCH-DP-Deployment-View.md
928
2884
  desc: >
929
2885
  The environment into which the solution is deployed, mapping software elements to the
930
2886
  runtime platform, hardware, and network topology.
2887
+ refs: >
2888
+ - Rozanski/Woods: Software Systems Architecture, 2nd ed.: The Deployment Viewpoint (2011),
2889
+ https://www.viewpoints-and-perspectives.info/home/viewpoints/deployment/
2890
+ - Kruchten: Architectural Blueprints -- The "4+1" View Model of Software Architecture (1995),
2891
+ https://ieeexplore.ieee.org/document/469759
2892
+ - Brown: The C4 Model: Deployment Diagram (2018),
2893
+ https://c4model.com/diagrams/deployment
931
2894
  diagram:
932
2895
  type: grid
933
2896
  nodes: "[[ARCH:DP.NODE:*]]"
@@ -981,10 +2944,17 @@
981
2944
  - kind: ARCH
982
2945
  name: Operations View
983
2946
  id: OV
984
- file: ARCH-07-OV-Operations-View.md
2947
+ file: 29-ARCH-OV-Operations-View.md
985
2948
  desc: >
986
2949
  The way the solution is operated, administered, and supported in production, defining
987
2950
  installation, monitoring, and management concerns.
2951
+ refs: >
2952
+ - Rozanski/Woods: Software Systems Architecture, 2nd ed.: The Operational Viewpoint (2011),
2953
+ https://www.viewpoints-and-perspectives.info/home/viewpoints/operational/
2954
+ - Beyer et al.: Site Reliability Engineering: How Google Runs Production Systems (2016),
2955
+ https://sre.google/sre-book/table-of-contents/
2956
+ - ISO/IEC 20000-1:2018: Information technology -- Service management -- Part 1: Service management system requirements (2018),
2957
+ https://www.iso.org/standard/70636.html
988
2958
  diagram:
989
2959
  type: grid
990
2960
  nodes: "[[ARCH:OV.CONCERN:*]]"
@@ -1004,7 +2974,7 @@
1004
2974
  `Provisioning`, `Monitoring`, `Logging`, `Alerting`, `Backup`, `Recovery`,
1005
2975
  `Upgrade`, or `Support`.
1006
2976
  value: enum(Installation,Configuration,Provisioning,Monitoring,Logging,Alerting,Backup,Recovery,Upgrade,Support)
1007
- - name: ELEMENT
2977
+ - name: ELEMENTS
1008
2978
  desc: >
1009
2979
  Comma-separated references to the FUNCTIONALITY-VIEW or DEPLOYMENT-VIEW
1010
2980
  objects the concern applies to.
@@ -1014,9 +2984,16 @@
1014
2984
  - kind: ARCH
1015
2985
  name: Quality Perspectives
1016
2986
  id: QP
1017
- file: ARCH-08-QP-Quality-Perspectives.md
2987
+ file: 30-ARCH-QP-Quality-Perspectives.md
1018
2988
  desc: >
1019
2989
  How the Non-Functional Requirements (NR) are addressed.
2990
+ refs: >
2991
+ - Rozanski/Woods: Software Systems Architecture, 2nd ed.: The Perspectives (2011),
2992
+ https://www.viewpoints-and-perspectives.info/home/perspectives/
2993
+ - Bass/Clements/Kazman: Software Architecture in Practice, 4th ed. (2021),
2994
+ https://www.informit.com/store/software-architecture-in-practice-9780136886099
2995
+ - ISO/IEC 25010:2023: Systems and software engineering -- Systems and software Quality Requirements and Evaluation (SQuaRE) -- Product quality model (2023),
2996
+ https://www.iso.org/standard/78176.html
1020
2997
  diagram:
1021
2998
  type: grid
1022
2999
  nodes: "[[ARCH:QP.PERSPECTIVE:*]]"
@@ -1033,7 +3010,7 @@
1033
3010
  diagram:
1034
3011
  type: hub
1035
3012
  center: self
1036
- nodes: "[[ARCH:QP.PERSPECTIVE:*]], [[SPEC:NR.REQUIREMENT:*]], [[ARCH:FV.COMPONENT:*]], [[ARCH:DP.NODE:*]]"
3013
+ nodes: "[[ARCH:QP.PERSPECTIVE:*]], [[REQS:NR.REQUIREMENT:*]], [[ARCH:FV.COMPONENT:*]], [[ARCH:DP.NODE:*]]"
1037
3014
  qualified: true
1038
3015
  properties:
1039
3016
  - QUALITY
@@ -1047,17 +3024,19 @@
1047
3024
  differs from them.
1048
3025
 
1049
3026
  The NR categories follow the ISO/IEC 25010:2023 top-level characteristics
1050
- (and include `Safety` and `Flexibility`), whereas the perspective qualities
1051
- decompose some of these into the finer-grained, architecturally actionable
1052
- attributes `Scalability`, `Availability`, `Privacy`, `Accessibility`, and
1053
- `Portability`. The quality therefore need not match the category of the
1054
- requirements it addresses.
3027
+ (and include `Safety` and `Flexibility`) plus the non-quality categories
3028
+ `Compliance` and `Constraint`, whereas the perspective qualities decompose
3029
+ some of the characteristics into the finer-grained, architecturally
3030
+ actionable attributes `Scalability`, `Availability`, `Privacy`,
3031
+ `Accessibility`, and `Portability`, and address a `Constraint` through the
3032
+ quality it protects. The quality therefore need not match the category of
3033
+ the requirements it addresses.
1055
3034
  value: enum(Performance,Scalability,Reliability,Availability,Security,Privacy,Usability,Accessibility,Maintainability,Portability,Compatibility,Compliance)
1056
3035
  - name: ADDRESSES
1057
3036
  desc: >
1058
3037
  Comma-separated references to the NON-FUNCTIONAL-REQUIREMENTS objects the
1059
3038
  perspective addresses.
1060
- value: list([[SPEC:NR.*]])
3039
+ value: list([[REQS:NR.*]])
1061
3040
  - name: TACTIC
1062
3041
  desc: >
1063
3042
  The architectural tactic or strategy applied to achieve the quality (e.g.
@@ -1073,10 +3052,17 @@
1073
3052
  - kind: ARCH
1074
3053
  name: Decision Record
1075
3054
  id: DR
1076
- file: ARCH-09-DR-Decision-Record.md
3055
+ file: 31-ARCH-DR-Decision-Record.md
1077
3056
  desc: >
1078
3057
  The major decisions related to the architecture, each recording the forces at play, the
1079
3058
  chosen response, and the reasoning that justifies it.
3059
+ refs: >
3060
+ - Nygard: Documenting Architecture Decisions (2011),
3061
+ https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions
3062
+ - Tyree/Akerman: Architecture Decisions: Demystifying Architecture (2005),
3063
+ https://ieeexplore.ieee.org/document/1407822
3064
+ - ADR: Architectural Decision Records (2017),
3065
+ https://adr.github.io/
1080
3066
  diagram:
1081
3067
  type: grid
1082
3068
  nodes: "[[ARCH:DR.DECISION:*]]"
@@ -1246,11 +3232,18 @@
1246
3232
  - kind: ARCH
1247
3233
  name: Technology Stack
1248
3234
  id: TS
1249
- file: ARCH-10-TS-Technology-Stack.md
3235
+ file: 32-ARCH-TS-Technology-Stack.md
1250
3236
  desc: >
1251
3237
  The concrete technology products the solution is built upon, organized by tier and lifecycle
1252
3238
  phase, recording for each component its chosen product, its purpose, and the alternatives
1253
3239
  that were considered but not chosen.
3240
+ refs: >
3241
+ - ThoughtWorks: Technology Radar (2010),
3242
+ https://www.thoughtworks.com/radar
3243
+ - Ford: Build Your Own Technology Radar (2013),
3244
+ https://nealford.com/memeagora/2013/05/28/build_your_own_technology_radar.html
3245
+ - Fowler: Patterns of Enterprise Application Architecture (2002),
3246
+ https://martinfowler.com/books/eaa.html
1254
3247
  diagram:
1255
3248
  type: grid
1256
3249
  nodes: "[[ARCH:TS.TIER:*]]"
@@ -1264,8 +3257,6 @@
1264
3257
  - `Server`: Runs on the server side (e.g. backend, application, API).
1265
3258
  - `Middleware`: Runs between client and server (e.g. message broker, gateway).
1266
3259
  - `Database`: Runs as the data store (e.g. relational or document database).
1267
- format:
1268
- maxTableColumns: 5
1269
3260
  diagram:
1270
3261
  type: hub
1271
3262
  center: self
@@ -1274,6 +3265,7 @@
1274
3265
  - PRODUCT
1275
3266
  config:
1276
3267
  size-node-width-max: 440
3268
+ size-node-height-scale: 1.75
1277
3269
  childs:
1278
3270
  - kind: COMPONENT
1279
3271
  desc: >