Summary
The mobile collaborator system is not just thinner than web; it is structurally incomplete. In the Dart Frog backend, collaborators are effectively an invitee-only feature with two routes:
GET /api/collaborations
PATCH /api/collaborations/:id/respond
That leaves the host-side lifecycle missing, drops the permission model from the mobile contract, and skips the post-accept provisioning that the web app treats as part of collaboration acceptance. The result is a collaboration feature that can list invitations and flip PENDING -> ACCEPTED, but cannot safely support plan management, collaborator coordination, or even the current web MVP of schedule visibility.
This issue focuses on the collaborator bucket itself. It overlaps with but is distinct from:
Why this matters
On web, the collaborator system is treated as a cross-cutting product feature spanning:
- invitation + response
- host-side collaborator management
- role/custom permission checks
- collaborator-only Stream channels
- read-only schedule visibility
- co-host availability overlay
- revenue split preview / collaborator earnings context
On mobile, the backend and Flutter app only implement a narrow invitation inbox. That is not just parity debt. It creates concrete correctness problems:
- accepted collaborators are not provisioned into the collaborator coordination flow
- the data contract discards fields required for future authorization and management
- the backend trusts client hints (
planType) where it should resolve server-side
- the product model in docs/web implies capabilities the mobile backend cannot satisfy
Current mobile implementation
Backend surface
Only two collaboration routes exist in the mobile Dart Frog backend:
backend/routes/api/collaborations/index.dart
backend/routes/api/collaborations/[id]/respond.dart
The repository behind them is:
backend/lib/database/repositories/collaborator_repository.dart
Flutter surface
The mobile app only supports:
- fetch collaborations
- accept/decline invitation
Relevant files:
lib/data/datasources/remote/collaborator_remote_source.dart
lib/domain/entities/collaborator/collaborator_entities.dart
lib/features/collaborations/screens/collaborations_screen.dart
lib/features/collaborations/widgets/collaboration_card.dart
No host-side collaborator management flow was found in Flutter.
Findings
1. Mobile collaborator lifecycle is invitee-only; the host-side API surface is missing entirely
The mobile backend exposes no route to:
- invite a collaborator
- list collaborators for a plan
- update collaborator role/share
- remove collaborator
- preview revenue splits
- fetch collaborator availability for scheduling
Evidence:
- Mobile only has
backend/routes/api/collaborations/index.dart and backend/routes/api/collaborations/[id]/respond.dart
- Web exposes:
app/api/collaborations/webinar/[planId]/route.ts
app/api/collaborations/class/[planId]/route.ts
app/api/collaborations/webinar/[planId]/[id]/route.ts
app/api/collaborations/class/[planId]/[id]/route.ts
app/api/collaborations/webinar/[planId]/revenue-split/route.ts
app/api/collaborations/class/[planId]/revenue-split/route.ts
app/api/collaborators/[consultantProfileId]/availability/route.ts
- The web API is explicitly documented in
familiarise_web/docs/collaborators/02-api-reference.md:42-144, :239-320
Impact:
- hosts cannot manage collaborators from mobile
- no safe mobile backend contract exists for a future host management UI
- product behavior diverges across platforms at the API level, not just the UI level
2. GET /api/collaborations is structurally lossy versus the web contract
The mobile route returns only:
webinarCollaborations
classCollaborations
- summary counts
See:
backend/routes/api/collaborations/index.dart:43-60
backend/lib/database/repositories/collaborator_repository.dart:10-75
By contrast, the web route returns:
- incoming collaborations
- hosted plans with active collaborators
- host user metadata
See:
familiarise_web/app/api/collaborations/route.ts:31-45
familiarise_web/lib/collaborators/service.ts:545-644
Important data that web includes but mobile drops:
hostedWebinarPlans
hostedClassPlans
- collaborator rosters on hosted plans
- schedule summaries (
webinars, classes, slot counts)
- owner context (
hostUser)
- collaborator profile IDs / nested profile info
Impact:
- mobile cannot represent the host perspective at all
- accepted collaborators cannot get the read-only schedule context that web exposes as the current MVP
- the mobile dashboard can only show a count and a flat invitation list, not the actual collaboration state
3. The mobile collaborator DTO drops fields that already exist in schema and are needed for authorization
The mobile schema registry still exposes collaborator fields such as:
permissions
invitedById
respondedAt
consultantProfileId
See:
backend/lib/database/schema_registry_builder.dart:1674-1692
backend/lib/database/schema_registry_builder.dart:1726-1744
But the repository flatteners deliberately discard most of them:
backend/lib/database/repositories/collaborator_repository.dart:177-230
The Flutter entity also keeps only:
id
planType
role
status
revenueSharePercentage
planTitle
planPrice
hostName
hostImage
inviterName
createdAt
See:
lib/domain/entities/collaborator/collaborator_entities.dart:8-21
lib/data/datasources/remote/collaborator_remote_source.dart:124-141
Impact:
- mobile cannot express custom collaborator permission overrides even though the DB supports them
- mobile cannot render acceptance timestamps or reliable collaborator identity context
- future mobile authorization work will require a payload/schema redesign instead of additive changes
4. The mobile backend has no collaborator permission layer, despite the shared data model supporting it
The web app has an explicit permission model documented in:
familiarise_web/docs/collaborators/04-permissions.md:5-49
familiarise_web/docs/collaborators/04-permissions.md:53-88
familiarise_web/docs/collaborators/04-permissions.md:92-124
That model supports:
- role-based permissions
- optional JSON overrides via
permissions
- API-side permission checks for edit/publish/invite/analytics/manage
On mobile:
- no collaborator permission helper/service was found
- no collaboration route returns permission data
- no plan/event route appears to check collaborator permissions
Impact:
- any future mobile collaborator capabilities will either remain host-only or be added ad hoc without a coherent authorization model
- the backend schema and product docs imply a permission system that the mobile API does not expose or enforce
5. Accepting an invitation in mobile does not provision collaborator coordination state
The mobile accept flow only updates status and respondedAt:
backend/lib/database/repositories/collaborator_repository.dart:77-119
There are no collaborator-specific side effects in the mobile repo. A search for collaborator channel creation patterns returned no matching implementation in Dart:
- no
collab- chat channel pattern
- no
createCollaboratorChannel
- no collaborator-specific notification trigger
The web service explicitly treats acceptance as provisioning time:
familiarise_web/lib/collaborators/service.ts:123-182
And the docs call out side effects on accept:
- create Stream channel:
familiarise_web/docs/collaborators/02-api-reference.md:168-173
- channel lifecycle / naming:
familiarise_web/docs/collaborators/05-stream-integration.md:15-25, :38-56, :80-95
Impact:
- accepted collaborators on mobile are not provisioned into the private coordination channel model that web expects
- collaboration acceptance mutates the DB but not the rest of the collaboration system
- downstream chat/coordination UX cannot converge because the backend never creates the collaboration artifact
6. The mobile respond endpoint trusts client-provided planType instead of resolving the collaboration server-side
The route accepts planType in the request body and passes it through:
backend/routes/api/collaborations/[id]/respond.dart:30-79
The repository uses that client-provided value to decide whether to query WebinarCollaborator or ClassCollaborator:
backend/lib/database/repositories/collaborator_repository.dart:78-85
This means the route does not derive the collaboration type from the id itself. A wrong or stale planType turns into a false negative response (not found or already responded) even when the collaboration exists.
The web route currently has the same body contract, but the mobile backend is especially brittle because it has no richer collaborator fetch/manage surface to recover from or self-correct this state.
Impact:
- acceptance/decline is needlessly dependent on client state that the server could resolve
- bad payloads create confusing 404-like behavior instead of deterministic validation
- server authority over collaborator identity/type is weaker than necessary
7. Mobile omits the current web MVP for collaborator schedule visibility
The web collaborator MVP is explicitly documented as view-only schedule visibility:
familiarise_web/docs/collaborators/06-scheduling-approaches.md:7-47
Web implements this by expanding getMyCollaborations() with nested webinar/class schedule data:
familiarise_web/lib/collaborators/service.ts:415-538
familiarise_web/components/collaborators/InvitationsPanel.tsx:23-149
familiarise_web/components/collaborators/InvitationsPanel.tsx:186-360
Mobile exposes no equivalent:
lib/features/collaborations/screens/collaborations_screen.dart:40-134
lib/features/collaborations/widgets/collaboration_card.dart:23-180
The mobile active state is just a static card with:
- title
- type
- role
- share
- host info
- active badge
Impact:
- accepted collaborators on mobile cannot see event timing/status/capacity for the plans they joined
- mobile does not implement even the current read-only collaborator scheduling model from web
- this creates a practical coordination gap even before more advanced scheduling features are considered
8. Mobile lacks the collaborator availability overlay contract used for host scheduling decisions
The web app has a dedicated availability endpoint:
familiarise_web/app/api/collaborators/[consultantProfileId]/availability/route.ts:7-167
That endpoint is not just a convenience read:
- it authorizes owner / accepted collaborator / admin access
- it returns weekly slots, custom slots, and booked slots
- it includes collaborated commitments in booked slot calculation (
:102-149)
No equivalent route exists in the mobile backend.
Impact:
- hosts on mobile have no backend support for checking collaborator availability before scheduling webinars/classes
- any future mobile scheduling UI will miss a key conflict signal that web already relies on
- collaborated commitments remain invisible to the mobile scheduling surface
9. Mobile collaboration counts and lists only consider PENDING / ACCEPTED, with no lifecycle/history surface
The mobile repository hard-codes collaboration visibility to PENDING and ACCEPTED:
backend/lib/database/repositories/collaborator_repository.dart:18-21
backend/lib/database/repositories/collaborator_repository.dart:45-48
backend/lib/database/repositories/collaborator_repository.dart:127-174
That may be acceptable for an inbox, but because mobile has no host management or history views, it also means the platform has no mobile surface for:
- declined invites
- removed collaborators
- re-invite / reactivation state
- collaboration churn audit
The web service explicitly handles reactivation cases for REMOVED / DECLINED in invite flows:
familiarise_web/lib/collaborators/service.ts:46-114
Impact:
- mobile collaboration lifecycle is flattened to “pending or active,” which hides state transitions the backend schema already models
- operations like re-invite or removal cannot be represented cleanly on mobile
Root cause
The mobile implementation appears to have been built as a narrow invitation inbox on top of a richer shared domain model:
- schema contains collaborator permissions and lifecycle fields
- web implements the broader lifecycle
- mobile only serializes a small subset and exposes only two routes
That creates a permanent drift hazard: each new collaborator feature requires a contract redesign rather than incremental addition.
Recommended fix plan
1. Treat collaborators as a full backend domain, not a dashboard widget
Port or re-implement the missing route surface in Dart Frog:
GET /api/collaborations
- include hosted plans, collaborator rosters, and schedule summary
GET /api/collaborations/webinar/:planId
POST /api/collaborations/webinar/:planId
PATCH /api/collaborations/webinar/:planId/:id
DELETE /api/collaborations/webinar/:planId/:id
- class equivalents
- revenue split preview endpoints
- collaborator availability endpoint
2. Redesign the mobile collaborator DTO before expanding the UI
Add explicit fields for at least:
consultantProfileId
invitedById
respondedAt
permissions
- hosted plan data
- schedule summaries
Do not keep extending the current flattened response if mobile is expected to support host-side flows.
3. Make acceptance server-authoritative and provision side effects
On accept:
- resolve the collaboration type server-side instead of trusting
planType
- update status atomically
- create/update the collaborator Stream channel
- notify the host
- return the updated collaboration with enough context for immediate UI refresh
4. Introduce a shared collaborator permission layer in the mobile backend
Add permission helpers analogous to web for:
- owner checks
- accepted-collaborator checks
- role default permission checks
- custom JSON override checks
Use those in any future plan/program/analytics/participant management routes that become collaborator-accessible.
5. Decide and document the intended mobile scope
If mobile is intentionally invitee-only, that needs to be stated clearly in docs and API naming. Right now:
- schema implies a richer system
- web implements a richer system
- mobile exposes partial state without clarifying scope
If the product goal is parity, the backend contract should move toward web. If not, the missing sectors should be treated as explicit product decisions, not accidental drift.
Acceptance criteria
- Mobile backend supports collaborator invitation, update, removal, and list-by-plan flows for webinar/class plans
GET /api/collaborations returns both collaboration inbox data and hosted plan collaboration data
- Acceptance creates or updates the collaborator Stream channel and notifies the host
- Collaboration payloads include permission and lifecycle fields required for future authorization
- Collaborator availability overlay endpoint exists in Dart Frog
- Mobile UI can at minimum support:
- pending invitation response
- active collaboration schedule visibility
- host-side collaborator list/management entry points
Regression tests to add
- accept invite succeeds without trusting a client-supplied wrong
planType
- accept invite creates collaborator channel membership for host + accepted collaborators
- decline invite updates state without side effects
- host cannot invite self
- invite/update flows enforce total collaborator share <= 90%
- hosted collaborations query returns hosted plans plus collaborator rosters
- collaborator availability endpoint includes collaborated commitments in booked slots
- permission helpers enforce owner vs collaborator capabilities correctly
Nice-to-have cleanup
- Rename mobile collaborator files/folders to reflect the real domain split:
invitations
hosted_collaborations
collaborator_management
rather than treating everything as one flat “collaborations” list
- Add backend docs in the mobile repo for the intended collaborator contract so future contributors do not assume web parity where none exists
Summary
The mobile collaborator system is not just thinner than web; it is structurally incomplete. In the Dart Frog backend, collaborators are effectively an invitee-only feature with two routes:
GET /api/collaborationsPATCH /api/collaborations/:id/respondThat leaves the host-side lifecycle missing, drops the permission model from the mobile contract, and skips the post-accept provisioning that the web app treats as part of collaboration acceptance. The result is a collaboration feature that can list invitations and flip
PENDING -> ACCEPTED, but cannot safely support plan management, collaborator coordination, or even the current web MVP of schedule visibility.This issue focuses on the collaborator bucket itself. It overlaps with but is distinct from:
Why this matters
On web, the collaborator system is treated as a cross-cutting product feature spanning:
On mobile, the backend and Flutter app only implement a narrow invitation inbox. That is not just parity debt. It creates concrete correctness problems:
planType) where it should resolve server-sideCurrent mobile implementation
Backend surface
Only two collaboration routes exist in the mobile Dart Frog backend:
backend/routes/api/collaborations/index.dartbackend/routes/api/collaborations/[id]/respond.dartThe repository behind them is:
backend/lib/database/repositories/collaborator_repository.dartFlutter surface
The mobile app only supports:
Relevant files:
lib/data/datasources/remote/collaborator_remote_source.dartlib/domain/entities/collaborator/collaborator_entities.dartlib/features/collaborations/screens/collaborations_screen.dartlib/features/collaborations/widgets/collaboration_card.dartNo host-side collaborator management flow was found in Flutter.
Findings
1. Mobile collaborator lifecycle is invitee-only; the host-side API surface is missing entirely
The mobile backend exposes no route to:
Evidence:
backend/routes/api/collaborations/index.dartandbackend/routes/api/collaborations/[id]/respond.dartapp/api/collaborations/webinar/[planId]/route.tsapp/api/collaborations/class/[planId]/route.tsapp/api/collaborations/webinar/[planId]/[id]/route.tsapp/api/collaborations/class/[planId]/[id]/route.tsapp/api/collaborations/webinar/[planId]/revenue-split/route.tsapp/api/collaborations/class/[planId]/revenue-split/route.tsapp/api/collaborators/[consultantProfileId]/availability/route.tsfamiliarise_web/docs/collaborators/02-api-reference.md:42-144,:239-320Impact:
2.
GET /api/collaborationsis structurally lossy versus the web contractThe mobile route returns only:
webinarCollaborationsclassCollaborationsSee:
backend/routes/api/collaborations/index.dart:43-60backend/lib/database/repositories/collaborator_repository.dart:10-75By contrast, the web route returns:
See:
familiarise_web/app/api/collaborations/route.ts:31-45familiarise_web/lib/collaborators/service.ts:545-644Important data that web includes but mobile drops:
hostedWebinarPlanshostedClassPlanswebinars,classes, slot counts)hostUser)Impact:
3. The mobile collaborator DTO drops fields that already exist in schema and are needed for authorization
The mobile schema registry still exposes collaborator fields such as:
permissionsinvitedByIdrespondedAtconsultantProfileIdSee:
backend/lib/database/schema_registry_builder.dart:1674-1692backend/lib/database/schema_registry_builder.dart:1726-1744But the repository flatteners deliberately discard most of them:
backend/lib/database/repositories/collaborator_repository.dart:177-230The Flutter entity also keeps only:
idplanTyperolestatusrevenueSharePercentageplanTitleplanPricehostNamehostImageinviterNamecreatedAtSee:
lib/domain/entities/collaborator/collaborator_entities.dart:8-21lib/data/datasources/remote/collaborator_remote_source.dart:124-141Impact:
4. The mobile backend has no collaborator permission layer, despite the shared data model supporting it
The web app has an explicit permission model documented in:
familiarise_web/docs/collaborators/04-permissions.md:5-49familiarise_web/docs/collaborators/04-permissions.md:53-88familiarise_web/docs/collaborators/04-permissions.md:92-124That model supports:
permissionsOn mobile:
Impact:
5. Accepting an invitation in mobile does not provision collaborator coordination state
The mobile accept flow only updates
statusandrespondedAt:backend/lib/database/repositories/collaborator_repository.dart:77-119There are no collaborator-specific side effects in the mobile repo. A search for collaborator channel creation patterns returned no matching implementation in Dart:
collab-chat channel patterncreateCollaboratorChannelThe web service explicitly treats acceptance as provisioning time:
familiarise_web/lib/collaborators/service.ts:123-182And the docs call out side effects on accept:
familiarise_web/docs/collaborators/02-api-reference.md:168-173familiarise_web/docs/collaborators/05-stream-integration.md:15-25,:38-56,:80-95Impact:
6. The mobile respond endpoint trusts client-provided
planTypeinstead of resolving the collaboration server-sideThe route accepts
planTypein the request body and passes it through:backend/routes/api/collaborations/[id]/respond.dart:30-79The repository uses that client-provided value to decide whether to query
WebinarCollaboratororClassCollaborator:backend/lib/database/repositories/collaborator_repository.dart:78-85This means the route does not derive the collaboration type from the
iditself. A wrong or staleplanTypeturns into a false negative response (not found or already responded) even when the collaboration exists.The web route currently has the same body contract, but the mobile backend is especially brittle because it has no richer collaborator fetch/manage surface to recover from or self-correct this state.
Impact:
7. Mobile omits the current web MVP for collaborator schedule visibility
The web collaborator MVP is explicitly documented as view-only schedule visibility:
familiarise_web/docs/collaborators/06-scheduling-approaches.md:7-47Web implements this by expanding
getMyCollaborations()with nested webinar/class schedule data:familiarise_web/lib/collaborators/service.ts:415-538familiarise_web/components/collaborators/InvitationsPanel.tsx:23-149familiarise_web/components/collaborators/InvitationsPanel.tsx:186-360Mobile exposes no equivalent:
lib/features/collaborations/screens/collaborations_screen.dart:40-134lib/features/collaborations/widgets/collaboration_card.dart:23-180The mobile active state is just a static card with:
Impact:
8. Mobile lacks the collaborator availability overlay contract used for host scheduling decisions
The web app has a dedicated availability endpoint:
familiarise_web/app/api/collaborators/[consultantProfileId]/availability/route.ts:7-167That endpoint is not just a convenience read:
:102-149)No equivalent route exists in the mobile backend.
Impact:
9. Mobile collaboration counts and lists only consider
PENDING/ACCEPTED, with no lifecycle/history surfaceThe mobile repository hard-codes collaboration visibility to
PENDINGandACCEPTED:backend/lib/database/repositories/collaborator_repository.dart:18-21backend/lib/database/repositories/collaborator_repository.dart:45-48backend/lib/database/repositories/collaborator_repository.dart:127-174That may be acceptable for an inbox, but because mobile has no host management or history views, it also means the platform has no mobile surface for:
The web service explicitly handles reactivation cases for
REMOVED/DECLINEDin invite flows:familiarise_web/lib/collaborators/service.ts:46-114Impact:
Root cause
The mobile implementation appears to have been built as a narrow invitation inbox on top of a richer shared domain model:
That creates a permanent drift hazard: each new collaborator feature requires a contract redesign rather than incremental addition.
Recommended fix plan
1. Treat collaborators as a full backend domain, not a dashboard widget
Port or re-implement the missing route surface in Dart Frog:
GET /api/collaborationsGET /api/collaborations/webinar/:planIdPOST /api/collaborations/webinar/:planIdPATCH /api/collaborations/webinar/:planId/:idDELETE /api/collaborations/webinar/:planId/:id2. Redesign the mobile collaborator DTO before expanding the UI
Add explicit fields for at least:
consultantProfileIdinvitedByIdrespondedAtpermissionsDo not keep extending the current flattened response if mobile is expected to support host-side flows.
3. Make acceptance server-authoritative and provision side effects
On accept:
planType4. Introduce a shared collaborator permission layer in the mobile backend
Add permission helpers analogous to web for:
Use those in any future plan/program/analytics/participant management routes that become collaborator-accessible.
5. Decide and document the intended mobile scope
If mobile is intentionally invitee-only, that needs to be stated clearly in docs and API naming. Right now:
If the product goal is parity, the backend contract should move toward web. If not, the missing sectors should be treated as explicit product decisions, not accidental drift.
Acceptance criteria
GET /api/collaborationsreturns both collaboration inbox data and hosted plan collaboration dataRegression tests to add
planTypeNice-to-have cleanup
invitationshosted_collaborationscollaborator_managementrather than treating everything as one flat “collaborations” list