feat(registry): expose membership tier on public operator lookups#4513
Conversation
f7787ff to
31ec08b
Compare
|
Reviewed — implementation is solid, ship-ready after one mechanical step. What's good
One mechanical step before merge I opened #4515 to land that catchup as a clean no-op-against-code PR. After it merges, please rebase this branch — the yaml diff here will shrink to just the three new (I also updated the PR body to call out the three fields and the bundled 477 fix — original text said "two".) Optional follow-up (non-blocking) Nice work. 🚢 |
/api/registry/operator?domain=X now surfaces the queried member's AAO
membership tier when the profile owner has opted their member card into
public visibility (is_public=true). The member object grows two optional
fields: membership_tier (raw enum, e.g. company_leader) and
membership_tier_label (human-readable, e.g. Leader).
Private profiles still return only { slug, display_name } — tier reflects
billing state, so we follow the existing profile-card visibility toggle
rather than introducing a second one. The fields are absent (not null)
for private profiles and for orgs without a resolvable tier, so existing
consumers see no shape change.
Public operator lookup now exposes is_founding_member alongside the
membership tier when the profile is public. Founding Member is orthogonal
to tier — founding orgs like Scope3 display both (Partner + Founding
Member) on their member card, so a single tier field doesn't capture the
intent.
Also fixes the company_icl label in services/membership-tiers.ts from
"Member" to "Partner" so it matches the AAO pricing page and the
dashboard's local tier map (which already used "Partner"). The label was
internal-only previously; surfacing it on the operator endpoint forced
the naming inconsistency to surface.
Schema, OpenAPI spec, and unit tests updated. Private profiles still
return only { slug, display_name } — no shape change for existing
consumers.
Re-regen captures Emma's three new member.* fields plus a small post-#4515 drift sweep that landed today (verification_mode/verified query params on agent listing; 400 response shape). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
31ec08b to
995f9cb
Compare
Summary
/api/registry/operator?domain=Xnow surfaces the queried member's AAO public-card info when the profile owner has opted their member card into public visibility (is_public=true). Thememberobject grows three optional fields:is_founding_member— boolean, present whenever the profile is public (true or false; absent for private profiles)membership_tier— raw enum (e.g.individual_professional,company_leader) for programmatic gating, present only when the org also has a resolvable tiermembership_tier_label— human-readable label (e.g.Professional,Partner,Leader) matching the AAO pricing page; presence mirrorsmembership_tierPrivate profiles still return only
{ slug, display_name }. Tier and Founding Member reflect billing/cohort state, so we follow the existing profile-card visibility toggle (is_public) rather than introducing a second one. Fields are absent (notnull) when not applicable, so existing consumers see no shape change.Also fixes the
company_icllabel intierLabel()fromMembertoPartnerso it matches the public pricing page and the dashboard (which already usedPartner). Founding Member is orthogonal to tier — founding orgs typically display both badges (e.g. Scope3 showsPartner+Founding Member).Also in this PR
Migration 477 hot-fix.
477_broadcast_delivery_criteria.sqlcalled_append_criterion()without redefining it. The helper was created and dropped in migration 407, so later migrations using it must redefine it inline. 477 has been failing CI on every PR for ~2 days; bundling the fix here unblocks this branch and everything else in flight. Same create/use/drop structure as 407; no criterion text or IDs change.Visibility rules
slug/display_nameis_founding_membermembership_tier/_labelis_public=trueAND org has a resolvable tieris_public=trueBUT no resolvable tieris_public=false)member: nullTest plan
npm run typecheckcleannpm run buildcleantests/unit/operator-publisher-lookup.test.ts— schema validation for all four visibility regions (public+tier, public-no-tier, private, no-profile)tests/unit/membership-tiers.test.ts— updatedcompany_icl → Partnerassertionstatic/openapi/registry.yaml)/api/registry/operator?domain=<public-member-domain>post-deploy, confirm tier fields land inmemberNotes on the OpenAPI diff
Most of the yaml changes will disappear after #4515 (the separate catchup PR) lands — that one absorbs the unrelated drift (
Publisher.hosting.*,MemberAgentTypeInputsplit, new endpoints, etc.) so this PR's diff shrinks to just the three newmember.*fields plus the operator-endpoint description block. Rebase order: wait for #4515, then rebase this branch and the yaml diff cleans up.