# Concepts

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

### The door

A machine imports one thing of the Ownbox's, `from core import sdk`, and `sdk.machine("<slug>")` hands back the machine
object, `m`. Every call on `m` crosses the door to the Ownbox, which answers it under what the owner allowed. The
same code runs unchanged on your computer, in the Ownbox's dry runs, and installed.

### Permissions, asked and granted

`machine.yaml` asks, under `permissions:`, for exactly what the machine touches. Nothing is allowed unless it is named
there. The owner sees every line on the review card in plain words before the machine runs. What the owner grants is
never more than the machine asked for. A call outside the grant is refused `not_permitted`, and the refusal names the
line to add.

### The review card

The card that holds a finished build until a person decides. It shows what the machine asks for, each permission in
plain words, the packages it installs, how its tests went, and what it costs. A line that reaches outside the Ownbox or
changes its records is marked for the owner's attention. Nothing installs until a person taps **Approve**, and Approve
holds only for the exact code, version and permissions the card showed.

### Dry runs

Before the owner is asked, the Ownbox runs the draft twice, never both at once. The **data run** reads the owner's real
data and reaches nothing. The **fetch run** reaches only the hosts the owner tapped for the test, and reads a sample
business instead of theirs. See [Testing](https://www.ownbox.io/sdk/guide/testing).

### Step keys and service keys

Two different things share the word *key*. A **step key** is the `key=` argument on every call that acts (`send_dm`,
`reply_to_comment`, `send_email`, `notify`, `spend`): it names the step, and the same key again within a day is
answered with the first answer, so a retry never acts twice. A **service key** is a secret for another company's API,
listed under `keys:` in machine.yaml. The owner enters it on the machine's Keys page, and the Ownbox attaches it to
`m.fetch(url, key="<name>")` on the way out. The machine never sees it.

### Answers and refusals

A call the Ownbox will not make raises `sdk.BoxRefused`, whose `.code` says why: the grant does not cover it, or it
is past a limit. A call the grant covers answers its outcome instead: the people, conversation and send calls carry a
`status` and a `code`, because "not sent" is a normal outcome a machine decides on. Read the `status`; never assume a
send went.

### The local Ownbox

The Ownbox `ownbox run` and `ownbox preview` start on your computer. It answers every call as an Ownbox does in a fetch
run where the owner tapped nothing: the business's data comes from a sample, the AI answers one fixed sentence, a fetch
is checked and then refused `not_tapped`, and every send, spend and proposal is listed as what it would have done.

### Partner Ownboxes

On a partner's Ownbox, Ownbox reviews a machine as well as the owner. The owner's Approve sends the sealed build to
Ownbox, which reviews that exact code and says yes, or no with the reason. It installs only on Ownbox's yes, and the
yes covers only that code.
