@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.
- package/LICENSE +215 -0
- package/README.md +647 -0
- package/dist/conformance/src/cli.d.ts +20 -0
- package/dist/conformance/src/cli.js +560 -0
- package/dist/conformance/src/cli.js.map +1 -0
- package/dist/conformance/src/format-errors.d.ts +20 -0
- package/dist/conformance/src/format-errors.js +116 -0
- package/dist/conformance/src/format-errors.js.map +1 -0
- package/dist/conformance/src/integrity/canonicalize.d.ts +25 -0
- package/dist/conformance/src/integrity/canonicalize.js +100 -0
- package/dist/conformance/src/integrity/canonicalize.js.map +1 -0
- package/dist/conformance/src/integrity/digest.d.ts +54 -0
- package/dist/conformance/src/integrity/digest.js +126 -0
- package/dist/conformance/src/integrity/digest.js.map +1 -0
- package/dist/conformance/src/integrity/types.d.ts +86 -0
- package/dist/conformance/src/integrity/types.js +36 -0
- package/dist/conformance/src/integrity/types.js.map +1 -0
- package/dist/conformance/src/integrity/verify-chain.d.ts +23 -0
- package/dist/conformance/src/integrity/verify-chain.js +235 -0
- package/dist/conformance/src/integrity/verify-chain.js.map +1 -0
- package/dist/conformance/src/integrity/verify-event.d.ts +29 -0
- package/dist/conformance/src/integrity/verify-event.js +140 -0
- package/dist/conformance/src/integrity/verify-event.js.map +1 -0
- package/dist/conformance/src/privacy/entropy.d.ts +14 -0
- package/dist/conformance/src/privacy/entropy.js +86 -0
- package/dist/conformance/src/privacy/entropy.js.map +1 -0
- package/dist/conformance/src/privacy/field-names.d.ts +36 -0
- package/dist/conformance/src/privacy/field-names.js +121 -0
- package/dist/conformance/src/privacy/field-names.js.map +1 -0
- package/dist/conformance/src/privacy/lint-event.d.ts +18 -0
- package/dist/conformance/src/privacy/lint-event.js +272 -0
- package/dist/conformance/src/privacy/lint-event.js.map +1 -0
- package/dist/conformance/src/privacy/rules.d.ts +44 -0
- package/dist/conformance/src/privacy/rules.js +161 -0
- package/dist/conformance/src/privacy/rules.js.map +1 -0
- package/dist/conformance/src/privacy/safe-formats.d.ts +32 -0
- package/dist/conformance/src/privacy/safe-formats.js +118 -0
- package/dist/conformance/src/privacy/safe-formats.js.map +1 -0
- package/dist/conformance/src/privacy/size-analysis.d.ts +36 -0
- package/dist/conformance/src/privacy/size-analysis.js +87 -0
- package/dist/conformance/src/privacy/size-analysis.js.map +1 -0
- package/dist/conformance/src/privacy/token-patterns.d.ts +24 -0
- package/dist/conformance/src/privacy/token-patterns.js +126 -0
- package/dist/conformance/src/privacy/token-patterns.js.map +1 -0
- package/dist/conformance/src/privacy/traverse.d.ts +33 -0
- package/dist/conformance/src/privacy/traverse.js +61 -0
- package/dist/conformance/src/privacy/traverse.js.map +1 -0
- package/dist/conformance/src/privacy/types.d.ts +58 -0
- package/dist/conformance/src/privacy/types.js +32 -0
- package/dist/conformance/src/privacy/types.js.map +1 -0
- package/dist/conformance/src/privacy/url-analysis.d.ts +40 -0
- package/dist/conformance/src/privacy/url-analysis.js +148 -0
- package/dist/conformance/src/privacy/url-analysis.js.map +1 -0
- package/dist/conformance/src/profiles/check-profile.d.ts +22 -0
- package/dist/conformance/src/profiles/check-profile.js +72 -0
- package/dist/conformance/src/profiles/check-profile.js.map +1 -0
- package/dist/conformance/src/profiles/evaluate-rule.d.ts +27 -0
- package/dist/conformance/src/profiles/evaluate-rule.js +87 -0
- package/dist/conformance/src/profiles/evaluate-rule.js.map +1 -0
- package/dist/conformance/src/profiles/load-profile.d.ts +30 -0
- package/dist/conformance/src/profiles/load-profile.js +95 -0
- package/dist/conformance/src/profiles/load-profile.js.map +1 -0
- package/dist/conformance/src/profiles/resolve-pointer.d.ts +44 -0
- package/dist/conformance/src/profiles/resolve-pointer.js +123 -0
- package/dist/conformance/src/profiles/resolve-pointer.js.map +1 -0
- package/dist/conformance/src/profiles/select-rules.d.ts +13 -0
- package/dist/conformance/src/profiles/select-rules.js +42 -0
- package/dist/conformance/src/profiles/select-rules.js.map +1 -0
- package/dist/conformance/src/profiles/types.d.ts +101 -0
- package/dist/conformance/src/profiles/types.js +31 -0
- package/dist/conformance/src/profiles/types.js.map +1 -0
- package/dist/conformance/src/profiles/validate-profile-definition.d.ts +12 -0
- package/dist/conformance/src/profiles/validate-profile-definition.js +47 -0
- package/dist/conformance/src/profiles/validate-profile-definition.js.map +1 -0
- package/dist/conformance/src/sources.d.ts +53 -0
- package/dist/conformance/src/sources.js +153 -0
- package/dist/conformance/src/sources.js.map +1 -0
- package/dist/conformance/src/validate-core.d.ts +30 -0
- package/dist/conformance/src/validate-core.js +62 -0
- package/dist/conformance/src/validate-core.js.map +1 -0
- package/dist/conformance/src/validate.d.ts +34 -0
- package/dist/conformance/src/validate.js +62 -0
- package/dist/conformance/src/validate.js.map +1 -0
- package/dist/conformance/src/validator-interface.d.ts +35 -0
- package/dist/conformance/src/validator-interface.js +19 -0
- package/dist/conformance/src/validator-interface.js.map +1 -0
- package/package.json +85 -0
- package/profiles/README.md +201 -0
- package/profiles/api-and-integration-management/README.md +271 -0
- package/profiles/api-and-integration-management/profile.json +258 -0
- package/profiles/backup-and-recovery/README.md +318 -0
- package/profiles/backup-and-recovery/profile.json +178 -0
- package/profiles/customer-and-account-management/README.md +340 -0
- package/profiles/customer-and-account-management/profile.json +237 -0
- package/profiles/deployment-and-change-management/README.md +359 -0
- package/profiles/deployment-and-change-management/profile.json +298 -0
- package/profiles/document-management/README.md +120 -0
- package/profiles/document-management/profile.json +170 -0
- package/profiles/financial-transaction-management/README.md +339 -0
- package/profiles/financial-transaction-management/profile.json +247 -0
- package/profiles/identity-and-access-management/README.md +112 -0
- package/profiles/identity-and-access-management/profile.json +120 -0
- package/profiles/incident-management/README.md +338 -0
- package/profiles/incident-management/profile.json +256 -0
- package/profiles/message-broker-management/README.md +344 -0
- package/profiles/message-broker-management/profile.json +399 -0
- package/profiles/profile-definition.schema.json +213 -0
- package/profiles/secrets-and-key-management/README.md +331 -0
- package/profiles/secrets-and-key-management/profile.json +219 -0
- package/schemas/v0.1/audit-event.schema.json +911 -0
- package/semantic-conventions/README.md +52 -0
- package/semantic-conventions/authentication.md +111 -0
- package/semantic-conventions/configuration-and-change.md +122 -0
- package/semantic-conventions/correlation-and-tracing.md +387 -0
- package/semantic-conventions/data-access.md +115 -0
- package/semantic-conventions/event-naming.md +114 -0
- package/semantic-conventions/identity-and-access.md +112 -0
- package/semantic-conventions/privileged-operations.md +110 -0
- package/semantic-conventions/workflow-and-approval.md +109 -0
- package/specification/actor-model.md +135 -0
- package/specification/approval-and-delegation.md +150 -0
- package/specification/authentication.md +116 -0
- package/specification/authorization.md +117 -0
- package/specification/change-model.md +134 -0
- package/specification/delivery.md +136 -0
- package/specification/design-principles.md +137 -0
- package/specification/event-model.md +387 -0
- package/specification/evidence-model.md +109 -0
- package/specification/extension-model.md +159 -0
- package/specification/integrity.md +314 -0
- package/specification/overview.md +172 -0
- package/specification/privacy.md +386 -0
- package/specification/resource-model.md +116 -0
- 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
|
+
```
|