Security in MindFlow is layered: authentication (who you are), authorisation (what you can do), and audit (what happened). Every sensitive action produces an audit record. Backups, scheduled tasks, and the plugin system are all visible and controllable to the clinic admin.
pages/2fa_setup.php and pages/2fa_verify.php implement RFC 6238 Time-based One-Time Password (TOTP) 2FA for all staff accounts. Compatible with any TOTP app (Google Authenticator, Authy, Microsoft Authenticator). Recovery codes are generated at setup and stored hashed.
Passwords are hashed with Argon2id (PHP password_hash PASSWORD_ARGON2ID) with tuned memory/time cost. Minimum complexity is enforced. Password reset tokens are single-use, hashed in the database, and expire after 60 minutes.
login_attempts tracks failed logins per IP and per username. After 5 failures in 10 minutes, the account is soft-locked and an email alert is sent to the admin.
includes/google_login.php + api/google_jwt_callback.php: staff can sign in with a Google Workspace account if the clinic admin has configured a Google OAuth client ID/secret. This is in addition to (not a replacement for) the password-based login — 2FA still applies.
Users are assigned a role. roles defines the role name; role_permissions maps each role to a set of permission strings (e.g., patients.view, billing.edit, ipd.admit). includes/rbac.php provides checkPermission() used on every protected action.
Permissions are defined at the action level (view, create, edit, delete) per module. A receptionist can be given patients.view but not prescriptions.create. The default roles (Admin, Doctor, Nurse, Receptionist, Pharmacist) are a starting point; admins can define custom roles.
Module-level access (e.g., accessing the Pharmacy portal) is controlled by includes/features.php featureEnabled() checks before RBAC — so a feature that is disabled at the plan level is inaccessible regardless of role.
audit_logs records every significant action: patient record viewed, note saved, prescription signed, billing change, role change, login, logout. Columns: user_id, action, object_type, object_id, ip_address, user_agent, timestamp, payload_hash.
security_incidents (pages/security_incidents.php): a register for data breaches, unauthorised access events, and other security incidents. Separate from clinical incident reports. Each entry has severity, description, affected patients (count), containment actions, and resolution status.
data_rights_requests (pages/data_rights.php): tracks patient Subject Access Requests (SAR) and erasure requests under the DPDP Act. Status workflow: received → acknowledged → fulfilled / rejected, with a deadline tracker.
pages/system_logs.php: PHP error log viewer, cron run history, and a tail of the application log — filterable by level and date range. Accessible to clinic admins only.
pages/backup.php + api/backup.php: database dumps are scheduled via the cron manager. Dumps are written to /backups/ (configurable path), compressed, and optionally encrypted. Backup history is visible in the UI with download links for the most recent N dumps.
pages/data_reset.php allows a clinic admin to wipe all clinical data from a deployment (patients, appointments, notes, billing, etc.) while preserving settings and user accounts. Protected by a confirmation code. Primarily used for demo/trial resets.
A patient erasure request (from the portal or from the data rights register) triggers a hard-delete of PII fields in the patients table and soft-deletion of linked records. The audit_log retains the anonymised event (action + timestamp) but not the patient's identity.
api/plan_control.php (used by the SaaS hoster) and general-purpose API endpoints are authenticated via API keys stored in app_settings. All API calls are logged in external_api_logs (endpoint, method, response code, latency). pages/api_usage.php visualises this log.
includes/plugin_loader.php discovers installed plugins (plugins/*/plugin.json), registers their hooks, and loads their settings. Plugins can add nav items, API handlers, and settings panels. includes/hooks.php provides the event system (do_action / add_action pattern). Plugins cannot override core code.
pages/cron_manager.php + includes/cron_jobs.php: all scheduled tasks (backup, reminder dispatch, appointment sync, expiry alerts, AI health audit) are defined here. Each task has a schedule (cron expression), last-run time, and a pass/fail log in cron_runs. The cron is triggered by a server cron job calling api/cron.php.
pages/updates.php + includes/updater.php: the admin can check for and apply application updates (database migrations + file updates) from within the admin UI, without server-level access.
The demo has real sample data — appointments, patients, prescriptions — so you can explore freely.