# Delegated Authority — humans keep the final say

The second of Witbitz's two guarantees (the first is [the double blind](./the-double-blind.md)). An agent never
owns authority — it **receives** it, limited and revocable, and a human approves anything high-stakes before it
happens. The runtime enforces one invariant: **no action runs without an approval.**

> Built + tested (async Spaces M2 Cut 4); runs inside the deployed `/space` render. Code: `agent/delegatedAuthority.mjs`.

---

## 1. Propose → approve → execute

An effectful action moves through three recorded steps, asynchronously (the human may approve on a *later* turn,
not in-the-moment):

1. **propose** — on its turn, the agent proposes an action; it is recorded **pending**, **not run**
   (`propose(room, { action, by })`).
2. **approve / deny** — a human decides on a later turn (`decide(room, { id, approve, by })`). A decision on a
   non-pending proposal is refused; a decided proposal can't be flipped.
3. **execute** — only an **approved** proposal runs, through the injected executor (`execute(room, { id, run })`),
   and only once.

## 2. The invariant

Enforced and unit-tested: **an un-approved proposal never runs, and no proposal double-runs.** Approval is a
precondition to execution, checked in the runtime — not left to the model's discretion. This is the couples-therapy
safety-floor idea raised to the action level: the model reasons, the human authorizes, the runtime gates.

## 3. Capabilities are just tools

A Space's effectful capabilities are ordinary **tools** in its config (`send_summary`, `schedule_checkin`, …) —
there is no separate "actions" concept. The turn runs the normal brain tool-loop; the *only* async-specific twist
is that a high-stakes tool call is **deferred to a human approval** instead of running in-room. `makeProposingBrain`
wires this: it runs the brain with the Space's tools and turns a tool call into a **pending proposal** (via
`proposeCallTool`) rather than an execution. On approve, `execute` runs the same proposal through the **same tool
executor** a live call would use, keyed on the tool name — so approval routes to the real implementation.

## 4. The audit trail

Every step — propose / approve / deny / execute (with result or error) — is appended to a single per-room
**`authority` doc**: `{ proposals, audit }`, an append-only log. It is **mk-sealed** like the ledger, so it is
**content-blind at rest** (the platform can't read it) and it **persists across weeks**. A wrong `mk` yields
nothing — the trail is readable only to a present member, in the decrypt-once render.

## 5. Code map

| Concern | Where |
|---|---|
| propose / decide / execute + the invariant | `agent/delegatedAuthority.mjs` (`propose`, `decide`, `execute`) |
| pending list | `agent/delegatedAuthority.mjs` (`pendingProposals`) |
| tool-call → proposal glue | `agent/delegatedAuthority.mjs` (`makeProposingBrain`, `proposeCallTool`) |
| the ops that drive it | `agent/spaceService.mjs` (`turn` proposes · `decide` approves→executes · `pending`) |
| the sealed authority doc | `agent/sessionStore.mjs` (`putDoc`/`getDoc`), sealed via `agent/envelope.mjs` |

## 6. Status

Built + tested (the invariant, deny-can't-execute, no-double-run, the ordered audit trail, platform-blindness) and
running inside the deployed `/space` Lambda. What it does today is the async **propose → approve → execute + audit**
loop; richer policy (spend caps, per-capability authority tiers, org-level delegation from the vision) builds on
this primitive.
