Skip to main content

Module approval

Module approval 

Expand description

Out-of-band SOP approval plane (EPIC C; EPIC G broker).

The resolution layer on top of EPIC A (the engine singleton) and EPIC B (the durable run store + append-only event log). resolve_gate (resolve) is the ONE gate-clearing entry point, reachable from four principals - the agent tool, the loopback CLI, the gateway, and the timeout tick - each recorded into B’s append-only ledger with a transport-derived principal that a client body can never forge. ApprovalBroker (broker) wraps that chokepoint with an authorization + quorum layer (EPIC G): required-group membership and N-distinct-approver quorum, resolved from the engine’s live [sop.approval] config. With no policy configured the broker is a pass-through to resolve_gate - unchanged behavior.

Modules§

broker
Approval broker (EPIC G, Phase 5).
channel_route
Real channel delivery for the approval route adapter (EPIC G follow-up).
decision
The decision a principal makes on a SOP gate, and the outcome of resolving it.
identity
Approval identity resolution seam.
ledger
The append-only approval ledger entry, mapped onto EPIC B’s SopEventRecord.
principal
WHO resolved a SOP approval gate, and from WHERE (EPIC C).
resolve
The single gate-clearing chokepoint (EPIC C, C3).
timeout
Fail-closed SOP approval-timeout behavior (EPIC C, C2). [SEC-FLIP]

Structs§

ApprovalBroker
Authorization + quorum layer over resolve_gate. Holds NO copy of the approval policy/group config - it resolves every policy and membership decision from the engine’s live [sop.approval] at use-time (single source of truth), so a config reload cannot leave the broker deciding on stale rules. It carries only the identity-resolution seam and the route adapter.
ApprovalPrincipal
WHO resolved a gate and from WHERE. Recorded into the append-only ledger.
ChannelRouteAdapter
A route adapter that delivers approval notices to configured channels.
GateLedgerEntry
One immutable ledger row per gate event. Becomes a SopEventRecord via into_event_record, which the store appends (assigning the monotonic seq).
GateNotice
Everything a route adapter needs to render a MEANINGFUL gate notice — not just “run X waits at step N” but WHAT is being approved.
LocalConfigApprovalIdentityResolver
Config-backed resolver over [sop.approval].groups.*.members. Stateless: it reads the config handed to it on each call, so there is no second copy of the membership map to go stale. A member entry may be source-qualified (<source>:<identity>, e.g. http:<subject>, agent:<alias>) to grant rights on ONE transport only - so a subject on the gateway and the same string on the agent tool do not collide - or a bare identity to grant it from any source. Channel principals are stricter: they match only channel:<channel-key>:<sender>, never channel:<sender> or a bare sender, so same-looking platform ids from different channel aliases cannot collide. A principal with no identity (e.g. the system tick) belongs to no group.
NoopRouteAdapter
A no-op route adapter: logs the delivery intent but sends nowhere. The default until real channel delivery is wired (a follow-up); keeps the broker and escalation functional without a channel dependency.

Enums§

ApprovalDecision
Approve or deny a waiting SOP gate.
ApprovalMode
WHO may clear a SOP approval gate. Layered with execution_mode / priority / requires_confirmation (all of which still apply). Closed set => serde enum.
ApprovalNoticeKind
Why an approval notice is being delivered. Route adapters render this so an on-call escalation cannot be mistaken for the initial request.
ApprovalRouteIssue
A route configuration problem reported at daemon startup before a parked gate would otherwise discover it during delivery.
ApprovalSource
The transport a gate resolution arrived on. The agent tool, the loopback CLI, the gateway WebSocket frame, the gateway HTTP route, or the daemon timeout tick.
ApprovalTimeoutAction
What happens to a SOP approval gate when it times out. Default is fail-closed: the gate never self-approves. Closed set => serde enum.
BrokerOutcome
The outcome of a broker-mediated gate resolution.
GateEventKind
The kind of gate event recorded in the ledger.
ResolveOutcome
What resolve_gate did. Returned to the caller (tool / CLI / gateway) so it can report, and so the executor/tick can act on a resumed action.

Traits§

ApprovalIdentityResolver
Resolve an approval principal to the approver groups it is a member of, against the live [sop.approval] config passed in at use-time (the single source of truth - never a cloned copy that could drift on reload).
ApprovalRouteAdapter
Deliver an approval notice to a named route (channel). The seam that lets approvals reach approvers beyond the originating channel (the cross-channel HITL gap) and that escalation uses to reach a distinct SECOND route on timeout. Delivery is best-effort: a route error must never clear or block a gate (the gate state is the source of truth; the route is only a notice).

Functions§

unresolvable_approval_routes
The configured approval routes (request_route + escalation_route) whose channel key is NOT among channel_keys - the channels the route adapter can actually deliver to (present in its map AND supports_outbound_send). A route names an undeliverable channel when it is absent from the map (e.g. an AMQP SOP-dispatch channel that needs runtime SOP handles the adapter lacks) OR present but inbound-only (its send is a no-op). The daemon logs these at STARTUP so the drift between “configured route” and “deliverable channel” surfaces at boot, not silently on the first parked gate. A route must have non-empty channel:recipient halves; malformed values are also surfaced at startup. Returns one ApprovalRouteIssue per invalid route.