Legal placeholder
Security Statement
The technical and organisational measures protecting the RavSolutions service — transport, sign-in, sessions, workspace separation, files, abuse protection, logging and incident response — and, stated as plainly, what we do not have.
- Last updated
- 2026-08-04
- Version
- 1.0.0
- Reading time
- 12 min read
1. What this statement is
This statement describes the technical and organisational measures that protect the RavSolutions service and the data held in it. It is written to be checked: it names measures that are actually implemented, and section 15 states, just as plainly, what we do not have.
It is not a warranty and it creates no service level commitment; the contractual terms are in the Terms and Conditions. Where the same measure also appears in the GDPR notice or in the data processing information, it is meant to say the same thing in substance.
It covers the service we operate. The security of the accounts, devices and passwords inside a subscriber's own workspace is the subscriber's responsibility; no measure described here protects a workspace whose credentials have been shared or reused.
2. How the service is built
The service consists of three front ends — the website, the application and the customer portal — a single API, a PostgreSQL database, a Redis instance and object storage. The front ends reach the API only over HTTPS.
Everything except object storage runs behind a reverse proxy on RackForest Zrt. infrastructure in Hungary (EU). The database and Redis are attached to an internal network only and publish no port, so neither can be reached from the internet; only the API can talk to them.
Uploaded files are not kept on the application servers but in Cloudflare R2 object storage configured for European Union. The bucket is private: it has no public access and no custom domain in front of it, and every file is served through a link the API signs.
Secrets — database credentials, signing keys, provider API keys — are supplied through the environment at deployment and are never committed to the source repository.
3. Transport security
All traffic to the website, the application, the portal and the API is served over HTTPS. Certificates are issued and renewed automatically by Let's Encrypt, and plain HTTP requests are redirected to HTTPS.
The reverse proxy sends HTTP Strict Transport Security with a max-age of one year, including subdomains and with preload, so a browser that has seen the site once will not fall back to an unencrypted connection.
Responses carry X-Content-Type-Options: nosniff, X-Frame-Options: SAMEORIGIN, a strict-origin-when-cross-origin referrer policy and a permissions policy that denies camera, microphone and geolocation. Server and framework identification headers are stripped. The API accepts cross-origin requests only from the application and portal origins.
The website, the application and the portal are served with a Content Security Policy. Scripts may load only from the service itself and, in the application, from Google Identity Services for signing in with Google; the website and the portal allow no third-party script at all. Embedding in a frame, plugin content and rewriting the document base are refused, and the API answers with a policy that permits nothing whatsoever.
4. Sign-in and passwords
A password must be at least eight characters and contain an upper-case letter, a lower-case letter and a digit. Passwords are stored only as a salted cryptographic hash produced by the ASP.NET Core Identity password hasher; they are never stored in a form that can be read back, and we cannot recover a forgotten password, only reset it.
After ten failed sign-in attempts an account is locked for fifteen minutes. The count is kept against the account rather than the caller, so an attempt spread across many addresses is stopped even though each address stays under the per-caller rate limit.
Signing in with a Google account is available. The identity token issued by Google is verified against Google before any session is created, and we never receive the Google password.
Registration sends a confirmation message to the address given, and the address is marked confirmed when the link in it is used. A forgotten password is reset through a one-time link sent to the registered address; a successful reset also clears an existing lockout, because being locked out is the usual reason for resetting.
5. Sessions and tokens
Access tokens are JSON Web Tokens valid for fifteen minutes. Every request is checked for issuer, audience, signature and expiry, with no clock tolerance allowed.
A refresh token is sixty-four bytes from a cryptographic random generator. The database holds only its SHA-256 hash, so the token itself cannot be read out of a copy of the database.
Every refresh rotates the token: the previous one is revoked and a new one issued. Refresh tokens expire after thirty days, and signing out revokes the token immediately.
A refresh is refused if the user has been deactivated or the workspace made inactive, so withdrawing someone's access takes effect at the latest when their current access token expires.
6. Access control and separation of workspaces
Each user holds a role within the workspace and the endpoints check it. Plan-dependent features are additionally guarded by their own authorisation policies, so a feature outside the subscribed plan is refused by the API rather than merely hidden in the interface.
Workspaces are separated at the data level: every record carries the identifier of the workspace it belongs to, and every query is scoped to the workspace of the caller. A record belonging to another workspace is not hidden from the result — it is never selected into it.
The workspace is taken from a claim in the signed access token and is resolved on the server. A workspace identifier supplied by the client is not trusted for anything.
Real-time connections use the same authentication as the rest of the API; a connection without a valid token is refused, incoming message size is capped, and detailed error information is returned only in development.
7. Customer portal access
A customer receives a link containing a randomly generated token that belongs to a single job and carries an expiry date. The token opens that one job and nothing else in the workspace.
Before the job is shown, the visitor must confirm the e-mail address or the phone number recorded for that customer. A successful confirmation produces a proof valid for twelve hours, signed with HMAC using a key derived from — but cryptographically independent of — the server signing secret, and verified in constant time.
Confirmation attempts are rate limited per caller and deliberately not per token: limiting per token would let anyone lock a customer out of their own job simply by spending its budget.
8. Uploaded files
Uploads are restricted to a fixed list of file types — JPEG, PNG, WebP, PDF, DOCX, XLSX and plain text — and to a maximum size that depends on the subscribed plan. Images are re-encoded on the server before they are stored.
Files are delivered through short-lived signed links generated by the API. Because the bucket itself is private, an expired or altered link grants nothing at all.
Uploading and downloading have separate per-caller rate limits, so a leaked link or a runaway client cannot be used to drain storage or bandwidth without limit.
Stored files are encrypted at rest by the storage provider.
9. Protection against abuse
The API applies rate limits partitioned per caller — by the workspace and user in the token where there is one, and by client address otherwise. Sign-in, Google sign-in, password reset and portal confirmation are limited to ten attempts a minute; registration to five.
The limiters read the caller's real address from the proxy's forwarded headers, and only the proxy itself is trusted to set them. Without that configuration every request would appear to come from the proxy and a single budget would be shared by everyone, which would turn the protection into an outage.
The reverse proxy applies a further overall rate limit in front of the application, so traffic is capped before it reaches the API at all.
Incoming data is validated on the server before it reaches the domain logic, and errors are returned as structured messages: no stack traces, no database messages and no internal paths are sent to the client.
10. Data at rest
The database and Redis are on the internal network only and accept connections from the API alone; neither is exposed to the internet.
Object storage encrypts stored files at rest, and the bucket is not publicly readable.
Backups are taken regularly and their restoration is tested. Data erased at the end of a subscription disappears from backups as those backups expire on their normal rotation, and until then they are not used for any other purpose.
11. Logging and traceability
The application writes server logs, and each workspace has an activity history recording which user changed what and when. The history is visible to the subscriber inside the application.
Server, application and security logs are kept for 90 days, except where a particular record is held longer for an ongoing security investigation.
Logs exist for operating the service and investigating incidents. We do not log passwords, session tokens or payment card data.
12. Operations
Access to production systems and production data is limited to the personnel who need it for operation or support, on a least-privilege basis and under a confidentiality obligation that continues after their engagement ends.
Third-party dependencies are pinned and managed centrally, so a version is changed in one place; we apply security updates to the platform and to its dependencies as they become available.
Database schema changes are applied as versioned migrations when the service starts, so the schema in production always matches the code that is running on it.
13. Providers
The providers that process data on our behalf — hosting, object storage, e-mail delivery, payment and invoicing — are named, with their role and region, in section 5 of the GDPR notice and section 8 of the data processing information.
A new provider is announced at least 30 days before it starts processing, so that a subscriber who objects has time to act.
14. Incident response
We keep an internal register of personal data breaches and follow a procedure covering detection, assessment, containment and notification.
Where a breach is likely to result in a risk to the rights and freedoms of natural persons we notify the competent supervisory authority without undue delay and, where feasible, within 72 hours of becoming aware of it (Art. 33 GDPR); where the risk is high we also inform the affected individuals in plain language (Art. 34 GDPR).
Where we act as processor we notify the subscriber acting as controller without undue delay after becoming aware of a breach, and assist them with their own notification duties.
15. What we do not have
No online service can be made absolutely secure. This page describes measures, not guarantees, and the Terms and Conditions give no availability or service level commitment.
We hold no ISO/IEC 27001 certification and no SOC 2 report, and the service has not been subjected to an independent penetration test. Should any of that change, this is the section where it will be stated.
Two-factor authentication for user accounts is not available yet. Account security therefore rests on the strength of the password, the account lockout and the rate limits described above, which is why we ask for a password that is not used anywhere else.
The service runs in a single region with no cross-region failover, and if that region fails the service is unavailable until it returns. We name it because a security statement that lists only strengths cannot be used to make a decision.
16. Reporting a vulnerability
If you find a vulnerability, please write to info@ravsolutions.eu with a description, the steps needed to reproduce it and the address affected. We confirm receipt and tell you how we intend to handle it.
Please give us a reasonable opportunity to fix the problem before making it public. While testing, do not access, alter or delete data that is not yours, do not degrade the service for others, and do not use social engineering against our staff or our providers.
We do not run a paid bug bounty programme. We will not take action against a reporter who acts in good faith and within the limits above.
17. Changes to this statement
This statement is kept current with the service. The version number and the effective date at the top of the page show which text is in force, and earlier versions are available on request.
When a measure described here changes, this page changes with it. Questions about the content can be sent to info@ravsolutions.eu.