refactor(backend): extract brief guards into Domain/Letters/BriefRules.cs (RB-30)
BriefStore's five guard decisions (Save, Submit, Send, and 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. A spec could not exercise the decision without a booted host and a real SQLite file. Extract the guards into a pure Domain/Letters/BriefRules.cs. BriefStore keeps its lock, its Db.Create(), its static shape, and every method signature — only the if cascades move. Add BriefRuleTests.cs (29 assertions, ~120 ms, no host boot) covering every branch, including the rejected-to-draft reopen on save, the required-filled gate on submit, and the non-drafter and self-review denials. The existing host-booting brief endpoint tests are unchanged and still pass, proving the extraction preserved behaviour. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -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; 238 backend behaviours across 41 test
|
||||
9 contexts; 259 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
|
||||
|
||||
Reference in New Issue
Block a user