Skip to content

Feat/studio activities - #1013

Merged
jakeaturner merged 11 commits into
stagingfrom
feat/studio-activities
Oct 28, 2026
Merged

jakeaturner merged 11 commits into
stagingfrom
feat/studio-activities

Conversation

@jakeaturner

Copy link
Copy Markdown
Collaborator

No description provided.

Conductor owns everything around an H5P activity: title, authorship,
collaborators, visibility, subjects, tags and licensing. h5p-service owns
the content and addresses it by the integer content id Studio assigned.

- Activity and ActivityCollection models.
- Commons read API: /commons/activities, /commons/activities/:activityID,
  /commons/activities/h5p/:h5pContentID, /commons/activities/author/:uuid,
  and /commons/activities-adapt-feed, the CSV that replaces Studio's
  /api/v2/nodes for ADAPT.
- Commons activity page at /activity/:activityID, embedding from
  CLIENT__H5P_EMBED_ORIGIN.
- Ignores studio_main/ (a copy of the legacy Studio install, which holds
  credentials) and migration-reports/.
…orters

Reads a Studio MySQL database read-only. Each importer is a dry run unless
given --commit, upserts by natural key so a re-run resumes, and
pseudonymises identities unless given --with-identities. Pseudonymised
records are stamped dataClass "synthetic".

- StudioImportActivities, StudioImportCollections and
  StudioImportLegacyPaths (with the StudioLegacyNode model).
- StudioSurvey and StudioArchiveExport.
- SQL fixtures with synthetic data for running against ephemeral databases.
- mysql2 3.24.6 as a devDependency.

All three importers ran on staging with the full corpus on 2026-10-26.
GET /commons/studio-legacy/:kind(h5p|node|collection)/:value answers with
a redirect to the activity's Commons page, using the paths and aliases the
legacy path importer recorded. Cloudflare sends old Studio page URLs here
after cutover. LibreTexts instance only.
- My H5P at /h5p: the signed-in user's owned and collaborating activities,
  with search and filters (GET /activities/mine).
- Create and edit screen at /h5p/new and /h5p/:activityID/edit. It frames
  h5p-service's editor page and saves metadata alongside content.
- Authoring API: POST /activities, PATCH and DELETE /activities/:activityID,
  editor tokens, subjects, and a cleanup job for activities whose first
  save never happened (PUT /activities/automation/cleanup, LibreAPI key).
- Conductor checks ownership and signs Ed25519 capability tokens for
  h5p-service (H5P_CAPABILITY_PRIVATE_KEY, H5P_SERVICE_URL).
  scripts/generate-h5p-capability-keys.mjs creates the key pair.

Hidden unless CLIENT__H5P_AUTHORING_ENABLED is "true". The API answers
503 (err93) until H5P_SERVICE_URL and the private key are set.
Replacements for the five Studio API paths ADAPT calls, in Studio's exact
shapes: bare arrays, string values, Drupal's escaping and date formats.

  /api/h5p/all?changed=, /api/h5p/{id}  -> /studio/h5p/:idOrAll
  /api/author/{email}                   -> /studio/author/:email (Basic auth)
  /api/collections/list, /{cid}         -> /studio/collections/...

The studio.libretexts.org Worker forwards each path here once it passes
scripts/diff-studio-compat.mjs against responses captured from Studio.
All five diff clean on staging.

These and /commons/activities-adapt-feed answer 404 outside
APP_ENV=production unless ADAPT_FEEDS_OUTSIDE_PRODUCTION=true. In
production they serve only dataClass "production" records.
/studio/author needs STUDIO_COMPAT_BASIC_USER and
STUDIO_COMPAT_BASIC_PASSWORD, and refuses everyone until both are set.
Copilot AI balanced review requested due to automatic review settings October 27, 2026 05:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

Comment thread server/api/activities.ts
Comment thread server/api/activities.ts
Comment thread server/api/activity-authoring.ts Outdated
Comment thread server/api/activity-authoring.ts Outdated
@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Severity: High — activity.ts:151: Migrated authors without Conductor accounts never regain ownership. The importer leaves createdBy empty and promises a lifecycle-webhook backfill, but no such backfill is implemented. Authorization checks only createdBy/collaborators, so these authors cannot manage their activities after registering. Backfill ownership when accounts are linked, or resolve ownership through authorCentralID.

Severity: Medium — Edit.tsx:397: After a metadata-save failure, subsequent Save clicks retry metadata and return without saving the editor. If the author makes further content changes before retrying, the UI reports “Activity saved” while those changes remain unsaved. Check editor/display-option changes before taking this shortcut.

Severity: Low — activities.ts:251: The anonymous H5P-ID lookup returns the entire activity document, including collaborators and internal identity/migration fields that the regular activity endpoint explicitly excludes. Use an allowlisted projection, ideally returning only the identifier needed for resolution.

* trailing slash, lowercase. The import and the resolver must agree on this.
*/
export function normalizeStudioAlias(alias: string): string {
const trimmed = alias.trim().replace(/\/+$/, "");
Comment thread server/scripts/generate-h5p-capability-keys.mjs Fixed
The link showed on every deployment, so merging to master would have shown
production users an empty My H5P before the Studio import. It now follows
CLIENT__H5P_AUTHORING_ENABLED, like New H5P and Edit.

Also polishes My H5P and the editor screen:
- New H5P comes after Upload, in the primary colour.
- Save and Delete get icons, and Delete is centred.
- The delete dialog's warning moves out of Dialog.Description into the body.
- Clearer helper text for the description and the metadata fields.
POST /activities and the new-activity editor token answer 403 (err94) unless
the user's verifiedInstructor is true. Owners and collaborators still edit
without verification. My H5P hides New H5P and Upload for everyone else, and
/h5p/new explains the rule and links to the verification request.
Replaces Studio's adapt cron. PUT /activities/automation/adapt-ids calls
ADAPT's PATCH get-adapt-question-id-by-h5p-id for up to 100 production
activities with no adaptID (500 with ?limit=), least recently checked first,
and records each attempt in adaptIDCheckedAt. Studio always took the 50 newest
nodes, so activities ADAPT never imported blocked the rest.

The Bearer token is STUDIO_COMPAT_BASIC_PASSWORD, which is ADAPT's
H5P_API_PASSWORD. ADAPT_ID_SYNC_EMAIL picks between several ADAPT questions on
one content id, as Studio's fixed address did. A found id moves updatedAt, as
Studio's node save moved changed, so ADAPT's ?changed= poll sees it. Outside
production the route answers 404 and the service refuses to contact ADAPT.
Copilot AI balanced review requested due to automatic review settings October 27, 2026 22:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

Copilot AI balanced review requested due to automatic review settings October 27, 2026 23:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

{
orgID: process.env.ORG_ID,
// The validator limits machine names to letters, digits, "_", "." and "-".
library: { $regex: `^${machineName.replace(/[.-]/g, "\\$&")} ` },
Copilot AI balanced review requested due to automatic review settings October 28, 2026 04:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

@jakeaturner
jakeaturner merged commit cb05b5d into staging Oct 28, 2026
8 of 10 checks passed
@jakeaturner
jakeaturner deleted the feat/studio-activities branch October 28, 2026 04:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants