From 91cc654cadbaa8224bd18a200426e034fdc86f0d Mon Sep 17 00:00:00 2001 From: ivan-pelly Date: Thu, 16 Apr 2026 18:10:53 -0700 Subject: [PATCH] Latest docs --- docs/architecture.html | 1105 +++++++++++++++++++++++++++++ docs/erd.html | 953 +++++++++++++++++++++++++ docs/index.html | 1 + docs/technical.html | 1517 +++++++++++++++++++++++++++++++++++++++- docs/um.html | 362 ++++++++-- 5 files changed, 3880 insertions(+), 58 deletions(-) create mode 100644 docs/architecture.html create mode 100644 docs/erd.html diff --git a/docs/architecture.html b/docs/architecture.html new file mode 100644 index 0000000..5716d4a --- /dev/null +++ b/docs/architecture.html @@ -0,0 +1,1105 @@ + + + + + + WIN — Architecture Overview + + + + +
+

WIN — Architectural Overview

+

High-level diagram of the system tiers, components, data model, auth flow, and role hierarchy.

+
+ + + +
+ + +
🏗 System Architecture
+ +
+ + +
+
Client
+
+ +
+
Angular SPA v20
+
    +
  • TypeScript 5.8 + SCSS
  • +
  • Angular Signals (state)
  • +
  • Lazy-loaded routes
  • +
  • JWT auth interceptor
  • +
  • Proactive token refresh
  • +
+
+ +
+
Desktop Layout
+
    +
  • Home / Workspace
  • +
  • Student detail view
  • +
  • Goal & Benchmark modals
  • +
  • Progress event modals
  • +
  • Report generation UI
  • +
  • Admin panel
  • +
+
+ +
+
Mobile Layout
+
    +
  • Student card list
  • +
  • Add progress event
  • +
  • Toggle benchmark
  • +
+
+ +
+
Shared Services
+
    +
  • AuthService (signals)
  • +
  • ApiService (HTTP)
  • +
  • StudentService
  • +
  • AdminService
  • +
  • ReportPromptService
  • +
  • PlatformService
  • +
+
+ +
+
+ +
+ + + + HTTPS / REST + JWT Bearer — win.opelly.me → winapi.opelly.me +
+ + +
+
Proxy
+
+ +
+
Traefik Reverse Proxy
+
    +
  • win.opelly.me → Angular (Nginx :8006)
  • +
  • winapi.opelly.me → API (:8005)
  • +
  • Let's Encrypt TLS
  • +
  • Gzip compression
  • +
  • Security headers
  • +
+
+ +
+
+ +
+ + + + HTTP (internal Docker network) +
+ + +
+
API
+
+ +
+
ASP.NET Core 9 C#
+
    +
  • JWT authentication middleware
  • +
  • Swagger / OpenAPI
  • +
  • CORS policy
  • +
  • Dependency injection
  • +
+
+ +
+
Controllers
+
    +
  • /api/Auth — login & tokens
  • +
  • /api/Student — CRUD
  • +
  • /api/Admin — district/users
  • +
  • /api/ReportPrompt — prompts
  • +
+
+ +
+
Services
+
    +
  • TokenService (JWT)
  • +
  • PermissionService
  • +
  • PasswordHasher (PBKDF2)
  • +
  • RecommendationService
  • +
  • TranscriptionService
  • +
  • ProgressReportBuilder
  • +
+
+ +
+
Repositories Dapper
+
    +
  • StudentRepository
  • +
  • UserRepository
  • +
  • AuthRepository
  • +
  • AdminRepository
  • +
  • ReportPromptRepository
  • +
+
+ +
+
+ +
+ + + + Stored procedures via Dapper — TCP :3309 (Docker internal) +
+ + +
+
Data
+
+ +
+
MySQL 8 Docker
+
    +
  • winstudentgoaltracker DB
  • +
  • 17 tables
  • +
  • 51 stored procedures
  • +
  • Initialised from db/docker-init/
  • +
+
+ +
+
Core Tables
+
    +
  • user, school_district, program
  • +
  • user_program (roles junction)
  • +
  • student, user_student
  • +
  • goal (recursive), benchmark
  • +
  • progress_event + junction
  • +
  • refresh_token
  • +
+
+ +
+
Procedure Groups
+
    +
  • sp_Student_* (CRUD)
  • +
  • sp_Goal_* / sp_Benchmark_*
  • +
  • sp_ProgressEvent_*
  • +
  • sp_RefreshToken_*
  • +
  • sp_Program_* / sp_User_*
  • +
  • sp_ProgressReport_*
  • +
+
+ +
+
+ + +
+ + + + Outbound HTTP from API tier only +
+ + +
+
External
+
+ +
+
Ollama LLM AI
+
    +
  • llm.opelly.me
  • +
  • Model: gemma4:e2b
  • +
  • Benchmark recommendations
  • +
  • 5-min timeout
  • +
+
+ +
+
STT Service AI
+
    +
  • stt.opelly.me
  • +
  • Speech-to-text transcription
  • +
  • Progress event dictation
  • +
  • 5-min timeout
  • +
+
+ +
+
+ +
+ + + +
🔐 Two-Phase Authentication Flow
+ +
+
+ +
+
1
+
+ User Submits Credentials + email + password
+ POST /api/Auth/Login +
+
+ +
+ + + +
+ +
+
2
+
+ Phase 1 Response + Session token (5 min)
+ program list
+ Stored in localStorage +
+
+ +
+ + + +
+ +
+
3
+
+ User Selects Program + session token + program ID
+ POST /api/Auth/SelectProgram +
+
+ +
+ + + +
+ +
+
4
+
+ Phase 2 Response + JWT (1 min) +
Refresh token (30 days)
+ JWT includes role + program_id +
+
+ +
+ + + +
+ +
+
5
+
+ Authenticated Requests + Bearer JWT on all API calls
+ Auth interceptor injects token +
+
+ +
+ + + +
+ +
+
6
+
+ Proactive Refresh + 10 s before JWT expiry:
POST /api/Auth/RefreshToken
+ Rotated refresh token returned +
+
+ +
+
+ +
+ Token storage: 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). +
+ + + +
🗄 Core Data Model
+ +
+ +
+
school_district
+
+
PK id_school_district
+
name
+
contact_email
+
Top-level tenant
+
+
+ +
+
program
+
+
PK id_program
+
FK id_school_district
+
name, description
+
Scope boundary for data
+
+
+ +
+
user
+
+
PK id_user
+
email, name
+
password_hash, password_salt
+
locked_until
+
+
+ +
+
user_program (junction)
+
+
PK id_user_program
+
FK id_user
+
FK id_program
+
FK id_role
+
is_primary, status
+
+
+ +
+
student
+
+
PK id_student
+
FK id_program
+
identifier, program_year
+
enrollment_date
+
next_iep_date
+
+
+ +
+
user_student (junction)
+
+
PK id_user_student
+
FK id_user
+
FK id_student
+
is_primary
+
+
+ +
+
goal
+
+
PK id_goal
+
FK id_goal_parent (self-ref)
+
FK id_student
+
description, category
+
baseline, target_completion_date
+
close_date, achieved
+
+
+ +
+
benchmark
+
+
PK id_benchmark
+
FK id_goal
+
benchmark (description)
+
short_name
+
+
+ +
+
progress_event
+
+
PK id_progress_event
+
FK id_goal
+
FK id_user_created
+
content (rich text)
+
is_sensitive
+
+
+ +
+
progress_event_benchmark (junction)
+
+
FK id_progress_event
+
FK id_benchmark
+
Links events to benchmarks
+
+
+ +
+
refresh_token
+
+
PK id_refresh_token
+
FK id_user, id_program
+
token_hash, token_salt
+
expires_at, revoked_at
+
replaced_by_token_id
+
+
+ +
+
report_prompt
+
+
PK id_report_prompt
+
FK program_id
+
report_name
+
prompt_template (LLM)
+
+
+ +
+ + +
+ Key relationships: +  school_district 1→N program  ·  + program 1→N student  ·  + student 1→N goal (recursive parent/child)  ·  + goal 1→N benchmark  ·  + goal 1→N progress_event  ·  + progress_event M↔N benchmark (junction)  ·  + user M↔N program (via user_program + role)  ·  + user M↔N student (via user_student) +
+ + + +
👥 Role Hierarchy & Permissions
+ +
+ + +
+
Role Tiers (highest → lowest)
+
+
+
+ super_admin  ·  full platform access +
+
+
+
+ district_admin  ·  manages programs +
+
+
+
+ program_admin  ·  manages users +
+
+
+
+ teacher  ·  full student CRUD +
+
+
+
+ paraeducator  ·  log events +
+
+
+
+ + +
+
Sample Permission Matrix
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Entity / Actionsuper_admindistrict_adminprogram_adminteacherparaeducator
Student — CreateAllowAllowAllowAllowDeny
Student — UpdateAllowAllowAllowMineDeny
Goal — CreateAllowAllowAllowMineDeny
Goal — UpdateAllowAllowAllowMineDeny
ProgressEvent — CreateAllowAllowAllowAllowMine
ProgressEvent — DeleteAllowAllowAllowMineDeny
Program — CreateAllowMineDenyDenyDeny
User — CreateAllowMineMineDenyDeny
+
+ Allow = full access   + Mine = own records only   + Deny = not permitted +
+
+ +
+ + + +
🐳 Deployment & Infrastructure
+ +
+ +
+

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
  • +
+
+ +
+ + + +
⚙️ Key Design Decisions
+ +
+ +
+

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
  • +
+
+ +
+ +
+ + + + + diff --git a/docs/erd.html b/docs/erd.html new file mode 100644 index 0000000..885b8f7 --- /dev/null +++ b/docs/erd.html @@ -0,0 +1,953 @@ + + + + + +Database ERD — Student Progress Tracker + + + + + +
+

⬡ ERD

+
+
Tables 17
+
+
Relations 0
+
+ + + ← Technical Docs +
+
+ +
+
+ +
+
+ +
+
Primary Key
+
Foreign Key
+
+ + Relationship +
+
+ +
+ + + +
+ +
+ + + + diff --git a/docs/index.html b/docs/index.html index 8d9c49b..cf82636 100644 --- a/docs/index.html +++ b/docs/index.html @@ -354,6 +354,7 @@ UI Documentation User Manual Documentation Technical Documentation + Architecture Overview 🎬 P6 Presentation Video diff --git a/docs/technical.html b/docs/technical.html index de89d12..4d34654 100644 --- a/docs/technical.html +++ b/docs/technical.html @@ -5,6 +5,7 @@ WIN Student Goal Tracker – Developer Documentation + + + + +
@@ -263,6 +533,7 @@ 13. Sustainability Considerations Appendix A – ERD Appendix B – Repository Structure + Appendix C – Architecture Overview
@@ -444,19 +715,1253 @@ JWT_EXPIRATION=3600

Appendix A – ERD

The system includes a structured relational database supporting users, roles, permissions, - programs, students, goals, progress tracking, and incident logging. + 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

+
+
Tables 17
+
+
Relations 0
+
+ + +
+
+ +
+
+ +
+
+ +
+
Primary Key
+
Foreign Key
+
+ + Relationship +
+
+ +
+ + + +
+ +
+

Appendix B – Repository Structure

-
/frontend
-/backend
-/database
-/docker
-/docs
+
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 + + + +
🏗 System Architecture
+ +
+ +
+
Client
+
+
+
Angular SPA v20
+
    +
  • TypeScript 5.8 + SCSS
  • +
  • Angular Signals (state)
  • +
  • Lazy-loaded routes
  • +
  • JWT auth interceptor
  • +
  • Proactive token refresh
  • +
+
+
+
Desktop Layout
+
    +
  • Home / Workspace
  • +
  • Student detail view
  • +
  • Goal & Benchmark modals
  • +
  • Progress event modals
  • +
  • Report generation UI
  • +
  • Admin panel
  • +
+
+
+
Mobile Layout
+
    +
  • Student card list
  • +
  • Add progress event
  • +
  • Toggle benchmark
  • +
+
+
+
Shared Services
+
    +
  • AuthService (signals)
  • +
  • ApiService (HTTP)
  • +
  • StudentService
  • +
  • AdminService
  • +
  • ReportPromptService
  • +
  • PlatformService
  • +
+
+
+
+ +
+ + HTTPS / REST + JWT Bearer — win.opelly.me → winapi.opelly.me +
+ +
+
Proxy
+
+
+
Traefik Reverse Proxy
+
    +
  • win.opelly.me → Angular (Nginx :8006)
  • +
  • winapi.opelly.me → API (:8005)
  • +
  • Let's Encrypt TLS
  • +
  • Gzip compression
  • +
  • Security headers
  • +
+
+
+
+ +
+ + HTTP (internal Docker network) +
+ +
+
API
+
+
+
ASP.NET Core 9 C#
+
    +
  • JWT authentication middleware
  • +
  • Swagger / OpenAPI
  • +
  • CORS policy
  • +
  • Dependency injection
  • +
+
+
+
Controllers
+
    +
  • /api/Auth — login & tokens
  • +
  • /api/Student — CRUD
  • +
  • /api/Admin — district/users
  • +
  • /api/ReportPrompt — prompts
  • +
+
+
+
Services
+
    +
  • TokenService (JWT)
  • +
  • PermissionService
  • +
  • PasswordHasher (PBKDF2)
  • +
  • RecommendationService
  • +
  • TranscriptionService
  • +
  • ProgressReportBuilder
  • +
+
+
+
Repositories Dapper
+
    +
  • StudentRepository
  • +
  • UserRepository
  • +
  • AuthRepository
  • +
  • AdminRepository
  • +
  • ReportPromptRepository
  • +
+
+
+
+ +
+ + Stored procedures via Dapper — TCP :3309 (Docker internal) +
+ +
+
Data
+
+
+
MySQL 8 Docker
+
    +
  • winstudentgoaltracker DB
  • +
  • 17 tables
  • +
  • 51 stored procedures
  • +
  • Initialised from db/docker-init/
  • +
+
+
+
Core Tables
+
    +
  • user, school_district, program
  • +
  • user_program (roles junction)
  • +
  • student, user_student
  • +
  • goal (recursive), benchmark
  • +
  • progress_event + junction
  • +
  • refresh_token
  • +
+
+
+
Procedure Groups
+
    +
  • sp_Student_* (CRUD)
  • +
  • sp_Goal_* / sp_Benchmark_*
  • +
  • sp_ProgressEvent_*
  • +
  • sp_RefreshToken_*
  • +
  • sp_Program_* / sp_User_*
  • +
  • sp_ProgressReport_*
  • +
+
+
+
+ +
+ + Outbound HTTP from API tier only +
+ +
+
External
+
+
+
Ollama LLM AI
+
    +
  • llm.opelly.me
  • +
  • Model: gemma4:e2b
  • +
  • Benchmark recommendations
  • +
  • 5-min timeout
  • +
+
+
+
STT Service AI
+
    +
  • stt.opelly.me
  • +
  • Speech-to-text transcription
  • +
  • Progress event dictation
  • +
  • 5-min timeout
  • +
+
+
+
+ +
+ + +
🔐 Two-Phase Authentication Flow
+ +
+
+ +
+
1
+
+ User Submits Credentials + email + password
+ POST /api/Auth/Login +
+
+ +
+ +
+ +
+
2
+
+ Phase 1 Response + Session token (5 min)
+ program list
+ Stored in localStorage +
+
+ +
+ +
+ +
+
3
+
+ User Selects Program + session token + program ID
+ POST /api/Auth/SelectProgram +
+
+ +
+ +
+ +
+
4
+
+ Phase 2 Response + JWT (1 min) +
Refresh token (30 days)
+ JWT includes role + program_id +
+
+ +
+ +
+ +
+
5
+
+ Authenticated Requests + Bearer JWT on all API calls
+ Auth interceptor injects token +
+
+ +
+ +
+ +
+
6
+
+ Proactive Refresh + 10 s before JWT expiry:
POST /api/Auth/RefreshToken
+ Rotated refresh token returned +
+
+ +
+
+ +
+ Token storage: 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). +
+ + +
🗄 Core Data Model
+ +
+ +
+
school_district
+
+
PK id_school_district
+
name
+
contact_email
+
Top-level tenant
+
+
+ +
+
program
+
+
PK id_program
+
FK id_school_district
+
name, description
+
Scope boundary for data
+
+
+ +
+
user
+
+
PK id_user
+
email, name
+
password_hash, password_salt
+
locked_until
+
+
+ +
+
user_program (junction)
+
+
PK id_user_program
+
FK id_user
+
FK id_program
+
FK id_role
+
is_primary, status
+
+
+ +
+
student
+
+
PK id_student
+
FK id_program
+
identifier, program_year
+
enrollment_date
+
next_iep_date
+
+
+ +
+
user_student (junction)
+
+
PK id_user_student
+
FK id_user
+
FK id_student
+
is_primary
+
+
+ +
+
goal
+
+
PK id_goal
+
FK id_goal_parent (self-ref)
+
FK id_student
+
description, category
+
baseline, target_completion_date
+
close_date, achieved
+
+
+ +
+
benchmark
+
+
PK id_benchmark
+
FK id_goal
+
benchmark (description)
+
short_name
+
+
+ +
+
progress_event
+
+
PK id_progress_event
+
FK id_goal
+
FK id_user_created
+
content (rich text)
+
is_sensitive
+
+
+ +
+
progress_event_benchmark (junction)
+
+
FK id_progress_event
+
FK id_benchmark
+
Links events to benchmarks
+
+
+ +
+
refresh_token
+
+
PK id_refresh_token
+
FK id_user, id_program
+
token_hash, token_salt
+
expires_at, revoked_at
+
replaced_by_token_id
+
+
+ +
+
report_prompt
+
+
PK id_report_prompt
+
FK program_id
+
report_name
+
prompt_template (LLM)
+
+
+ +
+ +
+ Key relationships: +  school_district 1→N program  ·  + program 1→N student  ·  + student 1→N goal (recursive parent/child)  ·  + goal 1→N benchmark  ·  + goal 1→N progress_event  ·  + progress_event M↔N benchmark (junction)  ·  + user M↔N program (via user_program + role)  ·  + user M↔N student (via user_student) +
+ + +
👥 Role Hierarchy & Permissions
+ +
+ +
+
Role Tiers (highest → lowest)
+
+
super_admin  ·  full platform access
+
district_admin  ·  manages programs
+
program_admin  ·  manages users
+
teacher  ·  full student CRUD
+
paraeducator  ·  log events
+
+
+ +
+
Sample Permission Matrix
+ + + + + + + + + + + + + + + + + + + + + +
Entity / Actionsuper_admindistrict_adminprogram_adminteacherparaeducator
Student — CreateAllowAllowAllowAllowDeny
Student — UpdateAllowAllowAllowMineDeny
Goal — CreateAllowAllowAllowMineDeny
Goal — UpdateAllowAllowAllowMineDeny
ProgressEvent — CreateAllowAllowAllowAllowMine
ProgressEvent — DeleteAllowAllowAllowMineDeny
Program — CreateAllowMineDenyDenyDeny
User — CreateAllowMineMineDenyDeny
+
+ Allow = full access   + Mine = own records only   + Deny = not permitted +
+
+ +
+ + +
🐳 Deployment & Infrastructure
+ +
+
+

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
  • +
+
+
+ + +
⚙️ Key Design Decisions
+ +
+
+

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
  • +
+
+
+
+ + diff --git a/docs/um.html b/docs/um.html index cb1bddc..055cde1 100644 --- a/docs/um.html +++ b/docs/um.html @@ -193,7 +193,6 @@ } .callout{ - border-left:4px solid var(--primary); background:#eff6ff; padding:1rem; border-radius:12px; @@ -201,10 +200,13 @@ } .callout.success{ - border-left-color:var(--success); background:#f0fdf4; } + .callout.warn{ + background:#fffbeb; + } + code{ background:#eef2ff; padding:.15rem .4rem; @@ -244,6 +246,29 @@ margin-bottom:.25rem; } + .role-table{ + width:100%; + border-collapse:collapse; + margin-top:1rem; + font-size:.95rem; + } + + .role-table th, + .role-table td{ + text-align:left; + padding:.5rem .75rem; + border:1px solid var(--border); + } + + .role-table th{ + background:#f3f4f6; + font-weight:600; + } + + .role-table tr:nth-child(even) td{ + background:#f9fafb; + } + .footer{ text-align:center; color:var(--muted); @@ -263,8 +288,8 @@

WIN Student Goal Tracker

- User manual for teachers and program staff using the WIN platform to manage - students, goals, benchmarks, and progress events. + User manual for teachers, program staff, and administrators using the WIN + platform to manage students, goals, benchmarks, and progress events.

- This manual covers the current application workflow as implemented - in the deployed prototype. Features relating to district registration - and administration are documented separately. + This manual covers teacher and program staff workflows as well as + district administration features including program management and + user provisioning. +
+ + +
+

2. User Roles

+

+ Every user account is assigned a role when added to a program. The + role determines which actions that user can perform. There are five + roles in the system. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RoleDescriptionKey Permissions
TeacherStandard instructional staff member + Full access to their own students — create, edit, and delete + students, goals, benchmarks, and progress events. Can run + reports and use AI suggestions. +
ParaeducatorSupport staff assisting teachers + Can view students and log progress events. Cannot create or + delete students, goals, or benchmarks, and cannot run reports + or use AI suggestions. +
Program AdminStaff member who manages an entire program + Same as Teacher but scoped across all students in the program, + not just their own. Can run reports. +
District AdminAdministrator who manages a school district + All Program Admin abilities plus access to the Administration + panel. Can create and edit programs and add users to any + program within the district. +
Super AdminSystem-level administrator + Full access across all districts and programs. Can assign any + role, including Super Admin. Reserved for platform operators. +
+ +
+ A user's role is set when their account is created by a District + Admin. If you are unsure of your role, contact your district + administrator. +
+
+ +
+

3. Registering a New District

+

+ If your school district is not yet set up in the system, a district + administrator can self-register to create the district account, an + initial program, and their own login in one step. +

+ +
+ Registration creates a new, independent district. If your district + already exists, do not register again — contact your existing + district administrator to have a user account created for you. +
+ +

How to register

+
    +
  1. + Go to https://win.opelly.me/register or click + Register from the login page. +
  2. +
  3. + Fill in Your Details: name, email address, and + password. This becomes your login. +
  4. +
  5. + Fill in District Details: district name and an + optional contact email for the district. +
  6. +
  7. + Fill in Your First Program: the name and optional + description of the first program in your district (e.g. + "Special Education"). +
  8. +
  9. Click Create District & Account.
  10. +
+ +
+ After registration you will be directed to the login page. Sign in + with your new credentials. You will be assigned the District Admin + role automatically and can add more programs and users from the + Administration panel.
-

2. Accessing the Application

+

4. Accessing the Application

To begin, open the login page at https://win.opelly.me/login. @@ -365,15 +508,21 @@ After a successful login, the system will take you to the program selection screen. + +

+ If your account is locked after repeated failed attempts, you will + see a message indicating the account is temporarily unavailable. + Wait a few minutes before trying again or contact your administrator. +
-

3. Selecting a Program

+

5. Selecting a Program

After authentication, the system displays the list of programs available to the logged-in user. Each program card shows the - program name, your role (e.g. Teacher, Admin), and whether it is - your primary program. + program name, your role (e.g. Teacher, District Admin), and whether + it is your primary program.

    @@ -381,10 +530,16 @@
  1. Click the program you wish to work in.
  2. The application will open the main dashboard for that program.
+ +
+ A user can belong to multiple programs with different roles in each. + Selecting a program loads a session scoped to that program — switch + programs by logging out and logging back in. +
-

4. Student Dashboard

+

6. Student Dashboard

The main dashboard displays the students assigned to the current teacher or user. @@ -403,6 +558,10 @@ between viewing only your own students and all students in the program. +

  • + Students may be organized into labeled groups if a Program + Admin or District Admin has configured groupings. +
  • Click a student to open their goal workspace.
  • @@ -410,9 +569,14 @@

    Navigation

    • - The sidebar also provides links to Reports + The sidebar provides links to Reports and Log Out.
    • +
    • + District Admins and Super Admins also see an + Admin link that opens the Administration + panel (see Section 13). +
    • Click the edit icon next to a student to update their name or IEP date.
    @@ -420,10 +584,11 @@
    -

    5. Adding & Editing Students

    +

    7. Adding & Editing Students

    - Teachers can add a new student record directly from the dashboard, - or edit an existing student's information. + Teachers and Program Admins can add a new student record directly + from the dashboard, or edit an existing student's information. + Paraeducators cannot add or edit students.

    Adding a student

    @@ -447,7 +612,7 @@
    -

    6. Managing Goals

    +

    8. Managing Goals

    Selecting a student opens the goal workspace for that student. Goals are the main tracking objects used to measure student @@ -509,13 +674,18 @@

    -

    7. Managing Benchmarks

    +

    9. Managing Benchmarks

    Benchmarks break a goal into smaller, measurable steps. This makes it easier to see incremental progress over time. Each benchmark has a full description and an optional short name used for compact display.

    +

    + Teachers and Program Admins can add and edit benchmarks. + Paraeducators can view benchmarks but cannot create or modify them. +

    +

    To add a benchmark

    1. Select the goal tab for the relevant goal.
    2. @@ -530,7 +700,8 @@ When adding a new benchmark, you can click the ✦ Suggest with AI button. The system will analyze the student's goal and generate a recommended benchmark that you - can accept, modify, or discard before saving. + can accept, modify, or discard before saving. This feature is + available to Teachers and Program Admins only.

      Editing a benchmark

      @@ -545,10 +716,11 @@
    -

    8. Recording Progress Events

    +

    10. Recording Progress Events

    Progress events document meaningful activities, milestones, or notes - related to a student's goal. + related to a student's goal. All roles (including Paraeducators) can + log progress events.

    To log a progress event

    @@ -595,9 +767,10 @@
    -

    9. Deleting Records

    +

    11. Deleting Records

    - Students, goals, benchmarks, and progress events can all be deleted. + Students, goals, benchmarks, and progress events can all be deleted + by Teachers and Program Admins. Paraeducators cannot delete records. Deletions are permanent and cannot be undone.

    @@ -632,11 +805,12 @@
    -

    10. Reports

    +

    12. Reports

    The Reports section provides tools for extracting and summarizing student progress data. Access it from the Reports - link in the sidebar. + link in the sidebar. Reports are available to Teachers and Program + Admins. Paraeducators do not have access to the Reports section.

    Student Progress Report

    @@ -665,8 +839,73 @@
    +
    +

    13. Administration

    +

    + The Administration panel is available to District Admins and Super + Admins. It is accessed via the Admin link in the + sidebar, which is only visible to users with those roles. +

    + +

    + The Admin panel has two tabs: Programs and + Users. +

    + +

    Programs tab

    +

    + Lists all programs in your district. District Admins can create new + programs and edit existing ones. +

    + +

    Adding a program

    +
      +
    1. Click + Add Program.
    2. +
    3. Enter a Program Name (required) and an optional Description.
    4. +
    5. Click Create.
    6. +
    + +

    Editing a program

    +
      +
    1. Click Edit next to the program.
    2. +
    3. Update the name or description.
    4. +
    5. Click Save.
    6. +
    + +

    Users tab

    +

    + Lists all users across all programs in your district, showing each + user's name, email, role, and assigned program. +

    + +

    Adding a user

    +
      +
    1. Click + Add User.
    2. +
    3. Enter the user's Name, Email, and a temporary Password.
    4. +
    5. Select the Program to assign the user to.
    6. +
    7. Select the user's Role (see Section 2 for role descriptions).
    8. +
    9. Click Create User.
    10. +
    + +

    + The new user can immediately log in with the email and password you + provided. Share the credentials with them securely. +

    + +
    + District Admins cannot assign the Super Admin role. Only a Super + Admin can elevate another user to Super Admin. +
    + +
    + There is currently no in-app password reset. If a user forgets their + password, a District Admin will need to create a new account or + contact the platform operator for assistance. +
    +
    +
    -

    11. Mobile Experience

    +

    14. Mobile Experience

    The application automatically detects whether you are using a touch-based mobile device and presents a touch-optimized interface. @@ -691,37 +930,56 @@

    Some management features — such as adding students, creating goals, - editing benchmarks, running reports, and deleting records — are - only available in the desktop interface. Use a desktop browser for - full administrative access. + editing benchmarks, running reports, accessing the Admin panel, and + deleting records — are only available in the desktop interface. Use + a desktop browser for full administrative access.
    -

    12. Typical Workflow

    +

    15. Typical Workflow

    + +

    For a Teacher or Program Admin

      -
    1. Log into the application.
    2. -
    3. Select the appropriate program.
    4. -
    5. Review the list of assigned students.
    6. +
    7. Log into the application and select your program.
    8. +
    9. Review the list of assigned students in the sidebar.
    10. Add a student if needed.
    11. -
    12. Open a student record.
    13. -
    14. Review or create goals.
    15. +
    16. Open a student record and review or create goals.
    17. Add benchmarks to define milestones (use AI suggestions when helpful).
    18. Record progress events as the student advances, linking relevant benchmarks.
    19. Run reports as needed for IEP meetings or program reviews.
    + +

    For a Paraeducator

    +
      +
    1. Log into the application and select your program.
    2. +
    3. Browse students using the sidebar.
    4. +
    5. Open a student record and select a goal.
    6. +
    7. Switch to the Progress Events sub-tab and log a new event.
    8. +
    + +

    For a District Admin (initial setup)

    +
      +
    1. Register at /register to create your district and first program.
    2. +
    3. Log in and open the Admin panel from the sidebar.
    4. +
    5. Create additional programs if needed.
    6. +
    7. Add teacher and paraeducator accounts under the Users tab.
    8. +
    9. Share login credentials with each user.
    10. +
    -

    13. Usage Notes

    +

    16. Usage Notes

      -
    • Keep student names consistent to avoid duplicate entries.
    • +
    • Keep student names consistent (use initials or a non-identifying label) to avoid duplicate entries and to protect student privacy.
    • Update progress events regularly so the record stays current.
    • Use benchmarks to make large goals easier to track.
    • Link progress events to benchmarks for richer reporting.
    • Review student cards often to spot inactivity or missing updates.
    • Use the mobile app for quick progress logging in the field.
    • Log out when finished using the system on a shared device.
    • +
    • If your login is locked, wait a few minutes and try again, or contact your district administrator.
    • +
    • District Admins: share newly created passwords with users through a secure channel and advise them not to share their credentials.
    Back to Project Home @@ -731,7 +989,7 @@