Area: mobieusLearn (audit p8) · Surface: API /api/v1/learn/cohorts/grant (mobieusLearn — org-purchase cohort provisioning) · Dimension: documentation · Severity: major
The only mobieusLearn v1 API endpoint intended for external/third-party integration (provisioning a multi-seat cohort from a paid org purchase, idempotent on source_reference) has zero public documentation. An integrator reading /api/docs or /know/api-learn would never know it exists, despite the in-code docblock describing the full request body (buyer_user_id, course_id, seat_count, source_reference, etc.) and 200/201 idempotency semantics. This is the most integration-critical Learn endpoint and the only undocumented one.
Evidence
Route is real: /home/patrick/mobieus-io/platform/src/routes.php:272 `$router->post('/learn/cohorts/grant', 'Api\V1\LearnController@cohortsGrant');` and the handler exists at /home/patrick/mobieus-io/platform/src/Controllers/Api/V1/LearnController.php:301 `public function cohortsGrant(): void`. It is explicitly designed for external integrations (comment line 283: "safely retried by Stripe webhook handlers + external integrations"). But it is ABSENT from the public OpenAPI spec served at /api/docs: `curl -s https://support.mobieus.io/api/openapi.yaml | grep -c '/api/v1/learn/cohorts/grant'` returns 0 (all 25 other v1 learn paths are present; this is the only one in code-but-not-spec per `comm -23 code-paths spec-paths` → `/learn/cohorts/grant`). It is also absent from the wiki API article: `curl -s https://support.mobieus.io/know/api-learn | grep -c 'cohorts/grant'` returns 0 (that article documents courses, enrollments, certificates, cert-templates, attempts, modules, lessons, activities, SCORM — but not cohort grant).
Suggested fix. Add the `/api/v1/learn/cohorts/grant` path to /api/openapi.yaml under the Learn tag (mirror the docblock at LearnController.php:277-300 for the request body and 200/201 responses + idempotency note), and add a section to the /know/api-learn wiki article.
Filed by the automated tenant-app audit and adversarially evidence-verified. Status: verified. Open — not yet actioned.
Patrick Bass
@mobieus