WIN Student Goal Tracker
April 2026
1. Project Description
The WIN Student Goal Tracker is a web-based case management system designed to support organizations working with adults with special needs. The platform enables staff to track student goals, document services, and log critical incidents while maintaining strong privacy, auditability, and compliance with FERPA, IDEA, and FAPE.
The system is designed with sustainability in mind, ensuring that future developers can easily maintain, extend, and redeploy the application.
2. Architecture
Technology Stack & Infrastructure
Architecture Description
- Presentation Layer (Angular)
- Application Layer (.NET API)
- Data Layer (MySQL)
Traefik manages routing and HTTPS traffic.
3. Data Flow
Each scenario lists the UI file that initiates the action, the Angular service method called, the API endpoint hit, the .NET controller and repository method invoked, and the stored procedure that reads or writes the database.
1 — User Login
2 — View My Students (Home Dashboard)
3 — Open Student Workspace (Full Profile)
4 — Create Goal
5 — Log Progress Event
4. Recommended Hosting
- The entire application is currently hosted online with Hetzner (www.hetzner.com), on a plan donated by team members. The team has committed to hosting for at least the next two years, and if/when that changes, will help the partner transition to the hosting platform of their choice.
5. Application Installation
Prerequisites
Node.js, .NET 9 SDK, MySQL, Docker
Frontend
cd frontend
npm install
npm start
Backend
cd backend
dotnet restore
dotnet run
Database
Create DB, import schema, update .env.
Docker
docker-compose up --build
6. Authentication & Authorization
JWT-based authentication with refresh tokens.
Key files: AuthController.cs, JwtService.cs, middleware
7. Database Backup
Backup
mysqldump -u username -p dbname > backup.sql
Restore
mysql -u username -p dbname < backup.sql
From the UI
Administrators may back up the database via the "Backup" button in the Administrator panel
8. Environment Variables
DB_CONNECTION=...
JWT_SECRET=...
JWT_EXPIRATION=3600
Ensure .env is in .gitignore.
9. Partner Statement
The partner representatives Polly Balsillie and Fred Winter have reviewed the developer documentation and understands its scope and purpose.
Date: April 16, 2026
10. Installation Walkthrough Statement
N/A. An installation walkthrough was not appropriate for the partner, as they are non-technical. They are primarily users of the application, and at least two of our team members will continue to make ourselves available to support the application.
Date: April 16, 2026
11. Performance & UX Analysis
Lighthouse Results
Form Factor Analysis
- Mobile Portrait: Fully responsive and functional
- Mobile Landscape: Improved readability and layout
- Desktop: Optimal user experience
UX Observations
Clean navigation with consistent user workflows across devices.
Responsive Accessible High Performance SEO Ready12. Known Liabilities & Improvements
Issues: Potential performance scaling and mobile optimization opportunities
Improvements: Lazy loading, bundle optimization, responsive enhancements
13. Sustainability Considerations
Docker deployment, free-tier hosting, and modular design support long-term maintainability.
Appendix A – ERD
The system includes a structured relational database supporting users, roles, permissions, programs, students, goals, progress tracking, and incident logging. The interactive diagram below shows all 17 tables and their relationships. Drag tables to rearrange, scroll to zoom, and hover a table to highlight its connections.
Open full-page ERD⬡ ERD
Appendix B – Repository Structure
WinStudentGoalTracker/
├── api/ .NET 9 backend — controllers, services, repositories, Dockerfile
├── db/ MySQL schema and stored procedures; docker-init scripts for container startup
├── docs/ HTML documentation (technical spec, user manual, ERD, architecture, API)
├── ui/ Angular 20 frontend SPA
├── prototype/ Early role-assignment prototypes (not production code)
├── docker-compose.yml Orchestrates API, Angular/Nginx, MySQL, and Traefik containers
└── WinStudentGoalTracker.sln Visual Studio solution file
Appendix C – Architecture Overview
High-level diagrams of the system tiers, two-phase auth flow, data model, role hierarchy, deployment, and key design decisions.
Open full-page Architecture Overview- TypeScript 5.8 + SCSS
- Angular Signals (state)
- Lazy-loaded routes
- JWT auth interceptor
- Proactive token refresh
- Home / Workspace
- Student detail view
- Goal & Benchmark modals
- Progress event modals
- Report generation UI
- Admin panel
- Student card list
- Add progress event
- Toggle benchmark
- AuthService (signals)
- ApiService (HTTP)
- StudentService
- AdminService
- ReportPromptService
- PlatformService
- win.opelly.me → Angular (Nginx :8006)
- winapi.opelly.me → API (:8005)
- Let's Encrypt TLS
- Gzip compression
- Security headers
- JWT authentication middleware
- Swagger / OpenAPI
- CORS policy
- Dependency injection
- /api/Auth — login & tokens
- /api/Student — CRUD
- /api/Admin — district/users
- /api/ReportPrompt — prompts
- TokenService (JWT)
- PermissionService
- PasswordHasher (PBKDF2)
- RecommendationService
- TranscriptionService
- ProgressReportBuilder
- StudentRepository
- UserRepository
- AuthRepository
- AdminRepository
- ReportPromptRepository
- winstudentgoaltracker DB
- 17 tables
- 51 stored procedures
- Initialised from db/docker-init/
- user, school_district, program
- user_program (roles junction)
- student, user_student
- goal (recursive), benchmark
- progress_event + junction
- refresh_token
- sp_Student_* (CRUD)
- sp_Goal_* / sp_Benchmark_*
- sp_ProgressEvent_*
- sp_RefreshToken_*
- sp_Program_* / sp_User_*
- sp_ProgressReport_*
- llm.opelly.me
- Model: gemma4:e2b
- Benchmark recommendations
- 5-min timeout
- stt.opelly.me
- Speech-to-text transcription
- Progress event dictation
- 5-min timeout
POST /api/Auth/Login
+ program list
Stored in localStorage
POST /api/Auth/SelectProgram
Refresh token (30 days)
JWT includes role + program_id
Auth interceptor injects token
POST /api/Auth/RefreshToken
Rotated refresh token returned
auth_jwt, auth_refresh_token,
auth_session_token — all in localStorage.
|
401 interceptor: attempts one silent refresh; if that fails, redirects to
/login.
|
Refresh token rotation: each use replaces the old token (tracked via
replaced_by_token_id).
| Entity / Action | super_admin | district_admin | program_admin | teacher | paraeducator |
|---|---|---|---|---|---|
| Student — Create | Allow | Allow | Allow | Allow | Deny |
| Student — Update | Allow | Allow | Allow | Mine | Deny |
| Goal — Create | Allow | Allow | Allow | Mine | Deny |
| Goal — Update | Allow | Allow | Allow | Mine | Deny |
| ProgressEvent — Create | Allow | Allow | Allow | Allow | Mine |
| ProgressEvent — Delete | Allow | Allow | Allow | Mine | Deny |
| Program — Create | Allow | Mine | Deny | Deny | Deny |
| User — Create | Allow | Mine | Mine | Deny | Deny |
Docker Containers
- mysql:8 (port 3309)
- .NET API (port 8005)
- Angular / Nginx (port 8006)
- Traefik reverse proxy
Docker Networks
- web — external HTTPS routing
- backend — internal service mesh
- API depends on MySQL healthcheck
- UI depends on API (build time)
Environment Config
- MYSQL_ROOT_PASSWORD
- MYSQL_DATABASE / USER / PASSWORD
- JWT_KEY (signing secret)
- MYSQL_HOST / PORT
Frontend Environments
- Dev: localhost:5000 (API)
- Prod: winapi.opelly.me (API)
- Served by Nginx in production
- Angular CLI dev server locally
DB Initialisation
- Schemas from db/docker-init/
- 51 stored procedures
- Health check gates API startup
- No ORM migrations — raw SQL
AI / External Services
- Ollama LLM — llm.opelly.me
- STT service — stt.opelly.me
- Both called from API tier only
- 5-minute timeout on both
Two-Phase JWT Auth
- Phase 1: credentials → session token
- Phase 2: program select → scoped JWT
- Prevents data leakage before program chosen
- JWT scoped to one program at a time
Refresh Token Rotation
- New token issued on each refresh
- Old token replaced (not deleted)
- Genealogy tracked via replaced_by
- Prevents replay attacks
Program-Scoped Multi-Tenancy
- JWT contains program_id claim
- All queries filtered by program
- district_admin scoped to district
- super_admin bypasses scope
Dapper + Stored Procedures
- No ORM (Entity Framework)
- Business logic close to data
- Dapper maps rows to C# objects
- 51 procedures for full coverage
Angular Signals (not RxJS)
- Auth state as reactive signals
- Computed signals derive user context
- Simpler than Observable chains
- Auto-update dependent UI
Centralised Permission Matrix
- Declarative rules per entity + action
- Allow / MineOnly / Deny granularity
- Evaluated at request time in API
- Single source of truth for authz