diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml new file mode 100644 index 000000000..ec7f31c96 --- /dev/null +++ b/.github/workflows/documentation.yml @@ -0,0 +1,26 @@ +name: Docs +on: + push: + branches: [aci.documentation] +permissions: + contents: write +jobs: + docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 + - name: Install dependencies + run: | + pip install sphinx sphinx_rtd_theme + pip install -r requirements/docs.txt + - name: Sphinx build + run: | + sphinx-build docs _build + - name: Deploy + uses: peaceiris/actions-gh-pages@v3 + with: + publish_branch: gh-pages + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: _build/ + force_orphan: true diff --git a/docs/_diagrams/credential_management/course_certificate_awarded.dsl b/docs/_diagrams/credential_management/course_certificate_awarded.dsl new file mode 100644 index 000000000..b61b26f57 --- /dev/null +++ b/docs/_diagrams/credential_management/course_certificate_awarded.dsl @@ -0,0 +1,54 @@ +/* + * This is a high level diagram visualizing how a Course credential is awarded to a learner between the monolith and + * the Credentials IDA. It is written using Structurizr DSL (https://structurizr.org/). + */ +workspace { + model { + learner = person "Learner" "A learner taking courses on an Open edX site" + + group "edx-platform" { + grades_app = softwareSystem "Grades Django App" + certificates_app = softwareSystem "Certificates Django App" + credentials_lms_app = softwareSystem "Credentials (LMS) Django App" + programs_app = softwareSystem "Programs Django App" + celery = softwareSystem "Celery" + monolith_db = softwareSystem "edx-platform DB" + } + + group "Credentials IDA" { + credentials_app = softwareSystem "Credentials Django App" + api_app = softwareSystem "API Django App" + credentials_db = softwareSystem "Credentials DB" + credentials_eb_consumer = softwareSystem "Credentials Event Bus Consumer" + } + + event_bus = softwareSystem "Event Bus" + + credentials_eb_consumer -> event_bus "Polling, listening for Course Certificate events" + + learner -> grades_app "Earns passing grade in course" + grades_app -> certificates_app "Emits a `COURSE_GRADE_NOW_PASSED` signal" + certificates_app -> monolith_db "Award course certificate in LMS" + certificates_app -> event_bus "Publishes a `CERTIFICATE_CREATED` event" + certificates_app -> programs_app "Emits a `COURSE_CERT_CHANGED` signal" + programs_app -> celery "Queues a `award_course_certificate` task" + celery -> credentials_lms_app "Processes `award_course_certificate` task" + credentials_lms_app -> api_app "Makes API request to award a course certificate to learner" + api_app -> credentials_app "Processes API request" + credentials_eb_consumer -> credentials_app "Processes `CERTIFICATE_CREATED` event" + credentials_app -> credentials_db "Award (Course) Credential to learner" + } + + views { + systemlandscape "SystemLandscape" { + include * + autoLayout lr + } + + styles { + element "Person" { + shape Person + } + } + } +} diff --git a/docs/_diagrams/credential_management/course_certificate_revoked.dsl b/docs/_diagrams/credential_management/course_certificate_revoked.dsl new file mode 100644 index 000000000..656bf6495 --- /dev/null +++ b/docs/_diagrams/credential_management/course_certificate_revoked.dsl @@ -0,0 +1,54 @@ +/* + * This is a high level diagram visualizing how a Course credential is revoked from a learner between the monolith and + * the Credentials IDA. It is written using Structurizr DSL (https://structurizr.org/). + */ +workspace { + model { + learner = person "Learner" "A learner taking courses on an Open edX site" + + group "edx-platform" { + grades_app = softwareSystem "Grades Django App" + certificates_app = softwareSystem "Certificates Django App" + credentials_lms_app = softwareSystem "Credentials (LMS) Django App" + programs_app = softwareSystem "Programs Django App" + celery = softwareSystem "Celery" + monolith_db = softwareSystem "edx-platform DB" + } + + group "Credentials IDA" { + credentials_app = softwareSystem "Credentials Django App" + api_app = softwareSystem "API Django App" + credentials_db = softwareSystem "Credentials DB" + credentials_eb_consumer = softwareSystem "Credentials Event Bus Consumer" + } + + event_bus = softwareSystem "Event Bus" + + credentials_eb_consumer -> event_bus "Polling, listening for Course Certificate events" + + learner -> grades_app "Learner no longer course" + grades_app -> certificates_app "Emits a `COURSE_GRADE_NOW_FAILED` signal" + certificates_app -> monolith_db "Revoke course certificate in LMS" + certificates_app -> event_bus "Publishes a `CERTIFICATE_REVOKED` event" + certificates_app -> programs_app "Emits a `COURSE_CERT_CHANGED` signal" + programs_app -> celery "Queues an `award_course_certificate` task (note inaccurate legacy name)" + celery -> credentials_lms_app "Processes the `award_course_certificate` task" + credentials_lms_app -> api_app "Makes API request to revoke a course certificate from learner" + api_app -> credentials_app "Processes API request" + credentials_eb_consumer -> credentials_app "Processes `CERTIFICATE_REVOKED` event" + credentials_app -> credentials_db "Revoke (Course) Credential from learner" + } + + views { + systemlandscape "SystemLandscape" { + include * + autoLayout lr + } + + styles { + element "Person" { + shape Person + } + } + } +} diff --git a/docs/_diagrams/credential_management/program_certificate_awarded.dsl b/docs/_diagrams/credential_management/program_certificate_awarded.dsl new file mode 100644 index 000000000..35cd0ac16 --- /dev/null +++ b/docs/_diagrams/credential_management/program_certificate_awarded.dsl @@ -0,0 +1,46 @@ +/* + * This is a high level diagram visualizing how a Program credential is awarded to a learner between the monolith and + * the Credentials IDA. It is written using Structurizr DSL (https://structurizr.org/). + */ +workspace { + model { + learner = person "Learner" "A learner taking courses on Open edX site" + + group "edx-platform" { + grades_app = softwareSystem "Grades Django App" + certificates_app = softwareSystem "Certificates Django App" + credentials_lms_app = softwareSystem "Credentials (LMS) Django App" + programs_app = softwareSystem "Programs Django App" + celery = softwareSystem "Celery" + } + + group "Credentials IDA" { + credentials_app = softwareSystem "Credentials Django App" + api_app = softwareSystem "API Django App" + } + + event_bus = softwareSystem "Event Bus" + + learner -> grades_app "Earns passing grade in final course of a program" + grades_app -> certificates_app "Emits a `COURSE_GRADE_NOW_PASSED` signal" + certificates_app -> programs_app "Emits a `COURSE_CERT_AWARDED` signal" + programs_app -> celery "Queues an `award_program_certificate` task" + celery -> credentials_lms_app "Processes `award_program_certificate` task" + credentials_lms_app -> api_app "Makes API request to award program certificate to learner" + api_app -> credentials_app "Issues Program Credential to learner" + credentials_app -> event_bus "Emits `PROGRAM_CERTIFICATE_AWARDED` event to the Event Bus" + } + + views { + systemlandscape "SystemLandscape" { + include * + autoLayout lr + } + + styles { + element "Person" { + shape Person + } + } + } +} diff --git a/docs/_diagrams/credential_management/program_certificate_revoked.dsl b/docs/_diagrams/credential_management/program_certificate_revoked.dsl new file mode 100644 index 000000000..8ee348211 --- /dev/null +++ b/docs/_diagrams/credential_management/program_certificate_revoked.dsl @@ -0,0 +1,46 @@ +/* + * This is a high level diagram visualizing how a Program credential is revoked from a learner between the monolith and + * the Credentials IDA. It is written using Structurizr DSL (https://structurizr.org/). + */ +workspace { + model { + learner = person "Learner" "A learner taking courses on Open edX site" + + group "edx-platform" { + grades_app = softwareSystem "Grades Django App" + certificates_app = softwareSystem "Certificates Django App" + credentials_lms_app = softwareSystem "Credentials (LMS) Django App" + programs_app = softwareSystem "Programs Django App" + celery = softwareSystem "Celery" + } + + group "Credentials IDA" { + credentials_app = softwareSystem "Credentials Django App" + api_app = softwareSystem "API Django App" + } + + event_bus = softwareSystem "Event Bus" + + learner -> grades_app "Learner no longer passing course in a Program" + grades_app -> certificates_app "Emits a `COURSE_GRADE_NOW_FAILED` signal" + certificates_app -> programs_app "Emits a `COURSE_CERT_REVOKED` signal" + programs_app -> celery "Queues a `revoke_program_certificate` task" + celery -> credentials_lms_app "Processes `revoke_program_certificates` task" + credentials_lms_app -> api_app "Makes API request to revoke program certificate from learner" + api_app -> credentials_app "Revokes Program Credential from learner" + credentials_app -> event_bus "Emits `PROGRAM_CERTIFICATE_REVOKED` event to the Event Bus" + } + + views { + systemlandscape "SystemLandscape" { + include * + autoLayout lr + } + + styles { + element "Person" { + shape Person + } + } + } +} diff --git a/docs/_diagrams/learner_record_mfe/learner_record_mfe.dsl b/docs/_diagrams/learner_record_mfe/learner_record_mfe.dsl new file mode 100644 index 000000000..cd8fbce74 --- /dev/null +++ b/docs/_diagrams/learner_record_mfe/learner_record_mfe.dsl @@ -0,0 +1,43 @@ +/* + * This is a high level diagram visualizing how a learner can access their program records and how data is retreived. + * It is written using Structurizr DSL (https://structurizr.org/). + */ +workspace { + model { + learner = person "Learner" "Registered learner on Open edX site" + + group "edx-platform LMS" { + program_dashboard = softwareSystem "Program Dashboard (Legacy FE)" + } + + group "Credentials IDA" { + records_app = softwareSystem "Records Django App" + } + + profile_mfe = softwareSystem "(User) Profile MFE" + lr_mfe = softwareSystem "Learner Record MFE" + + learner -> program_dashboard "views their Program Dashboard" + learner -> profile_mfe "views their user Profile" + + program_dashboard -> records_app "clicks `View Program Record` button" + profile_mfe -> records_app "clicks `View my Records` button" + + records_app -> lr_mfe "Learner redirected to" + lr_mfe -> records_app "REST API call to" + lr_mfe -> learner "Renders program record info for" + } + + views { + systemlandscape "SystemLandscape" { + include * + autoLayout lr + } + + styles { + element "Person" { + shape Person + } + } + } +} diff --git a/docs/_diagrams/learner_record_mfe/learner_record_mfe_program_records.dsl b/docs/_diagrams/learner_record_mfe/learner_record_mfe_program_records.dsl new file mode 100644 index 000000000..d4533249c --- /dev/null +++ b/docs/_diagrams/learner_record_mfe/learner_record_mfe_program_records.dsl @@ -0,0 +1,40 @@ +/* + * This is a high level diagram visualizing how the system retrieves information about a learner's progress in a + * specific program. It is written using Structurizr DSL (https://structurizr.org/). + */ +workspace { + model { + learner = person "Learner" "Registered learner on Open edX site" + + group "Credentials IDA" { + catalog_app = softwareSystem "Catalog Django App" + core_app = softwareSystem "Core Django App" + credentials_app = softwareSystem "Credentials Django App" + records_app = softwareSystem "Records Django App" + } + + lr_mfe = softwareSystem "Learner Record MFE" + + learner -> lr_mfe "clicks `View Program Record` button" + lr_mfe -> records_app "REST API to retrieve program progress data" + records_app -> core_app "retrieves user info" + records_app -> catalog_app "retrieves pathway info" + records_app -> credentials_app "retrieves credential info" + records_app -> records_app "retrieves grade and sharing info" + records_app -> lr_mfe "returns program record info" + lr_mfe -> learner "renders program record for" + } + + views { + systemlandscape "SystemLandscape" { + include * + autoLayout lr + } + + styles { + element "Person" { + shape Person + } + } + } +} diff --git a/docs/_diagrams/program_completion_emails/program_completion_email.dsl b/docs/_diagrams/program_completion_emails/program_completion_email.dsl new file mode 100644 index 000000000..cae1ecdf4 --- /dev/null +++ b/docs/_diagrams/program_completion_emails/program_completion_email.dsl @@ -0,0 +1,38 @@ +/* + * This is a high level diagram visualizing when the Credentials IDA emits a "program completion email". It is written + * using Structurizr DSL (https://structurizr.org/). + */ +workspace { + model { + learner = person "Learner" "A learner taking courses on Open edX site" + + lms = softwareSystem "edx-platform LMS" + + group "Credentials IDA" { + credentials_app = softwareSystem "Credentials Django App" + api_app = softwareSystem "API Django App" + edx_ace = softwareSystem "edX ACE App" + } + + learner -> lms "Earns passing grade in final course of a program" + lms -> api_app "Makes API request to award program certificate to learner" + api_app -> credentials_app "Issues Program Credential to learner" + credentials_app -> credentials_app "Determine if email should be sent based on Program completion" + credentials_app -> edx_ace "Personalizes email based on message template and config" + edx_ace -> learner "Sends congratulatory message to learner" + + } + + views { + systemlandscape "SystemLandscape" { + include * + autoLayout lr + } + + styles { + element "Person" { + shape Person + } + } + } +} diff --git a/docs/_static/images/badges/badges-admin-penalty-rules.png b/docs/_static/images/badges/badges-admin-penalty-rules.png new file mode 100644 index 000000000..1b726a9bb Binary files /dev/null and b/docs/_static/images/badges/badges-admin-penalty-rules.png differ diff --git a/docs/_static/images/course_certificate_awarded.png b/docs/_static/images/course_certificate_awarded.png new file mode 100644 index 000000000..85db02495 Binary files /dev/null and b/docs/_static/images/course_certificate_awarded.png differ diff --git a/docs/_static/images/course_certificate_revoked.png b/docs/_static/images/course_certificate_revoked.png new file mode 100644 index 000000000..c5d3d9122 Binary files /dev/null and b/docs/_static/images/course_certificate_revoked.png differ diff --git a/docs/_static/images/learner_record_mfe_create_program_record_link.png b/docs/_static/images/learner_record_mfe_create_program_record_link.png new file mode 100644 index 000000000..3a8b55aec Binary files /dev/null and b/docs/_static/images/learner_record_mfe_create_program_record_link.png differ diff --git a/docs/_static/images/learner_record_mfe_diagram.png b/docs/_static/images/learner_record_mfe_diagram.png new file mode 100644 index 000000000..7aceca42a Binary files /dev/null and b/docs/_static/images/learner_record_mfe_diagram.png differ diff --git a/docs/_static/images/learner_record_mfe_download_program_record.png b/docs/_static/images/learner_record_mfe_download_program_record.png new file mode 100644 index 000000000..067991c55 Binary files /dev/null and b/docs/_static/images/learner_record_mfe_download_program_record.png differ diff --git a/docs/_static/images/learner_record_mfe_program_record_diagram.png b/docs/_static/images/learner_record_mfe_program_record_diagram.png new file mode 100644 index 000000000..5f82f4c4f Binary files /dev/null and b/docs/_static/images/learner_record_mfe_program_record_diagram.png differ diff --git a/docs/_static/images/learner_record_mfe_share_program_record.png b/docs/_static/images/learner_record_mfe_share_program_record.png new file mode 100644 index 000000000..2e341f204 Binary files /dev/null and b/docs/_static/images/learner_record_mfe_share_program_record.png differ diff --git a/docs/_static/images/program_certificate_awarded.png b/docs/_static/images/program_certificate_awarded.png new file mode 100644 index 000000000..51549ae38 Binary files /dev/null and b/docs/_static/images/program_certificate_awarded.png differ diff --git a/docs/_static/images/program_certificate_revoked.png b/docs/_static/images/program_certificate_revoked.png new file mode 100644 index 000000000..3769e871e Binary files /dev/null and b/docs/_static/images/program_certificate_revoked.png differ diff --git a/docs/_static/images/program_completion_email.png b/docs/_static/images/program_completion_email.png new file mode 100644 index 000000000..41ef54091 Binary files /dev/null and b/docs/_static/images/program_completion_email.png differ diff --git a/docs/_static/images/screenshot_program_completion_email_django_admin.png b/docs/_static/images/screenshot_program_completion_email_django_admin.png new file mode 100644 index 000000000..9c08a9cff Binary files /dev/null and b/docs/_static/images/screenshot_program_completion_email_django_admin.png differ diff --git a/docs/_static/images/verifiable_credentials-admin-section.png b/docs/_static/images/verifiable_credentials-admin-section.png new file mode 100644 index 000000000..851101b2f Binary files /dev/null and b/docs/_static/images/verifiable_credentials-admin-section.png differ diff --git a/docs/_static/images/verifiable_credentials-issuance-lines.png b/docs/_static/images/verifiable_credentials-issuance-lines.png new file mode 100644 index 000000000..6b71c0b70 Binary files /dev/null and b/docs/_static/images/verifiable_credentials-issuance-lines.png differ diff --git a/docs/_static/images/verifiable_credentials-issuance-sequence.png b/docs/_static/images/verifiable_credentials-issuance-sequence.png new file mode 100644 index 000000000..85c15a022 Binary files /dev/null and b/docs/_static/images/verifiable_credentials-issuance-sequence.png differ diff --git a/docs/_static/images/verifiable_credentials-issuer-configuration.png b/docs/_static/images/verifiable_credentials-issuer-configuration.png new file mode 100644 index 000000000..1bb85f68d Binary files /dev/null and b/docs/_static/images/verifiable_credentials-issuer-configuration.png differ diff --git a/docs/_static/images/verifiable_credentials-lcw-accept-credential.png b/docs/_static/images/verifiable_credentials-lcw-accept-credential.png new file mode 100644 index 000000000..68bfcffaf Binary files /dev/null and b/docs/_static/images/verifiable_credentials-lcw-accept-credential.png differ diff --git a/docs/_static/images/verifiable_credentials-lcw-add-credential.png b/docs/_static/images/verifiable_credentials-lcw-add-credential.png new file mode 100644 index 000000000..81a8c6a2e Binary files /dev/null and b/docs/_static/images/verifiable_credentials-lcw-add-credential.png differ diff --git a/docs/_static/images/verifiable_credentials-lcw-credential-preview.png b/docs/_static/images/verifiable_credentials-lcw-credential-preview.png new file mode 100644 index 000000000..0cdfe78c5 Binary files /dev/null and b/docs/_static/images/verifiable_credentials-lcw-credential-preview.png differ diff --git a/docs/_static/images/verifiable_credentials-lcw-home-empty.png b/docs/_static/images/verifiable_credentials-lcw-home-empty.png new file mode 100644 index 000000000..5853eb78f Binary files /dev/null and b/docs/_static/images/verifiable_credentials-lcw-home-empty.png differ diff --git a/docs/_static/images/verifiable_credentials-lcw-qrcode-scanner.png b/docs/_static/images/verifiable_credentials-lcw-qrcode-scanner.png new file mode 100644 index 000000000..0f2816c82 Binary files /dev/null and b/docs/_static/images/verifiable_credentials-lcw-qrcode-scanner.png differ diff --git a/docs/_static/images/verifiable_credentials-lcw-setup1.png b/docs/_static/images/verifiable_credentials-lcw-setup1.png new file mode 100644 index 000000000..3834369f2 Binary files /dev/null and b/docs/_static/images/verifiable_credentials-lcw-setup1.png differ diff --git a/docs/_static/images/verifiable_credentials-lcw-setup2.png b/docs/_static/images/verifiable_credentials-lcw-setup2.png new file mode 100644 index 000000000..0ef243a3f Binary files /dev/null and b/docs/_static/images/verifiable_credentials-lcw-setup2.png differ diff --git a/docs/_static/images/verifiable_credentials-lcw-setup3.png b/docs/_static/images/verifiable_credentials-lcw-setup3.png new file mode 100644 index 000000000..ded3a9ce1 Binary files /dev/null and b/docs/_static/images/verifiable_credentials-lcw-setup3.png differ diff --git a/docs/_static/images/verifiable_credentials-lcw-share-public-link-created.png b/docs/_static/images/verifiable_credentials-lcw-share-public-link-created.png new file mode 100644 index 000000000..4fd5f3406 Binary files /dev/null and b/docs/_static/images/verifiable_credentials-lcw-share-public-link-created.png differ diff --git a/docs/_static/images/verifiable_credentials-lcw-share-public-link.png b/docs/_static/images/verifiable_credentials-lcw-share-public-link.png new file mode 100644 index 000000000..91ada1e2f Binary files /dev/null and b/docs/_static/images/verifiable_credentials-lcw-share-public-link.png differ diff --git a/docs/_static/images/verifiable_credentials-lcw-share.png b/docs/_static/images/verifiable_credentials-lcw-share.png new file mode 100644 index 000000000..79d416133 Binary files /dev/null and b/docs/_static/images/verifiable_credentials-lcw-share.png differ diff --git a/docs/_static/images/verifiable_credentials-lcw-verification-status.png b/docs/_static/images/verifiable_credentials-lcw-verification-status.png new file mode 100644 index 000000000..27120a2b1 Binary files /dev/null and b/docs/_static/images/verifiable_credentials-lcw-verification-status.png differ diff --git a/docs/_static/images/verifiable_credentials-learner-record-mfe.png b/docs/_static/images/verifiable_credentials-learner-record-mfe.png new file mode 100644 index 000000000..4d67c578c Binary files /dev/null and b/docs/_static/images/verifiable_credentials-learner-record-mfe.png differ diff --git a/docs/analytics.rst b/docs/analytics.rst index e31716dc4..e999a52f6 100644 --- a/docs/analytics.rst +++ b/docs/analytics.rst @@ -1,7 +1,7 @@ Analytics ========= -The credentials IDA uses Segment.io to track events. If you set the ``segment_key`` variable in your site_configuration, a variety of events (segment API calls) will be triggered when navigating through the UI. +The Credentials IDA uses Segment.io to track events. If you set the ``segment_key`` variable in your site_configuration, a variety of events (segment API calls) will be triggered when navigating through the UI. Analytics for legacy/template pages =================================== @@ -22,7 +22,7 @@ For example (from ``templates/_actions.html``): {% trans 'Share this certificate via Facebook' as tmsg %}{{ tmsg | htmlescape }} - + Analytics for react pages ========================= diff --git a/docs/badges/_details.rst b/docs/badges/_details.rst new file mode 100644 index 000000000..7fb703d96 --- /dev/null +++ b/docs/badges/_details.rst @@ -0,0 +1,154 @@ +Implementation Details +====================== + +Badges feature is implemented as a separate application within the Credentials Open edX service: + +.. code-block:: + + credentials/apps/badges/ + +Events (Event Bus) +------------------ + + Badges feature always relies on events (public signals) with user data. + +New events +~~~~~~~~~~ + +Badges feature extends the set of already `published events`_ with its own set of new public events: + +- `BADGE_AWARDED` (Credentials) +- `BADGE_REVOKED` (Credentials) + +In addition to already present `public events`_ Badges also relies on (but event types set may be extended): + +- `COURSE_GRADE_NOW_PASSED` (LMS) +- `COURSE_GRADE_NOW_FAILED` (LMS) + + +Data models +----------- + +Badges application maintains a set of data models. + +BadgeTemplate +~~~~~~~~~~~~~ + + + +Requirement +~~~~~~~~~~~ + +**Requirement** describes an association between a BadgeTemplate and an Event. + +It carries *Rules*: **which** event, **how** and **when** must occur. +Badge can have multiple Requirements. + +.. code-block:: python + + Requirement: + """ + Defines a single rule for a badge type. + """ + - BadgeTemplate (relation) + - event_type (event identifier) + + - times default=1 (allows repetitive events) + - start optional (allows time range events) + - end optional (allows time range events) + - rule_set: default=1 (allows requirements combination) + +Fulfillment +~~~~~~~~~~~ + +**Fulfillment** record is associated with a Learner. It tracks a single Requirement fulfillment for given learner. + +.. code-block:: python + + Fulfillment: + """ + Tracks rule fulfillment for user. + """ + - Requirement (relation) + - username: + - times: + - completed + +UserCredential +~~~~~~~~~~~~~~ + +Earned badges are `UserCredential` records with a generic relation to the `BadgeTemplate`. + +Badges extend currently present: + - program certificates + - course certificates + +.. code-block:: python + + UserCredential: + """ + Earned badge. + """ + ... + - uuid + - username: + - status: "awarded" | "revoked" + ... + + +Badge Processor +--------------- + +**BadgeProcessor** (BP) is an entity which is responsible for incoming public events processing. + +- `BadgeProcessor` class is inherited from the `BaseProcessor` which provides expected interface. +- `BadgeProcessor` is auto-registered as a receiver for all configured event types. + +Event processing pipeline +~~~~~~~~~~~~~~~~~~~~~~~~~ + +For received Event: + +- active badge templates set identification; +- relevant requirements identification; +- requirements restrictions checks (e.g. time range, not yet implemented); +- requirements effect application - corresponding fulfillments update for the given user; + + `Badge Processor` doesn't bother about user's badging progress, since it is the main responsibility of the `Badge Collector`. + +.. note:: + `Distribution backends`_ should be able to override processing implementation. + +Badge Collector +--------------- + +**BadgeCollector** (BC) is an entity which is responsible for users badging progress tracking, as well as for awarding of already completed badges. + +- `BadgeCollector` class is inherited from the `BaseCollector` which provides expected interface. +- `BadgeCollector` is registered as a receiver for Fulfillment records. + +Badge Collector is subscribed for `Fulfillment` records updates. + +Badge collecting pipeline +~~~~~~~~~~~~~~~~~~~~~~~~~ + +For updated requirement Fulfillment: + +- `award` effect + - single requirement fulfillment evaluation (completion flag is set) + - related requirements fulfillment evaluation (completion flag is set) + - badge completion evaluation + - completed badge awarding (UserCredential is created) +- `revoke` effect + - single requirement fulfillment revocation (completion flag is reset) + - completed badge revocation (UserCredential status="revoked") + +Feature sequence diagrams +------------------------- + +See `Credly backend examples`_. + +.. _published events: /event_bus.html#events-published +.. _public events: /event_bus.html#events-consumed +.. _Distribution backends: distribution.html +.. _Credly backend examples: distribution.html#more-details \ No newline at end of file diff --git a/docs/badges/_distribution.rst b/docs/badges/_distribution.rst new file mode 100644 index 000000000..62c245ecd --- /dev/null +++ b/docs/badges/_distribution.rst @@ -0,0 +1,346 @@ +Distribution +============ + + Credentials Badges feature is self-contained, but it allows badges *distribution* (propagation) to external services as well. + +**Badge distribution backends** are Credentials plugins (auto-discovered installable applications) which highly rely on internal `badges` application, but extend its functions. + +Badges backend may be responsible for: + +- communication between external service and Open edX (Credentials); +- implementation of service-specific badge templates (credential types); +- earned (issued) learners' badges propagation to corresponding services' user profiles; +- additional side effects (e.g. users notification); +- etc. + +.. note:: + There is `Credly (by Pearson)`_ built-in backend which may serve as an integration example. + +---- + +Credly backend +-------------- + +- `Overview`_ +- `Configuration`_ +- `Badge templates management`_ +- `Requirements setup`_ +- `Awarded badges`_ +- `Side effects`_ +- `More details`_ + +Overview +~~~~~~~~ + +Credly badges distribution backend is implemented as a baked-in plugin (it is prepared to be extracted into a separate repo). + +.. code-block:: + + # package location: + credentials/apps/badges/distribution/credly/ + +This application extends the core badges functions in the following ways: + +- another section appears in the Credentials admin interface; +- new badge template type is available for configuration; +- new specific user credential type is produced; +- Credly's API integration configuration is available (per Credly Organization); +- a set of automations is provided: + - badge templates are pulled for each Credly Organization; +- additional actions happen during badges progress collecting: + - TBD + +.. image:: ../_static/images/badges/badges-admin-credly-badges.png + :alt: Credly Badges plugin + + +Configuration +~~~~~~~~~~~~~ + +Credly badges extension allows `Credly web service API`_ authorization configuration. + +.. note:: + + Backend is configured to use (configurable from deployment environment) these settings: + + .. code-block:: python + + # production: + CREDLY_API_BASE_URL = "https://api.credly.com/v1/" + + # sandbox: + CREDLY_API_BASE_URL = "https://sandbox-api.credly.com/v1/" + + +Organizations +############# + + Credly service has a concept of `Organizations` (Credly Organization). Integration happens in a context of one or more Credly Organizations to a single Open edX installation. + +Credly Badges application allows Credly Organizations management via admin interface: + +.. image:: ../_static/images/badges/badges-admin-credly-organization.png + :alt: Credly Organization + +``CredlyOrganization`` record represents API credentials (ID and API key) for a specific Credly Organization. + +On each Credly Organization record's update plugin validates provided information by trying to fetch corresponding Credly organization details. Additional information is auto-filled on success. + + +Badge templates management +~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Credly badge templates are linked to their organization. + +The backend provides its own badge templates type (``origin = credly``): + +.. code-block:: + + CredlyBadgeTemplate(BadgeTemplate): + """ + Extended version of the core BadgeTemplate data model implementation. + + In addition to standard field set also includes extra attributes from Credly badge template. + """ + - - - core properties - - - + + - uuid + - name: + - description: + - icon: + + - - - specific properties - - - + + - organization: + - state: "draft" | "active" | "archived" (managed by Credly) + - origin: "credly" + +Under the hood ``CredlyBadgeTemplate`` data is split onto 2 data tables: + +- core `BadgeTemplate` attributes are placed into a separate table, so badge templates with ``credly`` type are completely valid from perspective of the main badge application; +- extra `CredlyBadgeTemplate` attributes are kept in a separate table and linked 1-1 to the core data (Django model inheritance); + +Badge templates creation +######################## + +It is expected that Credly badge templates are pulled for each configured Credly Organization (e.g. auto-created). + +To mirror all existing Credly badge templates, navigate ``Credly Organizations`` list view, then select wanted organizations in a list and use ``Sync organization badge templates`` action. + + There is ``sync_organization_badge_templates`` management command as well. + +.. image:: ../_static/images/badges/badges-admin-credly-templates-sync.png + :alt: Credly badge templates synchronization + +The action will iterate through selected Credly organizations and: + +1. Pull available for Organization badge templates from `Credly API`_: + +.. code-block:: + + GET /organizations//badge_templates + +2. Create ``CredlyBadgeTemplate`` records for each available template. + +Keeping badge templates in sync +############################### + +Credly service provides `webhooks support`_ for different internal events. + +This Credly Badges backend implements a webhook endpoint to listen to incoming updates for badge templates. + +.. code-block:: + + POST /credly-badges/api/webhook/ + +To communicate an additional configuration is required on the Credly side (here is the Sandbox configuration example): + +1. Set a full URL for your Credentials installation. +2. Activate badge template events. + +.. image:: ../_static/images/badges/badges-admin-credly-badges-webhook.png + :alt: Webhook configuration + +The following Credly badge templates webhook events are processed: + +- ``badge_template.created`` (event is triggered whenever a badge template is created) + - system creates new ``CredlyBadgeTemplate`` in inactive state; + - badge template is not processed until manual activation; +- ``badge_template.changed`` (event is triggered whenever a badge template is edited) + - system updates corresponding ``CredlyBadgeTemplate`` relevant attributes; + - badge template processing continues; +- ``badge_template.deleted`` (event is triggered whenever a badge template is deleted) + - system deactivate corresponding ``CredlyBadgeTemplate``; + - badges issuance processing stops; + +Requirements setup +~~~~~~~~~~~~~~~~~~ + +TBD + +Created badges `must be configured`_. + +Desired Requirements are created for each badge template manually: + +- create a Requirement for a single course with specific ID for completion event. +- create a Requirement for a single course with specific ID for revocation event (reverse effect). + +CCX courses +########### + +TBD + + Both event types (for passing course grade and failing course grade) carry additional information for custom courses identification. + +Awarded badges +~~~~~~~~~~~~~~ + +Already awarded badges are stored as `UserCredential`_ records. + +Credly backend manages its own extended version of user credential: + +.. code-block:: + + CredlyBadge(UserCredential): + """ + Earned badge. + """ + - - - unified attrs - - - + ... + - uuid + - username: + - status: "awarded" | "revoked" + ... + + - - - specific attrs - - - + + - issued_badge_id: + - issued_at: + - accept_badge_url: + + +Side effects +~~~~~~~~~~~~ + +`Badge Collector`_ emits signals when: + +- a badge is `awarded`_ +- a badge is `revoked`_ + +There are events which may be used as triggers for distribution **side effects**: + +- on award: + - credentials.apps.badges.distribution.credly.handlers.notify_user_awarding + - credentials.apps.badges.distribution.credly.handlers.issue_badge +- on revoke: + - credentials.apps.badges.distribution.credly.handlers.notify_user_revocation + - credentials.apps.badges.distribution.credly.handlers.revoke_badge + +Badge issuance +############## + +Badge issuance side effect is performed via `issue a badge Credly API`_ endpoint. +Required fields: + +.. code-block:: + + recipient_email: + issued_to_first_name: + issued_to_last_name: + badge_template_id: + issued_at: + +Badge revocation +################ + +Badge revocation side effect is performed via `revoke a badge Credly API`_ endpoint. +Required data: ``badge_id`` + +.. code-block:: + + PUT /organizations//badges//revoke + { + "reason": "Check bounced", + "suppress_revoke_notification_email": false + } + +More details +~~~~~~~~~~~~ + +Here are some details which should clarify how the feature works. + +Credly badges initial setup +########################### + +Initial setup (1-4) + As a general prerequisite in order to integrate with Credly we must have Credly account (here represented with a single Organization). + API interaction requires authorization credentials for the Open edX installation. + +Open edX configuration (5-6) + Open edX installation (Credly API client) setup. + Includes creation of a configuration record which must allow authorized interactions with Credly's API. + +Badge templates management (7-10) + Once API is available, Open edX badges can be bulk-created based on Credly Organization badge templates. + Credly Badges backend caches extra data from templates. + +Requirements setup (11-13) + Each created Open edX badge can be quickly configured for a pre-defined rules. + Additionally each requirement must be specified to make award/revoke rules more specific. + +.. image:: ../_static/images/badges/badges-setup-sequence.png + :alt: Credly Badges setup sequence diagram + + +Badge awarding flow +################### + +Grade update (1-2) + Learner acts for course grade update. + Learner's grade satisfies course's grading policy. + +Event propagation (3-4) + Course "completion" event is emitted from LMS to Event Bus. + Course "completion" event is consumed on the Credentials side. + +Badges Processor + Processor receives event. + All relevant Requirement records are analyzed for Event. + Corresponding Fulfillment records are updated for User. + +Badges Collector(s) + Collector analyzes Fulfillments completion. + If ready badge is awarded (user credential record is created). + Badge awarding event is emitted from Credentials to Event Bus. + Credly API request for badge issuance is sent. + Other side effects are possible (e.g. user notification). + +.. image:: ../_static/images/badges/badges-award-sequence.png + :alt: Credly Badges awarding sequence diagram + +Badge revocation flow +##################### + +Revocation flow mirrors awarding flow. + +.. image:: ../_static/images/badges/badges-revoke-sequence.png + :alt: Credly Badges revocation sequence diagram + +.. _Credly (by Pearson): https://info.credly.com/ +.. _Credly API : https://www.credly.com/docs/badge_templates +.. _must be configured : configuration.html#requirements-setup +.. _UserCredential : details.html#usercredential +.. _Badge Collector : details.html#badge-collector +.. _awarded : collecting.html#badge-awarding +.. _revoked : collecting.html#badge-revocation +.. _issue a badge Credly API : https://www.credly.com/docs/issued_badges#issue-a-badge +.. _revoke a badge Credly API : https://www.credly.com/docs/issued_badges#revoke-a-badge +.. _Overview: distribution.html#overview +.. _Configuration: distribution.html#configuration +.. _Badge templates management: distribution.html#badge-templates-management +.. _Requirements setup: distribution.html#requirements-setup +.. _Awarded badges: distribution.html#awarded-badges +.. _Side effects: distribution.html#side-effects +.. _More details: distribution.html#more-details +.. _Credly web service API: https://www.credly.com/docs/web_service_api +.. _webhooks support: https://credly.com/docs/webhooks \ No newline at end of file diff --git a/docs/badges/_puml/badge-awarding-flow-sequence.puml b/docs/badges/_puml/badge-awarding-flow-sequence.puml new file mode 100644 index 000000000..02b704e57 --- /dev/null +++ b/docs/badges/_puml/badge-awarding-flow-sequence.puml @@ -0,0 +1,63 @@ +@startuml name "Credly Badges award flow" + +!pragma teoz true +autonumber + +title "Credly badges award effect (sequence diagram)" + +box "Open edX" + actor "Open edX\n Learner" as learner + box "Platform IDA" #LightBlue + participant "LMS" as lms + end box + participant "EventBus" as ebus + box "Credentials IDA" #LightBlue + participant "Badges app" as badges + participant "Credly Badges app" as backend + end box +end box +box "External badging services" + box "Credly by Pearson" #LightSeaGreen + participant "Credly" as credly + end box + participant "Other" as other +end box + + +learner -> lms : Enters LMS course +learner -> lms : Performs graded action\n (e.g. submits answer) + +lms -> ebus : Emits\n**COURSE_GRADE_NOW_PASSED** +ebus <- badges : Receives\n**COURSE_GRADE_NOW_PASSED** + +rnote over badges,backend + **BadgeProcessor handles event** + - analyses Requirements + - updates Fulfillment(s) +endrnote + +rnote over badges + **BadgeCollector handles event** + - analyses Fulfillment(s) + - awards Badge(s) + - emits awarding event +endrnote + +ebus <- badges : Emits\n**BADGE_AWARDED** +lms -> ebus : Receives\n**BADGE_AWARDED** + +rnote over backend + **CredlyBadgeCollector** + **handles event** + - analyses Fulfillment(s) + - awards CredlyBadge(s) + - emits awarding event +endrnote + +ebus <- backend : Emits\n**BADGE_AWARDED** +lms -> ebus : Receives\n**BADGE_AWARDED** + +backend -> credly : Issues user badge\n(API issuance request) +backend -> learner : Optionally, notifies a Learner. + +@enduml \ No newline at end of file diff --git a/docs/badges/_puml/badge-revocation-flow-sequence.puml b/docs/badges/_puml/badge-revocation-flow-sequence.puml new file mode 100644 index 000000000..6fa17a24a --- /dev/null +++ b/docs/badges/_puml/badge-revocation-flow-sequence.puml @@ -0,0 +1,63 @@ +@startuml name "Credly Badges revoke flow" + +!pragma teoz true +autonumber + +title "Credly badges revoke effect (sequence diagram)" + +box "Open edX" + actor "Open edX\n Learner" as learner + box "Platform IDA" #LightBlue + participant "LMS" as lms + end box + participant "EventBus" as ebus + box "Credentials IDA" #LightBlue + participant "Badges app" as badges + participant "Credly Badges app" as backend + end box +end box +box "External badging services" + box "Credly by Pearson" #LightSeaGreen + participant "Credly" as credly + end box + participant "Other" as other +end box + + +learner -> lms : Enters LMS course +learner -> lms : Performs graded action\n (e.g. submits answer) + +lms -> ebus : Emits\n**COURSE_GRADE_NOW_FAILED** +ebus <- badges : Receives\n**COURSE_GRADE_NOW_FAILED** + +rnote over badges,backend + **BadgeProcessor handles event** + - analyses Requirements + - updates Fulfillment(s) +endrnote + +rnote over badges + **BadgeCollector handles event** + - analyses Fulfillment(s) + - revokes Badge(s) + - emits revocation event +endrnote + +ebus <- badges : Emits\n**BADGE_REVOKED** +lms -> ebus : Receives\n**BADGE_REVOKED** + +rnote over backend + **CredlyBadgeCollector** + handles event: + - analyses Fulfillment(s) + - revokes Badge(s) + - emits revocation event +endrnote + +ebus <- backend : Emits\n**BADGE_REVOKED** +lms -> ebus : Receives\n**BADGE_REVOKED** + +backend -> credly : Revokes issued user badge\n(API revocation request) +backend -> learner : Optionally, notifies a Learner. + +@enduml \ No newline at end of file diff --git a/docs/badges/_puml/credly-setup-sequence.puml b/docs/badges/_puml/credly-setup-sequence.puml new file mode 100644 index 000000000..fc79af5f5 --- /dev/null +++ b/docs/badges/_puml/credly-setup-sequence.puml @@ -0,0 +1,78 @@ +@startuml name "Credly Badges setup" + +!pragma teoz true +autonumber + +title "Credly badges intial configuration (sequence diagram)" + +box "Open edX" + actor "Open edX\n Admin" as oex_admin + box "Platform IDA" #LightBlue + participant "LMS" as lms + end box + participant "EventBus" as ebus + box "Credentials IDA" #LightBlue + participant "Badges app" as badges + participant "Credly Badges app" as backend + end box +end box +box "External badging services" + box "Credly by Pearson" #LightSeaGreen + participant "Credly" as credly + actor "Credly\n Admin" as credly_admin + end box + participant "Other" as other +end box + + +== Inital setup == + +credly_admin -> credly : Configures API Client credentials\n for Open edX installation + +credly_admin -> credly : Creates Organization +credly_admin -> credly : Creates a badge template "A" +credly_admin -> credly : Creates a badge template "B" + + +== Open edX Configuration == + +oex_admin -> backend : Enters Credentials admin\n (Credly Badges app) +oex_admin -> backend : Creates Organization configuration\n (Credly client API connection) + + +== Badge templates management == + +oex_admin -> backend : Performs list action "Sync badge templates" +backend -> credly : Requests available badge templates\n (Credly organization) +backend <-- credly : Returns available (Org) badge templates + +rnote over badges,backend + - CredlyBadgeTemplate(A) is created + - CredlyBadgeTemplate(B) is created +endrnote + +backend <-[#red]-> credly : Uses webhook to keep\n badge templates in sync? + + +== Requirements setup == + +oex_admin -> backend : Configures each template with forward and reverse effects. + +rnote over badges,backend + - Award effect Requirements are created + - Revoke effect Requirements are created +endrnote + +hnote over badges,backend #LightGreen + At this moment all CredlyBadges + are configured to be given/revoked + for "specific course(s) completion". +endhnote + +oex_admin -> backend : Activates configured badge templates + +rnote over badges,backend + BadgeProcessor starts taking + into account new requirements. +endhnote +@enduml \ No newline at end of file diff --git a/docs/badges/configuration.rst b/docs/badges/configuration.rst index d3bfe2ef5..962eae7e4 100644 --- a/docs/badges/configuration.rst +++ b/docs/badges/configuration.rst @@ -1,7 +1,11 @@ Configuration ============= -The Badges feature is configured via the Credentials admin interface. +.. note:: + + This section provides information on how and where to set up badge templates and organizations. + +The Badges feature is configured in the Credentials admin panel. .. image:: ../_static/images/badges/badges-admin.png :alt: Badges administration @@ -9,25 +13,41 @@ The Badges feature is configured via the Credentials admin interface. Credly Organizations -------------------- - Multiple Credly Organizations can be configured. +Multiple Credly Organizations can be configured. **All communication between Open edX Credentials and Credly service happens on behalf of a Credly Organization.** -Enter "Credly Organizations" list page (`/admin/badges/credlyorganization/`) and create a new item: +Go to the Credly Organization section in the admin panel and create a new item: -- to set the UUID use your Credly Organization identifier; -- to set the authorization token issue one in the Credly Organization's dashboard; +1. to set the UUID use your Credly Organization identifier; +2. to set the authorization token issue one in the Credly Organization's dashboard. Check: the system pulls the Organization's details and updates its name. -In case of errors check used credentials for the Organization. +In case of errors check the used credentials for the Organization. Badge templates --------------- - **Badge template** is another **credential** type. Credly badge template is a kind of a badge template. +*Credly badge templates* (badge templates for short) are created in the Credly Organization's dashboard and then, if published, they are retrieved by the Credentials via API. + +Webhooks +~~~~~~~~~~~~~~~ + +.. note:: + + Webhooks is a connection with Credly and external platform that allows your server to be notified about events occuring within Credly. + +Webhooks are set up on Credly management dashboard as Credly is a main initiator of the syncronization. + +You should be able to select an action from the list so that whenever this action happens internally, external platform will be alerted and updated. -*Credly badge templates* (badge templates for brevity) are created in the Credly Organization's dashboard and then, if published, they are retrieved by the Credentials via API. +Without the syncronization, actions such as: + +- Update of the badge template +- Archivation of the badge template + +external platform will not be aware of any changes so it might continue issuing outdated badges. Synchronization ~~~~~~~~~~~~~~~ @@ -140,6 +160,22 @@ All key paths are generated based on the event type specified for the parent Bad Please, see `configuration examples`_ for clarity. +Badge Penalties +--------------- + + Penalties allow badge progress resetting based on user activity. + +Badge penalties are optional. +There could be 0 or more badge penalties configured for a badge template. + +Each badge penalty is *targeted* to 1 or more badge requirements. +A penalty setup is similar to a badge requirement, but has different effect: it decreases badge progress for a user. + +When a penalty has worked all linked badge requirements are "rolled back" (user's progress for such requirements is reset). + +.. image:: ../_static/images/badges/badges-admin-penalty-rules.png + :alt: Badge penalty rules edit + Activation ---------- diff --git a/docs/badges/examples.rst b/docs/badges/examples.rst index 7e53e8064..7a526cac8 100644 --- a/docs/badges/examples.rst +++ b/docs/badges/examples.rst @@ -1,11 +1,11 @@ Configuration examples ====================== -These examples will put some light on how to configure requirements and data rules for desired use cases. +These examples will show how to configure requirements and ``data rules`` for necessary use cases. .. note:: - **Any of the following examples can be combined together for more specific use cases**. + Any of the following examples can be combined for more specific use cases. Implemented use cases @@ -17,9 +17,9 @@ Implemented use cases Not that useful. Any interaction (e.g. submit button click) with gradable block in any course leads to a badge. -- Requirement 1: - - event type: ``org.openedx.learning.course.passing.status.updated.v1`` - - description: ``On any grade update.`` +1. **Requirement 1**: + a. event type: ``org.openedx.learning.course.passing.status.updated.v1`` + b. description: ``On any grade update.`` 2. ANY COURSE completion @@ -28,13 +28,13 @@ Implemented use cases Requires **passing grade** for any course. Once course'd grade becomes "passing" after gradable problem submission, a badge is awarded. -- Requirement 1: - - event type: ``org.openedx.learning.course.passing.status.updated.v1`` - - description: ``On any (not CCX) course completion.`` - - Data rule 1: - - key path: ``is_passing`` - - operator: ``equals`` - - value: ``true`` +1. **Requirement 1**: + a. event type: ``org.openedx.learning.course.passing.status.updated.v1`` + b. description: ``On any (not CCX) course completion.`` + c. **Data rule 1**: + i. key path: ``is_passing`` + ii. operator: ``equals`` + iii. value: ``true`` 3. ANY CCX course completion @@ -42,13 +42,13 @@ Implemented use cases Requires **passing grade** for any CCX course. -- Requirement 1: - - event type: ``org.openedx.learning.ccx.course.passing.status.updated.v1`` - - description: ``On any CCX course completion.`` - - Data rule 1: - - key path: ``is_passing`` - - operator: ``equals`` - - value: ``true`` +1. **Requirement 1**: + a. event type: ``org.openedx.learning.ccx.course.passing.status.updated.v1`` + b. description: ``On any CCX course completion.`` + c. **Data rule 1**: + i. key path: ``is_passing`` + ii. operator: ``equals`` + iii. value: ``true`` 4. ANY COURSE completion EXCEPT a specific course @@ -56,17 +56,17 @@ Implemented use cases Requires **passing grade** for any course **excluding** the "Demo" course. -- Requirement 1: - - event type: ``org.openedx.learning.course.passing.status.updated.v1`` - - description: ``On any course completion, but not the "Demo" course.`` - - Data rule 1: - - key path: ``is_passing`` - - operator: ``equals`` - - value: ``true`` - - Data rule 2: - - key path: ``course.course_key`` - - operator: ``not equals`` - - value: ``course-v1:edX+DemoX+Demo_Course`` +1. **Requirement 1**: + a. event type: ``org.openedx.learning.course.passing.status.updated.v1`` + b. description: ``On any course completion, but not the "Demo" course.`` + c. **Data rule 1**: + i. key path: ``is_passing`` + ii. operator: ``equals`` + iii. value: ``true`` + d. **Data rule 2**: + i. key path: ``course.course_key`` + ii. operator: ``not equals`` + iii. value: ``course-v1:edX+DemoX+Demo_Course`` 5. SPECIFIC COURSE completion @@ -74,17 +74,17 @@ Implemented use cases Requires **passing grade** for exact course ("Demo" course). -- Requirement 1: - - event type: ``org.openedx.learning.course.passing.status.updated.v1`` - - description: ``On the Demo course completion.`` - - Data rule 1: - - key path: ``is_passing`` - - operator: ``equals`` - - value: ``true`` - - Data rule 2: - - key path: ``course.course_key`` - - operator: ``equals`` - - value: ``course-v1:edX+DemoX+Demo_Course`` +1. **Requirement 1**: + a. event type: ``org.openedx.learning.course.passing.status.updated.v1`` + b. description: ``On the Demo course completion.`` + c. **Data rule 1**: + i. key path: ``is_passing`` + ii. operator: ``equals`` + iii. value: ``true`` + d. **Data rule 2**: + i. key path: ``course.course_key`` + ii. operator: ``equals`` + iii. value: ``course-v1:edX+DemoX+Demo_Course`` 6. MULTIPLE SPECIFIC COURSES completion @@ -93,31 +93,31 @@ Implemented use cases **All** specified courses must be completed. Different requirement groups force each requirement to be fulfilled. -- Requirement 1: - - event type: ``org.openedx.learning.course.passing.status.updated.v1`` - - description: ``On the "Demo" course completion.`` - - group: ``A`` - - Data rule 1: - - key path: ``is_passing`` - - operator: ``equals`` - - value: ``true`` - - Data rule 2: - - key path: ``course.course_key`` - - operator: ``equals`` - - value: ``course-v1:edX+DemoX+Demo_Course`` - -- Requirement 2: - - event type: ``org.openedx.learning.course.passing.status.updated.v1`` - - description: ``On the "Other" course completion.`` - - group: ``B`` - - Data rule 1: - - key path: ``is_passing`` - - operator: ``equals`` - - value: ``true`` - - Data rule 2: - - key path: ``course.course_key`` - - operator: ``equals`` - - value: ``course-v1:edX+DemoX+OTHER_Course`` +1. **Requirement 1**: + a. event type: ``org.openedx.learning.course.passing.status.updated.v1`` + b. description: ``On the "Demo" course completion.`` + c. group: ``A`` + d. **Data rule 1**: + i. key path: ``is_passing`` + ii. operator: ``equals`` + iii. value: ``true`` + e. **Data rule 2**: + i. key path: ``course.course_key`` + ii. operator: ``equals`` + iii. value: ``course-v1:edX+DemoX+Demo_Course`` + +2. **Requirement 2**: + a. event type: ``org.openedx.learning.course.passing.status.updated.v1`` + b. description: ``On the "Other" course completion.`` + c. group: ``B`` + d. **Data rule 1**: + i. key path: ``is_passing`` + ii. operator: ``equals`` + iii. value: ``true`` + e. **Data rule 2**: + i. key path: ``course.course_key`` + ii. operator: ``equals`` + iii. value: ``course-v1:edX+DemoX+OTHER_Course`` 7. SPECIFIC CCX course completion @@ -125,56 +125,56 @@ Implemented use cases Requires **passing grade** for exact CCX course ("Demo CCX1" course). -- Requirement 1: - - event type: ``org.openedx.learning.ccx.course.passing.status.updated.v1`` - - description: ``On the Demo CCX1 course completion.`` - - Data rule 1: - - key path: ``is_passing`` - - operator: ``equals`` - - value: ``true`` - - Data rule 2: - - key path: ``course.ccx_course_key`` - - operator: ``equals`` - - value: ``ccx-v1:edX+DemoX+Demo_Course+ccx@1`` +1. **Requirement 1**: + a. event type: ``org.openedx.learning.ccx.course.passing.status.updated.v1`` + b. description: ``On the Demo CCX1 course completion.`` + c. **Data rule 1**: + i. key path: ``is_passing`` + ii. operator: ``equals`` + iii. value: ``true`` + d. **Data rule 2**: + i. key path: ``course.ccx_course_key`` + ii. operator: ``equals`` + iii. value: ``ccx-v1:edX+DemoX+Demo_Course+ccx@1`` 8. ANY CCX course completion ON a SPECIFIC MASTER course ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Requires **passing grade** for any "child" CCX course that based on the master "Demo" course. -- Requirement 1: - - event type: ``org.openedx.learning.ccx.course.passing.status.updated.v1`` - - description: ``On any Demo CCX course completion.`` - - Data rule 1: - - key path: ``is_passing`` - - operator: ``equals`` - - value: ``true`` - - Data rule 2: - - key path: ``course.master_course_key`` - - operator: ``equals`` - - value: ``course-v1:edX+DemoX+Demo_Course`` +1. **Requirement 1**: + a. event type: ``org.openedx.learning.ccx.course.passing.status.updated.v1`` + b. description: ``On any Demo CCX course completion.`` + c. **Data rule 1**: + i. key path: ``is_passing`` + ii. operator: ``equals`` + iii. value: ``true`` + d. **Data rule 2**: + i. key path: ``course.master_course_key`` + ii. operator: ``equals`` + iii. value: ``course-v1:edX+DemoX+Demo_Course`` 9. ANY CCX course completion ON a SPECIFIC MASTER course EXCEPT a SPECIFIC CCX course ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Complicated. - Requires **passing grade** for **any "child"** CCX course that based on the master "Demo" course, **excluding** the "Demo CCX2" course. - -- Requirement 1: - - event type: ``org.openedx.learning.ccx.course.passing.status.updated.v1`` - - description: ``On any Demo CCX course completion.`` - - Data rule 1: - - key path: ``is_passing`` - - operator: ``equals`` - - value: ``true`` - - Data rule 2: - - key path: ``course.master_course_key`` - - operator: ``equals`` - - value: ``course-v1:edX+DemoX+Demo_Course`` - - Data rule 3: - - key path: ``course.ccx_course_key`` - - operator: ``not equals`` - - value: ``ccx-v1:edX+DemoX+Demo_Course+ccx@2`` + Requires **passing grade** for **any "child" CCX course** that based on the master "Demo" course, **excluding** the "Demo CCX2" course. + +1. **Requirement 1**: + a. event type: ``org.openedx.learning.ccx.course.passing.status.updated.v1`` + b. description: ``On any Demo CCX course completion.`` + c. **Data rule 1**: + i. key path: ``is_passing`` + ii. operator: ``equals`` + iii. value: ``true`` + d. **Data rule 2**: + i. key path: ``course.master_course_key`` + ii. operator: ``equals`` + iii. value: ``course-v1:edX+DemoX+Demo_Course`` + e. **Data rule 3**: + i. key path: ``course.ccx_course_key`` + ii. operator: ``not equals`` + iii. value: ``ccx-v1:edX+DemoX+Demo_Course+ccx@2`` 10. ONE OF MULTIPLE SPECIFIC COURSES completion ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -182,31 +182,31 @@ Implemented use cases At least a single from the specified courses must be completed. Grouped requirements are processed as **"ANY FROM A GROUP"**. -- Requirement 1: - - event type: ``org.openedx.learning.course.passing.status.updated.v1`` - - description: ``On the "Demo" course completion.`` - - group: ``A`` - - Data rule 1: - - key path: ``is_passing`` - - operator: ``equals`` - - value: ``true`` - - Data rule 2: - - key path: ``course.course_key`` - - operator: ``equals`` - - value: ``course-v1:edX+DemoX+Demo_Course`` - -- Requirement 2: - - event type: ``org.openedx.learning.course.passing.status.updated.v1`` - - description: ``On the "Other" course completion.`` - - group: ``A`` - - Data rule 1: - - key path: ``is_passing`` - - operator: ``equals`` - - value: ``true`` - - Data rule 2: - - key path: ``course.course_key`` - - operator: ``equals`` - - value: ``course-v1:edX+DemoX+OTHER_Course`` +1. **Requirement 1**: + a. event type: ``org.openedx.learning.course.passing.status.updated.v1`` + b. description: ``On the "Demo" course completion.`` + c. group: ``A`` + d. **Data rule 1**: + i. key path: ``is_passing`` + ii. operator: ``equals`` + iii. value: ``true`` + e. **Data rule 2**: + i. key path: ``course.course_key`` + ii. operator: ``equals`` + iii. value: ``course-v1:edX+DemoX+Demo_Course`` + +2. **Requirement 2**: + a. event type: ``org.openedx.learning.course.passing.status.updated.v1`` + b. description: ``On the "Other" course completion.`` + c. group: ``A`` + d. **Data rule 1**: + i. key path: ``is_passing`` + ii. operator: ``equals`` + iii. value: ``true`` + e. **Data rule 2**: + i. key path: ``course.course_key`` + ii. operator: ``equals`` + iii. value: ``course-v1:edX+DemoX+OTHER_Course`` 11. SPECIFIC MASTER course OR ANY of its CCX courses EXCEPT a SPECIFIC CCX course completion @@ -214,44 +214,44 @@ Implemented use cases Here requirements 1 and 2 are grouped, so any of them lead to a badge. -- Requirement 1: - - event type: ``org.openedx.learning.course.passing.status.updated.v1`` - - description: ``On the "Demo" course completion OR...`` - - group: ``A`` - - Data rule 1: - - key path: ``is_passing`` - - operator: ``equals`` - - value: ``true`` - - Data rule 2: - - key path: ``course.course_key`` - - operator: ``equals`` - - value: ``course-v1:edX+DemoX+Demo_Course`` - -- Requirement 2: - - event type: ``org.openedx.learning.ccx.course.passing.status.updated.v1`` - - description: ``...OR any Demo CCX courses completion EXCLUDING CCX3.`` - - group: ``A`` - - Data rule 1: - - key path: ``is_passing`` - - operator: ``equals`` - - value: ``true`` - - Data rule 2: - - key path: ``course.master_course_key`` - - operator: ``equals`` - - value: ``course-v1:edX+DemoX+Demo_Course`` - - Data rule 3: - - key path: ``course.ccx_course_key`` - - operator: ``not equals`` - - value: ``ccx-v1:edX+DemoX+Demo_Course+ccx@3`` +1. **Requirement 1**: + a. event type: ``org.openedx.learning.course.passing.status.updated.v1`` + b. description: ``On the "Demo" course completion OR...`` + c. group: ``A`` + d. **Data rule 1**: + i. key path: ``is_passing`` + ii. operator: ``equals`` + iii. value: ``true`` + e. **Data rule 2**: + i. key path: ``course.course_key`` + ii. operator: ``equals`` + iii. value: ``course-v1:edX+DemoX+Demo_Course`` + +2. **Requirement 2**: + a. event type: ``org.openedx.learning.ccx.course.passing.status.updated.v1`` + b. description: ``...OR any Demo CCX courses completion EXCLUDING CCX3.`` + c. group: ``A`` + d. **Data rule 1**: + i. key path: ``is_passing`` + ii. operator: ``equals`` + iii. value: ``true`` + e. **Data rule 2**: + i. key path: ``course.master_course_key`` + ii. operator: ``equals`` + iii. value: ``course-v1:edX+DemoX+Demo_Course`` + f. **Data rule 3**: + i. key path: ``course.ccx_course_key`` + ii. operator: ``not equals`` + iii. value: ``ccx-v1:edX+DemoX+Demo_Course+ccx@3`` ----- Future work ----------- -- Events set extension (e.g. "Email activation", "Profile data completion", "Course section completion", ...); -- Repetitive events (e.g. "5 arbitrary courses completion"); -- Prerequisite events (e.g. "5 specific courses completion in a specified order"); -- Time-ranged event (e.g. "Arbitrary course completion during the February 2022"); -- Badge dependencies (e.g. "Badge A + Badge B = Badge C"); -- Multiple times same badge earning (e.g. "3 arbitrary course completions make badge earned x3"); +1. Events set extension (e.g. "Email activation", "Profile data completion", "Course section completion", ...); +2. Repetitive events (e.g. "5 arbitrary courses completion"); +3. Prerequisite events (e.g. "5 specific courses completion in a specified order"); +4. Time-ranged event (e.g. "Arbitrary course completion during the February 2022"); +5. Badge dependencies (e.g. "Badge A + Badge B = Badge C"); +6. Multiple times same badge earning (e.g. "3 arbitrary course completions make badge earned x3"); diff --git a/docs/badges/index.rst b/docs/badges/index.rst index 4513cec71..087d0c13e 100644 --- a/docs/badges/index.rst +++ b/docs/badges/index.rst @@ -1,14 +1,28 @@ -Badges (in progress) -==================== +Badges +====== The Badges feature allows learners to earn achievements (badges) for their learning activities. - **Badge Template** is another kind of **credential**. - **Badge** is another kind of **user credential**. - Current Badges version is highly integrated with the `Credly (by Pearson)`_ service, but it is fully prepared to be used separately. + What is Credly? + + **Credly** is the end-to-end solution for creating, issuing, and managing digital credentials. Thousands of organizations use **Credly** to recognize achievement. + Users use Credly as a professional board to store badges to visualize their professional success – which courses were completed and when. Badges provide employers and peers concrete evidence of what you had to do to earn your credential and what you're now capable of. Credly also offers labor market insights based on users’ skills. Users can search and apply for job opportunities right through Credly. + + +Glossary +-------- + +1. **Badge template** – a template of a badge (with design, name, and description) that will be used in settings to set up special rules to create a badge for users to receive on the platform. + +2. **Authorization token** – It's a temporary key that verifies identity and authorizes resource access. A token can be computer-generated or hardware-based. A valid token allows a user to retain access to an online service or web application until the token expires. + +3. **UUID** – Universally Unique Identifier – is a value used to identify an object or entity on the internet uniquely. Depending on the specific mechanisms used, a UUID is either guaranteed to be different or is, at least, extremely likely to be different from any other UUID generated. + ---- .. toctree:: diff --git a/docs/badges/processing.rst b/docs/badges/processing.rst index 44ec4785f..6b274e35c 100644 --- a/docs/badges/processing.rst +++ b/docs/badges/processing.rst @@ -8,6 +8,8 @@ See the Event Bus documentation for details. Events subscription ------------------- +.. note:: + Only explicitly configured `event types`_ take part in the processing. See Badges `default settings`_ for the default set of supported events. @@ -17,6 +19,8 @@ Though, it is expected that any public signal from the `openedx-events`_ library Learner identification ---------------------- +.. note:: + Each incoming event must be associated with a specific learner. The system tries to identify a learner by the `UserData` object in the event payload. @@ -30,8 +34,8 @@ Requirements analysis Since any requirement is associated with a single event type, all relevant requirements are collected for the incoming signal: -- appropriate event type; -- active badge templates; +1. appropriate event type; +2. active badge templates; Each requirement's rules are checked against the event payload. Requirement processing is dropped as soon as the system recognizes not applying rules. @@ -42,12 +46,14 @@ Progress update Current learners' badge progress is stored in the ``Badge Progress`` record. +.. note:: + Since badge templates can have more than one requirement, the system should track intermediate progresses as well. Once all rules of the processed requirement apply, the system: -- ensures there is the badge progress record for the learner; -- marks the requirement as fulfilled for the learner; +1. ensures there is the badge progress record for the learner; +2. marks the requirement as fulfilled for the learner; .. image:: ../_static/images/badges/badges-admin-progress-records.png :alt: Badge progress records @@ -58,18 +64,41 @@ If a Badge Progress is recognized as completed (all requirements for the badge t Badge awarding -------------- +.. note:: + Once all requirements for the badge template are fulfilled, the system should award the badge. On badge progress completion, the system: -- creates an *internal* user credential record for the learner; -- notifies (public signal) about new badge awarded; -- tries to issue an *external* Credly badge for the learner; +1. creates an *internal* user credential record for the learner; +2. notifies (public signal) about new badge awarded; +3. tries to issue an *external* Credly badge for the learner; .. note:: The Badges application implements its extended ``UserCredential`` version (the CredlyBadge) to track external issuing state. Once the Credly badge is successfully issued the **CredlyBadge is updated with its UUID and state**. +Badge revoking is optional. Business needs. Configuration. And why. + .. _event types: https://docs.openedx.org/projects/openedx-events/en/latest/ .. _openedx-events: https://github.com/openedx/openedx-events .. _default settings: settings.html#default-settings + +Badge revocation +---------------- + +Badges can also be revoked. Its a separete set of rules that need to be set up. + +1. Go to Badge Penalties section in admin panel (admin/badges/badge_pentalties). + +.. image:: ../_static/images/badges/badges-admin-penalty-rules.png + :alt: Badge penalties + +2. Select a certain requirement that was previously set up to link penalty + a. To know how to set up badge template requirements, go to the `Configuration`_ section. + +3. Note that all penalties have to be linked to a certain requirement, so that when that requirement is not fulfilled, system would know when to revoke the badge. + +.. _Configuration: configuration.html + +When system revokes a badge, the status of a badge will change from awarded to revoked in the admin panel (admim/badges/credly_badges) as the revoke process is synced with external platform. diff --git a/docs/badges/quickstart.rst b/docs/badges/quickstart.rst index 2d50a9c20..dfbac1752 100644 --- a/docs/badges/quickstart.rst +++ b/docs/badges/quickstart.rst @@ -1,23 +1,24 @@ Quick Start =========== - Learners *earn* badges based on Open edX platform activity. - +.. note:: + + This section includes brief information about the feature – what to start with; where to set up credentials, etc. -0. Credly service prerequisites -------------------------------- +0. Prerequisites – Credly account +--------------------------------- -Since current Badges version is deeply integrated with the Credly service, Credly account is a prerequisite. +To start using this feature a Credly account is necessary. -- a **Credly Organization** is expected to be created; -- 1 or more **badge templates** are expected to be created and activated in the Organization; -- Credly Organization **authorization token** is issued; +1. Register on Credly and create your account. +2. Create Organization in Credly. +3. Create at least 1 badge template and activate it. +4. Credly Organization 1. Enable feature ----------------- -Badges feature is optional and it is disabled by default. -So, it must be enabled to be accessible. +Badges feature is optional and it is disabled by default. So, it must be enabled to be accessible. .. code-block:: @@ -30,50 +31,59 @@ So, it must be enabled to be accessible. 2. Configure Credly integration ------------------------------- - Multiple Credly Organizations can be configured. +.. note:: + + For detailed information, go to the `Configuration`_ section. + +Go to the Credentials service admin panel and configure the integration with the Credly service: + +1. In the admin panel go to /admin/badges/credly_organization to add Credly Organization. + a. Add UUID (unique identifier) for the Credly organization + b. Add the authorization token of the Credly organization. -Enter the Credentials service admin interface and configure the integration with the Credly service: +Please note that UUID and authorization token will be given to you during the creation of the Credly Organization on the Credly side -- create a Credly Organization (`/admin/badges/credlyorganization/`); -- set the UUID for the Organization; -- set the authorization token; +Check: the system pulls the Organization's data and updates its name. -Check: the system pulls the Organization data and updates its name. +.. _Configuration: configuration.html 3. Synchronize badge templates ------------------------------ + Note: For detailed information, go to the `Configuration`_ section. -From the "Credly Organizations" list, select the Organization(s) you want to use and select ``Sync organization badge templates`` action. +From the “Credly Organizations” list, select the Organization(s) you want to use and select ``Sync organization badge templates`` action. -The system pulls the list of badge templates from the Credly Organization. Navigate to the "Credly badge templates" list and check newly created templates. +The system pulls the list of badge templates from the Credly Organization. Navigate to the “Credly badge templates” list and check newly created templates. + +.. _Configuration: configuration.html 4. Setup badge requirements --------------------------- - Requirements describe **what** and **how** must happen on the system to earn a badge. +.. note:: -The crucial part of the badge template configuration is requirements specification. -At least one requirement must be associated with a badge template. + Requirements describe **what** and **how** must happen on the system to earn a badge. -Enter the first badge template details page and configure its requirement(s): +The crucial part of the badge template configuration is the requirements specification. At least one requirement must be associated with a badge template. -- find "Badge Requirements" section; -- add new item and select an event type (what is expected to happen); -- optionally, put a description; -- save and navigate to the Requirement details (``Change`` link); +Go to the first badge template details page (admin/badges/credly_badge_templates) and add requirements for it: -- optionally, specify a data rule(s) in the "Data Rules" section (how exactly it is expected to happen); -- add new item and describe the rule; -- select a key path - target payload parameter; -- select an operator - how to compare the value; -- enter a value - expected parameter's value; +1. find the “Badge Requirements” section; +2. add a new item and select an event type (what is expected to happen); + a. optionally, put a description; +3. save and navigate to the Requirement details (Change link); + a. optionally, specify data rules in the “Data Rules” section (how exactly it is expected to happen); +4. add a new item and describe the rule; +5. select a key path - specific data element; +6. select an operator - how to compare the value; +7. enter a value - expected parameter’s value. .. note:: - A configuration for the badge template that must be issued on a **specific course completion** looks as following: - - - Requirement: + A configuration for the badge template that must be issued on a specific course completion looks as following: + + - Requirement 1: - event type: ``org.openedx.learning.course.passing.status.updated.v1`` - description: ``On the Demo course completion.`` - Data rule 1: @@ -92,43 +102,45 @@ It is possible to put more than one requirement in a badge template. To active a badge template check the ``is active`` checkbox on its edit page. -Once badge requirements are configured, it should be "enabled" to start "working". +Once badge requirements are set up, it should be “enabled” to start “working”. -Active badge templates start being taking into account immediately. +Once enabled, the badge template will be active and ready. .. warning:: - Configuration updates for active badge template are discouraged since it may cause learners' inconsistent experience. + Configuration updates for active badge templates are discouraged since they may cause learners’ inconsistent experience. 6. See users Badge Progress --------------------------- -Current badge progress can be seen in the "Badge progress records" section. +Current badge progress can be seen in the “Badge progress records” section in the Credentials admin panel. -Since badge template can have more than one requirement, there can be partially completed badges. +Since badge templates can have more than one requirement, there can be partially completed badges. 7. See awarded user credentials ------------------------------- -Already earned badges are listed in the "Credly badges" list page. +Already earned badges are listed in the "Credly badges" section of the admin panel. + +.. note:: The Credly Badge is an extended version of a user credential record. Once badge progress is complete (all requirements were *fulfilled*), the system: -- creates internal user credential (CredlyBadge); -- notifies about the badge awarding (public signal); -- requests Credly service to issue the badge (API request). +1. creates internal user credentials (CredlyBadge); +2. notifies about the badge awarding (public signal); +3. requests Credly service to issue the badge (API request). 8. See issued Credly badges --------------------------- -Earned internal badges (user credentials) propagate to the Credly service. +Earned internal badges (user credentials) spread to the Credly service. -On a successful Credly badge issuing the CredlyBadge user credential is updated with its requisites: +On a successful Credly badge issuing, the CredlyBadge user credential is updated with its requisites: -- external UUID; -- external state; +1. external UUID; +2. external state; The Credly badge is visible in the Credly service. diff --git a/docs/badges/settings.rst b/docs/badges/settings.rst index eba8dfcdf..093dd8ad4 100644 --- a/docs/badges/settings.rst +++ b/docs/badges/settings.rst @@ -1,11 +1,15 @@ Settings ======== +.. note:: + + You can find technical details on how to set up proper configurations for badges to be active in this section. + Badges feature settings allow configuration: -- feature availability; -- event bus public signals subset for badges; -- the Credly service integration details (URLs, sandbox usage, etc.); +1. feature availability; +2. event bus public signals subset for badges; +3. the Credly service integration details (URLs, sandbox usage, etc.); Feature switch @@ -84,8 +88,8 @@ Source public signals Platform's event bus producer configuration was extended with 2 public signals: -- information about the fact someone's course grade was updated (allows course completion recognition); -- information about the fact someone's CCX course grade was updated (allows CCX course completion recognition); +1. information about the fact someone’s course grade was updated (allows course completion recognition); +2. information about the fact someone’s CCX course grade was updated (allows CCX course completion recognition). .. code-block:: python @@ -112,8 +116,8 @@ Emitted public signals The Badges feature introduced 2 own event types: -- information about the fact someone has earned a badge; -- information about the fact someone's badge was revoked; +1. information about the fact someone has earned a badge; +2. information about the fact someone's badge was revoked; .. code-block:: python @@ -132,6 +136,8 @@ The Badges feature introduced 2 own event types: Consuming workers ~~~~~~~~~~~~~~~~~ +.. note:: + Consumers implementation depends on the used event bus. Event bus options: diff --git a/docs/conf.py b/docs/conf.py index b677f988e..73806e69a 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -9,7 +9,7 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import edx_theme +from datetime import datetime # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -23,9 +23,7 @@ # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = [ - "edx_theme", -] +extensions = [] # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] @@ -41,8 +39,8 @@ # General information about the project. project = "edX Credentials" -author = edx_theme.AUTHOR -copyright = edx_theme.COPYRIGHT +copyright = f"{datetime.now().year}, Axim Collaborative, Inc" # pylint: disable=redefined-builtin +author = "Axim Collaborative, Inc" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -92,15 +90,46 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = "edx_theme" +html_theme = "sphinx_book_theme" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -# html_theme_options = {} +html_theme_options = { + "repository_url": "https://github.com/openedx/credentials", + "repository_branch": "master", + "path_to_docs": "docs/", + "home_page_in_toc": True, + "use_repository_button": True, + "use_issues_button": True, + "use_edit_page_button": True, + "navigation_with_keys": False, + # Please don't change unless you know what you're doing. + "extra_footer": """ + + Creative Commons License + +
+ These works by + Axim Collaborative, Inc + are licensed under a + Creative Commons Attribution-ShareAlike 4.0 International License. + """, +} # Add any paths that contain custom themes here, relative to this directory. -html_theme_path = [edx_theme.get_html_theme_path()] +# html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". @@ -111,12 +140,12 @@ # The name of an image file (relative to this directory) to place at the top # of the sidebar. -# html_logo = None +html_logo = "https://logos.openedx.org/open-edx-logo-color.png" # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -# html_favicon = None +html_favicon = "https://logos.openedx.org/open-edx-favicon.ico" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, diff --git a/docs/credentials_api.rst b/docs/credentials_api.rst index f5e4ed9d7..2125a0cb4 100644 --- a/docs/credentials_api.rst +++ b/docs/credentials_api.rst @@ -1,19 +1,19 @@ Credentials API =============== -The ``credentials`` resource should be used for all API calls. - -+----------------------------------------+--------+---------------------------------+ -| Task | Method | Endpoint | -+========================================+========+=================================+ -| Get a list of credentials | GET | /api/v2/credentials/ | -+----------------------------------------+--------+---------------------------------+ -| Get a specific credential | GET | /api/v2/credentials/:uuid | -+----------------------------------------+--------+---------------------------------+ -| Create a new credential | POST | /api/v2/credentials/ | -+----------------------------------------+--------+---------------------------------+ -| Update a credential | PATCH | /api/v2/credentials/:uuid | -+----------------------------------------+--------+---------------------------------+ ++-------------------------------------------------------------+--------+------------------------------------------+ +| Task | Method | Endpoint | ++=============================================================+========+==========================================+ +| Get a list of credentials | GET | /api/v2/credentials/ | ++-------------------------------------------------------------+--------+------------------------------------------+ +| Get a specific credential | GET | /api/v2/credentials/:uuid | ++-------------------------------------------------------------+--------+------------------------------------------+ +| Create a new credential | POST | /api/v2/credentials/ | ++-------------------------------------------------------------+--------+------------------------------------------+ +| Update a credential | PATCH | /api/v2/credentials/:uuid | ++-------------------------------------------------------------+--------+------------------------------------------+ +| Query for a user's earned certificates for specific courses | POST | /api/credentials/v1/learner_cert_status/ | ++-------------------------------------------------------------+--------+------------------------------------------+ Create a New Credential @@ -42,7 +42,7 @@ Create a New Credential * The ``username`` and ``credential`` parameters are required. * The ``attributes`` parameter is optional. * If you use the ``whitelist`` or ``grade`` attributes, you can only change the ``value`` - parameter.
 + parameter. * If you send a program-based user credential request, you can only provide the ``whitelist`` attribute. * When creating a user credential for a program, the API also checks to see if an updated email needs to be sent to a credit pathway. For more information, please consult the Credit Pathways doc. @@ -206,3 +206,150 @@ You can filter the returned list of credentials by using the ``program_uuid`` pa } ] } + +Query for an individual learner's earned certificates for specific courses +-------------------------------------------------------------------------- + +Query for an individual learner's earned certificates for a list of courses or course runs. + +**Note**: + +* You must include `exactly one` of ``lms_user_id`` or ``username``. +* You must include at least one of ``courses`` and ``course_runs``, and you may include a mix of both. + * The ``courses`` list should contain a list of course UUIDs. + * The ``course_runs`` list should contain a list of course run keys. + +If the ``username`` or ``lms_user_id`` has not earned any certificates, this endpoint +will return successfully, and the ``status`` object will be empty. + +**Example Request** + +.. code-block:: text + + POST api/credentials/v1/learner_cert_status/ + +.. code-block:: json + + { + "username": "sample_user", + "courses": [ + "4ad04e84-1512-11ee-be56-0242ac120002", + "4ad051fe-1512-11ee-be56-0242ac120002" + ], + "course_runs": [ + "course-v1:edX+AA302+2T2023a" + ] + } + +**Example Response** + +In this example, this user has earned a certificate in only one of the courses requested, so that is the only returned value. + +.. code-block:: json + + { + "lms_user_id": 3, + "username": "sample_user", + "status": [ + { + "course_uuid": "4ad04e84-1512-11ee-be56-0242ac120002", + "course_run": { + "uuid": "4747fefb-6f31-4689-bcfb-8ff32da191f4", + "key": "course-v1:edX+AA302+2T2023a" + }, + "status": "awarded", + "type": "verified", + "certificate_available_date": null, + "grade": { + "letter_grade": "Pass", + "percent_grade": 1, + "verified": true + } + } + ] + } + +Query for multiple learners' earned certificates for specific courses +-------------------------------------------------------------------------- + +Query for multiple learners' earned certificates for a list of courses or course runs. + +**Note**: + +For each requested response: + +* You must include `exactly one` of ``lms_user_id`` or ``username``. +* You must include at least one of ``courses`` and ``course_runs``, and you may include a mix of both. + * The ``courses`` list should contain a list of course UUIDs. + * The ``course_runs`` list should contain a list of course run keys. + +If the ``username`` or ``lms_user_id`` has not earned any certificates (or does not exist in the system), +the ``status`` object will be empty. + +**Example Request** + +.. code-block:: text + + POST api/credentials/v1/bulk_learner_cert_status/ + +.. code-block:: json + + [ + { + "username": "sample_user", + "courses": [ + "4ad04e84-1512-11ee-be56-0242ac120002", + "4ad051fe-1512-11ee-be56-0242ac120002" + ], + "course_runs": [ + "course-v1:edX+AA302+2T2023a" + ] + }, + { + "lms_user_id": 8674309, + "courses": [ + "4ad04e84-1513-11ee-be56-0242ac12000f", + "4ad051fe-1513-11ee-be56-0242ac12000f" + ], + "course_runs": [ + "course-v1:edX+ZZ302+2T2023a" + ] + } + ] + +**Example Response** + +In this example, the first user has earned a certificate in only one of the +courses requested, and the second user hasn't earned a certificate at all, so +only one return value contains a populated status block. + +.. code-block:: json + + [ + { + "lms_user_id": 3, + "username": "sample_user", + "status": [ + { + "course_uuid": "4ad04e84-1512-11ee-be56-0242ac120002", + "course_run": { + "uuid": "4747fefb-6f31-4689-bcfb-8ff32da191f4", + "key": "course-v1:edX+AA302+2T2023a" + }, + "status": "awarded", + "type": "verified", + "certificate_available_date": null, + "grade": { + "letter_grade": "Pass", + "percent_grade": 1, + "verified": true + } + } + ] + }, + { + "lms_user_id": 8674309, + "username": null, + "status": [] + } + ] diff --git a/docs/decisions/0006-plugin-extensions.rst b/docs/decisions/0006-plugin-extensions.rst new file mode 100644 index 000000000..3c6d21d62 --- /dev/null +++ b/docs/decisions/0006-plugin-extensions.rst @@ -0,0 +1,59 @@ +Django App Plugin extensions +============================ + +Status +------ + +Accepted + + +Context +------- + +More functionality is planned to be added to the Credentials service as a part of +`credentials/issues/1734`_ and `credentials/issues/1736`_. +Credentials may benefit from adoption of the `Django App Plugin`_ functionality. +It would provide additional possibilities to support many integrations with third-party +services for credentials sharing, like digital credentials platforms, digital wallets, +credentials signing services, etc. + +For more information on plugins in particular, see the `Django Apps Plugin README`_. + +.. _`credentials/issues/1734`: https://github.com/openedx/credentials/issues/1734 +.. _`credentials/issues/1736`: https://github.com/openedx/credentials/issues/1736 +.. _Django App Plugin: https://github.com/openedx/edx-django-utils/blob/master/edx_django_utils/plugins/README.rst +.. _Django Apps Plugin README: https://github.com/openedx/edx-django-utils/blob/master/edx_django_utils/plugins/README.rst + + +Decision +-------- + +* Implement improved plugin support of Django apps in the Credentials service by adopting `edx_django_utils`_ module. Django apps plugins will support `overrides system`_ for core functionality. + +* Use plugin applications for future extension points and optional functionality for the Credentials service. + +.. _edx_django_utils: https://github.com/openedx/edx-django-utils +.. _overrides system: https://github.com/openedx/edx-django-utils/blob/master/edx_django_utils/plugins/pluggable_override.py#L11 + +Consequences +------------ + +* It will be easier to extend the Credentials service and implement new business cases without building a monolithic unit. + +* It will be possible to override the core functionality of the Credentials service for specific use cases without direct code modifications. + +* It will become easier to support Credentials system "upgradability". + +* It may introduce complexity for code discovery in case of implicit overrides and a lack of documentation on particular plugin functionality. + +Rejected Alternatives +--------------------- + +* Adding Django applications directly to credentials/apps. + +References +---------- + +The Open edX platform Django apps ADR 0014: https://github.com/openedx/edx-platform/blob/master/docs/decisions/0014-no-new-apps.rst + +How to enable plugins for an IDA: https://github.com/openedx/edx-django-utils/blob/master/edx_django_utils/plugins/docs/how_tos/how_to_enable_plugins_for_an_ida.rst diff --git a/docs/decisions/0007-learner-status-endpoint.rst b/docs/decisions/0007-learner-status-endpoint.rst new file mode 100644 index 000000000..5e3822dcd --- /dev/null +++ b/docs/decisions/0007-learner-status-endpoint.rst @@ -0,0 +1,47 @@ +Endpoint for Learner Credential Status +###################################### + +Status +**Draft** + +Context +******* + +Because of the loose coupling between programs, courses and course-runs, there is a need for a mechanism to evaluate a learner's status in multiple courses in the context of a program. +The loose coupling means that a program is defined in Discovery by a list of courses. Those courses have course-runs, and the course-runs are automatically added to the program definition. +The program definition in Discovery can also have exceptions - course-runs that are excluded from the program. + +The gap between courses included in a program vs actual course-runs completed by a learner can lead to situations where a learner believes that they have completed all the courses in a program. However, the program remains incomplete because the course-run they completed has been excluded from the program. The issue being that they don't have visibility into these exceptions. +These use cases are currently difficult to reconcile because the only way to correlate the courses that a learner has taken and the exception list for course-runs in a program is through the admin interface. For a system that only tracks what courses a learner has taken, additional queries need to be made to map the course-runs associated with the courses. + +There are teams that need to get the current status of a set of courses for a learner for issues such as subscriptions. +Support often has to determine the status of a learner's credentials with respect to a program to determine if a learner has completed a course on the exclude list. + + +Decision +******** + +Add an API to the Credentials service that takes a learner ID and a list of courses, and returns the completion status for the learner for each of the courses. + +A follow up to the API will allow passing in a learner and a program, and the API will return the status for all the course-runs and tag any course-runs in the exclude list for that program. + + +Consequences +************ + +More load on credentials. +Credentials may at times be out of sync with the system of record, platform. It is not the source of truth, so this endpoint will be helpful, but not definitive. + +Rejected Alternatives +********************* + +- Add the endpoint to platform. + This was rejected because the long term plan is to move the course credential responsibilities to the Credentials IDA, and it would need to be + reimplemented. It would be coming from the current source of truth, but platform may not have the discovery information needed for reconciling the program data. + +References +********** + +.. (Optional) List any additional references here that would be useful to the future reader. See `Documenting Architecture Decisions`_ for further input. + +.. _Documenting Architecture Decisions: https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions diff --git a/docs/decisions/0008-verifiable-credentials-issuing.rst b/docs/decisions/0008-verifiable-credentials-issuing.rst new file mode 100644 index 000000000..5a9015f36 --- /dev/null +++ b/docs/decisions/0008-verifiable-credentials-issuing.rst @@ -0,0 +1,129 @@ +Issue verifiable credentials to learners +======================================== + +Status +------ + +Accepted + + +Context +------- + +As of July 2023, the Credentials Service is used as backend to support programs certificates. +Administrators can configure certificates, and learners can view and share earned certificates with anyone +to prove their achievements on the Open edX platform. +However, the sharing options for earned credentials is very limited, also it's hard to verify printed credentials or +get any additional information beyond the data explicitly included on the earned certificate. + +We want to adopt `verifiable credentials (VC)`_ to improve the sharing of the earned credentials, and enhance interoperability +with external digital credentials platforms and wallets. +This will allow learners to receive high-value credentials they can use in the real world. + +Every verifiable credential is a set of one or more claims made by an issuer about a subject – learner in the Open edX context. +A verifiable credential is a tamper-evident credential that has authorship and can be cryptographically verified. +After issuing a verifiable credential, it can be used to build a verifiable presentation, which can also be cryptographically verified. + +Verifiable credentials are closely related to decentralized digital identities and decentralized identifiers (DIDs). +DID is a portable URL-based identifier, associated with an entity, a thing with distinct and independent existence such as person, +organization, or device. +DIDs are used in a verifiable credential to associate it with a subject, so that a verifiable credential itself can be easily ported +from one repository to another without the need to reissue the credential. +You can find more information on DIDs in the `W3C DID-core specification`_. + +Except `Verifiable Credentials Data Model v1.1`_, there are other standards +that are based on the Verifiable Credentials, and therefore are fully compatible with it. +The most prominent are 1EdTech `Open Badges v3.0`_ and `The European Blockchain Services Infrastructure (EBSI) Verifiable Credentials`_. + +The ecosystem of verifiable credentials is growing rapidly, and they are becoming more common in all types of education, +including the formal, informal, and non-formal education. +The Digital Credentials Consortium (DCC), and The European Blockchain Services Infrastructure (EBSI) +are working towards making Verifiable Credentials accessible to anyone. + +This ADR describes the implementation of the Verifiable Credentials issuing mechanism, +that will add the possibility to create and sign a verifiable credential, based on the user's achievements on the Open edX system. + + + +Decision +-------- + +To issue verifiable credentials, it is decided to create a new Django application in the Credentials Service named `verifiable_credentials`. +It will provide configuration options for verifiable credentials, interfaces, and utilities for verifiable credentials issuing. + +The new application should be optional to run for the deployers of the Open edX system, it should be toggled using DjangoSetting toggle. + +The application should provide extensibility options using plugins and other instruments, that will allow the Open edX deployers +and contributors to easily implement and enable new verifiable credentials backends. +These backends can be used to: + +* build JSON-LD documents based on several VC based standards, e.g., `Verifiable Credentials Data Model v1.1`_, + `Open Badges v3.0`_, `EBSI Verifiable Credentials`_; + +* implement integrations with different verifiable credentials signing services, such as `SpruceID's didkit-python`_, `DCC's sign-and-verify`_, and other open-source and proprietary solutions. + +* issue credentials directly to different mobile and web digital credentials wallets, such as `DCC's Learner Credentials Wallet (LCW)`_. + +In addition to the new application, it was decided to implement three initial issuing and composition backends to: + +* transform user credentials as programs certificates, that are stored in the Credentials Service to `JSON-LD`_ according to `Open Badges v3.0`_ specification; + +* issue verifiable credentials directly to `DCC's Learner Credentials Wallet (LCW)`_; + +* sign verifiable credentials with the library `didkit-python`_, the python bindings for the open-source Rust-based `DIDKit`_ library maintained by SpruceID. + +We want to focus on the implementation of issuing the program certificates in the form of verifiable credentials, +and eventually support other credentials types that are available in the Credentials Service as well. + +The issuer configuration would be set on the site or organization level. Administrator would have an option to enable verifiable credentials generation for some user credentials instances, and disable it for others. + +Learners will see the list of all earned credentials that can be issued in a form of the verifiable credentials upon learners' request. + + +Consequences +------------ + +Implementation of the verifiable credentials issuing mechanism in the Credentials Service will open new +ways for learners to share and prove their achievements outside the Open edX platform. + + +Rejected Alternatives +--------------------- + +* Using `Open Badges v2.0`_ as the main digital credentials standard for sharing digital credentials. + +* Integration with `Europass Digital Credentials Infrastructure (EDCI)`_, the verifiable credentials standard based on XML documents. + +* Using `JWT`_ instead of `JSON-LD`_ as `verifiable credentials assertion format`_. + +* Integrate with the `DCC's sign-and-verify`_ REST API signing Node.JS server. + + +References +---------- + +`Design for verifiable credentials integration into the Open edX`_ + +`Verifiable Credentials for Education, Employment, and Achievement Use Cases`_ + + + +.. _`verifiable credentials (VC)`: https://www.w3.org/TR/vc-data-model/ +.. _`Verifiable Credentials Data Model v1.1`: https://www.w3.org/TR/vc-data-model/ +.. _`W3C DID-core specification`: https://www.w3.org/TR/did-core/ +.. _`Open Badges v3.0`: https://1edtech.github.io/openbadges-specification/ob_v3p0.html +.. _`The European Blockchain Services Infrastructure (EBSI) Verifiable Credentials`: https://ec.europa.eu/digital-building-blocks/wikis/display/EBSI/What+is+ebsi +.. _`EBSI Verifiable Credentials`: https://ec.europa.eu/digital-building-blocks/wikis/display/EBSI/What+is+ebsi +.. _`DCC's sign-and-verify`: https://github.com/digitalcredentials/sign-and-verify +.. _`DCC's Learner Credentials Wallet (LCW)`: https://lcw.app/ +.. _`MATTR wallet`: https://learn.mattr.global/docs/concepts/digital-wallets +.. _`JSON-LD`: https://www.w3.org/TR/vc-data-model/#json-ld +.. _`SpruceID's didkit-python`: https://github.com/spruceid/didkit-python +.. _`didkit-python`: https://github.com/spruceid/didkit-python +.. _`DIDKit`: https://github.com/spruceid/didkit +.. _`Open Badges v2.0`: https://www.imsglobal.org/sites/default/files/Badges/OBv2p0Final/index.html +.. _`Europass Digital Credentials Infrastructure (EDCI)`: https://github.com/european-commission-empl/European-Learning-Model +.. _`JWT`: https://www.rfc-editor.org/rfc/rfc7519 +.. _`verifiable credentials assertion format`: https://w3c.github.io/vc-imp-guide/#benefits-of-json-ld-and-ld-proofs +.. _`Design for verifiable credentials integration into the Open edX`: https://openedx.atlassian.net/wiki/spaces/OEPM/pages/3490840577 +.. _`Verifiable Credentials for Education, Employment, and Achievement Use Cases`: https://w3c-ccg.github.io/vc-ed-use-cases/ diff --git a/docs/decisions/0009-issue-verifiable-credentails-in-learner-records-mfe.rst b/docs/decisions/0009-issue-verifiable-credentails-in-learner-records-mfe.rst new file mode 100644 index 000000000..378011825 --- /dev/null +++ b/docs/decisions/0009-issue-verifiable-credentails-in-learner-records-mfe.rst @@ -0,0 +1,57 @@ +Issue verifiable credentials to learners in the Learner Record MFE +================================================================== + +Status +------ + +Accepted + + +Context +------- + +Following the `decision `_ to integrate `verifiable credentials`_ into the Credentials Service, +this ADR describes the implementation of the user interface, so that learners can request verifiable credentials based on their achievements in the Open edX system. + +To generate a verifiable credential, the learner needs to provide their wallet DID. +In most digital credentials wallets, it can be done automatically from the mobile application by either scanning a QR code or opening a deep link. +The QR code or the deep link include additional parameters, which allow the mobile app to prepare a request to the server and receive signed, verifiable credentials. + +Learners can issue the same Open edX credentials multiple times, but every time a verifiable credential is issued, +it will have a unique proof. Therefore, every issued verifiable credential is unique. + +Decision +-------- + +* It is decided to implement the user interface for issuing credentials in the `Learner Record`_ micro-frontend, as it currently contains views for a learners current status in a program and the ability to share any earned credentials publicly or with institutions. + +* Since the verifiable credentials functionality is optional for Open edX deployers, it has been decided to introduce a flag toggle in the `Learner Record`_ MFE, called 'ENABLE_VERIFIABLE_CREDENTIALS'. If this flag is disabled, the functionality related to verifiable credentials will not be available for users. + +* The MFE should determine the user's device type, whether it is a desktop or mobile device. If the user opens verifiable credentials interface from desktop, the QR Code generated on a server should be displayed. If the user requests its credentials from a mobile device, the option to download the credentials using a deep link is shown. + +* The learner may choose several credentials to issue, and then add them one-by-one into the digital wallet app. + +Consequences +------------ + +Learners will have greater opportunities to share the Open edX credentials in the real world. + +The `Learner Record`_ micro-frontend will be extended with an optional functionality for verifiable credentials. + +Rejected Alternatives +--------------------- + +* Create a new micro-frontend for verifiable credentials. + +* Use Django templates and legacy theming to implement user interface for the verifiable credentials in the Credentials Service. + +References +---------- + +Technical design proposal for verifiable credentials: https://openedx.atlassian.net/wiki/spaces/OEPM/pages/3490840577/Verifiable+Credentials+design#Design-Proposal + +User Interface wireframes: https://openedx.atlassian.net/wiki/spaces/OEPM/pages/3490840577/Verifiable+Credentials+design#MFE-wireframes + +.. _`verifiable credentials`: https://www.w3.org/TR/vc-data-model/ + +.. _`Learner Record`: https://github.com/openedx/frontend-app-learner-record diff --git a/docs/event_bus.rst b/docs/event_bus.rst new file mode 100644 index 000000000..0f61e804f --- /dev/null +++ b/docs/event_bus.rst @@ -0,0 +1,61 @@ +Event Bus +========= + +The Credentials IDA supports the use of the Open edX Event Bus to consume and publish asynchronous `Open edX Events`_. + +For more information on how to start using the Event Bus in your environment, see the `How to start using the Event Bus`_ doc in the Open edX Confluence and the `Event Bus how-to docs in GitHub`_. + +Events Consumed +~~~~~~~~~~~~~~~ + +Before Credentials can consume these events, you must: + +* Have the appropriate configuration enabled for the LMS to publish course certificate events to the Event Bus: + + * for ``CERTIFICATE_CREATED`` events, you must have the ``SEND_CERTIFICATE_CREATED_SIGNAL`` setting enabled in your LMS configuration + * for ``CERTIFICATE_REVOKED`` events, you must have the ``SEND_CERTIFICATE_REVOKED_SIGNAL`` setting enabled in your LMS configuration + +* Have the ``EVENT_BUS_REDIS_CONSUMERS_ENABLED`` or the ``EVENT_BUS_KAFKA_CONSUMERS_ENABLED`` setting enabled in your Credentials configuration, depending on the underlying Event Bus implementation used in your Open edX environment. + +There is additional configuration required to run the Event Bus in an Open edX environment, this configuration is beyond the scope of this document. Please see `How to start using the Event Bus`_ for more information. + +CERTIFICATE_CREATED +------------------- + +The Credentials IDA supports consuming ``CERTIFICATE_CREATED`` events published by the LMS of ``edx-platform``. If configured, this event is fired by the LMS when a (course) certificate is awarded to a learner. Upon successful processing of this event, a (course) credential is created for the learner in Credentials. + +.. image:: _static/images/course_certificate_awarded.png + :alt: A diagram showing how a course credential is awarded to a learner and how the data moves between the monolith and the Credentials IDA. A textual rendition is availalable in JSON in the document course_certificate_awarded.dsl, also in this repository. + +CERTIFICATE_REVOKED +------------------- + +The Credentials IDA supports consuming ``CERTIFICATE_REVOKED`` events published by the LMS of ``edx-platform``. If configured, this event is fired by the LMS when a (course) certificate is revoked from a learner. Upon successful processing of this event, a (course) credential will be revoked from the learner in Credentials. + +.. image:: _static/images/course_certificate_revoked.png + :alt: A diagram showing how a course credential is revoked from a learner and how the data moves between the monolith and the Credentials IDA. A textual rendition is availalable in JSON in the document course_certificate_revoked.dsl, also in this repository. + +Events Published +~~~~~~~~~~~~~~~~ + +The Credentials IDA supports publishing events to the Event Bus when a (program) credential is awarded or revoked from a learner. + +PROGRAM_CERTIFICATE_AWARDED +--------------------------- + +To publish an event to the Event Bus when a program credential is awarded to a learner, you must enable the ``SEND_PROGRAM_CERTIFICATE_AWARDED_SIGNAL`` in the Credentials IDA's configuration. + +.. image:: _static/images/program_certificate_awarded.png + :alt: A diagram showing how a program credential is awarded to a learner and how the data moves between the monolith and the Credentials IDA. A textual rendition is availalable in JSON in the document program_certificate_awarded.dsl, also in this repository. + +PROGRAM_CERTIFICATE_REVOKED +--------------------------- + +To publish an event to the Event Bus when a program credential is revoked from a learner, you must enable the ``SEND_PROGRAM_CERTIFICATE_REVOKED_SIGNAL`` in the Credentials IDA's configuration. + +.. image:: _static/images/program_certificate_awarded.png + :alt: A diagram showing how a program credential is revoked from a learner and how the data moves between the monolith and the Credentials IDA. A textual rendition is availalable in JSON in the document program_certificate_revoked.dsl, also in this repository. + +.. _Open edX Events: https://github.com/openedx/openedx-events +.. _How to start using the Event Bus: https://openedx.atlassian.net/wiki/spaces/AC/pages/3508699151/How+to+start+using+the+Event+Bus?focusedCommentId=3571417100 +.. _Event Bus how-to docs in GitHub: https://github.com/openedx/openedx-events/tree/main/docs/how-tos diff --git a/docs/index.rst b/docs/index.rst index d4adbfd38..b987b1aed 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -17,12 +17,15 @@ This repository contains the edX Credentials Service, used as the backend to sup internationalization theming credentials_admin + learner_records configuring_certificates - program_records + verifiable_credentials/overview pathways analytics credentials_api + event_bus edx_extensions lms_user_id + program_completion_emails decisions badges/index diff --git a/docs/learner_records.rst b/docs/learner_records.rst new file mode 100644 index 000000000..c268f0fde --- /dev/null +++ b/docs/learner_records.rst @@ -0,0 +1,111 @@ +Learner Records +=============== + +The Credentials IDA keeps track of learners' progress through their courses and programs. A learner can view and share +their achievements in a program, called a ``Program Record``, through the `Learner Record Microfrontend`_ (MFE). + +The Learner Record MFE must be configured and deployed independently from the Credentials IDA. + +A learner *must* be logged in to view their program records, they can navigate to their program records from one of +two places: + +- By clicking the ``View My Records`` button from their LMS Profile page, OR +- By clicking the ``View Program Record`` button from their LMS Program Dashboard page. + +Initially, when a learner visits the Learner Record MFE, the learner will see a list of all programs they are enrolled +in. If desired, a learner can then retrieve their certificate and grade data for each program they are enrolled in. + +Below are a few high level diagrams showing how data is retrieved for rendering a learner's program records. + +Rendering a learner's list of enrolled programs: + +.. image:: _static/images/learner_record_mfe_diagram.png + :alt: A diagram showing how data is retrieved to render a learner's Learner Record. A textual rendition is available in JSON in the document learner_record_mfe.dsl, also in this repository. + +Rendering a learner's program record: + +.. image:: _static/images/learner_record_mfe_program_record_diagram.png + :alt: A diagram showing how data is retrieved to render a learner's Program Record. A textual rendition is available in JSON in the document learner_record_mfe_program_records.dsl, also in this repository. + +Caveat: If a learner has earned a certificate that is *not* associated with a Program, it will not be shown as part of +the learner's Learner Record. + +Configuration +------------- + +Syncing Catalog Data +^^^^^^^^^^^^^^^^^^^^ + +In order for Credentials (and thus the Learner Record MFE) to display program, course, and pathway information to +learners, the system must ingest data from the Catalog (`Course Discovery`_) IDA. + +This catalog data is ingested through use of the `Copy Catalog`_ management command. This command must be run +periodically to keep the catalog data fresh in the Credentials database. + +Enabling Program Records +^^^^^^^^^^^^^^^^^^^^^^^^ + +Program Record support is enabled by default. Optionally, an Administrator may disable support for the program record +feature by disabling the ``Enable Learner Records`` checkbox in your site's ``Site Configuration`` (via Django Admin). + +Creation +-------- + +Program Records don't have a concrete representation in the Credentials database. + +The Credentials IDA receives certificate and grade data from the LMS as learners' progress and complete their courses. +When a learner accesses the records of a specific program, their certificate and grade data is retrieved from the +Credentials IDA's records and displayed. + +Backpopulation +^^^^^^^^^^^^^^ + +If, for any reason, you need to backpopulate certificate or grade data in Credentials, you can run the +`Notify Credentials`_ (LMS) management command. + +Sharing +------- + +The Learner Record MFE supports the ability for a learner to share their program progress. When a learner click the +``Create program record link`` button, a public version of the program record page is created. Anyone with that link can +view it, without needing to be logged in (or requiring an account). + +.. image:: _static/images/learner_record_mfe_create_program_record_link.png + :alt: A screenshot of an example program record page, highlighting the location of the "Create program record link" button. + +In addition, the public program record page includes a ``Download program record`` button that downloads a CSV version +of the learner's progress in their program. + +.. image:: _static/images/learner_record_mfe_download_program_record.png + :alt: A screenshot of an example public program record page, highlighting the location of the "Download program record" button. + +Currently, there is no user management of the shared record. If a learner wants to stop sharing a public program +record, an admin must delete the record's entry via Django Admin (through the ``ProgramCertRecord`` model). + +Sharing For Credit +^^^^^^^^^^^^^^^^^^ + +A learner can also choose to send a program record to a site partner, to receive credit from that partner for the +certificates they have earned. This is referred to as a ``Credit Pathway``. + +When a learner shares their program progress through a pathway (by clicking the ``Share program record`` button), an +email is sent to the selected partner with a link to the Learner's public program record page. If a public version of +the program record does not exist at this time, one is created. + +.. image:: _static/images/learner_record_mfe_share_program_record.png + :alt: A screenshot of an example program record page, highlighting the location of the "Share program record" button. + +Each partner will have their own process for initiating or processing a credit request and is beyond the scope of this +document. + +Read the `Pathways`_ documentation for more information on how to enable and configure credit requesting +credit. + +If no credit pathways are enabled for a given program, the ``Send Learner Record`` button will not appear on the +learner's program record page. + +.. _Learner Record Microfrontend: https://github.com/openedx/frontend-app-learner-record +.. _Course Discovery: https://github.com/openedx/course-discovery +.. _Copy Catalog: https://github.com/openedx/credentials/blob/master/credentials/apps/catalog/management/commands/copy_catalog.py +.. _Notify Credentials: https://github.com/openedx/edx-platform/blob/master/openedx/core/djangoapps/credentials/management/commands/notify_credentials.py +.. _Pathways: https://github.com/openedx/credentials/blob/master/docs/pathways.rst diff --git a/docs/lms_user_id.rst b/docs/lms_user_id.rst index d3a2ed9e1..f1dcd3c26 100644 --- a/docs/lms_user_id.rst +++ b/docs/lms_user_id.rst @@ -5,15 +5,14 @@ According to `OEP-32`_, The **LMS_USER_ID** is now the standard for uniquely ide #. If a user is awarded a credential by the LMS, when credentials is notified, a user in the **CORE_USER** table is created. The **LMS_USER_ID** will now also be populated. #. If a user logs into the system, and navigates to their record page, if a user does not already exist for them in the credentials service, one will be created and the **LMS_USER_ID** will be populated. +#. If the system is configured to use the event bus to consume (course) ``CERTIFICATE_CREATED`` events, and if the user doesn't exist in Credentials yet, a user in the **CORE_USER** table is created. The **LMS_USER_ID** will be populated. Backpopulating Pre-existing users ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Although new users interacting with the system will automatically have this column populated, users who already exist in the system will not. For those users, a `management command`_ exists to backpopulate the data. This command requires an S3 bucket to dump information into. The command also allows for stepped completion, to facilitate manually verifying information before completing the process. +Although new users interacting with the system will automatically have this column populated, users who already exist in the system will not. -Usage -~~~~~ -Although credentials now supports **LMS_USER_ID**, it is not currently being widely used within the service. It is only being updated for new users, and is not required for use with any API. If the data is missing from a user, there should be no issues for general operation of the service. +For those users, a `management command`_ exists to backpopulate the data. This management command utilizes endpoints in the LMS to retrieve and sync missing ids for learners in Credentials. .. _OEP-32: https://open-edx-proposals.readthedocs.io/en/latest/oep-0032-arch-unique-identifier-for-users.html -.. _management command: https://github.com/openedx/credentials/blob/master/credentials/apps/core/management/commands/sync_lms_user_ids.py -.. _required for that user to have the **LMS_USER_ID**: https://github.com/openedx/credentials/blob/b5ceeaceaea23ba209510b0bafa4404e26ce87c9/credentials/apps/credentials/issuers.py#L183 \ No newline at end of file +.. _management command: https://github.com/openedx/credentials/blob/master/credentials/apps/core/management/commands/sync_ids_from_platform.py +.. _required for that user to have the **LMS_USER_ID**: https://github.com/openedx/credentials/blob/b5ceeaceaea23ba209510b0bafa4404e26ce87c9/credentials/apps/credentials/issuers.py#L183 diff --git a/docs/program_completion_emails.rst b/docs/program_completion_emails.rst new file mode 100644 index 000000000..237abc0ed --- /dev/null +++ b/docs/program_completion_emails.rst @@ -0,0 +1,65 @@ +Program Completion Emails +========================= + +The Credentials IDA can be configured to send a congratulatory message to learners upon successful completion of their +programs. + +Learners will only receive a single message per Program. If a learner was to have a program credential revoked (e.g. +they are no longer passing a course that is part of the program), and then re-earn their program certificate at a later +date, they will *not* receive another completion message. + +This feature supports defining both HTML and PlainText message templates and uses `edX ACE`_ to send the messages. + +.. image:: _static/images/program_completion_email.png + :alt: A diagram showing the components involved in sending a program completion message to a learner. A textual rendition is availalable as JSON in the document program_completion_emails.dsl, also in this repository. + +Configuration +------------- + +This feature is gated by both a feature flag and some additional configuration (in the form of a +**Program Completion Email Configuration**). + +Feature Flag +~~~~~~~~~~~~ + +To enable this feature the ``SEND_EMAIL_ON_PROGRAM_COMPLETION`` setting must be added to the Credential IDA's +configuration and set to **True**. This feature is disabled by default. + +Program Completion Email Configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Once the feature is enabled, an Open edX Administrator must create a **Program Completion Email Configuration** that +defines the content of the messages sent to learners. These configurations are managed via Django Admin. + +.. image:: _static/images/screenshot_program_completion_email_django_admin.png + :alt: Credential's Django Admin interface, the Credentials management group, with Program Completion Email Configurations as the third item down in the list. + +The first step is adding a unique **identifier** for the configuration. If you would like a base template that defines +a message for all program completers, this identifier should be ``default``. If you would like a message to be sent to +all learners of a specific Program type, the identifier should be the program type slug (e.g. +``professional-certificate``, ``xseries``, or ``masters``). If you would like a message to be sent to all learners of a +specific Program, the identifier should be the Program's UUID (from Discovery). + +By default, the HTML templates support the following elements: ``a``, ``b``, ``blockquote``, ``div``, ``em``, ``i``, +``li``, ``ol``, ``p``, ``span``, ``strong``, ``ul``, and heading levels ``h1`` through ``h6``. The list of acceptable +HTML elements can be modified by updating the ``ALLOWED_EMAIL_HTML_TAGS`` setting in the Credentials configuration. + +Lastly, the ``Enabled`` checkbox must be enabled to enable the configuration. + +How It Works +------------ + +When sending a Program Completion Email, the system will select the **most specific** template to a learner. Consider +the following scenario. There is a default configuration, a **Professional Certificate** program type configuration, +and a configuration for a specific Program (we will refer to it as **Program A**). + +* Learner 1 is enrolled in **Program A**. Upon completion, they will receive the program specific **Program A** message. +* Learner 2 is enrolled in a **Professional Certificate** program. Upon completion, they will receive the program level + message. +* Learner 3 is enrolled in an **XSeries** program. Upon completion, they will receive the default message (as there is + no program specific template nor a template defined for the **XSeries** program type). + +If there is no default template defined a learner will not receieve any message from the system upon completion of +their program. + +.. _edX ACE: https://github.com/openedx/edx-ace diff --git a/docs/testing.rst b/docs/testing.rst index 07a4ac84b..7d64acbcb 100644 --- a/docs/testing.rst +++ b/docs/testing.rst @@ -11,11 +11,10 @@ To make testing easier, there are a few commands that mirror our suites in CI: .. code-block:: bash - $ make acceptance_tests_suite $ make unit_tests_suite $ make quality_and_translations_tests_suite -This will run acceptance tests, the Python and Javascript tests, and our quality and translation suite, respectively. +This will run the Python, the Javascript tests, and our quality and translation suite, respectively. Writing Python Tests diff --git a/docs/verifiable_credentials/_puml/verifiable_credentials-issuance-sequence.puml b/docs/verifiable_credentials/_puml/verifiable_credentials-issuance-sequence.puml new file mode 100644 index 000000000..288b843bf --- /dev/null +++ b/docs/verifiable_credentials/_puml/verifiable_credentials-issuance-sequence.puml @@ -0,0 +1,58 @@ +@startuml name "Verifiable Credentials" + +title "Full issuance process (mobile wallet)" + +autonumber + +actor Learner as learner +box "Open edX" +participant "Learner Record MFE" as mfe +participant "Credentials IDA\n(verifiable_credentials)" as credentials +end box +box "Storage Backends" +participant "Mobile Wallet" as mobile +end box + +learner -> mfe : Opens tab \n"Verifiable Credentials" + +mfe -> credentials : Fetch Learner's program certificates +mfe <-- credentials : UserCredential data list + +rnote over mfe: Program Certificate cards displayed + +mfe -> credentials : Fetch available storages +mfe <-- credentials : storages configuration + +alt a single storage special case + rnote over mfe: "Create" button rendered + learner -> mfe : Clicks "Create" button +else multiple storage case + rnote over mfe: "Create with..." dropdown rendered + learner -> mfe : Clicks "Create with..." dropdown and\npicks a desired storage/wallet +end + +mfe -> credentials : Issuance initialization\n POST "/init/: {credential ID, storage ID} + +rnote over credentials: Issuance line created: \n- UserCredential association \n- Storage backend resolved \n- Issuer resolved \n- Data model resolved \n- Deep-link generated + +mfe <-- credentials : Backend-specific data \n{deep-link, QR code, apps download links} + +alt mobile client + rnote over mfe: Displays modal with:\n- deeplink button \n- apps download links \n- additional instructions + rnote over learner : Optionally downloads, \ninstalls mobile application + learner -> mfe : Clicks "Download Credential" +else web client + rnote over mfe: Displays modal with:\n- **QR code** \n- deeplink button \n- apps download links \n- additional instructions + rnote over learner : Optionally downloads, \ninstalls mobile application + learner -> mfe : Scans QR code with mobile application +end + +mfe -> mobile : Deeplink initiates mobile openning + +rnote over mobile: Storage process deeplink params \nand composes issuance request + +credentials <- mobile : Verifiable credential issuance request\n POST "/issue/: {issuance line ID} +rnote over credentials: Issuance process: \n- request validation \n- issuance line update \n- gathering data \n- credential document composition \n- document signing \n- serialization +credentials --> mobile : Verifiable credential returned + +@enduml \ No newline at end of file diff --git a/docs/verifiable_credentials/components.rst b/docs/verifiable_credentials/components.rst new file mode 100644 index 000000000..286e75751 --- /dev/null +++ b/docs/verifiable_credentials/components.rst @@ -0,0 +1,174 @@ +Components +========== + +The Verifiable Credentials feature includes the following parts: + +- **Verifiable Credentials application** (`credentials.apps.verifiable_credentials` within the Open edX Credentials IDA); +- **Learner Record MFE** (`frontend-app-learner-record` micro-frontend); +- third-party plugins (see `Extensibility`_) +- digital wallets (see `Storages`_) + +Verifiable Credentials application +---------------------------------- + +The core backend logic and all related API are encapsulated in the `Verifiable Credentials application`_. + +Once the Verifiable Credentials feature `is enabled `__: + +1. Admin site "Verifiable Credentials" section becomes available in the Credentials IDA. +2. Extra urls become available in the Credentials IDA. +3. Extra API endpoints become available within the Credentials IDA. + +Administration site +~~~~~~~~~~~~~~~~~~~ + +Application section includes: + +- a list of available issuers +- a list of initiated issuance lines + +.. image:: ../_static/images/verifiable_credentials-admin-section.png + :alt: Admin section + +Currently, only a single Issuer configuration can be active in a moment of time: + +.. image:: ../_static/images/verifiable_credentials-issuer-configuration.png + :alt: Issuance Configurations + +Issuance configuration describes an Issuer - Organization/University/School on behalf of which verifiable credentials are created. Issuer's ID becomes a part of a verifiable credential and a cryptographic proof is generated with the help of Issuer's private key. Each Issuer has a verbose name. It can be deactivated (checkbox). + +.. note:: + Private key itself is a secret that is generated with the help of a cryptographic software. + Issuer ID must be a `decentralized identifier`_ created based on a private key. + +Issuance Line + Each request for a verifiable credential issuance initiates a separate Issuance Line. It tracks verifiable credential processing life cycle and keeps a connection with a source Open edX user achievement. + +.. image:: ../_static/images/verifiable_credentials-issuance-lines.png + :alt: Issuance Lines + +Issuance line has its unique identifier and additionally includes this information: + +1. **User Credential** - related Open edX achievement (e.g. "Program Certificate") +2. **Issuer ID** - issuer's which signs this verifiable credential +3. **Storage ID** - a storage backend (digital wallet) which will keep a verifiable credential +4. **Processing status** - if a verifiable credential was successfully uploaded to storage +5. **Status list info** - indicates if a verifiable credential still valid and unique status index within an Issuer's status list + +Learner Record Microfrontend +----------------------------- + +The Verifiable Credentials feature extends the `Learner Record MFE`_ with additional UI. An extra "Verifiable Credentials" page (tab) becomes available. + +.. image:: ../_static/images/verifiable_credentials-learner-record-mfe.png + :alt: Verifiable Credentials page + +1. Once the Verifiable Credentials feature `is enabled `__ tabs navigation appears +2. All learner's Open edX credentials (currently, program certificates only) are listed within the page +3. Achievement card has an action button that allows verifiable credential requesting based on the corresponding Open edX credential +4. Storages options (experimental) + +.. note:: + Currently, a single (built-in) storage backend is implemented out of the box (`Learner Credential Wallet`_). In this case the only storage option is available by default, so "Create" action button won't have a dropdown. Additional storages appear under the "Create with" dropdown automatically once configured. + +Status List API +--------------- + +There are a plenty of reasons verifiable credential may be already invalid, inactive or disposed: + +- revocation +- implicit expiration +- a lot of other purposes + +Open edX maintains status for internal credentials ("awarded", "revoked"). + +.. note:: + Once a Program Certificate X is revoked - **all** verifiable credentials which were issued based on that achievement must become revoked as well. + +Public Status List API allows instant verifiable credentials checks. Each issuer maintains its own statuses sequence. Every issued verifiable credential takes a unique position in that sequence. + +.. code-block:: sh + + # Status List API endpoint: + GET /verifiable_credentials/api/v1/status-list/2021/v1// + + # Example: + https://credentials.example.com/verifiable_credentials/api/v1/status-list/2021/v1/did:key:z6MkkePoGJV8CQJJULSHHUEv71okD9PsrqXnZpNQuoUfb3id/ + +A full set of status-related information is baked into a verifiable credential: + +- where to find status list API endpoint +- what's the exact status position in a sequence + +.. note:: + See Status List v2021 approach `Privacy Considerations`_ + +Status List example +~~~~~~~~~~~~~~~~~~~ + +Status List itself is a verifiable credential. But it serves a different purpose. + +.. code-block:: sh + + # specific Issuer's status list: + + { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://w3id.org/security/suites/ed25519-2020/v1", + "https://w3id.org/vc/status-list/2021/v1" + ], + "id": "https://credentials.example.com/verifiable_credentials/api/v1/status-list/2021/v1/did:key:z6MkkePoGJV8CQJJULSHHUEv71okD9PsrqXnZpNQuoUfb3id/", + "type": [ + "VerifiableCredential", + "StatusList2021Credential" + ], + "credentialSubject": { + "id": "https://credentials.example.com/verifiable_credentials/api/v1/status-list/2021/v1/did:key:z6MkkePoGJV8CQJJULSHHUEv71okD9PsrqXnZpNQuoUfb3id/#list", + "type": "StatusList2021", + "encodedList": "H4sIAJzSq2QC/+3BAQ0AAADCoPdPbQ43oAAAAAAAAAAAAODfAC7KO00QJwAA", + "statusPurpose": "revocation" + }, + "issuer": { + "id": "did:key:z6MkkePoGJV8CQJJULSHHUEv71okD9PsrqXnZpNQuoUfb3id" + }, + "issuanceDate": "2023-05-16T20:33:39Z", + "proof": { + "type": "Ed25519Signature2020", + "proofPurpose": "assertionMethod", + "proofValue": "z2qgpEUHecAxtRNuRXqPavaLwq2cfTzLSykFa8FPEVxvuPxBkfHdqo17XTpA2q9wR7CYwBjsfDBXT2amXAZbRqdPz", + "verificationMethod": "did:key:z6MkkePoGJV8CQJJULSHHUEv71okD9PsrqXnZpNQuoUfb3id#z6MkkePoGJV8CQJJULSHHUEv71okD9PsrqXnZpNQuoUfb3id", + "created": "2023-07-10T09:42:52.259Z" + }, + "issued": "2023-05-16T20:33:39Z", + "validFrom": "2023-05-16T20:33:39Z" + } + +Status Entry example +~~~~~~~~~~~~~~~~~~~~ + +Every verifiable credential carries its status list "registration" info. + +.. code-block:: sh + + # specific verifiable credential status section: + + "credentialStatus": { + "id": "https://credentials.example.com/verifiable_credentials/api/v1/status-list/2021/v1/did:key:z6MkkePoGJV8CQJJULSHHUEv71okD9PsrqXnZpNQuoUfb3id/#15", + "type": "StatusList2021Entry", + "statusListCredential": "https://credentials.example.com/verifiable_credentials/api/v1/status-list/2021/v1/did:key:z6MkkePoGJV8CQJJULSHHUEv71okD9PsrqXnZpNQuoUfb3id/", + "statusPurpose": "revocation", + "statusListIndex": "15" + }, + +Also see related `management command`_ + + +.. _Verifiable Credentials application: https://github.com/openedx/credentials/tree/master/credentials/apps/verifiable_credentials +.. _Learner Record MFE: https://github.com/openedx/frontend-app-learner-record +.. _Extensibility: extensibility.html +.. _decentralized identifier: https://en.wikipedia.org/wiki/Decentralized_identifier +.. _Learner Credential Wallet: https://lcw.app/ +.. _Privacy Considerations: https://w3c.github.io/vc-status-list-2021/#privacy-considerations +.. _management command: configuration.html#status-list-helper +.. _storages: storages.html \ No newline at end of file diff --git a/docs/verifiable_credentials/configuration.rst b/docs/verifiable_credentials/configuration.rst new file mode 100644 index 000000000..7f2c615a5 --- /dev/null +++ b/docs/verifiable_credentials/configuration.rst @@ -0,0 +1,192 @@ +Configuration +============= + +Verifiable Credentials feature is optional. It is disabled by default. + +Learner Record micro-frontend +----------------------------- + +The most of configuration is related to the Credentials IDA (`verifiable_credentials` app), but there are few UI-related settings. + +``ENABLE_VERIFIABLE_CREDENTIALS`` (boolean) - enables feature appearance (extra routes) + +``SUPPORT_URL_VERIFIABLE_CREDENTIALS`` (URL string) - footer support link + +Verifiable Credentials application +---------------------------------- + +``ENABLE_VERIFIABLE_CREDENTIALS`` (boolean) - main feature flag + +The feature introduces its own set of default settings which are namespaced in the VERIFIABLE_CREDENTIALS setting, like this: + +.. code-block:: python + + VERIFIABLE_CREDENTIALS = { + 'DEFAULT_DATA_MODELS': [ + "credentials.apps.verifiable_credentials.composition.open_badges.OpenBadgesDataModel", + ], + "STATUS_LIST_LENGTH": 50000, + "DEFAULT_ISSUER": { + "NAME": "The University of the Digital Future", + "KEY": '{"kty":"OKP","crv":"Ed25519","x":"IGUT8E_aRNzLqouWO4zdeZ6l4CEXsVmJDOpOQS69m7o","d":"vn8xgdO5Ki3zlvRNc2nUqcj50Ise1Vl1tlbs9DUL-hg"}', + "ID": "did:key:z6MkgdiV7pVPCapM8oUwfhxBwYZgh8dXkHkJykSAc4DHKD7X", + }, + } + +Such configuration overrides the corresponding built-in settings: + +1. Data models list narrowed down to a single specification +2. Status list length extended to 50K positions +3. Default issuer configured with concrete credentials + +Built-in values +--------------- + +There is a set of built-in predefined settings: + +.. code-block:: python + + # verifiable_credentials/settings.py + + DEFAULTS = { + "DEFAULT_DATA_MODELS": [ + "credentials.apps.verifiable_credentials.composition.verifiable_credentials.VerifiableCredentialsDataModel", + "credentials.apps.verifiable_credentials.composition.open_badges.OpenBadgesDataModel", + ], + "DEFAULT_STORAGES": [ + "credentials.apps.verifiable_credentials.storages.learner_credential_wallet.LCWallet", + ], + "DEFAULT_ISSUER": { + "ID": "generate-me-with-didkit-lib", + "KEY": "generate-me-with-didkit-lib", + "NAME": "Default (system-wide)", + }, + "DEFAULT_ISSUANCE_REQUEST_SERIALIZER": "credentials.apps.verifiable_credentials.issuance.serializers.IssuanceLineSerializer", + "DEFAULT_RENDERER": "credentials.apps.verifiable_credentials.issuance.renderers.JSONLDRenderer", + "STATUS_LIST_STORAGE": "credentials.apps.verifiable_credentials.storages.status_list.StatusList2021", + "STATUS_LIST_DATA_MODEL": "credentials.apps.verifiable_credentials.composition.status_list.StatusListDataModel", + "STATUS_LIST_LENGTH": 10000, + } + +Default data models +------------------- + +Deployment configuration can override `data models set`_ with the respect of the following restrictions: + +- there always must be at least 1 data model available +- each storage is pre-configured to use some data model which must be available + +Default storages +---------------- + +Deployment configuration can override `storages set`_ with the respect of the following restrictions: + +- there always must be at least 1 storage available + + +Default issuer +-------------- + +.. note:: + Currently, there is only a single active issuer (system-wide) available So, all verifiable credentials are created (issued) on behalf of this Issuer. + +There is the `Issuance Configuration`_ database model, which initial record is created based on these settings. + +NAME +~~~~ + +Verbose issuer name (it is placed into each verifiable credential). + +KEY +~~~ + +A private secret key (JWK) which is used for verifiable credentials issuance (proof/digital signature generation). It can be generated with the help of the `didkit`_ Python (Rust) library. + +ID +~~ + +A unique issuer decentralized identifier (created from a private key, `example`_). + +Status List configuration +------------------------- + +Length +~~~~~~ + +``STATUS_LIST_LENGTH`` - default = 10000 (16KB) + +Possibly, the only status list settings to configure. A status sequence positions count (how many issued verifiable credentials statuses are included). See `related specs`_ for details. + +Storage +~~~~~~~ + +``STATUS_LIST_STORAGE`` + +A technical storage class (allows status list implementation override). + +Data model +~~~~~~~~~~ + +``STATUS_LIST_DATA_MODEL`` + +A data model class (allows status list implementation override). + +---- + +Other settings are available for advanced tweaks but usually are not meant to be configured: + +- Default issuance request serializer (incoming issuance request parsing) +- Default renderer (outgoing verifiable credential presentation) + +Management commands +------------------- + +There are a couple of service commands available for the verifiable_credentials application. + +Issuer credentials helper +~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Generates private key for Issuer (JWK) and a decentralized identifier (DID) based on that key.** + +.. code-block:: sh + + root@credentials:/edx/app/credentials/credentials# ./manage.py generate_issuer_credentials + >> {'did': 'did:key:z6MkgdiV7pVPCapM8oUwfhxBwYZgh8dXkHkJykSAc4DHKD7X', + 'private_key': '{"kty":"OKP","crv":"Ed25519","x":"IGUT8E_aRNzLqouWO4zdeZ6l4CEXsVmJDOpOQS69m7o","d":"vn8xgdO5Ki3zlvRNc2nUqcj50Ise1Vl1tlbs9DUL-hg"}'} + +Issuer configuration helpers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Create initial Issuance Configuration based on deployment issuer(s) setup.** + +.. code-block:: sh + + root@credentials:/edx/app/credentials/credentials# ./manage.py create_default_issuer + +Initial Issuance configuration is created based on VERIFIABLE_CREDENTIALS[DEFAULT_ISSUER] via data migration during the first deployment. Helper allows manually repeat that is needed (Additional configurations can be created from django admin interface). + +**Remove Issuance Configuration based on Issuer ID.** + +.. code-block:: sh + + root@credentials:/edx/app/credentials/credentials# ./manage.py remove_issuance_configuration did:key:z6MkgdiV7pVPCapM8oUwfhxBwYZgh8dXkHkJykSAc4DHKD7X + +Issuance configuration delete operation is forbidden in admin interface (only deactivation is available). This tool allows to cleanup configurations list if needed. + +Status List helper +~~~~~~~~~~~~~~~~~~ + +**Generate Status List 2021 verifiable credential** + +.. code-block:: sh + + root@credentials:/edx/app/credentials/credentials# ./manage.py generate_status_list did:key:z6MkgdiV7pVPCapM8oUwfhxBwYZgh8dXkHkJykSAc4DHKD7X + +Allows Status List verifiable credential generation (for a given Issuer ID). + +.. _data models set: extensibility.html#data-models +.. _storages set: extensibility.html#storages +.. _didkit: https://pypi.org/project/didkit/ +.. _example: https://github.com/spruceid/didkit-python/blob/main/examples/python_django/didkit_django/issue_credential.py#L12 +.. _related specs : https://w3c.github.io/vc-status-list-2021/#revocation-bitstring-length +.. _Issuance Configuration: components.html#administration-site \ No newline at end of file diff --git a/docs/verifiable_credentials/extensibility.rst b/docs/verifiable_credentials/extensibility.rst new file mode 100644 index 000000000..9c1c2dc96 --- /dev/null +++ b/docs/verifiable_credentials/extensibility.rst @@ -0,0 +1,64 @@ +Extensibility +============= + +Storages +-------- + +Storage backend classes describe a destination for issued verifiable credentials. Basically, storages are wallets (mobile or web applications). + +See available options on `Storages page`_. + +Data Models +----------- + +Data model classes are `DRF`_ serializers which compose verifiable credentials of different specifications. + +Credentials data models +~~~~~~~~~~~~~~~~~~~~~~~ + +There are 2 specifications included by default: + +- `Open Badges Specification v3.0`_ (see `OB3.0 model`_) +- `Verifiable Credentials Data Model v1.1`_ (see `VC1.1 model`_) - experimental + +Additional specifications may be implemented as separate `plugins`_. + +Credentials status information +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. note:: + + Status information allows instant checks to figure out if the presented verifiable credential is still valid. The credential issuer can invalidate a verifiable credential by updating its indexed record in the status list. + +`Status List v2021`_ is a special kind of verifiable credential. It serves as a mechanism of verification for issued verifiable credentials (meaning, it does not carry achievement information itself but it is a registry of statuses for all created achievement-related verifiable credentials). + +- `Verifiable Credential Status List v2021`_ + +There are 2 parts of the approach: + +- status entry (becomes a part of each issued verifiable credential and carries the info "how to check status") +- status list (an Issuer-centric separate freely reachable statuses registry) + +Plugins +------- + +Both `data models`_ and `storages`_ may be implemented as Credentials IDA installable pluggable applications. + +.. note:: + + For storage plugin example, please, see the `openedx-wallet`_ training storage (by the `Raccoon Gang`_) . + +.. _Verifiable Credentials Data Model v1.1: https://www.w3.org/TR/vc-data-model-1.1/ +.. _Open Badges Specification v3.0: https://1edtech.github.io/openbadges-specification/ob_v3p0.html +.. _Verifiable Credential Status List v2021: https://w3c.github.io/vc-status-list-2021/ +.. _data models: extensibility.html#data-models +.. _storages: extensibility.html#storages +.. _storages page: storages.html +.. _plugins: extensibility.html#plugins +.. _Raccoon Gang : https://raccoongang.com +.. _Learner Credential Wallet: https://lcw.app +.. _DRF: https://www.django-rest-framework.org/ +.. _Status List v2021: components.html#status-list-api +.. _VC1.1 model: https://github.com/openedx/credentials/tree/master/credentials/apps/verifiable_credentials/composition/verifiable_credentials.py +.. _OB3.0 model: https://github.com/openedx/credentials/tree/master/credentials/apps/verifiable_credentials/composition/open_badges.py +.. _openedx-wallet: https://github.com/raccoongang/openedx-wallet \ No newline at end of file diff --git a/docs/verifiable_credentials/overview.rst b/docs/verifiable_credentials/overview.rst new file mode 100644 index 000000000..b13182be8 --- /dev/null +++ b/docs/verifiable_credentials/overview.rst @@ -0,0 +1,27 @@ +Verifiable Credentials +====================== + +An optional feature that allows issuance of the `Verifiable Credentials`_ based on the Open edX achievements. + + *Verifiable credentials will allows us to represent our achievements in a provable, portable, sharable, privacy and autonomy preserving way.* + +Please, see `Extensibility`_ section for the list of supported: + +- verifiable credential specifications (data models) +- digital wallets (storages) + +---- + +.. toctree:: + :maxdepth: 1 + + quickstart + usage + components + configuration + extensibility + storages + tech_details + +.. _Verifiable Credentials: https://en.wikipedia.org/wiki/Verifiable_credentials +.. _Extensibility: extensibility.html \ No newline at end of file diff --git a/docs/verifiable_credentials/quickstart.rst b/docs/verifiable_credentials/quickstart.rst new file mode 100644 index 000000000..0755e9e53 --- /dev/null +++ b/docs/verifiable_credentials/quickstart.rst @@ -0,0 +1,87 @@ +Quick Start +=================================== + +.. contents:: Steps + :local: + :class: no-bullets + +This guide outlines initial preparations for the Verifiable Credentials feature. + +1. Feature activation +--------------------- + +Since Verifiable Credentials feature is optional, it must be enabled to be accessible. + +.. code:: + + # both Credentials service and Learner Record MFE: + ENABLE_VERIFIABLE_CREDENTIALS = true + +See Configuration_ for more details. + +2. Issuer credentials generation +-------------------------------- + +Once enabled Verifiable Credentials feature has reasonable defaults. The only additional activity is needed - issuer_ credentials setup. Unless we already have appropriate issuer key and issuer ID, we have to generate those: + +.. code:: + + # use management command: + root@credentials:/edx/app/credentials/credentials# ./manage.py generate_issuer_credentials + >> { + 'did': 'did:key:z6MkgdiV7pVPCapM8oUwfhxBwYZgh8dXkHkJykSAc4DHKD7X', + 'private_key': '{"kty":"OKP","crv":"Ed25519","x":"IGUT8E_aRNzLqouWO4zdeZ6l4CEXsVmJDOpOQS69m7o","d":"vn8xgdO5Ki3zlvRNc2nUqcj50Ise1Vl1tlbs9DUL"}' + } + +Here: + + - "did" - unique Issuer decentralized identifier + - "private_key" - Issuer private JWK + +See `Management commands`_ for more details. + +3. Issuer credentials setup +--------------------------- + +Generated issuer credentials we'll use to update automatically generated with stub values Issuance Configuration. + +Enter Credentials Administration interface and find "VERIFIABLE CREDENTIALS" section (`/admin/verifiable_credentials/issuanceconfiguration/`). + +.. code:: + + Issuer id: use "did" + Issuer key: use "private_key" + Issuer name: will be used as issuer's verbose name + +.. note:: + :class: dropdown + + Make sure the configuration is enabled. + +See `Administration site`_ for more details. + +4. Ensure status list is accessible +----------------------------------- + +Status List API endpoint is crucial for the feature. Once everything is configured correctly it must be publicly available: + +.. code:: + + # each Issuer maintains its own Status List: + https://credentials.example.com/verifiable_credentials/api/v1/status-list/2021/v1// + +See `Status List API`_ for more details. + +5. Issuer registration (Learner Credential Wallet) +-------------------------------------------------- + +This step is specific for the Learner Credential Wallet storage. + +See Learner Credential Wallet `usage prerequisites`_. + +.. _issuer: https://www.w3.org/TR/vc-data-model-1.1/#dfn-issuers +.. _configuration: configuration.html#configuration +.. _management commands: configuration.html#management-commands +.. _administration site: components.html#administration-site +.. _status list API: components.html#status-list-api +.. _usage prerequisites: storages.html#usage-prerequisites \ No newline at end of file diff --git a/docs/verifiable_credentials/storages.rst b/docs/verifiable_credentials/storages.rst new file mode 100644 index 000000000..83f202b5d --- /dev/null +++ b/docs/verifiable_credentials/storages.rst @@ -0,0 +1,155 @@ +Storages +======== + +Currently there is the only digital wallet is supported for production. + +Learner Credential Wallet +------------------------- + +`Official web-site`_: + + Learner Credential Wallet is an open source mobile wallet developed by the Digital Credentials Consortium, a network of leading international universities designing an open infrastructure for academic credentials. + +Learner Credential Wallet (LCWallet) is a mobile app available for Android and IOS devices. + +Usage prerequisites +~~~~~~~~~~~~~~~~~~~ + +LCWallet maintainer (`Digital Credentials Consortium`_) requires verifiable credentials issuer to be allow-listed (included to the trusted issuers list - `community issuer registry`_). + +.. note:: + + For development/testing purposes a `Sandbox Registry`_ is available. If you would like to be added to the Sandbox Registry, please open a pull requests directly against that repository, matching the format for existing issuers in `registry.json` + +Learner experience +~~~~~~~~~~~~~~~~~~ + +This explains a generic usage flow for learners. + +#. Learners have to download and install the official application (Google Play or App Store, we'll use Android version for examples). + +#. Once installed there is initial one-time setup guide. + + .. image:: ../_static/images/verifiable_credentials-lcw-setup1.png + :alt: Learner Credential Wallet setup step 1 + :width: 30% + .. image:: ../_static/images/verifiable_credentials-lcw-setup2.png + :alt: Learner Credential Wallet setup step 2 + :width: 30% + .. image:: ../_static/images/verifiable_credentials-lcw-setup3.png + :alt: Learner Credential Wallet setup step 3 + :width: 30% + +#. Learners navigate Learner Record MFE interface (`Verifiable Credentials tab`_) and claim for a verifiable credential issuance (clicking a :guilabel:`Create` button). + +#. On the next step learners are asked for QR code scanning - that's where the LCWallet app starts its flow. Learners use :guilabel:`Scan QR code` option in the mobile application. + + .. image:: ../_static/images/verifiable_credentials-lcw-home-empty.png + :alt: Learner Credential Wallet empty + :width: 30% + .. image:: ../_static/images/verifiable_credentials-lcw-add-credential.png + :alt: Learner Credential Wallet add credential + :width: 30% + .. image:: ../_static/images/verifiable_credentials-lcw-qrcode-scanner.png + :alt: Learner Credential Wallet QR code scanner + :width: 30% + +#. LCWallet processes QR code, communicates with the Open edX Platform and gets new verifiable credential. If everything is correct, now digital wallet holds the verifiable credential for the given Open edX credential (program certificate). + + .. image:: ../_static/images/verifiable_credentials-lcw-accept-credential.png + :alt: Learner Credential Wallet accept credential + :width: 30% + .. image:: ../_static/images/verifiable_credentials-lcw-credential-preview.png + :alt: Learner Credential Wallet credential preview + :width: 30% + .. image:: ../_static/images/verifiable_credentials-lcw-verification-status.png + :alt: Learner Credential Wallet credential status + :width: 30% + +#. From this point learners are free to share their achievements in different ways + + .. image:: ../_static/images/verifiable_credentials-lcw-share.png + :alt: Learner Credential Wallet share credential + :width: 30% + .. image:: ../_static/images/verifiable_credentials-lcw-share-public-link.png + :alt: Learner Credential Wallet share credential with public link + :width: 30% + .. image:: ../_static/images/verifiable_credentials-lcw-share-public-link-created.png + :alt: Learner Credential Wallet shared with public link credential + :width: 30% + +.. code:: + + # an example of a verifiable presentation being shared: + { + "@context": [ + "https://www.w3.org/2018/credentials/v1" + ], + "type": [ + "VerifiablePresentation" + ], + "verifiableCredential": [ + { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://w3id.org/security/suites/ed25519-2020/v1", + "https://w3id.org/vc/status-list/2021/v1", + "https://purl.imsglobal.org/spec/ob/v3p0/context.json" + ], + "id": "urn:uuid:7e33f82c-474b-4331-9cb7-71d2ace136e4", + "type": [ + "VerifiableCredential", + "OpenBadgeCredential" + ], + "credentialSubject": { + "id": "did:key:z6MkoXpRTvd9KhEdbjaieR2XCs6XewVyW32dyKjG1GoPGNww", + "name": "demo", + "achievement": { + "criteria": { + "narrative": "Demo successfully completed all courses and received passing grades for a Professional Certificate in dcc program a program offered by , in collaboration with Open edX." + }, + "description": "Program certificate is granted on program dcc program completion offered by , in collaboration with Open edX. The dcc program program includes 1 course(s).", + "id": "31187856-01ac-4abc-9b77-4add9cf7c50b", + "name": "Program certificate for passing a program dcc program", + "type": "Achievement" + }, + "type": "AchievementSubject" + }, + "issuer": { + "id": "did:key:z6MkkePoGJV8CQJJULSHHUEv71okD9PsrqXnZpNQuoUfb3id", + "type": "Profile", + "name": "Default verifiable credentials issuer" + }, + "issuanceDate": "2023-07-10T15:25:41Z", + "proof": { + "type": "Ed25519Signature2020", + "proofPurpose": "assertionMethod", + "proofValue": "z5HRVyz1ZHUY7f8m6ttUS7JViKqwhFBWt2caEnauEAKmWs69ud93ok6AMrmfjZe1bLdrLcPusVNtNXCzwHXLaFJmJ", + "verificationMethod": "did:key:z6MkkePoGJV8CQJJULSHHUEv71okD9PsrqXnZpNQuoUfb3id#z6MkkePoGJV8CQJJULSHHUEv71okD9PsrqXnZpNQuoUfb3id", + "created": "2023-07-10T15:25:41.581Z" + }, + "credentialStatus": { + "id": "https://credentials.example.com/verifiable_credentials/api/v1/status-list/2021/v1/did:key:z6MkkePoGJV8CQJJULSHHUEv71okD9PsrqXnZpNQuoUfb3id/#6", + "type": "StatusList2021Entry", + "statusPurpose": "revocation", + "statusListIndex": "6", + "statusListCredential": "https://credentials.example.com/verifiable_credentials/api/v1/status-list/2021/v1/did:key:z6MkkePoGJV8CQJJULSHHUEv71okD9PsrqXnZpNQuoUfb3id/" + }, + "name": "Program certificate for passing a program dcc program", + "issued": "2023-07-10T15:25:41Z", + "validFrom": "2023-07-10T15:25:41Z" + } + ] + } + +Other options +------------- + +Additionally, you can install the `openedx-wallet`_ POC for investigation/onboarding purposes. This wallet is not recommended for production deployment. + +.. _Official web-site: https://lcw.app/ +.. _Digital Credentials Consortium: https://digitalcredentials.mit.edu/ +.. _community issuer registry: https://github.com/digitalcredentials/community-registry +.. _`Sandbox Registry`: https://github.com/digitalcredentials/sandbox-registry +.. _`Verifiable Credentials tab`: components.html#learner-record-microfrontend +.. _openedx-wallet: https://github.com/raccoongang/openedx-wallet \ No newline at end of file diff --git a/docs/verifiable_credentials/tech_details.rst b/docs/verifiable_credentials/tech_details.rst new file mode 100644 index 000000000..1dab77d6a --- /dev/null +++ b/docs/verifiable_credentials/tech_details.rst @@ -0,0 +1,57 @@ +Implementation Details +====================== + +The following may clarify implicit internal details. + +Prerequisites +------------- + +Required initial activities. + +1. Before the main feature flag (settings) is enabled the verifiable_credentials app won't register its urlconf, admin. +2. Default built-in configuration is almost self-contained - the only required step is to configure Issuer's credentials (see `management command helper`_). If Issuer is configured in deployment environment from the start, those settings are used during the app data migration, otherwise manual Issuance Configuration edit is needed (Credentials admin site). +3. There can be a list of Issuance Configuration records, but only the last enabled is taken into account in current implementation. + +Events flow +----------- + +Here is how everything happens. + +.. image:: ../_static/images/verifiable_credentials-issuance-sequence.png + :alt: Verifiable Credentials issuance sequence diagram + +- 1 - Learner navigates to the Learner Record MFE, enters the Verifiable Credentials page. +- 2,3 - Frontend fetches all Learner's credentials (program certificates). +- 4,5 - Frontend fetches configured storages list. +- Learner chooses theirs credential (program certificate) to issue verifiable credential for. +- 6,7 - Learner initiates an issuance (standard case: single storage, experimental case: many storages). +- 8 - Issuance Line is created with given context (storage + program certificate). +- 9 - all pre-requisites are evaluated and deep-link/QR-code generated. +- Learner is present modal dialog with deep-link/QR-code to proceed with a mobile wallet app. +- 10,11 - Learner interacts with a dialog data (clicks/scans). +- 12 - Learner navigates to a mobile wallet app. +- 13 - mobile wallet app requests verifiable credential from an issuance API endpoint (on behalf of a Learner). +- verifiable_credentials application processes Issuance Line data (collects required data, composes it into a desired shape, evaluates status list data, adds signature). +- 14 - well-formed verifiable credential returned to a mobile wallet app. +- Mobile app verifies given verifiable credential (validates structure, signature, status info). + +New dependencies +---------------- + +Verifiable Credentials feature has introduced a couple of extra packages. + +didkit-python +~~~~~~~~~~~~~ + +``didkit==0.3.2`` + +A tool for verifiable credentials operations (issuance, verification, signing, validation). + +qrcode +~~~~~~ + +``qrcode==7.4.2`` + +We generate mobile deep-link QR-codes on a backend. + +.. _management command helper: configuration.html#issuer-credentials-helper diff --git a/docs/verifiable_credentials/usage.rst b/docs/verifiable_credentials/usage.rst new file mode 100644 index 000000000..1001cca03 --- /dev/null +++ b/docs/verifiable_credentials/usage.rst @@ -0,0 +1,61 @@ +Usage +===== + +The Open edX platform allows students to earn credentials (e.g. course certificates, program certificates). Based on such credentials learners are able to create a digital cryptographically proved peace of data - a verifiable credential. + +.. note:: + Verifiable credentials are aimed for machines. + +A single Open edX achievement can be used as a source for numerous verifiable credentials (identical or different data models). + +Verifiable credential includes data about: + +- who has achieved it (subject) + - student's unique decentralized identifier (DID); + - student's arbitrary personal data (optional); +- what exactly was achieved (credential) + - type (program certificate); + - title (program name, possibly courses list); +- when it happened (timestamp) + - date and time verifiable credential was created (issued); + - expiration moment (optionally); +- who proves it (issuer) + - there is always at least one issuer - organization/university/etc. who "confirms" credential's data is the Truth; +- how to check if it is still valid (status) + - there are different status check methods; + - there are different reasons for status update (source achievement revocation, for example); + +**All that data is signed, so it can't be tampered in any way - that's the point.** + +Learners +-------- + +The general usage flow is the following: + +- **Student** finishes a course/program and **earns an achievement/credential** (e.g. Program Certificate X); +- **Student requests a verifiable credential** that confirms Program Certificate X exists (additional background can be included as well - e.g. average/total grade, etc.); +- The **Open edX platform creates (issues)** a verifiable credential on behalf of related Issuer (Organization/University/School); +- **Verifiable credential is uploaded** to some Learner's storage (verifiable credentials wallet, a mobile/web app); +- **Student presents** a verifiable credential to any Interested Party (another Org/University/School); +- **Interested Party verifies** a verifiable credential's status - checks if it wasn't tampered in any way; checks if it still has valid status (not expired, not revoked); + +.. note:: + Please, see the `Learner Record micro-frontend`_ for details. + +Administrators +-------------- + +The Open edX users with administrator rights are able to manage/monitor the Verifiable Credentials application within the Credentials IDA admin site. + +.. note:: + Please, see the `Verifiable Credentials application`_ for details. + +Relying Parties +--------------- + +Third-parties whom a verifiable credential is presented want to ensure the current status of such artifact. That's where the `Status List`_ mechanism comes into play. + + +.. _Learner Record micro-frontend: components.html#learner-record-microfrontend +.. _Verifiable Credentials application: components.html#verifiable-credentials-application +.. _Status List: components.html#status-list-api \ No newline at end of file diff --git a/requirements/docs.txt b/requirements/docs.txt index 04f2af974..deca965fc 100644 --- a/requirements/docs.txt +++ b/requirements/docs.txt @@ -14,7 +14,7 @@ charset-normalizer==2.1.1 # via requests docutils==0.19 # via sphinx -edx-sphinx-theme==3.0.0 +sphinx-book-theme # via -r requirements/docs.in idna==3.4 # via requests