Skip to content

docs: add ADR for cross-instance taxonomy identity#656

Open
mgwozdz-unicon wants to merge 5 commits into
openedx:mainfrom
mgwozdz-unicon:cbe-cross-instance-taxonomy-identity-adr
Open

docs: add ADR for cross-instance taxonomy identity#656
mgwozdz-unicon wants to merge 5 commits into
openedx:mainfrom
mgwozdz-unicon:cbe-cross-instance-taxonomy-identity-adr

Conversation

@mgwozdz-unicon

Copy link
Copy Markdown
Contributor
  • Adds ADR 0011, proposing a stable, immutable uuid field on Taxonomy so that competency
    criteria copied along with course content (new course run, course export/import, course/library
    copy) can be bound by reference to the correct taxonomy on the target instance, rather than an
    export_id match that isn't reliable across instances.
  • Defines the reconciliation policy for repeat imports: if the incoming tag diff is additions
    only, apply it; if it includes any rename, reparent, or delete, refuse the import rather than
    risk silently mutating taxonomy state that unrelated content on the target depends on.
  • Scopes this decision to the legacy XBlock/modulestore course path only. Cross-instance library
    copy, the newer openedx_content Component/Container model, and full taxonomy/tag versioning
    are explicitly out of scope, noted as excluded or deferred with reasoning.

@openedx-webhooks openedx-webhooks added the open-source-contribution PR author is not from Axim or 2U label Jul 10, 2026
@openedx-webhooks

Copy link
Copy Markdown

Thanks for the pull request, @mgwozdz-unicon!

This repository is currently maintained by @axim-engineering.

Once you've gone through the following steps feel free to tag them in a comment and let them know that your changes are ready for engineering review.

🔘 Get product approval

If you haven't already, check this list to see if your contribution needs to go through the product review process.

  • If it does, you'll need to submit a product proposal for your contribution, and have it reviewed by the Product Working Group.
    • This process (including the steps you'll need to take) is documented here.
  • If it doesn't, simply proceed with the next step.
🔘 Provide context

To help your reviewers and other members of the community understand the purpose and larger context of your changes, feel free to add as much of the following information to the PR description as you can:

  • Dependencies

    This PR must be merged before / after / at the same time as ...

  • Blockers

    This PR is waiting for OEP-1234 to be accepted.

  • Timeline information

    This PR must be merged by XX date because ...

  • Partner information

    This is for a course on edx.org.

  • Supporting documentation
  • Relevant Open edX discussion forum threads
🔘 Get a green build

If one or more checks are failing, continue working on your changes until this is no longer the case and your build turns green.

Details
Where can I find more information?

If you'd like to get more details on all aspects of the review process for open source pull requests (OSPRs), check out the following resources:

When can I expect my changes to be merged?

Our goal is to get community contributions seen and reviewed as efficiently as possible.

However, the amount of time that it takes to review and merge a PR can vary significantly based on factors such as:

  • The size and impact of the changes that it introduces
  • The need for product review
  • Maintenance status of the parent repository

💡 As a result it may take up to several weeks or months to complete a review and merge your PR.

@bradenmacdonald bradenmacdonald left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not totally opposed to using UUIDs here, but I don't think it's necessary and I do think you can achieve everything that you want by making an effort to make the default value of export_id "more unique" than it currently is.

Comment on lines +22 to +24
No stable, cross-instance identity exists for a ``Taxonomy`` or ``Tag`` today. ``Taxonomy.export_id``
and ``Tag.external_id`` are both editable, instance-scoped identifiers designed for import-file
bookkeeping (see :ref:`openedx-tagging-adr-0006`), not for answering "does the target already have

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I guess it's not documented clearly but the goal of export_id is actually to identify taxonomies across different instances, exactly what you are requesting with this ADR. It is meant for answering "does the target already have this taxonomy."

See openedx/modular-learning#183

"As a content author, I want a consistent way to identify taxonomies, especially across instances".

Comment on lines +50 to +59
Add an immutable ``uuid`` field to ``Taxonomy``, generated at creation and preserved through
export/import. ``export_id`` cannot serve this purpose on its own: it is free text, chosen and
editable by whoever administers a taxonomy, so nothing guarantees that the same ``export_id`` on
two different instances refers to the same taxonomy, or that two different taxonomies on two
instances never happen to share one. A ``uuid`` is generated once, never touched by a person, and
so cannot collide or drift the way a human-chosen identifier can. ``export_id`` keeps its existing
role as the human-meaningful identifier; ``uuid`` adds the machine identity it was never designed
to provide. This follows the existing convention in this codebase of using ``uuid`` for a stable
external reference (see ``PublishableEntity.uuid``, :ref:`openedx-content-adr-0003`), applied here
to a model that currently lacks it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think a UUID is what we want.

If I set up the Lightcast Open Skills taxonomy on instance A, and someone else sets up the Lightcast Open Skills taxononomy on instance B, there should be some way to indicate that they're the same, and future exports/imports across the instances will handle that. But if they each get an immutable UUID at the time of original import, then there is no way to achieve that. Whereas with export ID, it's easy, you just make sure they both have the same export ID like io.lightcast.open-skills.

Comment on lines +166 to +169
``Taxonomy``/``Tag`` could gain version history (e.g. via ``django-simple-history``, matching
``CompetencyCriteria``), which would let drift between source and target be tracked precisely
rather than detected only as additive or not. Likely needed eventually, but not required for this
use case, since the additions-only reconciliation policy already satisfies it without history.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please link to #455 which is our tentative plan for making taxonomies versioned.

Comment on lines +174 to +184
Two institutions may independently author what they each consider the same taxonomy on their own
instances, without ever having copied content between each other. Since a ``uuid`` establishes
identity only once two taxonomies have actually shared a copy operation, importing between them
today would create a second, unrelated taxonomy on the receiving side, not recognize them as the
same one. Automatic matching cannot safely resolve this: falling back to matching by name or
content similarity would reintroduce the false-positive risk ``uuid`` was introduced to avoid, two
instances with genuinely different taxonomies that happen to look similar would be silently
merged. The eventual resolution is a deliberate, human-initiated action: an administrator manually
reassigns one instance's taxonomy to adopt the other's ``uuid``, retroactively establishing shared
identity going forward. Not designed here, since it is a distinct, rare operation, orthogonal to
the copy-time behavior this decision covers.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what I was saying above, but it can be done more easily via export_id. It's awkward to compare and edit UUIDs.

Reuse the existing Taxonomy.export_id field for cross-instance
identity instead of adding a new uuid field, per review feedback.
@mgwozdz-unicon

Copy link
Copy Markdown
Contributor Author

Thanks @bradenmacdonald , this makes sense, went with export_id in the latest commit rather than adding a new uuid field.

You're right that export_id already has what's needed here: it's required, unique, and format-validated at the model level, and the REST API already accepts a caller-supplied value on create. Linked modular-learning#183 in the Context section so the intended purpose is documented where the next person will look for it.

Additionally:

  • Added "Add a new immutable uuid field" to Rejected Alternatives, so the reasoning for not going that route is on record.
  • The "Manual merge of independently-created taxonomies" deferred item now notes that today this requires a direct API call: Studio's Taxonomy Editing UI has no field to set or edit export_id.
  • Linked openedx-core#455 in the versioning section per your comment there.

Let me know if I've missed anything.

@ormsbee ormsbee left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @bradenmacdonald's review, and using export_id. It's similar to what we already do for things like courses and libraries, where we rely on meaningful keys.

One thing I want flag is that courses and libraries are implicitly namespaced to an org, which is something that we're not currently doing with taxonomies. We don't really have system vs. org-level libraries or courses. If there is ever a situation in which multiple orgs want to independently tweak or update the same logical taxonomy, we may want to consider some kind of namespacing conventions.

@mgwozdz-unicon

Copy link
Copy Markdown
Contributor Author

One thing I want flag is that courses and libraries are implicitly namespaced to an org, which is something that we're not currently doing with taxonomies. We don't really have system vs. org-level libraries or courses. If there is ever a situation in which multiple orgs want to independently tweak or update the same logical taxonomy, we may want to consider some kind of namespacing conventions.

I added a note about this to the "Excluded from this decision" section to flag it for the future.

@mgwozdz-unicon
mgwozdz-unicon requested a review from ormsbee July 13, 2026 12:48
@mphilbrick211 mphilbrick211 added the FC Relates to an Axim Funded Contribution project label Jul 13, 2026
@mphilbrick211 mphilbrick211 moved this from Needs Triage to Ready for Review in Contributions Jul 13, 2026

@jesperhodge jesperhodge left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some clarifications needed :)

Context
-------

Competency Based Education (CBE) will bring about the use case where, when course content is

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before this ADR uses "competency criteria," can we get one plain sentence defining it? Something like: "A competency criterion asserts that a piece of course content demonstrates a specific competency, which it identifies by pointing at a tag in a taxonomy." Right now CompetencyCriteria/CompetencyCriteriaGroup show up in parentheses on line 17 with zero setup, and this ADR lives in openedx_tagging, which explicitly isn't supposed to know about competencies. A reader coming from the tagging side needs to know why a criterion touches a taxonomy at all before the rest of the Context makes sense.

Comment on lines +17 to +20
it. Competency criteria (``CompetencyCriteria``, ``CompetencyCriteriaGroup``) are versioned via
``django-simple-history`` per :ref:`openedx-learning-adr-0003`, but the taxonomies and tags they
reference are deliberately non-evaluative, unversioned display metadata. Copying a criterion
therefore also means resolving the taxonomy and tags it points to on the target.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
it. Competency criteria (``CompetencyCriteria``, ``CompetencyCriteriaGroup``) are versioned via
``django-simple-history`` per :ref:`openedx-learning-adr-0003`, but the taxonomies and tags they
reference are deliberately non-evaluative, unversioned display metadata. Copying a criterion
therefore also means resolving the taxonomy and tags it points to on the target.
it. Each competency criterion (CompetencyCriteria) identifies the competency it evaluates by referencing a specific Tag in a Taxonomy. Criteria themselves are versioned via django-simple-history (see :ref:openedx-learning-adr-0003), but the taxonomy and tags they reference are deliberately not: they're non-evaluative display metadata that can change independently without creating a new version of the criteria pointing at them. Copying a criterion therefore also means resolving the taxonomy and tags it points to on the target, since the copy has to land somewhere with a matching tag for it to reference.

Copy semantics
~~~~~~~~~~~~~~

Competency criteria are copied **by reference**: the target's criteria are bound to a taxonomy

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this actually work?

  • A CompetencyCriteria is indeed bound to a tag application that is bound to an object and a taxonomy, where the object is an object in e.g. the course that's being copied. Does a course copy copy the taxonomy, and do the tags resolve so that the object tag ids actually apply to the new taxonomy_id that has the same export_id?
  • A CompetencyCriteria is also bound to a CompetencyCriteriaGroup. How is this CompetencyCriteriaGroup copied to the new course or content?
  • Do I understand by reference to mean a reference of the criteria to the export_id of a taxonomy? Or by reference to the competency criteria? In that case I'm confused who references them and how the reference could be resolved if we have a different environment with a different database.
  • A CompetencyCriteriaGroup is optionally bound to a course_id. I assume that is a course run. I assume it actually has to have the course_id to apply to a course. Since a CompetencyCriteria belongs to a CompetencyCriteriaGroup that belongs to a course, wouldn't copying it by reference mean that it does not apply to the new course now?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To clarify my point 1:
An object_tag encodes a course run in the object_id. So if we do a course re-run, for example, the object_tags reference the previous course run, which means that the new course has no tags. When tags are copied to the new course, the copy of the tags somehow needs to be resolved to the new object_ids of the course content, not the same as previously. I assume this is handled via this tags file in course imports - and we will now apply the same logic to re-runs and such - but can you confirm this assumption is true?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if this is handled at all in course re-runs today. (But it should be.) Some testing will be required.

@jesperhodge

Copy link
Copy Markdown
Contributor

Claude flagged this:
"One inconsistency worth flagging for the team: ADR 0002 says course_id FKs to openedx_catalog_courserun, while ADR 0011 frames the near-term copy target as the legacy modulestore course. The two ADRs describe different course-model layers without reconciling them."

Distinguishes CompetencyCriteria/CompetencyCriteriaGroup/ObjectTag recreation
(copied by value, re-keyed to new object/course ids) from Taxonomy/Tag identity
(never duplicated, resolved by reference via export_id). Also defines
competency criterion in plain terms with a reference to ADR 0002, and ties
"course" to CourseRun (openedx_catalog), reconciling with ADR 0002's course_id.
@mgwozdz-unicon

Copy link
Copy Markdown
Contributor Author

@jesperhodge, addressed your comments:

  1. Added a plain-sentence definition of a competency criterion to the Context section, and pointed to ADR 0002 for the full model. This ADR still only owns taxonomy/tag identity, not the competency model itself.
  2. Took your suggested wording for that paragraph, with minor tweaks.
  3. This was a fair question, "by reference" was doing double duty for two different things. Now split apart in Copy semantics:
    • Taxonomy/Tag are never duplicated, for any of the three mechanisms. That's the only thing "by reference" describes now: same-instance mechanisms (new course run, library copy) already share the identical taxonomy row, so there's nothing to resolve; cross-instance (course export/import) resolves the reference via export_id, per the existing Resolution on import section.
    • ObjectTag, CompetencyCriteria, and CompetencyCriteriaGroup are copied by value: duplicated and re-keyed to the new object/course ids, using an old-id-to-new-id mapping built during the copy. A new CompetencyCriteriaGroup shares a parent group with the original (combined by OR by default).
    • So to your bullet 4: yes, a CompetencyCriteriaGroup copied this way does end up with the new course_id, since it's a new row, not the old one repointed.
  4. Confirmed by checking the actual rerun code: ObjectTag copying is not implemented for course reruns today, only for unrelated flows (block duplicate/paste, library-to-course upstream sync). The Context section now says this plainly rather than implying copy_tags() just needs wiring in. Building this is new platform work; agreed it's a scope conversation for the team rather than something to spell out in the ADR.

On the course_id inconsistency you flagged separately: checked both ADRs against the actual CourseRun model. It's not actually two competing identifier systems, CourseRun.course_key (openedx_catalog) is the same modulestore course key ADR 0011 already talks about; the model's docstring says it's meant to be the canonical FK target for exactly this kind of reference. ADR 0011 just never said so. Added a sentence in Context tying "course" explicitly to CourseRun, so it's clear this is the same course-run identity ADR 0002's course_id references, not a different one.

@bradenmacdonald your suspicion on the rerun/ObjectTag question was right, confirmed above.

@bradenmacdonald

Copy link
Copy Markdown
Contributor

@mgwozdz-unicon @jesperhodge Note that there is code to duplicate tags when an XBlock is duplicated but reruns don't involve the XBLOCK_DUPLICATED event.

We probably need to add a similar handler for the COURSE_RERUN_COMPLETED event.

@jesperhodge jesperhodge left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks very good! No reservations from my side, this looks ready.

Feel free to reject all the suggestions! They are completely optional.

As we have been looking at making ADRs relatively concise and skip implementation detail, I've just gone through this and looked for places that could be shortened or where we can skip implementation details as such.

This is not meant as "please improve this", but instead just as inspiration for you on how we can make this ADR more concise, if desired. Shortening technical documents is hard, so I thought I just see what suggestions may be helpful to you.

Comment on lines +68 to +75
Use the existing ``Taxonomy.export_id`` field as the cross-instance identity, rather than adding a
new field. ``export_id`` is already required, unique, and format-validated
(``^[\w\-.]+$``) at the model level, and the REST API already accepts a caller-supplied value on
taxonomy creation. Two institutions that each set up the same third-party taxonomy (for example,
Lightcast Open Skills) can establish that they're the same taxonomy simply by using the same
``export_id`` (for example, a reverse-DNS-style value like ``io.lightcast.open-skills``), something
an immutable, randomly-generated identifier could never let them do, since two independent imports
would always get two different random values with no way to reconcile them afterward.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Use the existing ``Taxonomy.export_id`` field as the cross-instance identity, rather than adding a
new field. ``export_id`` is already required, unique, and format-validated
(``^[\w\-.]+$``) at the model level, and the REST API already accepts a caller-supplied value on
taxonomy creation. Two institutions that each set up the same third-party taxonomy (for example,
Lightcast Open Skills) can establish that they're the same taxonomy simply by using the same
``export_id`` (for example, a reverse-DNS-style value like ``io.lightcast.open-skills``), something
an immutable, randomly-generated identifier could never let them do, since two independent imports
would always get two different random values with no way to reconcile them afterward.
Use the existing ``Taxonomy.export_id`` field as the cross-instance identity across multiple institutions and external systems, rather than adding a
new field.

Comment on lines +81 to +84
``Tag`` does not need a new identifier: ``Tag.external_id`` (already used by the tag import/export
plan-building logic, see :ref:`openedx-tagging-adr-0006`) is sufficient for within-taxonomy
matching. Free-text taxonomies have no ``Tag`` rows and travel as literal strings unconditionally;
no reconciliation applies to them.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
``Tag`` does not need a new identifier: ``Tag.external_id`` (already used by the tag import/export
plan-building logic, see :ref:`openedx-tagging-adr-0006`) is sufficient for within-taxonomy
matching. Free-text taxonomies have no ``Tag`` rows and travel as literal strings unconditionally;
no reconciliation applies to them.
The existing ``Tag.external_id`` is sufficient for within-taxonomy matching.

Comment on lines +77 to +79
``export_id``'s existing mutability (it can be edited after creation) is also a feature here rather
than a gap: it is how the deferred manual-merge case below would actually be performed, by editing
one instance's ``export_id`` to match the other's.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
``export_id``'s existing mutability (it can be edited after creation) is also a feature here rather
than a gap: it is how the deferred manual-merge case below would actually be performed, by editing
one instance's ``export_id`` to match the other's.
``export_id``'s remains mutable and supports the manual-merge case below by editing
one instance's ``export_id`` to match the other's.

Comment on lines +95 to +103
The ``Taxonomy``/``Tag`` rows a recreated ``ObjectTag`` points to are handled differently: they are
never duplicated, only referenced, and it's this taxonomy/tag relationship the rest of this
decision means by **by reference**. For a same-instance mechanism (new course run, library copy),
source and target already share the identical taxonomy row, so no resolution is needed at all. For
a cross-instance mechanism (course export/import), the reference is resolved to whichever taxonomy
on the target shares the source's ``export_id``, per Resolution on import, below. This is a larger
commitment than a by-value taxonomy copy, but a by-value copy would leave the target's competency
evaluation permanently disconnected from the taxonomy it depends on, undermining the goal of this
use case.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The ``Taxonomy``/``Tag`` rows a recreated ``ObjectTag`` points to are handled differently: they are
never duplicated, only referenced, and it's this taxonomy/tag relationship the rest of this
decision means by **by reference**. For a same-instance mechanism (new course run, library copy),
source and target already share the identical taxonomy row, so no resolution is needed at all. For
a cross-instance mechanism (course export/import), the reference is resolved to whichever taxonomy
on the target shares the source's ``export_id``, per Resolution on import, below. This is a larger
commitment than a by-value taxonomy copy, but a by-value copy would leave the target's competency
evaluation permanently disconnected from the taxonomy it depends on, undermining the goal of this
use case.
The ``Taxonomy``/``Tag`` rows a recreated ``ObjectTag`` points to are handled differently: they are
never duplicated, only referenced, and it's this taxonomy/tag relationship the rest of this
decision means by **by reference**.

Since resolution on import is already outlined below, we don't need it here again.

evaluation permanently disconnected from the taxonomy it depends on, undermining the goal of this
use case.

Resolution on import

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Resolution on import
Resolution on course export/import

Comment on lines +108 to +112
This section, and Reconciliation on repeat import, below, apply specifically to course
export/import: it is the only mechanism where a matching taxonomy might not already exist on the
target. New course run and library copy need no taxonomy-side resolution at all, per Copy
semantics, above.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This section, and Reconciliation on repeat import, below, apply specifically to course
export/import: it is the only mechanism where a matching taxonomy might not already exist on the
target. New course run and library copy need no taxonomy-side resolution at all, per Copy
semantics, above.

No need to list everything that is not affected.

target. New course run and library copy need no taxonomy-side resolution at all, per Copy
semantics, above.

On import, whether the source and target are the same deployment or two different organizations'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
On import, whether the source and target are the same deployment or two different organizations'
On course import, whether the source and target are the same deployment or two different organizations'

Comment on lines +121 to +123
A single uniform rule was chosen over branching by deployment relationship because the
reconciliation policy below already guards against silent corruption in both cases; adding a
second behavior for the cross-organization case would add complexity without removing risk.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If necessary, this can explained in the "rejected alternatives" section, or it can just be dropped.

Suggested change
A single uniform rule was chosen over branching by deployment relationship because the
reconciliation policy below already guards against silent corruption in both cases; adding a
second behavior for the cross-organization case would add complexity without removing risk.

Comment on lines +138 to +145
The actor triggering a course copy has no standing to mutate a taxonomy shared with other,
unrelated content on the target instance. In a manual tag re-import (the existing use of this
plan-building logic), the file represents the deliberate intent of whoever owns that taxonomy. A
copied course's snapshot only reflects what the source looked like at export time: a tag missing
from it doesn't mean the source deleted it, it may be something the target added independently.
Auto-applying deletes or renames on that basis risks silently corrupting taxonomy state that
unrelated courses on the target depend on. Additions carry no such risk: they only ever add new
identities, never touch existing ones.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The actor triggering a course copy has no standing to mutate a taxonomy shared with other,
unrelated content on the target instance. In a manual tag re-import (the existing use of this
plan-building logic), the file represents the deliberate intent of whoever owns that taxonomy. A
copied course's snapshot only reflects what the source looked like at export time: a tag missing
from it doesn't mean the source deleted it, it may be something the target added independently.
Auto-applying deletes or renames on that basis risks silently corrupting taxonomy state that
unrelated courses on the target depend on. Additions carry no such risk: they only ever add new
identities, never touch existing ones.

Probably not needed.

Comment on lines +150 to +155
A refusal is modeled as an ordinary import task failure, using the existing
``UserTaskStatus.fail(message)`` / ``Error`` artifact / ``import_status_handler`` mechanism in
``contentstore``. The Studio Authoring MFE's import flow already reads this same ``Message`` field
(``CourseImportContext.tsx``), so this requires no new frontend or backend surface, and no
distinction needs to be drawn between a Platform Administrator and a Course Author watching the
same import: whoever is watching sees the existing failure message.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
A refusal is modeled as an ordinary import task failure, using the existing
``UserTaskStatus.fail(message)`` / ``Error`` artifact / ``import_status_handler`` mechanism in
``contentstore``. The Studio Authoring MFE's import flow already reads this same ``Message`` field
(``CourseImportContext.tsx``), so this requires no new frontend or backend surface, and no
distinction needs to be drawn between a Platform Administrator and a Course Author watching the
same import: whoever is watching sees the existing failure message.
A refusal is modeled as an ordinary import task failure.

We can probably drop the rest as implementation details, especially since those mechanics already exist on edx-platform.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

FC Relates to an Axim Funded Contribution project open-source-contribution PR author is not from Axim or 2U

Projects

Status: Ready for Review

Development

Successfully merging this pull request may close these issues.

6 participants