Skip to content

Commit beed95c

Browse files
committed
feat(spec)!: enforce strict allOf form for derivation and redesign traits as URN-referenced types
- Add §3.2.1 (Top-level composition rules): derived GTS Type Schemas MUST use the canonical single-item allOf with a \$ref to the immediate parent; overlay constraints live at the top level. Top-level anyOf/oneOf/not are forbidden on all GTS Type Schemas (nested usage is unaffected). Rationale captured in ADR-0002. - Rewrite §9.7 traits model: x-gts-traits-schema becomes a single GTS Type URN string referencing a registered trait-type; inline schema, \$ref, and composition forms are removed. Trait-types are first-class GTS Type Schemas with their own parallel-derivation chain. Shallow merge with immutable-once-set semantics preserved. - Make the trait-completeness rule explicit: a non-abstract host with unresolved required trait fields is invalid by definition; registry MUST reject it at registration and OP#6 MUST reject instances of it as defense in depth. - Extend OP#12 to enforce the structural rules from §3.2.1 in addition to the existing constraint-compatibility checks. - Migrate all examples in events/types/, mcp/types/, and typespec/vms/types/ to strict Form A and the new trait-type model. Add gts.x.core.traits.event_meta.v1~ as the canonical trait-type referenced by the base event schema. - Update the register_derived test helper to emit strict Form A (single-item allOf + overlay spread at top level). Add register_trait_type and register_host_with_trait_ref helpers. - Add 15 structural test classes to test_op12_* covering canonical form, rejections (Form B, 3+ items, no-\$ref, multi-\$ref, skip-level, wrong parent, hybrid, top-level union/negation, base-with-allOf), and accepted nested-union shapes. - Rewrite test_op13_* (38 classes) around URN-referenced trait-types: value validation cases, trait-type derivation (narrowing, loosening rejection, field extension, default inheritance), parallel-derivation rules, abstract vs concrete completeness, MAJOR-version pinning, cycle detection, and instance-validation defense-in-depth. - Migrate the three trait-aware tests in test_refimpl_x_gts_final_abstract.py to the URN model. - Add ADR-0002 (MADR) with worked Option-1..4 comparison, running example, and explicit payload behavior under each option. - Log change as version 0.12 (BREAKING). Signed-off-by: Aviator 5 <ai.agent.tor@gmail.com>
1 parent c01f956 commit beed95c

18 files changed

Lines changed: 2550 additions & 1874 deletions

README.md

Lines changed: 215 additions & 108 deletions
Large diffs are not rendered by default.

adr/0002-strict-allof-derivation-form.md

Lines changed: 348 additions & 0 deletions
Large diffs are not rendered by default.

examples/events/types/gts.x.core.events.type.v1~.schema.json

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,7 @@
1111
"tenantId",
1212
"occurredAt"
1313
],
14-
"x-gts-traits-schema": {
15-
"type": "object",
16-
"additionalProperties": false,
17-
"properties": {
18-
"topicRef": {
19-
"description": "GTS ID of the topic/stream where events of this type are published.",
20-
"type": "string",
21-
"x-gts-ref": "gts.x.core.events.topic.v1~",
22-
"default": "gts.x.core.events.topic.v1~x.core._.default.v1"
23-
},
24-
"retention": {
25-
"description": "ISO 8601 duration for event retention.",
26-
"type": "string",
27-
"default": "P30D"
28-
}
29-
}
30-
},
14+
"x-gts-traits-schema": "gts://gts.x.core.traits.event_meta.v1~",
3115
"properties": {
3216
"type": {
3317
"description": "Identifier of the event type in GTS format.",

examples/events/types/gts.x.core.events.type.v1~x.commerce.orders.order_placed.v1.0~.schema.json

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,31 @@
44
"title": "Event Instance Schema: order.placed",
55
"type": "object",
66
"allOf": [
7-
{ "$ref": "gts://gts.x.core.events.type.v1~" },
8-
{
7+
{ "$ref": "gts://gts.x.core.events.type.v1~" }
8+
],
9+
"required": ["type", "payload", "subjectType"],
10+
"x-gts-traits": {
11+
"topicRef": "gts.x.core.events.topic.v1~x.commerce._.orders.v1",
12+
"retention": "P90D"
13+
},
14+
"properties": {
15+
"type": {
16+
"const": "gts.x.core.events.type.v1~x.commerce.orders.order_placed.v1.0~",
17+
"$comment": "The value is required only for IDE-side validation"
18+
},
19+
"payload": {
920
"type": "object",
10-
"required": ["type", "payload", "subjectType"],
11-
"x-gts-traits": {
12-
"topicRef": "gts.x.core.events.topic.v1~x.commerce._.orders.v1",
13-
"retention": "P90D"
14-
},
21+
"required": ["orderId", "customerId", "totalAmount", "items"],
1522
"properties": {
16-
"type": {
17-
"const": "gts.x.core.events.type.v1~x.commerce.orders.order_placed.v1.0~",
18-
"$comment": "The value is required only for IDE-side validation"
19-
},
20-
"payload": {
21-
"type": "object",
22-
"required": ["orderId", "customerId", "totalAmount", "items"],
23-
"properties": {
24-
"orderId": { "type": "string", "format": "uuid" },
25-
"customerId": { "type": "string", "format": "uuid" },
26-
"totalAmount": { "type": "number" },
27-
"items": { "type": "array", "items": { "type": "object" } }
28-
}
29-
},
30-
"subjectType": {
31-
"type": "string",
32-
"x-gts-ref": "gts.x.commerce.orders.order.v1.0~"
33-
}
23+
"orderId": { "type": "string", "format": "uuid" },
24+
"customerId": { "type": "string", "format": "uuid" },
25+
"totalAmount": { "type": "number" },
26+
"items": { "type": "array", "items": { "type": "object" } }
3427
}
28+
},
29+
"subjectType": {
30+
"type": "string",
31+
"x-gts-ref": "gts.x.commerce.orders.order.v1.0~"
3532
}
36-
]
33+
}
3734
}

examples/events/types/gts.x.core.events.type.v1~x.commerce.orders.order_placed.v1.1~.schema.json

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,32 @@
44
"title": "Event Instance Schema: order.placed",
55
"type": "object",
66
"allOf": [
7-
{ "$ref": "gts://gts.x.core.events.type.v1~" },
8-
{
7+
{ "$ref": "gts://gts.x.core.events.type.v1~" }
8+
],
9+
"required": ["type", "payload", "subjectType"],
10+
"x-gts-traits": {
11+
"topicRef": "gts.x.core.events.topic.v1~x.commerce._.orders.v1",
12+
"retention": "P90D"
13+
},
14+
"properties": {
15+
"type": {
16+
"const": "gts.x.core.events.type.v1~x.commerce.orders.order_placed.v1.1~",
17+
"$comment": "The value is required only for IDE-side validation"
18+
},
19+
"payload": {
920
"type": "object",
10-
"required": ["type", "payload", "subjectType"],
11-
"x-gts-traits": {
12-
"topicRef": "gts.x.core.events.topic.v1~x.commerce._.orders.v1",
13-
"retention": "P90D"
14-
},
21+
"required": ["orderId", "customerId", "totalAmount", "items"],
1522
"properties": {
16-
"type": {
17-
"const": "gts.x.core.events.type.v1~x.commerce.orders.order_placed.v1.1~",
18-
"$comment": "The value is required only for IDE-side validation"
19-
},
20-
"payload": {
21-
"type": "object",
22-
"required": ["orderId", "customerId", "totalAmount", "items"],
23-
"properties": {
24-
"orderId": { "type": "string", "format": "uuid" },
25-
"customerId": { "type": "string", "format": "uuid" },
26-
"totalAmount": { "type": "number" },
27-
"items": { "type": "array", "items": { "type": "object" } },
28-
"new_field_in_v1_1": { "type": "string", "default": "some_value" }
29-
}
30-
},
31-
"subjectType": {
32-
"type": "string",
33-
"x-gts-ref": "gts.x.commerce.orders.order.v1.0~"
34-
}
23+
"orderId": { "type": "string", "format": "uuid" },
24+
"customerId": { "type": "string", "format": "uuid" },
25+
"totalAmount": { "type": "number" },
26+
"items": { "type": "array", "items": { "type": "object" } },
27+
"new_field_in_v1_1": { "type": "string", "default": "some_value" }
3528
}
29+
},
30+
"subjectType": {
31+
"type": "string",
32+
"x-gts-ref": "gts.x.commerce.orders.order.v1.0~"
3633
}
37-
]
34+
}
3835
}

examples/events/types/gts.x.core.events.type.v1~x.core.idp.contact_created.v1~.schema.json

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,32 @@
55
"description": "Event instance schema for the user.created event type",
66
"type": "object",
77
"allOf": [
8-
{ "$ref": "gts://gts.x.core.events.type.v1~" },
9-
{
8+
{ "$ref": "gts://gts.x.core.events.type.v1~" }
9+
],
10+
"required": ["type", "payload", "subjectType"],
11+
"x-gts-traits": {
12+
"topicRef": "gts.x.core.events.topic.v1~x.core.idp.contacts.v1",
13+
"retention": "P365D"
14+
},
15+
"properties": {
16+
"type": {
17+
"const": "gts.x.core.events.type.v1~x.core.idp.contact_created.v1.0~",
18+
"$comment": "The value is required only for IDE-side validation"
19+
},
20+
"payload": {
1021
"type": "object",
11-
"required": ["type", "payload", "subjectType"],
12-
"x-gts-traits": {
13-
"topicRef": "gts.x.core.events.topic.v1~x.core.idp.contacts.v1",
14-
"retention": "P365D"
15-
},
22+
"required": ["userId", "email", "name", "roles"],
23+
"additionalProperties": false,
1624
"properties": {
17-
"type": {
18-
"const": "gts.x.core.events.type.v1~x.core.idp.contact_created.v1.0~",
19-
"$comment": "The value is required only for IDE-side validation"
20-
},
21-
"payload": {
22-
"type": "object",
23-
"required": ["userId", "email", "name", "roles"],
24-
"additionalProperties": false,
25-
"properties": {
26-
"userId": { "type": "string", "format": "uuid" },
27-
"email": { "type": "string", "format": "email" },
28-
"name": { "type": "string" },
29-
"roles": { "type": "array", "items": { "type": "string" } }
30-
}
31-
},
32-
"subjectType": {
33-
"type": "string",
34-
"x-gts-ref": "gts.x.core.idp.contact.v1.0~"
35-
}
25+
"userId": { "type": "string", "format": "uuid" },
26+
"email": { "type": "string", "format": "email" },
27+
"name": { "type": "string" },
28+
"roles": { "type": "array", "items": { "type": "string" } }
3629
}
30+
},
31+
"subjectType": {
32+
"type": "string",
33+
"x-gts-ref": "gts.x.core.idp.contact.v1.0~"
3734
}
38-
]
35+
}
3936
}

examples/events/types/gts.x.core.events.type_combined.v1~.schema.json

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,7 @@
99
"tenantId",
1010
"occurredAt"
1111
],
12-
"x-gts-traits-schema": {
13-
"type": "object",
14-
"additionalProperties": false,
15-
"properties": {
16-
"topicRef": {
17-
"description": "ID of the topic where events of this type are stored.",
18-
"type": "string",
19-
"x-gts-ref": "gts.x.core.events.topic.v1~"
20-
}
21-
}
22-
},
12+
"x-gts-traits-schema": "gts://gts.x.core.traits.event_meta.v1~",
2313
"properties": {
2414
"$schema": {
2515
"description": "Link to the event type schema.",

examples/events/types/gts.x.core.events.type_combined.v1~x.commerce.orders.order_placed.v1.0~.schema.json

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,30 @@
44
"title": "Event Instance Schema (Combined Anonymous Instance ID): order.placed",
55
"type": "object",
66
"allOf": [
7-
{ "$ref": "gts://gts.x.core.events.type_combined.v1~" },
8-
{
7+
{ "$ref": "gts://gts.x.core.events.type_combined.v1~" }
8+
],
9+
"required": ["payload", "subjectType"],
10+
"x-gts-traits": {
11+
"topicRef": "gts.x.core.events.topic.v1~x.commerce._.orders.v1"
12+
},
13+
"properties": {
14+
"id": {
15+
"type": "string",
16+
"x-gts-ref": "gts.x.core.events.type_combined.v1~x.commerce.orders.order_placed.v1.0~*"
17+
},
18+
"payload": {
919
"type": "object",
10-
"required": ["payload", "subjectType"],
20+
"required": ["orderId", "customerId", "totalAmount", "items"],
1121
"properties": {
12-
"id": {
13-
"type": "string",
14-
"x-gts-ref": "gts.x.core.events.type_combined.v1~x.commerce.orders.order_placed.v1.0~*"
15-
},
16-
"payload": {
17-
"type": "object",
18-
"required": ["orderId", "customerId", "totalAmount", "items"],
19-
"properties": {
20-
"orderId": { "type": "string", "format": "uuid" },
21-
"customerId": { "type": "string", "format": "uuid" },
22-
"totalAmount": { "type": "number" },
23-
"items": { "type": "array", "items": { "type": "object" } }
24-
}
25-
},
26-
"subjectType": {
27-
"type": "string",
28-
"x-gts-ref": "gts.x.commerce.orders.order.v1.0~"
29-
}
22+
"orderId": { "type": "string", "format": "uuid" },
23+
"customerId": { "type": "string", "format": "uuid" },
24+
"totalAmount": { "type": "number" },
25+
"items": { "type": "array", "items": { "type": "object" } }
3026
}
27+
},
28+
"subjectType": {
29+
"type": "string",
30+
"x-gts-ref": "gts.x.commerce.orders.order.v1.0~"
3131
}
32-
]
32+
}
3333
}

examples/events/types/gts.x.core.idp.contact.v1.0~x.core.idp.billing_contact.v1.0~.schema.json

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,18 @@
44
"title": "User",
55
"type": "object",
66
"allOf": [
7-
{ "$ref": "gts://gts.x.core.idp.contact.v1.0~" },
8-
{
7+
{ "$ref": "gts://gts.x.core.idp.contact.v1.0~" }
8+
],
9+
"properties": {
10+
"custom_properties": {
911
"type": "object",
12+
"required": ["phone_number", "address", "currency"],
1013
"properties": {
11-
"custom_properties": {
12-
"type": "object",
13-
"required": ["phone_number", "address", "currency"],
14-
"properties": {
15-
"phone_number": { "type": "string" },
16-
"address": { "type": "string" },
17-
"currency": { "type": "string" }
18-
},
19-
"additionalProperties": true
20-
}
21-
}
14+
"phone_number": { "type": "string" },
15+
"address": { "type": "string" },
16+
"currency": { "type": "string" }
17+
},
18+
"additionalProperties": true
2219
}
23-
]
20+
}
2421
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"$id": "gts://gts.x.core.traits.event_meta.v1~",
3+
"$schema": "http://json-schema.org/draft-07/schema#",
4+
"title": "Event Meta Trait",
5+
"type": "object",
6+
"description": "Trait-type attached to event host-types. Carries cross-cutting metadata: where instances of the event are published (topicRef) and how long they are retained.",
7+
"properties": {
8+
"topicRef": {
9+
"description": "GTS ID of the topic/stream where events of this type are published.",
10+
"type": "string",
11+
"x-gts-ref": "gts.x.core.events.topic.v1~",
12+
"default": "gts.x.core.events.topic.v1~x.core._.default.v1"
13+
},
14+
"retention": {
15+
"description": "ISO 8601 duration for event retention.",
16+
"type": "string",
17+
"default": "P30D"
18+
}
19+
}
20+
}

0 commit comments

Comments
 (0)