-
Notifications
You must be signed in to change notification settings - Fork 26
docs: tag mutability adr #491
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| .. _openedx-tagging-adr-0010: | ||
|
|
||
| 10. Mutability and Identity of Taxonomy Tags | ||
| ============================================== | ||
|
|
||
| Status | ||
| ------ | ||
|
|
||
| Accepted | ||
|
|
||
| Context | ||
| ------- | ||
|
|
||
| Taxonomy tags rely on three different identifiers, each serving a distinct purpose: | ||
|
|
||
| #. ``id``: the internal, environment-specific database primary key. | ||
| #. ``value``: a string used for display, search indexing, and short-lived API interactions. It is unique within a taxonomy, and mutable. | ||
| #. ``external_id``: a string used to track a tag's identity across system boundaries, particularly during long-lived use cases like taxonomy import and export. | ||
|
|
||
| The system treats ``external_id`` as immutable. The architectural tension arises when an ``external_id`` legitimately needs to change - for example, to correct a typo, or to align with an upstream terminology change (e.g. updating an external standard from "equity considerations" to "use considerations"). | ||
|
|
||
| If ``external_id`` is strictly immutable, a user must delete the existing tag and create a new one, destroying all existing object associations (foreign keys) tied to that tag. | ||
|
|
||
| Conversely, if ``external_id`` were freely mutable, we would break the mechanism used to maintain continuity during taxonomy import/export. Since internal database ``id`` values cannot be used across different environments (they are auto-incremented and environment-specific), the system would have no reliable way to map an incoming, updated tag to the existing tag already in the database. | ||
|
|
||
| The core problem: how do we uniquely identify tags across decoupled environments while allowing administrators to mutate both display values and external identifiers, without destroying existing data relationships? | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In general, that's by using the Well-behaved taxonomies should never change their IDs, and if you look at the lightcast skills taxonomy changelog for example, you'll see that that's the case. (Although sometimes tags are merged together, consolidating two IDs into one.)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Makes sense, but whose responsibility this kind of thing is I cannot answer. I assume it's a product question @jmakowski1123
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I guess my question then - related to the other ADR - is: why would it then be okay for us to change the external_id on our side? Wouldn't we then need to be the ones who need to provide tracking and mapping?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because some taxonomies are going to be changing their IDs upstream, so we have no choice but to allow them to be changed on our side too. Whoever defines the taxonomy at each institution is responsible for publishing the new versions of the taxonomy and the changelog, with all that information. We're not responsible for that; we just need a way to keep the Open edX system in sync.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Makes sense to me.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or did you mean to say we can have mutability and don't need the previous_external_id field or rename?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Strictly speaking, all we need is the ability for admins to edit the external_id in the django admin, but as a nice-to-have we should implement a In the long term if this turns out to be a common requirement, we could also allow editing it in the UI directly, but I'd probably recommend not implementing that for now, until we know how often it's required. |
||
|
|
||
| Decision | ||
| -------- | ||
|
|
||
| Role and scope of identifiers | ||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
|
||
| To maintain clean boundaries between internal systems and external data mobility, the roles of our identifiers are strictly defined: | ||
|
|
||
| * **Internal database ``id``:** reserved for internal, environment-specific relational mapping. It is not exposed in import/export payloads, since it has no cross-environment portability. | ||
| * **``value``:** the mutable, human-readable label. It is unique within a taxonomy, but is not relied upon as a stable identifier for import/export. | ||
| * **``external_id``:** the primary identifier used to match a ``Tag`` across a taxonomy's own import/export. Its scope is limited to that: it is not the identifier used when content tags (``ObjectTag``) reference or export their taxonomy and tag. Content tags instead cache the tag's ``value`` and the taxonomy's ``export_id`` (see :ref:`openedx-tagging-adr-0006`), which is a separate, taxonomy-level identifier. | ||
|
|
||
| Handling identifier mutability | ||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
|
||
| * The taxonomy editor UI displays external IDs, but doesn't allow changing them. It may allow specifying one when creating a tag, and/or generate one based on the value if none is specified. | ||
| * In the rare case where an external ID needs to be changed, an administrator can do so via the Django admin UI. | ||
|
|
||
| This matches the current implementation: the tag update REST API only accepts an updated ``value`` (``Taxonomy.update_tag()`` only supports updating a tag's value), while ``external_id`` can only be set at tag creation, or changed directly through the Django admin. | ||
|
|
||
| Changelog | ||
| --------- | ||
|
|
||
| 2026-07-07: | ||
|
|
||
| * Finalized the decision based on the PR discussion, replacing the previously open options for handling identifier mutability. | ||
| * Moved from ``docs/decisions/`` to ``docs/openedx_tagging/decisions/``, and renumbered, to match current ADR location and numbering conventions. | ||
| * Clarified that ``external_id``'s scope is limited to a taxonomy's own import/export, distinct from ``Taxonomy.export_id``, which content tags use to reference their taxonomy (see :ref:`openedx-tagging-adr-0006`). | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is only true if the external systems also treat the IDs as immutable. But we learned today that some use cases do require IDs to be changed. So we need to support that.