requirements-manager 0.1.1

Plain-text requirements management tool
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
# File Format Specification

Formal specification of the Requiem requirement file format.

## Overview

Requiem requirements are stored as Markdown files with YAML frontmatter. This document provides the formal specification.

### File Extension

`.md` (Markdown)

### Character Encoding

UTF-8

### Filename Format

```
{NAMESPACE-}*{KIND}-{ID}.md
```

Where:
- `NAMESPACE`: Zero or more namespace segments (alphanumeric, hyphen-separated)
- `KIND`: Alphanumeric requirement kind (e.g., `USR`, `SYS`)
- `ID`: Positive integer (zero-padded to configured digits, default 3)

**Examples**:
```
USR-001.md
SYS-042.md
AUTH-USR-001.md
MOBILE-AUTH-LOGIN-SYS-005.md
```

**Validation Rules**:
- Must end with `.md`
- NAMESPACE segments: non-empty, alphanumeric plus hyphen
- KIND: non-empty, alphanumeric
- ID: positive integer (1 or more), may have leading zeros
- Segments separated by single hyphen `-`
- No consecutive hyphens `--`
- No leading or trailing hyphens

## File Structure

Requirements consist of three parts:

1. **YAML Frontmatter**: Metadata enclosed in `---` delimiters
2. **HRID Heading**: First heading with HRID as first token
3. **Markdown Body**: Requirement text in CommonMark format

### General Structure

```
---
<YAML frontmatter>
---
# <HRID> <Title>
<blank line optional>
<Markdown content>
```

### Example

```markdown
---
_version: '1'
uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
created: 2025-07-22T12:19:56.950194157Z
tags:
- authentication
- security
parents:
- uuid: 3fc6800c-5acc-457e-baf9-a29b42b663fd
  fingerprint: c4020419ead000e9b5f9cfd4ebf6192e73f905c27e6897548d8f6e12fd7f1356
  hrid: USR-001
---
# SYS-001 Email Validation

The system shall validate user email addresses according to RFC 5322.

Email validation must occur before account creation.
```

## YAML Frontmatter

### Delimiters

- **Opening delimiter**: `---` on first line
- **Closing delimiter**: `---` on its own line
- Both required

### Schema Version 1

Current version: `1`

#### Required Fields

##### `_version`

**Type**: String (quoted)

**Format**: `"1"`

**Purpose**: Schema version for forward/backward compatibility

**Validation**:
- Must be present
- Must be string type (quoted in YAML)
- Currently only `"1"` is valid

**Example**:
```yaml
_version: '1'
```

##### `uuid`

**Type**: UUID (string format)

**Format**: UUID v4 (RFC 4122)

**Purpose**: Globally unique, stable identifier

**Validation**:
- Must be present
- Must be valid UUID format: `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
- Should be generated with `uuid::Uuid::new_v4()` or equivalent
- Must be unique across all requirements (globally)
- Must never change after creation

**Example**:
```yaml
uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
```

##### `created`

**Type**: Timestamp (string format)

**Format**: ISO 8601 with timezone (RFC 3339)

**Purpose**: Requirement creation timestamp

**Validation**:
- Must be present
- Must be valid ISO 8601 timestamp
- Must include timezone (use UTC: `Z` suffix)
- Format: `YYYY-MM-DDTHH:MM:SS.sssssssssZ`

**Example**:
```yaml
created: 2025-07-22T12:19:56.950194157Z
```

**Notes**:
- Nanosecond precision supported
- Timezone must be UTC (`Z` suffix)
- Set once at creation; never modified

#### Optional Fields

##### `tags`

**Type**: Array of strings

**Format**: YAML list

**Purpose**: Categorize and tag requirements

**Validation**:
- Optional (omit if no tags)
- Array elements must be strings
- Empty array allowed but should be omitted
- No duplicate tags within same requirement
- Tags are case-sensitive

**Example**:
```yaml
tags:
- authentication
- security
- high-priority
```

**Omission**:
```yaml
# No tags field = no tags
_version: '1'
uuid: ...
# tags field omitted
```

**Serialization**:
- Include only if non-empty: `skip_serializing_if = "BTreeSet::is_empty"`
- Stored as `BTreeSet` internally (sorted, unique)

##### `parents`

**Type**: Array of parent objects

**Format**: YAML list of objects

**Purpose**: Link to parent (upstream) requirements

**Validation**:
- Optional (omit if no parents, e.g., root requirements)
- Array elements must be parent objects (see Parent Object Schema)
- Empty array allowed but should be omitted
- Duplicate parent UUIDs allowed (though unusual)

**Example**:
```yaml
parents:
- uuid: 3fc6800c-5acc-457e-baf9-a29b42b663fd
  fingerprint: c4020419ead000e9b5f9cfd4ebf6192e73f905c27e6897548d8f6e12fd7f1356
  hrid: USR-001
- uuid: 7a8f9e2b-1c3d-4e5f-6a7b-8c9d0e1f2a3b
  fingerprint: a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456
  hrid: USR-003
```

**Omission**:
```yaml
# No parents field = no parents (root requirement)
_version: '1'
uuid: ...
# parents field omitted
```

**Serialization**:
- Include only if non-empty: `skip_serializing_if = "Vec::is_empty"`

#### Parent Object Schema

Each parent object has three fields:

##### `uuid`

**Type**: UUID (string format)

**Format**: UUID v4

**Purpose**: Stable reference to parent requirement

**Validation**:
- Must be present in parent object
- Must be valid UUID format
- Should match `uuid` field of an existing requirement

**Example**:
```yaml
uuid: 3fc6800c-5acc-457e-baf9-a29b42b663fd
```

##### `fingerprint`

**Type**: String (hex-encoded SHA256 hash)

**Format**: 64-character hexadecimal string

**Purpose**: Content hash of parent for change detection

**Validation**:
- Must be present in parent object
- Must be 64-character hexadecimal string
- Generated by hashing parent's content and tags with SHA256

**Example**:
```yaml
fingerprint: c4020419ead000e9b5f9cfd4ebf6192e73f905c27e6897548d8f6e12fd7f1356
```

**Generation**:
```
1. Collect parent's content (markdown body) and tags
2. Serialize with Borsh encoding
3. Hash with SHA256
4. Encode as hexadecimal string (64 characters)
```

##### `hrid`

**Type**: String (HRID format)

**Format**: `{NAMESPACE-}*{KIND}-{ID}`

**Purpose**: Human-readable reference to parent (convenience field)

**Validation**:
- Must be present in parent object
- Must be valid HRID format
- Should match parent's filename (without `.md` extension)

**Example**:
```yaml
hrid: USR-001
```

**Notes**:
- Convenience field for human readability
- May become outdated if parent is renamed
- Corrected by `req clean` command
- UUID is authoritative; HRID is informational

### Schema Evolution

Future schema versions (e.g., `_version: "2"`) will be backward-compatible:
- New optional fields may be added
- Required fields will not be removed
- Field semantics will not change incompatibly

Parsers should:
- Ignore unknown fields
- Provide defaults for missing optional fields
- Reject unknown `_version` values (fail-safe)

## HRID Heading

### Format

The first heading in the markdown must contain the HRID as the first token:

```markdown
# <HRID> <Title Text>
```

### Requirements

- Must be a level-1 heading (`#`)
- HRID must be the first token (word)
- Followed by space and title text
- HRID must match the filename (without `.md`)

### Examples

```markdown
# USR-001 Plain Text Storage
# SYS-042 Email Validation System
# AUTH-LOGIN-SYS-001 Password Hashing
```

### Rationale

The HRID is stored in the heading (not frontmatter) for compatibility with Sphinx and MdBook, which use the first heading as the page title.

## Markdown Body

### Format

CommonMark (Markdown specification)

### Location

Everything after the first heading is the markdown body.

### Content

Free-form Markdown:
- Headings (`##`, `###`, etc. - first `#` is reserved for HRID)
- Paragraphs
- Lists (ordered, unordered)
- Code blocks (fenced, indented)
- Emphasis (bold, italic)
- Links
- Images
- Blockquotes
- Tables
- Any CommonMark-compliant content

### Whitespace

- Leading/trailing whitespace: preserved
- Empty lines between frontmatter and body: ignored
- Empty body: valid (empty string)

### Example

```markdown
---
_version: '1'
uuid: ...
created: ...
---
# USR-001 Email Validation

The system shall validate user email addresses.

## Rationale

Email validation ensures...

## Acceptance Criteria

- Valid email format
- Rejects invalid emails
- Provides clear error messages
```

## Parsing Rules

### Frontmatter Parsing

1. First line must be `---`
2. Read lines until next `---` on its own line
3. Parse collected lines as YAML
4. Validate against schema
5. Remaining lines are markdown body

### Error Handling

**Missing opening delimiter**:
```
Error: Expected frontmatter starting with '---'
```

**Missing closing delimiter**:
```
Error: Unexpected EOF while parsing frontmatter
```

**Invalid YAML**:
```
Error: Failed to parse YAML: <syntax error details>
```

**Missing required field**:
```
Error: Missing required field '<field_name>'
```

**Invalid UUID format**:
```
Error: Invalid UUID format: '<value>'
```

**Invalid timestamp format**:
```
Error: Invalid timestamp format: '<value>'
```

**Unknown _version**:
```
Error: Unknown schema version: '<value>'
```

### Strict vs. Permissive

Requiem parsing is strict by default:
- All required fields must be present
- All fields must be valid
- Unknown fields in schema version 1 cause errors (currently)

Controlled by `allow_invalid` config option:
- `allow_invalid = false` (default): Strict parsing, fail on errors
- `allow_invalid = true`: Skip invalid requirements with warnings

## Serialization Rules

### Field Order

Fields serialized in this order:
1. `_version`
2. `uuid`
3. `created`
4. `tags` (if present)
5. `parents` (if present)

### Omission Rules

- `tags`: Omitted if empty
- `parents`: Omitted if empty

### Formatting

- YAML indentation: 2 spaces
- String quoting: Single quotes for strings containing special characters
- Array formatting: One element per line with `-` prefix
- Object formatting: Indented key-value pairs

### Example Output

```yaml
---
_version: '1'
uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
created: 2025-07-22T12:19:56.950194157Z
tags:
- authentication
- security
parents:
- uuid: 3fc6800c-5acc-457e-baf9-a29b42b663fd
  fingerprint: c4020419ead000e9b5f9cfd4ebf6192e73f905c27e6897548d8f6e12fd7f1356
  hrid: USR-001
---

Requirement text here.
```

## Validation

### Syntactic Validation

- Valid YAML frontmatter
- Valid Markdown body (CommonMark)
- Correct delimiters

### Semantic Validation

- Required fields present
- Field types correct
- UUID format valid
- Timestamp format valid
- HRID format valid (in parent references)
- Fingerprint format valid (64-char hex)

### Referential Integrity

- Parent UUIDs reference existing requirements
- No self-references (requirement is not its own parent)
- No duplicate UUIDs across all requirements

### Configuration-Based Validation

- HRID KIND in `allowed_kinds` (if configured)
- File follows naming convention (if `allow_unrecognised = false`)

## Canonical Example

```markdown
---
_version: '1'
uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
created: 2025-07-22T12:19:56.950194157Z
tags:
- authentication
- security
- high-priority
parents:
- uuid: 3fc6800c-5acc-457e-baf9-a29b42b663fd
  fingerprint: c4020419ead000e9b5f9cfd4ebf6192e73f905c27e6897548d8f6e12fd7f1356
  hrid: USR-001
- uuid: 7a8f9e2b-1c3d-4e5f-6a7b-8c9d0e1f2a3b
  fingerprint: a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456
  hrid: USR-003
---
# SYS-001 Email Validation

The system shall validate user email addresses according to RFC 5322.

## Rationale

Email validation ensures that user accounts can be contacted and that
authentication tokens can be delivered reliably.

## Acceptance Criteria

- Email addresses must match RFC 5322 format
- Invalid email addresses must be rejected with clear error message
- Validation must occur before account creation

## References

- RFC 5322: Internet Message Format
- OWASP Email Validation Guidelines
```

## Summary

**File format**:
- Markdown (`.md`) files with UTF-8 encoding
- YAML frontmatter enclosed in `---` delimiters
- CommonMark markdown body

**Required frontmatter fields**:
- `_version`: Schema version (currently `"1"`)
- `uuid`: Unique identifier (UUID v4)
- `created`: Creation timestamp (ISO 8601 with UTC)

**Optional frontmatter fields**:
- `tags`: Array of tags
- `parents`: Array of parent objects (uuid, fingerprint, hrid)

**Validation**:
- Strict by default
- Controlled by `allow_invalid` config option
- Includes syntactic, semantic, and referential checks

## Next Steps

- See [CLI Command Reference](./cli.md) for working with requirements
- See [Configuration Reference](./configuration.md) for config options
- Review [Working with Requirements](../working-with-requirements/file-format.md) for practical examples