backend-manager 5.11.5 → 5.11.7
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/package.json +1 -1
- package/src/cli/commands/serve.js +49 -2
- package/src/manager/functions/core/actions/api/general/add-marketing-contact.js +4 -1
- package/src/manager/libraries/prompts/infer-contact.md +5 -0
- package/src/manager/routes/marketing/contact/post.js +4 -1
- package/src/test/fixtures/firebase-project/.temp/newsletter/run-2026-07-03T23-24-21/metadata.json +14 -0
- package/src/test/fixtures/firebase-project/.temp/newsletter/run-2026-07-03T23-24-21/newsletter.html +486 -0
- package/src/test/fixtures/firebase-project/.temp/newsletter/run-2026-07-03T23-24-21/newsletter.md +41 -0
- package/src/test/fixtures/firebase-project/.temp/newsletter/run-2026-07-03T23-24-21/newsletter.mjml +97 -0
- package/src/test/fixtures/firebase-project/.temp/newsletter/run-2026-07-03T23-24-21/structure.json +42 -0
- package/src/test/fixtures/firebase-project/.temp/newsletter/run-2026-07-03T23-24-21/summary.md +1 -0
- package/src/test/fixtures/firebase-project/.temp/newsletter/run-2026-07-03T23-25-51/metadata.json +14 -0
- package/src/test/fixtures/firebase-project/.temp/newsletter/run-2026-07-03T23-25-51/newsletter.html +486 -0
- package/src/test/fixtures/firebase-project/.temp/newsletter/run-2026-07-03T23-25-51/newsletter.md +41 -0
- package/src/test/fixtures/firebase-project/.temp/newsletter/run-2026-07-03T23-25-51/newsletter.mjml +97 -0
- package/src/test/fixtures/firebase-project/.temp/newsletter/run-2026-07-03T23-25-51/structure.json +42 -0
- package/src/test/fixtures/firebase-project/.temp/newsletter/run-2026-07-03T23-25-51/summary.md +1 -0
- package/src/test/fixtures/firebase-project/.temp/newsletter/run-2026-07-03T23-27-47/metadata.json +14 -0
- package/src/test/fixtures/firebase-project/.temp/newsletter/run-2026-07-03T23-27-47/newsletter.html +486 -0
- package/src/test/fixtures/firebase-project/.temp/newsletter/run-2026-07-03T23-27-47/newsletter.md +41 -0
- package/src/test/fixtures/firebase-project/.temp/newsletter/run-2026-07-03T23-27-47/newsletter.mjml +97 -0
- package/src/test/fixtures/firebase-project/.temp/newsletter/run-2026-07-03T23-27-47/structure.json +42 -0
- package/src/test/fixtures/firebase-project/.temp/newsletter/run-2026-07-03T23-27-47/summary.md +1 -0
- package/src/test/fixtures/firebase-project/.temp/test-mode.json +1 -1
- package/src/test/fixtures/firebase-project/database-debug.log +8 -8
- package/src/test/fixtures/firebase-project/firestore-debug.log +56 -54
- package/src/test/fixtures/firebase-project/pubsub-debug.log +4 -4
- package/test/email/marketing-lifecycle.js +5 -0
- package/test/email/validation.js +42 -7
- package/test/functions/admin/edit-post.js +14 -10
- package/test/functions/general/add-marketing-contact.js +56 -16
- package/test/routes/admin/post.js +14 -10
- package/test/routes/marketing/contact.js +43 -10
|
@@ -9,9 +9,11 @@
|
|
|
9
9
|
// Test email patterns - look like real emails but +bem suffix identifies them for cleanup.
|
|
10
10
|
// Names should be inferred by AI from the email local part.
|
|
11
11
|
//
|
|
12
|
-
// Fixed test domain (`
|
|
13
|
-
// domain caused cross-brand state divergence in SendGrid/Beehiiv and
|
|
14
|
-
// company inference
|
|
12
|
+
// Fixed test domain (`itwcreativeworks.com`) — deterministic across brands (using the
|
|
13
|
+
// running brand's domain caused cross-brand state divergence in SendGrid/Beehiiv and
|
|
14
|
+
// non-deterministic company inference), and we control it: mailbox verdicts are stable
|
|
15
|
+
// and any double-opt-in email lands on our own domain. Was `acme.com`, but the AI now
|
|
16
|
+
// treats that domain as a placeholder (empty names, confidence 0), breaking inference.
|
|
15
17
|
//
|
|
16
18
|
// `valid`: use a name that won't be flagged as fictional/placeholder by the AI prompt.
|
|
17
19
|
// (The infer-contact prompt rejects fictional names — e.g. "rachel.greene" sometimes
|
|
@@ -21,7 +23,7 @@
|
|
|
21
23
|
// NOT start with "test"/"example" which are in BLOCKED_LOCAL_PATTERNS, NOT be on
|
|
22
24
|
// a corporate/disposable domain). Real-looking name on a real domain with no actual
|
|
23
25
|
// mailbox there is the safest pick.
|
|
24
|
-
const TEST_DOMAIN = '
|
|
26
|
+
const TEST_DOMAIN = 'itwcreativeworks.com';
|
|
25
27
|
const TEST_EMAILS = {
|
|
26
28
|
valid: () => `sarah.martinez+bem@${TEST_DOMAIN}`, // Should infer: Sarah Martinez
|
|
27
29
|
invalid: () => `nonexistent.user+bem@${TEST_DOMAIN}`, // No such mailbox — mailbox verification should flag as invalid
|
|
@@ -164,6 +166,10 @@ module.exports = {
|
|
|
164
166
|
email: testEmail,
|
|
165
167
|
source: 'bem-test',
|
|
166
168
|
// No firstName/lastName - should be inferred
|
|
169
|
+
// skipValidation bypasses the mailbox verification check — this test's concern
|
|
170
|
+
// is AI name inference (which runs after validation); without it the mailbox
|
|
171
|
+
// check 400s the fabricated address before the inference asserts run.
|
|
172
|
+
skipValidation: true,
|
|
167
173
|
});
|
|
168
174
|
|
|
169
175
|
assert.isSuccess(response, 'Add marketing contact should succeed');
|
|
@@ -245,6 +251,27 @@ module.exports = {
|
|
|
245
251
|
source: 'bem-test',
|
|
246
252
|
});
|
|
247
253
|
|
|
254
|
+
// Outcome A: the provider rejected the fabricated mailbox → admin 400. Every
|
|
255
|
+
// earlier check passes deterministically for this address (format/localPart/
|
|
256
|
+
// disposable/corporate return their own dedicated messages, typo can't match,
|
|
257
|
+
// and the domain has real MX), so reaching the generic validation-failed 400
|
|
258
|
+
// proves the paid mailbox pipeline ran and rejected. Nothing was added, so
|
|
259
|
+
// cleanup is a no-op.
|
|
260
|
+
if (response.status === 400) {
|
|
261
|
+
assert.ok(
|
|
262
|
+
response.error?.includes('Email validation failed'),
|
|
263
|
+
`400 should be the validation-failed branch, got: ${response.error}`
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
if (response.error.includes('(dns)')) {
|
|
267
|
+
skip('Transient DNS failure — mailbox check never ran');
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
assert.ok(response.error.includes('(mailbox)'), `Failed check should be mailbox, got: ${response.error}`);
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Outcome B: provider accepted (valid/catch-all/unknown) or failed open.
|
|
248
275
|
assert.isSuccess(response, 'Add marketing contact should succeed');
|
|
249
276
|
|
|
250
277
|
// Check that validation info is included
|
|
@@ -256,9 +283,10 @@ module.exports = {
|
|
|
256
283
|
|
|
257
284
|
const mbResult = response.data.validation.checks.mailbox;
|
|
258
285
|
|
|
259
|
-
//
|
|
260
|
-
|
|
261
|
-
|
|
286
|
+
// Provider errors fail open as { valid: true, error, provider } with NO status
|
|
287
|
+
// field — out of credits, bad key, timeouts. Nothing assertable; skip.
|
|
288
|
+
if (mbResult.error) {
|
|
289
|
+
skip(`Mailbox verification unavailable: ${mbResult.error}`);
|
|
262
290
|
}
|
|
263
291
|
|
|
264
292
|
assert.hasProperty(mbResult, 'status', 'Mailbox check should return status');
|
|
@@ -301,13 +329,18 @@ module.exports = {
|
|
|
301
329
|
// verify here is that mailbox check ran and didn't mark the email as `valid`.
|
|
302
330
|
const mbResult = response.data?.validation?.checks?.mailbox;
|
|
303
331
|
|
|
304
|
-
//
|
|
305
|
-
if (mbResult?.error
|
|
306
|
-
skip(
|
|
332
|
+
// Provider errors fail open with no status — the test can't exercise rejection; skip.
|
|
333
|
+
if (mbResult?.error) {
|
|
334
|
+
skip(`Mailbox verification unavailable: ${mbResult.error}`);
|
|
307
335
|
}
|
|
308
336
|
|
|
309
337
|
// If the response was a 400, that's the legitimate rejection path — done.
|
|
310
338
|
if (response.status === 400) {
|
|
339
|
+
if (response.error?.includes('(dns)')) {
|
|
340
|
+
skip('Transient DNS failure — mailbox check never ran');
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
assert.ok(response.error?.includes('(mailbox)'), `Failed check should be mailbox, got: ${response.error}`);
|
|
311
344
|
return;
|
|
312
345
|
}
|
|
313
346
|
|