Merge RB-30 — extract BriefStore's guards into Domain/Letters/BriefRules.cs

TE-008: five guard decisions in BriefStore (Save, Submit, Send, the shared
Approve/Reject review path) were pure functions of status tag, actor role and
entity completeness, but each sat inside a lock-held, DB-opening method, so a
spec could not exercise a decision without a booted host and a real SQLite
file. BriefRules.cs holds the five pure statics; BriefStore keeps its lock,
its Db.Create(), its static shape and every method signature. 29 new
free-running unit assertions in BriefRuleTests.cs; the existing host-booting
brief endpoint tests are unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

# Conflicts:
#	docs/project/refactor-backlog-setup/refactor-backlog/99-backlog.md
#	libs/shared/docs/behaviour-spec.mdx
This commit is contained in:
eho
2026-08-28 08:08:00 +02:00
6 changed files with 456 additions and 13 deletions
+25 -1
View File
@@ -21,7 +21,7 @@ tested where._
Every bullet below is a real test name from the suite — an `it()` title (frontend) or a test
method name (backend), read as a sentence. Nothing here is hand-written prose: this page
**is** the suite, reshaped for a business reader. 467 frontend behaviours across
9 contexts; 240 backend behaviours across 41 test
9 contexts; 261 backend behaviours across 42 test
classes.
## Frontend (by context)
@@ -1017,6 +1017,30 @@ classes.
- Me returns no capabilities for drafter and the brief set for approver
- Reset recreates a fresh draft with locked prefilled sections
### BriefRuleTests
- A drafter may save a draft or rejected letter
- A drafter may not save a non editable letter
- A non drafter is forbidden to save regardless of status
- Saving a rejected letter reopens it to draft
- Saving a draft letter leaves its status unchanged
- No required sections means nothing to fill
- An optional empty section does not block submission
- A required section with a block is filled
- A required section with no blocks is not filled
- One unfilled required section blocks submission even if others are filled
- A drafter may submit a filled draft
- A drafter may not submit an unfilled draft
- A drafter may not submit a letter that is not a draft
- A non drafter is forbidden to submit even a filled draft
- An approved letter may be sent
- Only an approved letter may be sent
- An approver may decide a submitted letter drafted by someone else
- A drafter may not approve or reject
- An approver may not decide a letter they drafted themselves
- An approver may not decide a letter that is not submitted
- Entitlement is checked before status forbidden wins over conflict
### DiplomaRuleTests
- Profession is derived from program