Security

Built for trust. Every layer audited.

NusaBook handles your guests' phone numbers, conversation history, and booking data. Here's exactly how we protect them — concrete safeguards, not marketing claims.

How we think about it

Three pillars, defense in depth.

Security isn't one feature you turn on. It's many small protections layered together. Below: the load-bearing ones.

Tenant data isolation

Your bookings, customers, and conversations live in their own row-level partition. Other businesses on the platform cannot read or write them — enforced at two layers, not one.

  • PostgreSQL Row-Level Security on every tenant table (bookings, customers, conversations, services, platform events). Policies check business_id against the signed-in user's owned business.
  • Application-layer ownership check on every server action — even if RLS ever had a gap, the app code would catch a cross-tenant attempt and return 'not found'.
  • Automated cross-tenant access test runs on every pull request, deliberately using a fake database client that doesn't simulate RLS. The test fails if the app-layer check is ever removed.
  • Service-role database access is gated to three places only: admin (us), webhook handlers (signature-validated), and cron jobs (secret-validated). Never reachable from a customer URL.

AI safety guardrails

Your AI concierge can answer guests, take bookings, and quote prices — but only ones in your catalog. It cannot negotiate, give discounts, comp services, or be tricked into promising a free villa.

  • Server-side catalog enforcement: every booking the AI creates uses the price stored in your dashboard, never a price the AI quoted in chat. A jailbroken AI cannot produce a $0 booking — the database row carries the real price.
  • Hardened system prompt: explicit rules forbidding discounts, freebies, refund promises, and 'honoring' deals customers claim a staff member offered.
  • Inbound messages are wrapped in <customer_message> tags before reaching Claude. The wrap pairs with prompt instructions that say content inside the tag is data, not commands.
  • Pattern scanner on every inbound message: 'ignore previous instructions', role-takeover, developer-mode, fake-system, delimiter injection. Detected attempts log an audit event so we see them — without giving the customer a 'refused' signal an attacker could iterate on.
  • Price-drift audit: if the AI quotes a number more than 25% off the catalog price, we log a 'price_drift_detected' event for human review. The booking still gets the catalog price.

Account security

Your dashboard, billing, and guest data sit behind battle-tested authentication. We don't write our own login — we use Supabase Auth on top of GoTrue with industry-standard primitives.

  • Email + password sign-in uses bcrypt hashing (10 rounds). No plaintext credentials, ever.
  • Optional Google OAuth for tenants who prefer single sign-on. We never see your Google password.
  • Email verification required before a new account can complete onboarding. Auto-purge of unverified accounts older than 7 days keeps the auth pool clean.
  • Vercel BotID protects the signup form. Bot signups are filtered at the edge before they reach our database.
  • Per-IP rate limit on signup (5 attempts per hour) catches credential-stuffing patterns.
  • Two-factor authentication available for tenant dashboards (rolling out — opt-in via Settings → Security).

The full list

Every safeguard, named.

If a section is missing from this page, we haven't built it yet. We update this list when new protections ship — not the other way around.

Encryption in transit + at rest

  • TLS 1.3 on every connection between your browser, our app, our database, and our payment + messaging providers.
  • Database storage encrypted at rest (AES-256) via Supabase's managed Postgres.
  • All secrets (Stripe keys, Anthropic keys, Twilio tokens) live in environment variables, never in the source code or the client bundle.
  • Database backups encrypted at rest with the same standard.

Payment safety — we never see your card

  • Subscription checkout redirects to Stripe's PCI-compliant hosted page. Your card number never reaches our servers.
  • We store only Stripe customer IDs and subscription metadata — opaque references, not card data.
  • Card updates, cancellations, invoice downloads all happen on Stripe's customer portal, not in our UI.
  • Webhook events from Stripe are signature-verified before we touch any tenant row.

GDPR alignment + data ownership

  • Your guests' phone numbers and message contents belong to you (NusaBook is the processor, you are the controller — see our Data Processing Agreement).
  • Right to be forgotten: when you cancel, we delete your tenant data within 30 days. Backups roll off within 90.
  • Export-on-demand: every page in your dashboard supports CSV/JSON export so you can leave with your data.
  • We never sell guest data, never share it with advertisers, and never train models on your conversations.

WhatsApp Business — proper Meta channel

  • Production tenants use Meta's official WhatsApp Business API via embedded signup — you authorize NusaBook once, you can revoke any time from your Meta dashboard.
  • We never ask for or store your Meta password.
  • Each tenant gets their own WhatsApp number, isolated from every other tenant. A message to one business cannot accidentally route to another.

Code-level static analysis

  • GitHub CodeQL scans every pull request for OWASP-Top-10 patterns (injection, XSS, path traversal, hardcoded secrets, broken auth).
  • Dependabot opens automatic PRs for vulnerable npm packages. Security advisories above low severity bypass the weekly schedule and open immediately.
  • GitHub Secret Scanning + Push Protection rejects accidental commits of Stripe / Supabase / Twilio / Anthropic keys before they leave a developer machine.

Role-based access (planned)

  • Owner can see revenue, change billing, edit the catalog. Staff can answer the inbox + see the calendar, but cannot see billing or sales totals.
  • Manager role for senior staff who handle reschedules and supplier coordination but don't need accounting access.
  • Every role boundary is enforced server-side, not just in the UI. Hiding a button is not security; refusing a request is.
  • Rolling out in Phase 2 of the platform security work.

What we don't claim

We don't claim to be SOC 2 audited (the audit is on the roadmap, not done). We don't claim zero downtime (we're a young SaaS — when an incident happens we'll tell you on a status page). We don't claim our AI is impossible to jailbreak (no model is — we make the cost of an attack high and the consequences of a successful one low).

If you spot something we've missed, email security@nusabook.com — we take responsible disclosure seriously and respond within 48 hours.

Questions?

For sales / general security questions: hello@nusabook.com.

For vulnerability disclosure or anything sensitive: security@nusabook.com. We respond within 48 hours and credit responsible reporters.

Security — NusaBook