Products · Build a dot

Security

Ask for the permissions your dot needs, handle a no, keep secrets and personal details off the phone, keep your host list short and protect your server.

People trust Dash with their money. Dash enforces some rules for every dot, and the rest on this page are up to you.

Permissions

To use the camera, photos, files, contacts, the person's Dash account or payments, declare a permission in dot.json with a reason:

dot.json
{
  "permissions": {
    "camera": "Scan the QR code on your ferry ticket",
    "contacts": "Choose a cousin to send airtime to"
  }
}
PermissionThe calls it unlocks
cameradash.media.pickPhoto({ source: 'camera' }) and dash.media.scanCode()
photoLibrarydash.media.pickPhoto({ source: 'library' })
filesdash.media.pickFile()
contactsdash.contacts.pickPhone()
accountdash.account.signIn(). See Sign the person in
paymentsdash.payments.request() and get(). See Take payments
remindersdash.reminders.set(), cancel() and list(). See Reminders

Ask only for what you use. Each one shows in your dot's About screen, and a long list makes people wary.

Dash asks the first time the dot needs a permission and shows your reason. "Scan the QR code on your ferry ticket" gets a yes far more often than "Camera access". People can change their answer later with the switches in About, in the dot's menu.

When the answer is no

The call fails with denied. So does a call whose permission isn't in dot.json. Dash won't ask again while the dot is open. Offer another way instead:

pages/send/controller.ts
import { isDashError, unlessCancelled } from '@monimesl/dot-runtime';

// One of the page's actions
async chooseCousin() {
  try {
    const contact = await unlessCancelled(this.dash.contacts.pickPhone());
    if (contact) {
      this.setState({ phone: contact.phone });
    }
  } catch (error) {
    if (!isDashError(error, 'denied')) {
      throw error;
    }
    // No contacts. Let them type the number.
    this.setState({ typeNumber: true });
  }
},

Handle errors explains isDashError and unlessCancelled.

Keep secrets off the phone

Anyone who has your dot can read all of it, .env included. API keys, access tokens and passwords belong on your server. The dot calls your server, and your server calls the Monime API.

To keep someone signed in to your server, store their session token with dash.storage.secret.

Keep the host list short

Your dot can only reach the hosts in network.hosts. A short list also limits what bad code from a dependency could do with your customers' data. List api.boenergy.sl rather than *.boenergy.sl when one host will do.

Limits Dash sets

A page can't use the camera or microphone itself. Use dash.media instead.

Keep personal details out of errors

If your onError hook sends errors to your error tracker, keep names and numbers out of their messages. Write throw new Error('No seat left on this ferry'), not the person's name.

Protect your server

Anyone can send requests to your server, not only your dot. Treat it like any public API:

  • Check every request. Work out prices and amounts on the server, not from what the dot sends.
  • Handle each order once, even when the dot retries. See Send an order once.
  • Confirm payments on your server, not with what the dot reports.
  • Don't let an accountIdToken from dash.account.signIn alone open the person's records or money. Your server can't tell it from one someone made up.

Keep reading