CoreLayer Docs
Configuration

Permissions

Configure the permission guard's risk policy and per-app overrides.

The Permission Guard decides, for every tool call, whether to run it, notify you, ask you, or refuse. The decision is a pure function of the tool's declared risk and the policy below.

Risk → action

RiskDefault action
lowauto — run silently
mediumnotify — run and surface a notification
highconfirm — suspend until you decide
criticaldeny — refuse

Default policy

defaultPolicy: {
  low: "auto",
  medium: "notify",
  high: "confirm",
  critical: "deny",
}

This is the policy the daemon runs with. The mapping is defined in @jarvis/permission-guard and applied to every tool call.

It is not yet user-configurable. The guard is constructed with its defaults, and config.json has no permissions section — an earlier version of these docs described a permissions.rules array that does not exist. Do not add one and expect it to take effect.

Per-app overrides

The guard supports per-app overrides in its configuration shape:

appPermissions: {
  "filesystem": { write: true,  execute: false },
  "untrusted-mcp": { write: false, execute: false },
}

How each flag maps:

Riskwrite: truewrite: false
mediumnotifyconfirm
highconfirmdeny
Riskexecute: trueexecute: false
criticalconfirmdeny

low is always auto.

The overrides are evaluated when present, but nothing in the daemon currently reads them from disk, so they apply only to code that constructs the guard with them.

Voice mode

Voice execution is stricter regardless of risk: read-only actions are auto-allowed, everything else requires confirmation. A spoken request is easier to trigger by accident than a typed one.

Approval requests

When the action is confirm, the guard does not hold the decision in memory:

  1. An approval_request is persisted with an action digest, risk, scope, and expiry
  2. The run is suspended
  3. The UI shows the request — approve, deny, or remember
  4. The decision resumes or fails the run

Endpoints:

GET  /api/approvals
GET  /api/approvals/:id
POST /api/approvals/:id/approve
POST /api/approvals/:id/deny
POST /api/approvals/:id/remember
POST /api/approvals/batch/approve
POST /api/approvals/batch/deny
POST /api/approvals/expire-stale

"This request is stale" is a real state: unattended queues accumulate requests nobody answered, and expire-stale closes them rather than leaving runs suspended forever.

Permission memories

"Remember" stores a decision against the action digest — the concrete action, not the tool name. The same action is not asked again; a different path, command, or parameter set produces a different digest and is asked again.

Audit

Every decision is written to audit_log and is queryable:

GET /api/audit?actor=jarvis&action=tool.execute&riskLevel=high&since=2026-10-01T00:00:00Z&limit=50

An entry records actor, action, resource, riskLevel, permissionDecision, confirmedByUser, result, metadata, and createdAt.

Next Steps

On this page