From 4472c92a854156517e0a859d05ec6bbcb79d61a6 Mon Sep 17 00:00:00 2001 From: Braden MacDonald Date: Thu, 2 Apr 2026 17:08:27 -0700 Subject: [PATCH] docs: update ADRs with "Status" notes as of 2026 --- docs/decisions/0002-content-flexibility.rst | 13 +++++++++++- .../decisions/0005-identifier-conventions.rst | 15 ++++++++++++- docs/decisions/0006-app-label-prefix.rst | 12 +++++++++++ docs/decisions/0007-tagging-app.rst | 21 ++++++++++++++++--- .../decisions/0009-tagging-administrators.rst | 9 +++++++- .../0010-taxonomy-enable-context.rst | 15 ++++++++++++- docs/decisions/0011-tag-changes.rst | 12 +++++++++-- .../0014-single-taxonomy-view-api.rst | 14 ++++++++++++- .../0016-python-public-api-conventions.rst | 12 +++++++++++ .../decisions/0017-generalized-containers.rst | 15 ++++++++++++- docs/decisions/0019-selectors.rst | 11 ++++++++++ 11 files changed, 138 insertions(+), 11 deletions(-) diff --git a/docs/decisions/0002-content-flexibility.rst b/docs/decisions/0002-content-flexibility.rst index cea33e9c5..bf13e5c04 100644 --- a/docs/decisions/0002-content-flexibility.rst +++ b/docs/decisions/0002-content-flexibility.rst @@ -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. @@ -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. diff --git a/docs/decisions/0005-identifier-conventions.rst b/docs/decisions/0005-identifier-conventions.rst index 6aae93c4f..b7fe95c90 100644 --- a/docs/decisions/0005-identifier-conventions.rst +++ b/docs/decisions/0005-identifier-conventions.rst @@ -1,6 +1,11 @@ 5. Identifier Conventions ========================= +Status +------ + +Likely superseded by `OEP-68 `_. + Context ------- @@ -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 --------------------- @@ -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. diff --git a/docs/decisions/0006-app-label-prefix.rst b/docs/decisions/0006-app-label-prefix.rst index 376d079e5..ad23d1b28 100644 --- a/docs/decisions/0006-app-label-prefix.rst +++ b/docs/decisions/0006-app-label-prefix.rst @@ -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 ------- @@ -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" diff --git a/docs/decisions/0007-tagging-app.rst b/docs/decisions/0007-tagging-app.rst index 9993a49bb..82ee9ecb1 100644 --- a/docs/decisions/0007-tagging-app.rst +++ b/docs/decisions/0007-tagging-app.rst @@ -1,6 +1,11 @@ 7. Tagging App structure ======================== +Status +------ + +Partially accepted, partially obsolete (see note under "ObjectTag"). + Context ------- @@ -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 `_, 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 --------------------- @@ -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 diff --git a/docs/decisions/0009-tagging-administrators.rst b/docs/decisions/0009-tagging-administrators.rst index 0c984ff37..255b3f1e0 100644 --- a/docs/decisions/0009-tagging-administrators.rst +++ b/docs/decisions/0009-tagging-administrators.rst @@ -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. @@ -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 diff --git a/docs/decisions/0010-taxonomy-enable-context.rst b/docs/decisions/0010-taxonomy-enable-context.rst index 4c12badbc..d81233aaa 100644 --- a/docs/decisions/0010-taxonomy-enable-context.rst +++ b/docs/decisions/0010-taxonomy-enable-context.rst @@ -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 ------- @@ -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. @@ -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 diff --git a/docs/decisions/0011-tag-changes.rst b/docs/decisions/0011-tag-changes.rst index 6e1ea7d6d..6628135b9 100644 --- a/docs/decisions/0011-tag-changes.rst +++ b/docs/decisions/0011-tag-changes.rst @@ -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. @@ -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 diff --git a/docs/decisions/0014-single-taxonomy-view-api.rst b/docs/decisions/0014-single-taxonomy-view-api.rst index cfdf24c98..70a528df8 100644 --- a/docs/decisions/0014-single-taxonomy-view-api.rst +++ b/docs/decisions/0014-single-taxonomy-view-api.rst @@ -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 -------- @@ -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. @@ -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" diff --git a/docs/decisions/0016-python-public-api-conventions.rst b/docs/decisions/0016-python-public-api-conventions.rst index 20bb1f766..cb030f77f 100644 --- a/docs/decisions/0016-python-public-api-conventions.rst +++ b/docs/decisions/0016-python-public-api-conventions.rst @@ -1,6 +1,11 @@ 16. Python Public API Conventions ================================= +Status +------ + +Superseded by decision 0020. + Context -------- @@ -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" diff --git a/docs/decisions/0017-generalized-containers.rst b/docs/decisions/0017-generalized-containers.rst index 71d6abb4f..5840b3731 100644 --- a/docs/decisions/0017-generalized-containers.rst +++ b/docs/decisions/0017-generalized-containers.rst @@ -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 ------- @@ -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`` diff --git a/docs/decisions/0019-selectors.rst b/docs/decisions/0019-selectors.rst index fbc656f92..118c2d4be 100644 --- a/docs/decisions/0019-selectors.rst +++ b/docs/decisions/0019-selectors.rst @@ -1,6 +1,11 @@ 19. Selectors for Dynamically Selecting Content =============================================== +Status +------ + +Proposed. + Context ------- @@ -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"