> How Contals protects personal data – EU storage on Cloudflare, server-checked access control, encryption, backups, deletion, logging and operator access – each…

Source: https://contals.com/es/data-protection/toms/  
Language: es

# Technical and organizational measures (TOMs)

How Contals protects personal data – EU storage on Cloudflare, server-checked access control, encryption, backups, deletion, logging and operator access – each measure marked implemented, prepared or planned. Annex 2 of the DPA.

Última actualización: 16 de octubre de 2026

Esta página está disponible en inglés y en alemán. Las versiones en inglés y en alemán son las vinculantes; en caso de discrepancia, prevalece la versión alemana.

**Version 1.0 of 16 October 2026.** Annex 2 of the  [data processing agreement](https://contals.com/en/data-protection/dpa/) . Contals is in early access. Each measure is marked: **Implemented** (built and tested, active in every deployment) · **Prepared** (built, needs a configuration step when production is set up) · **Planned** (decided, not built yet).

## 1\. Infrastructure

| Measure | Status |
| --- | --- |
| All services run on Cloudflare (Workers, Durable Objects, D1, R2, Queues). Physical security and data-center operations are Cloudflare’s (ISO/IEC 27001, 27701, 27018, SOC 2 Type II, BSI C5, EU Cloud Code of Conduct) | Implemented |
| Stored data in Cloudflare’s **EU jurisdiction**: board and user data (Durable Objects), databases (D1), archive and backups (R2), internal queues | Implemented (code) · Prepared (resources are created in the EU at launch) |
| Internal object names are random and meaningless; no titles, names or e-mail addresses in object names or storage keys (Cloudflare logs object IDs outside the EU) | Implemented |
| Encryption at rest by Cloudflare (AES-256), keys managed by Cloudflare | Implemented |
| End-to-end encryption with keys held by you | **Not offered** |

## 2\. Sign-in

| Measure | Status |
| --- | --- |
| An account exists only after its e-mail address is confirmed; unconfirmed sign-ups are deleted after 7 days | Implemented |
| Password (at least 10 characters, stored as a scrypt hash), one-time sign-in link (15 minutes) with a 6-digit code in the same e-mail for the installed app (10 minutes, stored only as a fingerprint, at most 5 attempts per code; link or code work once – whichever comes first), sign-in with Google, Microsoft, Apple and others (only with a verified address), single sign-on (OIDC, SAML) per organization | Implemented |
| A forgotten password is replaced through a sign-in link: the session it opens (after the second factor) may set a new password once within 30 minutes without the old one; the other devices are signed out, the change is logged and e-mailed; not offered when the organization requires single sign-on | Implemented |
| The sign-in form also works before the page’s scripts have loaded (handled on the server, same-origin checks, no address or password in links); joining through an invite link with another provider keeps only the link in a 30-minute cookie that scripts cannot read | Implemented |
| Secure session cookies (HttpOnly, Secure, SameSite, bound to app.contals.com alone – no other address can set them), 30-day sessions; signing out or revoking a device closes its open boards at once | Implemented |
| Confirmation and sign-in links in e-mails work only after a click on the page they open, so e-mail security scanners cannot use them | Implemented |
| With single sign-on required, organization owners keep their password and sign-in links for emergencies; every such sign-in is logged, listed for the owners and admins and e-mailed to them | Implemented |
| Overview of signed-in devices; sign out other devices | Implemented |
| Limits against password guessing and mass sign-ups – per IP address counted at Cloudflare’s network edge, nothing stored by us; at most a few sign-in links and confirmation e-mails per address | Implemented |
| Minimum age 16 (younger people with the consent of a parent or guardian): confirmed with a checkbox at sign-up, on invitations and when an AI agent connects an account; accounts created through a sign-in link, another provider or single sign-on answer it once before anything else; only the date of the confirmation is stored, never a birth date | Implemented |
| Bot check (Cloudflare Turnstile) on sign-up, sign-in links, date polls and bookings | Prepared (active once configured at launch) |
| Two-factor sign-in: a code from an authenticator app after every sign-in (password, sign-in link, Google & co.), 10 single-use recovery codes, passkeys (fingerprint, face or device PIN) that count as both factors; changes need a fresh sign-in and send a notice (a changed or reset password, too); owners can require it for everyone in their organization and reset a member’s factors (logged, the person is told) | Implemented |
| Check against breached passwords | **Planned** |
| Expired sign-in sessions (with their browser name; no IP address is stored) are deleted a day after they expire | Implemented |

## 3\. Access to data

| Measure | Status |
| --- | --- |
| New boards are **private**: only people added to them can open them | Implemented |
| Board roles viewer, contributor, editor, admin; **every change is checked on the server** against the person’s role | Implemented |
| Volunteers and guests can never manage a board; viewers can only read | Implemented |
| Organization and workspace admins manage private boards **without** seeing content; opening one anyway (“break-glass”) is logged and shown to all board members | Implemented |
| Removing someone ends their access at once, including open connections; their browser deletes its local copy | Implemented |
| Invitations always need the invited person’s consent | Implemented |
| Invite links: only owners and admins of a workspace create them, only for the free roles volunteer and viewer, with an end date and a limit of joins; the link is stored only as a hash and shown once; joining needs a confirmed address and the person’s own account; someone removed after joining cannot come back through the same link; creating, ending and using a link are in the audit log | Implemented |
| Exports contain only boards the exporting person can read; every export is logged | Implemented |
| API tokens never exceed the owner’s rights; tokens are stored only as hashes | Implemented |
| Calendar feeds: secret link per person (stored as a hash), renewable and revocable, access checked on every fetch; confidential boards show only “Busy” | Implemented |
| Imports: export files are read in the browser; uploaded content waits in storage in the EU only while the import runs, within size limits per import and organization (deleted at the end, leftovers after 7 days at the latest); no accounts are created for imported people; Trello keys are never stored | Implemented |
| Confidential boards (a setting for board admins): no titles in links, download names or browser tab titles; no content in chat notifications or inbox entries; e-mails and the summary e-mail name it only as “a confidential board”; calendar feeds show “Busy”; never sent to AI providers; not available through the API, the MCP server or AI agents; every opening is logged. Public pages (bookings, polls) keep working and are not covered | Implemented |
| AI with your organization’s own provider: off until an owner or admin enters a provider, confirms a data processing agreement with it and switches AI on; your data policy decides what may be sent (titles always; descriptions and checklists on, comments and people’s names off by default; e-mail addresses never); AI can be switched off per workspace and per feature; every change the assistant proposes waits for confirmation; checked on the server | Implemented |
| Community templates: the public structure is built on the server through an allowlist (no descriptions, comments, people, field values, links, attachments or dates – due dates become relative days); its texts are checked for contact data; Contals staff review every template before it becomes public; confidential boards can never be shared; a takedown or withdrawal reaches the website within 10 minutes (edge cache) | Implemented |
| Public pages for date polls and bookings: secret links that can be rotated or revoked, public links can be forbidden per board, rate limits per IP address (nothing stored), only name, e-mail and answers are kept – outside the board storage and its archive; a booker’s details are visible to the board’s editors and admins only | Implemented |

## 4\. Separation of customers

| Measure | Status |
| --- | --- |
| Each board has its own database (one Durable Object per board) | Implemented |
| Searches and lists across boards are always limited to the boards the person may open | Implemented |
| Production and test environments separated (own names, databases, storage, keys and access tokens) | Implemented |
| Administrative access to the infrastructure limited to Unique-P GmbH (currently its managing director), protected by two-factor authentication; access by Cloudflare’s own staff follows Cloudflare’s data processing agreement | Implemented |

## 5\. Transmission and integrity

| Measure | Status |
| --- | --- |
| Encrypted connections only (HTTPS, secure WebSockets), HSTS | Implemented · Prepared (zone settings at launch) |
| Content Security Policy, protection against framing, no MIME sniffing, no full referrers to other sites, origin checks | Implemented |
| Every change to a board is recorded (who, when, what) and visible as activity | Implemented |
| Audit log of security-relevant actions (access granted or revoked, break-glass, exports, deletions, invitations, API tokens, single sign-on, openings of confidential boards): 180 days in the database, then 2 years in the separate backup storage | Implemented · Prepared (storage rule applied at launch) |
| Audit log page for organization owners and admins on every plan: filters by person, type and dates, CSV download (itself logged); entries name people by ID, older entries show e-mail addresses masked | Implemented |
| “Report abuse” on public poll and booking pages (what and why and the page’s link token, so the page can be found – no reporter identity, no IP address); a takedown closes the page’s open reports and tells the board’s managers or the template’s publisher; links in the public texts of free organizations are shown as text | Implemented |
| Secrets of integrations (single sign-on, chat webhooks, AI provider keys) additionally encrypted (AES-256-GCM) with key rotation; shown only masked | Implemented |
| Attached files: the type is read from the content (programs and scripts refused); location and camera data removed from photos before they are stored; files opened only from a separate host (files.contals.com, which never sees the app’s cookies) with links that expire after 10 to 20 minutes, without cookies, never run as a page; on confidential boards no file names in links; a storage limit per organization | Implemented · Prepared (the signing key at launch) |
| Requests to chat platforms only to known platform hosts over HTTPS; requests to your AI provider only over HTTPS to public addresses, without redirects | Implemented |
| Push notifications encrypted end to end for the receiving device and signed with our key; only the browser vendors’ push services are accepted as addresses; texts on a lock screen as the person chose and always short for confidential boards; push only after a click, never on shared devices, removed on sign-out | Implemented |

## 6\. Availability

| Measure | Status |
| --- | --- |
| A change is confirmed only after it is stored durably | Implemented |
| Point-in-time recovery for 30 days (boards and databases) | Implemented (platform) · Open: Cloudflare does not document separately where the recovery data is kept; our own backups below stay in the EU |
| Tamper-proof archive of all board changes (bucket lock), kept 90 days | Implemented · Prepared (storage rules applied at launch) |
| Daily backup of the account databases (every table a restore needs) into separate backup storage in the EU jurisdiction, kept 35 days | Implemented · Prepared (storage rules applied at launch) |
| Nightly copy of every board that changed, kept 35 days in the same backup storage (and encrypted at DigitalOcean); a single board can be restored from a night’s copy – every deletion recorded since then is applied again, and the restore is logged | Implemented · Prepared (storage rules applied at launch) |
| A second copy of the backups and of the nightly board copies at DigitalOcean in Frankfurt, **encrypted by us** before it leaves (DigitalOcean cannot read it), kept 35 days (audit archive 2 years) | Implemented · Prepared (storage and keys set up at launch) |
| Restore drill: a script restores a night’s backups into empty databases, applies every recorded deletion again, checks them and a board copy; monthly | Implemented (script) · Prepared (monthly from the launch) |
| Limits against abuse (boards, cards, changes per minute, invitations, API requests) | Implemented |
| Firewall rules that block unknown paths before the application runs; DDoS protection by Cloudflare | Prepared |
| Health checks and alerts to the operator (no customer data in them); external uptime monitoring | Implemented · Prepared |

## 7\. Deletion and your rights

| Measure | Status |
| --- | --- |
| Account deletion by the person: access ends and the name is pseudonymized at once; remaining personal data is deleted after 30 days. Within these 30 days only support can restore an account, on the person’s request from its address: name, address and personal settings come back, memberships, credentials, API tokens and calendar links do not; the list of deletions records the restore before anything changes, so a later restore from a backup ends in the same state, the restore is logged (IDs) and the person is told by e-mail | Implemented |
| Deleted boards go to the trash and are purged after 14 days | Implemented |
| Organizations are deleted 30 days after an owner asks for it (the end of a paid plan deletes nothing – the organization continues on the free plan): read-only and exportable for 30 days, owners told by e-mail; then every workspace, board, member list and file of an import is deleted; billing records stay 10 years, usage and audit records with IDs only | Implemented |
| Every board keeps its history for 13 months; older changes are folded into the board and their earlier texts deleted | Implemented |
| A deleted attached file is erased after 24 hours; files are not part of backups, so they do not come back with a restore | Implemented |
| Export of a board, workspace or organization as JSON with the board history of the last 13 months | Implemented |
| Deleting a card or comment removes it from the board | Implemented |
| Editing or deleting a comment, or deleting a status update, also erases the earlier text from the board history, the search index and exports | Implemented – earlier versions of card titles and descriptions stay in the history for up to 13 months; the tamper-proof archive and recovery copies keep the text until their retention ends |
| The tamper-proof archive (90 days) and backups (35 days) keep data until their retention ends (disclosed in the DPA); every deletion is recorded in a separate list (IDs only, 120 days) before it happens and applied again after any restore | Prepared (archive) · Implemented (list of deletions) |
| Inbox items: read items deleted after 90 days, at most 2,000 items per person | Implemented |
| Push subscriptions (per device, in the person’s own storage in the EU) deleted when push is switched off, on sign-out on that device, when the push service reports them expired and at once when the account is deleted; due-reminder schedules kept until two days after the due date; notification e-mails only for unread items, outside the person’s quiet hours, with one-click unsubscribe | Implemented |
| AI: assistant conversations kept in the person’s own storage (EU) for 30 days and deletable at any time; the usage log keeps token counts only – no prompts, no answers | Implemented |
| “Since your last visit”: per person and board only the last version seen, forgotten after 400 days without a visit; the summary on the board never quotes comments | Implemented |
| Summary e-mail: only boards the person can open, no titles from confidential boards, never comment texts, empty summaries are not sent, one click unsubscribes; the send log keeps IDs and counts for 90 days | Implemented (from the e-mail launch) |
| E-mail: address and content are kept only until the mail is sent, then only a hash of the address and the delivery status for 30 days – also after an account is deleted, to protect against abuse; notification e-mails can be unsubscribed with one click | Implemented (from the e-mail launch) |
| Date polls: a guest’s e-mail address is erased after the final date was sent, with the guest’s answer or the poll, and at the latest 90 days after the poll’s last date. Bookings: the booker’s name, e-mail address and answers are erased by an admin (the card then gets a neutral title and loses its earlier titles from the history), with the board, and automatically 90 days after the appointment | Implemented |
| Retention rules per board (board admins, off by default): done cards are archived or deleted a chosen number of days after they were completed; deleting also erases their comments and texts from the board history; cards with data of people without an account (date polls, bookings) are archived instead | Implemented |
| A free organization nobody uses for 90 days is paused (read-only, nothing deleted) until an owner signs in; owners hear about it 14 and 3 days before | Implemented |

## 8\. Logging and operator access

| Measure | Status |
| --- | --- |
| Logs and usage statistics contain IDs, counts and error codes only – no content, no e-mail addresses | Implemented |
| Page views of the website, the documentation (not its search) and the app’s pages for signing in, invitations and invite links are counted with Fathom Analytics: no cookies; nothing loaded with Global Privacy Control or Do Not Track; in the app only page templates, never tokens or query strings; never after sign-in or on public pages | Implemented |
| Cloudflare processes request metadata (IP address, URL path, browser) partly outside the EU. Links to normal boards contain the board and card title; links to confidential boards do not, and an organization can switch on “no titles in links” for all its boards | Implemented |
| The operations area is protected by Cloudflare Access and shows usage and health, the requests for the free Trello migration (what the requester typed, with their name and e-mail address) and the community templates waiting for review (the structure an organization submitted for publication) – never board content | Implemented |
| Free Trello migration: staff never ask for passwords, never sign in to a customer’s accounts and never receive export files – the customer runs the import in their own account and shares their screen in the call; calls are not recorded; requests are deleted 180 days after they are closed | Implemented (rules) · Prepared (the video call tool is chosen before the first call) |
| Contals staff do not read customer content in normal operations; there is no support tool for it. Access for support needs your request for the specific case and is logged | Implemented · Planned (formal procedure) |
| Whoever administers the Cloudflare account can technically reach stored data: that is only Unique-P GmbH (currently its managing director), with two-factor authentication | Implemented |
| Written confidentiality obligation for everyone with production access | Planned (with the first collaborator) |
| Incident response and breach notification process ( [summary](https://contals.com/en/data-protection/) ); notices go to the organization’s owners and the privacy contact it recorded in its settings | Implemented |

## 9\. Development

| Measure | Status |
| --- | --- |
| Every change passes type checks, architecture rules, unit, property and end-to-end tests, including generated permission tests | Implemented |
| Dependency rules (lockfile, minimum release age, blocked install scripts) and regular dependency audits | Implemented |
| Internal security review at maximum depth (October 2026): high findings fixed, medium findings partly open | Implemented |
| External penetration test | **Planned** |
| Development and tests use only test data | Implemented |

 [← Documentación de protección de datos](https://contals.com/es/data-protection/)
