Add 21 files, update 16 files, rename 1 file

This commit is contained in:
[dyad] committed 2026-08-02 17:26:49 +02:00
1 parent b9e4ed4dfc
commit 278293b397
39 files changed
+2434 -61

No files matched your search

+40
View File
@@ -0,0 +1,40 @@
# Architecture
SchoolOS is a single Next.js application with TypeScript, Prisma, and SQLite.
It is intentionally deployable as one self-hosted container for a single
school. Core personal data remains in SQLite; generated uploads, exports, and
backups live in persistent local storage.
## Components
- Next.js App Router hosts the UI and API routes.
- Prisma owns schema validation, migrations, and database access.
- SQLite is the default relational store. Use WAL mode in the deployment
bootstrap and retain the database plus `-wal` and `-shm` files during backups.
- The storage layer uses local filesystem paths first. Future S3-compatible
storage must use the same storage interface rather than feature-specific SDKs.
- `src/lib/storage.ts` is the single local filesystem boundary. It constrains
uploads, exports, and backups to configured roots and rejects path traversal.
- Notification, Calendar, Policy, and Authorization remain shared services;
feature modules must not create duplicate delivery, date, or permission logic.
## Deployment Boundary
`docker-compose.yml` runs the application with a named `/data` volume:
- `/data/db`: SQLite database files
- `/data/uploads`: uploaded evidence and documents
- `/data/exports`: generated reports and rights exports
- `/data/backups`: verified backups
Use a reverse proxy that terminates TLS in production. Configure
`NEXT_PUBLIC_APP_URL` with the public HTTPS URL.
## Security Notes
- Server-side authorization is mandatory; hiding navigation does not grant
access control.
- Secrets belong only in `.env` or deployment secret management.
- AI is optional and must remain disabled until policy/DPIA gates allow it.
- This engineering documentation is not legal advice. A school must involve its
DPO, Schultrager, and Personalrat before production use.
+51
View File
@@ -0,0 +1,51 @@
# Contributing
## Setup
1. Use Node.js 22 and pnpm.
2. Copy `.env.example` to `.env` and set `DATABASE_URL`.
3. Install dependencies with `pnpm install`.
4. Generate Prisma client with `pnpm db:generate`.
5. Create local schema with `pnpm db:push` or run the reviewed migration flow.
6. Seed only non-production data with `pnpm db:seed`.
7. Start the app with `pnpm dev`.
## Required Checks
Run these before opening a pull request:
```bash
pnpm prisma validate
pnpm lint
pnpm test
pnpm typecheck
git diff --check
```
## Engineering Rules
- Use server-side authorization for every route. UI visibility is never a
substitute for access control.
- Scope every school-owned query to the caller school. Scope teacher data to
assigned classes, student data to self, and parent data to linked children.
- Use `src/lib/access-policy.ts` and `src/lib/role-access.ts` instead of
duplicating access rules.
- Use `src/lib/storage.ts` for local files. Never assemble arbitrary paths from
request input.
- Use the Calendar and Notification modules as shared sources, not local copies
of deadlines or delivery logic.
- Keep new UI icon-based with Lucide. Do not introduce emoji UI affordances.
- Preserve existing palette, shared motion vocabulary, responsive behavior, and
role-aware page ownership defined in `TODO.md`.
- Add a migration for every Prisma schema change and update relevant docs/tests.
- Do not add hardcoded policy values when a school-configurable policy is
required.
## Pull Requests
- Keep a pull request narrowly scoped to one TODO phase item.
- Explain security, migration, audit, export/erasure, and retention effects.
- Include tests for authorization failures and cross-school IDOR attempts when
a route handles school or student data.
- Do not commit `.env`, database files, backup files, uploaded documents, or
generated test artifacts.
+77
View File
@@ -0,0 +1,77 @@
# Data Model
SchoolOS uses Prisma with SQLite. IDs are portable strings and timestamps are
stored in UTC. The schema is the source of truth; this document is a domain
map, not a replacement for `prisma/schema.prisma`.
## Organization And Identity
- `School`, `SchoolYear`, `SchoolDistrict`: organizational boundaries.
- `User`: authenticated account, role, school membership, locale, and soft
deletion state.
- `ClassGroup`, `ClassGroupTeacher`, `Enrollment`: teaching assignments and
current/historical class membership.
- `Student`, `ParentStudentLink`, `ParentContact`, `EmergencyContact`: student
profile and linked guardians. Access must always be evaluated through the
active student, parent link, class assignment, and school scope.
## Academic Record
- `Subject`, `CompetencyTemplate`, `CompetencyCategory`, `Competency`, and
`MasteryLevelDefinition` define editable school competency frameworks.
- `ClassCompetencyAssignment` links a framework to a class.
- `LearningProgressEntry` is the evidence record used by progress, mastery,
and competence visualizations.
- `Assessment`, `AssessmentCompetencyLink`, and `AssessmentResult` capture
assessment creation, competency links, and student results.
- `GradingScheme`, `GradingWeightRule`, and `ComputedGrade` hold calculation
rules and computed outcomes.
- `Report`, `ReportCardTemplate`, and `ReportSection` hold report-card drafts,
templates, and sections.
## Classroom Operations
- `AttendanceSession` and `AttendanceRecord`: attendance and absence status.
- `LessonPlan`, `Homework`, and `HomeworkSubmission`: instructional planning
and student work.
- `TimetableSlot`, `CalendarEvent`, `SchoolEvent`, and `EventRegistration`:
time-bound school activity.
- `TeacherAbsence`, substitute models, transport models, and library checkout
models support daily school operations.
## Student Support And Communication
- `TeacherNote`, `BehaviorCategory`, `BehaviorIncident`, and
`BehaviorIntervention`: staff-only support context.
- `IllnessReport`, `CounselingAppointment`, `HealthRecord`, and `Wellness`
models contain sensitive information; they require strict role, student, and
school checks.
- `CommunicationRoom`, `CommunicationRoomMember`, `CommunicationMessage`,
`ParentMessage`, `Announcement`, and `Notification` provide communication
and delivery records.
## Student Work And Learning Hub
- `Notebook`, `NotebookPage`, `NotebookPageVersion`, and `Drawing` store
digital student work and version history.
- `Resource`, `SubjectCategory`, `SubjectContent`, `SubjectTopic`,
`SubjectLesson`, and `LessonQuestion` represent learning content.
- Badge, reward, competition, portfolio, goal, and study-plan models support
student-facing learning workflows.
## Compliance And Audit
- `AuditLog` records sensitive operational actions.
- `DataExportRequest`, `DeletionFlag`, `DataRetentionPolicy`, `DpiaRecord`,
`ComplianceConsultation`, and `SchoolComplianceStatus` support rights,
retention, and governance workflows.
- `Backup` stores metadata for storage-backed backup files; backup files live
below `BACKUP_PATH` and must not be placed in the database.
## Change Rules
- Additive schema changes require a Prisma migration and an updated seed path.
- Never rename or remove a stored field without a migration/backfill plan.
- New personal-data fields require a purpose, access policy, audit requirement,
export behavior, erasure behavior, and retention category before release.
- New feature tables must include school scope where the data is school-owned.
+1116
View File
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -138,7 +138,7 @@ schulos/
## License
MIT License — see [LICENSE](./LICENSE) for details.
MIT License — see [LICENSE](../LICENSE) for details.
## Contributing
+31
View File
@@ -0,0 +1,31 @@
# Roadmap
The execution roadmap is maintained in the root `TODO.md` checklist. This file
is the public summary of its delivery order.
## In Progress
- Delivery and security baseline: Docker, CI baseline, Argon2id, origin checks,
local storage, WAL, and verified online backups.
## Next
1. Complete account lifecycle security: reset tokens, verification, optional
TOTP, and auth-related end-to-end tests.
2. Build the school policy engine: configurable escalation, holidays, retention,
communication locks, quiet hours, and module gates.
3. Consolidate navigation into canonical module owners and tabbed pages; build
role-aware Bento dashboards without duplicate workflows.
4. Complete academic workflows: template cloning history, fast entry, grading
finalization attribution, versioned reports, real PDF and ZIP exports.
## Later
- Communication policy and notification delivery completion.
- Calendar, leave, substitution, and operations consolidation.
- Learning Hub governance, AI safety, and exam middleware.
- Digital notebook annotation and PWA support.
- Emergency signage, compliance automation, and full E2E/accessibility release
gates.
See `TODO.md` for detailed checkboxes, acceptance criteria, and blockers.
+95
View File
@@ -0,0 +1,95 @@
# Self Hosting
## Prerequisites
- Docker Engine with Docker Compose plugin
- A DNS name and HTTPS reverse proxy for production use
## Quick Start
1. Copy `.env.example` to `.env`.
2. Set `NEXT_PUBLIC_APP_URL` to the public application URL.
3. Review storage and optional SMTP values.
4. Build and start the service with `docker compose up -d --build`.
5. Review logs with `docker compose logs -f schulos`.
6. Run Prisma migrations inside the service when a release includes migrations.
7. Seed demo data only in a non-production instance with `pnpm db:seed`.
The service listens on port `3000` by default. Set `SCHULOS_PORT` in `.env` to
change the host port.
## Request Origin Protection
All mutation requests below `/api/` require a matching `Origin` or `Referer`.
Set `NEXT_PUBLIC_APP_URL` to the public HTTPS origin. For an approved second
origin, such as a separate admin host, provide comma-separated origins. Do not
include wildcard origins.
## Backup
Back up the complete persistent volume, including the database, uploads,
exports, and backups. For SQLite in WAL mode, preserve the main `.db` file and
its `-wal` and `-shm` companions or use SQLite's online backup command.
Test restores into a separate disposable deployment before relying on a backup.
The in-app backup endpoint writes a school-scoped JSON file to `BACKUP_PATH` and
verifies its readability before a restore drill; it does not automatically
overwrite a live database.
### WAL And Verified SQLite Backups
Run the following commands from the deployment directory after setting the
production environment values:
```bash
pnpm db:wal
pnpm db:backup
```
`db:wal` enables WAL mode, normal synchronous behavior, foreign-key checks, and
a checkpoint. `db:backup` uses SQLite's online `.backup` command, writes the
copy to `BACKUP_PATH`, and runs `PRAGMA integrity_check` on the result. A
successful command prints the backup file path, byte size, and `integrity: ok`.
Inside Docker, run the same commands with:
```bash
docker compose exec schulos pnpm db:wal
docker compose exec schulos pnpm db:backup
```
Do not restore onto the active school deployment. Copy the verified backup to a
separate maintenance environment, set its `DATABASE_URL` to the copied file,
and complete a login and data-read smoke test first.
## Upgrade
1. Take and verify a backup.
2. Pull the reviewed release.
3. Run `docker compose up -d --build`.
4. Run required Prisma migrations.
5. Confirm health, login, and critical role workflows.
## Password Hash Migration
New passwords use Argon2id. Existing bcrypt password hashes remain valid for
one successful login and are transparently upgraded to Argon2id at that time.
No bulk password reset is required for this migration.
## Account Recovery
Password reset requests create a one-time, SHA-256-hashed token with the TTL
configured by `PASSWORD_RESET_TTL_SECONDS`. The API always returns the same
success message whether or not an account exists. In development only, or when
`AUTH_SHOW_RESET_TOKEN=true`, the raw token is returned for local testing.
By default, self-hosted registrations are marked verified immediately. Set
`AUTH_REQUIRE_EMAIL_VERIFICATION=true` only after integrating a reviewed email
verification delivery flow. TOTP and recovery-code enrollment remain a planned
security enhancement.
## Compliance Notice
This software can support privacy-compliant operations but is not legal advice.
The deploying school must involve its DPO, Schultrager, and Personalrat before
processing real student data.