Workspace

Roles and personal data

How roles decide which conversations a person sees and how they see each kind of personal data, how to mark custom attributes that hold ID or payment details, and the Access page that shows the result for everyone.

Last updated

Who sees what in Kommio comes from three things on each role (Settings › Roles, where each permission has a readable name and a one-line hint): its permissions, what it may do; its visibility, which conversations and contacts it sees; and its field grants, how it sees each kind of personal data. The built-in roles are listed under permissions and scopes, and Settings › Access shows the result for every person.

Kinds of personal data

Every personal field carries a tag, and every role has a mode per tag: visible, masked (part of the value, such as m•••@example.com, •••• 3000 for payment details or ••• for an ID document) or hidden (nothing; the response names the field in _redacted so the app can say "Hidden for your role").

TagLabelBuilt-in fieldsCustom attributes
pii.emailEmail addressesContact emails, the email a visitor typedYes
pii.phonePhone numbersContact phonesYes
pii.addressPostal addressesYes
pii.identity_docID documentsYes
paymentPayment detailsYes
internal_notePrivate notesPrivate notes (hidden: not shown, not searched)No
agent_identityTeam members' email addressesMember addressesNo
ip_addressIP addressesWebsite visitors' IP, the audit log's IPNo

A role holding sensitive:reveal may reveal a masked value in full, one field of one record at a time, with an optional reason; every reveal is written to the audit log. A hidden value cannot be revealed.

Personal data in custom attributes

Help desks that check identities often keep ID and bank numbers in custom attributes. Mark such an attribute under Settings › Custom attributes › Sensitivity (custom_attributes:manage; every change is audited). From then on its values follow each role's grant for that tag, exactly like the built-in fields:

  • Everywhere a value reaches a person: contact and conversation details and lists, the contact page and the conversation's side panel, search results, the change history and audit log snapshots (where a contact's emails and phones now follow their grants too), and exports. A masked value arrives masked, a hidden one is left out, and both are listed in _redacted as custom_attributes.<key>. Signed website attributes with the same key are redacted the same way.
  • Reveal: the eye button beside a masked value, or POST /sensitive/reveal with attributes.<key> for a contact or a conversation.
  • Writing: a person who sees a value hidden cannot set or remove it (403), and saving a form without it keeps it. A person who sees it masked needs the write permission and must give a new value: sending back the masked text keeps the stored value, so a form save never overwrites it with •••. The app shows masked values read-only.
  • Reply placeholders: a person's reply may not use a placeholder whose value their role sees masked or hidden, such as {{contact.attributes.<key>}} or the built-in {{contact.email}} and {{contact.phone}}; the reply is refused with 422 rather than put into a message what the person may not see. Rules, flows and bots are not people and expand every placeholder.
  • Filters and views: a person's own filters and views may not match on an attribute they see masked or hidden, since matching is a way to learn a value. Rules and shared views set up by someone who manages them still match.
  • AI: custom attributes are never sent to an AI provider, and the values of sensitive ones are cut from the conversation text unless the person asking sees that kind of data in clear; payment and ID document values are always cut, and automatic summaries cut them all.
  • Integrations: API keys and installed apps see every field their permissions reach. Webhook event payloads never carry attribute values. A rule's "Send a webhook" action with the full payload carries attributes, emails and phones in clear, because the workspace chose where to send them.
  • Data connectors keep writing the attributes they map; what they write follows the same rules when it is read.
a contact read by a role that sees ID documents masked and payment hidden
{
  "id": 133,
  "name": "Maria K. Nowak",
  "custom_attributes": { "plan": "gold", "id_number": "•••" },
  "_redacted": ["custom_attributes.id_number", "custom_attributes.iban"]
}

Settings › Access

The Access page answers, for every member, disabled member and pending invitation:

  • Which conversations they see in each inbox: all of them, the unassigned ones and their own, their teams' and their own, only those assigned to them, or none. It is computed with the same function that filters their conversation list, and a test holds the two equal.
  • What they may do with them (read, reply, manage) and their key permissions: assign, manage, delete, edit, export and erase contacts, reveal, settings, people, roles and the audit log.
  • How they see each kind of personal data, and which custom attributes carry each tag.

It also answers the reverse questions: pick an inbox to see who sees it and with which permission, or a kind of data to see who sees it in clear, masked or not at all. It exports to CSV, and every export is audited. The whole page needs agents:manage or roles:manage, so Administrators by default (GET /access/overview). API keys and apps are not listed: they see the whole workspace within their permissions.

People who manage inboxes or teams (inboxes:manage or teams:manage, so Supervisors by default) get a reduced overview on the same page, with reduced: true in the answer: the inboxes they oversee, meaning those where their own role sees more than the conversations assigned to them, and the people who work in those inboxes, with which conversations each sees there and what they may do with them, and roles by name. Key permissions, how each kind of personal data is shown, the kinds of data and the CSV export stay with the people who manage roles, because they describe what those people may change. No new permission is involved.

Every claim on these pages is covered by a test in the repository, and the API reference is generated from the same contract every server serves at /api/openapi. Corrections to [email protected].