Skip to content

feat(member-profile): auto-populate primary_brand_domain from verified WorkOS domain#4157

Merged
bokelley merged 1 commit intomainfrom
bokelley/medianet-public-agent-brand
May 6, 2026
Merged

feat(member-profile): auto-populate primary_brand_domain from verified WorkOS domain#4157
bokelley merged 1 commit intomainfrom
bokelley/medianet-public-agent-brand

Conversation

@bokelley
Copy link
Copy Markdown
Contributor

@bokelley bokelley commented May 6, 2026

Summary

  • Auto-set member_profiles.primary_brand_domain when WorkOS verifies a claimable email domain on the org and the field is null. Closes the surprise where SSO members hit the publish-agent gate even though their email domain was the obvious brand identity.
  • Backfill script for profiles created before this change.
  • Improve the terse "Set your primary brand domain first" error to be actionable.

Driver

Media.net escalation #321 — Warren had media.net verified via WorkOS but couldn't publish his sales agent. Root cause: member_profiles.primary_brand_domain was null and only the brand-domain-challenge flow (which requires publishing brand.json) ever wrote it. Members reasonably assumed "Verified" was the success state.

The fix mirrors what the WorkOS webhook already does for organizations.email_domain (auto-promote on first verified domain) and brands (mirror via markBrandDomainVerified) — extends the same idea to member_profiles.primary_brand_domain. Same gating (assertClaimableBrandDomain), so shared-platform domains can't auto-claim.

Existing brand-claim values are never clobbered — only writes when NULL. Cross-org disputes and adopt-vs-fresh manifest decisions still flow through request_brand_domain_challenge / verify_brand_domain_challenge.

Out of scope (tracked separately)

  • Member-facing Linked Domains UI (members currently can't self-manage domains — only admins can). Stage 2.
  • Rationalizing the four overlapping "domain" columns (organization_domains, organizations.email_domain, member_profiles.primary_brand_domain, brands.domain). Stage 3 — wants design steer.
  • WPP Media drift case (local sub_id with no Stripe-side match) — surfaced during cohort cleanup; different shape.

Test plan

  • New integration test server/tests/integration/workos-domain-auto-primary.test.ts covers: claimable single domain → auto-populate, existing value preserved, no profile yet (no-op), shared-platform domain skipped, pending state skipped.
  • Existing typecheck + unit tests pass (precommit hook).
  • After merge: run npx tsx server/scripts/backfill-primary-brand-domain.ts --dry-run against prod to preview, then without --dry-run to apply.

🤖 Generated with Claude Code

…d WorkOS domain

When WorkOS verifies a claimable email domain on an org, set the member
profile's primary_brand_domain if null. Closes the surprise where SSO members
hit "Set your primary brand domain first" on the publish-agent path even
though their email domain was the obvious brand identity. Existing
brand-claim values are never clobbered.

Adds a backfill script for profiles created before this change, and rewrites
the publish-path error to be actionable instead of terse.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bokelley bokelley merged commit de4e9e6 into main May 6, 2026
12 checks passed
@bokelley bokelley deleted the bokelley/medianet-public-agent-brand branch May 6, 2026 16:12
bokelley added a commit that referenced this pull request May 6, 2026
…fy parallel lists (#4166)

* fix(server): block free-email provider domains from brand claims, unify parallel lists

Extends SHARED_PLATFORM_DOMAINS with 31 high-volume free-email provider
domains (Gmail, Outlook, iCloud, Proton, Yahoo, AOL, Yandex, QQ, Tutanota,
etc.) as defense-in-depth for brand identity hijacking via admin overrides
or future trust paths. Surfaced during security review of PR #4157.

Extracts FREE_EMAIL_PROVIDER_DOMAINS as a shared exported constant and
replaces five previously-diverged inline arrays across admin-tools.ts
(check_domain_health + suggest_prospects), slack-db.ts, and admin/domains.ts
(x2) with imports of the shared constant.

Adds assertClaimableBrandDomain unit tests (the function was previously
untested).

Closes #4165.

https://claude.ai/code/session_01Wgjm3A6JbHWgfPCyDxUmoL

* fix(server): clarify duck.com comment, extend assertClaimableBrandDomain test coverage

https://claude.ai/code/session_01Wgjm3A6JbHWgfPCyDxUmoL

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant