@nlabs/reaktor 1.19.0 → 1.20.0-reactorbox.1

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.
Files changed (139) hide show
  1. package/README.md +290 -0
  2. package/docs/GENERATION.md +4 -0
  3. package/lib/actions/apps.js +17 -2
  4. package/lib/actions/contentGeneration.d.ts +19 -1
  5. package/lib/actions/contentGeneration.js +59 -24
  6. package/lib/actions/contentGenerationSources.d.ts +29 -0
  7. package/lib/actions/contentGenerationSources.js +103 -0
  8. package/lib/actions/crm.d.ts +6 -2
  9. package/lib/actions/crm.js +91 -12
  10. package/lib/actions/crmCanonicalOutcomes.d.ts +88 -0
  11. package/lib/actions/crmCanonicalOutcomes.js +398 -0
  12. package/lib/actions/crmCanonicalPolicy.d.ts +92 -0
  13. package/lib/actions/crmCanonicalPolicy.js +104 -0
  14. package/lib/actions/crmCheckoutRecovery.d.ts +72 -0
  15. package/lib/actions/crmCheckoutRecovery.js +413 -0
  16. package/lib/actions/crmCheckoutRecoveryPolicy.d.ts +38 -0
  17. package/lib/actions/crmCheckoutRecoveryPolicy.js +61 -0
  18. package/lib/actions/crmDeliveryEvents.d.ts +24 -0
  19. package/lib/actions/crmDeliveryEvents.js +207 -0
  20. package/lib/actions/crmDeliveryEvidence.d.ts +17 -0
  21. package/lib/actions/crmDeliveryEvidence.js +58 -0
  22. package/lib/actions/crmExecution.d.ts +125 -0
  23. package/lib/actions/crmExecution.js +830 -0
  24. package/lib/actions/crmFinancialEvidence.d.ts +12 -0
  25. package/lib/actions/crmFinancialEvidence.js +60 -0
  26. package/lib/actions/crmInsights.d.ts +60 -0
  27. package/lib/actions/crmInsights.js +225 -0
  28. package/lib/actions/crmLeadFollowups.d.ts +66 -0
  29. package/lib/actions/crmLeadFollowups.js +209 -0
  30. package/lib/actions/crmOutcomes.d.ts +106 -0
  31. package/lib/actions/crmOutcomes.js +289 -0
  32. package/lib/actions/crmRecoveryRetention.d.ts +13 -0
  33. package/lib/actions/crmRecoveryRetention.js +163 -0
  34. package/lib/actions/crmReminderDispatch.d.ts +10 -0
  35. package/lib/actions/crmReminderDispatch.js +65 -0
  36. package/lib/actions/crmSourceOwnership.d.ts +7 -0
  37. package/lib/actions/crmSourceOwnership.js +27 -0
  38. package/lib/actions/crmSupportInsights.d.ts +18 -0
  39. package/lib/actions/crmSupportInsights.js +47 -0
  40. package/lib/actions/crmWinback.d.ts +71 -0
  41. package/lib/actions/crmWinback.js +347 -0
  42. package/lib/actions/crmWinbackConsent.d.ts +29 -0
  43. package/lib/actions/crmWinbackConsent.js +158 -0
  44. package/lib/actions/crmWinbackPolicy.d.ts +33 -0
  45. package/lib/actions/crmWinbackPolicy.js +115 -0
  46. package/lib/actions/crmWinbackShopSource.d.ts +15 -0
  47. package/lib/actions/crmWinbackShopSource.js +63 -0
  48. package/lib/actions/email.d.ts +4 -1
  49. package/lib/actions/email.js +25 -3
  50. package/lib/actions/index.d.ts +56 -0
  51. package/lib/actions/index.js +42 -1
  52. package/lib/actions/merchantAccountExperiment.d.ts +50 -0
  53. package/lib/actions/merchantAccountExperiment.js +424 -0
  54. package/lib/actions/merchantAccountExperimentConfig.d.ts +7 -0
  55. package/lib/actions/merchantAccountExperimentConfig.js +32 -0
  56. package/lib/actions/merchantAccountExperimentHost.d.ts +69 -0
  57. package/lib/actions/merchantAccountExperimentHost.js +92 -0
  58. package/lib/actions/merchantAccountExperimentPolicy.d.ts +66 -0
  59. package/lib/actions/merchantAccountExperimentPolicy.js +121 -0
  60. package/lib/actions/merchantAccountExperimentRelay.d.ts +10 -0
  61. package/lib/actions/merchantAccountExperimentRelay.js +75 -0
  62. package/lib/actions/merchantCalendar.d.ts +34 -0
  63. package/lib/actions/merchantCalendar.js +119 -0
  64. package/lib/actions/merchantCalendarBookings.d.ts +17 -0
  65. package/lib/actions/merchantCalendarBookings.js +113 -0
  66. package/lib/actions/merchantCalendarDelegation.d.ts +80 -0
  67. package/lib/actions/merchantCalendarDelegation.js +353 -0
  68. package/lib/actions/merchantCalendarDiscovery.d.ts +38 -0
  69. package/lib/actions/merchantCalendarDiscovery.js +124 -0
  70. package/lib/actions/merchantCalendarEventHost.d.ts +105 -0
  71. package/lib/actions/merchantCalendarEventHost.js +16 -0
  72. package/lib/actions/merchantCalendarEventPrivacy.d.ts +7 -0
  73. package/lib/actions/merchantCalendarEventPrivacy.js +70 -0
  74. package/lib/actions/merchantCalendarEventRepository.d.ts +121 -0
  75. package/lib/actions/merchantCalendarEventRepository.js +295 -0
  76. package/lib/actions/merchantCalendarEventTransport.d.ts +65 -0
  77. package/lib/actions/merchantCalendarEventTransport.js +132 -0
  78. package/lib/actions/merchantCalendarEvents.d.ts +172 -0
  79. package/lib/actions/merchantCalendarEvents.js +365 -0
  80. package/lib/actions/merchantCalendarInvitationConsent.d.ts +28 -0
  81. package/lib/actions/merchantCalendarInvitationConsent.js +118 -0
  82. package/lib/actions/merchantCalendarManagedSource.d.ts +22 -0
  83. package/lib/actions/merchantCalendarManagedSource.js +24 -0
  84. package/lib/actions/merchantCalendarOAuth.d.ts +92 -0
  85. package/lib/actions/merchantCalendarOAuth.js +502 -0
  86. package/lib/actions/merchantCalendarOAuthConfig.d.ts +4 -0
  87. package/lib/actions/merchantCalendarOAuthConfig.js +30 -0
  88. package/lib/actions/merchantCalendarOAuthRepository.d.ts +57 -0
  89. package/lib/actions/merchantCalendarOAuthRepository.js +108 -0
  90. package/lib/actions/merchantCalendarOAuthTransport.d.ts +4 -0
  91. package/lib/actions/merchantCalendarOAuthTransport.js +25 -0
  92. package/lib/actions/merchantCalendarScopes.d.ts +4 -0
  93. package/lib/actions/merchantCalendarScopes.js +31 -0
  94. package/lib/actions/merchantFinance.d.ts +65 -0
  95. package/lib/actions/merchantFinance.js +244 -0
  96. package/lib/actions/merchantFinanceProvider.d.ts +57 -0
  97. package/lib/actions/merchantFinanceProvider.js +180 -0
  98. package/lib/actions/merchantOperations.d.ts +94 -0
  99. package/lib/actions/merchantOperations.js +489 -0
  100. package/lib/actions/providerCredentials.d.ts +35 -0
  101. package/lib/actions/providerCredentials.js +166 -0
  102. package/lib/actions/s3.d.ts +10 -7
  103. package/lib/actions/s3.js +59 -14
  104. package/lib/actions/supportChannelSources.d.ts +66 -0
  105. package/lib/actions/supportChannelSources.js +183 -0
  106. package/lib/actions/supportCommerce.d.ts +62 -0
  107. package/lib/actions/supportCommerce.js +252 -0
  108. package/lib/actions/supportConnect.d.ts +39 -0
  109. package/lib/actions/supportConnect.js +224 -0
  110. package/lib/actions/supportContext.d.ts +31 -0
  111. package/lib/actions/supportContext.js +88 -0
  112. package/lib/actions/supportConversation.d.ts +102 -0
  113. package/lib/actions/supportConversation.js +100 -0
  114. package/lib/actions/supportEmailEvents.d.ts +20 -0
  115. package/lib/actions/supportEmailEvents.js +130 -0
  116. package/lib/actions/supportEmailHandoff.d.ts +114 -0
  117. package/lib/actions/supportEmailHandoff.js +356 -0
  118. package/lib/actions/supportOperations.d.ts +32 -0
  119. package/lib/actions/supportOperations.js +74 -0
  120. package/lib/actions/supportPolicy.d.ts +9 -0
  121. package/lib/actions/supportPolicy.js +44 -0
  122. package/lib/actions/supportPurposeConsent.d.ts +32 -0
  123. package/lib/actions/supportPurposeConsent.js +196 -0
  124. package/lib/actions/supportPurposePrivacy.d.ts +15 -0
  125. package/lib/actions/supportPurposePrivacy.js +181 -0
  126. package/lib/actions/supportSemanticReview.d.ts +64 -0
  127. package/lib/actions/supportSemanticReview.js +239 -0
  128. package/lib/actions/users.js +22 -3
  129. package/lib/constants/collections.d.ts +2 -1
  130. package/lib/constants/collections.js +2 -1
  131. package/lib/mutations/crm/crm.js +395 -7
  132. package/lib/queries/crm/crm.js +251 -5
  133. package/lib/types/auth.types.d.ts +2 -0
  134. package/lib/types/crm.types.d.ts +6 -0
  135. package/lib/types/users.types.d.ts +2 -0
  136. package/lib/utils/authUtils.js +17 -1
  137. package/lib/utils/graphqlUtils.d.ts +2 -0
  138. package/lib/utils/stripeUtils.ts.bak +1 -1
  139. package/package.json +8 -6
@@ -0,0 +1,88 @@
1
+ import type { ApiContext } from '../types/auth.types.js';
2
+ import type { CrmCanonicalEvent, CrmVerifiedFinancialProviderEvidence } from './crmCanonicalPolicy.js';
3
+ import type { CrmOutcomeGrantBounds } from './crmInsights.js';
4
+ export interface CrmCanonicalReadInput {
5
+ appId: string;
6
+ campaignId: string;
7
+ financial?: boolean;
8
+ organizationId: string;
9
+ projectId: string;
10
+ }
11
+ export interface CrmCanonicalFinanceBindingInput extends CrmCanonicalReadInput {
12
+ associationId: string;
13
+ evidenceRef: string;
14
+ expectedRevision: number;
15
+ expectedSourceRevisions: {
16
+ association: number;
17
+ invoice: string;
18
+ nativePayment: string;
19
+ order: string;
20
+ paymentEvidence: string;
21
+ user: string;
22
+ };
23
+ id: string;
24
+ invoiceId: string;
25
+ issuerId: string;
26
+ nativePaymentId: string;
27
+ paymentEvidenceId: string;
28
+ status: 'active' | 'revoked';
29
+ }
30
+ export interface CrmCanonicalFinancialObservation {
31
+ evidence: CrmVerifiedFinancialProviderEvidence;
32
+ id: string;
33
+ issuerId: string;
34
+ nativeOrderId: string;
35
+ revision: string;
36
+ shopifyCustomerId?: string;
37
+ shopifyOrderId?: string;
38
+ status: 'verified_settlement_namespace_unproven';
39
+ }
40
+ export interface CrmCanonicalSnapshot {
41
+ appId: string;
42
+ campaignId: string;
43
+ complete: boolean;
44
+ events: CrmCanonicalEvent[];
45
+ financialObservations: CrmCanonicalFinancialObservation[];
46
+ generatedAt: string;
47
+ held: Record<string, number>;
48
+ issuerIds?: string[];
49
+ organizationId: string;
50
+ projectId: string;
51
+ revision: number;
52
+ schemaVersion: 'crm_canonical_outcomes_v1';
53
+ sourceKind: 'lifecycle' | 'financial';
54
+ validUntil: string;
55
+ }
56
+ export declare const createCrmCanonicalReadKey: (context: ApiContext, appId: string, bounds: CrmOutcomeGrantBounds, financial: boolean, expiresAt: string, now?: () => number) => Promise<{
57
+ appId: string;
58
+ expiresAt: string;
59
+ id: string;
60
+ readKey: string;
61
+ scopes: import("./crmInsights.js").InsightScope[];
62
+ }>;
63
+ /** Binds existing owned evidence by CAS; registration never claims provider settlement authenticity. */
64
+ export declare const registerCrmCanonicalFinanceBinding: (context: ApiContext, input: CrmCanonicalFinanceBindingInput, now?: () => number) => Promise<{
65
+ id: string;
66
+ revision: number;
67
+ status: "active" | "revoked";
68
+ }>;
69
+ /** Complete scoped owner observations; financial rows remain separate until namespace proof. */
70
+ export declare const getCrmCanonicalOutcomes: (context: ApiContext, input: CrmCanonicalReadInput, now?: () => number) => Promise<CrmCanonicalSnapshot>;
71
+ export interface CrmCanonicalCorrectionInput extends CrmCanonicalReadInput {
72
+ associationId: string;
73
+ deleted?: boolean;
74
+ eventId: string;
75
+ evidenceRef: string;
76
+ expectedAssociationRevision: number;
77
+ expectedEventRevision: number;
78
+ expectedSourceRevision: string;
79
+ orderId?: string;
80
+ stage?: 'new' | 'qualified' | 'won' | 'lost' | 'disqualified';
81
+ }
82
+ /** Correct a real owner observation by CAS; never backdate/create an invented event or modify money. */
83
+ export declare const correctCrmCanonicalObservation: (context: ApiContext, input: CrmCanonicalCorrectionInput, now?: () => number) => Promise<{
84
+ associationRevision: number;
85
+ eventId: string;
86
+ eventRevision: number;
87
+ sourceRevision: string;
88
+ }>;
@@ -0,0 +1,398 @@
1
+ /* eslint-disable no-await-in-loop, no-underscore-dangle -- Native CAS and ordered source snapshot reconciliation. */ import { aql } from 'arangojs';
2
+ import { scopeContextToApp } from '../utils/appContext.js';
3
+ import { useDb } from '../utils/arangodbUtils.js';
4
+ import { requireCrmAdministrator } from './crm.js';
5
+ import { crmCanonicalDigest, crmCanonicalHistoryEvents } from './crmCanonicalPolicy.js';
6
+ import { ensureOwnerExecutionCollection } from './crmExecution.js';
7
+ import { nativeFinanceSource, readNativeCrmFinancialEvidence, validateNativeFinance } from './crmFinancialEvidence.js';
8
+ import { authorizeCrmInsightSource, createCrmInsightsReadKey } from './crmInsights.js';
9
+ const key = (value)=>typeof value === 'string' && /^[\w.-]{1,160}$/.test(value);
10
+ const validInput = (input)=>Boolean(input && [
11
+ input.appId,
12
+ input.organizationId,
13
+ input.projectId,
14
+ input.campaignId
15
+ ].every(key) && (input.financial === undefined || typeof input.financial === 'boolean'));
16
+ export const createCrmCanonicalReadKey = async (context, appId, bounds, financial, expiresAt, now = Date.now)=>{
17
+ requireCrmAdministrator(context);
18
+ const scoped = await scopeContextToApp(context, appId);
19
+ const db = useDb(scoped.databaseName);
20
+ if (!key(bounds?.organizationId) || !await db.query(aql`RETURN DOCUMENT('groups', ${bounds.organizationId})`).then((cursor)=>cursor.next())) {
21
+ throw new Error('canonical_organization_required');
22
+ }
23
+ if (financial) {
24
+ if (!bounds.issuerIds?.length) {
25
+ throw new Error('canonical_issuer_bounds_required');
26
+ }
27
+ for (const issuerId of bounds.issuerIds){
28
+ const issuer = await db.query(aql`RETURN DOCUMENT('merchantInvoiceProfiles', ${issuerId})`).then((cursor)=>cursor.next());
29
+ if (!issuer || issuer.appId !== appId) {
30
+ throw new Error('canonical_owned_issuer_required');
31
+ }
32
+ }
33
+ }
34
+ return createCrmInsightsReadKey(context, appId, [
35
+ financial ? 'crm:canonical_finance' : 'crm:canonical_outcomes'
36
+ ], expiresAt, now, bounds);
37
+ };
38
+ /** Binds existing owned evidence by CAS; registration never claims provider settlement authenticity. */ export const registerCrmCanonicalFinanceBinding = async (context, input, now = Date.now)=>{
39
+ requireCrmAdministrator(context);
40
+ const revisions = input?.expectedSourceRevisions;
41
+ if (!validInput(input) || ![
42
+ input.id,
43
+ input.associationId,
44
+ input.issuerId,
45
+ input.invoiceId,
46
+ input.paymentEvidenceId,
47
+ input.nativePaymentId
48
+ ].every(key) || !input.evidenceRef?.trim() || input.evidenceRef.length > 1000 || !Number.isSafeInteger(input.expectedRevision) || input.expectedRevision < 0 || ![
49
+ 'active',
50
+ 'revoked'
51
+ ].includes(input.status) || !revisions || Object.keys(revisions).sort().join(',') !== 'association,invoice,nativePayment,order,paymentEvidence,user' || !Number.isSafeInteger(revisions.association) || revisions.association < 1 || ![
52
+ revisions.invoice,
53
+ revisions.nativePayment,
54
+ revisions.order,
55
+ revisions.paymentEvidence,
56
+ revisions.user
57
+ ].every(key)) {
58
+ throw new Error('invalid_canonical_finance_binding');
59
+ }
60
+ const scoped = await scopeContextToApp(context, input.appId);
61
+ const db = useDb(scoped.databaseName);
62
+ await ensureOwnerExecutionCollection(db, 'crmCanonicalFinanceBindings');
63
+ await ensureOwnerExecutionCollection(db, 'hasCrmCanonicalFinance', true);
64
+ const tx = await db.beginTransaction({
65
+ exclusive: [
66
+ 'crmCanonicalFinanceBindings',
67
+ 'hasCrmCanonicalFinance'
68
+ ],
69
+ read: [
70
+ 'hasCrmCampaignOutcome',
71
+ 'customerOrders',
72
+ 'users',
73
+ 'merchantIssuedInvoices',
74
+ 'merchantPaymentEvidence',
75
+ 'payments',
76
+ 'merchantInvoiceProfiles'
77
+ ]
78
+ }, {
79
+ lockTimeout: 10
80
+ });
81
+ try {
82
+ const source = await tx.step(()=>nativeFinanceSource(db, input.associationId, input, input.invoiceId, input.paymentEvidenceId, input.nativePaymentId));
83
+ if (!validateNativeFinance(source, input, input.issuerId, now()) || Object.entries(input.expectedSourceRevisions).some(([field, revision])=>field === 'association' ? source.association.revision !== revision : source[field]?._rev !== revision)) {
84
+ throw new Error('canonical_finance_source_conflict');
85
+ }
86
+ const prior = await tx.step(()=>db.query(aql`RETURN DOCUMENT('crmCanonicalFinanceBindings', ${input.id})`)).then((cursor)=>cursor.next());
87
+ const identity = {
88
+ appId: input.appId,
89
+ associationId: input.associationId,
90
+ campaignId: input.campaignId,
91
+ invoiceId: input.invoiceId,
92
+ issuerId: input.issuerId,
93
+ nativePaymentId: input.nativePaymentId,
94
+ organizationId: input.organizationId,
95
+ paymentEvidenceId: input.paymentEvidenceId,
96
+ projectId: input.projectId
97
+ };
98
+ if ((prior?.revision || 0) !== input.expectedRevision || prior?.status === 'revoked' || prior && Object.entries(identity).some(([field, value])=>prior[field] !== value)) {
99
+ throw new Error('canonical_finance_binding_conflict');
100
+ }
101
+ const record = {
102
+ _key: input.id,
103
+ ...identity,
104
+ evidenceRef: input.evidenceRef,
105
+ expectedSourceRevisions: input.expectedSourceRevisions,
106
+ id: input.id,
107
+ modifiedAt: now(),
108
+ revision: input.expectedRevision + 1,
109
+ status: input.status
110
+ };
111
+ await tx.step(()=>db.query(aql`UPSERT {_key: ${input.id}} INSERT ${record} UPDATE ${record} IN crmCanonicalFinanceBindings`));
112
+ const edge = {
113
+ _from: `customerOrders/${source.order._key}`,
114
+ _key: input.id,
115
+ _to: `merchantIssuedInvoices/${input.invoiceId}`
116
+ };
117
+ await tx.step(()=>db.query(aql`UPSERT {_key: ${input.id}} INSERT ${edge} UPDATE ${edge} IN hasCrmCanonicalFinance`));
118
+ await tx.commit();
119
+ return {
120
+ id: input.id,
121
+ revision: record.revision,
122
+ status: input.status
123
+ };
124
+ } catch (error) {
125
+ await tx.abort();
126
+ throw error;
127
+ }
128
+ };
129
+ const authorize = async (context, input, at)=>{
130
+ if (!validInput(input) || Object.keys(input).some((key)=>![
131
+ 'appId',
132
+ 'campaignId',
133
+ 'financial',
134
+ 'organizationId',
135
+ 'projectId'
136
+ ].includes(key))) {
137
+ throw new Error('invalid_canonical_read_scope');
138
+ }
139
+ const authority = await authorizeCrmInsightSource(context, input.appId, at);
140
+ const bounds = authority.outcomeBounds;
141
+ if (!authority.scopes.includes(input.financial ? 'crm:canonical_finance' : 'crm:canonical_outcomes') || !bounds || bounds.organizationId !== input.organizationId || bounds.projectId !== input.projectId || !bounds.campaignIds.includes(input.campaignId)) {
142
+ throw new Error('canonical_read_access_required');
143
+ }
144
+ return authority;
145
+ };
146
+ const readHistory = async (db, input)=>db.collection('hasCrmCampaignOutcome').exists().then((exists)=>exists ? db.query(aql`
147
+ FOR association IN hasCrmCampaignOutcome FILTER association.appId == ${input.appId}
148
+ AND association.organizationId == ${input.organizationId} AND association.projectId == ${input.projectId}
149
+ AND association.campaignId == ${input.campaignId} AND association.kind == 'form_submission'
150
+ SORT association.id LIMIT 501
151
+ LET source = DOCUMENT('crmFormSubmissions', association.sourceId)
152
+ LET user = DOCUMENT('users', association.userId)
153
+ RETURN {association, source: source ? {revision: source._rev, history: source.crmOutcomeEvents || [],
154
+ truncated: source.crmOutcomeHistoryTruncated, deleted: source.deleted} : {revision: '', history: [],
155
+ deleted: true},
156
+ suppressed: user == null OR user.deleted == true OR user.crmAnalyticsSuppressed == true}
157
+ `).then((cursor)=>cursor.all()) : []);
158
+ /** Complete scoped owner observations; financial rows remain separate until namespace proof. */ export const getCrmCanonicalOutcomes = async (context, input, now = Date.now)=>{
159
+ const at = now();
160
+ const authority = await authorize(context, input, at);
161
+ const db = useDb(authority.context.databaseName);
162
+ const held = {};
163
+ const addHold = (reason)=>{
164
+ held[reason] = (held[reason] || 0) + 1;
165
+ };
166
+ const rows = input.financial ? [] : await readHistory(db, input);
167
+ let complete = rows.length <= 500;
168
+ let events = [];
169
+ for (const row of rows.slice(0, 500)){
170
+ const result = crmCanonicalHistoryEvents(row, at);
171
+ if (result.held) {
172
+ addHold(result.held);
173
+ }
174
+ complete &&= !result.incomplete;
175
+ events.push(...result.events);
176
+ }
177
+ const financialObservations = [];
178
+ const bindings = input.financial && await db.collection('crmCanonicalFinanceBindings').exists() ? await db.query(aql`FOR binding IN crmCanonicalFinanceBindings FILTER binding.appId == ${input.appId}
179
+ AND binding.organizationId == ${input.organizationId} AND binding.projectId == ${input.projectId}
180
+ AND binding.campaignId == ${input.campaignId}
181
+ AND binding.issuerId IN ${authority.outcomeBounds?.issuerIds || []} SORT binding.id LIMIT 51 RETURN binding`).then((cursor)=>cursor.all()) : [];
182
+ complete &&= bindings.length <= 50;
183
+ for (const binding of bindings.slice(0, 50)){
184
+ if (binding.status !== 'active') {
185
+ continue;
186
+ }
187
+ if (!authority.outcomeBounds?.issuerIds?.includes(binding.issuerId)) {
188
+ throw new Error('canonical_issuer_access_required');
189
+ }
190
+ const verification = await readNativeCrmFinancialEvidence(db, input, binding, at);
191
+ if (!verification.evidence) {
192
+ addHold(verification.held);
193
+ if ([
194
+ 'provider_verification_unavailable',
195
+ 'provider_refund_evidence_incomplete'
196
+ ].includes(verification.held)) {
197
+ complete = false;
198
+ }
199
+ continue;
200
+ }
201
+ const { source } = verification;
202
+ financialObservations.push({
203
+ evidence: verification.evidence,
204
+ id: crmCanonicalDigest([
205
+ input.appId,
206
+ binding.id
207
+ ]),
208
+ issuerId: binding.issuerId,
209
+ nativeOrderId: crmCanonicalDigest([
210
+ input.appId,
211
+ source.order._key
212
+ ]),
213
+ revision: verification.revision,
214
+ shopifyCustomerId: source.user.shopifyCustomerId,
215
+ shopifyOrderId: source.order.shopifyOrderId,
216
+ status: 'verified_settlement_namespace_unproven'
217
+ });
218
+ addHold('verified_financial_namespace_unproven');
219
+ }
220
+ const current = await authorize(context, input, now());
221
+ if (current.context.databaseName !== authority.context.databaseName || current.expiresAt !== authority.expiresAt || crmCanonicalDigest(current.outcomeBounds) !== crmCanonicalDigest(authority.outcomeBounds) || crmCanonicalDigest(current.scopes) !== crmCanonicalDigest(authority.scopes) || crmCanonicalDigest(rows) !== crmCanonicalDigest(input.financial ? [] : await readHistory(db, input))) {
222
+ throw new Error('canonical_source_or_grant_changed');
223
+ }
224
+ if (events.length > 500) {
225
+ complete = false;
226
+ events = events.slice(0, 500);
227
+ addHold('bounded_history_truncated');
228
+ }
229
+ const snapshot = {
230
+ appId: input.appId,
231
+ campaignId: input.campaignId,
232
+ complete,
233
+ events,
234
+ financialObservations,
235
+ generatedAt: new Date(at).toISOString(),
236
+ held,
237
+ issuerIds: input.financial ? [
238
+ ...authority.outcomeBounds.issuerIds
239
+ ].sort() : undefined,
240
+ organizationId: input.organizationId,
241
+ projectId: input.projectId,
242
+ revision: 1,
243
+ schemaVersion: 'crm_canonical_outcomes_v1',
244
+ sourceKind: input.financial ? 'financial' : 'lifecycle',
245
+ validUntil: new Date(Math.min(at + 900000, authority.expiresAt || Infinity)).toISOString()
246
+ };
247
+ // A stable monotonic source revision is committed with complete snapshot replacement; incomplete reads never erase
248
+ // history.
249
+ await ensureOwnerExecutionCollection(db, 'crmCanonicalSnapshots');
250
+ await db.collection('crmCanonicalSnapshots').ensureIndex({
251
+ expireAfter: 0,
252
+ fields: [
253
+ 'expiresAt'
254
+ ],
255
+ type: 'ttl'
256
+ });
257
+ const id = crmCanonicalDigest([
258
+ input.appId,
259
+ input.organizationId,
260
+ input.projectId,
261
+ input.campaignId,
262
+ Boolean(input.financial),
263
+ input.financial ? [
264
+ ...authority.outcomeBounds.issuerIds
265
+ ].sort() : []
266
+ ]);
267
+ const tx = await db.beginTransaction({
268
+ exclusive: [
269
+ 'crmCanonicalSnapshots'
270
+ ]
271
+ }, {
272
+ lockTimeout: 10
273
+ });
274
+ try {
275
+ const prior = await tx.step(()=>db.query(aql`RETURN DOCUMENT('crmCanonicalSnapshots', ${id})`)).then((cursor)=>cursor.next());
276
+ const digest = crmCanonicalDigest({
277
+ events,
278
+ financialObservations,
279
+ held
280
+ });
281
+ snapshot.revision = prior ? prior.revision + Number(prior.digest !== digest) : 1;
282
+ if (complete) {
283
+ const previous = prior?.events || [];
284
+ snapshot.events = events.map((event)=>{
285
+ const old = previous.find((item)=>item.eventId === event.eventId);
286
+ return {
287
+ ...event,
288
+ revision: old ? Math.max(event.revision, old.revision + Number(Boolean(old.deleted))) : event.revision
289
+ };
290
+ });
291
+ snapshot.events.push(...previous.filter((event)=>!events.some((item)=>item.eventId === event.eventId)).map((event)=>({
292
+ ...event,
293
+ deleted: true,
294
+ revision: event.revision + Number(!event.deleted)
295
+ })));
296
+ if (snapshot.events.length > 1000) {
297
+ throw new Error('canonical_tombstone_retention_bound');
298
+ }
299
+ const persisted = {
300
+ _key: id,
301
+ digest,
302
+ events: snapshot.events,
303
+ expiresAt: Math.floor(at / 1000) + 30 * 86400,
304
+ revision: snapshot.revision
305
+ };
306
+ await tx.step(()=>db.query(aql`UPSERT {_key: ${id}} INSERT ${persisted}
307
+ UPDATE ${persisted} IN crmCanonicalSnapshots`));
308
+ }
309
+ await tx.commit();
310
+ } catch (error) {
311
+ await tx.abort();
312
+ throw error;
313
+ }
314
+ return snapshot;
315
+ };
316
+ /** Correct a real owner observation by CAS; never backdate/create an invented event or modify money. */ export const correctCrmCanonicalObservation = async (context, input, now = Date.now)=>{
317
+ requireCrmAdministrator(context);
318
+ if (!validInput(input) || !key(input.associationId) || !key(input.expectedSourceRevision) || !/^[a-f0-9]{64}$/.test(input.eventId) || !input.evidenceRef?.trim() || input.evidenceRef.length > 1000 || !Number.isSafeInteger(input.expectedAssociationRevision) || input.expectedAssociationRevision < 1 || !Number.isSafeInteger(input.expectedEventRevision) || input.expectedEventRevision < 1 || input.deleted !== true && ![
319
+ 'new',
320
+ 'qualified',
321
+ 'won',
322
+ 'lost',
323
+ 'disqualified'
324
+ ].includes(input.stage || '')) {
325
+ throw new Error('invalid_canonical_observation_correction');
326
+ }
327
+ const scoped = await scopeContextToApp(context, input.appId);
328
+ const db = useDb(scoped.databaseName);
329
+ const tx = await db.beginTransaction({
330
+ exclusive: [
331
+ 'hasCrmCampaignOutcome',
332
+ 'crmFormSubmissions'
333
+ ],
334
+ read: [
335
+ 'customerOrders'
336
+ ]
337
+ }, {
338
+ lockTimeout: 10
339
+ });
340
+ const query = (value)=>tx.step(()=>db.query(value));
341
+ try {
342
+ const association = await query(aql`RETURN DOCUMENT('hasCrmCampaignOutcome', ${input.associationId})`).then((cursor)=>cursor.next());
343
+ if (!association || association.appId !== input.appId || association.organizationId !== input.organizationId || association.projectId !== input.projectId || association.campaignId !== input.campaignId || association.kind !== 'form_submission' || association.revision !== input.expectedAssociationRevision) {
344
+ throw new Error('canonical_correction_association_conflict');
345
+ }
346
+ const source = await query(aql`RETURN DOCUMENT('crmFormSubmissions', ${association.sourceId})`).then((cursor)=>cursor.next());
347
+ const index = source?.crmOutcomeEvents?.findIndex((event)=>event.id === input.eventId) ?? -1;
348
+ const event = source?.crmOutcomeEvents?.[index];
349
+ if (!source || source._rev !== input.expectedSourceRevision || source._rev !== association.sourceRevision || !event || event.revision !== input.expectedEventRevision || event.deleted || !Number.isSafeInteger(event.at) || event.at > now()) {
350
+ throw new Error('canonical_correction_source_conflict');
351
+ }
352
+ if (input.stage === 'won' && input.deleted !== true) {
353
+ if (!key(input.orderId)) {
354
+ throw new Error('canonical_won_order_required');
355
+ }
356
+ const order = await query(aql`RETURN DOCUMENT('customerOrders', ${input.orderId})`).then((cursor)=>cursor.next());
357
+ if (!order || order.userId !== source.userId || !order.shopifyOrderId || association.productId && !order.productIds?.includes(association.productId)) {
358
+ throw new Error('canonical_won_order_mismatch');
359
+ }
360
+ }
361
+ const history = source.crmOutcomeEvents.map((value, position)=>position === index ? {
362
+ ...value,
363
+ correctedAt: now(),
364
+ correctionEvidenceRef: input.evidenceRef,
365
+ deleted: input.deleted === true || undefined,
366
+ revision: value.revision + 1,
367
+ stage: input.deleted === true ? value.stage : input.stage
368
+ } : value);
369
+ const updates = {
370
+ crmOutcomeEvents: history,
371
+ ...index === history.length - 1 && !input.deleted ? {
372
+ crmLeadStage: input.stage
373
+ } : {}
374
+ };
375
+ const saved = await query(aql`UPDATE ${source._key} WITH ${updates} IN crmFormSubmissions RETURN NEW`).then((cursor)=>cursor.next());
376
+ const update = {
377
+ revision: association.revision + 1,
378
+ sourceRevision: saved._rev,
379
+ ...index === history.length - 1 && !input.deleted ? {
380
+ orderId: input.stage === 'won' ? input.orderId : null,
381
+ stage: input.stage
382
+ } : {}
383
+ };
384
+ await query(aql`UPDATE ${input.associationId} WITH ${update} IN hasCrmCampaignOutcome`);
385
+ await tx.commit();
386
+ return {
387
+ associationRevision: update.revision,
388
+ eventId: input.eventId,
389
+ eventRevision: event.revision + 1,
390
+ sourceRevision: saved._rev
391
+ };
392
+ } catch (error) {
393
+ await tx.abort();
394
+ throw error;
395
+ }
396
+ };
397
+
398
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9uaXRyb2c3L0RldmVsb3BtZW50L3JlYWt0b3IvcGFja2FnZXMvcmVha3Rvci9zcmMvYWN0aW9ucy9jcm1DYW5vbmljYWxPdXRjb21lcy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBuby1hd2FpdC1pbi1sb29wLCBuby11bmRlcnNjb3JlLWRhbmdsZSAtLSBOYXRpdmUgQ0FTIGFuZCBvcmRlcmVkIHNvdXJjZSBzbmFwc2hvdCByZWNvbmNpbGlhdGlvbi4gKi9cbmltcG9ydCB7YXFsfSBmcm9tICdhcmFuZ29qcyc7XG5cbmltcG9ydCB7c2NvcGVDb250ZXh0VG9BcHB9IGZyb20gJy4uL3V0aWxzL2FwcENvbnRleHQuanMnO1xuaW1wb3J0IHt1c2VEYn0gZnJvbSAnLi4vdXRpbHMvYXJhbmdvZGJVdGlscy5qcyc7XG5pbXBvcnQge3JlcXVpcmVDcm1BZG1pbmlzdHJhdG9yfSBmcm9tICcuL2NybS5qcyc7XG5pbXBvcnQge2NybUNhbm9uaWNhbERpZ2VzdCwgY3JtQ2Fub25pY2FsSGlzdG9yeUV2ZW50c30gZnJvbSAnLi9jcm1DYW5vbmljYWxQb2xpY3kuanMnO1xuaW1wb3J0IHtlbnN1cmVPd25lckV4ZWN1dGlvbkNvbGxlY3Rpb259IGZyb20gJy4vY3JtRXhlY3V0aW9uLmpzJztcbmltcG9ydCB7bmF0aXZlRmluYW5jZVNvdXJjZSwgcmVhZE5hdGl2ZUNybUZpbmFuY2lhbEV2aWRlbmNlLCB2YWxpZGF0ZU5hdGl2ZUZpbmFuY2V9IGZyb20gJy4vY3JtRmluYW5jaWFsRXZpZGVuY2UuanMnO1xuaW1wb3J0IHthdXRob3JpemVDcm1JbnNpZ2h0U291cmNlLCBjcmVhdGVDcm1JbnNpZ2h0c1JlYWRLZXl9IGZyb20gJy4vY3JtSW5zaWdodHMuanMnO1xuXG5pbXBvcnQgdHlwZSB7QXBpQ29udGV4dH0gZnJvbSAnLi4vdHlwZXMvYXV0aC50eXBlcy5qcyc7XG5pbXBvcnQgdHlwZSB7Q3JtQ2Fub25pY2FsRXZlbnQsIENybUNhbm9uaWNhbE5hdGl2ZUhpc3RvcnksXG4gIENybVZlcmlmaWVkRmluYW5jaWFsUHJvdmlkZXJFdmlkZW5jZX0gZnJvbSAnLi9jcm1DYW5vbmljYWxQb2xpY3kuanMnO1xuaW1wb3J0IHR5cGUge0NybU91dGNvbWVHcmFudEJvdW5kc30gZnJvbSAnLi9jcm1JbnNpZ2h0cy5qcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ3JtQ2Fub25pY2FsUmVhZElucHV0IHtcbiAgYXBwSWQ6IHN0cmluZztcbiAgY2FtcGFpZ25JZDogc3RyaW5nO1xuICBmaW5hbmNpYWw/OiBib29sZWFuO1xuICBvcmdhbml6YXRpb25JZDogc3RyaW5nO1xuICBwcm9qZWN0SWQ6IHN0cmluZztcbn1cbmV4cG9ydCBpbnRlcmZhY2UgQ3JtQ2Fub25pY2FsRmluYW5jZUJpbmRpbmdJbnB1dCBleHRlbmRzIENybUNhbm9uaWNhbFJlYWRJbnB1dCB7XG4gIGFzc29jaWF0aW9uSWQ6IHN0cmluZztcbiAgZXZpZGVuY2VSZWY6IHN0cmluZztcbiAgZXhwZWN0ZWRSZXZpc2lvbjogbnVtYmVyO1xuICBleHBlY3RlZFNvdXJjZVJldmlzaW9uczoge2Fzc29jaWF0aW9uOiBudW1iZXI7IGludm9pY2U6IHN0cmluZzsgbmF0aXZlUGF5bWVudDogc3RyaW5nO1xuICAgIG9yZGVyOiBzdHJpbmc7IHBheW1lbnRFdmlkZW5jZTogc3RyaW5nOyB1c2VyOiBzdHJpbmc7fTtcbiAgaWQ6IHN0cmluZztcbiAgaW52b2ljZUlkOiBzdHJpbmc7XG4gIGlzc3VlcklkOiBzdHJpbmc7XG4gIG5hdGl2ZVBheW1lbnRJZDogc3RyaW5nO1xuICBwYXltZW50RXZpZGVuY2VJZDogc3RyaW5nO1xuICBzdGF0dXM6ICdhY3RpdmUnIHwgJ3Jldm9rZWQnO1xufVxuZXhwb3J0IGludGVyZmFjZSBDcm1DYW5vbmljYWxGaW5hbmNpYWxPYnNlcnZhdGlvbiB7XG4gIGV2aWRlbmNlOiBDcm1WZXJpZmllZEZpbmFuY2lhbFByb3ZpZGVyRXZpZGVuY2U7XG4gIGlkOiBzdHJpbmc7XG4gIGlzc3VlcklkOiBzdHJpbmc7XG4gIG5hdGl2ZU9yZGVySWQ6IHN0cmluZztcbiAgcmV2aXNpb246IHN0cmluZztcbiAgc2hvcGlmeUN1c3RvbWVySWQ/OiBzdHJpbmc7XG4gIHNob3BpZnlPcmRlcklkPzogc3RyaW5nO1xuICBzdGF0dXM6ICd2ZXJpZmllZF9zZXR0bGVtZW50X25hbWVzcGFjZV91bnByb3Zlbic7XG59XG5leHBvcnQgaW50ZXJmYWNlIENybUNhbm9uaWNhbFNuYXBzaG90IHtcbiAgYXBwSWQ6IHN0cmluZztcbiAgY2FtcGFpZ25JZDogc3RyaW5nO1xuICBjb21wbGV0ZTogYm9vbGVhbjtcbiAgZXZlbnRzOiBDcm1DYW5vbmljYWxFdmVudFtdO1xuICBmaW5hbmNpYWxPYnNlcnZhdGlvbnM6IENybUNhbm9uaWNhbEZpbmFuY2lhbE9ic2VydmF0aW9uW107XG4gIGdlbmVyYXRlZEF0OiBzdHJpbmc7XG4gIGhlbGQ6IFJlY29yZDxzdHJpbmcsIG51bWJlcj47XG4gIGlzc3Vlcklkcz86IHN0cmluZ1tdO1xuICBvcmdhbml6YXRpb25JZDogc3RyaW5nO1xuICBwcm9qZWN0SWQ6IHN0cmluZztcbiAgcmV2aXNpb246IG51bWJlcjtcbiAgc2NoZW1hVmVyc2lvbjogJ2NybV9jYW5vbmljYWxfb3V0Y29tZXNfdjEnO1xuICBzb3VyY2VLaW5kOiAnbGlmZWN5Y2xlJyB8ICdmaW5hbmNpYWwnO1xuICB2YWxpZFVudGlsOiBzdHJpbmc7XG59XG5jb25zdCBrZXkgPSAodmFsdWU6IHVua25vd24pOiB2YWx1ZSBpcyBzdHJpbmcgPT4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyAmJiAvXltcXHcuLV17MSwxNjB9JC8udGVzdCh2YWx1ZSk7XG5jb25zdCB2YWxpZElucHV0ID0gKGlucHV0OiBDcm1DYW5vbmljYWxSZWFkSW5wdXQpOiBib29sZWFuID0+IEJvb2xlYW4oaW5wdXRcbiAgJiYgW2lucHV0LmFwcElkLCBpbnB1dC5vcmdhbml6YXRpb25JZCwgaW5wdXQucHJvamVjdElkLCBpbnB1dC5jYW1wYWlnbklkXS5ldmVyeShrZXkpXG4gICYmIChpbnB1dC5maW5hbmNpYWwgPT09IHVuZGVmaW5lZCB8fCB0eXBlb2YgaW5wdXQuZmluYW5jaWFsID09PSAnYm9vbGVhbicpKTtcbmV4cG9ydCBjb25zdCBjcmVhdGVDcm1DYW5vbmljYWxSZWFkS2V5ID0gYXN5bmMgKFxuICBjb250ZXh0OiBBcGlDb250ZXh0LCBhcHBJZDogc3RyaW5nLCBib3VuZHM6IENybU91dGNvbWVHcmFudEJvdW5kcywgZmluYW5jaWFsOiBib29sZWFuLCBleHBpcmVzQXQ6IHN0cmluZyxcbiAgbm93ID0gRGF0ZS5ub3dcbikgPT4ge1xuICByZXF1aXJlQ3JtQWRtaW5pc3RyYXRvcihjb250ZXh0KTtcbiAgY29uc3Qgc2NvcGVkID0gYXdhaXQgc2NvcGVDb250ZXh0VG9BcHAoY29udGV4dCwgYXBwSWQpO1xuICBjb25zdCBkYiA9IHVzZURiKHNjb3BlZC5kYXRhYmFzZU5hbWUpO1xuICBpZigha2V5KGJvdW5kcz8ub3JnYW5pemF0aW9uSWQpIHx8ICFhd2FpdCBkYi5xdWVyeShhcWxgUkVUVVJOIERPQ1VNRU5UKCdncm91cHMnLCAke2JvdW5kcy5vcmdhbml6YXRpb25JZH0pYClcbiAgICAudGhlbigoY3Vyc29yKSA9PiBjdXJzb3IubmV4dCgpKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignY2Fub25pY2FsX29yZ2FuaXphdGlvbl9yZXF1aXJlZCcpO1xuICB9XG4gIGlmKGZpbmFuY2lhbCkge1xuICAgIGlmKCFib3VuZHMuaXNzdWVySWRzPy5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY2Fub25pY2FsX2lzc3Vlcl9ib3VuZHNfcmVxdWlyZWQnKTtcbiAgICB9XG4gICAgZm9yKGNvbnN0IGlzc3VlcklkIG9mIGJvdW5kcy5pc3N1ZXJJZHMpIHtcbiAgICAgIGNvbnN0IGlzc3VlciA9IGF3YWl0IGRiLnF1ZXJ5KGFxbGBSRVRVUk4gRE9DVU1FTlQoJ21lcmNoYW50SW52b2ljZVByb2ZpbGVzJywgJHtpc3N1ZXJJZH0pYClcbiAgICAgICAgLnRoZW4oKGN1cnNvcikgPT4gY3Vyc29yLm5leHQoKSk7XG4gICAgICBpZighaXNzdWVyIHx8IGlzc3Vlci5hcHBJZCAhPT0gYXBwSWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdjYW5vbmljYWxfb3duZWRfaXNzdWVyX3JlcXVpcmVkJyk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBjcmVhdGVDcm1JbnNpZ2h0c1JlYWRLZXkoY29udGV4dCwgYXBwSWQsXG4gICAgW2ZpbmFuY2lhbCA/ICdjcm06Y2Fub25pY2FsX2ZpbmFuY2UnIDogJ2NybTpjYW5vbmljYWxfb3V0Y29tZXMnXSwgZXhwaXJlc0F0LCBub3csIGJvdW5kcyk7XG59O1xuLyoqIEJpbmRzIGV4aXN0aW5nIG93bmVkIGV2aWRlbmNlIGJ5IENBUzsgcmVnaXN0cmF0aW9uIG5ldmVyIGNsYWltcyBwcm92aWRlciBzZXR0bGVtZW50IGF1dGhlbnRpY2l0eS4gKi9cbmV4cG9ydCBjb25zdCByZWdpc3RlckNybUNhbm9uaWNhbEZpbmFuY2VCaW5kaW5nID0gYXN5bmMgKFxuICBjb250ZXh0OiBBcGlDb250ZXh0LCBpbnB1dDogQ3JtQ2Fub25pY2FsRmluYW5jZUJpbmRpbmdJbnB1dCwgbm93ID0gRGF0ZS5ub3dcbikgPT4ge1xuICByZXF1aXJlQ3JtQWRtaW5pc3RyYXRvcihjb250ZXh0KTtcbiAgY29uc3QgcmV2aXNpb25zID0gaW5wdXQ/LmV4cGVjdGVkU291cmNlUmV2aXNpb25zO1xuICBpZighdmFsaWRJbnB1dChpbnB1dCkgfHwgIVtpbnB1dC5pZCwgaW5wdXQuYXNzb2NpYXRpb25JZCwgaW5wdXQuaXNzdWVySWQsIGlucHV0Lmludm9pY2VJZCxcbiAgICBpbnB1dC5wYXltZW50RXZpZGVuY2VJZCwgaW5wdXQubmF0aXZlUGF5bWVudElkXS5ldmVyeShrZXkpIHx8ICFpbnB1dC5ldmlkZW5jZVJlZj8udHJpbSgpXG4gICAgfHwgaW5wdXQuZXZpZGVuY2VSZWYubGVuZ3RoID4gMTAwMCB8fCAhTnVtYmVyLmlzU2FmZUludGVnZXIoaW5wdXQuZXhwZWN0ZWRSZXZpc2lvbikgfHwgaW5wdXQuZXhwZWN0ZWRSZXZpc2lvbiA8IDBcbiAgICB8fCAhWydhY3RpdmUnLCAncmV2b2tlZCddLmluY2x1ZGVzKGlucHV0LnN0YXR1cykgfHwgIXJldmlzaW9uc1xuICAgIHx8IE9iamVjdC5rZXlzKHJldmlzaW9ucykuc29ydCgpLmpvaW4oJywnKSAhPT0gJ2Fzc29jaWF0aW9uLGludm9pY2UsbmF0aXZlUGF5bWVudCxvcmRlcixwYXltZW50RXZpZGVuY2UsdXNlcidcbiAgICB8fCAhTnVtYmVyLmlzU2FmZUludGVnZXIocmV2aXNpb25zLmFzc29jaWF0aW9uKSB8fCByZXZpc2lvbnMuYXNzb2NpYXRpb24gPCAxXG4gICAgfHwgIVtyZXZpc2lvbnMuaW52b2ljZSwgcmV2aXNpb25zLm5hdGl2ZVBheW1lbnQsIHJldmlzaW9ucy5vcmRlciwgcmV2aXNpb25zLnBheW1lbnRFdmlkZW5jZSxcbiAgICAgIHJldmlzaW9ucy51c2VyXS5ldmVyeShrZXkpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkX2Nhbm9uaWNhbF9maW5hbmNlX2JpbmRpbmcnKTtcbiAgfVxuICBjb25zdCBzY29wZWQgPSBhd2FpdCBzY29wZUNvbnRleHRUb0FwcChjb250ZXh0LCBpbnB1dC5hcHBJZCk7XG4gIGNvbnN0IGRiID0gdXNlRGIoc2NvcGVkLmRhdGFiYXNlTmFtZSk7XG4gIGF3YWl0IGVuc3VyZU93bmVyRXhlY3V0aW9uQ29sbGVjdGlvbihkYiwgJ2NybUNhbm9uaWNhbEZpbmFuY2VCaW5kaW5ncycpO1xuICBhd2FpdCBlbnN1cmVPd25lckV4ZWN1dGlvbkNvbGxlY3Rpb24oZGIsICdoYXNDcm1DYW5vbmljYWxGaW5hbmNlJywgdHJ1ZSk7XG4gIGNvbnN0IHR4ID0gYXdhaXQgZGIuYmVnaW5UcmFuc2FjdGlvbih7ZXhjbHVzaXZlOiBbJ2NybUNhbm9uaWNhbEZpbmFuY2VCaW5kaW5ncycsICdoYXNDcm1DYW5vbmljYWxGaW5hbmNlJ10sXG4gICAgcmVhZDogWydoYXNDcm1DYW1wYWlnbk91dGNvbWUnLCAnY3VzdG9tZXJPcmRlcnMnLCAndXNlcnMnLCAnbWVyY2hhbnRJc3N1ZWRJbnZvaWNlcycsICdtZXJjaGFudFBheW1lbnRFdmlkZW5jZScsXG4gICAgICAncGF5bWVudHMnLCAnbWVyY2hhbnRJbnZvaWNlUHJvZmlsZXMnXX0sIHtsb2NrVGltZW91dDogMTB9KTtcbiAgdHJ5IHtcbiAgICBjb25zdCBzb3VyY2UgPSBhd2FpdCB0eC5zdGVwKCgpID0+IG5hdGl2ZUZpbmFuY2VTb3VyY2UoZGIsIGlucHV0LmFzc29jaWF0aW9uSWQsIGlucHV0LFxuICAgICAgaW5wdXQuaW52b2ljZUlkLCBpbnB1dC5wYXltZW50RXZpZGVuY2VJZCwgaW5wdXQubmF0aXZlUGF5bWVudElkKSk7XG4gICAgaWYoIXZhbGlkYXRlTmF0aXZlRmluYW5jZShzb3VyY2UsIGlucHV0LCBpbnB1dC5pc3N1ZXJJZCwgbm93KCkpXG4gICAgICB8fCBPYmplY3QuZW50cmllcyhpbnB1dC5leHBlY3RlZFNvdXJjZVJldmlzaW9ucykuc29tZSgoW2ZpZWxkLCByZXZpc2lvbl0pID0+XG4gICAgICAgIChmaWVsZCA9PT0gJ2Fzc29jaWF0aW9uJyA/IHNvdXJjZS5hc3NvY2lhdGlvbi5yZXZpc2lvbiAhPT0gcmV2aXNpb24gOiBzb3VyY2VbZmllbGRdPy5fcmV2ICE9PSByZXZpc2lvbikpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Nhbm9uaWNhbF9maW5hbmNlX3NvdXJjZV9jb25mbGljdCcpO1xuICAgIH1cbiAgICBjb25zdCBwcmlvciA9IGF3YWl0IHR4LnN0ZXAoKCkgPT4gZGIucXVlcnkoYXFsYFJFVFVSTiBET0NVTUVOVCgnY3JtQ2Fub25pY2FsRmluYW5jZUJpbmRpbmdzJywgJHtpbnB1dC5pZH0pYCkpXG4gICAgICAudGhlbigoY3Vyc29yKSA9PiBjdXJzb3IubmV4dCgpKTtcbiAgICBjb25zdCBpZGVudGl0eSA9IHthcHBJZDogaW5wdXQuYXBwSWQsIGFzc29jaWF0aW9uSWQ6IGlucHV0LmFzc29jaWF0aW9uSWQsIGNhbXBhaWduSWQ6IGlucHV0LmNhbXBhaWduSWQsXG4gICAgICBpbnZvaWNlSWQ6IGlucHV0Lmludm9pY2VJZCwgaXNzdWVySWQ6IGlucHV0Lmlzc3VlcklkLCBuYXRpdmVQYXltZW50SWQ6IGlucHV0Lm5hdGl2ZVBheW1lbnRJZCxcbiAgICAgIG9yZ2FuaXphdGlvbklkOiBpbnB1dC5vcmdhbml6YXRpb25JZCwgcGF5bWVudEV2aWRlbmNlSWQ6IGlucHV0LnBheW1lbnRFdmlkZW5jZUlkLCBwcm9qZWN0SWQ6IGlucHV0LnByb2plY3RJZH07XG4gICAgaWYoKHByaW9yPy5yZXZpc2lvbiB8fCAwKSAhPT0gaW5wdXQuZXhwZWN0ZWRSZXZpc2lvbiB8fCBwcmlvcj8uc3RhdHVzID09PSAncmV2b2tlZCdcbiAgICAgIHx8IChwcmlvciAmJiBPYmplY3QuZW50cmllcyhpZGVudGl0eSkuc29tZSgoW2ZpZWxkLCB2YWx1ZV0pID0+IHByaW9yW2ZpZWxkXSAhPT0gdmFsdWUpKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdjYW5vbmljYWxfZmluYW5jZV9iaW5kaW5nX2NvbmZsaWN0Jyk7XG4gICAgfVxuICAgIGNvbnN0IHJlY29yZCA9IHtfa2V5OiBpbnB1dC5pZCwgLi4uaWRlbnRpdHksIGV2aWRlbmNlUmVmOiBpbnB1dC5ldmlkZW5jZVJlZixcbiAgICAgIGV4cGVjdGVkU291cmNlUmV2aXNpb25zOiBpbnB1dC5leHBlY3RlZFNvdXJjZVJldmlzaW9ucyxcbiAgICAgIGlkOiBpbnB1dC5pZCwgbW9kaWZpZWRBdDogbm93KCksIHJldmlzaW9uOiBpbnB1dC5leHBlY3RlZFJldmlzaW9uICsgMSwgc3RhdHVzOiBpbnB1dC5zdGF0dXN9O1xuICAgIGF3YWl0IHR4LnN0ZXAoKCkgPT4gZGIucXVlcnkoYXFsYFVQU0VSVCB7X2tleTogJHtpbnB1dC5pZH19IElOU0VSVCAke3JlY29yZH0gVVBEQVRFICR7cmVjb3JkfSBJTiBjcm1DYW5vbmljYWxGaW5hbmNlQmluZGluZ3NgKSk7XG4gICAgY29uc3QgZWRnZSA9IHtfZnJvbTogYGN1c3RvbWVyT3JkZXJzLyR7c291cmNlLm9yZGVyLl9rZXl9YCwgX2tleTogaW5wdXQuaWQsXG4gICAgICBfdG86IGBtZXJjaGFudElzc3VlZEludm9pY2VzLyR7aW5wdXQuaW52b2ljZUlkfWB9O1xuICAgIGF3YWl0IHR4LnN0ZXAoKCkgPT4gZGIucXVlcnkoYXFsYFVQU0VSVCB7X2tleTogJHtpbnB1dC5pZH19IElOU0VSVCAke2VkZ2V9IFVQREFURSAke2VkZ2V9IElOIGhhc0NybUNhbm9uaWNhbEZpbmFuY2VgKSk7XG4gICAgYXdhaXQgdHguY29tbWl0KCk7XG4gICAgcmV0dXJuIHtpZDogaW5wdXQuaWQsIHJldmlzaW9uOiByZWNvcmQucmV2aXNpb24sIHN0YXR1czogaW5wdXQuc3RhdHVzfTtcbiAgfSBjYXRjaChlcnJvcikge1xuICAgIGF3YWl0IHR4LmFib3J0KCk7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cbn07XG5jb25zdCBhdXRob3JpemUgPSBhc3luYyAoY29udGV4dDogQXBpQ29udGV4dCwgaW5wdXQ6IENybUNhbm9uaWNhbFJlYWRJbnB1dCwgYXQ6IG51bWJlcikgPT4ge1xuICBpZighdmFsaWRJbnB1dChpbnB1dCkgfHwgT2JqZWN0LmtleXMoaW5wdXQpLnNvbWUoKGtleSkgPT5cbiAgICAhWydhcHBJZCcsICdjYW1wYWlnbklkJywgJ2ZpbmFuY2lhbCcsICdvcmdhbml6YXRpb25JZCcsICdwcm9qZWN0SWQnXS5pbmNsdWRlcyhrZXkpKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZF9jYW5vbmljYWxfcmVhZF9zY29wZScpO1xuICB9XG4gIGNvbnN0IGF1dGhvcml0eSA9IGF3YWl0IGF1dGhvcml6ZUNybUluc2lnaHRTb3VyY2UoY29udGV4dCwgaW5wdXQuYXBwSWQsIGF0KTtcbiAgY29uc3QgYm91bmRzID0gYXV0aG9yaXR5Lm91dGNvbWVCb3VuZHM7XG4gIGlmKCFhdXRob3JpdHkuc2NvcGVzLmluY2x1ZGVzKGlucHV0LmZpbmFuY2lhbCA/ICdjcm06Y2Fub25pY2FsX2ZpbmFuY2UnIDogJ2NybTpjYW5vbmljYWxfb3V0Y29tZXMnKVxuICAgIHx8ICFib3VuZHMgfHwgYm91bmRzLm9yZ2FuaXphdGlvbklkICE9PSBpbnB1dC5vcmdhbml6YXRpb25JZCB8fCBib3VuZHMucHJvamVjdElkICE9PSBpbnB1dC5wcm9qZWN0SWRcbiAgICB8fCAhYm91bmRzLmNhbXBhaWduSWRzLmluY2x1ZGVzKGlucHV0LmNhbXBhaWduSWQpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdjYW5vbmljYWxfcmVhZF9hY2Nlc3NfcmVxdWlyZWQnKTtcbiAgfVxuICByZXR1cm4gYXV0aG9yaXR5O1xufTtcbmNvbnN0IHJlYWRIaXN0b3J5ID0gYXN5bmMgKGRiOiBSZXR1cm5UeXBlPHR5cGVvZiB1c2VEYj4sIGlucHV0OiBDcm1DYW5vbmljYWxSZWFkSW5wdXQpID0+XG4gIGRiLmNvbGxlY3Rpb24oJ2hhc0NybUNhbXBhaWduT3V0Y29tZScpLmV4aXN0cygpLnRoZW4oKGV4aXN0cykgPT4gKGV4aXN0cyA/IGRiLnF1ZXJ5KGFxbGBcbiAgICBGT1IgYXNzb2NpYXRpb24gSU4gaGFzQ3JtQ2FtcGFpZ25PdXRjb21lIEZJTFRFUiBhc3NvY2lhdGlvbi5hcHBJZCA9PSAke2lucHV0LmFwcElkfVxuICAgICAgQU5EIGFzc29jaWF0aW9uLm9yZ2FuaXphdGlvbklkID09ICR7aW5wdXQub3JnYW5pemF0aW9uSWR9IEFORCBhc3NvY2lhdGlvbi5wcm9qZWN0SWQgPT0gJHtpbnB1dC5wcm9qZWN0SWR9XG4gICAgICBBTkQgYXNzb2NpYXRpb24uY2FtcGFpZ25JZCA9PSAke2lucHV0LmNhbXBhaWduSWR9IEFORCBhc3NvY2lhdGlvbi5raW5kID09ICdmb3JtX3N1Ym1pc3Npb24nXG4gICAgU09SVCBhc3NvY2lhdGlvbi5pZCBMSU1JVCA1MDFcbiAgICBMRVQgc291cmNlID0gRE9DVU1FTlQoJ2NybUZvcm1TdWJtaXNzaW9ucycsIGFzc29jaWF0aW9uLnNvdXJjZUlkKVxuICAgIExFVCB1c2VyID0gRE9DVU1FTlQoJ3VzZXJzJywgYXNzb2NpYXRpb24udXNlcklkKVxuICAgIFJFVFVSTiB7YXNzb2NpYXRpb24sIHNvdXJjZTogc291cmNlID8ge3JldmlzaW9uOiBzb3VyY2UuX3JldiwgaGlzdG9yeTogc291cmNlLmNybU91dGNvbWVFdmVudHMgfHwgW10sXG4gICAgICB0cnVuY2F0ZWQ6IHNvdXJjZS5jcm1PdXRjb21lSGlzdG9yeVRydW5jYXRlZCwgZGVsZXRlZDogc291cmNlLmRlbGV0ZWR9IDoge3JldmlzaW9uOiAnJywgaGlzdG9yeTogW10sXG4gICAgICAgIGRlbGV0ZWQ6IHRydWV9LFxuICAgICAgc3VwcHJlc3NlZDogdXNlciA9PSBudWxsIE9SIHVzZXIuZGVsZXRlZCA9PSB0cnVlIE9SIHVzZXIuY3JtQW5hbHl0aWNzU3VwcHJlc3NlZCA9PSB0cnVlfVxuICBgKS50aGVuKChjdXJzb3IpID0+IGN1cnNvci5hbGwoKSkgOiBbXSkpO1xuLyoqIENvbXBsZXRlIHNjb3BlZCBvd25lciBvYnNlcnZhdGlvbnM7IGZpbmFuY2lhbCByb3dzIHJlbWFpbiBzZXBhcmF0ZSB1bnRpbCBuYW1lc3BhY2UgcHJvb2YuICovXG5leHBvcnQgY29uc3QgZ2V0Q3JtQ2Fub25pY2FsT3V0Y29tZXMgPSBhc3luYyAoXG4gIGNvbnRleHQ6IEFwaUNvbnRleHQsIGlucHV0OiBDcm1DYW5vbmljYWxSZWFkSW5wdXQsIG5vdyA9IERhdGUubm93XG4pXG46IFByb21pc2U8Q3JtQ2Fub25pY2FsU25hcHNob3Q+ID0+IHtcbiAgY29uc3QgYXQgPSBub3coKTtcbiAgY29uc3QgYXV0aG9yaXR5ID0gYXdhaXQgYXV0aG9yaXplKGNvbnRleHQsIGlucHV0LCBhdCk7XG4gIGNvbnN0IGRiID0gdXNlRGIoYXV0aG9yaXR5LmNvbnRleHQuZGF0YWJhc2VOYW1lKTtcbiAgY29uc3QgaGVsZDogUmVjb3JkPHN0cmluZywgbnVtYmVyPiA9IHt9O1xuICBjb25zdCBhZGRIb2xkID0gKHJlYXNvbjogc3RyaW5nKSA9PiB7XG4gICAgaGVsZFtyZWFzb25dID0gKGhlbGRbcmVhc29uXSB8fCAwKSArIDE7XG4gIH07XG4gIGNvbnN0IHJvd3MgPSBpbnB1dC5maW5hbmNpYWwgPyBbXSA6IGF3YWl0IHJlYWRIaXN0b3J5KGRiLCBpbnB1dCkgYXMgQ3JtQ2Fub25pY2FsTmF0aXZlSGlzdG9yeVtdO1xuICBsZXQgY29tcGxldGUgPSByb3dzLmxlbmd0aCA8PSA1MDA7XG4gIGxldCBldmVudHM6IENybUNhbm9uaWNhbEV2ZW50W10gPSBbXTtcbiAgZm9yKGNvbnN0IHJvdyBvZiByb3dzLnNsaWNlKDAsIDUwMCkpIHtcbiAgICBjb25zdCByZXN1bHQgPSBjcm1DYW5vbmljYWxIaXN0b3J5RXZlbnRzKHJvdywgYXQpO1xuICAgIGlmKHJlc3VsdC5oZWxkKSB7XG4gICAgICBhZGRIb2xkKHJlc3VsdC5oZWxkKTtcbiAgICB9XG4gICAgY29tcGxldGUgJiY9ICFyZXN1bHQuaW5jb21wbGV0ZTtcbiAgICBldmVudHMucHVzaCguLi5yZXN1bHQuZXZlbnRzKTtcbiAgfVxuICBjb25zdCBmaW5hbmNpYWxPYnNlcnZhdGlvbnM6IENybUNhbm9uaWNhbEZpbmFuY2lhbE9ic2VydmF0aW9uW10gPSBbXTtcbiAgY29uc3QgYmluZGluZ3MgPSBpbnB1dC5maW5hbmNpYWwgJiYgYXdhaXQgZGIuY29sbGVjdGlvbignY3JtQ2Fub25pY2FsRmluYW5jZUJpbmRpbmdzJykuZXhpc3RzKClcbiAgICA/IGF3YWl0IGRiLnF1ZXJ5KGFxbGBGT1IgYmluZGluZyBJTiBjcm1DYW5vbmljYWxGaW5hbmNlQmluZGluZ3MgRklMVEVSIGJpbmRpbmcuYXBwSWQgPT0gJHtpbnB1dC5hcHBJZH1cbiAgICAgIEFORCBiaW5kaW5nLm9yZ2FuaXphdGlvbklkID09ICR7aW5wdXQub3JnYW5pemF0aW9uSWR9IEFORCBiaW5kaW5nLnByb2plY3RJZCA9PSAke2lucHV0LnByb2plY3RJZH1cbiAgICAgIEFORCBiaW5kaW5nLmNhbXBhaWduSWQgPT0gJHtpbnB1dC5jYW1wYWlnbklkfVxuICAgICAgQU5EIGJpbmRpbmcuaXNzdWVySWQgSU4gJHthdXRob3JpdHkub3V0Y29tZUJvdW5kcz8uaXNzdWVySWRzIHx8IFtdfSBTT1JUIGJpbmRpbmcuaWQgTElNSVQgNTEgUkVUVVJOIGJpbmRpbmdgKVxuICAgICAgLnRoZW4oKGN1cnNvcikgPT4gY3Vyc29yLmFsbCgpKSA6IFtdO1xuICBjb21wbGV0ZSAmJj0gYmluZGluZ3MubGVuZ3RoIDw9IDUwO1xuICBmb3IoY29uc3QgYmluZGluZyBvZiBiaW5kaW5ncy5zbGljZSgwLCA1MCkpIHtcbiAgICBpZihiaW5kaW5nLnN0YXR1cyAhPT0gJ2FjdGl2ZScpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBpZighYXV0aG9yaXR5Lm91dGNvbWVCb3VuZHM/Lmlzc3Vlcklkcz8uaW5jbHVkZXMoYmluZGluZy5pc3N1ZXJJZCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY2Fub25pY2FsX2lzc3Vlcl9hY2Nlc3NfcmVxdWlyZWQnKTtcbiAgICB9XG4gICAgY29uc3QgdmVyaWZpY2F0aW9uID0gYXdhaXQgcmVhZE5hdGl2ZUNybUZpbmFuY2lhbEV2aWRlbmNlKGRiLCBpbnB1dCwgYmluZGluZywgYXQpO1xuICAgIGlmKCF2ZXJpZmljYXRpb24uZXZpZGVuY2UpIHtcbiAgICAgIGFkZEhvbGQodmVyaWZpY2F0aW9uLmhlbGQhKTtcbiAgICAgIGlmKFsncHJvdmlkZXJfdmVyaWZpY2F0aW9uX3VuYXZhaWxhYmxlJywgJ3Byb3ZpZGVyX3JlZnVuZF9ldmlkZW5jZV9pbmNvbXBsZXRlJ10uaW5jbHVkZXModmVyaWZpY2F0aW9uLmhlbGQhKSkge1xuICAgICAgICBjb21wbGV0ZSA9IGZhbHNlO1xuICAgICAgfVxuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGNvbnN0IHtzb3VyY2V9ID0gdmVyaWZpY2F0aW9uO1xuICAgIGZpbmFuY2lhbE9ic2VydmF0aW9ucy5wdXNoKHtldmlkZW5jZTogdmVyaWZpY2F0aW9uLmV2aWRlbmNlLCBpZDogY3JtQ2Fub25pY2FsRGlnZXN0KFtpbnB1dC5hcHBJZCwgYmluZGluZy5pZF0pLFxuICAgICAgaXNzdWVySWQ6IGJpbmRpbmcuaXNzdWVySWQsIG5hdGl2ZU9yZGVySWQ6IGNybUNhbm9uaWNhbERpZ2VzdChbaW5wdXQuYXBwSWQsIHNvdXJjZS5vcmRlci5fa2V5XSksXG4gICAgICByZXZpc2lvbjogdmVyaWZpY2F0aW9uLnJldmlzaW9uISxcbiAgICAgIHNob3BpZnlDdXN0b21lcklkOiBzb3VyY2UudXNlci5zaG9waWZ5Q3VzdG9tZXJJZCxcbiAgICAgIHNob3BpZnlPcmRlcklkOiBzb3VyY2Uub3JkZXIuc2hvcGlmeU9yZGVySWQsIHN0YXR1czogJ3ZlcmlmaWVkX3NldHRsZW1lbnRfbmFtZXNwYWNlX3VucHJvdmVuJ30pO1xuICAgIGFkZEhvbGQoJ3ZlcmlmaWVkX2ZpbmFuY2lhbF9uYW1lc3BhY2VfdW5wcm92ZW4nKTtcbiAgfVxuICBjb25zdCBjdXJyZW50ID0gYXdhaXQgYXV0aG9yaXplKGNvbnRleHQsIGlucHV0LCBub3coKSk7XG4gIGlmKGN1cnJlbnQuY29udGV4dC5kYXRhYmFzZU5hbWUgIT09IGF1dGhvcml0eS5jb250ZXh0LmRhdGFiYXNlTmFtZSB8fCBjdXJyZW50LmV4cGlyZXNBdCAhPT0gYXV0aG9yaXR5LmV4cGlyZXNBdFxuICAgIHx8IGNybUNhbm9uaWNhbERpZ2VzdChjdXJyZW50Lm91dGNvbWVCb3VuZHMpICE9PSBjcm1DYW5vbmljYWxEaWdlc3QoYXV0aG9yaXR5Lm91dGNvbWVCb3VuZHMpXG4gICAgfHwgY3JtQ2Fub25pY2FsRGlnZXN0KGN1cnJlbnQuc2NvcGVzKSAhPT0gY3JtQ2Fub25pY2FsRGlnZXN0KGF1dGhvcml0eS5zY29wZXMpXG4gICAgfHwgY3JtQ2Fub25pY2FsRGlnZXN0KHJvd3MpICE9PSBjcm1DYW5vbmljYWxEaWdlc3QoaW5wdXQuZmluYW5jaWFsID8gW10gOiBhd2FpdCByZWFkSGlzdG9yeShkYiwgaW5wdXQpKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignY2Fub25pY2FsX3NvdXJjZV9vcl9ncmFudF9jaGFuZ2VkJyk7XG4gIH1cbiAgaWYoZXZlbnRzLmxlbmd0aCA+IDUwMCkge1xuICAgIGNvbXBsZXRlID0gZmFsc2U7XG4gICAgZXZlbnRzID0gZXZlbnRzLnNsaWNlKDAsIDUwMCk7XG4gICAgYWRkSG9sZCgnYm91bmRlZF9oaXN0b3J5X3RydW5jYXRlZCcpO1xuICB9XG4gIGNvbnN0IHNuYXBzaG90OiBDcm1DYW5vbmljYWxTbmFwc2hvdCA9IHthcHBJZDogaW5wdXQuYXBwSWQsIGNhbXBhaWduSWQ6IGlucHV0LmNhbXBhaWduSWQsIGNvbXBsZXRlLFxuICAgIGV2ZW50cywgZmluYW5jaWFsT2JzZXJ2YXRpb25zLCBnZW5lcmF0ZWRBdDogbmV3IERhdGUoYXQpLnRvSVNPU3RyaW5nKCksIGhlbGQsXG4gICAgaXNzdWVySWRzOiBpbnB1dC5maW5hbmNpYWwgPyBbLi4uYXV0aG9yaXR5Lm91dGNvbWVCb3VuZHMhLmlzc3VlcklkcyFdLnNvcnQoKSA6IHVuZGVmaW5lZCxcbiAgICBvcmdhbml6YXRpb25JZDogaW5wdXQub3JnYW5pemF0aW9uSWQsXG4gICAgcHJvamVjdElkOiBpbnB1dC5wcm9qZWN0SWQsIHJldmlzaW9uOiAxLCBzY2hlbWFWZXJzaW9uOiAnY3JtX2Nhbm9uaWNhbF9vdXRjb21lc192MScsXG4gICAgc291cmNlS2luZDogaW5wdXQuZmluYW5jaWFsID8gJ2ZpbmFuY2lhbCcgOiAnbGlmZWN5Y2xlJyxcbiAgICB2YWxpZFVudGlsOiBuZXcgRGF0ZShNYXRoLm1pbihhdCArIDkwMDAwMCwgYXV0aG9yaXR5LmV4cGlyZXNBdCB8fCBJbmZpbml0eSkpLnRvSVNPU3RyaW5nKCl9O1xuICAvLyBBIHN0YWJsZSBtb25vdG9uaWMgc291cmNlIHJldmlzaW9uIGlzIGNvbW1pdHRlZCB3aXRoIGNvbXBsZXRlIHNuYXBzaG90IHJlcGxhY2VtZW50OyBpbmNvbXBsZXRlIHJlYWRzIG5ldmVyIGVyYXNlXG4gIC8vIGhpc3RvcnkuXG4gIGF3YWl0IGVuc3VyZU93bmVyRXhlY3V0aW9uQ29sbGVjdGlvbihkYiwgJ2NybUNhbm9uaWNhbFNuYXBzaG90cycpO1xuICBhd2FpdCBkYi5jb2xsZWN0aW9uKCdjcm1DYW5vbmljYWxTbmFwc2hvdHMnKS5lbnN1cmVJbmRleCh7ZXhwaXJlQWZ0ZXI6IDAsIGZpZWxkczogWydleHBpcmVzQXQnXSwgdHlwZTogJ3R0bCd9KTtcbiAgY29uc3QgaWQgPSBjcm1DYW5vbmljYWxEaWdlc3QoW2lucHV0LmFwcElkLCBpbnB1dC5vcmdhbml6YXRpb25JZCwgaW5wdXQucHJvamVjdElkLCBpbnB1dC5jYW1wYWlnbklkLFxuICAgIEJvb2xlYW4oaW5wdXQuZmluYW5jaWFsKSwgaW5wdXQuZmluYW5jaWFsID8gWy4uLmF1dGhvcml0eS5vdXRjb21lQm91bmRzIS5pc3N1ZXJJZHMhXS5zb3J0KCkgOiBbXV0pO1xuICBjb25zdCB0eCA9IGF3YWl0IGRiLmJlZ2luVHJhbnNhY3Rpb24oe2V4Y2x1c2l2ZTogWydjcm1DYW5vbmljYWxTbmFwc2hvdHMnXX0sIHtsb2NrVGltZW91dDogMTB9KTtcbiAgdHJ5IHtcbiAgICBjb25zdCBwcmlvciA9IGF3YWl0IHR4LnN0ZXAoKCkgPT4gZGIucXVlcnkoYXFsYFJFVFVSTiBET0NVTUVOVCgnY3JtQ2Fub25pY2FsU25hcHNob3RzJywgJHtpZH0pYCkpXG4gICAgICAudGhlbigoY3Vyc29yKSA9PiBjdXJzb3IubmV4dCgpKTtcbiAgICBjb25zdCBkaWdlc3QgPSBjcm1DYW5vbmljYWxEaWdlc3Qoe2V2ZW50cywgZmluYW5jaWFsT2JzZXJ2YXRpb25zLCBoZWxkfSk7XG4gICAgc25hcHNob3QucmV2aXNpb24gPSBwcmlvciA/IHByaW9yLnJldmlzaW9uICsgTnVtYmVyKHByaW9yLmRpZ2VzdCAhPT0gZGlnZXN0KSA6IDE7XG4gICAgaWYoY29tcGxldGUpIHtcbiAgICAgIGNvbnN0IHByZXZpb3VzOiBDcm1DYW5vbmljYWxFdmVudFtdID0gcHJpb3I/LmV2ZW50cyB8fCBbXTtcbiAgICAgIHNuYXBzaG90LmV2ZW50cyA9IGV2ZW50cy5tYXAoKGV2ZW50KSA9PiB7XG4gICAgICAgIGNvbnN0IG9sZCA9IHByZXZpb3VzLmZpbmQoKGl0ZW0pID0+IGl0ZW0uZXZlbnRJZCA9PT0gZXZlbnQuZXZlbnRJZCk7XG4gICAgICAgIHJldHVybiB7Li4uZXZlbnQsIHJldmlzaW9uOiBvbGQgPyBNYXRoLm1heChldmVudC5yZXZpc2lvbixcbiAgICAgICAgICBvbGQucmV2aXNpb24gKyBOdW1iZXIoQm9vbGVhbihvbGQuZGVsZXRlZCkpKSA6IGV2ZW50LnJldmlzaW9ufTtcbiAgICAgIH0pO1xuICAgICAgc25hcHNob3QuZXZlbnRzLnB1c2goLi4ucHJldmlvdXMuZmlsdGVyKChldmVudCkgPT4gIWV2ZW50cy5zb21lKChpdGVtKSA9PiBpdGVtLmV2ZW50SWQgPT09IGV2ZW50LmV2ZW50SWQpKVxuICAgICAgICAubWFwKChldmVudCkgPT4gKHsuLi5ldmVudCwgZGVsZXRlZDogdHJ1ZSBhcyBjb25zdCwgcmV2aXNpb246IGV2ZW50LnJldmlzaW9uICsgTnVtYmVyKCFldmVudC5kZWxldGVkKX0pKSk7XG4gICAgICBpZihzbmFwc2hvdC5ldmVudHMubGVuZ3RoID4gMTAwMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Nhbm9uaWNhbF90b21ic3RvbmVfcmV0ZW50aW9uX2JvdW5kJyk7XG4gICAgICB9XG4gICAgICBjb25zdCBwZXJzaXN0ZWQgPSB7X2tleTogaWQsIGRpZ2VzdCwgZXZlbnRzOiBzbmFwc2hvdC5ldmVudHMsXG4gICAgICAgIGV4cGlyZXNBdDogTWF0aC5mbG9vcihhdCAvIDEwMDApICsgKDMwICogODY0MDApLCByZXZpc2lvbjogc25hcHNob3QucmV2aXNpb259O1xuICAgICAgYXdhaXQgdHguc3RlcCgoKSA9PiBkYi5xdWVyeShhcWxgVVBTRVJUIHtfa2V5OiAke2lkfX0gSU5TRVJUICR7cGVyc2lzdGVkfVxuICAgICAgICBVUERBVEUgJHtwZXJzaXN0ZWR9IElOIGNybUNhbm9uaWNhbFNuYXBzaG90c2ApKTtcbiAgICB9XG4gICAgYXdhaXQgdHguY29tbWl0KCk7XG4gIH0gY2F0Y2goZXJyb3IpIHtcbiAgICBhd2FpdCB0eC5hYm9ydCgpO1xuICAgIHRocm93IGVycm9yO1xuICB9XG4gIHJldHVybiBzbmFwc2hvdDtcbn07XG5leHBvcnQgaW50ZXJmYWNlIENybUNhbm9uaWNhbENvcnJlY3Rpb25JbnB1dCBleHRlbmRzIENybUNhbm9uaWNhbFJlYWRJbnB1dCB7XG4gIGFzc29jaWF0aW9uSWQ6IHN0cmluZztcbiAgZGVsZXRlZD86IGJvb2xlYW47XG4gIGV2ZW50SWQ6IHN0cmluZztcbiAgZXZpZGVuY2VSZWY6IHN0cmluZztcbiAgZXhwZWN0ZWRBc3NvY2lhdGlvblJldmlzaW9uOiBudW1iZXI7XG4gIGV4cGVjdGVkRXZlbnRSZXZpc2lvbjogbnVtYmVyO1xuICBleHBlY3RlZFNvdXJjZVJldmlzaW9uOiBzdHJpbmc7XG4gIG9yZGVySWQ/OiBzdHJpbmc7XG4gIHN0YWdlPzogJ25ldycgfCAncXVhbGlmaWVkJyB8ICd3b24nIHwgJ2xvc3QnIHwgJ2Rpc3F1YWxpZmllZCc7XG59XG4vKiogQ29ycmVjdCBhIHJlYWwgb3duZXIgb2JzZXJ2YXRpb24gYnkgQ0FTOyBuZXZlciBiYWNrZGF0ZS9jcmVhdGUgYW4gaW52ZW50ZWQgZXZlbnQgb3IgbW9kaWZ5IG1vbmV5LiAqL1xuZXhwb3J0IGNvbnN0IGNvcnJlY3RDcm1DYW5vbmljYWxPYnNlcnZhdGlvbiA9IGFzeW5jIChcbiAgY29udGV4dDogQXBpQ29udGV4dCwgaW5wdXQ6IENybUNhbm9uaWNhbENvcnJlY3Rpb25JbnB1dCwgbm93ID0gRGF0ZS5ub3dcbikgPT4ge1xuICByZXF1aXJlQ3JtQWRtaW5pc3RyYXRvcihjb250ZXh0KTtcbiAgaWYoIXZhbGlkSW5wdXQoaW5wdXQpIHx8ICFrZXkoaW5wdXQuYXNzb2NpYXRpb25JZCkgfHwgIWtleShpbnB1dC5leHBlY3RlZFNvdXJjZVJldmlzaW9uKVxuICAgIHx8ICEvXlthLWYwLTldezY0fSQvLnRlc3QoaW5wdXQuZXZlbnRJZCkgfHwgIWlucHV0LmV2aWRlbmNlUmVmPy50cmltKCkgfHwgaW5wdXQuZXZpZGVuY2VSZWYubGVuZ3RoID4gMTAwMFxuICAgIHx8ICFOdW1iZXIuaXNTYWZlSW50ZWdlcihpbnB1dC5leHBlY3RlZEFzc29jaWF0aW9uUmV2aXNpb24pIHx8IGlucHV0LmV4cGVjdGVkQXNzb2NpYXRpb25SZXZpc2lvbiA8IDFcbiAgICB8fCAhTnVtYmVyLmlzU2FmZUludGVnZXIoaW5wdXQuZXhwZWN0ZWRFdmVudFJldmlzaW9uKSB8fCBpbnB1dC5leHBlY3RlZEV2ZW50UmV2aXNpb24gPCAxXG4gICAgfHwgKGlucHV0LmRlbGV0ZWQgIT09IHRydWUgJiYgIVsnbmV3JywgJ3F1YWxpZmllZCcsICd3b24nLCAnbG9zdCcsICdkaXNxdWFsaWZpZWQnXS5pbmNsdWRlcyhpbnB1dC5zdGFnZSB8fCAnJykpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkX2Nhbm9uaWNhbF9vYnNlcnZhdGlvbl9jb3JyZWN0aW9uJyk7XG4gIH1cbiAgY29uc3Qgc2NvcGVkID0gYXdhaXQgc2NvcGVDb250ZXh0VG9BcHAoY29udGV4dCwgaW5wdXQuYXBwSWQpO1xuICBjb25zdCBkYiA9IHVzZURiKHNjb3BlZC5kYXRhYmFzZU5hbWUpO1xuICBjb25zdCB0eCA9IGF3YWl0IGRiLmJlZ2luVHJhbnNhY3Rpb24oe2V4Y2x1c2l2ZTogWydoYXNDcm1DYW1wYWlnbk91dGNvbWUnLCAnY3JtRm9ybVN1Ym1pc3Npb25zJ10sXG4gICAgcmVhZDogWydjdXN0b21lck9yZGVycyddfSwge2xvY2tUaW1lb3V0OiAxMH0pO1xuICBjb25zdCBxdWVyeSA9ICh2YWx1ZTogUmV0dXJuVHlwZTx0eXBlb2YgYXFsPikgPT4gdHguc3RlcCgoKSA9PiBkYi5xdWVyeSh2YWx1ZSkpO1xuICB0cnkge1xuICAgIGNvbnN0IGFzc29jaWF0aW9uID0gYXdhaXQgcXVlcnkoYXFsYFJFVFVSTiBET0NVTUVOVCgnaGFzQ3JtQ2FtcGFpZ25PdXRjb21lJywgJHtpbnB1dC5hc3NvY2lhdGlvbklkfSlgKVxuICAgICAgLnRoZW4oKGN1cnNvcikgPT4gY3Vyc29yLm5leHQoKSkgYXMgQ3JtQ2Fub25pY2FsTmF0aXZlSGlzdG9yeVsnYXNzb2NpYXRpb24nXTtcbiAgICBpZighYXNzb2NpYXRpb24gfHwgYXNzb2NpYXRpb24uYXBwSWQgIT09IGlucHV0LmFwcElkIHx8IGFzc29jaWF0aW9uLm9yZ2FuaXphdGlvbklkICE9PSBpbnB1dC5vcmdhbml6YXRpb25JZFxuICAgICAgfHwgYXNzb2NpYXRpb24ucHJvamVjdElkICE9PSBpbnB1dC5wcm9qZWN0SWQgfHwgYXNzb2NpYXRpb24uY2FtcGFpZ25JZCAhPT0gaW5wdXQuY2FtcGFpZ25JZFxuICAgICAgfHwgYXNzb2NpYXRpb24ua2luZCAhPT0gJ2Zvcm1fc3VibWlzc2lvbicgfHwgYXNzb2NpYXRpb24ucmV2aXNpb24gIT09IGlucHV0LmV4cGVjdGVkQXNzb2NpYXRpb25SZXZpc2lvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdjYW5vbmljYWxfY29ycmVjdGlvbl9hc3NvY2lhdGlvbl9jb25mbGljdCcpO1xuICAgIH1cbiAgICBjb25zdCBzb3VyY2UgPSBhd2FpdCBxdWVyeShhcWxgUkVUVVJOIERPQ1VNRU5UKCdjcm1Gb3JtU3VibWlzc2lvbnMnLCAke2Fzc29jaWF0aW9uLnNvdXJjZUlkfSlgKVxuICAgICAgLnRoZW4oKGN1cnNvcikgPT4gY3Vyc29yLm5leHQoKSkgYXMge19rZXk6IHN0cmluZzsgX3Jldjogc3RyaW5nOyB1c2VySWQ6IHN0cmluZztcbiAgICAgIGNybU91dGNvbWVFdmVudHM6IHthdDogbnVtYmVyOyBkZWxldGVkPzogYm9vbGVhbjsgaWQ6IHN0cmluZzsgcmV2aXNpb246IG51bWJlcjsgc3RhZ2U6IHN0cmluZ31bXTt9O1xuICAgIGNvbnN0IGluZGV4ID0gc291cmNlPy5jcm1PdXRjb21lRXZlbnRzPy5maW5kSW5kZXgoKGV2ZW50KSA9PiBldmVudC5pZCA9PT0gaW5wdXQuZXZlbnRJZCkgPz8gLTE7XG4gICAgY29uc3QgZXZlbnQgPSBzb3VyY2U/LmNybU91dGNvbWVFdmVudHM/LltpbmRleF07XG4gICAgaWYoIXNvdXJjZSB8fCBzb3VyY2UuX3JldiAhPT0gaW5wdXQuZXhwZWN0ZWRTb3VyY2VSZXZpc2lvbiB8fCBzb3VyY2UuX3JldiAhPT0gYXNzb2NpYXRpb24uc291cmNlUmV2aXNpb25cbiAgICAgIHx8ICFldmVudCB8fCBldmVudC5yZXZpc2lvbiAhPT0gaW5wdXQuZXhwZWN0ZWRFdmVudFJldmlzaW9uIHx8IGV2ZW50LmRlbGV0ZWRcbiAgICAgIHx8ICFOdW1iZXIuaXNTYWZlSW50ZWdlcihldmVudC5hdCkgfHwgZXZlbnQuYXQgPiBub3coKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdjYW5vbmljYWxfY29ycmVjdGlvbl9zb3VyY2VfY29uZmxpY3QnKTtcbiAgICB9XG4gICAgaWYoaW5wdXQuc3RhZ2UgPT09ICd3b24nICYmIGlucHV0LmRlbGV0ZWQgIT09IHRydWUpIHtcbiAgICAgIGlmKCFrZXkoaW5wdXQub3JkZXJJZCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdjYW5vbmljYWxfd29uX29yZGVyX3JlcXVpcmVkJyk7XG4gICAgICB9XG4gICAgICBjb25zdCBvcmRlciA9IGF3YWl0IHF1ZXJ5KGFxbGBSRVRVUk4gRE9DVU1FTlQoJ2N1c3RvbWVyT3JkZXJzJywgJHtpbnB1dC5vcmRlcklkfSlgKS50aGVuKChjdXJzb3IpID0+IGN1cnNvci5uZXh0KCkpIGFzIHt1c2VySWQ6IHN0cmluZzsgc2hvcGlmeU9yZGVySWQ6IHN0cmluZzsgcHJvZHVjdElkcz86IHN0cmluZ1tdfTtcbiAgICAgIGlmKCFvcmRlciB8fCBvcmRlci51c2VySWQgIT09IHNvdXJjZS51c2VySWQgfHwgIW9yZGVyLnNob3BpZnlPcmRlcklkXG4gICAgICAgIHx8IChhc3NvY2lhdGlvbi5wcm9kdWN0SWQgJiYgIW9yZGVyLnByb2R1Y3RJZHM/LmluY2x1ZGVzKGFzc29jaWF0aW9uLnByb2R1Y3RJZCkpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignY2Fub25pY2FsX3dvbl9vcmRlcl9taXNtYXRjaCcpO1xuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBoaXN0b3J5ID0gc291cmNlLmNybU91dGNvbWVFdmVudHMubWFwKCh2YWx1ZSwgcG9zaXRpb24pID0+IChwb3NpdGlvbiA9PT0gaW5kZXggPyB7Li4udmFsdWUsXG4gICAgICBjb3JyZWN0ZWRBdDogbm93KCksIGNvcnJlY3Rpb25FdmlkZW5jZVJlZjogaW5wdXQuZXZpZGVuY2VSZWYsIGRlbGV0ZWQ6IGlucHV0LmRlbGV0ZWQgPT09IHRydWUgfHwgdW5kZWZpbmVkLFxuICAgICAgcmV2aXNpb246IHZhbHVlLnJldmlzaW9uICsgMSwgc3RhZ2U6IGlucHV0LmRlbGV0ZWQgPT09IHRydWUgPyB2YWx1ZS5zdGFnZSA6IGlucHV0LnN0YWdlfSA6IHZhbHVlKSk7XG4gICAgY29uc3QgdXBkYXRlcyA9IHtjcm1PdXRjb21lRXZlbnRzOiBoaXN0b3J5LCAuLi4oaW5kZXggPT09IGhpc3RvcnkubGVuZ3RoIC0gMSAmJiAhaW5wdXQuZGVsZXRlZFxuICAgICAgPyB7Y3JtTGVhZFN0YWdlOiBpbnB1dC5zdGFnZX0gOiB7fSl9O1xuICAgIGNvbnN0IHNhdmVkID0gYXdhaXQgcXVlcnkoYXFsYFVQREFURSAke3NvdXJjZS5fa2V5fSBXSVRIICR7dXBkYXRlc30gSU4gY3JtRm9ybVN1Ym1pc3Npb25zIFJFVFVSTiBORVdgKVxuICAgICAgLnRoZW4oKGN1cnNvcikgPT4gY3Vyc29yLm5leHQoKSkgYXMge19yZXY6IHN0cmluZ307XG4gICAgY29uc3QgdXBkYXRlID0ge3JldmlzaW9uOiBhc3NvY2lhdGlvbi5yZXZpc2lvbiArIDEsIHNvdXJjZVJldmlzaW9uOiBzYXZlZC5fcmV2LFxuICAgICAgLi4uKGluZGV4ID09PSBoaXN0b3J5Lmxlbmd0aCAtIDEgJiYgIWlucHV0LmRlbGV0ZWQgPyB7b3JkZXJJZDogaW5wdXQuc3RhZ2UgPT09ICd3b24nID8gaW5wdXQub3JkZXJJZCA6IG51bGwsXG4gICAgICAgIHN0YWdlOiBpbnB1dC5zdGFnZX0gOiB7fSl9O1xuICAgIGF3YWl0IHF1ZXJ5KGFxbGBVUERBVEUgJHtpbnB1dC5hc3NvY2lhdGlvbklkfSBXSVRIICR7dXBkYXRlfSBJTiBoYXNDcm1DYW1wYWlnbk91dGNvbWVgKTtcbiAgICBhd2FpdCB0eC5jb21taXQoKTtcbiAgICByZXR1cm4ge2Fzc29jaWF0aW9uUmV2aXNpb246IHVwZGF0ZS5yZXZpc2lvbiwgZXZlbnRJZDogaW5wdXQuZXZlbnRJZCwgZXZlbnRSZXZpc2lvbjogZXZlbnQucmV2aXNpb24gKyAxLFxuICAgICAgc291cmNlUmV2aXNpb246IHNhdmVkLl9yZXZ9O1xuICB9IGNhdGNoKGVycm9yKSB7XG4gICAgYXdhaXQgdHguYWJvcnQoKTtcbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxufTtcbiJdLCJuYW1lcyI6WyJhcWwiLCJzY29wZUNvbnRleHRUb0FwcCIsInVzZURiIiwicmVxdWlyZUNybUFkbWluaXN0cmF0b3IiLCJjcm1DYW5vbmljYWxEaWdlc3QiLCJjcm1DYW5vbmljYWxIaXN0b3J5RXZlbnRzIiwiZW5zdXJlT3duZXJFeGVjdXRpb25Db2xsZWN0aW9uIiwibmF0aXZlRmluYW5jZVNvdXJjZSIsInJlYWROYXRpdmVDcm1GaW5hbmNpYWxFdmlkZW5jZSIsInZhbGlkYXRlTmF0aXZlRmluYW5jZSIsImF1dGhvcml6ZUNybUluc2lnaHRTb3VyY2UiLCJjcmVhdGVDcm1JbnNpZ2h0c1JlYWRLZXkiLCJrZXkiLCJ2YWx1ZSIsInRlc3QiLCJ2YWxpZElucHV0IiwiaW5wdXQiLCJCb29sZWFuIiwiYXBwSWQiLCJvcmdhbml6YXRpb25JZCIsInByb2plY3RJZCIsImNhbXBhaWduSWQiLCJldmVyeSIsImZpbmFuY2lhbCIsInVuZGVmaW5lZCIsImNyZWF0ZUNybUNhbm9uaWNhbFJlYWRLZXkiLCJjb250ZXh0IiwiYm91bmRzIiwiZXhwaXJlc0F0Iiwibm93IiwiRGF0ZSIsInNjb3BlZCIsImRiIiwiZGF0YWJhc2VOYW1lIiwicXVlcnkiLCJ0aGVuIiwiY3Vyc29yIiwibmV4dCIsIkVycm9yIiwiaXNzdWVySWRzIiwibGVuZ3RoIiwiaXNzdWVySWQiLCJpc3N1ZXIiLCJyZWdpc3RlckNybUNhbm9uaWNhbEZpbmFuY2VCaW5kaW5nIiwicmV2aXNpb25zIiwiZXhwZWN0ZWRTb3VyY2VSZXZpc2lvbnMiLCJpZCIsImFzc29jaWF0aW9uSWQiLCJpbnZvaWNlSWQiLCJwYXltZW50RXZpZGVuY2VJZCIsIm5hdGl2ZVBheW1lbnRJZCIsImV2aWRlbmNlUmVmIiwidHJpbSIsIk51bWJlciIsImlzU2FmZUludGVnZXIiLCJleHBlY3RlZFJldmlzaW9uIiwiaW5jbHVkZXMiLCJzdGF0dXMiLCJPYmplY3QiLCJrZXlzIiwic29ydCIsImpvaW4iLCJhc3NvY2lhdGlvbiIsImludm9pY2UiLCJuYXRpdmVQYXltZW50Iiwib3JkZXIiLCJwYXltZW50RXZpZGVuY2UiLCJ1c2VyIiwidHgiLCJiZWdpblRyYW5zYWN0aW9uIiwiZXhjbHVzaXZlIiwicmVhZCIsImxvY2tUaW1lb3V0Iiwic291cmNlIiwic3RlcCIsImVudHJpZXMiLCJzb21lIiwiZmllbGQiLCJyZXZpc2lvbiIsIl9yZXYiLCJwcmlvciIsImlkZW50aXR5IiwicmVjb3JkIiwiX2tleSIsIm1vZGlmaWVkQXQiLCJlZGdlIiwiX2Zyb20iLCJfdG8iLCJjb21taXQiLCJlcnJvciIsImFib3J0IiwiYXV0aG9yaXplIiwiYXQiLCJhdXRob3JpdHkiLCJvdXRjb21lQm91bmRzIiwic2NvcGVzIiwiY2FtcGFpZ25JZHMiLCJyZWFkSGlzdG9yeSIsImNvbGxlY3Rpb24iLCJleGlzdHMiLCJhbGwiLCJnZXRDcm1DYW5vbmljYWxPdXRjb21lcyIsImhlbGQiLCJhZGRIb2xkIiwicmVhc29uIiwicm93cyIsImNvbXBsZXRlIiwiZXZlbnRzIiwicm93Iiwic2xpY2UiLCJyZXN1bHQiLCJpbmNvbXBsZXRlIiwicHVzaCIsImZpbmFuY2lhbE9ic2VydmF0aW9ucyIsImJpbmRpbmdzIiwiYmluZGluZyIsInZlcmlmaWNhdGlvbiIsImV2aWRlbmNlIiwibmF0aXZlT3JkZXJJZCIsInNob3BpZnlDdXN0b21lcklkIiwic2hvcGlmeU9yZGVySWQiLCJjdXJyZW50Iiwic25hcHNob3QiLCJnZW5lcmF0ZWRBdCIsInRvSVNPU3RyaW5nIiwic2NoZW1hVmVyc2lvbiIsInNvdXJjZUtpbmQiLCJ2YWxpZFVudGlsIiwiTWF0aCIsIm1pbiIsIkluZmluaXR5IiwiZW5zdXJlSW5kZXgiLCJleHBpcmVBZnRlciIsImZpZWxkcyIsInR5cGUiLCJkaWdlc3QiLCJwcmV2aW91cyIsIm1hcCIsImV2ZW50Iiwib2xkIiwiZmluZCIsIml0ZW0iLCJldmVudElkIiwibWF4IiwiZGVsZXRlZCIsImZpbHRlciIsInBlcnNpc3RlZCIsImZsb29yIiwiY29ycmVjdENybUNhbm9uaWNhbE9ic2VydmF0aW9uIiwiZXhwZWN0ZWRTb3VyY2VSZXZpc2lvbiIsImV4cGVjdGVkQXNzb2NpYXRpb25SZXZpc2lvbiIsImV4cGVjdGVkRXZlbnRSZXZpc2lvbiIsInN0YWdlIiwia2luZCIsInNvdXJjZUlkIiwiaW5kZXgiLCJjcm1PdXRjb21lRXZlbnRzIiwiZmluZEluZGV4Iiwic291cmNlUmV2aXNpb24iLCJvcmRlcklkIiwidXNlcklkIiwicHJvZHVjdElkIiwicHJvZHVjdElkcyIsImhpc3RvcnkiLCJwb3NpdGlvbiIsImNvcnJlY3RlZEF0IiwiY29ycmVjdGlvbkV2aWRlbmNlUmVmIiwidXBkYXRlcyIsImNybUxlYWRTdGFnZSIsInNhdmVkIiwidXBkYXRlIiwiYXNzb2NpYXRpb25SZXZpc2lvbiIsImV2ZW50UmV2aXNpb24iXSwibWFwcGluZ3MiOiJBQUFBLG1IQUFtSCxHQUNuSCxTQUFRQSxHQUFHLFFBQU8sV0FBVztBQUU3QixTQUFRQyxpQkFBaUIsUUFBTyx5QkFBeUI7QUFDekQsU0FBUUMsS0FBSyxRQUFPLDRCQUE0QjtBQUNoRCxTQUFRQyx1QkFBdUIsUUFBTyxXQUFXO0FBQ2pELFNBQVFDLGtCQUFrQixFQUFFQyx5QkFBeUIsUUFBTywwQkFBMEI7QUFDdEYsU0FBUUMsOEJBQThCLFFBQU8sb0JBQW9CO0FBQ2pFLFNBQVFDLG1CQUFtQixFQUFFQyw4QkFBOEIsRUFBRUMscUJBQXFCLFFBQU8sNEJBQTRCO0FBQ3JILFNBQVFDLHlCQUF5QixFQUFFQyx3QkFBd0IsUUFBTyxtQkFBbUI7QUFxRHJGLE1BQU1DLE1BQU0sQ0FBQ0MsUUFBb0MsT0FBT0EsVUFBVSxZQUFZLGtCQUFrQkMsSUFBSSxDQUFDRDtBQUNyRyxNQUFNRSxhQUFhLENBQUNDLFFBQTBDQyxRQUFRRCxTQUNqRTtRQUFDQSxNQUFNRSxLQUFLO1FBQUVGLE1BQU1HLGNBQWM7UUFBRUgsTUFBTUksU0FBUztRQUFFSixNQUFNSyxVQUFVO0tBQUMsQ0FBQ0MsS0FBSyxDQUFDVixRQUM1RUksQ0FBQUEsTUFBTU8sU0FBUyxLQUFLQyxhQUFhLE9BQU9SLE1BQU1PLFNBQVMsS0FBSyxTQUFRO0FBQzFFLE9BQU8sTUFBTUUsNEJBQTRCLE9BQ3ZDQyxTQUFxQlIsT0FBZVMsUUFBK0JKLFdBQW9CSyxXQUN2RkMsTUFBTUMsS0FBS0QsR0FBRztJQUVkMUIsd0JBQXdCdUI7SUFDeEIsTUFBTUssU0FBUyxNQUFNOUIsa0JBQWtCeUIsU0FBU1I7SUFDaEQsTUFBTWMsS0FBSzlCLE1BQU02QixPQUFPRSxZQUFZO0lBQ3BDLElBQUcsQ0FBQ3JCLElBQUllLFFBQVFSLG1CQUFtQixDQUFDLE1BQU1hLEdBQUdFLEtBQUssQ0FBQ2xDLEdBQUcsQ0FBQywwQkFBMEIsRUFBRTJCLE9BQU9SLGNBQWMsQ0FBQyxDQUFDLENBQUMsRUFDeEdnQixJQUFJLENBQUMsQ0FBQ0MsU0FBV0EsT0FBT0MsSUFBSSxLQUFLO1FBQ2xDLE1BQU0sSUFBSUMsTUFBTTtJQUNsQjtJQUNBLElBQUdmLFdBQVc7UUFDWixJQUFHLENBQUNJLE9BQU9ZLFNBQVMsRUFBRUMsUUFBUTtZQUM1QixNQUFNLElBQUlGLE1BQU07UUFDbEI7UUFDQSxLQUFJLE1BQU1HLFlBQVlkLE9BQU9ZLFNBQVMsQ0FBRTtZQUN0QyxNQUFNRyxTQUFTLE1BQU1WLEdBQUdFLEtBQUssQ0FBQ2xDLEdBQUcsQ0FBQywyQ0FBMkMsRUFBRXlDLFNBQVMsQ0FBQyxDQUFDLEVBQ3ZGTixJQUFJLENBQUMsQ0FBQ0MsU0FBV0EsT0FBT0MsSUFBSTtZQUMvQixJQUFHLENBQUNLLFVBQVVBLE9BQU94QixLQUFLLEtBQUtBLE9BQU87Z0JBQ3BDLE1BQU0sSUFBSW9CLE1BQU07WUFDbEI7UUFDRjtJQUNGO0lBQ0EsT0FBTzNCLHlCQUF5QmUsU0FBU1IsT0FDdkM7UUFBQ0ssWUFBWSwwQkFBMEI7S0FBeUIsRUFBRUssV0FBV0MsS0FBS0Y7QUFDdEYsRUFBRTtBQUNGLHNHQUFzRyxHQUN0RyxPQUFPLE1BQU1nQixxQ0FBcUMsT0FDaERqQixTQUFxQlYsT0FBd0NhLE1BQU1DLEtBQUtELEdBQUc7SUFFM0UxQix3QkFBd0J1QjtJQUN4QixNQUFNa0IsWUFBWTVCLE9BQU82QjtJQUN6QixJQUFHLENBQUM5QixXQUFXQyxVQUFVLENBQUM7UUFBQ0EsTUFBTThCLEVBQUU7UUFBRTlCLE1BQU0rQixhQUFhO1FBQUUvQixNQUFNeUIsUUFBUTtRQUFFekIsTUFBTWdDLFNBQVM7UUFDdkZoQyxNQUFNaUMsaUJBQWlCO1FBQUVqQyxNQUFNa0MsZUFBZTtLQUFDLENBQUM1QixLQUFLLENBQUNWLFFBQVEsQ0FBQ0ksTUFBTW1DLFdBQVcsRUFBRUMsVUFDL0VwQyxNQUFNbUMsV0FBVyxDQUFDWCxNQUFNLEdBQUcsUUFBUSxDQUFDYSxPQUFPQyxhQUFhLENBQUN0QyxNQUFNdUMsZ0JBQWdCLEtBQUt2QyxNQUFNdUMsZ0JBQWdCLEdBQUcsS0FDN0csQ0FBQztRQUFDO1FBQVU7S0FBVSxDQUFDQyxRQUFRLENBQUN4QyxNQUFNeUMsTUFBTSxLQUFLLENBQUNiLGFBQ2xEYyxPQUFPQyxJQUFJLENBQUNmLFdBQVdnQixJQUFJLEdBQUdDLElBQUksQ0FBQyxTQUFTLGtFQUM1QyxDQUFDUixPQUFPQyxhQUFhLENBQUNWLFVBQVVrQixXQUFXLEtBQUtsQixVQUFVa0IsV0FBVyxHQUFHLEtBQ3hFLENBQUM7UUFBQ2xCLFVBQVVtQixPQUFPO1FBQUVuQixVQUFVb0IsYUFBYTtRQUFFcEIsVUFBVXFCLEtBQUs7UUFBRXJCLFVBQVVzQixlQUFlO1FBQ3pGdEIsVUFBVXVCLElBQUk7S0FBQyxDQUFDN0MsS0FBSyxDQUFDVixNQUFNO1FBQzlCLE1BQU0sSUFBSTBCLE1BQU07SUFDbEI7SUFDQSxNQUFNUCxTQUFTLE1BQU05QixrQkFBa0J5QixTQUFTVixNQUFNRSxLQUFLO0lBQzNELE1BQU1jLEtBQUs5QixNQUFNNkIsT0FBT0UsWUFBWTtJQUNwQyxNQUFNM0IsK0JBQStCMEIsSUFBSTtJQUN6QyxNQUFNMUIsK0JBQStCMEIsSUFBSSwwQkFBMEI7SUFDbkUsTUFBTW9DLEtBQUssTUFBTXBDLEdBQUdxQyxnQkFBZ0IsQ0FBQztRQUFDQyxXQUFXO1lBQUM7WUFBK0I7U0FBeUI7UUFDeEdDLE1BQU07WUFBQztZQUF5QjtZQUFrQjtZQUFTO1lBQTBCO1lBQ25GO1lBQVk7U0FBMEI7SUFBQSxHQUFHO1FBQUNDLGFBQWE7SUFBRTtJQUM3RCxJQUFJO1FBQ0YsTUFBTUMsU0FBUyxNQUFNTCxHQUFHTSxJQUFJLENBQUMsSUFBTW5FLG9CQUFvQnlCLElBQUloQixNQUFNK0IsYUFBYSxFQUFFL0IsT0FDOUVBLE1BQU1nQyxTQUFTLEVBQUVoQyxNQUFNaUMsaUJBQWlCLEVBQUVqQyxNQUFNa0MsZUFBZTtRQUNqRSxJQUFHLENBQUN6QyxzQkFBc0JnRSxRQUFRekQsT0FBT0EsTUFBTXlCLFFBQVEsRUFBRVosVUFDcEQ2QixPQUFPaUIsT0FBTyxDQUFDM0QsTUFBTTZCLHVCQUF1QixFQUFFK0IsSUFBSSxDQUFDLENBQUMsQ0FBQ0MsT0FBT0MsU0FBUyxHQUNyRUQsVUFBVSxnQkFBZ0JKLE9BQU9YLFdBQVcsQ0FBQ2dCLFFBQVEsS0FBS0EsV0FBV0wsTUFBTSxDQUFDSSxNQUFNLEVBQUVFLFNBQVNELFdBQVk7WUFDNUcsTUFBTSxJQUFJeEMsTUFBTTtRQUNsQjtRQUNBLE1BQU0wQyxRQUFRLE1BQU1aLEdBQUdNLElBQUksQ0FBQyxJQUFNMUMsR0FBR0UsS0FBSyxDQUFDbEMsR0FBRyxDQUFDLCtDQUErQyxFQUFFZ0IsTUFBTThCLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FDeEdYLElBQUksQ0FBQyxDQUFDQyxTQUFXQSxPQUFPQyxJQUFJO1FBQy9CLE1BQU00QyxXQUFXO1lBQUMvRCxPQUFPRixNQUFNRSxLQUFLO1lBQUU2QixlQUFlL0IsTUFBTStCLGFBQWE7WUFBRTFCLFlBQVlMLE1BQU1LLFVBQVU7WUFDcEcyQixXQUFXaEMsTUFBTWdDLFNBQVM7WUFBRVAsVUFBVXpCLE1BQU15QixRQUFRO1lBQUVTLGlCQUFpQmxDLE1BQU1rQyxlQUFlO1lBQzVGL0IsZ0JBQWdCSCxNQUFNRyxjQUFjO1lBQUU4QixtQkFBbUJqQyxNQUFNaUMsaUJBQWlCO1lBQUU3QixXQUFXSixNQUFNSSxTQUFTO1FBQUE7UUFDOUcsSUFBRyxBQUFDNEQsQ0FBQUEsT0FBT0YsWUFBWSxDQUFBLE1BQU85RCxNQUFNdUMsZ0JBQWdCLElBQUl5QixPQUFPdkIsV0FBVyxhQUNwRXVCLFNBQVN0QixPQUFPaUIsT0FBTyxDQUFDTSxVQUFVTCxJQUFJLENBQUMsQ0FBQyxDQUFDQyxPQUFPaEUsTUFBTSxHQUFLbUUsS0FBSyxDQUFDSCxNQUFNLEtBQUtoRSxRQUFTO1lBQ3pGLE1BQU0sSUFBSXlCLE1BQU07UUFDbEI7UUFDQSxNQUFNNEMsU0FBUztZQUFDQyxNQUFNbkUsTUFBTThCLEVBQUU7WUFBRSxHQUFHbUMsUUFBUTtZQUFFOUIsYUFBYW5DLE1BQU1tQyxXQUFXO1lBQ3pFTix5QkFBeUI3QixNQUFNNkIsdUJBQXVCO1lBQ3REQyxJQUFJOUIsTUFBTThCLEVBQUU7WUFBRXNDLFlBQVl2RDtZQUFPaUQsVUFBVTlELE1BQU11QyxnQkFBZ0IsR0FBRztZQUFHRSxRQUFRekMsTUFBTXlDLE1BQU07UUFBQTtRQUM3RixNQUFNVyxHQUFHTSxJQUFJLENBQUMsSUFBTTFDLEdBQUdFLEtBQUssQ0FBQ2xDLEdBQUcsQ0FBQyxjQUFjLEVBQUVnQixNQUFNOEIsRUFBRSxDQUFDLFNBQVMsRUFBRW9DLE9BQU8sUUFBUSxFQUFFQSxPQUFPLCtCQUErQixDQUFDO1FBQzdILE1BQU1HLE9BQU87WUFBQ0MsT0FBTyxDQUFDLGVBQWUsRUFBRWIsT0FBT1IsS0FBSyxDQUFDa0IsSUFBSSxFQUFFO1lBQUVBLE1BQU1uRSxNQUFNOEIsRUFBRTtZQUN4RXlDLEtBQUssQ0FBQyx1QkFBdUIsRUFBRXZFLE1BQU1nQyxTQUFTLEVBQUU7UUFBQTtRQUNsRCxNQUFNb0IsR0FBR00sSUFBSSxDQUFDLElBQU0xQyxHQUFHRSxLQUFLLENBQUNsQyxHQUFHLENBQUMsY0FBYyxFQUFFZ0IsTUFBTThCLEVBQUUsQ0FBQyxTQUFTLEVBQUV1QyxLQUFLLFFBQVEsRUFBRUEsS0FBSywwQkFBMEIsQ0FBQztRQUNwSCxNQUFNakIsR0FBR29CLE1BQU07UUFDZixPQUFPO1lBQUMxQyxJQUFJOUIsTUFBTThCLEVBQUU7WUFBRWdDLFVBQVVJLE9BQU9KLFFBQVE7WUFBRXJCLFFBQVF6QyxNQUFNeUMsTUFBTTtRQUFBO0lBQ3ZFLEVBQUUsT0FBTWdDLE9BQU87UUFDYixNQUFNckIsR0FBR3NCLEtBQUs7UUFDZCxNQUFNRDtJQUNSO0FBQ0YsRUFBRTtBQUNGLE1BQU1FLFlBQVksT0FBT2pFLFNBQXFCVixPQUE4QjRFO0lBQzFFLElBQUcsQ0FBQzdFLFdBQVdDLFVBQVUwQyxPQUFPQyxJQUFJLENBQUMzQyxPQUFPNEQsSUFBSSxDQUFDLENBQUNoRSxNQUNoRCxDQUFDO1lBQUM7WUFBUztZQUFjO1lBQWE7WUFBa0I7U0FBWSxDQUFDNEMsUUFBUSxDQUFDNUMsT0FBTztRQUNyRixNQUFNLElBQUkwQixNQUFNO0lBQ2xCO0lBQ0EsTUFBTXVELFlBQVksTUFBTW5GLDBCQUEwQmdCLFNBQVNWLE1BQU1FLEtBQUssRUFBRTBFO0lBQ3hFLE1BQU1qRSxTQUFTa0UsVUFBVUMsYUFBYTtJQUN0QyxJQUFHLENBQUNELFVBQVVFLE1BQU0sQ0FBQ3ZDLFFBQVEsQ0FBQ3hDLE1BQU1PLFNBQVMsR0FBRywwQkFBMEIsNkJBQ3JFLENBQUNJLFVBQVVBLE9BQU9SLGNBQWMsS0FBS0gsTUFBTUcsY0FBYyxJQUFJUSxPQUFPUCxTQUFTLEtBQUtKLE1BQU1JLFNBQVMsSUFDakcsQ0FBQ08sT0FBT3FFLFdBQVcsQ0FBQ3hDLFFBQVEsQ0FBQ3hDLE1BQU1LLFVBQVUsR0FBRztRQUNuRCxNQUFNLElBQUlpQixNQUFNO0lBQ2xCO0lBQ0EsT0FBT3VEO0FBQ1Q7QUFDQSxNQUFNSSxjQUFjLE9BQU9qRSxJQUE4QmhCLFFBQ3ZEZ0IsR0FBR2tFLFVBQVUsQ0FBQyx5QkFBeUJDLE1BQU0sR0FBR2hFLElBQUksQ0FBQyxDQUFDZ0UsU0FBWUEsU0FBU25FLEdBQUdFLEtBQUssQ0FBQ2xDLEdBQUcsQ0FBQzt5RUFDakIsRUFBRWdCLE1BQU1FLEtBQUssQ0FBQzt3Q0FDL0MsRUFBRUYsTUFBTUcsY0FBYyxDQUFDLDhCQUE4QixFQUFFSCxNQUFNSSxTQUFTLENBQUM7b0NBQzNFLEVBQUVKLE1BQU1LLFVBQVUsQ0FBQzs7Ozs7Ozs7RUFRckQsQ0FBQyxFQUFFYyxJQUFJLENBQUMsQ0FBQ0MsU0FBV0EsT0FBT2dFLEdBQUcsTUFBTSxFQUFFO0FBQ3hDLDhGQUE4RixHQUM5RixPQUFPLE1BQU1DLDBCQUEwQixPQUNyQzNFLFNBQXFCVixPQUE4QmEsTUFBTUMsS0FBS0QsR0FBRztJQUdqRSxNQUFNK0QsS0FBSy9EO0lBQ1gsTUFBTWdFLFlBQVksTUFBTUYsVUFBVWpFLFNBQVNWLE9BQU80RTtJQUNsRCxNQUFNNUQsS0FBSzlCLE1BQU0yRixVQUFVbkUsT0FBTyxDQUFDTyxZQUFZO0lBQy9DLE1BQU1xRSxPQUErQixDQUFDO0lBQ3RDLE1BQU1DLFVBQVUsQ0FBQ0M7UUFDZkYsSUFBSSxDQUFDRSxPQUFPLEdBQUcsQUFBQ0YsQ0FBQUEsSUFBSSxDQUFDRSxPQUFPLElBQUksQ0FBQSxJQUFLO0lBQ3ZDO0lBQ0EsTUFBTUMsT0FBT3pGLE1BQU1PLFNBQVMsR0FBRyxFQUFFLEdBQUcsTUFBTTBFLFlBQVlqRSxJQUFJaEI7SUFDMUQsSUFBSTBGLFdBQVdELEtBQUtqRSxNQUFNLElBQUk7SUFDOUIsSUFBSW1FLFNBQThCLEVBQUU7SUFDcEMsS0FBSSxNQUFNQyxPQUFPSCxLQUFLSSxLQUFLLENBQUMsR0FBRyxLQUFNO1FBQ25DLE1BQU1DLFNBQVN6RywwQkFBMEJ1RyxLQUFLaEI7UUFDOUMsSUFBR2tCLE9BQU9SLElBQUksRUFBRTtZQUNkQyxRQUFRTyxPQUFPUixJQUFJO1FBQ3JCO1FBQ0FJLGFBQWEsQ0FBQ0ksT0FBT0MsVUFBVTtRQUMvQkosT0FBT0ssSUFBSSxJQUFJRixPQUFPSCxNQUFNO0lBQzlCO0lBQ0EsTUFBTU0sd0JBQTRELEVBQUU7SUFDcEUsTUFBTUMsV0FBV2xHLE1BQU1PLFNBQVMsSUFBSSxNQUFNUyxHQUFHa0UsVUFBVSxDQUFDLCtCQUErQkMsTUFBTSxLQUN6RixNQUFNbkUsR0FBR0UsS0FBSyxDQUFDbEMsR0FBRyxDQUFDLG1FQUFtRSxFQUFFZ0IsTUFBTUUsS0FBSyxDQUFDO29DQUN0RSxFQUFFRixNQUFNRyxjQUFjLENBQUMsMEJBQTBCLEVBQUVILE1BQU1JLFNBQVMsQ0FBQztnQ0FDdkUsRUFBRUosTUFBTUssVUFBVSxDQUFDOzhCQUNyQixFQUFFd0UsVUFBVUMsYUFBYSxFQUFFdkQsYUFBYSxFQUFFLENBQUMsd0NBQXdDLENBQUMsRUFDM0dKLElBQUksQ0FBQyxDQUFDQyxTQUFXQSxPQUFPZ0UsR0FBRyxNQUFNLEVBQUU7SUFDeENNLGFBQWFRLFNBQVMxRSxNQUFNLElBQUk7SUFDaEMsS0FBSSxNQUFNMkUsV0FBV0QsU0FBU0wsS0FBSyxDQUFDLEdBQUcsSUFBSztRQUMxQyxJQUFHTSxRQUFRMUQsTUFBTSxLQUFLLFVBQVU7WUFDOUI7UUFDRjtRQUNBLElBQUcsQ0FBQ29DLFVBQVVDLGFBQWEsRUFBRXZELFdBQVdpQixTQUFTMkQsUUFBUTFFLFFBQVEsR0FBRztZQUNsRSxNQUFNLElBQUlILE1BQU07UUFDbEI7UUFDQSxNQUFNOEUsZUFBZSxNQUFNNUcsK0JBQStCd0IsSUFBSWhCLE9BQU9tRyxTQUFTdkI7UUFDOUUsSUFBRyxDQUFDd0IsYUFBYUMsUUFBUSxFQUFFO1lBQ3pCZCxRQUFRYSxhQUFhZCxJQUFJO1lBQ3pCLElBQUc7Z0JBQUM7Z0JBQXFDO2FBQXNDLENBQUM5QyxRQUFRLENBQUM0RCxhQUFhZCxJQUFJLEdBQUk7Z0JBQzVHSSxXQUFXO1lBQ2I7WUFDQTtRQUNGO1FBQ0EsTUFBTSxFQUFDakMsTUFBTSxFQUFDLEdBQUcyQztRQUNqQkgsc0JBQXNCRCxJQUFJLENBQUM7WUFBQ0ssVUFBVUQsYUFBYUMsUUFBUTtZQUFFdkUsSUFBSTFDLG1CQUFtQjtnQkFBQ1ksTUFBTUUsS0FBSztnQkFBRWlHLFFBQVFyRSxFQUFFO2FBQUM7WUFDM0dMLFVBQVUwRSxRQUFRMUUsUUFBUTtZQUFFNkUsZUFBZWxILG1CQUFtQjtnQkFBQ1ksTUFBTUUsS0FBSztnQkFBRXVELE9BQU9SLEtBQUssQ0FBQ2tCLElBQUk7YUFBQztZQUM5RkwsVUFBVXNDLGFBQWF0QyxRQUFRO1lBQy9CeUMsbUJBQW1COUMsT0FBT04sSUFBSSxDQUFDb0QsaUJBQWlCO1lBQ2hEQyxnQkFBZ0IvQyxPQUFPUixLQUFLLENBQUN1RCxjQUFjO1lBQUUvRCxRQUFRO1FBQXdDO1FBQy9GOEMsUUFBUTtJQUNWO0lBQ0EsTUFBTWtCLFVBQVUsTUFBTTlCLFVBQVVqRSxTQUFTVixPQUFPYTtJQUNoRCxJQUFHNEYsUUFBUS9GLE9BQU8sQ0FBQ08sWUFBWSxLQUFLNEQsVUFBVW5FLE9BQU8sQ0FBQ08sWUFBWSxJQUFJd0YsUUFBUTdGLFNBQVMsS0FBS2lFLFVBQVVqRSxTQUFTLElBQzFHeEIsbUJBQW1CcUgsUUFBUTNCLGFBQWEsTUFBTTFGLG1CQUFtQnlGLFVBQVVDLGFBQWEsS0FDeEYxRixtQkFBbUJxSCxRQUFRMUIsTUFBTSxNQUFNM0YsbUJBQW1CeUYsVUFBVUUsTUFBTSxLQUMxRTNGLG1CQUFtQnFHLFVBQVVyRyxtQkFBbUJZLE1BQU1PLFNBQVMsR0FBRyxFQUFFLEdBQUcsTUFBTTBFLFlBQVlqRSxJQUFJaEIsU0FBUztRQUN6RyxNQUFNLElBQUlzQixNQUFNO0lBQ2xCO0lBQ0EsSUFBR3FFLE9BQU9uRSxNQUFNLEdBQUcsS0FBSztRQUN0QmtFLFdBQVc7UUFDWEMsU0FBU0EsT0FBT0UsS0FBSyxDQUFDLEdBQUc7UUFDekJOLFFBQVE7SUFDVjtJQUNBLE1BQU1tQixXQUFpQztRQUFDeEcsT0FBT0YsTUFBTUUsS0FBSztRQUFFRyxZQUFZTCxNQUFNSyxVQUFVO1FBQUVxRjtRQUN4RkM7UUFBUU07UUFBdUJVLGFBQWEsSUFBSTdGLEtBQUs4RCxJQUFJZ0MsV0FBVztRQUFJdEI7UUFDeEUvRCxXQUFXdkIsTUFBTU8sU0FBUyxHQUFHO2VBQUlzRSxVQUFVQyxhQUFhLENBQUV2RCxTQUFTO1NBQUUsQ0FBQ3FCLElBQUksS0FBS3BDO1FBQy9FTCxnQkFBZ0JILE1BQU1HLGNBQWM7UUFDcENDLFdBQVdKLE1BQU1JLFNBQVM7UUFBRTBELFVBQVU7UUFBRytDLGVBQWU7UUFDeERDLFlBQVk5RyxNQUFNTyxTQUFTLEdBQUcsY0FBYztRQUM1Q3dHLFlBQVksSUFBSWpHLEtBQUtrRyxLQUFLQyxHQUFHLENBQUNyQyxLQUFLLFFBQVFDLFVBQVVqRSxTQUFTLElBQUlzRyxXQUFXTixXQUFXO0lBQUU7SUFDNUYsbUhBQW1IO0lBQ25ILFdBQVc7SUFDWCxNQUFNdEgsK0JBQStCMEIsSUFBSTtJQUN6QyxNQUFNQSxHQUFHa0UsVUFBVSxDQUFDLHlCQUF5QmlDLFdBQVcsQ0FBQztRQUFDQyxhQUFhO1FBQUdDLFFBQVE7WUFBQztTQUFZO1FBQUVDLE1BQU07SUFBSztJQUM1RyxNQUFNeEYsS0FBSzFDLG1CQUFtQjtRQUFDWSxNQUFNRSxLQUFLO1FBQUVGLE1BQU1HLGNBQWM7UUFBRUgsTUFBTUksU0FBUztRQUFFSixNQUFNSyxVQUFVO1FBQ2pHSixRQUFRRCxNQUFNTyxTQUFTO1FBQUdQLE1BQU1PLFNBQVMsR0FBRztlQUFJc0UsVUFBVUMsYUFBYSxDQUFFdkQsU0FBUztTQUFFLENBQUNxQixJQUFJLEtBQUssRUFBRTtLQUFDO0lBQ25HLE1BQU1RLEtBQUssTUFBTXBDLEdBQUdxQyxnQkFBZ0IsQ0FBQztRQUFDQyxXQUFXO1lBQUM7U0FBd0I7SUFBQSxHQUFHO1FBQUNFLGFBQWE7SUFBRTtJQUM3RixJQUFJO1FBQ0YsTUFBTVEsUUFBUSxNQUFNWixHQUFHTSxJQUFJLENBQUMsSUFBTTFDLEdBQUdFLEtBQUssQ0FBQ2xDLEdBQUcsQ0FBQyx5Q0FBeUMsRUFBRThDLEdBQUcsQ0FBQyxDQUFDLEdBQzVGWCxJQUFJLENBQUMsQ0FBQ0MsU0FBV0EsT0FBT0MsSUFBSTtRQUMvQixNQUFNa0csU0FBU25JLG1CQUFtQjtZQUFDdUc7WUFBUU07WUFBdUJYO1FBQUk7UUFDdEVvQixTQUFTNUMsUUFBUSxHQUFHRSxRQUFRQSxNQUFNRixRQUFRLEdBQUd6QixPQUFPMkIsTUFBTXVELE1BQU0sS0FBS0EsVUFBVTtRQUMvRSxJQUFHN0IsVUFBVTtZQUNYLE1BQU04QixXQUFnQ3hELE9BQU8yQixVQUFVLEVBQUU7WUFDekRlLFNBQVNmLE1BQU0sR0FBR0EsT0FBTzhCLEdBQUcsQ0FBQyxDQUFDQztnQkFDNUIsTUFBTUMsTUFBTUgsU0FBU0ksSUFBSSxDQUFDLENBQUNDLE9BQVNBLEtBQUtDLE9BQU8sS0FBS0osTUFBTUksT0FBTztnQkFDbEUsT0FBTztvQkFBQyxHQUFHSixLQUFLO29CQUFFNUQsVUFBVTZELE1BQU1YLEtBQUtlLEdBQUcsQ0FBQ0wsTUFBTTVELFFBQVEsRUFDdkQ2RCxJQUFJN0QsUUFBUSxHQUFHekIsT0FBT3BDLFFBQVEwSCxJQUFJSyxPQUFPLE1BQU1OLE1BQU01RCxRQUFRO2dCQUFBO1lBQ2pFO1lBQ0E0QyxTQUFTZixNQUFNLENBQUNLLElBQUksSUFBSXdCLFNBQVNTLE1BQU0sQ0FBQyxDQUFDUCxRQUFVLENBQUMvQixPQUFPL0IsSUFBSSxDQUFDLENBQUNpRSxPQUFTQSxLQUFLQyxPQUFPLEtBQUtKLE1BQU1JLE9BQU8sR0FDckdMLEdBQUcsQ0FBQyxDQUFDQyxRQUFXLENBQUE7b0JBQUMsR0FBR0EsS0FBSztvQkFBRU0sU0FBUztvQkFBZWxFLFVBQVU0RCxNQUFNNUQsUUFBUSxHQUFHekIsT0FBTyxDQUFDcUYsTUFBTU0sT0FBTztnQkFBQyxDQUFBO1lBQ3ZHLElBQUd0QixTQUFTZixNQUFNLENBQUNuRSxNQUFNLEdBQUcsTUFBTTtnQkFDaEMsTUFBTSxJQUFJRixNQUFNO1lBQ2xCO1lBQ0EsTUFBTTRHLFlBQVk7Z0JBQUMvRCxNQUFNckM7Z0JBQUl5RjtnQkFBUTVCLFFBQVFlLFNBQVNmLE1BQU07Z0JBQzFEL0UsV0FBV29HLEtBQUttQixLQUFLLENBQUN2RCxLQUFLLFFBQVMsS0FBSztnQkFBUWQsVUFBVTRDLFNBQVM1QyxRQUFRO1lBQUE7WUFDOUUsTUFBTVYsR0FBR00sSUFBSSxDQUFDLElBQU0xQyxHQUFHRSxLQUFLLENBQUNsQyxHQUFHLENBQUMsY0FBYyxFQUFFOEMsR0FBRyxTQUFTLEVBQUVvRyxVQUFVO2VBQ2hFLEVBQUVBLFVBQVUseUJBQXlCLENBQUM7UUFDakQ7UUFDQSxNQUFNOUUsR0FBR29CLE1BQU07SUFDakIsRUFBRSxPQUFNQyxPQUFPO1FBQ2IsTUFBTXJCLEdBQUdzQixLQUFLO1FBQ2QsTUFBTUQ7SUFDUjtJQUNBLE9BQU9pQztBQUNULEVBQUU7QUFZRixzR0FBc0csR0FDdEcsT0FBTyxNQUFNMEIsaUNBQWlDLE9BQzVDMUgsU0FBcUJWLE9BQW9DYSxNQUFNQyxLQUFLRCxHQUFHO0lBRXZFMUIsd0JBQXdCdUI7SUFDeEIsSUFBRyxDQUFDWCxXQUFXQyxVQUFVLENBQUNKLElBQUlJLE1BQU0rQixhQUFhLEtBQUssQ0FBQ25DLElBQUlJLE1BQU1xSSxzQkFBc0IsS0FDbEYsQ0FBQyxpQkFBaUJ2SSxJQUFJLENBQUNFLE1BQU04SCxPQUFPLEtBQUssQ0FBQzlILE1BQU1tQyxXQUFXLEVBQUVDLFVBQVVwQyxNQUFNbUMsV0FBVyxDQUFDWCxNQUFNLEdBQUcsUUFDbEcsQ0FBQ2EsT0FBT0MsYUFBYSxDQUFDdEMsTUFBTXNJLDJCQUEyQixLQUFLdEksTUFBTXNJLDJCQUEyQixHQUFHLEtBQ2hHLENBQUNqRyxPQUFPQyxhQUFhLENBQUN0QyxNQUFNdUkscUJBQXFCLEtBQUt2SSxNQUFNdUkscUJBQXFCLEdBQUcsS0FDbkZ2SSxNQUFNZ0ksT0FBTyxLQUFLLFFBQVEsQ0FBQztRQUFDO1FBQU87UUFBYTtRQUFPO1FBQVE7S0FBZSxDQUFDeEYsUUFBUSxDQUFDeEMsTUFBTXdJLEtBQUssSUFBSSxLQUFNO1FBQ2pILE1BQU0sSUFBSWxILE1BQU07SUFDbEI7SUFDQSxNQUFNUCxTQUFTLE1BQU05QixrQkFBa0J5QixTQUFTVixNQUFNRSxLQUFLO0lBQzNELE1BQU1jLEtBQUs5QixNQUFNNkIsT0FBT0UsWUFBWTtJQUNwQyxNQUFNbUMsS0FBSyxNQUFNcEMsR0FBR3FDLGdCQUFnQixDQUFDO1FBQUNDLFdBQVc7WUFBQztZQUF5QjtTQUFxQjtRQUM5RkMsTUFBTTtZQUFDO1NBQWlCO0lBQUEsR0FBRztRQUFDQyxhQUFhO0lBQUU7SUFDN0MsTUFBTXRDLFFBQVEsQ0FBQ3JCLFFBQWtDdUQsR0FBR00sSUFBSSxDQUFDLElBQU0xQyxHQUFHRSxLQUFLLENBQUNyQjtJQUN4RSxJQUFJO1FBQ0YsTUFBTWlELGNBQWMsTUFBTTVCLE1BQU1sQyxHQUFHLENBQUMseUNBQXlDLEVBQUVnQixNQUFNK0IsYUFBYSxDQUFDLENBQUMsQ0FBQyxFQUNsR1osSUFBSSxDQUFDLENBQUNDLFNBQVdBLE9BQU9DLElBQUk7UUFDL0IsSUFBRyxDQUFDeUIsZUFBZUEsWUFBWTVDLEtBQUssS0FBS0YsTUFBTUUsS0FBSyxJQUFJNEMsWUFBWTNDLGNBQWMsS0FBS0gsTUFBTUcsY0FBYyxJQUN0RzJDLFlBQVkxQyxTQUFTLEtBQUtKLE1BQU1JLFNBQVMsSUFBSTBDLFlBQVl6QyxVQUFVLEtBQUtMLE1BQU1LLFVBQVUsSUFDeEZ5QyxZQUFZMkYsSUFBSSxLQUFLLHFCQUFxQjNGLFlBQVlnQixRQUFRLEtBQUs5RCxNQUFNc0ksMkJBQTJCLEVBQUU7WUFDekcsTUFBTSxJQUFJaEgsTUFBTTtRQUNsQjtRQUNBLE1BQU1tQyxTQUFTLE1BQU12QyxNQUFNbEMsR0FBRyxDQUFDLHNDQUFzQyxFQUFFOEQsWUFBWTRGLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFDM0Z2SCxJQUFJLENBQUMsQ0FBQ0MsU0FBV0EsT0FBT0MsSUFBSTtRQUUvQixNQUFNc0gsUUFBUWxGLFFBQVFtRixrQkFBa0JDLFVBQVUsQ0FBQ25CLFFBQVVBLE1BQU01RixFQUFFLEtBQUs5QixNQUFNOEgsT0FBTyxLQUFLLENBQUM7UUFDN0YsTUFBTUosUUFBUWpFLFFBQVFtRixrQkFBa0IsQ0FBQ0QsTUFBTTtRQUMvQyxJQUFHLENBQUNsRixVQUFVQSxPQUFPTSxJQUFJLEtBQUsvRCxNQUFNcUksc0JBQXNCLElBQUk1RSxPQUFPTSxJQUFJLEtBQUtqQixZQUFZZ0csY0FBYyxJQUNuRyxDQUFDcEIsU0FBU0EsTUFBTTVELFFBQVEsS0FBSzlELE1BQU11SSxxQkFBcUIsSUFBSWIsTUFBTU0sT0FBTyxJQUN6RSxDQUFDM0YsT0FBT0MsYUFBYSxDQUFDb0YsTUFBTTlDLEVBQUUsS0FBSzhDLE1BQU05QyxFQUFFLEdBQUcvRCxPQUFPO1lBQ3hELE1BQU0sSUFBSVMsTUFBTTtRQUNsQjtRQUNBLElBQUd0QixNQUFNd0ksS0FBSyxLQUFLLFNBQVN4SSxNQUFNZ0ksT0FBTyxLQUFLLE1BQU07WUFDbEQsSUFBRyxDQUFDcEksSUFBSUksTUFBTStJLE9BQU8sR0FBRztnQkFDdEIsTUFBTSxJQUFJekgsTUFBTTtZQUNsQjtZQUNBLE1BQU0yQixRQUFRLE1BQU0vQixNQUFNbEMsR0FBRyxDQUFDLGtDQUFrQyxFQUFFZ0IsTUFBTStJLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRTVILElBQUksQ0FBQyxDQUFDQyxTQUFXQSxPQUFPQyxJQUFJO1lBQ2hILElBQUcsQ0FBQzRCLFNBQVNBLE1BQU0rRixNQUFNLEtBQUt2RixPQUFPdUYsTUFBTSxJQUFJLENBQUMvRixNQUFNdUQsY0FBYyxJQUM5RDFELFlBQVltRyxTQUFTLElBQUksQ0FBQ2hHLE1BQU1pRyxVQUFVLEVBQUUxRyxTQUFTTSxZQUFZbUcsU0FBUyxHQUFJO2dCQUNsRixNQUFNLElBQUkzSCxNQUFNO1lBQ2xCO1FBQ0Y7UUFDQSxNQUFNNkgsVUFBVTFGLE9BQU9tRixnQkFBZ0IsQ0FBQ25CLEdBQUcsQ0FBQyxDQUFDNUgsT0FBT3VKLFdBQWNBLGFBQWFULFFBQVE7Z0JBQUMsR0FBRzlJLEtBQUs7Z0JBQzlGd0osYUFBYXhJO2dCQUFPeUksdUJBQXVCdEosTUFBTW1DLFdBQVc7Z0JBQUU2RixTQUFTaEksTUFBTWdJLE9BQU8sS0FBSyxRQUFReEg7Z0JBQ2pHc0QsVUFBVWpFLE1BQU1pRSxRQUFRLEdBQUc7Z0JBQUcwRSxPQUFPeEksTUFBTWdJLE9BQU8sS0FBSyxPQUFPbkksTUFBTTJJLEtBQUssR0FBR3hJLE1BQU13SSxLQUFLO1lBQUEsSUFBSTNJO1FBQzdGLE1BQU0wSixVQUFVO1lBQUNYLGtCQUFrQk87WUFBUyxHQUFJUixVQUFVUSxRQUFRM0gsTUFBTSxHQUFHLEtBQUssQ0FBQ3hCLE1BQU1nSSxPQUFPLEdBQzFGO2dCQUFDd0IsY0FBY3hKLE1BQU13SSxLQUFLO1lBQUEsSUFBSSxDQUFDLENBQUM7UUFBQztRQUNyQyxNQUFNaUIsUUFBUSxNQUFNdkksTUFBTWxDLEdBQUcsQ0FBQyxPQUFPLEVBQUV5RSxPQUFPVSxJQUFJLENBQUMsTUFBTSxFQUFFb0YsUUFBUSxpQ0FBaUMsQ0FBQyxFQUNsR3BJLElBQUksQ0FBQyxDQUFDQyxTQUFXQSxPQUFPQyxJQUFJO1FBQy9CLE1BQU1xSSxTQUFTO1lBQUM1RixVQUFVaEIsWUFBWWdCLFFBQVEsR0FBRztZQUFHZ0YsZ0JBQWdCVyxNQUFNMUYsSUFBSTtZQUM1RSxHQUFJNEUsVUFBVVEsUUFBUTNILE1BQU0sR0FBRyxLQUFLLENBQUN4QixNQUFNZ0ksT0FBTyxHQUFHO2dCQUFDZSxTQUFTL0ksTUFBTXdJLEtBQUssS0FBSyxRQUFReEksTUFBTStJLE9BQU8sR0FBRztnQkFDckdQLE9BQU94SSxNQUFNd0ksS0FBSztZQUFBLElBQUksQ0FBQyxDQUFDO1FBQUM7UUFDN0IsTUFBTXRILE1BQU1sQyxHQUFHLENBQUMsT0FBTyxFQUFFZ0IsTUFBTStCLGFBQWEsQ0FBQyxNQUFNLEVBQUUySCxPQUFPLHlCQUF5QixDQUFDO1FBQ3RGLE1BQU10RyxHQUFHb0IsTUFBTTtRQUNmLE9BQU87WUFBQ21GLHFCQUFxQkQsT0FBTzVGLFFBQVE7WUFBRWdFLFNBQVM5SCxNQUFNOEgsT0FBTztZQUFFOEIsZUFBZWxDLE1BQU01RCxRQUFRLEdBQUc7WUFDcEdnRixnQkFBZ0JXLE1BQU0xRixJQUFJO1FBQUE7SUFDOUIsRUFBRSxPQUFNVSxPQUFPO1FBQ2IsTUFBTXJCLEdBQUdzQixLQUFLO1FBQ2QsTUFBTUQ7SUFDUjtBQUNGLEVBQUUifQ==