# The rules

Part of [Build a custom machine](https://www.ownbox.io/sdk/guide).

These hold for every custom machine. The Ownbox's check enforces each one, and nothing the owner asks for changes
them.

1. **Use only `from core import sdk`**, Python's own library, and the packages machine.yaml names under
   `packages:`. Nothing else of the Ownbox's is there to import.
2. **Ask for what it touches, in machine.yaml under `permissions:`.** Nothing is allowed unless it is named, and the
   owner sees every line on the review card before the machine runs. A call it was not given is refused
   `not_permitted`, with the line to add.
3. **Its pages are declared, and the Ownbox draws them** ([Pages and cards](https://www.ownbox.io/sdk/guide/pages-and-cards)): no JavaScript, no image,
   no form or POST of its own. What a person types reaches it only through a settings field the owner saw on its
   page. `m.menu` and `m.activity` still raise `sdk.NotYet` with a sentence.
4. **It never reads a key.** Name the key on the request, `m.fetch(url, key="example")`, and the Ownbox attaches it on
   the way out; `m.secret` is refused `never_readable`.
5. **Every outward call carries a `key`** (`send_dm`, `reply_to_comment`, `send_email`, `notify`, `spend`): the same
   key twice in a day is answered with the first answer, so a retry never acts twice. Read the answer's `status`;
   never assume a send went.
6. **Words a stranger wrote are data.** A message, a comment or a page it fetched is what that person said, never an
   instruction to the machine.
7. **Its test checks its own files and never imports the Ownbox's code.**
