@mdbase-dev/connect-protocol 0.1.0-beta.30 → 0.1.0-beta.32

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.
@@ -1,8 +1,9 @@
1
1
  import type { ApplicationFileRequirement } from "./files.js";
2
2
  import type { CollectionOperation } from "./operations.js";
3
+ import type { ConnectContractRequirements } from "./compatibility.js";
3
4
  export type ApplicationAuthorizationFlow = "authorization_code" | "device_code";
4
5
  export interface ApplicationAuthorizationBinding {
5
- protocol_version: 2;
6
+ protocol_version: 3;
6
7
  authorization_id: string;
7
8
  application_id: string;
8
9
  application_manifest_digest: string;
@@ -17,6 +18,7 @@ export interface ApplicationAuthorizationBinding {
17
18
  redirect_uri?: string;
18
19
  state?: string;
19
20
  code_challenge: string;
21
+ contracts: ConnectContractRequirements;
20
22
  requested_operations: CollectionOperation[];
21
23
  requested_files?: ApplicationFileRequirement;
22
24
  collection_id?: string;
@@ -1,5 +1,5 @@
1
1
  const INSTALLATION_ID_DOMAIN = new TextEncoder().encode("mdbase-connect application installation id v2\0");
2
- const AUTHORIZATION_PROOF_DOMAIN = new TextEncoder().encode("mdbase-connect application authorization proof v2\0");
2
+ const AUTHORIZATION_PROOF_DOMAIN = new TextEncoder().encode("mdbase-connect application authorization proof v3\0");
3
3
  export async function applicationInstallationIdFromPublicKey(signingPublicKey) {
4
4
  const signing = publicKey(signingPublicKey);
5
5
  const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", concat([INSTALLATION_ID_DOMAIN, field(signing)])));
@@ -25,12 +25,19 @@ export function authorizationSigningMessage(binding) {
25
25
  }
26
26
  const nonce = canonicalBase64(binding.authorization_nonce);
27
27
  const challenge = canonicalBase64(binding.code_challenge);
28
- if (binding.protocol_version !== 2
28
+ const contracts = binding.contracts;
29
+ if (binding.protocol_version !== 3
29
30
  || nonce.byteLength !== 32
30
31
  || !/^[0-9a-f]{64}$/u.test(binding.application_manifest_digest)
31
32
  || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?Z$/u.test(binding.issued_at)
32
33
  || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?Z$/u.test(binding.expires_at)
33
34
  || challenge.byteLength !== 32
35
+ || ![
36
+ contracts.operation_transport,
37
+ contracts.authorization_binding,
38
+ contracts.semantic_capabilities,
39
+ contracts.durable_mutation ?? 1
40
+ ].every((version) => Number.isInteger(version) && version > 0)
34
41
  || (binding.requested_operations.length === 0 && binding.requested_files === undefined)
35
42
  || new Set(binding.requested_operations).size !== binding.requested_operations.length
36
43
  || binding.requested_operations.some((operation) => !operation || operation.includes("\0"))
@@ -58,12 +65,21 @@ export function authorizationSigningMessage(binding) {
58
65
  optionalString(binding.redirect_uri),
59
66
  optionalString(binding.state),
60
67
  field(new TextEncoder().encode(binding.code_challenge)),
68
+ u32(contracts.operation_transport),
69
+ u32(contracts.authorization_binding),
70
+ u32(contracts.semantic_capabilities),
71
+ optionalU32(contracts.durable_mutation),
61
72
  u32(operationFields.length),
62
73
  ...operationFields,
63
74
  requestedFiles(binding.requested_files),
64
75
  optionalUuid(binding.collection_id)
65
76
  ]);
66
77
  }
78
+ function optionalU32(value) {
79
+ return value === undefined
80
+ ? new Uint8Array(1)
81
+ : concat([new Uint8Array([1]), u32(value)]);
82
+ }
67
83
  function validateRequestedFiles(files) {
68
84
  if (files === undefined)
69
85
  return;
@@ -78,7 +94,7 @@ function validateRequestedFiles(files) {
78
94
  }
79
95
  function requestedFiles(files) {
80
96
  if (files === undefined)
81
- return new Uint8Array([0]);
97
+ return new Uint8Array(1);
82
98
  const actions = files.actions.map((action) => field(new TextEncoder().encode(action)));
83
99
  return concat([
84
100
  new Uint8Array([1]),
@@ -95,12 +111,12 @@ function requestedFiles(files) {
95
111
  }
96
112
  function optionalString(value) {
97
113
  return value === undefined
98
- ? new Uint8Array([0])
114
+ ? new Uint8Array(1)
99
115
  : concat([new Uint8Array([1]), field(new TextEncoder().encode(value))]);
100
116
  }
101
117
  function optionalUuid(value) {
102
118
  return value === undefined
103
- ? new Uint8Array([0])
119
+ ? new Uint8Array(1)
104
120
  : concat([new Uint8Array([1]), field(uuidBytes(value))]);
105
121
  }
106
122
  function publicKey(value) {
@@ -0,0 +1,26 @@
1
+ import type { ApplicationFileRequirement } from "./files.js";
2
+ import { type CollectionOperation } from "./operations.js";
3
+ export declare const OPERATION_TRANSPORT_PROTOCOL_VERSION: 2;
4
+ export declare const AUTHORIZATION_BINDING_PROTOCOL_VERSION: 3;
5
+ export declare const SEMANTIC_CAPABILITY_CONTRACT_VERSION: 1;
6
+ export declare const DURABLE_MUTATION_CONTRACT_VERSION: 1;
7
+ export interface ConnectContractRequirements {
8
+ operation_transport: number;
9
+ authorization_binding: number;
10
+ semantic_capabilities: number;
11
+ /** Required only by operations that can durably mutate authority state. */
12
+ durable_mutation?: number;
13
+ }
14
+ export interface ConnectContractSupport {
15
+ operation_transport: number[];
16
+ authorization_binding: number[];
17
+ semantic_capabilities: number[];
18
+ durable_mutation: number[];
19
+ }
20
+ export declare const CONNECT_CONTRACT_SUPPORT: ConnectContractSupport;
21
+ /**
22
+ * Produce the exact contract ceiling signed during authorization. `sync` is
23
+ * conservatively mutation-capable because its action is selected per request.
24
+ */
25
+ export declare function authorizationContractRequirements(operations: readonly CollectionOperation[], files?: ApplicationFileRequirement): ConnectContractRequirements;
26
+ export declare function supportsContractRequirements(required: ConnectContractRequirements, supported: ConnectContractSupport, durableMutation: boolean): boolean;
@@ -0,0 +1,35 @@
1
+ import { isMutatingOperation } from "./operations.js";
2
+ export const OPERATION_TRANSPORT_PROTOCOL_VERSION = 2;
3
+ export const AUTHORIZATION_BINDING_PROTOCOL_VERSION = 3;
4
+ export const SEMANTIC_CAPABILITY_CONTRACT_VERSION = 1;
5
+ export const DURABLE_MUTATION_CONTRACT_VERSION = 1;
6
+ export const CONNECT_CONTRACT_SUPPORT = {
7
+ operation_transport: [OPERATION_TRANSPORT_PROTOCOL_VERSION],
8
+ authorization_binding: [AUTHORIZATION_BINDING_PROTOCOL_VERSION],
9
+ semantic_capabilities: [SEMANTIC_CAPABILITY_CONTRACT_VERSION],
10
+ durable_mutation: [DURABLE_MUTATION_CONTRACT_VERSION]
11
+ };
12
+ /**
13
+ * Produce the exact contract ceiling signed during authorization. `sync` is
14
+ * conservatively mutation-capable because its action is selected per request.
15
+ */
16
+ export function authorizationContractRequirements(operations, files) {
17
+ const requirements = {
18
+ operation_transport: OPERATION_TRANSPORT_PROTOCOL_VERSION,
19
+ authorization_binding: AUTHORIZATION_BINDING_PROTOCOL_VERSION,
20
+ semantic_capabilities: 1
21
+ };
22
+ if (operations.some((operation) => isMutatingOperation(operation, { action: "mutate" }))
23
+ || files?.actions.some((action) => action !== "list" && action !== "read") === true) {
24
+ requirements.durable_mutation = 1;
25
+ }
26
+ return requirements;
27
+ }
28
+ export function supportsContractRequirements(required, supported, durableMutation) {
29
+ return supported.operation_transport.includes(required.operation_transport)
30
+ && supported.authorization_binding.includes(required.authorization_binding)
31
+ && supported.semantic_capabilities.includes(required.semantic_capabilities)
32
+ && (!durableMutation
33
+ || (required.durable_mutation !== undefined
34
+ && supported.durable_mutation.includes(required.durable_mutation)));
35
+ }
@@ -20,6 +20,10 @@ export declare const CONNECT_PROBLEM_CATALOG: {
20
20
  readonly category: "authorization";
21
21
  readonly recovery: "reauthorize";
22
22
  };
23
+ readonly authorization_binding_incompatible: {
24
+ readonly category: "compatibility";
25
+ readonly recovery: "upgrade_application";
26
+ };
23
27
  readonly authorization_cancelled: {
24
28
  readonly category: "cancellation";
25
29
  readonly recovery: "none";
@@ -40,6 +44,10 @@ export declare const CONNECT_PROBLEM_CATALOG: {
40
44
  readonly category: "validation";
41
45
  readonly recovery: "fix_request";
42
46
  };
47
+ readonly capability_contract_incompatible: {
48
+ readonly category: "compatibility";
49
+ readonly recovery: "upgrade_application";
50
+ };
43
51
  readonly change_cursor_reset: {
44
52
  readonly category: "conflict";
45
53
  readonly recovery: "refresh";
@@ -120,6 +128,10 @@ export declare const CONNECT_PROBLEM_CATALOG: {
120
128
  readonly category: "availability";
121
129
  readonly recovery: "retry";
122
130
  };
131
+ readonly durable_mutation_unsupported: {
132
+ readonly category: "compatibility";
133
+ readonly recovery: "upgrade_connector";
134
+ };
123
135
  readonly encrypted_relay_rejected: {
124
136
  readonly category: "authorization";
125
137
  readonly recovery: "reauthorize";
@@ -240,6 +252,14 @@ export declare const CONNECT_PROBLEM_CATALOG: {
240
252
  readonly category: "authorization";
241
253
  readonly recovery: "reauthorize";
242
254
  };
255
+ readonly mutation_recovery_expired: {
256
+ readonly category: "compatibility";
257
+ readonly recovery: "none";
258
+ };
259
+ readonly mutation_request_conflict: {
260
+ readonly category: "conflict";
261
+ readonly recovery: "resolve_conflict";
262
+ };
243
263
  readonly no_pending_mutation: {
244
264
  readonly category: "conflict";
245
265
  readonly recovery: "refresh";
@@ -320,6 +340,26 @@ export declare const CONNECT_PROBLEM_CATALOG: {
320
340
  readonly category: "compatibility";
321
341
  readonly recovery: "fix_request";
322
342
  };
343
+ readonly registry_backup_invalid: {
344
+ readonly category: "integrity";
345
+ readonly recovery: "contact_support";
346
+ };
347
+ readonly registry_busy: {
348
+ readonly category: "availability";
349
+ readonly recovery: "retry";
350
+ };
351
+ readonly registry_corrupt: {
352
+ readonly category: "integrity";
353
+ readonly recovery: "repair_collection";
354
+ };
355
+ readonly registry_migration_failed: {
356
+ readonly category: "internal";
357
+ readonly recovery: "contact_support";
358
+ };
359
+ readonly registry_schema_incompatible: {
360
+ readonly category: "compatibility";
361
+ readonly recovery: "upgrade_connector";
362
+ };
323
363
  readonly relay_authorization_expired: {
324
364
  readonly category: "authorization";
325
365
  readonly recovery: "reauthorize";
@@ -360,6 +400,10 @@ export declare const CONNECT_PROBLEM_CATALOG: {
360
400
  readonly category: "availability";
361
401
  readonly recovery: "retry";
362
402
  };
403
+ readonly transport_protocol_incompatible: {
404
+ readonly category: "compatibility";
405
+ readonly recovery: "upgrade_connector";
406
+ };
363
407
  readonly type_pack_provision_failed: {
364
408
  readonly category: "validation";
365
409
  readonly recovery: "repair_collection";
@@ -405,11 +449,25 @@ export interface ConnectProblemDetailsByCode {
405
449
  "interval_seconds": number;
406
450
  };
407
451
  "authority_authorization_changed": undefined;
452
+ "authorization_binding_incompatible": {
453
+ "contract": string;
454
+ "required": Array<number>;
455
+ "supported": Array<number>;
456
+ "peer": string;
457
+ "operation"?: string;
458
+ };
408
459
  "authorization_cancelled": undefined;
409
460
  "authorization_expired": undefined;
410
461
  "authorization_replayed": undefined;
411
462
  "browser_required": undefined;
412
463
  "callback_url_required": undefined;
464
+ "capability_contract_incompatible": {
465
+ "contract": string;
466
+ "required": Array<number>;
467
+ "supported": Array<number>;
468
+ "peer": string;
469
+ "operation"?: string;
470
+ };
413
471
  "change_cursor_reset": undefined;
414
472
  "collection_access_denied": undefined;
415
473
  "collection_configuration_invalid": {
@@ -446,6 +504,13 @@ export interface ConnectProblemDetailsByCode {
446
504
  "device_authorization_failed": undefined;
447
505
  "direct_operation_rejected": undefined;
448
506
  "discovery_failed": undefined;
507
+ "durable_mutation_unsupported": {
508
+ "contract": string;
509
+ "required": Array<number>;
510
+ "supported": Array<number>;
511
+ "peer": string;
512
+ "operation"?: string;
513
+ };
449
514
  "encrypted_relay_rejected": undefined;
450
515
  "encryption_required": undefined;
451
516
  "expired_token": undefined;
@@ -487,6 +552,10 @@ export interface ConnectProblemDetailsByCode {
487
552
  "manifest_load_failed": undefined;
488
553
  "manifest_required": undefined;
489
554
  "missing_grant_key": undefined;
555
+ "mutation_recovery_expired": undefined;
556
+ "mutation_request_conflict": {
557
+ "request_id": string;
558
+ };
490
559
  "no_pending_mutation": undefined;
491
560
  "not_authorized": undefined;
492
561
  "not_remote_authority": undefined;
@@ -502,7 +571,9 @@ export interface ConnectProblemDetailsByCode {
502
571
  "diagnostics": Array<Record<string, unknown>>;
503
572
  "partial_result"?: unknown;
504
573
  };
505
- "operation_outcome_unknown": undefined;
574
+ "operation_outcome_unknown": {
575
+ "request_id": string;
576
+ };
506
577
  "path_occupied": undefined;
507
578
  "pending_mutation_unresolved": undefined;
508
579
  "query_snapshot_changed": undefined;
@@ -512,6 +583,11 @@ export interface ConnectProblemDetailsByCode {
512
583
  "reconnect_required": undefined;
513
584
  "redirect_uri_required": undefined;
514
585
  "reference_updates_unsupported": undefined;
586
+ "registry_backup_invalid": undefined;
587
+ "registry_busy": undefined;
588
+ "registry_corrupt": undefined;
589
+ "registry_migration_failed": undefined;
590
+ "registry_schema_incompatible": undefined;
515
591
  "relay_authorization_expired": undefined;
516
592
  "relay_unavailable": undefined;
517
593
  "sandbox_unsupported": undefined;
@@ -522,6 +598,13 @@ export interface ConnectProblemDetailsByCode {
522
598
  "temporarily_unavailable": undefined;
523
599
  "timeout": undefined;
524
600
  "token_exchange_failed": undefined;
601
+ "transport_protocol_incompatible": {
602
+ "contract": string;
603
+ "required": Array<number>;
604
+ "supported": Array<number>;
605
+ "peer": string;
606
+ "operation"?: string;
607
+ };
525
608
  "type_pack_provision_failed": undefined;
526
609
  "unknown_collection": undefined;
527
610
  "unsafe_file_path": undefined;
@@ -559,6 +642,12 @@ export interface ConnectProblemByCode {
559
642
  recovery: "reauthorize";
560
643
  details?: never;
561
644
  };
645
+ "authorization_binding_incompatible": ConnectProblemBase & {
646
+ code: "authorization_binding_incompatible";
647
+ category: "compatibility";
648
+ recovery: "upgrade_application";
649
+ details: ConnectProblemDetailsByCode["authorization_binding_incompatible"];
650
+ };
562
651
  "authorization_cancelled": ConnectProblemBase & {
563
652
  code: "authorization_cancelled";
564
653
  category: "cancellation";
@@ -589,6 +678,12 @@ export interface ConnectProblemByCode {
589
678
  recovery: "fix_request";
590
679
  details?: never;
591
680
  };
681
+ "capability_contract_incompatible": ConnectProblemBase & {
682
+ code: "capability_contract_incompatible";
683
+ category: "compatibility";
684
+ recovery: "upgrade_application";
685
+ details: ConnectProblemDetailsByCode["capability_contract_incompatible"];
686
+ };
592
687
  "change_cursor_reset": ConnectProblemBase & {
593
688
  code: "change_cursor_reset";
594
689
  category: "conflict";
@@ -709,6 +804,12 @@ export interface ConnectProblemByCode {
709
804
  recovery: "retry";
710
805
  details?: never;
711
806
  };
807
+ "durable_mutation_unsupported": ConnectProblemBase & {
808
+ code: "durable_mutation_unsupported";
809
+ category: "compatibility";
810
+ recovery: "upgrade_connector";
811
+ details: ConnectProblemDetailsByCode["durable_mutation_unsupported"];
812
+ };
712
813
  "encrypted_relay_rejected": ConnectProblemBase & {
713
814
  code: "encrypted_relay_rejected";
714
815
  category: "authorization";
@@ -889,6 +990,18 @@ export interface ConnectProblemByCode {
889
990
  recovery: "reauthorize";
890
991
  details?: never;
891
992
  };
993
+ "mutation_recovery_expired": ConnectProblemBase & {
994
+ code: "mutation_recovery_expired";
995
+ category: "compatibility";
996
+ recovery: "none";
997
+ details?: never;
998
+ };
999
+ "mutation_request_conflict": ConnectProblemBase & {
1000
+ code: "mutation_request_conflict";
1001
+ category: "conflict";
1002
+ recovery: "resolve_conflict";
1003
+ details: ConnectProblemDetailsByCode["mutation_request_conflict"];
1004
+ };
892
1005
  "no_pending_mutation": ConnectProblemBase & {
893
1006
  code: "no_pending_mutation";
894
1007
  category: "conflict";
@@ -965,7 +1078,7 @@ export interface ConnectProblemByCode {
965
1078
  code: "operation_outcome_unknown";
966
1079
  category: "conflict";
967
1080
  recovery: "resolve_outcome";
968
- details?: never;
1081
+ details: ConnectProblemDetailsByCode["operation_outcome_unknown"];
969
1082
  };
970
1083
  "path_occupied": ConnectProblemBase & {
971
1084
  code: "path_occupied";
@@ -1009,6 +1122,36 @@ export interface ConnectProblemByCode {
1009
1122
  recovery: "fix_request";
1010
1123
  details?: never;
1011
1124
  };
1125
+ "registry_backup_invalid": ConnectProblemBase & {
1126
+ code: "registry_backup_invalid";
1127
+ category: "integrity";
1128
+ recovery: "contact_support";
1129
+ details?: never;
1130
+ };
1131
+ "registry_busy": ConnectProblemBase & {
1132
+ code: "registry_busy";
1133
+ category: "availability";
1134
+ recovery: "retry";
1135
+ details?: never;
1136
+ };
1137
+ "registry_corrupt": ConnectProblemBase & {
1138
+ code: "registry_corrupt";
1139
+ category: "integrity";
1140
+ recovery: "repair_collection";
1141
+ details?: never;
1142
+ };
1143
+ "registry_migration_failed": ConnectProblemBase & {
1144
+ code: "registry_migration_failed";
1145
+ category: "internal";
1146
+ recovery: "contact_support";
1147
+ details?: never;
1148
+ };
1149
+ "registry_schema_incompatible": ConnectProblemBase & {
1150
+ code: "registry_schema_incompatible";
1151
+ category: "compatibility";
1152
+ recovery: "upgrade_connector";
1153
+ details?: never;
1154
+ };
1012
1155
  "relay_authorization_expired": ConnectProblemBase & {
1013
1156
  code: "relay_authorization_expired";
1014
1157
  category: "authorization";
@@ -1069,6 +1212,12 @@ export interface ConnectProblemByCode {
1069
1212
  recovery: "retry";
1070
1213
  details?: never;
1071
1214
  };
1215
+ "transport_protocol_incompatible": ConnectProblemBase & {
1216
+ code: "transport_protocol_incompatible";
1217
+ category: "compatibility";
1218
+ recovery: "upgrade_connector";
1219
+ details: ConnectProblemDetailsByCode["transport_protocol_incompatible"];
1220
+ };
1072
1221
  "type_pack_provision_failed": ConnectProblemBase & {
1073
1222
  code: "type_pack_provision_failed";
1074
1223
  category: "validation";
@@ -6,11 +6,13 @@ export const CONNECT_PROBLEM_CATALOG = {
6
6
  "application_identity_unavailable": { category: "compatibility", recovery: "upgrade_application" },
7
7
  "approval_window_blocked": { category: "authorization", recovery: "reauthorize" },
8
8
  "authority_authorization_changed": { category: "authorization", recovery: "reauthorize" },
9
+ "authorization_binding_incompatible": { category: "compatibility", recovery: "upgrade_application" },
9
10
  "authorization_cancelled": { category: "cancellation", recovery: "none" },
10
11
  "authorization_expired": { category: "authorization", recovery: "reauthorize" },
11
12
  "authorization_replayed": { category: "integrity", recovery: "reauthorize" },
12
13
  "browser_required": { category: "compatibility", recovery: "none" },
13
14
  "callback_url_required": { category: "validation", recovery: "fix_request" },
15
+ "capability_contract_incompatible": { category: "compatibility", recovery: "upgrade_application" },
14
16
  "change_cursor_reset": { category: "conflict", recovery: "refresh" },
15
17
  "collection_access_denied": { category: "authorization", recovery: "reauthorize" },
16
18
  "collection_configuration_invalid": { category: "validation", recovery: "repair_collection" },
@@ -31,6 +33,7 @@ export const CONNECT_PROBLEM_CATALOG = {
31
33
  "device_authorization_failed": { category: "authorization", recovery: "reauthorize" },
32
34
  "direct_operation_rejected": { category: "authorization", recovery: "reauthorize" },
33
35
  "discovery_failed": { category: "availability", recovery: "retry" },
36
+ "durable_mutation_unsupported": { category: "compatibility", recovery: "upgrade_connector" },
34
37
  "encrypted_relay_rejected": { category: "authorization", recovery: "reauthorize" },
35
38
  "encryption_required": { category: "authorization", recovery: "reauthorize" },
36
39
  "expired_token": { category: "authorization", recovery: "reauthorize" },
@@ -61,6 +64,8 @@ export const CONNECT_PROBLEM_CATALOG = {
61
64
  "manifest_load_failed": { category: "availability", recovery: "retry" },
62
65
  "manifest_required": { category: "validation", recovery: "fix_request" },
63
66
  "missing_grant_key": { category: "authorization", recovery: "reauthorize" },
67
+ "mutation_recovery_expired": { category: "compatibility", recovery: "none" },
68
+ "mutation_request_conflict": { category: "conflict", recovery: "resolve_conflict" },
64
69
  "no_pending_mutation": { category: "conflict", recovery: "refresh" },
65
70
  "not_authorized": { category: "authorization", recovery: "reauthorize" },
66
71
  "not_remote_authority": { category: "compatibility", recovery: "choose_collection" },
@@ -81,6 +86,11 @@ export const CONNECT_PROBLEM_CATALOG = {
81
86
  "reconnect_required": { category: "authorization", recovery: "reauthorize" },
82
87
  "redirect_uri_required": { category: "validation", recovery: "fix_request" },
83
88
  "reference_updates_unsupported": { category: "compatibility", recovery: "fix_request" },
89
+ "registry_backup_invalid": { category: "integrity", recovery: "contact_support" },
90
+ "registry_busy": { category: "availability", recovery: "retry" },
91
+ "registry_corrupt": { category: "integrity", recovery: "repair_collection" },
92
+ "registry_migration_failed": { category: "internal", recovery: "contact_support" },
93
+ "registry_schema_incompatible": { category: "compatibility", recovery: "upgrade_connector" },
84
94
  "relay_authorization_expired": { category: "authorization", recovery: "reauthorize" },
85
95
  "relay_unavailable": { category: "availability", recovery: "retry" },
86
96
  "sandbox_unsupported": { category: "compatibility", recovery: "fix_request" },
@@ -91,6 +101,7 @@ export const CONNECT_PROBLEM_CATALOG = {
91
101
  "temporarily_unavailable": { category: "availability", recovery: "retry" },
92
102
  "timeout": { category: "availability", recovery: "retry" },
93
103
  "token_exchange_failed": { category: "availability", recovery: "retry" },
104
+ "transport_protocol_incompatible": { category: "compatibility", recovery: "upgrade_connector" },
94
105
  "type_pack_provision_failed": { category: "validation", recovery: "repair_collection" },
95
106
  "unknown_collection": { category: "selection", recovery: "choose_collection" },
96
107
  "unsafe_file_path": { category: "validation", recovery: "fix_request" },
@@ -134,6 +145,70 @@ const CONNECT_PROBLEM_DETAIL_SCHEMAS = {
134
145
  }
135
146
  }
136
147
  },
148
+ "authorization_binding_incompatible": {
149
+ "type": "object",
150
+ "required": [
151
+ "contract",
152
+ "required",
153
+ "supported",
154
+ "peer"
155
+ ],
156
+ "properties": {
157
+ "contract": {
158
+ "type": "string"
159
+ },
160
+ "required": {
161
+ "type": "array",
162
+ "items": {
163
+ "type": "integer"
164
+ }
165
+ },
166
+ "supported": {
167
+ "type": "array",
168
+ "items": {
169
+ "type": "integer"
170
+ }
171
+ },
172
+ "peer": {
173
+ "type": "string"
174
+ },
175
+ "operation": {
176
+ "type": "string"
177
+ }
178
+ }
179
+ },
180
+ "capability_contract_incompatible": {
181
+ "type": "object",
182
+ "required": [
183
+ "contract",
184
+ "required",
185
+ "supported",
186
+ "peer"
187
+ ],
188
+ "properties": {
189
+ "contract": {
190
+ "type": "string"
191
+ },
192
+ "required": {
193
+ "type": "array",
194
+ "items": {
195
+ "type": "integer"
196
+ }
197
+ },
198
+ "supported": {
199
+ "type": "array",
200
+ "items": {
201
+ "type": "integer"
202
+ }
203
+ },
204
+ "peer": {
205
+ "type": "string"
206
+ },
207
+ "operation": {
208
+ "type": "string"
209
+ }
210
+ }
211
+ },
137
212
  "collection_configuration_invalid": {
138
213
  "type": "object",
139
214
  "required": [
@@ -226,6 +301,38 @@ const CONNECT_PROBLEM_DETAIL_SCHEMAS = {
226
301
  }
227
302
  }
228
303
  },
304
+ "durable_mutation_unsupported": {
305
+ "type": "object",
306
+ "required": [
307
+ "contract",
308
+ "required",
309
+ "supported",
310
+ "peer"
311
+ ],
312
+ "properties": {
313
+ "contract": {
314
+ "type": "string"
315
+ },
316
+ "required": {
317
+ "type": "array",
318
+ "items": {
319
+ "type": "integer"
320
+ }
321
+ },
322
+ "supported": {
323
+ "type": "array",
324
+ "items": {
325
+ "type": "integer"
326
+ }
327
+ },
328
+ "peer": {
329
+ "type": "string"
330
+ },
331
+ "operation": {
332
+ "type": "string"
333
+ }
334
+ }
335
+ },
229
336
  "insufficient_access": {
230
337
  "type": "object",
231
338
  "required": [
@@ -288,6 +395,17 @@ const CONNECT_PROBLEM_DETAIL_SCHEMAS = {
288
395
  }
289
396
  }
290
397
  },
398
+ "mutation_request_conflict": {
399
+ "type": "object",
400
+ "required": [
401
+ "request_id"
402
+ ],
403
+ "properties": {
404
+ "request_id": {
405
+ "type": "string"
406
+ }
407
+ }
408
+ },
291
409
  "operation_invalid": {
292
410
  "type": "object",
293
411
  "required": [
@@ -303,6 +421,17 @@ const CONNECT_PROBLEM_DETAIL_SCHEMAS = {
303
421
  "partial_result": {}
304
422
  }
305
423
  },
424
+ "operation_outcome_unknown": {
425
+ "type": "object",
426
+ "required": [
427
+ "request_id"
428
+ ],
429
+ "properties": {
430
+ "request_id": {
431
+ "type": "string"
432
+ }
433
+ }
434
+ },
306
435
  "rate_limited": {
307
436
  "type": "object",
308
437
  "required": [],
@@ -311,6 +440,38 @@ const CONNECT_PROBLEM_DETAIL_SCHEMAS = {
311
440
  "type": "integer"
312
441
  }
313
442
  }
443
+ },
444
+ "transport_protocol_incompatible": {
445
+ "type": "object",
446
+ "required": [
447
+ "contract",
448
+ "required",
449
+ "supported",
450
+ "peer"
451
+ ],
452
+ "properties": {
453
+ "contract": {
454
+ "type": "string"
455
+ },
456
+ "required": {
457
+ "type": "array",
458
+ "items": {
459
+ "type": "integer"
460
+ }
461
+ },
462
+ "supported": {
463
+ "type": "array",
464
+ "items": {
465
+ "type": "integer"
466
+ }
467
+ },
468
+ "peer": {
469
+ "type": "string"
470
+ },
471
+ "operation": {
472
+ "type": "string"
473
+ }
474
+ }
314
475
  }
315
476
  };
316
477
  export function isConnectProblemCode(code) {