Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion docs/decisions/0002-content-flexibility.rst
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
2. Approach to Content Flexibility
==================================

Status
------

Proposed. The "Sequence" and "Navigation" concepts described below have not been realized.


Context
-------

Open edX courses follow a strict Course > Section > Subsection > Unit > Module hierarchy. There are a number of use cases that do not fit this pattern:
Open edX courses follow a strict Course > Section > Subsection > Unit > XBlock hierarchy. There are a number of use cases that do not fit this pattern:

* A problem bank shared via LTI, with individual problems for use in other LMS systems.
* Short courses that do not require the "Section" middle layer of hierarchy.
Expand Down Expand Up @@ -47,6 +53,11 @@ To realize the benefits of this system would require significant changes to Stud
Changelog
---------

2026-04-02:

* Renamed "Module" to "XBlock" to be consistent with updated platform terminology.
* Added "Status"

2023-02-06:

* Renamed "Item" to "Component" to be consistent with user-facing Studio terminology.
Expand Down
15 changes: 14 additions & 1 deletion docs/decisions/0005-identifier-conventions.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
5. Identifier Conventions
=========================

Status
------

Likely superseded by `OEP-68 <https://github.com/openedx/openedx-proposals/pull/773>`_.

Context
-------

Expand Down Expand Up @@ -28,7 +33,7 @@ Key
Implementation Notes
--------------------

Helpers to generate these field types are in the ``openedx_learning.lib.fields`` module.
Helpers to generate these field types are in the ``openedx_django_lib.fields`` module.

Rejected Alternatives
---------------------
Expand All @@ -37,3 +42,11 @@ A number of names were considered for ``key``, and were rejected for different r

* ``identifier`` is used in some standards like QTI, but it's too easily confused with ``id`` or the general concept of the three types of identity-related fields we have.
* ``slug`` was considered, but ultimately rejected because that implied these fields would be human-readable, and that's not guaranteed. Most XBlock content that comes from MongoDB will be using GUIDs, for instance.

Changelog
---------

2026-04-02:

* Added "Status"
* Updated the path to the ``fields`` module.
12 changes: 12 additions & 0 deletions docs/decisions/0006-app-label-prefix.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
6. App Label Prefix
===================

Status
------

Obsolete. See decision 0020. Apps like ``openedx_content`` no longer use the ``oel_`` prefix, and this repo is no longer called "learning core".

Context
-------

Expand All @@ -11,3 +16,10 @@ Decision
--------

All apps in this repo will create a default AppConfig that sets the ``label`` to have a prefix of ``oel_`` before the app name. So if the app name is ``publishing``, the ``label`` will be ``oel_publishing``. This means that all generated database tables will similarly be prefixed with ``oel_``.

Changelog
---------

2026-04-02:

* Added "Status"
21 changes: 18 additions & 3 deletions docs/decisions/0007-tagging-app.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
7. Tagging App structure
========================

Status
------

Partially accepted, partially obsolete (see note under "ObjectTag").

Context
-------

Expand All @@ -17,18 +22,20 @@ Classes which require dependencies on other Open edX projects should be defined
Taxonomy
~~~~~~~~

The ``openedx_tagging`` module defines ``openedx_tagging.core.models.Taxonomy``, whose data and functionality are self-contained to the ``openedx_tagging`` app. However in Studio, we need to be able to limit access to some Taxonomy by organization, using the same "course creator" access which limits course creation for an organization to a defined set of users.
The ``openedx_tagging`` module defines ``openedx_tagging.models.Taxonomy``, whose data and functionality are self-contained to the ``openedx_tagging`` app. However in Studio, we need to be able to limit access to some Taxonomy by organization, using the same "course creator" access which limits course creation for an organization to a defined set of users.

So in edx-platform, we will create the ``openedx.features.content_tagging`` app, to contain the models and logic for linking Organization owners to Taxonomies. Here, we can subclass ``Taxonomy`` as needed, preferably using proxy models. The APIs are responsible for ensuring that any ``Taxonomy`` instances are cast to the appropriate subclass.
So in edx-platform, we will create the ``openedx.core.djangoapps.content_tagging`` app, to contain the models and logic for linking Organization owners to Taxonomies. Here, we can subclass ``Taxonomy`` as needed, preferably using proxy models. The APIs are responsible for ensuring that any ``Taxonomy`` instances are cast to the appropriate subclass.

ObjectTag
~~~~~~~~~

Similarly, the ``openedx_tagging`` module defined ``openedx_tagging.core.models.ObjectTag``, also self-contained to the
Similarly, the ``openedx_tagging`` module defines ``openedx_tagging.models.ObjectTag``, also self-contained to the
``openedx_tagging`` app.

But to tag content in the LMS/Studio, we need to enforce ``object_id`` as a CourseKey or UsageKey type. So to do this, we subclass ``ObjectTag``, and use this class when creating content object tags. Once the ``object_id`` is set, it is not editable, and so this key validation need not happen again.

Note 2026-04-02: In 2024, `we simplified this <https://github.com/openedx/openedx-platform/pull/34146>`_, and ObjectTags are no longer subclassable. Instead, Django ``rules`` permissions hooks allow openedx-platform to extend the ``can_change_object_tag`` permission rule as needed.

Rejected Alternatives
---------------------

Expand All @@ -38,3 +45,11 @@ Embed in edx-platform
Embedding the logic in edx-platform would provide the content tagging logic specifically required for the MVP.

However, we plan to extend tagging to other object types (e.g. People) and contexts (e.g. Marketing), and so a generic, standalone library is preferable in the log run.

Changelog
---------

2026-04-02:

* Added "Status"
* Updated references to module paths
9 changes: 8 additions & 1 deletion docs/decisions/0009-tagging-administrators.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ In the Studio context, a modified version of "course creator" access will be use

Permission #1 requires no external access, so can be enforced by the ``openedx_tagging`` app.

But because permissions #2 + #3 require access to the edx-platform CMS model `CourseCreator`_, this access can only be enforced in Studio, and so will live under ``cms.djangoapps.content_tagging`` along with the ``ContentTag`` class. Tagging MVP must work for libraries v1, v2 and courses created in Studio, and so tying these permissions to Studio is reasonable for the MVP.
But because permissions #2 + #3 require access to the edx-platform CMS model `CourseCreator`_, this access can only be enforced in Studio, and so will live under ``openedx.core.djangoapps.content_tagging`` along with the ``ContentTag`` class. Tagging MVP must work for libraries v1, v2 and courses created in Studio, and so tying these permissions to Studio is reasonable for the MVP.

Per `OEP-9`_, ``openedx_tagging`` will allow applications to use the standard Django API to query permissions, for example: ``user.has_perm('openedx_tagging.edit_taxonomy', taxonomy)``, and the appropriate permissions will be applied in that application's context.

Expand All @@ -40,3 +40,10 @@ This is a standard way to grant access in Django apps, but it is not used in Ope
.. _CourseCreator: https://github.com/openedx/edx-platform/blob/4dc35c73ffa6d6a1dcb6e9ea1baa5bed40721125/cms/djangoapps/course_creators/models.py#L27
.. _OEP-9: https://open-edx-proposals.readthedocs.io/en/latest/best-practices/oep-0009-bp-permissions.html
.. _views: https://github.com/dfunckt/django-rules#permissions-in-views

Changelog
---------

2026-04-02:

* Updated references to module paths
15 changes: 14 additions & 1 deletion docs/decisions/0010-taxonomy-enable-context.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
10. Taxonomy enabled for context
================================

Status
------

Rejected. The "all available taxonomies" advanced setting described was never implemented, and the ``OrgTaxonomy`` subclass of taxonomies was instead replaced with a ``TaxonomyOrg`` model that links organizations to regular ``Taxonomy`` instances.

Context
-------

Expand Down Expand Up @@ -59,7 +64,7 @@ If ``enabled = True``, then the :ref:`Organization` and :ref:`Course` contexts d
Organization
~~~~~~~~~~~~

OrgTaxonomy has a many-to-many relationship with the Organization model, accessed via the ``org_owners`` field. OrgTaxonomy lives under `cms.djangoapps.tagging` and so has access to the Organization model and logic in Studio.
OrgTaxonomy has a many-to-many relationship with the Organization model, accessed via the ``org_owners`` field. OrgTaxonomy lives under ``openedx.core.djangoapps.content_tagging`` and so has access to the Organization model and logic in Studio.

An OrgTaxonomy is enabled for all organizations if ``org_owners == []``.
If there are any ``org_owners`` set, then the OrgTaxonomy is only enabled for those orgas, i.e. only courses in these orgs will see the taxonomy field in Studio.
Expand Down Expand Up @@ -91,3 +96,11 @@ This was deemed too granular for the MVP, and the data structures and UI can be

.. _Advanced Settings: https://github.com/openedx/edx-platform/blob/4dc35c73ffa6d6a1dcb6e9ea1baa5bed40721125/cms/djangoapps/models/settings/course_metadata.py#L28
.. _Course Waffle Flags: https://github.com/openedx/edx-platform/blob/4dc35c73ffa6d6a1dcb6e9ea1baa5bed40721125/openedx/core/djangoapps/waffle_utils/models.py#L14

Changelog
---------

2026-04-02:

* Added "Status"
* Updated references to module paths
12 changes: 10 additions & 2 deletions docs/decisions/0011-tag-changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ Decision
Preserve content tag name:value pairs even if the associated taxonomy or tag is removed.
Reflect name:value changes from the linked taxonomy:tag immediately to the user.

Content tags (through their base ObjectTag class) store a foreign key to their Taxonomy and Tag (if relevant), but they also store a copy of the Taxonomy.name and Tag.value, which can be used if there is no Taxonomy or Tag available.
Content tags (through their base ObjectTag class) store a foreign key to their Taxonomy and Tag (if relevant), but they also store a copy of the Taxonomy.export_id and Tag.value, which can be used if there is no Taxonomy or Tag available.

We consult the authoritative Taxonomy.name and Tag.value whenever displaying a content tag, so any changes are immediately reflected to the user.

If a Taxonomy or Tag is deleted, the linked content tags will remain, and cached copies of the name:value pair will be displayed.
If a Taxonomy or Tag is deleted, the linked content tags will remain, and cached copies of the (name/export_id):value pair will be displayed.

This cached "value" field enables content tags (through their base ObjectTag class) to store free-text tag values, so that the free-text Taxonomy itself need not be modified when new free-text tags are added.

Expand All @@ -33,3 +33,11 @@ Require foreign keys
Require a foreign key from a content tag to Taxonomy for the name, and Tag for the value.

Only using foreign keys puts the labor-intensive content tag data at risk during taxonomy changes, and requires free-text tags to be made part of a taxonomy.

Changelog
---------

2026-04-02:

* Updated: ObjectTag instances now store a reference to ``taxonomy.export_id``, not ``taxonomy.name``
* Updated references to module paths
14 changes: 13 additions & 1 deletion docs/decisions/0014-single-taxonomy-view-api.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
14. Single taxonomy view API
=====================================

Status
------

Accepted, but the API has evolved beyond the description here and now supports loading tags of unlimited depth.

Context
--------

Expand Down Expand Up @@ -101,7 +106,7 @@ The list of tags will be ordered in tree order (and alphabetically). If it has c

**Pros:**

- The edX's interfaces show the tags in the form of a tree.
- The UI interface shows the tags in the form of a tree.
- The frontend needs no further processing as it is in a displayable format.
- It is kept as a simple implementation.

Expand Down Expand Up @@ -157,3 +162,10 @@ can return all the tags in one page. So we can perform the tag search on the fro

- It is not scalable.
- Sets limits of tags that can be created in the taxonomy.

Changelog
---------

2026-04-02:

* Added "Status"
12 changes: 12 additions & 0 deletions docs/decisions/0016-python-public-api-conventions.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
16. Python Public API Conventions
=================================

Status
------

Superseded by decision 0020.

Context
--------

Expand Down Expand Up @@ -88,3 +93,10 @@ Use ``_api`` modules in apps instead of ``api``.
I'm not adding this because it feels unintuitive that apps would import a private module from other apps, e.g. the ``components`` app importing from ``openedx_learning.apps.publishing._api``. My hope is that documentation and import linter rules in edx-platform will be enough to make it clear that APIs should only be imported from ``openedx_learning.api``.

We should revisit this at a later time if this turns out to be a source of confusion.

Changelog
---------

2026-04-02:

* Added "Status"
15 changes: 14 additions & 1 deletion docs/decisions/0017-generalized-containers.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
17. Modeling Containers as a Generalized Capability for Holding Content
========================================================================

Status
------

Accepted, except that "Selectors" have not been finalized nor implemented. Container implementation has been separated from ``publishing`` and is part of a separate "applet".

Context
-------

Expand Down Expand Up @@ -92,4 +97,12 @@ This section defines the rules for pruning container versions, explaining when a
- In a top-down approach, start the deletion process with the parent container and work your way down to its children. E.g., when pruning Section V2 > Subsection V1 > Unit V3, the deletion process starts in the greater container working its way down to the smaller.
- Pruning a container version will not affect the container's history or the children of other container versions, so containers will not be deleted if they are shared by other containers.

.. _PublishableEntity: https://github.com/openedx/openedx-learning/blob/main/openedx_learning/apps/authoring/publishing/models.py#L100-L184
.. _PublishableEntity: https://github.com/openedx/openedx-core/blob/4c1a9f1/src/openedx_content/applets/publishing/models/publishable_entity.py#L27

Changelog
---------

2026-04-02:

* Added "Status"
* Updated link to ``PublishableEntity``
11 changes: 11 additions & 0 deletions docs/decisions/0019-selectors.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
19. Selectors for Dynamically Selecting Content
===============================================

Status
------

Proposed.

Context
-------

Expand Down Expand Up @@ -40,3 +45,9 @@ This section describes how different types of selectors work and how they handle

A new version of a selector is created whenever the pool of concent changes by adding, removing or reordering existing members.

Changelog
---------

2026-04-02:

* Added "Status"