Security
SourceWyse holds a hotel’s own operating material and answers its staff’s questions from it. This page says how that material is kept, and what this platform does not claim. Every statement below is one a test, a script or a document in the codebase demonstrates.
The outside companies that receive anything are Anthropic, OpenAI, Supabase, Vercel, Stripe, Cloudflare, Resend, Sentry, The external uptime monitor. The register saying what each one receives, where it processes it and what it does with it afterwards is generated from the code itself, and is sent on request to the address at the foot of this page.
One property cannot see another
Every hotel's material lives in one database alongside every other hotel's, separated by rules the database itself enforces rather than by care taken in the software above it.
Every table that holds a property's material has row level security switched on. A harness signs in as one property's owner and attempts to read and to write every other property's rows, on every one of those tables, and it runs on every change.
tests/isolation/run.ts
What each role may do is decided by one function from role and product, and every screen renders from it. There are no permission checks scattered through the interface to fall out of step with each other.
tests/capabilities/map.test.ts
A member of staff can ask and can flag an answer. Staff hold no password, see no coverage figures, and reach no settings.
lib/capabilities.ts
When an operator of the platform crosses into a client's account, the crossing is written down as an event by the data layer, not by whoever remembered to log it.
tests/data/operator.test.ts
Guest information does not get in
The assistant is for staff and is never guest facing. What is kept about a guest is initials and a preference, and the check that enforces it runs before anything is written down.
Guest details are detected and cut at the point material enters the platform, on every upload and on every transcript of a recording. A document that reads as a guest record is not stored at all.
tests/ingest/gate.test.ts
The record that something was caught holds no guest content itself, which is checked by schema rather than by convention.
tests/ingest/pipeline.test.ts
A question asked of the assistant is recorded in the event history as a one way hash and never as text.
tests/telemetry/writers.test.ts
When something in the product fails, the report that leaves carries no byte of the failure's message. A test plants real hotel documents, a real guest note, a real answer and real key shapes into a failure and finds none of them in what is sent.
tests/security/scrub.test.ts
Files, and how they are held
Uploads and recordings sit in private storage under the property they belong to.
Neither storage area is public, and there is no route to a stored file without a signature.
tests/ingest/uploads.test.ts
The only way a file leaves is a signed link that stops working sixty seconds after it is made, so a link that is forwarded or left in a browser's history is already dead.
lib/ingest/storage.ts
A file has to be the kind of thing its name claims before it is stored. The contents are read, not the name, and a disagreement is refused with both halves named.
tests/ingest/uploads.test.ts
Uploads are bounded per file and per property, and nothing uploaded is ever served back as a page or run as code by this product.
docs/data-handling.md
Getting in
The four doors a stranger can reach are bounded per connection and per address, with a lockout that doubles, and every limit is a value an operator can change without a deployment.
tests/auth/rate-limit.test.ts
None of those doors reveals whether an address has an account here, in what it says or in how long it takes to say it.
tests/auth/rate-limit.test.ts
A session has a fixed lifetime written on its own row when it is created, and an expired row is refused even when the token it arrives with would still be accepted.
tests/auth/flows.test.ts
Owners, administrators and operators sign in with a password and may add two factor authentication. Staff sign in by a link sent to their email and never hold a password at all.
tests/auth/doors.test.ts
Every response carries a content security policy with no inline scripts permitted, plus strict transport security, a referrer policy, a permissions policy and no content type sniffing. A real browser walks every public page and raises no policy violation.
tests/security/headers.test.ts
Keeping it, and losing it
Published material is retired with a pointer to what replaced it rather than deleted, so the old wording is still readable with the date it stopped being true. A database trigger allows a true deletion in only two places: a draft that was never published, and the account deletion script.
tests/registry/registry.test.ts
The whole database is copied every night into separate storage with a different provider, and restoring a single property from a copy is exercised by a test rather than assumed.
tests/backups/backups.test.ts
Closing an account removes its rows and its stored files within thirty days, and the removal is itself recorded so there is an audit trail of what went.
scripts/delete-account.ts
The event history is kept for thirteen months, and the nightly copies are pruned on the same clock.
tests/telemetry/retention.test.ts
Material at rest is held by Supabase, and backups by Cloudflare, both of which encrypt what they store. Who receives what, and on whose terms, is set out company by company in the subprocessor register.
docs/subprocessors.md
How it is built
Development, tests and screenshots run against a database on a developer machine. The live database is reachable only from the deployment, and a check fails the build if a production key or hostname appears anywhere in the code.
scripts/check-no-prod-keys.mjs
Every push and every proposed change runs the whole test suite against a database built from nothing, and a further check refuses to let any test suite sit outside that run.
.github/workflows/ci.yml
Work that must not happen twice, such as charging a card or sending an email, runs through a ledger keyed by the work itself, so a job that runs twice has its effect once.
tests/jobs/jobs.test.ts
The list of outside companies that receive anything is generated from the code, and the build fails when the software reaches a company that list does not name.
scripts/check-subprocessors.mjs
The product connects to no booking system, no payment system of the hotel's and no third party service on the hotel's behalf. Material arrives by upload, by paste, by recording, or by one authorised read of the property's own public website.
docs/subprocessors.md
What this platform does not claim
A page that lists only strengths is read as claiming everything it does not deny. These are the things SourceWyse has not done.
- SourceWyse has no SOC 2 report. There is no audit under way and no date to give you.
- There is no ISO 27001 certificate.
- No third party has run a penetration test against this platform.
- There is no formal bug bounty. If you find something, the address below is a person who will read it.
- This page describes the platform as built and tested. It is not a warranty, and it is not a substitute for the terms of the agreement.
Reporting something
If you have found a weakness, or your website was read by SourceWyse and you would rather it was not, write to security@sourcewyse.com. A person reads it. Our readers identify themselves as SourceWyse and obey a rule written for that name in a robots.txt file.