Skip to content

v4.0 — Teams V1

Objectuve's first B2B revenue stream: a paid, private, multi-community workspace any group can buy, invite into, and share goals in — live end-to-end in production.

Summary

Before this milestone, Objectuve had no way to sell to a group. Communities existed, billing existed (the Supporter tier), but nothing tied the two together into a paid team product. Coaching groups, corporate wellness cohorts, and school groups had no self-service path from "we want this for our group" to an active, billed workspace with private sub-communities, a leaderboard, and shared goals.

Teams V1 ships that path end-to-end: a Team Owner starts a checkout, gets a 14-day no-card trial, invites members by link or email, members self-select into sub-communities ("Running Crew," "Meditation Circle"), points accrue to a weekly/monthly/all-time leaderboard, and admins can stand up collective goals the whole team contributes to. Billing lifecycle (trial → active → past_due → grace → canceled) is driven by real Stripe webhooks, not inferred state. Every surface is gated fail-closed behind teams_enabled and four independent kill switches, so the whole feature accumulated on master dormant for weeks before going live — no long-lived integration branch, no big-bang cutover.

GA shipped 2026-07-15 on tag v4.0.3: teams_enabled retired (Teams is now visible to every user, not a scoped test account), the pricing page and purchase CTAs went live on objectuve.com, and the trial→paid Stripe conversion path was live-fire verified against production by Josh himself — a real defect (a webhook double-reading request.body, silently 400ing every checkout.session.completed event) was caught and fixed before that verification, and a second real defect (trial-end auto-downgrading teams that had actually paid) was caught and fixed the same day GA shipped. Teams is Objectuve's first revenue line that doesn't come from an individual subscriber.

Goal

Ship Teams V1: a paid, private, multi-community workspace for groups who share a goal. First B2B revenue stream. Lead ICP: coaching groups, 5–20 seats. No SOC 2, no SSO, no enterprise sales.

Deliver a self-service experience from pricing → checkout → invite → member → collective goal → leaderboard, behind kill-switch feature flags.

Scope — What Shipped

  • Data model: 7 new tables (teams, team_subscriptions, team_memberships, team_leaderboard_entries, collective_goals, collective_goal_contributions, team_invites) plus team_id/is_default_for_team on communities and team_subscription_id on payment_records.
  • Billing: Stripe Checkout (test → live mode), no-card 14-day trial, seat management, invoice.paid/invoice.payment_failed-webhook-driven lifecycle transitions, 4 lifecycle mailers (welcome, upgraded, downgraded, 30-day check-in), full isolation from personal Supporter billing.
  • Access control: TeamAccessPolicy (Owner/Admin/Member/External Coach × view/manage-team/manage-billing, all 12 combinations tested) and the TeamScopedView composable (CI-enforced contract test) as the two universal gates for every team-data read and mutation.
  • Invites & membership: Public unauthenticated /join-team/{code} landing, link + email invites, seat-cap enforcement, promote/remove members, sub-community CRUD with 30-day soft-delete grace.
  • Leaderboards: Async (Sidekiq) points engine off the check-in path, weekly/monthly/all-time views, per-member opt-out (raw-count anti-metric, not a hidden percentage), Monday recap push notification + in-app card.
  • Collective goals: Admin-created team/sub-community-scoped goals, member opt-in/opt-out preserving contribution history, server-side (never localStorage) privacy-contract acknowledgment before first opt-in.
  • Operations: Beta participant compensation grant, internal admin Teams monitoring view (admin_dashboard/), billing-failure runbook, 10/10 PostHog success metrics instrumented plus anti-metrics (opt-out rate, TeamPulseSurvey "feel surveilled" NPS signal).
  • North Star completeness: a daily snapshot job (Teams::SnapshotNorthStarMetricsJob) sources MRR, paying/trialing team counts, and average seats into PostHog — the last un-sourced panel on the 12-month North Star dashboard.
  • Marketing: a #teams-showcase section on the public landing page with real product screenshots, plus the GA pricing panel and purchase CTAs.
  • Flag retirement: teams_enabled, the master gate, removed entirely at GA; the four kill switches (teams_billing_v1, teams_bulk_invite, teams_leaderboards, teams_collective_goals) remain operational for subsystem-level rollback.

Phases

PhaseNameStatusPlansHighlights
1Data model & billing primitivesShipped17 new tables, Plan seed rows, TeamAccessPolicy scaffold — fully dormant, zero app-code references
2Billing flow & Stripe webhookShipped1Checkout, webhook, lifecycle jobs; first user-reachable phase, registers teams_enabled + teams_billing_v1
3Invites, membership, sub-communitiesShipped1Invite lifecycle, public join landing, TeamScopedView contract test in CI
4Team leaderboards & points engineShipped1Async points engine, opt-out anti-metric, Monday recap
5Collective goals & contribution flowShipped1Opt-in/opt-out, server-side privacy-contract acknowledgment
6Closed beta operationsShipped1PostHog instrumentation, beta compensation grant, admin monitoring view
7V1.1 shape-only + GA prepShipped1teams_enabled retired, GA pricing live, Stripe-driven trial→paid conversion, two real money-path bugs caught by live-fire testing
8Marketing landing — Teams showcaseShipped1Public showcase section, real product screenshots (net-new ask, sequenced after core surfaces shipped)
9North Star data completenessShipped1Daily MRR/team-count/seat-average snapshot job closes METRIC-4

Key Decisions

  • Trunk-based delivery, no integration branch. Every phase PR merged straight to master and rode the normal deploy pipeline dormant behind teams_enabled. Avoided the multi-week merge-conflict risk of a long-lived Teams branch, at the cost of needing airtight fail-closed gating on both frontend and backend for every surface.
  • TeamAccessPolicy and TeamScopedView as the only two data-boundary gates. Scaffolded in Phase 1/3 and never bypassed by a later phase — this is why cross-phase integration held with zero access-control regressions across 9 phases.
  • Snapshots carry stocks, events carry flows (Phase 9). MRR/team-counts are point-in-time aggregates from Postgres; conversions and cancellations are PostHog events with their own timestamps. Mixing the two would have double-counted or under-counted metrics — the design rule is now documented for future dashboard work.
  • Deploy timing is not a feature-flag gate (OBJ-1386). Phase 8's marketing showcase went publicly live via a non-GA tag two days early because a prior assumption ("marketing deploy rides the GA train") was false — production.yml deploys the marketing site on every prod tag. Corrected in the delivery isolation policy; Josh accepted the early visibility rather than treating it as an incident.
  • Live-fire verification over spec coverage alone, for money paths. Both real defects this milestone caught (the Stripe webhook request.body double-read; the trial-end auto-downgrade of paid teams) were found by driving the actual Stripe integration, not by unit specs — both had passing spec coverage before the bug was found.

Requirements Coverage

69 / 69 requirements satisfied (per v4.0-teams-v1-MILESTONE-AUDIT.md).

CategoryCountStatus
BILLING-*17All satisfied
INVITE-*7All satisfied
GOALS-*17All satisfied
LEADERBOARD-*7All satisfied
PRIVACY-*3All satisfied
METRIC-*6All satisfied
DOCS-*7All satisfied
MKTG-*5All satisfied

Full phase-by-phase requirement lists: v4.0-teams-v1-ROADMAP.md on GitHub.

Outcomes

Any user can now go from objectuve.com's pricing panel to an active, billed Team workspace without a sales conversation — start a 14-day no-card trial, invite a group, and have a working private community with a leaderboard and a collective goal the same day. Objectuve has its first revenue stream that monetizes a group rather than an individual, funding the mission that individual progress stays free. Operationally, Teams billing failures have a runbook, the admin team has a monitoring view with no personal-data leakage across the team boundary, and the 12-month North Star dashboard has a real, fully-sourced data feed for MRR and team growth.

Tech Debt

  • (Phase 6) No documented 5-team, 14-day closed beta cohort ran before GA — Teams moved from dark/flag-gated straight to GA. Not a code gap; the formal beta-validation step in the original Definition of Done was superseded by a direct-to-GA decision that was never recorded as such.
  • (Phase 5–7) PostHog registration of the four kill-switch flags (project 368400) was never independently confirmed — no crew member ever obtained PostHog write access to run the sync script. featureFlags.ts-side registration is done; the PostHog side is unconfirmed.
  • (Phase 7) docs/product/phase-7-teams.md §8's component-status table is stale in places — spot-checked two rows (N7c, N7d) that the table calls "spec-only" but are actually real, shipped, wired components. A full re-verification pass is recommended before anyone builds on top of that table's claims.
  • (Phase 7, already corrected) The v4.0.3 tag was cut outside scripts/release.sh during a runtime outage, so the in-app CHANGELOG modal silently dropped the GA "What's New" entry in the shipped build. Fixed post-hoc via PR #1556; worth a CI guard so a non-release.sh tag can't ship a headerless changelog again.
  • (Phase 7) Post-tag live no-card checkout has not been independently re-driven by a human with a live Stripe seat since the tag cut. Failure mode is revenue under-collection, not customer harm.
  • df728be062 — Phase 1: data model & billing primitives (PR #1249)
  • f19b8698a — Phase 2: billing flow & Stripe webhook (PR #1255)
  • 32bfa8ff7 — Phase 3: invites, membership & sub-communities (PR #1268)
  • fccd23a1c — Phase 4: leaderboards & points engine (PR #1280)
  • fcc9de904 — Phase 5: collective goals & contribution flow (PR #1303)
  • 907cb14f8 — Phase 6: closed beta operations (PR #1318)
  • bdfb10692 — Phase 8: marketing landing Teams showcase (PR #1378)
  • 0b9304c52 — Phase 9: North Star snapshot job (PR #1541)
  • Phase 7 (GA): teams_enabled retirement (PR #1498), GA purchase CTAs (PR #1512), no-card trial checkout (PR #1514), Stripe invoice.paid conversion (PR #1515), tag v4.0.3 (2026-07-15)

Last updated: 2026-07-16

Loading…