Your data lives in its own database. Always.
Most ERPs put 100+ customers in one shared database with a row-level customer filter. We don't. Each customer institution gets its own physical database — separate backups, separate keys, separate blast radius.
Six guarantees, every one of them structural — not configurable.
These aren't settings you can turn off. They're how the system is built.
Per-institution separate dedicated databases
Each customer institution gets a dedicated database with its own connection string, backup schedule, encryption keys. A bug in customer A's code path cannot return customer B's data — there's no shared connection to query in the first place. (A multi-branch trust or university with affiliated colleges is one customer — all of its schools share one DB; the isolation boundary is the customer, not the individual school.)
- Connection-string resolver routes every query to the right DB at request scope
- Cross-customer queries are physically impossible — wrong DB, wrong server in many deployments
- Backups are per-customer — restore one customer without touching anyone else
- Per-customer data residency: place customer DBs in different regions if required
935+ permissions, enforced on every endpoint
Every AppService method is decorated with [AbpAuthorize(AppPermissions.X)]. No 'if user is admin, allow everything' shortcuts.
- Centralised permission tree, ~935 leaf permissions
- Cached permission catalogue keeps warm-call latency under 500 ms even with 935 perms loaded
- Self-service permission editor for school admins — assign at role + user level
- Class-level + method-level authorisation combine — both must pass
Audit log on every entity
Every domain entity carries CreatedBy, CreatedOn, LastModifiedBy, LastModifiedOn, and IsDeleted as first-class schema columns. Every change is attributable. Soft-delete is the default.
- Created / modified / deleted columns on every table
- Soft-delete by default — hard delete requires an admin action with reason
- Maker-checker on financial operations (Approval Workflow engine)
- Change history viewer on Voucher / Lead / Student / Staff records
Per-device session management
A user can log in from N devices. Admin sees all sessions, force-logout per device. Lost phone? One click, that device is signed out. The other devices stay logged in.
- User-visible 'My devices' list on /me
- Force-logout from any session (security incident, lost device)
- Per-device push-token registration (no token leaks between devices)
- Host + school admin can review and revoke any session
DPDP-Act readiness
Data Protection and Privacy Act 2023 readiness from day one. Data residency, consent registry, right-to-erasure flow, named grievance officer surface. Cookie-less analytics by default.
- Per-customer data residency: customer DBs can be placed in different regions
- Consent registry — communication preferences stored per parent / student
- Right-to-erasure runbook: school admin → erasure request → DPO approval → hard-delete batch job
- Cookieless analytics (no banner needed) on the public marketing site
Transport, headers, and the boring stuff that matters
TLS everywhere. Strict Content-Security-Policy. HSTS preload. Cross-origin policies tightened. Server-fingerprint headers stripped. Anti-forgery on every form. The basics, done right.
- TLS 1.2+ everywhere; HSTS with includeSubDomains + preload
- Strict CSP, X-Frame-Options: DENY, COOP same-origin, CORP same-site
- Server / X-Powered-By / X-AspNet-Version headers stripped
- __Host- prefix on the anti-forgery cookie (browser-enforced no-Domain)
- Allow-list HTML sanitiser on all user-rendered content
Found something? Tell us.
We run a responsible-disclosure program. Email security@schoolconsole.net or read the full policy at /legal/security. Auto-acknowledge within 24 hours, substantive response in 5 business days, 90-day window before public disclosure.