@vev-software/atlas-contracts 0.1.3 → 0.1.5

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/dist/index.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  */
6
6
  /** The atlas-contracts schema major version. */
7
7
  export declare const CONTRACT_VERSION: "1";
8
- export type AssetKind = "system" | "application" | "server" | "infrastructure" | "data-area" | "dataset" | "column";
8
+ export type AssetKind = "system" | "application" | "server" | "infrastructure" | "data-area" | "dataset" | "column" | "integration" | "business-process";
9
9
  export type Lifecycle = "draft" | "active" | "retired";
10
10
  export type RelationshipType = "runs-on" | "hosts" | "connects-to" | "depends-on" | "part-of" | "joins-on";
11
11
  /** A manual, lightweight classification: a key with an optional value. */
@@ -201,12 +201,19 @@ export interface Observation {
201
201
  * The public wire format a discovery scanner emits into Atlas: a batch of raw observations that
202
202
  * the private Atlas Enterprise reconciliation engine turns into catalogue assets.
203
203
  */
204
+ export interface ObservedRelationship {
205
+ fromObservedId: string;
206
+ toObservedId: string;
207
+ type: RelationshipType;
208
+ description?: string | null;
209
+ }
204
210
  export interface DiscoveryObservationBatch {
205
211
  contractVersion: typeof CONTRACT_VERSION;
206
212
  kind: "discovery-observation";
207
213
  source: ObservationSource;
208
214
  observedAt: string;
209
215
  observations: Observation[];
216
+ relationships?: ObservedRelationship[];
210
217
  }
211
218
  /** The layout format of a `Diagram`. */
212
219
  export type DiagramFormat = "atlas-layout";
@@ -343,3 +350,127 @@ export interface AtlasBundle {
343
350
  restore?: RestoreHints | null;
344
351
  excluded?: ExcludedCategory[];
345
352
  }
353
+ /** Digest classification of an item. Deliberately narrower than `AssetKind`. */
354
+ export type DigestKind = "system" | "application" | "platform" | "vendor";
355
+ /**
356
+ * The intended change for an item, taken from the Target Architecture contract's change intents
357
+ * and extended with `replace` for digest purposes.
358
+ */
359
+ export type PlannedChange = "add" | "change" | "replace" | "retire";
360
+ /**
361
+ * Which asset kinds and tags were included in a digest. Both arrays are required and may be
362
+ * empty: an empty `kinds` means no kinds were included, and an empty `tags` means no tag filter
363
+ * was applied (tag matching is OR within the list, AND with the kind filter).
364
+ */
365
+ export interface LandscapeDigestScope {
366
+ kinds: DigestKind[];
367
+ tags: Tag[];
368
+ }
369
+ /**
370
+ * One minimized landscape item. Carries only the fields a consented consumer needs; everything
371
+ * else is forbidden by the schema.
372
+ */
373
+ export interface LandscapeDigestItem {
374
+ kind: DigestKind;
375
+ name: string;
376
+ lifecycle: Lifecycle;
377
+ vendor?: string | null;
378
+ plannedChange?: PlannedChange | null;
379
+ /** A count only — never the identities of the integrated parties. */
380
+ integrationCount?: number | null;
381
+ }
382
+ /**
383
+ * A minimized, versioned summary of an Atlas landscape for consented consumers. `sequence` is
384
+ * monotonic per `sourceInstanceId` (first is 1, strictly higher after, gaps allowed); consumers
385
+ * reject a sequence at or below the last accepted for the same source (replay protection).
386
+ */
387
+ export interface LandscapeDigest {
388
+ contractVersion: typeof CONTRACT_VERSION;
389
+ digestId: string;
390
+ generatedAt: string;
391
+ sourceInstanceId: string;
392
+ sequence: number;
393
+ scope: LandscapeDigestScope;
394
+ items: LandscapeDigestItem[];
395
+ }
396
+ export type TargetScopeKind = "estate" | "domain" | "capability-area";
397
+ export type TargetVersionStatus = "draft" | "proposed" | "approved" | "active" | "superseded" | "rejected" | "archived";
398
+ export type ChangeIntent = "add" | "change" | "retire";
399
+ /** What part of the estate a Target Architecture governs. */
400
+ export interface TargetScope {
401
+ kind: TargetScopeKind;
402
+ ref?: string | null;
403
+ name?: string | null;
404
+ }
405
+ /** One asset-level intended change in a target version or gap. */
406
+ export interface TargetAssetMember {
407
+ intent: ChangeIntent;
408
+ assetRef?: string | null;
409
+ asset?: Asset | null;
410
+ rationale?: string | null;
411
+ }
412
+ /** One relationship-level intended change in a target version or gap. */
413
+ export interface TargetRelationshipMember {
414
+ intent: ChangeIntent;
415
+ relationshipRef?: string | null;
416
+ relationship?: Relationship | null;
417
+ rationale?: string | null;
418
+ }
419
+ /** One ordered To-Be version (Plateau analogue) in a Target Architecture. */
420
+ export interface TargetVersion {
421
+ id: string;
422
+ name: string;
423
+ sequence: number;
424
+ status: TargetVersionStatus;
425
+ rationale?: string | null;
426
+ intendedHorizon?: string | null;
427
+ effectiveDate?: string | null;
428
+ assetChanges?: TargetAssetMember[];
429
+ relationshipChanges?: TargetRelationshipMember[];
430
+ }
431
+ /** One optional intermediate gap slice inside a transition. */
432
+ export interface TargetGap {
433
+ id: string;
434
+ name: string;
435
+ description?: string | null;
436
+ assetChanges?: TargetAssetMember[];
437
+ relationshipChanges?: TargetRelationshipMember[];
438
+ }
439
+ /** One deliverable within a transition work package. */
440
+ export interface Deliverable {
441
+ id: string;
442
+ name: string;
443
+ description?: string | null;
444
+ }
445
+ /** A transition work package grouping one or more deliverables. */
446
+ export interface WorkPackage {
447
+ id: string;
448
+ name: string;
449
+ description?: string | null;
450
+ deliverables?: Deliverable[];
451
+ }
452
+ /** Optional intermediate transition architecture between two target versions. */
453
+ export interface TargetTransition {
454
+ id: string;
455
+ name: string;
456
+ fromVersionId: string;
457
+ toVersionId: string;
458
+ description?: string | null;
459
+ gaps?: TargetGap[];
460
+ workPackages?: WorkPackage[];
461
+ }
462
+ /**
463
+ * A versioned, landscape-level To-Be target: the named target, its ordered versions, the status
464
+ * vocabulary and optional transition/gap shapes.
465
+ */
466
+ export interface TargetArchitectureDocument {
467
+ contractVersion: typeof CONTRACT_VERSION;
468
+ kind: "target-architecture";
469
+ id: string;
470
+ name: string;
471
+ description?: string | null;
472
+ scope: TargetScope;
473
+ generator?: Generator | null;
474
+ versions: TargetVersion[];
475
+ transitions?: TargetTransition[];
476
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vev-software/atlas-contracts",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Public, versioned data model and interop contracts for VEV Atlas — the catalogue asset model plus manual relationships, tags and the landscape import/export document.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -7,7 +7,7 @@
7
7
  "AssetKind": {
8
8
  "type": "string",
9
9
  "description": "The kind of asset held in the catalogue. The data-layer kinds (data-area, dataset, column) model the data architecture beneath a system, down to the column. The AI kinds (ai-service, ai-model) catalogue AI platforms and models as first-class assets.",
10
- "enum": ["system", "application", "server", "infrastructure", "data-area", "dataset", "column", "ai-service", "ai-model"]
10
+ "enum": ["system", "application", "server", "infrastructure", "data-area", "dataset", "column", "ai-service", "ai-model", "integration", "business-process"]
11
11
  },
12
12
  "Lifecycle": {
13
13
  "type": "string",
@@ -21,6 +21,49 @@
21
21
  "maxLength": 128,
22
22
  "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$"
23
23
  },
24
+ "RelationshipId": {
25
+ "type": "string",
26
+ "description": "Stable identifier for a relationship. Never reused or re-meaning'd once published.",
27
+ "minLength": 1,
28
+ "maxLength": 128,
29
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$"
30
+ },
31
+ "TargetScopeKind": {
32
+ "type": "string",
33
+ "description": "The landscape scope a Target Architecture governs.",
34
+ "enum": ["estate", "domain", "capability-area"]
35
+ },
36
+ "TargetVersionStatus": {
37
+ "type": "string",
38
+ "description": "Lifecycle status of a TargetVersion. A TargetArchitecture must carry exactly one active version.",
39
+ "enum": ["draft", "proposed", "approved", "active", "superseded", "rejected", "archived"]
40
+ },
41
+ "ChangeIntent": {
42
+ "type": "string",
43
+ "description": "How a target member changes the live estate.",
44
+ "enum": ["add", "change", "retire"]
45
+ },
46
+ "TargetScope": {
47
+ "type": "object",
48
+ "description": "What part of the estate a Target Architecture governs: the whole estate, one domain, or one capability area.",
49
+ "additionalProperties": false,
50
+ "required": ["kind"],
51
+ "properties": {
52
+ "kind": { "$ref": "#/$defs/TargetScopeKind" },
53
+ "ref": {
54
+ "type": ["string", "null"],
55
+ "description": "Optional opaque identifier of the scoped thing when the target does not cover the whole estate.",
56
+ "minLength": 1,
57
+ "maxLength": 128
58
+ },
59
+ "name": {
60
+ "type": ["string", "null"],
61
+ "description": "Optional human-readable scope name.",
62
+ "minLength": 1,
63
+ "maxLength": 256
64
+ }
65
+ }
66
+ },
24
67
  "Tag": {
25
68
  "type": "object",
26
69
  "description": "Manual, lightweight classification. A key with an optional value.",
@@ -31,9 +31,41 @@
31
31
  "description": "The raw observations in this batch. May be empty (a scan that saw nothing new).",
32
32
  "items": { "$ref": "#/$defs/Observation" },
33
33
  "default": []
34
+ },
35
+ "relationships": {
36
+ "type": "array",
37
+ "description": "Observed relationships between the things in this batch, referenced by their observedId — e.g. a foreign key (joins-on) or data-layer containment (part-of). Optional and defaults to empty, so a scanner that emits none stays valid. Held facts only; the private reconciler resolves the observedId endpoints to catalogue assets.",
38
+ "items": { "$ref": "#/$defs/ObservedRelationship" },
39
+ "default": []
34
40
  }
35
41
  },
36
42
  "$defs": {
43
+ "ObservedRelationship": {
44
+ "type": "object",
45
+ "description": "A relationship between two observed things, by observedId. NOT an Atlas relationship (no asset ids); the reconciler resolves endpoints and re-expresses it in the catalogue.",
46
+ "additionalProperties": false,
47
+ "required": ["fromObservedId", "toObservedId", "type"],
48
+ "properties": {
49
+ "fromObservedId": {
50
+ "type": "string",
51
+ "description": "The referencing observation's observedId.",
52
+ "minLength": 1,
53
+ "maxLength": 256
54
+ },
55
+ "toObservedId": {
56
+ "type": "string",
57
+ "description": "The referenced observation's observedId.",
58
+ "minLength": 1,
59
+ "maxLength": 256
60
+ },
61
+ "type": {
62
+ "type": "string",
63
+ "description": "The held relationship vocabulary. Mirrors relationship.schema.json.",
64
+ "enum": ["runs-on", "hosts", "connects-to", "depends-on", "part-of", "joins-on"]
65
+ },
66
+ "description": { "type": ["string", "null"], "maxLength": 1024 }
67
+ }
68
+ },
37
69
  "ObservationSource": {
38
70
  "type": "object",
39
71
  "description": "Which scanner produced the batch. The authoritative tenant binding is the authenticated machine-principal at ingestion (a Fabric concern), NOT this payload; 'tenantRef' is an optional, opaque hint only.",
@@ -0,0 +1,105 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://contracts.vev.software/atlas/v1/landscape-digest.schema.json",
4
+ "title": "Atlas landscape share digest (v1)",
5
+ "description": "A minimized, versioned summary of an Atlas landscape for consented consumers. Push-only sharing surface: Atlas produces the digest and delivers it as a file or over an outbound HTTPS call; a consumer never pulls from the customer's network. Minimization is enforced by the schema (additionalProperties: false): no hostnames, IP addresses, server or discovery details, descriptions, attachments, people, column-level data or credentials. The digest is a summary for sharing — not the customer-owned portability export (landscape.schema.json) and not an import document. See docs/landscape-digest.md.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["contractVersion", "digestId", "generatedAt", "sourceInstanceId", "sequence", "scope", "items"],
9
+ "properties": {
10
+ "contractVersion": {
11
+ "type": "string",
12
+ "description": "The atlas-contracts schema major version this digest conforms to.",
13
+ "const": "1"
14
+ },
15
+ "digestId": {
16
+ "type": "string",
17
+ "description": "Stable identifier for this digest. Opaque to consumers; unique per produced digest (a UUIDv7 is recommended).",
18
+ "minLength": 1,
19
+ "maxLength": 128,
20
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$"
21
+ },
22
+ "generatedAt": {
23
+ "type": "string",
24
+ "description": "When the digest was produced (RFC 3339).",
25
+ "format": "date-time"
26
+ },
27
+ "sourceInstanceId": {
28
+ "type": "string",
29
+ "description": "Opaque identifier of the producing Atlas instance. Consumers use it to scope sequence/replay state; it carries no tenant or customer semantics. A source that resets its sequence must mint a new sourceInstanceId.",
30
+ "minLength": 1,
31
+ "maxLength": 128
32
+ },
33
+ "sequence": {
34
+ "type": "integer",
35
+ "description": "Monotonic per sourceInstanceId: the first digest is sequence 1, each later digest is strictly higher (gaps allowed). Consumers must reject a sequence at or below the last one accepted for the same source (replay protection).",
36
+ "minimum": 1
37
+ },
38
+ "scope": {
39
+ "$ref": "#/$defs/DigestScope"
40
+ },
41
+ "items": {
42
+ "type": "array",
43
+ "description": "The minimized landscape items. Every item's kind must be a member of scope.kinds (checked by the conformance kit; JSON Schema cannot express it).",
44
+ "items": { "$ref": "#/$defs/DigestItem" }
45
+ }
46
+ },
47
+ "$defs": {
48
+ "DigestKind": {
49
+ "type": "string",
50
+ "description": "Digest classification of an item. Deliberately narrower than the catalogue AssetKind: platform folds in server/infrastructure/AI substrate, vendor is a producer-derived summary entry, and data-layer kinds (data-area, dataset, column) are excluded from digests.",
51
+ "enum": ["system", "application", "platform", "vendor"]
52
+ },
53
+ "PlannedChange": {
54
+ "type": "string",
55
+ "description": "The intended change for an item, taken from the Target Architecture contract's change intents (add/change/retire) and extended with replace for digest purposes. The shared ChangeIntent vocabulary is not modified.",
56
+ "enum": ["add", "change", "replace", "retire"]
57
+ },
58
+ "DigestScope": {
59
+ "type": "object",
60
+ "description": "Which asset kinds and tags were included in this digest. Both arrays are required and may be empty: an empty kinds array means no kinds were included, and an empty tags array means no tag filter was applied (tag matching is OR within the list, AND with the kind filter).",
61
+ "additionalProperties": false,
62
+ "required": ["kinds", "tags"],
63
+ "properties": {
64
+ "kinds": {
65
+ "type": "array",
66
+ "description": "The digest item kinds included.",
67
+ "items": { "$ref": "#/$defs/DigestKind" },
68
+ "uniqueItems": true
69
+ },
70
+ "tags": {
71
+ "type": "array",
72
+ "description": "The tag filters that qualified inclusion (key, and value when present).",
73
+ "items": { "$ref": "common.schema.json#/$defs/Tag" }
74
+ }
75
+ }
76
+ },
77
+ "DigestItem": {
78
+ "type": "object",
79
+ "description": "One minimized landscape item. Carries only the fields a consented consumer needs: classification, name, lifecycle, and optional vendor / planned change / integration count. Everything else (hostnames, IPs, server and discovery details, descriptions, attachments, people, column-level data, credentials) is forbidden by additionalProperties: false.",
80
+ "additionalProperties": false,
81
+ "required": ["kind", "name", "lifecycle"],
82
+ "properties": {
83
+ "kind": { "$ref": "#/$defs/DigestKind" },
84
+ "name": {
85
+ "type": "string",
86
+ "description": "The item's catalogue name.",
87
+ "minLength": 1,
88
+ "maxLength": 256
89
+ },
90
+ "lifecycle": { "$ref": "common.schema.json#/$defs/Lifecycle" },
91
+ "vendor": {
92
+ "type": ["string", "null"],
93
+ "description": "Optional vendor of the item, when known.",
94
+ "maxLength": 128
95
+ },
96
+ "plannedChange": { "$ref": "#/$defs/PlannedChange" },
97
+ "integrationCount": {
98
+ "type": "integer",
99
+ "description": "Optional count of integrations the item participates in. A count only — never the identities of the integrated parties.",
100
+ "minimum": 0
101
+ }
102
+ }
103
+ }
104
+ }
105
+ }
@@ -0,0 +1,321 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://contracts.vev.software/atlas/v1/target-architecture.schema.json",
4
+ "title": "Atlas Target Architecture document (v1)",
5
+ "description": "A versioned, landscape-level To-Be target: the named target, its ordered versions, the status vocabulary and optional transition/gap shapes. Product-native truth only: ArchiMate remains a peripheral mapping. See atlas-contracts#35.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["contractVersion", "kind", "id", "name", "scope", "versions"],
9
+ "properties": {
10
+ "contractVersion": {
11
+ "type": "string",
12
+ "description": "The atlas-contracts schema major version this document conforms to.",
13
+ "const": "1"
14
+ },
15
+ "kind": {
16
+ "type": "string",
17
+ "const": "target-architecture"
18
+ },
19
+ "id": {
20
+ "type": "string",
21
+ "description": "Stable identifier for the target architecture.",
22
+ "minLength": 1,
23
+ "maxLength": 128,
24
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$"
25
+ },
26
+ "name": {
27
+ "type": "string",
28
+ "description": "Human-readable name of the target architecture.",
29
+ "minLength": 1,
30
+ "maxLength": 256
31
+ },
32
+ "description": {
33
+ "type": ["string", "null"],
34
+ "maxLength": 4096
35
+ },
36
+ "scope": {
37
+ "$ref": "common.schema.json#/$defs/TargetScope"
38
+ },
39
+ "generator": {
40
+ "description": "Optional provenance: what produced this target document.",
41
+ "oneOf": [
42
+ { "type": "null" },
43
+ { "$ref": "common.schema.json#/$defs/Generator" }
44
+ ]
45
+ },
46
+ "versions": {
47
+ "type": "array",
48
+ "minItems": 1,
49
+ "items": { "$ref": "#/$defs/TargetVersion" },
50
+ "contains": {
51
+ "type": "object",
52
+ "required": ["status"],
53
+ "properties": {
54
+ "status": { "const": "active" }
55
+ }
56
+ },
57
+ "minContains": 1,
58
+ "maxContains": 1
59
+ },
60
+ "transitions": {
61
+ "type": "array",
62
+ "items": { "$ref": "#/$defs/TargetTransition" },
63
+ "default": []
64
+ }
65
+ },
66
+ "$defs": {
67
+ "TargetAssetMember": {
68
+ "type": "object",
69
+ "description": "One asset-level intended change in a TargetVersion or transition/gap step.",
70
+ "additionalProperties": false,
71
+ "required": ["intent"],
72
+ "properties": {
73
+ "intent": { "$ref": "common.schema.json#/$defs/ChangeIntent" },
74
+ "assetRef": {
75
+ "oneOf": [
76
+ { "type": "null" },
77
+ { "$ref": "common.schema.json#/$defs/AssetId" }
78
+ ]
79
+ },
80
+ "asset": {
81
+ "oneOf": [
82
+ { "type": "null" },
83
+ { "$ref": "asset.schema.json" }
84
+ ]
85
+ },
86
+ "rationale": {
87
+ "type": ["string", "null"],
88
+ "maxLength": 4096
89
+ }
90
+ },
91
+ "allOf": [
92
+ {
93
+ "if": { "properties": { "intent": { "const": "add" } }, "required": ["intent"] },
94
+ "then": { "required": ["asset"] }
95
+ },
96
+ {
97
+ "if": { "properties": { "intent": { "const": "change" } }, "required": ["intent"] },
98
+ "then": { "required": ["assetRef", "asset"] }
99
+ },
100
+ {
101
+ "if": { "properties": { "intent": { "const": "retire" } }, "required": ["intent"] },
102
+ "then": { "required": ["assetRef"] }
103
+ }
104
+ ]
105
+ },
106
+ "TargetRelationshipMember": {
107
+ "type": "object",
108
+ "description": "One relationship-level intended change in a TargetVersion or transition/gap step.",
109
+ "additionalProperties": false,
110
+ "required": ["intent"],
111
+ "properties": {
112
+ "intent": { "$ref": "common.schema.json#/$defs/ChangeIntent" },
113
+ "relationshipRef": {
114
+ "oneOf": [
115
+ { "type": "null" },
116
+ { "$ref": "common.schema.json#/$defs/RelationshipId" }
117
+ ]
118
+ },
119
+ "relationship": {
120
+ "oneOf": [
121
+ { "type": "null" },
122
+ { "$ref": "relationship.schema.json" }
123
+ ]
124
+ },
125
+ "rationale": {
126
+ "type": ["string", "null"],
127
+ "maxLength": 4096
128
+ }
129
+ },
130
+ "allOf": [
131
+ {
132
+ "if": { "properties": { "intent": { "const": "add" } }, "required": ["intent"] },
133
+ "then": { "required": ["relationship"] }
134
+ },
135
+ {
136
+ "if": { "properties": { "intent": { "const": "change" } }, "required": ["intent"] },
137
+ "then": { "required": ["relationshipRef", "relationship"] }
138
+ },
139
+ {
140
+ "if": { "properties": { "intent": { "const": "retire" } }, "required": ["intent"] },
141
+ "then": { "required": ["relationshipRef"] }
142
+ }
143
+ ]
144
+ },
145
+ "TargetVersion": {
146
+ "type": "object",
147
+ "description": "One ordered To-Be version (ArchiMate Plateau analogue) within a Target Architecture.",
148
+ "additionalProperties": false,
149
+ "required": ["id", "name", "sequence", "status"],
150
+ "properties": {
151
+ "id": {
152
+ "type": "string",
153
+ "minLength": 1,
154
+ "maxLength": 128,
155
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$"
156
+ },
157
+ "name": {
158
+ "type": "string",
159
+ "minLength": 1,
160
+ "maxLength": 256
161
+ },
162
+ "sequence": {
163
+ "type": "integer",
164
+ "minimum": 1
165
+ },
166
+ "status": { "$ref": "common.schema.json#/$defs/TargetVersionStatus" },
167
+ "rationale": {
168
+ "type": ["string", "null"],
169
+ "maxLength": 4096
170
+ },
171
+ "intendedHorizon": {
172
+ "type": ["string", "null"],
173
+ "maxLength": 128
174
+ },
175
+ "effectiveDate": {
176
+ "type": ["string", "null"],
177
+ "format": "date"
178
+ },
179
+ "assetChanges": {
180
+ "type": "array",
181
+ "items": { "$ref": "#/$defs/TargetAssetMember" },
182
+ "default": []
183
+ },
184
+ "relationshipChanges": {
185
+ "type": "array",
186
+ "items": { "$ref": "#/$defs/TargetRelationshipMember" },
187
+ "default": []
188
+ }
189
+ }
190
+ },
191
+ "TargetGap": {
192
+ "type": "object",
193
+ "description": "An optional intermediate gap slice between two target versions.",
194
+ "additionalProperties": false,
195
+ "required": ["id", "name"],
196
+ "properties": {
197
+ "id": {
198
+ "type": "string",
199
+ "minLength": 1,
200
+ "maxLength": 128,
201
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$"
202
+ },
203
+ "name": {
204
+ "type": "string",
205
+ "minLength": 1,
206
+ "maxLength": 256
207
+ },
208
+ "description": {
209
+ "type": ["string", "null"],
210
+ "maxLength": 4096
211
+ },
212
+ "assetChanges": {
213
+ "type": "array",
214
+ "items": { "$ref": "#/$defs/TargetAssetMember" },
215
+ "default": []
216
+ },
217
+ "relationshipChanges": {
218
+ "type": "array",
219
+ "items": { "$ref": "#/$defs/TargetRelationshipMember" },
220
+ "default": []
221
+ }
222
+ }
223
+ },
224
+ "Deliverable": {
225
+ "type": "object",
226
+ "description": "One deliverable within a transition work package.",
227
+ "additionalProperties": false,
228
+ "required": ["id", "name"],
229
+ "properties": {
230
+ "id": {
231
+ "type": "string",
232
+ "minLength": 1,
233
+ "maxLength": 128,
234
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$"
235
+ },
236
+ "name": {
237
+ "type": "string",
238
+ "minLength": 1,
239
+ "maxLength": 256
240
+ },
241
+ "description": {
242
+ "type": ["string", "null"],
243
+ "maxLength": 4096
244
+ }
245
+ }
246
+ },
247
+ "WorkPackage": {
248
+ "type": "object",
249
+ "description": "A transition work package grouping one or more deliverables.",
250
+ "additionalProperties": false,
251
+ "required": ["id", "name"],
252
+ "properties": {
253
+ "id": {
254
+ "type": "string",
255
+ "minLength": 1,
256
+ "maxLength": 128,
257
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$"
258
+ },
259
+ "name": {
260
+ "type": "string",
261
+ "minLength": 1,
262
+ "maxLength": 256
263
+ },
264
+ "description": {
265
+ "type": ["string", "null"],
266
+ "maxLength": 4096
267
+ },
268
+ "deliverables": {
269
+ "type": "array",
270
+ "items": { "$ref": "#/$defs/Deliverable" },
271
+ "default": []
272
+ }
273
+ }
274
+ },
275
+ "TargetTransition": {
276
+ "type": "object",
277
+ "description": "Optional intermediate transition architecture between two versions.",
278
+ "additionalProperties": false,
279
+ "required": ["id", "name", "fromVersionId", "toVersionId"],
280
+ "properties": {
281
+ "id": {
282
+ "type": "string",
283
+ "minLength": 1,
284
+ "maxLength": 128,
285
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$"
286
+ },
287
+ "name": {
288
+ "type": "string",
289
+ "minLength": 1,
290
+ "maxLength": 256
291
+ },
292
+ "description": {
293
+ "type": ["string", "null"],
294
+ "maxLength": 4096
295
+ },
296
+ "fromVersionId": {
297
+ "type": "string",
298
+ "minLength": 1,
299
+ "maxLength": 128,
300
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$"
301
+ },
302
+ "toVersionId": {
303
+ "type": "string",
304
+ "minLength": 1,
305
+ "maxLength": 128,
306
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$"
307
+ },
308
+ "gaps": {
309
+ "type": "array",
310
+ "items": { "$ref": "#/$defs/TargetGap" },
311
+ "default": []
312
+ },
313
+ "workPackages": {
314
+ "type": "array",
315
+ "items": { "$ref": "#/$defs/WorkPackage" },
316
+ "default": []
317
+ }
318
+ }
319
+ }
320
+ }
321
+ }