add : docomentation

This commit is contained in:
a2nr 2026-05-14 16:33:45 +07:00
parent 7384b6e585
commit 9e5617274e
4 changed files with 275 additions and 0 deletions

View File

@ -0,0 +1,121 @@
# 01. Architecture & Setup
## High-Level System Architecture
The Elemes LMS-C project uses a multi-container architecture orchestrated via Podman, with a Tailscale Funnel acting as the public ingress point.
```
Internet (HTTPS :443)
Tailscale Funnel (elemes-ts)
├── / → SvelteKit Frontend (elemes-frontend :3000)
├── /assets/ → Flask Backend (elemes :5000)
├── /velxio/api/compile → Flask Backend (Rate-limited Proxy :5000)
├── /velxio/ → Velxio Arduino Simulator (velxio :80)
SvelteKit Frontend (elemes-frontend :3000)
├── SSR pages (lesson content embedded in HTML)
├── CodeMirror 6 editor (lazy-loaded)
├── CircuitJS simulator (iframe, GWT-compiled) — mode "circuit"
├── Velxio Arduino simulator (iframe, React) — mode "velxio"
├── API proxy: /api/* → Flask
└── PWA manifest
▼ /api/*
Flask API Backend (elemes :5000)
├── Code compilation (Proxied to Compiler Worker)
├── Arduino Proxy (/velxio-compile → Velxio :80)
├── Token authentication (CSV)
├── Progress tracking
└── Lesson content parsing (markdown)
▼ HTTP
Compiler Worker (compiler-worker :8080)
├── gVisor Sandbox (runsc runtime)
├── Gunicorn (4 workers)
└── Isolation: gcc / python3 execution
Velxio Arduino Simulator (velxio :80)
├── React + Vite frontend (editor + simulator canvas)
├── FastAPI backend (arduino-cli compile)
├── AVR8 / RP2040 CPU emulation (browser)
└── PostMessage bridge ↔ Elemes (EmbedBridge.ts)
```
## Container Setup
| Container | Image | Port | Fungsi |
|-----------|-------|------|--------|
| `elemes` | Python 3.11 | 5000 | Flask API (auth, lessons, progress, compile-proxy) |
| `compiler-worker` | Python 3.11 + gcc | 8080 | **Sandboxed** execution engine (gVisor) |
| `elemes-frontend` | Node 20 | 3000 | SvelteKit SSR |
| `velxio` | Node + Python + arduino-cli | 80 | Simulator Arduino (React + FastAPI) |
| `elemes-ts` | Tailscale | 443 | HTTPS Funnel + reverse proxy |
## Directory Structure
```
project/
├── .env # Konfigurasi environment
├── content/ # Folder materi pelajaran (file .md)
│ ├── home.md # Halaman utama & daftar pelajaran
│ ├── hello_world.md # Contoh materi
│ └── ...
├── assets/ # Gambar untuk materi (opsional)
│ └── gambar.png
├── tokens_siswa.csv # Data token siswa (auto-generated)
├── state/ # State Tailscale (auto-generated)
└── elemes/ # Folder engine LMS (JANGAN DIUBAH)
├── elemes.sh # Script untuk menjalankan LMS
└── ...
```
## Setup and Execution
The primary entry point for managing the system is the `elemes.sh` script located in the `elemes` folder.
1. **Initialization:**
```bash
cd elemes
./elemes.sh init
```
Generates `.env`, `content/`, and `tokens_siswa.csv` from examples. Safe to run multiple times.
2. **Configuration:**
Edit `../.env` to set branding and Tailscale configuration:
```env
APP_BAR_TITLE=Pemrograman C - SMK Nusantara
COPYRIGHT_TEXT=SMK Nusantara @ 2025
PAGE_TITLE_SUFFIX=SMK Nusantara
CONTENT_DIR=content
TOKENS_FILE=tokens.csv
ELEMES_HOST=lms-smk-nusantara
TS_AUTHKEY=tskey-auth-xxxx
```
3. **Running the Application:**
```bash
./elemes.sh runbuild # Build images and start containers
./elemes.sh run # Start containers without rebuilding
./elemes.sh stop # Stop all containers
```
4. **Managing Users (Tokens):**
To update columns in the CSV based on available lessons:
```bash
./elemes.sh generatetoken
```
Then manually edit `tokens_siswa.csv` (using semicolon `;` delimiter) to add student rows. The first data row is always the teacher token.
## Security Overview
The system incorporates several security layers to ensure stability and safety:
1. **Isolated Execution:** User-submitted C and Python code runs inside a `compiler-worker` container protected by a **gVisor (`runsc`) sandbox**, preventing RCE attacks from reaching the host kernel.
2. **Rate Limiting & Tarpitting:**
- Anonymous users: Limited to **1 compile per 2 minutes** per IP, with a global queue of 20 slots.
- Login endpoints: Max **50 requests per minute per IP**.
- Failed logins: Suffer a **1.5-second tarpit delay** to neutralize brute-force attacks.
3. **Cookie Security:** The `student_token` session cookie uses `httponly: true`, `samesite: 'Lax'`, and dynamically sets `secure: true` based on the `COOKIE_SECURE` environment variable.

72
docs/02-backend-flask.md Normal file
View File

@ -0,0 +1,72 @@
# 02. Backend (Flask API)
The backend is built with Flask, providing API endpoints for the SvelteKit frontend to fetch lessons, track progress, manage authentication, and proxy compilation requests.
## Application Factory (`elemes/app.py`)
- `def create_app():`
Initializes the Flask application, loads configuration from `elemes/config.py` (which reads from `.env`), and registers the following blueprints:
- `auth_bp` (`routes/auth.py`)
- `lessons_bp` (`routes/lessons.py`)
- `compile_bp` (`routes/compile.py`)
- `progress_bp` (`routes/progress.py`)
## Core API Routes
### Authentication (`routes/auth.py`)
- `def login():` (POST `/login`)
Receives `token` in JSON payload. Validates via `token_service.validate_token()`. On success, sets the `student_token` cookie. Rate-limited and includes a 1.5s tarpit for failures.
- `def logout():` (POST `/logout`)
Clears the `student_token` cookie.
- `def validate_token_route():` (POST `/validate-token`)
Checks if the current `student_token` cookie is valid.
### Lessons (`routes/lessons.py`)
- `def api_lessons():` (GET `/lessons`)
Returns a list of all lessons and the rendered `home.md` content via `lesson_service.get_ordered_lessons_with_learning_objectives()`.
- `def api_lesson(filename):` (GET `/lesson/<slug>.json`)
Returns the fully parsed lesson data (content, initial code, circuits, key texts, active tabs) via `lesson_service.render_markdown_content(filepath)`.
- `def get_key_text(filename):` (GET `/get-key-text/<slug>`)
Returns only the required keywords for a specific lesson without exposing the full content logic.
### Compilation (`routes/compile.py`)
- `def compile_code():` (POST `/compile`)
Accepts `code` and `language`. Routes execution to the sandboxed worker using the `CompilerFactory`. Incorporates rate-limiting for anonymous users.
- `def velxio_compile():` (POST `/velxio-compile` mapped from `/velxio/api/compile`)
A proxy endpoint that forwards Arduino compilation requests to the Velxio container, enforcing rate limits for anonymous users.
### Progress Tracking (`routes/progress.py`)
- `def track_progress():` (POST `/track-progress`)
Accepts `lesson_name` and `status`. Updates the CSV file via `token_service.update_student_progress()`.
- `def api_progress_report():` (GET `/progress-report.json`)
Returns a matrix of all student progress. Requires a teacher token.
- `def export_progress_csv():` (GET `/progress-report/export-csv`)
Exports progress data as a CSV download. Requires a teacher token.
## Services
### Token Service (`services/token_service.py`)
Manages reads and writes to the `tokens_siswa.csv` file.
- `def _load_tokens_safely() -> Tuple[Dict[str, dict], List[str]]:` Reads CSV data safely.
- `def validate_token(token):` Returns `True` if the token exists.
- `def is_teacher_token(token):` Returns `True` if the token belongs to the first row (the teacher).
- `def get_student_progress(token):` Returns a dictionary of lesson progress for a specific token.
- `def update_student_progress(token, lesson_name, status="completed"):` Writes progress back to the CSV.
### Lesson Service (`services/lesson_service.py`)
Parses Markdown files to extract content and configuration.
- `def get_ordered_lessons_with_learning_objectives(progress=None):` Returns lessons ordered as they appear in `home.md`, optionally injected with user progress status.
- `def render_markdown_content(file_path):` The core parsing function. Uses regex to extract markers like `---INITIAL_CODE---`, `---VELXIO_CIRCUIT---`, etc. It identifies the `active_tabs` needed for the frontend.
- `def _parse_flashcards(text):` Specifically parses `---QUIZ_FLASHCARD---` blocks into a structured JSON array for the frontend MCQ/Flashcard component.
## Compiler Framework (`compiler/`)
The compilation logic is abstracted via a factory pattern.
- `class CompilerFactory:` (`compiler/__init__.py`)
- `def get_compiler(self, language):` Returns the appropriate `BaseCompiler` instance (e.g., `CCompiler` or `PythonCompiler`).
- `class BaseCompiler(ABC):` (`compiler/base_compiler.py`)
- `def compile(self, code, timeout=10):` Abstract method.
- `def run(self, file_path, timeout=5):` Abstract method.
- `class CCompiler(BaseCompiler):` and `class PythonCompiler(BaseCompiler):`
Implementation wrappers that construct payloads and send HTTP requests to the `compiler-worker` container (`http://compiler-worker:8080/execute`).

View File

@ -0,0 +1,39 @@
# 03. Frontend (SvelteKit)
The frontend is built using SvelteKit and Vite. It utilizes Svelte 5 for its reactivity model.
## Framework & State Management
The frontend uses two main state management patterns:
1. **Svelte 5 Runes (`$state`, `$derived`, `$effect`)**: Used extensively in `.svelte` and `.svelte.ts` files. For instance, the lesson view uses `lessonState.svelte.ts` to manage all reactive data (active tabs, compilation status) outside of the UI components, moving away from a "God Component" architecture.
2. **Writable Stores**: Used in standard `.ts` files (e.g., `lib/stores/auth.ts`, `lib/stores/theme.ts`) where Runes are not processed by the Svelte compiler.
## API Services (`lib/services/api.ts`)
This module provides wrappers for all backend calls. In production, SvelteKit uses `hooks.server.ts` to proxy requests starting with `/api/` to the Flask backend.
- `export function login(token: string, customFetch = fetch)`
- `export function logout(customFetch = fetch)`
- `export function validateToken(token: string, customFetch = fetch)`
- `export function getLessons(customFetch = fetch)`
- `export function getLesson(slug: string, customFetch = fetch, token = '')`
- `export function getKeyText(filename: string, customFetch = fetch)`
- `export function compileCode(req: CompileRequest, customFetch = fetch)`
- `export function trackProgress(lessonName: string, status: string = 'completed', customFetch = fetch)`
- `export function resetProgress(lessonName: string, customFetch = fetch)`
## Key Components
- **`LessonWorkspace.svelte`**: The main presentational component for the interactive lesson area. It wraps the editor, output panels, and tab switchers.
- **`CodeEditor.svelte`**: Wraps CodeMirror 6. It is lazy-loaded to reduce the initial bundle size and provides syntax highlighting for C and Python. It also implements strict anti-paste measures.
- **`VelxioIframe.svelte`**: Isolates the initialization of the `VelxioBridge`, the `postMessage` logic, and auto-save capabilities specific to the Arduino simulator.
- **`CircuitEditor.svelte`**: Wraps the Falstad CircuitJS simulator (a GWT-compiled app) inside an iframe. It mounts a transparent `CrosshairOverlay.svelte` on touch devices to enable precise interactions by translating touch events to synthetic mouse events.
## Security & Anti Copy-Paste
To prevent students from copying lesson text or pasting external code:
1. **`lib/actions/noSelect.ts`**: A Svelte action that applies CSS (`user-select: none`) and attaches DOM event listeners (`onselectstart`, `oncopy`, `oncontextmenu` calling `preventDefault()`) to the lesson content.
2. **Code Editor Defenses**: `CodeEditor.svelte` implements multiple layers:
- DOM handlers for `paste`, `drop`, and `beforeinput`.
- CodeMirror transaction filters to block `input.paste` and heuristics (e.g., blocking inserts > 20 characters or > 2 lines).
- Clipboard API overriding when available.

View File

@ -0,0 +1,43 @@
# 04. Lesson Evaluation
The LMS determines the type of lesson and how to evaluate it based on specific markers found in the Markdown content.
## Markdown Markers
| Mode | Marker | Evaluation Logic |
|------|--------|------------------|
| **C / Python** | `---INITIAL_CODE---` / `---INITIAL_PYTHON---` | Standard stdout matching against `---EXPECTED_OUTPUT---` and presence of `---KEY_TEXT---`. |
| **Circuit** | `---INITIAL_CIRCUIT---` | Node voltage matching against `---EXPECTED_CIRCUIT_OUTPUT---` and `---KEY_TEXT_CIRCUIT---`. |
| **Arduino (Velxio)** | `---INITIAL_CODE_ARDUINO---` | Serial output sequence matching, lenient graph wiring comparison, and `---KEY_TEXT---`. |
| **Quiz** | `---QUIZ_FLASHCARD---` | State completion tracking (all questions answered correctly). |
## Evaluators (`lib/services/`)
The evaluation logic is isolated into specific service files:
### General & C/Python (`evaluators.ts`, `exercise.ts`)
- `export function checkKeyText(code: string, keyText: string): boolean`
Checks if all lines in the `keyText` are present in the provided `code`.
- `export function processLanguageEvaluation(...)`
Coordinates the compilation request and output verification for C and Python.
### Circuit Evaluation (`evaluators.ts`, `exercise.ts`)
- `export function evaluateCircuitSubmission(...)`
Handles the flow of extracting the circuit state.
- `export function validateNodes(actualVoltages: Record<string, number>, expectedNodes: Record<string, NodeResult>): boolean`
Validates if the actual node voltages match the expected voltages within a specified tolerance.
### Arduino/Velxio Evaluation (`velxio-evaluator.ts`, `velxio-bridge.ts`)
- `class VelxioBridge` (`velxio-bridge.ts`)
Manages the `window.postMessage` protocol between the LMS and the Velxio iframe.
- Commands: `elemes:load_code`, `elemes:load_circuit`, `elemes:get_source_code`, `elemes:get_serial_log`, `elemes:get_wires`.
- Events: `velxio:ready`, `velxio:compile_result`.
- `export function evaluateVelxioSubmission(...)`
Orchestrates the 3-part Arduino evaluation:
1. **Key Text**: Checks the retrieved source code.
2. **Serial Output**: Uses `matchSerialSubsequence(actual, expected)` to ensure expected log lines appear in the correct order.
3. **Wiring**: Performs a lenient graph comparison (expected edges must exist; extra edges are allowed; ground pins are normalized).
### Flowchart Evaluation (`flowchart-evaluator.ts`)
- `export function evaluateFlowchartSubmission(...)`
Parses flowchart JSON data and verifies structural correctness against the expected model.