<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ilias Almerekov</title>
    <description>The latest articles on DEV Community by Ilias Almerekov (@iliasalmerekov).</description>
    <link>https://dev.to/iliasalmerekov</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3956020%2F72d7bd34-06c2-40e6-8c25-f68fc28c9697.jpeg</url>
      <title>DEV Community: Ilias Almerekov</title>
      <link>https://dev.to/iliasalmerekov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/iliasalmerekov"/>
    <language>en</language>
    <item>
      <title>Reviving My School's AI Assistant: Moodle + Ollama</title>
      <dc:creator>Ilias Almerekov</dc:creator>
      <pubDate>Thu, 28 May 2026 07:54:01 +0000</pubDate>
      <link>https://dev.to/iliasalmerekov/reviving-my-schools-ai-assistant-moodle-ollama-4o63</link>
      <guid>https://dev.to/iliasalmerekov/reviving-my-schools-ai-assistant-moodle-ollama-4o63</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/github-2026-05-21"&gt;GitHub Finish-Up-A-Thon Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Moodle AI Assistant — an AI-powered learning companion embedded directly into Moodle, the LMS used at my vocational school Berufsschule ITECH in Germany, where I'm training as a Fachinformatiker (IT Specialist)&lt;/p&gt;

&lt;p&gt;This project means a lot to me because it solves a real problem I see every day at school: students get stuck on assignments after hours, teachers get flooded with the same repeated questions, and there's no smart help available on demand. I built this to change that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Github Repository: &lt;a href="https://github.com/IliasAlmerekov/moodle" rel="noopener noreferrer"&gt;https://github.com/IliasAlmerekov/moodle&lt;/a&gt;&lt;br&gt;
Demo Video: &lt;a href="https://youtube.com/shorts/Iiy4re43cMM?feature=share" rel="noopener noreferrer"&gt;https://youtube.com/shorts/Iiy4re43cMM?feature=share&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Comeback Story
&lt;/h2&gt;

&lt;p&gt;The project started as a school initiative at Berufsschule ITECH. My teachers loved the idea and we were planning to finish it together and actually deploy it to the school's real Moodle instance. Then our block-based curriculum kicked in — a new Lernfeld (learning field) began, everyone's schedules shifted, and the project quietly slipped into the "we'll get back to it someday" pile.&lt;/p&gt;

&lt;p&gt;It sat there. Months passed. Then I found the GitHub Finish-Up-A-Thon Challenge — and something clicked. This was exactly the push I needed. The thought of finally showing my teachers a working, production-ready version of what we once planned together was all the motivation I needed to open the repo again.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Experience with GitHub Copilot
&lt;/h2&gt;

&lt;p&gt;When I first built this project, I had a GitHub Student subscription with access to powerful models and no strict weekly limits. Back then, Copilot was my real pair programmer — it helped me move fast and learn even faster.&lt;/p&gt;

&lt;p&gt;Unfortunately, the tighter weekly limits that came later made it much harder to use Copilot the same way. But those months of working with it weren't wasted — I learned a lot, grew as a developer, and now I feel ready to come back to this project and do a full refactoring, applying everything I picked up along the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Comeback 04.06.2026: What was broken and What I Actually Fixed?
&lt;/h2&gt;

&lt;p&gt;The prototype worked — it answered questions. But it was a single-file Fastify server with logic mixed into routes, and it would not have survived contact with real students. Here's the honest before → after, by area:&lt;/p&gt;

&lt;p&gt;🔐 Identity&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Before: userId trusted straight from the request body — any user could read another's chat (IDOR).&lt;/li&gt;
&lt;li&gt;After: HMAC-SHA256 signed identity, constant-time verify, per-session ownership checks (401/403).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🏛️ Architecture&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Before: Business logic tangled into route handlers.&lt;/li&gt;
&lt;li&gt;After: Clean Architecture, 4 layers, dependency rule enforced — use cases testable without Fastify or Docker.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🤖 AI grounding&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Before: The model could see all courses.&lt;/li&gt;
&lt;li&gt;After: Course search is fail-closed to the student's own enrolments; no secrets reachable by the model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🛡️ Frontend XSS&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Before: Model output dumped into raw innerHTML.&lt;/li&gt;
&lt;li&gt;After: DOMPurify + tag/attribute allowlist + Moodle-origin-locked links, with a CSP backstop.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⚙️ Reliability&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Before: Direct fetch, no limits.&lt;/li&gt;
&lt;li&gt;After: Timeout + retry (Moodle), circuit breaker + bounded queue (Ollama), graceful shutdown, SSE abort on disconnect.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💾 Persistence&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Before: In-memory — every restart wiped all chat history.&lt;/li&gt;
&lt;li&gt;After: SQLite (WAL, prepared statements, indexed, retention pruning) behind a repository interface.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🚀 Deploy&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Before: Manual, container ran as root.&lt;/li&gt;
&lt;li&gt;After: Multi-stage non-root Docker image, healthchecks, ordered startup, one-command Compose.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ Quality gate&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Before: None.&lt;/li&gt;
&lt;li&gt;After: 417 tests, ESLint, Prettier, npm audit, Gitleaks, Trivy image scan + container smoke test in CI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The 3 critical blockers I closed for this challenge&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Unauthenticated PII leak — /moodle/user/:id and /moodle/users/:id/courses returned personal data with no auth (only accidentally hidden by nginx routing). Now production-gated to 404.&lt;/li&gt;
&lt;li&gt;Known high-severity CVEs — Fastify 4.28.1 carried 3 high CVEs (body-validation bypass, host/proto spoof). Upgraded to Fastify 5 + matching
plugins; npm audit now reports 0 vulnerabilities.&lt;/li&gt;
&lt;li&gt;Root container, no build hardening — rebuilt as a multi-stage image running as USER node with npm ci and a HEALTHCHECK.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Where I was honest instead of perfect&lt;/p&gt;

&lt;p&gt;I didn't fake "done." The per-user rate limiter is in-memory (fine for a single instance, documented as a known limit), and the prompt-injection guard is a best-effort blocklist — its real safety net is that the model simply can't reach anything sensitive (fail-closed course scope, no secrets in context). These are written down in the README's Limitations section, not hidden.&lt;/p&gt;

&lt;p&gt;The result&lt;/p&gt;

&lt;p&gt;The prototype went from "it answers questions on my laptop" to a production-lite service: Clean Architecture (90/100 in my own readiness&lt;br&gt;
  review), HMAC auth, sanitized LLM output, resilient external calls, persistent history, a hardened container, and a full CI pipeline — all&lt;br&gt;
  behind a single docker compose up.&lt;/p&gt;

&lt;p&gt;The next step is the one that started it all: showing my teachers a working version, and finally deploying it to the school's real Moodle&lt;br&gt;
  instance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thank You 🙏
&lt;/h2&gt;

&lt;p&gt;Huge thanks to GitHub and the DEV community for the chance to take part in such a cool challenge. The Finish-Up-A-Thon was exactly the push I needed to reopen a project I genuinely cared about and finally carry it across the finish line.&lt;/p&gt;

&lt;p&gt;These challenges do more than hand out prompts — they turn "someday" projects into shipped ones and give motivation real momentum. Thank you for creating that space. I had a great time building this, and I'll happily jump into more challenges like this one in the future. 🚀&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
    </item>
  </channel>
</rss>
