@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,135 @@
1
+ # Actor Model
2
+
3
+ **Specification version: 0.1 · Status: Experimental · This document: Normative**
4
+
5
+ ## 1. The distinction the model exists to make
6
+
7
+ Modern applications rarely have a single participant in an operation. A request arrives at a gateway,
8
+ is forwarded to a service, executed by a worker, and performed against a resource owned by someone
9
+ else entirely. "Who did this?" has more than one answer, and an audit model that collapses them is
10
+ useless in exactly the situations that matter most.
11
+
12
+ OpenAuditModel separates three things:
13
+
14
+ | Concept | Question it answers | Field |
15
+ | ------------ | -------------------------------------------- | ---------- |
16
+ | **Actor** | Who technically performed the operation? | `actor` |
17
+ | **Subject** | On whose behalf was the operation performed? | `subject` |
18
+ | **Resource** | What was the operation performed on? | `resource` |
19
+
20
+ An administrator resetting a customer's password is the actor; the customer is the resource. An
21
+ administrator impersonating a customer to place an order is the actor; the customer is the subject;
22
+ the order is the resource. These are different events and the model MUST be able to tell them apart.
23
+
24
+ ## 2. Principal
25
+
26
+ `actor` and `subject` share one shape, the **principal**.
27
+
28
+ ### 2.1 Required
29
+
30
+ | Field | Meaning |
31
+ | ------ | ---------------------------------------------------------------- |
32
+ | `type` | Kind of principal. |
33
+ | `id` | Stable identifier of the principal within its issuing authority. |
34
+
35
+ ### 2.2 Optional
36
+
37
+ | Field | Meaning |
38
+ | ---------------- | --------------------------------------- |
39
+ | `displayName` | Human-readable name. Personal data. |
40
+ | `tenantId` | Tenant the principal belongs to. |
41
+ | `organizationId` | Organization the principal belongs to. |
42
+ | `roles` | Roles relevant to **this** operation. |
43
+ | `attributes` | Producer-defined additional attributes. |
44
+
45
+ ## 3. Principal types
46
+
47
+ `type` MUST be one of:
48
+
49
+ | Value | Meaning |
50
+ | ---------- | ----------------------------------------------------------------------------------------------- |
51
+ | `user` | A human-operated account. |
52
+ | `service` | A workload, service account or automated client acting under its own identity. |
53
+ | `system` | The application itself, for operations with no external initiator, such as scheduled processes. |
54
+ | `admin` | A human-operated account exercising administrative privilege for this operation. |
55
+ | `external` | A principal originating outside the operator's identity boundary. |
56
+ | `unknown` | The producer cannot determine the kind of principal. |
57
+
58
+ Notes:
59
+
60
+ - `admin` is a statement about **this operation**, not a permanent property of an account. The same
61
+ account may appear as `user` for ordinary operations and `admin` for privileged ones. Producers
62
+ that cannot make this distinction reliably SHOULD use `user` and record privilege in `roles`.
63
+ - `unknown` MUST NOT be used to avoid deciding. It exists for imported and legacy data where the
64
+ information genuinely does not exist.
65
+ - A principal kind that does not fit these values, such as a device, SHOULD use the closest core type
66
+ and describe the detail in `attributes`. The vocabulary is closed in v0.1 and reopening it is an
67
+ open question for v0.2.
68
+
69
+ ## 4. Identifiers
70
+
71
+ - `id` MUST be stable for the lifetime of the principal. A value that changes when the principal is
72
+ renamed, moves department or changes email address is not an identifier.
73
+ - `id` SHOULD be an opaque internal identifier rather than an email address, username or national
74
+ identification number. Direct personal identifiers make audit data harder to minimize, harder to
75
+ retain lawfully, and harder to share for analysis.
76
+ - Personally identifiable display names MUST NOT be required by an implementation. A stable
77
+ identifier is sufficient to satisfy the model; `displayName` exists for systems that must present
78
+ the event to humans without a directory lookup, and SHOULD be omitted otherwise.
79
+ - `roles` SHOULD contain only the roles relevant to the audited operation. An event is not the place
80
+ to snapshot a principal's complete role inventory.
81
+
82
+ ## 5. Subject
83
+
84
+ `subject` is the principal **on whose behalf** the actor performed the operation.
85
+
86
+ ### 5.1 When to use it
87
+
88
+ | Situation | actor | subject |
89
+ | -------------------------------------------------------------------- | --------------------------- | ------------- |
90
+ | An API service performing an operation for a signed-in user | the service | the user |
91
+ | An administrator impersonating a customer | the administrator | the customer |
92
+ | A background worker executing a previously requested operation | the worker service account | the requester |
93
+ | A delegated administrator performing an approved action for an owner | the delegated administrator | the owner |
94
+
95
+ ### 5.2 Rules
96
+
97
+ 1. `subject` MUST NOT be used as a generic target of the operation. The audited target belongs in
98
+ `resource`. This is the single most common modelling mistake this section exists to prevent.
99
+ 2. `subject` MUST be omitted when the actor acted for itself. An event where actor and subject are
100
+ the same principal carries no additional information and SHOULD NOT duplicate it.
101
+ 3. When `delegation.type` is `impersonation`, `on-behalf-of` or `delegated`, `subject` is REQUIRED.
102
+ The canonical schema enforces this.
103
+ 4. Service-to-service operations do NOT automatically require a subject. A service that performs
104
+ scheduled maintenance under its own authority has no subject. See
105
+ [approval-and-delegation.md](approval-and-delegation.md).
106
+
107
+ ### 5.3 Examples
108
+
109
+ A service acting for a user:
110
+
111
+ ```json
112
+ {
113
+ "actor": { "type": "service", "id": "service-account-reporting-worker" },
114
+ "subject": { "type": "user", "id": "user-8842" },
115
+ "delegation": { "type": "on-behalf-of", "reference": "export-request-4471" },
116
+ "resource": { "type": "report", "id": "export-4471" }
117
+ }
118
+ ```
119
+
120
+ An administrator acting **on** a user — no subject, because nobody delegated authority:
121
+
122
+ ```json
123
+ {
124
+ "actor": { "type": "admin", "id": "admin-4821" },
125
+ "resource": { "type": "user", "id": "user-7391" }
126
+ }
127
+ ```
128
+
129
+ ## 6. Attributes
130
+
131
+ `attributes` carries producer-defined principal detail that has no core representation, such as a
132
+ workload class or an authentication realm.
133
+
134
+ `attributes` MUST NOT contain credentials, tokens, keys or session material, and SHOULD NOT contain
135
+ personal data beyond what the audit purpose requires. See [privacy.md](privacy.md).
@@ -0,0 +1,150 @@
1
+ # Approval and Delegation
2
+
3
+ **Specification version: 0.1 · Status: Experimental · This document: Normative**
4
+
5
+ ## 1. Three questions that are routinely confused
6
+
7
+ | Question | Field | Nature |
8
+ | ------------------------------------------------------ | ---------------- | ------------------------------------- |
9
+ | How did the actor prove who it is? | `authentication` | Identity evidence |
10
+ | Is the actor permitted to do this? | `authorization` | Policy evaluation, usually automatic |
11
+ | Did someone decide this may proceed? | `approval` | Decision by principals, usually human |
12
+ | How did the actor obtain authority to act for another? | `delegation` | Transfer of authority |
13
+
14
+ They are independent. An operation may be authenticated and authorized but unapproved; approved but
15
+ denied by policy; or performed by a delegated actor whose own authorization is what was evaluated.
16
+ Each has its own object, and a producer MUST NOT use one to express another.
17
+
18
+ ## 2. Approval
19
+
20
+ `approval` records a decision, usually by humans, that the operation may proceed. It is OPTIONAL.
21
+
22
+ ### 2.1 Structure
23
+
24
+ All fields are OPTIONAL; when the object is present it MUST contain at least one.
25
+
26
+ | Field | Meaning |
27
+ | ------------------- | ------------------------------------------------------ |
28
+ | `status` | State of the approval at the time of the event. |
29
+ | `workflowId` | Approval workflow definition or instance. |
30
+ | `requestId` | The approval request itself. |
31
+ | `requiredApprovals` | Number of approvals required by policy. |
32
+ | `receivedApprovals` | Number of approvals received at the time of the event. |
33
+ | `approvers` | Principals that approved. |
34
+ | `approvedAt` | When the approval reached its current status. |
35
+
36
+ ### 2.2 Status
37
+
38
+ `status`, when present, MUST be one of:
39
+
40
+ | Value | Meaning |
41
+ | -------------- | ----------------------------------------------------------------- |
42
+ | `not-required` | Policy determined that no approval was needed for this operation. |
43
+ | `pending` | Approval was requested and has not been decided. |
44
+ | `approved` | The required approvals were received. |
45
+ | `rejected` | Approval was refused. |
46
+ | `expired` | The approval request lapsed before it was decided. |
47
+ | `unknown` | The producer cannot determine the approval state. |
48
+
49
+ `not-required` is not the same as omitting the object. `not-required` asserts that the question was
50
+ asked and answered; omission says nothing at all. Producers that evaluate approval requirements
51
+ SHOULD record `not-required` explicitly, because "no approval was needed" is itself an auditable
52
+ statement.
53
+
54
+ ### 2.3 Rules
55
+
56
+ 1. Approval MUST NOT be required for all events. Most operations in most applications have no
57
+ approval step, and forcing an approval object onto them produces noise, not evidence.
58
+ 2. A profile MAY require approval for a specific class of events. That requirement belongs to the
59
+ profile, never to the core model. See [profiles/](../profiles/).
60
+ 3. `approvers` SHOULD identify the principals whose decisions were counted, not everyone who was
61
+ notified.
62
+ 4. `receivedApprovals` SHOULD be consistent with the length of `approvers` when both are present. The
63
+ schema does not enforce this, because an approver may legitimately be recorded without being
64
+ identifiable to the producing application.
65
+ 5. An event with `status` of `pending` or `rejected` and a successful outcome describes a control
66
+ bypass. Producers SHOULD record it accurately rather than suppressing it; that combination is
67
+ exactly what a reviewer needs to find.
68
+
69
+ ## 3. Delegation
70
+
71
+ `delegation` records **how the actor obtained authority to act for the subject**. It is OPTIONAL.
72
+
73
+ ### 3.1 Structure
74
+
75
+ | Field | Required | Meaning |
76
+ | ------------ | -------- | -------------------------------------------------------- |
77
+ | `type` | Yes | Kind of delegation. |
78
+ | `reason` | No | Why delegation was used. |
79
+ | `reference` | No | Grant, ticket or session that authorized the delegation. |
80
+ | `approvedBy` | No | Principal that approved the delegation. |
81
+
82
+ `type` is REQUIRED when the object is present. Delegation without a type cannot be interpreted, and
83
+ the conditional rule in §3.3 depends on it.
84
+
85
+ ### 3.2 Types
86
+
87
+ | Value | Meaning |
88
+ | --------------- | --------------------------------------------------------------------------------------------- |
89
+ | `impersonation` | The actor assumed the subject's identity. The system behaved as if the subject acted. |
90
+ | `on-behalf-of` | The actor acted for the subject using its own identity. |
91
+ | `delegated` | Authority was granted to the actor in advance, for example a delegated administrator. |
92
+ | `service-chain` | The operation traversed intermediate services. Describes transport, not a person's authority. |
93
+
94
+ ### 3.3 Subject requirement
95
+
96
+ When `delegation.type` is `impersonation`, `on-behalf-of` or `delegated`, the event MUST contain
97
+ `subject`. The canonical schema enforces this.
98
+
99
+ The reason is simple: each of these types asserts that someone else's authority was used. An
100
+ assertion of borrowed authority that does not say whose authority was borrowed is not auditable.
101
+
102
+ `service-chain` does **not** require a subject. Service-to-service operations are routine and often
103
+ have no human principal behind them at all. Requiring a subject for every service call would force
104
+ producers to invent one, which is worse than recording nothing.
105
+
106
+ ### 3.4 Impersonation
107
+
108
+ Impersonation is the highest-risk case in this model, because the system's own records elsewhere will
109
+ show the subject acting. Producers that support impersonation:
110
+
111
+ - MUST record `actor` as the impersonating principal, never as the subject.
112
+ - SHOULD record `reason` and `reference`.
113
+ - SHOULD record `approvedBy` where the impersonation required approval.
114
+ - SHOULD include `privileged-access` in `controlCategories`.
115
+
116
+ ## 4. Worked example
117
+
118
+ An administrator impersonates a customer to reproduce a fault, with an approved support case:
119
+
120
+ ```json
121
+ {
122
+ "event": {
123
+ "name": "identity.session.impersonate",
124
+ "category": "identity",
125
+ "outcome": "success",
126
+ "severity": "critical"
127
+ },
128
+ "actor": { "type": "admin", "id": "admin-4821" },
129
+ "subject": { "type": "user", "id": "user-7391" },
130
+ "delegation": {
131
+ "type": "impersonation",
132
+ "reason": "Reproducing a reported checkout failure.",
133
+ "reference": "support-case-3391",
134
+ "approvedBy": { "type": "user", "id": "user-1180" }
135
+ },
136
+ "resource": { "type": "session", "id": "session-impersonation-5f21" },
137
+ "authorization": { "decision": "allow", "policy": "support-impersonation" },
138
+ "approval": {
139
+ "status": "approved",
140
+ "requestId": "approval-request-7781",
141
+ "requiredApprovals": 1,
142
+ "receivedApprovals": 1,
143
+ "approvedAt": "2026-03-14T10:02:00Z"
144
+ },
145
+ "controlCategories": ["privileged-access", "change-approval"]
146
+ }
147
+ ```
148
+
149
+ Note what each object contributes: `authorization` says policy permitted it, `approval` says a person
150
+ sanctioned it, `delegation` says whose authority was used, and `subject` says who that was.
@@ -0,0 +1,116 @@
1
+ # Authentication Context
2
+
3
+ **Specification version: 0.1 · Status: Experimental · This document: Normative**
4
+
5
+ ## 1. Purpose
6
+
7
+ `authentication` records **how the actor proved its identity** for the session behind this operation.
8
+ It is OPTIONAL.
9
+
10
+ It answers questions such as: was this a password sign-in or a certificate? Was multi-factor
11
+ authentication satisfied? Which identity provider asserted the identity? How old is the session?
12
+
13
+ ## 2. Structure
14
+
15
+ All fields are OPTIONAL. When the object is present it MUST contain at least one of them.
16
+
17
+ | Field | Meaning |
18
+ | ----------------- | ------------------------------------------------------------------- |
19
+ | `method` | Authentication method used. Closed vocabulary, see §3. |
20
+ | `provider` | Identity provider that performed authentication. |
21
+ | `mfa` | Whether multi-factor authentication was satisfied for this session. |
22
+ | `assuranceLevel` | Producer-defined assurance level. |
23
+ | `sessionId` | Session correlation identifier. |
24
+ | `authenticatedAt` | When the session behind this operation was authenticated. |
25
+
26
+ ## 3. Methods
27
+
28
+ `method`, when present, MUST be one of:
29
+
30
+ ```text
31
+ password mfa oidc saml certificate
32
+ api-key service-account session anonymous
33
+ other unknown
34
+ ```
35
+
36
+ Notes:
37
+
38
+ - `mfa` as a _method_ means the producer knows only that a multi-factor flow was used and cannot
39
+ identify the primary factor. Where the primary factor is known, producers SHOULD record it in
40
+ `method` and set the `mfa` boolean to `true`. The two are not redundant: `method` is _what_ was
41
+ used, `mfa` is _whether a second factor was satisfied_.
42
+ - `session` means the operation reused an established session rather than performing a fresh
43
+ authentication.
44
+ - `other` and `unknown` are escape values. `unknown` MUST NOT be used to avoid deciding.
45
+
46
+ ## 4. Absence is not anonymity
47
+
48
+ This is the most important rule in this document.
49
+
50
+ **An absent `authentication` object and `method: anonymous` mean different things.**
51
+
52
+ | Situation | Correct representation |
53
+ | --------------------------------------------------------- | -------------------------------------- |
54
+ | No authentication context is available or applicable | Omit `authentication` entirely |
55
+ | The principal was deliberately unauthenticated | `authentication.method` is `anonymous` |
56
+ | The producer knows a session existed but not how it began | `authentication.method` is `unknown` |
57
+
58
+ A consumer MUST NOT treat a missing `authentication` object as evidence that the operation was
59
+ unauthenticated, and MUST NOT treat it as an error.
60
+
61
+ The model MUST allow authentication context to be absent for:
62
+
63
+ - System-generated operations.
64
+ - Background jobs and scheduled processes.
65
+ - Non-interactive service-to-service operations.
66
+ - Events imported from legacy systems that never recorded it.
67
+
68
+ ## 5. Assurance level
69
+
70
+ `assuranceLevel` is a producer-defined token describing how strongly the identity was established,
71
+ for example `low`, `substantial` or `high`.
72
+
73
+ The core specification deliberately does NOT define an assurance scale and does NOT map to any
74
+ external assurance framework. Assurance frameworks are jurisdiction-specific and revised on their own
75
+ schedules; binding the core model to one would violate
76
+ [design principle 9](design-principles.md#9-regulation-neutral-industry-neutral-jurisdiction-neutral).
77
+ Producers that need a framework mapping SHOULD publish it alongside their own value definitions.
78
+
79
+ ## 6. Session identifiers
80
+
81
+ `sessionId` is a **correlation identifier**, not a credential.
82
+
83
+ `sessionId` MUST NOT be a usable session token, bearer token, cookie value or anything else that
84
+ would allow a reader of the audit event to assume the session. Where the underlying session
85
+ identifier is itself the credential, producers MUST record a derived, non-reversible correlation
86
+ value instead — for example a keyed hash — or omit the field.
87
+
88
+ See [privacy.md](privacy.md) for the complete list of values that MUST NOT be recorded.
89
+
90
+ ## 7. Relationship to authorization and approval
91
+
92
+ Authentication, authorization and approval are three different questions and MUST NOT be conflated:
93
+
94
+ | Question | Field |
95
+ | ---------------------------------------------------- | ---------------- |
96
+ | Who is this principal, and how do we know? | `authentication` |
97
+ | Is this principal permitted to do this? | `authorization` |
98
+ | Did someone decide this should be allowed to happen? | `approval` |
99
+
100
+ See [authorization.md](authorization.md) and
101
+ [approval-and-delegation.md](approval-and-delegation.md).
102
+
103
+ ## 8. Example
104
+
105
+ ```json
106
+ {
107
+ "authentication": {
108
+ "method": "oidc",
109
+ "provider": "corporate-idp",
110
+ "mfa": true,
111
+ "assuranceLevel": "high",
112
+ "sessionId": "session-b71f",
113
+ "authenticatedAt": "2026-03-14T09:58:02Z"
114
+ }
115
+ }
116
+ ```
@@ -0,0 +1,117 @@
1
+ # Authorization Context
2
+
3
+ **Specification version: 0.1 · Status: Experimental · This document: Normative**
4
+
5
+ ## 1. Purpose
6
+
7
+ `authorization` records the **decision** that permitted or denied the operation. It is OPTIONAL.
8
+
9
+ The purpose is to make the decision reviewable after the fact: which policy applied, which version of
10
+ it, what it decided, and why. Without this, a reviewer looking at a denied operation cannot tell
11
+ whether the control worked or whether the request never reached it.
12
+
13
+ ## 2. Structure
14
+
15
+ | Field | Required | Meaning |
16
+ | --------------- | -------- | ---------------------------------------------------- |
17
+ | `decision` | Yes | Outcome of the authorization evaluation. |
18
+ | `engine` | No | Component that produced the decision. |
19
+ | `policy` | No | Identifier of the policy that produced the decision. |
20
+ | `policyVersion` | No | Version of that policy. |
21
+ | `reason` | No | Sanitized explanation of the decision. |
22
+ | `permissions` | No | Permissions evaluated or required for the operation. |
23
+
24
+ When `authorization` is present, `decision` is REQUIRED. An authorization object that records a
25
+ policy but no decision is not useful and is rejected by the schema.
26
+
27
+ ## 3. Decisions
28
+
29
+ `decision` MUST be one of:
30
+
31
+ | Value | Meaning |
32
+ | ---------------- | ---------------------------------------------------------- |
33
+ | `allow` | The operation was permitted. |
34
+ | `deny` | The operation was refused by the authorization evaluation. |
35
+ | `not-applicable` | No authorization evaluation applied to this operation. |
36
+ | `unknown` | The producer cannot determine what the evaluation decided. |
37
+
38
+ A `deny` decision normally accompanies `event.outcome` of `failure`, and the event MUST then carry
39
+ `event.error`. Recording the denial as a successful operation misrepresents the control.
40
+
41
+ `not-applicable` is meaningful: it distinguishes "no policy governs this" from "we did not record
42
+ it". Producers SHOULD prefer omitting the object entirely when they simply have no information.
43
+
44
+ ## 4. This is a record, not an engine
45
+
46
+ OpenAuditModel records authorization **results**. It MUST NOT become an authorization system.
47
+
48
+ Consequently:
49
+
50
+ 1. The model defines no policy language, no rule syntax and no evaluation semantics.
51
+ 2. The schema MUST NOT require any particular policy engine, and MUST NOT contain any engine's
52
+ vocabulary. `engine` is a free identifier precisely so that no engine is privileged.
53
+ 3. A consumer MUST NOT attempt to re-evaluate a policy from an audit event. Audit events describe
54
+ what happened; they are not an input to access control.
55
+ 4. Nothing in this specification should be read as requiring centralized policy evaluation. An
56
+ application whose authorization is ordinary code in a service can populate `decision`, `reason`
57
+ and `permissions` perfectly well.
58
+
59
+ ## 5. Policy identification
60
+
61
+ `policy` and `policyVersion` exist so that a reviewer can reconstruct **which rule** produced the
62
+ decision. Recording a decision without identifying the rule that produced it makes historical review
63
+ unreliable, because policies change.
64
+
65
+ Producers that version their policies SHOULD populate `policyVersion`. A `policy` value SHOULD be
66
+ stable across releases in the same way an event name is.
67
+
68
+ ## 6. Reason
69
+
70
+ `authorization.reason` is a sanitized, human-readable explanation of the decision, such as
71
+ "role does not grant the requested permission on this tenant".
72
+
73
+ It MUST NOT contain the full policy document, the complete attribute set that was evaluated,
74
+ credentials, or personal data beyond what the audit purpose requires. A consumer MUST NOT parse it.
75
+
76
+ This field is distinct from the top-level `reason` object, which records the **business
77
+ justification for performing the operation**. One explains the machine decision; the other explains
78
+ human intent. An event may carry both.
79
+
80
+ ## 7. Permissions
81
+
82
+ `permissions` lists the permissions evaluated or required for the operation, using the producer's own
83
+ permission vocabulary. It SHOULD contain the permissions relevant to **this** operation, not the
84
+ principal's complete permission set.
85
+
86
+ ## 8. Example
87
+
88
+ ```json
89
+ {
90
+ "authorization": {
91
+ "decision": "allow",
92
+ "engine": "policy-service",
93
+ "policy": "privileged-configuration-change",
94
+ "policyVersion": "23",
95
+ "reason": "Actor holds the platform administrator role within an approved change window.",
96
+ "permissions": ["configuration.setting.update"]
97
+ }
98
+ }
99
+ ```
100
+
101
+ A denial:
102
+
103
+ ```json
104
+ {
105
+ "event": {
106
+ "name": "document.file.download",
107
+ "category": "data-access",
108
+ "outcome": "failure",
109
+ "error": { "code": "permission-denied", "type": "authorization", "retryable": false }
110
+ },
111
+ "authorization": {
112
+ "decision": "deny",
113
+ "policy": "document-access",
114
+ "reason": "Requested classification exceeds the actor's clearance."
115
+ }
116
+ }
117
+ ```
@@ -0,0 +1,134 @@
1
+ # Change Model
2
+
3
+ **Specification version: 0.1 · Status: Experimental · This document: Normative**
4
+
5
+ ## 1. Purpose
6
+
7
+ `change` records **what the operation changed**. It is OPTIONAL.
8
+
9
+ The difficulty is that the most useful audit answer — "what was it before?" — is also the most
10
+ dangerous one to record. A naive implementation that serializes the whole record before and after
11
+ turns the audit log into a second, less protected copy of the production database. This document
12
+ exists to make the safe options first-class.
13
+
14
+ ## 2. Structure
15
+
16
+ All fields are OPTIONAL; when the object is present it MUST contain at least one.
17
+
18
+ | Field | Meaning |
19
+ | --------------- | ---------------------------------------------------------- |
20
+ | `type` | Kind of change performed. |
21
+ | `changedFields` | Paths of the fields that changed. |
22
+ | `before` | Sanitized prior state, or the part of it that changed. |
23
+ | `after` | Sanitized resulting state, or the part of it that changed. |
24
+ | `beforeHash` | Digest of the prior state. |
25
+ | `afterHash` | Digest of the resulting state. |
26
+ | `ticketId` | Change or service ticket associated with the change. |
27
+ | `incidentId` | Incident associated with the change. |
28
+ | `deploymentId` | Deployment or release associated with the change. |
29
+
30
+ ## 3. Change types
31
+
32
+ `type`, when present, MUST be one of:
33
+
34
+ ```text
35
+ create update delete restore move execute none other
36
+ ```
37
+
38
+ Notes:
39
+
40
+ - `execute` describes an operation that ran something without changing stored state in the ordinary
41
+ sense — resetting a consumer offset, triggering a job, rotating a key.
42
+ - `none` records that an operation completed without changing anything. This is meaningful for
43
+ idempotent operations, where "nothing changed" is a real result rather than a missing value.
44
+ - `other` exists so that producers are not forced into a wrong value.
45
+
46
+ ## 4. Complete state is never required
47
+
48
+ The schema MUST NOT require complete `before` and `after` objects. A producer MAY describe a change
49
+ in whichever of these ways fits its risk profile:
50
+
51
+ | Approach | What it records | When to prefer it |
52
+ | ----------------------- | ---------------------------------------- | --------------------------------------------------- |
53
+ | **Changed field names** | `changedFields` only | The fact of change matters; values are sensitive |
54
+ | **Sanitized state** | `before` and `after` for selected fields | Values are needed for review and are safe to record |
55
+ | **Hashes** | `beforeHash` and `afterHash` | Verification is needed without disclosure |
56
+ | **References** | `ticketId`, `incidentId`, `deploymentId` | The authoritative detail lives in another system |
57
+
58
+ These compose. Recording `changedFields` together with hashes gives a reviewer the shape of a change
59
+ and the ability to verify a claimed prior state, while disclosing neither.
60
+
61
+ ## 5. What MUST NOT go into before and after
62
+
63
+ `before` and `after` MUST NOT contain:
64
+
65
+ - Passwords, password hashes, or password history.
66
+ - Access tokens, refresh tokens, API keys, private keys or connection strings.
67
+ - Complete database records copied verbatim.
68
+ - Full request or response payloads.
69
+ - Special-category personal data that the audit purpose does not require.
70
+
71
+ A change to a credential MUST be recorded as the **fact** of the change, never as its values:
72
+
73
+ ```json
74
+ {
75
+ "event": { "name": "identity.credential.rotate", "category": "identity", "outcome": "success" },
76
+ "change": { "type": "update", "changedFields": ["clientSecret"], "ticketId": "change-4410" }
77
+ }
78
+ ```
79
+
80
+ Recording `{"before": {"clientSecret": "..."}}` is a defect, not a more complete audit event.
81
+
82
+ ## 6. Guidance for before and after values
83
+
84
+ 1. Producers SHOULD record only the fields named in `changedFields`, not the entire object.
85
+ 2. Producers SHOULD apply the same masking rules to `before` and `after` that they apply to any other
86
+ sensitive output, and SHOULD record `privacy.processing` when they do. See
87
+ [privacy.md](privacy.md).
88
+ 3. Large collections SHOULD be summarized rather than embedded. A permission change affecting 4,000
89
+ users is better recorded as a count and a scope than as 4,000 identifiers.
90
+ 4. `before` and `after` SHOULD be structurally comparable. Recording an object in one and a rendered
91
+ string in the other prevents automated diffing.
92
+ 5. Where a change is not expressible as a field diff — a document body replaced, a binary uploaded —
93
+ producers SHOULD use hashes or an evidence reference instead. See
94
+ [evidence-model.md](evidence-model.md).
95
+
96
+ ## 7. Hashes
97
+
98
+ `beforeHash` and `afterHash` allow a reviewer to verify a claimed prior or resulting state without
99
+ the audit event containing it.
100
+
101
+ - The algorithm and encoding SHOULD be documented by the producer, and SHOULD match the algorithm
102
+ recorded in `integrity.hashAlgorithm` where an integrity object is present.
103
+ - A hash of a low-entropy value is reversible by enumeration. Producers MUST NOT treat a hash of a
104
+ small value space, such as a boolean flag or a status enumeration, as a privacy control.
105
+
106
+ ## 8. Correlation to change management
107
+
108
+ `ticketId`, `incidentId` and `deploymentId` connect the technical change to the process that
109
+ authorized it. They are plain identifiers: the model deliberately does not define a change management
110
+ process, a ticket format or a workflow.
111
+
112
+ Where the change was approved, `approval` records the approval itself; `change.ticketId` records the
113
+ record it was approved under. See [approval-and-delegation.md](approval-and-delegation.md).
114
+
115
+ ## 9. Example
116
+
117
+ ```json
118
+ {
119
+ "change": {
120
+ "type": "update",
121
+ "changedFields": ["sessionLifetimeMinutes", "requireReauthenticationForPrivilegedActions"],
122
+ "before": {
123
+ "sessionLifetimeMinutes": 720,
124
+ "requireReauthenticationForPrivilegedActions": false
125
+ },
126
+ "after": {
127
+ "sessionLifetimeMinutes": 60,
128
+ "requireReauthenticationForPrivilegedActions": true
129
+ },
130
+ "ticketId": "change-9910",
131
+ "deploymentId": "deployment-2026-03-16-3"
132
+ }
133
+ }
134
+ ```