@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.
Files changed (34) hide show
  1. package/LICENSE +30 -0
  2. package/README.md +115 -0
  3. package/package.json +40 -0
  4. package/schema/document-standard-template.md +139 -0
  5. package/schema/standards.schema.json +154 -0
  6. package/standards/integration/governance/_category_.json +1 -0
  7. package/standards/integration/governance/integration-styles.md +56 -0
  8. package/standards/integration/index.md +9 -0
  9. package/standards/integration/standards/_category_.json +1 -0
  10. package/standards/integration/standards/api/_category_.json +1 -0
  11. package/standards/integration/standards/api/error-handling.md +250 -0
  12. package/standards/integration/standards/api/resource-design.md +286 -0
  13. package/standards/integration/standards/data-formats/_category_.json +1 -0
  14. package/standards/integration/standards/data-formats/character-encoding.md +206 -0
  15. package/standards/integration/standards/data-formats/date-format.md +102 -0
  16. package/standards/integration/standards/data-formats/datetime-formats.md +265 -0
  17. package/standards/integration/standards/data-formats/monetary-format.md +61 -0
  18. package/standards/integration/standards/events/_category_.json +1 -0
  19. package/standards/integration/standards/events/event-envelope.md +270 -0
  20. package/standards/integration/standards/foundational/_category_.json +1 -0
  21. package/standards/integration/standards/foundational/naming-conventions.md +334 -0
  22. package/standards/integration/standards/observability/_category_.json +1 -0
  23. package/standards/integration/standards/observability/integration-observability.md +226 -0
  24. package/standards/integration/standards/resilience/_category_.json +1 -0
  25. package/standards/integration/standards/resilience/integration-resilience-patterns.md +291 -0
  26. package/standards/integration/standards/resilience/retry-policy.md +268 -0
  27. package/standards/integration/standards/resilience/timeout.md +269 -0
  28. package/standards/integration/standards/versioning/_category_.json +1 -0
  29. package/standards/integration/standards/versioning/backward-forward-compatibility.md +230 -0
  30. package/standards/product/Guidelines/_category_.json +1 -0
  31. package/standards/product/Guidelines/requirement-document.md +54 -0
  32. package/standards/product/index.md +9 -0
  33. package/standards/project-management/index.md +9 -0
  34. 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}