Specification v0.1 · open · vendor-neutral

How it works

An agent asks. Your home checks the mandate. Then it answers allow, ask or deny – and writes it down.

Five building blocks

  • Household The people who live there. They write the mandate. Term in the specification:principal
  • Agent Any AI that wants to do something – a voice assistant, an energy app. Term in the specification:agent
  • Device A light, a lock, a heater. Grouped into 13 categories. Term in the specification:resource
  • Action What the agent wants: turn on, open, set to 21 °C. Term in the specification:action
  • Decision The answer to one request: allow, ask or deny. Term in the specification:decision

The path of a request

The agent never talks to the device directly. Everything goes through the home guard.

Show path
Agentsends a request
request
Home guardinside your home · checks the mandate
answer
Decision allowaskdeny
commandno command
Device does the action nothing happens
checks
Mandateyour house rules
PhoneAlex confirms
Log Every request and decision is recorded – also refused ones.

Allow: The guard finds a matching rule and passes the command on right away.Ask: The guard sends a question to Alex’s phone. Only after “Approve” does the door open. No answer within 2 minutes means no.Deny: No rule allows it, or a rule forbids it. The device never receives a command.

One mandate, two views

The same rules – once as sentences for people, once as JSON for machines. Both say exactly the same.

Edit it in the playground

Plain language

  • May read the state of every deviceallow
  • May turn lights on, off and dim themallow
  • May set the temperature up to 22 °Callow
  • May unlock and open doors if Alex confirms within 2 minask
  • May not use cameras – not even lookdeny
  • May not disarm the alarmdeny
  • Everything elsedeny

JSON

voice-assistant.json
{
  "type": "https://home-mandate.org/mandate/v0",
  "id": "m-voice-assistant",
  "principal": "household:hm-7f3a",
  "agent": { "client_id": "hm-client:voice-7c21e9a4", "display_name": "Voice assistant" },
  "rules": [
    { "id": "r-read-all", "resource": { "any": true }, "actions": ["read"], "decision": "allow" },
    { "id": "r-lights", "resource": { "category": "light" }, "actions": ["turn_on", "turn_off", "set"], "decision": "allow" },
    { "id": "r-climate", "resource": { "category": "climate" }, "actions": ["set_temperature"], "decision": "allow",
      "constraints": { "temperature": { "max": 2200 } } },
    { "id": "r-locks", "resource": { "category": "lock" }, "actions": ["unlock", "open"], "decision": "ask",
      "approval": { "timeout": "PT2M", "approvers": ["alex"] } },
    { "id": "r-no-cameras", "resource": { "category": "camera" }, "actions": ["*"], "decision": "deny" },
    { "id": "r-no-alarm", "resource": { "category": "alarm" }, "actions": ["disarm"], "decision": "deny" }
  ],
  "default": "deny",
  "approval": { "timeout": "PT2M", "approvers": ["alex"] },
  "limits": { "max_actions_per_hour": 60 },
  "valid_from": "2026-10-01T00:00:00+02:00",
  "created_by": "alex",
  "created_at": "2026-10-01T09:12:00+02:00"
}

The ground rules

  1. Not allowed means forbidden.If no rule fits, the answer is deny.
  2. The strictest rule wins.Order doesn’t matter. deny beats ask, ask beats allow.
  3. Critical actions are special.An allow only counts if every matching allow rule names them and carries allow_critical. Otherwise allow becomes ask: a person must confirm.
  4. No answer means no.If nobody confirms an ask in time, the answer is deny.
  5. Decided at home, written down.The guard decides, not the agent – the agent can only ask. Every decision is recorded in the log.

The log works like a tachograph

Each entry contains the fingerprint (SHA-256 hash) of the entry before it. If someone changes an old entry, its fingerprint changes – and the next entry no longer matches.

  1. #1 · 19:02
    Light on · living room allow
    prev
    null
    digest
    1f56…0405
  2. matches
    #2 · 19:05 changed
    Disarm alarm deny allow
    prev
    1f56…0405
    digest
    399d…eb0a
    9fc0…39b7
  3. matches doesn’t match
    #3 · 19:06
    Unlock front door ask
    prev
    399d…eb0a
    digest
    a8e4…e87d
  4. matches
    #4 · 19:07
    Set heating to 21 °C allow
    prev
    a8e4…e87d
    digest
    3b32…0251
Chain intact. Every fingerprint matches the entry before it. Change detected. Entry 2 was edited, so its fingerprint changed. The fingerprint stored in entry 3 no longer matches – the check fails at entry 3.

The chain is not signed: whoever can rewrite the whole log can also recompute every fingerprint. It becomes evidence together with a copy or a signed checkpoint kept outside the log.

For techies: the four entries

Digest of an entry: "sha256:" + hex(SHA-256(JCS(entry))), over the complete entry including prev. The first entry has prev null. Exchange format: JSON Lines.

audit.jsonl
{"type":"https://home-mandate.org/audit/v0","id":"01a13111-6c20-7101-8a01-00005eed0101","seq":1,"recorded_at":"2026-10-12T19:02:01+02:00","event":"decision","principal":"household:hm-7f3a","agent":{"client_id":"hm-client:voice-7c21e9a4"},"request":{"time":"2026-10-12T19:02:00+02:00","timezone":"Europe/Berlin","resource":{"entity_id":"light.living_room","category":"light","areas":["living_room"]},"action":"turn_on"},"mandate":{"id":"m-voice-assistant","digest":"sha256:1bd044ea0d93302d8207adf47a8c5f06f231707cb0822b2e2a88fa51c2d63b64"},"evaluation":{"decision":"allow","reason":"rule","rule_id":"r-lights"},"result":{"status":"executed"},"prev":null}
{"type":"https://home-mandate.org/audit/v0","id":"01a13114-3940-7102-9a02-00005eed0102","seq":2,"recorded_at":"2026-10-12T19:05:01+02:00","event":"decision","principal":"household:hm-7f3a","agent":{"client_id":"hm-client:voice-7c21e9a4"},"request":{"time":"2026-10-12T19:05:00+02:00","timezone":"Europe/Berlin","resource":{"entity_id":"alarm.house","category":"alarm"},"action":"disarm"},"mandate":{"id":"m-voice-assistant","digest":"sha256:1bd044ea0d93302d8207adf47a8c5f06f231707cb0822b2e2a88fa51c2d63b64"},"evaluation":{"decision":"deny","reason":"rule","rule_id":"r-no-alarm"},"result":{"status":"denied","denied_by":"mandate"},"prev":"sha256:1f56a91f3a236721aab9ce2aa120f825ed748afa732dd8523025a12ecec70405"}
{"type":"https://home-mandate.org/audit/v0","id":"01a13115-2420-7103-aa03-00005eed0103","seq":3,"recorded_at":"2026-10-12T19:06:40+02:00","event":"decision","principal":"household:hm-7f3a","agent":{"client_id":"hm-client:voice-7c21e9a4"},"request":{"time":"2026-10-12T19:06:00+02:00","timezone":"Europe/Berlin","resource":{"entity_id":"lock.front_door","category":"lock","areas":["hall"]},"action":"unlock"},"mandate":{"id":"m-voice-assistant","digest":"sha256:1bd044ea0d93302d8207adf47a8c5f06f231707cb0822b2e2a88fa51c2d63b64"},"evaluation":{"decision":"ask","reason":"rule","rule_id":"r-locks","approval_timeout":"PT2M"},"approval":{"outcome":"approved","by":"alex","at":"2026-10-12T19:06:40+02:00"},"result":{"status":"executed"},"prev":"sha256:399dfdceacfa98d5183d713ae58fe974d8212aefc82a04e2c1b665150381eb0a"}
{"type":"https://home-mandate.org/audit/v0","id":"01a13116-0e80-7104-ba04-00005eed0104","seq":4,"recorded_at":"2026-10-12T19:07:01+02:00","event":"decision","principal":"household:hm-7f3a","agent":{"client_id":"hm-client:voice-7c21e9a4"},"request":{"time":"2026-10-12T19:07:00+02:00","timezone":"Europe/Berlin","resource":{"entity_id":"climate.living_room","category":"climate","areas":["living_room"]},"action":"set_temperature","parameters":{"temperature":2100}},"mandate":{"id":"m-voice-assistant","digest":"sha256:1bd044ea0d93302d8207adf47a8c5f06f231707cb0822b2e2a88fa51c2d63b64"},"evaluation":{"decision":"allow","reason":"rule","rule_id":"r-climate"},"result":{"status":"executed"},"prev":"sha256:a8e48436333684cb6ae658427a366aeace6e36e35728a78fde6edb0b2457e87d"}

Read on