@openauditmodel/cli 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -6
- package/dist/conformance/src/cli.js +113 -6
- package/dist/conformance/src/cli.js.map +1 -1
- package/dist/conformance/src/privacy/types.d.ts +19 -0
- package/dist/conformance/src/privacy/types.js +8 -0
- package/dist/conformance/src/privacy/types.js.map +1 -1
- package/dist/conformance/src/profiles/coverage.d.ts +62 -0
- package/dist/conformance/src/profiles/coverage.js +114 -0
- package/dist/conformance/src/profiles/coverage.js.map +1 -0
- package/package.json +7 -2
- package/profiles/README.md +42 -0
- package/profiles/api-and-integration-management/0.1/profile.json +258 -0
- package/profiles/backup-and-recovery/0.1/profile.json +178 -0
- package/profiles/customer-and-account-management/0.1/profile.json +237 -0
- package/profiles/deployment-and-change-management/0.1/profile.json +298 -0
- package/profiles/document-management/0.1/profile.json +170 -0
- package/profiles/financial-transaction-management/0.1/profile.json +247 -0
- package/profiles/identity-and-access-management/0.1/profile.json +120 -0
- package/profiles/incident-management/0.1/profile.json +256 -0
- package/profiles/incident-management/0.2/profile.json +287 -0
- package/profiles/incident-management/README.md +39 -21
- package/profiles/incident-management/profile.json +37 -6
- package/profiles/message-broker-management/0.1/profile.json +399 -0
- package/profiles/secrets-and-key-management/0.1/profile.json +219 -0
- package/semantic-conventions/README.md +15 -10
- package/semantic-conventions/backup-and-recovery.md +124 -0
- package/semantic-conventions/customer-and-account.md +133 -0
- package/semantic-conventions/financial-transactions.md +128 -0
- package/semantic-conventions/message-brokers.md +128 -0
- package/semantic-conventions/secrets-and-keys.md +132 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
{
|
|
2
|
+
"profileVersion": "0.1",
|
|
3
|
+
"name": "incident-management",
|
|
4
|
+
"version": "0.1",
|
|
5
|
+
"status": "experimental",
|
|
6
|
+
"coreVersions": ["0.1"],
|
|
7
|
+
"title": "Incident Management Profile",
|
|
8
|
+
"description": "Additional conformance requirements for the lifecycle of incidents, problems and corrective actions: raising, reprioritising, assigning, escalating, resolving, closing, cancelling and reopening a case, recording a root cause analysis, and opening and verifying a corrective action. Every requirement adds to the OpenAuditModel Core Specification; none relaxes it. High-volume monitoring, timeline and read events such as monitoring.alert.raise, incident.note.create and incident.case.view are deliberately not governed.",
|
|
9
|
+
"rules": [
|
|
10
|
+
{
|
|
11
|
+
"id": "INC-CORE-001",
|
|
12
|
+
"description": "Every governed incident, problem and corrective-action operation records the authorization decision that permitted it and the lifecycle state the record was left in.",
|
|
13
|
+
"rationale": "A case record is rewritten by many hands over days or weeks, and the trail is read long after everyone involved has moved on. Without a recorded decision nothing distinguishes a transition policy allowed from one an operator forced through a console. Without the resulting state, a reviewer replaying the events cannot say what condition the case was actually in at any point, because the profile cannot look inside `/change/after` and a consumer would have to parse a free-form object to find out. Recording the state in one typed, namespaced field is what makes the sequence readable and indexable at all.",
|
|
14
|
+
"severity": "error",
|
|
15
|
+
"events": [
|
|
16
|
+
"corrective-action.close",
|
|
17
|
+
"corrective-action.open",
|
|
18
|
+
"corrective-action.verify",
|
|
19
|
+
"incident.assignment.change",
|
|
20
|
+
"incident.case.cancel",
|
|
21
|
+
"incident.case.close",
|
|
22
|
+
"incident.case.create",
|
|
23
|
+
"incident.case.reopen",
|
|
24
|
+
"incident.case.resolve",
|
|
25
|
+
"incident.major.declare",
|
|
26
|
+
"incident.priority.change",
|
|
27
|
+
"incident.rca.approve",
|
|
28
|
+
"incident.rca.create",
|
|
29
|
+
"incident.rca.update",
|
|
30
|
+
"problem.case.close",
|
|
31
|
+
"problem.case.create"
|
|
32
|
+
],
|
|
33
|
+
"requiredPaths": ["/authorization"],
|
|
34
|
+
"requiredMetadata": [
|
|
35
|
+
{
|
|
36
|
+
"path": "/incident/status",
|
|
37
|
+
"type": "string"
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"id": "INC-CORE-002",
|
|
43
|
+
"description": "A governed incident operation should carry the correlation identifier shared by the rest of the handling and name the resources the case is about.",
|
|
44
|
+
"rationale": "Incident handling is the clearest example in this specification of an operation that is not one event. Raising, escalating, resolving, analysing, remediating and closing are separate events emitted hours or weeks apart, often by different applications and principals, and they are assembled by correlation rather than by timestamp. These are recommended and not required because a conforming producer may have no correlation facility at all, and because an incident about a process rather than a system legitimately has no affected resource to name. A missing correlation identifier should prompt a question, not fail a build.",
|
|
45
|
+
"severity": "warning",
|
|
46
|
+
"events": [
|
|
47
|
+
"corrective-action.close",
|
|
48
|
+
"corrective-action.open",
|
|
49
|
+
"corrective-action.verify",
|
|
50
|
+
"incident.assignment.change",
|
|
51
|
+
"incident.case.cancel",
|
|
52
|
+
"incident.case.close",
|
|
53
|
+
"incident.case.create",
|
|
54
|
+
"incident.case.reopen",
|
|
55
|
+
"incident.case.resolve",
|
|
56
|
+
"incident.major.declare",
|
|
57
|
+
"incident.priority.change",
|
|
58
|
+
"incident.rca.approve",
|
|
59
|
+
"incident.rca.create",
|
|
60
|
+
"incident.rca.update",
|
|
61
|
+
"incident.sla.breach",
|
|
62
|
+
"problem.case.close",
|
|
63
|
+
"problem.case.create"
|
|
64
|
+
],
|
|
65
|
+
"recommendedPaths": ["/request/correlationId", "/relatedResources"]
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"id": "INC-CREATE-001",
|
|
69
|
+
"description": "Raising a case should record how the condition was noticed, when it began, and how badly it hurt.",
|
|
70
|
+
"rationale": "Detection time and business impact are known accurately only at the moment a case is opened, and are reconstructed badly or not at all afterwards. They are recommended rather than required because impact and urgency scales differ between organizations and some cases are raised by a customer with no measurable detection point, and a requirement that could not be met honestly would be satisfied with a placeholder instead.",
|
|
71
|
+
"severity": "warning",
|
|
72
|
+
"events": ["incident.case.create", "problem.case.create"],
|
|
73
|
+
"recommendedPaths": [
|
|
74
|
+
"/reason",
|
|
75
|
+
"/metadata/incident/detectedAt",
|
|
76
|
+
"/metadata/incident/impact",
|
|
77
|
+
"/metadata/incident/urgency"
|
|
78
|
+
]
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"id": "INC-STATE-001",
|
|
82
|
+
"description": "An operation that moves a case between lifecycle states records the transition as a before and after.",
|
|
83
|
+
"rationale": "The state a case ends in is not the same fact as the state it came from. Only the transition shows that a case went from open to closed rather than from cancelled to closed, and only the transition makes an impossible sequence visible — a closure of something never resolved, a resolution of something already closed. An event that records the destination alone is a snapshot, and a trail of snapshots cannot be replayed.",
|
|
84
|
+
"severity": "error",
|
|
85
|
+
"events": [
|
|
86
|
+
"incident.priority.change",
|
|
87
|
+
"incident.assignment.change",
|
|
88
|
+
"incident.major.declare",
|
|
89
|
+
"incident.case.resolve",
|
|
90
|
+
"incident.case.close",
|
|
91
|
+
"incident.case.cancel",
|
|
92
|
+
"problem.case.close",
|
|
93
|
+
"corrective-action.close"
|
|
94
|
+
],
|
|
95
|
+
"requiredPaths": ["/change"]
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"id": "INC-STATE-002",
|
|
99
|
+
"description": "A transition that reflects a judgement — reprioritisation, escalation to major, closure or cancellation — records why it was made.",
|
|
100
|
+
"rationale": "These are the transitions where the record and the decision can diverge. Downgrading a priority, declaring a major incident, closing a case or abandoning one are all defensible and all abusable, and the difference is the justification. A case closed with no stated reason is indistinguishable from a case closed to make a queue look shorter, and that ambiguity is precisely what an incident trail exists to remove. Resolution and reassignment are excluded because they carry their own structured explanation.",
|
|
101
|
+
"severity": "error",
|
|
102
|
+
"events": [
|
|
103
|
+
"incident.priority.change",
|
|
104
|
+
"incident.major.declare",
|
|
105
|
+
"incident.case.close",
|
|
106
|
+
"incident.case.cancel",
|
|
107
|
+
"problem.case.close",
|
|
108
|
+
"corrective-action.close"
|
|
109
|
+
],
|
|
110
|
+
"requiredPaths": ["/reason"]
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"id": "INC-PRIORITY-001",
|
|
114
|
+
"description": "Raising a case, reassessing its priority, escalating it to major and reporting a missed commitment all record the priority in force.",
|
|
115
|
+
"rationale": "Priority is the field every downstream obligation hangs from: who is paged, how fast a response is owed, whether an escalation was warranted and whether a service commitment was met. Recorded only at creation, it cannot answer any question about the middle of the incident. The profile requires the field and deliberately does not close its vocabulary, because priority scales are an organizational choice and a profile that imposed one would be describing a single service desk rather than a domain.",
|
|
116
|
+
"severity": "error",
|
|
117
|
+
"events": [
|
|
118
|
+
"incident.case.create",
|
|
119
|
+
"problem.case.create",
|
|
120
|
+
"incident.priority.change",
|
|
121
|
+
"incident.major.declare",
|
|
122
|
+
"incident.sla.breach"
|
|
123
|
+
],
|
|
124
|
+
"requiredMetadata": [
|
|
125
|
+
{
|
|
126
|
+
"path": "/incident/priority",
|
|
127
|
+
"type": "string"
|
|
128
|
+
}
|
|
129
|
+
]
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"id": "INC-ASSIGN-001",
|
|
133
|
+
"description": "Handing a case or a corrective action to someone names the principal who became accountable for it.",
|
|
134
|
+
"rationale": "Accountability that is not recorded is not accountability. A reassignment or a corrective action opened without naming who now owns it produces a trail that shows work being moved and never shows who was asked to do it, which is the one question a follow-up review always asks.The principal is recorded in namespaced metadata rather than in `/subject`, because [actor-model.md](../../specification/actor-model.md) §5 defines `subject` as the principal *on whose behalf* the actor acted, and forbids its use as a generic target. A grantee or assignee is neither. This follows the identity profile, which records a role in `/metadata/role/id` for the same reason.",
|
|
135
|
+
"severity": "error",
|
|
136
|
+
"events": ["incident.assignment.change", "corrective-action.open"],
|
|
137
|
+
"requiredMetadata": [
|
|
138
|
+
{
|
|
139
|
+
"path": "/incident/assigneeId",
|
|
140
|
+
"type": "string"
|
|
141
|
+
}
|
|
142
|
+
],
|
|
143
|
+
"recommendedPaths": ["/reason"]
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"id": "INC-RESOLVE-001",
|
|
147
|
+
"description": "Resolving a case records what kind of resolution it was.",
|
|
148
|
+
"rationale": "A workaround, a permanent fix, a duplicate and a condition that disappeared on its own are four different outcomes with four different follow-up obligations, and a status of `resolved` collapses all of them into one word. The distinction is what tells a later reader whether the underlying fault is still present in production. The recommended fields point at the rest of the story: when the service was actually restored, and which corrective action carries the remaining work.",
|
|
149
|
+
"severity": "error",
|
|
150
|
+
"events": ["incident.case.resolve"],
|
|
151
|
+
"requiredMetadata": [
|
|
152
|
+
{
|
|
153
|
+
"path": "/incident/resolutionType",
|
|
154
|
+
"type": "string"
|
|
155
|
+
}
|
|
156
|
+
],
|
|
157
|
+
"recommendedPaths": [
|
|
158
|
+
"/reason",
|
|
159
|
+
"/metadata/incident/resolvedAt",
|
|
160
|
+
"/metadata/incident/correctiveAction/id"
|
|
161
|
+
]
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"id": "INC-CLOSE-001",
|
|
165
|
+
"description": "When the producer has declared that closing this case required approval, the closure records the approval decision.",
|
|
166
|
+
"rationale": "Whether a closure needs a second pair of eyes is an organizational policy, not a fact this specification can decide: a service desk closing thousands of routine tickets a week and a safety board closing a reportable incident are both conforming, and requiring approval for every closure would describe one of them and be switched off by the other. The producer declares the obligation and the profile enforces the consequence. The rule requires the decision to be recorded, not to be favourable: an event whose approval is still pending or was rejected and whose outcome is success describes a control bypass, and the trail must be able to say so.",
|
|
167
|
+
"severity": "error",
|
|
168
|
+
"events": [
|
|
169
|
+
"incident.case.close",
|
|
170
|
+
"incident.case.cancel",
|
|
171
|
+
"problem.case.close",
|
|
172
|
+
"corrective-action.close"
|
|
173
|
+
],
|
|
174
|
+
"when": {
|
|
175
|
+
"path": "/metadata/incident/approvalRequired",
|
|
176
|
+
"equals": true
|
|
177
|
+
},
|
|
178
|
+
"requiredPaths": ["/approval/status"],
|
|
179
|
+
"recommendedPaths": ["/approval/approvers", "/approval/approvedAt"]
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"id": "INC-REOPEN-001",
|
|
183
|
+
"description": "Reopening a closed case is a new lifecycle transition, recorded with the transition it made and the reason it was made.",
|
|
184
|
+
"rationale": "A reopen is the strongest evidence an incident trail can carry that a resolution was wrong, so it is the transition most worth recording well. It is treated as a new auditable step and nothing more: the earlier closure and any approval attached to it remain valid historical records of what was decided at that time, and this profile does not assert that a reopen retracts them or that a fresh approval is owed, because that is an organizational process this specification does not make. Reusing the original correlation identifier, recommended by INC-CORE-002, is what keeps the whole handling readable as one story rather than two unrelated cases.",
|
|
185
|
+
"severity": "error",
|
|
186
|
+
"events": ["incident.case.reopen"],
|
|
187
|
+
"requiredPaths": ["/change", "/reason"],
|
|
188
|
+
"recommendedPaths": ["/evidence"]
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
"id": "INC-RCA-001",
|
|
192
|
+
"description": "A root cause analysis event records the method the analysis was performed with.",
|
|
193
|
+
"rationale": "An analysis is trustworthy in proportion to how it was conducted, and the method is the only part of that a machine-readable trail can carry. Two organizations using different techniques still both know which one they used, so the field is universal even though its vocabulary is not, and it is left open for that reason. The profile does not attempt to require the analysis document itself: the rule language cannot inspect the contents of `/evidence`, so a supporting record is recommended by INC-EVIDENCE-001 rather than dishonestly claimed to be enforced.",
|
|
194
|
+
"severity": "error",
|
|
195
|
+
"events": ["incident.rca.approve", "incident.rca.create", "incident.rca.update"],
|
|
196
|
+
"requiredMetadata": [
|
|
197
|
+
{
|
|
198
|
+
"path": "/incident/rca/method",
|
|
199
|
+
"type": "string"
|
|
200
|
+
}
|
|
201
|
+
]
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"id": "INC-RCA-002",
|
|
205
|
+
"description": "Approving a root cause analysis records the approval decision.",
|
|
206
|
+
"rationale": "This event is an approval, so requiring the approval state is not an added process obligation but a requirement that the event describe itself. An approval event with no recorded decision states that an analysis was reviewed without stating what the review concluded. The status is required rather than required to be `approved`, so that a rejection or a lapsed request stays recordable and visible.",
|
|
207
|
+
"severity": "error",
|
|
208
|
+
"events": ["incident.rca.approve"],
|
|
209
|
+
"requiredPaths": ["/approval/status"],
|
|
210
|
+
"recommendedPaths": ["/approval/approvers", "/approval/approvedAt"]
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"id": "INC-CAPA-001",
|
|
214
|
+
"description": "Verifying a corrective action records how the verification was carried out.",
|
|
215
|
+
"rationale": "Verification is the step that turns a promise into evidence, and an unqualified assertion that an action was verified is worth nothing: reading a ticket, watching production for a week and re-running the failure are all called verification and are not comparable. Recording the method is what lets a later reader judge whether the fix was actually demonstrated. The vocabulary is open because verification techniques are domain-specific.",
|
|
216
|
+
"severity": "error",
|
|
217
|
+
"events": ["corrective-action.verify"],
|
|
218
|
+
"requiredMetadata": [
|
|
219
|
+
{
|
|
220
|
+
"path": "/incident/correctiveAction/verificationMethod",
|
|
221
|
+
"type": "string"
|
|
222
|
+
}
|
|
223
|
+
],
|
|
224
|
+
"recommendedPaths": ["/metadata/incident/correctiveAction/verifiedAt"]
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
"id": "INC-SLA-001",
|
|
228
|
+
"description": "A missed service commitment names the commitment that was missed.",
|
|
229
|
+
"rationale": "A breach event that does not say what was breached records only that someone was unhappy. The commitment identifier is what lets the breach be tied to the obligation it violated and counted against it later, when the commitment itself may have been renegotiated. The profile requires the identifier and asserts nothing about durations or thresholds: the v0.1 rule language compares values for equality and cannot evaluate a numeric range, so a target is recorded as a name rather than checked as a bound. This event is excluded from INC-CORE-001 because a breach is a system observation rather than an authorized human action, and demanding an authorization decision for it would force producers to invent one.",
|
|
230
|
+
"severity": "error",
|
|
231
|
+
"events": ["incident.sla.breach"],
|
|
232
|
+
"requiredMetadata": [
|
|
233
|
+
{
|
|
234
|
+
"path": "/incident/sla/target",
|
|
235
|
+
"type": "string"
|
|
236
|
+
}
|
|
237
|
+
],
|
|
238
|
+
"recommendedPaths": ["/metadata/incident/sla/breachedAt"]
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
"id": "INC-EVIDENCE-001",
|
|
242
|
+
"description": "Root-cause and corrective-action events should reference the material that supports them.",
|
|
243
|
+
"rationale": "The analysis document, the change record and the verification report are what make an incident conclusion checkable rather than merely stated, and `/evidence` is where the core model puts references to them. This is a recommendation and not a requirement for a reason worth stating plainly: the v0.1 rule language can test that `/evidence` is present and non-empty, and cannot test that it contains an entry of any particular type. A rule that required `/evidence` would be satisfied by an unrelated reference, so the profile asks for evidence rather than pretending to verify it.",
|
|
244
|
+
"severity": "warning",
|
|
245
|
+
"events": [
|
|
246
|
+
"corrective-action.close",
|
|
247
|
+
"corrective-action.open",
|
|
248
|
+
"corrective-action.verify",
|
|
249
|
+
"incident.rca.approve",
|
|
250
|
+
"incident.rca.create",
|
|
251
|
+
"incident.rca.update"
|
|
252
|
+
],
|
|
253
|
+
"recommendedPaths": ["/evidence"]
|
|
254
|
+
}
|
|
255
|
+
]
|
|
256
|
+
}
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
{
|
|
2
|
+
"profileVersion": "0.1",
|
|
3
|
+
"name": "incident-management",
|
|
4
|
+
"version": "0.2",
|
|
5
|
+
"status": "experimental",
|
|
6
|
+
"coreVersions": ["0.1"],
|
|
7
|
+
"title": "Incident Management Profile",
|
|
8
|
+
"description": "Additional conformance requirements for the lifecycle of incidents, problems and corrective actions: raising, reprioritising, assigning, escalating, resolving, closing, cancelling and reopening a case, recording a root cause analysis, and opening and verifying a corrective action. Every requirement adds to the OpenAuditModel Core Specification; none relaxes it. High-volume monitoring, timeline and read events such as monitoring.alert.raise, incident.note.create and incident.case.view are deliberately not governed.",
|
|
9
|
+
"rules": [
|
|
10
|
+
{
|
|
11
|
+
"id": "INC-CORE-001",
|
|
12
|
+
"description": "Every governed incident, problem and corrective-action operation records the authorization decision that permitted it and the lifecycle state the record was left in.",
|
|
13
|
+
"rationale": "A case record is rewritten by many hands over days or weeks, and the trail is read long after everyone involved has moved on. Without a recorded decision nothing distinguishes a transition policy allowed from one an operator forced through a console. Without the resulting state, a reviewer replaying the events cannot say what condition the case was actually in at any point, because the profile cannot look inside `/change/after` and a consumer would have to parse a free-form object to find out. Recording the state in one typed, namespaced field is what makes the sequence readable and indexable at all.",
|
|
14
|
+
"severity": "error",
|
|
15
|
+
"events": [
|
|
16
|
+
"corrective-action.close",
|
|
17
|
+
"corrective-action.open",
|
|
18
|
+
"corrective-action.verify",
|
|
19
|
+
"incident.assignment.change",
|
|
20
|
+
"incident.case.cancel",
|
|
21
|
+
"incident.cancel",
|
|
22
|
+
"incident.case.close",
|
|
23
|
+
"incident.close",
|
|
24
|
+
"incident.case.create",
|
|
25
|
+
"incident.create",
|
|
26
|
+
"incident.case.reopen",
|
|
27
|
+
"incident.reopen",
|
|
28
|
+
"incident.case.resolve",
|
|
29
|
+
"incident.resolve",
|
|
30
|
+
"incident.major.declare",
|
|
31
|
+
"incident.priority.change",
|
|
32
|
+
"incident.rca.approve",
|
|
33
|
+
"incident.rca.create",
|
|
34
|
+
"incident.rca.update",
|
|
35
|
+
"problem.case.close",
|
|
36
|
+
"problem.close",
|
|
37
|
+
"problem.case.create",
|
|
38
|
+
"problem.create"
|
|
39
|
+
],
|
|
40
|
+
"requiredPaths": ["/authorization"],
|
|
41
|
+
"requiredMetadata": [
|
|
42
|
+
{
|
|
43
|
+
"path": "/incident/status",
|
|
44
|
+
"type": "string"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"id": "INC-CORE-002",
|
|
50
|
+
"description": "A governed incident operation should carry the correlation identifier shared by the rest of the handling and name the resources the case is about.",
|
|
51
|
+
"rationale": "Incident handling is the clearest example in this specification of an operation that is not one event. Raising, escalating, resolving, analysing, remediating and closing are separate events emitted hours or weeks apart, often by different applications and principals, and they are assembled by correlation rather than by timestamp. These are recommended and not required because a conforming producer may have no correlation facility at all, and because an incident about a process rather than a system legitimately has no affected resource to name. A missing correlation identifier should prompt a question, not fail a build.",
|
|
52
|
+
"severity": "warning",
|
|
53
|
+
"events": [
|
|
54
|
+
"corrective-action.close",
|
|
55
|
+
"corrective-action.open",
|
|
56
|
+
"corrective-action.verify",
|
|
57
|
+
"incident.assignment.change",
|
|
58
|
+
"incident.case.cancel",
|
|
59
|
+
"incident.cancel",
|
|
60
|
+
"incident.case.close",
|
|
61
|
+
"incident.close",
|
|
62
|
+
"incident.case.create",
|
|
63
|
+
"incident.create",
|
|
64
|
+
"incident.case.reopen",
|
|
65
|
+
"incident.reopen",
|
|
66
|
+
"incident.case.resolve",
|
|
67
|
+
"incident.resolve",
|
|
68
|
+
"incident.major.declare",
|
|
69
|
+
"incident.priority.change",
|
|
70
|
+
"incident.rca.approve",
|
|
71
|
+
"incident.rca.create",
|
|
72
|
+
"incident.rca.update",
|
|
73
|
+
"incident.sla.breach",
|
|
74
|
+
"problem.case.close",
|
|
75
|
+
"problem.close",
|
|
76
|
+
"problem.case.create",
|
|
77
|
+
"problem.create"
|
|
78
|
+
],
|
|
79
|
+
"recommendedPaths": ["/request/correlationId", "/relatedResources"]
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"id": "INC-CREATE-001",
|
|
83
|
+
"description": "Raising a case should record how the condition was noticed, when it began, and how badly it hurt.",
|
|
84
|
+
"rationale": "Detection time and business impact are known accurately only at the moment a case is opened, and are reconstructed badly or not at all afterwards. They are recommended rather than required because impact and urgency scales differ between organizations and some cases are raised by a customer with no measurable detection point, and a requirement that could not be met honestly would be satisfied with a placeholder instead.",
|
|
85
|
+
"severity": "warning",
|
|
86
|
+
"events": [
|
|
87
|
+
"incident.case.create",
|
|
88
|
+
"incident.create",
|
|
89
|
+
"problem.case.create",
|
|
90
|
+
"problem.create"
|
|
91
|
+
],
|
|
92
|
+
"recommendedPaths": [
|
|
93
|
+
"/reason",
|
|
94
|
+
"/metadata/incident/detectedAt",
|
|
95
|
+
"/metadata/incident/impact",
|
|
96
|
+
"/metadata/incident/urgency"
|
|
97
|
+
]
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"id": "INC-STATE-001",
|
|
101
|
+
"description": "An operation that moves a case between lifecycle states records the transition as a before and after.",
|
|
102
|
+
"rationale": "The state a case ends in is not the same fact as the state it came from. Only the transition shows that a case went from open to closed rather than from cancelled to closed, and only the transition makes an impossible sequence visible — a closure of something never resolved, a resolution of something already closed. An event that records the destination alone is a snapshot, and a trail of snapshots cannot be replayed.",
|
|
103
|
+
"severity": "error",
|
|
104
|
+
"events": [
|
|
105
|
+
"incident.priority.change",
|
|
106
|
+
"incident.assignment.change",
|
|
107
|
+
"incident.major.declare",
|
|
108
|
+
"incident.case.resolve",
|
|
109
|
+
"incident.resolve",
|
|
110
|
+
"incident.case.close",
|
|
111
|
+
"incident.close",
|
|
112
|
+
"incident.case.cancel",
|
|
113
|
+
"incident.cancel",
|
|
114
|
+
"problem.case.close",
|
|
115
|
+
"problem.close",
|
|
116
|
+
"corrective-action.close"
|
|
117
|
+
],
|
|
118
|
+
"requiredPaths": ["/change"]
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"id": "INC-STATE-002",
|
|
122
|
+
"description": "A transition that reflects a judgement — reprioritisation, escalation to major, closure or cancellation — records why it was made.",
|
|
123
|
+
"rationale": "These are the transitions where the record and the decision can diverge. Downgrading a priority, declaring a major incident, closing a case or abandoning one are all defensible and all abusable, and the difference is the justification. A case closed with no stated reason is indistinguishable from a case closed to make a queue look shorter, and that ambiguity is precisely what an incident trail exists to remove. Resolution and reassignment are excluded because they carry their own structured explanation.",
|
|
124
|
+
"severity": "error",
|
|
125
|
+
"events": [
|
|
126
|
+
"incident.priority.change",
|
|
127
|
+
"incident.major.declare",
|
|
128
|
+
"incident.case.close",
|
|
129
|
+
"incident.close",
|
|
130
|
+
"incident.case.cancel",
|
|
131
|
+
"incident.cancel",
|
|
132
|
+
"problem.case.close",
|
|
133
|
+
"problem.close",
|
|
134
|
+
"corrective-action.close"
|
|
135
|
+
],
|
|
136
|
+
"requiredPaths": ["/reason"]
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"id": "INC-PRIORITY-001",
|
|
140
|
+
"description": "Raising a case, reassessing its priority, escalating it to major and reporting a missed commitment all record the priority in force.",
|
|
141
|
+
"rationale": "Priority is the field every downstream obligation hangs from: who is paged, how fast a response is owed, whether an escalation was warranted and whether a service commitment was met. Recorded only at creation, it cannot answer any question about the middle of the incident. The profile requires the field and deliberately does not close its vocabulary, because priority scales are an organizational choice and a profile that imposed one would be describing a single service desk rather than a domain.",
|
|
142
|
+
"severity": "error",
|
|
143
|
+
"events": [
|
|
144
|
+
"incident.case.create",
|
|
145
|
+
"incident.create",
|
|
146
|
+
"problem.case.create",
|
|
147
|
+
"problem.create",
|
|
148
|
+
"incident.priority.change",
|
|
149
|
+
"incident.major.declare",
|
|
150
|
+
"incident.sla.breach"
|
|
151
|
+
],
|
|
152
|
+
"requiredMetadata": [
|
|
153
|
+
{
|
|
154
|
+
"path": "/incident/priority",
|
|
155
|
+
"type": "string"
|
|
156
|
+
}
|
|
157
|
+
]
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"id": "INC-ASSIGN-001",
|
|
161
|
+
"description": "Handing a case or a corrective action to someone names the principal who became accountable for it.",
|
|
162
|
+
"rationale": "Accountability that is not recorded is not accountability. A reassignment or a corrective action opened without naming who now owns it produces a trail that shows work being moved and never shows who was asked to do it, which is the one question a follow-up review always asks.The principal is recorded in namespaced metadata rather than in `/subject`, because [actor-model.md](../../specification/actor-model.md) §5 defines `subject` as the principal *on whose behalf* the actor acted, and forbids its use as a generic target. A grantee or assignee is neither. This follows the identity profile, which records a role in `/metadata/role/id` for the same reason.",
|
|
163
|
+
"severity": "error",
|
|
164
|
+
"events": ["incident.assignment.change", "corrective-action.open"],
|
|
165
|
+
"requiredMetadata": [
|
|
166
|
+
{
|
|
167
|
+
"path": "/incident/assigneeId",
|
|
168
|
+
"type": "string"
|
|
169
|
+
}
|
|
170
|
+
],
|
|
171
|
+
"recommendedPaths": ["/reason"]
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"id": "INC-RESOLVE-001",
|
|
175
|
+
"description": "Resolving a case records what kind of resolution it was.",
|
|
176
|
+
"rationale": "A workaround, a permanent fix, a duplicate and a condition that disappeared on its own are four different outcomes with four different follow-up obligations, and a status of `resolved` collapses all of them into one word. The distinction is what tells a later reader whether the underlying fault is still present in production. The recommended fields point at the rest of the story: when the service was actually restored, and which corrective action carries the remaining work.",
|
|
177
|
+
"severity": "error",
|
|
178
|
+
"events": ["incident.case.resolve", "incident.resolve"],
|
|
179
|
+
"requiredMetadata": [
|
|
180
|
+
{
|
|
181
|
+
"path": "/incident/resolutionType",
|
|
182
|
+
"type": "string"
|
|
183
|
+
}
|
|
184
|
+
],
|
|
185
|
+
"recommendedPaths": [
|
|
186
|
+
"/reason",
|
|
187
|
+
"/metadata/incident/resolvedAt",
|
|
188
|
+
"/metadata/incident/correctiveAction/id"
|
|
189
|
+
]
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"id": "INC-CLOSE-001",
|
|
193
|
+
"description": "When the producer has declared that closing this case required approval, the closure records the approval decision.",
|
|
194
|
+
"rationale": "Whether a closure needs a second pair of eyes is an organizational policy, not a fact this specification can decide: a service desk closing thousands of routine tickets a week and a safety board closing a reportable incident are both conforming, and requiring approval for every closure would describe one of them and be switched off by the other. The producer declares the obligation and the profile enforces the consequence. The rule requires the decision to be recorded, not to be favourable: an event whose approval is still pending or was rejected and whose outcome is success describes a control bypass, and the trail must be able to say so.",
|
|
195
|
+
"severity": "error",
|
|
196
|
+
"events": [
|
|
197
|
+
"incident.case.close",
|
|
198
|
+
"incident.close",
|
|
199
|
+
"incident.case.cancel",
|
|
200
|
+
"incident.cancel",
|
|
201
|
+
"problem.case.close",
|
|
202
|
+
"problem.close",
|
|
203
|
+
"corrective-action.close"
|
|
204
|
+
],
|
|
205
|
+
"when": {
|
|
206
|
+
"path": "/metadata/incident/approvalRequired",
|
|
207
|
+
"equals": true
|
|
208
|
+
},
|
|
209
|
+
"requiredPaths": ["/approval/status"],
|
|
210
|
+
"recommendedPaths": ["/approval/approvers", "/approval/approvedAt"]
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"id": "INC-REOPEN-001",
|
|
214
|
+
"description": "Reopening a closed case is a new lifecycle transition, recorded with the transition it made and the reason it was made.",
|
|
215
|
+
"rationale": "A reopen is the strongest evidence an incident trail can carry that a resolution was wrong, so it is the transition most worth recording well. It is treated as a new auditable step and nothing more: the earlier closure and any approval attached to it remain valid historical records of what was decided at that time, and this profile does not assert that a reopen retracts them or that a fresh approval is owed, because that is an organizational process this specification does not make. Reusing the original correlation identifier, recommended by INC-CORE-002, is what keeps the whole handling readable as one story rather than two unrelated cases.",
|
|
216
|
+
"severity": "error",
|
|
217
|
+
"events": ["incident.case.reopen", "incident.reopen"],
|
|
218
|
+
"requiredPaths": ["/change", "/reason"],
|
|
219
|
+
"recommendedPaths": ["/evidence"]
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
"id": "INC-RCA-001",
|
|
223
|
+
"description": "A root cause analysis event records the method the analysis was performed with.",
|
|
224
|
+
"rationale": "An analysis is trustworthy in proportion to how it was conducted, and the method is the only part of that a machine-readable trail can carry. Two organizations using different techniques still both know which one they used, so the field is universal even though its vocabulary is not, and it is left open for that reason. The profile does not attempt to require the analysis document itself: the rule language cannot inspect the contents of `/evidence`, so a supporting record is recommended by INC-EVIDENCE-001 rather than dishonestly claimed to be enforced.",
|
|
225
|
+
"severity": "error",
|
|
226
|
+
"events": ["incident.rca.approve", "incident.rca.create", "incident.rca.update"],
|
|
227
|
+
"requiredMetadata": [
|
|
228
|
+
{
|
|
229
|
+
"path": "/incident/rca/method",
|
|
230
|
+
"type": "string"
|
|
231
|
+
}
|
|
232
|
+
]
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
"id": "INC-RCA-002",
|
|
236
|
+
"description": "Approving a root cause analysis records the approval decision.",
|
|
237
|
+
"rationale": "This event is an approval, so requiring the approval state is not an added process obligation but a requirement that the event describe itself. An approval event with no recorded decision states that an analysis was reviewed without stating what the review concluded. The status is required rather than required to be `approved`, so that a rejection or a lapsed request stays recordable and visible.",
|
|
238
|
+
"severity": "error",
|
|
239
|
+
"events": ["incident.rca.approve"],
|
|
240
|
+
"requiredPaths": ["/approval/status"],
|
|
241
|
+
"recommendedPaths": ["/approval/approvers", "/approval/approvedAt"]
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
"id": "INC-CAPA-001",
|
|
245
|
+
"description": "Verifying a corrective action records how the verification was carried out.",
|
|
246
|
+
"rationale": "Verification is the step that turns a promise into evidence, and an unqualified assertion that an action was verified is worth nothing: reading a ticket, watching production for a week and re-running the failure are all called verification and are not comparable. Recording the method is what lets a later reader judge whether the fix was actually demonstrated. The vocabulary is open because verification techniques are domain-specific.",
|
|
247
|
+
"severity": "error",
|
|
248
|
+
"events": ["corrective-action.verify"],
|
|
249
|
+
"requiredMetadata": [
|
|
250
|
+
{
|
|
251
|
+
"path": "/incident/correctiveAction/verificationMethod",
|
|
252
|
+
"type": "string"
|
|
253
|
+
}
|
|
254
|
+
],
|
|
255
|
+
"recommendedPaths": ["/metadata/incident/correctiveAction/verifiedAt"]
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
"id": "INC-SLA-001",
|
|
259
|
+
"description": "A missed service commitment names the commitment that was missed.",
|
|
260
|
+
"rationale": "A breach event that does not say what was breached records only that someone was unhappy. The commitment identifier is what lets the breach be tied to the obligation it violated and counted against it later, when the commitment itself may have been renegotiated. The profile requires the identifier and asserts nothing about durations or thresholds: the v0.1 rule language compares values for equality and cannot evaluate a numeric range, so a target is recorded as a name rather than checked as a bound. This event is excluded from INC-CORE-001 because a breach is a system observation rather than an authorized human action, and demanding an authorization decision for it would force producers to invent one.",
|
|
261
|
+
"severity": "error",
|
|
262
|
+
"events": ["incident.sla.breach"],
|
|
263
|
+
"requiredMetadata": [
|
|
264
|
+
{
|
|
265
|
+
"path": "/incident/sla/target",
|
|
266
|
+
"type": "string"
|
|
267
|
+
}
|
|
268
|
+
],
|
|
269
|
+
"recommendedPaths": ["/metadata/incident/sla/breachedAt"]
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
"id": "INC-EVIDENCE-001",
|
|
273
|
+
"description": "Root-cause and corrective-action events should reference the material that supports them.",
|
|
274
|
+
"rationale": "The analysis document, the change record and the verification report are what make an incident conclusion checkable rather than merely stated, and `/evidence` is where the core model puts references to them. This is a recommendation and not a requirement for a reason worth stating plainly: the v0.1 rule language can test that `/evidence` is present and non-empty, and cannot test that it contains an entry of any particular type. A rule that required `/evidence` would be satisfied by an unrelated reference, so the profile asks for evidence rather than pretending to verify it.",
|
|
275
|
+
"severity": "warning",
|
|
276
|
+
"events": [
|
|
277
|
+
"corrective-action.close",
|
|
278
|
+
"corrective-action.open",
|
|
279
|
+
"corrective-action.verify",
|
|
280
|
+
"incident.rca.approve",
|
|
281
|
+
"incident.rca.create",
|
|
282
|
+
"incident.rca.update"
|
|
283
|
+
],
|
|
284
|
+
"recommendedPaths": ["/evidence"]
|
|
285
|
+
}
|
|
286
|
+
]
|
|
287
|
+
}
|