Keep personal data in the person's own country
Mark fields as vaulted so a vault in the person's country holds the values and your database keeps only tokens, with reads allowed only for a stated purpose.
Status Status is where the work is: Planned (in a milestone, not started), Building (tickets in progress), Preview (usable, may change), then the stability it ships at.
Stability The promise an interface ships with.
- Stable Follows semantic versioning; breaking changes need a new major, 12 months of overlap and a codemod.
- Beta Usable in production; may change before it becomes stable.
- Experimental May change or go away; needs an explicit opt-in in main.yaml.
You will send the personal fields of people in countries beyond MainSDK's three regions to a vault in their own country, and read them back only for an allowed purpose. It takes about 30 minutes plus a vault account.
You need
- A MainSDK app with
dbandkeysconfigured. - An account with a vault provider: InCountry, Skyflow, VGS, Basis Theory or Piiano.
1. Mark the fields
markets: [in, ae]
db:
fields:
user.name: { label: personal, vault: true }
user.phone: { label: personal, vault: true }
vault:
driver: incountry
countries: [in, ae]
locations: { in: loc-in, ae: loc-ae }
route: { by: user.country }A field labelled pan is refused: card numbers are never stored, so hand card data to pay. mainsdk check fails when a market is outside vault.countries (MAIN-DATA-0181) and when a query filters on the raw value of a vaulted field (MAIN-DATA-0180).
2. Write and read through Vaults
Vaults from mainsdk/vault takes the fields, a driver client, the locations and a purpose policy. write sends the vaulted values to the vault in the row's country and returns the row with tokens such as tok_ae_<ref>. A row with no vaulted field never touches the vault. read fills in real values only where the policy allows the viewer and purpose, and audits every detokenise; otherwise the field comes back as { token, redacted: true }.
3. Erase through the vault
Register vaultEraseHook with privacy.register("vault", ...). It deletes the person's tokens and throws until the vault confirms, so the signed erasure record lists the vault only once the data is gone.
4. Keep personal data out of model prompts
redactorFromConfig from mainsdk/vault-redact builds a redactor for ai.redact: the built-in one masks email addresses, card numbers and phone numbers, and agentcloak calls AgentCloak. Values are restored in the reply only when policy allows.
Check it worked
Run npx mainsdk check. In a test, write a row for a UAE user against fakeInCountry from @mainsdk/testing and confirm the database row holds only the token.
Was this page helpful?