The Problem: A Silent Integration
In week one of Google Summer of Code 2026, a contributor working on CircuitVerse—an open-source digital logic simulator—discovered that the LMS-LTI integration with Canvas was broken in four separate ways. The integration looked complete on the surface: code existed, routes were defined, and the UI accepted inputs. But when a real student clicked "Open Assignment," nothing worked as expected.
The four bugs:
- Student hit a login page
- Student landed on the wrong page
- Teacher couldn't grade
- Grade showed 0 in Canvas
Bug 1: Session Never Established
When a student clicked the LTI link in Canvas, CircuitVerse received the launch data, found the matching user, and even created a blank project. But it never called sign_in(@user). The session was never established.
# Before:
# sign_in(@user) was missing
# After:
sign_in(@user)
This single line fixed the authentication handoff. The student now landed logged in, not on /users/sign_in.
Bug 2: Wrong Redirect
After authentication, the student was redirected to the group's home page (group_path(@group)) instead of their specific project. The fix was straightforward:
# Before:
group_path(@group)
# After:
user_project_path(@user, @project)
Now the student lands directly on their project page with a "Launch Simulator" button.
Bug 3: Grading Form Hidden
The teacher could see the student's circuit but had no grading form. The code hid it until the assignment deadline passed:
def can_be_graded?
mentor_access? && assignment.graded? && (assignment.deadline - Time.current).negative?
end
For testing, the contributor removed both the deadline check and the UI minDate restriction that prevented setting past dates.
Bug 4: Grade Passback to Canvas
After grading, the grade was saved in CircuitVerse but never sent to Canvas. Three conditions had to be true:
- Feature flag:
Flipper.enable(:lms_integration)was required. It was off by default. - LTI session: The teacher had to launch from Canvas (setting
session[:is_lti]), not log in directly. - Max points: Canvas assignment had
max_points = 0. LTI sends scores as a decimal (0-1), so 68/100 → 0.68 × 0 = 0. Setting max points to 100 fixed it.
After all three fixes, the gradebook showed 68/100.
Why This Matters
Each bug returned success codes, loaded pages, and showed no errors. The integration tested each system in isolation—both Canvas and CircuitVerse worked fine. Only end-to-end testing as a real user revealed the broken handoff.
Next Steps
The contributor now plans to upgrade from LTI 1.1 to LTI 1.3, which adds security improvements like OAuth 2.0 and message signatures.

