Separating one shop from another
Every workspace’s data carries an organization identifier, and every query that reads or writes it filters on that identifier — tickets, messages, contacts, tags, skills, tasks, crawled pages, integration credentials and analytics alike. The identifier always comes from the signed-in session, never from anything the browser sends, so a request cannot be aimed at another workspace by editing it.
In several places the database enforces it as well as the code: the tables that link a tag or a chat conversation to a ticket use a composite foreign key including the organization, so the database itself refuses a row that crosses workspaces.
An automated test suite exists for exactly this failure. It creates two workspaces and asserts that neither can read the other’s tickets, analytics, contacts or people, and it runs against a real PostgreSQL instance rather than a mock.
Encryption
- All traffic to wilph.com is served over TLS, with HTTP Strict Transport Security set for two years.
- Data at rest is encrypted by our database and hosting providers.
- On top of that, the values that would be most damaging to leak are encrypted by Wilph before they reach the database, with AES-256-GCM and a key derived separately per purpose: integration credentials, mailbox OAuth access and refresh tokens, and Meta Page tokens.
- Secrets are never sent back to the browser. An integration form shows that a secret is saved, not what it is, and leaving the field blank keeps the stored value.
Accounts and access
- Passwords are hashed by our authentication library; we never see them.
- Sign-in, sign-up, password reset and verification endpoints are rate limited, counted in the database so the limit means the same thing however many servers are running. Password guessing is limited per account as well as per network address, so a pool of addresses cannot be pointed at one owner’s password.
- Resetting a password ends every existing session, because a reset is what somebody does after losing control of one.
- Owners and admins can change workspace settings, integrations, tags, skills and agent configuration. Ordinary members can use the helpdesk and see status, but not change how it is connected.
- Access to production systems is limited to those who need it to run the service.
The parts a stranger can reach
The chat widget, the direct-message webhooks and the inbound email address are reachable without logging in, so each is guarded on its own terms.
- The widget only loads on the domains you list, checked against the browser-set origin header, which page scripts cannot forge. A subdomain is never implied by its parent.
- Meta webhooks are verified against a signature over the raw request body; Stripe and email webhooks likewise. An unsigned or wrongly-signed delivery is rejected before anything is read from it.
- Four layers of rate limit sit in front of the public chat endpoint — per visitor, per day, per workspace and per deployment — and the direct-message and email-draft paths have their own. The last layer in each exists so one abused widget cannot exhaust capacity that every customer shares.
- Visitor IP addresses are never stored. Rate-limit counters hold a salted SHA-256 hash, which distinguishes visitors and is useless to anyone reading the table.
The website crawler
Crawling a customer’s site means fetching a URL somebody typed, which is a classic way into an internal network. The crawler refuses anything that is not a public domain, refuses IP addresses in every notation, resolves the hostname before connecting and refuses private ranges, and validates every redirect hop itself rather than letting the HTTP client follow them. It respects robots.txt and never queues cart, checkout or account pages.
What the AI is allowed to do
- Answers are grounded in your own crawled pages and the playbooks you enabled. A question neither covers never reaches the model.
- Crawled page text and visitor messages are treated as untrusted input, not as instructions, so text on a page cannot redirect the assistant.
- Your own configuration shapes how an answer is written, never what may be claimed. The model is forbidden from stating that a refund or an order change has happened, and it has no ability to make one.
- On email and in your inbox, a draft waits for a person. Automatic answering exists only on the chat widget and the direct-message channels, and both direct-message agents ship switched off.
Logging
Errors from the import, Replay and OAuth paths are logged as allowlisted metadata only — never the raw provider, model or database error. A database error can embed the parameters of the query that failed, and in those paths the parameters are somebody’s email. Prompts are not logged; token counts are.
Browser hardening
Every response carries a content security policy, frame-ancestors denial, MIME-sniffing protection, a referrer policy, a permissions policy and HSTS. Production builds ship no browser source maps.
What we have not built
Stated here rather than left to be discovered:
- No SOC 2 report and no ISO 27001 certificate. Wilph is a small company and has not been through either audit.
- No third-party penetration test has been carried out yet.
- No two-factor authentication and no single sign-on. Both are on the roadmap; neither exists today.
- Data is hosted in the United States. EU-only residency is not available — see the sub-processor page.
- Attachments on incoming email are not stored. The ticket records that files were omitted.
- There is no row-level security in the database as a second line behind the query filters. The automated tenancy tests exist because of that, not instead of it.
Reporting a vulnerability
If you find a security problem, email info@wilph.com with enough detail to reproduce it. We will acknowledge within three working days. Please give us a reasonable chance to fix it before telling anyone else, and please do not run automated scans against production or access data that is not yours — a report is welcome, a live test on a customer’s workspace is not.
How to reach us
Questions about this document, or any request about your data, go to info@wilph.com. We answer in English or Danish.