@pdtf/schemas 3.6.0-dev.19 → 3.6.0-dev.21

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.
@@ -0,0 +1,1129 @@
1
+ {
2
+ "mappingVersion": 1,
3
+ "$id": "https://trust.propdata.org.uk/schemas/v4/mapping.json",
4
+ "description": "Generated mapping between PDTF V3 JSON Pointers and V4 entity documents. Do not edit by hand — regenerate with `npm run generate:v4`.",
5
+ "generator": "src/utils/generateV4Schemas.js",
6
+ "source": {
7
+ "packageName": "@pdtf/schemas",
8
+ "packageVersion": "3.6.0-dev.21",
9
+ "v3SchemaId": "https://trust.propdata.org.uk/schemas/v3/pdtf-transaction.json",
10
+ "combinedPath": "src/schemas/v3/combined.json",
11
+ "combinedSha256": "1c6c5812f73a36d3674d5fb7b5eb1f6ce524d09c4195e281e078b9e41ea94f6d"
12
+ },
13
+ "entities": {
14
+ "Property": {
15
+ "$id": "https://trust.propdata.org.uk/schemas/v4/entities/property.json",
16
+ "kind": "derived",
17
+ "idScheme": "urn"
18
+ },
19
+ "Title": {
20
+ "$id": "https://trust.propdata.org.uk/schemas/v4/entities/title.json",
21
+ "kind": "derived",
22
+ "idScheme": "urn"
23
+ },
24
+ "Transaction": {
25
+ "$id": "https://trust.propdata.org.uk/schemas/v4/entities/transaction.json",
26
+ "kind": "derived",
27
+ "idScheme": "did"
28
+ },
29
+ "Person": {
30
+ "$id": "https://trust.propdata.org.uk/schemas/v4/entities/person.json",
31
+ "kind": "derived",
32
+ "idScheme": "did"
33
+ },
34
+ "Organisation": {
35
+ "$id": "https://trust.propdata.org.uk/schemas/v4/entities/organisation.json",
36
+ "kind": "standalone",
37
+ "idScheme": "did"
38
+ },
39
+ "Representation": {
40
+ "$id": "https://trust.propdata.org.uk/schemas/v4/entities/representation.json",
41
+ "kind": "credential",
42
+ "idScheme": "did"
43
+ },
44
+ "TransactionRole": {
45
+ "$id": "https://trust.propdata.org.uk/schemas/v4/entities/transactionRole.json",
46
+ "kind": "credential",
47
+ "idScheme": "did"
48
+ },
49
+ "Gift": {
50
+ "$id": "https://trust.propdata.org.uk/schemas/v4/entities/gift.json",
51
+ "kind": "credential",
52
+ "idScheme": "did"
53
+ },
54
+ "SellerCapacity": {
55
+ "$id": "https://trust.propdata.org.uk/schemas/v4/entities/sellerCapacity.json",
56
+ "kind": "credential",
57
+ "idScheme": "did"
58
+ },
59
+ "Offer": {
60
+ "$id": "https://trust.propdata.org.uk/schemas/v4/entities/offer.json",
61
+ "kind": "credential",
62
+ "idScheme": "did"
63
+ }
64
+ },
65
+ "roundTrip": {
66
+ "entities": [
67
+ "Property",
68
+ "Title",
69
+ "Transaction",
70
+ "Person",
71
+ "Representation",
72
+ "SellerCapacity",
73
+ "Offer",
74
+ "Gift",
75
+ "TransactionRole"
76
+ ],
77
+ "note": "All of these are required to reconstruct a V3 instance. The credentials are not redundant copies: role and every relationship live only on them, so that revoking a credential removes what it asserts rather than leaving a second copy on the transaction. Organisation is the one entity outside the round trip.",
78
+ "roleImpliedByCredential": {
79
+ "SellerCapacity": "Seller",
80
+ "Offer": "Buyer",
81
+ "Gift": "Gift Donor"
82
+ },
83
+ "strippedKeySuffixes": [
84
+ "Ref",
85
+ "Required"
86
+ ],
87
+ "knownExceptions": [
88
+ "Overlay metadata keys (*Ref, *Required) are schema-level only and are stripped from V4; they never appear in instance data.",
89
+ "A Title carrying only keys shared by both source arrays recomposes into propertyPack.titlesToBeSold only (primarySource), not into ownershipsToBeTransferred.",
90
+ "propertyPack.ownership.ownershipsToBeTransferred is canonicalised on recomposition: entries are emitted in propertyPack.titlesToBeSold order rather than their original order. The array is correlated by titleNumber and its order carries no meaning in V3, so this is a deliberate normalisation — it removes the index-divergence class of bug rather than reproducing it. Entry CONTENT is preserved exactly.",
91
+ "An explicitly empty container recomposes as absent: propertyPack {}, propertyPack.ownership {} and propertyPack.titlesToBeSold [] are all valid V3 but carry no data, and the entity model has no place to record 'present but empty'. (participants [] is invalid V3 — minItems 1 — so it does not arise.)",
92
+ "recompose always emits $schema, set to source.v3SchemaId. An instance that omitted it gains one; this is a normalisation, since a V3 instance is expected to declare its schema.",
93
+ "The round trip restores deep equality, NOT byte equality: object key order is not preserved, because keys are regrouped by entity and reassembled. JSON attaches no meaning to key order, but do not compare a recomposed instance to the original by hashing or string equality — compare structurally, or canonicalise first (e.g. JCS) if you need a stable digest."
94
+ ]
95
+ },
96
+ "arrayKeys": [
97
+ {
98
+ "pointer": "/participants",
99
+ "keys": [
100
+ {
101
+ "pointer": "/participantId",
102
+ "scope": "canonical"
103
+ },
104
+ {
105
+ "pointer": "/externalIds/{source}",
106
+ "scope": "vendor"
107
+ }
108
+ ]
109
+ },
110
+ {
111
+ "pointer": "/participants/{index}/verification/identity/reports",
112
+ "keys": [
113
+ {
114
+ "pointer": "/reportName",
115
+ "scope": "canonical"
116
+ }
117
+ ]
118
+ },
119
+ {
120
+ "pointer": "/participants/{index}/verification/antiMoneyLaundering/reports",
121
+ "keys": [
122
+ {
123
+ "pointer": "/reportName",
124
+ "scope": "canonical"
125
+ }
126
+ ]
127
+ },
128
+ {
129
+ "pointer": "/participants/{index}/verification/sourceOfFunds/reports",
130
+ "keys": [
131
+ {
132
+ "pointer": "/reportName",
133
+ "scope": "canonical"
134
+ }
135
+ ]
136
+ },
137
+ {
138
+ "pointer": "/propertyPack/media",
139
+ "keys": [
140
+ {
141
+ "pointer": "/mediaId",
142
+ "scope": "canonical"
143
+ }
144
+ ]
145
+ },
146
+ {
147
+ "pointer": "/propertyPack/buildInformation/roomDimensions/rooms",
148
+ "keys": [
149
+ {
150
+ "pointer": "/roomName",
151
+ "scope": "canonical"
152
+ }
153
+ ]
154
+ },
155
+ {
156
+ "pointer": "/propertyPack/nearbyFacilities/healthCare/{index}/openingHours",
157
+ "keys": [
158
+ {
159
+ "pointer": "/day",
160
+ "scope": "canonical"
161
+ }
162
+ ]
163
+ },
164
+ {
165
+ "pointer": "/propertyPack/ownership/ownershipsToBeTransferred",
166
+ "keys": [
167
+ {
168
+ "pointer": "/titleNumber",
169
+ "scope": "canonical"
170
+ }
171
+ ]
172
+ },
173
+ {
174
+ "pointer": "/propertyPack/energyEfficiency/recommendations",
175
+ "keys": [
176
+ {
177
+ "pointer": "/lmkKey",
178
+ "scope": "canonical"
179
+ }
180
+ ]
181
+ },
182
+ {
183
+ "pointer": "/propertyPack/fixturesAndFittings/basicFittings/otherItems",
184
+ "keys": [
185
+ {
186
+ "pointer": "/itemName",
187
+ "scope": "canonical"
188
+ }
189
+ ]
190
+ },
191
+ {
192
+ "pointer": "/propertyPack/fixturesAndFittings/kitchen/otherItems",
193
+ "keys": [
194
+ {
195
+ "pointer": "/itemName",
196
+ "scope": "canonical"
197
+ }
198
+ ]
199
+ },
200
+ {
201
+ "pointer": "/propertyPack/fixturesAndFittings/carpets/otherRooms",
202
+ "keys": [
203
+ {
204
+ "pointer": "/itemName",
205
+ "scope": "canonical"
206
+ }
207
+ ]
208
+ },
209
+ {
210
+ "pointer": "/propertyPack/fixturesAndFittings/curtainsAndCurtainRails/curtainRailsPolesPelmets/otherRooms",
211
+ "keys": [
212
+ {
213
+ "pointer": "/itemName",
214
+ "scope": "canonical"
215
+ }
216
+ ]
217
+ },
218
+ {
219
+ "pointer": "/propertyPack/fixturesAndFittings/curtainsAndCurtainRails/curtainsBlinds/otherRooms",
220
+ "keys": [
221
+ {
222
+ "pointer": "/itemName",
223
+ "scope": "canonical"
224
+ }
225
+ ]
226
+ },
227
+ {
228
+ "pointer": "/propertyPack/fixturesAndFittings/lightFittings/otherRooms",
229
+ "keys": [
230
+ {
231
+ "pointer": "/itemName",
232
+ "scope": "canonical"
233
+ }
234
+ ]
235
+ },
236
+ {
237
+ "pointer": "/propertyPack/fixturesAndFittings/fittedUnits/otherRooms",
238
+ "keys": [
239
+ {
240
+ "pointer": "/itemName",
241
+ "scope": "canonical"
242
+ }
243
+ ]
244
+ },
245
+ {
246
+ "pointer": "/propertyPack/fixturesAndFittings/outdoorArea/otherItems",
247
+ "keys": [
248
+ {
249
+ "pointer": "/itemName",
250
+ "scope": "canonical"
251
+ }
252
+ ]
253
+ },
254
+ {
255
+ "pointer": "/propertyPack/fixturesAndFittings/otherItems/otherItems",
256
+ "keys": [
257
+ {
258
+ "pointer": "/itemName",
259
+ "scope": "canonical"
260
+ }
261
+ ]
262
+ },
263
+ {
264
+ "pointer": "/propertyPack/environmentalIssues/flooding/floodRisk/riskSubcategories",
265
+ "keys": [
266
+ {
267
+ "pointer": "/subCategory",
268
+ "scope": "canonical"
269
+ }
270
+ ]
271
+ },
272
+ {
273
+ "pointer": "/propertyPack/environmentalIssues/radon/radonRisk/riskSubcategories",
274
+ "keys": [
275
+ {
276
+ "pointer": "/subCategory",
277
+ "scope": "canonical"
278
+ }
279
+ ]
280
+ },
281
+ {
282
+ "pointer": "/propertyPack/environmentalIssues/contaminatedLand/contaminatedLandRisk/riskSubcategories",
283
+ "keys": [
284
+ {
285
+ "pointer": "/subCategory",
286
+ "scope": "canonical"
287
+ }
288
+ ]
289
+ },
290
+ {
291
+ "pointer": "/propertyPack/environmentalIssues/groundStability/groundStabilityRisk/riskSubcategories",
292
+ "keys": [
293
+ {
294
+ "pointer": "/subCategory",
295
+ "scope": "canonical"
296
+ }
297
+ ]
298
+ },
299
+ {
300
+ "pointer": "/propertyPack/environmentalIssues/infrastructure/infrastructureRisk/riskSubcategories",
301
+ "keys": [
302
+ {
303
+ "pointer": "/subCategory",
304
+ "scope": "canonical"
305
+ }
306
+ ]
307
+ },
308
+ {
309
+ "pointer": "/propertyPack/environmentalIssues/energy/energyRisk/riskSubcategories",
310
+ "keys": [
311
+ {
312
+ "pointer": "/subCategory",
313
+ "scope": "canonical"
314
+ }
315
+ ]
316
+ },
317
+ {
318
+ "pointer": "/propertyPack/environmentalIssues/transportation/transportationRisk/riskSubcategories",
319
+ "keys": [
320
+ {
321
+ "pointer": "/subCategory",
322
+ "scope": "canonical"
323
+ }
324
+ ]
325
+ },
326
+ {
327
+ "pointer": "/propertyPack/environmentalIssues/planning/planningRisk/riskSubcategories",
328
+ "keys": [
329
+ {
330
+ "pointer": "/subCategory",
331
+ "scope": "canonical"
332
+ }
333
+ ]
334
+ },
335
+ {
336
+ "pointer": "/propertyPack/environmentalIssues/climate/climateRisk/riskSubcategories",
337
+ "keys": [
338
+ {
339
+ "pointer": "/subCategory",
340
+ "scope": "canonical"
341
+ }
342
+ ]
343
+ },
344
+ {
345
+ "pointer": "/propertyPack/environmentalIssues/coalMining/riskSubcategories",
346
+ "keys": [
347
+ {
348
+ "pointer": "/subCategory",
349
+ "scope": "canonical"
350
+ }
351
+ ]
352
+ },
353
+ {
354
+ "pointer": "/propertyPack/environmentalIssues/nonCoalMining/riskSubcategories",
355
+ "keys": [
356
+ {
357
+ "pointer": "/subCategory",
358
+ "scope": "canonical"
359
+ }
360
+ ]
361
+ },
362
+ {
363
+ "pointer": "/propertyPack/environmentalIssues/coastalErosion/riskSubcategories",
364
+ "keys": [
365
+ {
366
+ "pointer": "/subCategory",
367
+ "scope": "canonical"
368
+ }
369
+ ]
370
+ },
371
+ {
372
+ "pointer": "/propertyPack/guaranteesWarrantiesAndIndemnityInsurances/doubleGlazing/fensaCertificates/certificates",
373
+ "keys": [
374
+ {
375
+ "pointer": "/certificateId",
376
+ "scope": "canonical"
377
+ }
378
+ ]
379
+ },
380
+ {
381
+ "pointer": "/propertyPack/saleReadyDeclarations/sellerSignatures",
382
+ "keys": [
383
+ {
384
+ "pointer": "/signatureId",
385
+ "scope": "canonical"
386
+ },
387
+ {
388
+ "pointer": "/externalIds/{source}",
389
+ "scope": "vendor"
390
+ }
391
+ ]
392
+ },
393
+ {
394
+ "pointer": "/propertyPack/localSearches/localLandCharges",
395
+ "keys": [
396
+ {
397
+ "pointer": "/hmlrReference",
398
+ "scope": "canonical"
399
+ }
400
+ ]
401
+ },
402
+ {
403
+ "pointer": "/propertyPack/localSearches/localLandCharges/{index}/otherData",
404
+ "keys": [
405
+ {
406
+ "pointer": "/dataLabel",
407
+ "scope": "canonical"
408
+ }
409
+ ]
410
+ },
411
+ {
412
+ "pointer": "/propertyPack/localSearches/localAuthoritySearches/planningAndBuildingRegulations/decisionsAndPendingApplications/planningPermission",
413
+ "keys": [
414
+ {
415
+ "pointer": "/refNumber",
416
+ "scope": "canonical"
417
+ }
418
+ ]
419
+ },
420
+ {
421
+ "pointer": "/propertyPack/localSearches/localAuthoritySearches/planningAndBuildingRegulations/decisionsAndPendingApplications/listedBuildingConsent",
422
+ "keys": [
423
+ {
424
+ "pointer": "/refNumber",
425
+ "scope": "canonical"
426
+ }
427
+ ]
428
+ },
429
+ {
430
+ "pointer": "/propertyPack/localSearches/localAuthoritySearches/planningAndBuildingRegulations/decisionsAndPendingApplications/conservationAreaConsent",
431
+ "keys": [
432
+ {
433
+ "pointer": "/refNumber",
434
+ "scope": "canonical"
435
+ }
436
+ ]
437
+ },
438
+ {
439
+ "pointer": "/propertyPack/localSearches/localAuthoritySearches/planningAndBuildingRegulations/decisionsAndPendingApplications/lawfulnessOfExistingUse",
440
+ "keys": [
441
+ {
442
+ "pointer": "/refNumber",
443
+ "scope": "canonical"
444
+ }
445
+ ]
446
+ },
447
+ {
448
+ "pointer": "/propertyPack/localSearches/localAuthoritySearches/planningAndBuildingRegulations/decisionsAndPendingApplications/certificateOfLawfulnessOfProposedUse",
449
+ "keys": [
450
+ {
451
+ "pointer": "/refNumber",
452
+ "scope": "canonical"
453
+ }
454
+ ]
455
+ },
456
+ {
457
+ "pointer": "/propertyPack/localSearches/localAuthoritySearches/planningAndBuildingRegulations/decisionsAndPendingApplications/lawfulnessOfProposedListedWorks",
458
+ "keys": [
459
+ {
460
+ "pointer": "/refNumber",
461
+ "scope": "canonical"
462
+ }
463
+ ]
464
+ },
465
+ {
466
+ "pointer": "/propertyPack/localSearches/localAuthoritySearches/planningAndBuildingRegulations/decisionsAndPendingApplications/heritagePartnershipAgreement",
467
+ "keys": [
468
+ {
469
+ "pointer": "/refNumber",
470
+ "scope": "canonical"
471
+ }
472
+ ]
473
+ },
474
+ {
475
+ "pointer": "/propertyPack/localSearches/localAuthoritySearches/planningAndBuildingRegulations/decisionsAndPendingApplications/listedBuildingConsentOrder",
476
+ "keys": [
477
+ {
478
+ "pointer": "/refNumber",
479
+ "scope": "canonical"
480
+ }
481
+ ]
482
+ },
483
+ {
484
+ "pointer": "/propertyPack/localSearches/localAuthoritySearches/planningAndBuildingRegulations/decisionsAndPendingApplications/localListedBuildingConsentOrder",
485
+ "keys": [
486
+ {
487
+ "pointer": "/refNumber",
488
+ "scope": "canonical"
489
+ }
490
+ ]
491
+ },
492
+ {
493
+ "pointer": "/propertyPack/localSearches/localAuthoritySearches/planningAndBuildingRegulations/decisionsAndPendingApplications/buildingRegulationsApproval",
494
+ "keys": [
495
+ {
496
+ "pointer": "/refNumber",
497
+ "scope": "canonical"
498
+ }
499
+ ]
500
+ },
501
+ {
502
+ "pointer": "/propertyPack/localSearches/localAuthoritySearches/planningAndBuildingRegulations/decisionsAndPendingApplications/buildingRegulationsCompletion",
503
+ "keys": [
504
+ {
505
+ "pointer": "/refNumber",
506
+ "scope": "canonical"
507
+ }
508
+ ]
509
+ },
510
+ {
511
+ "pointer": "/propertyPack/localSearches/localAuthoritySearches/planningAndBuildingRegulations/decisionsAndPendingApplications/buildingRegulationsSelfCertification",
512
+ "keys": [
513
+ {
514
+ "pointer": "/refNumber",
515
+ "scope": "canonical"
516
+ }
517
+ ]
518
+ },
519
+ {
520
+ "pointer": "/propertyPack/titlesToBeSold",
521
+ "keys": [
522
+ {
523
+ "pointer": "/titleNumber",
524
+ "scope": "canonical"
525
+ }
526
+ ]
527
+ },
528
+ {
529
+ "pointer": "/propertyPack/titlesToBeSold/{index}/registerExtract/ocSummaryData/lease/leaseEntry/{index}/leaseParty",
530
+ "keys": [
531
+ {
532
+ "pointer": "/partyNumber",
533
+ "scope": "canonical"
534
+ }
535
+ ]
536
+ },
537
+ {
538
+ "pointer": "/propertyPack/searches",
539
+ "keys": [
540
+ {
541
+ "pointer": "/searchId",
542
+ "scope": "canonical"
543
+ }
544
+ ]
545
+ },
546
+ {
547
+ "pointer": "/propertyPack/documents",
548
+ "keys": [
549
+ {
550
+ "pointer": "/documentId",
551
+ "scope": "canonical"
552
+ },
553
+ {
554
+ "pointer": "/externalIds/{source}",
555
+ "scope": "vendor"
556
+ }
557
+ ]
558
+ },
559
+ {
560
+ "pointer": "/propertyPack/surveys",
561
+ "keys": [
562
+ {
563
+ "pointer": "/surveyId",
564
+ "scope": "canonical"
565
+ }
566
+ ]
567
+ },
568
+ {
569
+ "pointer": "/propertyPack/surveys/{index}/outside/chimneyStacks/photos",
570
+ "keys": [
571
+ {
572
+ "pointer": "/photoId",
573
+ "scope": "canonical"
574
+ }
575
+ ]
576
+ },
577
+ {
578
+ "pointer": "/propertyPack/surveys/{index}/outside/roofCoverings/photos",
579
+ "keys": [
580
+ {
581
+ "pointer": "/photoId",
582
+ "scope": "canonical"
583
+ }
584
+ ]
585
+ },
586
+ {
587
+ "pointer": "/propertyPack/surveys/{index}/outside/rainwaterPipesGutters/photos",
588
+ "keys": [
589
+ {
590
+ "pointer": "/photoId",
591
+ "scope": "canonical"
592
+ }
593
+ ]
594
+ },
595
+ {
596
+ "pointer": "/propertyPack/surveys/{index}/outside/mainWalls/photos",
597
+ "keys": [
598
+ {
599
+ "pointer": "/photoId",
600
+ "scope": "canonical"
601
+ }
602
+ ]
603
+ },
604
+ {
605
+ "pointer": "/propertyPack/surveys/{index}/outside/windows/photos",
606
+ "keys": [
607
+ {
608
+ "pointer": "/photoId",
609
+ "scope": "canonical"
610
+ }
611
+ ]
612
+ },
613
+ {
614
+ "pointer": "/propertyPack/surveys/{index}/outside/outsideDoors/photos",
615
+ "keys": [
616
+ {
617
+ "pointer": "/photoId",
618
+ "scope": "canonical"
619
+ }
620
+ ]
621
+ },
622
+ {
623
+ "pointer": "/propertyPack/surveys/{index}/outside/conservatoryPorches/photos",
624
+ "keys": [
625
+ {
626
+ "pointer": "/photoId",
627
+ "scope": "canonical"
628
+ }
629
+ ]
630
+ },
631
+ {
632
+ "pointer": "/propertyPack/surveys/{index}/outside/otherJoinery/photos",
633
+ "keys": [
634
+ {
635
+ "pointer": "/photoId",
636
+ "scope": "canonical"
637
+ }
638
+ ]
639
+ },
640
+ {
641
+ "pointer": "/propertyPack/surveys/{index}/outside/other/photos",
642
+ "keys": [
643
+ {
644
+ "pointer": "/photoId",
645
+ "scope": "canonical"
646
+ }
647
+ ]
648
+ },
649
+ {
650
+ "pointer": "/propertyPack/surveys/{index}/services/electricity/photos",
651
+ "keys": [
652
+ {
653
+ "pointer": "/photoId",
654
+ "scope": "canonical"
655
+ }
656
+ ]
657
+ },
658
+ {
659
+ "pointer": "/propertyPack/surveys/{index}/services/gasOil/photos",
660
+ "keys": [
661
+ {
662
+ "pointer": "/photoId",
663
+ "scope": "canonical"
664
+ }
665
+ ]
666
+ },
667
+ {
668
+ "pointer": "/propertyPack/surveys/{index}/services/water/photos",
669
+ "keys": [
670
+ {
671
+ "pointer": "/photoId",
672
+ "scope": "canonical"
673
+ }
674
+ ]
675
+ },
676
+ {
677
+ "pointer": "/propertyPack/surveys/{index}/services/heating/photos",
678
+ "keys": [
679
+ {
680
+ "pointer": "/photoId",
681
+ "scope": "canonical"
682
+ }
683
+ ]
684
+ },
685
+ {
686
+ "pointer": "/propertyPack/surveys/{index}/services/waterHeating/photos",
687
+ "keys": [
688
+ {
689
+ "pointer": "/photoId",
690
+ "scope": "canonical"
691
+ }
692
+ ]
693
+ },
694
+ {
695
+ "pointer": "/propertyPack/surveys/{index}/services/drainage/photos",
696
+ "keys": [
697
+ {
698
+ "pointer": "/photoId",
699
+ "scope": "canonical"
700
+ }
701
+ ]
702
+ },
703
+ {
704
+ "pointer": "/propertyPack/surveys/{index}/services/commonServices/photos",
705
+ "keys": [
706
+ {
707
+ "pointer": "/photoId",
708
+ "scope": "canonical"
709
+ }
710
+ ]
711
+ },
712
+ {
713
+ "pointer": "/propertyPack/valuations",
714
+ "keys": [
715
+ {
716
+ "pointer": "/valuationId",
717
+ "scope": "canonical"
718
+ }
719
+ ]
720
+ },
721
+ {
722
+ "pointer": "/valuationComparisonData/propertyDetails",
723
+ "keys": [
724
+ {
725
+ "pointer": "/uprn",
726
+ "scope": "canonical"
727
+ }
728
+ ]
729
+ },
730
+ {
731
+ "pointer": "/contracts",
732
+ "keys": [
733
+ {
734
+ "pointer": "/contractId",
735
+ "scope": "canonical"
736
+ }
737
+ ]
738
+ },
739
+ {
740
+ "pointer": "/contracts/{index}/signatures",
741
+ "keys": [
742
+ {
743
+ "pointer": "/signatureId",
744
+ "scope": "canonical"
745
+ },
746
+ {
747
+ "pointer": "/externalIds/{source}",
748
+ "scope": "vendor"
749
+ }
750
+ ]
751
+ },
752
+ {
753
+ "pointer": "/chain/onwardPurchase",
754
+ "keys": [
755
+ {
756
+ "pointer": "/transactionId",
757
+ "scope": "canonical"
758
+ },
759
+ {
760
+ "pointer": "/externalIds/{source}",
761
+ "scope": "vendor"
762
+ }
763
+ ]
764
+ }
765
+ ],
766
+ "arrayKeyScopes": {
767
+ "canonical": "Lives in the shared payload, so any party holding the transaction can resolve it. This is what claims and credentials should address.",
768
+ "vendor": "A per-source back-reference under externalIds. Resolvable only by a party that knows that source's namespace, and absent entirely on items that source did not write. Use as a fallback, never as the identifier in a credential presented to a third party."
769
+ },
770
+ "unkeyedArrays": {
771
+ "description": "Arrays of objects with no candidate key at all — neither a canonical identifier nor externalIds — so their items can only be addressed by position. Listed so the gap is visible rather than silent. Most are single-source provider payloads replaced wholesale, where position is stable in practice.",
772
+ "pointers": [
773
+ "/propertyPack/buildInformation/higherRiskBuildingRegistration/accountablePersons",
774
+ "/propertyPack/buildInformation/higherRiskBuildingRegistration/accountablePersons/{index}/accountability",
775
+ "/propertyPack/nearbyFacilities/schools",
776
+ "/propertyPack/nearbyFacilities/transport",
777
+ "/propertyPack/nearbyFacilities/healthCare",
778
+ "/propertyPack/legalOwners/namesOfLegalOwners",
779
+ "/propertyPack/localSearches/localLandCharges/{index}/availableDocument",
780
+ "/propertyPack/localSearches/localAuthoritySearches/planningAndBuildingRegulations/designationsAndProposals/plans",
781
+ "/propertyPack/localSearches/localAuthoritySearches/planningAndBuildingRegulations/designationsAndProposals/plans/{index}/designations",
782
+ "/propertyPack/localSearches/localAuthoritySearches/roadsAndPublicRightsOfWay/roadsFootwaysAndFootpaths/highwaysMaintainableAtPublicExpense",
783
+ "/propertyPack/localSearches/localAuthoritySearches/roadsAndPublicRightsOfWay/roadsFootwaysAndFootpaths/subjectToAdoption",
784
+ "/propertyPack/localSearches/localAuthoritySearches/roadsAndPublicRightsOfWay/roadsFootwaysAndFootpaths/toBeMadeUpWithReclaim",
785
+ "/propertyPack/localSearches/localAuthoritySearches/roadsAndPublicRightsOfWay/roadsFootwaysAndFootpaths/toBeMadeUpWithoutReclaim",
786
+ "/propertyPack/titlesToBeSold/{index}/registerExtract/ocSummaryData/lease/leaseEntry",
787
+ "/propertyPack/titlesToBeSold/{index}/additionalDocuments",
788
+ "/valuationComparisonData/propertyDetails/{index}/media",
789
+ "/contracts/{index}/contract/template/requiredSignatories"
790
+ ]
791
+ },
792
+ "projections": {
793
+ "Representation": {
794
+ "description": "A professional representation relationship. Emitted once per (representative, represented party) pair, so a conveyancer instructed jointly by two sellers yields two, and sellers who instruct separate conveyancers yield one each.",
795
+ "source": {
796
+ "entity": "Transaction",
797
+ "pointer": "/participants/{index}"
798
+ },
799
+ "emitWhen": "/actingFor is present and non-empty",
800
+ "fanOut": "/actingFor",
801
+ "resolveBy": "participantId",
802
+ "fields": {
803
+ "representative": "/participants/{index}/participant",
804
+ "representedParty": "/participants/{index}/actingFor/{n} resolved against /participants/*/participantId",
805
+ "role": "/participants/{index}/role",
806
+ "organisation": "/participants/{index}/organisation",
807
+ "organisationReference": "/participants/{index}/organisationReference",
808
+ "transaction": "/id"
809
+ }
810
+ },
811
+ "SellerCapacity": {
812
+ "description": "The capacity in which a seller sells — the relationship that embodies the Seller role. Emitted once per participant whose role is Seller, whether or not a capacity has been declared yet.",
813
+ "source": {
814
+ "entity": "Transaction",
815
+ "pointer": "/participants/{index}"
816
+ },
817
+ "emitWhen": "/role is \"Seller\", or /sellersCapacity is present",
818
+ "fields": {
819
+ "seller": "/participants/{index}/participant",
820
+ "sellersCapacity": "/participants/{index}/sellersCapacity",
821
+ "dateBecameOwnerOrAuthority": "/participants/{index}/dateBecameOwnerOrAuthority",
822
+ "transaction": "/id"
823
+ },
824
+ "notes": "V3 does not tie a seller's capacity to a particular title, so the optional `title` reference is left unset. A transaction selling more than one title therefore yields a capacity scoped to the transaction, not to a title."
825
+ },
826
+ "TransactionRole": {
827
+ "description": "A party's role where no more specific relationship credential applies — Lender, Landlord, Tenant, Gift Donor, Platform Support — or where the specific relationship is not yet established. Emitted so that every participant carrying a role has exactly one credential embodying it.",
828
+ "source": {
829
+ "entity": "Transaction",
830
+ "pointer": "/participants/{index}"
831
+ },
832
+ "emitWhen": "/role is present and no other credential names this participant as its role-bearer",
833
+ "fields": {
834
+ "participant": "/participants/{index}/participant",
835
+ "role": "/participants/{index}/role",
836
+ "organisation": "/participants/{index}/organisation",
837
+ "organisationReference": "/participants/{index}/organisationReference",
838
+ "transaction": "/id"
839
+ }
840
+ },
841
+ "Offer": {
842
+ "description": "An offer made by a prospective buyer — the relationship that embodies the Buyer role. Emitted once per participant carrying an offerId, merged with that offer's data from Transaction.offers.",
843
+ "source": {
844
+ "entity": "Transaction",
845
+ "pointer": "/participants/{index}"
846
+ },
847
+ "emitWhen": "/offerId is present",
848
+ "fields": {
849
+ "offerId": "/participants/{index}/offerId",
850
+ "buyer": "/participants/{index}/participant",
851
+ "…": "the remaining fields from /offers/{offerId}",
852
+ "transaction": "/id"
853
+ },
854
+ "notes": "An offer in Transaction.offers that no participant references stays transaction data and yields no credential, since Offer requires a buyer."
855
+ }
856
+ },
857
+ "collisions": [
858
+ {
859
+ "key": "titleNumber",
860
+ "entity": "Title",
861
+ "sources": [
862
+ "/propertyPack/titlesToBeSold/{index}/titleNumber",
863
+ "/propertyPack/ownership/ownershipsToBeTransferred/{index}/titleNumber"
864
+ ],
865
+ "rule": "same-fact",
866
+ "resolution": "Identical fact in both sources and the key that correlates them. Decomposition takes either; recomposition writes the value back to every source array it emits an entry for."
867
+ }
868
+ ],
869
+ "rules": [
870
+ {
871
+ "id": "title.titlesToBeSold",
872
+ "v3Pointer": "/propertyPack/titlesToBeSold/{index}",
873
+ "entity": "Title",
874
+ "entityPointer": "",
875
+ "keys": {
876
+ "mode": "include",
877
+ "values": [
878
+ "titleNumber",
879
+ "titleExtents",
880
+ "registerExtract",
881
+ "additionalDocuments",
882
+ "keyFacts",
883
+ "covenantAnalysis"
884
+ ]
885
+ },
886
+ "instance": {
887
+ "cardinality": "many",
888
+ "orderedBy": {
889
+ "entity": "Transaction",
890
+ "pointer": "/titlesToBeSold"
891
+ },
892
+ "correlateBy": "titleNumber",
893
+ "primarySource": true
894
+ },
895
+ "notes": "Primary source: a Title carrying only shared keys recomposes to this array."
896
+ },
897
+ {
898
+ "id": "title.ownershipsToBeTransferred",
899
+ "v3Pointer": "/propertyPack/ownership/ownershipsToBeTransferred/{index}",
900
+ "entity": "Title",
901
+ "entityPointer": "",
902
+ "keys": {
903
+ "mode": "include",
904
+ "values": [
905
+ "titleNumber",
906
+ "titlePropertyDescription",
907
+ "ownershipType",
908
+ "estateRentcharges",
909
+ "titleRestrictions",
910
+ "wholeFreeholdForSale",
911
+ "managedFreeholdOrCommonholdInformation",
912
+ "leaseholdInformation",
913
+ "otherOwnershipDetails"
914
+ ]
915
+ },
916
+ "instance": {
917
+ "cardinality": "many",
918
+ "orderedBy": {
919
+ "entity": "Transaction",
920
+ "pointer": "/titlesToBeSold"
921
+ },
922
+ "correlateBy": "titleNumber",
923
+ "primarySource": false
924
+ },
925
+ "notes": "Indices of the two source arrays are NOT assumed to correspond; they are correlated by titleNumber value."
926
+ },
927
+ {
928
+ "id": "transaction.saleContext.legalOwners",
929
+ "v3Pointer": "/propertyPack/legalOwners",
930
+ "entity": "Transaction",
931
+ "entityPointer": "/saleContext/legalOwners",
932
+ "instance": {
933
+ "cardinality": "single"
934
+ }
935
+ },
936
+ {
937
+ "id": "transaction.saleContext",
938
+ "v3Pointer": "/propertyPack/ownership",
939
+ "entity": "Transaction",
940
+ "entityPointer": "/saleContext",
941
+ "keys": {
942
+ "mode": "exclude",
943
+ "values": [
944
+ "ownershipsToBeTransferred"
945
+ ]
946
+ },
947
+ "instance": {
948
+ "cardinality": "single"
949
+ }
950
+ },
951
+ {
952
+ "id": "property",
953
+ "v3Pointer": "/propertyPack",
954
+ "entity": "Property",
955
+ "entityPointer": "",
956
+ "keys": {
957
+ "mode": "exclude",
958
+ "values": [
959
+ "titlesToBeSold",
960
+ "ownership",
961
+ "legalOwners"
962
+ ]
963
+ },
964
+ "instance": {
965
+ "cardinality": "single"
966
+ }
967
+ },
968
+ {
969
+ "id": "transaction.participants",
970
+ "v3Pointer": "/participants/{index}",
971
+ "entity": "Transaction",
972
+ "entityPointer": "/participants/{index}",
973
+ "keys": {
974
+ "mode": "include",
975
+ "values": [
976
+ "did",
977
+ "participantId",
978
+ "organisation",
979
+ "organisationReference"
980
+ ]
981
+ },
982
+ "instance": {
983
+ "cardinality": "many",
984
+ "orderedBy": {
985
+ "entity": "Transaction",
986
+ "pointer": "/participants"
987
+ }
988
+ },
989
+ "notes": "The roster only: transaction-scoped identity and firm. The entity reference itself is at /participants/{index}/participant."
990
+ },
991
+ {
992
+ "id": "credential.sellerCapacity",
993
+ "v3Pointer": "/participants/{index}",
994
+ "entity": "SellerCapacity",
995
+ "entityPointer": "",
996
+ "keys": {
997
+ "mode": "include",
998
+ "values": [
999
+ "sellersCapacity",
1000
+ "dateBecameOwnerOrAuthority"
1001
+ ]
1002
+ },
1003
+ "instance": {
1004
+ "cardinality": "many",
1005
+ "matchOn": "/seller"
1006
+ },
1007
+ "impliesRole": "Seller"
1008
+ },
1009
+ {
1010
+ "id": "credential.offer",
1011
+ "v3Pointer": "/participants/{index}",
1012
+ "entity": "Offer",
1013
+ "entityPointer": "",
1014
+ "keys": {
1015
+ "mode": "include",
1016
+ "values": [
1017
+ "offerId"
1018
+ ]
1019
+ },
1020
+ "instance": {
1021
+ "cardinality": "many",
1022
+ "matchOn": "/buyer"
1023
+ },
1024
+ "impliesRole": "Buyer"
1025
+ },
1026
+ {
1027
+ "id": "credential.gift",
1028
+ "v3Pointer": "/participants/{index}",
1029
+ "entity": "Gift",
1030
+ "entityPointer": "",
1031
+ "keys": {
1032
+ "mode": "include",
1033
+ "values": [
1034
+ "giftDetails",
1035
+ "offerId"
1036
+ ]
1037
+ },
1038
+ "instance": {
1039
+ "cardinality": "many",
1040
+ "matchOn": "/donor"
1041
+ },
1042
+ "impliesRole": "Gift Donor"
1043
+ },
1044
+ {
1045
+ "id": "credential.representation",
1046
+ "v3Pointer": "/participants/{index}",
1047
+ "entity": "Representation",
1048
+ "entityPointer": "",
1049
+ "keys": {
1050
+ "mode": "include",
1051
+ "values": [
1052
+ "role",
1053
+ "actingFor"
1054
+ ]
1055
+ },
1056
+ "fieldMap": {
1057
+ "role": "/role",
1058
+ "actingFor": "/representedParty"
1059
+ },
1060
+ "instance": {
1061
+ "cardinality": "many",
1062
+ "matchOn": "/representative"
1063
+ },
1064
+ "notes": "actingFor becomes one Representation per represented party; its role is the credential's own discriminator."
1065
+ },
1066
+ {
1067
+ "id": "credential.transactionRole",
1068
+ "v3Pointer": "/participants/{index}",
1069
+ "entity": "TransactionRole",
1070
+ "entityPointer": "",
1071
+ "keys": {
1072
+ "mode": "include",
1073
+ "values": [
1074
+ "role"
1075
+ ]
1076
+ },
1077
+ "instance": {
1078
+ "cardinality": "many",
1079
+ "matchOn": "/participant"
1080
+ },
1081
+ "notes": "Carries role for the roles no specific credential covers, and for a party whose specific relationship is not yet established."
1082
+ },
1083
+ {
1084
+ "id": "person",
1085
+ "v3Pointer": "/participants/{index}",
1086
+ "entity": "Person",
1087
+ "entityPointer": "",
1088
+ "keys": {
1089
+ "mode": "include",
1090
+ "values": [
1091
+ "name",
1092
+ "dateOfBirth",
1093
+ "phone",
1094
+ "email",
1095
+ "address",
1096
+ "did",
1097
+ "externalIds",
1098
+ "participantStatus",
1099
+ "verification"
1100
+ ]
1101
+ },
1102
+ "instance": {
1103
+ "cardinality": "many",
1104
+ "orderedBy": {
1105
+ "entity": "Transaction",
1106
+ "pointer": "/participants",
1107
+ "idField": "participant"
1108
+ }
1109
+ }
1110
+ },
1111
+ {
1112
+ "id": "transaction",
1113
+ "v3Pointer": "",
1114
+ "entity": "Transaction",
1115
+ "entityPointer": "",
1116
+ "keys": {
1117
+ "mode": "exclude",
1118
+ "values": [
1119
+ "propertyPack",
1120
+ "participants",
1121
+ "$schema"
1122
+ ]
1123
+ },
1124
+ "instance": {
1125
+ "cardinality": "single"
1126
+ }
1127
+ }
1128
+ ]
1129
+ }