feat: introduce pluggable wallet policy engine (AOP-style)#36
Open
nimdeveloper wants to merge 23 commits intotetherto:developfrom
Open
feat: introduce pluggable wallet policy engine (AOP-style)#36nimdeveloper wants to merge 23 commits intotetherto:developfrom
nimdeveloper wants to merge 23 commits intotetherto:developfrom
Conversation
Co-authored-by: Chetas Murali <thephantomblu@gmail.com>
Co-authored-by: Chetas Murali <thephantomblu@gmail.com>
feat: rename to WDK, publish workflow
chore: public release, bump version
Co-authored-by: Jonathan Dunne <jonathanpdunne@gmail.com>
Update `bare-node-runtime`
Add fiat protocol
Fix Issue Template
* style: format existing codes * feat: add full list of mutating wallet and protocol methods * feat: add PolicyViolationError class for handling policy rejection errors * feat: add runPolicies function for sequential policy evaluation * feat: implement policy registration and enforcement in WDK class * feat: add registerPolicies function for policy management in WdkManager tests * feat: update typescript types * style: remove comments * refactor: remove MUTATING_METHODS constant and dynamically gather methods from instance prototype * refactor: remove MUTATING_METHODS constant types * fix: update PolicyViolationError import and usage in tests * refactor: improve Policy typedef documentation for clarity * refactor: migrate runPolicies function to WDK class and update Policy typedefs * refactor: update _withPolicyGate method signature to use generic type and improve parameter clarity * refactor: standardize string quotes and improve Policy typedef documentation for clarity * refactor: update PolicyTarget to use blockchain identifier and adjust related method signatures * refactor: update PolicyViolationError to use PolicyTarget type for target parameter * refactor: add registerPolicies document entries and revert format changes on README and test files for consistency * refactor: remove unused runPolicies function from policies type definitions * refactor: clean up whitespace and update class names for consistency in wdk-manager * refactor: simplify policy evaluation by using mock functions in registerPolicies test * refactor: update wallet methods and policies for transaction handling in WdkManager tests * refactor: enhance policy evaluation and testing in WdkManager * refactor: rename runPolicies to _runPolicies and introduce PolicyEvaluator type * refactor: update return type of registerPolicies method to WdkManager
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Wallet Policies
This PR introduces Wallet Policies, a non-breaking feature that allows registering policy objects to gate mutating wallet, account, and protocol methods. Policies are evaluated before method execution. If a policy fails, a
PolicyViolationErroris thrown and execution is halted.This feature is implemented using an Aspect-Oriented Programming (AOP) approach to cleanly separate cross-cutting concerns from wallet business logic.
Motivation and Context
WDK currently lacks a unified mechanism to enforce runtime constraints such as:
These concerns are cross-cutting: they affect many unrelated methods across accounts and protocols. Without AOP, we would either duplicate checks inside every mutating method or make each class aware of external enforcement logic — both reduce maintainability and violate separation of concerns.
This PR introduces a lightweight AOP-style policy engine that allows defining enforcement logic once and declaratively applying it to selected wallet methods.
Aspect-Oriented Programming (AOP) Model
Join Point
A join point is a place where behavior can be intercepted. In WDK, every mutating method call is a join point:
Pointcut
A pointcut defines which join points to target, expressed declaratively:
Pointcuts can scope by blockchain, protocol, method name, or all methods.
Advice
Advice is the code that runs at the join point via
evaluate(). Advice is async-safe, enabling real-world enforcement tasks beyond simple in-memory checks — for example:Advice runs before the original method. Policies execute sequentially and fail-fast — the first failing policy halts execution.
Aspect
An aspect combines a pointcut with advice. In this implementation, a policy object is an aspect:
Weaving
Weaving attaches aspects to join points at runtime inside
_withPolicyGate():The original method is wrapped once, ensuring no modification to original class implementations and clean separation of concerns.
Design Decisions
Why not use
Proxy?Proxyintercepts all property access, complicates debugging, and makes execution flow less explicit. Instead, explicit method wrapping is used, which targets only specific methods, preserves performance, and keeps weaving controlled and predictable.Why use
Symbol?Two internal Symbols store policy metadata per instance to prevent property name collisions, keep metadata non-enumerable, avoid polluting the public API, and ensure clean instance-level isolation.
Implementation Summary
registerPolicies()— validates and registers aspects (policies)_runPolicies()— executes advice sequentially (async-safe, fail-fast)_withPolicyGate()— performs runtime weavingThis change is fully backward compatible and introduces no breaking behavior.
Type of Change