Skip to content

v4.19 — Teams V1 Wiring Completion

Every enabled control a paying team owner or member can tap now does the real thing — and everything deliberately deferred to V1.1 reads as an honest "coming soon," never a dead button.

Summary

Teams V1 went GA on tag v4.0.3 (2026-07-15), but the OBJ-1817 audit found the pattern was systemic: several controls that shipped enabled fired nothing when tapped, and one headline feature — in-app collective-goal creation — had no UI surface at all despite its opt-in/contribution flow already being live. The trigger was OBJ-1808's seat-cap "Add seats" CTA advertising a specific charge and then silently no-op'ing; the audit found the same shape of gap in billing, collective goals, and sub-communities.

v4.19 closed every one of those gaps in four sequential phases on the integration branch gsd/v4.19-teams-v1-wiring. Phase 1 wired the seat-cap "Add seats" flow to Teams::AdjustTeamSeats and built a real grace-state resubscribe checkout path, closing OBJ-1808 findings #2 and #4 — plus a same-milestone follow-up (OBJ-1835) fixing an initial resubscribe defect that would have re-granted a free trial to a churned, previously-paying team. Phase 2 gave Teams::CreateCollectiveGoal its first UI caller: an in-app owner/admin creation flow. Phase 3 wired Teams::JoinSubCommunity/LeaveSubCommunity and active-room switching, closing the "owners can create rooms, but no member can join one" loop, and added the backend read query multi-room joiners needed to land on a real room picker instead of a bare dashboard. Phase 4, the final phase, wired the fresh-member "mark today done" CTA to a real destination and honestly gated all eight remaining V1.1-shaped stubs (notifications bell, points breakdown, team-picker chevron, sub-community filter, team-activity view, room edit, room feed, leaderboard scope switcher) so none of them render as an enabled dead control.

Every phase ran the full Multica crew chain (Desi → Codi → Riley → Roy → Vicki → Dori), with Orion coordinating phase-to-phase dispatch from the milestone's parent issue (OBJ-1827). Two deviations surfaced and were resolved without blocking the ship: the resubscribe trial-reset defect (fixed via OBJ-1835, run in parallel with Phase 2 rather than folded into Phase 4), and a Roy-flagged N+1 query on the Team Home page's room list (bundled into the Phase 3 PR per Josh's call and closed as OBJ-1851 in the same ship).

The work is complete and merged to master via promotion PR #1956 (OBJ-2012). See Outcomes below.

Goal

Finish wiring the Teams V1 surfaces that shipped to GA (v4.0.3) but silently no-op. Every enabled control a paying team owner or member can tap should do the real thing — fire its mutation, navigate, or start checkout — and anything deliberately deferred to V1.1 should render as an honest "coming soon" placeholder, never an enabled dead button. Concretely: wire the seat-cap "Add seats" flow and a grace-state resubscribe path (billing); surface in-app collective-goal creation (a dark headline feature); wire sub-community join/leave/switch (a broken create-a-room-nobody-can-join loop); give the fresh-member CTA a real destination; and honestly gate the V1.1-shaped stubs.

.planning/milestones/v4.19-teams-v1-wiring-ROADMAP.md

Scope — What Shipped

  • Seat-cap "Add seats" wiredTeamMembersTab.vue's onAddSeats now fires ADJUST_TEAM_SEATS_MUTATION (mirroring TeamBillingTab.handleSaveSeats's toast + refetch + close pattern) instead of closing the modal and doing nothing.
  • Grace-state resubscribe, end-to-end — a new useTeamResubscribe.ts composable starts a fresh Stripe checkout (not a portal session — the subscription is already canceled) from both TeamHomeView's banner CTA and TeamSettingsView's billing tab. Ships with a same-milestone follow-up (OBJ-1835) so the resumed subscription bills immediately rather than granting a new 14-day trial.
  • In-app collective-goal creationuseCreateCollectiveGoal.ts wires CREATE_COLLECTIVE_GOAL_MUTATION (backend + GraphQL constant existed with zero callers before this milestone) behind teams_collective_goals; new goals render in CollectiveProgressCard. Non-check_ins metrics are gated as coming-soon pending broader metric aggregation.
  • Sub-community join/leave/switchuseSubCommunityMembership.ts wires JOIN_SUB_COMMUNITY_MUTATION/LEAVE_SUB_COMMUNITY_MUTATION; onBrowseAll mounts the previously-orphaned SubCommunityBrowser.vue; onSelectRoom sets the active room.
  • Post-accept multi-room onboarding — a new TeamAccessPolicy-guarded backend read query lets AcceptTeamInviteTeamHomeView?browse=1 render SubCommunityBrowser with the team's real rooms instead of discarding the browse intent.
  • Fresh-member CTA wiredTeamHomeView.onMarkTodayDone routes to /dashboard's real personal check-in surface (no team-scoped check-in path exists in V1, so this deliberately leaves team context rather than inventing one — documented inline).
  • All 8 remaining V1.1-shaped stubs honestly gated — notifications bell (OBJ-1819), points breakdown (OBJ-1820), team-picker chevron (OBJ-1821), sub-community filter (OBJ-1822), team-activity view (OBJ-1823), room edit (OBJ-1824, gate lifted — see below), room feed (OBJ-1825), leaderboard scope switcher (OBJ-1826) — each now renders a disabled affordance with a ComingSoonPill/toast, never an enabled no-op.
  • N+1 query fixTEAM_HOME_QUERY.rooms[].isMember batch-loads membership instead of one query per room (OBJ-1851, bundled into Phase 3).
  • Docsdocs/product/phase-7-teams.md, docs/architecture/graphql.md, docs/features/communities.md, and both CHANGELOGs updated per phase.

Phases

PhaseNameStatusPRsHighlights
1Billing dead-ends — seat-cap + grace resubscribeShipped#1831, #1836 (follow-up)Closes OBJ-1808 #2/#4; follow-up fixes resubscribe trial-reset to immediately-billed
2In-app collective-goal creationShipped#1833First UI caller for a mutation that existed since GA with zero callers
3Sub-community join/leave/switchShipped#1842Closes the create-a-room-nobody-can-join loop; N+1 fix (OBJ-1851) bundled per Josh's call
4Fresh-member CTA + honest gating (final)Shipped#1848All 8 V1.1 stubs honestly gated; no enabled Teams control silently no-ops

Key Decisions

  • Resubscribe follow-up shipped standalone and in parallel, not folded into Phase 4 (Orion, confirmed by Josh) — the trial-reset fix is a backend billing-correctness change on a different surface from Phase 4's frontend gating; running it in parallel with Phase 2 got the revenue-leak risk closed sooner instead of waiting on the phase chain.
  • N+1 query fix bundled into Phase 3's PR rather than a separate follow-up (Josh's explicit product call) — kept the fix shipping alongside the code that introduced the query shape, rather than opening a second review cycle for a fix Roy had already scoped.
  • Fresh-member CTA leaves team context rather than inventing a team-scoped check-in (Codi, per the ROADMAP's own "wire it, or honestly gate it with a justification" instruction) — no team-scoped check-in surface exists in V1, so onMarkTodayDone routes to the real personal-dashboard check-in instead of fabricating a team-specific equivalent that doesn't map to anything real.
  • All 8 gating targets tied to their V1.1 backlog ticket, not a generic "coming soon" — each disabled affordance references its own OBJ-18xx ticket, so the placeholder reads as an honest, trackable deferral rather than an unexplained dead end.

Requirements Coverage

6 / 6 requirements satisfied (per .planning/milestones/v4.19-teams-v1-wiring-MILESTONE-AUDIT.md — this milestone has no separate REQUIREMENTS.md; the ROADMAP's Definition of Done is the requirements source of record).

CategoryCountStatus
Billing dead-ends (Phase 1)1Satisfied
Collective-goal creation (Phase 2)1Satisfied
Sub-community join/leave/switch (Phase 3)1Satisfied
Fresh-member CTA + honest gating (Phase 4)1Satisfied
Native boundary respected1Satisfied
Docs updated per phase1Satisfied

Full requirements list: v4.19-teams-v1-wiring-ROADMAP.md on GitHub.

Outcomes

In the codebase, every Teams V1 control that shipped enabled at GA now does the real thing: seat-cap upgrades fire the seat mutation, grace-state teams can resubscribe (and resume as immediately-billed, not a fresh trial), owners/admins can create collective goals in-app, members can browse/join/leave/switch sub-communities and multi-room joiners land on a real picker, and the fresh-member CTA performs a real check-in. Every remaining V1.1-shaped surface is an honest, ticket-linked "coming soon" rather than a silent dead end.

Merged to master via promotion PR #1956 (OBJ-2012). The features stay behind the existing teams_billing_v1/teams_collective_goals kill switches; teams_enabled itself was already retired at GA. Riding the next Wednesday release train is the one concrete step standing between this milestone's code being on master and paying Teams customers actually seeing it.

Tech Debt

  • (Phase 3) Per-phase RSpec/Vitest coverage and the TeamScopedView contract test were CI-gated at each PR's merge but not independently re-run as part of this close audit.
  • (Out of milestone scope) OBJ-1819–1826 — the 8 gated V1.1 stubs — remain honestly gated, not built. Deferred to the Teams V1.1 backlog project. Update: OBJ-1824 (sub-community room edit) shipped separately via PR #2207 — see docs/product/phase-7-teams.md and docs/architecture/graphql/mutations.md's updateSubCommunity entry.
  • (Out of milestone scope) OBJ-1811 (native App Store 3.1.1 billing boundary) is a separate, in-flight track; this milestone only confirmed it stayed respected, it didn't touch it.
  • d125c67 — Phase 1 merge: seat-cap "Add seats" + grace resubscribe billing dead-ends
  • 5387ea4 — Phase 1 follow-up merge: resubscribe resumes immediately-billed
  • 9cf49d9 — Phase 2 merge: in-app collective-goal creation
  • edcd01ea — Phase 3 merge: sub-community join/leave/switch (+ N+1 fix)
  • f12bfdbf3 — Phase 4 merge: fresh-member check-in CTA + honest gating of 8 V1.1 stubs

Last updated: 2026-08-08

Loading…