Trust centre
One page for the questions a security review asks: who touches the data, what protects it, and where it lives.
Register last updated: 2026-09-02
Everything here is written from files in the public repository, and each claim names the document behind it. Where something is not true yet, this page says so — a trust page that publishes only the reassuring half is worth less than none.
At a glance
One server
The application, its MySQL database and its backups all sit on a single Plesk-managed host. No managed database service, no object store and no CDN holds your data.
No selling, no billing
The platform is free for mentees and mentors. There is no payment processor, no ad network and no data broker anywhere in the codebase.
Optional by default
AI, calendar sync, hosted video, push and every analytics provider stay dormant until an operator sets their environment variables — and most also need the individual person to agree.
No trackers on the CRM
Analytics and live chat are mounted from the public shell only, never from the application itself. A signed-in pageview would carry a mentee’s name to a vendor, so it cannot happen.
Free for mentees and mentors. Nothing on this page is a paid add-on.
Who operates this deployment
This instance is operated by Mehmet Erşahin. Full contact details are published in the imprint.
Subprocessors
Every third party this codebase can send data to. The list is derived from the deployment configuration file, so it cannot quietly fall behind the code.
| Subprocessor | Purpose | Data categories | Hosting location | DPA / SCC basis | Optional per deployment |
|---|---|---|---|---|---|
| Plesk-managed server (operator)DATABASE_URL | Runs the application container, the MySQL database and the backups. | All application data: accounts, profiles, CVs, interaction logs, messages, uploaded documents. | The operator’s single server; the country is named on request. | Direct contract between the operator and their hosting provider. | Required |
| Primary SMTP relaySMTP_HOST, SMTP_USER, SMTP_FROM | Mail that has to reach a human: address verification, invitations, password reset, message notifications. | Recipient name and e-mail address, subject and body, links carrying signed tokens. | Operator-chosen; the shipped default is the deployment’s own mail server. | Direct contract with whichever relay the operator points it at. | Required |
| Bulk SMTP relaySMTP_BULK_HOST, SMTP_BULK_FROM | A second outbound channel for digests, reminders, announcements and newsletters. | The same categories as the primary relay, for non-urgent mail only. | Operator-chosen; deliberately often a different provider and sending domain. | Direct contract with that relay. | Optional |
| AnthropicANTHROPIC_API_KEY | AI-assisted CV reading and the AI assistant features. | Text extracted from an uploaded CV, and the prompt built around it. | Anthropic’s API. | Anthropic’s commercial terms, held by the operator. | Optional + consent |
| Google CalendarGOOGLE_CLIENT_ID, GOOGLE_CALENDAR_ENABLED | Mirroring in-app meetings into a user’s own Google Calendar. | Meeting title, description, start and end time, attendee addresses, and that user’s OAuth tokens. | Google. | Google’s API terms, held by the operator. | Optional + consent |
| 8x8 JaaSJAAS_APP_ID, JAAS_API_KEY_ID, JAAS_PRIVATE_KEY | Hosted video rooms for one-to-one meetings. | Display name, room identifier and the live audio and video stream. | 8x8’s JaaS infrastructure. | 8x8’s JaaS terms, held by the operator. | Optional |
| meet.jit.si (8x8) | The default video room when JaaS is not configured, the fallback when a JaaS call cannot start, and the permanent home of group and recurring meetings. | Display name, room identifier and the live audio and video stream. | 8x8’s public instance. | Public-service terms only — no contract. | Required |
| Browser push servicesVAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY | Background notifications for new messages with the app closed. The service is chosen by the subscriber’s browser, not by us. | The push endpoint the browser issued, an encrypted payload, and the contact address identifying the sender. | The browser vendor’s push service — Google, Mozilla or Apple. | None available: the protocol gives the sender no counterparty. Payloads are encrypted to the subscriber’s own keys. | Optional + consent |
| Plausible AnalyticsNEXT_PUBLIC_PLAUSIBLE_DOMAIN | Pageview measurement on public marketing pages only. | Pageview URL, referrer, coarse device and browser data. Cookieless. | Operator-chosen; defaults to plausible.io, and is self-hostable. | Plausible’s DPA, held by the operator — or none needed when self-hosted. | Optional + consent |
| PostHogNEXT_PUBLIC_POSTHOG_KEY | Pageview measurement on public marketing pages only. Autocapture, session recording and local storage are forced off in code. | Pageview URL, referrer, coarse device and browser data. | Operator-chosen; the shipped default is PostHog’s EU region. | PostHog’s DPA, held by the operator. | Optional + consent |
| Google Analytics 4NEXT_PUBLIC_GA4_MEASUREMENT_ID | Pageview measurement on public marketing pages only, loaded with IP anonymisation. | Pageview URL, referrer, truncated IP, coarse device and browser data. | Google. | Google’s Analytics terms and standard contractual clauses, held by the operator. | Optional + consent |
| tawk.to | The live-chat widget on the public home page. | The visitor’s IP address, and whatever they type into the chat. | tawk.to. | tawk.to’s terms, held by the operator. | Optional + consent |
| GitHub Actions + ghcr.io | Continuous integration, container image builds and the registry the server pulls from. Supply chain, not request handling. | Source code, build logs and container images. No end-user personal data. | GitHub-hosted runners and registry. | GitHub’s terms, held by the operator. | Required |
Controls
The short version of the security overview. Every item is backed by a document in the repository.
Fail-closed authorization
Scoping runs through one function. A role with no scope builder gets a 403 rather than an unfiltered query, so adding a role grants nothing until someone writes its rules. Regression-tested in CI.
Sessions and two-factor
bcrypt password hashing, JWT sessions, role-based two-factor enforcement and “sign out of all devices”. Staying signed in is a separate rotating, revocable per-device token — not a longer session.
Consent before anything optional
Analytics and live chat load only once a stored, versioned consent record allows them. The version is bumped whenever a category’s meaning changes, so an old yes never silently covers a new vendor.
Backups, and a rehearsed restore
A full dump before every production deploy and daily at 03:15 UTC, restrictive file permissions, an automated liveness check, and a restore drill with a written log.
Nothing compiles on the server
Images are built on hosted runners and pulled by the host, which only swaps the container and health-checks it. Contributors develop against synthetic data, and each pull request gets its own database, dropped when it closes.
Audited, with the gaps written down
A role × endpoint security audit and a triaged static-analysis report. The areas that tested clean are recorded so that breaking one counts as a regression — and the areas never examined are listed just as explicitly.
What is not true yet
Publishing only the reassuring half would make the rest worth less.
- Multi-tenant isolation is not enforced in production. The organization model, per-tenant plans, branding and SSO are live and the enforcement engine is written, but the enforcement flag is off and the per-route rollout is still in progress: the live application is effectively single-tenant, and nothing filters by organization today.
- Production, the shared preview and every pull-request environment run on one host. They are separate containers with separate databases, not separate machines.
- There is no SOC 2 report and no ISO 27001 certificate for this deployment. What exists instead is a public repository, this register, and internal audit documents you can read.
- Web Push has no contractual counterparty — the protocol offers the sender none. Payloads are encrypted to the subscriber’s own keys, and the feature stays off unless a keypair is configured and the user opts in.
Hosting and data residency
The application, its database and its backups run on one Plesk-managed server. This repository does not assert a hosting country and will not: the project is open source and other people run their own instances, so a region written into the source would be a claim about somebody else’s server. The operator of this deployment states its location on request.
What the code does pin, and you can therefore verify without asking anyone: the shipped PostHog default is the EU region, Plausible is cookieless and self-hostable, and every other third-party path is inert until an operator switches it on.
The residency answer of last resort
InternshipCRM is licensed AGPL-3.0-or-later. You may run your own instance, on your own infrastructure, in your own jurisdiction, without asking permission and without paying anyone. That is the strongest data-residency guarantee this project can offer, because it removes us from the question entirely. Dual licensing is available from the rights holder, Mehmet Erşahin — a natural person, not a company.
Read the source
The long-form versions live in the repository, next to the code they describe: