Skip to content

[RFC] Shared veto/timelock primitive and pluggable triggers #23

Description

@rosspeili

Summary

Define the architectural seam between (a) a shared, auditable queue → veto window → execute core and (b) pluggable trigger sources per policy type—so one “dormancy oracle” role cannot flip every policy flavor in the system.

Discussion first; adapter interfaces and manifest profile fields follow this decision.

Problem

Marketing and the reference spec describe many scenarios (dormancy, attestations, oracle facts, staged release, corporate continuity). Implementing them as one policy schema and one global attestor tends to:

  • Create a god-mode role that can mark any policy eligible
  • Produce an unauditable manifest (composite + ad-hoc params)
  • Confuse revocation semantics (a treasury rarely “changes its mind” like a person; staged release is clock-driven)

Commentary from the community aligns: contracts for escrow + timelock are tractable; policy expressiveness is the hard part.

Recommended direction (open for discussion)

Split the stack:

Layer Responsibility Examples
Shared core One audited path: commit → arm → satisfy → veto/cooling-off → execute; replay + conflict rules Same vault logic for every profile
Trigger adapter Proves eligibility for one trigger type; cannot satisfy unrelated policies Inactivity counter, EIP-712 attestors, time clock
Policy profile Binds which adapters and triggers are allowed treasury, personal, staged

Flow: adapters feed up into the shared core; profiles constrain which adapter may arm or satisfy each policy.

  • Shared primitive: veto/timelock, execution nonces, global priority (ADR 001 direction).
  • Not shared: a single off-chain “dormancy oracle” that can arm or satisfy unrelated policies. Each policy profile binds allowed trigger types and which adapter contract(s) may call markEligible (or successor).

Policy profiles (working set): treasury | personal | staged — each references cancel/liveness rules from Issue #___ (cancel RFC) and allowed trigger enums.

Discussion welcome: whether profiles are manifest-only labels vs on-chain enum; whether one deployment hosts multiple profiles.

What we need to decide (discussion checklist)

  • Minimal ITriggerAdapter (or equivalent) interface: who may call, what evidence is stored, replay rules
  • Rule: adapters MUST NOT hold a global cancel over policies they did not arm
  • Profile → allowed triggers matrix (e.g. treasury: inactivity + multisig; personal: attestation + inactivity; staged: time only)
  • How cooling-off defaults vary by profile (non-zero for attestation-linked; zero only when explicitly accepted)
  • Executor / permissionless execute gates per profile (ADR 001 hybrid model)
  • Relationship to future smart-account module (path B): same primitive, different custody shell?

What will be affected

  • Architecture overview diagram and module table (reference §15)
  • Policy manifest schema (profile, adapter allowlist, trigger type validation)
  • v1 MVP scope boundaries (what ships in bytecode vs stubs)
  • Vault factory / per-policy configuration
  • Trust boundaries doc (oracle vs executor vs owner)
  • Future subgraph: profile and adapterAddress indexing

Target end behavior

  1. A compromised attestor for personal policies cannot satisfy treasury policies on the same deployment.
  2. Authors pick a profile and get a constrained, reviewable trigger surface—not arbitrary JSON.
  3. Security reviewers audit one core + small adapter set, not N bespoke deployments.
  4. New trigger types ship as new adapters + schema bump, not forks of the vault.

Out of scope

  • Full OpenZeppelin Governor/Timelock fork (informative comparison only)
  • Cross-chain CAIP oracle IDs (unless needed for a profile decision)

Suggested acceptance criteria

  • Profile list and trigger matrix agreed
  • Adapter trust rules written (who can call what)
  • Manifest validation rules sketched (even if schema PR is separate)
  • Clear v1: time-only profile path documented

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedExtra attention is neededquestionFurther information is requested

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions