diff --git a/docs/openedx_learning/decisions/0004-pathway-catalog-content-split.rst b/docs/openedx_learning/decisions/0004-pathway-catalog-content-split.rst new file mode 100644 index 000000000..262dbe5ad --- /dev/null +++ b/docs/openedx_learning/decisions/0004-pathway-catalog-content-split.rst @@ -0,0 +1,90 @@ +.. _openedx-learning-adr-0004: + +4. Pathways: Split Between Catalog and Content +============================================== + +Status +------ + +Draft + +Context +------- + +Courses in ``openedx-core`` already separate the *catalog* side (``openedx_catalog``: ``CatalogCourse``, +``CourseRun`` - what learners browse and enroll against) from the *content* side (``openedx_content`` - what is +authored, versioned, and published). Pathways have the same two aspects, and the same reasons to keep them apart: + +- **Different change rates.** The display name, description shown in the catalog, and SEO metadata are revised + frequently and casually. The definition of what a learner must do to complete the Pathway changes rarely and + deliberately. +- **Different people doing the editing.** Catalog data is typically maintained by marketing or communications staff; + the Pathway definition is maintained by content authors. Both are visible to learners, so the distinction is about + who edits what, not about who can see it. +- **Different permissions follow from that.** We expect instances to want to let marketing staff update catalog + copy without granting them the ability to change what learners must complete, and vice versa. Keeping the two + apart makes that possible without inventing field-level permissions. However, with the new RBAC system, this + may be less of a concern. +- **Auditability.** Progress and credentials must be judged against the definition that was in effect at the time, + which requires versioning the definition - but versioning catalog copy would be pure overhead. + +Decisions +--------- + +1. A Pathway is split into two parts: + + - **Catalog Pathway** - the learner-browsable, enrollable thing. It includes the display name, the description + shown in the catalog, SEO metadata, and a **Category**. It is **not versioned**. + + - **Pathway content** - the definition of the Pathway: its Items and its completion criteria. The content is + **versioned**, so that we can always tell what the definition was at any given moment. A version of the Pathway + content *implements* a Catalog Pathway. + +2. The **Category** is a student-facing label for the kind of Pathway (e.g. "Master's Degree", "Annual Training"). + Learners see the Category rather than the word "Pathway". It is always required: rather than falling back to + "Pathway" in code, we ship a default database entry with that name, so the behavior is uniform and operators can + rename or extend the set without a code change. + +3. In authoring contexts (Studio, Django admin, code, docs), the terminology is always "Pathway", with the Category + shown explicitly. Relabelling is a learner-facing concern of the catalog side only. + +4. **Dependency direction**: ``openedx_content`` knows about ``openedx_catalog``, never the reverse. This has the + following consequences: + + - Pathway Items may reference ``CourseRun`` entities directly. + - The link from a Catalog Pathway to the Pathway content that implements it lives on the content side. + - Anything that has to tie the two sides together belongs in ``openedx_content``, or in something downstream of + it, but never in ``openedx_catalog``. + +5. **Enrollment** ties a learner to a Catalog Pathway. Progress is evaluated against the currently published + content version, not against a version frozen at enrollment time, so that authoring changes reach learners who + are already enrolled. + +Example content of each model: + +============================ =================================== +Catalog Pathway Pathway content +============================ =================================== +Display name Pathway Items +Category Completion criteria +Description References to CourseRuns +SEO metadata Link to the related Catalog Pathway +Enrollment +============================ =================================== + +.. Run `dot -Tsvg images/pathway-catalog-content.dot > images/pathway-catalog-content.svg` to regenerate the diagram + after making changes to `images/pathway-catalog-content.dot`. + +.. image:: images/pathway-catalog-content.svg + :alt: Catalog Pathway vs versioned Pathway content + :width: 100% + +Consequences +------------ + +- Catalog edits never create new content versions; definition edits (Items, criteria) always do. +- Because evaluation follows the published version rather than the enrollment-time version, edits to a Pathway apply + to learners who are already enrolled, which is what we want, but it means edits need care and re-evaluation. +- The unversioned Catalog Pathway can be long-lived even if its content definition is changed significantly over time. +- The dependency direction means a Catalog Pathway cannot, on its own, tell which content implements it. Queries in + that direction start from the content side. diff --git a/docs/openedx_learning/decisions/images/pathway-catalog-content.dot b/docs/openedx_learning/decisions/images/pathway-catalog-content.dot new file mode 100644 index 000000000..10bafb89f --- /dev/null +++ b/docs/openedx_learning/decisions/images/pathway-catalog-content.dot @@ -0,0 +1,40 @@ +digraph pathway_catalog_content { + rankdir=LR; + fontname="Helvetica"; + compound=true; + node [shape=box, style=rounded, fontname="Helvetica", fontsize=11]; + edge [fontname="Helvetica", fontsize=10]; + + subgraph cluster_catalog { + label="openedx_catalog (not versioned)"; + fontsize=10; + fontcolor="#4d4d4d"; + style=dashed; + color="#b3b3b3"; + catalog [label="Catalog Pathway\n\nname, category,\ndescription, SEO"]; + courserun [label="CourseRun"]; + } + + subgraph cluster_content { + label="openedx_content (versioned)"; + fontsize=10; + fontcolor="#4d4d4d"; + style=dashed; + color="#b3b3b3"; + v1 [label="content v1\n\nItems, criteria"]; + v2 [label="content v2\n\nItems, criteria\n(currently published)"]; + v1 -> v2 [style=dotted, color="#808080", arrowsize=0.7, label="revision"]; + } + + user [label="User", shape=ellipse]; + enrollment [label="Enrollment"]; + + user -> enrollment [label="learner"]; + enrollment -> catalog [label="enrolled in"]; + enrollment -> v2 [label="progress evaluated\nagainst the currently\npublished version", style=dashed, color="#808080", fontcolor="#4d4d4d"]; + + v2 -> catalog [label="implements"]; + v2 -> courserun [label="Items reference"]; + + direction [label="dependency direction:\nopenedx_content knows about\nopenedx_catalog, never the reverse", shape=plaintext, fontsize=10, fontcolor="#4d4d4d"]; +} diff --git a/docs/openedx_learning/decisions/images/pathway-catalog-content.svg b/docs/openedx_learning/decisions/images/pathway-catalog-content.svg new file mode 100644 index 000000000..df9a619a9 --- /dev/null +++ b/docs/openedx_learning/decisions/images/pathway-catalog-content.svg @@ -0,0 +1,115 @@ + + + + + + +pathway_catalog_content + + +cluster_catalog + +openedx_catalog (not versioned) + + +cluster_content + +openedx_content (versioned) + + + +catalog + +Catalog Pathway +name, category, +description, SEO + + + +courserun + +CourseRun + + + +v1 + +content v1 +Items, criteria + + + +v2 + +content v2 +Items, criteria +(currently published) + + + +v1->v2 + + +revision + + + +v2->catalog + + +implements + + + +v2->courserun + + +Items reference + + + +user + +User + + + +enrollment + +Enrollment + + + +user->enrollment + + +learner + + + +enrollment->catalog + + +enrolled in + + + +enrollment->v2 + + +progress evaluated +against the currently +published version + + + +direction +dependency direction: +openedx_content knows about +openedx_catalog, never the reverse + + +