Decide a permission ask
Allows or denies a pending ask, optionally remembering the decision for the session or permanently. A denial is reported to the agent with its reason and the agent continues rather than crashing. Every decision is recorded in the audit. Deciding an already-decided ask is a conflict.
Authorizations
Enforced on every transport, with no exempt operation. A person's request — over the default local unix socket exactly as over a TCP listener — must carry a JWT issued by the configured identity provider, which the host verifies itself against that issuer's key set: signature, issuer, expiry, and the person and organisation it names. Requests without a valid one receive 401 NRY-0011. The socket's file permissions are transport and are not an authorisation.
Path Parameters
The permission ask's id.
Body
A decision on a pending permission ask. A denial is never remembered: remember must be none (or absent) whenever decision is deny, and any other combination is refused with 400. The host offers four answers — allow once, allow always in this project, allow always globally, and deny with a message — so a remembered refusal is not one of them, and the prompt states before the answer exists that remembering would grant an allow rule.
allow, deny Scope to remember the decision at — none decides only this ask, session remembers for this session, project appends a rule scoped to this repository, global appends a rule to the user's own configuration. Two "always" scopes rather than one because "fine in THIS repository" and "fine everywhere I work" are different claims, and a single "always" forces everybody to over-grant. Only an allow is remembered; any scope other than none alongside decision=deny is a 400.
none, session, project, global Optional correction shown to the agent, useful on deny. It reaches the model verbatim as something it can act on: a denial saying only "denied" teaches nothing, so the model tries a variant and burns the turn, while "do not push to main, open a PR branch instead" ends the exchange.
4096Response
The recorded decision. This operation answers a PENDING ask and 409s anything else, so decidedBy and decidedAt are always present in this response. They are optional on the shared schema because the audit listing reports expired entries too, which nobody decided — a client reading only this operation may treat both as guaranteed.
One entry of the decision audit. There is exactly one decision per ask, so the decision's id IS the ask's id: id and permissionId carry the same identifier.
WHAT IS RECORDED, stated here because it is narrower than "every decision" and deliberately so: every ASK and its answer, whoever answered it, and every DENY — including the ones taken without asking anybody, which is the shape almost every denial has in unattended work. A rule-derived ALLOW on a free action is NOT a row. Recording every permitted read would write thousands of rows per session and bury the two questions this audit exists to answer — what was denied and why, and what did I approve.
AND A DECISION IS NOT A RECORD OF EXECUTION. It says what was decided, not what ran: a call interrupted in the same instant its decision was released can leave an allow here for something that never happened. Read it as the trail of judgements, and the transcript for what followed.
expired is an ask nobody answered before the call it was blocking ended. It carries no decider and no decidedAt, because "nobody answered" is itself the finding when somebody asks why an action did not happen.
allow, deny, expired When the decision was raised. It is what the audit is ordered and paged by, so a page boundary is stable while new decisions land.
1284096Who decided — a human, the policy deciding without asking (which includes a rule that landed after the ask was raised and covered it), or the configured executable at the permission-ask decision point. Absent on an expired entry.
user, policy, hook WHICH person decided, beside decidedBy's kind. Any member of the organisation may decide a permission request raised on a conversation that is not marked private, so a decision taken for somebody else is an ordinary event here and this is the only field that distinguishes it from one the owner took.
Absent when no person decided — a rule or a hook answered, or the ask expired with nobody answering — and absent on every decision this host recorded before it began recording who. An absent value is never the owner: a decision nobody recorded and a decision the owner took are different facts, and reading one as the other would attribute commands to people who never approved them.
256Whose conversation the decision was taken ON — the owner this request was parked on, which is the same value the session's own owner field carries. Read beside decidedBySubject it answers "who let that command run, and on whose work", from the audit alone.
Absent only for a row this host can attribute to nobody: a refinement round whose conversation was purged before owners were recorded.
256Why, in the decider's own words: a person's message on a deny-with-message, the rule a policy refusal names, or the hook that decided — a hook denial that does not say which hook is an audit trail ending in a shrug. Absent when the outcome speaks for itself.
4096none, session, project, global Absent on an expired entry, which nobody decided.

