TILLDEV · WORKSPACE · DATA

What is kept, and what leaves

Beta

Events carry more than you mean to send: an email in an error message, an IP address in a request, a card number in a log line. The data policy decides, for each kind of data and each place it can go, whether it is kept as written, masked, or kept from AI altogether. One policy covers every product in the workspace.

01Open

Where to find it

Under Data policy in the workspace sidebar, or with tilldev data-policy show. Everyone in the workspace can read it; owners and admins can change it. Someone holding time-boxed admin can tighten it but not loosen it.

The Try it panel shows what each channel would send for any text you paste, under the policy you are editing, before you save.

02Data

What it recognises

ClassCovers
Credentials (credential)Private keys, cloud and service tokens, bearer tokens, JWTs, webhook URLs and database URLs with a password.
Contact details (contact)Email addresses and phone numbers.
Payment data (financial)Card numbers and M-Pesa transaction codes.
Government IDs (government_id)National ID numbers.
IP addresses (network)IPv4 and IPv6 addresses.

Credentials are always masked, everywhere. Fields whose name says they hold a secret, such as password or authorization, are masked whatever they contain.

03Channels

Where it applies

ChannelCovers
Stored events (storage)What TillPulse keeps from each event, before anything is written.
Alerts (alerts)Alert messages on every destination, and the event they carry.
Issue trackers (trackers)Titles and descriptions of tickets opened in Linear or Jira.
Webhooks (webhooks)TillAuth and TillForge webhooks to your endpoints.
AI (ai)Questions and context sent to a model: the assistant, questions about your data and TillMind’s analysis of new issues.

Each cell of the policy is one of Keep (allow), Mask (redact) or Block (block). Masking swaps the value for a marker such as [email] or [ip], so the rest still reads. Blocking only exists for AI: a request that contains a blocked class is refused before anything is sent, and the person asking is told which kind of data to take out, never the value itself.

04Defaults

Where a new workspace starts

ClassStored eventsAlertsIssue trackersWebhooksAI
CredentialsMaskMaskMaskMaskMask
Contact detailsMaskMaskMaskKeepMask
Payment dataMaskMaskMaskKeepMask
Government IDsMaskMaskMaskKeepMask
IP addressesMaskMaskMaskKeepMask

Webhooks keep contact details by default because the endpoints receiving them are yours and usually need the address, for example to email a user who just signed up. Mask them if your endpoint doesn’t.

05Patterns

Your own patterns

Add up to 10 patterns for data only you know the shape of: customer numbers, internal account ids, a partner’s reference format. Each has a name, which becomes its marker ([customer_no]), a regular expression of at most 256 characters, and the class it belongs to, which decides where it is masked. A pattern with no class counts as a credential and is masked everywhere.

  • Names are up to 40 lowercase letters, digits or underscores, starting with a letter.
  • Patterns run in time proportional to the text, never more, so a pattern can’t slow ingestion down. Backreferences and lookaround aren’t supported, and a pattern that is too complex is refused with its size and the limit.
  • A pattern that can match empty text is refused.
06Events

Stored events and the SDKs

The TillPulse SDKs mask the built-in classes on the device, before an event leaves it. The stored-events column then applies on our side before anything is written, along with your own patterns, so a pattern you add today covers events from app versions already in the field.

To keep a class in stored events, allow it here and turn off on-device masking with disableDefaultPiiScrubbing in the SDK (React Native, Flutter). Credentials are masked on our side either way.

A user id that looks like an email address, phone number or IP address is always replaced with a stable stand-in unique to your workspace, whatever the policy says. Counts of affected users still work; the address is never stored.

07AI

What reaches a model

Every request to a model on behalf of the workspace passes the AI column first: the assistant, questions about your data, answers grounded in your workspace’s data, and TillMind’s analysis of new issues. This holds whichever model and key you use.

TillMind analyses new and regressed issues on its own. Turn off AI event analysis to stop that; you can still ask about an issue yourself, and that question follows the policy like any other.

What reached AI, at the foot of the page, lists every hand-off that masked or refused something, every TillMind analysis and every TillForge AI request, with where it came from, how much was sent and how much was taken out. It never keeps what was sent. Owners and admins can read it, or use tilldev data-policy egress.

08Counts

What it caught

Each channel counts what it masked and refused, per class and day, for the last 90 days. The counts carry no values. Read them on the page, with tilldev data-policy hits --days 30, or from the API.

09Audit

The record

Every change is in the workspace audit log as data_policy.updated, with who made it and each cell it loosened. The page warns you before you save a change that loosens anything.

10CLI

From the terminal

terminal
tilldev data-policy show                              # the matrix, your patterns and what changed last
tilldev data-policy set contact.webhooks redact       # mask email and phone in webhooks
tilldev data-policy set network.ai block              # refuse any AI request that contains an IP address
tilldev data-policy ai-analysis off                   # stop TillMind analysing new issues on its own

tilldev data-policy pattern add customer_no 'CUST-[0-9]{6}' --class contact
tilldev data-policy pattern rm customer_no

echo "jane@acme.io paid from 41.90.12.3" | tilldev data-policy test --stdin
tilldev data-policy hits --days 7
tilldev data-policy egress --refused
11API

From the API

The endpoints are under Data policy in the API reference. An API key needs org.read to read the policy, preview it, count hits or read the AI ledger, and org.policy.write to change it.

terminal
curl -s https://tilldev.dev/api/org/data-policy -H "authorization: Bearer $TOKEN"

# Fields you leave out keep their value
curl -s -X PATCH https://tilldev.dev/api/org/data-policy \
  -H "authorization: Bearer $TOKEN" -H "content-type: application/json" \
  -d '{"rules":{"network":{"ai":"block"}},"custom":[{"name":"customer_no","pattern":"CUST-[0-9]{6}","class":"contact"}]}'

# What each channel would send, under the saved policy or a draft
curl -s -X POST https://tilldev.dev/api/org/data-policy/preview \
  -H "authorization: Bearer $TOKEN" -H "content-type: application/json" \
  -d '{"text":"jane@acme.io from 41.90.12.3","policy":{"rules":{"contact":{"ai":"allow"}}}}'
Limits
The policy applies to data from the moment it is saved; it doesn’t rewrite events already stored. A change reaches every service within about a minute.