@pam-ai/pam-ordo-contracts 3.15.1 → 3.17.0
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/contract-invariants.d.ts +134 -0
- package/dist/contract-invariants.d.ts.map +1 -0
- package/dist/contract-invariants.js +8 -0
- package/dist/contract-invariants.js.map +1 -0
- package/dist/generated.d.ts +147 -6
- package/dist/generated.d.ts.map +1 -1
- package/dist/index.d.ts +97 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/fixtures/inbox-policy-v1.json +7 -0
- package/fixtures/manifest.json +37 -31
- package/fixtures/mention-ref-legacy.json +5 -0
- package/fixtures/mention-ref-outstanding.json +7 -0
- package/fixtures/mention-ref-resolved.json +7 -0
- package/fixtures/resolve-mention-command.json +6 -0
- package/fixtures/resolve-mention-result-nothing-outstanding.json +11 -0
- package/fixtures/resolve-mention-result.json +11 -0
- package/openapi/openapi.json +363 -8
- package/package.json +1 -1
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import type { MentionRef, ResolveMentionResult, SearchInboxContactsParams } from './index.js';
|
|
2
|
+
type Assert<T extends true> = T;
|
|
3
|
+
type Accepts<Value, Shape> = Value extends Shape ? true : false;
|
|
4
|
+
type Rejects<Value, Shape> = Value extends Shape ? false : true;
|
|
5
|
+
/**
|
|
6
|
+
* `GET /v1/inbox/contacts` takes a query, a roState, or both — never neither,
|
|
7
|
+
* and never a roState that names no state.
|
|
8
|
+
*/
|
|
9
|
+
export type SearchInboxContactsInvariants = [
|
|
10
|
+
Assert<Accepts<{
|
|
11
|
+
query: 'ellery';
|
|
12
|
+
}, SearchInboxContactsParams>>,
|
|
13
|
+
Assert<Accepts<{
|
|
14
|
+
roState: ['OPEN'];
|
|
15
|
+
}, SearchInboxContactsParams>>,
|
|
16
|
+
Assert<Accepts<{
|
|
17
|
+
query: 'ellery';
|
|
18
|
+
roState: ['OPEN'];
|
|
19
|
+
}, SearchInboxContactsParams>>,
|
|
20
|
+
Assert<Accepts<{
|
|
21
|
+
roState: ['OPEN'];
|
|
22
|
+
limit: 25;
|
|
23
|
+
}, SearchInboxContactsParams>>,
|
|
24
|
+
Assert<Rejects<Record<string, never>, SearchInboxContactsParams>>,
|
|
25
|
+
Assert<Rejects<{
|
|
26
|
+
limit: 25;
|
|
27
|
+
}, SearchInboxContactsParams>>,
|
|
28
|
+
Assert<Rejects<{
|
|
29
|
+
roState: [];
|
|
30
|
+
}, SearchInboxContactsParams>>,
|
|
31
|
+
Assert<Rejects<{
|
|
32
|
+
roState: [];
|
|
33
|
+
limit: 25;
|
|
34
|
+
}, SearchInboxContactsParams>>
|
|
35
|
+
];
|
|
36
|
+
/** A Mention's two resolution fields move together, or are both absent. */
|
|
37
|
+
export type MentionRefInvariants = [
|
|
38
|
+
Assert<Accepts<{
|
|
39
|
+
id: '1';
|
|
40
|
+
userId: 'u';
|
|
41
|
+
createdAt: 't';
|
|
42
|
+
}, MentionRef>>,
|
|
43
|
+
Assert<Accepts<{
|
|
44
|
+
id: '1';
|
|
45
|
+
userId: 'u';
|
|
46
|
+
createdAt: 't';
|
|
47
|
+
resolvedAt: null;
|
|
48
|
+
resolvedByUserId: null;
|
|
49
|
+
}, MentionRef>>,
|
|
50
|
+
Assert<Accepts<{
|
|
51
|
+
id: '1';
|
|
52
|
+
userId: 'u';
|
|
53
|
+
createdAt: 't';
|
|
54
|
+
resolvedAt: 't';
|
|
55
|
+
resolvedByUserId: 'u';
|
|
56
|
+
}, MentionRef>>,
|
|
57
|
+
Assert<Rejects<{
|
|
58
|
+
id: '1';
|
|
59
|
+
userId: 'u';
|
|
60
|
+
createdAt: 't';
|
|
61
|
+
resolvedAt: 't';
|
|
62
|
+
resolvedByUserId: null;
|
|
63
|
+
}, MentionRef>>,
|
|
64
|
+
Assert<Rejects<{
|
|
65
|
+
id: '1';
|
|
66
|
+
userId: 'u';
|
|
67
|
+
createdAt: 't';
|
|
68
|
+
resolvedAt: null;
|
|
69
|
+
resolvedByUserId: 'u';
|
|
70
|
+
}, MentionRef>>,
|
|
71
|
+
Assert<Rejects<{
|
|
72
|
+
id: '1';
|
|
73
|
+
userId: 'u';
|
|
74
|
+
createdAt: 't';
|
|
75
|
+
resolvedAt: 't';
|
|
76
|
+
}, MentionRef>>,
|
|
77
|
+
Assert<Rejects<{
|
|
78
|
+
id: '1';
|
|
79
|
+
userId: 'u';
|
|
80
|
+
createdAt: 't';
|
|
81
|
+
resolvedByUserId: 'u';
|
|
82
|
+
}, MentionRef>>
|
|
83
|
+
];
|
|
84
|
+
type Outcome = {
|
|
85
|
+
operationId: 'op';
|
|
86
|
+
applied: true;
|
|
87
|
+
replayed: false;
|
|
88
|
+
conversationId: 'c';
|
|
89
|
+
workCycleId: 'w';
|
|
90
|
+
};
|
|
91
|
+
/** Resolving something means it happened at a time. Zero says nothing either way. */
|
|
92
|
+
export type ResolveMentionResultInvariants = [
|
|
93
|
+
Assert<Accepts<{
|
|
94
|
+
data: Outcome & {
|
|
95
|
+
resolvedCount: 3;
|
|
96
|
+
resolvedAt: 't';
|
|
97
|
+
};
|
|
98
|
+
}, ResolveMentionResult>>,
|
|
99
|
+
Assert<Accepts<{
|
|
100
|
+
data: Outcome & {
|
|
101
|
+
resolvedCount: 0;
|
|
102
|
+
resolvedAt: null;
|
|
103
|
+
};
|
|
104
|
+
}, ResolveMentionResult>>,
|
|
105
|
+
Assert<Accepts<{
|
|
106
|
+
data: Outcome & {
|
|
107
|
+
resolvedCount: 0;
|
|
108
|
+
resolvedAt: 't';
|
|
109
|
+
};
|
|
110
|
+
}, ResolveMentionResult>>,
|
|
111
|
+
Assert<Accepts<{
|
|
112
|
+
data: Outcome & {
|
|
113
|
+
resolvedCount: 0;
|
|
114
|
+
};
|
|
115
|
+
}, ResolveMentionResult>>,
|
|
116
|
+
Assert<Rejects<{
|
|
117
|
+
data: Outcome & {
|
|
118
|
+
resolvedCount: 3;
|
|
119
|
+
resolvedAt: null;
|
|
120
|
+
};
|
|
121
|
+
}, ResolveMentionResult>>,
|
|
122
|
+
Assert<Rejects<{
|
|
123
|
+
data: Outcome & {
|
|
124
|
+
resolvedCount: 3;
|
|
125
|
+
};
|
|
126
|
+
}, ResolveMentionResult>>
|
|
127
|
+
];
|
|
128
|
+
/**
|
|
129
|
+
* `resolvedAt` narrows the pairing, which is the reason a reader wants it: the
|
|
130
|
+
* resolver comes back a `string`, not a `string | null`.
|
|
131
|
+
*/
|
|
132
|
+
export declare function mentionResolver(mention: MentionRef): string | null;
|
|
133
|
+
export {};
|
|
134
|
+
//# sourceMappingURL=contract-invariants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-invariants.d.ts","sourceRoot":"","sources":["../src/contract-invariants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAoB9F,KAAK,MAAM,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC;AAChC,KAAK,OAAO,CAAC,KAAK,EAAE,KAAK,IAAI,KAAK,SAAS,KAAK,GAAG,IAAI,GAAG,KAAK,CAAC;AAChE,KAAK,OAAO,CAAC,KAAK,EAAE,KAAK,IAAI,KAAK,SAAS,KAAK,GAAG,KAAK,GAAG,IAAI,CAAC;AAEhE;;;GAGG;AACH,MAAM,MAAM,6BAA6B,GAAG;IAC1C,MAAM,CAAC,OAAO,CAAC;QAAE,KAAK,EAAE,QAAQ,CAAA;KAAE,EAAE,yBAAyB,CAAC,CAAC;IAC/D,MAAM,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,CAAC,MAAM,CAAC,CAAA;KAAE,EAAE,yBAAyB,CAAC,CAAC;IACjE,MAAM,CAAC,OAAO,CAAC;QAAE,KAAK,EAAE,QAAQ,CAAC;QAAC,OAAO,EAAE,CAAC,MAAM,CAAC,CAAA;KAAE,EAAE,yBAAyB,CAAC,CAAC;IAClF,MAAM,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC;QAAC,KAAK,EAAE,EAAE,CAAA;KAAE,EAAE,yBAAyB,CAAC,CAAC;IAE5E,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,yBAAyB,CAAC,CAAC;IACjE,MAAM,CAAC,OAAO,CAAC;QAAE,KAAK,EAAE,EAAE,CAAA;KAAE,EAAE,yBAAyB,CAAC,CAAC;IACzD,MAAM,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,EAAE,CAAA;KAAE,EAAE,yBAAyB,CAAC,CAAC;IAC3D,MAAM,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,EAAE,CAAC;QAAC,KAAK,EAAE,EAAE,CAAA;KAAE,EAAE,yBAAyB,CAAC,CAAC;CACvE,CAAC;AAEF,2EAA2E;AAC3E,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,CAAC,OAAO,CAAC;QAAE,EAAE,EAAE,GAAG,CAAC;QAAC,MAAM,EAAE,GAAG,CAAC;QAAC,SAAS,EAAE,GAAG,CAAA;KAAE,EAAE,UAAU,CAAC,CAAC;IACrE,MAAM,CACJ,OAAO,CACL;QAAE,EAAE,EAAE,GAAG,CAAC;QAAC,MAAM,EAAE,GAAG,CAAC;QAAC,SAAS,EAAE,GAAG,CAAC;QAAC,UAAU,EAAE,IAAI,CAAC;QAAC,gBAAgB,EAAE,IAAI,CAAA;KAAE,EAClF,UAAU,CACX,CACF;IACD,MAAM,CACJ,OAAO,CACL;QAAE,EAAE,EAAE,GAAG,CAAC;QAAC,MAAM,EAAE,GAAG,CAAC;QAAC,SAAS,EAAE,GAAG,CAAC;QAAC,UAAU,EAAE,GAAG,CAAC;QAAC,gBAAgB,EAAE,GAAG,CAAA;KAAE,EAChF,UAAU,CACX,CACF;IAED,MAAM,CACJ,OAAO,CACL;QAAE,EAAE,EAAE,GAAG,CAAC;QAAC,MAAM,EAAE,GAAG,CAAC;QAAC,SAAS,EAAE,GAAG,CAAC;QAAC,UAAU,EAAE,GAAG,CAAC;QAAC,gBAAgB,EAAE,IAAI,CAAA;KAAE,EACjF,UAAU,CACX,CACF;IACD,MAAM,CACJ,OAAO,CACL;QAAE,EAAE,EAAE,GAAG,CAAC;QAAC,MAAM,EAAE,GAAG,CAAC;QAAC,SAAS,EAAE,GAAG,CAAC;QAAC,UAAU,EAAE,IAAI,CAAC;QAAC,gBAAgB,EAAE,GAAG,CAAA;KAAE,EACjF,UAAU,CACX,CACF;IACD,MAAM,CAAC,OAAO,CAAC;QAAE,EAAE,EAAE,GAAG,CAAC;QAAC,MAAM,EAAE,GAAG,CAAC;QAAC,SAAS,EAAE,GAAG,CAAC;QAAC,UAAU,EAAE,GAAG,CAAA;KAAE,EAAE,UAAU,CAAC,CAAC;IACtF,MAAM,CAAC,OAAO,CAAC;QAAE,EAAE,EAAE,GAAG,CAAC;QAAC,MAAM,EAAE,GAAG,CAAC;QAAC,SAAS,EAAE,GAAG,CAAC;QAAC,gBAAgB,EAAE,GAAG,CAAA;KAAE,EAAE,UAAU,CAAC,CAAC;CAC7F,CAAC;AAEF,KAAK,OAAO,GAAG;IACb,WAAW,EAAE,IAAI,CAAC;IAClB,OAAO,EAAE,IAAI,CAAC;IACd,QAAQ,EAAE,KAAK,CAAC;IAChB,cAAc,EAAE,GAAG,CAAC;IACpB,WAAW,EAAE,GAAG,CAAC;CAClB,CAAC;AAEF,qFAAqF;AACrF,MAAM,MAAM,8BAA8B,GAAG;IAC3C,MAAM,CAAC,OAAO,CAAC;QAAE,IAAI,EAAE,OAAO,GAAG;YAAE,aAAa,EAAE,CAAC,CAAC;YAAC,UAAU,EAAE,GAAG,CAAA;SAAE,CAAA;KAAE,EAAE,oBAAoB,CAAC,CAAC;IAChG,MAAM,CAAC,OAAO,CAAC;QAAE,IAAI,EAAE,OAAO,GAAG;YAAE,aAAa,EAAE,CAAC,CAAC;YAAC,UAAU,EAAE,IAAI,CAAA;SAAE,CAAA;KAAE,EAAE,oBAAoB,CAAC,CAAC;IACjG,MAAM,CAAC,OAAO,CAAC;QAAE,IAAI,EAAE,OAAO,GAAG;YAAE,aAAa,EAAE,CAAC,CAAC;YAAC,UAAU,EAAE,GAAG,CAAA;SAAE,CAAA;KAAE,EAAE,oBAAoB,CAAC,CAAC;IAChG,MAAM,CAAC,OAAO,CAAC;QAAE,IAAI,EAAE,OAAO,GAAG;YAAE,aAAa,EAAE,CAAC,CAAA;SAAE,CAAA;KAAE,EAAE,oBAAoB,CAAC,CAAC;IAE/E,MAAM,CAAC,OAAO,CAAC;QAAE,IAAI,EAAE,OAAO,GAAG;YAAE,aAAa,EAAE,CAAC,CAAC;YAAC,UAAU,EAAE,IAAI,CAAA;SAAE,CAAA;KAAE,EAAE,oBAAoB,CAAC,CAAC;IACjG,MAAM,CAAC,OAAO,CAAC;QAAE,IAAI,EAAE,OAAO,GAAG;YAAE,aAAa,EAAE,CAAC,CAAA;SAAE,CAAA;KAAE,EAAE,oBAAoB,CAAC,CAAC;CAChF,CAAC;AAEF;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAElE"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `resolvedAt` narrows the pairing, which is the reason a reader wants it: the
|
|
3
|
+
* resolver comes back a `string`, not a `string | null`.
|
|
4
|
+
*/
|
|
5
|
+
export function mentionResolver(mention) {
|
|
6
|
+
return mention.resolvedAt ? mention.resolvedByUserId : null;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=contract-invariants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-invariants.js","sourceRoot":"","sources":["../src/contract-invariants.ts"],"names":[],"mappings":"AA2FA;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,OAAmB;IACjD,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9D,CAAC"}
|
package/dist/generated.d.ts
CHANGED
|
@@ -84,6 +84,7 @@ export interface paths {
|
|
|
84
84
|
/**
|
|
85
85
|
* Search the rooftop's Customers to start an outbound Conversation
|
|
86
86
|
* @description The outbound half of the Inbox. The Inbox itself is incoming-only, so a Conversation an advisor needs to START cannot be found in it: the Customer may have no thread at all, only an open repair order, or a thread another advisor owns. This searches the whole rooftop's Customers rather than the reader's own Conversations, and reports how each one already relates to them so the picker can say what opening it will do. Requires VIEW_CUSTOMER_DIRECTORY, which is a stronger grant than VIEW_OWN_INBOX: it exposes Customers the reader has never messaged. Contact detail is hydrated from the system that masters it, so a hydration gap degrades a field and never removes a Customer.
|
|
87
|
+
* SEARCH OR BROWSE, AND ONE OF THEM IS REQUIRED. Supply a query, a roState, or both; supplying neither is a 400 rather than the rooftop's entire book of business, which is a page nobody asked for and the one request most likely to be slow.
|
|
87
88
|
*/
|
|
88
89
|
get: operations["searchInboxContacts"];
|
|
89
90
|
put?: never;
|
|
@@ -418,6 +419,23 @@ export interface paths {
|
|
|
418
419
|
patch?: never;
|
|
419
420
|
trace?: never;
|
|
420
421
|
};
|
|
422
|
+
"/v1/inbox/commands/resolve-mention": {
|
|
423
|
+
parameters: {
|
|
424
|
+
query?: never;
|
|
425
|
+
header?: never;
|
|
426
|
+
path?: never;
|
|
427
|
+
cookie?: never;
|
|
428
|
+
};
|
|
429
|
+
get?: never;
|
|
430
|
+
put?: never;
|
|
431
|
+
/** Mark the caller's outstanding Mentions on one WorkCycle dealt with */
|
|
432
|
+
post: operations["resolveInboxMentions"];
|
|
433
|
+
delete?: never;
|
|
434
|
+
options?: never;
|
|
435
|
+
head?: never;
|
|
436
|
+
patch?: never;
|
|
437
|
+
trace?: never;
|
|
438
|
+
};
|
|
421
439
|
"/v1/inbox/commands/dismiss-notification": {
|
|
422
440
|
parameters: {
|
|
423
441
|
query?: never;
|
|
@@ -529,8 +547,16 @@ export interface components {
|
|
|
529
547
|
*/
|
|
530
548
|
type: "UNASSIGNED";
|
|
531
549
|
};
|
|
550
|
+
/** @description Route an enabled repair-order transition to the concrete advisor User carried by the accepted source record, after rooftop and capability validation through PAM Permissions. This routing-only target is valid only for the source.repair_order_transition category. When the source has no eligible advisor, retain the WorkCycle unassigned rather than selecting a configured fallback User. */
|
|
551
|
+
InboxPolicySourceAdvisorTargetV1: {
|
|
552
|
+
/**
|
|
553
|
+
* @description discriminator enum property added by openapi-typescript
|
|
554
|
+
* @enum {string}
|
|
555
|
+
*/
|
|
556
|
+
type: "SOURCE_ADVISOR";
|
|
557
|
+
};
|
|
532
558
|
InboxPolicyRecipientTargetV1: components["schemas"]["InboxPolicyUserTargetV1"] | components["schemas"]["InboxPolicyTeamTargetV1"];
|
|
533
|
-
InboxPolicyRoutingTargetV1: components["schemas"]["InboxPolicyUserTargetV1"] | components["schemas"]["InboxPolicyTeamTargetV1"] | components["schemas"]["InboxPolicyUnassignedTargetV1"];
|
|
559
|
+
InboxPolicyRoutingTargetV1: components["schemas"]["InboxPolicyUserTargetV1"] | components["schemas"]["InboxPolicyTeamTargetV1"] | components["schemas"]["InboxPolicyUnassignedTargetV1"] | components["schemas"]["InboxPolicySourceAdvisorTargetV1"];
|
|
534
560
|
InboxPolicyNeedsAttentionV1: {
|
|
535
561
|
enabled: boolean;
|
|
536
562
|
recipients: components["schemas"]["InboxPolicyRecipientTargetV1"][];
|
|
@@ -542,7 +568,7 @@ export interface components {
|
|
|
542
568
|
createsWorkCycle: boolean;
|
|
543
569
|
routing: components["schemas"]["InboxPolicyRoutingTargetV1"];
|
|
544
570
|
needsAttention: components["schemas"]["InboxPolicyNeedsAttentionV1"];
|
|
545
|
-
};
|
|
571
|
+
} & unknown;
|
|
546
572
|
InboxPolicyOverdueDisabledV1: {
|
|
547
573
|
/** @constant */
|
|
548
574
|
enabled: false;
|
|
@@ -827,6 +853,11 @@ export interface components {
|
|
|
827
853
|
data: {
|
|
828
854
|
contacts: components["schemas"]["ContactRow"][];
|
|
829
855
|
};
|
|
856
|
+
/** @description Present on a browse, which can exceed one page. A search is bounded by its own query and may omit this entirely, which is why the envelope is optional rather than required — an existing consumer that never reads it stays valid. */
|
|
857
|
+
meta?: {
|
|
858
|
+
/** @description Opaque keyset cursor, or null on the last page. */
|
|
859
|
+
nextCursor: string | null;
|
|
860
|
+
};
|
|
830
861
|
};
|
|
831
862
|
InboxListResponse: {
|
|
832
863
|
data: {
|
|
@@ -883,7 +914,21 @@ export interface components {
|
|
|
883
914
|
userId: string;
|
|
884
915
|
/** Format: date-time */
|
|
885
916
|
createdAt: string;
|
|
886
|
-
|
|
917
|
+
/**
|
|
918
|
+
* Format: date-time
|
|
919
|
+
* @description When the recipient marked this Mention dealt with, or null while it is still outstanding. A Mention was previously immutable and this is the one thing that may change about it: the words, the author and the recipient never do, and resolution records what the recipient did about it rather than editing what was said. Optional so a producer that predates DASH-322 is still valid; absent reads the same as null.
|
|
920
|
+
*/
|
|
921
|
+
resolvedAt?: string | null;
|
|
922
|
+
/** @description Who resolved it, which is always the recipient — a Mention is recipient-scoped and nobody else can clear somebody's claim on their own attention. Published so a reader can tell a resolution apart from a Mention that was never raised, and so the two fields cannot disagree. Null exactly when resolvedAt is null. */
|
|
923
|
+
resolvedByUserId?: string | null;
|
|
924
|
+
} & (unknown | {
|
|
925
|
+
resolvedAt: null;
|
|
926
|
+
resolvedByUserId: null;
|
|
927
|
+
} | {
|
|
928
|
+
/** Format: date-time */
|
|
929
|
+
resolvedAt: string;
|
|
930
|
+
resolvedByUserId: string;
|
|
931
|
+
});
|
|
887
932
|
VehicleRef: {
|
|
888
933
|
sourceSystem: string;
|
|
889
934
|
externalId: string;
|
|
@@ -934,6 +979,13 @@ export interface components {
|
|
|
934
979
|
displayNumber: components["schemas"]["HydratedText"];
|
|
935
980
|
status: components["schemas"]["HydratedText"];
|
|
936
981
|
vehicle: components["schemas"]["VehicleRef"] | null;
|
|
982
|
+
/**
|
|
983
|
+
* Format: date-time
|
|
984
|
+
* @description When this repair order was opened.
|
|
985
|
+
* ON THE REPAIR ORDER RATHER THAN ON THE ROW THAT CARRIES IT, because that is whose fact it is. Sorting Customers by "most recent open RO" was previously impossible at any cost: neither ContactRow nor this carried a single timestamp, so recency could not be derived by a client or asked for from the service.
|
|
986
|
+
* Nullable, and null is not a defect: a source system that reports a repair order without an open date is publishing what it has, and a row must not disappear because an enrichment did not arrive. Rows with no openedAt sort last under RECENT_REPAIR_ORDER.
|
|
987
|
+
*/
|
|
988
|
+
openedAt?: string | null;
|
|
937
989
|
availability: components["schemas"]["Availability"];
|
|
938
990
|
};
|
|
939
991
|
ConversationDetailResponse: {
|
|
@@ -1420,6 +1472,42 @@ export interface components {
|
|
|
1420
1472
|
/** Format: uuid */
|
|
1421
1473
|
notificationId: string;
|
|
1422
1474
|
};
|
|
1475
|
+
/**
|
|
1476
|
+
* @description Mark the caller's outstanding Mentions on one WorkCycle dealt with.
|
|
1477
|
+
* CONVERSATION-WIDE, NOT PER-MENTION, and the shape is the point. A recipient does not think in Mentions; they think "I have handled this thread". Two colleagues naming the same person in one exchange raises two Mentions, and clearing one of them would leave the row on the Mentions list with nothing on screen to explain why.
|
|
1478
|
+
* It resolves only the CALLER's Mentions. A Mention is a claim on one person's attention, so nobody else can discharge it, and the command carries no recipient for that reason: the identity comes from the token.
|
|
1479
|
+
* Idempotent by operationId, and monotonic besides — resolving an already resolved Mention keeps the first resolvedAt rather than moving it, so a retry cannot rewrite when somebody dealt with something.
|
|
1480
|
+
*/
|
|
1481
|
+
ResolveMentionCommand: {
|
|
1482
|
+
operationId: string;
|
|
1483
|
+
clientOrgId: string;
|
|
1484
|
+
/** Format: uuid */
|
|
1485
|
+
conversationId: string;
|
|
1486
|
+
/** Format: uuid */
|
|
1487
|
+
workCycleId: string;
|
|
1488
|
+
};
|
|
1489
|
+
ResolveMentionResult: {
|
|
1490
|
+
/**
|
|
1491
|
+
* @description RESOLVING SOMETHING MEANS IT HAPPENED AT A TIME. resolvedCount was required while resolvedAt stayed optional and nullable regardless of it, so `{ resolvedCount: 3, resolvedAt: null }` validated — three Mentions dealt with at no moment, which no reader can render and which the rows themselves cannot be in, since the pairing CHECK on conversation_mentions gives every resolved row a timestamp.
|
|
1492
|
+
* One-directional on purpose. A count of zero says nothing about resolvedAt: pressing Done twice, or replying and then pressing it, resolves nothing new and still has a real moment to report from the first time — and a caller who never had a Mention here has none. Both are honest answers, so zero admits a timestamp or null.
|
|
1493
|
+
*/
|
|
1494
|
+
data: {
|
|
1495
|
+
operationId: string;
|
|
1496
|
+
applied: boolean;
|
|
1497
|
+
replayed: boolean;
|
|
1498
|
+
/** Format: uuid */
|
|
1499
|
+
conversationId: string;
|
|
1500
|
+
/** Format: uuid */
|
|
1501
|
+
workCycleId: string;
|
|
1502
|
+
/** @description How many of the caller's Mentions this resolved. Zero is a success, not a failure: it means they had none outstanding, which is the ordinary result of pressing Done twice or of replying first and then pressing it. */
|
|
1503
|
+
resolvedCount: number;
|
|
1504
|
+
/**
|
|
1505
|
+
* Format: date-time
|
|
1506
|
+
* @description When they were resolved. Set whenever anything is or was resolved; null only when the caller had nothing outstanding and nothing already resolved to report.
|
|
1507
|
+
*/
|
|
1508
|
+
resolvedAt?: string | null;
|
|
1509
|
+
};
|
|
1510
|
+
};
|
|
1423
1511
|
BaseCommand: components["schemas"]["CommandEnvelope"];
|
|
1424
1512
|
UserAssignmentTarget: {
|
|
1425
1513
|
/**
|
|
@@ -1674,6 +1762,16 @@ export interface components {
|
|
|
1674
1762
|
"application/json": components["schemas"]["CustomerNoteCommandResult"];
|
|
1675
1763
|
};
|
|
1676
1764
|
};
|
|
1765
|
+
/** @description Applied, replayed, or no-op Mention resolution result. */
|
|
1766
|
+
MentionsResolved: {
|
|
1767
|
+
headers: {
|
|
1768
|
+
"x-correlation-id": components["headers"]["CorrelationId"];
|
|
1769
|
+
[name: string]: unknown;
|
|
1770
|
+
};
|
|
1771
|
+
content: {
|
|
1772
|
+
"application/json": components["schemas"]["ResolveMentionResult"];
|
|
1773
|
+
};
|
|
1774
|
+
};
|
|
1677
1775
|
/** @description Applied, replayed, or monotonic no-op notification state result. */
|
|
1678
1776
|
NotificationCommandApplied: {
|
|
1679
1777
|
headers: {
|
|
@@ -1843,6 +1941,11 @@ export interface components {
|
|
|
1843
1941
|
"application/json": components["schemas"]["DeleteCustomerNoteCommand"];
|
|
1844
1942
|
};
|
|
1845
1943
|
};
|
|
1944
|
+
ResolveMentionCommand: {
|
|
1945
|
+
content: {
|
|
1946
|
+
"application/json": components["schemas"]["ResolveMentionCommand"];
|
|
1947
|
+
};
|
|
1948
|
+
};
|
|
1846
1949
|
NotificationCommand: {
|
|
1847
1950
|
content: {
|
|
1848
1951
|
"application/json": components["schemas"]["NotificationCommand"];
|
|
@@ -2022,9 +2125,25 @@ export interface operations {
|
|
|
2022
2125
|
};
|
|
2023
2126
|
searchInboxContacts: {
|
|
2024
2127
|
parameters: {
|
|
2025
|
-
query
|
|
2026
|
-
/**
|
|
2027
|
-
|
|
2128
|
+
query?: {
|
|
2129
|
+
/**
|
|
2130
|
+
* @description A name fragment, or a telephone number in any format.
|
|
2131
|
+
* OPTIONAL SINCE 3.16.0. It was required, which made the picker a search box and nothing else: an advisor who knew they wanted "whoever has a car in the shop" had to guess a name first. Omitting it now browses rather than searches, and roState is what makes that a useful list instead of the rooftop's entire book of business.
|
|
2132
|
+
*/
|
|
2133
|
+
query?: string;
|
|
2134
|
+
/**
|
|
2135
|
+
* @description Narrow to Customers by the state of their car, using the same three values and the same meanings as the Conversation list: OPEN is a currently active repair order, CLOSED has had one and has none now, NONE never had one.
|
|
2136
|
+
* This is what makes an omitted query answerable. "Everyone with a car in the shop right now" is a question an advisor actually has, and it is bounded by the service drive rather than by the size of the rooftop; "everyone" is not, which is why browsing without either a query or a roState is refused.
|
|
2137
|
+
* An EMPTY ARRAY IS A 400, not an unfiltered browse. Presence is not a filter: `?roState=` names no state, so it would satisfy the at-least-one rule while asking for exactly the unbounded page that rule exists to refuse — and it is the shape a client reaches by serialising an empty selection rather than omitting the parameter, so it arrives by accident rather than by intent.
|
|
2138
|
+
*/
|
|
2139
|
+
roState?: ("OPEN" | "CLOSED" | "NONE")[];
|
|
2140
|
+
/**
|
|
2141
|
+
* @description RECENT_REPAIR_ORDER puts the most recently opened repair order first, which is the order a service drive works in — the car that just arrived is the call that has not been made yet. NAME is the stable alphabetical order a search result wants.
|
|
2142
|
+
* Defaults to NAME when a query is given and RECENT_REPAIR_ORDER when one is not, because a browse has no relevance to fall back on.
|
|
2143
|
+
*/
|
|
2144
|
+
sort?: "NAME" | "RECENT_REPAIR_ORDER";
|
|
2145
|
+
/** @description Opaque keyset cursor. Present because a browse is not bounded the way a search is: a busy rooftop can carry several hundred open repair orders, and a limit alone would silently truncate the answer. */
|
|
2146
|
+
cursor?: string;
|
|
2028
2147
|
/** @description Which side of the directory to read. MINE returns only Customers whose Conversation the reader owns; EVERYONE returns the rest. One set is always in the way of the other, so this is a switch rather than a filter. */
|
|
2029
2148
|
relationship?: "MINE" | "EVERYONE";
|
|
2030
2149
|
limit?: number;
|
|
@@ -2476,6 +2595,28 @@ export interface operations {
|
|
|
2476
2595
|
503: components["responses"]["ServiceUnavailable"];
|
|
2477
2596
|
};
|
|
2478
2597
|
};
|
|
2598
|
+
resolveInboxMentions: {
|
|
2599
|
+
parameters: {
|
|
2600
|
+
query?: never;
|
|
2601
|
+
header: {
|
|
2602
|
+
/** @description Authorized rooftop context. For commands this value must match body.clientOrgId; neither value is trusted without DASH-233 resolution. */
|
|
2603
|
+
"x-client-org-id": components["parameters"]["ClientOrgId"];
|
|
2604
|
+
};
|
|
2605
|
+
path?: never;
|
|
2606
|
+
cookie?: never;
|
|
2607
|
+
};
|
|
2608
|
+
requestBody: components["requestBodies"]["ResolveMentionCommand"];
|
|
2609
|
+
responses: {
|
|
2610
|
+
200: components["responses"]["MentionsResolved"];
|
|
2611
|
+
400: components["responses"]["BadRequest"];
|
|
2612
|
+
401: components["responses"]["Unauthorized"];
|
|
2613
|
+
403: components["responses"]["Forbidden"];
|
|
2614
|
+
404: components["responses"]["NotFound"];
|
|
2615
|
+
409: components["responses"]["Conflict"];
|
|
2616
|
+
500: components["responses"]["InternalError"];
|
|
2617
|
+
503: components["responses"]["ServiceUnavailable"];
|
|
2618
|
+
};
|
|
2619
|
+
};
|
|
2479
2620
|
dismissInboxNotification: {
|
|
2480
2621
|
parameters: {
|
|
2481
2622
|
query?: never;
|