feat: implement permissions and actions management
- Add permissions logic for status options in corrective actions. - Create tests for permissions functionality. - Implement queries for user authentication and actions management. - Develop Actions page to display and manage corrective actions. - Create authentication pages for login, setup, and password reset. - Add IncidentDetail page to view incident details and associated actions. - Implement Settings page for user management and password changes.
This commit is contained in:
1 parent
708da6b9f7
commit
3f6dff5f24
94 files changed
+7213
-643
No files matched your search
@@ -0,0 +1,55 @@
|
||||
// Incident status workflow, shared so the web app can show the same options and reasons the API enforces.
|
||||
import type { ActionStatus } from './api-types.ts'
|
||||
import { hasRole, type IncidentStatus, type Role, type Severity } from './enums.ts'
|
||||
|
||||
export interface Transition {
|
||||
from: IncidentStatus
|
||||
to: IncidentStatus
|
||||
minRole: Role
|
||||
label: string
|
||||
}
|
||||
|
||||
export const transitions: Transition[] = [
|
||||
{ from: 'reported', to: 'triage', minRole: 'supervisor', label: 'Start triage' },
|
||||
{ from: 'triage', to: 'investigation', minRole: 'supervisor', label: 'Start investigation' },
|
||||
{ from: 'triage', to: 'actions', minRole: 'supervisor', label: 'Skip to corrective actions' },
|
||||
{ from: 'triage', to: 'closed', minRole: 'supervisor', label: 'Close: no further action' },
|
||||
{ from: 'investigation', to: 'actions', minRole: 'supervisor', label: 'Move to corrective actions' },
|
||||
{ from: 'actions', to: 'investigation', minRole: 'supervisor', label: 'Back to investigation' },
|
||||
{ from: 'actions', to: 'verification', minRole: 'supervisor', label: 'Send for verification' },
|
||||
{ from: 'verification', to: 'actions', minRole: 'safety_manager', label: 'Return to actions' },
|
||||
{ from: 'verification', to: 'closed', minRole: 'safety_manager', label: 'Verify and close' },
|
||||
{ from: 'closed', to: 'investigation', minRole: 'safety_manager', label: 'Reopen' },
|
||||
]
|
||||
|
||||
export interface WorkflowFacts {
|
||||
severity: Severity
|
||||
rootCauseCount: number
|
||||
actionStatuses: ActionStatus[]
|
||||
}
|
||||
|
||||
/** Why a transition isn't possible yet, or undefined if it is. */
|
||||
export function transitionBlocker(transition: Transition, facts: WorkflowFacts): string | undefined {
|
||||
const live = facts.actionStatuses.filter((status) => status !== 'cancelled')
|
||||
if (transition.from === 'triage' && transition.to === 'closed' && (facts.severity === 'high' || facts.severity === 'critical')) {
|
||||
return 'High and critical incidents must be investigated before closing'
|
||||
}
|
||||
if (transition.to === 'actions' && transition.from === 'investigation' && facts.rootCauseCount === 0) {
|
||||
return 'Record at least one root cause first'
|
||||
}
|
||||
if (transition.to === 'verification') {
|
||||
if (live.length === 0) return 'Add at least one corrective action first'
|
||||
if (live.some((status) => status === 'open' || status === 'in_progress')) return 'All corrective actions must be done first'
|
||||
}
|
||||
if (transition.from === 'verification' && transition.to === 'closed' && live.some((status) => status !== 'verified')) {
|
||||
return 'Verify every corrective action first'
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
/** Transitions from `status` that `role` may perform, with blockers explained. */
|
||||
export function availableTransitions(status: IncidentStatus, role: Role, facts: WorkflowFacts) {
|
||||
return transitions
|
||||
.filter((t) => t.from === status && hasRole(role, t.minRole))
|
||||
.map((t) => ({ to: t.to, label: t.label, blockedReason: transitionBlocker(t, facts) }))
|
||||
}
|
||||
Reference in new issue
Block a user