SCORM Runtime and API

Since version 1.3.0: BricksMembers includes a SCORM Cloud-backed runtime for package import, package-to-post assignment, learner launch, provider sync, Cloud postbacks, and completion bridging into the canonical progress system.

This developer post documents the SCORM subsystem as implemented in BricksMembers. The module is intentionally provider-scoped: SCORM Cloud is the only exposed runtime provider, while local manifest parsing is used only for validation and metadata extraction before upload.

Ownership summary

ConcernOwner
Module bootstrapBaselMedia\BricksMembers\Modules\Scorm\ScormFeatureRegistrar
Schema installationBaselMedia\BricksMembers\Modules\Scorm\ScormSchemaService
Package, SCO, assignment, registration, runtime, and event rowsBaselMedia\BricksMembers\Modules\Scorm\ScormRepository
Settings and secret-preserving normalizationBaselMedia\BricksMembers\Modules\Scorm\ScormSettingsService
SCORM ZIP validation and import orchestrationBaselMedia\BricksMembers\Modules\Scorm\ScormPackageImportService
Manifest parsingBaselMedia\BricksMembers\Modules\Scorm\ScormManifestParser
SCORM Cloud API callsBaselMedia\BricksMembers\Modules\Scorm\ScormCloudApiClient
SCORM Cloud provider behaviorBaselMedia\BricksMembers\Modules\Scorm\ScormCloudProvider
Registration, launch, sync, and snapshotsBaselMedia\BricksMembers\Modules\Scorm\ScormRegistrationService
Completion bridgeBaselMedia\BricksMembers\Modules\Scorm\ScormProgressBridgeService
Admin-post transportBaselMedia\BricksMembers\Modules\Scorm\ScormAdminActionHandler
REST transportBaselMedia\BricksMembers\Modules\Scorm\ScormRestController
Bricks element adapterBRM_Element_Scorm_Player

The canonical write owner for SCORM rows is ScormRepository. Transport adapters must validate input and delegate. SCORM completion must go through ScormProgressBridgeService and ProgressCompletionService; SCORM code must not write progress tables directly.

Bootstrap path

  1. ModuleRegistry reads brm_enable_scorm.
  2. ScormFeatureRegistrar::boot() returns early when the module is inactive.
  3. When active, the registrar installs additive schema through ScormSchemaService.
  4. Admin-post actions, REST routes, cron hooks, and the Bricks element delegate to SCORM services.
  5. Recurring cron hooks sync recent Cloud registrations and purge old event rows.

The feature map for ownership and routing is docs/feature-maps/scorm.md. Update it whenever entry points, write owners, provider boundaries, storage, or completion flow changes.

Storage contract

The SCORM schema is additive and versioned by ScormSchemaService. It creates the following tables when the module is active:

  • wp_brm_scorm_packages
  • wp_brm_scorm_scos
  • wp_brm_scorm_post_assignments
  • wp_brm_scorm_registrations
  • wp_brm_scorm_runtime_values
  • wp_brm_scorm_events

Settings live in brm_scorm_settings. SCORM Cloud secret and postback secret values live behind SecretOptionService using brm_scorm_cloud_secret_key and brm_scorm_cloud_postback_secret.

Admin-post actions

ActionHandlerBehavior
brm_save_scorm_settingshandle_save_settings()Saves provider defaults, Cloud API settings, launch TTL, diagnostics, and optional postback-secret rotation.
brm_import_scorm_packagehandle_import()Validates the uploaded ZIP, parses the manifest, creates package metadata, and uploads to SCORM Cloud.
brm_assign_scorm_packagehandle_assign()Connects a package UUID to a target post with completion policy, optional score, and launch mode.
brm_sync_scorm_importhandle_sync_import()Refreshes SCORM Cloud import status for a package with an import job ID.

All admin-post actions require RoleCapabilityRegistry::CAP_MANAGE_SCORM and a matching nonce. They redirect back to the SCORM admin surface with a status or error code.

REST API

RouteMethodPermissionBehavior
/wp-json/bricksmembers/v1/scorm/packagesGETSCORM admin capabilityLists packages for admin UI/API consumers.
/wp-json/bricksmembers/v1/scorm/importPOSTSCORM admin capabilityImports a package from REST file params.
/wp-json/bricksmembers/v1/scorm/launchPOSTLogged-in user plus rate limit; content access checked in callbackCreates or reuses a learner registration and returns a SCORM Cloud launch link.
/wp-json/bricksmembers/v1/scorm/sync/{provider_registration_id}POSTRegistration owner or SCORM admin plus rate limitSyncs provider status and applies completion bridge if eligible.
/wp-json/bricksmembers/v1/scorm/cloud/postbackPOSTRate limit plus postback secret inside callbackReceives SCORM Cloud postbacks and syncs the referenced registration.

The Cloud postback route is public at the REST permission layer because SCORM Cloud cannot send a WordPress nonce. It still authenticates with the configured secret before it mutates provider registration state.

Launch and sync flow

  1. The brm-scorm-player Bricks element posts the current post ID to /scorm/launch.
  2. ScormRestController::launch() requires a logged-in user and checks read_post.
  3. Non-admin users also pass through ContentAccessGateService::can_user_access_content_now().
  4. ScormRegistrationService::build_launch_for_post() reads the current post assignment, creates or reuses a registration, and asks the provider for a launch URL.
  5. The frontend opens the launch URL embedded or in a new window, depending on the assignment or element override.
  6. SCORM Cloud postbacks or explicit sync requests call ScormRegistrationService::sync_provider_registration().
  7. The sync stores the provider snapshot and asks ScormProgressBridgeService whether BricksMembers progress should be completed.

Completion bridge

ScormProgressBridgeService evaluates the assignment completion policy against the synced registration snapshot. Supported policies are completed, passed, complete_or_passed, complete_and_passed, and score_threshold.

When the policy passes, the bridge calls ProgressCompletionService with trigger metadata that identifies SCORM as the source. This preserves the normal progress contract for downstream dashboards, automations, and structure progress.

Bricks element contract

BRM_Element_Scorm_Player registers the brm-scorm-player element. The element renders a launch shell only. It does not store package IDs, provider launch URLs, or progress data.

  • postId: optional post context override.
  • launchMode: assignment default, embedded iframe, or new window.
  • buttonText: visible launch label.
  • button_style, button_size, acss_button_style, and acss_button_size: shared checkout/button style controls reused for the launch button.

The element enqueues assets/js/scorm-player.js and localizes the REST URL, REST nonce, and UI strings. User-facing JavaScript strings must continue to come from localized PHP data.

Security model

  • SCORM ZIP uploads are untrusted and must go through ScormPackageImportService.
  • ZIP import validates file type, byte limits, entry count, unsafe paths, manifest size, manifest XML, and launchable SCO presence.
  • Admin mutation routes require CAP_MANAGE_SCORM plus dedicated nonces.
  • Launch requires a logged-in user, post read permission, and active BricksMembers content access for non-admin users.
  • Launch, sync, and postback routes use explicit RateLimiting action buckets.
  • Cloud postbacks require the configured postback secret and reject oversized payloads.
  • Provider credentials and postback secrets are stored with SecretOptionService.

Provider boundary

SCORM Cloud integration is isolated in ScormCloudApiClient and ScormCloudProvider. Do not add provider-specific HTTP calls to controllers, elements, cron callbacks, or repositories.

Do not expose a local SCORM runtime option unless the implementation includes a real runtime adapter, secure local asset serving, CMI persistence, attempt/resume behavior, and browser compatibility coverage.

Testing guidance

SCORM changes should be covered at the cheapest layer that can fail the regression. Unit coverage should focus on manifest parsing, upload rejection, settings normalization, repository writes, launch permission, postback authentication, sync behavior, and completion policy mapping. Browser or WordPress-admin smoke coverage is appropriate when changing the SCORM admin page or Bricks element behavior.

At minimum, run targeted PHPUnit coverage for the changed SCORM owner, PHPCS for changed PHP files, PHPStan, security QA for REST/postback changes, and release QA when the change affects package behavior or public release docs.

Edit guidance

  • Start in ScormSettingsService for credentials, defaults, launch TTL, retention, and secret rotation.
  • Start in ScormPackageImportService for upload validation and package import orchestration.
  • Start in ScormCloudApiClient or ScormCloudProvider for provider transport changes.
  • Start in ScormRegistrationService for launch, registration, sync, and provider snapshots.
  • Start in ScormProgressBridgeService for completion-policy behavior.
  • Start in ScormRestController or ScormAdminActionHandler only for transport validation and response behavior.
  • Update docs/feature-maps/scorm.md, docs/modules/scorm.md, and the user/developer posts when ownership, routes, storage, security, or launch/completion behavior changes.
Get BricksMembers

Start Building Your Membership Site Today

Create, sell, and manage your content without limits. BricksMembers gives you everything you need to build membership and LMS sites with Bricks Builder.

Lifetime updates & bug fixes • Premium support • 0% transaction fees • 60-day money-back guarantee