@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
package/README.md
ADDED
|
@@ -0,0 +1,647 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="assets/logo.png" alt="OpenAuditModel" width="420">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# OpenAuditModel
|
|
6
|
+
|
|
7
|
+
> **OpenAuditModel defines a common, verifiable and backend-independent audit event model for
|
|
8
|
+
> business applications.**
|
|
9
|
+
>
|
|
10
|
+
> **One audit model for every application.**
|
|
11
|
+
|
|
12
|
+
| | |
|
|
13
|
+
| ------------------------- | ---------------------------------------------------------------- |
|
|
14
|
+
| **Specification version** | 0.1 |
|
|
15
|
+
| **Project status** | **Experimental** |
|
|
16
|
+
| **Production readiness** | **Not production-ready** |
|
|
17
|
+
| **Compliance** | **No compliance guarantee** |
|
|
18
|
+
| **Canonical schema** | `https://openauditmodel.org/schemas/audit-event/0.1/schema.json` |
|
|
19
|
+
| **License** | Apache License 2.0 |
|
|
20
|
+
|
|
21
|
+
Version 0.1 is an experimental specification. Field names, constraints, vocabularies and the
|
|
22
|
+
compatibility strategy may all change. Nothing here constitutes legal advice, and conformance to this
|
|
23
|
+
specification is not compliance with any law, regulation, standard or contract.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Quick start
|
|
28
|
+
|
|
29
|
+
Not yet published to a package registry. One clone, one build, then commands against any file.
|
|
30
|
+
Requires Node.js 22 or newer.
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
git clone https://github.com/OpenAuditModel/OpenAuditModel.git
|
|
34
|
+
cd OpenAuditModel && npm install && npm run build
|
|
35
|
+
|
|
36
|
+
cat > audit-event.json <<'EOF'
|
|
37
|
+
{
|
|
38
|
+
"specVersion": "0.1",
|
|
39
|
+
"id": "018f1b70-2c18-7f3a-b46d-5e8a1c9d0b12",
|
|
40
|
+
"time": "2026-03-14T11:47:52.108Z",
|
|
41
|
+
"event": {
|
|
42
|
+
"name": "financial.transfer.execute",
|
|
43
|
+
"category": "data-modification",
|
|
44
|
+
"outcome": "success"
|
|
45
|
+
},
|
|
46
|
+
"actor": { "type": "user", "id": "user-5120" },
|
|
47
|
+
"resource": { "type": "money-transfer", "id": "transfer-2026-004418" },
|
|
48
|
+
"application": { "name": "payments-api", "environment": "production" }
|
|
49
|
+
}
|
|
50
|
+
EOF
|
|
51
|
+
|
|
52
|
+
npm run auditmodel -- validate audit-event.json
|
|
53
|
+
npm run auditmodel -- lint-privacy audit-event.json
|
|
54
|
+
npm run auditmodel -- check-profile audit-event.json --profile financial-transaction-management
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The binary is `auditmodel` once built (`node dist/conformance/src/cli.js` directly, or `npm run
|
|
58
|
+
auditmodel --` as above); `openauditmodel` is accepted as an alias. The profile is passed with
|
|
59
|
+
`--profile`, never positionally.
|
|
60
|
+
|
|
61
|
+
That third command **fails**, and it is meant to. The event is schema-valid but the financial profile
|
|
62
|
+
requires an authorization decision, a correlation identifier, a transaction reference, an amount, a
|
|
63
|
+
currency, a direction, a status and a linked resource. The output names each missing field with a
|
|
64
|
+
JSON Pointer. Adding them is the point of the exercise:
|
|
65
|
+
|
|
66
|
+
```jsonc
|
|
67
|
+
"authorization": { "decision": "allow" },
|
|
68
|
+
"request": { "correlationId": "transfer-2026-004418" },
|
|
69
|
+
"relatedResources": [{ "type": "account", "id": "account-ref-781" }],
|
|
70
|
+
"metadata": {
|
|
71
|
+
"financial": {
|
|
72
|
+
"transactionId": "txn-2026-0314-0091",
|
|
73
|
+
"amount": 1250.5,
|
|
74
|
+
"currency": "EUR",
|
|
75
|
+
"direction": "outbound",
|
|
76
|
+
"status": "settled"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
With those added the event conforms and `check-profile` exits `0`. Note what the profile asked for
|
|
82
|
+
and what it did not: an amount and a currency, but no account number, no counterparty name and no
|
|
83
|
+
payment instruction. A profile requires the fields that make an operation reviewable, not the
|
|
84
|
+
business record itself.
|
|
85
|
+
|
|
86
|
+
### Exit codes
|
|
87
|
+
|
|
88
|
+
The same contract across every command, so a CI job can branch on it:
|
|
89
|
+
|
|
90
|
+
| Code | Meaning |
|
|
91
|
+
| ---- | ------------------------------------------------------------------------------------ |
|
|
92
|
+
| `0` | A verdict was produced and it passed. |
|
|
93
|
+
| `1` | A verdict was produced and it failed — invalid, a privacy finding, a rule violation. |
|
|
94
|
+
| `2` | The tool could not run: unreadable file, bad arguments, unknown profile. |
|
|
95
|
+
| `3` | **No verdict was produced.** Nothing was evaluated. |
|
|
96
|
+
|
|
97
|
+
`3` is the one worth understanding, because it is the code that is easy to misread as success:
|
|
98
|
+
|
|
99
|
+
- `check-profile` returns it when **no rule in the profile governs the event**. That usually means the
|
|
100
|
+
event name does not match the profile's vocabulary — `transfer.created` instead of
|
|
101
|
+
`financial.transfer.execute`, say. **Not-applicable is not conformance.** The profile said nothing
|
|
102
|
+
about this event; it did not approve it.
|
|
103
|
+
- `lint-privacy` returns it when the input **is not an OpenAuditModel event**, so nothing was scanned.
|
|
104
|
+
The linter reads the locations the specification defines on an audit event; point it at an
|
|
105
|
+
arbitrary application log and it has nowhere to look. It reports that plainly rather than
|
|
106
|
+
reporting `clean`.
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# conforming → 0 the profile's rules were checked and passed
|
|
110
|
+
# violations → 1 the event matched the profile and failed a rule
|
|
111
|
+
# not applicable → 3 the event name matched no rule in the profile
|
|
112
|
+
npm run auditmodel -- check-profile audit-event.json --profile document-management
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
That last command returns `3` for the financial event above: `document-management` governs no
|
|
116
|
+
`financial.*` event. Running an event against the wrong profile can never produce a pass.
|
|
117
|
+
|
|
118
|
+
### Exporting an existing audit trail
|
|
119
|
+
|
|
120
|
+
Adoption does not require changing where you store anything. The lowest-friction path is an export
|
|
121
|
+
mapper, which is also the shape enterprise customers ask for:
|
|
122
|
+
|
|
123
|
+
```text
|
|
124
|
+
existing audit database → mapper → OpenAuditModel NDJSON → customer, archive or SIEM
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
`validate`, `lint-privacy` and `check-profile` all accept `.ndjson` and `.jsonl`, so the export can be
|
|
128
|
+
checked in CI before it is handed to anyone.
|
|
129
|
+
|
|
130
|
+
## What is OpenAuditModel?
|
|
131
|
+
|
|
132
|
+
OpenAuditModel is an open, vendor-neutral specification for the structure of an audit event: a
|
|
133
|
+
record of an auditable operation performed in a business application.
|
|
134
|
+
|
|
135
|
+
It consists of:
|
|
136
|
+
|
|
137
|
+
- A **normative specification** describing what an audit event is and what a producer must record.
|
|
138
|
+
- A **canonical JSON Schema** (Draft 2020-12) that machine-verifies the structure.
|
|
139
|
+
- A **conformance toolchain** — a CLI, fixtures and tests — so that conformance is provable rather
|
|
140
|
+
than asserted.
|
|
141
|
+
|
|
142
|
+
The model itself is not a product, a service, a library or a pipeline: an audit event is valid with
|
|
143
|
+
nothing deployed. The repository does also contain an optional MCP server for tooling, which is not
|
|
144
|
+
part of the specification and which nobody needs in order to conform.
|
|
145
|
+
|
|
146
|
+
## What problem does it solve?
|
|
147
|
+
|
|
148
|
+
Almost every application records auditable operations, and almost every application invents its own
|
|
149
|
+
shape for them. The consequences are familiar:
|
|
150
|
+
|
|
151
|
+
- Audit records cannot be validated, so defects are found years later, in retained data.
|
|
152
|
+
- Two systems' audit trails cannot be read together without bespoke translation.
|
|
153
|
+
- Every new application re-litigates the same questions: what is an actor, how do we record acting on
|
|
154
|
+
behalf of someone, where does the approval go.
|
|
155
|
+
- Audit data accumulates secrets and personal data because nobody decided what should be recorded.
|
|
156
|
+
- Migrating storage means rewriting the data model.
|
|
157
|
+
|
|
158
|
+
OpenAuditModel answers those questions once, in a way that is checkable by a validator.
|
|
159
|
+
|
|
160
|
+
It standardizes how applications describe operations such as authentication, authorization, identity
|
|
161
|
+
changes, privileged operations, data access, data modification, configuration changes, workflow
|
|
162
|
+
approvals, delegation, impersonation, administrative actions, security-relevant actions, external
|
|
163
|
+
data sharing, resource lifecycle operations, and deployment and operational changes.
|
|
164
|
+
|
|
165
|
+
## Why is an audit event different from an application debug log?
|
|
166
|
+
|
|
167
|
+
An application log line says:
|
|
168
|
+
|
|
169
|
+
```text
|
|
170
|
+
Document downloaded successfully.
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
That is enough to debug the download and almost useless six months later. A structured audit event
|
|
174
|
+
answers the questions a reviewer, an investigator or a customer will actually ask:
|
|
175
|
+
|
|
176
|
+
- Who performed the operation?
|
|
177
|
+
- Was it a user, a service or the system itself?
|
|
178
|
+
- Was it performed on behalf of someone else?
|
|
179
|
+
- What action was performed?
|
|
180
|
+
- What resource was affected?
|
|
181
|
+
- What was the result?
|
|
182
|
+
- What authorization decision allowed or denied it?
|
|
183
|
+
- Was approval involved, and by whom?
|
|
184
|
+
- What changed?
|
|
185
|
+
- Which application produced the event, in which environment?
|
|
186
|
+
- How does it correlate with a request or a distributed trace?
|
|
187
|
+
- Does it contain personal data?
|
|
188
|
+
- Can its integrity be checked?
|
|
189
|
+
|
|
190
|
+
An audit event is written for a reader who was not there, does not have the source code, and is
|
|
191
|
+
reading it years later. A debug log is written for the engineer looking at it today. Both are useful;
|
|
192
|
+
they are not the same artifact, and one does not substitute for the other.
|
|
193
|
+
|
|
194
|
+
**Not every audit event needs every optional field.** A conforming event can be seven fields long.
|
|
195
|
+
See [examples/valid/minimal-event.json](examples/valid/minimal-event.json).
|
|
196
|
+
|
|
197
|
+
## What does OpenAuditModel _not_ do?
|
|
198
|
+
|
|
199
|
+
It is **not**:
|
|
200
|
+
|
|
201
|
+
a log storage backend · a database · a SIEM · a GRC platform · a dashboard · an audit management
|
|
202
|
+
application · a compliance certification product · a policy engine · an authorization system · a
|
|
203
|
+
telemetry transport · a guarantee of regulatory or legal compliance.
|
|
204
|
+
|
|
205
|
+
It is **not a replacement for** OpenTelemetry, CloudEvents, ECS, OCSF, CADF or OSCAL.
|
|
206
|
+
|
|
207
|
+
The specification defines no web server, no REST API, no database, no user interface, no SaaS
|
|
208
|
+
service, no production SDK, no regulatory mapping packs, no country-specific fields and no
|
|
209
|
+
product-specific fields. That is by design, not by omission. The repository ships one optional
|
|
210
|
+
component — an MCP server that exposes the conformance engines to AI agents — which stores nothing
|
|
211
|
+
and is not required to produce or consume a conforming event.
|
|
212
|
+
|
|
213
|
+
## How does it relate to existing standards?
|
|
214
|
+
|
|
215
|
+
OpenAuditModel complements existing standards rather than reinventing them. None of them is required.
|
|
216
|
+
|
|
217
|
+
| Standard | Relationship |
|
|
218
|
+
| ----------------------------- | -------------------------------------------------------------------------------- |
|
|
219
|
+
| **CloudEvents** | MAY be used as a transport envelope. The complete audit event travels as `data`. |
|
|
220
|
+
| **OpenTelemetry** | MAY be used for telemetry transport, collection and trace correlation. |
|
|
221
|
+
| **ECS** | Supported through an informative export mapping. |
|
|
222
|
+
| **OCSF** | Supported through an informative security-event mapping. |
|
|
223
|
+
| **CADF** | A conceptual reference for audit semantics. |
|
|
224
|
+
| **OSCAL** | May later be used for control and assessment mappings. Not addressed in v0.1. |
|
|
225
|
+
| **JSON Schema Draft 2020-12** | Defines the canonical machine-verifiable structure. |
|
|
226
|
+
|
|
227
|
+
### Specifically, OpenTelemetry
|
|
228
|
+
|
|
229
|
+
OpenTelemetry is an excellent way to **transport and correlate** audit events, and
|
|
230
|
+
`request.traceId` / `request.spanId` are defined to be W3C Trace Context compatible so that an audit
|
|
231
|
+
event joins cleanly to the trace of the request that caused it.
|
|
232
|
+
|
|
233
|
+
OpenTelemetry does not define semantics for approval, delegation, business justification, before and
|
|
234
|
+
after change state, evidence references or per-event tamper-evidence. This project does not claim
|
|
235
|
+
that it does, and does not attempt to replace it. One caution: telemetry pipelines sample, and audit
|
|
236
|
+
trails must not be sampled. See [mappings/opentelemetry.md](mappings/opentelemetry.md).
|
|
237
|
+
|
|
238
|
+
### Specifically, CloudEvents
|
|
239
|
+
|
|
240
|
+
CloudEvents standardizes the envelope; OpenAuditModel standardizes what is inside it. They compose
|
|
241
|
+
because neither tries to do the other's job. Using CloudEvents is optional, and an OpenAuditModel
|
|
242
|
+
event is valid standalone. See [mappings/cloudevents.md](mappings/cloudevents.md).
|
|
243
|
+
|
|
244
|
+
### Specifically, ECS, OCSF and CADF
|
|
245
|
+
|
|
246
|
+
ECS is a field vocabulary for search; OCSF is a schema for security telemetry; CADF is a conceptual
|
|
247
|
+
model for cloud audit. OpenAuditModel exports to the first two and takes conceptual framing from the
|
|
248
|
+
third. All three mappings are informative, one-directional, and honest about what does not map — see
|
|
249
|
+
[mappings/](mappings/).
|
|
250
|
+
|
|
251
|
+
## Why is the model backend-independent?
|
|
252
|
+
|
|
253
|
+
Because audit tooling normally arrives attached to a backend, and the model then acquires fields that
|
|
254
|
+
exist for that backend's benefit. Adopting the model means adopting the product, data cannot move
|
|
255
|
+
between stores without translation, and an audit trail that must be readable in a decade depends on a
|
|
256
|
+
product that may not exist then.
|
|
257
|
+
|
|
258
|
+
OpenAuditModel therefore defines no transport, no storage concept and no required pipeline.
|
|
259
|
+
Schema identifiers never have to be dereferenced, so validation needs no network call and no domain
|
|
260
|
+
registration has to be maintained for the schema to keep working. An event is equally valid written
|
|
261
|
+
to a file, inserted into a table, published to a topic or held in memory.
|
|
262
|
+
|
|
263
|
+
See [ADR 0003](decisions/0003-backend-and-transport-independence.md).
|
|
264
|
+
|
|
265
|
+
## What is in v0.1?
|
|
266
|
+
|
|
267
|
+
```text
|
|
268
|
+
specification/ 15 normative documents defining the model
|
|
269
|
+
schemas/v0.1/ the canonical JSON Schema (Draft 2020-12)
|
|
270
|
+
semantic-conventions/ recommended event names and vocabularies
|
|
271
|
+
profiles/ ten enforceable domain profiles, 127 rules
|
|
272
|
+
mappings/ informative mappings to CloudEvents, OTel, ECS, OCSF, CADF
|
|
273
|
+
examples/ 11 valid and 7 invalid conformance fixtures
|
|
274
|
+
examples/integrity/ generated tamper-evidence fixtures, valid and invalid
|
|
275
|
+
examples/privacy/ clean and finding fixtures for the privacy linter
|
|
276
|
+
examples/profiles/ conforming, violating and out-of-scope profile fixtures
|
|
277
|
+
conformance/ the `auditmodel` CLI and its test suite
|
|
278
|
+
mcp/ the remote MCP server, distributed as a container image
|
|
279
|
+
deploy/ Docker Compose and reverse-proxy examples
|
|
280
|
+
decisions/ 11 architecture decision records
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
The core model requires seven fields — `specVersion`, `id`, `time`, `event`, `actor`, `resource`,
|
|
284
|
+
`application` — and offers nineteen optional context objects covering subject, delegation,
|
|
285
|
+
authentication, authorization, approval, request correlation, change, reason, evidence, integrity,
|
|
286
|
+
privacy, control categories, metadata and extensions.
|
|
287
|
+
|
|
288
|
+
Start with [specification/overview.md](specification/overview.md), then
|
|
289
|
+
[specification/event-model.md](specification/event-model.md).
|
|
290
|
+
|
|
291
|
+
## What is experimental?
|
|
292
|
+
|
|
293
|
+
All of it. Specifically, expect these to change:
|
|
294
|
+
|
|
295
|
+
- **The compatibility strategy.** `specVersion` is pinned to `"0.1"` by a `const` in the schema.
|
|
296
|
+
How future versions negotiate compatibility is undecided.
|
|
297
|
+
- **Closed vocabularies.** `actor.type` and `event.severity` are closed enumerations in v0.1.
|
|
298
|
+
Whether they should be is an open question.
|
|
299
|
+
- **Array bounds and length limits.** The current values are conservative defaults, not researched
|
|
300
|
+
ones.
|
|
301
|
+
- **Profiles.** Ten are implemented and enforceable, but none has production adoption evidence yet:
|
|
302
|
+
their requirements are reasoned, not validated against real deployments.
|
|
303
|
+
- **Planned commands.** `check-coverage` is documented as future work and does not exist.
|
|
304
|
+
- **The profile rule vocabulary.** Six capabilities and one conditional operator. Profile inheritance,
|
|
305
|
+
composition and multi-profile checking are not implemented.
|
|
306
|
+
- **Privacy rule thresholds and vocabularies.** Hard-coded in v0.1, with no configuration and no
|
|
307
|
+
suppression mechanism.
|
|
308
|
+
- **The digest exclusion set.** Now fixed, so any future change to it invalidates every stored digest
|
|
309
|
+
rather than only new events.
|
|
310
|
+
|
|
311
|
+
Two things are already committed to, even while experimental: event names do not silently change
|
|
312
|
+
meaning, and extensions never weaken the core.
|
|
313
|
+
|
|
314
|
+
## How can an event be validated?
|
|
315
|
+
|
|
316
|
+
Requires Node.js 22 or newer. Everything runs offline.
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
npm install
|
|
320
|
+
npm run build
|
|
321
|
+
|
|
322
|
+
npm run auditmodel -- validate examples/valid/minimal-event.json
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
After building, the CLI can also be run directly:
|
|
326
|
+
|
|
327
|
+
```bash
|
|
328
|
+
node dist/conformance/src/cli.js validate examples/valid
|
|
329
|
+
auditmodel validate <event-file> # when installed or linked
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
Output:
|
|
333
|
+
|
|
334
|
+
```text
|
|
335
|
+
schema: https://openauditmodel.org/schemas/audit-event/0.1/schema.json (schemas/v0.1/audit-event.schema.json)
|
|
336
|
+
|
|
337
|
+
ok examples/valid/minimal-event.json
|
|
338
|
+
|
|
339
|
+
1 event checked: 1 valid, 0 invalid, 0 unreadable
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
A path may be a JSON file holding one event, a JSON file holding an array of events, a `.jsonl` or
|
|
343
|
+
`.ndjson` file holding one event per line, or a directory of those files.
|
|
344
|
+
|
|
345
|
+
A failure reports the JSON Pointer of every problem:
|
|
346
|
+
|
|
347
|
+
```text
|
|
348
|
+
FAIL examples/invalid/delegation-without-subject.json
|
|
349
|
+
/subject missing required property "subject" [required]
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
Exit codes: `0` valid, `1` at least one event failed validation, `2` usage error or a file that could
|
|
353
|
+
not be read or parsed.
|
|
354
|
+
|
|
355
|
+
Validation is one half of conformance. The rules a schema cannot express — do not record secrets, do
|
|
356
|
+
not misuse `subject` as a target, do not silently redefine an event name — are normative in the
|
|
357
|
+
specification and are not detectable by any validator. See
|
|
358
|
+
[specification/privacy.md](specification/privacy.md).
|
|
359
|
+
|
|
360
|
+
## How is an event's integrity verified?
|
|
361
|
+
|
|
362
|
+
An event MAY carry `integrity` material: a digest of itself, and a link to the previous event in a
|
|
363
|
+
chain. Two commands check it, both entirely offline.
|
|
364
|
+
|
|
365
|
+
```bash
|
|
366
|
+
auditmodel verify-integrity examples/integrity/valid/single-event-sha256.json
|
|
367
|
+
auditmodel verify-chain examples/integrity/valid/three-event-chain
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
```text
|
|
371
|
+
ok examples/integrity/valid/single-event-sha256.json
|
|
372
|
+
schema valid
|
|
373
|
+
canonicalization: RFC8785
|
|
374
|
+
hash algorithm: SHA-256
|
|
375
|
+
integrity hash valid
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
```text
|
|
379
|
+
chain chain-platform-control-service-instance-7c1a
|
|
380
|
+
events: 3
|
|
381
|
+
sequences: 1..3
|
|
382
|
+
ok all 3 event digests valid
|
|
383
|
+
ok all 2 previous-hash links valid
|
|
384
|
+
ok chain starts at a genesis event
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
A failure names the finding and shows both digests, never the event:
|
|
388
|
+
|
|
389
|
+
```text
|
|
390
|
+
FAIL examples/integrity/invalid/tampered-event.json
|
|
391
|
+
integrity hash mismatch [hash-mismatch]
|
|
392
|
+
declared: 03638029fc5fa4b1b043b762ab6c59b21ab8a60328a7a9956dcb8ccd9aac4e93
|
|
393
|
+
calculated: 193a462d707f0402e78cc172827e55579c80492905ca70647f4ce1c270f0706e
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
**What is verified.** That the event validates against the canonical schema; that its declared
|
|
397
|
+
canonicalization and hash algorithm are ones the verifier implements; that recalculating its digest
|
|
398
|
+
reproduces `integrity.hash`; and, for chains, that every event links to its predecessor, that
|
|
399
|
+
sequences are unique and orderable, and that one algorithm is used throughout.
|
|
400
|
+
|
|
401
|
+
**What is not verified.** Signatures, keys and certificates — none of which v0.1 touches. Nor whether
|
|
402
|
+
the events you supplied are all the events that existed: chain verification proves consistency of the
|
|
403
|
+
supplied set, and an attacker who removes the _end_ of a chain leaves something internally consistent.
|
|
404
|
+
Detecting that needs an external checkpoint, which is out of scope.
|
|
405
|
+
|
|
406
|
+
**How the digest is calculated.** Deep-clone the event, remove exactly `/integrity/hash` and
|
|
407
|
+
`/integrity/signature`, serialize with **RFC 8785** (the JSON Canonicalization Scheme), encode as
|
|
408
|
+
UTF-8, hash, and encode as lower-case hexadecimal. RFC 8785 is used because a digest over JSON is
|
|
409
|
+
meaningless unless property order, number formatting and escaping are fixed first.
|
|
410
|
+
|
|
411
|
+
Everything else is _inside_ the digest — including `sequence`, `previousHash`, `chainId`, `batchId`,
|
|
412
|
+
`hashAlgorithm` and `canonicalization`. That is deliberate: if chain metadata were excluded, an
|
|
413
|
+
attacker could re-link and re-order events freely while every hash still verified.
|
|
414
|
+
|
|
415
|
+
**Supported algorithms.** `SHA-256`, `SHA-384` and `SHA-512`, matched case-sensitively. The schema
|
|
416
|
+
keeps the vocabulary open so a future algorithm needs no schema change — but acceptance by the schema
|
|
417
|
+
is not support, and an event declaring anything else is reported as unverifiable rather than verified.
|
|
418
|
+
|
|
419
|
+
**Tamper-evident, not tamper-proof.** Verification detects modification of the events it is given. It
|
|
420
|
+
does not prevent deletion, does not provide storage immutability, and creates no legal evidentiary
|
|
421
|
+
status. See [specification/integrity.md](specification/integrity.md) §8 and
|
|
422
|
+
[ADR 0006](decisions/0006-event-digest-and-chain-verification.md).
|
|
423
|
+
|
|
424
|
+
## How are privacy risks detected?
|
|
425
|
+
|
|
426
|
+
Audit data concentrates who did what to whom, and instrumentation written once and rarely revisited
|
|
427
|
+
is exactly where a password ends up in a log that is kept for seven years.
|
|
428
|
+
|
|
429
|
+
```bash
|
|
430
|
+
auditmodel lint-privacy examples/privacy/findings/access-token-field.json
|
|
431
|
+
auditmodel lint-privacy examples/privacy --format json
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
```text
|
|
435
|
+
FAIL examples/privacy/findings/access-token-field.json (1 finding)
|
|
436
|
+
CRITICAL OAM-PRIV-001 confidence high /metadata/accessToken
|
|
437
|
+
A property name associated with credentials carries a non-empty value.
|
|
438
|
+
recommendation: Remove the value. Record only the fact of the operation, or a
|
|
439
|
+
non-sensitive identifier for the credential.
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
Seventeen rules across ten categories: credential-shaped property names, authorization header values,
|
|
443
|
+
private key markers, published token formats, URLs with embedded user information, evidence
|
|
444
|
+
references carrying query strings, connection strings, oversized values and raw payload fields — plus
|
|
445
|
+
one heuristic that measures character entropy.
|
|
446
|
+
|
|
447
|
+
**The output never contains the value that produced a finding.** Not a preview, not a prefix, not a
|
|
448
|
+
decoded token claim. Linter output ends up in CI logs and pull request comments, which are usually
|
|
449
|
+
less protected than the audit store; a tool that echoed its matches would move secrets from a
|
|
450
|
+
controlled system into an uncontrolled one, precisely when a secret was present.
|
|
451
|
+
|
|
452
|
+
**It runs entirely locally.** No remote service, no scanning API, no model, no network. It resolves
|
|
453
|
+
no reference, fetches no evidence URL and opens no file an event names. It never modifies or redacts
|
|
454
|
+
an event: the fix for a secret in an audit record is to change the instrumentation and rotate the
|
|
455
|
+
credential, not to rewrite history.
|
|
456
|
+
|
|
457
|
+
**A finding is a suspicion, and a clean result is not a clearance.** A finding does not establish a
|
|
458
|
+
breach, a regulatory violation or a confirmed credential. And a password that happens to be a
|
|
459
|
+
dictionary word, stored under a field named `note`, matches nothing — as does most personal data,
|
|
460
|
+
which is not shaped like a secret at all. Severity and confidence are reported separately for this
|
|
461
|
+
reason: a field named `password` is critical/high, a random-looking string in an arbitrary field is
|
|
462
|
+
medium/low.
|
|
463
|
+
|
|
464
|
+
Exit codes: `0` no findings, `1` findings or a schema-invalid event, `2` usage or input error. Full
|
|
465
|
+
rule catalogue, thresholds, inspected paths and honest limits:
|
|
466
|
+
[specification/privacy.md](specification/privacy.md) §6 and
|
|
467
|
+
[ADR 0007](decisions/0007-deterministic-privacy-linting.md).
|
|
468
|
+
|
|
469
|
+
## How do I use it from an AI agent?
|
|
470
|
+
|
|
471
|
+
A remote MCP server exposes the same deterministic engines the CLI uses, so an agent writing
|
|
472
|
+
instrumentation can validate, privacy-lint and profile-check an event without cloning anything.
|
|
473
|
+
|
|
474
|
+
```bash
|
|
475
|
+
claude mcp add --transport http openauditmodel https://mcp.openauditmodel.org/mcp
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
Seven tools — `validate_event`, `verify_integrity`, `verify_chain`, `lint_privacy`,
|
|
479
|
+
`check_profile`, `generate_event_template`, `get_event_guidance` — three prompts, and twenty-nine
|
|
480
|
+
read-only resources covering the specification, both schemas, the semantic conventions and the IAM
|
|
481
|
+
profile.
|
|
482
|
+
|
|
483
|
+
**It is a remote service, and this matters.** MCP tool inputs are processed ephemerally by the
|
|
484
|
+
OpenAuditModel MCP service. The service does not intentionally persist audit event content or
|
|
485
|
+
include tool arguments in application logs. Users should review their organization’s data-handling
|
|
486
|
+
requirements before submitting production audit events to a remote MCP service. Nothing here claims
|
|
487
|
+
your events stay on your machine — they do not. For regulated audit data, use the CLI, which sends
|
|
488
|
+
nothing anywhere.
|
|
489
|
+
|
|
490
|
+
No model runs inside the server: every tool is deterministic and read-only, and the prompts return
|
|
491
|
+
guidance text for your agent to act on. Findings never carry the value that produced them.
|
|
492
|
+
|
|
493
|
+
> Deployed and verified: `https://mcp.openauditmodel.org/mcp` answers, and the site above serves the
|
|
494
|
+
> canonical schemas. Both are still an unauthenticated v0.1 alpha — see
|
|
495
|
+
> [mcp/README.md](mcp/README.md), "Public alpha risk".
|
|
496
|
+
|
|
497
|
+
Run it yourself — which keeps your audit events inside your own network. The image is built from this
|
|
498
|
+
repository; there is no registry to pull from:
|
|
499
|
+
|
|
500
|
+
```bash
|
|
501
|
+
docker build --tag openauditmodel-mcp:local --file Dockerfile .
|
|
502
|
+
|
|
503
|
+
docker run --rm -p 127.0.0.1:3000:3000 \
|
|
504
|
+
-e OAM_ALLOWED_ORIGINS=https://openauditmodel.org \
|
|
505
|
+
openauditmodel-mcp:local
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
See [mcp/README.md](mcp/README.md), [deploy/README.md](deploy/README.md) and
|
|
509
|
+
[ADR 0011](decisions/0011-self-hosted-docker-mcp-server.md).
|
|
510
|
+
|
|
511
|
+
## How are extensions added?
|
|
512
|
+
|
|
513
|
+
Two extension points, for two different purposes.
|
|
514
|
+
|
|
515
|
+
**`metadata`** carries domain-specific audit interpretation data with plain keys:
|
|
516
|
+
|
|
517
|
+
```json
|
|
518
|
+
{ "metadata": { "assignedRole": "support-agent", "expiresAt": "2026-06-16T00:00:00Z" } }
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
**`extensions`** carries vendor-specific or product-specific data under a reverse-domain namespace of
|
|
522
|
+
at least three segments, which the validator enforces:
|
|
523
|
+
|
|
524
|
+
```json
|
|
525
|
+
{
|
|
526
|
+
"extensions": {
|
|
527
|
+
"com.example.identity.directory.id": "directory-1",
|
|
528
|
+
"io.vendor.product.feature.enabled": true
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
Keys like `clusterId` or `customValue` are rejected. Extensions must never weaken a required core
|
|
534
|
+
field or change the meaning of an existing one, and consumers must ignore extensions they do not
|
|
535
|
+
understand. See [specification/extension-model.md](specification/extension-model.md) and
|
|
536
|
+
[ADR 0004](decisions/0004-reverse-domain-extension-namespaces.md).
|
|
537
|
+
|
|
538
|
+
## What are profiles, and how are they checked?
|
|
539
|
+
|
|
540
|
+
A profile is an optional, stricter set of requirements for one domain. The core says every event
|
|
541
|
+
needs an actor; a profile says that _in this domain_, a privileged role assignment also needs an
|
|
542
|
+
approval and a multi-factor authenticated session.
|
|
543
|
+
|
|
544
|
+
```bash
|
|
545
|
+
auditmodel check-profile examples/profiles/identity-and-access-management/valid \
|
|
546
|
+
--profile identity-and-access-management
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
```text
|
|
550
|
+
ok .../valid/role-assign-privileged.json (IAM-CORE-001, IAM-CORE-002, IAM-ROLE-001, IAM-ROLE-002)
|
|
551
|
+
|
|
552
|
+
FAIL .../invalid/privileged-role-without-mfa.json (1 violation)
|
|
553
|
+
ERROR IAM-ROLE-002 /authentication/mfa
|
|
554
|
+
required by the profile to equal true
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
**A profile only ever adds.** Every profile-conforming event is a core-conforming event, and this is
|
|
558
|
+
enforced structurally rather than by review: the rule vocabulary contains no keyword that could remove
|
|
559
|
+
a requirement — no `optionalPaths`, no `exemptPaths`, no `overrides` — and core validation runs first,
|
|
560
|
+
so an event failing the core schema is reported as core-invalid with its profile rules never
|
|
561
|
+
evaluated.
|
|
562
|
+
|
|
563
|
+
**Profiles are data, not code.** A profile is a JSON document validated against
|
|
564
|
+
[profile-definition.schema.json](profiles/profile-definition.schema.json). Six capabilities: two
|
|
565
|
+
selector forms, three requirement forms, one recommendation form, and one conditional — a single path
|
|
566
|
+
compared for equality against a single scalar. No expressions, no scripts, no regular expressions,
|
|
567
|
+
nothing executed. The eleven-rule identity profile is expressed entirely in JSON, with no TypeScript.
|
|
568
|
+
Adding a profile requires no code.
|
|
569
|
+
|
|
570
|
+
**An event no rule governs is `not-applicable`, never conforming**, and exits `3`. Silence is not
|
|
571
|
+
conformance: a pipeline checking document events against an identity profile must not read a pass as
|
|
572
|
+
assurance.
|
|
573
|
+
|
|
574
|
+
| Profile | Status |
|
|
575
|
+
| ------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------- |
|
|
576
|
+
| [Identity and access management](profiles/identity-and-access-management/) | **Implemented** — 11 rules across accounts, roles, permissions, service accounts and credential rotation |
|
|
577
|
+
| [Document management](profiles/document-management/) | **Implemented** — 11 rules across sharing, permissions, versioning, retention and legal hold |
|
|
578
|
+
| [Incident management](profiles/incident-management/) | **Implemented** — 15 rules across incident, problem and corrective-action lifecycle |
|
|
579
|
+
| [Message broker management](profiles/message-broker-management/) | **Implemented** — 12 rules across broker control-plane, ACL, quota, configuration and offset administration |
|
|
580
|
+
| [Deployment and change management](profiles/deployment-and-change-management/) | **Implemented** — 13 rules across deployment, release, rollback and configuration change |
|
|
581
|
+
| [Financial transaction management](profiles/financial-transaction-management/) | **Implemented** — 12 rules across transfers, payments, reversals, settlement and limits |
|
|
582
|
+
| [Secrets and key management](profiles/secrets-and-key-management/) | **Implemented** — 14 rules across secret, key and certificate lifecycle and high-risk access |
|
|
583
|
+
| [Customer and account management](profiles/customer-and-account-management/) | **Implemented** — 13 rules across customer and business-account lifecycle |
|
|
584
|
+
| [Backup and recovery](profiles/backup-and-recovery/) | **Implemented** — 13 rules across backup, restore, recovery and failover |
|
|
585
|
+
| [API and integration management](profiles/api-and-integration-management/) | **Implemented** — 13 rules across API credential, webhook and integration lifecycle |
|
|
586
|
+
|
|
587
|
+
**Profiles are not regulatory mappings**, and profile conformance is not legal compliance. A profile
|
|
588
|
+
requires audit fields; it cites no regulation, article or jurisdiction, and the definition format
|
|
589
|
+
gives it nowhere to put one. Profiles also do not replace privacy linting: a profile says which fields
|
|
590
|
+
must be present, the linter says which values must not, and every published profile fixture is
|
|
591
|
+
required by test to pass both.
|
|
592
|
+
|
|
593
|
+
See [profiles/README.md](profiles/README.md), [ADR 0005](decisions/0005-core-and-profile-separation.md)
|
|
594
|
+
and [ADR 0008](decisions/0008-declarative-profile-conformance.md).
|
|
595
|
+
|
|
596
|
+
## Legal and compliance limitations
|
|
597
|
+
|
|
598
|
+
Read this section before citing OpenAuditModel in any compliance context.
|
|
599
|
+
|
|
600
|
+
1. **No compliance guarantee.** Conformance is a statement about the shape and semantics of data. It
|
|
601
|
+
is not compliance with GDPR, HIPAA, SOC 2, ISO 27001, PCI DSS, or any other framework, and must not
|
|
602
|
+
be presented as such.
|
|
603
|
+
2. **No legal advice.** Nothing in this repository is legal advice.
|
|
604
|
+
3. **No regulatory mappings.** The core model contains no regulation identifiers, article numbers,
|
|
605
|
+
control identifiers or jurisdiction-specific fields, deliberately. `controlCategories` carries
|
|
606
|
+
regulation-neutral labels only.
|
|
607
|
+
4. **No evidentiary status.** A hash or signature does not automatically make an audit record
|
|
608
|
+
admissible or probative. That depends on jurisdiction, process and key custody.
|
|
609
|
+
5. **Tamper-evident, not immutable.** Integrity metadata makes alteration detectable. It does not
|
|
610
|
+
prevent deletion, does not provide storage immutability and does not replace write-once storage.
|
|
611
|
+
See [specification/integrity.md](specification/integrity.md).
|
|
612
|
+
6. **Validation cannot detect secrets.** A password in `metadata` passes every test in this
|
|
613
|
+
repository. See [specification/privacy.md](specification/privacy.md).
|
|
614
|
+
7. **Experimental.** The model may change incompatibly before 1.0.
|
|
615
|
+
|
|
616
|
+
## Contributing
|
|
617
|
+
|
|
618
|
+
Contributions are welcome, including disagreement with the decisions recorded in
|
|
619
|
+
[decisions/](decisions/).
|
|
620
|
+
|
|
621
|
+
Specification changes follow an RFC-like process: open an issue using the specification change
|
|
622
|
+
template, describing the problem, the proposed change, the compatibility impact and the conformance
|
|
623
|
+
tests that would prove it. [CONTRIBUTING.md](CONTRIBUTING.md) explains how to propose a core field, a
|
|
624
|
+
semantic convention, a domain profile, an external mapping or a vendor extension, and how
|
|
625
|
+
compatibility is evaluated.
|
|
626
|
+
|
|
627
|
+
Please also read [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md). Security issues go to
|
|
628
|
+
[SECURITY.md](SECURITY.md), not to the public tracker.
|
|
629
|
+
|
|
630
|
+
## Licensing
|
|
631
|
+
|
|
632
|
+
All content in this repository — specification text, JSON Schemas, examples, tooling and tests — is
|
|
633
|
+
licensed under the **Apache License 2.0**. See [LICENSE](LICENSE).
|
|
634
|
+
|
|
635
|
+
A single license was chosen deliberately for v0.1. Splitting documentation under a separate content
|
|
636
|
+
license such as CC BY 4.0 is a reasonable thing for a standards project to do, and adds a licensing
|
|
637
|
+
boundary that contributors have to reason about on every change. If the project's governance later
|
|
638
|
+
justifies that boundary, the change will be recorded as an architecture decision. Until then, one
|
|
639
|
+
license applies to everything.
|
|
640
|
+
|
|
641
|
+
This repository contains no copyrighted control framework text, no proprietary framework content, no
|
|
642
|
+
licensed regulatory commentary and no vendor documentation.
|
|
643
|
+
|
|
644
|
+
## Status of this repository
|
|
645
|
+
|
|
646
|
+
Version 0.1 is a specification, a canonical schema and a conformance toolchain. It is experimental,
|
|
647
|
+
not production-ready, and carries no compliance guarantee.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
export declare const EXIT_OK = 0;
|
|
3
|
+
export declare const EXIT_INVALID = 1;
|
|
4
|
+
export declare const EXIT_ERROR = 2;
|
|
5
|
+
/**
|
|
6
|
+
* No verdict was produced for the input.
|
|
7
|
+
*
|
|
8
|
+
* `check-profile`: nothing checked was governed by the profile.
|
|
9
|
+
* `lint-privacy`: the input could not be evaluated as an audit event, so it was
|
|
10
|
+
* not scanned at all.
|
|
11
|
+
*
|
|
12
|
+
* Distinct from 0 in both cases for the same reason: a pipeline must not be able
|
|
13
|
+
* to read "the tool said nothing" as "the tool was satisfied". Distinct from 1
|
|
14
|
+
* because 1 means a real verdict was produced and it was negative, which is a
|
|
15
|
+
* different thing for an operator to act on.
|
|
16
|
+
*/
|
|
17
|
+
export declare const EXIT_NO_VERDICT = 3;
|
|
18
|
+
/** Retained name for the `check-profile` reading of {@link EXIT_NO_VERDICT}. */
|
|
19
|
+
export declare const EXIT_NOT_APPLICABLE = 3;
|
|
20
|
+
export declare function run(argv: readonly string[]): number;
|