5.1.1 Officers Services
Officer lifecycle operations are divided between versioned workflow orchestration and reusable domain services.
Service map
| Service | Responsibility |
|---|---|
OfficerManagerInterface |
Shared release and office-wide recalculation contract |
DefaultOfficerManager |
ActiveWindow, reporting, role, warrant-cancellation, and release implementation |
OfficerWorkflowActions |
Workflow-callable mutations and notification-variable preparation |
OfficerAssignmentWorkflowActions |
Atomic assignment edits, warrant-extension requests, and update notification variables |
OfficerWorkflowConditions |
Office/warrant/assignment conditions used by definitions |
OfficersWorkflowProvider |
Registers triggers, actions, conditions, and entities |
OfficersNavigationProvider |
Plugin navigation contribution |
OfficersViewCellProvider |
Branch/member detail cells |
Services/Api/* |
Read-only department, office, roster, and branch API projections |
Manager contract
release() ends one assignment with the acting member, effective date, reason, and release status. It coordinates ActiveWindow changes, granted-role cleanup, required-warrant cancellation, and workflow event dispatch.
recalculateOfficersForOffice() revisits current and upcoming assignments after deputy_to_id, reports_to_id, or grants_role_id changes. Its ServiceResult includes counts or a bounded failure reason.
The interface intentionally has no hire method. New hires run through the versioned officers-hire workflow so conflict handling, warrant requests, roles, and notifications remain restartable and auditable.
Assignment update contract
officer-assignment-update.json is an active ephemeral workflow triggered by Officers.AssignmentUpdateRequested. Its trigger accepts officerId, actorId, normalized startOn and nullable expiresOn dates, emailAddress, deputyDescription, and termNote.
The default node sequence is:
Officers.UpdateOfficerAssignmentatomically updates the assignment and linked role, records a required term note, shortens any active current warrant that outlasts an earlier non-past end, and handles past-end warrant termination. Its result includes the officer/member/office/branch IDs, change flags,changeSummary,termChangeNote, and an initialwarrantMessage.Officers.RequestWarrantExtensionreceives the officer, actor, and initial warrant message. If the current warrant ends before the term, it requests coverage beginning the following day and ending at the earlier of the revised term end or the available warrant-period end. It returns whether a request was created, the final member-facing warrant message, and a warning when the period leaves part of the term uncovered.Officers.PrepareAssignmentUpdateNotificationVarsloads tenant-local names and the member-account email, formats the term dates, then combines the update summaries with the warrant result.Core.SendEmailrenders the tenant-editableofficer-assignment-updated-notificationtemplate. Supported conditional blocks suppress empty term-note and warrant-status sections.
Keep the first node’s assignment, role, note, and warrant-shortening or retroactive warrant mutations in one database transaction. Keep warrant-extension requests and notification preparation as distinct nodes so deployments can customize them. Ephemeral workflows do not add a transaction around the complete graph, so later nodes cannot roll back an already committed assignment update. A complete update returns workflowResult.success = true and updated = true; expected post-update failures also include warning details so the controller can report saved-with-warning and avoid a duplicate update retry.
Transaction and context rules
- The caller/workflow must already be in the correct tenant context.
- Keep all loaded member, branch, office, role, warrant, and workflow records on that connection.
- Treat a failed assignment-update result as a domain failure and stop before follow-up work. After that update commits, route expected extension or notification failures to a warning end and continue only the explicitly configured safe follow-up path.
- Action error ports receive normalized
success: falseresults. A thrown exception fails the ephemeral run, so actions with an expected warning path must normalize their operational failures. - Use
WarrantManagerInterfacerather than editing warrants. - Use
ActiveWindowManagerInterfacerather than inventing status/date calculations. - Format notification dates before passing variables to the mail action.
- Do not set a granted role’s revoker while merely changing a future/current term window; a revoker removes the permission immediately.
- Keep the linked role synchronized with changed term dates. An issued current warrant may be shortened to a revised term end but must never be lengthened by the assignment action; longer coverage requires the separate request action.
- Treat pending-warrant reconciliation as a core manager contract, not an officer-only rule. Identity is the null-safe entity type, entity ID, member ID, and member-role ID tuple. An exact normalized request reuses the in-flight warrant; changed name or dates within that identity replace it in a fresh roster with fresh approvals. Use
withdrawPendingRequests()when no replacement coverage is needed. Shared old rosters remain active while any pending items remain, and fully superseded rosters are marked replaced while their approval workflows are cancelled. - Past-end corrections must record one effective timestamp and explain in the term note that access and warrant authority remained valid until that correction was recorded.
Extending officer behavior
Add reusable calculations to the manager, workflow-specific adapters to OfficerWorkflowActions, and declarative branching to the JSON definition. Register new action/condition metadata through OfficersWorkflowProvider. Keep authorization in controllers/policies; service availability is not permission.
Verification
Test the manager directly for release/recalculation edge cases, then test the workflow for orchestration and failure handling. Assignment-update coverage should include blank-email assignments, start-only/end-only/both date changes, required-note rollback, date ordering, same-day versus past-end behavior, role-window synchronization without revocation, current-warrant shortening without lengthening, exact-pending reuse, changed-pending replacement, partially covering and absent warrant periods, uncovered-term warnings, member-account notification variables, ephemeral execution, and tenant isolation.