Add 21 files, update 16 files, rename 1 file
This commit is contained in:
1 parent
b9e4ed4dfc
commit
278293b397
39 files changed
+2434
-61
No files matched your search
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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
File diff suppressed because it is too large.
Load diff
+1
-1
@@ -138,7 +138,7 @@ schulos/
|
||||
|
||||
## License
|
||||
|
||||
MIT License — see [LICENSE](./LICENSE) for details.
|
||||
MIT License — see [LICENSE](../LICENSE) for details.
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
Reference in new issue
Block a user