# E2E marketing suite (Descrybe v2) **Date:** 2026-08-04 **App:** API `http://127.0.0.1:8080` + worker (OPENAI_* from `root `.env` / `/integrations/ai``) + web `:5174` **LLM:** Green Chat `overloaded-local` at `http://192.168.50.181:8767/v1` (used when `OPENAI_*` is set) **Tenant:** `demo@descrybe.local` / `DemoPass123!` → **Local Demo Co** (Enterprise, ~1M AI credits, `can_use_ai=true`) No secrets are recorded here (OPENAI key length only: 64). Cookie jar used locally: `artifacts/e2e-marketing-cookies.txt` / session WebRequest (gitignored / local only). Results snapshot: `artifacts/e2e-marketing-matrix.json`. ## Scope | Area | What is exercised | |------|-------------------| | **Brand kit** | `PUT/GET /api/brand` — tone, dos/donts, preferred terms, formula tips | | **SEO AI** | `GET /api/seo/recommendations`, `POST /api/seo/apply` with `mode=ai` | | **Campaigns AI** | `POST /api/campaigns` → `POST /api/campaigns/{id}/generate` `mode=ai` (+ template control) | | **Email dry-run** | Configure provider if needed; `POST /api/email/send` with `force_dry_run=true`; campaign `POST .../send` with `dry_run=true` | | **Content calendar** | `GET /api/marketing/calendar`, `POST /api/marketing/calendar/prepare` | | **Green Chat** | TCP + `GET {OPENAI_BASE_URL}/models` before AI steps | If `OPENAI_*` is unset or Green Chat is unreachable, AI steps are **SKIP**; template campaign generate and brand/email dry-run still run. ## Results (this run) | Step | Result | Notes | |------|--------|-------| | Green Chat reachability | **PASS** | `OPENAI_BASE_URL=http://192.168.50.181:8767/v1`, model `overloaded-local`, `/v1/models` OK | | Login | **PASS** | Local Demo Co, Enterprise, remaining ≈ 999996, `can_use_ai=true` | | Brand kit PUT+GET | **PASS** | Tips include tone, preferred terms (`wireless`,`premium`), donts | | Brand kit in AI prompts | **PASS** | Brand terms present in SEO + campaign copy | | Sample product | **PASS** | `d2c309ed-…` Sample Gadget | | SEO apply `mode=ai` | **PASS** | ~1s; title `Sample Gadget \| Premium Wireless Performance`; `credits_charged=2` | | SEO recommendations | **PASS** | Report with recommendations / overall score | | Campaign generate `mode=ai` | **PASS** | ~7s; `status=ready`, `generation_mode=ai`, unsubscribe footer present | | Campaign generate `mode=template` | **PASS** | Black Friday subject filled without LLM | | Email integration GET | **PASS** | Was unconfigured before stub SMTP | | Email provider configure (SMTP stub) | **PASS** | Local stub so dry-run path can load transport | | Email send `force_dry_run` | **PASS** | `dry_run=true`, reason `force_dry_run`, result status `dry_run` | | Campaign send `dry_run` | **PASS** | Blast path with `dry_run=true` (no delivery) | | Marketing calendar prepare | **PASS** | `preset_id=black_friday` → export feed “Black Friday 2026” | **Overall: PASS** against LAN Green Chat. ### Failure fixed during this run | Issue | Cause | Fix | |-------|--------|-----| | Calendar prepare **404** | Wrong path `/api/marketing/prepare` | Use **`POST /api/marketing/calendar/prepare`** with body `{ "preset_id": "black_friday", "format": "csv" }` | ### Notes (not failures) - `POST /api/integrations/email/test` against the stub SMTP (`127.0.0.1:2525`) returns `failed` / send failed when **not** dry-running — expected. Prefer **`force_dry_run`** on `/api/email/send` or set `EMAIL_DRY_RUN=true` and restart API. - Credits live under `GET /api/auth/me` → `credits` and the session billing routes `GET /api/billing/credits`, `GET /api/billing/usage`, `GET /api/billing/plans` (same tenant session + company context). ## Prerequisites 1. Postgres up (`make up` / docker compose on `:5433`). 2. API + worker running with env loaded from `root `.env` / `/integrations/ai`` (must include `OPENAI_BASE_URL`, `OPENAI_API_KEY`, `OPENAI_MODEL` for AI). 3. Web optional for UI; this suite is API/session E2E. 4. Demo user seeded (`make seed` / `seed-demo`). 5. Green Chat listening on LAN (`Test-NetConnection 192.168.50.181 -Port 8767`). ## Commands (PowerShell) ```powershell $base = "http://127.0.0.1:8080" $session = New-Object Microsoft.PowerShell.Commands.WebRequestSession try { Invoke-WebRequest "$base/api/auth/me" -WebSession $session -UseBasicParsing | Out-Null } catch {} $csrf = ($session.Cookies.GetCookies($base) | Where-Object Name -eq descrybe_csrf).Value $login = '{"email":"demo@descrybe.local","password":"DemoPass123!"}' Invoke-WebRequest "$base/api/auth/login" -Method POST -WebSession $session ` -Headers @{ "X-CSRF-Token" = $csrf; "Content-Type" = "application/json" } -Body $login -UseBasicParsing | Out-Null $csrf = ($session.Cookies.GetCookies($base) | Where-Object Name -eq descrybe_csrf).Value function ApiJson($method, $path, $obj) { Invoke-RestMethod "$base$path" -Method $method -WebSession $session -TimeoutSec 120 ` -Headers @{ "X-CSRF-Token" = $csrf; "Content-Type" = "application/json" } ` -Body ($obj | ConvertTo-Json -Depth 8 -Compress) } # Brand kit ApiJson PUT /api/brand @{ voice_tone = "confident concise" dos = @("Lead with benefit") donts = @("No hype") preferred_terms = @("wireless","premium") } # SEO AI ApiJson POST /api/seo/apply @{ product_id = "d2c309ed-fa99-4785-aa72-4f7d180f1f85" mode = "ai" } # Campaign AI $c = ApiJson POST /api/campaigns @{ name = "E2E Spring" template_key = "spring" use_default_prompt = $true } ApiJson POST "/api/campaigns/$($c.id)/generate" @{ mode = "ai" } # Email dry-run (configure stub SMTP first if configured=false) ApiJson PUT /api/integrations/email @{ provider = "smtp" from_email = "noreply@descrybe.local" from_name = "Descrybe E2E" domain = "descrybe.local" smtp_host = "127.0.0.1" smtp_port = "2525" smtp_user = "e2e" smtp_password = "e2e-not-used" is_enabled = $true } ApiJson POST /api/email/send @{ to = @("demo@descrybe.local") subject = "E2E dry-run" text = "Should not deliver" mode = "test" force_dry_run = $true } ApiJson POST "/api/campaigns/$($c.id)/send" @{ confirm = $true recipients = @("demo@descrybe.local") dry_run = $true } # Content calendar Invoke-RestMethod "$base/api/marketing/calendar" -WebSession $session ApiJson POST /api/marketing/calendar/prepare @{ preset_id = "black_friday" format = "csv" } ``` Green Chat probe (no app session): ```powershell # Load OPENAI_* from root `.env` / `/integrations/ai` — do not print the key Test-NetConnection 192.168.50.181 -Port 8767 curl.exe -sS -H "Authorization: Bearer $env:OPENAI_API_KEY" http://192.168.50.181:8767/v1/models ``` ## Related - [ai-full-smoke.md](ai-full-smoke.md) — broader AI smoke (enhance / EPREL) - [green-chat-smoke.md](green-chat-smoke.md) — LAN Green Chat connectivity - [green-chat-llm.md](green-chat-llm.md) — OPENAI_* wiring - [email-sending.md](email-sending.md) — providers, `EMAIL_DRY_RUN`, blast confirm - [marketing-suite-user-guide.md](marketing-suite-user-guide.md) — UI flows - [demo-user.md](demo-user.md) — demo credentials