feat(fp): WP-23 — org-template backend + admin role

Second template axis (org identity: letterhead, footer, signature,
margins) server-side: OrgTemplateStore with JSON version history,
publish/rollback, sent-brief version pinning, admin role + capability,
5 admin endpoints, org-logo upload category. FE seam widened only
(Role/Capability unions, interceptor); WP-24/26 consume it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
eho
2026-07-05 11:17:05 +02:00
co-authored by Claude Fable 5
parent 44eb2d2186
commit 5a610c10f0
31 changed files with 5017 additions and 1834 deletions
+34 -1
View File
@@ -151,10 +151,43 @@ public sealed record BriefDto(
// (PRD-0002 phase P1) — the FE renders these, it never recomputes them.
public sealed record BriefDecisionsDto(bool CanEdit, bool CanApprove, bool CanReject, bool CanSend);
public sealed record BriefViewDto(BriefDto Brief, IReadOnlyList<LibraryPassageDto> AvailablePassages, BriefDecisionsDto Decisions);
// The brief's screen DTO also carries the org template it renders with (WP-23):
// the sub-org's current PUBLISHED version — or, once sent, the version pinned at
// send time (sent letters are immutable; a republish never re-renders them).
public sealed record BriefViewDto(
BriefDto Brief, IReadOnlyList<LibraryPassageDto> AvailablePassages, BriefDecisionsDto Decisions,
OrgTemplateDto OrgTemplate);
public sealed record SaveBriefRequest(IReadOnlyList<LetterSectionDto> Sections);
public sealed record RejectBriefRequest(string Comments);
// PRD-0002 §6: coarse, role-derived capabilities for nav/menu-level checks.
public sealed record MeDto(IReadOnlyList<string> Capabilities);
// --- Organization templates (WP-23, Brief v2 PRD §3) ---
// The second template axis: appearance/identity per sub-organization (letterhead,
// footer, signature, margins). Orthogonal to the case-type template (sections +
// placeholders); the two only meet at render time.
public sealed record MarginsDto(int TopMm, int RightMm, int BottomMm, int LeftMm);
// Version: 0 = a draft (work in progress), n>0 = the published snapshot it is.
public sealed record OrgTemplateDto(
string SubOrgId, string OrgName, string ReturnAddress, string? LogoDocumentId,
string FooterContact, string FooterLegal,
string SignatureName, string SignatureRole, string SignatureClosing,
MarginsDto Margins, int Version = 0);
public sealed record OrgTemplateVersionDto(int Version, string PublishedAt, OrgTemplateDto Template);
// Screen DTO for the admin editor: the editable draft, what's live, the append-only
// history, and the publish-impact count ("dit raakt N nog niet verzonden brieven").
public sealed record OrgTemplateAdminViewDto(
OrgTemplateDto Draft, int PublishedVersion,
IReadOnlyList<OrgTemplateVersionDto> History, int UnsentBriefs);
public sealed record SubOrgSummaryDto(string SubOrgId, string OrgName, int PublishedVersion);
public sealed record SaveOrgTemplateRequest(OrgTemplateDto Draft);
public sealed record PublishOrgTemplateResponse(int Version, int AffectedUnsentBriefs);