Eridian

Dual Control

Two-person approval on high-risk model actions and policy writes.

Dual control requires a second authenticated operator before a high-risk mutation takes effect. The first actor proposes. The second actor, with a disjoint role, approves or rejects. The model does not self-approve. Dashboard sessions and API keys are both subject to the gate.

Gated Actions

ActionDefault on Enterprise
Publish a prompt templateRequired when evals_required is true
Change project residencyRequired
Raise a budget above the desk thresholdRequired
Expand allowed_models on a routing policyRequired
Disable PII redaction on a projectRequired
Disable fail_closed residencyRequired
Create a production API key with governance:manageRequired
Disable dual control itselfRequired, plus owner role
risk.report.approveRequired on Eridian Risk
risk.assessment.approveRequired
risk.case.close (high severity)Required
risk.case.hold.liftRequired
legal.redline.confirm when playbook high_riskRequired
Archive a Dev repository when evals_requiredRequired

Starter and Growth may enable the same gates. They are off by default on those plans. Risk-specific approve/reject flows: Risk Approvals.

Propose

POST /v1/approvals
Authorization: Bearer eridian_sk_...
Content-Type: application/json
{
  "project_id": "prj_legal_001",
  "action": "template.publish",
  "resource": "tpl_contract_summary_v3",
  "payload": { "version": "3.3.0" },
  "justification": "Eval run evr_19c4 passed pii_leak=0 and exact_match=0.84."
}
{
  "id": "apr_44e1",
  "object": "eridian.approval",
  "status": "pending",
  "action": "template.publish",
  "proposer_id": "usr_kadart",
  "expires_at": 1718486400
}

The proposer cannot approve their own request. Approver must hold governance:manage and must not be the same SSO principal.

Approve or Reject

POST /v1/approvals/apr_44e1/approve
POST /v1/approvals/apr_44e1/reject
Authorization: Bearer eridian_sk_...
{
  "comment": "Checked eval report evr_19c4 and residency eu-west-1."
}

Approved mutations apply immediately and emit approval.approved plus the underlying audit event (template.publish, policy.updated, and so on). Rejected mutations emit approval.rejected and leave the resource unchanged.

Timeout

Pending approvals expire after 24 hours (configurable 1 to 72). Expiry emits approval.expired. The resource stays on its last published version.

Inference Path

Dual control does not sit on ordinary POST /v1/inference. It sits on control-plane writes and on optional tool actions you mark as high_risk in a template (for example, a workflow that emits an outbound payment instruction). Those template-backed calls return HTTP 403 dual_control_required with an approval_id until the second operator approves.

{
  "error": {
    "type": "eridian.error",
    "code": "dual_control_required",
    "message": "Action template.publish requires a second approver.",
    "request_id": "axm_req_8f3a2b1c",
    "param": "apr_44e1"
  }
}

See Evaluations, Audit Log, Risk Approvals, and Governance.

Production API credentials are issued with an institution workspace. Contact sales if you need access.