Security
A description of the controls the platform actually implements, so they can be verified rather than assumed.
Authentication
- Passwords are hashed with scrypt and a per-user salt.
- Login compares against a dummy hash when the address is unknown, so a failed login takes the same time whether or not the account exists.
- Sessions are opaque random tokens in an httpOnly, SameSite=Lax cookie (Secure in production). Only a SHA-256 hash is stored server-side.
- Changing or resetting a password revokes every session on every device.
- Verification and reset tokens are single-use, hashed at rest, and expire (24 hours and 1 hour respectively).
- Google sign-in verifies a CSRF state parameter, and refuses to link an unverified Google address to an existing account.
Authorization
- Role-based access control with a permission table, not scattered role comparisons. Roles: USER, AGENT_BUILDER, SUPPORT, MANAGER, ADMIN, SUPER_ADMIN.
- Every query that reads customer data is scoped by user id, so an identifier from another account resolves to a 404 rather than a leak.
- Admin routes check the specific permission they need, independently of the layout that renders the page.
- Nobody can change their own role or status, or grant a role above their own rank.
Request protection
- CSRF: cookie-authenticated mutations require an Origin match and a double-submit token.
- Rate limiting on login, registration, password reset, agent runs, public forms and webhooks.
- Input validation with Zod at every API boundary. Invalid input returns field-level errors, never a stack trace.
- Database access goes through Prisma with parameterised queries; there is no string-built SQL.
- Outbound requests from agents and workflow nodes reject loopback and private network ranges, blocking SSRF.
Secrets
- Integration credentials and OAuth tokens are encrypted with AES-256-GCM before storage and never sent to a browser.
- API keys are stored as SHA-256 hashes. The raw key appears exactly once, in the creation response.
- Provider API keys live only in server environment variables. All model calls happen server-side.
- Logs pass through a redaction filter that strips credential-shaped fields.
Agent execution
- Tools declare a risk tier: READ, WRITE or DESTRUCTIVE. An agent version declares the highest tier it may perform automatically.
- A call above that ceiling is refused, recorded as awaiting approval, and reported to the model as not performed.
- Runs are bounded by step count, token budget and a wall-clock timeout.
- Every step is persisted with its input, output, duration and risk tier.
Payments
- PROMIVO never sees or stores card data. Stripe handles it end to end.
- Webhook signatures are verified before the payload is read as data.
- Every event is persisted under a unique constraint, so a redelivery is recognised and skipped rather than double-applied.
- Entitlements are granted only by the webhook handler, never by a client-side success redirect.
Reporting a vulnerability
Reach us through the contact page with steps to reproduce. Please give us a reasonable window to fix an issue before disclosing it publicly.