docs: ADR-0004 cohost role for competition co-management#351
docs: ADR-0004 cohost role for competition co-management#351zacjones93 wants to merge 5 commits intomainfrom
Conversation
Proposes a new `cohost` system role on the competition_event team to allow cross-gym partners to co-manage a single competition without granting full organizing team access. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
WalkthroughAdds a proposed ADR introducing a per-competition "cohost" system role, detailing schema additions, auth gating, route-level access rules, navigation/dashboard visibility, and a token-based cohost invite/accept flow; also updates the ADR index to include the new document. Changes
Sequence Diagram(s)sequenceDiagram
participant Organizer
participant Server
participant EmailService
participant Invitee
participant Database
participant ParentRoute
Organizer->>Server: POST /invite-cohost (competitionId, email, permissions)
Server->>Database: create cohost_invite(record with token)
Server->>EmailService: send invite email (token)
EmailService-->>Invitee: deliver invite link
Invitee->>Server: GET /accept-invite?token=...
Server->>Database: validate token -> create cohost membership (SYSTEM_ROLES_ENUM.COHOST + metadata)
Server-->>Invitee: redirect to app / confirmation
ParentRoute->>Server: loader check cohost membership (competitionId, userId)
Server->>Database: fetch membership -> respond {isCohost, cohostPermissions}
ParentRoute-->>Client: provide isCohost & cohostPermissions for child route guards
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~3 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
apps/wodsmith-start/docs/decisions/0004-add-cohost-role-for-competition-co-management.md (1)
67-68: Pick one canonical schema file location for cohost metadata.Using “
volunteers.ts(or newcohost.ts)” leaves implementation ambiguous and can cause drift across contributors. Prefer one target file path in the ADR.Also applies to: 222-223
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/wodsmith-start/docs/decisions/0004-add-cohost-role-for-competition-co-management.md` around lines 67 - 68, Choose one canonical schema file for cohost metadata (either volunteers.ts or create a new cohost.ts) and update the ADR to reference that single filename; replace the ambiguous “volunteers.ts (or new cohost.ts)” text at the cited locations with the chosen filename and update the code block header to match, and ensure any later references in the document (e.g., the mentions at the other noted lines) are made consistent with the chosen schema file name so contributors have one clear target.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@apps/wodsmith-start/docs/decisions/0004-add-cohost-role-for-competition-co-management.md`:
- Around line 202-208: The decision doc omitted the invite acceptance flow for
cohost tokens—add a route/function to retrieve and accept cohost invites (e.g.,
getCohostInviteFn and an accept-token handler for cohost tokens) and update the
“Affected Paths Summary” and verification checklist to include the invite-token
retrieval + acceptance lifecycle; specifically list getCohostInviteFn (or
equivalent invite-token GET) and the accept-token POST flow, ensure permission
checks mirror existing invite-token handlers, and document tests/verification
steps for token validation, email link handling, and post-accept membership
state.
- Around line 105-110: The ADR currently returns isCohost and cohostPermissions
from the parent route loader but child routes rely on accessing them via context
in beforeLoad guards; since beforeLoad runs before loaders, move the role
context into the parent route's beforeLoad instead of the loader: compute
isCohost (using session and competition.competitionTeamId) and cohostPermissions
(via getCohostPermissions(session, competition.competitionTeamId)) inside the
parent beforeLoad and return them on the context object so child beforeLoad
guards can read context.isCohost and context.cohostPermissions; keep the loader
responsible for fetching competition data only.
---
Nitpick comments:
In
`@apps/wodsmith-start/docs/decisions/0004-add-cohost-role-for-competition-co-management.md`:
- Around line 67-68: Choose one canonical schema file for cohost metadata
(either volunteers.ts or create a new cohost.ts) and update the ADR to reference
that single filename; replace the ambiguous “volunteers.ts (or new cohost.ts)”
text at the cited locations with the chosen filename and update the code block
header to match, and ensure any later references in the document (e.g., the
mentions at the other noted lines) are made consistent with the chosen schema
file name so contributors have one clear target.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: d9c6eb4c-02df-427d-9c91-db5b6e7986e4
📒 Files selected for processing (2)
apps/wodsmith-start/docs/decisions/0004-add-cohost-role-for-competition-co-management.mdapps/wodsmith-start/docs/decisions/README.md
- Move isCohost/cohostPermissions from loader to beforeLoad context (child beforeLoad runs before parent loaders in TanStack Router) - Add cohost invite acceptance flow (getCohostInviteFn, acceptCohostInviteFn, acceptance route) - Use canonical src/db/schemas/cohost.ts for metadata interface - Add 7 verification checklist items for acceptance + context propagation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
3 issues found across 2 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/wodsmith-start/docs/decisions/0004-add-cohost-role-for-competition-co-management.md">
<violation number="1" location="apps/wodsmith-start/docs/decisions/0004-add-cohost-role-for-competition-co-management.md:103">
P1: Opening `$competitionId` to cohosts is not enough by itself; many organizer actions still enforce organizing-team permissions, so cohosts would reach pages they cannot actually use.</violation>
<violation number="2" location="apps/wodsmith-start/docs/decisions/0004-add-cohost-role-for-competition-co-management.md:136">
P2: The guard example uses `context.isCohost`, but child routes only receive parent loader data via `parentMatchPromise`/`getRouteApi` in this router setup.</violation>
<violation number="3" location="apps/wodsmith-start/docs/decisions/0004-add-cohost-role-for-competition-co-management.md:188">
P1: The dashboard plan misses the current `organizingTeams.length === 0` path, so cohost-only users would still land on the empty state instead of seeing their cohosted competitions.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
- Add Phase 3b: server function authorization with new requireCompetitionManagePermission helper that accepts both organizing team (admin/owner) and competition team (cohost) paths - Document all 22 server-fn files (~179 call sites) needing migration - Fix dashboard plan for cohost-only users who have no organizing teams - Add 5 verification checklist items for server fn auth + dashboard Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/wodsmith-start/docs/decisions/0004-add-cohost-role-for-competition-co-management.md">
<violation number="1" location="apps/wodsmith-start/docs/decisions/0004-add-cohost-role-for-competition-co-management.md:238">
P2: File count inconsistency: the header says "26 files" but only 22 are listed, and other parts of the document (consequences, summary table) correctly say "22 files". Update the count to match the actual list.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| 2. For actions gated by configurable cohost permissions (pricing, settings, revenue), pass the relevant `cohostPermission` key | ||
| 3. Update incrementally — start with the most common server functions (competition detail, divisions, events, registrations, volunteers, results) and expand | ||
|
|
||
| **Files requiring server function auth updates** (26 files, ~179 call sites): |
There was a problem hiding this comment.
P2: File count inconsistency: the header says "26 files" but only 22 are listed, and other parts of the document (consequences, summary table) correctly say "22 files". Update the count to match the actual list.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/wodsmith-start/docs/decisions/0004-add-cohost-role-for-competition-co-management.md, line 238:
<comment>File count inconsistency: the header says "26 files" but only 22 are listed, and other parts of the document (consequences, summary table) correctly say "22 files". Update the count to match the actual list.</comment>
<file context>
@@ -175,6 +176,89 @@ if (context.isCohost && !context.cohostPermissions?.canViewRevenue) {
+2. For actions gated by configurable cohost permissions (pricing, settings, revenue), pass the relevant `cohostPermission` key
+3. Update incrementally — start with the most common server functions (competition detail, divisions, events, registrations, volunteers, results) and expand
+
+**Files requiring server function auth updates** (26 files, ~179 call sites):
+- `src/server-fns/competition-detail-fns.ts`
+- `src/server-fns/competition-divisions-fns.ts`
</file context>
| **Files requiring server function auth updates** (26 files, ~179 call sites): | |
| **Files requiring server function auth updates** (22 files, ~179 call sites): |
…hboard - Remove dashboard changes (Phase 5) — /compete/organizer/ stays organizer-only - Parent route skips entitlement for $competitionId routes (same pattern as onboard bypass), defers auth to child beforeLoad - Add Phase 5: cohost entry point via "Manage Competition" link on public competition page (/compete/$slug) - Remove hasCohostMembershipsFn (no longer needed) - Dashboard cohost section deferred to future enhancement Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/wodsmith-start/docs/decisions/0004-add-cohost-role-for-competition-co-management.md">
<violation number="1" location="apps/wodsmith-start/docs/decisions/0004-add-cohost-role-for-competition-co-management.md:145">
P2: This path-based bypass is too broad: it would also skip the `HOST_COMPETITIONS` gate for organizer dashboard routes like `/compete/organizer/new` and `/compete/organizer/series`, not just competition-detail pages.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
The regex /^\/compete\/organizer\/[^/]+/ was too broad — it matched dashboard routes like /new and /series. Competition IDs always start with "comp_" (e.g., comp_01HXYZ), so check the prefix instead. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
cohostsystem role on the competition_event teamDetails
This ADR proposes Option A: cohost role on the competition_event team over Option B (organizing team) because:
Includes a detailed 7-phase implementation plan covering schema changes, auth gates, route guards, sidebar, dashboard, invite flow, and session data.
Test plan
🤖 Generated with Claude Code
Summary by cubic
Adds ADR-0004 proposing a new per-competition
cohostrole so cross‑gym partners can manage a single event without full organizing team access. Clarifies auth, route guards, invite flow, and that cohosts enter from the public competition page.New Features
cohoston thecompetition_eventteam with configurable permissions (revenue, settings, pricing) and safe defaults; sidebar hides gated items.isCohost/cohostPermissionsin parentbeforeLoadcontext; parent organizer route bypasses entitlement only for IDs starting withcomp_and defers to child guard; organizer dashboard remains organizer‑only./compete/$slugto reach/compete/organizer/$competitionIdfor cohosts (and admins/owners).requireCompetitionManagePermissionto accept organizing or competition team paths (with optional cohost permission); documents migration across ~22 server-fn files (~179 call sites).getCohostInviteFnandacceptCohostInviteFn; canonical metadata insrc/db/schemas/cohost.ts.Dependencies
Written for commit 2c84268. Summary will update on new commits.
Summary by CodeRabbit