Gotchas
Hard-won fixes from real Canvas + Moodle integrations. Most are handled for you; the rest are things only you can set.
AGS / grades
Section titled “AGS / grades”/scoresbefore the query string. Canvas line items carry?type_id=N;/scoresmust go in the path (…/lineitem/scores?type_id=N). Handled byscoresUrl.- Assertion
aud= the token endpoint, not the issuer. Handled bygetToken. gradingProgress: 'FullyGraded'or the grade is stored but never surfaced. Handled bypostScore.- Moodle returns
400 []for non-students. A grade only posts for an enrolled, gradable student — not the admin/teacher who installed the tool. Test as a student. - Request the exact scope (score / lineitem), space-joined.
Launch / identity
Section titled “Launch / identity”- Canvas issuer is
https://canvas.instructure.comfor hosted and most self-hosted (not the web URL). - No-email users (Canvas Test Student, privacy) — identify by
sub, not email. deployment_idmust match the registered platform, or the launch fails validation.
Supabase adapter
Section titled “Supabase adapter”service_roleneeds a table GRANT. RLS bypass ≠ table access; without the grant you getpermission denied(42501) that looks like “platform not found”. The shipped schema includes the grant.- Local Supabase CLI generates its own keys. Don’t assume the well-known demo key — read the actual
service_rolekey fromsupabase status.
Iframe
Section titled “Iframe”- CSP
frame-ancestorsmust list every LMS origin that embeds you (cspFrameAncestors), or the browser blocks the frame. Scheme + host, no trailing slash. - Cookies need
SameSite=None; Secureto survive the cross-site iframe (sameSiteNoneCookie/sessionRedirect); addPartitioned(CHIPS) as third-party cookies are deprecated. - Public tunnel/host. The LMS fetches your JWKS and posts launches server-to-server — the host must be reachable without auth.