Data and security

This page collects, in one place, the answers people usually have to extract piecemeal: what is stored where, who can see it, what leaves the platform and how long it is kept. Two things here depend on the plan: how long run history is kept (three days on free) and the size of the team (one seat for an invited member on top of the owner on free — see Team and roles); exact values are in Plan limits. Roles, data scoping, secrets and the deploy channels are not plan-gated and work on any plan.

What is scoped to a workspace

The workspace is a data boundary, and the boundary is drawn in storage rather than in the interface. Every query carries the workspace id, so an object from a neighbouring workspace is not merely hidden — it is not found.

DataScopeWho can read it
Scenarios, versions, runs, logsworkspaceany member
Files and storageworkspaceany member
Database collectionsworkspaceany member
Knowledge bases and their vectorsworkspaceany member
Chat historyworkspaceany member
Agent memory and variablesworkspacethis workspace's scenarios
Secretsworkspacenames — editor and above; values — nobody
Connectionsworkspacemembers see the settings, secret fields masked
Quark balance, plan, profileowner's accountthe account owner

A practical consequence: the platform cannot move data between workspaces. If clients must be kept apart, split them into workspaces up front rather than “once we grow”.

Inside one workspace there are three roles deciding who reads and who changes; the breakdown is in Team and roles. One point is worth repeating here: a viewer reads all of the data — chat history, files, collection contents. The role limits changes, not curiosity.

Secrets

A secret is a “name → value” pair belonging to the workspace: Settings → Secrets. Any template refers to it as {{ secret.NAME }}, so the name has to be a valid identifier — like an environment variable: OPENAI_API_KEY, CRM_TOKEN.

How it works:

  • Stored encrypted. The value sits in the database as ciphertext; the encryption key is derived from the installation’s master key and is not the key that signs login tokens.
  • The value never comes back out. The API returns only the name and a “value is set” flag. Neither an admin, nor the owner, nor support can look at a stored secret — it can only be overwritten. When editing, an empty value field means “keep the current one”.
  • Decrypted once per run. The first {{ secret.* }} in a run loads and decrypts the set into process memory for the duration of that run; nothing decrypted touches disk.
  • A workspace admin changes secrets, while an editor can see the names (needed for autocomplete in the editor). A viewer sees not even the names: the list of names is a map of your integrations.
  • Deleting a secret does not break the graph on the spot. A reference to a deleted secret expands to an empty string and the scenario keeps running — with an empty key in the header. The failure arrives from the remote service and reads like “invalid key”, not like “no such secret”. Which is exactly why deleting one deserves a second thought.

Connection credentials (an IMAP password, a CRM token, a model provider key) behave the same way: encrypted, never returned, empty field on edit means “leave it”.

Secrets do not reach logs or error text. Node input/output snapshots replace credential fields with the connection’s name, and every error string goes through a sanitizer that strips this run’s secret values, Bearer …, sk-…-style keys and passwords inside URLs. The reason: a chatty remote often quotes the key it was given back inside its own error message, and without the scrubbing that message would become a viewer for the key.

What leaves the platform

Every outbound HTTP request — from an HTTP node, a connection, a model call — goes through one guarded client with an address policy. The policy is applied on every connection and every redirect, not once against the URL string: an address that points into a private network after a redirect is refused there. Loopback, RFC1918 and link-local ranges are closed, and each request has a hard timeout and a response-size ceiling.

User JavaScript (the JavaScript Code node) runs outside the platform process, in a separate sandbox: no database, no secrets, no file storage, a read-only filesystem, restricted networking, and quotas on time and concurrency. Details are in Your own code.

De-identifying the request to a model

The conversation text can be sent to a model with recognised personal data replaced by markers: a phone number, email, tax or insurance id, card number, IBAN, address or full name becomes <PHONE_RU_a1b2c3> and the like, and the originals are put back into the model’s answer — including the arguments of any tool it called, so your CRM receives the real number rather than a marker. The mapping between marker and original is restored on our side and is never handed to the model provider.

Where it is switched on: Settings → De-identification for the whole workspace, plus a field on the node when one step needs to differ. By default the channel decides: on where the other party is a stranger — public chat, the widget, Telegram, VK — and off for internal runs from the editor, on a schedule, by webhook or through the API.

What it does not cover — more important than what it does:

  • attachments: photos, scanned documents and voice messages pass through, because recognition is textual;
  • knowledge-base ingestion — a document’s text reaches the embedding provider as it is;
  • web search, media prompts and HTTP node calls — separate outbound paths.

Recognition is not guaranteed to be complete: some data in free-form text remains. That is why the interface and this page say “de-identify recognised data” rather than “remove personal data” — the second would be a promise the mechanism does not make.

We keep the originals. Chat history, logs and the run breakdown are not rewritten: otherwise the breakdown would stop answering “what did the customer actually say”. De-identification is about the outbound request, not about storage.

If the recogniser is unavailable while de-identification is on, the run fails with a clear error and the request does not leave — there is no silent degradation here.

The screen says what is in force right now. The recogniser first runs in a measuring phase: it reads real traffic, records what it catches and what it costs in latency, and changes nothing that is sent. Everything above describes the phase after that, once masking switches on. Settings → De-identification names the phase in force, including the one where your choice is stored and starts working the day it is enabled.

Channel keys are the right to spend your quarks

The public chat link, the widget token and the webhook key are not “API access”. Each grants exactly one thing: running one published scenario, with the quarks billed to the workspace owner’s balance. Hence the practice: the chat link is handed to customers, the webhook key is not — the first is protected from abuse by channel rate limits, the second admits a machine.

KeyWhat it grantsHow it is issuedHow to invalidate it
Public chat and widget linktalking to one scenarioautomatically on first publishturn the channel off and republish
Webhook keystarting a scenario over HTTPautomatically when publishing to webhookturn the channel off and republish
Widget signing secretsigning end-user JWTsa button in settingsrefresh button
Assistant MCP keydriving the platform over MCPa button in settingsrotate or disable

Every door, and what is missing from among them, is covered in API access.

An attachment a scenario returned into a chat is reachable through a signed link: it is unguessable, but it works without a login and without an expiry — otherwise an attachment in a conversation would stop opening a month later. The practical conclusion: such a link is access to the file, and it deserves the same care as the file itself. Files are served with headers that stop the browser executing their contents: uploaded HTML will not become a page on your domain.

How long things live

  • Run history is pruned by plan: from three days on free up to 90 on Business; the exact values are in the limits table, which is generated from the configuration. The prune is “soft” — logs and per-node rows are deleted and the heavy inputs/outputs are nulled, while the run row itself keeps its status and timing, so statistics stay intact. Opening an old run says plainly that its details were purged.
  • Chat history is never deleted automatically. A person clears it, from the chat’s own controls (editor role). Keep that in mind if a customer contract forbids storing conversations.
  • Recorded Telegram group history is off by default, is switched on per scenario, and has its own plan-driven retention and message cap.
  • Files, collections, knowledge bases and memory have no expiry — they live until deleted and count against the owner’s storage quotas (Plan limits).

Archiving a workspace deletes none of this: the data stays, only a slot in the workspace quota is freed.

Signing in

The password is stored as a hash. A sign-in lasts while you work and ends after a week without a single action — then the platform asks for the password again. Changing the password ends the sign-in on every device at once. Sign-in and registration attempts are rate-limited. Logins, role changes and secret edits go into a security audit log with time, actor and IP — a log available today only to the installation’s global administrator.

If the password is forgotten

The sign-in screen carries a “forgot your password?” link. It asks for an address and mails a one-time link to it; the link is good for one hour and works once. Opening it asks for a new password and signs you straight in.

The confirmation the form shows is the same whether or not that address has an account, and that is deliberate: an answer that differed would let anybody with a list of company addresses find out, one submit at a time, who works with you. So a letter that never arrives means one of three things — a typo, no account on that address, or the letter landed in spam.

Two consequences worth knowing before they surprise you:

  • Changing the password ends every other session. The tab you changed it in keeps working; a phone, a second browser and a colleague’s borrowed laptop all ask for a sign-in again. That is what makes a reset useful after a leak rather than merely tidy.
  • The token travels in the link’s fragment (the part after #), which browsers never send to a server. It stays out of our access logs, out of Referer headers and out of any proxy in between. A mail client that wraps the link across two lines breaks it, though — copy the whole line if the page says the link is incomplete.

The same password can also be changed from inside the app, in Settings → Account, where the current password is required. The installation’s administrator still cannot set somebody’s password for them — that handle does not exist, and recovery goes through the address on the account.