@openauditmodel/cli 0.1.0

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.
Files changed (134) hide show
  1. package/LICENSE +215 -0
  2. package/README.md +647 -0
  3. package/dist/conformance/src/cli.d.ts +20 -0
  4. package/dist/conformance/src/cli.js +560 -0
  5. package/dist/conformance/src/cli.js.map +1 -0
  6. package/dist/conformance/src/format-errors.d.ts +20 -0
  7. package/dist/conformance/src/format-errors.js +116 -0
  8. package/dist/conformance/src/format-errors.js.map +1 -0
  9. package/dist/conformance/src/integrity/canonicalize.d.ts +25 -0
  10. package/dist/conformance/src/integrity/canonicalize.js +100 -0
  11. package/dist/conformance/src/integrity/canonicalize.js.map +1 -0
  12. package/dist/conformance/src/integrity/digest.d.ts +54 -0
  13. package/dist/conformance/src/integrity/digest.js +126 -0
  14. package/dist/conformance/src/integrity/digest.js.map +1 -0
  15. package/dist/conformance/src/integrity/types.d.ts +86 -0
  16. package/dist/conformance/src/integrity/types.js +36 -0
  17. package/dist/conformance/src/integrity/types.js.map +1 -0
  18. package/dist/conformance/src/integrity/verify-chain.d.ts +23 -0
  19. package/dist/conformance/src/integrity/verify-chain.js +235 -0
  20. package/dist/conformance/src/integrity/verify-chain.js.map +1 -0
  21. package/dist/conformance/src/integrity/verify-event.d.ts +29 -0
  22. package/dist/conformance/src/integrity/verify-event.js +140 -0
  23. package/dist/conformance/src/integrity/verify-event.js.map +1 -0
  24. package/dist/conformance/src/privacy/entropy.d.ts +14 -0
  25. package/dist/conformance/src/privacy/entropy.js +86 -0
  26. package/dist/conformance/src/privacy/entropy.js.map +1 -0
  27. package/dist/conformance/src/privacy/field-names.d.ts +36 -0
  28. package/dist/conformance/src/privacy/field-names.js +121 -0
  29. package/dist/conformance/src/privacy/field-names.js.map +1 -0
  30. package/dist/conformance/src/privacy/lint-event.d.ts +18 -0
  31. package/dist/conformance/src/privacy/lint-event.js +272 -0
  32. package/dist/conformance/src/privacy/lint-event.js.map +1 -0
  33. package/dist/conformance/src/privacy/rules.d.ts +44 -0
  34. package/dist/conformance/src/privacy/rules.js +161 -0
  35. package/dist/conformance/src/privacy/rules.js.map +1 -0
  36. package/dist/conformance/src/privacy/safe-formats.d.ts +32 -0
  37. package/dist/conformance/src/privacy/safe-formats.js +118 -0
  38. package/dist/conformance/src/privacy/safe-formats.js.map +1 -0
  39. package/dist/conformance/src/privacy/size-analysis.d.ts +36 -0
  40. package/dist/conformance/src/privacy/size-analysis.js +87 -0
  41. package/dist/conformance/src/privacy/size-analysis.js.map +1 -0
  42. package/dist/conformance/src/privacy/token-patterns.d.ts +24 -0
  43. package/dist/conformance/src/privacy/token-patterns.js +126 -0
  44. package/dist/conformance/src/privacy/token-patterns.js.map +1 -0
  45. package/dist/conformance/src/privacy/traverse.d.ts +33 -0
  46. package/dist/conformance/src/privacy/traverse.js +61 -0
  47. package/dist/conformance/src/privacy/traverse.js.map +1 -0
  48. package/dist/conformance/src/privacy/types.d.ts +58 -0
  49. package/dist/conformance/src/privacy/types.js +32 -0
  50. package/dist/conformance/src/privacy/types.js.map +1 -0
  51. package/dist/conformance/src/privacy/url-analysis.d.ts +40 -0
  52. package/dist/conformance/src/privacy/url-analysis.js +148 -0
  53. package/dist/conformance/src/privacy/url-analysis.js.map +1 -0
  54. package/dist/conformance/src/profiles/check-profile.d.ts +22 -0
  55. package/dist/conformance/src/profiles/check-profile.js +72 -0
  56. package/dist/conformance/src/profiles/check-profile.js.map +1 -0
  57. package/dist/conformance/src/profiles/evaluate-rule.d.ts +27 -0
  58. package/dist/conformance/src/profiles/evaluate-rule.js +87 -0
  59. package/dist/conformance/src/profiles/evaluate-rule.js.map +1 -0
  60. package/dist/conformance/src/profiles/load-profile.d.ts +30 -0
  61. package/dist/conformance/src/profiles/load-profile.js +95 -0
  62. package/dist/conformance/src/profiles/load-profile.js.map +1 -0
  63. package/dist/conformance/src/profiles/resolve-pointer.d.ts +44 -0
  64. package/dist/conformance/src/profiles/resolve-pointer.js +123 -0
  65. package/dist/conformance/src/profiles/resolve-pointer.js.map +1 -0
  66. package/dist/conformance/src/profiles/select-rules.d.ts +13 -0
  67. package/dist/conformance/src/profiles/select-rules.js +42 -0
  68. package/dist/conformance/src/profiles/select-rules.js.map +1 -0
  69. package/dist/conformance/src/profiles/types.d.ts +101 -0
  70. package/dist/conformance/src/profiles/types.js +31 -0
  71. package/dist/conformance/src/profiles/types.js.map +1 -0
  72. package/dist/conformance/src/profiles/validate-profile-definition.d.ts +12 -0
  73. package/dist/conformance/src/profiles/validate-profile-definition.js +47 -0
  74. package/dist/conformance/src/profiles/validate-profile-definition.js.map +1 -0
  75. package/dist/conformance/src/sources.d.ts +53 -0
  76. package/dist/conformance/src/sources.js +153 -0
  77. package/dist/conformance/src/sources.js.map +1 -0
  78. package/dist/conformance/src/validate-core.d.ts +30 -0
  79. package/dist/conformance/src/validate-core.js +62 -0
  80. package/dist/conformance/src/validate-core.js.map +1 -0
  81. package/dist/conformance/src/validate.d.ts +34 -0
  82. package/dist/conformance/src/validate.js +62 -0
  83. package/dist/conformance/src/validate.js.map +1 -0
  84. package/dist/conformance/src/validator-interface.d.ts +35 -0
  85. package/dist/conformance/src/validator-interface.js +19 -0
  86. package/dist/conformance/src/validator-interface.js.map +1 -0
  87. package/package.json +85 -0
  88. package/profiles/README.md +201 -0
  89. package/profiles/api-and-integration-management/README.md +271 -0
  90. package/profiles/api-and-integration-management/profile.json +258 -0
  91. package/profiles/backup-and-recovery/README.md +318 -0
  92. package/profiles/backup-and-recovery/profile.json +178 -0
  93. package/profiles/customer-and-account-management/README.md +340 -0
  94. package/profiles/customer-and-account-management/profile.json +237 -0
  95. package/profiles/deployment-and-change-management/README.md +359 -0
  96. package/profiles/deployment-and-change-management/profile.json +298 -0
  97. package/profiles/document-management/README.md +120 -0
  98. package/profiles/document-management/profile.json +170 -0
  99. package/profiles/financial-transaction-management/README.md +339 -0
  100. package/profiles/financial-transaction-management/profile.json +247 -0
  101. package/profiles/identity-and-access-management/README.md +112 -0
  102. package/profiles/identity-and-access-management/profile.json +120 -0
  103. package/profiles/incident-management/README.md +338 -0
  104. package/profiles/incident-management/profile.json +256 -0
  105. package/profiles/message-broker-management/README.md +344 -0
  106. package/profiles/message-broker-management/profile.json +399 -0
  107. package/profiles/profile-definition.schema.json +213 -0
  108. package/profiles/secrets-and-key-management/README.md +331 -0
  109. package/profiles/secrets-and-key-management/profile.json +219 -0
  110. package/schemas/v0.1/audit-event.schema.json +911 -0
  111. package/semantic-conventions/README.md +52 -0
  112. package/semantic-conventions/authentication.md +111 -0
  113. package/semantic-conventions/configuration-and-change.md +122 -0
  114. package/semantic-conventions/correlation-and-tracing.md +387 -0
  115. package/semantic-conventions/data-access.md +115 -0
  116. package/semantic-conventions/event-naming.md +114 -0
  117. package/semantic-conventions/identity-and-access.md +112 -0
  118. package/semantic-conventions/privileged-operations.md +110 -0
  119. package/semantic-conventions/workflow-and-approval.md +109 -0
  120. package/specification/actor-model.md +135 -0
  121. package/specification/approval-and-delegation.md +150 -0
  122. package/specification/authentication.md +116 -0
  123. package/specification/authorization.md +117 -0
  124. package/specification/change-model.md +134 -0
  125. package/specification/delivery.md +136 -0
  126. package/specification/design-principles.md +137 -0
  127. package/specification/event-model.md +387 -0
  128. package/specification/evidence-model.md +109 -0
  129. package/specification/extension-model.md +159 -0
  130. package/specification/integrity.md +314 -0
  131. package/specification/overview.md +172 -0
  132. package/specification/privacy.md +386 -0
  133. package/specification/resource-model.md +116 -0
  134. package/specification/terminology.md +135 -0
@@ -0,0 +1,115 @@
1
+ # Data Access Events
2
+
3
+ **Specification version: 0.1 · Status: Experimental**
4
+
5
+ Categories: `data-access`, `data-modification`
6
+
7
+ ## 1. Recommended event names
8
+
9
+ ### Reading
10
+
11
+ | Name | Operation |
12
+ | ------------------------ | ------------------------------ |
13
+ | `data.record.read` | A record was read individually |
14
+ | `data.record.search` | A search returned records |
15
+ | `data.report.generate` | A report was produced |
16
+ | `data.export.create` | An export was produced |
17
+ | `data.export.download` | An export was retrieved |
18
+ | `document.file.view` | A document was viewed |
19
+ | `document.file.download` | A document was downloaded |
20
+
21
+ ### Writing
22
+
23
+ | Name | Operation |
24
+ | --------------------- | ----------------------------- |
25
+ | `data.record.create` | A record was created |
26
+ | `data.record.update` | A record was modified |
27
+ | `data.record.delete` | A record was deleted |
28
+ | `data.record.restore` | A deleted record was restored |
29
+ | `data.import.create` | Data was imported |
30
+
31
+ ### Sharing
32
+
33
+ | Name | Operation |
34
+ | ---------------------------- | ---------------------------------------------------- |
35
+ | `document.share.create` | Access was granted to a recipient |
36
+ | `document.share.revoke` | A share was withdrawn |
37
+ | `document.permission.grant` | A permission was granted on a resource |
38
+ | `document.permission.revoke` | A permission was removed |
39
+ | `data.transfer.external` | Data was transmitted outside the operator's boundary |
40
+
41
+ ## 2. Not everything is worth auditing
42
+
43
+ Read events are the highest-volume category in most systems and the least useful by default. An audit
44
+ trail that records every list view is expensive, hard to search, and hides the events that matter.
45
+
46
+ Producers SHOULD audit reads where at least one of these holds:
47
+
48
+ - The resource is classified above `internal`.
49
+ - The read crosses a tenant, organization or customer boundary.
50
+ - The actor is privileged, or is acting for someone else.
51
+ - The volume is unusual: an export, a bulk search, a full extract.
52
+ - The data is personal data and the operator has committed to access transparency.
53
+
54
+ Producers SHOULD NOT audit ordinary reads of unclassified data by their owner. That is what
55
+ application logs are for.
56
+
57
+ ## 3. Context to populate
58
+
59
+ | Field | Guidance |
60
+ | ------------------------- | ----------------------------------------------------------------- |
61
+ | `resource.classification` | Frequently the reason the event is being recorded at all |
62
+ | `resource.ownerId` | Who the data belongs to, where it differs from the actor |
63
+ | `privacy` | `containsPersonalData`, `dataCategories`, `processing`, `purpose` |
64
+ | `authorization` | The decision that permitted the access |
65
+ | `reason` | For support access and any access to another party's data |
66
+ | `request.route` | The route template, never a resolved URL with a query string |
67
+ | `metadata` | `recordCount`, `exportFormat`, `scope`, `filterName` |
68
+ | `controlCategories` | `data-access-logging`, `external-data-sharing` |
69
+
70
+ ## 4. Search and bulk reads
71
+
72
+ A search returns an unknown number of records. Recording each one is usually infeasible and often
73
+ undesirable. Recommended handling:
74
+
75
+ - Record one `data.record.search` event with `resource` set to the collection searched.
76
+ - Record `metadata.recordCount`, and the **name** of the filter applied, not its values.
77
+ - MUST NOT record the query string or the search terms. Search terms routinely contain personal data
78
+ and are among the most sensitive values a system holds. See
79
+ [privacy.md](../specification/privacy.md).
80
+
81
+ ## 5. External sharing
82
+
83
+ Sharing outside the operator's boundary is a distinct control, and SHOULD be recorded as such:
84
+
85
+ - Include `external-data-sharing` in `controlCategories`.
86
+ - Record the recipient **type** and **domain**, not the recipient's address, unless the audit purpose
87
+ specifically requires identifying the individual.
88
+ - Record share constraints — expiry, password protection, watermarking, download permission — in
89
+ `metadata`, because they are what a reviewer assesses.
90
+ - Emit a matching `document.share.revoke` when the share ends, so that the trail shows exposure
91
+ windows rather than only their beginning.
92
+
93
+ See [examples/valid/document-external-share.json](../examples/valid/document-external-share.json).
94
+
95
+ ## 6. Exports
96
+
97
+ Exports concentrate risk: one operation moves a large volume of data out of the controlled system.
98
+
99
+ - `data.export.create` records production of the export; `data.export.download` records retrieval.
100
+ Both are worth recording, because they can be separated by days and performed by different
101
+ principals.
102
+ - Record `metadata.recordCount` and `metadata.exportFormat`.
103
+ - Record `privacy` fully. An export is the event most likely to be reviewed under a data protection
104
+ question.
105
+ - Where the export is produced by a service for a user, record the `subject` and `delegation`. See
106
+ [examples/valid/service-account-data-export.json](../examples/valid/service-account-data-export.json).
107
+
108
+ ## 7. Modification
109
+
110
+ For data modification, `change` carries the substance. Prefer `changedFields` over values; see
111
+ [change-model.md](../specification/change-model.md).
112
+
113
+ `data-modification` is the category for business data. Changes to application or platform settings
114
+ belong in `configuration`; see
115
+ [configuration-and-change.md](configuration-and-change.md).
@@ -0,0 +1,114 @@
1
+ # Event Naming
2
+
3
+ **Specification version: 0.1 · Status: Experimental**
4
+
5
+ The normative naming rules are in [event-model.md](../specification/event-model.md) §7. This document
6
+ gives the recommended vocabularies and the reasoning behind them.
7
+
8
+ ## 1. The shape
9
+
10
+ ```text
11
+ domain.resource.action
12
+ ```
13
+
14
+ | Segment | Answers | Examples |
15
+ | ---------- | ------------------------- | ---------------------------------------- |
16
+ | `domain` | Which area of the system? | `authentication`, `identity`, `document` |
17
+ | `resource` | Which kind of thing? | `role`, `share`, `case`, `setting` |
18
+ | `action` | What was done to it? | `assign`, `create`, `close`, `update` |
19
+
20
+ Two segments are permitted where a resource segment would be artificial:
21
+
22
+ ```text
23
+ authentication.login
24
+ authentication.logout
25
+ ```
26
+
27
+ Action segments may be hyphenated where the action is genuinely two words:
28
+
29
+ ```text
30
+ queue.consumer.offset-reset
31
+ identity.credential.self-service-reset
32
+ ```
33
+
34
+ ## 2. Recommended categories
35
+
36
+ `event.category` groups names for filtering and routing. It is an open vocabulary; these values cover
37
+ the domains this model targets:
38
+
39
+ | Category | Covers |
40
+ | ---------------------- | -------------------------------------------------------- |
41
+ | `authentication` | Proving identity, sessions, factors, credentials |
42
+ | `identity` | Accounts, roles, permissions, service accounts |
43
+ | `data-access` | Reading, exporting, sharing, downloading |
44
+ | `data-modification` | Creating, updating, deleting business data |
45
+ | `configuration` | Application and platform settings, secrets |
46
+ | `deployment` | Releases, rollouts, rollbacks |
47
+ | `workflow` | Requests, approvals, case and incident lifecycle |
48
+ | `privileged-operation` | Administrative and break-glass operations |
49
+ | `data-infrastructure` | Brokers, topics, queues, caches, database administration |
50
+ | `security` | Security-relevant events that fit no other category |
51
+ | `resource-lifecycle` | Provisioning and decommissioning of resources |
52
+
53
+ A category is a coarse label. When an event fits two, choose the one a reviewer would filter on.
54
+
55
+ ## 3. Recommended activity types
56
+
57
+ `event.type` is an OPTIONAL, domain-independent classifier. It exists so that a consumer can ask
58
+ "show me every deletion" without knowing every domain's vocabulary.
59
+
60
+ ```text
61
+ create read update delete execute
62
+ approve reject share grant revoke
63
+ login logout export import rotate
64
+ ```
65
+
66
+ `event.type` never replaces `event.name`. `identity.role.revoke` and `document.permission.revoke` are
67
+ different operations that share `type: revoke`.
68
+
69
+ ## 4. Rules, restated
70
+
71
+ 1. **Stable.** A published name keeps its meaning. If the meaning changes, the name changes.
72
+ 2. **No product names.** `document.share.create`, not `sharepointish.share.create`.
73
+ 3. **No company names.** The audit trail outlives the vendor relationship.
74
+ 4. **No jurisdiction names.** `data.export.create`, not `data.export.create-eu`.
75
+ 5. **Describe the operation, not the mechanism.** `identity.role.assign` is right whether the role was
76
+ assigned through a console, an API, a sync job or a script. Names that encode the mechanism
77
+ fragment the trail and break when the mechanism changes.
78
+ 6. **Same name for success and failure.** Use `outcome`, not a different name.
79
+
80
+ ## 5. The failure-name anti-pattern
81
+
82
+ This is the most common naming mistake, and it is worth stating twice:
83
+
84
+ ```text
85
+ authentication.login outcome: success ← RECOMMENDED
86
+ authentication.login outcome: failure ← RECOMMENDED
87
+
88
+ authentication.login-success ← NOT RECOMMENDED
89
+ authentication.login-failed ← NOT RECOMMENDED
90
+ ```
91
+
92
+ Encoding the outcome in the name doubles the vocabulary, makes "how often does this operation fail?"
93
+ a string-matching problem, and guarantees that some operations get a failure name and others do not.
94
+
95
+ ## 6. Granularity
96
+
97
+ Prefer the granularity a reviewer would ask about.
98
+
99
+ | Too coarse | Too fine | Recommended |
100
+ | --------------------- | ----------------------------------------------- | ------------------------------ |
101
+ | `document.update` | `document.metadata.title.update` | `document.version.create` |
102
+ | `identity.change` | `identity.role.assign.via-bulk-import` | `identity.role.assign` |
103
+ | `configuration.write` | `configuration.setting.session-lifetime.update` | `configuration.setting.update` |
104
+
105
+ Detail that varies per operation belongs in `resource`, `change.changedFields` and `metadata`, not in
106
+ the name. A name is a category; a category with one member is not a category.
107
+
108
+ ## 7. Naming new events
109
+
110
+ 1. Find the closest existing convention document and follow its pattern.
111
+ 2. Use the resource type you already use in `resource.type` as the resource segment where possible.
112
+ 3. Use a verb in the imperative for the action: `assign`, not `assigned` or `assignment`.
113
+ 4. Check the name does not encode outcome, mechanism, product, company or jurisdiction.
114
+ 5. Check that a reviewer who has never seen your system can guess what it means.
@@ -0,0 +1,112 @@
1
+ # Identity and Access Events
2
+
3
+ **Specification version: 0.1 · Status: Experimental**
4
+
5
+ Category: `identity`
6
+
7
+ ## 1. Recommended event names
8
+
9
+ ### Accounts
10
+
11
+ | Name | Operation |
12
+ | ----------------------- | --------------------------------- |
13
+ | `identity.user.create` | An account was created |
14
+ | `identity.user.update` | Account attributes changed |
15
+ | `identity.user.disable` | An account was disabled |
16
+ | `identity.user.enable` | A disabled account was re-enabled |
17
+ | `identity.user.delete` | An account was deleted |
18
+
19
+ ### Roles and permissions
20
+
21
+ | Name | Operation |
22
+ | ------------------------------ | ----------------------------------- |
23
+ | `identity.role.create` | A role was defined |
24
+ | `identity.role.update` | A role definition changed |
25
+ | `identity.role.delete` | A role was removed |
26
+ | `identity.role.assign` | A role was granted to a principal |
27
+ | `identity.role.revoke` | A role was removed from a principal |
28
+ | `identity.permission.grant` | A permission was granted directly |
29
+ | `identity.permission.revoke` | A permission was removed |
30
+ | `identity.group.member-add` | A principal joined a group |
31
+ | `identity.group.member-remove` | A principal left a group |
32
+
33
+ ### Machine identities and sessions
34
+
35
+ | Name | Operation |
36
+ | ---------------------------------- | -------------------------------------- |
37
+ | `identity.service-account.create` | A machine identity was created |
38
+ | `identity.service-account.disable` | A machine identity was disabled |
39
+ | `identity.credential.rotate` | A machine credential was replaced |
40
+ | `identity.session.impersonate` | A principal began acting as another |
41
+ | `identity.delegation.grant` | Authority was delegated to a principal |
42
+ | `identity.delegation.revoke` | A delegation was withdrawn |
43
+
44
+ ## 2. Which principal goes where
45
+
46
+ This is the most error-prone area in the whole model.
47
+
48
+ | Operation | `actor` | `resource` | `subject` |
49
+ | ------------------------------------------ | ----------------- | ---------------------- | --------- |
50
+ | Administrator assigns a role to a user | the administrator | the **user** | absent |
51
+ | User accepts an invitation | the user | the user's own account | absent |
52
+ | Service provisions an account from HR data | the service | the new account | absent |
53
+ | Administrator impersonates a user | the administrator | the session | the user |
54
+ | Delegated administrator acts for an owner | the delegate | the affected resource | the owner |
55
+
56
+ The target of an identity operation is a `resource`, not a `subject`. `subject` appears only when
57
+ someone's authority was borrowed. See [actor-model.md](../specification/actor-model.md).
58
+
59
+ The role or permission being granted is a **related resource** or `metadata`, not the primary
60
+ resource — the primary resource is what changed, and what changed is the principal's access.
61
+
62
+ ## 3. Context to populate
63
+
64
+ | Field | Guidance |
65
+ | ------------------- | ----------------------------------------------------------------------- |
66
+ | `relatedResources` | The role, permission, group or scope involved |
67
+ | `change` | `changedFields`, and before/after where the values are safe to record |
68
+ | `authorization` | The decision that permitted the change |
69
+ | `approval` | Where access requires approval, including `not-required` when evaluated |
70
+ | `reason` | The access request or ticket that justifies the grant |
71
+ | `metadata` | `assignedRole`, `assignmentScope`, `effectiveFrom`, `expiresAt` |
72
+ | `controlCategories` | `privileged-access`, `separation-of-duties`, `change-approval` |
73
+
74
+ ## 4. Privileged grants
75
+
76
+ An event that grants administrative access SHOULD:
77
+
78
+ - Set `event.severity` to `high` or `critical`.
79
+ - Include `privileged-access` in `controlCategories`.
80
+ - Populate `approval` where the operator requires approval for privileged grants.
81
+ - Record `metadata.expiresAt` for time-bound grants, so that a reviewer can distinguish standing
82
+ privilege from just-in-time access.
83
+
84
+ ## 5. Effective time
85
+
86
+ Access changes are often scheduled. `time` is when the **change was recorded**, not when it takes
87
+ effect. Where they differ, record the effective window in `metadata`:
88
+
89
+ ```json
90
+ {
91
+ "metadata": {
92
+ "assignedRole": "support-agent",
93
+ "effectiveFrom": "2026-03-16T00:00:00Z",
94
+ "expiresAt": "2026-06-16T00:00:00Z"
95
+ }
96
+ }
97
+ ```
98
+
99
+ A separate event SHOULD be emitted when a time-bound grant actually expires, so that the trail shows
100
+ the access ending rather than only the intention that it would.
101
+
102
+ ## 6. Bulk changes
103
+
104
+ Access changes are frequently bulk operations. Producers SHOULD emit one event per affected principal
105
+ where the principals are individually significant — which, for access, they usually are. Where a bulk
106
+ operation is recorded as one event, the count and scope MUST be recorded in `metadata`, and the
107
+ producer MUST document the choice. See [resource-model.md](../specification/resource-model.md) §6.
108
+
109
+ ## 7. Example
110
+
111
+ See [examples/valid/user-role-assignment.json](../examples/valid/user-role-assignment.json) for a
112
+ complete role assignment with authorization, approval, reason and change context.
@@ -0,0 +1,110 @@
1
+ # Privileged Operations
2
+
3
+ **Specification version: 0.1 · Status: Experimental**
4
+
5
+ Category: `privileged-operation`
6
+
7
+ ## 1. What counts as privileged
8
+
9
+ An operation is privileged when it can affect data or controls beyond the actor's ordinary scope.
10
+ Concretely, when at least one of these holds:
11
+
12
+ - It uses administrative authority rather than the actor's own entitlements.
13
+ - It bypasses or disables a control.
14
+ - It reaches across a tenant, customer or organization boundary.
15
+ - It acts on another principal's data or identity.
16
+ - It changes security-relevant configuration.
17
+ - It operates directly on infrastructure rather than through the application.
18
+
19
+ Privilege is a property of **the operation**, not of the account. The same account performs ordinary
20
+ and privileged operations, and the audit trail should distinguish them.
21
+
22
+ ## 2. Recommended event names
23
+
24
+ | Name | Operation |
25
+ | ----------------------------------- | --------------------------------------------------- |
26
+ | `identity.session.impersonate` | A principal began acting as another |
27
+ | `privileged.access.request` | Elevated access was requested |
28
+ | `privileged.access.grant` | Elevated access was granted |
29
+ | `privileged.access.revoke` | Elevated access was withdrawn |
30
+ | `privileged.break-glass.activate` | An emergency access path was used |
31
+ | `privileged.break-glass.close` | An emergency access episode was closed |
32
+ | `privileged.control.disable` | A control was switched off |
33
+ | `privileged.control.enable` | A control was switched back on |
34
+ | `privileged.database.query-execute` | A direct data store query was run |
35
+ | `privileged.maintenance.execute` | A maintenance operation was performed on production |
36
+
37
+ Domain-specific privileged operations keep their domain name and are marked privileged through
38
+ `controlCategories` and `severity`, rather than being renamed. `configuration.setting.update` on
39
+ production security configuration is a privileged operation with the name it already has.
40
+
41
+ ## 3. Required signals
42
+
43
+ For an operation the producer considers privileged, it SHOULD:
44
+
45
+ 1. Set `event.severity` to `high` or `critical`.
46
+ 2. Include `privileged-access` in `controlCategories`.
47
+ 3. Populate `authorization` with the decision that permitted it.
48
+ 4. Populate `reason` with a business justification.
49
+ 5. Populate `approval` where the operator requires approval, including `not-required` when that was
50
+ evaluated.
51
+ 6. Populate `authentication`, including `mfa`, where the operator requires re-authentication for
52
+ privileged actions.
53
+ 7. Populate `subject` and `delegation` where the operation was performed for someone else.
54
+
55
+ The value of a privileged-operation trail is that a reviewer can answer "was this justified?" without
56
+ asking the person who did it. An event with none of the fields above cannot answer that.
57
+
58
+ ## 4. Break-glass access
59
+
60
+ Emergency access exists because controls sometimes have to be bypassed. The audit trail is what makes
61
+ that acceptable.
62
+
63
+ Producers SHOULD:
64
+
65
+ - Emit `privileged.break-glass.activate` at the start and `privileged.break-glass.close` at the end,
66
+ so the episode has a duration rather than a single moment.
67
+ - Share one `request.correlationId` across every operation performed during the episode, so the
68
+ entire episode can be reviewed as a unit.
69
+ - Record `reason` with a real justification, and `reason.reference` pointing at the incident.
70
+ - Set `event.severity` to `critical`.
71
+ - Record `approval` even when it was retrospective, using `approvedAt` to make the sequence visible.
72
+
73
+ ## 5. Direct data store access
74
+
75
+ Running queries directly against a production data store bypasses every application-level control,
76
+ including the application's own audit trail.
77
+
78
+ Producers that support it SHOULD record:
79
+
80
+ - The store as `resource`, and the affected tables or collections in `relatedResources` where known.
81
+ - `metadata.statementType` — `select`, `update`, `delete` — and `metadata.affectedRowCount`.
82
+ - `metadata.queryHash` where a query needs to be identifiable across events.
83
+
84
+ Producers MUST NOT record query text or parameters automatically. Both routinely contain personal
85
+ data, and parameters in particular are the values of the very records being accessed. See
86
+ [privacy.md](../specification/privacy.md) §2.
87
+
88
+ ## 6. Message broker and infrastructure operations
89
+
90
+ Operations on brokers, queues and caches are administrative operations on data-carrying
91
+ infrastructure, and are privileged when performed against production.
92
+
93
+ - Use the broker family as the domain segment: `kafka.consumer.offset-reset`,
94
+ `rabbitmq.queue.purge`, `redis.key.delete`.
95
+ - Record the affected topic, queue or key space in `relatedResources`.
96
+ - Record offsets, partitions and counts in `metadata`.
97
+ - MUST NOT record message payloads. See
98
+ [profiles/message-broker-management/](../profiles/message-broker-management/).
99
+
100
+ See
101
+ [examples/valid/kafka-consumer-offset-reset.json](../examples/valid/kafka-consumer-offset-reset.json).
102
+
103
+ ## 7. Control changes
104
+
105
+ Disabling a control is the operation most worth auditing and the one most likely to go unaudited,
106
+ because it is often performed on the system that does the auditing.
107
+
108
+ Producers SHOULD emit `privileged.control.disable` and `privileged.control.enable` as a pair, record
109
+ the control in `resource`, and record the window in `metadata`. A control that was disabled and never
110
+ re-enabled should be visible as an open pair, not inferred from silence.
@@ -0,0 +1,109 @@
1
+ # Workflow and Approval Events
2
+
3
+ **Specification version: 0.1 · Status: Experimental**
4
+
5
+ Category: `workflow`
6
+
7
+ ## 1. Recommended event names
8
+
9
+ ### Requests and approvals
10
+
11
+ | Name | Operation |
12
+ | ---------------------------- | -------------------------------------------------- |
13
+ | `workflow.request.create` | A request entered a workflow |
14
+ | `workflow.request.submit` | A request was submitted for decision |
15
+ | `workflow.approval.request` | Approval was requested from one or more principals |
16
+ | `workflow.approval.grant` | An approver approved |
17
+ | `workflow.approval.reject` | An approver refused |
18
+ | `workflow.approval.expire` | An approval request lapsed undecided |
19
+ | `workflow.approval.delegate` | Approval authority was passed to another principal |
20
+ | `workflow.stage.advance` | A workflow moved to the next stage |
21
+ | `workflow.request.cancel` | A request was withdrawn |
22
+ | `workflow.request.close` | A request reached a terminal state |
23
+
24
+ ### Case and incident lifecycle
25
+
26
+ | Name | Operation |
27
+ | ---------------------------- | ------------------------------------- |
28
+ | `incident.case.create` | An incident was raised |
29
+ | `incident.priority.change` | Priority was reassessed |
30
+ | `incident.assignment.change` | Ownership changed |
31
+ | `incident.major.declare` | An incident was escalated to major |
32
+ | `incident.case.resolve` | An incident was resolved |
33
+ | `incident.case.close` | An incident was closed |
34
+ | `incident.case.reopen` | A closed incident was reopened |
35
+ | `incident.rca.create` | A root cause analysis was recorded |
36
+ | `incident.rca.approve` | A root cause analysis was approved |
37
+ | `incident.sla.breach` | A service level commitment was missed |
38
+
39
+ ## 2. The approval object versus approval events
40
+
41
+ Both exist, and they answer different questions.
42
+
43
+ | Question | Where it is answered |
44
+ | ----------------------------------------------- | ------------------------------------- |
45
+ | Was this operation approved? | `approval` on the **operated** event |
46
+ | Who approved what, when, and did anyone refuse? | Separate `workflow.approval.*` events |
47
+
48
+ A configuration change carries `approval` describing the state of its approval. The approval decisions
49
+ themselves — each approver, each timestamp, each rejection — are their own events, because they are
50
+ separate auditable operations performed by different principals at different times.
51
+
52
+ Producers SHOULD emit both. Recording only the summary loses who decided; recording only the decisions
53
+ makes it impossible to tell what they authorized.
54
+
55
+ ## 3. Approval status transitions
56
+
57
+ Recommended transitions, and the event that records each:
58
+
59
+ ```text
60
+ not-required (no approval event; recorded on the operated event)
61
+ pending → approved workflow.approval.grant
62
+ pending → rejected workflow.approval.reject
63
+ pending → expired workflow.approval.expire
64
+ ```
65
+
66
+ An operated event whose `approval.status` is `pending`, `rejected` or `expired` and whose outcome is
67
+ `success` describes a control bypass. Producers MUST record it accurately.
68
+
69
+ ## 4. Context to populate
70
+
71
+ | Field | Guidance |
72
+ | ---------------------------- | ------------------------------------------------------------------ |
73
+ | `resource` | The request, case or workflow instance |
74
+ | `relatedResources` | The resource the workflow governs, and any affected services |
75
+ | `approval.approvers` | Only the principals whose decisions counted |
76
+ | `approval.requiredApprovals` | The policy threshold, so a reviewer can see whether it was met |
77
+ | `change` | Status transitions, as `changedFields` with before and after |
78
+ | `evidence` | The approval record, the analysis document, the ticket |
79
+ | `reason` | Why the decision was made, where a justification is required |
80
+ | `request.correlationId` | Shared across the whole workflow, so its events can be assembled |
81
+ | `controlCategories` | `change-approval`, `separation-of-duties`, `incident-traceability` |
82
+
83
+ ## 5. Correlation across a workflow
84
+
85
+ A workflow produces many events over hours or weeks, from different applications and principals. They
86
+ are assembled by correlation, not by timestamp.
87
+
88
+ Producers SHOULD:
89
+
90
+ - Use one `request.correlationId` for the life of the workflow instance.
91
+ - Use the workflow instance identifier consistently in `approval.workflowId`.
92
+ - Reference the same case identifier in `change.incidentId` or `reason.reference`.
93
+
94
+ ## 6. Separation of duties
95
+
96
+ Where policy requires that the approver differ from the requester, the audit trail must make the
97
+ comparison possible. Producers SHOULD:
98
+
99
+ - Record `actor` on the operated event and `approval.approvers` such that both are identifiable.
100
+ - Include `separation-of-duties` in `controlCategories`.
101
+ - Emit the event even when the check **passes**. A control that only produces evidence when it fails
102
+ cannot be shown to have been operating.
103
+
104
+ The model records the facts. It does not evaluate the rule: OpenAuditModel is not a policy engine.
105
+
106
+ ## 7. Example
107
+
108
+ See [examples/valid/incident-case-close.json](../examples/valid/incident-case-close.json) for an
109
+ incident closure with approvals, evidence references, status transition and trace correlation.