Skip to content

Broaden DelegateAuthenticator vouch to Scopes.isOperator - #96

Draft
chunter-cb wants to merge 5 commits into
mainfrom
feat/delegate-isoperator
Draft

Broaden DelegateAuthenticator vouch to Scopes.isOperator#96
chunter-cb wants to merge 5 commits into
mainfrom
feat/delegate-isoperator

Conversation

@chunter-cb

Copy link
Copy Markdown
Collaborator

Draft — stacked on #95 (base: feat/scope-reorder-colocate-policy). Review/merge after #95.

Summary

Broaden the DelegateAuthenticator vouch from admin-only (scope == 0) to Scopes.isOperator (admin or OPERATOR). A delegate's operational key can now vouch, mirroring the authority it already wields over the delegate account's own execution and ERC-1271 surface.

Why

Unifies the two authority tiers behind one predicate (isOperator): "can act as this account" now uniformly means "can drive execution, sign ERC-1271, and vouch as a delegate." This unlocks operator-key delegation (org/treasury accounts, key rotation, sub-accounts) without exposing an admin key.

Semantic change (deliberate)

  • A primary account authorizes ActorId.fromAddress(delegate) — a single address, no scope granularity. Previously this meant "only the delegate's admin can wield this delegation"; it now means "any OPERATOR key on the delegate can."
  • This reverses the prior intentionally admin-only invariant and its regression test (test_authenticate_revert_operationalSenderCannotVouchtest_authenticate_success_operatorCanVouch).
  • Non-operational scopes (payer-only, policy-only) still revert with InvalidNestedSignature.
  • No live deployments — this is a design decision, not a migration.

Test plan

  • forge test — 402 passing
  • DelegateAuthenticator.sol branch coverage 100%
  • forge fmt

…once

Regroup scope bits so the always-present grants come first (OPERATOR, SELF_PAYER,
SPONSOR_PAYER) and the optional POLICY and NONCE bits sit at the back, so a chain
that omits the policy and nonce systems needs no renumbering. Rename SENDER to
OPERATOR to reflect that it is the more permissive grant: OPERATOR and POLICY do
not combine (OPERATOR may originate to any call.to; POLICY-only is gated to the
actor's manager).

Co-locate each actor's optional policy (manager, commitment) with its 32-byte
config in a single ActorRecord mapping, so a Verkle witness can cover config and
policy together instead of three separate keyspaces.

Make Keystore fully policy/nonce-agnostic: it no longer imports Scopes and never
reads a scope bit to decide policy attachment. Attachment is a length check on the
authorize payload (empty 32-byte config, or 84-byte config+policy). A chain can
drop the policy and nonce systems and nothing in Keystore breaks.
Drop the chain-specific "a chain may omit" framing from the Scopes/Keystore/README
comments — POLICY and NONCE are simply optional grants. Rename the leftover SENDER /
SCOPE_SENDER test aliases (and their prose) to OPERATOR so the suite matches the
renamed source symbol.
Convert the change-type dispatch from an if/else-if chain to independent
`if (...) { ...; continue; }` arms so forge instruments each op's match /
no-match paths in isolation (the chain form left five arms as coverage dashes
under --ir-minimum despite all being exercised). Behavior is identical: same
handlers, same order, same UnknownChangeType fallback. Add an unknown-non-self
actor read test documenting the empty-config resolver path.
Point the four policy test files' SCOPE_OPERATOR/SCOPE_POLICY constants at the
Scopes library instead of inlined hex so they can't drift if bits move again.
Rewrite the change-dispatch comment to name the forge --ir-minimum coverage
artifact precisely rather than implying a universal instrumentation claim.
Let any operational actor on the delegate account — the admin (scope == 0) or an
OPERATOR-scoped key — satisfy the DelegateAuthenticator vouch, instead of the
admin only. This aligns delegation with the delegate account's own execution /
ERC-1271 authority (isOperator): "can act as the delegate" now also means "can
vouch as the delegate", unlocking operator-key delegation without exposing an
admin key. Non-operational scopes (e.g. payer-only) still revert.

Reverses the prior intentionally admin-only invariant and its regression test.
Base automatically changed from feat/scope-reorder-colocate-policy to main August 28, 2026 21:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant