RobnuAI cannot read another seller. The database refuses.
Safety isn't a marketing feature. It's the wiring. Every RobnuAI surface — copilot today, ads-automation tomorrow — runs through withSellerScope, which sets the Postgres GUC for the request and inherits row-level security. Cross-tenant access is impossible at the database layer, not the code layer.
- Application layer: every Prisma query goes through withSellerScope; the seller_id is locked at the request boundary.
- Database layer: Postgres RLS enforces seller_id on every seller-scoped table. A leaked code path still cannot return another tenant's row.
- Gateway layer: PII redaction sits between RobnuAI and any external provider. Names, phones, addresses, GSTINs are redacted before the call and re-hydrated after.
What you get.
withSellerScope
The single sanctioned data-path helper. Wraps queries in a transaction; sets SET LOCAL ROLE robnu_tenant + app.current_seller_id. There is no other way to read seller data.
Postgres RLS
Defense-in-depth on seller_id. Even if a developer forgets a where clause, the database refuses. Helper functions app_current_seller_id() and app_is_admin_scope() govern policy.
PII redaction
Redaction runs at the gateway boundary. The model never sees a real customer name, phone, address, or GSTIN. The response is re-hydrated on the way back so the seller sees real data.
Encryption-at-rest with a key only your tenant can use.
Every seller has a Data Encryption Key (DEK) wrapped under your AWS KMS alias. When AWS_S3_PER_SELLER_KMS=true, the alias is alias/robnu/seller-{sellerId} — otherwise the seller's DEK is wrapped under the default Robnu alias. Either way, the cleartext DEK lives in process memory only for the duration of an encrypt/decrypt operation.
PII columns on Order — customer_name_enc, customer_phone_enc, customer_email_enc, address_enc — are stored encrypted with the seller's DEK. The same DEK protects S3 objects via SSE-KMS. The end-to-end story: a leaked S3 bucket without your KMS alias decrypts to ciphertext.
What's logged on every RobnuAI action.
- Every conversation is a row in ai_conversations with seller_id locked at create.
- Every message is a row in ai_messages with role + content + tool_call_id.
- Every tool call is a row in ai_tool_calls with arguments_json and result_json.
- Every prediction is a row in ai_predictions with model_version + inputs hash.
- Every extraction is a row in ai_document_extractions with source storage_key.
- Every action against marketplace data lands in audit_log with actor + impersonation_session_id.
Practical answers.
RobnuAI uses providers under contracts that prohibit training on your data. PII is redacted before any provider call. The training-data answer is enforced both contractually and operationally.
Two layers stop them. The application layer requires going through withSellerScope. The database layer has RLS policies that filter by seller_id. SuperAdmins use a separate role with explicit ImpersonationSession scoping — every read is logged with the session ID.
Yes. There's a tenant-level kill switch that disables all RobnuAI surfaces for your seller. Conversations stop, document extraction stops, agents stop. Existing rows stay for audit but no new ones are created.
Conversations are persisted in your tenant for replay and audit. Provider gateways log only the redacted, PII-stripped form. Robnu staff cannot read your conversations without an ImpersonationSession, which leaves a trail.
Security overview is on /security — vault, KMS DEK-per-seller, encryption-at-rest, audit log, JWT, DPDP-aligned. RobnuAI safety is built on the same primitives.
Try it inside your own dashboard.
Free during early access. No card. Forever free under 25 orders/day.
