backend-manager 5.0.203 → 5.1.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 +72 -0
- package/CLAUDE.md +100 -1529
- package/TODO-CHARGEBLAST.md +32 -0
- package/TODO-email-auth.md +14 -0
- package/docs/admin-post-route.md +24 -0
- package/docs/ai-library.md +23 -0
- package/docs/architecture.md +31 -0
- package/docs/auth-hooks.md +74 -0
- package/docs/cli-firestore-auth.md +59 -0
- package/docs/cli-logs.md +67 -0
- package/docs/code-patterns.md +67 -0
- package/docs/common-mistakes.md +11 -0
- package/docs/common-operations.md +64 -0
- package/docs/directory-structure.md +119 -0
- package/docs/environment-detection.md +7 -0
- package/docs/file-naming.md +11 -0
- package/docs/key-files.md +36 -0
- package/docs/marketing-campaigns.md +244 -0
- package/docs/marketing-fields.md +25 -0
- package/docs/mcp.md +95 -0
- package/docs/payment-system.md +325 -0
- package/docs/response-headers.md +7 -0
- package/docs/routes.md +126 -0
- package/docs/sanitization.md +61 -0
- package/docs/schemas.md +39 -0
- package/docs/stripe-webhook-forwarding.md +18 -0
- package/docs/testing.md +129 -0
- package/docs/usage-rate-limiting.md +67 -0
- package/package.json +8 -4
- package/scripts/update-disposable-domains.js +1 -1
- package/src/defaults/CHANGELOG.md +15 -0
- package/src/defaults/CLAUDE.md +8 -4
- package/src/defaults/docs/README.md +17 -0
- package/src/defaults/test/README.md +33 -0
- package/src/manager/events/cron/daily/marketing-newsletter-generate.js +48 -8
- package/src/manager/functions/core/actions/api/admin/create-post.js +3 -27
- package/src/manager/functions/core/actions/api/general/add-marketing-contact.js +5 -0
- package/src/manager/helpers/utilities.js +21 -0
- package/src/manager/index.js +1 -1
- package/src/manager/libraries/ai/index.js +162 -0
- package/src/manager/libraries/ai/providers/anthropic.js +193 -0
- package/src/manager/libraries/ai/providers/claude-code.js +206 -0
- package/src/manager/libraries/ai/providers/openai.js +934 -0
- package/src/manager/libraries/email/data/blocked-local-parts.json +55 -0
- package/src/manager/libraries/email/data/blocked-local-patterns.js +11 -0
- package/src/manager/libraries/email/data/corporate-domains.json +23 -0
- package/src/manager/libraries/{disposable-domains.json → email/data/disposable-domains.json} +3 -0
- package/src/manager/libraries/email/generators/lib/filter.js +179 -0
- package/src/manager/libraries/email/generators/lib/image-host.js +231 -0
- package/src/manager/libraries/email/generators/lib/mjml-template.js +83 -0
- package/src/manager/libraries/email/generators/lib/structure.js +278 -0
- package/src/manager/libraries/email/generators/lib/svg-illustrator.js +184 -0
- package/src/manager/libraries/email/generators/lib/templates/classic-schema.js +63 -0
- package/src/manager/libraries/email/generators/lib/templates/clean.js +82 -0
- package/src/manager/libraries/email/generators/lib/templates/editorial-helpers.js +100 -0
- package/src/manager/libraries/email/generators/lib/templates/editorial.js +317 -0
- package/src/manager/libraries/email/generators/lib/templates/field-report-helpers.js +138 -0
- package/src/manager/libraries/email/generators/lib/templates/field-report.js +497 -0
- package/src/manager/libraries/email/generators/lib/templates/index.js +28 -0
- package/src/manager/libraries/email/generators/lib/templates/shared.js +534 -0
- package/src/manager/libraries/email/generators/newsletter.js +377 -95
- package/src/manager/libraries/email/marketing/index.js +16 -2
- package/src/manager/libraries/email/providers/beehiiv.js +7 -3
- package/src/manager/libraries/email/validation.js +53 -38
- package/src/manager/libraries/openai.js +13 -932
- package/src/manager/routes/admin/post/deduplicate-image-alts.js +52 -0
- package/src/manager/routes/admin/post/post.js +10 -17
- package/src/manager/routes/marketing/contact/post.js +5 -1
- package/templates/_.env +4 -0
- package/templates/_.gitignore +1 -0
- package/templates/backend-manager-config.json +48 -4
- package/test/helpers/email-validation.js +141 -3
- package/test/helpers/slugify.js +394 -0
- package/test/marketing/fixtures/clean.json +31 -0
- package/test/marketing/fixtures/editorial.json +31 -0
- package/test/marketing/fixtures/field-report.json +54 -0
- package/test/marketing/newsletter-generate.js +731 -0
- package/test/marketing/newsletter-templates.js +512 -0
- package/test/routes/admin/deduplicate-image-alts.js +190 -0
- /package/src/manager/libraries/{custom-disposable-domains.json → email/data/custom-disposable-domains.json} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -14,6 +14,78 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
|
14
14
|
- `Fixed` for any bug fixes.
|
|
15
15
|
- `Security` in case of vulnerabilities.
|
|
16
16
|
|
|
17
|
+
# [5.1.1] - 2026-05-13
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- **Corporate / social-media domain blacklist** — new `corporate` check in `email/validation.js` blocks marketing-list adds from corporate social-media domains (meta.com, instagram.com, soundcloud.com, tiktok.com, x.com, reddit.com, linkedin.com, youtube.com, discord.com, telegram.org, signal.org, and more — 21 domains total). Added to `DEFAULT_CHECKS` so every existing caller of `validate()` picks it up automatically. New `isCorporate(emailOrDomain)` helper exported alongside `isDisposable()`.
|
|
22
|
+
- **Defense-in-depth guards** in `Marketing.add()` and `Marketing.sync()` — even when validation is bypassed (e.g. testing mode), corporate domains are blocked before any Beehiiv or SendGrid call.
|
|
23
|
+
- **13 new tests** in `test/helpers/email-validation.js` covering the `corporate` validate-check, the `isCorporate()` helper, case-insensitivity, edge cases, and check-ordering behavior. Suite: 44 pass, 0 fail, 2 skip (ZeroBounce-only).
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- **Email data files reorganized** — all blacklists now live in `src/manager/libraries/email/data/` (one folder, next to their consumer), instead of being scattered one level up alongside unrelated libraries:
|
|
28
|
+
- `disposable-domains.json`, `custom-disposable-domains.json`, `corporate-domains.json` — domain blocklists
|
|
29
|
+
- `blocked-local-parts.json` — categorized local-part blocklist (`generic`, `system`, `junk`, `placeholder`), extracted from a hardcoded `Set` in `validation.js`
|
|
30
|
+
- `blocked-local-patterns.js` — regex patterns, extracted from `validation.js` (kept as JS so RegExp literals stay native)
|
|
31
|
+
- **`scripts/update-disposable-domains.js`** — prepare-step downloader now writes to `email/data/disposable-domains.json`.
|
|
32
|
+
|
|
33
|
+
# [5.1.0] - 2026-05-13
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
|
|
37
|
+
#### Newsletter generation system
|
|
38
|
+
- **Three production-quality templates** with distinct aesthetics, each owning its own content schema and AI prompt — switching templates produces fundamentally different content, not a recolor:
|
|
39
|
+
- `clean` — Stripe/Linear marketing aesthetic. Safe, conservative, works everywhere.
|
|
40
|
+
- `editorial` — Magazine-style: masthead, drop-cap intro, numbered sections, pull-quotes, italic signoff.
|
|
41
|
+
- `field-report` — Wire-service correspondent × Bloomberg terminal. Dispatch kickers, datelines, mono data callouts, end-of-dispatch terminators, correspondent signoff.
|
|
42
|
+
- **Schema-per-template architecture** (`lib/structure.js` is now a generic dispatcher). `BASE_SCHEMA` declares universals (subject, preheader, signoff, citations); each template extends with its own fields via `schema.properties` + `schema.required`. `clean` + `editorial` share `CLASSIC_SCHEMA` (`{intro, sections: [{title, body, cta?, image_prompt}]}`); `field-report` declares `{tldr, dateline, dispatches: [{kicker, headline, byline, location, lede, dispatch, dataPoints, cta, image_prompt}]}`.
|
|
43
|
+
- **Templates export `buildPrompt({brand, newsletterConfig, sources})`** — each template fully owns its AI brief. `clean` + `editorial` use the shared classic prompt; `field-report` has its own wire-service-correspondent voice.
|
|
44
|
+
- **Graceful omission everywhere** — every template's `build()` handles missing optional fields (returns `''` for omitted blocks instead of throwing). Empty sections/dispatches drop entirely (no hollow stubs).
|
|
45
|
+
- **Asset hosting pipeline (`lib/image-host.js`)** — `uploadAssets({ images, html, brandId, campaignId, subject })` uploads section PNGs + `newsletter.html` to `itw-creative-works/newsletter-assets/{brandId}/{campaignId}/` via Git Trees API. PNG magic-byte verification + strict path regex. Public-safety guarantees baked in.
|
|
46
|
+
|
|
47
|
+
#### Daily cron pipeline (production-ready)
|
|
48
|
+
- **`marketing-newsletter-generate.js` now runs the FULL pipeline end-to-end**: fetch sources → AI structure → AI SVG → upload PNGs to GitHub → render HTML with embedded CDN URLs → upload `newsletter.html` to the same folder → upload Beehiiv draft (fails gracefully on free plan with `SEND_API_NOT_ENTERPRISE_PLAN`) → write `marketing-campaigns/{newId}` Firestore doc with `assets: { folderUrl, htmlUrl, imageUrls, beehiivPostId, campaignId }`.
|
|
49
|
+
- **Reserved Firestore doc ID is used as the GitHub folder name** so URLs and the campaign doc always match.
|
|
50
|
+
|
|
51
|
+
#### Unified AI library
|
|
52
|
+
- **`src/manager/libraries/ai/`** — `Manager.AI(assistant).request({ provider: 'openai' | 'anthropic' | 'claude-code', ... })` dispatches to either provider with a consistent options + return shape. OpenAI is the default (back-compat); Anthropic added for SVG generation; `claude-code` provider added via `@anthropic-ai/claude-agent-sdk` for credit-less subscription-backed generation.
|
|
53
|
+
- New env var: `BACKEND_MANAGER_ANTHROPIC_API_KEY` / `ANTHROPIC_API_KEY`.
|
|
54
|
+
|
|
55
|
+
#### Iteration test as mirror of production
|
|
56
|
+
- **Fixture mode is the default** (`npx mgr test bem:marketing/newsletter-generate`) — loads `test/marketing/fixtures/<active-template>.json` and renders straight through MJML. ~35ms, $0, deterministic. Used in CI to catch layout regressions for free.
|
|
57
|
+
- **EXTENDED mode** (`TEST_EXTENDED_MODE=1`) is now a TRUE mirror of the production cron: always uploads to GitHub, always tries Beehiiv draft, no per-side-effect opt-outs.
|
|
58
|
+
- **Three fixture JSONs** shipped at `test/marketing/fixtures/{clean,editorial,field-report}.json` — one per template, each matching its template's content shape. Convention enforced: adding a new template REQUIRES a matching fixture (default test run fails with `fixture not found` otherwise).
|
|
59
|
+
- **17-test fixture suite** (`test/marketing/newsletter-templates.js`) covers graceful omission, empty-section drop, CTA conditional rendering, citation rendering, sponsorship rendering, button padding regression guard, long subjects, minimum-viable structures, template metadata, schema export contract.
|
|
60
|
+
|
|
61
|
+
#### Other additions
|
|
62
|
+
- **`Manager.Utilities().slugify()`** — canonical URL slug builder. Strips non-alphanumeric chars, collapses hyphens, trims, lowercases. Single source of truth shared by admin/post + any consumer that needs to predict slugs (e.g. sponsorship platform).
|
|
63
|
+
- **`routes/admin/post/deduplicate-image-alts.js`** — utility that suffixes alt-text when two images share alt-text but have different URLs (prevents filename collisions on upload). Wired into both `routes/admin/post/post.js` and `actions/api/admin/create-post.js`. Unit-tested.
|
|
64
|
+
- New env vars in `templates/_.env`: `BACKEND_MANAGER_ANTHROPIC_API_KEY`, `ANTHROPIC_API_KEY`.
|
|
65
|
+
- `templates/_.gitignore` now includes `.temp/` in the BEM defaults section.
|
|
66
|
+
|
|
67
|
+
#### Documentation split
|
|
68
|
+
- **CLAUDE.md reduced from ~1500 lines to a navigable table of contents.**
|
|
69
|
+
- **21 new `docs/*.md` deep references**: architecture, directory-structure, code-patterns, file-naming, environment-detection, response-headers, routes, schemas, sanitization, auth-hooks, common-operations, admin-post-route, payment-system, marketing-campaigns, mcp, usage-rate-limiting, ai-library, marketing-fields, stripe-webhook-forwarding, testing, cli-firestore-auth, cli-logs.
|
|
70
|
+
|
|
71
|
+
### Changed
|
|
72
|
+
|
|
73
|
+
- **Config restructuring**: `marketing.newsletter` → `marketing.beehiiv.content`. Nesting under the provider that publishes the result makes the coupling explicit and leaves room for future `marketing.sendgrid.content` for promo email blasts. `marketing.beehiiv.enabled` now gates the whole content pipeline (no separate `newsletter.enabled` flag — disabling beehiiv disables newsletter generation as a side effect, since there's nowhere for the generated content to land).
|
|
74
|
+
- **Marketing library** (`libraries/email/marketing/index.js`) — now prefers `settings.contentHtml` over running the markdown pipeline. Lets generators produce pre-rendered HTML directly. UTM tagging still runs on the chosen HTML either way.
|
|
75
|
+
- **`Manager.AI()`** now points to the unified `libraries/ai/index.js`. `libraries/openai.js` is a thin compatibility shim that re-exports `libraries/ai/providers/openai.js`.
|
|
76
|
+
- **Footer no longer renders a hand-rolled `${brandUrl}/unsubscribe` link** — Beehiiv and SendGrid both auto-append CAN-SPAM-compliant unsubscribe links on sent emails. The hand-rolled one was a dead second link. Fixture suite now has a regression guard preventing accidental re-adds.
|
|
77
|
+
- **Beehiiv provider** (`libraries/email/providers/beehiiv.js`) — `createPost()` accepts an explicit `publicationId` arg (bypasses singleton-Manager lookup); `getPublicationId()` null-guards an uninitialized Manager singleton (matters for test stubs).
|
|
78
|
+
- **`admin/post.js` + `actions/api/admin/create-post.js`** — replaced inline slugify implementations with calls to the new `Manager.Utilities().slugify()`. Wired alt-text dedup helper into the post-creation flow.
|
|
79
|
+
- **`.temp/` moved** from `functions/.temp/` to project root (matches UJM/BXM/electron-manager convention).
|
|
80
|
+
- **`src/defaults/CLAUDE.md`** — strengthened framework-docs callout for consumer projects; clarified the Default/Custom marker boundary.
|
|
81
|
+
|
|
82
|
+
### Removed
|
|
83
|
+
|
|
84
|
+
- **`marketing.newsletter.provider/sectionStyle`** — `provider` defaults now live in code (openai for structure, anthropic for SVG), overridable per-run via env vars. `sectionStyle` was a free-form hint string the AI ignored.
|
|
85
|
+
- **`marketing.beehiiv.uploadAs`** — vestigial config from the abandoned Beehiiv-send-path detour.
|
|
86
|
+
- **`NEWSLETTER_GITHUB_UPLOAD` env flag** — redundant. EXTENDED mode now always uploads (production-equivalent run).
|
|
87
|
+
- **Footer's hand-rolled unsubscribe link** (see Changed).
|
|
88
|
+
|
|
17
89
|
# [5.0.203] - 2026-05-13
|
|
18
90
|
### Fixed
|
|
19
91
|
- `Settings.resolve()` now surfaces a clear `No schema for <METHOD> request: expected <schema>/<method>.js or <schema>/index.js` error (code 500) when both the method-specific schema (e.g. `delete.js`) and the `index.js` fallback are absent. Previously the raw Node `Cannot find module .../<schema>/index.js` error propagated to consumers, leaking the require stack and surfacing the internal `/workspace/...` deploy path.
|