@precepts/standards 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 +30 -0
- package/README.md +115 -0
- package/package.json +40 -0
- package/schema/document-standard-template.md +139 -0
- package/schema/standards.schema.json +154 -0
- package/standards/integration/governance/_category_.json +1 -0
- package/standards/integration/governance/integration-styles.md +56 -0
- package/standards/integration/index.md +9 -0
- package/standards/integration/standards/_category_.json +1 -0
- package/standards/integration/standards/api/_category_.json +1 -0
- package/standards/integration/standards/api/error-handling.md +250 -0
- package/standards/integration/standards/api/resource-design.md +286 -0
- package/standards/integration/standards/data-formats/_category_.json +1 -0
- package/standards/integration/standards/data-formats/character-encoding.md +206 -0
- package/standards/integration/standards/data-formats/date-format.md +102 -0
- package/standards/integration/standards/data-formats/datetime-formats.md +265 -0
- package/standards/integration/standards/data-formats/monetary-format.md +61 -0
- package/standards/integration/standards/events/_category_.json +1 -0
- package/standards/integration/standards/events/event-envelope.md +270 -0
- package/standards/integration/standards/foundational/_category_.json +1 -0
- package/standards/integration/standards/foundational/naming-conventions.md +334 -0
- package/standards/integration/standards/observability/_category_.json +1 -0
- package/standards/integration/standards/observability/integration-observability.md +226 -0
- package/standards/integration/standards/resilience/_category_.json +1 -0
- package/standards/integration/standards/resilience/integration-resilience-patterns.md +291 -0
- package/standards/integration/standards/resilience/retry-policy.md +268 -0
- package/standards/integration/standards/resilience/timeout.md +269 -0
- package/standards/integration/standards/versioning/_category_.json +1 -0
- package/standards/integration/standards/versioning/backward-forward-compatibility.md +230 -0
- package/standards/product/Guidelines/_category_.json +1 -0
- package/standards/product/Guidelines/requirement-document.md +54 -0
- package/standards/product/index.md +9 -0
- package/standards/project-management/index.md +9 -0
- package/standards/ux/index.md +9 -0
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
---
|
|
2
|
+
identifier: "INTG-STD-015"
|
|
3
|
+
name: "Event Envelope Standard"
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
status: "MANDATORY"
|
|
6
|
+
|
|
7
|
+
domain: "INTEGRATION"
|
|
8
|
+
documentType: "standard"
|
|
9
|
+
category: "protocol"
|
|
10
|
+
appliesTo: ["events", "streaming", "webhooks"]
|
|
11
|
+
|
|
12
|
+
lastUpdated: "2026-03-28"
|
|
13
|
+
owner: "Integration Architecture Board"
|
|
14
|
+
|
|
15
|
+
standardsCompliance:
|
|
16
|
+
iso: []
|
|
17
|
+
rfc: []
|
|
18
|
+
w3c: []
|
|
19
|
+
other: ["CNCF-CloudEvents-v1.0.2"]
|
|
20
|
+
|
|
21
|
+
taxonomy:
|
|
22
|
+
capability: "event-driven"
|
|
23
|
+
subCapability: "event-envelope"
|
|
24
|
+
layer: "contract"
|
|
25
|
+
|
|
26
|
+
enforcement:
|
|
27
|
+
method: "automated"
|
|
28
|
+
validationRules:
|
|
29
|
+
requiredAttributes: ["specversion", "id", "source", "type"]
|
|
30
|
+
specversion: "1.0"
|
|
31
|
+
sourceFormat: "URI-reference"
|
|
32
|
+
idUniqueness: "unique-per-source"
|
|
33
|
+
rejectionCriteria:
|
|
34
|
+
- "Missing required CloudEvents context attributes"
|
|
35
|
+
- "Invalid specversion value"
|
|
36
|
+
- "Non-URI source attribute"
|
|
37
|
+
- "Duplicate event ID from same source"
|
|
38
|
+
|
|
39
|
+
dependsOn: ["INTG-STD-004", "INTG-STD-005"]
|
|
40
|
+
supersedes: ""
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
# Event Envelope
|
|
44
|
+
|
|
45
|
+
## Purpose
|
|
46
|
+
|
|
47
|
+
This standard mandates **CloudEvents v1.0.2** as the universal event envelope for all events produced, consumed, or relayed across integration boundaries. Without a uniform envelope, each team invents its own metadata schema, making cross-system correlation, schema evolution, and observability prohibitively expensive. CloudEvents - a CNCF graduated specification - provides a vendor-neutral, protocol-agnostic envelope with broad ecosystem support (Knative, Azure Event Grid, Amazon EventBridge, Google Eventarc).
|
|
48
|
+
|
|
49
|
+
> *Normative language (**MUST**, **MUST NOT**, **SHOULD**, **MAY**) follows RFC 2119 semantics.*
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Rules
|
|
54
|
+
|
|
55
|
+
### R-1: Mandatory CloudEvents Adoption
|
|
56
|
+
|
|
57
|
+
All events crossing a service boundary **MUST** use the CloudEvents v1.0.2 envelope. The `specversion` attribute **MUST** be `"1.0"`. Non-conforming events **MUST** be rejected by gateways, brokers, and consumers.
|
|
58
|
+
|
|
59
|
+
### R-2: Required Context Attributes
|
|
60
|
+
|
|
61
|
+
Every CloudEvent **MUST** include these four context attributes:
|
|
62
|
+
|
|
63
|
+
| Attribute | Type | Constraint | Description |
|
|
64
|
+
|-----------|------|------------|-------------|
|
|
65
|
+
| `specversion` | String | Exactly `"1.0"` | CloudEvents specification version |
|
|
66
|
+
| `id` | String | Non-empty; unique within scope of `source` | Event identifier; UUID v4 or ULID **RECOMMENDED** |
|
|
67
|
+
| `source` | URI-reference | Non-empty; absolute URI **RECOMMENDED** | Identifies the producing system and context |
|
|
68
|
+
| `type` | String | Non-empty; reverse-DNS prefix **REQUIRED** | Describes the kind of occurrence |
|
|
69
|
+
|
|
70
|
+
The combination of `source` + `id` **MUST** be globally unique for distinct events. A producer **MAY** reuse the same `id` when re-delivering the same logical event (idempotency).
|
|
71
|
+
|
|
72
|
+
### R-3: Recommended Context Attributes
|
|
73
|
+
|
|
74
|
+
Producers **SHOULD** include the following optional attributes:
|
|
75
|
+
|
|
76
|
+
| Attribute | Type | Constraint | Recommendation |
|
|
77
|
+
|-----------|------|------------|----------------|
|
|
78
|
+
| `time` | Timestamp | RFC 3339, UTC (`Z` suffix) | **SHOULD** be included for audit trail. **MUST** use UTC per INTG-STD-002 when present. |
|
|
79
|
+
| `datacontenttype` | String | RFC 2046 media type | **SHOULD** be included when data is present. Defaults to `application/json` when omitted. |
|
|
80
|
+
| `dataschema` | URI | Absolute URI | **SHOULD** be included for schema-governed events. **MUST** point to a versioned schema endpoint. |
|
|
81
|
+
| `subject` | String | Non-empty | **SHOULD** be included when the event pertains to a specific resource within the source. |
|
|
82
|
+
|
|
83
|
+
### R-4: Event Type Naming
|
|
84
|
+
|
|
85
|
+
Event types **MUST** follow INTG-STD-004 (Naming Standard):
|
|
86
|
+
|
|
87
|
+
- **MUST** use reverse-DNS prefix rooted at the organization domain.
|
|
88
|
+
- **MUST** follow the pattern: `{reverse-dns}.{domain}.{entity}.{action}[.{version}]`
|
|
89
|
+
- **MUST** use lowercase with dots as separators.
|
|
90
|
+
- A version suffix (e.g., `.v2`) **SHOULD** be appended for breaking schema changes.
|
|
91
|
+
|
|
92
|
+
### R-5: Source Attribute Formatting
|
|
93
|
+
|
|
94
|
+
The `source` attribute **MUST** be a valid URI-reference per RFC 3986. Producers **SHOULD** use absolute URIs. The source **MUST** identify the producing system and **MAY** include a path to narrow context. The source **MUST NOT** expose internal hostnames, IP addresses, port numbers, or infrastructure identifiers (see R-14).
|
|
95
|
+
|
|
96
|
+
### R-6: Extension Attributes
|
|
97
|
+
|
|
98
|
+
Extension attribute names **MUST** contain only lowercase ASCII letters (`a`-`z`) and digits (`0`-`9`), with a recommended maximum length of 20 characters.
|
|
99
|
+
|
|
100
|
+
Recommended extensions:
|
|
101
|
+
|
|
102
|
+
| Extension | Source Specification | Purpose |
|
|
103
|
+
|-----------|---------------------|---------|
|
|
104
|
+
| `traceparent` | W3C Trace Context | Distributed tracing. Producers **SHOULD** propagate from the originating request. |
|
|
105
|
+
| `tracestate` | W3C Trace Context | Vendor-specific tracing data. **SHOULD** accompany `traceparent`. |
|
|
106
|
+
| `partitionkey` | CloudEvents Partitioning | Ordered delivery within a partition. **SHOULD** be set for causally ordered events. |
|
|
107
|
+
| `sequence` | CloudEvents Sequence | Event ordering from a source. **MAY** be used with `partitionkey`. |
|
|
108
|
+
|
|
109
|
+
Custom extensions **MUST** be namespaced to avoid collisions (e.g., `examplecorrelationid`). Custom extensions **MUST NOT** redefine semantics of documented CloudEvents extensions. Intermediaries **SHOULD** forward all extension attributes, even unrecognized ones.
|
|
110
|
+
|
|
111
|
+
### R-7: Structured Content Mode
|
|
112
|
+
|
|
113
|
+
In structured mode, the entire CloudEvent **MUST** be serialized as a single JSON object per the CloudEvents JSON Format. The transport content-type **MUST** be `application/cloudevents+json; charset=utf-8`. JSON payloads **MUST** be embedded directly in `data` (not string-escaped). Binary payloads **MUST** use `data_base64` instead. The `data` and `data_base64` fields **MUST NOT** both be present.
|
|
114
|
+
|
|
115
|
+
### R-8: Binary Content Mode
|
|
116
|
+
|
|
117
|
+
In binary mode, context attributes **MUST** be mapped to transport-native headers and the data payload **MUST** occupy the message body directly. For HTTP, headers use the `ce-` prefix. For Kafka, headers use the `ce_` prefix with UTF-8 encoded values. The transport content-type header **MUST** reflect the actual data media type. The `datacontenttype` attribute **MUST NOT** appear as a separate header in HTTP binary mode.
|
|
118
|
+
|
|
119
|
+
### R-9: Content Mode Selection
|
|
120
|
+
|
|
121
|
+
| Transport | Default Mode | Guidance |
|
|
122
|
+
|-----------|-------------|----------|
|
|
123
|
+
| HTTP (webhooks, REST callbacks) | Structured | Binary **MAY** be used when payload size dominates and header inspection is not needed. |
|
|
124
|
+
| Kafka | Structured | Binary **MAY** be used on high-throughput internal topics with tightly coupled consumers. |
|
|
125
|
+
| AMQP | Binary | Leverages AMQP application properties for context attributes. |
|
|
126
|
+
| MQTT | Structured | **MUST** use structured for MQTT v3.1 (no user-defined headers). MQTT v5 **MAY** use binary. |
|
|
127
|
+
|
|
128
|
+
Producers **MUST** document which content mode they emit in their API or AsyncAPI definition.
|
|
129
|
+
|
|
130
|
+
### R-10: Batch Delivery
|
|
131
|
+
|
|
132
|
+
Batch delivery **MUST** use the CloudEvents JSON Batch Format. The content-type **MUST** be `application/cloudevents-batch+json; charset=utf-8`. The body **MUST** be a JSON array of complete CloudEvents. An empty batch **MUST** be `[]`. Each event **MUST** independently satisfy all attribute requirements. Consumers **MUST NOT** assume ordering unless events share the same `partitionkey` and include `sequence` values.
|
|
133
|
+
|
|
134
|
+
A single batch **MUST NOT** exceed 1 MiB unless producer and consumer have an explicit bilateral agreement. Producers **SHOULD** target 100 events or fewer per batch.
|
|
135
|
+
|
|
136
|
+
### R-11: Event Size Constraints
|
|
137
|
+
|
|
138
|
+
| Constraint | Limit | Rationale |
|
|
139
|
+
|-----------|-------|-----------|
|
|
140
|
+
| Single event (envelope + data) | **MUST NOT** exceed 256 KiB | Lowest common denominator across major brokers and webhook receivers |
|
|
141
|
+
| Context attributes only | **SHOULD NOT** exceed 4 KiB | Keep headers lightweight for binary mode |
|
|
142
|
+
| `data` payload | **SHOULD NOT** exceed 252 KiB | Envelope overhead budget |
|
|
143
|
+
|
|
144
|
+
Events exceeding 256 KiB **MUST** use the claim-check pattern: store the payload externally and include a retrieval URI in the `data` field with `claimCheckUri` and `claimCheckContentType` fields.
|
|
145
|
+
|
|
146
|
+
### R-12: HTTP Protocol Binding
|
|
147
|
+
|
|
148
|
+
HTTP-bound CloudEvents **MUST** comply with the CloudEvents HTTP Protocol Binding v1.0.2. Events **MUST** be sent as HTTP POST requests. Receivers **MUST** return `2xx` for successfully received events. A `429` response **MUST** trigger sender-side backoff. A `5xx` response **SHOULD** trigger retry with exponential backoff. Senders **SHOULD** support the CloudEvents webhook validation handshake (HTTP OPTIONS with `WebHook-Request-Origin`).
|
|
149
|
+
|
|
150
|
+
### R-13: Kafka Protocol Binding
|
|
151
|
+
|
|
152
|
+
Kafka-bound CloudEvents **MUST** comply with the CloudEvents Kafka Protocol Binding v1.0.2. The Kafka message key **SHOULD** be set to the `partitionkey` extension value when present, or to the `subject` attribute, to colocate related events. Producers **MUST** set `partitionkey` when causal ordering is required.
|
|
153
|
+
|
|
154
|
+
### R-14: Security - Metadata Hygiene
|
|
155
|
+
|
|
156
|
+
Event envelope metadata **MUST NOT** leak internal infrastructure details:
|
|
157
|
+
|
|
158
|
+
- `source` **MUST NOT** contain internal hostnames, private IPs, container/pod identifiers, or internal ports.
|
|
159
|
+
- Extension attributes **MUST NOT** carry credentials, tokens, session identifiers, or PII.
|
|
160
|
+
- `dataschema` **MUST** be reachable only from authorized networks or **MUST** be a logical identifier (URN).
|
|
161
|
+
- Gateways at trust boundaries **SHOULD** validate and sanitize envelope attributes before forwarding externally.
|
|
162
|
+
|
|
163
|
+
### R-15: Auditability
|
|
164
|
+
|
|
165
|
+
- Producers **MUST** set `id` to a value traceable in the producing system's logs.
|
|
166
|
+
- Producers **SHOULD** set `time` for temporal correlation and `traceparent` for distributed trace correlation.
|
|
167
|
+
- Consumers **MUST** log `id`, `source`, `type`, and `time` upon receipt.
|
|
168
|
+
- The combination of `source` + `id` + `time` **MUST** be sufficient to locate the originating event in producer logs.
|
|
169
|
+
|
|
170
|
+
### R-16: Allowed Serialization Formats
|
|
171
|
+
|
|
172
|
+
The CloudEvents JSON Event Format **MUST** be the default serialization. All implementations **MUST** support it. Producers and consumers **MAY** use CloudEvents Protobuf or Avro formats by bilateral agreement, but **MUST** still carry all required context attributes.
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Examples
|
|
177
|
+
|
|
178
|
+
### Valid Event - Structured Content Mode
|
|
179
|
+
|
|
180
|
+
```json
|
|
181
|
+
{
|
|
182
|
+
"specversion": "1.0",
|
|
183
|
+
"id": "01HZX3KQVB8E72GQJHF5RM6YWN",
|
|
184
|
+
"source": "//orders.example.com/checkout",
|
|
185
|
+
"type": "com.example.order.created",
|
|
186
|
+
"time": "2026-03-28T14:22:31.482Z",
|
|
187
|
+
"datacontenttype": "application/json",
|
|
188
|
+
"dataschema": "https://schemas.example.com/orders/created/v1.json",
|
|
189
|
+
"subject": "order-8842",
|
|
190
|
+
"traceparent": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
|
|
191
|
+
"data": {
|
|
192
|
+
"orderId": "order-8842",
|
|
193
|
+
"customerId": "cust-1029",
|
|
194
|
+
"totalAmount": { "value": "149.99", "currency": "USD" }
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Invalid Event - Missing Required Attributes
|
|
200
|
+
|
|
201
|
+
The following event is **non-compliant** and **MUST** be rejected:
|
|
202
|
+
|
|
203
|
+
```json
|
|
204
|
+
{
|
|
205
|
+
"id": "evt-100",
|
|
206
|
+
"type": "OrderCreated",
|
|
207
|
+
"data": { "orderId": "order-100" }
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**Violations:** Missing `specversion` (required). Missing `source` (required). `type` uses PascalCase without reverse-DNS prefix (violates R-4).
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Enforcement Rules
|
|
216
|
+
|
|
217
|
+
### Gateway Enforcement
|
|
218
|
+
|
|
219
|
+
API gateways and event brokers at trust boundaries **MUST** enforce:
|
|
220
|
+
|
|
221
|
+
1. **Ingress validation** - All required context attributes present and well-formed (`specversion` matches `^1\.0$`; `id` is non-empty; `source` is a valid URI-reference; `type` matches `^[a-z][a-z0-9]*(\.[a-z][a-z0-9]*(-[a-z0-9]+)*){3,}$`).
|
|
222
|
+
2. **Source sanitization** - Reject `source` values matching internal infrastructure patterns (private IPs, `.internal`, `.local`, `localhost`, `k8s://`).
|
|
223
|
+
3. **Size enforcement** - Reject events exceeding 256 KiB with HTTP 413 or equivalent.
|
|
224
|
+
4. **Time validation** - When present, `time` **MUST** match RFC 3339 UTC format (`^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,9})?Z$`).
|
|
225
|
+
5. **Extension name validation** - Extension attribute names **MUST** match `^[a-z][a-z0-9]{0,19}$`.
|
|
226
|
+
|
|
227
|
+
### Producer Enforcement
|
|
228
|
+
|
|
229
|
+
Build pipelines **SHOULD** include a CloudEvents linting step validating required attributes, `source`/`type` naming per INTG-STD-004, and approved extension names.
|
|
230
|
+
|
|
231
|
+
### Consumer Enforcement
|
|
232
|
+
|
|
233
|
+
Consumers **MUST** reject events missing any required context attribute, log `id`/`source`/`type`/`time` of every received event, and forward unrecognized extension attributes when re-emitting.
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## References
|
|
238
|
+
|
|
239
|
+
| Reference | URI |
|
|
240
|
+
|-----------|-----|
|
|
241
|
+
| CloudEvents Specification v1.0.2 | https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md |
|
|
242
|
+
| CloudEvents JSON Event Format v1.0.2 | https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/formats/json-format.md |
|
|
243
|
+
| CloudEvents HTTP Protocol Binding v1.0.2 | https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/http-protocol-binding.md |
|
|
244
|
+
| CloudEvents Kafka Protocol Binding v1.0.2 | https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/kafka-protocol-binding.md |
|
|
245
|
+
| W3C Trace Context | https://www.w3.org/TR/trace-context/ |
|
|
246
|
+
| INTG-STD-004 - Naming Standard | Internal |
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Rationale
|
|
251
|
+
|
|
252
|
+
**Why CloudEvents over a custom envelope?** CloudEvents is the only CNCF graduated event envelope specification with broad industry adoption across Azure Event Grid, Amazon EventBridge, Google Eventarc, and Knative. A custom envelope would forgo ecosystem compatibility and impose a perpetual translation tax.
|
|
253
|
+
|
|
254
|
+
**Why structured mode as default?** Structured mode keeps envelope and data together as a single unit, eliminating header-body mismatches during transport hops. Binary mode is permitted for documented performance-sensitive paths.
|
|
255
|
+
|
|
256
|
+
**Why the 256 KiB size limit?** This is the lowest common denominator across major event infrastructure. The claim-check pattern provides an escape hatch for large payloads.
|
|
257
|
+
|
|
258
|
+
**Why prohibit internal topology in source?** Event metadata flows across trust boundaries - a `source` containing internal hostnames or IPs reveals cloud provider, VPC structure, and service ports to external consumers.
|
|
259
|
+
|
|
260
|
+
**Why `time` is SHOULD rather than MUST?** Some producers (legacy adapters, IoT gateways) cannot guarantee accurate clocks. Systems requiring strict temporal ordering should use the `sequence` extension.
|
|
261
|
+
|
|
262
|
+
**Why ULID or UUID v4 for event IDs?** Both provide strong uniqueness without centralized coordination. ULIDs add temporal sortability. Sequential integers are discouraged as they require coordination and leak volume information.
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## Version History
|
|
267
|
+
|
|
268
|
+
| Version | Date | Change |
|
|
269
|
+
| ------- | ---------- | ------------------ |
|
|
270
|
+
| 1.0.0 | 2026-03-28 | Initial definition |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"label": "Foundational", "position": 1}
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
---
|
|
2
|
+
identifier: "INTG-STD-004"
|
|
3
|
+
name: "Integration Naming Conventions"
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
status: "MANDATORY"
|
|
6
|
+
|
|
7
|
+
domain: "INTEGRATION"
|
|
8
|
+
documentType: "standard"
|
|
9
|
+
category: "naming"
|
|
10
|
+
appliesTo: ["api", "events", "a2a", "files", "mcp", "webhooks", "grpc", "graphql", "batch", "streaming"]
|
|
11
|
+
|
|
12
|
+
lastUpdated: "2026-03-28"
|
|
13
|
+
owner: "Integration Architecture Board"
|
|
14
|
+
|
|
15
|
+
standardsCompliance:
|
|
16
|
+
iso: []
|
|
17
|
+
rfc: ["RFC-9110", "RFC-9457"]
|
|
18
|
+
w3c: []
|
|
19
|
+
other: ["Google-AIP-140", "Google-AIP-190", "Zalando-RESTful-API-Guidelines"]
|
|
20
|
+
|
|
21
|
+
taxonomy:
|
|
22
|
+
capability: "naming"
|
|
23
|
+
subCapability: "conventions"
|
|
24
|
+
layer: "contract"
|
|
25
|
+
|
|
26
|
+
enforcement:
|
|
27
|
+
method: "automated"
|
|
28
|
+
validationRules:
|
|
29
|
+
fieldNames: "snake_case"
|
|
30
|
+
urlPaths: "kebab-case"
|
|
31
|
+
eventTypes: "dot.notation.past.tense"
|
|
32
|
+
rejectionCriteria:
|
|
33
|
+
- "Mixed case conventions within a single API"
|
|
34
|
+
- "Verbs in URL path segments"
|
|
35
|
+
- "Abbreviations without prior approval"
|
|
36
|
+
|
|
37
|
+
dependsOn: []
|
|
38
|
+
supersedes: ""
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
# Naming Conventions
|
|
42
|
+
|
|
43
|
+
## Purpose
|
|
44
|
+
|
|
45
|
+
This standard defines **MANDATORY** naming conventions for all artifacts exchanged across integration boundaries - JSON fields, REST API paths, event types, queue topics, HTTP headers, enum values, query parameters, and file names. Consistent naming eliminates mapping ambiguity between services, enables automated CI/CD linting, and ensures AI agents operate on predictable structures.
|
|
46
|
+
|
|
47
|
+
> *Normative language follows RFC 2119 semantics.*
|
|
48
|
+
|
|
49
|
+
| Context | Convention | Example |
|
|
50
|
+
|---------|-----------|---------|
|
|
51
|
+
| JSON field names | `snake_case` | `order_total` |
|
|
52
|
+
| URL path segments | `kebab-case` | `/shipping-addresses` |
|
|
53
|
+
| Event type names | `dot.notation` | `order.payment.completed` |
|
|
54
|
+
| Queue/topic names | `dot.notation` | `retail.orders.created.v1` |
|
|
55
|
+
| HTTP headers | `Kebab-Case` | `X-Correlation-Id` |
|
|
56
|
+
| Enum values | `UPPER_SNAKE_CASE` | `PAYMENT_PENDING` |
|
|
57
|
+
| Query parameters | `snake_case` | `page_size` |
|
|
58
|
+
| File/directory names | `kebab-case` | `order-export-2026-03.csv` |
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Rules
|
|
63
|
+
|
|
64
|
+
#### General
|
|
65
|
+
|
|
66
|
+
### R-1: American English
|
|
67
|
+
|
|
68
|
+
All names **MUST** use American English (`color` not `colour`).
|
|
69
|
+
|
|
70
|
+
### R-2: Descriptive Names
|
|
71
|
+
|
|
72
|
+
Names **MUST** be descriptive. Single-character or opaque abbreviations **MUST NOT** be used. Names **MUST NOT** encode internal system names or infrastructure details. Use `customer_address` not `tbl_cust_addr`.
|
|
73
|
+
|
|
74
|
+
### R-3: Approved Abbreviations
|
|
75
|
+
|
|
76
|
+
Pre-approved abbreviations (all others **MUST** go through the registry):
|
|
77
|
+
|
|
78
|
+
| `id` identifier | `config` configuration | `info` information | `spec` specification |
|
|
79
|
+
|---|---|---|---|
|
|
80
|
+
| `stats` statistics | `auth` authentication | `msg` message | `org` organization |
|
|
81
|
+
| `env` environment | `max` maximum | `min` minimum | `avg` average |
|
|
82
|
+
| `src` source | `dest` destination | `prev` previous | `temp` temporary |
|
|
83
|
+
| `num` number | `qty` quantity | | |
|
|
84
|
+
|
|
85
|
+
### R-4: Name Syntax
|
|
86
|
+
|
|
87
|
+
Names **MUST NOT** begin with a digit. Names **MUST NOT** contain leading, trailing, or consecutive separators. Reserved words (`class`, `new`, `type`, `default`) **SHOULD** be avoided. Where unavoidable, **MUST** be domain-qualified (`account_type`).
|
|
88
|
+
|
|
89
|
+
#### JSON Field Names
|
|
90
|
+
|
|
91
|
+
### R-5: snake_case for JSON Fields
|
|
92
|
+
|
|
93
|
+
**MUST** use `snake_case`. **MUST NOT** use `camelCase`, `PascalCase`, or `kebab-case`.
|
|
94
|
+
|
|
95
|
+
### R-6: Plural Arrays and Singular Scalars
|
|
96
|
+
|
|
97
|
+
Arrays **MUST** be plural (`line_items`). Scalars/objects **MUST** be singular (`order`).
|
|
98
|
+
|
|
99
|
+
### R-7: Boolean Field Names
|
|
100
|
+
|
|
101
|
+
Booleans **MUST** use adjective/past-participle form (`active`, `verified`). **SHOULD** omit `is_` unless the bare word is reserved (`is_new`).
|
|
102
|
+
|
|
103
|
+
### R-8: Temporal Suffixes
|
|
104
|
+
|
|
105
|
+
Date/time fields **SHOULD** use temporal suffixes: `_at` (timestamp), `_on` (date), `_until` (expiry), `_after` (lower bound), `_duration` (elapsed).
|
|
106
|
+
|
|
107
|
+
### R-9: Field Name Word Order
|
|
108
|
+
|
|
109
|
+
**MUST NOT** include structural prepositions: `error_reason` not `reason_for_error`. Adjectives **MUST** precede the noun: `primary_address` not `address_primary`. Fields **MUST** represent state, not intent: `collected_items` not `collect_items`.
|
|
110
|
+
|
|
111
|
+
### R-10: URI and URL Suffixes
|
|
112
|
+
|
|
113
|
+
URI/URL fields **SHOULD** use `_url` (locator) or `_uri` (identifier) suffixes.
|
|
114
|
+
|
|
115
|
+
#### REST API URL Paths
|
|
116
|
+
|
|
117
|
+
### R-11: kebab-case URL Paths
|
|
118
|
+
|
|
119
|
+
Path segments **MUST** use `kebab-case`. **MUST NOT** include trailing slashes.
|
|
120
|
+
|
|
121
|
+
### R-12: Plural Resource Nouns
|
|
122
|
+
|
|
123
|
+
Resources **MUST** be plural nouns. Singular only for singletons (`/users/{user_id}/profile`).
|
|
124
|
+
|
|
125
|
+
### R-13: No Verbs in Paths
|
|
126
|
+
|
|
127
|
+
**MUST NOT** contain verbs. Model actions as sub-resources: `POST /orders/{id}/cancellation` not `POST /orders/{id}/cancel`.
|
|
128
|
+
|
|
129
|
+
### R-14: snake_case Path Parameters
|
|
130
|
+
|
|
131
|
+
Path parameters **MUST** use `snake_case`: `/orders/{order_id}` not `/orders/{orderId}`.
|
|
132
|
+
|
|
133
|
+
### R-15: Version Prefix
|
|
134
|
+
|
|
135
|
+
**SHOULD NOT** include `/api`. Version prefix **MUST** use `/v{major}`: `/v1/orders`.
|
|
136
|
+
|
|
137
|
+
### R-16: Maximum Nesting Depth
|
|
138
|
+
|
|
139
|
+
Nesting **MUST NOT** exceed three levels. Use query filters for deeper relationships.
|
|
140
|
+
|
|
141
|
+
#### Event Type Names
|
|
142
|
+
|
|
143
|
+
### R-17: Dot-Notation Event Types
|
|
144
|
+
|
|
145
|
+
**MUST** use dot-notation: `{domain}.{resource}.{action}` with past-tense action. Multi-word segments **MUST** use `snake_case`: `order_management.purchase_order.approved`. Valid: `order.payment.completed`. Invalid: `order.payment.complete` (not past tense), `ORDER.PAYMENT.COMPLETED` (uppercase).
|
|
146
|
+
|
|
147
|
+
### R-18: Event Segment Depth
|
|
148
|
+
|
|
149
|
+
Additional segments **MAY** be appended; total depth **SHOULD NOT** exceed five.
|
|
150
|
+
|
|
151
|
+
### R-19: Event Catalog Registration
|
|
152
|
+
|
|
153
|
+
Types **MUST** be registered in the event catalog. Unregistered types **MUST** be rejected.
|
|
154
|
+
|
|
155
|
+
#### Message Queue and Topic Names
|
|
156
|
+
|
|
157
|
+
### R-20: Topic Name Structure
|
|
158
|
+
|
|
159
|
+
**MUST** use: `{domain}.{resource}.{event_type}.v{major}`. Valid: `retail.orders.created.v1`. Multi-word segments **MUST** use `snake_case`. **MUST NOT** contain application or team names. Describe the business event.
|
|
160
|
+
|
|
161
|
+
### R-21: Dead Letter and Retry Suffixes
|
|
162
|
+
|
|
163
|
+
Dead letter queues **MUST** append `.dlq`. Retry topics **MUST** append `.retry.{attempt}`.
|
|
164
|
+
|
|
165
|
+
#### HTTP Header Names
|
|
166
|
+
|
|
167
|
+
### R-22: Custom Header Casing
|
|
168
|
+
|
|
169
|
+
Custom headers **MUST** use `Kebab-Case` (title capitalized). `X-` prefix only for organization-specific headers; omit for broad adoption per RFC 6648.
|
|
170
|
+
|
|
171
|
+
### R-23: Standard Header Names
|
|
172
|
+
|
|
173
|
+
**MUST** use these exact names when semantics match:
|
|
174
|
+
|
|
175
|
+
| Header | Purpose |
|
|
176
|
+
|--------|---------|
|
|
177
|
+
| `X-Correlation-Id` | Distributed trace correlation |
|
|
178
|
+
| `X-Request-Id` | Unique request identifier |
|
|
179
|
+
| `X-Tenant-Id` | Multi-tenant context |
|
|
180
|
+
| `X-Flow-Id` | Business process flow |
|
|
181
|
+
| `X-Idempotency-Key` | Client-supplied idempotency token |
|
|
182
|
+
|
|
183
|
+
### R-24: No Internal Details in Headers
|
|
184
|
+
|
|
185
|
+
**MUST NOT** leak internal system names or infrastructure details.
|
|
186
|
+
|
|
187
|
+
#### Enum Values
|
|
188
|
+
|
|
189
|
+
### R-25: UPPER_SNAKE_CASE Enums
|
|
190
|
+
|
|
191
|
+
**MUST** use `UPPER_SNAKE_CASE`. **MUST NOT** use numeric codes, abbreviations, or single characters.
|
|
192
|
+
|
|
193
|
+
### R-26: Self-Descriptive Enum Values
|
|
194
|
+
|
|
195
|
+
Values **MUST** be self-descriptive without the field name: `PAYMENT_PENDING` not `PP`.
|
|
196
|
+
|
|
197
|
+
### R-27: UNKNOWN Default Value
|
|
198
|
+
|
|
199
|
+
Every enum **MUST** include `UNKNOWN` as the default for forward compatibility.
|
|
200
|
+
|
|
201
|
+
### R-28: Deprecated Value Preservation
|
|
202
|
+
|
|
203
|
+
Deprecated values **MUST** be preserved until all consumers migrate.
|
|
204
|
+
|
|
205
|
+
#### Query Parameter Names
|
|
206
|
+
|
|
207
|
+
### R-29: Query Parameter Conventions
|
|
208
|
+
|
|
209
|
+
**MUST** use `snake_case`. Standard pagination: `page_size` (integer), `page` (integer, 1-based), `cursor` (string). Sorting: `sort_by`, `sort_order` (`asc`/`desc`). Filters **SHOULD** use the field name directly. Complex filters **MAY** use brackets: `created_at[gte]=2026-01-01T00:00:00Z`.
|
|
210
|
+
|
|
211
|
+
### R-30: Boolean Query Parameters
|
|
212
|
+
|
|
213
|
+
Boolean parameters **MUST** accept `true`/`false` strings. Presence alone **MUST NOT** imply truth.
|
|
214
|
+
|
|
215
|
+
#### File and Directory Names
|
|
216
|
+
|
|
217
|
+
### R-31: File Naming Pattern
|
|
218
|
+
|
|
219
|
+
**MUST** use `kebab-case`. Pattern: `{resource}-{qualifier}-{date}.{extension}`.
|
|
220
|
+
|
|
221
|
+
### R-32: File Extension Conventions
|
|
222
|
+
|
|
223
|
+
Extensions **MUST** be lowercase. Schema files **MUST** follow `{resource}.{version}.schema.json`.
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Examples
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
GET /v1/purchase-orders/{purchase_order_id}/line-items?status=SHIPPED&sort_by=created_at&page_size=10
|
|
231
|
+
|
|
232
|
+
Headers:
|
|
233
|
+
X-Correlation-Id: 8f14e45f-ceea-467f-a8dc-e67e2d16eb68
|
|
234
|
+
X-Tenant-Id: tenant-acme-corp
|
|
235
|
+
|
|
236
|
+
Response:
|
|
237
|
+
{
|
|
238
|
+
"line_items": [
|
|
239
|
+
{
|
|
240
|
+
"line_item_id": "li-001",
|
|
241
|
+
"product_name": "Wireless Keyboard",
|
|
242
|
+
"quantity": 5,
|
|
243
|
+
"unit_price": { "amount": "49.99", "currency_code": "USD" },
|
|
244
|
+
"status": "SHIPPED",
|
|
245
|
+
"shipped": true,
|
|
246
|
+
"created_at": "2026-03-27T14:30:00Z",
|
|
247
|
+
"tracking_url": "https://tracking.example.com/pkg/12345"
|
|
248
|
+
}
|
|
249
|
+
],
|
|
250
|
+
"pagination": { "page": 1, "page_size": 10, "total_items": 1 }
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
Event: procurement.line_item.shipped
|
|
254
|
+
Topic: procurement.line_items.shipped.v1
|
|
255
|
+
File: line-item-shipments-2026-03-28.csv
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## Enforcement Rules
|
|
261
|
+
|
|
262
|
+
| Boundary | Validates | Rejection |
|
|
263
|
+
|----------|-----------|-----------|
|
|
264
|
+
| CI/CD Pipeline | OpenAPI paths, field names, enum values | Build fails, PR blocked |
|
|
265
|
+
| Schema Registry | Field names, event types | Registration rejected |
|
|
266
|
+
| API Gateway | URL path segments, header names | Route deployment rejected |
|
|
267
|
+
| Event Bus | Event type names, topic names | Publish rejected with error |
|
|
268
|
+
| Contract Review | All naming contexts | Review blocked |
|
|
269
|
+
|
|
270
|
+
### Hard Rejections (**MUST** reject)
|
|
271
|
+
|
|
272
|
+
Mixed case conventions in a single contract; verbs in URL path segments; non-past-tense event actions; unapproved abbreviations; internal system names in public contracts; missing version segment in topic names; enum values not in `UPPER_SNAKE_CASE`.
|
|
273
|
+
|
|
274
|
+
### Soft Warnings (**SHOULD** fix)
|
|
275
|
+
|
|
276
|
+
`is_` prefix on booleans (unless bare word is reserved); URL nesting beyond three levels; missing temporal suffix on date/time fields; query parameter names inconsistent with JSON fields.
|
|
277
|
+
|
|
278
|
+
### Validation Regex
|
|
279
|
+
|
|
280
|
+
| Context | Pattern |
|
|
281
|
+
|---------|---------|
|
|
282
|
+
| JSON fields | `^[a-z][a-z0-9]*(_[a-z0-9]+)*$` |
|
|
283
|
+
| URL path segments | `^[a-z][a-z0-9]*(-[a-z0-9]+)*$` |
|
|
284
|
+
| Path parameters | `\{[a-z][a-z0-9]*(_[a-z0-9]+)*\}` |
|
|
285
|
+
| Event types | `^[a-z][a-z0-9]*(_[a-z0-9]+)*(\.[a-z][a-z0-9]*(_[a-z0-9]+)*){2,4}$` |
|
|
286
|
+
| Queue/topic names | `^[a-z][a-z0-9]*(_[a-z0-9]+)*(\.[a-z][a-z0-9]*(_[a-z0-9]+)*){2,}\.v[0-9]+(\.(dlq\|retry\.[0-9]+))?$` |
|
|
287
|
+
| Enum values | `^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$` |
|
|
288
|
+
| Custom HTTP headers | `^X-([A-Z][a-z0-9]*(-[A-Z][a-z0-9]*)*)$` |
|
|
289
|
+
| File names | `^[a-z][a-z0-9]*(-[a-z0-9]+)*\.[a-z]+$` |
|
|
290
|
+
|
|
291
|
+
OpenAPI specs **MUST** be validated via Spectral or equivalent in CI/CD. AsyncAPI specs **MUST** be validated for event/topic naming. Schema registries **MUST** reject non-conforming field names. API gateways **SHOULD** enforce path conventions at route registration.
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## References
|
|
296
|
+
|
|
297
|
+
### Normative
|
|
298
|
+
|
|
299
|
+
- [RFC 9110 - HTTP Semantics](https://www.rfc-editor.org/rfc/rfc9110)
|
|
300
|
+
- [RFC 9457 - Problem Details for HTTP APIs](https://www.rfc-editor.org/rfc/rfc9457)
|
|
301
|
+
- [RFC 2119 - Key Words for Use in RFCs](https://www.rfc-editor.org/rfc/rfc2119)
|
|
302
|
+
- [RFC 6648 - Deprecating X- Prefix](https://www.rfc-editor.org/rfc/rfc6648)
|
|
303
|
+
|
|
304
|
+
### Informative
|
|
305
|
+
|
|
306
|
+
- [Google AIP-140: Field Names](https://google.aip.dev/140) | [AIP-190: Naming](https://google.aip.dev/190) | [AIP-122: Resources](https://google.aip.dev/122)
|
|
307
|
+
- [Zalando RESTful API Guidelines](https://opensource.zalando.com/restful-api-guidelines/)
|
|
308
|
+
- [Microsoft REST API Guidelines](https://github.com/microsoft/api-guidelines)
|
|
309
|
+
- [CloudEvents Specification](https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md)
|
|
310
|
+
- [Confluent Kafka Topic Naming](https://www.confluent.io/learn/kafka-topic-naming-convention/)
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## Rationale
|
|
315
|
+
|
|
316
|
+
**snake_case for JSON fields:** Aligns with Google AIP-140 and Zalando. Most interoperable convention - valid identifier in Python, Ruby, Rust, SQL; maps cleanly to camelCase via serialization libraries.
|
|
317
|
+
|
|
318
|
+
**kebab-case for URLs:** Most readable in browser bars and logs, avoids case-sensitivity ambiguity. Google, Zalando, and Microsoft converge here.
|
|
319
|
+
|
|
320
|
+
**Dot-notation for events/topics:** Enables wildcard subscription (`order.payment.*`) in brokers like RabbitMQ and NATS. Slashes conflict with URL semantics; hyphens prevent wildcard matching.
|
|
321
|
+
|
|
322
|
+
**UPPER_SNAKE_CASE for enums:** Near-universal constant convention across languages. Visually distinct from field names and URL segments.
|
|
323
|
+
|
|
324
|
+
**Security:** Business-domain naming prevents leaking internal table names, service mesh topology, or infrastructure details that aid reconnaissance.
|
|
325
|
+
|
|
326
|
+
**Observability:** Uniform naming enables distributed trace aggregation without per-service field mapping. Predictable event structures enable pattern-based alerting (`*.payment.failed`).
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## Version History
|
|
331
|
+
|
|
332
|
+
| Version | Date | Change |
|
|
333
|
+
| ------- | ---------- | ------------------ |
|
|
334
|
+
| 1.0.0 | 2026-03-28 | Initial definition |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"label": "Observability", "position": 6}
|