@@ -303,6 +303,70 @@ Capabilities outside `dev.ucp.*` version fully independently:
303303
304304Vendor schemas follow the same self-describing requirements.
305305
306+ ## Extensibility and Forward Compatibility
307+
308+ When designing schemas, you must account for how older clients will validate newer payloads. In serialization formats
309+ like Protobuf, adding a new field or enum value is generally a safe, forward-compatible change.
310+
311+ Because modern code generators (e.g. [ Quicktype] ( https://quicktype.io/ ) ) translate JSON Schemas into strictly typed
312+ classes (e.g., Go structs or Java Enums), certain schema constraints will cause deserialization errors on older clients
313+ as the protocol evolves. Avoiding such changes helps minimize the need to up-version the protocol.
314+
315+ ### Open Enumerations
316+
317+ If a field's list of values might expand in the future (e.g., adding a ` "refunded" ` status or a new payment method),
318+ ** do not use ` enum ` ** .
319+
320+ Instead, define a standard ` string ` , document the requirement to ignore unknown values in the ` description ` , and use
321+ ` examples ` to convey current expected values to code generators. Avoid complex "Open Set" validation patterns
322+ (e.g., combining ` anyOf ` with ` const ` ), as they frequently confuse client-side code generators and make schemas
323+ difficult to read.
324+
325+ ``` json
326+ "cancellation_reason" : {
327+ "type" : " string" ,
328+ "description" : " Reason for order cancellation. Clients MUST tolerate and ignore unknown values." ,
329+ "examples" : [" customer_requested" , " inventory_shortage" , " fraud_suspected" ]
330+ }
331+ ```
332+
333+ ### Closed Enumerations
334+
335+ Use strict ` enum ` or ` const ` only for permanently fixed domains or when unknown values are inherently unsupported.
336+ Reserve them for cases where adding a new value inherently requires integrators to update their code (e.g., protocol
337+ versions, strict type discriminators, or days of the week).
338+
339+ ``` json
340+ "status" : {
341+ "type" : " string" ,
342+ "enum" : [" open" , " completed" , " expired" ],
343+ "description" : " Lifecycle state. This domain is strictly bounded; unknown states represent a breakdown in the state machine and MUST be rejected."
344+ }
345+ ```
346+
347+ ### Open Objects (` additionalProperties ` )
348+
349+ Marking an object as closed preemptively prevents any future non-breaking additions to the schema. In a distributed
350+ protocol, what would otherwise be a backward-compatible field addition (e.g., adding a "gift_message" field to an order)
351+ becomes a breaking change for any client validating against a closed schema.
352+
353+ By default, JSON Schema is open and ignores unknown properties. Authors should leave this keyword omitted except in rare
354+ circumstances: polymorphic discriminators (where strictness prevents oneOf validation ambiguity), security-critical
355+ payloads (where unknown fields may indicate tampering), or protocol envelopes (where strictness is useful to catch
356+ typos in core metadata like the ` ucp ` block).
357+
358+ ** Anti-Pattern (Prevents adding new fields without a reversion):**
359+
360+ ``` json
361+ "totals" : {
362+ "type" : " object" ,
363+ "properties" : {
364+ "subtotal" : {"type" : " integer" }
365+ },
366+ "additionalProperties" : false
367+ }
368+ ```
369+
306370## Complete Example: Capability Schema
307371
308372A capability schema defines both payload structure and declaration variants:
0 commit comments