Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
ca31bf5
docs: specify growth lifecycle hard cutover
blove Sep 2, 2026
c46b4df
docs: plan growth lifecycle hard cutover
blove Sep 2, 2026
392bcf6
fix: exclude imported contacts from lifecycle campaign
blove Sep 2, 2026
c1b5a00
feat: mark imported lifecycle contacts
blove Sep 2, 2026
ba8271a
feat: reconcile scheduled lifecycle mail
blove Sep 2, 2026
f5200fd
feat: add durable website growth boundary
blove Sep 2, 2026
b773095
feat: persist acquisition forms in neon
blove Sep 2, 2026
01f608f
feat: submit growth approval envelopes
blove Sep 2, 2026
f398de4
feat: expose lifecycle stop and dispatch routes
blove Sep 2, 2026
ced496d
refactor: remove legacy website email pipeline
blove Sep 2, 2026
827b017
test(ci): expect the fourth operator CLI suite
blove Sep 2, 2026
385201c
docs: mark the hard-cutover plan through repository verification
blove Sep 2, 2026
4d51b8e
fix(security): escape the signed token echoed into stop confirmation …
blove Sep 2, 2026
d1bf321
Merge remote-tracking branch 'origin/main' into blove/growth-hard-cut…
blove Sep 2, 2026
9789ad2
fix: reconcile the hard cutover with the unified control plane
blove Sep 2, 2026
8395332
Merge remote-tracking branch 'origin/main' into blove/growth-hard-cut…
blove Sep 2, 2026
1258cc5
docs: record the verified cutover firewall rule and correct its respo…
blove Sep 3, 2026
96ad885
Merge remote-tracking branch 'origin/main' into blove/growth-hard-cut…
blove Sep 3, 2026
22c2ffb
Merge remote-tracking branch 'origin/main' into blove/growth-hard-cut…
blove Sep 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,10 @@ jobs:
runs-on: ubuntu-latest
permissions:
contents: write
env:
# Server pages read the growth form policy while rendering, so the build
# needs the same switch the deployed environment sets. It is not a secret.
GROWTH_FORM_POLICY: growth_v1
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
Expand Down
29 changes: 24 additions & 5 deletions apps/website/e2e/website.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { test, expect } from '@playwright/test';

// Mirrored from apps/website/src/lib/growth/form-policy.ts, which is server-only
// and therefore cannot be imported into a Playwright spec.
const GROWTH_FORM_POLICY_VERSION = 'growth_v1.2026-09-01';
const UUID_V4 =
/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu;

const docsRoute = '/docs/langgraph/getting-started/introduction';

async function expectNoHorizontalOverflow(
Expand Down Expand Up @@ -88,7 +94,7 @@ test('contact page submits a lead payload and renders success state', async ({ p
});
});

await page.goto('/contact?source=e2e_contact&track=enterprise');
await page.goto('/contact');
const contactForm = page.locator('main form').first();
await contactForm.getByRole('textbox', { name: 'Email', exact: true }).fill('jane@acme.com');
await contactForm.getByRole('textbox', { name: 'Name' }).fill('Jane Smith');
Expand All @@ -98,13 +104,14 @@ test('contact page submits a lead payload and renders success state', async ({ p

await expect(page.getByText("Thanks. We'll be in touch within one business day.")).toBeVisible();
expect(leadPayload).toMatchObject({
form_kind: 'contact',
email: 'jane@acme.com',
name: 'Jane Smith',
company: 'Acme',
message: 'We are evaluating Threadplane.',
source_page: 'e2e_contact',
track: 'enterprise',
policy_version: GROWTH_FORM_POLICY_VERSION,
});
expect(leadPayload?.['submission_id']).toMatch(UUID_V4);
});

test('pricing lead form posts to /api/leads and renders success state', async ({ page }) => {
Expand All @@ -128,11 +135,14 @@ test('pricing lead form posts to /api/leads and renders success state', async ({

await expect(page.getByText(/we'll be in touch within one business day/i)).toBeVisible();
expect(leadPayload).toMatchObject({
form_kind: 'pricing',
email: 'jane@acme.com',
name: 'Jane Smith',
company: 'Acme',
message: 'Volume seats and security review.',
policy_version: GROWTH_FORM_POLICY_VERSION,
});
expect(leadPayload?.['submission_id']).toMatch(UUID_V4);
});

test('footer newsletter form posts to /api/newsletter and renders success state', async ({ page }) => {
Expand All @@ -152,7 +162,11 @@ test('footer newsletter form posts to /api/newsletter and renders success state'
await footer.getByRole('button', { name: 'Subscribe' }).click();

await expect(page.getByText("✓ You're subscribed!")).toBeVisible();
expect(payload).toEqual({ email: 'reader@acme.com' });
expect(payload).toMatchObject({
email: 'reader@acme.com',
policy_version: GROWTH_FORM_POLICY_VERSION,
});
expect(payload?.['submission_id']).toMatch(UUID_V4);
});

test('whitepaper signup form posts to /api/whitepaper-signup and renders success state', async ({ page }) => {
Expand All @@ -171,7 +185,12 @@ test('whitepaper signup form posts to /api/whitepaper-signup and renders success
await page.locator('#whitepaper-block').getByRole('button', { name: 'Download (free)' }).click();

await expect(page.getByText(/check your inbox/i)).toBeVisible();
expect(payload).toEqual({ email: 'reader@acme.com', paper: 'chat' });
expect(payload).toMatchObject({
email: 'reader@acme.com',
paper: 'chat',
policy_version: GROWTH_FORM_POLICY_VERSION,
});
expect(payload?.['submission_id']).toMatch(UUID_V4);
});

test('docs page renders sidebar and content', async ({ page }) => {
Expand Down
15 changes: 0 additions & 15 deletions apps/website/emails/angular-download.ts

This file was deleted.

15 changes: 0 additions & 15 deletions apps/website/emails/chat-download.ts

This file was deleted.

66 changes: 0 additions & 66 deletions apps/website/emails/drip-angular-followup.ts

This file was deleted.

66 changes: 0 additions & 66 deletions apps/website/emails/drip-chat-followup.ts

This file was deleted.

Loading
Loading