@mj-biz-apps/common-activity-sync 5.42.0 → 5.44.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/ActivitySyncEngine.d.ts +93 -1
- package/dist/ActivitySyncEngine.d.ts.map +1 -1
- package/dist/ActivitySyncEngine.js +295 -15
- package/dist/ActivitySyncEngine.js.map +1 -1
- package/dist/attachments.d.ts +106 -0
- package/dist/attachments.d.ts.map +1 -0
- package/dist/attachments.js +147 -0
- package/dist/attachments.js.map +1 -0
- package/dist/content-capture.d.ts +92 -0
- package/dist/content-capture.d.ts.map +1 -0
- package/dist/content-capture.js +35 -0
- package/dist/content-capture.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/participants.d.ts +30 -0
- package/dist/participants.d.ts.map +1 -1
- package/dist/participants.js +48 -0
- package/dist/participants.js.map +1 -1
- package/dist/providers/GraphCalendarTransport.d.ts +115 -0
- package/dist/providers/GraphCalendarTransport.d.ts.map +1 -0
- package/dist/providers/GraphCalendarTransport.js +139 -0
- package/dist/providers/GraphCalendarTransport.js.map +1 -0
- package/dist/providers/GraphCommunicationTransport.d.ts.map +1 -1
- package/dist/providers/GraphCommunicationTransport.js +18 -4
- package/dist/providers/GraphCommunicationTransport.js.map +1 -1
- package/dist/providers/GraphMessageMapper.d.ts +2 -0
- package/dist/providers/GraphMessageMapper.d.ts.map +1 -1
- package/dist/providers/GraphMessageMapper.js +3 -0
- package/dist/providers/GraphMessageMapper.js.map +1 -1
- package/dist/providers/MSGraphActivitySyncProvider.d.ts +39 -4
- package/dist/providers/MSGraphActivitySyncProvider.d.ts.map +1 -1
- package/dist/providers/MSGraphActivitySyncProvider.js +45 -10
- package/dist/providers/MSGraphActivitySyncProvider.js.map +1 -1
- package/dist/providers/MSGraphCalendarSyncProvider.d.ts +55 -14
- package/dist/providers/MSGraphCalendarSyncProvider.d.ts.map +1 -1
- package/dist/providers/MSGraphCalendarSyncProvider.js +112 -38
- package/dist/providers/MSGraphCalendarSyncProvider.js.map +1 -1
- package/dist/providers/MessageTransport.d.ts +90 -0
- package/dist/providers/MessageTransport.d.ts.map +1 -1
- package/dist/providers/MessageTransport.js +72 -0
- package/dist/providers/MessageTransport.js.map +1 -1
- package/dist/providers/RecordedMessageTransport.d.ts.map +1 -1
- package/dist/providers/RecordedMessageTransport.js +25 -11
- package/dist/providers/RecordedMessageTransport.js.map +1 -1
- package/dist/stages.d.ts +11 -0
- package/dist/stages.d.ts.map +1 -1
- package/dist/stages.js.map +1 -1
- package/dist/types.d.ts +14 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +6 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MSGraphActivitySyncProvider.js","sourceRoot":"","sources":["../../src/providers/MSGraphActivitySyncProvider.ts"],"names":[],"mappings":";;;;;;;;;AAAA
|
|
1
|
+
{"version":3,"file":"MSGraphActivitySyncProvider.js","sourceRoot":"","sources":["../../src/providers/MSGraphActivitySyncProvider.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { BaseActivitySyncProvider } from '../BaseActivitySyncProvider.js';
|
|
2
2
|
import type { ActivitySourceQuery, NormalizedItem, RawBatch } from '../types.js';
|
|
3
|
+
import type { ActivityMessageTransport, ActivityTransportContext, ActivityTransportFactory } from './MessageTransport.js';
|
|
3
4
|
export declare const LIVE_GRAPH_CALENDAR_REFUSAL: string;
|
|
5
|
+
export declare const NO_CALENDAR_TRANSPORT_REFUSAL: string;
|
|
6
|
+
export declare const NO_CALENDAR_CREDENTIAL_REF_REFUSAL: string;
|
|
4
7
|
export interface GraphAttendeeLike {
|
|
5
8
|
type?: string;
|
|
6
9
|
emailAddress?: {
|
|
@@ -33,27 +36,65 @@ export interface GraphEventLike {
|
|
|
33
36
|
attendees?: GraphAttendeeLike[];
|
|
34
37
|
isCancelled?: boolean;
|
|
35
38
|
seriesMasterId?: string;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
GetEvents(params: {
|
|
39
|
-
Mailbox: string;
|
|
40
|
-
Since: Date | null;
|
|
41
|
-
Top: number;
|
|
42
|
-
}): Promise<{
|
|
43
|
-
Success?: boolean;
|
|
44
|
-
ErrorMessage?: string;
|
|
45
|
-
Events?: GraphEventLike[];
|
|
46
|
-
}>;
|
|
39
|
+
/** Graph's own flag. An .ics or a deck attached to the invite lands here. */
|
|
40
|
+
hasAttachments?: boolean;
|
|
47
41
|
}
|
|
48
42
|
/** Map one Graph event. Exported so a check can prove the mapping without a mailbox. */
|
|
49
43
|
export declare function MapGraphEvent(event: GraphEventLike, issues: string[]): NormalizedItem | null;
|
|
50
44
|
export declare class MSGraphCalendarSyncProvider extends BaseActivitySyncProvider {
|
|
45
|
+
/**
|
|
46
|
+
* Defaults to the HOST'S ATTESTATION, and to the same one mail uses.
|
|
47
|
+
*
|
|
48
|
+
* A bare `false` made this unreachable in the only way that ships — `ClassFactory` passes no
|
|
49
|
+
* arguments — so live calendar fetch could be enabled by tests and nothing else. It is the
|
|
50
|
+
* same Exchange Application Access Policy that scopes `Mail.Read` and `Calendars.Read`, so a
|
|
51
|
+
* host that has attested for one has attested for both; a second switch would let someone
|
|
52
|
+
* record half a decision.
|
|
53
|
+
*/
|
|
51
54
|
private readonly AllowLiveFetch;
|
|
52
|
-
|
|
55
|
+
/** Where events come from. Without one this provider refuses rather than pretending. */
|
|
56
|
+
private Transport?;
|
|
57
|
+
/** How a host builds a transport for a connection. See {@link Configure}. */
|
|
58
|
+
private readonly Factory?;
|
|
53
59
|
readonly Kind: "Calendar";
|
|
54
60
|
readonly ProviderTypeCode = "Microsoft365";
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Reflects the TRANSPORT rather than being hard-coded true.
|
|
63
|
+
*
|
|
64
|
+
* The engine refuses to write `Source: 'Integration'` rows from a non-live provider. While this
|
|
65
|
+
* class always claimed `IsLive = true`, a replayed calendar run would have been indistinguishable
|
|
66
|
+
* from a real one in the database afterwards — the exact confusion the flag exists to prevent.
|
|
67
|
+
* Defaults to true with no transport, so an unconfigured provider is treated as the stricter case.
|
|
68
|
+
*/
|
|
69
|
+
get IsLive(): boolean;
|
|
70
|
+
constructor(
|
|
71
|
+
/**
|
|
72
|
+
* Defaults to the HOST'S ATTESTATION, and to the same one mail uses.
|
|
73
|
+
*
|
|
74
|
+
* A bare `false` made this unreachable in the only way that ships — `ClassFactory` passes no
|
|
75
|
+
* arguments — so live calendar fetch could be enabled by tests and nothing else. It is the
|
|
76
|
+
* same Exchange Application Access Policy that scopes `Mail.Read` and `Calendars.Read`, so a
|
|
77
|
+
* host that has attested for one has attested for both; a second switch would let someone
|
|
78
|
+
* record half a decision.
|
|
79
|
+
*/
|
|
80
|
+
AllowLiveFetch?: boolean,
|
|
81
|
+
/** Where events come from. Without one this provider refuses rather than pretending. */
|
|
82
|
+
Transport?: ActivityMessageTransport | undefined,
|
|
83
|
+
/** How a host builds a transport for a connection. See {@link Configure}. */
|
|
84
|
+
Factory?: ActivityTransportFactory | undefined);
|
|
85
|
+
/** Why this provider cannot fetch, decided at Configure time and reported at fetch time. */
|
|
86
|
+
private ConfigurationRefusal;
|
|
87
|
+
/**
|
|
88
|
+
* Reads `ActivitySyncConnection.CredentialsRef` and builds this connection's transport from it.
|
|
89
|
+
*
|
|
90
|
+
* Identical in shape to the message provider's, and deliberately so: a connection configures ONE
|
|
91
|
+
* credential, and both of its surfaces resolve through it. A calendar-specific path would let the
|
|
92
|
+
* two disagree about which credential a connection uses.
|
|
93
|
+
*
|
|
94
|
+
* A transport passed to the CONSTRUCTOR wins and is never replaced — a database row must not be
|
|
95
|
+
* able to reach in and swap it.
|
|
96
|
+
*/
|
|
97
|
+
Configure(context: ActivityTransportContext): void;
|
|
57
98
|
protected FetchRaw(query: ActivitySourceQuery): Promise<RawBatch>;
|
|
58
99
|
protected Normalize(raw: RawBatch): NormalizedItem[];
|
|
59
100
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MSGraphCalendarSyncProvider.d.ts","sourceRoot":"","sources":["../../src/providers/MSGraphCalendarSyncProvider.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MSGraphCalendarSyncProvider.d.ts","sourceRoot":"","sources":["../../src/providers/MSGraphCalendarSyncProvider.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAC1E,OAAO,KAAK,EAAE,mBAAmB,EAAmB,cAAc,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAElG,OAAO,KAAK,EACR,wBAAwB,EACxB,wBAAwB,EACxB,wBAAwB,EAC3B,MAAM,uBAAuB,CAAC;AAE/B,eAAO,MAAM,2BAA2B,QAKwC,CAAC;AAEjF,eAAO,MAAM,6BAA6B,QAEU,CAAC;AAErD,eAAO,MAAM,kCAAkC,QAGpB,CAAC;AAE5B,MAAM,WAAW,iBAAiB;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACtD;AAED,MAAM,WAAW,cAAc;IAC3B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,GAAG,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,QAAQ,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,SAAS,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE;YAAE,OAAO,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IACnE,SAAS,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAChC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,cAAc,CAAC,EAAE,OAAO,CAAC;CAC5B;AAiBD,wFAAwF;AACxF,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,cAAc,GAAG,IAAI,CAiD5F;AAED,qBACa,2BAA4B,SAAQ,wBAAwB;IAiBjE;;;;;;;;OAQG;IACH,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,wFAAwF;IACxF,OAAO,CAAC,SAAS,CAAC;IAClB,6EAA6E;IAC7E,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;IA7B7B,SAAgB,IAAI,EAAG,UAAU,CAAU;IAC3C,SAAgB,gBAAgB,kBAAkB;IAElD;;;;;;;OAOG;IACH,IAAW,MAAM,IAAI,OAAO,CAE3B;;IAGG;;;;;;;;OAQG;IACc,cAAc,GAAE,OAAsC;IACvE,wFAAwF;IAChF,SAAS,CAAC,EAAE,wBAAwB,YAAA;IAC5C,6EAA6E;IAC5D,OAAO,CAAC,EAAE,wBAAwB,YAAA;IAKvD,4FAA4F;IAC5F,OAAO,CAAC,oBAAoB,CAAuB;IAEnD;;;;;;;;;OASG;IACa,SAAS,CAAC,OAAO,EAAE,wBAAwB,GAAG,IAAI;cA6BlD,QAAQ,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC;IA0BvE,SAAS,CAAC,SAAS,CAAC,GAAG,EAAE,QAAQ,GAAG,cAAc,EAAE;CAQvD"}
|
|
@@ -8,17 +8,37 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
8
8
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
9
|
};
|
|
10
10
|
/**
|
|
11
|
-
* Microsoft Graph calendar.
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* Microsoft Graph calendar.
|
|
12
|
+
*
|
|
13
|
+
* WHAT CHANGED. This class declared a `GraphEventFetcher` seam that NOTHING IMPLEMENTED, reachable
|
|
14
|
+
* only as the second constructor argument — which `MJGlobal.ClassFactory` never passes, because it
|
|
15
|
+
* builds plugins with no arguments. So through the engine every calendar fetch returned
|
|
16
|
+
* `Payloads: []` and logged "no transport is wired". Written, typechecked, exported and refused:
|
|
17
|
+
* the same defect `MSGraphActivitySyncProvider` had before its transport landed, one surface over.
|
|
18
|
+
*
|
|
19
|
+
* It now uses the same `ActivityMessageTransport` seam as mail, served by the same host factory,
|
|
20
|
+
* which dispatches on `DriverClass`. `GraphCalendarTransport` wraps MJ's `GetEvents`; a recorded
|
|
21
|
+
* transport replays captured payloads through the same mapper.
|
|
22
|
+
*
|
|
23
|
+
* THE TENANT-WIDE READ IS STILL REFUSED BY DEFAULT, and for the same reason as mail: app-only
|
|
24
|
+
* `Calendars.Read` reads EVERY calendar in the tenant until an Exchange policy scopes the app
|
|
25
|
+
* registration. It is the SAME policy and the SAME attestation — a host that has confirmed it for
|
|
26
|
+
* mail has confirmed it for calendar, so this reads `AllowLiveMailboxFetch` rather than inventing a
|
|
27
|
+
* second switch someone could set to only half the truth.
|
|
14
28
|
*/
|
|
15
|
-
import { LogError } from '@memberjunction/core';
|
|
16
29
|
import { RegisterClass } from '@memberjunction/global';
|
|
17
30
|
import { BaseActivitySyncProvider } from '../BaseActivitySyncProvider.js';
|
|
31
|
+
import { HostActivityTransportFactory, HostAllowsLiveMailboxFetch } from './MessageTransport.js';
|
|
18
32
|
export const LIVE_GRAPH_CALENDAR_REFUSAL = 'Live Graph calendar fetch is disabled. App-only auth makes Calendars.Read tenant-wide, ' +
|
|
19
33
|
'so it reads EVERY calendar until an Exchange Application Access Policy scopes the app ' +
|
|
20
34
|
'registration to a security group — the same policy Mail.Read needs. Confirm it exists ' +
|
|
21
|
-
'before enabling this, and use FixtureActivitySyncProvider until then.'
|
|
35
|
+
'before enabling this, and use FixtureActivitySyncProvider until then. Once confirmed, call ' +
|
|
36
|
+
'AllowLiveMailboxFetch() at host bootstrap with the group the policy names.';
|
|
37
|
+
export const NO_CALENDAR_TRANSPORT_REFUSAL = 'No calendar transport was supplied. Construct this provider with a GraphCalendarTransport ' +
|
|
38
|
+
'(live) or a RecordedMessageTransport (replay).';
|
|
39
|
+
export const NO_CALENDAR_CREDENTIAL_REF_REFUSAL = 'This ActivitySyncConnection names no credential. Set its CredentialsRef to the NAME of an ' +
|
|
40
|
+
'"Azure Service Principal" credential in MJ — that column holds a Credentials engine key, ' +
|
|
41
|
+
'never a secret value.';
|
|
22
42
|
function normalize(value) {
|
|
23
43
|
const trimmed = value?.trim().toLowerCase();
|
|
24
44
|
return trimmed ? trimmed : null;
|
|
@@ -72,6 +92,7 @@ export function MapGraphEvent(event, issues) {
|
|
|
72
92
|
ExternalID: externalID,
|
|
73
93
|
ExternalThreadID: event.seriesMasterId?.trim() || null,
|
|
74
94
|
TypeCode: 'Meeting',
|
|
95
|
+
HasAttachments: event.hasAttachments === true,
|
|
75
96
|
Subject: event.subject?.trim() || '(no subject)',
|
|
76
97
|
Body: event.bodyPreview ?? null,
|
|
77
98
|
StartedAt: startedAt,
|
|
@@ -84,48 +105,101 @@ export function MapGraphEvent(event, issues) {
|
|
|
84
105
|
};
|
|
85
106
|
}
|
|
86
107
|
let MSGraphCalendarSyncProvider = class MSGraphCalendarSyncProvider extends BaseActivitySyncProvider {
|
|
87
|
-
|
|
108
|
+
/**
|
|
109
|
+
* Reflects the TRANSPORT rather than being hard-coded true.
|
|
110
|
+
*
|
|
111
|
+
* The engine refuses to write `Source: 'Integration'` rows from a non-live provider. While this
|
|
112
|
+
* class always claimed `IsLive = true`, a replayed calendar run would have been indistinguishable
|
|
113
|
+
* from a real one in the database afterwards — the exact confusion the flag exists to prevent.
|
|
114
|
+
* Defaults to true with no transport, so an unconfigured provider is treated as the stricter case.
|
|
115
|
+
*/
|
|
116
|
+
get IsLive() {
|
|
117
|
+
return this.Transport?.IsLive ?? true;
|
|
118
|
+
}
|
|
119
|
+
constructor(
|
|
120
|
+
/**
|
|
121
|
+
* Defaults to the HOST'S ATTESTATION, and to the same one mail uses.
|
|
122
|
+
*
|
|
123
|
+
* A bare `false` made this unreachable in the only way that ships — `ClassFactory` passes no
|
|
124
|
+
* arguments — so live calendar fetch could be enabled by tests and nothing else. It is the
|
|
125
|
+
* same Exchange Application Access Policy that scopes `Mail.Read` and `Calendars.Read`, so a
|
|
126
|
+
* host that has attested for one has attested for both; a second switch would let someone
|
|
127
|
+
* record half a decision.
|
|
128
|
+
*/
|
|
129
|
+
AllowLiveFetch = HostAllowsLiveMailboxFetch(),
|
|
130
|
+
/** Where events come from. Without one this provider refuses rather than pretending. */
|
|
131
|
+
Transport,
|
|
132
|
+
/** How a host builds a transport for a connection. See {@link Configure}. */
|
|
133
|
+
Factory) {
|
|
88
134
|
super();
|
|
89
135
|
this.AllowLiveFetch = AllowLiveFetch;
|
|
90
|
-
this.
|
|
136
|
+
this.Transport = Transport;
|
|
137
|
+
this.Factory = Factory;
|
|
91
138
|
this.Kind = 'Calendar';
|
|
92
139
|
this.ProviderTypeCode = 'Microsoft365';
|
|
93
|
-
this.
|
|
140
|
+
/** Why this provider cannot fetch, decided at Configure time and reported at fetch time. */
|
|
141
|
+
this.ConfigurationRefusal = null;
|
|
94
142
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
143
|
+
/**
|
|
144
|
+
* Reads `ActivitySyncConnection.CredentialsRef` and builds this connection's transport from it.
|
|
145
|
+
*
|
|
146
|
+
* Identical in shape to the message provider's, and deliberately so: a connection configures ONE
|
|
147
|
+
* credential, and both of its surfaces resolve through it. A calendar-specific path would let the
|
|
148
|
+
* two disagree about which credential a connection uses.
|
|
149
|
+
*
|
|
150
|
+
* A transport passed to the CONSTRUCTOR wins and is never replaced — a database row must not be
|
|
151
|
+
* able to reach in and swap it.
|
|
152
|
+
*/
|
|
153
|
+
Configure(context) {
|
|
154
|
+
if (this.Transport) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
const ref = (context.CredentialsRef ?? '').trim();
|
|
158
|
+
if (!ref) {
|
|
159
|
+
this.ConfigurationRefusal = NO_CALENDAR_CREDENTIAL_REF_REFUSAL;
|
|
160
|
+
return;
|
|
98
161
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
'Keep AllowLiveFetch false and use FixtureActivitySyncProvider.',
|
|
106
|
-
],
|
|
107
|
-
};
|
|
162
|
+
const factory = this.Factory ?? HostActivityTransportFactory();
|
|
163
|
+
if (!factory) {
|
|
164
|
+
this.ConfigurationRefusal =
|
|
165
|
+
`This connection names credential "${ref}", but no transport factory is registered in ` +
|
|
166
|
+
'this host, so the credential cannot be resolved.';
|
|
167
|
+
return;
|
|
108
168
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
169
|
+
// NOT caught. A factory that throws is a host wiring fault, and swallowing it here would
|
|
170
|
+
// recreate the silent misconfiguration this change exists to end.
|
|
171
|
+
const built = factory(context);
|
|
172
|
+
if (!built) {
|
|
173
|
+
this.ConfigurationRefusal =
|
|
174
|
+
`The transport factory served no transport for credential "${ref}" on driver ` +
|
|
175
|
+
`"${context.DriverClass}".`;
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
this.Transport = built;
|
|
179
|
+
this.ConfigurationRefusal = null;
|
|
180
|
+
}
|
|
181
|
+
async FetchRaw(query) {
|
|
182
|
+
// THE TENANT-WIDE REFUSAL IS CHECKED FIRST, matching the message provider. With no transport
|
|
183
|
+
// and no attestation — the default construction — the useful thing to say is WHY live fetch
|
|
184
|
+
// is off, not that a transport is missing. A recorded transport is exempt: the refusal exists
|
|
185
|
+
// to prevent reading calendars we are not scoped to, and a replay reads none.
|
|
186
|
+
if ((this.Transport?.IsLive ?? true) && !this.AllowLiveFetch) {
|
|
187
|
+
const issues = [LIVE_GRAPH_CALENDAR_REFUSAL];
|
|
188
|
+
if (!this.Transport && this.ConfigurationRefusal) {
|
|
189
|
+
// ALSO true, and with a DIFFERENT fix. Reporting only the first sends an operator to
|
|
190
|
+
// chase an Exchange policy when what is missing is a CredentialsRef or a factory.
|
|
191
|
+
issues.push(this.ConfigurationRefusal);
|
|
120
192
|
}
|
|
121
|
-
return {
|
|
122
|
-
Payloads: (response?.Events ?? []),
|
|
123
|
-
Issues: [],
|
|
124
|
-
};
|
|
193
|
+
return { Payloads: [], Issues: issues };
|
|
125
194
|
}
|
|
126
|
-
|
|
127
|
-
return { Payloads: [], Issues: [
|
|
195
|
+
if (!this.Transport) {
|
|
196
|
+
return { Payloads: [], Issues: [this.ConfigurationRefusal ?? NO_CALENDAR_TRANSPORT_REFUSAL] };
|
|
128
197
|
}
|
|
198
|
+
// Deliberately NOT caught. `BaseActivitySyncProvider.Fetch` already distinguishes a throw
|
|
199
|
+
// ("could not look" — Failed, watermark preserved) from an empty batch ("looked, found
|
|
200
|
+
// nothing"). Swallowing a transport failure into an empty batch would report a successful
|
|
201
|
+
// sync of a calendar we never reached, and advance the watermark past it.
|
|
202
|
+
return await this.Transport.Fetch(query);
|
|
129
203
|
}
|
|
130
204
|
Normalize(raw) {
|
|
131
205
|
const items = [];
|
|
@@ -139,7 +213,7 @@ let MSGraphCalendarSyncProvider = class MSGraphCalendarSyncProvider extends Base
|
|
|
139
213
|
};
|
|
140
214
|
MSGraphCalendarSyncProvider = __decorate([
|
|
141
215
|
RegisterClass(BaseActivitySyncProvider, 'Microsoft365.Calendar'),
|
|
142
|
-
__metadata("design:paramtypes", [Boolean, Object])
|
|
216
|
+
__metadata("design:paramtypes", [Boolean, Object, Function])
|
|
143
217
|
], MSGraphCalendarSyncProvider);
|
|
144
218
|
export { MSGraphCalendarSyncProvider };
|
|
145
219
|
//# sourceMappingURL=MSGraphCalendarSyncProvider.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MSGraphCalendarSyncProvider.js","sourceRoot":"","sources":["../../src/providers/MSGraphCalendarSyncProvider.ts"],"names":[],"mappings":";;;;;;;;;AAAA
|
|
1
|
+
{"version":3,"file":"MSGraphCalendarSyncProvider.js","sourceRoot":"","sources":["../../src/providers/MSGraphCalendarSyncProvider.ts"],"names":[],"mappings":";;;;;;;;;AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAE1E,OAAO,EAAE,4BAA4B,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AAOjG,MAAM,CAAC,MAAM,2BAA2B,GACpC,yFAAyF;IACzF,wFAAwF;IACxF,wFAAwF;IACxF,6FAA6F;IAC7F,4EAA4E,CAAC;AAEjF,MAAM,CAAC,MAAM,6BAA6B,GACtC,4FAA4F;IAC5F,gDAAgD,CAAC;AAErD,MAAM,CAAC,MAAM,kCAAkC,GAC3C,4FAA4F;IAC5F,2FAA2F;IAC3F,uBAAuB,CAAC;AAuB5B,SAAS,SAAS,CAAC,KAAgC;IAC/C,MAAM,OAAO,GAAG,KAAK,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5C,OAAO,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AACpC,CAAC;AAED,SAAS,SAAS,CAAC,IAA0D;IACzE,MAAM,GAAG,GAAG,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACnC,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,QAAQ,IAAI,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5D,IAAI,IAAI,KAAK,KAAK,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACvE,MAAM,OAAO,GAAG,wBAAwB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC;IACrE,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC;IACjC,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;AAC1D,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,aAAa,CAAC,KAAqB,EAAE,MAAgB;IACjE,MAAM,UAAU,GAAG,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC;IACpC,IAAI,CAAC,UAAU,EAAE,CAAC;QACd,MAAM,CAAC,IAAI,CAAC,gEAAgE,CAAC,CAAC;QAC9E,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACzC,IAAI,CAAC,SAAS,EAAE,CAAC;QACb,MAAM,CAAC,IAAI,CAAC,SAAS,UAAU,4CAA4C,CAAC,CAAC;QAC7E,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,MAAM,YAAY,GAAsB,EAAE,CAAC;IAC3C,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,SAAS,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;IACpE,IAAI,SAAS,EAAE,CAAC;QACZ,YAAY,CAAC,IAAI,CAAC;YACd,OAAO,EAAE,SAAS;YAClB,IAAI,EAAE,KAAK,CAAC,SAAS,EAAE,YAAY,EAAE,IAAI,IAAI,IAAI;YACjD,IAAI,EAAE,WAAW;YACjB,YAAY,EAAE,OAAO;SACxB,CAAC,CAAC;IACP,CAAC;IACD,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,SAAS,IAAI,EAAE,EAAE,CAAC;QAC3C,MAAM,OAAO,GAAG,SAAS,CAAC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAC1D,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,SAAS;YAAE,SAAS;QAChD,YAAY,CAAC,IAAI,CAAC;YACd,OAAO,EAAE,OAAO;YAChB,IAAI,EAAE,QAAQ,CAAC,YAAY,EAAE,IAAI,IAAI,IAAI;YACzC,IAAI,EAAE,UAAU;YAChB,YAAY,EAAE,OAAO;SACxB,CAAC,CAAC;IACP,CAAC;IAED,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACrC,OAAO;QACH,UAAU,EAAE,UAAU;QACtB,gBAAgB,EAAE,KAAK,CAAC,cAAc,EAAE,IAAI,EAAE,IAAI,IAAI;QACtD,QAAQ,EAAE,SAAS;QACnB,cAAc,EAAE,KAAK,CAAC,cAAc,KAAK,IAAI;QAC7C,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,cAAc;QAChD,IAAI,EAAE,KAAK,CAAC,WAAW,IAAI,IAAI;QAC/B,SAAS,EAAE,SAAS;QACpB,OAAO,EAAE,OAAO,IAAI,OAAO,CAAC,OAAO,EAAE,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;QAC7E,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,IAAI;QACrD,SAAS,EAAE,UAAU;QACrB,YAAY,EAAE,YAAY;QAC1B,SAAS,EAAE,KAAK,CAAC,WAAW,KAAK,IAAI;QACrC,GAAG,EAAE,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,IAAI,EAAE;KACpD,CAAC;AACN,CAAC;AAGM,IAAM,2BAA2B,GAAjC,MAAM,2BAA4B,SAAQ,wBAAwB;IAIrE;;;;;;;OAOG;IACH,IAAW,MAAM;QACb,OAAO,IAAI,CAAC,SAAS,EAAE,MAAM,IAAI,IAAI,CAAC;IAC1C,CAAC;IAED;IACI;;;;;;;;OAQG;IACc,iBAA0B,0BAA0B,EAAE;IACvE,wFAAwF;IAChF,SAAoC;IAC5C,6EAA6E;IAC5D,OAAkC;QAEnD,KAAK,EAAE,CAAC;QANS,mBAAc,GAAd,cAAc,CAAwC;QAE/D,cAAS,GAAT,SAAS,CAA2B;QAE3B,YAAO,GAAP,OAAO,CAA2B;QA7BvC,SAAI,GAAG,UAAmB,CAAC;QAC3B,qBAAgB,GAAG,cAAc,CAAC;QAiClD,4FAA4F;QACpF,yBAAoB,GAAkB,IAAI,CAAC;IAHnD,CAAC;IAKD;;;;;;;;;OASG;IACa,SAAS,CAAC,OAAiC;QACvD,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,OAAO;QACX,CAAC;QACD,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAClD,IAAI,CAAC,GAAG,EAAE,CAAC;YACP,IAAI,CAAC,oBAAoB,GAAG,kCAAkC,CAAC;YAC/D,OAAO;QACX,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,4BAA4B,EAAE,CAAC;QAC/D,IAAI,CAAC,OAAO,EAAE,CAAC;YACX,IAAI,CAAC,oBAAoB;gBACrB,qCAAqC,GAAG,+CAA+C;oBACvF,kDAAkD,CAAC;YACvD,OAAO;QACX,CAAC;QACD,yFAAyF;QACzF,kEAAkE;QAClE,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;YACT,IAAI,CAAC,oBAAoB;gBACrB,6DAA6D,GAAG,cAAc;oBAC9E,IAAI,OAAO,CAAC,WAAW,IAAI,CAAC;YAChC,OAAO;QACX,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC;IACrC,CAAC;IAES,KAAK,CAAC,QAAQ,CAAC,KAA0B;QAC/C,6FAA6F;QAC7F,4FAA4F;QAC5F,8FAA8F;QAC9F,8EAA8E;QAC9E,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YAC3D,MAAM,MAAM,GAAG,CAAC,2BAA2B,CAAC,CAAC;YAC7C,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;gBAC/C,qFAAqF;gBACrF,kFAAkF;gBAClF,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;YAC3C,CAAC;YACD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAC5C,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YAClB,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,IAAI,CAAC,oBAAoB,IAAI,6BAA6B,CAAC,EAAE,CAAC;QAClG,CAAC;QAED,0FAA0F;QAC1F,uFAAuF;QACvF,0FAA0F;QAC1F,0EAA0E;QAC1E,OAAO,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC7C,CAAC;IAES,SAAS,CAAC,GAAa;QAC7B,MAAM,KAAK,GAAqB,EAAE,CAAC;QACnC,KAAK,MAAM,OAAO,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,aAAa,CAAC,OAAyB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;YACpE,IAAI,MAAM;gBAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC;QACD,OAAO,KAAK,CAAC;IACjB,CAAC;CACJ,CAAA;AA/GY,2BAA2B;IADvC,aAAa,CAAC,wBAAwB,EAAE,uBAAuB,CAAC;;GACpD,2BAA2B,CA+GvC"}
|
|
@@ -78,4 +78,94 @@ export type ActivityTransportFactory = (context: ActivityTransportContext) => Ac
|
|
|
78
78
|
export declare function RegisterActivityTransportFactory(factory: ActivityTransportFactory | null): void;
|
|
79
79
|
/** The registered factory, or null when this host serves none. */
|
|
80
80
|
export declare function HostActivityTransportFactory(): ActivityTransportFactory | null;
|
|
81
|
+
/**
|
|
82
|
+
* WHAT A HOST MUST WRITE DOWN BEFORE IT MAY READ A REAL MAILBOX.
|
|
83
|
+
*
|
|
84
|
+
* `MSGraphProvider` authenticates app-only, so the `Mail.Read` APPLICATION permission is granted
|
|
85
|
+
* against the tenant and not against a mailbox: it reads EVERY mailbox in the organisation. The
|
|
86
|
+
* `Mailbox` on a connection narrows what we ASK for, not what we are ALLOWED to read. The only thing
|
|
87
|
+
* that narrows the grant is an Exchange Application Access Policy binding the app registration to a
|
|
88
|
+
* mail-enabled security group.
|
|
89
|
+
*
|
|
90
|
+
* So the opt-in is not a boolean. A boolean records that somebody wanted live fetch; this records
|
|
91
|
+
* that somebody CHECKED, which group they found, and who is answerable for it — the things an audit
|
|
92
|
+
* actually asks for, and the things a person is forced to look up rather than guess. `Confirmed` is
|
|
93
|
+
* the literal `true` rather than `boolean` deliberately: a variable that happens to be false will
|
|
94
|
+
* not type-check, so the attestation cannot be satisfied by passing a flag through.
|
|
95
|
+
*/
|
|
96
|
+
interface AttestationBase {
|
|
97
|
+
/** Literal `true`. See above — a `boolean` variable is rejected by the compiler. */
|
|
98
|
+
Confirmed: true;
|
|
99
|
+
/** Who decided. A person, so the decision has an owner. */
|
|
100
|
+
ConfirmedBy: string;
|
|
101
|
+
/** When they decided. Policies get deleted; a stale attestation should be visible as stale. */
|
|
102
|
+
ConfirmedAt: Date;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* The app registration is restricted, and this names the restriction.
|
|
106
|
+
*/
|
|
107
|
+
export interface ScopedMailboxAttestation extends AttestationBase {
|
|
108
|
+
Scope: 'RestrictedToGroup';
|
|
109
|
+
/** The mail-enabled security group the Exchange assignment binds the app to. */
|
|
110
|
+
ScopedToGroup: string;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The tenant-wide grant was looked at and ACCEPTED. A real outcome, not a failure state.
|
|
114
|
+
*
|
|
115
|
+
* WHY THIS EXISTS AT ALL. The first version of this type demanded `ScopedToGroup`, which quietly
|
|
116
|
+
* assumed every deployment would create an Exchange RBAC assignment. Most do not — adding an API
|
|
117
|
+
* permission in Entra is one team's five-minute job, and Exchange RBAC for Applications is a
|
|
118
|
+
* different system that often nobody owns. A gate that only accepts "scoped" leaves an organisation
|
|
119
|
+
* that decided otherwise with two options: invent a group name, or bypass the gate. Both are worse
|
|
120
|
+
* than what it was protecting, because both destroy the record.
|
|
121
|
+
*
|
|
122
|
+
* So the shape now matches the decisions people actually make. What stays impossible is the third
|
|
123
|
+
* state — nobody looked — because neither variant can be satisfied without a name, a date, and
|
|
124
|
+
* either a group or a written reason.
|
|
125
|
+
*/
|
|
126
|
+
export interface TenantWideMailboxAttestation extends AttestationBase {
|
|
127
|
+
Scope: 'TenantWideAccepted';
|
|
128
|
+
/**
|
|
129
|
+
* What is being accepted, in the deciding person's own words.
|
|
130
|
+
*
|
|
131
|
+
* Free text and REQUIRED, deliberately. A boolean here would be a tick-box, and a tick-box records
|
|
132
|
+
* that somebody clicked rather than that somebody understood. Writing the sentence is the point:
|
|
133
|
+
* it is what an audit reads, and what the next person finds when they ask why this app can read
|
|
134
|
+
* every mailbox in the tenant.
|
|
135
|
+
*/
|
|
136
|
+
AcceptedRisk: string;
|
|
137
|
+
}
|
|
138
|
+
export type LiveMailboxPolicyAttestation = ScopedMailboxAttestation | TenantWideMailboxAttestation;
|
|
139
|
+
/**
|
|
140
|
+
* Record that this host is scoped, and may therefore read real mailboxes. Pass null to revoke.
|
|
141
|
+
*
|
|
142
|
+
* DELIBERATELY NOT DRIVEN BY DATA. `ActivitySyncConnection` is an ordinary editable entity, and
|
|
143
|
+
* anyone who can edit a row could otherwise turn on tenant-wide mail reading by typing in a form.
|
|
144
|
+
* The same reasoning already applies to the transport itself — "a database row should not be able to
|
|
145
|
+
* reach in and swap it" — and it applies with more force here. This is a bootstrap-time decision in
|
|
146
|
+
* code, made by whoever deploys the host.
|
|
147
|
+
*
|
|
148
|
+
* The blank checks are the point rather than defensive noise: an attestation with an empty group or
|
|
149
|
+
* no name records nothing, and silently accepting one would turn this back into a boolean.
|
|
150
|
+
*
|
|
151
|
+
* ── EVERY INVARIANT IS ENFORCED HERE, NOT ONLY IN THE ENV LOADER ────────────────────────────────
|
|
152
|
+
*
|
|
153
|
+
* `LoadLiveMailboxPolicyFromEnv` validates all of this and is the path a deployment takes. It is not
|
|
154
|
+
* the only path: this function is exported, and a host bootstrap, a `.mjs` harness or any TypeScript
|
|
155
|
+
* caller with a cast reaches it directly — where `Confirmed: true` and `ConfirmedAt: Date` are
|
|
156
|
+
* compile-time shapes that enforce nothing at runtime. Checking them only in the loader made the
|
|
157
|
+
* guarantee a property of one caller rather than of the gate, so an attestation with no date, or with
|
|
158
|
+
* `Confirmed: false`, was accepted and opened tenant-wide mail AND calendar for the whole host.
|
|
159
|
+
*
|
|
160
|
+
* WHAT IS DELIBERATELY NOT CHECKED is staleness. An attestation that expired on a date boundary would
|
|
161
|
+
* turn live fetch off on a working deployment with no one having changed anything, which trades a
|
|
162
|
+
* reviewed decision for a silent outage. The date is required so the record is honest about WHEN, not
|
|
163
|
+
* so it can lapse.
|
|
164
|
+
*/
|
|
165
|
+
export declare function AllowLiveMailboxFetch(attestation: LiveMailboxPolicyAttestation | null): void;
|
|
166
|
+
/** The recorded attestation, or null when this host has not opted in. */
|
|
167
|
+
export declare function HostLiveMailboxPolicy(): LiveMailboxPolicyAttestation | null;
|
|
168
|
+
/** Whether this host has attested that its app registration is scoped. */
|
|
169
|
+
export declare function HostAllowsLiveMailboxFetch(): boolean;
|
|
170
|
+
export {};
|
|
81
171
|
//# sourceMappingURL=MessageTransport.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageTransport.d.ts","sourceRoot":"","sources":["../../src/providers/MessageTransport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEjE;;;;;;GAMG;AACH,MAAM,WAAW,wBAAwB;IACrC,oGAAoG;IACpG,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAEzB,KAAK,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CACxD;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,wBAAwB;IACrC,oGAAoG;IACpG,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,2FAA2F;IAC3F,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,gGAAgG;IAChG,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,QAAQ,CAAC;CAC1B;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,OAAO,EAAE,wBAAwB,KAAK,wBAAwB,GAAG,IAAI,CAAC;AAmB9G;;;;;GAKG;AACH,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,wBAAwB,GAAG,IAAI,GAAG,IAAI,CAE/F;AAED,kEAAkE;AAClE,wBAAgB,4BAA4B,IAAI,wBAAwB,GAAG,IAAI,CAE9E"}
|
|
1
|
+
{"version":3,"file":"MessageTransport.d.ts","sourceRoot":"","sources":["../../src/providers/MessageTransport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEjE;;;;;;GAMG;AACH,MAAM,WAAW,wBAAwB;IACrC,oGAAoG;IACpG,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAEzB,KAAK,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CACxD;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,wBAAwB;IACrC,oGAAoG;IACpG,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,2FAA2F;IAC3F,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,gGAAgG;IAChG,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,QAAQ,CAAC;CAC1B;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,OAAO,EAAE,wBAAwB,KAAK,wBAAwB,GAAG,IAAI,CAAC;AAmB9G;;;;;GAKG;AACH,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,wBAAwB,GAAG,IAAI,GAAG,IAAI,CAE/F;AAED,kEAAkE;AAClE,wBAAgB,4BAA4B,IAAI,wBAAwB,GAAG,IAAI,CAE9E;AAED;;;;;;;;;;;;;;GAcG;AACH,UAAU,eAAe;IACrB,oFAAoF;IACpF,SAAS,EAAE,IAAI,CAAC;IAChB,2DAA2D;IAC3D,WAAW,EAAE,MAAM,CAAC;IACpB,+FAA+F;IAC/F,WAAW,EAAE,IAAI,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,wBAAyB,SAAQ,eAAe;IAC7D,KAAK,EAAE,mBAAmB,CAAC;IAC3B,gFAAgF;IAChF,aAAa,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,4BAA6B,SAAQ,eAAe;IACjE,KAAK,EAAE,oBAAoB,CAAC;IAC5B;;;;;;;OAOG;IACH,YAAY,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,4BAA4B,GAAG,wBAAwB,GAAG,4BAA4B,CAAC;AAInG;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,4BAA4B,GAAG,IAAI,GAAG,IAAI,CA2C5F;AAED,yEAAyE;AACzE,wBAAgB,qBAAqB,IAAI,4BAA4B,GAAG,IAAI,CAE3E;AAED,0EAA0E;AAC1E,wBAAgB,0BAA0B,IAAI,OAAO,CAEpD"}
|
|
@@ -27,4 +27,76 @@ export function RegisterActivityTransportFactory(factory) {
|
|
|
27
27
|
export function HostActivityTransportFactory() {
|
|
28
28
|
return hostFactory;
|
|
29
29
|
}
|
|
30
|
+
let hostLivePolicy = null;
|
|
31
|
+
/**
|
|
32
|
+
* Record that this host is scoped, and may therefore read real mailboxes. Pass null to revoke.
|
|
33
|
+
*
|
|
34
|
+
* DELIBERATELY NOT DRIVEN BY DATA. `ActivitySyncConnection` is an ordinary editable entity, and
|
|
35
|
+
* anyone who can edit a row could otherwise turn on tenant-wide mail reading by typing in a form.
|
|
36
|
+
* The same reasoning already applies to the transport itself — "a database row should not be able to
|
|
37
|
+
* reach in and swap it" — and it applies with more force here. This is a bootstrap-time decision in
|
|
38
|
+
* code, made by whoever deploys the host.
|
|
39
|
+
*
|
|
40
|
+
* The blank checks are the point rather than defensive noise: an attestation with an empty group or
|
|
41
|
+
* no name records nothing, and silently accepting one would turn this back into a boolean.
|
|
42
|
+
*
|
|
43
|
+
* ── EVERY INVARIANT IS ENFORCED HERE, NOT ONLY IN THE ENV LOADER ────────────────────────────────
|
|
44
|
+
*
|
|
45
|
+
* `LoadLiveMailboxPolicyFromEnv` validates all of this and is the path a deployment takes. It is not
|
|
46
|
+
* the only path: this function is exported, and a host bootstrap, a `.mjs` harness or any TypeScript
|
|
47
|
+
* caller with a cast reaches it directly — where `Confirmed: true` and `ConfirmedAt: Date` are
|
|
48
|
+
* compile-time shapes that enforce nothing at runtime. Checking them only in the loader made the
|
|
49
|
+
* guarantee a property of one caller rather than of the gate, so an attestation with no date, or with
|
|
50
|
+
* `Confirmed: false`, was accepted and opened tenant-wide mail AND calendar for the whole host.
|
|
51
|
+
*
|
|
52
|
+
* WHAT IS DELIBERATELY NOT CHECKED is staleness. An attestation that expired on a date boundary would
|
|
53
|
+
* turn live fetch off on a working deployment with no one having changed anything, which trades a
|
|
54
|
+
* reviewed decision for a silent outage. The date is required so the record is honest about WHEN, not
|
|
55
|
+
* so it can lapse.
|
|
56
|
+
*/
|
|
57
|
+
export function AllowLiveMailboxFetch(attestation) {
|
|
58
|
+
if (attestation === null) {
|
|
59
|
+
hostLivePolicy = null;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
// `Confirmed: true` is a literal type, so TypeScript rejects `false` at a typed call site and
|
|
63
|
+
// nothing rejects it anywhere else. An unconfirmed attestation is a decision not yet made.
|
|
64
|
+
if (attestation.Confirmed !== true) {
|
|
65
|
+
throw new Error('AllowLiveMailboxFetch requires Confirmed === true. An attestation that does not confirm ' +
|
|
66
|
+
'anything is not a decision, and live fetch stays off until one is made.');
|
|
67
|
+
}
|
|
68
|
+
if (!attestation.ConfirmedBy?.trim()) {
|
|
69
|
+
throw new Error('AllowLiveMailboxFetch requires ConfirmedBy — who made this decision.');
|
|
70
|
+
}
|
|
71
|
+
// WHEN, and a real date. The whole point of the record is that someone can later ask when this was
|
|
72
|
+
// agreed; an Invalid Date answers that question with silence.
|
|
73
|
+
const confirmedAt = attestation.ConfirmedAt;
|
|
74
|
+
if (!(confirmedAt instanceof Date) || Number.isNaN(confirmedAt.getTime())) {
|
|
75
|
+
throw new Error('AllowLiveMailboxFetch requires ConfirmedAt — a valid Date saying when this was decided. ' +
|
|
76
|
+
'Reading the mail of an entire organisation on an undated say-so is not auditable.');
|
|
77
|
+
}
|
|
78
|
+
if (attestation.Scope === 'RestrictedToGroup') {
|
|
79
|
+
if (!attestation.ScopedToGroup?.trim()) {
|
|
80
|
+
throw new Error('A RestrictedToGroup attestation requires ScopedToGroup — the mail-enabled security ' +
|
|
81
|
+
'group the Exchange assignment binds the app registration to. Run ' +
|
|
82
|
+
'Get-ManagementRoleAssignment (or Get-ApplicationAccessPolicy on older tenants) to find it.');
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
if (!attestation.AcceptedRisk?.trim()) {
|
|
87
|
+
throw new Error('A TenantWideAccepted attestation requires AcceptedRisk — a sentence saying what is ' +
|
|
88
|
+
'being accepted. Accepting that this app can read every mailbox in the tenant is a ' +
|
|
89
|
+
'legitimate decision; recording it as a bare flag is not.');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
hostLivePolicy = attestation;
|
|
93
|
+
}
|
|
94
|
+
/** The recorded attestation, or null when this host has not opted in. */
|
|
95
|
+
export function HostLiveMailboxPolicy() {
|
|
96
|
+
return hostLivePolicy;
|
|
97
|
+
}
|
|
98
|
+
/** Whether this host has attested that its app registration is scoped. */
|
|
99
|
+
export function HostAllowsLiveMailboxFetch() {
|
|
100
|
+
return hostLivePolicy !== null;
|
|
101
|
+
}
|
|
30
102
|
//# sourceMappingURL=MessageTransport.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageTransport.js","sourceRoot":"","sources":["../../src/providers/MessageTransport.ts"],"names":[],"mappings":"AA8EA;;;;;;;;;;;;;;GAcG;AACH,IAAI,WAAW,GAAoC,IAAI,CAAC;AAExD;;;;;GAKG;AACH,MAAM,UAAU,gCAAgC,CAAC,OAAwC;IACrF,WAAW,GAAG,OAAO,CAAC;AAC1B,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,4BAA4B;IACxC,OAAO,WAAW,CAAC;AACvB,CAAC"}
|
|
1
|
+
{"version":3,"file":"MessageTransport.js","sourceRoot":"","sources":["../../src/providers/MessageTransport.ts"],"names":[],"mappings":"AA8EA;;;;;;;;;;;;;;GAcG;AACH,IAAI,WAAW,GAAoC,IAAI,CAAC;AAExD;;;;;GAKG;AACH,MAAM,UAAU,gCAAgC,CAAC,OAAwC;IACrF,WAAW,GAAG,OAAO,CAAC;AAC1B,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,4BAA4B;IACxC,OAAO,WAAW,CAAC;AACvB,CAAC;AAgED,IAAI,cAAc,GAAwC,IAAI,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,qBAAqB,CAAC,WAAgD;IAClF,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;QACvB,cAAc,GAAG,IAAI,CAAC;QACtB,OAAO;IACX,CAAC;IACD,8FAA8F;IAC9F,2FAA2F;IAC3F,IAAI,WAAW,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CACX,0FAA0F;YACtF,yEAAyE,CAChF,CAAC;IACN,CAAC;IACD,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,IAAI,EAAE,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,sEAAsE,CAAC,CAAC;IAC5F,CAAC;IACD,mGAAmG;IACnG,8DAA8D;IAC9D,MAAM,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC;IAC5C,IAAI,CAAC,CAAC,WAAW,YAAY,IAAI,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;QACxE,MAAM,IAAI,KAAK,CACX,0FAA0F;YACtF,mFAAmF,CAC1F,CAAC;IACN,CAAC;IACD,IAAI,WAAW,CAAC,KAAK,KAAK,mBAAmB,EAAE,CAAC;QAC5C,IAAI,CAAC,WAAW,CAAC,aAAa,EAAE,IAAI,EAAE,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CACX,qFAAqF;gBACjF,mEAAmE;gBACnE,4FAA4F,CACnG,CAAC;QACN,CAAC;IACL,CAAC;SAAM,CAAC;QACJ,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,IAAI,EAAE,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CACX,qFAAqF;gBACjF,oFAAoF;gBACpF,0DAA0D,CACjE,CAAC;QACN,CAAC;IACL,CAAC;IACD,cAAc,GAAG,WAAW,CAAC;AACjC,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,qBAAqB;IACjC,OAAO,cAAc,CAAC;AAC1B,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,0BAA0B;IACtC,OAAO,cAAc,KAAK,IAAI,CAAC;AACnC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RecordedMessageTransport.d.ts","sourceRoot":"","sources":["../../src/providers/RecordedMessageTransport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAEtE,4EAA4E;AAC5E,MAAM,WAAW,eAAe;IAC5B,6FAA6F;IAC7F,OAAO,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACpC,8FAA8F;IAC9F,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,wBAAyB,YAAW,wBAAwB;IACrE,SAAgB,QAAQ,EAAE,MAAM,CAAC;IAEjC;;;OAGG;IACH,SAAgB,MAAM,SAAS;IAE/B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA+B;gBAEtC,UAAU,EAAE,eAAe,EAAE;IAKnC,KAAK,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"RecordedMessageTransport.d.ts","sourceRoot":"","sources":["../../src/providers/RecordedMessageTransport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAEtE,4EAA4E;AAC5E,MAAM,WAAW,eAAe;IAC5B,6FAA6F;IAC7F,OAAO,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACpC,8FAA8F;IAC9F,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,wBAAyB,YAAW,wBAAwB;IACrE,SAAgB,QAAQ,EAAE,MAAM,CAAC;IAEjC;;;OAGG;IACH,SAAgB,MAAM,SAAS;IAE/B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA+B;gBAEtC,UAAU,EAAE,eAAe,EAAE;IAKnC,KAAK,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC;CA2DpE"}
|
|
@@ -30,20 +30,34 @@ export class RecordedMessageTransport {
|
|
|
30
30
|
`${recording.Payloads.length - query.Limit} were not returned.`);
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
|
-
* A CAPPED REPLAY WITHHOLDS THE WATERMARK
|
|
33
|
+
* A CAPPED REPLAY WITHHOLDS THE WATERMARK. ON EVERY RUN, INCLUDING THE FIRST.
|
|
34
34
|
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* be safe.
|
|
35
|
+
* This used to read `capped && !!query.Since`, on the reasoning that a first run has no
|
|
36
|
+
* watermark and so nothing to strand behind one. That reasoning is wrong, and the way it is
|
|
37
|
+
* wrong is worth writing down, because it is the same shape as the live-path defect this
|
|
38
|
+
* package was just fixed for.
|
|
40
39
|
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
40
|
+
* The loss on a first run is not about an EXISTING watermark. It is about the watermark the
|
|
41
|
+
* run CREATES. Nothing enforces the order of a recording, and a NEWEST-FIRST one truncated to
|
|
42
|
+
* Limit returns the newest N and withholds the oldest; a watermark computed from what it DID
|
|
43
|
+
* return is then NEWER than the payloads it did not, and those are buried behind a mark that
|
|
44
|
+
* claims to cover them. That is the live bug exactly, reached without a prior watermark.
|
|
45
|
+
*
|
|
46
|
+
* It matters past the fixture because the mark is DURABLE and the transport behind it is
|
|
47
|
+
* swappable: a host that replays a truncated recording and later points the same connection
|
|
48
|
+
* at the live transport inherits the claim, and the live run skips real mail.
|
|
49
|
+
*
|
|
50
|
+
* So the flag is set whenever the limit binds, exactly as the live path now does. Withholding
|
|
51
|
+
* costs a re-read that de-duplication absorbs. Advancing costs correctness of the watermark.
|
|
52
|
+
*
|
|
53
|
+
* WHAT THIS DOES NOT FIX, so nobody reads more into it. `slice(0, Limit)` is POSITIONAL and
|
|
54
|
+
* the window is applied downstream, so a truncated replay re-takes the same first N payloads
|
|
55
|
+
* on every run whatever `Since` says. A recording longer than Limit cannot be replayed in
|
|
56
|
+
* full, in any order, capped or not — measured, not assumed. This flag keeps that from
|
|
57
|
+
* becoming a false watermark in the database; giving the fixture transport real paging is a
|
|
58
|
+
* separate change, and the Issues above already name the shortfall on every run.
|
|
45
59
|
*/
|
|
46
|
-
return { Payloads: payloads, Issues: issues, Capped: capped
|
|
60
|
+
return { Payloads: payloads, Issues: issues, Capped: capped };
|
|
47
61
|
}
|
|
48
62
|
}
|
|
49
63
|
//# sourceMappingURL=RecordedMessageTransport.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RecordedMessageTransport.js","sourceRoot":"","sources":["../../src/providers/RecordedMessageTransport.ts"],"names":[],"mappings":"AAsCA,MAAM,OAAO,wBAAwB;IAWjC,YAAmB,UAA6B;QARhD;;;WAGG;QACa,WAAM,GAAG,KAAK,CAAC;QAK3B,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACrF,IAAI,CAAC,QAAQ,GAAG,4BAA4B,UAAU,CAAC,MAAM,eAAe,CAAC;IACjF,CAAC;IAEM,KAAK,CAAC,KAAK,CAAC,KAA0B;QACzC,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACvD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAE1C,IAAI,CAAC,SAAS,EAAE,CAAC;YACb,sFAAsF;YACtF,mFAAmF;YACnF,wDAAwD;YACxD,MAAM,IAAI,KAAK,CACX,qCAAqC,KAAK,CAAC,OAAO,KAAK;gBACnD,uBAAuB,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,GAAG,CAClF,CAAC;QACN,CAAC;QAED,6FAA6F;QAC7F,iEAAiE;QACjE,MAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAE1D,MAAM,MAAM,GAAG;YACX,uBAAuB,SAAS,CAAC,UAAU,oDAAoD;SAClG,CAAC;QACF,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC;QACvD,IAAI,MAAM,EAAE,CAAC;YACT,MAAM,CAAC,IAAI,CACP,mBAAmB,SAAS,CAAC,QAAQ,CAAC,MAAM,yBAAyB,KAAK,CAAC,KAAK,OAAO;gBACnF,GAAG,SAAS,CAAC,QAAQ,CAAC,MAAM,GAAG,KAAK,CAAC,KAAK,qBAAqB,CACtE,CAAC;QACN,CAAC;QAED
|
|
1
|
+
{"version":3,"file":"RecordedMessageTransport.js","sourceRoot":"","sources":["../../src/providers/RecordedMessageTransport.ts"],"names":[],"mappings":"AAsCA,MAAM,OAAO,wBAAwB;IAWjC,YAAmB,UAA6B;QARhD;;;WAGG;QACa,WAAM,GAAG,KAAK,CAAC;QAK3B,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACrF,IAAI,CAAC,QAAQ,GAAG,4BAA4B,UAAU,CAAC,MAAM,eAAe,CAAC;IACjF,CAAC;IAEM,KAAK,CAAC,KAAK,CAAC,KAA0B;QACzC,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACvD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAE1C,IAAI,CAAC,SAAS,EAAE,CAAC;YACb,sFAAsF;YACtF,mFAAmF;YACnF,wDAAwD;YACxD,MAAM,IAAI,KAAK,CACX,qCAAqC,KAAK,CAAC,OAAO,KAAK;gBACnD,uBAAuB,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,GAAG,CAClF,CAAC;QACN,CAAC;QAED,6FAA6F;QAC7F,iEAAiE;QACjE,MAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAE1D,MAAM,MAAM,GAAG;YACX,uBAAuB,SAAS,CAAC,UAAU,oDAAoD;SAClG,CAAC;QACF,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC;QACvD,IAAI,MAAM,EAAE,CAAC;YACT,MAAM,CAAC,IAAI,CACP,mBAAmB,SAAS,CAAC,QAAQ,CAAC,MAAM,yBAAyB,KAAK,CAAC,KAAK,OAAO;gBACnF,GAAG,SAAS,CAAC,QAAQ,CAAC,MAAM,GAAG,KAAK,CAAC,KAAK,qBAAqB,CACtE,CAAC;QACN,CAAC;QAED;;;;;;;;;;;;;;;;;;;;;;;;;;;WA2BG;QACH,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAClE,CAAC;CACJ"}
|
package/dist/stages.d.ts
CHANGED
|
@@ -44,6 +44,17 @@ export interface RuleRow {
|
|
|
44
44
|
DateTo: Date | string | null;
|
|
45
45
|
ParticipantScope: ParticipantScope | null;
|
|
46
46
|
ActivitySyncRuleSetID: string | null;
|
|
47
|
+
/**
|
|
48
|
+
* `1 = also pull attachments into ActivityFile rows` — the column's own description.
|
|
49
|
+
*
|
|
50
|
+
* On the RULE rather than the connection because it is a per-decision choice: a rule that files
|
|
51
|
+
* customer threads may well want the contract attached, while one filing internal chatter does
|
|
52
|
+
* not. It is read at WRITE time from the rule that decided, not at fetch time, because rules run
|
|
53
|
+
* after the fetch.
|
|
54
|
+
*/
|
|
55
|
+
IncludeAttachments: boolean;
|
|
56
|
+
/** Attachments larger than this are skipped and REPORTED. Null means no cap. */
|
|
57
|
+
MaxAttachmentBytes: number | null;
|
|
47
58
|
}
|
|
48
59
|
export interface KnownAddressHit {
|
|
49
60
|
Address: string;
|