Skip to content

F2: Client-Project binding (assign/reassign projects to clients) #5

@rororowyourboat

Description

@rororowyourboat

Summary

Establish a parent-child relationship between Clients and Projects so every Project can be organizationally anchored to a Client.

Scope

  • Extend ProjectCreateCommand schema with optional(ClientId) field
  • Add new commands: project.client.assign, project.client.reassign, project.client.unassign
  • Add new events: project.client.assigned, project.client.reassigned (carries previousClientId), project.client.unassigned
  • Add clientId column to projection_projects table (nullable, new migration)
  • Update OrchestrationProject schema with Schema.optional(Schema.NullOr(ClientId)) and Schema.withDecodingDefault(() => null) for backward compatibility
  • Update decider to validate target Client exists and is active on assign/reassign
  • Update projector to set clientId on project projection
  • Handle cascade on client.deleted: unassign all Projects belonging to that Client

Constraints

  • A Project may have at most one clientId at any time
  • Assigning to an archived or deleted Client is rejected
  • Reassign to same Client is a no-op (no event emitted)
  • Creating a Project without clientId is still valid (appears in "Unassigned")

Key files to modify

  • packages/contracts/src/orchestration.ts — extend ProjectCreateCommand, add new command/event types
  • apps/server/src/orchestration/decider.ts — new command cases
  • apps/server/src/orchestration/projector.ts — new event cases + cascade logic
  • apps/server/src/persistence/Migrations/ — new migration adding client_id column
  • apps/server/src/persistence/Layers/ProjectionProjects.ts — update SQL queries

Dependencies

  • F1 (Client entity must exist first)

Acceptance criteria

  • New projects can be created with a clientId
  • Existing projects without clientId continue to work (backward compat)
  • Can assign an unassigned project to a Client
  • Can reassign a project from one Client to another
  • Can unassign a project (returns to "Unassigned")
  • Assigning to archived/deleted Client is rejected
  • Deleting a Client unassigns its Projects

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1Priority 1 - Foundationclient-hierarchyClient hierarchy & workspace organizationenhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions