Skip to content

Latest commit

 

History

History
106 lines (79 loc) · 5.59 KB

File metadata and controls

106 lines (79 loc) · 5.59 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Running the Server

# Start (production)
npm start

# Start (dev, auto-restarts on file change)
npm run dev

# As a systemd service (installed on this machine)
sudo systemctl start ap-python-server
sudo systemctl restart ap-python-server
sudo systemctl status ap-python-server
sudo journalctl -u ap-python-server -f   # live logs

There are no automated tests. Verify behavior by running the server and hitting the endpoints directly.

Required Environment

The server will refuse to start without a .env file containing at minimum:

SESSION_SECRET=<hex string>
PORT=4000
NODE_ENV=production
DEFAULT_TEACHER_PASSWORD=SMCSChief
ALLOWED_ORIGINS=http://localhost:4000,http://127.0.0.1:4000,http://<server-ip>:4000

Critical: cookie.secure in the session config (server.js:178) is hardcoded to false — do not change it back to process.env.NODE_ENV === 'production'. The server runs HTTP only; secure: true silently drops session cookies and breaks all auth.

Architecture

The entire backend is a single file: server.js (~3600 lines). database.js handles SQLite initialization only and is required once.

Data layer

  • SQLite via the sqlite3 package (callback-style, not promise-based)
  • DB file: appython.db in the project root — excluded from git; copy it manually when migrating machines
  • Schema is defined and migrated in database.js via ALTER TABLE ... ADD COLUMN IF NOT EXISTS guards

Key tables:

Table Purpose
students Accounts with bcrypt-hashed passwords, login tracking, lockout
assignments Title + markdown prompt + rubric + is_visible + tab_monitoring_enabled + max_submissions
submissions Code, feedback, grade (stored as string e.g. "9/12"), execution output
project_files Multi-file project support; one row per file per student per assignment
drafts Auto-saved code (upsert on student_id + assignment_id)
tab_violations Records when students navigate away during a monitored quiz
settings Key/value store: claude_api_key, teacher_password (bcrypt hash), ai_model, teacher_network_access, etc.
canvas_student_mapping Maps internal student IDs to Canvas LMS user IDs per course
submission_adjustments Per-student overrides to max_submissions

Authentication model

Two separate sessions share the same express-session / session-file-store:

  • Teacher: req.session.isTeacher === true — set on POST /api/teacher/login
  • Student: req.session.studentId — set on POST /api/student/login

Teacher endpoints additionally enforce localhostOnly middleware unless teacher_network_access is '1' in the settings table. This flag is loaded into the module-level variable teacherNetworkAccessEnabled at startup and updated in-memory when toggled via the API.

AI / grading pipeline

  • The Anthropic client is instantiated per-request via getAnthropicClient(), which reads the API key from the DB each time.
  • Grading uses Claude tool use: callGradingAI() forces the model to call the grade_submission tool, which returns structured rubric_scores (array of sections with earned/possible points) + narrative_feedback. processGradingResult() sums the scores and appends the grade string.
  • AI tutor (/api/chat) streams nothing — it returns a single response. It reads chat history from the DB for context and passes the student's current code and last console output in the system prompt.
  • The AI model used for both grading and tutoring is read from settings.ai_model at request time.

Python code execution

/api/run-code writes student code to a temp file and runs it with:

  • python3 -u solution.py (unbuffered output for real-time streaming)
  • 10-second execution timeout via setTimeout + process.kill()
  • 50,000-character output cap

Interactive execution (input() support) uses Socket.io: the client connects via WebSocket, the server spawns the Python process and pipes stdout/stderr back over the socket, and stdin is fed in as the user types.

Frontend

Static files in public/. No build step — plain HTML/CSS/JS served directly.

  • student.html — student coding interface (CodeMirror editor with Python mode, AI tutor chat, submit)
  • pyteacher13.html — teacher dashboard (assignments, submissions, grades, settings, Canvas sync)
  • index.html — landing page

Canvas LMS integration

The teacher dashboard can sync grades to Canvas. Config (API token + base URL) is stored in settings.canvas_config. The /api/canvas/* routes proxy requests to the Canvas REST API and handle the student name → Canvas user ID mapping via canvas_student_mapping.

Inserting data directly (bypassing the API)

When the API requires authentication that's hard to automate, it's safe to insert into the DB directly using a Node script run from the project root (where node_modules/sqlite3 is available):

const sqlite3 = require('sqlite3');
const db = new sqlite3.Database('appython.db');
db.run('INSERT INTO assignments ...', [...values], function(err) { ... });

Run with node <script>.js from /home/student/Documents/PythonQuizAISite/.

Service and deployment notes

  • Systemd service file: needs to be created/updated for Python site (port 4000)
  • Sessions stored in ./sessions/ (file-based, 7-day TTL)
  • Logs written to ./logs/ (combined, error, security — rotating at 10MB)
  • The appython.db database is the single source of truth for all application state; back it up before making schema changes