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:

  1. Student hit a login page
  2. Student landed on the wrong page
  3. Teacher couldn't grade
  4. 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:

  1. Feature flag: Flipper.enable(:lms_integration) was required. It was off by default.
  2. LTI session: The teacher had to launch from Canvas (setting session[:is_lti]), not log in directly.
  3. 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.