Skip to content

ContentAssigner

Updated 13 Jul 2026jirkamotejl

ContentAssigner is a reconciliation engine. Its purpose is to turn content assignment intent into effective user study state.

Current source: knowspread/docs/content_assigner.md.

flowchart LR
  Event[Business event] --> Dispatcher[ContentAssigner::Dispatcher]
  Dispatcher --> Job[ContentAssigner::Job]
  Job --> AssignmentJob[ContentAssignmentJob]
  AssignmentJob --> Assigner[ContentAssigner::Assigner]
  Assigner --> Sources[ParticipationSource]
  Assigner --> Participations[ContentParticipation]
  Assigner --> Licenses[ContentLicense]
  Assigner --> Emails[EmailNotifierJob]
TermRole in the process
AssignedContentIntent that content should be studied by a user or group.
ContentParticipationEffective study record for a concrete user.
ParticipationSourceExplanation of why a ContentParticipation exists.
ContentLicenseConsumed seat for a user and content in a company space.
  • Migrate the verified parts from the old document.
  • Add current links to classes and specs.
  • Split architecture, edge cases, troubleshooting, and API impact.
  • Mark the owner and last review date.

ContentAssigner should not be called because a controller wants to manually create ContentParticipation. It should run when the domain intent changed:

  • content was assigned to a group,
  • content was removed from a group,
  • a user was added to a group,
  • a user was removed from a group,
  • content was assigned directly to a user,
  • a user was added or returned to a company space,
  • a new active content version was promoted,
  • a user completed repeated training.

The output should not be just a row creation. It should be a consistent set of participations, sources, licenses, notifications, and future recalculations.

AssignedContent is intent. ContentParticipation is effective state. If there is a mismatch, ContentAssigner resolves it, not the controller.