pipework 0.71.0 → 0.72.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.
- package/CHANGELOG.md +11 -0
- package/REFERENCE.md +54 -0
- package/dist/core/config/discover.d.ts +2 -1
- package/dist/core/config/discover.d.ts.map +1 -1
- package/dist/core/config/discover.js +2 -56
- package/dist/core/config/discover.js.map +1 -1
- package/dist/core/config/namespace.d.ts +1 -0
- package/dist/core/config/namespace.d.ts.map +1 -1
- package/dist/core/config/schema.d.ts +1 -0
- package/dist/core/config/schema.d.ts.map +1 -1
- package/dist/core/config/schema.js +2 -0
- package/dist/core/config/schema.js.map +1 -1
- package/dist/core/config/ts-inline-hooks.d.ts +3 -0
- package/dist/core/config/ts-inline-hooks.d.ts.map +1 -0
- package/dist/core/config/ts-inline-hooks.js +65 -0
- package/dist/core/config/ts-inline-hooks.js.map +1 -0
- package/dist/core/config/ts-register.js +2 -0
- package/dist/core/config/ts-register.js.map +1 -1
- package/dist/core/config/ts-resolve-hooks.d.ts.map +1 -1
- package/dist/core/config/ts-resolve-hooks.js +2 -0
- package/dist/core/config/ts-resolve-hooks.js.map +1 -1
- package/dist/data/migrate/internal-definitions.d.ts.map +1 -1
- package/dist/data/migrate/internal-definitions.js +7 -0
- package/dist/data/migrate/internal-definitions.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/infra/alerts/handle.d.ts.map +1 -1
- package/dist/infra/alerts/handle.js +12 -76
- package/dist/infra/alerts/handle.js.map +1 -1
- package/dist/infra/alerts/sinks.d.ts +17 -21
- package/dist/infra/alerts/sinks.d.ts.map +1 -1
- package/dist/infra/alerts/sinks.js +0 -1
- package/dist/infra/alerts/sinks.js.map +1 -1
- package/dist/infra/outbox/core.d.ts +52 -0
- package/dist/infra/outbox/core.d.ts.map +1 -0
- package/dist/infra/outbox/core.js +91 -0
- package/dist/infra/outbox/core.js.map +1 -0
- package/dist/infra/support/handle.d.ts +271 -0
- package/dist/infra/support/handle.d.ts.map +1 -0
- package/dist/infra/support/handle.js +548 -0
- package/dist/infra/support/handle.js.map +1 -0
- package/dist/infra/support/index.d.ts +3 -0
- package/dist/infra/support/index.d.ts.map +1 -0
- package/dist/infra/support/index.js +2 -0
- package/dist/infra/support/index.js.map +1 -0
- package/dist/infra/support/namespace.d.ts +19 -0
- package/dist/infra/support/namespace.d.ts.map +1 -0
- package/dist/infra/support/namespace.js +9 -0
- package/dist/infra/support/namespace.js.map +1 -0
- package/dist/infra/support/schema.d.ts +214 -0
- package/dist/infra/support/schema.d.ts.map +1 -0
- package/dist/infra/support/schema.js +91 -0
- package/dist/infra/support/schema.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,548 @@
|
|
|
1
|
+
import { sql } from '../../data/db/sql.js';
|
|
2
|
+
import { pipe, pipeSystem } from '../../data/db/db.js';
|
|
3
|
+
import { fitting } from '../../request/di/index.js';
|
|
4
|
+
import { requireContext } from '../../request/context/store.js';
|
|
5
|
+
import { inTenant } from '../../auth/tenant/in-tenant.js';
|
|
6
|
+
import { resolveActorId } from '../../data/write/audit/actor.js';
|
|
7
|
+
import { getBaseLogger } from '../../core/logging/index.js';
|
|
8
|
+
import { ConflictError, ForbiddenError, NotFoundError, ValidationError } from '../../core/errors/index.js';
|
|
9
|
+
import { defineStateMachine } from '../../async/state-machine/define.js';
|
|
10
|
+
import { __flowStep } from '../../trace/runtime/flow-step.js';
|
|
11
|
+
import { createOutbox } from '../outbox/core.js';
|
|
12
|
+
import { TICKET_STATES } from './schema.js';
|
|
13
|
+
/** A draft could not be approved, edited or discarded: it is already approved, discarded, or changed since `expectedVersion`. */
|
|
14
|
+
export class DraftStateError extends ConflictError {
|
|
15
|
+
reason;
|
|
16
|
+
constructor(reason, message) {
|
|
17
|
+
super(message, { reason });
|
|
18
|
+
this.reason = reason;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
22
|
+
const DEFAULT_LIST_LIMIT = 50;
|
|
23
|
+
const MAX_LIST_LIMIT = 200;
|
|
24
|
+
const ENTITY = 'SupportTicket';
|
|
25
|
+
function toDate(value) {
|
|
26
|
+
if (value instanceof Date)
|
|
27
|
+
return value;
|
|
28
|
+
const text = String(value);
|
|
29
|
+
return new Date(/(Z|[+-]\d\d(:?\d\d)?)$/.test(text) ? text : `${text.replace(' ', 'T')}Z`);
|
|
30
|
+
}
|
|
31
|
+
function toTicket(r) {
|
|
32
|
+
return {
|
|
33
|
+
id: r['id'], tenantId: r['tenant_id'], state: r['state'],
|
|
34
|
+
category: (r['category'] ?? null), subject: r['subject'],
|
|
35
|
+
contactEmail: r['contact_email'], contactName: (r['contact_name'] ?? null),
|
|
36
|
+
userId: (r['user_id'] ?? null), conversationId: (r['conversation_id'] ?? null),
|
|
37
|
+
createdAt: toDate(r['created_at']), updatedAt: toDate(r['updated_at']), lastCustomerMessageAt: toDate(r['last_customer_message_at']),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function toMessage(r) {
|
|
41
|
+
return {
|
|
42
|
+
id: r['id'], ticketId: r['ticket_id'], kind: r['kind'],
|
|
43
|
+
channel: r['channel'], subject: (r['subject'] ?? null),
|
|
44
|
+
text: r['text'], html: (r['html'] ?? null), fromAddress: (r['from_address'] ?? null),
|
|
45
|
+
inboundEmailId: (r['inbound_email_id'] ?? null),
|
|
46
|
+
attachments: (r['attachments'] ?? null),
|
|
47
|
+
draftStatus: (r['draft_status'] ?? null), version: Number(r['version']),
|
|
48
|
+
approvedBy: (r['approved_by'] ?? null),
|
|
49
|
+
approvedAt: r['approved_at'] === null || r['approved_at'] === undefined ? null : toDate(r['approved_at']),
|
|
50
|
+
emailMessageId: (r['email_message_id'] ?? null), createdBy: (r['created_by'] ?? null),
|
|
51
|
+
createdAt: toDate(r['created_at']),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function toLink(r) {
|
|
55
|
+
return {
|
|
56
|
+
id: r['id'], ticketId: r['ticket_id'], kind: r['kind'], ref: r['ref'],
|
|
57
|
+
label: (r['label'] ?? null), createdAt: toDate(r['created_at']),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function nonEmpty(field, value) {
|
|
61
|
+
if (typeof value !== 'string' || value.trim() === '')
|
|
62
|
+
throw new ValidationError({ [field]: ['must be a non-empty string'] }, `Support ${field} must be a non-empty string.`);
|
|
63
|
+
return value;
|
|
64
|
+
}
|
|
65
|
+
function requireUuid(field, value) {
|
|
66
|
+
if (typeof value !== 'string' || !UUID_RE.test(value))
|
|
67
|
+
throw new ValidationError({ [field]: ['must be a UUID'] }, `Support ${field} must be a UUID.`);
|
|
68
|
+
return value;
|
|
69
|
+
}
|
|
70
|
+
/** Mail templates for `mail.create({ templates: { ...support.templates, ... } })`: the reply is rendered verbatim from the approved draft, nothing added. */
|
|
71
|
+
export const supportTemplates = {
|
|
72
|
+
'pipework.support.reply': ({ subject, text, html }) => ({ subject, text, ...(html !== undefined && html !== null ? { html } : {}) }),
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Creates the support handle: tickets for a tenant's customers, opened from received email, with replies
|
|
76
|
+
* sent only after an approval.
|
|
77
|
+
*
|
|
78
|
+
* Needs blueprint `support: {}` (tables `support_ticket`, `support_message`, `support_link` with forced
|
|
79
|
+
* row-level security, and the event outbox `support_event_delivery`) and, for email, `email: {}`.
|
|
80
|
+
* The app's mail templates must include `support.templates`, which render an approved draft verbatim.
|
|
81
|
+
*
|
|
82
|
+
* The only code path that sends a reply is `approve`: it needs an actor that `canApprove` accepts (and, by
|
|
83
|
+
* default, who is not the draft's author), and hands `mail.send` exactly the approved text and html in the
|
|
84
|
+
* ticket's conversation. Events (`ticket.created`, `ticket.customer-replied`, `draft.awaiting-approval`)
|
|
85
|
+
* go to the sinks through an outbox with retries, delivered by `job` or `tick()`. Every change is a
|
|
86
|
+
* `SupportTicket:<verb>` audit record under the Flow's open trace step.
|
|
87
|
+
*/
|
|
88
|
+
export function createSupport(config) {
|
|
89
|
+
if (config.sinks.length === 0)
|
|
90
|
+
throw new Error('[pipework] support.create needs at least one sink.');
|
|
91
|
+
const sinks = new Map();
|
|
92
|
+
for (const s of config.sinks) {
|
|
93
|
+
if (sinks.has(s.name))
|
|
94
|
+
throw new Error(`[pipework] support.create: two sinks are named "${s.name}"; give each its own name.`);
|
|
95
|
+
sinks.set(s.name, s);
|
|
96
|
+
}
|
|
97
|
+
const sinkNames = JSON.stringify([...sinks.keys()]);
|
|
98
|
+
const jobType = config.jobType ?? 'pipework.support.events';
|
|
99
|
+
const replyTemplate = config.replyTemplate ?? 'pipework.support.reply';
|
|
100
|
+
const distinctApprover = config.distinctApprover ?? true;
|
|
101
|
+
const screen = config.screen ?? ((email) => {
|
|
102
|
+
const v = email.verdicts;
|
|
103
|
+
if (v === null)
|
|
104
|
+
return 'accept';
|
|
105
|
+
if (v.virus === 'FAIL')
|
|
106
|
+
return 'drop';
|
|
107
|
+
return v.dmarc === 'FAIL' || (v.spf === 'FAIL' && v.dkim === 'FAIL') ? 'separate' : 'accept';
|
|
108
|
+
});
|
|
109
|
+
const log = getBaseLogger();
|
|
110
|
+
// Edges into `awaiting_approval`, out of it, and to `answered` are taken only by draft, discard, approve and a
|
|
111
|
+
// customer message (metadata.internal); `transition` cannot take them.
|
|
112
|
+
const internal = (ctx) => ctx.metadata?.['internal'] === true;
|
|
113
|
+
const machine = defineStateMachine({
|
|
114
|
+
states: TICKET_STATES,
|
|
115
|
+
initial: 'open',
|
|
116
|
+
transitions: [
|
|
117
|
+
{ from: 'open', to: 'triaged' },
|
|
118
|
+
{ from: 'triaged', to: 'awaiting_approval', guard: internal },
|
|
119
|
+
{ from: 'awaiting_approval', to: ['triaged', 'answered'], guard: internal },
|
|
120
|
+
{ from: 'open', to: 'closed' },
|
|
121
|
+
{ from: 'triaged', to: 'closed' },
|
|
122
|
+
{ from: 'answered', to: 'closed' },
|
|
123
|
+
{ from: 'triaged', to: 'open', guard: internal },
|
|
124
|
+
{ from: 'awaiting_approval', to: 'open', guard: internal },
|
|
125
|
+
{ from: 'answered', to: 'open', guard: internal },
|
|
126
|
+
{ from: 'closed', to: 'open', guard: internal },
|
|
127
|
+
],
|
|
128
|
+
});
|
|
129
|
+
function tenantOf(explicit, flow) {
|
|
130
|
+
if (explicit !== null)
|
|
131
|
+
return requireUuid('tenantId', explicit);
|
|
132
|
+
if (flow.tenant === null) {
|
|
133
|
+
throw new Error('[pipework] This support method needs a tenant in the Flow.\n\n' +
|
|
134
|
+
' Call it from an authenticated tenant route, or use the ...For(tenantId, ...) form\n' +
|
|
135
|
+
' (getFor, draftReplyFor, approveFor, ...) from a webhook or a job with no tenant.\n');
|
|
136
|
+
}
|
|
137
|
+
return flow.tenant;
|
|
138
|
+
}
|
|
139
|
+
async function run(explicit, fn) {
|
|
140
|
+
const flow = requireContext();
|
|
141
|
+
const tenantId = tenantOf(explicit, flow);
|
|
142
|
+
if (explicit !== null)
|
|
143
|
+
return inTenant(flow, tenantId, tx => fn(tx, tenantId, flow));
|
|
144
|
+
return pipe.transaction((tx) => fn(tx, tenantId, flow));
|
|
145
|
+
}
|
|
146
|
+
// An audit record under the Flow's open trace step (none: nothing). In a transaction it is a savepoint, so a
|
|
147
|
+
// failed write cannot abort the change it describes.
|
|
148
|
+
async function audit(flow, tx, tenantId, verb, entityId, details) {
|
|
149
|
+
const trace = flow.trace;
|
|
150
|
+
const stepId = trace?.buffer.openStepId ?? null;
|
|
151
|
+
if (trace === null || stepId === null)
|
|
152
|
+
return;
|
|
153
|
+
const write = async (db) => {
|
|
154
|
+
await db.execute(sql `
|
|
155
|
+
INSERT INTO audit_record
|
|
156
|
+
(trace_day, trace_id, trace_step_id, tenant_id, actor_id, entity, verb, entity_id, after, occurred_at)
|
|
157
|
+
VALUES (${trace.openedDay}, ${trace.id}, ${stepId}, ${tenantId}, ${resolveActorId(flow)},
|
|
158
|
+
${ENTITY}, ${verb}, ${entityId}, ${JSON.stringify(details)}::jsonb, now())`);
|
|
159
|
+
};
|
|
160
|
+
try {
|
|
161
|
+
if (tx === null)
|
|
162
|
+
await write(pipeSystem());
|
|
163
|
+
else
|
|
164
|
+
await tx.transaction(write);
|
|
165
|
+
}
|
|
166
|
+
catch (err) {
|
|
167
|
+
log.error({ err, traceId: trace.id }, `Failed to write the support ${verb} audit record`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
async function emit(tx, kind, ticket) {
|
|
171
|
+
const payload = {
|
|
172
|
+
kind, ticketId: ticket.id, tenantId: ticket.tenantId, subject: ticket.subject, state: ticket.state,
|
|
173
|
+
category: ticket.category, at: new Date().toISOString(),
|
|
174
|
+
};
|
|
175
|
+
await tx.execute(sql `
|
|
176
|
+
INSERT INTO support_event_delivery (ticket_id, kind, sink, payload, created_at, next_attempt_at)
|
|
177
|
+
SELECT ${ticket.id}::uuid, ${kind}, s.sink, ${JSON.stringify(payload)}::jsonb, clock_timestamp(), clock_timestamp()
|
|
178
|
+
FROM jsonb_array_elements_text(${sinkNames}::jsonb) AS s(sink)`);
|
|
179
|
+
await config.queue.enqueue(tx, { type: jobType, payload: {}, continueFlow: true });
|
|
180
|
+
}
|
|
181
|
+
async function loadTicket(tx, tenantId, ticketId, lock) {
|
|
182
|
+
requireUuid('ticketId', ticketId);
|
|
183
|
+
const rows = lock
|
|
184
|
+
? await tx.execute(sql `SELECT * FROM support_ticket WHERE id = ${ticketId}::uuid AND tenant_id = ${tenantId}::uuid FOR UPDATE`)
|
|
185
|
+
: await tx.execute(sql `SELECT * FROM support_ticket WHERE id = ${ticketId}::uuid AND tenant_id = ${tenantId}::uuid`);
|
|
186
|
+
if (rows[0] === undefined)
|
|
187
|
+
throw new NotFoundError('Support ticket', { ticketId });
|
|
188
|
+
return toTicket(rows[0]);
|
|
189
|
+
}
|
|
190
|
+
async function loadDraftRow(tx, tenantId, draftId) {
|
|
191
|
+
requireUuid('draftId', draftId);
|
|
192
|
+
const rows = await tx.execute(sql `SELECT * FROM support_message WHERE id = ${draftId}::uuid AND tenant_id = ${tenantId}::uuid AND kind = 'draft'`);
|
|
193
|
+
if (rows[0] === undefined)
|
|
194
|
+
throw new NotFoundError('Support draft', { draftId });
|
|
195
|
+
return rows[0];
|
|
196
|
+
}
|
|
197
|
+
async function moveTo(flow, tx, ticket, to, internalMove) {
|
|
198
|
+
await machine.transition({ entityId: ticket.id, entityType: 'SupportTicket', from: ticket.state, to, metadata: { internal: internalMove } });
|
|
199
|
+
const rows = await tx.execute(sql `UPDATE support_ticket SET state = ${to}, updated_at = clock_timestamp() WHERE id = ${ticket.id}::uuid RETURNING *`);
|
|
200
|
+
await audit(flow, tx, ticket.tenantId, 'transition', ticket.id, { from: ticket.state, to });
|
|
201
|
+
return toTicket(rows[0]);
|
|
202
|
+
}
|
|
203
|
+
async function discardLive(flow, tx, ticket, reason) {
|
|
204
|
+
const rows = await tx.execute(sql `
|
|
205
|
+
UPDATE support_message SET draft_status = 'discarded'
|
|
206
|
+
WHERE ticket_id = ${ticket.id}::uuid AND kind = 'draft' AND draft_status = 'draft' RETURNING id`);
|
|
207
|
+
for (const r of rows)
|
|
208
|
+
await audit(flow, tx, ticket.tenantId, 'discard', ticket.id, { draftId: r['id'], reason });
|
|
209
|
+
return rows.length > 0;
|
|
210
|
+
}
|
|
211
|
+
async function lockConversation(tx, tenantId, key) {
|
|
212
|
+
await tx.execute(sql `SELECT pg_advisory_xact_lock(hashtextextended(${`pipework.support:${tenantId}:${key}`}, 0))`);
|
|
213
|
+
}
|
|
214
|
+
async function ingest(flow, tx, tenantId, m) {
|
|
215
|
+
await lockConversation(tx, tenantId, m.conversationId ?? m.inboundEmailId ?? m.ticketId ?? m.contactEmail);
|
|
216
|
+
if (m.inboundEmailId !== null) {
|
|
217
|
+
const seen = await tx.execute(sql `SELECT ticket_id FROM support_message WHERE tenant_id = ${tenantId}::uuid AND inbound_email_id = ${m.inboundEmailId}::uuid`);
|
|
218
|
+
if (seen[0] !== undefined)
|
|
219
|
+
return { status: 'duplicate', ticketId: seen[0]['ticket_id'], created: false };
|
|
220
|
+
}
|
|
221
|
+
let ticket = null;
|
|
222
|
+
if (m.ticketId !== null) {
|
|
223
|
+
ticket = await loadTicket(tx, tenantId, m.ticketId, true);
|
|
224
|
+
if (ticket.contactEmail !== m.contactEmail) {
|
|
225
|
+
throw new ForbiddenError('The sender is not the ticket\'s contact.', { ticketId: m.ticketId });
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
else if (m.conversationId !== null && m.separate !== true) {
|
|
229
|
+
const found = await tx.execute(sql `
|
|
230
|
+
SELECT t.id FROM support_ticket t
|
|
231
|
+
WHERE t.tenant_id = ${tenantId}::uuid AND t.contact_email = ${m.contactEmail}
|
|
232
|
+
AND (t.conversation_id = ${m.conversationId}::uuid OR EXISTS (
|
|
233
|
+
SELECT 1 FROM support_message sm JOIN pipework_email_inbound i ON i.id = sm.inbound_email_id
|
|
234
|
+
WHERE sm.ticket_id = t.id AND i.conversation_id = ${m.conversationId}::uuid))
|
|
235
|
+
ORDER BY (t.conversation_id = ${m.conversationId}::uuid) DESC NULLS LAST, t.created_at DESC, t.id LIMIT 1`);
|
|
236
|
+
if (found[0] !== undefined)
|
|
237
|
+
ticket = await loadTicket(tx, tenantId, found[0]['id'], true);
|
|
238
|
+
}
|
|
239
|
+
let created = false;
|
|
240
|
+
if (ticket === null) {
|
|
241
|
+
let conversationId = m.conversationId;
|
|
242
|
+
if (m.separate === true)
|
|
243
|
+
conversationId = null;
|
|
244
|
+
if (conversationId !== null) {
|
|
245
|
+
const held = await tx.execute(sql `SELECT 1 FROM support_ticket WHERE tenant_id = ${tenantId}::uuid AND conversation_id = ${conversationId}::uuid`);
|
|
246
|
+
if (held.length > 0)
|
|
247
|
+
conversationId = null;
|
|
248
|
+
}
|
|
249
|
+
const rows = await tx.execute(sql `
|
|
250
|
+
INSERT INTO support_ticket (tenant_id, state, subject, contact_email, contact_name, user_id, conversation_id)
|
|
251
|
+
VALUES (${tenantId}::uuid, 'open', ${m.subject}, ${m.contactEmail}, ${m.contactName}, ${m.userId}, ${conversationId}::uuid)
|
|
252
|
+
RETURNING *`);
|
|
253
|
+
ticket = toTicket(rows[0]);
|
|
254
|
+
created = true;
|
|
255
|
+
await audit(flow, tx, tenantId, 'create', ticket.id, { subject: ticket.subject, contact: ticket.contactEmail, channel: m.channel });
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
await discardLive(flow, tx, ticket, 'customer-replied');
|
|
259
|
+
if (ticket.state !== 'open')
|
|
260
|
+
ticket = await moveTo(flow, tx, ticket, 'open', true);
|
|
261
|
+
const rows = await tx.execute(sql `UPDATE support_ticket SET last_customer_message_at = clock_timestamp(), updated_at = clock_timestamp() WHERE id = ${ticket.id}::uuid RETURNING *`);
|
|
262
|
+
ticket = toTicket(rows[0]);
|
|
263
|
+
}
|
|
264
|
+
await tx.execute(sql `
|
|
265
|
+
INSERT INTO support_message (tenant_id, ticket_id, kind, channel, text, html, from_address, inbound_email_id, attachments)
|
|
266
|
+
VALUES (${tenantId}::uuid, ${ticket.id}::uuid, 'inbound', ${m.channel}, ${m.text}, ${m.html}, ${m.fromAddress},
|
|
267
|
+
${m.inboundEmailId}::uuid, ${m.attachments === null ? null : JSON.stringify(m.attachments)}::jsonb)`);
|
|
268
|
+
await audit(flow, tx, tenantId, 'receive', ticket.id, { channel: m.channel, emailId: m.inboundEmailId, created, separated: m.separate === true });
|
|
269
|
+
await emit(tx, created ? 'ticket.created' : 'ticket.customer-replied', ticket);
|
|
270
|
+
return { status: 'received', ticketId: ticket.id, created };
|
|
271
|
+
}
|
|
272
|
+
async function receiveEmail(email) {
|
|
273
|
+
const flow = requireContext();
|
|
274
|
+
if (email.tenantId === null) {
|
|
275
|
+
log.warn({ emailId: email.id }, 'support: received email has no tenant; dropped');
|
|
276
|
+
return { status: 'no-tenant' };
|
|
277
|
+
}
|
|
278
|
+
const tenantId = email.tenantId;
|
|
279
|
+
const contactEmail = email.from.address.trim().toLowerCase();
|
|
280
|
+
const verdict = contactEmail === '' ? 'drop' : screen(email);
|
|
281
|
+
if (verdict === 'drop') {
|
|
282
|
+
await audit(flow, null, tenantId, 'drop', email.id, {
|
|
283
|
+
reason: contactEmail === '' ? 'no-sender' : 'screened', virus: email.verdicts?.virus ?? null,
|
|
284
|
+
});
|
|
285
|
+
return { status: 'dropped' };
|
|
286
|
+
}
|
|
287
|
+
const attachments = email.attachments.flatMap(a => a.file === null
|
|
288
|
+
? []
|
|
289
|
+
: [{ id: a.file.id, filename: a.filename, mediaType: a.mediaType, size: a.size }]);
|
|
290
|
+
return inTenant(flow, tenantId, tx => ingest(flow, tx, tenantId, {
|
|
291
|
+
channel: 'email', contactEmail, contactName: email.from.name === '' ? null : email.from.name, userId: null,
|
|
292
|
+
subject: email.subject.trim() === '' ? '(no subject)' : email.subject, text: email.text ?? '', html: email.html,
|
|
293
|
+
fromAddress: contactEmail, inboundEmailId: email.id, conversationId: email.conversationId,
|
|
294
|
+
attachments: attachments.length === 0 ? null : attachments, ticketId: null, separate: verdict === 'separate',
|
|
295
|
+
}));
|
|
296
|
+
}
|
|
297
|
+
async function receive(tenantId, input) {
|
|
298
|
+
const flow = requireContext();
|
|
299
|
+
requireUuid('tenantId', tenantId);
|
|
300
|
+
nonEmpty('text', input.text);
|
|
301
|
+
const contactEmail = nonEmpty('contact.email', input.contact.email).trim().toLowerCase();
|
|
302
|
+
if (input.channel !== 'chat' && input.channel !== 'api')
|
|
303
|
+
throw new ValidationError({ channel: ['must be chat or api'] }, 'support.receive: channel must be "chat" or "api".');
|
|
304
|
+
const firstLine = input.text.trim().split('\n')[0].slice(0, 200);
|
|
305
|
+
return inTenant(flow, tenantId, tx => ingest(flow, tx, tenantId, {
|
|
306
|
+
channel: input.channel, contactEmail, contactName: input.contact.name ?? null, userId: input.contact.userId ?? null,
|
|
307
|
+
subject: input.subject ?? firstLine, text: input.text, html: input.html ?? null, fromAddress: contactEmail,
|
|
308
|
+
inboundEmailId: null, conversationId: null, attachments: null, ticketId: input.ticketId ?? null,
|
|
309
|
+
}));
|
|
310
|
+
}
|
|
311
|
+
async function getDetail(tx, tenantId, ticketId) {
|
|
312
|
+
const ticket = await loadTicket(tx, tenantId, ticketId, false);
|
|
313
|
+
const messages = await tx.execute(sql `SELECT * FROM support_message WHERE ticket_id = ${ticketId}::uuid ORDER BY created_at, id`);
|
|
314
|
+
const links = await tx.execute(sql `SELECT * FROM support_link WHERE ticket_id = ${ticketId}::uuid ORDER BY created_at, id`);
|
|
315
|
+
return { ticket, messages: messages.map(toMessage), links: links.map(toLink) };
|
|
316
|
+
}
|
|
317
|
+
async function listTickets(tx, tenantId, options = {}) {
|
|
318
|
+
const limit = Math.min(options.limit ?? DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT);
|
|
319
|
+
if (!Number.isInteger(limit) || limit < 1)
|
|
320
|
+
throw new ValidationError({ limit: ['must be a positive integer'] }, 'support.list: limit must be a positive integer.');
|
|
321
|
+
let cursorAt = null;
|
|
322
|
+
let cursorId = null;
|
|
323
|
+
if (options.cursor !== undefined) {
|
|
324
|
+
const [at, id] = Buffer.from(options.cursor, 'base64url').toString('utf-8').split('|');
|
|
325
|
+
if (at === undefined || id === undefined || !UUID_RE.test(id) || Number.isNaN(Date.parse(at))) {
|
|
326
|
+
throw new ValidationError({ cursor: ['is not a cursor from a previous page'] }, 'support.list: bad cursor.');
|
|
327
|
+
}
|
|
328
|
+
cursorAt = at;
|
|
329
|
+
cursorId = id;
|
|
330
|
+
}
|
|
331
|
+
const rows = await tx.execute(sql `
|
|
332
|
+
SELECT t.*, t.created_at::text AS created_at_raw FROM support_ticket t
|
|
333
|
+
WHERE t.tenant_id = ${tenantId}::uuid
|
|
334
|
+
AND (${options.state ?? null}::text IS NULL OR t.state = ${options.state ?? null})
|
|
335
|
+
AND (${options.category ?? null}::text IS NULL OR t.category = ${options.category ?? null})
|
|
336
|
+
AND (${cursorAt}::timestamptz IS NULL OR (t.created_at, t.id) < (${cursorAt}::timestamptz, ${cursorId}::uuid))
|
|
337
|
+
ORDER BY t.created_at DESC, t.id DESC LIMIT ${limit + 1}`);
|
|
338
|
+
const page = rows.slice(0, limit);
|
|
339
|
+
const last = page[page.length - 1];
|
|
340
|
+
const next = rows.length > limit && last !== undefined
|
|
341
|
+
? Buffer.from(`${String(last['created_at_raw'])}|${String(last['id'])}`).toString('base64url')
|
|
342
|
+
: null;
|
|
343
|
+
return { tickets: page.map(toTicket), next };
|
|
344
|
+
}
|
|
345
|
+
async function setCategory(flow, tx, tenantId, ticketId, category) {
|
|
346
|
+
if (category !== null)
|
|
347
|
+
nonEmpty('category', category);
|
|
348
|
+
const before = await loadTicket(tx, tenantId, ticketId, true);
|
|
349
|
+
const rows = await tx.execute(sql `UPDATE support_ticket SET category = ${category}, updated_at = clock_timestamp() WHERE id = ${ticketId}::uuid RETURNING *`);
|
|
350
|
+
await audit(flow, tx, tenantId, 'categorise', ticketId, { from: before.category, to: category });
|
|
351
|
+
return toTicket(rows[0]);
|
|
352
|
+
}
|
|
353
|
+
async function transition(flow, tx, tenantId, ticketId, to) {
|
|
354
|
+
if (!TICKET_STATES.includes(to))
|
|
355
|
+
throw new ValidationError({ to: [`must be one of ${TICKET_STATES.join(', ')}`] }, `support.transition: unknown state "${String(to)}".`);
|
|
356
|
+
const ticket = await loadTicket(tx, tenantId, ticketId, true);
|
|
357
|
+
return moveTo(flow, tx, ticket, to, false);
|
|
358
|
+
}
|
|
359
|
+
async function addNote(flow, tx, tenantId, ticketId, text) {
|
|
360
|
+
nonEmpty('text', text);
|
|
361
|
+
await loadTicket(tx, tenantId, ticketId, true);
|
|
362
|
+
const rows = await tx.execute(sql `
|
|
363
|
+
INSERT INTO support_message (tenant_id, ticket_id, kind, channel, text, created_by)
|
|
364
|
+
VALUES (${tenantId}::uuid, ${ticketId}::uuid, 'note', 'api', ${text}, ${resolveActorId(flow)}) RETURNING *`);
|
|
365
|
+
await tx.execute(sql `UPDATE support_ticket SET updated_at = clock_timestamp() WHERE id = ${ticketId}::uuid`);
|
|
366
|
+
await audit(flow, tx, tenantId, 'note', ticketId, { messageId: rows[0]['id'] });
|
|
367
|
+
return toMessage(rows[0]);
|
|
368
|
+
}
|
|
369
|
+
async function link(flow, tx, tenantId, ticketId, l) {
|
|
370
|
+
nonEmpty('kind', l.kind);
|
|
371
|
+
nonEmpty('ref', l.ref);
|
|
372
|
+
await loadTicket(tx, tenantId, ticketId, true);
|
|
373
|
+
await tx.execute(sql `
|
|
374
|
+
INSERT INTO support_link (tenant_id, ticket_id, kind, ref, label)
|
|
375
|
+
VALUES (${tenantId}::uuid, ${ticketId}::uuid, ${l.kind}, ${l.ref}, ${l.label ?? null})
|
|
376
|
+
ON CONFLICT (ticket_id, kind, ref) DO UPDATE SET label = COALESCE(EXCLUDED.label, support_link.label)`);
|
|
377
|
+
const rows = await tx.execute(sql `SELECT * FROM support_link WHERE ticket_id = ${ticketId}::uuid AND kind = ${l.kind} AND ref = ${l.ref}`);
|
|
378
|
+
await audit(flow, tx, tenantId, 'link', ticketId, { kind: l.kind, ref: l.ref });
|
|
379
|
+
return toLink(rows[0]);
|
|
380
|
+
}
|
|
381
|
+
async function draftReply(flow, tx, tenantId, ticketId, draft) {
|
|
382
|
+
nonEmpty('text', draft.text);
|
|
383
|
+
if (draft.subject !== undefined)
|
|
384
|
+
nonEmpty('subject', draft.subject);
|
|
385
|
+
let ticket = await loadTicket(tx, tenantId, ticketId, true);
|
|
386
|
+
if (ticket.state === 'awaiting_approval') {
|
|
387
|
+
await discardLive(flow, tx, ticket, 'replaced');
|
|
388
|
+
}
|
|
389
|
+
else {
|
|
390
|
+
// From open the draft passes through triaged: both moves are taken and audited.
|
|
391
|
+
if (ticket.state === 'open')
|
|
392
|
+
ticket = await moveTo(flow, tx, ticket, 'triaged', true);
|
|
393
|
+
ticket = await moveTo(flow, tx, ticket, 'awaiting_approval', true);
|
|
394
|
+
}
|
|
395
|
+
const rows = await tx.execute(sql `
|
|
396
|
+
INSERT INTO support_message (tenant_id, ticket_id, kind, channel, subject, text, html, draft_status, created_by)
|
|
397
|
+
VALUES (${tenantId}::uuid, ${ticketId}::uuid, 'draft', 'email', ${draft.subject ?? null}, ${draft.text}, ${draft.html ?? null}, 'draft', ${resolveActorId(flow)})
|
|
398
|
+
RETURNING id, version`);
|
|
399
|
+
const draftId = rows[0]['id'];
|
|
400
|
+
await audit(flow, tx, tenantId, 'draft', ticketId, { draftId, version: 1 });
|
|
401
|
+
await emit(tx, 'draft.awaiting-approval', ticket);
|
|
402
|
+
return { draftId, version: Number(rows[0]['version']) };
|
|
403
|
+
}
|
|
404
|
+
async function editDraft(flow, tx, tenantId, draftId, patch) {
|
|
405
|
+
if (patch.text !== undefined)
|
|
406
|
+
nonEmpty('text', patch.text);
|
|
407
|
+
if (patch.subject !== undefined)
|
|
408
|
+
nonEmpty('subject', patch.subject);
|
|
409
|
+
const row = await loadDraftRow(tx, tenantId, draftId);
|
|
410
|
+
await loadTicket(tx, tenantId, row['ticket_id'], true);
|
|
411
|
+
const rows = await tx.execute(sql `
|
|
412
|
+
UPDATE support_message SET
|
|
413
|
+
text = COALESCE(${patch.text ?? null}, text), html = COALESCE(${patch.html ?? null}, html),
|
|
414
|
+
subject = COALESCE(${patch.subject ?? null}, subject), version = version + 1, created_by = ${resolveActorId(flow)}
|
|
415
|
+
WHERE id = ${draftId}::uuid AND draft_status = 'draft' RETURNING version`);
|
|
416
|
+
if (rows[0] === undefined)
|
|
417
|
+
throw staleDraft(String(row['draft_status']));
|
|
418
|
+
const version = Number(rows[0]['version']);
|
|
419
|
+
await audit(flow, tx, tenantId, 'draft', row['ticket_id'], { draftId, version, edited: true });
|
|
420
|
+
return { draftId, version };
|
|
421
|
+
}
|
|
422
|
+
function staleDraft(status, version) {
|
|
423
|
+
if (status === 'approved')
|
|
424
|
+
return new DraftStateError('approved', 'This draft is already approved.');
|
|
425
|
+
if (status === 'discarded')
|
|
426
|
+
return new DraftStateError('discarded', 'This draft was discarded.');
|
|
427
|
+
return new DraftStateError('changed', `This draft changed since it was read (version ${String(version?.actual)}, expected ${String(version?.expected)}).`);
|
|
428
|
+
}
|
|
429
|
+
async function discardDraft(flow, tx, tenantId, draftId) {
|
|
430
|
+
const row = await loadDraftRow(tx, tenantId, draftId);
|
|
431
|
+
const ticket = await loadTicket(tx, tenantId, row['ticket_id'], true);
|
|
432
|
+
const rows = await tx.execute(sql `UPDATE support_message SET draft_status = 'discarded' WHERE id = ${draftId}::uuid AND draft_status = 'draft' RETURNING id`);
|
|
433
|
+
if (rows[0] === undefined)
|
|
434
|
+
throw staleDraft(String(row['draft_status']));
|
|
435
|
+
await audit(flow, tx, tenantId, 'discard', ticket.id, { draftId, reason: 'discarded' });
|
|
436
|
+
await moveTo(flow, tx, ticket, 'triaged', true);
|
|
437
|
+
}
|
|
438
|
+
async function approve(explicit, draftId, options) {
|
|
439
|
+
const flow = requireContext();
|
|
440
|
+
const tenantId = tenantOf(explicit, flow);
|
|
441
|
+
const actorId = resolveActorId(flow);
|
|
442
|
+
if (actorId === null)
|
|
443
|
+
throw new ForbiddenError('Approving a reply needs an authenticated actor.');
|
|
444
|
+
if (!Number.isInteger(options.expectedVersion))
|
|
445
|
+
throw new ValidationError({ expectedVersion: ['must be an integer'] }, 'support.approve needs the expectedVersion the approver read.');
|
|
446
|
+
if (!(await config.canApprove({ actorId, tenantId }))) {
|
|
447
|
+
throw new ForbiddenError('This actor may not approve replies.', { actorId, tenantId });
|
|
448
|
+
}
|
|
449
|
+
return run(explicit, async (tx) => {
|
|
450
|
+
// The ticket row is locked first, so a customer message, a discard and a second approve wait for this one.
|
|
451
|
+
const row = await loadDraftRow(tx, tenantId, draftId);
|
|
452
|
+
const ticket = await loadTicket(tx, tenantId, row['ticket_id'], true);
|
|
453
|
+
const draft = toMessage(await loadDraftRow(tx, tenantId, draftId));
|
|
454
|
+
if (distinctApprover && draft.createdBy === actorId) {
|
|
455
|
+
throw new ForbiddenError('A draft cannot be approved by its author.', { actorId });
|
|
456
|
+
}
|
|
457
|
+
const claimed = await tx.execute(sql `
|
|
458
|
+
UPDATE support_message SET draft_status = 'approved', approved_by = ${actorId}, approved_at = clock_timestamp()
|
|
459
|
+
WHERE id = ${draftId}::uuid AND draft_status = 'draft' AND version = ${options.expectedVersion}
|
|
460
|
+
RETURNING *`);
|
|
461
|
+
if (claimed[0] === undefined)
|
|
462
|
+
throw staleDraft(draft.draftStatus ?? 'changed', { expected: options.expectedVersion, actual: draft.version });
|
|
463
|
+
// What is sent is what the update matched, not the earlier read.
|
|
464
|
+
const approved = toMessage(claimed[0]);
|
|
465
|
+
if (ticket.state !== 'awaiting_approval') {
|
|
466
|
+
throw new DraftStateError('not-awaiting-approval', `The ticket is ${ticket.state}, not awaiting approval.`);
|
|
467
|
+
}
|
|
468
|
+
const parent = await tx.execute(sql `
|
|
469
|
+
SELECT inbound_email_id FROM support_message
|
|
470
|
+
WHERE ticket_id = ${ticket.id}::uuid AND kind = 'inbound' AND inbound_email_id IS NOT NULL
|
|
471
|
+
ORDER BY created_at DESC, id DESC LIMIT 1`);
|
|
472
|
+
const inReplyTo = (parent[0]?.['inbound_email_id'] ?? null);
|
|
473
|
+
const subject = approved.subject ?? (/^re:/i.test(ticket.subject) ? ticket.subject : `Re: ${ticket.subject}`);
|
|
474
|
+
const sent = await config.mail.send(tx, {
|
|
475
|
+
to: ticket.contactEmail, template: replyTemplate,
|
|
476
|
+
data: { subject, text: approved.text, ...(approved.html !== null ? { html: approved.html } : {}) },
|
|
477
|
+
key: `support-reply:${draftId}`,
|
|
478
|
+
...(ticket.conversationId !== null ? { conversationId: ticket.conversationId } : {}),
|
|
479
|
+
...(inReplyTo !== null ? { inReplyTo } : {}),
|
|
480
|
+
});
|
|
481
|
+
await tx.execute(sql `UPDATE support_message SET email_message_id = ${sent.messageId}::uuid WHERE id = ${draftId}::uuid`);
|
|
482
|
+
const outbound = await tx.execute(sql `
|
|
483
|
+
INSERT INTO support_message (tenant_id, ticket_id, kind, channel, subject, text, html, approved_by, approved_at, email_message_id, created_by)
|
|
484
|
+
VALUES (${tenantId}::uuid, ${ticket.id}::uuid, 'outbound', 'email', ${subject}, ${approved.text}, ${approved.html}, ${actorId},
|
|
485
|
+
clock_timestamp(), ${sent.messageId}::uuid, ${approved.createdBy})
|
|
486
|
+
RETURNING id`);
|
|
487
|
+
await moveTo(flow, tx, ticket, 'answered', true);
|
|
488
|
+
await audit(flow, tx, tenantId, 'approve', ticket.id, { draftId, version: draft.version, approvedBy: actorId, emailMessageId: sent.messageId, author: draft.createdBy });
|
|
489
|
+
return { messageId: outbound[0]['id'], emailMessageId: sent.messageId };
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
const outbox = createOutbox({
|
|
493
|
+
table: 'support_event_delivery', groupColumn: 'ticket_id', database: undefined, sinks,
|
|
494
|
+
maxAttempts: config.maxAttempts ?? 10, backoffMs: config.backoffMs ?? 5000, label: 'support event delivery given up',
|
|
495
|
+
toDelivery: (row, attempt) => ({
|
|
496
|
+
id: row['id'], kind: row['kind'], key: row['ticket_id'], sink: row['sink'],
|
|
497
|
+
payload: row['payload'], attempt,
|
|
498
|
+
}),
|
|
499
|
+
onDelivered: (row, attempt) => auditDelivery('deliver', row, { attempt }),
|
|
500
|
+
onGivenUp: (row, attempt, error) => auditDelivery('deliver-failed', row, { attempt, error }),
|
|
501
|
+
});
|
|
502
|
+
async function auditDelivery(verb, row, extra) {
|
|
503
|
+
const flow = requireContext();
|
|
504
|
+
const payload = row['payload'];
|
|
505
|
+
await audit(flow, null, payload.tenantId, verb, row['ticket_id'], { sink: row['sink'], kind: row['kind'], ...extra });
|
|
506
|
+
}
|
|
507
|
+
const tickStep = __flowStep({ ref: 'pipework/support:tick' }, () => outbox.drain());
|
|
508
|
+
const job = fitting.use().job(jobType).fit(async () => tickStep());
|
|
509
|
+
// Each call exists twice: for the Flow's tenant, and as `<name>For(tenantId, ...)`.
|
|
510
|
+
const ops = {
|
|
511
|
+
get: (_f, tx, t, id) => getDetail(tx, t, id),
|
|
512
|
+
list: (_f, tx, t, o) => listTickets(tx, t, o),
|
|
513
|
+
setCategory: (f, tx, t, id, c) => setCategory(f, tx, t, id, c),
|
|
514
|
+
transition: (f, tx, t, id, to) => transition(f, tx, t, id, to),
|
|
515
|
+
addNote: (f, tx, t, id, text) => addNote(f, tx, t, id, text),
|
|
516
|
+
link: (f, tx, t, id, l) => link(f, tx, t, id, l),
|
|
517
|
+
draftReply: (f, tx, t, id, d) => draftReply(f, tx, t, id, d),
|
|
518
|
+
editDraft: (f, tx, t, id, d) => editDraft(f, tx, t, id, d),
|
|
519
|
+
discardDraft: (f, tx, t, id) => discardDraft(f, tx, t, id),
|
|
520
|
+
};
|
|
521
|
+
const api = {
|
|
522
|
+
approve: (draftId, options) => approve(null, draftId, options),
|
|
523
|
+
approveFor: (tenantId, draftId, options) => approve(tenantId, draftId, options),
|
|
524
|
+
};
|
|
525
|
+
for (const [name, fn] of Object.entries(ops)) {
|
|
526
|
+
const call = fn;
|
|
527
|
+
api[name] = (...args) => run(null, (tx, t, f) => call(f, tx, t, ...args));
|
|
528
|
+
api[`${name}For`] = (tenantId, ...args) => run(tenantId, (tx, t, f) => call(f, tx, t, ...args));
|
|
529
|
+
}
|
|
530
|
+
return {
|
|
531
|
+
...api,
|
|
532
|
+
receiveEmail,
|
|
533
|
+
receive,
|
|
534
|
+
job: job,
|
|
535
|
+
tick: () => tickStep(),
|
|
536
|
+
async deliveries(options = {}) {
|
|
537
|
+
const rows = options.ticketId === undefined
|
|
538
|
+
? await pipeSystem().execute(sql `SELECT * FROM support_event_delivery ORDER BY created_at, id`)
|
|
539
|
+
: await pipeSystem().execute(sql `SELECT * FROM support_event_delivery WHERE ticket_id = ${options.ticketId}::uuid ORDER BY created_at, id`);
|
|
540
|
+
return rows.map(r => ({
|
|
541
|
+
id: r['id'], ticketId: r['ticket_id'], kind: r['kind'], sink: r['sink'],
|
|
542
|
+
attempts: Number(r['attempts']), deliveredAt: r['delivered_at'] === null ? null : toDate(r['delivered_at']),
|
|
543
|
+
failedAt: r['failed_at'] === null ? null : toDate(r['failed_at']), lastError: (r['last_error'] ?? null),
|
|
544
|
+
}));
|
|
545
|
+
},
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
//# sourceMappingURL=handle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handle.js","sourceRoot":"","sources":["../../../src/infra/support/handle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { createSupport, supportTemplates, DraftStateError } from './handle.js';
|
|
2
|
+
export type { Support, SupportConfig, TicketApi, Ticket, TicketMessage, TicketLink, TicketDetail, TicketState, ListOptions, ListPage, DraftInput, SupportSink, SupportDelivery, ScreenVerdict, ReceiveResult, ReceiveInput, SupportEventKind, SupportEventPayload, } from './handle.js';
|
|
3
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/infra/support/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC9E,YAAY,EACV,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,EACtH,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,gBAAgB,EAAE,mBAAmB,GAC5H,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/infra/support/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA"}
|