Dual-control approvals for Deadlines + Official Court Events (4-eye principle) #3
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
Today any team member with project visibility can create, edit, complete or delete a Frist or Termin. For HLC's regulated practice that's too loose — a single mistake or unauthorised edit on a Frist can cascade into a missed deadline with malpractice exposure. m wants a 4-eye principle enforced on both entity types: every state-changing action submitted by one person must be signed off by a qualified second person before the change becomes "complete".
Goals
Locked design constraints (m, 2026-05-06)
Out of scope (v1)
Open design questions (for inventor — m will answer in design pass)
partner/senior-attorney/attorney/senior-PA/PA/paralegal. Where do they live —paliad.user_rolestable, an enum on team membership, an array on user profile? Are roles global (firm-wide), per-team, or per-project?/inboxpage, both, or one? Existing deadline reminder mail flow is unrelated — keep distinct or share infrastructure?paliad.deadline_eventsfor chronology. Should approvals piggyback on that, or get a dedicatedpaliad.approvalstable? Both names must surface in views.can_see_project()with acan_approve_in_project()companion, or push the gating into the application layer?created_by/approved_by. Backfillcreated_byfrom audit log if available, leaveapproved_byNULL with a "legacy — pre-approval" marker?References
paliad.deadline_events— existing audit trail (chronology source)paliad.can_see_project()— team-based RLS functioninternal/services/deadline_service.go,internal/services/appointment_service.go— service layerinternal/services/event_deadline_service.go— unified Deadlines + Termine read path (good integration point)paliad.projects— project hierarchy + team membership (RLS foundation)Inventor brief
mai/cronus/inventor-approvals(head will scope; cronus may rename — head should verify withgit -C worktree branch --show-current)docs/design-approvals-2026-05-06.mdarchiving the locked constraints, open-question answers from m, role taxonomy, rule grammar, schema sketch, migration plan, RLS plan, UI sketch (inbox + pending-state badges), implementation step order./mai-codershift unless m gives explicit go on the design.Inventor design committed @
7d1ddb9—docs/design-approvals-2026-05-06.md(828 lines).m's locked answers (2026-05-06) and design summary:
paliad.project_teams.roleper-project (NO new firm-wide column). Addssenior_pavalue to enum.Plus m's interjection: pending state visualised everywhere — list views, agenda, dashboard traffic-light, project detail, CalDAV (`[PENDING] ` title prefix), email reminders. Silence on pending creates more risk than visible-but-flagged.
Schema: migration 054 adds (1)
senior_pato project_teams.role CHECK, (2)paliad.approval_role_level()SQL function, (3)paliad.approval_policies(8 rows max per project), (4)paliad.approval_requests(with pre_image jsonb for revert-on-reject), (5)approval_status/pending_request_id/approved_by/approved_atcolumns on deadlines + appointments, (6)appointments.completed_at(new — needed for appointment:complete lifecycle).8-commit implementation phasing: schema → ApprovalService core → wire into Deadline+Appointment services → policy authoring page → inbox → pending pills → CalDAV+email integration → Verlauf rendering. Each commit testable in isolation.
Inventor recommends cronus same worktree for the impl shift. Alternative: split into cronus (commits 1-3 schema+service core) then curie/fritz (commits 4-8 UI). Head decides.
Inventor parked. Awaiting m go/no-go before any coder shift.