Skip to content

ChatGPT 5.4: Collaborator lifecycle review: invitee-only mobile contract, missing host management, and no post-accept provisioning #58

@teetangh

Description

@teetangh

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions